Servlet是什么恬砂?
Servlet是JavaEE規(guī)范的一種,主要是為了擴(kuò)展Java作為Web服務(wù)的功能蓬痒,統(tǒng)一接口觉既。由其他內(nèi)部廠商如tomcat,jetty內(nèi)部實(shí)現(xiàn)web的功能乳幸。如一個(gè)http請(qǐng)求到來:
容器將請(qǐng)求封裝為servlet中的HttpServletRequest對(duì)象瞪讼,調(diào)用init(),service()等方法輸出response,由容器包裝為httpresponse返回給客戶端的過程粹断。
在Servlet規(guī)范中符欠,提供了ServletContext,ServletRequest,ServletResponse,Filter等諸多接口。
基本類圖和調(diào)用關(guān)系如下:
下面簡(jiǎn)要介紹下接口的作用瓶埋,生命周期和使用:
Servlet
:作用:用于處理請(qǐng)求(service方法)
生命周期:加載實(shí)例化希柿、初始化、處理客戶端請(qǐng)求养筒、銷毀曾撤。
加載實(shí)例化主要是交由web容器完成,而其他三個(gè)階段則對(duì)應(yīng)Servlet的init晕粪、service和destroy方法挤悉。Servlet對(duì)象被創(chuàng)建出來后需要對(duì)其進(jìn)行初始化操作,初始化工作可以放在以ServletConfig類型為參數(shù)的ini方法中巫湘,ServletConfig為web.xml配置文件中配置的對(duì)應(yīng)的初始化參數(shù)装悲,由web容器完成web.xml配置讀取并封裝成ServletConfig對(duì)象;當(dāng)Servlet初始化完成后尚氛,開始接受客戶端的請(qǐng)求诀诊,這些請(qǐng)求被封裝成ServletRequest類型的請(qǐng)求對(duì)象和ServletResponse類型的響應(yīng)對(duì)象,通過service方法處理請(qǐng)求并響應(yīng)客戶端阅嘶;當(dāng)一個(gè)Servlet需要從web容器中移除時(shí)属瓣,就會(huì)調(diào)用對(duì)應(yīng)的destroy方法用于釋放所有的資源,并且調(diào)用destroy方法之前要保證所有正在執(zhí)行service方法的線程都完成執(zhí)行讯柔。
使用:servlet規(guī)范中定義了
GenericServlet
接口抡蛙,定義了通用,協(xié)議獨(dú)立的servlet,他們的子接口HttpServlet
就是用來處理http請(qǐng)求的Servlet,根據(jù)http協(xié)議擴(kuò)展了不同方式的請(qǐng)求處理方法磷杏,如doPost,doGet.
ServletContext
:Servlet與Servlet容器之間直接通信的接口,一個(gè)web應(yīng)用只獨(dú)有一個(gè)ServletContext.
作用:
- 用于在web應(yīng)用范圍內(nèi)存取共享數(shù)據(jù),如setAttribute(String name, Object object)溜畅,getAttribute()
- 獲取當(dāng)前Web應(yīng)用的資源,如getContextPath()
- 獲取服務(wù)器端的文件系統(tǒng)資源极祸,如getResourceAsStream()
- 輸出日志慈格,如log(String msg) : 向Servlet的日志文件中寫日志
- 在具體ServletContext 實(shí)現(xiàn)中,提供了添加Servlet遥金,F(xiàn)ilter,Listener到ServletContext里面的方法
生命周期:和web應(yīng)用的生命周期一樣
使用:一般由web容器實(shí)現(xiàn)浴捆,如tomcat
Filter
:
作用:用于Web容器對(duì)請(qǐng)求和響應(yīng)做統(tǒng)一處理,例如統(tǒng)一改變HTTP請(qǐng)求內(nèi)容和響應(yīng)內(nèi)容稿械,它可以作用在某個(gè)Servlet或一組Servlet
生命周期:加載實(shí)例化选泻、初始化(init)、處理客戶端請(qǐng)求(doFilter)、銷毀(destroy)
使用:在doFilter方法中調(diào)用chain.doFilter(request, response)
之前的代碼可用來做一些請(qǐng)求校驗(yàn)页眯,之后代碼可用來做一些響應(yīng)包裝梯捕。
ServletRequest
:封裝了客戶端請(qǐng)求的所有信息,如果使用HTTP協(xié)議通信則包括HTTP協(xié)議的請(qǐng)求行和請(qǐng)求頭窝撵。HTTP協(xié)議對(duì)應(yīng)請(qǐng)求對(duì)象類型是HttpServletRequest類
作用:
- 獲取HTTP協(xié)議請(qǐng)求頭部傀顾,如getHeader、getHeaders
- 獲取請(qǐng)求路徑碌奉,如getContextPath短曾、getServletPath
- 獲取cookie的方法,如getCookies
- 獲取session的方法赐劣,如getSession,session是存儲(chǔ)在服務(wù)器內(nèi)存中嫉拐,返回響應(yīng)的時(shí)候會(huì)寫入瀏覽器一個(gè)sessionId的cookie,用來標(biāo)示這一個(gè)會(huì)話
生命周期:只在servlet的service方法或過濾器的doFilter方法作用域內(nèi)有效魁兼,除非啟用了異步處理調(diào)用了ServletRequest接口對(duì)象的startAsync方法婉徘,此時(shí)request對(duì)象會(huì)一直有效,直到調(diào)用AsyncContext的complete方法璃赡。另外判哥,web容器通常會(huì)為了性能而不銷毀ServletRequest接口的對(duì)象,而是重復(fù)利用ServletRequest接口對(duì)象碉考。
ServletResponse
:Servlet通過ServletResponse對(duì)象來生成響應(yīng)結(jié)果塌计。
作用:定義了一系列與生成響應(yīng)結(jié)果相關(guān)的方法,如:
- setCharacterEncoding() —— 設(shè)置相應(yīng)正文的字符編碼侯谁。響應(yīng)正文的默認(rèn)字符編碼為ISO-8859-1锌仅;
- setContentLength() —— 設(shè)置響應(yīng)正文的長(zhǎng)度;
- setBufferSize() —— 設(shè)置用于存放響應(yīng)正文數(shù)據(jù)的緩沖區(qū)的大小
- getBufferSize() —— 獲得用于存放響應(yīng)正文數(shù)據(jù)的緩沖區(qū)的大星郊热芹;
- reset() —— 清空緩沖區(qū)內(nèi)的正文數(shù)據(jù),并且清空響應(yīng)狀態(tài)代碼及響應(yīng)頭
- resetBuffer() —— 僅僅清空緩沖區(qū)的正文數(shù)據(jù)惨撇,不清空響應(yīng)狀態(tài)代碼及響應(yīng)頭伊脓;
- flushBuffer() —— 強(qiáng)制性地把緩沖區(qū)內(nèi)的響應(yīng)正文數(shù)據(jù)發(fā)送到客戶端;
- isCommitted() —— 返回一個(gè)boolean類型的值魁衙,如果為true报腔,表示緩沖區(qū)內(nèi)的數(shù)據(jù)已經(jīng)提交給客戶,即數(shù)據(jù)已經(jīng)發(fā)送到客戶端剖淀;
- getOutputStream() —— 返回一個(gè)ServletOutputStream對(duì)象纯蛾,Servlet用它來輸出二進(jìn)制的正文數(shù)據(jù);
- getWriter() —— 返回一個(gè)PrinterWriter對(duì)象纵隔,Servlet用它來輸出字符串形式的正文數(shù)據(jù)翻诉;
為了提高輸出數(shù)據(jù)的效率炮姨,ServletOutputStream和PrintWriter首先把數(shù)據(jù)寫到緩沖區(qū)內(nèi)。當(dāng)緩沖區(qū)內(nèi)的數(shù)據(jù)被提交給客戶后碰煌,ServletResponse的isComitted方法返回true舒岸。
生命周期:ServletResponse接口只在Servlet的service方法或過濾器的doFilter方法作用域內(nèi)有效,除非它關(guān)聯(lián)的ServletResponse接口調(diào)用了startAsync方法啟用異步處理拄查,此時(shí)ServletResponse接口會(huì)一直有效吁津,直到調(diào)用AsyncContext的complete方法。另外堕扶,web容器通常會(huì)為了性能而不銷毀ServletResponse接口對(duì)象,而是重復(fù)利用ServletResponse接口對(duì)象梭依。
Listener
:當(dāng)觸發(fā)某個(gè)事件稍算,如servlet context初始化完成時(shí),需要做一些事情役拴,servlet規(guī)范中定義了若干個(gè)Listener用于監(jiān)聽這些事件糊探。
作用:用于對(duì)特定對(duì)象的生命周期和特定事件進(jìn)行響應(yīng)處理,主要用于對(duì)Session,request,context等進(jìn)行監(jiān)控河闰。
監(jiān)聽域?qū)ο笞陨淼膭?chuàng)建和銷毀的事件監(jiān)聽器
- ServletContextListener:ServletContext的創(chuàng)建和銷毀:contextInitialized方法和contextDestroyed方法科平,作為定時(shí)器、加載全局屬性對(duì)象姜性、創(chuàng)建全局?jǐn)?shù)據(jù)庫(kù)連接瞪慧、加載緩存信息等
- HttpSessionListener:HttpSession的創(chuàng)建和銷毀:sessionCreated和sessionDestroyed方法,可用于統(tǒng)計(jì)在線人數(shù)部念、記錄訪問日志等
- ServletRequestListener: ServletRequest的創(chuàng)建和銷毀:requestInitialized和requestDestroyed方法
監(jiān)聽域?qū)ο笾械膶傩缘脑黾雍蛣h除的事件監(jiān)聽器
- ServletContextAttributeListener弃酌、HttpSessionAttributeListener、ServletRequestAttributeListener接口儡炼。
- 實(shí)現(xiàn)方法:attributeAdded妓湘、attributeRemoved、attributeReplaced
監(jiān)聽綁定到HttpSeesion域中的某個(gè)對(duì)象的狀態(tài)的事件監(jiān)聽器(創(chuàng)建普通JavaBean)
- HttpSession中的對(duì)象狀態(tài):綁定→解除綁定乌询;鈍化→活化
- 實(shí)現(xiàn)接口及方法:HttpSessionBindingListener接口(valueBound和valueUnbound方法)榜贴、HttpSessionActivationListener接口(sessionWillPassivate和sessionDidActivate方法)
tomcat是什么?
tomcat等容器其實(shí)就是web服務(wù)的實(shí)現(xiàn)妹田,暴露端口唬党,按照特定資源URL找到處理的servlet。然后處理請(qǐng)求秆麸。
web.xml其實(shí)tomcat在啟動(dòng)時(shí)候需要加載的配置歡迎頁初嘹、Filter、Listener沮趣、Servlet等類的定義屯烦。當(dāng)然不止加載這些東西,這些東西是需要加載到JVM堆內(nèi)存中實(shí)例化的對(duì)象。
Tomcat啟動(dòng)時(shí)加載資源主要有三個(gè)階段:
- 第一階段:JVM相關(guān)資源
(1)$JAVA_HOME/jre/lib/ext/*.jar
(2)系統(tǒng)classpath環(huán)境變量中的*.jar和*.class
- 第二階段:Tomcat自身相關(guān)資源
(1)$CATALINA_HOME/common/classes/*.class
(2)$CATALINA_HOME/commons/endorsed/*.jar
(3)$CATALINA_HOME/commons/i18n/*.jar
(4)$CATALINA_HOME/common/lib/*.jar
(5)$CATALINA_HOME/server/classes/*.class
(6)$CATALINA_HOME/server/lib/*.jar
(7)$CATALINA_BASE/shared/classes/*.class
(8)$CATALINA_BASE/shared/lib/*.jar
- 第三階段:Web應(yīng)用相關(guān)資源
(1)具體應(yīng)用的webapp目錄: /WEB-INF/classes/*.class
(2)具體應(yīng)用的webapp: /WEB-INF/lib/*.jar
在tomcat目錄${CATALINA_HOME}/conf
下和web應(yīng)用目錄${CATALINA_HOME}/webapps/WebDemo
(WebDemo為web應(yīng)用名)下都有web.xml這個(gè)文件驻龟,但是內(nèi)容不一樣温眉。
Tomcat在激活、加載翁狐、部署web應(yīng)用時(shí)类溢,會(huì)解析加載${CATALINA_HOME}/conf目錄下所有web應(yīng)用通用的web.xml,然后解析加載web應(yīng)用目錄中的WEB-INF/web.xml露懒。
其實(shí)根據(jù)他們的位置闯冷,我們就可以知道,conf/web.xml文件中的設(shè)定會(huì)應(yīng)用于所有的web應(yīng)用程序懈词,而某些web應(yīng)用程序的WEB-INF/web.xml中的設(shè)定只應(yīng)用于該應(yīng)用程序本身蛇耀。
如果沒有WEB-INF/web.xml文件,tomcat會(huì)輸出找不到的消息坎弯,但仍然會(huì)部署并使用web應(yīng)用程序纺涤,servlet規(guī)范的作者想要實(shí)現(xiàn)一種能迅速并簡(jiǎn)易設(shè)定新范圍的方法,以用作測(cè)試抠忘,因此撩炊,這個(gè)web.xml并不是必要的,不過通常最好還是讓每一個(gè)上線的web應(yīng)用程序都有一個(gè)自己的WEB-INF/web.xml崎脉。
web.xml中可以配置web應(yīng)用名稱拧咳,圖標(biāo),描述荧嵌,ServletContext上下文參數(shù)呛踊,F(xiàn)liter配置,Listener配置啦撮,Servlet配置谭网,會(huì)話超時(shí)配置,MIME類型配置等等赃春。
Spring MVC 是什么愉择?
Spring MVC (SpringBoot)其實(shí)就是基于tomcat等這些web容器對(duì)我們的CS請(qǐng)求能做更多的事情,如校驗(yàn)织中,攔截(AOP思想)锥涕,后期渲染等等,好讓我們專注于業(yè)務(wù)的開發(fā)狭吼。
Springmvc的核心是一個(gè)DispatcherServlet层坠,負(fù)責(zé)請(qǐng)求的解析,攔截刁笙,轉(zhuǎn)發(fā)破花,響應(yīng)等等谦趣。相關(guān)類圖和請(qǐng)求處理流程為:
其中FrameworkServlet會(huì)和Spring的ApplicationContext聯(lián)系起來,它實(shí)現(xiàn)了ApplicationContextAware接口座每。
當(dāng)然Spring MVC框架也提供rest訪問前鹅,從而可實(shí)現(xiàn)前后端的分離。
import org.springframework.web.bind.annotation.RestController;
@RestController
public class RestfulWebServiceController {
@GetMapping("/message")
public MyOutputResource getMessage() {
return new MyOutputResource("Hello!");
}
}
感謝您的閱讀峭梳,我是Monica23334 || Monica2333 舰绘。立下每周寫一篇原創(chuàng)文章flag的小姐姐,關(guān)注我并期待打臉吧~
參考資料:
Java Servlet 3.1 規(guī)范
servlet的本質(zhì)是什么葱椭,它是如何工作的捂寿?
Servlet規(guī)范總結(jié)
【Java.Web】Servlet —— Servlet的類的體系結(jié)構(gòu)
Servlet 工作原理解析
Cookie 與 Session 的區(qū)別
Session原理和Tomcat實(shí)現(xiàn)分析
An Introduction to Tomcat Servlet Interactions
關(guān)于web.xml配置的那些事兒
How Spring Web MVC Really Works