转载

SpringMVC 拦截器源码解析

前言:这两天学习了代理模式,自然想到了SpringMVC 的 AOP 使用的就是动态代理,拦截器使用的就是 jdk 的动态代理。今天看了看源码,记录一下。SpringMVC 的拦截器使用移步: Java Servlet 过滤器与 SpringMVC 拦截器的区别?

源码解析

springMVC 的所有连接入口都会进入 DispatcherServlet,然后在这里面去调用真正的 Controller。而拦截器要达到的作用则是在调用 Controller 前后去做一些事情。所以现在需要看看 DispatcherServlet 的源码。

DispatcherServlet

DispatcherServlet 的源码入口在 doService() 方法。

protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {

if(this.logger.isDebugEnabled()) {

String resumed = WebAsyncUtils.getAsyncManager(request).hasConcurrentResult()?" resumed":"";

this.logger.debug("DispatcherServlet with name '" + this.getServletName() + "'" + resumed + " processing " + request.getMethod() + " request for [" + getRequestUri(request) + "]");

}

Map<String, Object> attributesSnapshot = null;

if(WebUtils.isIncludeRequest(request)) {

attributesSnapshot = new HashMap();

Enumeration attrNames = request.getAttributeNames();

label108:

while(true) {

String attrName;

do {

if(!attrNames.hasMoreElements()) {

break label108;

}

attrName = (String)attrNames.nextElement();

} while(!this.cleanupAfterInclude && !attrName.startsWith("org.springframework.web.servlet"));

attributesSnapshot.put(attrName, request.getAttribute(attrName));

}

}

request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.getWebApplicationContext());

request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver);

request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver);

request.setAttribute(THEME_SOURCE_ATTRIBUTE, this.getThemeSource());

FlashMap inputFlashMap = this.flashMapManager.retrieveAndUpdate(request, response);

if(inputFlashMap != null) {

request.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE, Collections.unmodifiableMap(inputFlashMap));

}

request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap());

request.setAttribute(FLASH_MAP_MANAGER_ATTRIBUTE, this.flashMapManager);

try {

this.doDispatch(request, response);

} finally {

if(!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted() && attributesSnapshot != null) {

this.restoreAttributesAfterInclude(request, attributesSnapshot);

}

}

}

doService() 方法里面处理了一些信息之后,调用了 doDispatch() 方法。

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {

HttpServletRequest processedRequest = request;

HandlerExecutionChain mappedHandler = null;

boolean multipartRequestParsed = false;

WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);

try {

try {

ModelAndView mv = null;

Object dispatchException = null;

try {

processedRequest = this.checkMultipart(request);

multipartRequestParsed = processedRequest != request;

mappedHandler = this.getHandler(processedRequest);

if(mappedHandler == null || mappedHandler.getHandler() == null) {

this.noHandlerFound(processedRequest, response);

return;

}

HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler());

String method = request.getMethod();

boolean isGet = "GET".equals(method);

if(isGet || "HEAD".equals(method)) {

long lastModified = ha.getLastModified(request, mappedHandler.getHandler());

if(this.logger.isDebugEnabled()) {

this.logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified);

}

if((new ServletWebRequest(request, response)).checkNotModified(lastModified) && isGet) {

return;

}

}

if(!mappedHandler.applyPreHandle(processedRequest, response)) {

return;

}

mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

if(asyncManager.isConcurrentHandlingStarted()) {

return;

}

this.applyDefaultViewName(processedRequest, mv);

mappedHandler.applyPostHandle(processedRequest, response, mv);

} catch (Exception var20) {

dispatchException = var20;

} catch (Throwable var21) {

dispatchException = new NestedServletException("Handler dispatch failed", var21);

}

this.processDispatchResult(processedRequest, response, mappedHandler, mv, (Exception)dispatchException);

} catch (Exception var22) {

this.triggerAfterCompletion(processedRequest, response, mappedHandler, var22);

} catch (Throwable var23) {

this.triggerAfterCompletion(processedRequest, response, mappedHandler, new NestedServletException("Handler processing failed", var23));

}

} finally {

if(asyncManager.isConcurrentHandlingStarted()) {

if(mappedHandler != null) {

mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);

}

} else if(multipartRequestParsed) {

this.cleanupMultipart(processedRequest);

}

}

}

doDispatch() 方法中通过 this.getHandler(processedRequest); 获取到了处理器链 HandlerExecutionChain mappedHandle 之后,去执行了  mappedHandler.applyPreHandle(processedRequest, response) 方法,从而执行了拦截器的 preHandle 方法,如果返回为 false,则会调用处理器链的 triggerAfterCompletion 方法,然后 DispatchServlet 类中会直接 retreturn;如果返回为 true,则继续。

