1 2 3
| 环境: - org.springframework:spring-webmvc:5.3.10 - org.springframework.boot:spring-boot:2.5.5
|
web程序启动时的初始化顺序: ServletContext -> listener -> filter -> servlet spring bean的初始化是在listener中声明的, 可以在后面使用.
Filter
- Servlet规范规定的,只能用于Web程序中, 由Servlet容器提供支持
- 作用于Servlet执行前后
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| @Order(1) @WebFilter(filterName = "customized", urlPatterns = "/*") public class CustomizedFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { log.info("CustomizedFilter Init"); }
@Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { log.info("CustomizedFilter doFilter before");
filterChain.doFilter(servletRequest, servletResponse);
log.info("CustomizedFilter doFilter after"); }
@Override public void destroy() { log.info("CustomizedFilter destroy"); } }
|
必须要注解ServletComponentScan才能让自定义的Filter其效果.
在filterChain.doFilter调用的前后来执行操作, 作用于Servlet之前的前后.
DispatcherServlet
为Spring框架定制的Servlet, 用来对请求进行处理
- 获取请求处理链HandlerExecutionChain以及相应的HandlerAdapter
- 通过HandlerAdapter对请求进行处理
- 使用Interceptor对request/response进行拦截
- 对异常进行处理
Spring MVC中的各种相关配置可参考WebMvcAutoConfigurationAdapter
. 通过定义一个或者多个WebMvcConfigurer
来扩展Spring MVC中的配置
获取Handler
通过@RequestMapping
注解定义方法Handler的匹配要求, 生成对应的RequestMappingInfo
和多个RequestCondition
, 用于请求匹配, 匹配成功后调用对应的方法Handler。
1 2 3 4 5 6 7 8 9
| @RequestMapping(value = "/{ping}", method = RequestMethod.GET) public String getPingPong( String ping) { return ping; }
@GetMapping(value = "/{ping}", params = "ex=1") public String getPingPongEx( String ping) { return ping + " Ex"; }
|
DispatcherServlet::getHandler
用于获取请求处理链HandlerExecutionChain, 通过比较RequestMappingInfo和RequestCondition,查找最匹配的方法Handler。 定义的RequestCondition越多,则方法Handler的针对性越强;反之,则方法Handler越通用。
通过HandlerAdapter处理请求
HandlerAdapter.handle
主要做以下几件事:
HandlerMethodArgumentResolver
对输入参数进行解析
- 调用handler对请求进行处理
HandlerMethodReturnValueHandler
对返回进行处理
- ExceptionHandler异常统一处理
基于String输入的参数解析
通过定义Converters中的bean,就可以在启动时 通过WebMvcAutoConfigurationAdapter#addFormatters
添加进来, 用于AbstractNamedValueMethodArgumentResolver
的输入类型转换。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| @Getter @Setter public class Money { private String currency = "CNY"; private String value;
@Override public String toString() { return currency + " " + value; } }
@Component public class MoneyFormatter implements Formatter<Money> { @Override public Money parse(String text, Locale locale) throws ParseException { String[] input = text.split(" "); Money money = new Money(); if (input.length == 1) { money.setValue(input[0]); } else { money.setCurrency(input[0]); money.setValue(input[1]); } return money; }
@Override public String print(Money object, Locale locale) { return object.getCurrency() + " " + object.getValue(); } }
@GetMapping(value = "/price") public Money price( Money money) { return money; }
|
针对Body的输入和输出处理
通过HttpMessageConverter
对body进行序列化和反序列化, 其中最常用的就是json的处理模块MappingJackson2HttpMessageConverter
.
通过定义HttpMessageConverters
的bean,将自定义的HttpMessageConverter
添加进来, 通过WebMvcAutoConfigurationAdapter#configureMessageConverters
进行注册
1 2 3 4 5 6 7 8 9 10
| public StringConverter implements HttpMessageConverter<String> { ... }
@Bean public HttpMessageConverters converters() { return new HttpMessageConverters(new StringConverter()); }
|
JacksonJson序列化的支持
Spring MVC中提供了MappingJackson2HttpMessageConverter
对json对象进行序列化处理。 通过JsonComponnet相关的bean来注册JSON序列化组件
- JsonSerializer
- JsonDeserializer
1 2 3 4 5 6 7 8 9 10 11 12
| @JsonComponent public class MoneyJson extends StdSerializer<Money> {
protected MoneyJson() { super(Money.class); }
@Override public void serialize(Money money, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException { jsonGenerator.writeString(money.toString()); } }
|
Interceptor
Interceptor用于对Controller层进行拦截, 处理一些和controller没有依赖的业务,比如鉴权,日志等
- 作用于Controller前后执行
- 不能修改request
- spring中优先使用Interceptor, 而不是filter
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| public class CustomizedInterceptor extends HandlerInterceptorAdapter {
@Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { log.info("CustomizedInterceptor prehandle"); return true; }
@Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception { log.info("CustomizedInterceptor postHandle"); }
@Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception { log.info("CustomizedInterceptor afterCompletion"); }
}
@Configuration public class AppServiceConfig extends WebMvcConfigurationSupport {
@Autowired private CustomizedInterceptor customizedInterceptor;
@Override protected void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(customizedInterceptor).addPathPatterns("/**"); } }
|
Exception处理
对Request Mapping Handler方法抛出的异常进行处理。
- ExceptionHandler
- Controller层异常处理
- ControllerAdvice全局异常处理
Reference