Spring MVC请求处理流程及架构
2016-07-02 17:53
567 查看
在之前
Spring MVC DispatcherServlet的启动以及初始化 中介绍了DispatcherServlet的启动过程,通过这个过程中建立琪了与DispatcherServlet相关的ioc容器环境,并进行了必要的MVC模块初始化工作,为处理请求做好了准备。下面说明DispatcherServlet另一个重要的功能,就是处理web请求。
1、DispatcherServlet类继承体系
以上类图主要反映DispatcherServlet为处理web请求设计的相关类的继承体系,,可以看到,FrameworkServlet通过继承HttpServletBean而继承了HttpSerbvlet,在HttpSerbvlet实现了void service(HttpServletRequest
request, HttpServletResponse response)方法处理web请求,而FrameworkServlet重写了这个方法,除此之外还重写了doGet()和doPost()等方法。最终都将请求调用DispatcherServlet的doDispatcher()方法,doDispatche()是SpringMVC处理web请求的核心方法,在该方法中充分体现DispatcherServlet前置处理器的功能,将主要说明。
2、SpringMVC模式架构
以上架构实现主要在doDispatcher()方法中体现,核心架构的具体流程步骤如下:
1、 首先用户发送请求——>DispatcherServlet,前端控制器收到请求后自己不进行处理,而是委托给其他的解析器进行处理,作为统一访问点,进行全局的流程控制;
2、 DispatcherServlet——>HandlerMapping, HandlerMapping将会把请求映射为HandlerExecutionChain对象(包含一个Handler处理器(页面控制器)对象、多个HandlerInterceptor拦截器)对象,通过这种策略模式,很容易添加新的映射策略;
3、 DispatcherServlet——>HandlerAdapter,HandlerAdapter将会把处理器包装为适配器,从而支持多种类型的处理器,即适配器设计模式的应用,从而很容易支持很多类型的处理器;
4、 HandlerAdapter——>处理器功能处理方法的调用,HandlerAdapter将会根据适配的结果调用真正的处理器的功能处理方法,完成功能处理;并返回一个ModelAndView对象(包含模型数据、逻辑视图名);
5、 ModelAndView的逻辑视图名——> ViewResolver, ViewResolver将把逻辑视图名解析为具体的View,通过这种策略模式,很容易更换其他视图技术;
6、 View——>渲染,View会根据传进来的Model模型数据进行渲染,此处的Model实际是一个Map数据结构,因此很容易支持其他视图技术;
7、返回控制权给DispatcherServlet,由DispatcherServlet返回响应给用户,到此一个流程结束。
注: 此部分内容参考自互联网
3、SpringMVC请求处理具体流程
在MVC框架初始化完成后,对Http的请求处理是在doService()方法中完成,doService()方法在DispatcherServlet类中:
doDispatch()函数是DispatcherServlet完成dispatcher的核心方法,在该方法中通过HandlerMapping获取请求所对应的handler,之后选择合适的HandlerAdapter对handler进行适配,通过适配器调用handler相应的请求处理方法,并返回ModelAndView对象,通过ViewResolver对视图进行解析,得到View,最后通过View类渲染视图进行呈现。可以看到这里是SpringMVC模式的核心体现。
Spring MVC DispatcherServlet的启动以及初始化 中介绍了DispatcherServlet的启动过程,通过这个过程中建立琪了与DispatcherServlet相关的ioc容器环境,并进行了必要的MVC模块初始化工作,为处理请求做好了准备。下面说明DispatcherServlet另一个重要的功能,就是处理web请求。
1、DispatcherServlet类继承体系
以上类图主要反映DispatcherServlet为处理web请求设计的相关类的继承体系,,可以看到,FrameworkServlet通过继承HttpServletBean而继承了HttpSerbvlet,在HttpSerbvlet实现了void service(HttpServletRequest
request, HttpServletResponse response)方法处理web请求,而FrameworkServlet重写了这个方法,除此之外还重写了doGet()和doPost()等方法。最终都将请求调用DispatcherServlet的doDispatcher()方法,doDispatche()是SpringMVC处理web请求的核心方法,在该方法中充分体现DispatcherServlet前置处理器的功能,将主要说明。
2、SpringMVC模式架构
以上架构实现主要在doDispatcher()方法中体现,核心架构的具体流程步骤如下:
1、 首先用户发送请求——>DispatcherServlet,前端控制器收到请求后自己不进行处理,而是委托给其他的解析器进行处理,作为统一访问点,进行全局的流程控制;
2、 DispatcherServlet——>HandlerMapping, HandlerMapping将会把请求映射为HandlerExecutionChain对象(包含一个Handler处理器(页面控制器)对象、多个HandlerInterceptor拦截器)对象,通过这种策略模式,很容易添加新的映射策略;
3、 DispatcherServlet——>HandlerAdapter,HandlerAdapter将会把处理器包装为适配器,从而支持多种类型的处理器,即适配器设计模式的应用,从而很容易支持很多类型的处理器;
4、 HandlerAdapter——>处理器功能处理方法的调用,HandlerAdapter将会根据适配的结果调用真正的处理器的功能处理方法,完成功能处理;并返回一个ModelAndView对象(包含模型数据、逻辑视图名);
5、 ModelAndView的逻辑视图名——> ViewResolver, ViewResolver将把逻辑视图名解析为具体的View,通过这种策略模式,很容易更换其他视图技术;
6、 View——>渲染,View会根据传进来的Model模型数据进行渲染,此处的Model实际是一个Map数据结构,因此很容易支持其他视图技术;
7、返回控制权给DispatcherServlet,由DispatcherServlet返回响应给用户,到此一个流程结束。
注: 此部分内容参考自互联网
3、SpringMVC请求处理具体流程
在MVC框架初始化完成后,对Http的请求处理是在doService()方法中完成,doService()方法在DispatcherServlet类中:
@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) + "]"); } //这里对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)); } } } //这里将一些框架全局对象设置到request中,以便于handler和view中使用 // Make framework objects available to handlers and view objects. 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 {//这里是doDispatcher()函数分发请求的入口 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); } } } }
doDispatch()函数是DispatcherServlet完成dispatcher的核心方法,在该方法中通过HandlerMapping获取请求所对应的handler,之后选择合适的HandlerAdapter对handler进行适配,通过适配器调用handler相应的请求处理方法,并返回ModelAndView对象,通过ViewResolver对视图进行解析,得到View,最后通过View类渲染视图进行呈现。可以看到这里是SpringMVC模式的核心体现。
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,像文件上传这些,如果是通过MultipartResolver进行解析 processedRequest = checkMultipart(request); multipartRequestParsed = (processedRequest != request); //通过getHandler()方法,使用HandlerMapping完成请求到处理器的映射,获取到HandlerExecutionChain // Determine handler for the current request. mappedHandler = getHandler(processedRequest); if (mappedHandler == null || mappedHandler.getHandler() == null) { noHandlerFound(processedRequest, response); return; } //将获取到的Handler处理器进行适配,用响应的HandlerAdapter进行包装 // 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()) { logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified); } if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) { return; } } //如果设置了拦截器,那么在执行handler处理器方法处理之前,进行拦截器预处理 if (!mappedHandler.applyPreHandle(processedRequest, response)) { return; } //通过适配器调用执行处理器的相关功能处理方法,返回ModelAndView对象,包含视图和Model数据 // Actually invoke the handler. mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); if (asyncManager.isConcurrentHandlingStarted()) { return; } applyDefaultViewName(request, mv); //如果设置了拦截器,那么在执行handler处理器方法处理之后,进行拦截器后处理 mappedHandler.applyPostHandle(processedRequest, response, mv); } catch (Exception ex) { dispatchException = ex; } //这里处理请求结果,在个函数中,将判断是否有dispatchException,如果有,将通过ExceptionResolver进行解析处理。然后由ViewResolver解析View ,最后对View进行渲染呈现视图 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 { //如果请求是multipart,那么这里进行资源清理操作 // Clean up any resources used by a multipart request. if (multipartRequestParsed) { cleanupMultipart(processedRequest); } } } }
继续来看processDispatchResult()函数:
private void processDispatchResult(HttpServletRequest request, HttpServletResponse response, HandlerExecutionChain mappedHandler, ModelAndView mv, Exception exception) throws Exception { boolean errorView = false; //如果有异常发出,那么这里将通过processHandlerException()方法处理异常情况,注意返回值仍然是ModelAndView对象 if (exception != null) { if (exception instanceof ModelAndViewDefiningException) { logger.debug("ModelAndViewDefiningException encountered", exception); mv = ((ModelAndViewDefiningException) exception).getModelAndView(); } else { Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null); mv = processHandlerException(request, response, handler, exception); errorView = (mv != null); } } //这里得到最终的ModelAndView,然后进行渲染,渲染函数见下面 // Did the handler return a view to render? if (mv != null && !mv.wasCleared()) { render(mv, request, 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"); } } if (WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) { // Concurrent handling started during a forward return; } //这里如果设置有拦截器,那么在完成渲染、视图呈现后,进行拦截器AfterCompletion调用 if (mappedHandler != null) { mappedHandler.triggerAfterCompletion(request, response, null); } }
在渲染函数render中,主要通过ViewResolver完成视图解析获取对应的视图,然后通过View对象渲染呈现视图
protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception { // Determine locale for request and apply it to the response. Locale locale = this.localeResolver.resolveLocale(request); response.setLocale(locale); View view; if (mv.isReference()) { //由ViewResolver解析View // We need to resolve the view name. view = resolveViewName(mv.getViewName(), mv.getModelInternal(), locale, request); if (view == null) { throw new ServletException("Could not resolve view with name '" + mv.getViewName() + "' in servlet with name '" + getServletName() + "'"); } } else { // No need to lookup: the ModelAndView object contains the actual View object. view = mv.getView(); if (view == null) { throw new ServletException("ModelAndView [" + mv + "] neither contains a view name nor a " + "View object in servlet with name '" + getServletName() + "'"); } } // Delegate to the View object for rendering. if (logger.isDebugEnabled()) { logger.debug("Rendering view [" + view + "] in DispatcherServlet with name '" + getServletName() + "'"); } try { //通过View完成视图在渲染,渲染时会把Model传入 view.render(mv.getModelInternal(), request, response); } catch (Exception ex) { if (logger.isDebugEnabled()) { logger.debug("Error rendering view [" + view + "] in DispatcherServlet with name '" + getServletName() + "'", ex); } throw ex; } }
相关文章推荐
- Spring整合Dwr,Cannot locate BeanDefinitionParser for element [annotation-scan]
- spring3 MVC手工搭建Spring3项目demo
- spring mvc 开发需要的jar包的用途详解
- 基于注解的 Spring MVC 简单入门-网摘
- [MVC] 深入浅出Spring MVC
- spring mvc的web.xml的配置
- SpringMVC工作原理
- Spring MVC静态资源处理<mvc:resources><mvc:default-servlet-handler>
- Spring MVC 为例,从前台—>后台—>前台的编解码过程及出现乱码的案例
- 在spring mvc与mybatis中加入logback
- springmvc+mybatis
- 当项目使用SpringMvc时拦截器的注意事项
- spring mvc 的设计模式
- (struts2) spring mvc + mybatis + maven整合
- 文章标题
- springmvc集成mybatis
- Spring+Spring MVC 整合JasperReports
- 使用springmvc框架之第1篇:spring中bean的系统自动注册
- SpringMVC Json
- ajax跨域:JQuery + Spring MVC3.0