拦截器简概
核⼼接⼝
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。
拦截器
官方文档地址:https://docs.spring.io/spring-framework/docs/current/reference/html/web.html#mvc-exceptionhandlers
另可参考:https://blog.csdn.net/qq_34246965/article/details/122943699
所有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,或者直接在RequestMappingHandlerAdapter
上配置它。
配置拦截器
官网文档地址:https://docs.spring.io/spring-framework/docs/current/reference/html/web.html#mvc-config-interceptors
在Java配置中,可以注册拦截器作用到传入的请求,如下面的例子所示:
@Configuration
@EnableWebMvc // Spring Boot中想彻底⾃⼰控制 MVC 配置就带上@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry 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路径中许多不需要的字符。