spring-mvc 原理

一、Spring-MVC 加载流程:

1.客户端发送请求,前端控制器 DispatcherServlet 收到请求

2.DispatcherServlet 收到请求,调用 HandlerMapping 处理映射器

3.HandleMapping 处理映射器获取 Handler 处理器以及 HandlerInterceptor 拦截器,并且一并返回给 DispatcherServlet (其中处理器是可以通过配置文件以及注解来完成)

4.DispatcherServlet  前端处理器获取 HandlerAdapter 处理器适配器,然后 HandlerAdapter  会根据Handler 的规则去执行具体的 Handler ,然后返回一个 ModelAndView 给前端控制器 DispatcherServelet 

5. DispatcherServlet  前端控制器再将 ModelAndView  扔给 ViewResolver 视图解析器,然后返回一个具体的 view 给到前端控制器 DispatcherServlet  

6. 前端控制器将得到的 View 进行渲染,然后 DispatecherServlet 响应请求结果给客户端


步骤解释:

前端控制器(DispatcherServlet):接收请求,响应结果

处理器映射器(HandlerMapping):根据URL去查找处理器

处理器(Handler):就是程序员所写的处理逻辑

@RequestMapping("/test")
public String initPage(Model model) {
    model.addAttribute("nowTime", new Date());
    return "test/index";
}

或者

@RequestMapping("/test")
public ModelAndView detail(ModelAndView modelAndView, HttpServletRequest request) {
    modelAndView.addObject("nowTime", new Date());
    modelAndView.setViewName("test/index");
    return modelAndView;
}

处理器适配器(HandlerAdapter):会把处理器包装成适配器,这样就可以支持多种类型的处理器,类比笔记本的适配器(适配器模式的应用)

视图解析器(ViewResovler):进行视图解析,多返回的字符串,进行处理,可以解析成对应的页面


二、源码简单分析

1.先查看 web.xml 配置,这里只贴出 Spring-MVC 部分的配置,这里是上图核心中央处理器的配置,也就是前端控制器


2.查看 DispatcherServlet 可发现,它继承了 FrameworkServlet 类,继续查看,发现 FrameworkServlet 继承了 HttpServletBean 类,继续查看,发现HttpServletBean 继承了 HttpServlet 类,至此,我们知道 spring-mvc 是基于 Servlet 的,所以我们找到了 FrameworkServlet doService() 方法,但是这个方法是抽象方法,因此在DispatcherServlet  中找到了它的实现方法,如下面的源码,但是这个方法不是最核心的,最核心的应该是 doDispatch()方法,下面一点介绍原因

@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)) {
      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.
   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 {
      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);
         }
      }
   }
}

3.中央控制器的核心部分,从下面源码中可以看出来,整个中央处理器的过程都在这里,这个方法内部包括了 前端控制器DispatcherServlet 获取 Handler --> HandlerAdapter --> ModelAndView --> View 的过程

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 {
         processedRequest = checkMultipart(request);
         multipartRequestParsed = (processedRequest != request);

         // Determine handler for the current request.
         mappedHandler = getHandler(processedRequest);
         if (mappedHandler == null || mappedHandler.getHandler() == null) {
            noHandlerFound(processedRequest, response);
            return;
         }

        /*
         * 这里是通过处理映射器先得到 Handler 处理器,
          * 然后再跟进 Handle 处理器获取 HandlerAdapter 处理器适配器,最终获得的是 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;
            }
         }

         if (!mappedHandler.applyPreHandle(processedRequest, response)) {
            return;
         }
          // 这里是获取 ModelAndView 
         // Actually invoke the handler.
         mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

         if (asyncManager.isConcurrentHandlingStarted()) {
            return;
         }
          // 获取视图
         applyDefaultViewName(processedRequest, mv);
         mappedHandler.applyPostHandle(processedRequest, response, mv);
      }
      catch (Exception ex) {
         dispatchException = ex;
      }
      catch (Throwable err) {
         // As of 4.3, we're processing Errors thrown from handler methods as well,
         // making them available for @ExceptionHandler methods and other scenarios.
         dispatchException = new NestedServletException("Handler dispatch failed", err);
      }
      processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
   }
   catch (Exception ex) {
      triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
   }
   catch (Throwable err) {
      triggerAfterCompletion(processedRequest, response, mappedHandler,
            new NestedServletException("Handler processing failed", 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);
         }
      }
   }
}


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值