您的位置:首页 > 编程语言 > Java开发

源码深度解析SpringMvc请求运行机制(转)

2015-07-25 10:48 555 查看

源码深度解析SpringMvc请求运行机制

本文依赖的是springmvc4.0.5.RELEASE,通过源码深度解析了解springMvc的请求运行机制。通过源码我们可以知道从客户端发送一个URL请求给springMvc开始,到返回数据给客户端期间是怎么运转的。

1、用户请求处理过程:

1、用户发送请求时会先从DispathcherServler的doService方法开始,在该方法中会将ApplicationContext、localeResolver、themeResolver等对象添加到request中,紧接着就是调用doDispatch方法:

源码:

[java] view plaincopyprint?

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

}

}

}

doDispatch方法就是处理用户请求的方法。

2、进入该方法后首先会检查该请求是否是文件上传的请求(校验的规则是是否是post并且contenttType是否为multipart/为前缀)即调用的是checkMultipart方法;如果是的将request包装成MultipartHttpServletRequest。见源码:

doDispatch:

[java] view plaincopyprint?

processedRequest = checkMultipart(request);

checkMultipart:

[java] view plaincopyprint?

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:

[java] view plaincopyprint?

HandlerExecutionChain mappedHandler = null;

mappedHandler = getHandler(processedRequest);

getHandler方法:

[java] view plaincopyprint?

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;

}

[java] view plaincopyprint?

hm.getHandler方法:

[java] view plaincopyprint?

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:

[java] view plaincopyprint?

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中的模型数据进行视图渲染

本文转自:/article/2639710.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: