當前位置:首頁 » 操作系統 » springmvc源碼分析

springmvc源碼分析

發布時間: 2022-04-28 02:54:24

A. 如何深入理解springmvc

許多 ASP.NET 開發人員開始接觸 MVC,都認為 MVC 與 ASP.NET 完全沒有關系,是一個全新的 Web 開發。
事實上 ASP.NET 是創建 WEB 應用的框架,而 MVC 是一種能夠用更好的方法來組織並管理代碼的體系,所以可以稱之為 ASP.NET MVC。
因此,我們可以將原來的 ASP.NET 稱為 ASP.NET Webforms,新的 MVC 稱為 ASP.NET MVC。
深入理解,請參考下面的博客
http://gcdn.gcpowertools.com.cn/showtopic-23645-1-3.html

B. spring mvc後台框架源碼

1. 模塊化、服務化,流程化,耦合度低、擴展性好,靈活度高,工具類封裝完整,干凈利索,調用簡單方便
2. 提供Rest服務,支持APP手機應用(android和ios)介面、php、.net、易語言、VB等第三方介面調用
3. 全新高大尚HTML5+css3.0+bootstrap響應式開發界面UI,( 手機 PC 平板 截圖在下面)、前沿. spring restful 風格
4. 框架搭建完善成熟,在此基礎上做過很多項目,系統具有並發處理、分布式、穩定性。
5. 系統功能完善,此為框架平台,文檔、注釋齊全,提供技術支持,專門供二次開發
6. 在此基礎上可二次開發(OA、ERP、CRM ,醫療管理、金融、網站後台、APP後台、電子商務、商城(贈送UI)等等

C. 如何學習springmvc源代碼

首先要了解設計模式,這個是閱讀大師源碼的一個橋梁,很多代碼看上去很多,其實就是一種模式。了解了模式後,整個關系圖就清楚了。
還有善於分片閱讀,找簡單的讀,可以先讀spring jdbc,這部分的模板跟回調看起來會簡單點。
然後再看IOC,看IOC之前必須對spring IOC原理掌握的很透徹,怎麼擴展,怎麼寫膠水代碼整合其他框架。建議熟讀Spring-Reference。
然後再讀源碼,先學習怎麼寫出漂亮的代碼,再學習怎麼設計出漂亮的模式。

D. 如何讀懂spring mvc 源碼

讀順序:
1. SpringMVC入門
SpringMVC的入門文章, 對於某些沒接觸過SpringMVC的同學來說,可以閱讀以下,了解這個框架的結構以及使用,以入門的同學可以選擇不看~
2. SpringMVC核心分發器DispatcherServlet分析
SpringMVC入口Servlet -> DispatcherServlet的分析,解釋了DispatcherServlet的父類FrameworkServlet以及FrameworkServlet的父類HttpServletBean的作用
3. 詳解SpringMVC請求的時候是如何找到正確的Controller

E. 《看透SpringMVC源代碼分析與實踐》epub下載在線閱讀全文,求百度網盤雲資源

《看透SpringMVC源代碼分析與實踐》(韓路彪)電子書網盤下載免費在線閱讀

鏈接: https://pan..com/s/1ke0ymgIdAwC85IhD0uUG_Q

提取碼: zn6h

書名:看透SpringMVC源代碼分析與實踐

作者:韓路彪

出版社:機械工業出版社

副標題:源代碼分析與實踐

原作名:韓路彪

出版年:2016-1-1

頁數:309

內容簡介

國內資深Web開發專家根據Spring MVC全新技術撰寫,基於實際生產環境,從基礎知識、源代碼和實戰3個維度對Spring MVC的結構和實現進行詳細講解

全面介紹Spring MVC的架構、原理、核心概念和操作,通過案例完整呈現Tomcat的實現,系統總結Spring MVC九大組件的處理以及常用的技巧和實踐

在大型網站和復雜系統的開發中,java具有天然的優勢,而在Java的Web框架中Spring MVC以其強大的功能以及簡單且靈活的用法受到越來越多開發者的青睞。本書不僅詳細地分析Spring MVC的結構及其實現細節,而且講解網站的不同架構及其演變的過程,以及網路底層協議的概念及其實現方法,幫助讀者開發更高效的網站。

作者簡介

韓路彪當代知名作家。

F. 如何深入 spring mvc

SpringMVC是一個輕量級的MVC框架,SpringMVC由於其輕量級的實現以及與Spring框架的無縫整合等諸多優勢,近年來在MVC框架中脫穎而出,受到諸多開發人員的青睞,學習SpringMVC勢在必行。

Web環境中使用SpringMVC:SpringMVC提供了可插拔式的框架嵌入形式,將SpirngMVC插入或者從Web項目中卸載只需要簡單的修改配置文件即可。

  • 配置前端控制器,SpringMVC的入口程序為一個全局的Servlet,該Servlet攔截指定的一組請求交給SpringMVC框架執行後續的處理操作,在Web.xml中配置如下欄位。

  • [java]view plain

  • <!--SpingMVC的前端控制器-->

  • <servlet>

  • <servlet-name>dispatcher</servlet-name>

  • <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

  • <!--配置SpringMVC的IOC容器-->

  • <init-param>

  • <param-name>contextConfigLocation</param-name>

  • <param-value>/WEB-INF/root-context.xml</param-value>

  • </init-param>

  • <load-on-startup>1</load-on-startup>

  • </servlet>

  • <!--配置攔截所有的請求-->

  • <servlet-mapping>

  • <servlet-name>dispatcher</servlet-name>

  • <url-pattern>/</url-pattern>

  • </servlet-mapping></span></span>

  • 創建SpringMVC IOC容器的配置文件root-context.xml並定義視圖解析器,位置/WEB-INF/

  • [java]view plain

  • <!--配置自動掃面的包-->

  • <context:component-scanbase-package="cn.com.xiaofen"/>

  • <!--定義視圖解析器-->

  • <bean

  • class="org.springframework.web.servlet.view.InternalResourceViewResolver">

  • <propertyname="prefix"value="/WEB-INF/view/"></property>

  • <propertyname="suffix"value=".jsp"></property>

  • </bean>

  • <!--<mvc:default-servlet-handler/><mvc:annotation-driven/>--></span></span>

  • 定義控制器,SpringMVC中定義方法來響應客戶端請求,內存開銷更小效率更高。

  • [java]view plain

  • @Controller

  • @RequestMapping("/T")

  • publicclassT{

  • @RequestMapping("/t_1")

  • publicStringt_1(){

  • System.out.println("t_1");

  • return"index";

  • }

  • }

  • 定義視圖,根據實際的視圖解析器完成相關視圖的配置,當前配置視圖應該在/WEB-INF/view/下且文件類型為JSP文件,具體的應該在該目錄下新建一個名稱為index的jsp文件名稱。

  • SpringMVC處理請求的工作流:DispatcherServlet作為SpringMVC框架的入口程序,負責調度SpringMVC框架響應用戶的請求,如下圖為宏觀上SpingMVC處理一次請求大概需要經過以下調度過程。

  • 請求進入由前端控制器(DispatcherServlet )攔截。

  • 前端控制器分析請求將請求委託至具體的控制器來處理。

  • 控制器處理請求返回邏輯視圖(Model)。

  • 前端控制器得到邏輯視圖對象,調度視圖解析器,解析視圖模版給用戶響應。

  • 返回前端控制器。

  • SpringMVC請求流程(部分源碼分析):由DispatcherServlet的doService()方法入手,篇幅關系,下文僅列出核心的代碼,下文的代碼並並保證時間上的順序性。

  • DispatcherServlet調用doDispatch處理請求。

  • [java]view plain

  • try{

  • /*邏輯視圖及上文提到的Model*/

  • ModelAndViewmv=null;

  • ExceptiondispatchException=null;

  • try{

  • /*文件上傳預處理*/

  • processedRequest=checkMultipart(request);

  • multipartRequestParsed=(processedRequest!=request);

  • /*確定當前請求的處理者*/

  • mappedHandler=getHandler(processedRequest);

  • /*請求資源未發現*/

  • if(mappedHandler==null||mappedHandler.getHandler()==null){

  • noHandlerFound(processedRequest,response);

  • return;

  • }

  • /*確定當前請求的處理者適配器*/

  • HandlerAdapterha=getHandlerAdapter(mappedHandler.getHandler());

  • //...............

  • /*請求調度前應用的攔截器*/

  • if(!mappedHandler.applyPreHandle(processedRequest,response)){

  • return;

  • }

  • /*調用處理程序*/

  • mv=ha.handle(processedRequest,response,mappedHandler.getHandler());

  • //......

  • /*請求調度後應用的攔截器*/

  • mappedHandler.applyPostHandle(processedRequest,response,mv);

  • }

  • catch(Exceptionex){

  • dispatchException=ex;

  • }

  • /*解析視圖給用戶響應*/

  • processDispatchResult(processedRequest,response,mappedHandler,mv,dispatchException);

  • }

  • 理解HandlerMapper,一個HandlerMapper代表一個請求到到處理對象的映射,該對象的創建依據是請求響應關系。getHandler方法部分源碼分析如下。

  • [java]view plain

  • (HttpServletRequestrequest)throwsException{

  • 遍歷查找滿足條件的HandlerMapping

  • for(HandlerMappinghm:this.handlerMappings){

  • if(logger.isTraceEnabled()){

  • logger.trace(

  • "Testinghandlermap["+hm+"]inDispatcherServletwithname'"+getServletName()+"'");

  • }

  • HandlerExecutionChainhandler=hm.getHandler(request);

  • if(handler!=null){

  • 存在

  • returnhandler;

  • }

  • }

  • 不存在

  • returnnull;

  • }

  • 理解HandlerAapter,SpringMVC 中通過HandlerAdapter的handler方法來調用實際的處理請求的函數。getHandlerAapter 部分源碼如下。

  • [java]view plain

  • (Objecthandler)throwsServletException{

  • for(HandlerAdapterha:this.handlerAdapters){

  • if(logger.isTraceEnabled()){

  • logger.trace("Testinghandleradapter["+ha+"]");

  • }

  • 是否支持處理當前的HandlerMapper

  • if(ha.supports(handler)){

  • returnha;

  • }

  • }

  • 當前的HandlerMapper不能被處理報異常

  • thrownewServletException("Noadapterforhandler["+handler+

  • "]:ortsthishandler");

  • }

  • Model到視圖,SpringMVC 中ModelAndView保存了邏輯視圖與真實視圖的關系,確定了當前請求為用戶返回的View,processDispatchResult 源碼分析如下。

  • [java]view plain

  • (HttpServletRequestrequest,HttpServletResponseresponse,

  • ,ModelAndViewmv,Exceptionexception)throwsException{

  • booleanerrorView=false;

  • /*處理異常信息*/

  • if(exception!=null){

  • if(){

  • logger.debug("",exception);

  • mv=((ModelAndViewDefiningException)exception).getModelAndView();

  • }

  • else{

  • Objecthandler=(mappedHandler!=null?mappedHandler.getHandler():null);

  • mv=processHandlerException(request,response,handler,exception);

  • errorView=(mv!=null);

  • }

  • }

  • /*渲染視圖,返回響應*/

  • if(mv!=null&&!mv.wasCleared()){

  • render(mv,request,response);

  • if(errorView){

  • WebUtils.clearErrorRequestAttributes(request);

  • }

  • }

  • else{

  • if(logger.isDebugEnabled()){

  • logger.debug("'"+getServletName()+

  • "':");

  • }

  • }

  • }

G. spring MVC怎麼理解

Spring MVC Framework大至流程如下:
當web程序啟動的時候,ContextLoaderServlet會把對應的配置文件信息讀取出來,通過注射去初始化控制器DispatchServlet. 而當接受到一個HTTP請求的時候, DispatchServlet會讓HandlerMapping去處理這個請求.HandlerMapping根據請求URL(不一定非要是URL,完全可以自定義,非常靈活)來選擇一個Controller. 然後DispatchServlet會在調用選定的Controller的handlerRequest方法,並且在這個方法前後調用這個Controller的interceptor(假如有配置的話),然後返回一個視圖和模型的集合ModelAndView.框架通過ViewResolver來解析視圖並且返回一個View對象,最後調用View的render方法返回到客戶端
DispatcherServlet
這是框架的控制器,是一個具體類,它通過運行時的上下文對象來初始化.控制器本身並不去控制流程,而只是是Controller的」控制器」,他只是把處理請求的責任委託給了對應的Controller.

控制器繼承自抽象基類FrameworkServlet,它的屬性webApplicationContext就代表著這個web程序上下文,而這個上下文對象默認實現就是從一個XML文件讀取配置信息(當然也可以是其他文件格式). WebApplicationContext其實是beans包的東西,這個包提供了這個Spring整個框架的基礎結構,以後我會分析這個包的內容.但是現在僅僅需要知道WebApplicationContext代表一個web應用的上下文對象.

現在來看看DispatchServlet是如何工作的:
DispatchServlet由於繼承自抽象基類FrameworkServlet,而FrameworkServlet里的doGet(),doPost()方法里有調用serviceWrapper(),跳到serviceWrapper()里去看,結果發現它有把具體實現委託給了doService(request, response); 方法.所以現在已經很清楚了, DispatchServlet真正實現功能的是doService() 這個方法.

特別的, FrameworkServlet的initFrameworkServlet()這個方法是控制器的初始化方法,用來初始化HandlerMappings之類的對象,這也是延遲到子類實現的.其實就是一個Template模式的實現.don』t call us, we will call u.總的看來,Spring就是通過這樣來實現它的控制反轉的:用框架來控制流程,而不是用戶

跳到doService()一看究竟,就會發現真正工作的又是另一個助手函數doDispatch(request, response),沒辦法,繼續看下去,發現這樣兩行代碼
HandlerExecutionChain mappedHandler = null;
mappedHandler = getHandler(processedRequest, false);
看HandlerExecutionChain源碼就發現它其實就是對Controller和它的Interceptors的進行了包裝;

getHandler()就是從HandlerMappings(這是一個List,存放的handlerMapping對象)中取出對應的handlerMapping對象, 每個HandlerMapping對象代表一個Controller和URL的映射(其實在運行的時候是一個HandlerExecutionChain和URL的映射,而HandlerExecutionChain對象其實就是對Controller和它interceptors的一個包裝器,可以把HandlerMapping看成Controller和URL的映射).而這個HandlerMapping是通過配置文件在運行時注射進來的,一般是SimpleUrlHandlerMapping這個子類

取得了HandlerMapping對象,繼續向下看,發現:
if (mappedHandler.getInterceptors() != null) {
for (int i = 0; i < mappedHandler.getInterceptors().length; i++) {
HandlerInterceptor interceptor = mappedHandler.getInterceptors()[i];
if (!interceptor.preHandle(processedRequest, response, mappedHandler.getHandler())) {
triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, null);
return;
}
interceptorIndex = i;
}
}
這里就是在調用Controller的攔截器,原理就是這句了:
interceptor.preHandle(processedRequest, response, mappedHandler.getHandler(), mv);
preHandle方法傳入了mappedHandler.getHandler()這個參數來實現遞歸調用!而interceptor.postHandle方法如此一般.只不過這個方法是在handleRequest方法後調用

