拦截器简概
核⼼接⼝
- HandlerInteceptor
- boolean preHandle()
- void postHandle()
- void afterCompletion()
针对 @ResponseBody 和 ResponseEntity 的情况
- ResponseBodyAdvice
针对异步请求的接⼝
- AsyncHandlerInterceptor
- void afterConcurrentHandlingStarted()
拦截器的配置⽅式
常规⽅法
- WebMvcConfigurer.addInterceptors()
Spring Boot 中的配置
- 创建⼀个带 @Configuration 的 WebMvcConfigurer 配置类
- 不能带 @EnableWebMvc(想彻底⾃⼰控制 MVC 配置除外)
如果你想保留那些Spring Boot MVC定制,并做更多的MVC定制(拦截器、格式化器、视图控制器和其他功能),你可以添加你自己的WebMvcConfigurer类型的@Configuration类,但不需要@EnableWebMvc。
拦截器
官方文档地址: Spring .io/spring-framework/docs/current/reference/html/web.html#mvc-exceptionhandlers
另可参考:
所有HandlerMapping实现都支持 handler 拦截器,在需要将某些特定功能应用于某些请求时(例如,检查权限),这些拦截器非常有用。想要定制一个拦截器必须实现org.springframework.web.servlet包下的HandlerInterceptor接口,它有三个抽象方法(已有默认实现)——这提供了足够的灵活性来进行各种预处理和后处理:
- preHandle (..): 在实际 handler 运行之前
- postHandle (..): 在运行 handler 之后
- afterCompletion (..): 在完成完整的 request 之后
preHandle(..)方法返回一个 布尔 值 。可以使用此方法中断或继续执行链的处理。 当这个方法返回true时 , handler 执行链将继续。 当它返回false时 , DispatcherServlet 假定拦截器本身已经处理了请求(例如,呈现了一个适当的视图),不再继续执行执行链中的其他拦截器和实际的处理程序。
有关如何配置 拦截器 的示例,可参见MVC configuration 部分中的拦截器。也可以通过在单独的HandlerMapping实现上使用setters直接注册它们。
对于@ResponseBody和ResponseEntity方法, postHandle 方法就不太有用了,因为它们的响应是在HandlerAdapter内部和postHandle之前编写和提交的。这意味着要对响应进行任何更改(例如添加额外的标头)都太晚了。对于这样的场景,可以实现ResponseBodyAdvice并将其声明为 Controller Advice bean,或者直接在 Request MappingHandlerAdapter上配置它。

配置拦截器
官网文档地址:#mvc-config-interceptors
在 Java 配置中,可以注册拦截器作用到传入的请求,如下面的例子所示:
@Configuration
@EnableWebMvc // Spring Boot中想彻底⾃⼰控制 MVC 配置就带上@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(Interceptor Registry registry) {
registry.addInterceptor(new LocaleChangeInterceptor());
registry.addInterceptor(new ThemeChangeInterceptor()).addPathPatterns("/**").excludePathPatterns("/admin/**");
}
}
下面的例子展示了如何在XML中实现相同的配置:
<mvc:interceptors>
<bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor"/>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<mvc:exclude-mapping path="/admin/**"/>
<bean class="org.springframework.web.servlet.theme.ThemeChangeInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
注意点:把 映射拦截器作为安全层,其实是不太合适的,因为它可能与带注解的 controller 路径 匹配不匹配。带注解的 controller 可以透明地匹配尾随斜杠和路径扩展,以及其他路径匹配选项。虽然这些选项中的许多已经被弃用,但不匹配的可能性仍然存在。 一般来说,我们推荐使用 Spring Security ,它有一个专门的 MvcRequestMatcher 来匹配 Spring MVC 的路径匹配,同时也有一个安全防火墙来阻止URL路径中许多不需要的字符。