标签:spring mvc 源码 java
本文依赖的是springmvc4.0.5.RELEASE,通过源码深度解析了解springMvc的请求运行机制。通过源码我们可以知道从客户端发送一个URL请求给springMvc开始,到返回数据给客户端期间是怎么运转的。1、用户请求处理过程:
1、用户发送请求时会先从DispathcherServler的doService方法开始,在该方法中会将ApplicationContext、localeResolver、themeResolver等对象添加到request中,紧接着就是调用doDispatch方法:
源码:
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception { if (logger.isDebugEnabled()) { String resumed = WebAsyncUtils.getAsyncManager(request).hasConcurrentResult() ? " resumed" : ""; logger.debug("DispatcherServlet with name '" + getServletName() + "'" + resumed + " processing " + request.getMethod() + " request for [" + getRequestUri(request) + "]"); } // Keep a snapshot of the request attributes in case of an include, // to be able to restore the original attributes after the include. Map<String, Object> attributesSnapshot = null; if (WebUtils.isIncludeRequest(request)) { attributesSnapshot = new HashMap<String, Object>(); Enumeration<?> attrNames = request.getAttributeNames(); while (attrNames.hasMoreElements()) { String attrName = (String) attrNames.nextElement(); if (this.cleanupAfterInclude || attrName.startsWith("org.springframework.web.servlet")) { attributesSnapshot.put(attrName, request.getAttribute(attrName)); } } } // Make framework objects available to handlers and view objects. <strong>request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, getWebApplicationContext()); request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver); request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver); request.setAttribute(THEME_SOURCE_ATTRIBUTE, getThemeSource());</strong> 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 { <strong>doDispatch(request, response);</strong> } finally { if (WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) { return; } // Restore the original attribute snapshot, in case of an include. if (attributesSnapshot != null) { restoreAttributesAfterInclude(request, attributesSnapshot); } } }
2、进入该方法后首先会检查该请求是否是文件上传的请求(校验的规则是是否是post并且contenttType是否为multipart/为前缀)即调用的是checkMultipart方法;如果是的将request包装成MultipartHttpServletRequest。见源码:
doDispatch:
processedRequest = checkMultipart(request);checkMultipart:
protected HttpServletRequest checkMultipart(HttpServletRequest request) throws MultipartException { if (this.multipartResolver != null && this.multipartResolver.isMultipart(request)) { if (request instanceof MultipartHttpServletRequest) { logger.debug("Request is already a MultipartHttpServletRequest - if not in a forward, " + "this typically results from an additional MultipartFilter in web.xml"); } else if (request.getAttribute(WebUtils.ERROR_EXCEPTION_ATTRIBUTE) instanceof MultipartException) { logger.debug("Multipart resolution failed for current request before - " + "skipping re-resolution for undisturbed error rendering"); } else { return this.multipartResolver.resolveMultipart(request); } } // If not returned before: return original request. return request; }3、然后调用getHandler方法来匹配每个HandlerMapping对象,如果匹配成功会返回这个Handle的处理链HandlerExecutionChain对象,在获取该对象的内部其实也获取我们自定定义的拦截器,并执行了其中的方法
见源码:
doDispatch:
HandlerExecutionChain mappedHandler = null; mappedHandler = getHandler(processedRequest);getHandler方法:
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { for (HandlerMapping hm : this.handlerMappings) { if (logger.isTraceEnabled()) { logger.trace( "Testing handler map [" + hm + "] in DispatcherServlet with name '" + getServletName() + "'"); } HandlerExecutionChain handler = hm.getHandler(request); if (handler != null) { return handler; } } return null; }
hm.getHandler方法:
public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { Object handler = getHandlerInternal(request); if (handler == null) { handler = getDefaultHandler(); } if (handler == null) { return null; } // Bean name or resolved handler? if (handler instanceof String) { String handlerName = (String) handler; handler = getApplicationContext().getBean(handlerName); } return getHandlerExecutionChain(handler, request); }getHandlerExecutionChain:
protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) { HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ? (HandlerExecutionChain) handler : new HandlerExecutionChain(handler)); chain.addInterceptors(getAdaptedInterceptors()); String lookupPath = this.urlPathHelper.getLookupPathForRequest(request); for (MappedInterceptor mappedInterceptor : this.mappedInterceptors) { if (mappedInterceptor.matches(lookupPath, this.pathMatcher)) { chain.addInterceptor(mappedInterceptor.getInterceptor()); } } return chain; }4、执行拦截器的preHandle方法,如果返回false执行afterCompletion方法并理解返回
5、通过上述获取到了HandlerExecutionChain对象,通过该对象的getHandler()方法获得一个object通过HandlerAdapter进行封装得到HandlerAdapter对象
6、该对象调用handle方法来执行Controller中的方法,该对象如果返回一个ModelAndView给DispatcherServlet
7、DispatcherServlet借助ViewResolver完成逻辑试图名到真实视图对象的解析,得到View后DispatcherServlet使用这个View对ModelAndView中的模型数据进行视图渲染
版权声明:本文为博主原创文章,未经博主允许不得转载。
标签:spring mvc 源码 java
原文地址:http://blog.csdn.net/liyantianmin/article/details/46948963