繼續看下去:
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
發現Controller的handleRequest真正的操作又被代理給了HandlerAdapter的handle方法,並且返回一個ModelAndView,我想這里增加一層的意義應該是為了解除Controller和DispatchServlet的耦合吧.

接著就很簡單了,調用render()方法,在這個方法裡面由ViewResoler解析出視圖名,再調用視圖對象的render方法把合適的視圖展現給用戶

到此,控制器的流程就OVER了
HandlerMapping
通過使用HandlerMapping,控制器可以用URL和某一個Controller進行標準的映射,而實現URL映射的具體子類的UrlHandlerMapping.

Spring還允許我們自定義映射,比如通過Session,cookie或者用戶狀態來映射.而這一切僅僅只需要實現HandlerMapping介面而已.不過URL映射已經能滿足大部分的要求
Controller
Controller 類似Structs的Action, Controller介面只有一個方法handleRequest(),放回一個ModelAndView對象,如同設計目標所說的那樣,每個Controller都是一個java組件,所以它可以在上下文環境中任意配置,組件屬性都會在初始化的時候被配置.Spring自己提供了幾個具體的實現.方便我們使用
ViewResolver
Controller通常返回包含視圖名字而不是視圖對象的ModelAndView對象.從而徹底的解除了控制器和視圖之間的耦合關系,並且在這里還可以提供國際化的支持.
在你的配置文件中你可以:
welcomeView.class = org.springframework.web.servlet.view. InternalResourceView
welcomeView.url=/welcome.jsp
也可以
welcomeView.class = org.springframework.web.servlet.view.xslt. XsltView
welcomeView.url=/xslt/default.xslt

