Spring Web MVC
Spring Web MVC 是基于 Servlet 容器,使用 Spring
框架来开发 http web 服务。
web 服务启动时的初始化顺序: ServletContext -> listener -> filter -> servlet spring bean 的初始化是在 listener 中声明的, 保证了可以在后续流程中使用.
配置管理
使用 Spring Environment 将服务的配置和部署环境解耦,通过
spring.profiles.active=<profile1,...>
激活的配置来加载相关的配置。
配置的数据源:
- 命令行参数
- 系统的环境变量
- application 配置文件,支持
.properties和.yml/.yaml文件格式,推荐使用 yaml 格式application文件application-<profile>文件
@Configuration + @PropertySource指定的自定义配置文件
配置的优先级从小到大:
- 命令行参数
- 系统环境变量
- Jar 包外部同级目录下的
application-<profile>文件 - Jar 包外部同级目录下的
application文件 - Jar 包内部的
application-<profile>文件 - Jar 包内部的
application文件
Filter
- Servlet 规范规定的,只能用于 Web 服务中, 由
Servlet 容器提供支持 - 作用于 Servlet 执行前后
1 |
|
必须要对启动类添加注解ServletComponentScan才能让自定义的Filter其效果.
在filterChain.doFilter调用的前后来执行操作, 作用于Servlet之前的前后.
DispatcherServlet
为 Spring 框架定制的 Servlet, 用来对请求进行处理的入口。
- 路由,获取请求处理链HandlerExecutionChain以及相应的HandlerAdapter
- 通过HandlerAdapter对请求进行处理
- 使用Interceptor对request/response进行拦截
- 对异常进行处理
Spring
MVC中的各种相关配置可参考WebMvcAutoConfigurationAdapter.
通过定义一个或者多个WebMvcConfigurer来扩展Spring
MVC中的配置
路由
通过对 handler 方法添加 @RequestMapping
注解来定义请求处理器的匹配要求,
生成对应的RequestMappingInfo和多个RequestCondition,
用于请求路由, 选择最匹配的 handler 方法来处理请求。
1 |
|
DispatcherServlet::getHandler用于获取请求处理链
HandlerExecutionChain, 通过比较 RequestMappingInfo 和
RequestCondition,查找最匹配的 Handler 方法。 定义的 RequestCondition
越多,则 Handler 的针对性越强;反之,则 Handler 越通用。
Interceptor 拦截器
Interceptor 用于对请求对 handler 方法进行拦截, 处理一些和请求没有依赖的业务,比如鉴权,日志等
- 作用于 handler 方法,在其前后执行
- 不能修改request
- Spring 中优先使用 Interceptor, 而不是 filter
1 | public class CustomizedInterceptor extends HandlerInterceptorAdapter { |
请求处理
通过 HandlerAdapter 增强 handler 方法来对请求进行处理。
HandlerAdapter.handle主要做以下几件事:
HandlerMethodArgumentResolver对输入参数进行解析- 调用 handler 方法对请求进行处理
HandlerMethodReturnValueHandler对返回进行处理- ExceptionHandler异常统一处理
基于 String 输入的参数解析
主要是针对 path/query string/header
中的参数进行解析。
通过定义 Converters 中的 bean,就可以在启动时 通过
WebMvcAutoConfigurationAdapter#addFormatters 添加进来,
用于 AbstractNamedValueMethodArgumentResolver
的输入类型转换。
1 | // Money.java |
针对 Body 的输入和输出处理
通过 HttpMessageConverter 对 body 进行序列化和反序列化,
其中最常用的就是 json
的处理模块MappingJackson2HttpMessageConverter.
通过定义 HttpMessageConverters 的bean,将自定义的
HttpMessageConverter 添加进来, 通过
WebMvcAutoConfigurationAdapter#configureMessageConverters
进行注册
1 | // StringConverter.java |
JacksonJson序列化的支持
Spring
MVC中提供了MappingJackson2HttpMessageConverter对json对象进行序列化处理。
通过JsonComponnet相关的bean来注册JSON序列化组件
- JsonSerializer
- JsonDeserializer
1 |
|
参数校验
TODO
Exception处理
通过定义注解 @ExceptionHandler 对请求 Handler
方法抛出的异常进行处理。
处理的优先级从小到大:
- Controller 层异常处理
- (required) ControllerAdvice 全局异常处理
统一 Response
统一 Response 的目的是让对接的客户端能够以统一的方式来判断响应的结果,尤其是针对错误返回的场景。 判断响应结果的依据:
- http status code
- 业务相关的错误码
常见的统一 Response 结构:
1 | // 错误响应 |
Spring MVC 中通过 ResponseBodyAdvice
对返回结果进行统一处理, 它会在 handler 方法的返回值写入 response
前被调用;
如果正常响应不需要统一结构的响应,那么只需要在异常处理场景中返回错误响应结构即可。
测试
TODO
异步任务处理
- 应用内异步执行
@Async + 线程池@Async + Application Event
- 基于 MQ 分布式异步执行
@Async + 线程池
1 |
|
@Async + Application Event
Application Event 采用发布/订阅模式,基于事件驱动的方式处理本地的异步任务,用于服务内解耦,服务重启后事件丢失。
- 通过
ApplicationEventPublisher.publishEvent来发布事件 - 通过
@EventListener来监听事件
如果没有开启
@EnableAsync,则默认为同步处理;只有开启后才会使用相关联的线程池进行异步处理。
1 | // 异步执行配置 |
基于 MQ
适用场景:跨服务异步、削峰填谷、保证最终一致性
RPC 调用
- RestTemplate
- (推荐) Feign
TODO
Reference
- JSR 340: Java Servlet 3.1 Specification
- 中文翻译
- Spring MVC
- 玩转Spring全家桶 — 46 | Spring MVC中的常用视图(上)
- SpringMVC系列(一)核心:处理请求流程
- Spring Boot :Request请求处理流程
- Spring MVC工作流程以及请求处理流程
- 码农小汪-Spring MVC -DispatcherServlet 详解
- Servlet 工作原理解析
- Spring filter和拦截器(Interceptor)的区别和执行顺序
- Spring Boot 使用 Servlet、Filter、Listener
- SpringMVC源码剖析(五)-消息转换器HttpMessageConverter
- Spring MVC HandlerMapping HandlerAdapter
- SpringMVC中WebDataBinder的应用及原理
- 说说Spring中的WebDataBinder
- Spring Boot:定制HTTP消息转换器
- Spring Boot 统一异常处理最佳实践 – 拓展篇
- Spring IoC⭐️什么是 IoC?
- 掌握Spring Environment:配置管理的关键
- 详细分析ResponseBodyAdvice的使用与原理
- Spring MVC异步处理架构实战:线程池+消息队列+事件驱动+反应式高并发性能优化