Jsp&Servlet工作原理詳解(基于Tomcat容器)


Tomcat概述

1. Tomcat的總體架構(gòu)

Tomcat啟動(dòng)server服務(wù)器對(duì)外提供Service服務(wù)蝗拿,Container作為Service的核心組件(Container可以連接多個(gè)Connector構(gòu)成Service)御铃,有了Service就可以對(duì)外提供服務(wù)。
2. Tomcat容器模型

從上述知歧焦,Service對(duì)外提供Web應(yīng)用服務(wù)移斩,而Service核心組件Container的靈魂便是Servlet容器。而真正管理Servlet的是Context容器绢馍。Context容器直接管理Servlet在容器中的包裝類Wrapper向瓷,一個(gè)Web應(yīng)用對(duì)應(yīng)一個(gè)Context容器。添加一個(gè)Web應(yīng)用就會(huì)創(chuàng)建一個(gè)Context容器舰涌,并將這個(gè)Context容器加入到父容器Host中猖任。

JSP概述

1. JSP基本概念

JSP全稱是Java ServerPages,它和servle技術(shù)一樣瓷耙,都是SUN公司定義的一種用于開發(fā)動(dòng)態(tài)web資源的技術(shù)朱躺。JSP這門技術(shù)的最大的特點(diǎn)在于,寫jsp就像在寫html搁痛,但它相比html而言长搀,html只能為用戶提供靜態(tài)數(shù)據(jù),而Jsp技術(shù)允許在頁(yè)面中嵌套java代碼鸡典,為用戶提供動(dòng)態(tài)數(shù)據(jù)源请。

2. 常見JSP語(yǔ)法

? 對(duì)于代碼腳本,格式為<% java代碼片段 %>;
? 對(duì)于變量聲明彻况,格式為<%! int i=0; %>;
? 對(duì)于表達(dá)式谁尸,格式為<%= 表達(dá)式 %>;
? 對(duì)于注釋,格式為<%-- JSP注釋 --%>/;
? 對(duì)于指令纽甘,格式為<%@page ...%>,<%@taglib ...%>,<%@include ...%>
? 對(duì)于動(dòng)作良蛮,格式為<jsp:include></jsp:include>,<jsp:useBean></jsp:useBean>,<jsp:setProperty/>,<jsp:getProperty/>,<jsp:forward></jsp:forward>,<jsp:attribute></jsp:attribute>,<jsp:plugin></jsp:plugin>
? 對(duì)于對(duì)象,腳本中內(nèi)置了九大對(duì)象:request,response,out,session,config,application,Exception,pageContext,page
重點(diǎn)介紹幾個(gè)對(duì)象:
? Exception對(duì)象:當(dāng)jsp頁(yè)面運(yùn)行時(shí)發(fā)生了異常贷腕,容器會(huì)將異常信息封裝到該對(duì)象背镇,可以使用該對(duì)象提供的方法來(lái)輸出異常的信息。另外泽裳,必須在頁(yè)面設(shè)置isErrorPage="true"指令才能使用該隱含對(duì)象瞒斩。
? pageContext對(duì)象:容器會(huì)為每一個(gè)JSP實(shí)例(JSP所對(duì)應(yīng)的那個(gè)Servlet對(duì)象)創(chuàng)建唯一的一個(gè)符合pageContext接口的對(duì)象,稱之為page上下文涮总。該對(duì)象會(huì)一直存在胸囱,除非JSP實(shí)例被銷毀。它作用:①綁定數(shù)據(jù)(綁定的數(shù)據(jù)只有對(duì)應(yīng)的JSP實(shí)例才可以訪問(wèn)):setAttribute瀑梗、removeAttribute烹笔、getAttribute裳扯。②找到其他八個(gè)隱含對(duì)象(詳情看JSP標(biāo)簽)。
? config對(duì)象:即ServletConfig谤职,可以使用該對(duì)象獲得初始化參數(shù)饰豺。
? page對(duì)象:JSP實(shí)例本身(一般不用)。

3. JSP工作原理

