interceptor的应用与源码分析
2017-05-03 09:01
106 查看
最近项目中需要用到拦截器,因此研究了一下interceptor。interceptor是针对方法的拦截。
实现方式有两种一种是如上所示继承HandleInterceptorAdapter接口,另一种是实现HandleInterceptor接口,两种方式都可以
<mvc:mapping path="">为拦截器的拦截范围,<mvc:exclude-mapping path="">为拦截器的不被拦截范围
首先会执行getHandler方法,生成HandlerExecutionChain,其中包括handler和interceptorList,在真正通过handlerAdapter执行handler方法之前会遍历interceptor执行preHandle方法,如下所示
1 interceptor的应用
1.1 定义Interceptor
public class InterceptorTest extends HandlerInterceptorAdapter { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("preHandle in InterceptorTest"); return super.preHandle(request, response, handler); } @Override public void postHandle( HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("postHandle in InterceptorTest"); } @Override public void afterCompletion( HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("afterCompletion in InterceptorTest"); } }
实现方式有两种一种是如上所示继承HandleInterceptorAdapter接口,另一种是实现HandleInterceptor接口,两种方式都可以
1.2 定义xml文件
<mvc:interceptors> <mvc:interceptor> <mvc:mapping path="/**"/> <bean class="test.interceptor.interceptorTest" /> </mvc:interceptor> </mvc:interceptors>
<mvc:mapping path="">为拦截器的拦截范围,<mvc:exclude-mapping path="">为拦截器的不被拦截范围
2 interceptor的原理
我们看DispatcherServlet方法中的doDispatch方法,看源码可以知道:protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception { HttpServletRequest processedRequest = request; HandlerExecutionChain mappedHandler = null; int interceptorIndex = -1; try { ModelAndView mv; boolean errorView = false; try { processedRequest = checkMultipart(request); // Determine handler for the current request. mappedHandler = getHandler(processedRequest, false); if (mappedHandler == null || mappedHandler.getHandler() == null) { noHandlerFound(processedRequest, response); return; } // Determine handler adapter for the current request. HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler()); // Process last-modified header, if supported by the handler. String method = request.getMethod(); boolean isGet = "GET".equals(method); if (isGet || "HEAD".equals(method)) { long lastModified = ha.getLastModified(request, mappedHandler.getHandler()); if (logger.isDebugEnabled()) { String requestUri = urlPathHelper.getRequestUri(request); logger.debug("Last-Modified value for [" + requestUri + "] is: " + lastModified); } if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) { return; } } // Apply preHandle methods of registered interceptors. HandlerInterceptor[] interceptors = mappedHandler.getInterceptors(); if (interceptors != null) { for (int i = 0; i < interceptors.length; i++) { HandlerInterceptor interceptor = interceptors[i]; 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()); // Do we need view name translation? if (mv != null && !mv.hasView()) { mv.setViewName(getDefaultViewName(request)); } // Apply postHandle methods of registered interceptors. 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); } catch (Exception ex) { // Trigger after-completion for thrown exception. triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, ex); throw ex; } catch (Error err) { ServletException ex = new NestedServletException("Handler processing failed", err); // Trigger after-completion for thrown exception. triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, ex); throw ex; } finally { // Clean up any resources used by a multipart request. if (processedRequest != request) { cleanupMultipart(processedRequest); } } }
首先会执行getHandler方法,生成HandlerExecutionChain,其中包括handler和interceptorList,在真正通过handlerAdapter执行handler方法之前会遍历interceptor执行preHandle方法,如下所示
if (interceptors != null) { for (int i = 0; i < interceptors.length; i++) { HandlerInterceptor interceptor = interceptors[i]; if (!interceptor.preHandle(processedRequest, response, mappedHandler.getHandler())) { triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, null); return; } interceptorIndex = i; } }执行结束后会执行postHandle方法:
// Apply postHandle methods of registered interceptors. if (interceptors != null) { for (int i = interceptors.length - 1; i >= 0; i--) { HandlerInterceptor interceptor = interceptors[i]; interceptor.postHandle(processedRequest, response, mappedHandler.getHandler(), mv); } }
相关文章推荐
- 应用框架的设计与实现——.NET平台(5 缓存服务.源码分析)
- 应用框架的设计与实现——.NET平台(10 授权服务.源码分析)
- HBase的Compact和Split源码分析与应用--基于0.94.5
- 在不修改源码的情况下分析Android应用的操作日志
- Launcher3源码分析 — 所有应用页面的数据加载和绑定
- 通过对一个病毒源码的分析,了解VBS脚本语言的应用
- C++之STL(九):函数适配器bind2nd 、mem_fun_ref 源码分析、函数适配器应用举例
- 从零开始学C++之STL(九):函数适配器bind2nd 、mem_fun_ref 源码分析、函数适配器应用举例
- Android菜鸟开发之蓝牙(Bluetooth)---设置应用源码分析
- [Android]Volley源码分析(肆)应用
- android camera 源码分析(基于应用)
- JDK源码分析之Set类详解——适配器模式的应用
- android camera 源码分析(基于应用)
- ThreadLocal源码分析和应用
- U-BOOT源码分析及移植(转载)--嵌入式系统应用笔记
- 应用框架的设计与实现——.NET平台(7.事件通知服务.源码分析)
- springSecurity源码分析——枚举类的应用SecurityFilters
- IPTV/EPG 应用系统源码分析(一)
- 蓝牙(Bluetooth)---源码目录及设置应用源码分析
- Sphider 的应用和php源码分析