【Web开发】Spring MVC 的拦截器

发布于:2022-11-13 ⋅ 阅读:(599) ⋅ 点赞:(0)

拦截器简概

核⼼接⼝

  • 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直接注册它们。

对于@ResponseBodyResponseEntity方法,postHandle方法就不太有用了,因为它们的响应是在HandlerAdapter内部和postHandle之前编写和提交的。这意味着要对响应进行任何更改(例如添加额外的标头)都太晚了。对于这样的场景,可以实现ResponseBodyAdvice并将其声明为 Controller Advice bean,或者直接在RequestMappingHandlerAdapter上配置它。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VkfRLhk8-1668266544435)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/042b22c4e4184c4c9f20a8a60ed2924b~tplv-k3u1fbpfcp-zoom-1.image)]

配置拦截器

官网文档地址: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路径中许多不需要的字符。

本文含有隐藏内容,请 开通VIP 后查看