客戶端瀏覽器向服務(wù)器端發(fā)出request請(qǐng)求允蜈,服務(wù)端接受請(qǐng)求之后會(huì)先檢查此JSP文件是否存在:
■ 若不存在冤吨,則直接報(bào)錯(cuò);
■ 若存在饶套,則接著檢查所請(qǐng)求的這個(gè)JSP文件內(nèi)容(代碼)是否已經(jīng)被更新漩蟆,或者是否是JSP文件創(chuàng)建后的第一次被訪問(wèn);
□ 如果是妓蛮,那么這個(gè)JSP文件將會(huì)在服務(wù)器端的JSP引擎下轉(zhuǎn)換成一個(gè)Servlet的java源文件怠李;接著這個(gè)Servlet類會(huì)在java編譯器的作用下被編譯成字節(jié)碼文件,并裝載到JVM中去執(zhí)行蛤克。
□ 如果不是捺癞,則直接由服務(wù)器端檢索出它對(duì)應(yīng)的Servlet實(shí)例來(lái)處理。
注意:JSP 文件不是在服務(wù)器啟動(dòng)的時(shí)候轉(zhuǎn)換成 Servlet 類的构挤。而是在被客戶端訪問(wèn)的時(shí)候才可能發(fā)生轉(zhuǎn)換的 ( 如 JSP 文件內(nèi)容沒(méi)有被更新等翘簇,就不再發(fā)生 Servlet 轉(zhuǎn)換 )。

4. JSP編譯器詳解

Ⅰ儿倒、語(yǔ)法樹的生成
JasPer對(duì)JSP語(yǔ)法解析之后也會(huì)生成一棵樹,這棵樹中的各個(gè)節(jié)點(diǎn)保存了不同的信息呜笑,但對(duì)于JSP語(yǔ)法樹來(lái)說(shuō)比較簡(jiǎn)單夫否,因?yàn)樗挥幸粋€(gè)父節(jié)點(diǎn)和N個(gè)子節(jié)點(diǎn)。
比如說(shuō)圖中node1節(jié)點(diǎn)中保存的數(shù)據(jù)就可能是類似于<%-- JSP注釋 --%>這一類的注釋節(jié)點(diǎn)叫胁;而node2結(jié)點(diǎn)就可能保存的是形如<%= 表達(dá)式 %>的表達(dá)式節(jié)點(diǎn)凰慈;其余的節(jié)點(diǎn)就存儲(chǔ)JSP中其他的語(yǔ)法,有了這棵樹就可以很方便我們構(gòu)建出與之對(duì)應(yīng)的Servlet驼鹅。

Ⅱ微谓、語(yǔ)法樹的遍歷
對(duì)于語(yǔ)法樹,最典型的處理模式就是訪問(wèn)者模式输钩。它能很好的將將數(shù)據(jù)結(jié)構(gòu)與處理相分離豺型,提供很好的解耦作用。
經(jīng)過(guò)語(yǔ)法解析及使用訪問(wèn)者模式將HelloWorld.jsp文件編譯成相對(duì)應(yīng)的HelloWorld_jsp.java文件买乃,可以看到姻氨,Servlet類名由JSP文件名加_jsp拼成,類包名默認(rèn)為org.apache.jsp剪验。
JSP生成的JAVA類都必須繼承org.apache.jasper.runtime.HttpJspBase肴焊。這個(gè)類的結(jié)構(gòu)圖如上所示前联,它繼承HttpServlet是為了將HttpServlet中所有的功能都繼承下來(lái)。另外娶眷,又實(shí)現(xiàn)HttpJSPPage接口似嗤,定義了一個(gè)JSP類的Servlet的核心處理方法_JspService。除此之外届宠,還有_JspInit和_JspDestroy方法烁落,它們分別用于JSP的初始化和銷毀。這些方法都由Servlet的service席揽、init顽馋、destroy方法間接調(diào)用,多以JSP生成Servlet主要就是實(shí)現(xiàn)這幾個(gè)方法幌羞。通過(guò)JSP編譯器編譯后寸谜,生成了對(duì)應(yīng)的JAVA文件,接下來(lái)就需要將JAVA文件編譯成Class文件属桦,可以直接使用Eclipse JDT編譯器對(duì)其進(jìn)行編譯即可熊痴。

注意:JSP判斷重新編譯的條件的是什么?(重新編譯指的是將JSP文件編譯成JAVA再編譯成Class)
答:當(dāng)我們修改了某個(gè)JSP文件后或者某JSP文件引入的資源別修改后聂宾。所以最好的判斷的標(biāo)準(zhǔn)就是某JSP或資源的最后修改時(shí)間——LastModified屬性果善。


Servlet

1. Servlet基本概念
⑴、 Servlet是JavaWeb的三大組件之一系谐,它屬于動(dòng)態(tài)資源巾陕。Servlet的作用是處理請(qǐng)求,服務(wù)器會(huì)把接收到的請(qǐng)求交給Servlet來(lái)處理纪他,在Servlet中通常需要:1. 接收請(qǐng)求數(shù)據(jù) 2. 處理請(qǐng)求 3. 完成響應(yīng)
⑵鄙煤、實(shí)現(xiàn)Servlet的方式(由我們自己來(lái)編寫)
實(shí)現(xiàn)Servlet有三種方式:
實(shí)現(xiàn)javax.servlet.Servlet接口;
繼承javax.servlet.GenericServlet類茶袒;
繼承javax.servlet.http.HttpServlet類梯刚;