View
這也是一個java組件,它不做任何請求處理或是業務邏輯,它僅僅獲取模型傳遞的數據,並把數據顯示出來.它裡面的 render方法按照如下流程工作:
l 設置模型的數據到request作用域
l 取得視圖的URL
l 轉發到對應的URL

H. 如何學習springmvc源碼 csdn

善於利用時間:時間是有限的,知識是無限的,我們不可能在有限的時間里學會無限的知識,所以我們必須有選擇重點進行學習。所謂重點一個是薄弱的科目,二是各科的重點知識,利用有限時間針對性的進行學習能夠大大提高學習效率

I. 看透springmvc源代碼分析與實踐 怎麼樣

Tomcat 里的Server由org.apache.catalina.startup.Catalina來管理
,Catalina是整個Tomcat的管理類,它裡面的三個方法load,start,stop分別用來管理整個伺服器的生命周期,load方法用於根據conf/server.xml文件創建Server並調用
Server的init方法進行初始化,start
方法用於啟動伺服器,stop方法用於停止伺服器,start和stop方法在內部分別調用了Server的start
和stop方法,load方法內部調用了Server的init方法,這三個方法都
會按容器的結構逐層調用相應的方法,比如,Server的start方法中會調用
所有的Service中的start方法,Service中的start方法又會調用所包含的connectors和container的start方法,這樣整個伺服器就啟動了,init和stop方法也一樣,這就是tomcat生命周期的管理方式。

