我的springMVC+mybatis中的interceptor使用@autowired注入DAO失败,导致报空指针错误,这个是为什么呢?

:空指针说明没有注入进来,你可以检查一下你的这个拦截器interceptor是不是加了注解@component,并且spring配置文件扫描了这个类,你的类不交给spring容器管理,就不提注入这回事了。

一、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来实现线程安全。

  1. @Override
  2. public boolean preHandle(HttpServletRequest request,
  3. HttpServletResponse response, Object handler) throws Exception {
  4. if(usePerformance){
  5. StopWatch stopWatch = new StopWatch(handler.toString());
  6. stopWatchLocal.set(stopWatch);
  7. stopWatch.start(handler.toString());
  8. }
  9. return true;
  10. }
  11. @Override
  12. public void afterCompletion(HttpServletRequest request,
  13. HttpServletResponse response, Object handler, Exception ex)
  14. throws Exception {
  15. if(usePerformance){
  16. StopWatch stopWatch = stopWatchLocal.get();
  17. stopWatch.stop();
  18. String currentPath = request.getRequestURI();
  19. String queryString  = request.getQueryString();
  20. queryString = queryString == null ? "":"?" + queryString;
  21. log.info("access url path:" + currentPath + queryString +  " |time:" + stopWatch.getTotalTimeMillis());
  22. stopWatchLocal.set(null);
  23. }
  24. }

三、SpringMVC 拦截器实现分析

SpringMVC的拦截器不同于Spring的拦截器,SpringMVC具有统一的入口DispatcherServlet,所有的请求都通过DispatcherServlet,所以只需要在DispatcherServlet上做文章即可,DispatcherServlet也没有代理,同时SpringMVC管理的Controller也不有代理。哪不难想到我们在执行controller之前做某些动作,执行完毕做某些动作,render完成做某些动作。SpringMVC的拦截器对应提供了三个preHandle,postHandle,afterCompletion方法。只需在三个方法内写我们需要的逻辑就行,多了都是废话,还是代码实在。

如果你没有使用springMVC可以使用filter来完成:

  1. stopWatch.start();
  2. doFilterChain();
  3. stopWatch.stop();

三、SpringMVC 拦截器实现分析

SpringMVC的拦截器不同于Spring的拦截器,SpringMVC具有统一的入口DispatcherServlet,所有的请求都通过DispatcherServlet,所以只需要在DispatcherServlet上做文章即可,DispatcherServlet也没有代理,同时SpringMVC管理的Controller也不有代理。哪不难想到我们在执行controller之前做某些动作,执行完毕做某些动作,render完成做某些动作。SpringMVC的拦截器对应提供了三个preHandle,postHandle,afterCompletion方法。只需在三个方法内写我们需要的逻辑就行,多了都是废话,还是代码实在。

  1. HandlerInterceptor[] interceptors = mappedHandler.getInterceptors();
  2. if (interceptors != null) {
  3. for (int i = 0; i < interceptors.length; i++) {
  4. HandlerInterceptor interceptor = interceptors[i];
  5. //ha.handle是调用具体的controller在此之前执行preHandle                      if (!interceptor.preHandle(processedRequest, response, mappedHandler.getHandler())) {
  6. triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, null);
  7. return;
  8. }
  9. interceptorIndex = i;
  10. }
  11. }
  12. // Actually invoke the handler.
  13. mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

完成调用之后,调用render(),最后执行afterCompletion()。

  1. if (interceptors != null) {
  2. for (int i = interceptors.length - 1; i >= 0; i--) {
  3. HandlerInterceptor interceptor = interceptors[i];
  4. interceptor.postHandle(processedRequest, response, mappedHandler.getHandler(), mv);
  5. }
  6. }
  7. }
  8. catch (ModelAndViewDefiningException ex) {
  9. logger.debug("ModelAndViewDefiningException encountered", ex);
  10. mv = ex.getModelAndView();
  11. }
  12. catch (Exception ex) {
  13. Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);
  14. mv = processHandlerException(processedRequest, response, handler, ex);
  15. errorView = (mv != null);
  16. }
  17. // Did the handler return a view to render?
  18. if (mv != null && !mv.wasCleared()) {
  19. render(mv, processedRequest, response);
  20. if (errorView) {
  21. WebUtils.clearErrorRequestAttributes(request);
  22. }
  23. }
  24. else {
  25. if (logger.isDebugEnabled()) {
  26. logger.debug("Null ModelAndView returned to DispatcherServlet with name '" + getServletName() +
  27. "': assuming HandlerAdapter completed request handling");
  28. }
  29. }
  30. // Trigger after-completion for successful outcome.
  31. triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, null);

