• Spring Mvc 拦截器详解


    目录

     一、什么是拦截器

    二、拦截器配置

    三、定义拦截器

    四、 多个拦截器


     一、什么是拦截器

    Spring MVC中的拦截器(Interceptor)类似于Servlet中的过滤器(Filter),它主要用于拦截用户请求并作相应的处理。例如通过拦截器可以进行权限验证、记录请求信息的日志、判断用户是否登录等。

    所有 HandlerMapping 的实现都支持 handler 拦截器,当你想对某些请求应用特定的功能时,这些拦截器是非常有用的—​例如,检查一个 principal。拦截器必须实现 org.springframework.web.servlet 包中的 HandlerInterceptor,它有三个方法,应该可以提供足够的灵活性来进行各种预处理和后处理:

    • preHandle(..): 在实际 handler 运行之前

    • postHandle(..): handler 运行后

    • afterCompletion(..): 在整个请求完成后

    preHandle(..) 方法返回一个boolean值。你可以使用这个方法来中断或继续执行链的处理。当这个方法返回 true 时,handler 执行链继续进行。当它返回 false 时, DispatcherServlet 认为拦截器本身已经处理了请求(例如,渲染了一个适当的视图),并且不继续执行其他拦截器和执行链中的实际 handler。

    postHandle 方法在 @ResponseBody 和 ResponseEntity 方法中用处不大,因为这些方法的响应是在 HandlerAdapter 中和 postHandle 之前写入和提交的。这意味着对响应进行任何修改都太晚了,比如添加一个额外的 header。

    二、拦截器配置

    在Java配置中,你可以注册拦截器来应用于传入的请求,如下例所示:

    1. @Configuration
    2. @EnableWebMvc
    3. public class WebConfig implements WebMvcConfigurer {
    4. @Override
    5. public void addInterceptors(InterceptorRegistry registry) {
    6. registry.addInterceptor(new LocaleChangeInterceptor());
    7. registry.addInterceptor(new ThemeChangeInterceptor()).addPathPatterns("/**").excludePathPatterns("/admin/**");
    8. }
    9. }

    下面的例子显示了如何在XML中实现同样的配置:

    1. <mvc:interceptors>
    2. <bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor"/>
    3. <mvc:interceptor>
    4. <mvc:mapping path="/**"/>
    5. <mvc:exclude-mapping path="/admin/**"/>
    6. <bean class="org.springframework.web.servlet.theme.ThemeChangeInterceptor"/>
    7. </mvc:interceptor>
    8. </mvc:interceptors>

     映射的拦截器并不适合作为安全层,因为它有可能与注解的控制器路径匹配不匹配,它也可以透明地匹配尾部斜线和路径扩展,以及其他路径匹配选项。这些选项中的许多已经被废弃,但错配的可能性仍然存在。一般来说,我们推荐使用Spring Security,它包括一个专门的 MvcRequestMatcher,与Spring MVC的路径匹配保持一致,同时还有一个安全防火墙(security firewall),可以阻止URL路径中许多不需要的字符。

    三、定义拦截器

    1. package com.doker.interceptor;
    2. public class MyInterceptor implements HandlerInterceptor {
    3. /** * 预处理,controller 方法执行前 * 应用:用于身份认证、身份授权 * return true 放行,执行下一个拦截器,如果没有,执行 controller 中的方法 * return false 不放行,即不向下执行 */
    4. @Override
    5. public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    6. System.out.println("preHandle");
    7. return true;
    8. }
    9. /** * 后处理方法,controller 方法执行后,方法跳转 success.jsp 执行之前 * 应用:从modelAndView出发:将公用的模型数据(比如菜单导航)在这里传到视图,也可以在这里统一指定视图 */
    10. public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
    11. System.out.println("postHandle");
    12. }
    13. /** * success.jsp 页面执行后,该方法会执行 * 应用:统一异常处理,统一日志处理 */
    14. public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
    15. System.out.println("afterCompletion");
    16. }
    17. }

    四、 多个拦截器

    • 多个拦截器时,按照 springmvc.xml 配置的顺序执行。
    • (2个拦截器时) 拦截器1 preHandle 不放行,postHandle 和 afterCompletion 不会执行。
    • (2个拦截器时) 拦截器1 preHandle 不放行,拦截器2不执行。
    1. <mvc:interceptors>
    2. <mvc:interceptor>
    3. <!--拦截的资源URI-->
    4. <mvc:mapping path="/**"/>
    5. <!--不拦截哪些-->
    6. <!--<mvc:exclude-mapping path="" />-->
    7. <bean id="handlerInterceptorDemo1"
    8. class="com.doker.interceptor.MyInterceptor">
    9. </bean>
    10. </mvc:interceptor>
    11. <mvc:interceptor>
    12. <mvc:mapping path="/**"/>
    13. <bean id="handlerInterceptorDemo2"
    14. class="com.doker.interceptor.MyInterceptor1">
    15. </bean>
    16. </mvc:interceptor>
    17. </mvc:interceptors>

    所以,多个拦截器是按照配置的顺序决定的:handlerInterceptorDemo1—>handlerInterceptorDemo2。

  • 相关阅读:
    【建议收藏】5个神级AI提示词网站,让AI工具效率拉满
    【AIGC】Stable Diffusion Prompt 每日一练0916
    Xcode升级到15.0 解决DT_TOOLCHAIN_DIR问题
    历年行政区划码成品下载,欢迎白瞟,拿走不谢
    Windows10出现WIFI蓝牙图标消失,网卡驱动出现感叹号等无法上网的情况解决方案
    TensorFlow实战教程(二十四)-基于BiLSTM-CRF的医学命名实体识别研究(上)数据预处理
    RCU Library
    javascript的call、apply、bind的实现
    P1541 [NOIP2010 提高组] 乌龟棋(4维背包问题)
    【Spring项目中的Controller理解】
  • 原文地址:https://blog.csdn.net/leesinbad/article/details/133894847