Catalina中還有個await方法很重要,此方法直接調用 了Server的await方法,這個方法的作用是進入一個循環,讓主線程不會退出。

Tomcat的入口org.apache.catalina.startup.Bootstrap.main(),
Bootstrap的作用類似一個CatalinaAdaptor,具體過程還是使用Catalina來完成,這么做的好處是可以把啟動的入口和具體的管理類分開,這樣可以就可以方便創建出多種啟動方式 ,每種啟動方式只需要寫一個相應的CatalinaAdaptor就可以了。

Bootstrap是Tomcat的入口,正常情況下啟動Tomcat就是調用的Bootstrap的main方法,其代碼如下:
// org.apache.catalina.startup.Bootstrap
public static void main(String args[]) {
// 先新建一個Bootstrap
if (daemon == null) {
Bootstrap bootstrap = new Bootstrap();
try {
//初始化了ClassLoader,並用ClassLoader創建了Catalina實例,賦給catalinaDaemon變數
bootstrap.init();
} catch (Throwable t) {

handleThrowable(t);
t.printStackTrace();
return;
}
daemon = bootstrap;
} else {
Thread.currentThread().setContextClassLoader(daemon.catalinaLoader);
}
try {
String command = "start";
if (args.length > 0) {
command = args[args.length - 1];
}
if (command.equals("startd")) {
args[args.length - 1] = "start";

daemon.load(args);
daemon.start();
} else if (command.equals("stopd")) {
args[args.length - 1] = "stop";
daemon.stop();
} else if (command.equals("start")) {
daemon.setAwait(true);
daemon.load(args);
daemon.start();
} else if (command.equals("stop")) {
daemon.stopServer(args);
} else if (command.equals("configtest")) {
daemon.load(args);

if (null==daemon.getServer()) {
System.exit(1);
}
System.exit(0);
} else {
log.warn("Bootstrap: command \"" + command + "\" does not exist.");
}
} catch (Throwable t) {
if (t instanceof InvocationTargetException &&
t.getCause() != null) {
t = t.getCause();
}
handleThrowable(t);
t.printStackTrace();

System.exit(1);
}
}
可以看到這里的main非常簡單,只有兩部分內容:首先新建了Bootstrap,並執行init方法初始化;然後處理main方法傳入的命令,如果args參數為空,默認執行start。
在init方法里初始化了ClassLoader,並用ClassLoader創建了Catalina實例,然後賦給catalinaDaemon變數,後面對命令的操作都要使用catalinaDaemon來具體執行。
對start命令的處理調用了三個方法:setAwait(true)、load(args)和start()。這三個方法內部都調用了Catalina的相應方法進行具體執行,只不過是用反射來調用的。start方法(另外兩個方法會處理一些參數,調用方法類似)的代碼如下:

