Java web 入門——2.淺談servletContext姨谷、webApplicationContext與DispatcherServlet

Context我們通常解釋為上下文環(huán)境,我想用“容器”來表述它更容易理解一些映九。


context.png

1.ServletContext

ServletContext梦湘,即Servlet容器。首先件甥,對于一個web應用捌议,其部署在web容器中,web容器提供其一個全局的上下文環(huán)境引有,這個上下文就是ServletContext瓣颅,其包含從容器環(huán)境中獲得的初始化信息,提供對應用程序中所有Servlet共有的各種資源功能的訪問譬正,為后面的spring IoC容器提供宿主環(huán)境宫补。在啟動一個web應用時,ServletContext會為它創(chuàng)建一個ServletContext對象曾我,每個web應用有唯一的ServletContext對象粉怕。

(1)多個Servlet通過ServletContext對象訪問上文屬性

ServletConfig對象中維護了ServletContext對象的引用,開發(fā)人員在編寫servlet時抒巢,可以通過ServletConfig.getServletContext方法獲得ServletContext對象贫贝。

servlet可以通過名稱將對象屬性綁定到上下文,可以被同一個web應用的其他servlet使用蛉谜。

setAttribute
getAttribute
getAttributeNames
removeAttribute

示例:

// 獲取ServletContext對象
ServletContext context = this.getServletContext();    
context.setAttribute("appName", "webApp"); 

在其它的Servlet中利用ServletContext對象獲取

ServletContext context = this.getServletContext();   
String name = context.getAttribute("appName");   
(2)獲取WEB應用的初始化參數(shù)

getInitParameter
getInitParameterNames

在web.xml文件中配置需要初始化的參數(shù)信息

<web-app>   
 <context-param>   
   <param-name>url</param-name>   
    <param-value>http://localhost:3306/web</param-value>   
 </context-param>   
</web-app>  

獲取初始化參數(shù)

 ServletContext context = this.getServletContext();   
//獲取指定名稱的初始化參數(shù)   
String url = context.getInitParameter("url"); 
 //獲取web.xml文件中所有的初始化應用參數(shù)          
 Enumeration<String> enumer = context.getInitParameterNames();   
(3)實現(xiàn)Servlet的轉發(fā)
ServletContext context = this.getServletContext();   
 //根據(jù)轉發(fā)的地址獲取 RequestDispatcher對象
RequestDispatcher  rd  = context.getRequestDispatcher("/index.jsp");   
//調(diào)用轉發(fā)方法 以下采用任意方法即可    
rd.forward(request, response);   
  //rd.include(request, response);   

注意:forward與include的區(qū)別 :
forward方法調(diào)用后在響應中的沒有提交的內(nèi)容被自動消除稚晚,原先Servlet的執(zhí)行則終止。將請求轉發(fā)給其他的Servlet后型诚,由被調(diào)用的Servlet負責對請求做出響應客燕。
include方法使原先的Servlet和轉發(fā)到的Servlet都可以輸出響應信息,即原先的Servlet還可以繼續(xù)輸出響應

(4)用ServletContext對象讀取資源文件

getResource
getResourceAsStream
getResource和getResourceAsStream

讀取資源文件的三種方式狰贯,獲取實現(xiàn)的代碼如下:

ServletContext context = this.getServletContext();     

//第一種方式    
URL url = context.getResource("WEB-INF/classes/db.properties");   
InputStream is =  url.openStream();   

//第二種方式   
 // 讀取db.properties文件
String path =context.getRealPath("WEB-INF/classes/db.properties");   
 // 根據(jù)文件的路徑 構建文件對象
File file = new File(path);   
 // 根據(jù)file文件對象 創(chuàng)建輸入流
InputStream is = new FileInputStream(file);   

//第三種方式   
InputStream is = context.getResourceAsStream("WEB-INF/classes/db.properties ");    

Web服務器可能支持一個服務器上多個邏輯主機共享一個IP地址也搓。這功能有時被稱為“虛擬主機”。這種情況下暮现,每一個邏輯主機必須有它自己的servlet上下文还绘。Servlet上下文不可以被多個虛擬主機共享


2.WebApplicationContext

