`

SpringMVC 拦截器实现分析

 
阅读更多

一、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);

 

 

分享到:
评论
1 楼 shenselongge 2014-10-08  
没看到使用threadlocal来实现线程安全,怎么回事?

相关推荐

    SpringMVC 拦截器实现分析.docx

    以下是关于Spring MVC拦截器实现的详细分析: 1. **拦截器接口与方法**: Spring MVC的拦截器接口是`HandlerInterceptor`,它提供了三个关键方法: - `preHandle(HttpServletRequest request, ...

    防止SpringMVC拦截器拦截js等静态资源文件的解决方法

    在本文中,我们讨论了三种解决SpringMVC拦截器拦截静态资源文件的方法,并对这些方法的优劣进行了分析。 方案一是在拦截器中排除静态资源路径。在SpringMVC的配置文件中(通常是spring-mvc.xml),可以通过配置元素...

    springMVC拦截器项目

    SpringMVC 拦截器项目是一个典型的 Web 应用开发示例,它利用 SpringMVC 框架中的拦截器(Interceptor)机制来实现特定的功能,如权限控制、日志记录、性能统计等。SpringMVC 是 Spring 框架的一部分,专为构建基于 ...

    SpringMVC 拦截器 实现 登录退出功能

    综上所述,本项目是一个适合初学者了解和实践SpringMVC拦截器功能的小程序。通过学习和实践,你可以掌握如何使用拦截器实现登录验证和安全退出,同时加深对Intelli IDEA的使用理解。在实际应用中,拦截器常用于权限...

    企业级开发-SpringMVC使用拦截器实现用户登录权限验证实验报告.docx

    本实验报告将探讨如何利用 SpringMVC 的拦截器(Interceptor)来实现用户登录权限验证,确保只有已登录的用户才能访问特定的受保护资源。 首先,我们来看一下实验的基本步骤: 1. 创建 `User` 类:这是表示用户...

    SpringMVC拦截器源代码.zip

    这个名为“SpringMVC拦截器源代码.zip”的压缩包可能包含了Spring MVC拦截器的实现源码,这对于理解和学习如何自定义拦截器以增强应用功能非常有帮助。 1. **拦截器的基本概念** - 拦截器是AOP(面向切面编程)的...

    SpringMVC拦截器实现登录认证

    SpringMVC拦截器是实现登录认证的一种常见方法,它允许开发者在请求被实际处理之前或之后执行特定的逻辑。本文将深入探讨如何利用SpringMVC拦截器来实现这一功能。 首先,了解SpringMVC的核心组件是必要的。...

    springmvc拦截器实现登录验证

    在本场景中,我们探讨的是如何利用拦截器来实现登录验证功能,确保只有经过身份验证的用户才能访问受保护的资源。 首先,我们需要了解Spring MVC的拦截器工作原理。拦截器链是由多个拦截器组成,每个拦截器都有`...

    SpringMVC拦截器例子详解

    - 使用Java配置时,可以通过`@EnableWebMvc` 注解启用Web MVC配置,并在`WebMvcConfigurer` 实现类中重写`addInterceptors()` 方法来注册拦截器。 3. **自定义拦截器**: - 自定义拦截器需要继承`...

    SpringMVC拦截器

    ### SpringMVC拦截器 #### 一、拦截器概述 拦截器(Interceptor)是一种轻量级、低侵入式的AOP实现方式,在SpringMVC框架中有着广泛的应用。它主要用于处理那些与业务逻辑无关但又频繁出现的功能需求,如日志记录...

    SpringMvc 拦截器

    在Spring MVC框架中,拦截器(Interceptor)是一个强大的工具,用于在请求被控制器处理之前或之后执行特定的逻辑。它们可以用来实现通用的功能,如权限验证、日志记录、性能统计等,避免在每个控制器方法中重复编写...

    springmvc 拦截器

    自定义拦截器需要实现Spring MVC提供的HandlerInterceptor接口或 extend AbstractHandlerInterceptorAdapter抽象类。在自定义的拦截器类中,重写preHandle、postHandle和afterCompletion方法,编写相应的业务逻辑。...

    使用SessionListener+持久化Session+Springmvc拦截器实现单点登录

    以上就是使用`SessionListener`、持久化`Session`和`Springmvc拦截器`实现单点登录的基本原理和实现步骤。通过这样的设计,可以有效地提升用户体验,同时确保系统的安全性。在实际项目中,还需要根据具体需求进行...

    SpringMVC拦截器实现单点登录

    SpringMVC 拦截器实现单点登录是一种常见的安全控制机制,主要用于确保在同一时间只有一个用户能够使用同一账号进行操作。这种功能在多用户、多设备登录的环境中尤为重要,可以防止用户账号被盗用或者误操作。 单点...

    SpringMVC配置拦截器实现登录控制的方法

    4. SpringMVC中的拦截器实现登录控制的流程:首先配置拦截器,指定需要拦截的URL路径和排除的URL路径(如登录页面和静态资源路径等)。拦截器的实现类中,preHandle方法中首先检查请求的URI是否在排除的URL列表中,...

    SpringMVC拦截器源码.rar

    SpringMVC拦截器是基于AOP(面向切面编程)的概念实现的,它们遵循HandlerInterceptor接口。这个接口定义了三个方法: 1. `preHandle`: 在请求被处理器处理之前调用,返回`true`表示继续执行处理器,`false`则中断...

    Springmvc登录拦截器Demo

    本文将深入探讨如何使用Spring MVC的拦截器实现登录验证,并提供相关知识点。 1. **Spring MVC 拦截器简介** Spring MVC的拦截器是基于Servlet的Filter的一种扩展,它允许开发者在请求被控制器处理之前或之后执行...

    SpringMVC中的拦截器-拦截器方法的作用和执行顺序.avi

    SpringMVC中的拦截器-拦截器方法的作用和执行顺序.avi

    SpringMVC-12 拦截器

    在本教程“SpringMVC-12 拦截器”中,我们将深入探讨如何实现和配置自定义拦截器,以及多个拦截器的执行顺序。 首先,我们来了解如何创建一个自定义的拦截器。在Spring MVC中,我们需要创建一个实现了`...

    SpringMvc自定义拦截器(注解)代码实例

    首先,自定义拦截器需要实现Spring MVC提供的`HandlerInterceptor`接口。这个接口定义了三个关键方法: 1. `preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)`: 这是在请求被...

Global site tag (gtag.js) - Google Analytics