// org.apache.catalina.startup.Bootstrap
public void start()
throws Exception {
if( catalinaDaemon==null ) init();

Method method = catalinaDaemon.getClass().getMethod("start", (Class [] )null);
method.invoke(catalinaDaemon, (Object [])null);
}
這里首先判斷catalinaDaemon有沒有初始化,如果沒有則調用init方法對其進行初始化,然後使用Method進行反射調用Catalina的start方法。Method是java.lang.reflect包里的

類,代表一個具體的方法,可以使用其中的invoke方法來執行所代表的方法,invoke方法有兩個參數,第一參數是Method方法所在的實體,第二個參數是可變參數用於Method方法執行時所需要的參數,所以上面的調用相當於((Catalina)catalinaDaemon).start()。setAwait和load也用類似的方法調用了Catalina中的setAwait和load方法。
7.1.3Catalina的啟動過程
從前面的內容可以知道,Catalina的啟動主要是調用setAwait、load和start方法來完成的。setAwait方法用於設置Server啟動完成後是否進入等待狀態的標志,如果為true則進入,否則不進入;load方法用於載入配置文件,創建並初始化Server;start方法用於啟動伺服器。下面分別來看一下這三個方法。

首先來看setAwait方法,代碼如下:
// org.apache.catalina.startup.Catalina
public void setAwait(boolean b) {
await = b;
}
這個方法非常簡單,就是設置await屬性的值,await屬性會在start方法中的伺服器啟動完之後使用它來判斷是否進入等待狀態。
Catalina的load方法根據conf/server.xml創建了Server對象,並賦值給server屬性(具體解析操作是通過開源項目Digester完成的),然後調用了server的init方法,代碼如下:
// org.apache.catalina.startup.Catalina
public void load() {

long t1 = System.nanoTime();
// 省略創建 server代碼,創建過程使用Digester完成
try {
getServer().init();
} catch (LifecycleException e) {
if (Boolean.getBoolean("org.apache.catalina.startup.EXIT_ON_INIT_FAILURE")) {
throw new java.lang.Error(e);
} else {
log.error("Catalina.start", e);
}
}

long t2 = System.nanoTime();
if(log.isInfoEnabled()) {

//啟動過程中,控制台可以看到
log.info("Initialization processed in " + ((t2 - t1) / 1000000) + " ms");
}
}
Catalina的start方法主要調用了server的start方法啟動伺服器,並根據await屬性判斷是否讓程序進入了等待狀態,代碼如下:
//org.apache.catalina.startup.Catalina
public void start() {
if (getServer() == null) {
load();
}
long t1 = System.nanoTime();
try {

// 調用Server的start方法啟動伺服器
getServer().start();
} catch (LifecycleException e) {
log.fatal(sm.getString("catalina.serverStartFail"), e);
try {
getServer().destroy();
} catch (LifecycleException e1) {
log.debug("destroy() failed for failed Server ", e1);
}
return;
}

long t2 = System.nanoTime();
if(log.isInfoEnabled()) {

log.info("Server startup in " + ((t2 - t1) / 1000000) + " ms");
}
// 此處省略了注冊關閉鉤子代碼
// 進入等待狀態
if (await) {
await();
stop();
}
}
這里首先判斷Server是否已經存在了,如果不存在則調用load方法來初始化Server,然後調用Server的start方法來啟動伺服器,最後注冊了關閉鉤子並根據await屬性判斷是否進入等待狀態,之前我們已將這里的await屬性設置為true了,所以需要進入等待狀態。進入等待狀態會調用await和stop兩個方法,await方法直接調用了Server的await方法,Server的await方法內部會執行一個while循環,這樣程序就停到了await方法,當await方法里的while循環退出時,就會執行stop方法,從而關閉伺服器。
7.1.4Server的啟動過程
Server介面中提供addService(Service service)、removeService(Service
service)來添加和刪除Service,Server的init方法和start方法分別循環調用了每個Service的init方法和start方法來啟動所有Service。
Server的默認實現是org.apache.catalina.core.StandardServer,StandardServer繼承自Lifecycle-MBeanBase,LifecycleMBeanBase又繼承自LifecycleBase,init和start方法就定義在了LifecycleBase中,LifecycleBase里的init方法和start方法又調用initInternal方法和startInternal方法,這兩個方法都是模板方法,由子類具體實現,所以調用StandardServer的init和start方法時會執行StandardServer自己的initInternal和startInternal方法,這就是Tomcat生命周期的管理方式,更詳細的過程見7.2節。StandardServer中的initInternal和startInternal方法分別循環調用了每一個service的start和init方法,代碼如下:
//org.apache.catalina.core.StandardServer
protected void startInternal() throws LifecycleException {
……
synchronized (servicesLock) {
for (int i = 0; i < services.length; i++) {
services[i].start();
}
}
}
protected void initInternal() throws LifecycleException {
……
for (int i = 0; i < services.length; i++) {
services[i].init();
}
}
除了startInternal和initInternal方法,StandardServer中還實現了await方法,Catalina中就是調用它讓伺服器進入等待狀態的,其核心代碼如下:

