一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術(shù)|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務(wù)器之家 - 編程語言 - Java教程 - 詳解SpringMVC從基礎(chǔ)到源碼

詳解SpringMVC從基礎(chǔ)到源碼

2020-09-20 12:26沸羊羊_ Java教程

這篇文章主要介紹了詳解SpringMVC從基礎(chǔ)到源碼,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧

認識SpringMVC

SpringMVC 框架是以請求為驅(qū)動,圍繞 Servlet 設(shè)計,將請求發(fā)給控制器,然后通過模型對象,分派器來展示請求結(jié)果視圖。其中核心類是 DispatcherServlet,它是一個 Servlet,頂層是實現(xiàn)的Servlet接口。

詳解SpringMVC從基礎(chǔ)到源碼

SpringMVC 處理請求過程

詳解SpringMVC從基礎(chǔ)到源碼

  • 客戶端發(fā)起請求,會首先經(jīng)過前端控制器 DispatcherServlet 進行轉(zhuǎn)發(fā),轉(zhuǎn)發(fā)到 Handler Mapping
  • DispatcherServlet 從 Handler Mapping 查找處理請求的 Controller,Handler Mapping 作用就是完成 URL 到 Controller 的映射
  • Controller 處理請求并返回 ModelAndView 對象,ModelAndView 是封裝結(jié)果視圖的組件
  • 再將視圖結(jié)果返回給客戶端

Servlet 與 SpringMVC

SpringMVC 是在 Servlet 的基礎(chǔ)上進行了擴展,看看他們的繼承關(guān)系是什么樣的。

Servlet 繼承關(guān)系

詳解SpringMVC從基礎(chǔ)到源碼

SpringMVC 繼承關(guān)系

詳解SpringMVC從基礎(chǔ)到源碼

Servlet 與 SpringMVC 對比

  • Servlet 需要每個請求都在 web.xml 文件中配置一個 sevlet 節(jié)點
  • SpringMVC 的 DispatcherServlet 會攔截所有請求,讓 Controller 去處理

Structs2 與 Spring MVC

相同點

都是基于MVC模型的

不同點

  • Structs2 是基于類的,一個 request 創(chuàng)建一個 action,一個action 對應(yīng)一個 request ;Servlet 是基于方法的,也就是一個 request 對應(yīng)一個方法
  • Structs2 入口是 Filter;SpringMVC 入口是 Servlet
  • SpringMVC 的開發(fā)速度和性能優(yōu)于 Structs2 ,流程更易理解
  • SpringMVC 和 Spring 是無縫的,可以認為 SpringMVC 是100% 零配置

SpringMVC源碼分析

1、ApplicationContext 初始化時建立所有的URL和Controller 的對應(yīng)關(guān)系

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
/**
* 建立當前ApplicationContext中的所有controller和url的對應(yīng)關(guān)系
*/
protected void detectHandlers() throws BeansException {
  //日志級別是否是 Debug
  if (logger.isDebugEnabled()) {
    //應(yīng)用上下文就是工程的訪問路徑
    logger.debug("Looking for URL mappings in application context: " + getApplicationContext());
  }
     // 獲取ApplicationContext容器中所有bean的Name---Controller
  String[] beanNames = (this.detectHandlersInAncestorContexts ?
      BeanFactoryUtils.beanNamesForTypeIncludingAncestors(getApplicationContext(), Object.class) :
      getApplicationContext().getBeanNamesForType(Object.class));
 
  // 遍歷beanNames,并找到這些bean對應(yīng)的url
  for (String beanName : beanNames) {
       // 獲取Controller上的所有url(類上的url+方法上的url)
    String[] urls = determineUrlsForHandler(beanName);
    if (!ObjectUtils.isEmpty(urls)) {
      // 保存urls和beanName的對應(yīng)關(guān)系,put it to Map<urls,beanName>,該方法在父類AbstractUrlHandlerMapping中實現(xiàn)
      registerHandler(urls, beanName);
    }
    else {
      if (logger.isDebugEnabled()) {
        logger.debug("Rejected bean name '" + beanName + "': no URL paths identified");
      }
    }
  }
}

2、根據(jù)訪問URL找到對應(yīng) Controller 中處理請求的方法

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
/** 中央控制器,控制請求的轉(zhuǎn)發(fā) **/
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpServletRequest processedRequest = request;
HandlerExecutionChain mappedHandler = null;
int interceptorIndex = -1;
 
