spring mvc 的工作原理(1)DispatcherServlet 请求处理流程
2016-05-31 00:00
567 查看
摘要: 上一篇我简单的介绍了spring mvc的原理、流程,下面我要深入源码了解下。
类关系
DispatcherServlet 继承 FrameworkServlet 继承 HttpServletBean,HttpServletBean 是一个HttpServlet和EnvironmentCapable, EnvironmentAware接口的实现。
本章关注点在DispatcherServlet对请求的分派调用流程上,这些类暂不关注。
成员变量
1、静态变量主要是一些bean名称,以及request attribute 的key。如
2、具体的特殊的bean,上一章中提到的特殊bean。如
方法
方法重点关注doService,doDispatch这两个方法,其他的方法是get/set 和初始化方法,不是本章的关注对象。下面的这两个方法源码和注释。
注释不正确的地方,请指出。
从源码我们可以看出,基本上请求的出来流程正如第一篇中所描述的。
第一步是绑定各种各样的web context bean。
第二步是搜索获取对应请求的处理handler,以及对应的adapter。
第三步是执行找出的handler,前拦截器,handler, 后拦截器。
第四步是将结果或异常进行处理,如将string 映射到具体的view 或者输出json等。捕获异常的调用Exception handler 处理。
类关系
DispatcherServlet 继承 FrameworkServlet 继承 HttpServletBean,HttpServletBean 是一个HttpServlet和EnvironmentCapable, EnvironmentAware接口的实现。
本章关注点在DispatcherServlet对请求的分派调用流程上,这些类暂不关注。
成员变量
1、静态变量主要是一些bean名称,以及request attribute 的key。如
[code=language-java]/** Well-known name for the MultipartResolver object in the bean factory for this namespace. */ public static final String MULTIPART_RESOLVER_BEAN_NAME = "multipartResolver"; /** Well-known name for the LocaleResolver object in the bean factory for this namespace. */ public static final String LOCALE_RESOLVER_BEAN_NAME = "localeResolver"; /** Well-known name for the ThemeResolver object in the bean factory for this namespace. */ public static final String THEME_RESOLVER_BEAN_NAME = "themeResolver";
2、具体的特殊的bean,上一章中提到的特殊bean。如
[code=language-java]/** MultipartResolver used by this servlet */ private MultipartResolver multipartResolver; /** LocaleResolver used by this servlet */ private LocaleResolver localeResolver; /** ThemeResolver used by this servlet */ private ThemeResolver themeResolver; /** List of HandlerMappings used by this servlet */ private List<HandlerMapping> handlerMappings;
方法
方法重点关注doService,doDispatch这两个方法,其他的方法是get/set 和初始化方法,不是本章的关注对象。下面的这两个方法源码和注释。
[code=language-java] //重写HttpServlet 的请求处理方法 @Override 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)) { //是内部发出的请求 forward attributesSnapshot = new HashMap<String, Object>(); Enumeration<?> attrNames = request.getAttributeNames(); while (attrNames.hasMoreElements()) { String attrName = (String) attrNames.nextElement(); //如果是DispatcherServlet cleanupAfterInclude(是include 请求就清理)属性为true,或者request的属性是DispatcherServlet附加的,保存备份 if (this.cleanupAfterInclude || attrName.startsWith("org.springframework.web.servlet")) { attributesSnapshot.put(attrName, request.getAttribute(attrName)); } } } //附加webApplicationContext 的特殊bean // Make framework objects available to handlers and view objects. //web application context 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()); //闪存,重定向时可以不携带参数 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 { //分派到handler,进行业务逻辑处理 doDispatch(request, response); } finally { if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) { // Restore the original attribute snapshot, in case of an include. if (attributesSnapshot != null) { restoreAttributesAfterInclude(request, attributesSnapshot); } } } } protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception { HttpServletRequest processedRequest = request; HandlerExecutionChain mappedHandler = null; boolean multipartRequestParsed = false; WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request); try { ModelAndView mv = null; Exception dispatchException = null; try { //检查是否 multipart request processedRequest = checkMultipart(request); //request 不等于 processedRequest 表示检查到multi ,并构建返回 multi request multipartRequestParsed = (processedRequest != request); // Determine handler for the current request. //决定、判断、获取 handler mappedHandler = getHandler(processedRequest); if (mappedHandler == null || mappedHandler.getHandler() == null) { //找不到相应的handler ,返回并提示 noHandlerFound noHandlerFound(processedRequest, response); return; } // Determine handler adapter for the current request. //查找handler 的适配器(不同的方法细节多样、参数等,通过adapter 封装) HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler()); // Process last-modified header, if supported by the handler. //判断是否支持last-modified String method = request.getMethod(); boolean isGet = "GET".equals(method); if (isGet || "HEAD".equals(method)) { long lastModified = ha.getLastModified(request, mappedHandler.getHandler()); if (logger.isDebugEnabled()) { 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; } // Actually invoke the handler. //调用实际业务方法逻辑 mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); if (asyncManager.isConcurrentHandlingStarted()) { return; } //解析modelview 中的名称映射对应的视图模板。 applyDefaultViewName(processedRequest, mv); //执行后拦截器 mappedHandler.applyPostHandle(processedRequest, response, mv); } catch (Exception ex) { dispatchException = ex; } //处理执行的结果,异常的话,跳转处理异常的代码。 processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException); } catch (Exception ex) { triggerAfterCompletion(processedRequest, response, mappedHandler, ex); } catch (Error err) { triggerAfterCompletionWithError(processedRequest, response, mappedHandler, err); } finally { if (asyncManager.isConcurrentHandlingStarted()) { // Instead of postHandle and afterCompletion if (mappedHandler != null) { mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response); } } else { // Clean up any resources used by a multipart request. if (multipartRequestParsed) { cleanupMultipart(processedRequest); } } } }
注释不正确的地方,请指出。
从源码我们可以看出,基本上请求的出来流程正如第一篇中所描述的。
第一步是绑定各种各样的web context bean。
第二步是搜索获取对应请求的处理handler,以及对应的adapter。
第三步是执行找出的handler,前拦截器,handler, 后拦截器。
第四步是将结果或异常进行处理,如将string 映射到具体的view 或者输出json等。捕获异常的调用Exception handler 处理。
相关文章推荐
- 分享微信开发Html5轻游戏中的几个坑
- 一个jar包里的网站
- 一个jar包里的网站之文件上传
- 一个jar包里的网站之返回对媒体类型
- Spring和ThreadLocal
- Spring Boot 开发微服务
- Spring整合Quartz(JobDetailBean方式)
- Spring整合Quartz(JobDetailBean方式)
- C# MVC模式下商品抽奖功能实现
- Zend的MVC机制使用分析(二)
- ASP.NET MVC 4 捆绑和缩小实例介绍
- ASP.NET Mvc开发之查询数据
- ASP.NET MVC中将控制器分离到类库的实现
- asp.net实现在非MVC中使用Razor模板引擎的方法
- ASP.NET MVC中的AJAX应用
- 为ASP.NET MVC及WebApi添加路由优先级
- ASP.NET MVC中图表控件的使用方法
- Asp.net mvc实时生成缩率图到硬盘
- 剖析ASP.NET MVC的DependencyResolver组件