Spring MVC拦截器实现分析
一、Servlet Filter与Spring interceptor的执行顺序
Filter有顺序吗?我们怎么控制filter的执行顺序。通过Tomcat的代码分析,servlet在Filter执行完成后才调用,如有多个filter怎么控制执行顺序,首先会想到在web.xml配置某个参数,例如order之类的,但查找一下一番,servlet并没有这个参数。试试filter Mapping的配置的先后顺序,果然有效,原来filter的执行顺序就考filter mapping在web.xml中的顺序。
spring interceptor也是这样的执行顺序,不过interceptor多一个配置参数order通过他也可以来实现interceptor的执行顺序。很多应用场景中,执行顺序还是重要的,比如cache和transaction interceptor的执行顺序,很显然cache应该在transaction之前,这样发现命中了就不用打开事务,如果transaction在前,每次都打开事务即使cache命中,这是一个无谓东动作。
二、利用springMVC的interceptor实现页面性能监控(Filter亦可)
调优第一步,找出耗时比较长的页面进行优化。利用interceptor能轻易搞定。interceptor提供了preHandle和postHandle以及afterCompletion三个方法。preHandle调用controller具体方法之前调用,postHandle完成具体方法之后调用,afterCompletion完成对页面的render以后调用,至此整个页面渲染完成。也就是说我们在preHandle记录开始的时间,在afterCompletion记录结束的时间,就可或者整个页面生成的时间。Spring自带StopWatch工具类来实现时间跟踪,关键一点interceptor不是线程安全的。我们需要借助threadlocal来实现线程安全。
@Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { if(usePerformance){ StopWatch stopWatch = new StopWatch(handler.toString()); stopWatchLocal.set(stopWatch); stopWatch.start(handler.toString()); } return true; } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { if(usePerformance){ StopWatch stopWatch = stopWatchLocal.get(); stopWatch.stop(); String currentPath = request.getRequestURI(); String queryString = request.getQueryString(); queryString = queryString == null ? "":"?" + queryString; log.info("access url path:" + currentPath + queryString + " |time:" + stopWatch.getTotalTimeMillis()); stopWatchLocal.set(null); } }如果你没有使用springMVC可以使用filter来完成:
stopWatch.start(); doFilterChain(); stopWatch.stop();三、SpringMVC 拦截器实现分析
SpringMVC的拦截器不同于Spring的拦截器,SpringMVC具有统一的入口DispatcherServlet,所有的请求都通过DispatcherServlet,所以只需要在DispatcherServlet上做文章即可,DispatcherServlet也没有代理,同时SpringMVC管理的Controller也不有代理。哪不难想到我们在执行controller之前做某些动作,执行完毕做某些动作,render完成做某些动作。SpringMVC的拦截器对应提供了三个preHandle,postHandle,afterCompletion方法。只需在三个方法内写我们需要的逻辑就行,多了都是废话,还是代码实在。
HandlerInterceptor[] interceptors = mappedHandler.getInterceptors(); if (interceptors != null) { for (int i = 0; i interceptors.length; i++) { HandlerInterceptor interceptor = interceptors[i]; //ha.handle是调用具体的controller在此之前执行preHandle if (!interceptor.preHandle(processedRequest, response, mappedHandler.getHandler())) { triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, null); return; } interceptorIndex = i; } } // Actually invoke the handler. mv = ha.handle(processedRequest, response, mappedHandler.getHandler());完成调用之后,调用render(),最后执行afterCompletion()。
if (interceptors != null) { for (int i = interceptors.length - 1; i = 0; i--) { HandlerInterceptor interceptor = interceptors[i]; interceptor.postHandle(processedRequest, response, mappedHandler.getHandler(), mv); } } } catch (ModelAndViewDefiningException ex) { logger.debug("ModelAndViewDefiningException encountered", ex); mv = ex.getModelAndView(); } catch (Exception ex) { Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null); mv = processHandlerException(processedRequest, response, handler, ex); errorView = (mv != null); } // Did the handler return a view to render? if (mv != null !mv.wasCleared()) { render(mv, processedRequest, response); if (errorView) { WebUtils.clearErrorRequestAttributes(request); } } else { if (logger.isDebugEnabled()) { logger.debug("Null ModelAndView returned to DispatcherServlet with name " + getServletName() + ": assuming HandlerAdapter completed request handling"); } } // Trigger after-completion for successful outcome. triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, null); 本文出自seven的测试人生公众号最新内容请见作者的GitHub页:http://qaseven.github.io/Spring MVC开发用户流量拦截器 你好看官,里面请!今天笔者讲的是Spring MVC开发用户流量拦截器。不懂或者觉得我写的有问题可以在评论区留言,我看到会及时回复。 注意:本文仅用于学习参考,不可用于商业用途,如需转载请跟我联系。
Spring MVC拦截器和过滤器的区别 你好看官,里面请!今天笔者讲的是Spring MVC拦截器和过滤器的区别。不懂或者觉得我写的有问题可以在评论区留言,我看到会及时回复。 注意:本文仅用于学习参考,不可用于商业用途,如需转载请跟我联系。
Spring MVC 系列之拦截器 Interceptor 最全总结 理解拦截器 Interceptor 拦截器 Interceptor 在 Spring MVC 中的地位等同于 Servlet 规范中的过滤器 Filter,拦截的是处理器的执行,由于是全局行为,因此常用于做一些通用的功能,如请求日志打印、权限控制等。
Spring MVC 实现拦截器 SpringMVC的拦截器Interceptor类似于Servlet开发中的过滤器Filter,用于对处理器进行预处理和后处理。比如:可以实现:权限控制、日志、异常记录、记录方法执行时间.....
Java Spring Boot开发实战系列课程【第15讲】:Spring Boot 2.0 API与Spring REST Docs实战 立即下载
相关文章
- 从Spring迁移到Spring Boot
- 微服务框架:如果不用Spring Boot,还可以选择谁
- 带着问题学 Spring MVC 源码: 一、概述
- SpringMvc学习-5-Spring MVC 文件上传
- Spring MVC+Spring+Mybatis实现支付宝支付功能(附完整代码)
- Spring Cloud-Eureka 服务注册中心
- Spring Boot 2.4.0 正式发布!全新的配置处理机制,拥抱云原生!
- 《精通Spring MVC 4》——1.3 start.Spring.io简介
- 《精通Spring MVC 4》——2.2 对MVC的质疑及其最佳实践
- 《Spring攻略(第2版)》——1.8 使用工厂Bean和Utility Schema定义集合
- spring计划任务,springMvc计划任务,Spring@Scheduled,spring定时任务
- Spring整合CXF步骤,Spring实现webService,spring整合WebService
- Spring官网改版后下载
- 如何在Spring Boot项目中集成微信支付V3
- Spring Security 实战干货: 登录成功后返回 JWT Token
- Spring Boot使用layui的字体图标时无法正常显示解决办法
- spring mvc 框架核心文档
- Spring Mvc 公共Controller 使用拦截器注入请求信息
- spring core源码解读之ASM4用户手册翻译之一asm简介
- Spring 3 MVC: Themes In Spring-Tutorial With Example---reference
- spring的启动过程(spring 上下文和spring mvc上下文和web应用上下文servletContext之间的关系)
- spring MVC 架构图 中央控制器核心类DispatcherServlet