在web應用中栖袋,會使用到WebApplicationContext,它繼承自ApplicationContext抚太,但是與之不同的是WebApplicationContext需要ServletContext塘幅,也就是說它必須擁有Web容器的前提下才能完成啟動的工作昔案。它允許從相對于web根目錄的路徑中加載配置文件完成初始化工作。
在web.xml中會提供有contextLoaderListener电媳。在web容器啟動時踏揣,會觸發(fā)容器初始化事件。此時contextLoaderListener 會監(jiān)聽到這個事件匾乓,其調(diào)用contextInitialized方法捞稿,在這個方法中,spring會初始化一個啟動上下文拼缝,這個上下文被稱為根上下文娱局,即WebApplicationContext,這是一個接口類咧七,其實際的實現(xiàn)類是XmlWebApplicationContext衰齐。這個就是spring的IoC容器,其對應的Bean定義的配置由web.xml中的context-param標簽指定继阻。在這個IoC容器初始化完畢后耻涛,spring以WebApplicationContext.ROOTWEBAPPLICATIONCONTEXTATTRIBUTE為屬性Key,將其存儲到ServletContext中.

(1)在web.xml初始化WebApplicationContext:
<context-param>      
<param-name>contextConfigLocation</param-name>      
<param-value>/WEB-INF/applicationContext.xml</param-value>      
</context-param>      
     
<listener>      
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>      
</listener>  
<!--or -->
<servlet>      
<servlet-name>context</servlet-name>      
<servlet-class>org.springframework.web.context.ContextLoaderServlet</servlet-class>      
<load-on-startup>1</load-on-startup>      
</servlet> 

有兩種方法:
一種是用ContextLoaderListener這個Listerner瘟檩,另一種是ContextLoaderServlet這個Servlet抹缕,這兩個方法都是在web應用啟動的時候來初始化WebApplicationContext,我個人認為Listerner要比 Servlet更好一些墨辛,因為比起Listerner監(jiān)聽應用的啟動和結束歉嗓,而Servlet得啟動要稍微延遲一些,如果在這時要做一些業(yè)務的操作背蟆,啟動的前后順序是有影響的鉴分。

那么在ContextLoaderListener和ContextLoaderServlet中到底做了什么呢?
以ContextLoaderListener為例带膀,我們可以看到:

public void contextInitialized(ServletContextEvent event) {
this.contextLoader = createContextLoader();
this.contextLoader.initWebApplicationContext(event.getServletContext());
}
protected ContextLoader createContextLoader() {
return new ContextLoader();
}

ContextLoader 是一個工具類志珍,用來初始化WebApplicationContext,其主要方法就是initWebApplicationContext垛叨,我們繼續(xù)追蹤initWebApplicationContext這個方法(Spring中的源碼)伦糯,ContextLoader是把WebApplicationContext ( XmlWebApplicationContext是默認實現(xiàn)類)放在了 ServletContext中,ServletContext也是一個“容器”嗽元,也是一個類似Map的結構敛纲,而 WebApplicationContext在ServletContext中的KEY就是WebApplicationContext.ROOT_WEB_APPLICA TION CONTEXT ATTRIBUTE丰辣,我們?nèi)绻褂?WebApplicationContext 則需要從ServletContext取出傅物,Spring提供了一個 WebApplicationContextUtils類,可以方便的取出WebApplicationContext迅诬,只要把 ServletContext傳入就可以了佩谷。

(2)從ServletContext中獲取WebApplicationContext
WebApplicationContext  ctx=
WebApplicationContextUtils.getWebApplicationContext(request.getSession().getServletContext());

3.DispatcherServlet

contextLoaderListener監(jiān)聽器初始化完畢后旁壮,開始初始化web.xml中配置的Servlet监嗜,這個servlet可以配置多個,以最常見的DispatcherServlet為例抡谐,這個servlet實際上是一個標準的前端控制器裁奇,用以轉發(fā)、匹配麦撵、處理每個servlet請求刽肠。DispatcherServlet上下文在初始化的時候會建立自己的IoC上下文,用以持有spring mvc相關的bean免胃。在建立DispatcherServlet自己的IoC上下文時音五,會利用WebApplicationContext.ROOTWEBAPPLICATIONCONTEXTATTRIBUTE先從ServletContext中獲取之前的根上下文(即WebApplicationContext)作為自己上下文的parent上下文。有了這個parent上下文之后杜秸,再初始化自己持有的上下文放仗。這個DispatcherServlet初始化自己上下文的工作在其initStrategies方法中可以看到,大概的工作就是初始化處理器映射撬碟、視圖解析等诞挨。這個servlet自己持有的上下文默認實現(xiàn)類也是xmlWebApplicationContext。初始化完畢后呢蛤,spring以與servlet的名字相關的屬性為屬性Key(此處不是簡單的以servlet名為Key惶傻,而是通過一些轉換,具體可自行查看源碼)其障,也將其存到ServletContext中银室,以便后續(xù)使用。這樣每個servlet就持有自己的上下文励翼,即擁有自己獨立的bean空間蜈敢,同時各個servlet共享相同的bean,即根上下文定義的那些bean汽抚。

WebapplicationServlet為Spring的根上下文或父上下文抓狭,而DispatcherServlet則為子上下文。它的主要用作職責調(diào)度工作造烁,本身主要用于控制流程否过,主要職責如下:

