SpringBoot学习(四)开发web应用

Spring Boot非常适合web应用程序开发。可以使用嵌入式Tomcat、Jetty、Undertow或Netty创建自包含的HTTP服务器。大多数web应用程序使用spring-boot-starter-web模块来快速启动和运行。您还可以选择使用spring-boot-starter-webflux模块来构建反应性web应用程序。

1.Spring Web MVC框架

Spring Web MVC框架(通常简称为“Spring MVC”)是一个丰富的“模型-视图-控制器”Web框架。Spring MVC允许您创建特殊的@Controller或@RestController bean来处理传入的HTTP请求。控制器中的方法通过使用@RequestMapping注释映射到HTTP。

以下是示例:

@RestController
@RequestMapping(value="/users")
public class MyRestController {

    @RequestMapping(value="/{user}", method=RequestMethod.GET)
    public User getUser(@PathVariable Long user) {   //@PathVariable 将 URL 中占位符参数绑定到控制器处理方法的入参中:URL 中的 {xxx} 占位符可以通过@PathVariable(“xxx“) 绑定到操作方法的入参中。
        // ...
    }

    @RequestMapping(value="/{user}/customers", method=RequestMethod.GET)
    List<Customer> getUserCustomers(@PathVariable Long user) {
        // ...
    }

    @RequestMapping(value="/{user}", method=RequestMethod.DELETE)
    public User deleteUser(@PathVariable Long user) {
        // ...
    }

}

1.1Spring MVC 自动配置

Spring Boot为Spring MVC提供了自动配置,可以很好地与大多数应用程序配合使用。

自动配置在Spring的默认设置之上添加了以下特性:

a.包含contentatingviewresolver和BeanNameViewResolver bean。

b.支持为静态资源提供服务,包括对webjar的支持(本文档后面将介绍)。

c.转换器、GenericConverter和格式化器bean的自动注册。

d.支持HttpMessageConverters(本文档后面将介绍)。

e.MessageCodesResolver的自动注册(本文档后面将介绍)。

f.静态index . html的支持。

g.自定义的Favicon支持(稍后将在本文档中介绍)。

h.自动使用ConfigurableWebBindingInitializer bean(稍后将在本文档中介绍)。

如果您希望保留Spring Boot MVC功能,并且希望添加额外的MVC配置(拦截器、格式化器、视图控制器和其他功能),您可以添加自己的WebMvcConfigurer类型的@Configuration类,但是不需要@EnableWebMvc。如果希望提供RequestMappingHandlerMapping、RequestMappingHandlerAdapter或ExceptionHandlerExceptionResolver的自定义实例,可以声明WebMvcRegistrationsAdapter实例来提供此类组件。

如果你想完全控制Spring MVC,你可以用@EnableWebMvc添加你自己的@Configuration注解。

1.2HttpMessageConverters(http消息转换器)