spring mvc拦截器原理分析的更多相关文章

  1. SSM(spring mvc+spring+mybatis)学习路径——2-2、spring MVC拦截器

    目录 2-2 Spring MVC拦截器 第一章 概述 第二章 Spring mvc拦截器的实现 2-1 拦截器的工作原理 2-2 拦截器的实现 2-3 拦截器的方法介绍 2-4 多个拦截器应用 2- ...

  2. spring mvc 拦截器的使用

    Spring MVC 拦截器的使用 拦截器简介 Spring MVC 中的拦截器(Interceptor)类似于 Servler 中的过滤器(Filter).用于对处理器进行预处理和后处理.常用于日志 ...

  3. 【Java Web开发学习】Spring MVC 拦截器HandlerInterceptor

    [Java Web开发学习]Spring MVC 拦截器HandlerInterceptor 转载:https://www.cnblogs.com/yangchongxing/p/9324119.ht ...

  4. Spring Boot 2.X(九):Spring MVC - 拦截器(Interceptor)

    拦截器 1.简介 Spring MVC 中的拦截器(Interceptor)类似于 Servlet 开发中的过滤器 Filter,它主要用于拦截用户请求并作相应的处理,它也是 AOP 编程思想的体现, ...

  5. Spring MVC拦截器配置

    Spring MVC拦截器配置 (1)自定义拦截器 package learnspringboot.xiao.other; import org.springframework.web.servlet ...

  6. 写的太细了!Spring MVC拦截器的应用,建议收藏再看!

    Spring MVC拦截器 拦截器是Spring MVC中强大的控件,它可以在进入处理器之前做一些操作,或者在处理器完成后进行操作,甚至是在渲染视图后进行操作. 拦截器概述 对于任何优秀的MVC框架, ...

  7. 对于Spring MVC 拦截器的一些了解

    Spring MVC 拦截器的执行顺序 应用场景 假设请求 localhost:8080/ 则要求直接重定向到 localhost:8080/login ; 定义拦截器顺序 permission lo ...

  8. Spring MVC拦截器浅析

    Spring MVC拦截器 重点:Spring MVC的拦截器只会拦截控制器的请求,如果是jsp.js.image.html则会放行. 什么是拦截器 运行在服务器的程序,先于Servlet或JSP之前 ...

  9. spring mvc拦截器

    Java里的拦截器是动态拦截Action调用的对象.它提供了一种机制可以使开发者可以定义在一个action执行的前后执行的代码,也可以在一个action执行前阻止其执行,同时也提供了一种可以提取act ...

随机推荐

  1. bash编程的信号捕获:

    bash编程的信号捕获: kill -l KILL无法捕捉:   trap 'COMMAND' SIGNAL,    信号捕捉用于:在中途中止时做一些清理操作.   一. trap捕捉到信号之后,可以 ...

  2. 漫谈使用Kafka作为MQ中间件

    哪些场景适合使用Kafka线上系统会实时产生数以万计的日志信息,服务器运行状态,用户行为记录,业务消息 等信息,这些信息需要用于多个不同的目的,比如审计.安全.数据挖掘等,因此需要以分类的方式将这些信 ...

  3. 更改ubuntu的官方镜像源

    我们自己安装的ubuntu通常默认镜像源是官方的,并不好用,因为网速以及限制比较多,所以为了使用方便,通常都会去更改一下默认的镜像源配置. 这里我们使用清华大学开源镜像软件站,https://mirr ...

  4. centos7 中安装 mysql5.6 的过程

    前提是Centos的环境是好的,并且相关的软件包已经安装好. 1.创建用户,并修改创建的数据目录的属主 [root@bogon ~]# useradd -M mysql -s /sbin/nologi ...

  5. A Fast and Easy to Use AES Library

    http://www.codeproject.com/Articles/57478/A-Fast-and-Easy-to-Use-AES-Library Introduction EfAesLib i ...

  6. Onenote代码高亮的实现方法

    最终效果图 最终的效果图如下: VBA的编写参考 主要参考的是这篇博客中的思路:如何在Word中排出漂亮的代码 将VBA脚本复制到Word中并设置快捷键 Alt+F11 打开Word中的 VBS,将下 ...

  7. 数据结构( Pyhon 语言描述 ) — — 第8章:队列

    队列概览 队列是线性的集合 队列的插入限制在队尾,删除限制在队头.支持先进先出协议( FIFIO, first-in first-out ) 两个基本操作 add:在队尾添加一项 pop:从队头弹出一 ...

  8. cocos2d心得关于精灵帧缓存

    在cocos2d中,精灵帧缓存CCSpriteFrameCache是用来存储精灵帧的.它没有特别的属性,只存储了一些用来管理CCSpriteFrame的方法. 以一个例子来说明,一般在又纹理图集的程序 ...

  9. 牛客网暑期ACM多校训练营(第六场) J Heritage of skywalkert(数论, eth_element)

    链接: https://www.nowcoder.com/acm/contest/144/J 题意: 给定一个函数, 求它n次结果中任意两次的lcm最大值 分析: 首先要看出这个函数并没有什么含义, ...

  10. Python开发:网络编程

    Python 提供了两个级别访问的网络服务.: 低级别的网络服务支持基本的 Socket,它提供了标准的 BSD Sockets API,可以访问底层操作系统Socket接口的全部方法. 高级别的网络 ...