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