2. Servlet的生命周期
① Servlet維基百科解釋
? 當(dāng)servlet被部署在應(yīng)用服務(wù)器中(應(yīng)用服務(wù)器中用于管理Java組件的部分被抽象成為容器)以后,由容器控制servlet的生命周期薪寓。
? 除非特殊制定亡资,否則在容器啟動(dòng)的時(shí)候,servlet是不會(huì)被加載的向叉,servlet只會(huì)在第一次請(qǐng)求的時(shí)候被加載和實(shí)例化锥腻。
? servlet一旦被加載,一般不會(huì)從容器中刪除植康,直至應(yīng)用服務(wù)器關(guān)閉或重新啟動(dòng)旷太。但當(dāng)容器做內(nèi)存回收動(dòng)作時(shí),servlet有可能被刪除。也正是因?yàn)檫@個(gè)原因供璧,第一次訪問(wèn)servlet所用的時(shí)間要大大多于以后訪問(wèn)所用的時(shí)間存崖。

3. Servlet的實(shí)例化過(guò)程
(1)加載和實(shí)例化
如果Servlet容器還沒(méi)實(shí)例化一個(gè)Servlet對(duì)象,此時(shí)容器裝載和實(shí)例化一個(gè) Servlet睡毒。創(chuàng)建出該 Servlet 類的一個(gè)實(shí)例来惧。如果已經(jīng)存在一個(gè)Servlet對(duì)象,此時(shí)不再創(chuàng)建新實(shí)例演顾。
(2)初始化
在Servlet被創(chuàng)建后供搀,服務(wù)器會(huì)馬上調(diào)用Servlet的void init(ServletConfig)方法。請(qǐng)記住钠至,Servlet出生后馬上就會(huì)調(diào)用init()方法葛虐,而且一個(gè)Servlet的一生。這個(gè)方法只會(huì)被調(diào)用一次棉钧。
(3)處理請(qǐng)求
當(dāng)服務(wù)器每次接收到請(qǐng)求時(shí)屿脐,都會(huì)去調(diào)用Servlet的service()方法來(lái)處理請(qǐng)求。服務(wù)器接收到一次請(qǐng)求宪卿,就會(huì)調(diào)用service() 方法一次的诵,所以service()方法是會(huì)被調(diào)用多次的。
(4)銷毀
通常都是在服務(wù)器關(guān)閉時(shí)Servlet才會(huì)離去佑钾!在服務(wù)器被關(guān)閉時(shí)西疤,服務(wù)器會(huì)去銷毀Servlet,在銷毀Servlet之前服務(wù)器會(huì)先去調(diào)用Servlet的destroy()方法休溶,所以我們可以將一些資源釋放的代碼放入其中代赁。
其中,(1)(2)(4) 在 Servlet 的整個(gè)生命周期中只會(huì)被執(zhí)行一次兽掰。

4. Servlet工作原理


當(dāng)客戶端瀏覽器向服務(wù)器請(qǐng)求一個(gè)Servlet時(shí)管跺,服務(wù)器收到該請(qǐng)求后,首先到容器中檢索與請(qǐng)求匹配的Servlet實(shí)例是否已經(jīng)存在禾进。
1、若不存在廉涕,則Servlet容器負(fù)責(zé)加載并實(shí)例化出該類Servlet的一個(gè)實(shí)例對(duì)象泻云,接著容器框架負(fù)責(zé)調(diào)用該實(shí)例的init()方法來(lái)對(duì)實(shí)例做一些初始化工作,然后Servlet容器運(yùn)行該實(shí)例的service()方法狐蜕。
2宠纯、若存在,則容器框架直接調(diào)用該實(shí)例的service()方法层释。
在處理請(qǐng)求時(shí):
1. Servlet容器會(huì)創(chuàng)建一個(gè)請(qǐng)求對(duì)象ServletRequst婆瓜,其中封裝了用戶請(qǐng)求的信息,以便處理客戶端請(qǐng)求,此外還會(huì)創(chuàng)建一個(gè)響應(yīng)對(duì)象ServletResponse廉白,用于響應(yīng)客戶端請(qǐng)求个初,想客戶端返回?cái)?shù)據(jù)。
2. 然后Servlet容器把創(chuàng)建好的ServletRequst和ServletResponse對(duì)象傳給用戶所請(qǐng)求的Servlet猴蹂。
3. Servlet利用ServletResponse包含的數(shù)據(jù)和自身的業(yè)務(wù)邏輯處理請(qǐng)求院溺,并把處理好的結(jié)果寫在ServletResponse中,最后Servlet容器把響應(yīng)結(jié)果傳給用戶磅轻。

