Coin163

首页 > Spring MVC拦截器配置及其原理分析

Spring MVC拦截器配置及其原理分析

2020腾讯云双十一活动,全年最低!!!(领取3500元代金券),
地址https://cloud.tencent.com/act/cps/redirect?redirect=1073

2020阿里云最低价产品入口,含代金券(新老用户有优惠),
入口地址https://www.aliyun.com/minisite/goods

相关推荐:Spring MVC 事物配置

Spring MVC 事物配置 spring-hibernate.xml如下: <xml version="1.0" encoding="UTF-8"><beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:xsi="http://www.w3.org/2001

原创整理不易,转载请注明出处:Spring MVC拦截器配置及其原理分析
代码下载地址:http://blog.csdn.net/yaerfeng/article/details/24175129
SpringMVC的拦截器不同于Spring的拦截器,SpringMVC具有统一的入口DispatcherServlet,所有的请求都通过DispatcherServlet,所以只需要在DispatcherServlet上做文章即可,DispatcherServlet也没有代理,同时SpringMVC管理的Controller也不有代理。
一、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来实现线程安全。

ThreadLocal<StopWatch> stopWatchLocal = new ThreadLocal<StopWatch>();

boolean usePerformance=true;//测试

private static Logger logger = LoggerFactory.getLogger(VerificationHandlerInterceptor.class);
@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 拦截器实现分析
SpringMVC的拦截器不同于Spring的拦截器,SpringMVC具有统一的入口DispatcherServlet,所有的请求都通过DispatcherServlet,所以只需要在DispatcherServlet上做文章即可,DispatcherServlet也没有代理,同时SpringMVC管理的Controller也不有代理。哪不难想到我们在执行controller之前做某些动作,执行完毕做某些动作,render完成做某些动作。SpringMVC的拦截器对应提供了三个preHandle,postHandle,afterCompletion方法。只需在三个方法内写我们需要的逻辑就行,多了都是废话,还是代码实在。

相关推荐:spring MVC配置详解

现在主流的Web MVC框架除了Struts这个主力 外,其次就是Spring MVC了,因此这也是作为一名程序员需要掌握的主流框架,框架选择多了,应对多变的需求和业务时,可实行的方案自然就多了。不过要想灵活运用Spring MVC来应对大多数的Web开发,就必须要掌握它的配

如果你没有使用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()。

[java] view plaincopyprint?
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); 

原文

原创整理不易,转载请注明出处:Spring MVC拦截器配置及其原理分析 代码下载地址:http://blog.csdn.net/yaerfeng/article/details/24175129 SpringMVC的拦截器不同于Spring的拦截器,SpringMVC

------分隔线----------------------------