(1)文件上傳解析,如果請求類型是multipart將通過MultipartResolver進行文件上傳解析惭蟋;
(2)通過HandlerMapping苗桂,將請求映射到處理器(返回一個HandlerExecutionChain,它包括一個處理器告组、多個HandlerInterceptor攔截器)煤伟;
(3)通過HandlerAdapter支持多種類型的處理器(HandlerExecutionChain中的處理器);
(4)通過ViewResolver解析邏輯視圖名到具體視圖實現(xiàn);
(5)本地化解析持偏;
(6)渲染具體的視圖等驼卖;
(7)如果執(zhí)行過程中遇到異常將交給HandlerExceptionResolver來解析氨肌。

DispatcherServlet初始化的上下文加載的Bean是只對SpringMVC有效的Bean鸿秆, 如Controller、HandlerMapping怎囚、HandlerAdapter等等卿叽,該初始化上下文只加載Web相關組件。初始化完畢后恳守,spring以與servlet的名字相關(此處不是簡單的以servlet名為Key考婴,而是通過一些轉換,具體可自行查看源碼)的屬性為屬性Key催烘,也將其存到ServletContext中沥阱,以便后續(xù)使用。這樣每個servlet就持有自己的上下文伊群,即擁有自己獨立的bean空間考杉,同時各個servlet共享相同的bean,即根上下文定義的那些bean舰始。讓我們來看一個具體的DispatcherServlet的配置事例:

<servlet>
    <servlet-name>qsServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:conf/qs-servlet.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
     </servlet>

<servlet-mapping>
    <servlet-name>qsServlet</servlet-name>
    <url-pattern>*.do</url-pattern>
 </servlet-mapping>

param-value指定了web組件的配置文件
load-on-startup表示啟動容器時初始化該Servlet
url-pattern表示哪些請求交給Spring Web MVC處理崇棠, “/” 是用來定義默認servlet映射的。示例中用“*.do”表示攔截所有以do為擴展名的請求丸卷。

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末枕稀,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子谜嫉,更是在濱河造成了極大的恐慌萎坷,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,214評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件沐兰,死亡現(xiàn)場離奇詭異哆档,居然都是意外死亡,警方通過查閱死者的電腦和手機僧鲁,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評論 2 382
  • 文/潘曉璐 我一進店門虐呻,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人寞秃,你說我怎么就攤上這事斟叼。” “怎么了春寿?”我有些...
    開封第一講書人閱讀 152,543評論 0 341
  • 文/不壞的土叔 我叫張陵朗涩,是天一觀的道長。 經(jīng)常有香客問我绑改,道長谢床,這世上最難降的妖魔是什么兄一? 我笑而不...
    開封第一講書人閱讀 55,221評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮识腿,結果婚禮上出革,老公的妹妹穿的比我還像新娘。我一直安慰自己渡讼,他們只是感情好骂束,可當我...
    茶點故事閱讀 64,224評論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著成箫,像睡著了一般展箱。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上蹬昌,一...
    開封第一講書人閱讀 49,007評論 1 284
  • 那天混驰,我揣著相機與錄音,去河邊找鬼皂贩。 笑死栖榨,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的先紫。 我是一名探鬼主播治泥,決...
    沈念sama閱讀 38,313評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼遮精!你這毒婦竟也來了居夹?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 36,956評論 0 259
  • 序言:老撾萬榮一對情侶失蹤本冲,失蹤者是張志新(化名)和其女友劉穎准脂,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體檬洞,經(jīng)...
    沈念sama閱讀 43,441評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡狸膏,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,925評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了添怔。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片湾戳。...
    茶點故事閱讀 38,018評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖广料,靈堂內(nèi)的尸體忽然破棺而出砾脑,到底是詐尸還是另有隱情,我是刑警寧澤艾杏,帶...
    沈念sama閱讀 33,685評論 4 322
  • 正文 年R本政府宣布韧衣,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏畅铭。R本人自食惡果不足惜氏淑,卻給世界環(huán)境...
    茶點故事閱讀 39,234評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望硕噩。 院中可真熱鬧假残,春花似錦、人聲如沸榴徐。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽坑资。三九已至,卻和暖如春穆端,著一層夾襖步出監(jiān)牢的瞬間袱贮,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評論 1 261
  • 我被黑心中介騙來泰國打工体啰, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留攒巍,地道東北人。 一個月前我還...
    沈念sama閱讀 45,467評論 2 352
  • 正文 我出身青樓荒勇,卻偏偏與公主長得像柒莉,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子沽翔,可洞房花燭夜當晚...
    茶點故事閱讀 42,762評論 2 345