5. Servlet接口相關(guān)類型
ServletRequest:service() 方法的參數(shù)珍逸,它表示請(qǐng)求對(duì)象,它封裝了所有與請(qǐng)求相關(guān)的數(shù)據(jù)聋溜,它是由服務(wù)器創(chuàng)建的谆膳;
ServletResponse:service()方法的參數(shù),它表示響應(yīng)對(duì)象撮躁,在service()方法中完成對(duì)客戶端的響應(yīng)需要使用這個(gè)對(duì)象漱病;
ServletConfig:init()方法的參數(shù),它表示Servlet配置對(duì)象馒胆,它對(duì)應(yīng)Servlet的配置信息缨称,那對(duì)應(yīng)web.xml文件中的元素。
ServletContext:Servlet的運(yùn)行模式是一個(gè)典型的“握手型的交互式”運(yùn)行模式祝迂。所謂“握手型的交互式”就是兩個(gè)模塊為了交換數(shù)據(jù)通常都會(huì)準(zhǔn)備一個(gè)交易場(chǎng)景睦尽,這個(gè)場(chǎng)景一直跟隨這個(gè)交易過(guò)程直到這次交易過(guò)程完成為止。這個(gè)場(chǎng)景的初始化是根據(jù)這次交易對(duì)象指定的參數(shù)來(lái)定制的型雳。即交易場(chǎng)景就由ServletContext來(lái)描述当凡,而定制的參數(shù)集合就由ServletConfig來(lái)描述,而ServletRequest和ServletResponse就是要交互的具體對(duì)象纠俭,它們通常都作為運(yùn)輸工具來(lái)傳遞交互結(jié)果沿量。


參考文章:

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市冤荆,隨后出現(xiàn)的幾起案子朴则,更是在濱河造成了極大的恐慌,老刑警劉巖钓简,帶你破解...
    沈念sama閱讀 217,542評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件乌妒,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡外邓,警方通過(guò)查閱死者的電腦和手機(jī)撤蚊,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)损话,“玉大人侦啸,你說(shuō)我怎么就攤上這事槽唾。” “怎么了光涂?”我有些...
    開封第一講書人閱讀 163,912評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵庞萍,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我顶捷,道長(zhǎng)挂绰,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,449評(píng)論 1 293
  • 正文 為了忘掉前任服赎,我火速辦了婚禮葵蒂,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘重虑。我一直安慰自己践付,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,500評(píng)論 6 392
  • 文/花漫 我一把揭開白布缺厉。 她就那樣靜靜地躺著永高,像睡著了一般。 火紅的嫁衣襯著肌膚如雪提针。 梳的紋絲不亂的頭發(fā)上命爬,一...
    開封第一講書人閱讀 51,370評(píng)論 1 302
  • 那天,我揣著相機(jī)與錄音辐脖,去河邊找鬼饲宛。 笑死,一個(gè)胖子當(dāng)著我的面吹牛嗜价,可吹牛的內(nèi)容都是我干的艇抠。 我是一名探鬼主播,決...
    沈念sama閱讀 40,193評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼久锥,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼家淤!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起瑟由,我...
    開封第一講書人閱讀 39,074評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤絮重,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后歹苦,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體绿鸣,經(jīng)...
    沈念sama閱讀 45,505評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,722評(píng)論 3 335
  • 正文 我和宋清朗相戀三年暂氯,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片亮蛔。...
    茶點(diǎn)故事閱讀 39,841評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡痴施,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情辣吃,我是刑警寧澤动遭,帶...
    沈念sama閱讀 35,569評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站神得,受9級(jí)特大地震影響厘惦,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜哩簿,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,168評(píng)論 3 328
  • 文/蒙蒙 一宵蕉、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧节榜,春花似錦羡玛、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,783評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至讳窟,卻和暖如春让歼,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背丽啡。 一陣腳步聲響...
    開封第一講書人閱讀 32,918評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工谋右, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人碌上。 一個(gè)月前我還...
    沈念sama閱讀 47,962評(píng)論 2 370
  • 正文 我出身青樓倚评,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親馏予。 傳聞我的和親對(duì)象是個(gè)殘疾皇子天梧,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,781評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容