然后调用了 HandlerAdapter 的 handler() 方法;

然后调用了 mappedHandler.applyPostHandle(processedRequest, response, mv); 方法,从而执行了拦截器的 postHandle 方法;

然后调用了 this.processDispatchResult(processedRequest, response, mappedHandler, mv, (Exception)dispatchException); 方法;在 processDispatchResult() 方法里面渲染了对应的视图,然后调用了 mappedHandler.triggerAfterCompletion(request, response, (Exception)null); 方法,从而执行了拦截器的 afterCompletion 方法。

processDispatchResult() 源码如下:

private void processDispatchResult(HttpServletRequest request, HttpServletResponse response, HandlerExecutionChain mappedHandler, ModelAndView mv, Exception exception) throws Exception {

boolean errorView = false;

if(exception != null) {

if(exception instanceof ModelAndViewDefiningException) {

this.logger.debug("ModelAndViewDefiningException encountered", exception);

mv = ((ModelAndViewDefiningException)exception).getModelAndView();

} else {

Object handler = mappedHandler != null?mappedHandler.getHandler():null;

mv = this.processHandlerException(request, response, handler, exception);

errorView = mv != null;

}

}

if(mv != null && !mv.wasCleared()) {

this.render(mv, request, response);

if(errorView) {

WebUtils.clearErrorRequestAttributes(request);

}

} else if(this.logger.isDebugEnabled()) {

this.logger.debug("Null ModelAndView returned to DispatcherServlet with name '" + this.getServletName() + "': assuming HandlerAdapter completed request handling");

}

if(!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {

if(mappedHandler != null) {

mappedHandler.triggerAfterCompletion(request, response, (Exception)null);

}

}

}

从 doDispatch() 方法这里主要需要知道 HandlerExecutionChain mappedHandler = this.getHandler(processedRequest); 这一句调用的 getHandler() 方法,源码如下。

getHandle() 方法里是通过 HandlerMapping 的 getHandler 方法返回 HandlerExecutionChain 的。

从代码中不难看出整个逻辑就是依次判断 servlet 中的每个 handlerMapping 是否能够匹配该请求,直到找到那个匹配的然后返回处理结果。

protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {

Iterator var2 = this.handlerMappings.iterator();

HandlerExecutionChain handler;

do {

if(!var2.hasNext()) {

return null;

}

HandlerMapping hm = (HandlerMapping)var2.next();

if(this.logger.isTraceEnabled()) {

this.logger.trace("Testing handler map [" + hm + "] in DispatcherServlet with name '" + this.getServletName() + "'");

}

handler = hm.getHandler(request);

} while(handler == null);

return handler;

}

HandlerExecutionChain 类

applyPreHandle() 方法源码如下:可以看出是顺序调用拦截器的 preHandle() 方法。preHandle 返回 false 时调用了 triggerAfterCompletion 方法。

boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {

HandlerInterceptor[] interceptors = this.getInterceptors();

if(!ObjectUtils.isEmpty(interceptors)) {

for(int i = 0; i < interceptors.length; this.interceptorIndex = i++) {

HandlerInterceptor interceptor = interceptors[i];

if(!interceptor.preHandle(request, response, this.handler)) {

this.triggerAfterCompletion(request, response, (Exception)null);

return false;

}

}

}

return true;

}

applyPostHandle() 方法源码如下:可以看出这里是逆序调用 postHandle 方法。

void applyPostHandle(HttpServletRequest request, HttpServletResponse response, ModelAndView mv) throws Exception {

HandlerInterceptor[] interceptors = this.getInterceptors();

if(!ObjectUtils.isEmpty(interceptors)) {

for(int i = interceptors.length - 1; i >= 0; --i) {

HandlerInterceptor interceptor = interceptors[i];

interceptor.postHandle(request, response, this.handler, mv);

}

}

}

triggerAfterCompletion() 方法源码如下:可以看出这里也是逆序调用 afterCompletion 方法。

void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, Exception ex) throws Exception {

HandlerInterceptor[] interceptors = this.getInterceptors();

if(!ObjectUtils.isEmpty(interceptors)) {

for(int i = this.interceptorIndex; i >= 0; --i) {

HandlerInterceptor interceptor = interceptors[i];

try {

interceptor.afterCompletion(request, response, this.handler, ex);

} catch (Throwable var8) {

logger.error("HandlerInterceptor.afterCompletion threw exception", var8);

}

}

}

}

Linux公社的RSS地址 : https://www.linuxidc.com/rssFeed.aspx

本文永久更新链接地址: https://www.linuxidc.com/Linux/2019-03/157747.htm

原文  https://www.linuxidc.com/Linux/2019-03/157747.htm
正文到此结束
Loading...