简介
spring boot 非常适合进行web程序开发。可以通过使用spring-boot-starter-web快速创建一个内嵌tomcat或Jetty,或netty的应用。也可以通过使用spring-boot-starter-webflux创建交互式的应用。
Spring Web MVC框架
springMVC框架是一个基于“model,view,controller"的web框架,spring MVC让你可以@c
ontroller
或者 @RestController
beans 去处理http的请求。在你的control的方法中将会使用@RequestMapping 映注解映射成URL。
以下是
01. spring mvc的自动配置
@RestController
列子处理json数据:代码如下:@RestController
@RequestMapping(value="/users")
public class MyRestController {
@RequestMapping(value="/{user}", method=RequestMethod.GET)
public User getUser(@PathVariable Long user) {
// ...
}
@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) {
// ...
}
}
为大多数的应用都配置了spring mvc自动配置 。其自动配置默认在spring的基础上增加了如下特性:
- 包含了ContentNegotiatingViewResolver(根据请求头输出不同的形式:例如xml,json)与BeanNameViewResolver(返回的逻辑视图名称去匹配定义好的视图bean对象)。
- 支持服务静态资源(包括WebJars )
- 自动注册
Converter
,GenericConverter
, 与Formatter
beans -
支持
HttpMessageConverters
-
自动注册
MessageCodesResolver
- 静态index.html支持
- 自定义
Favicon
支持 - 自动使用ConfigurableWebBindingInitializer
如果想保持Spring Boot MVC特性,你想要添加附加的MVC 配置(interceptors, formatters, view controllers, 与其他配置)。你可以不使用@EnableWebMvc,而是添加其@Configuration配置类其。如果你希望提供自定义的
RequestMappingHandlerMapping
, RequestMappingHandlerAdapter
, or ExceptionHandlerExceptionResolver的
实例。可以使用WebMvcRegistrationsAdapter提供组件。
如果想完全控制MVC,通过使用@Configuration与
@EnableWebMvc 。
02. httpMessageConverters
Spring MVC 使用httpMessageConverters来转换http请求与响应。合理的默认值应该包含哪些不确定的情况,例如:对象可能会自动的被转换为JSON或者XML。默认情况下使用UTF-8.
如果要添加或者自定义的转换器,可以使用Spring Boot的
HttpMessageConverters类
其代码如下:import org.springframework.boot.autoconfigure.web.HttpMessageConverters;
import org.springframework.context.annotation.*;
import org.springframework.http.converter.*;
@Configuration
public class MyConfiguration {
@Bean
public HttpMessageConverters customConverters() {
HttpMessageConverter<?> additional = ...
HttpMessageConverter<?> another = ...
return new HttpMessageConverters(additional, another);
}
}
03. 自定义json serializer与json deserializer
如果使用Jackson去串行化一个数据或对象话一个json 数据,可能需要些自己的json对象转换器。自定义的json转换器通过一个module的形式注册到JsonComponent ,其提供了
@JsonComponent
使其能够快速注册到json上去。你可以使用@JsonComponent
直接进行n JsonSerializer
or JsonDeserializer
的转换,也可以使用内部类的形式:代码如下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> {
// ...
}
}
使用 @JsonComponent
会自动注册到jackson,因为@JsonComponent
的元数据使用@Component,数,component-scanning能够被应用。
04. messageCodeResolver
spring mvc 提供了
MessageCodesResolver
来根据产生的错误码来提示对应的错误信息。如果你设置了spring.mvc.message-codes-resolver.format属性 PREFIX_ERROR_CODE
或者是POSTFIX_ERROR_CODE
05.静态内容
默认情况下,spring boot 将根据经下的
/static
( /public
, /resources
, /META-INF/resources
)作为静态资源路径,它使用来自于from Spring WebFlux的ResourceWebHandler以便能修改其行为。
默认情况下,资源被映射成
/**
,,但是可以通过设置spring.webflux.static-path-pattern
进行调整,例如将资源重定位到 /resources/**
下,可以使用如下配置spring.webflux.static-path-pattern=/resources/**
通过使用 spring.resources.static-locations
可以自定义资源路径位置。也可以通过使用webjar的方式如果其打包为jar。
Spring Boot 也支持spring mvc支持的资源特性。允许使用cache-busting静态资源或者是对于Webjars使用未知版本资源。对于使用未知版本的webjar资源,需要添加
webjars-locator
依赖。比如:使用jquery为例:使用"/webjars/jquery/dist/jquery.min.js"
的结果为 "/webjars/jquery/x.y.z/dist/jquery.min.js"
.。如果使用jboss的话还需要依赖 webjars-locator-jboss-vfs
,否则会报404错误。
使用缓存清楚(cache busting),接下来的配置配置了对所有静态资源缓存清楚。高效的添加hash值内容。例如,在URL中的内容:
<link href="/css/spring-2a2d595e6ed9a0b24f027f2b63b134d6.css"/>
,、其主要配置为:spring.resources.chain.strategy.content.enabled=true
spring.resources.chain.strategy.content.paths=/**
当动态加载资源的时候,js模块加载,文件命名是不打开的,那就是为什么其他策略被支持并且能够被组合。一种修订的策略是在URL中 "fixed"中修定一个静态版本,不用更改其名字。如下配置: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版本使用 "/js/lib/"
使用上述配置之后为 ("/v12/js/lib/mymodule.js"
),其他的资源内容也是如下 (<link href="/css/spring-2a2d595e6ed9a0b24f027f2b63b134d6.css"/>
).
06. 开始页
Spring Boot支持静态的和模板的开始页。其首先在配置静态内容中寻找index.html.如果没有发现,则查找使用静态模板。
07. 自定义收藏夹图标
Spring Boot 寻找收藏夹图标在静态位置或者是classpath的根路径。
08. 配置web绑定初始化
Spring MVC使用
WebBindingInitializer
去初始化WebDataBinder初和特殊的请求。如果你创建ConfigurableWebBindingInitializer@bean,Spring Boot自动配置 Spring MVC 去配置它。09. 模板引擎
像REST 的web service一样,你可以使用 Spring MVC 动态填充内容。spring mvc支持不同的模板技术:Thymeleaf, FreeMarker, 与JSPs。包括其spring mvc自身的操作。
包括自动配置的支持的模板引擎如下:
如果使用默认的模板位置的话:其配置路径如下:
src/main/resources/templates
10. 错误处理
默认情况下, Spring Boot以一种合理的方式提供了/error mapping的映射处理。其在servlet container中作为一种全局的错误页,对于机器的客户端,其产生一个json格式的错误信息(包括http状态,以及异常信息)。对于浏览器客户端,有一种叫做“whitelabel”的错误,以html的格式渲染。完全替换默认的行为,可以实现一个
ErrorController
注册一个bean的类型并且添加一个 ErrorAttributes
的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);
}
}
10.1 自定义错误页
如果想要对给定的错误状态展示一个自定义的错误页。可以添加一个
/error
的文件夹。错误页面可以是一个静态的HTML或者是一个使用模板构建的。文件的名字必须要有准备的状态码或者是一系列的掩码。
例如:如果要映射成404到一个静态页面,文件结构应该如下:
src/
+- main/
+- java/
| + <source code>
+- resources/
+- public/
+- error/
| +- 404.html
+- <other public assets>
通过使用模板映射到5xx的错误,你的文件夹的结构应该如下:src/
+- main/
+- java/
| + <source code>
+- resources/
+- templates/
+- error/
| +- 5xx.ftl
+- <other templates>
对于一些比较复杂的映射,可以通过实现接口 ErrorViewResolver
来完成,如下列子
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 ...
}
}
10.2 非spring mvc映射错误文件
对于没有使用spring mvc的应用,可以通过实现接口
ErrorPageRegistrar
指向错误页面,如下代码所示:@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"));
}
}
如果注册的错误文件的路径在一个过滤器里面,其Filter
要指定错误的分发:如下代码@Bean
public FilterRegistrationBean myFilter() {
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(new MyFilter());
...
registration.setDispatcherTypes(EnumSet.allOf(DispatcherType.class));
return registration;
}
10.3在websphere上处理错误
默认情况下,WebSphere 8.0以后的版本通过servlet的服务方法能够完全完成,需要将其
com.ibm.ws.webcontainer.invokeFlushAfterService
设置为false。
11. spring hateoas
如果使用超文本开发api,spring boot 为Spring HATEOAS提供了自动配置来很好的为应用程序服务。其自动配置使用
@EnableHypermediaSupport
替换了 需求,和注册了一系列的bean使超文本易于构建。包括LinkDiscoverers
与ObjectMapper
的配置去编排成想要的结果信息。其 ObjectMapper
通过设置spring.jackson.*
来进行个性化。
可以通过使用
@EnableHypermediaSupport
来配置HATEOAS’s配置。这种方式可以让 ObjectMapper
较早的使用。
12.cors 支持(跨域访问的支持)
Cross-origin resource sharing (CORS)是被大多数的浏览器通过w3c的方式,允许你指定一种灵活的方式对于跨越资源的请求的授权。代替使用更弱的方式实现(例如 IFRAME or JSONP)
从spring 4.2开始,spring mvc 支持了跨越访问。通过使用
@CrossOrigin
配置,不需要使用其他的任何的特殊的配置。可以通过自定义的addCorsMappings(CorsRegistry)
注册方法注册 WebMvcConfigurer
bean,如下代码:
@Configuration
public class MyConfiguration {
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/**");
}
};
}
}
Spring WebFlux框架
spring webflux是在spring 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")
Flux<Customer> getUserCustomers(@PathVariable Long user) {
// ...
}
@DeleteMapping("/{user}")
public Mono<User> deleteUser(@PathVariable Long user) {
// ...
}
}
其功能性的变量“WebFlux.fn”:将实际处理请求与路由配置进行分离。如下代码:@Configuration
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) {
// ...
}
}
通用使用spring-boot-starter-webflux
配置,可以添加webflux(注意:通过添加spring-boot-starter-web
与 spring-boot-starter-webflux
将会导致webflux不会生效)。
01. 自动配置
自动配置除了支持spring的基本特性外,还添加了如下特性:
-
配置
HttpMessageReader
与HttpMessageWriter
与实例 - 支持静态资源(包括webjar)
如果想完全控制spring WebFlux,可以通过使用
@EnableWebFlux
配置。
02. http解码器httpmessageheader与httpmessagewriter
Spring WebFlux使用
HttpMessageReader
与HttpMessageWriter
转换器请求。他们通过用CodecConfigurer在类路径中配置。spring boot 通过使用 CodecCustomizer
实例。例如:spring.jackson.*,配置主键被应用于Jackson 中。如果想自定义转码为其,可以通过创建 CodecCustomizer
来处理:import org.springframework.boot.web.codec.CodecCustomizer;
@Configuration
public class MyConfiguration {
@Bean
public CodecCustomizer myCodecCustomizer() {
return codecConfigurer -> {
// ...
}
}
}
03. 静态内容
通过指定静态路径配置对应的路径信息:spring.webflux.static-path-pattern=/resources/**
04. 模板引擎
05. 错误处理
06. 自定义错误页面
与spring mvc类似
JAX-RS与JERSEY
如果你更喜欢 JAX-RS的restful endpoint编程模型,你可以使用它代替spring mvc。如果你在你的应用程序中注册他们的servlet或者是filter作为一个bean,Jersey 1.x 与 Apache CXF 会工作的更好。Jersey 2.x提供了对spring的支持,因此我们可以将其封装成一个starter。
在使用 Jersey 2.x的时候,需要依赖
spring-boot-starter-jersey
。你需要一个 ResourceConfig
的类型的bean注册到所有的端点。如下代码:@Component
public class JerseyConfig extends ResourceConfig {
public JerseyConfig() {
register(Endpoint.class);
}
}
你可以注册任意多的bean去实现多个高级化的配置。所有的注册的endpoints必须使用 @Components
,如下代码所示:@Component
@Path("/hello")
public class Endpoint {
@GET
public String message() {
return "Hello";
}
}
因为 Endpoint
是一个 spring Endpoint
,其生命周期是被spring进行管理。可以使用自动注解@Autowired以及@Value
去注入外部配置。默认 Jersey servlet被注册并且被mapping成为“/*”.可以在 ResourceConfig
中通过添加@ApplicationPath
改变其mapping。
默认情况下:Jersey 安装成一个
ServletRegistrationBean
的名字为jerseyServletRegistration的bean。默认,其servlet是lazily。你可以通过配置 spring.jersey.servlet.load-on-startup
改变其行为。你可以停用或者是通过定义相同的名字覆盖其配置。也可以通过设置 spring.jersey.type=filter
使用filter进行替换。
内嵌容器的支持
默认的内嵌容器:tomcat,默认的端口为8080.
01. servlets,filters,listener.
当使用内嵌容器的时候,也可以通过servlet标准定义servlets,filter与listener
02. 容器初始化
内嵌的容器不是执行servlet 3.0+,
javax.servlet.ServletContainerInitializer
或者是org.springframework.web.WebApplicationInitializer
接口。这减少地方包在运行一个war包范围内的情况下,会损坏spring boot。
如果执行容器初始化,需要注册一个实现
org.springframework.boot.web.servlet.ServletContextInitializer
的bean。其启动方法提供了 ServletContext
的链接以及如果必要,能够被很容易实现已经存在的WebApplicationInitializer的实现。
扫描servlets,filters,listerners:
可以通过
@WebServlet
, @WebFilter
, 与@WebListener自动完成扫描
03. 自定义内嵌的容器
通用的servlet容器配置可以通过spring的环境变量配置。通常,你可以在application.properties中进行设置。
通用的设置包括:
- 网络设置(包括:server.port与server.address)
- session设置(server.session.persistence,server.session.timeout以及server.session.store-dir与)
- 错误管理(server.error.path:错误信息地址)
- SSL
- HTTP compression
程序自定义
可以通过实现WebServerFactoryCustomizer接口,其通过了对ConfigurableServletWebServerFactory的链接。包括自定义的配置:其代码如下:
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);
}
}
自定义话configuration目录,其代码如下:@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;
}
当使用内嵌容器的时候,这儿有一些JSP支持方面的限制:
- tomcat 如果使用war包的话,它也应该能够工作。既一个war包可以部署到单独的容器中。一个单独的executable jar将不会工作。
- Jetty 使用war包也能够工作
- Undertow 不支持jsp
- 自定义的错误页面不应该覆盖默认的错误页面
以上内容参考https://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#boot-features-error-handling