try {
  ModelAndView mv;
  boolean errorView = false;
  try {
    // 1.檢查是否是文件上傳的請求
    processedRequest = checkMultipart(request);
 
    // 2.取得處理當前請求的controller,這里也稱為hanlder,處理器,第一個步驟的意義就在這里體現(xiàn)了.
    這里并不是直接返回controller,而是返回的HandlerExecutionChain請求處理器鏈對象,該對象封裝了handler和interceptors.
    mappedHandler = getHandler(processedRequest, false);
    // 如果handler為空,則返回404
    if (mappedHandler == null || mappedHandler.getHandler() == null) {
      noHandlerFound(processedRequest, response);
      return;
    }
    //3. 獲取處理request的處理器適配器handler adapter
    HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
    // 處理 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()) {
        String requestUri = urlPathHelper.getRequestUri(request);
        logger.debug("Last-Modified value for [" + requestUri + "] is: " + lastModified);
      }
      if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
        return;
      }
    }
 
    // 4.攔截器的預處理方法
    HandlerInterceptor[] interceptors = mappedHandler.getInterceptors();
    if (interceptors != null) {
      for (int i = 0; i < interceptors.length; i++) {
        HandlerInterceptor interceptor = interceptors[i];
        if (!interceptor.preHandle(processedRequest, response, mappedHandler.getHandler())) {
          triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, null);
          return;
        }
        interceptorIndex = i;
      }
    }
 
    // 5.實際的處理器處理請求,返回結(jié)果視圖對象
    mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
 
    // 結(jié)果視圖對象的處理
    if (mv != null && !mv.hasView()) {
      mv.setViewName(getDefaultViewName(request));
    }
 
    // 6.攔截器的后處理方法
    if (interceptors != null) {
      for (int i = interceptors.length - 1; i >= 0; i--) {
        HandlerInterceptor interceptor = interceptors[i];
        interceptor.postHandle(processedRequest, response, mappedHandler.getHandler(), mv);
      }
    }
  }
  catch (ModelAndViewDefiningException ex) {
    logger.debug("ModelAndViewDefiningException encountered", ex);
    mv = ex.getModelAndView();
  }
  catch (Exception ex) {
    Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);
    mv = processHandlerException(processedRequest, response, handler, ex);
    errorView = (mv != null);
  }
 
  
  if (mv != null && !mv.wasCleared()) {
    render(mv, processedRequest, 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");
    }
  }
 
  // 請求成功響應(yīng)之后的方法
  triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, null);
}

3、反射調(diào)用處理請求的方法返回結(jié)果視圖

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/** 獲取處理請求的方法,執(zhí)行并返回結(jié)果視圖 **/
protected ModelAndView invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, Object handler)
    throws Exception {
  // 1.獲取方法解析器
  ServletHandlerMethodResolver methodResolver = getMethodResolver(handler);    
  // 2.解析request中的url,獲取處理request的方法
  //通過 request 找 controller 中的處理方法,request的url與 controller 的url 進行匹配
  Method handlerMethod = methodResolver.resolveHandlerMethod(request);    
  // 3.方法調(diào)用器
  ServletHandlerMethodInvoker methodInvoker = new ServletHandlerMethodInvoker(methodResolver);
  ServletWebRequest webRequest = new ServletWebRequest(request, response);
  ExtendedModelMap implicitModel = new BindingAwareModelMap();
     // 4.執(zhí)行方法
  Object result = methodInvoker.invokeHandlerMethod(handlerMethod, handler, webRequest, implicitModel);    
  // 5.封裝結(jié)果視圖
  ModelAndView mav =
      methodInvoker.getModelAndView(handlerMethod, handler.getClass(), result, implicitModel, webRequest);
  methodInvoker.updateModelAttributes(handler, (mav != null ? mav.getModel() : null), implicitModel, webRequest);
  return mav;
}

到此這篇關(guān)于詳解SpringMVC從基礎(chǔ)到源碼的文章就介紹到這了,更多相關(guān)SpringMVC 源碼內(nèi)容請搜索服務(wù)器之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持服務(wù)器之家!

原文鏈接:https://blog.csdn.net/weixin_42653522/article/details/108345745

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 日日操美女 | 国产九九在线观看播放 | 99久久精品国语对白 | 91麻豆国产| 欧美怡红院视频一区二区三区 | 国产人成精品午夜在线观看 | 手机跑分排行最新排名 | 国内精品久久久久久久久 | xxx中国bbbwww | 香港三级系列在线播放 | 潘甜甜在线观看 | 爆操女友 | 成年视频在线观看免费 | 爽好舒服使劲添高h视频 | 日本妻子迷妹网 | 秘书喂奶好爽一边 | 精品第一国产综合精品蜜芽 | 毛片大全免费看 | 日本www午夜色在线视频 | 国产一区二区精品久 | 日本三级免费观看 | 91aaa免费免费国产在线观看 | 睡男神的这件小事小说在线阅读 | 精品人人做人人爽久久久 | nxgx国产| 国产精品成人 | 韩国三级日本三级香港三级黄 | 2022国产麻豆剧传媒剧情 | aaa毛片在线| 精品日韩欧美一区二区三区 | 沉香如屑西瓜视频免费观看完整版 | 欧美日韩亚洲第一区在线 | 日本激情在线 | 高h细节肉爽文办公室 | 青青草成人在线 | 99在线播放视频 | 免费操比视频 | 黄a在线观看 | 亚洲乱码一二三四五六区 | 国产成人在线播放视频 | 亚洲国产第一区二区三区 |