//org.apache.catalina.core.StandardServer
public void await() {
// 如果埠為-2則不進入循環,直接返回
if( port == -2 ) {

J. springmvc中的requestmapping註解怎麼實現的

使用@RequestMapping註解時,配置的信息最後都設置到了RequestMappingInfo中.

RequestMappingInfo封裝了PatternsRequestCondition,,ParamsRequestCondition等,所以自己不幹活,所有的活都是委託給具體的condition處理.

先看下封裝的RequestCondition吧,之前的文章將的比較細了,不清楚各個類具體是做什麼的,可以移步這里<SpringMVC源碼解讀 - RequestMapping註解實現解讀 - RequestCondition體系>

1 package org.springframework.web.servlet.mvc.method;
2 public final class RequestMappingInfo implements RequestCondition<RequestMappingInfo> {
3
4 private final PatternsRequestCondition patternsCondition;
5
6 private final methodsCondition;
7
8 private final ParamsRequestCondition paramsCondition;
9
10 private final HeadersRequestCondition headersCondition;
11
12 private final ConsumesRequestCondition consumesCondition;
13
14 private final ProcesRequestCondition procesCondition;
15
16 private final RequestConditionHolder customConditionHolder;
17 }

初始化沒什麼好看的,直接看介面的實現吧.

貌似combine也沒啥料,就是分別委託

1 /**
2 * Combines "this" request mapping info (i.e. the current instance) with another request mapping info instance.
3 * <p>Example: combine type- and method-level request mappings.
4 * @return a new request mapping info instance; never {@code null}
5 */
6 public RequestMappingInfo combine(RequestMappingInfo other) {
7 PatternsRequestCondition patterns = this.patternsCondition.combine(other.patternsCondition);
8 methods = this.methodsCondition.combine(other.methodsCondition);
9 ParamsRequestCondition params = this.paramsCondition.combine(other.paramsCondition);
10 HeadersRequestCondition headers = this.headersCondition.combine(other.headersCondition);
11 ConsumesRequestCondition consumes = this.consumesCondition.combine(other.consumesCondition);
12 ProcesRequestCondition proces = this.procesCondition.combine(other.procesCondition);
13 RequestConditionHolder custom = this.customConditionHolder.combine(other.customConditionHolder);
14
15 return new RequestMappingInfo(patterns, methods, params, headers, consumes, proces, custom.getCondition());
16 }

getMatchingCondition只是體現出可能基於性能消耗的考慮,把PatternsRequestCondition和RequestConditionHolder的比較放到後面單獨處理了.

1 /**
2 * Checks if all conditions in this request mapping info match the provided request and returns
3 * a potentially new request mapping info with conditions tailored to the current request.
4 * <p>For example the returned instance may contain the subset of URL patterns that match to
5 * the current request, sorted with best matching patterns on top.
6 * @return a new instance in case all conditions match; or {@code null} otherwise
7 */
8 public RequestMappingInfo getMatchingCondition(HttpServletRequest request) {
9 methods = methodsCondition.getMatchingCondition(request);
10 ParamsRequestCondition params = paramsCondition.getMatchingCondition(request);
11 HeadersRequestCondition headers = headersCondition.getMatchingCondition(request);
12 ConsumesRequestCondition consumes = consumesCondition.getMatchingCondition(request);
13 ProcesRequestCondition proces = procesCondition.getMatchingCondition(request);
14
15 if (methods == null || params == null || headers == null || consumes == null || proces == null) {
16 return null;
17 }
18
19 PatternsRequestCondition patterns = patternsCondition.getMatchingCondition(request);
20 if (patterns == null) {
21 return null;
22 }
23
24 RequestConditionHolder custom = customConditionHolder.getMatchingCondition(request);
25 if (custom == null) {
26 return null;
27 }
28
29 return new RequestMappingInfo(patterns, methods, params, headers, consumes, proces, custom.getCondition());
30 }

compareTo就是排了個不同RequestCondition的優先順序

1 /**
2 * Compares "this" info (i.e. the current instance) with another info in the context of a request.
3 * <p>Note: it is assumed both instances have been obtained via
4 * {@link #getMatchingCondition(HttpServletRequest)} to ensure they have conditions with
5 * content relevant to current request.
6 */
7 public int compareTo(RequestMappingInfo other, HttpServletRequest request) {
8 int result = patternsCondition.compareTo(other.getPatternsCondition(), request);
9 if (result != 0) {
10 return result;
11 }
12 result = paramsCondition.compareTo(other.getParamsCondition(), request);
13 if (result != 0) {
14 return result;
15 }
16 result = headersCondition.compareTo(other.getHeadersCondition(), request);
17 if (result != 0) {
18 return result;
19 }
20 result = consumesCondition.compareTo(other.getConsumesCondition(), request);
21 if (result != 0) {
22 return result;
23 }
24 result = procesCondition.compareTo(other.getProcesCondition(), request);
25 if (result != 0) {
26 return result;
27 }
28 result = methodsCondition.compareTo(other.getMethodsCondition(), request);
29 if (result != 0) {
30 return result;
31 }
32 result = customConditionHolder.compareTo(other.customConditionHolder, request);
33 if (result != 0) {
34 return result;
35 }
36 return 0;
37 }

熱點內容
iis上傳文件限制 發布:2024-11-19 16:37:55 瀏覽:406
面試題演算法 發布:2024-11-19 16:30:25 瀏覽:546
oracle存儲過程debug 發布:2024-11-19 16:30:25 瀏覽:233
linuxshjava 發布:2024-11-19 16:29:49 瀏覽:599
小程序saas平台源碼 發布:2024-11-19 16:27:16 瀏覽:838
汽車五門怎麼看配置 發布:2024-11-19 16:26:27 瀏覽:794
路由器密碼無線路由器怎麼設置 發布:2024-11-19 16:17:08 瀏覽:520
wifi直連android 發布:2024-11-19 15:59:58 瀏覽:939
android代碼設置顏色代碼 發布:2024-11-19 15:59:56 瀏覽:678
python3name 發布:2024-11-19 15:59:55 瀏覽:904