Spring MVC请求处理流程及架构

     在之前 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;
}
}














评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值