简介
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 de
serializer
如果使用
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