SpringMVC的处理器拦截器HandlerInterceptor详解

 更新时间:2024年01月30日 10:20:51   作者:曹牛牛  
这篇文章主要介绍了SpringMVC的处理器拦截器HandlerInterceptor详解,SpringWebMVC的处理器拦截器,类似于Servlet开发中的过滤器Filter,用于处理器进行预处理和后处理,需要的朋友可以参考下

简介

SpringWebMVC的处理器拦截器,类似于Servlet开发中的过滤器Filter,用于处理器进行预处理和后处理。

应用场景

1、日志记录,可以记录请求信息的日志,以便进行信息监控、信息统计等。

2、权限检查:如登陆检测,进入处理器检测是否登陆,如果没有直接返回到登陆页面。

3、性能监控:典型的是慢日志。

HandlerInterceptor

public interface HandlerInterceptor {
   /**
     * 预处理回调方法,实现处理器的预处理(如检查登陆),第三个参数为响应的处理器,自定义Controller
     * 返回值:true表示继续流程(如调用下一个拦截器或处理器);false表示流程中断(如登录检查失败),不会继续调用其他的拦截器或处理器,此时我们需要通过response来产生响应;
   */
    boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception;
   /**
     * 后处理回调方法,实现处理器的后处理(但在渲染视图之前),此时我们可以通过modelAndView(模型和视图对象)对模型数据进行处理或对视图进行处理,modelAndView也可能为null。
   */
    void postHandle(
            HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
            throws Exception;
   /**
    * 整个请求处理完毕回调方法,即在视图渲染完毕时回调,如性能监控中我们可以在此记录结束时间并输出消耗时间,还可以进行一些资源清理,类似于try-catch-finally中的finally,但仅调用处理器执行链中
   */
    void afterCompletion(
            HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception;
}

拦截器适配器HandlerInterceptorAdapter

有时候我们可能只需要实现三个回调方法中的某一个,如果实现HandlerInterceptor接口的话,三个方法必须实现,不管你需不需要,此时spring提供了一个HandlerInterceptorAdapter适配器(种适配器设计模式的实现),允许我们只实现需要的回调方法。

public abstract class HandlerInterceptorAdapter implements AsyncHandlerInterceptor {
    /**
     * 默认是true
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        return true;
    }
    /**
     * This implementation is empty.
     */
    @Override
    public void postHandle(
            HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
            throws Exception {
    }
    /**
     * This implementation is empty.
     */
    @Override
    public void afterCompletion(
            HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception {
    }
    /**
     * 不是HandlerInterceptor的接口实现,是AsyncHandlerInterceptor的,AsyncHandlerInterceptor实现了HandlerInterceptor
     */
    @Override
    public void afterConcurrentHandlingStarted(
            HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
    }
}

这样在我们业务中比如要记录系统日志,日志肯定是在afterCompletion之后记录的,否则中途失败了,也记录了,那就扯淡了。一定是程序正常跑完后,我们记录下那些对数据库做个增删改的操作日志进数据库。所以我们只需要继承HandlerInterceptorAdapter,并重写afterCompletion一个方法即可,因为preHandle默认是true。

运行流程总结如下:

1、拦截器执行顺序是按照Spring配置文件中定义的顺序而定的。

2、会先按照顺序执行所有拦截器的preHandle方法,一直遇到return false为止,比如第二个preHandle方法是return false,则第三个以及以后所有拦截器都不会执行。若都是return true,则按顺序加载完preHandle方法。

3、然后执行主方法(自己的controller接口),若中间抛出异常,则跟return false效果一致,不会继续执行postHandle,只会倒序执行afterCompletion方法。

4、在主方法执行完业务逻辑(页面还未渲染数据)时,按倒序执行postHandle方法。若第三个拦截器的preHandle方法return false,则会执行第二个和第一个的postHandle方法和afterCompletion(postHandle都执行完才会执行这个,也就是页面渲染完数据后,执行after进行清理工作)方法。(postHandle和afterCompletion都是倒序执行)

正常流程Demo

package com.bshf.recipe.demo.syslog;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class SyslogInterceptor implements HandlerInterceptor {
    /**
     * 预处理回调方法,实现处理器的预处理(如检查登陆),第三个参数为响应的处理器,自定义Controller
     * 返回值:true表示继续流程(如调用下一个拦截器或处理器);false表示流程中断(如登录检查失败),不会继续调用其他的拦截器或处理器,此时我们需要通过response来产生响应;
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        System.out.println("==========================================1================================================");
        return true;
    }
    /**
     * 后处理回调方法,实现处理器的后处理(但在渲染视图之前),此时我们可以通过modelAndView(模型和视图对象)对模型数据进行处理或对视图进行处理,modelAndView也可能为null。
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
            ModelAndView modelAndView) throws Exception {
        System.out.println("==========================================post1================================================");
    }
    /**
     * 整个请求处理完毕回调方法,即在视图渲染完毕时回调,如性能监控中我们可以在此记录结束时间并输出消耗时间,还可以进行一些资源清理,类似于try-catch-finally中的finally,但仅调用处理器执行链中
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception {
        System.out.println("==========================================after1================================================");
    }
}
package com.bshf.recipe.demo.syslog;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class SyslogInterceptor2 implements HandlerInterceptor {
    /**
     * 预处理回调方法,实现处理器的预处理(如检查登陆),第三个参数为响应的处理器,自定义Controller
     * 返回值:true表示继续流程(如调用下一个拦截器或处理器);false表示流程中断(如登录检查失败),不会继续调用其他的拦截器或处理器,此时我们需要通过response来产生响应;
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        System.out.println("==========================================2================================================");
        return true;
    }
    /**
     * 后处理回调方法,实现处理器的后处理(但在渲染视图之前),此时我们可以通过modelAndView(模型和视图对象)对模型数据进行处理或对视图进行处理,modelAndView也可能为null。
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
            ModelAndView modelAndView) throws Exception {
        System.out.println("==========================================post2================================================");
    }
    /**
     * 整个请求处理完毕回调方法,即在视图渲染完毕时回调,如性能监控中我们可以在此记录结束时间并输出消耗时间,还可以进行一些资源清理,类似于try-catch-finally中的finally,但仅调用处理器执行链中
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception {
        System.out.println("==========================================after2================================================");
    }
}
package com.bshf.recipe.demo.syslog;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class SyslogInterceptor3 implements HandlerInterceptor {
    /**
     * 预处理回调方法,实现处理器的预处理(如检查登陆),第三个参数为响应的处理器,自定义Controller
     * 返回值:true表示继续流程(如调用下一个拦截器或处理器);false表示流程中断(如登录检查失败),不会继续调用其他的拦截器或处理器,此时我们需要通过response来产生响应;
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        System.out.println("==========================================3================================================");
        return true;
    }
    /**
     * 后处理回调方法,实现处理器的后处理(但在渲染视图之前),此时我们可以通过modelAndView(模型和视图对象)对模型数据进行处理或对视图进行处理,modelAndView也可能为null。
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
            ModelAndView modelAndView) throws Exception {
        System.out.println("==========================================post3================================================");
    }
    /**
     * 整个请求处理完毕回调方法,即在视图渲染完毕时回调,如性能监控中我们可以在此记录结束时间并输出消耗时间,还可以进行一些资源清理,类似于try-catch-finally中的finally,但仅调用处理器执行链中
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception {
        System.out.println("==========================================after3================================================");
    }
}
<mvc:interceptors>
        <mvc:interceptor>
            <mvc:mapping path="/**"/>
            <bean class="com.bshf.recipe.demo.syslog.SyslogInterceptor" />
        </mvc:interceptor>
        
        <mvc:interceptor>
            <mvc:mapping path="/**"/>
            <bean class="com.bshf.recipe.demo.syslog.SyslogInterceptor2" />
        </mvc:interceptor>
        
        <mvc:interceptor>
            <mvc:mapping path="/**"/>
            <bean class="com.bshf.recipe.demo.syslog.SyslogInterceptor3" />
        </mvc:interceptor>
</mvc:interceptors>

<mvc:mapping path="/**"/>需要拦截的路径,这里匹配所有。这里的配置顺序将是拦截器执行顺序。

输出结果

==========================================1================================================
==========================================2================================================
==========================================3================================================
==========================================post3================================================
==========================================post2================================================
==========================================post1================================================
==========================================after3================================================
==========================================after2================================================
==========================================after1================================================

post和after是倒序的!!!!

中断流程Demo

将SyslogInterceptor3的preHandle方法返回false。其他不变,再看输出结果

==========================================1================================================
==========================================2================================================
==========================================3================================================
==========================================after2================================================
==========================================after1================================================

发现没有了post,post方法一个都没有输出。不仅如此,你的主程序代码(xxx.controller的一个接口)都不会被执行,所以只要遇到return false,则直接进行after清理工作,post和自己主程序代码都将被略过。

到此这篇关于SpringMVC的处理器拦截器HandlerInterceptor详解的文章就介绍到这了,更多相关拦截器HandlerInterceptor内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java8新特性Lambda表达式的一些复杂用法总结

    Java8新特性Lambda表达式的一些复杂用法总结

    lambda表达式是JAVA8中提供的一种新的特性,它支持Java也能进行简单的“函数式编程”。 下面这篇文章主要给大家介绍了关于Java8新特性Lambda表达式的一些复杂用法的相关资料,需要的朋友可以参考借鉴,下面来一起看看吧。
    2017-07-07
  • Android 资源 id详解及的动态获取

    Android 资源 id详解及的动态获取

    这篇文章主要介绍了Android 资源 id详解及的动态获取的相关资料,需要的朋友可以参考下
    2016-12-12
  • Java调用MySQL存储过程并获得返回值的方法

    Java调用MySQL存储过程并获得返回值的方法

    这篇文章主要介绍了Java调用MySQL存储过程并获得返回值的方法,实例分析了java实现MySQL存储过程的相关技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-07-07
  • java URL乱码的解决办法

    java URL乱码的解决办法

    这篇文章介绍了java URL乱码的解决办法,有需要的朋友可以参考一下
    2013-09-09
  • java 中HttpClient传输xml字符串实例详解

    java 中HttpClient传输xml字符串实例详解

    这篇文章主要介绍了java 中HttpClient传输xml字符串实例详解的相关资料,需要的朋友可以参考下
    2017-04-04
  • form表单回写技术java实现

    form表单回写技术java实现

    这篇文章主要为大家详细介绍了java实现form表单回写技术的相关资料,需要的朋友可以参考下
    2016-04-04
  • 浅谈SpringBoot中properties、yml、yaml的优先级

    浅谈SpringBoot中properties、yml、yaml的优先级

    优先级低的配置会被先加载,所以优先级高的配置会覆盖优先级低的配置,本文就来介绍一下SpringBoot中properties、yml、yaml的优先级,感兴趣的可以了解一下
    2023-08-08
  • Mybatis创建逆向工程的步骤

    Mybatis创建逆向工程的步骤

    Mybatis逆向工程是一个自动生成Mybatis Mapper接口、XML文件和Java实体类的工具,可以提高开发效率,避免手动编写大量的重复代码,本文主要介绍了Mybatis创建逆向工程的步骤,感兴趣的可以了解一下
    2023-10-10
  • 利用Stream聚合函数如何对BigDecimal求和

    利用Stream聚合函数如何对BigDecimal求和

    这篇文章主要介绍了利用Stream聚合函数如何对BigDecimal求和问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-05-05
  • Java同步锁synchronized用法的最全总结

    Java同步锁synchronized用法的最全总结

    这篇文章主要介绍了Java同步锁synchronized用法的最全总结,需要的朋友可以参考下,文章详细讲解了Java同步锁Synchronized的使用方法和需要注意的点,希望对你有所帮助
    2023-03-03

最新评论