Spring MVC使用HttpMessageConverter接口来转换HTTP请求和响应。合理的默认值是开箱即用的。例如,可以将对象自动转换为JSON(通过使用Jackson库)或XML(通过使用Jackson XML扩展(如果可用),或者通过使用JAXB(如果Jackson XML扩展不可用)。默认情况下,字符串是用UTF-8编码的。

如果需要添加或自定义转换器,可以使用Spring Boot的HttpMessageConverters类,如下面的清单所示:

import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
import org.springframework.context.annotation.*;
import org.springframework.http.converter.*;

@Configuration(proxyBeanMethods = false)
public class MyConfiguration {

    @Bean
    public HttpMessageConverters customConverters() {
        HttpMessageConverter<?> additional = ...  //添加额外的转换器
        HttpMessageConverter<?> another = ...
        return new HttpMessageConverters(additional, another);
    }

}

上下文中出现的任何HttpMessageConverter bean都将添加到转换器列表中。您还可以以相同的方式覆盖默认转换器。

1.3定制JSON的序列化(Serializers)和反序列化(Deserializers)

如果你使用Jackson来序列化和反序列化Json数据,你可能想写你自己的JsonSerializer和JsonDeserializer类。定制序列化器通常通过模块在Jackson中注册,但是Spring Boot提供了一个替代的@JsonComponent注释,使得直接注册Spring bean更加容易。

您可以直接在JsonSerializer、JsonDeserializer或KeyDeserializer实现上使用@JsonComponent注释。你也可以在包含序列化器/反序列化器作为内部类的类上使用它,如下面的例子所示:

import java.io.*;
import com.fasterxml.jackson.core.*;
import com.fasterxml.jackson.databind.*;
import org.springframework.boot.jackson.*;

@JsonComponent
public class Example {

    public static class Serializer extends JsonSerializer<SomeObject> {
        // ...
    }

    public static class Deserializer extends JsonDeserializer<SomeObject> {
        // ...
    }

}

ApplicationContext中的所有@JsonComponent bean都自动注册到Jackson。因为@JsonComponent是用@Component进行元注释的,所以通常的组件扫描规则是适用的。

Spring Boot还提供了JsonObjectSerializer和JsonObjectDeserializer基类,它们在序列化对象时为标准Jackson版本提供了有用的替代方法。有关详细信息,请参阅Javadoc中的JsonObjectSerializer和JsonObjectDeserializer。

如果我们想灵活一些,可以分别定义序列化类(继承JsonSerializer<T>或JsonObjectSerializer<T>)和反序列化类(继承JsonDeSerializer<T>或JsonObjectDeserializer<T>)。然后通过注解@JsonSerialize(using=MyJsonSerializer.class)和@JsonDeSerialize(using=MyJsonDeSerializer.class)来指向属性。还有其他的属性上的注解(忽略属性/日期转换等等@JsonSerialize @JsonIgnoreProperties @JsonIgnore @JsonFormat等等),可以参考:https://www.cnblogs.com/guxia/p/6598174.html

package org.springframework.boot.jackson;

import java.io.IOException;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;

/**
 * Helper base class for {@link JsonSerializer} implementations that serialize objects.
 *
 * @param <T> the supported object type
 * @author Phillip Webb
 * @since 1.4.0
 * @see JsonObjectDeserializer
 */
public abstract class JsonObjectSerializer<T> extends JsonSerializer<T> {

    @Override
    public final void serialize(T value, JsonGenerator jgen, SerializerProvider provider) throws IOException {
        try {
            jgen.writeStartObject();
            serializeObject(value, jgen, provider);
            jgen.writeEndObject();
        }
        catch (Exception ex) {
            if (ex instanceof IOException) {
                throw (IOException) ex;
            }
            throw new JsonMappingException(jgen, "Object serialize error", ex);
        }
    }

    /**
     * Serialize JSON content into the value type this serializer handles.
     * @param value the source value
     * @param jgen the JSON generator
     * @param provider the serializer provider
     * @throws IOException on error
     */
    protected abstract void serializeObject(T value, JsonGenerator jgen, SerializerProvider provider)
            throws IOException;

}

1.4.MessageCodesResolver(消息代码解析器)

Spring MVC有一个从绑定错误中生成错误代码的策略:MessageCodesResolver。如果你设置了spring.mvc.message-codes-resolver-format属性PREFIX_ERROR_CODE或POSTFIX_ERROR_CODE, Spring Boot为您创建了一个(参见DefaultMessageCodesResolver.Format中的枚举)。

1.5.静态目录

默认情况下,Spring Boot从类路径中名为/static(或/public或/resources或/META-INF/resources)的目录或ServletContext的根目录提供静态内容。它使用来自Spring MVC的ResourceHttpRequestHandler,因此您可以通过添加自己的WebMvcConfigurer并覆盖addResourceHandlers方法来修改行为。 参考:https://www.cnblogs.com/panxuejun/p/6737031.html

在独立的web应用程序中,还启用了容器中的缺省servlet,并充当备用机制,如果Spring决定不处理它,则从ServletContext的根目录提供内容。大多数情况下,这不会发生(除非修改默认的MVC配置),因为Spring总是可以通过DispatcherServlet处理请求。

默认情况下,资源映射在/**上,但是您可以使用spring.mvc对其进行调优。static-path-pattern财产。例如,将所有资源重新分配到/resources/**可以实现如下:

spring.mvc.static-path-pattern=/resources/**

您还可以使用spring.resources.static-locations自定义静态资源位置(替换默认的目录)。the root Servlet上下文路径“/”也被自动添加为一个位置。

除了前面提到的“标准”静态资源位置之外,webjar内容还有一个特殊的情况。任何在/webjars/**中有路径的资源都可以从jar文件中获得,前提是它们是以webjars格式打包的。

注:如果您的应用程序打包为jar,那么不要使用src/main/webapp目录。虽然这个目录是一个通用的标准,但是它只适用于war打包,如果您生成一个jar,那么大多数构建工具都会忽略它。

Spring Boot还支持Spring MVC提供的高级资源处理特性,允许使用例如破坏缓存的静态资源或为webjar使用版本不可知的url。

注:如果使用JBoss,则需要声明webjar -locator- JBoss -vfs依赖项,而不是webjar -locator-core。否则,所有webjar都将解析为404。

由于ResourceUrlEncodingFilter是为Thymeleaf和FreeMarker自动配置的,所以在运行时可以在模板中重写到资源的链接。使用jsp时应该手动声明此筛选器。其他模板引擎目前还不被自动支持,但是可以使用自定义模板宏/助手和ResourceUrlProvider。

当使用JavaScript模块加载器动态加载资源时,不能重命名文件。这就是为什么其他战略也受到支持,并且可以结合使用。“fixed”策略在URL中添加一个静态的版本字符串,而不改变文件名,如下例所示:

spring.resources.chain.strategy.content.enabled=true
spring.resources.chain.strategy.content.paths=/**
spring.resources.chain.strategy.fixed.enabled=true
spring.resources.chain.strategy.fixed.paths=/js/lib/
spring.resources.chain.strategy.fixed.version=v12

通过这个配置,位于“/js/lib/”下的JavaScript模块使用固定的版本策略(“/v12/js/lib/mymodule.js”),而其他资源仍然使用内容策略(<link href=“/css/spring-2a2d595e6ed9a0b24f027f2b63b134d6.css”/>)

1.6.欢迎页面

Spring Boot同时支持静态和模板化欢迎页面。它首先在配置的静态内容位置中查找index.html文件。如果没有找到,则查找索引模板。如果找到其中之一,它将自动用作应用程序的欢迎页面。

1.7.自定义图标

与其他静态资源一样,Spring Boot在配置的静态内容位置中查找favicon.ico。如果存在这样的文件,它将自动用作应用程序的favicon。

1.8.路径匹配和内容协商

Spring MVC可以通过查看请求路径并将其与应用程序中定义的映射(例如,@GetMapping对控制器方法的注释)匹配,从而将传入的HTTP请求映射到处理程序。

默认情况下,Spring Boot选择禁用后缀模式匹配,这意味着像“GET /projects/ Spring - Boot.json”这样的请求,将不会与@GetMapping(“/projects/spring-boot”)映射匹配。这被认为是Spring MVC应用程序的最佳实践。这个功能主要是有用的在过去的HTTP客户端没有发送正确的“接受”请求头;我们需要确保将正确的内容类型发送到客户机。如今,内容协商更加可靠。

还有其他方法可以处理不一致发送正确的“Accept”请求头的HTTP客户端。我们可以使用一个查询参数来确保诸如“GET /projects/spring-boot?”format=json"将被映射到@GetMapping("/projects/spring-boot"):

spring.mvc.contentnegotiation.favor-parameter=true

# We can change the parameter name, which is "format" by default:
# spring.mvc.contentnegotiation.parameter-name=myparam

# We can also register additional file extensions/media types with:
spring.mvc.contentnegotiation.media-types.markdown=text/markdown

如果您理解这些警告,并且仍然希望您的应用程序使用后缀模式匹配,则需要进行以下配置:

spring.mvc.contentnegotiation.favor-path-extension=true
spring.mvc.pathmatch.use-suffix-pattern=true

另外,与其开放所有后缀模式,不如只支持注册后缀模式更安全:

spring.mvc.contentnegotiation.favor-path-extension=true
spring.mvc.pathmatch.use-registered-suffix-pattern=true

# You can also register additional file extensions/media types with:
# spring.mvc.contentnegotiation.media-types.adoc=text/asciidoc

1.9.ConfigurableWebBindingInitializer(可配置的Web绑定初始化器)

Spring MVC使用WebBindingInitializer来初始化特定请求的WebDataBinder。如果你创建了自己的ConfigurableWebBindingInitializer @Bean, Spring Boot会自动配置Spring MVC来使用它。

1.10.模板引擎

除了REST web服务,您还可以使用Spring MVC来提供动态HTML内容。Spring MVC支持多种模板技术,包括Thymeleaf、FreeMarker和jsp。此外,许多其他模板引擎也包含自己的Spring MVC集成。

Spring Boot包含对下列模板引擎的自动配置支持: FreeMarker、Groovy、Thymeleaf、Mustache

注:如果可能,应该避免使用jsp。在与嵌入式servlet容器一起使用时,有几个已知的限制。

当您使用这些带有默认配置的模板引擎之一时,您的模板将自动从src/main/resources/templates中获取。

1.11异常处理

默认情况下,Spring Boot提供一个/error映射,它以一种合理的方式处理所有错误,并在servlet容器中注册为“全局”错误页面。对于机器客户端,它生成一个JSON响应,其中包含错误、HTTP状态和异常消息的详细信息。对于浏览器客户机,有一个“whitelabel”错误视图,它以HTML格式呈现相同的数据(要自定义它,请添加一个解析为错误的视图)。要完全替换默认行为,您可以实现ErrorController并注册该类型的bean定义,或者向其中添加ErrorAttributes类型的bean

BasicErrorController可以用作自定义ErrorController的基类。如果您希望为新的内容类型添加处理程序(默认情况下是专门处理文本/html,并为其他所有内容提供回退),这尤其有用。为此,扩展BasicErrorController,添加一个带有@RequestMapping(具有produces属性)的公共方法,并创建一个新类型的bean。

您还可以定义一个带有@ControllerAdvice注释的类,以自定义JSON文档以返回特定的控制器和/或异常类型,如下面的示例所示:

@ControllerAdvice(basePackageClasses = AcmeController.class)
public class AcmeControllerAdvice extends ResponseEntityExceptionHandler {

    @ExceptionHandler(YourException.class)
    @ResponseBody
    ResponseEntity<?> handleControllerException(HttpServletRequest request, Throwable ex) {
        HttpStatus status = getStatus(request);
        return new ResponseEntity<>(new CustomErrorType(status.value(), ex.getMessage()), status);
    }

    private HttpStatus getStatus(HttpServletRequest request) {
        Integer statusCode = (Integer) request.getAttribute("javax.servlet.error.status_code");
        if (statusCode == null) {
            return HttpStatus.INTERNAL_SERVER_ERROR;
        }
        return HttpStatus.valueOf(statusCode);
    }

}

在前面的示例中,如果与AcmeController在同一个包中定义的控制器抛出了YourException,则使用CustomErrorType POJO的JSON表示,而不是ErrorAttributes表示。

自定义错误页面

如果您想要显示给定状态码的自定义HTML错误页,可以将文件添加到/error文件夹。错误页面可以是静态HTML(即添加到任何静态资源文件夹下),也可以使用模板构建。文件的名称应该是准确的状态码或系列掩码。

例如,要将404映射到静态HTML文件,您的文件夹结构如下:

src/
 +- main/
     +- java/
     |   + <source code>
     +- resources/
         +- public/
             +- error/
             |   +- 404.html
             +- <other public assets>

要使用FreeMarker模板来映射所有5xx个错误,您的文件夹结构如下:

src/
 +- main/
     +- java/
     |   + <source code>
     +- resources/
         +- templates/
             +- error/
             |   +- 5xx.ftlh
             +- <other templates>

对于更复杂的映射,您还可以添加实现ErrorViewResolver接口的bean,如下面的示例所示:

public class MyErrorViewResolver implements ErrorViewResolver {

    @Override
    public ModelAndView resolveErrorView(HttpServletRequest request,
            HttpStatus status, Map<String, Object> model) {
        // Use the request or status to optionally return a ModelAndView
        return ...
    }

}

您还可以使用常规的Spring MVC特性,如@ExceptionHandler方法和@ControllerAdvice。然后ErrorController获取任何未处理的异常。

映射Spring MVC外部的错误页面

对于不使用Spring MVC的应用程序,可以使用ErrorPageRegistrar接口直接注册ErrorPages。这个抽象直接与底层的嵌入式servlet容器一起工作,即使您没有Spring MVC DispatcherServlet也可以工作。

@Bean
public ErrorPageRegistrar errorPageRegistrar(){
    return new MyErrorPageRegistrar();
}

// ...

private static class MyErrorPageRegistrar implements ErrorPageRegistrar {

    @Override
    public void registerErrorPages(ErrorPageRegistry registry) {
        registry.addErrorPages(new ErrorPage(HttpStatus.BAD_REQUEST, "/400"));
    }

}

注:如果您注册了一个ErrorPage,其路径最终由一个过滤器处理(这在一些非spring web框架中很常见,如Jersey和Wicket),那么过滤器必须显式地注册为一个错误调度程序,如下面的示例所示:

@Bean
public FilterRegistrationBean myFilter() {
    FilterRegistrationBean registration = new FilterRegistrationBean();
    registration.setFilter(new MyFilter());
    ...
    registration.setDispatcherTypes(EnumSet.allOf(DispatcherType.class));
    return registration;
}

注意,默认的FilterRegistrationBean不包含错误调度程序类型。

注意:当部署到servlet容器时,Spring Boot使用其错误页面过滤器将带有错误状态的请求转发到适当的错误页面。如果尚未提交响应,则只能将请求转发到正确的错误页面。默认情况下,WebSphere Application Server 8.0及以后在成功完成servlet的服务方法后提交响应。您应该通过设置com.ibm.ws.webcontainer.invokeFlushAfterService为false来禁用此行为。

1.12.Spring HATEOAS

如果您开发一个利用超媒体的RESTful API, Spring Boot将为Spring HATEOAS提供自动配置,这在大多数应用程序中都能很好地工作。自动配置取代了使用@EnableHypermediaSupport的需要,并注册了许多bean来简化构建基于超媒体的应用程序,包括一个LinkDiscoverers(用于客户端支持)和一个ObjectMapper(配置为正确地将响应封入所需的表示)。ObjectMapper是通过设置各种spring.jackson.*定制的属性,如果存在属性,则由Jackson2ObjectMapperBuilder bean创建。

您可以使用@EnableHypermediaSupport来控制Spring HATEOAS的配置。注意,这样做会禁用前面描述的ObjectMapper定制。

1.13.CORS 支持

跨源资源共享(Cross-origin resource sharing, CORS)是由大多数浏览器实现的W3C规范,它允许您以灵活的方式指定授权的跨域请求类型。,而不是使用一些不太安全、不太强大的方法,如IFRAME或JSONP。

从4.2版开始,Spring MVC就支持CORS。在Spring启动应用程序中使用带有@CrossOrigin注释的控制器方法CORS配置不需要任何特定的配置。通过使用定制的addcorsm(CorsRegistry)方法注册WebMvcConfigurer bean,可以定义全局CORS配置。

@Configuration(proxyBeanMethods = false)
public class MyConfiguration {

    @Bean
    public WebMvcConfigurer corsConfigurer() {
        return new WebMvcConfigurer() {
            @Override
            public void addCorsMappings(CorsRegistry registry) {
                registry.addMapping("/api/**");
            }
        };
    }
}

2.Spring WebFlux框架

Spring WebFlux是Spring framework 5.0中引入的新的反应性web框架。与Spring MVC不同,它不需要Servlet API,是完全异步和非阻塞的,并且通过反应器项目实现了反应式流规范。

Spring WebFlux有两种风格:功能性和基于注释的。基于注解的模式非常接近于Spring MVC模式,如下例所示:

@RestController
@RequestMapping("/users")
public class MyRestController {

    @GetMapping("/{user}")
    public Mono<User> getUser(@PathVariable Long user) {
        // ...
    }

    @GetMapping("/{user}/customers")
    public Flux<Customer> getUserCustomers(@PathVariable Long user) {
        // ...
    }

    @DeleteMapping("/{user}")
    public Mono<User> deleteUser(@PathVariable Long user) {
        // ...
    }

}

“WebFlux.fn”是函数变量,它将路由配置与请求的实际处理分离开来,如下例所示:

@Configuration(proxyBeanMethods = false)
public class RoutingConfiguration {

    @Bean
    public RouterFunction<ServerResponse> monoRouterFunction(UserHandler userHandler) {
        return route(GET("/{user}").and(accept(APPLICATION_JSON)), userHandler::getUser)
                .andRoute(GET("/{user}/customers").and(accept(APPLICATION_JSON)), userHandler::getUserCustomers)
                .andRoute(DELETE("/{user}").and(accept(APPLICATION_JSON)), userHandler::deleteUser);
    }

}

@Component
public class UserHandler {

    public Mono<ServerResponse> getUser(ServerRequest request) {
        // ...
    }

    public Mono<ServerResponse> getUserCustomers(ServerRequest request) {
        // ...
    }

    public Mono<ServerResponse> deleteUser(ServerRequest request) {
        // ...
    }
}

WebFlux是Spring框架的一部分,详细的信息可以在它的参考文档中找到。

您可以定义任意数量的RouterFunction bean来模块化路由器的定义。如果需要应用优先级,可以对bean进行排序。

首先,将spring-boot-starter-webflux模块添加到您的应用程序中。

在您的应用程序中同时添加Spring - Boot -starter-web和Spring - Boot -starter- WebFlux模块会在Spring Boot中自动配置Spring MVC,而不是WebFlux。之所以选择这种行为,是因为许多Spring开发人员将Spring -boot-starter-webflux添加到他们的Spring MVC应用程序中,以使用反应性的WebClient。您仍然可以通过将选择的应用程序类型设置为SpringApplication.setWebApplicationType(WebApplicationType.REACTIVE)来强制执行您的选择。

2.1.Spring WebFlux 自动配置

Spring Boot为Spring WebFlux提供了自动配置,可以很好地与大多数应用程序配合使用。

自动配置在Spring的默认设置之上添加了以下特性:

为HttpMessageReader和HttpMessageWriter实例配置编解码器(稍后将在本文档中描述)。

支持为静态资源提供服务,包括对webjar的支持(稍后将在本文中描述)。

如果你想保持Spring启动WebFlux特性,你想添加额外的WebFlux配置,你可以添加你自己的WebFluxConfigurer类型的@Configuration类,但是不需要@EnableWebFlux.

2.2.带有httpmessagereader和httpmessagewriter的HTTP编解码器

Spring WebFlux使用HttpMessageReader和HttpMessageWriter接口来转换HTTP请求和响应。它们配置了CodecConfigurer,通过查看类路径中可用的库来设置合理的默认值。

Spring Boot为编解码器提供了专用的配置属性,Spring .codec.*。它还通过使用CodecCustomizer实例应用进一步的定制。例如,spring.jackson。配置键应用于杰克逊编解码器。

如果需要添加或自定义CodecCustomizer,可以创建自定义CodecCustomizer组件,如下所示

import org.springframework.boot.web.codec.CodecCustomizer;

@Configuration(proxyBeanMethods = false)
public class MyConfiguration {

    @Bean
    public CodecCustomizer myCodecCustomizer() {
        return codecConfigurer -> {
            // ...
        };
    }

}

您还可以利用Boot的定制JSON序列化器和反序列化器。

2.3.静态目录

默认情况下,Spring Boot从类路径中名为/static(或/public或/resources或/META-INF/resources)的目录提供静态内容。它使用来自Spring WebFlux的ResourceWebHandler,因此您可以通过添加自己的WebFluxConfigurer并覆盖addResourceHandlers方法来修改行为。

默认情况下,资源被映射到/**上,但是您可以通过设置spring.webflux来调整它。static-path-pattern财产。例如,将所有资源重新分配到/resources/**可以实现如下:

spring.webflux.static-path-pattern=/resources/**

您还可以使用spring.resources.static-locations自定义静态资源位置。这样做将用目录位置列表替换默认值。如果这样做,默认的欢迎页面检测将切换到您的自定义位置。因此,如果在启动时在您的任何位置有index.html,它就是应用程序的主页。

除了前面列出的“标准”静态资源位置之外,Webjars内容还有一个特殊的情况。任何在/webjars/**中有路径的资源都可以从jar文件中获得,前提是它们是以webjars格式打包的。

注:Spring WebFlux应用程序并不严格依赖于Servlet API,所以它们不能作为war文件部署,也不使用src/main/webapp目录。

2.4.模板引擎

除了REST web服务,您还可以使用Spring WebFlux来提供动态HTML内容。Spring WebFlux支持多种模板技术,包括Thymeleaf、FreeMarker和Mustache。

Spring Boot包含对下列模板引擎的自动配置支持:FreeMarker、Thymeleaf和Mustache。

当您使用这些带有默认配置的模板引擎之一时,您的模板将自动从src/main/resources/templates中获取。

2.5.异常处理

要更改错误处理行为,可以实现ErrorWebExceptionHandler并注册该类型的bean定义。因为WebExceptionHandler是相当底层的,Spring Boot还提供了一个方便的AbstractErrorWebExceptionHandler,让您以WebFlux函数的方式处理错误,如下面的例子所示:

public class CustomErrorWebExceptionHandler extends AbstractErrorWebExceptionHandler {

    // Define constructor here

    @Override
    protected RouterFunction<ServerResponse> getRoutingFunction(ErrorAttributes errorAttributes) {

        return RouterFunctions
                .route(aPredicate, aHandler)
                .andRoute(anotherPredicate, anotherHandler);
    }

}

对于更完整的图片,您还可以直接子类化DefaultErrorWebExceptionHandler并覆盖特定的方法。

2.6.Web过滤器

Spring WebFlux提供了一个WebFilter接口,可以实现它来过滤HTTP请求-响应交换。在应用程序上下文中找到的WebFilter bean将自动用于筛选每个交换。

如果过滤器的顺序很重要,那么它们可以实现Ordered或使用@Order注释。Spring Boot自动配置可以为您配置web过滤器。当它这样做时,将使用下表中显示的订单:

Web Filter Order

MetricsWebFilter


Ordered.HIGHEST_PRECEDENCE + 1


WebFilterChainProxy (Spring Security)


-100


HttpTraceWebFilter


Ordered.LOWEST_PRECEDENCE - 10

3.JAX-RS和Jersey

如果您喜欢REST端点的JAX-RS编程模型,您可以使用其中一个可用的实现来代替Spring MVC。Jersey和Apache CXF的开箱即用效果非常好。CXF要求您在应用程序上下文中将其Servlet或过滤器注册为@Bean。Jersey有一些本机Spring支持,因此我们还在Spring Boot中为其提供了自动配置支持,以及一个启动器。

要开始使用Jersey,首先要包含spring-boot-starter-jersey作为一个依赖项,然后需要一个ResourceConfig类型的@Bean来注册所有的端点,如下例所示:

@Component
public class JerseyConfig extends ResourceConfig {

    public JerseyConfig() {
        register(Endpoint.class);
    }

}

对于更高级的定制,您还可以注册实现ResourceConfigCustomizer的任意数量的bean。

所有注册的端点都应该是带有HTTP资源注解的@Components (@GET等),如下例所示:

@Component
@Path("/hello")
public class Endpoint {

    @GET
    public String message() {
        return "Hello";
    }

}

因为端点是一个Spring @Component,所以它的生命周期是由Spring管理的,您可以使用@Autowired注解注入依赖项,使用@Value注解注入外部配置。默认情况下,Jersey servlet被注册并映射到/*。您可以通过将@ApplicationPath添加到您的ResourceConfig来更改映射。

默认情况下,Jersey被设置为名为jerseyServletRegistration的@Bean类型的servletregiationbean中的Servlet。默认情况下,servlet是惰性初始化的,但是您可以通过设置spring.jersey.servlet.load-on-startup来定制该行为。您可以通过创建自己的同名bean来禁用或覆盖该bean。您还可以通过设置spring.jersey来使用过滤器而不是servlet。type=filter(在这种情况下,要替换或覆盖的@Bean是jerseyFilterRegistration)。过滤器有一个@Order,您可以使用spring. jersei .filter.order来设置它。servlet和过滤器注册都可以通过使用spring. jersei .init.*指定属性的映射来获得初始化参数。

4.嵌入式Servlet容器支持

Spring Boot包含对嵌入式Tomcat、Jetty和Undertow服务器的支持。大多数开发人员使用适当的“Starter”来获得完全配置的实例。默认情况下,嵌入式服务器监听端口8080上的HTTP请求。

4.1.Servlet、Filters和listeners

在使用嵌入式servlet容器时,可以通过使用Spring bean或扫描servlet组件,从servlet规范注册servlet、过滤器和所有侦听器(如HttpSessionListener)。

将servlet、过滤器和侦听器注册为Spring bean

作为Spring bean的任何Servlet、过滤器或Servlet *Listener实例都将注册到嵌入的容器中。如果您希望引用应用程序中的值,这将特别方便。在配置属性。

默认情况下,如果上下文只包含一个Servlet,则将其映射到/。对于多个servlet bean, bean名用作路径前缀。过滤器映射到/*。

如果基于约定的映射不够灵活,可以使用ServletRegistrationBean、FilterRegistrationBean和ServletListenerRegistrationBean类来完成控制。

通常把过滤器Beans放得乱七八糟是安全的。如果需要特定的顺序,您应该使用@Order注释过滤器,或者让它实现Ordered。您不能通过使用@Order注释其bean方法来配置筛选器的顺序。如果您不能更改过滤器类以添加@Order或实现Ordered,则必须为过滤器定义FilterRegistrationBean,并使用setOrder(int)方法设置注册bean的订单。避免配置按顺序读取请求主体的筛选器。highest_priority,因为它可能与应用程序的字符编码配置相冲突。如果Servlet筛选器包装了请求,则应该使用小于或等于OrderedFilter.REQUEST_WRAPPER_FILTER_MAX_ORDER的订单对其进行配置。

注:要查看应用程序中每个过滤器的顺序,请为web日志组启用调试级别日志记录(logging.level.web=debug)。注册过滤器的详细信息,包括它们的顺序和URL模式,将在启动时被记录下来。

注:注册过滤器bean时要小心,因为它们在应用程序生命周期中很早就初始化了。如果需要注册一个与其他bean交互的过滤器,可以考虑使用一个DelegatingFilterProxyRegistrationBean.

4.2.Servlet上下文初始化

嵌入式servlet容器并不直接执行servlet 3.0+ javax.servlet.ServletContainerInitializer接口或Spring的org.springframework.web.WebApplicationInitializer接口。这是一个有意的设计决策,目的是为了降低在war中运行的第三方库可能会破坏Spring启动应用程序的风险。

如果您需要在SpringBoot应用中执行servlet上下文初始化,您应该注册一个实现org.springframework.boot.web.servlet.ServletContextInitializer接口。单一的onStartup方法提供了对ServletContext的访问,如果需要,可以轻松地用作现有WebApplicationInitializer的适配器。

扫描servlet、过滤器和侦听器

在使用嵌入式容器时,可以通过使用@ServletComponentScan启用@WebServlet、@WebFilter和@WebListener注释的类的自动注册。

@ServletComponentScan在独立容器中没有作用,而是使用容器的内置发现机制。

4.3ServletWebServerApplicationContext

在底层,Spring Boot使用不同类型的ApplicationContext来支持嵌入式servlet容器。ServletWebServerApplicationContext是一种特殊类型的WebApplicationContext,它通过搜索单个ServletWebServerFactory bean来引导自己。通常,TomcatServletWebServerFactory、JettyServletWebServerFactory或UndertowServletWebServerFactory是自动配置的。

您通常不需要知道这些实现类。大多数应用程序是自动配置的,适当的ApplicationContext和ServletWebServerFactory是代表您创建的。

4.4.定制嵌入的Servlet容器

可以使用Spring环境属性来配置通用的servlet容器设置。通常,您需要在application.properties文件中定义属性。

常见的服务器设置包括:

网络设置:监听传入HTTP请求的端口(server.port),接口地址绑定到server.address,等等。

a.会话设置:会话是否持久(server.servlet.session.persistent)、会话超时(server.servlet.session.timeout)、会话数据的位置(server.servlet.session.store-dir)、会话cookie配置(server.servlet.session.cookie.*)。

b.错误管理:错误页面的位置(server.error.path)等。

c.SSL

d.HTTP压缩

Spring Boot尽可能多地尝试公开公共设置,但这并不总是可能的。对于这些情况,专用名称空间提供特定于服务器的自定义(参见server.tomcat和server.undertow)。例如,可以使用嵌入式servlet容器的特定功能来配置访问日志。

编程定制

如果需要以编程方式配置嵌入的servlet容器,可以注册一个实现WebServerFactoryCustomizer接口的Spring bean。WebServerFactoryCustomizer提供对ConfigurableServletWebServerFactory的访问,其中包含许多定制setter方法。下面的例子显示了以编程方式设置端口:

import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory;
import org.springframework.stereotype.Component;

@Component
public class CustomizationBean implements WebServerFactoryCustomizer<ConfigurableServletWebServerFactory> {

    @Override
    public void customize(ConfigurableServletWebServerFactory server) {
        server.setPort(9000);
    }

}

注:TomcatServletWebServerFactory、JettyServletWebServerFactory和UndertowServletWebServerFactory是ConfigurableServletWebServerFactory的专用变体,它们分别为Tomcat、Jetty和Undertow提供了额外的定制setter方法。

自定义ConfigurableServletWebServerFactory

如果前面的定制技术太有限,您可以自己注册TomcatServletWebServerFactory、JettyServletWebServerFactory或UndertowServletWebServerFactory bean。

@Bean
public ConfigurableServletWebServerFactory webServerFactory() {
    TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
    factory.setPort(9000);
    factory.setSessionTimeout(10, TimeUnit.MINUTES);
    factory.addErrorPages(new ErrorPage(HttpStatus.NOT_FOUND, "/notfound.html"));
    return factory;
}

为许多配置选项提供了setter。如果您需要做一些更奇特的事情,还提供了几个受保护的方法“挂钩”。有关详细信息,请参阅源代码文档。

4.5.JSP的局限性

在运行使用嵌入式servlet容器(并打包为可执行归档文件)的Spring引导应用程序时,JSP支持存在一些限制。

a.对于Jetty和Tomcat,如果使用war打包,它应该可以工作。一个可执行的war在使用java -jar启动时可以工作,并且可以部署到任何标准容器中。使用可执行jar时不支持jsp。

b.Undertow不支持jsp。

c.创建自定义error.jsp页面不会覆盖默认的错误处理视图。应该使用自定义错误页面。

5.嵌入式反应服务器支持

Spring Boot包含对以下嵌入式反应性web服务器的支持:Reactor Netty、Tomcat、Jetty和Undertow。大多数开发人员使用适当的“Starter”来获得完全配置的实例。默认情况下,嵌入式服务器监听端口8080上的HTTP请求。

6.服务器资源配置

在自动配置反应器Netty或Jetty服务器时,Spring Boot将创建特定的bean,为服务器实例提供HTTP资源:ReactorResourceFactory或JettyResourceFactory。

默认情况下,这些资源也将与反应器Netty和Jetty客户端共享,以获得最佳性能,具体如下:

a.服务器和客户机使用相同的技术

b.客户端实例是使用WebClient构建的。Builder bean由Spring Boot自动配置

开发人员可以通过提供定制的ReactorResourceFactory来覆盖Jetty和Reactor Netty的资源配置

原文地址:https://www.cnblogs.com/muxi0407/p/12070720.html

时间: 2024-11-02 10:47:57

SpringBoot学习(四)开发web应用的相关文章

Web Service学习-CXF开发Web Service实例demo(一)

Web Service是什么? Web Service不是框架.更甚至不是一种技术. 而是一种跨平台,跨语言的规范 Web Service解决什么问题: 为了解决不同平台,不同语言所编写的应用之间怎样调用问题.比如.有一个C语言写的程序.它想去调用java语言写的某个方法. 集中解决:1,远程调用 2.跨平台调用 3,跨语言调用 实际应用: 1.同一个公司的新,旧系统的整合.Linux上的java应用,去调用windows平台的C应用 2,不同公司的业务整合.业务整合就带来不同公司的系统整合.不

SpringBoot学习(四)--&gt;SpringBoot快速入门,开山篇

SpringBoot是伴随着Spring4.0诞生的,旨在简化开发. SpringBoot官方文档:http://spring.io/projects/spring-boot 写个示例:Hello SpringBoot 1.创建Maven工程 工程结构如下: 2.配置pom.xml文件 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchem

Web Service学习-CXF开发Web Service的权限控制(二)

Web Service如何进行权限控制? 解决思路:服务器端要求input消息总是携带有用户名,密码信息,如果没有用户名和密码信息,直接拒绝调用 解决方案:拦截器 为了让程序员能访问,并修改CXF框架所生成的SOAP消息,CXF提供了拦截器 CXF(Celtix +XFire)说明: 如果不用CXF等框架,SOAP消息的生成,解析都是由程序员负责.无论是添加用户名,密码信息还是提取用户名,密码信息,都可由程序员代码完成. 如果使用CXF等框架,SOAP消息的生成,解析都是由CXF等框架来完成.

尚硅谷springboot学习20-web开发简介

使用SpringBoot 1).创建SpringBoot应用,添加我们需要的模块: 2).SpringBoot已经默认将这些场景配置好了,只需要在配置文件中指定少量配置就可以运行起来 3).自己编写业务代码: 深入理解自动配置原理 这个场景SpringBoot帮我们配置了什么?能不能修改?能修改哪些配置?能不能扩展?xxx xxxxAutoConfiguration:帮我们给容器中自动配置组件: xxxxProperties:配置类来封装配置文件的内容: 原文地址:https://www.cnb

尚硅谷springboot学习21-web开发-处理静态资源

SpringBoot对静态资源的映射规则 @ConfigurationProperties(prefix = "spring.resources", ignoreUnknownFields = false) public class ResourceProperties implements ResourceLoaderAware { //可以设置和静态资源有关的参数,缓存时间等 WebMvcAuotConfiguration: @Override public void addRes

Gradle学习(四) web工程构建

Gradle为应用开发提供了两个相关的插件:war plugin以及jetty plugin war plugin继承了java plugin为你的工程构建war包,jetty pugin继承了war plugin可以让的工程构建在嵌入式容器jetty中 构建War文件 首先在你的build.gradle中添加如下一行 apply plugin: 'war' 由于war plugin继承了java plugin,所有java plugin也会被默认的加入配置文件中 运行gradle build命

程序员带你学习安卓开发,十天快速入门-基础知识(四)

关注今日头条-做全栈攻城狮,学代码也要读书,爱全栈,更爱生活.提供程序员技术及生活指导干货. 如果你真想学习,请评论学过的每篇文章,记录学习的痕迹. 请把所有教程文章中所提及的代码,最少敲写三遍,达到熟悉的效果. 本系列课程是.Net程序员学习安卓开发系列课程. 下面是前三次课程列表: 程序员带你学习安卓开发,十天快速入门-安卓学习必要性 程序员带你学习安卓开发,十天快速入门-开发工具配置学习 程序员带你学习安卓开发,十天快速入-对比C#学习java语法 为了大家系统有效的快速入门安卓开发,推荐

学习IOS开发UI篇--UI知识点总结(四) UITabelView/UITableViewCell

UITabelView:常用属性 @property (nonatomic)          CGFloat    rowHeight;             // will return the default value if unset @property (nonatomic)          CGFloat     sectionHeaderHeight;   // will return the default value if unset @property (nonatom

NVIDIA Jetson TK1学习与开发(四):一些细节问题

本文把自己在学习或开发Jetson TK1过程中遇到的一些细节性的问题罗列出来,并提供解决方案. 首先就是wiki上提供的一些注意事项,网址:http://elinux.org/Jetson_TK1 1.An important step before connecting the Jetson to Internet It is really important to tell "apt" not to overwrite the file "libglx.so"

Cmdlet开发与学习(四)

前面讲完了一个基本的cmdlet的开发流程,下面将陆续地完善cmdlet的功能细节以及补充.       支持ShouldProcess       有的cmdlet操作有很大的破坏性,因此有必要再命令执行前提醒用户注意一些可能的执行后果,也就是说,存在与用户的交互.这个时候,通过使用ShouldProcess,可以达到预期的效果. 1 [Cmdlet(VerbsCommon.Get,"SQLServerBackupFile", 2 SupportsShouldProcess = tr