SpringMVC 框架是以請求為驅(qū)動,圍繞 Servlet 設(shè)計,將請求發(fā)給控制器,然后通過模型對象,分派器來展示請求結(jié)果視圖。其中核心類是 DispatcherServlet,它是一個 Servlet,頂層是實現(xiàn)的Servlet接口。
SpringMVC 處理請求過程
- 客戶端發(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 繼承關(guān)系
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