首页 > 编程知识 正文

SpringMvc拦截器HandlerInterceptor

时间:2023-05-06 03:25:14 阅读:198333 作者:3854

简介:

拦截器intercprot  和 过滤器 Filter 其实作用类似,可应用于:
1、日志记录:记录请求信息的日志,以便进行信息监控、信息统计、计算PV(Page View)等。
2、权限检查:如登录检测,进入处理器检测检测是否登录,如果没有直接返回到登录页面;
3、性能监控:有时候系统在某段时间莫名其妙的慢,可以通过拦截器在进入处理器之前记录开始时间。

自定义拦截器实现 HandlerInterceptor 接口,也可以继承HandlerInterceptorAdapter。 实现接口需要实现对应的3中方法,继承父类只需要实现需要的方法即可。

HandlerInterceptor 接口:

public interface HandlerInterceptor {    /**     * preHandle方法是进行处理器拦截用的,顾名思义,该方法将在Controller处理之前进行调用,     * SpringMVC中的Interceptor拦截器是链式的,可以同时存在多个Interceptor,     * 然后SpringMVC会根据声明的前后顺序一个接一个的执行,     * 而且所有的Interceptor中的preHandle方法都会在Controller方法调用之前调用。     * SpringMVC的这种Interceptor链式结构也是可以进行中断的,     * 这种中断方式是令preHandle的返回值为false,当preHandle的返回值为false的时候整个请求就结束了。     */    boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)            throws Exception;    /**     * postHandle是进行处理器拦截用的,它的执行在Controller的方法调用之后执行,但是它会在DispatcherServlet进行视图的渲染之前执行,     * 也就是说在这个方法中你可以对ModelAndView进行操作。这个方法的链式结构跟正常访问的方向是相反的,     * 也就是说先声明的Interceptor拦截器该方法反而会后调用。     */    void postHandle(            HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)            throws Exception;    /**     * 该方法也是需要当前对应的Interceptor的preHandle方法的返回值为true时才会执行。     * 该方法将在整个请求完成之后,也就是DispatcherServlet渲染了视图执行, 这个方法的主要作用是用于清理资源的,     */    void afterCompletion(            HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)            throws Exception;} 图例:

 通过也四张图可以看出:

1、如果一个拦截器的preHandle返回true,则该拦截器的afterCompletion方法一定会被调用。

 

源码分析: public class DispatcherServlet extends FrameworkServlet{protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {HttpServletRequest processedRequest = request;HandlerExecutionChain mappedHandler = null;Exception dispatchException = null;try {mappedHandler = getHandler(processedRequest);//调用preHandle方法if (!mappedHandler.applyPreHandle(processedRequest, response)) {//如果有拦截器preHandle返回false,程序不在向下执行。return;}//调用controller中的方法mv = ha.handle(processedRequest, response, mappedHandler.getHandler());//调用postHandle方法mappedHandler.applyPostHandle(processedRequest, response, mv);}catch (Exception ex) {dispatchException = ex;}//处理程序调用的结果processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);}/** * 处理程序调用的结果 */private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,HandlerExecutionChain mappedHandler, ModelAndView mv, Exception exception) throws Exception {//渲染视图if (mv != null && !mv.wasCleared()) {render(mv, request, response);}//调用afterCompletion方法if (mappedHandler != null) {mappedHandler.triggerAfterCompletion(request, response, null);}} }public class HandlerExecutionChain {private final Object handler;private HandlerInterceptor[] interceptors;//拦截器数组private int interceptorIndex = -1;boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {HandlerInterceptor[] interceptors = getInterceptors();//获取拦截器数组if (!ObjectUtils.isEmpty(interceptors)) {for (int i = 0; i < interceptors.length; i++) {HandlerInterceptor interceptor = interceptors[i];if (!interceptor.preHandle(request, response, this.handler)) {//如果有拦截器preHandle返回false。//触发拦截器的afterCompletion方法。triggerAfterCompletion(request, response, null);//后面的拦截器preHandle将不再执行return false;}this.interceptorIndex = i;}}return true;}void applyPostHandle(HttpServletRequest request, HttpServletResponse response, ModelAndView mv) throws Exception {HandlerInterceptor[] interceptors = getInterceptors();if (!ObjectUtils.isEmpty(interceptors)) { //postHandlefor (int i = interceptors.length - 1; i >= 0; i--) {HandlerInterceptor interceptor = interceptors[i];interceptor.postHandle(request, response, this.handler, mv);}}}void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, Exception ex)throws Exception {HandlerInterceptor[] interceptors = getInterceptors();if (!ObjectUtils.isEmpty(interceptors)) {for (int i = this.interceptorIndex; i >= 0; i--) {HandlerInterceptor interceptor = interceptors[i];try {interceptor.afterCompletion(request, response, this.handler, ex);}catch (Throwable ex2) {logger.error("HandlerInterceptor.afterCompletion threw exception", ex2);}}}}}

 

 filter和interceptor执行顺序:

 

过滤器和拦截器区别:

1、发生的时机不一样,filter是在servlet容器外,interceptor在servlet容器内,且可以对请求的3个关键步骤进行拦截处理。另外filter在过滤是只能对request和response进行操作,而interceptor可以对request、response、handler、modelAndView、exception进行操作。
2、拦截器不依赖与servlet容器,过滤器依赖与servlet容器
3、interceptor只能对action起作用,filter几乎对所有请求起作用。

 

测试用例:

 

@SpringBootApplication@ServletComponentScan@Controllerpublic class App { public static void main(String[] args) { SpringApplication.run(App.class, args); } @RequestMapping("/abcd") @ResponseBody public String index() { System.out.println("helloWord"); return "helloWord"; }}@Order(1)@WebFilter(urlPatterns = "/abcd/*",filterName = "myFilterOne")class MyFilter1 implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { System.out.println("filter1_start"); long start=System.currentTimeMillis(); filterChain.doFilter(servletRequest,servletResponse); System.out.println("filter1_end_"+(System.currentTimeMillis()-start)); } @Override public void destroy() { }}@Order(2)@WebFilter(urlPatterns = "/abcd/*", filterName = "myFilterTwo") class MyFilter2 implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { System.out.println("filter2_start"); filterChain.doFilter(servletRequest, servletResponse); System.out.println("filter2_end" ); } @Override public void destroy() { }}class MyInterceptor1 implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("interceptor1_preHandle"); request.setAttribute("start", System.currentTimeMillis()); return true; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("interceptor1_postHandle"); } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("interceptor1_afterCompletion_"+(System.currentTimeMillis()-(Long) request.getAttribute("start"))); }}class MyInterceptor2 implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("interceptor2_preHandle"); return true; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("interceptor2_postHandle"); } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("interceptor2_afterCompletion"); }}@Componentclass MyInterceptorConfig extends WebMvcConfigurerAdapter { public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new MyInterceptor1()).addPathPatterns("/abcd/**"); registry.addInterceptor(new MyInterceptor2()).addPathPatterns("/abcd/**"); }}

结果:

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。