前言
Spring Boot 中的spring-boot-web-starter中默認(rèn)配置的Web容器就是Tomcat,而Tomcat是實(shí)現(xiàn)了Servlet規(guī)范的Web容器稚机,以前在項(xiàng)目中經(jīng)常用到轮傍,但是由于Spring Boot的約定先于配置大大隱藏了Tomcat的復(fù)雜性汽馋,還有Servlet的一些底層實(shí)現(xiàn)纺讲,導(dǎo)致在項(xiàng)目用到一些Servlet的東西卻不知道其接口之間的關(guān)系未檩。加上最近找實(shí)習(xí)也遇到面試官問(wèn)這些問(wèn)題蕾总,之前零散在網(wǎng)上看的不系統(tǒng)粥航,回答的時(shí)候有點(diǎn)懵,于是花了一天去較為系統(tǒng)的了解這個(gè)Java Web中的重要接口生百。
思維導(dǎo)圖
先看看我導(dǎo)圖递雀,然后再自底向上一一道來(lái),歸納得不全蚀浆,只有常見(jiàn)的接口缀程,接口的實(shí)現(xiàn)也沒(méi)有時(shí)間細(xì)看搜吧。
什么是Servlet?
Servlet(server applet)是JavaEE(位于javax.servlet)中的編程規(guī)范杨凑,用在瀏覽器與Java之間訪問(wèn)交互滤奈,只需要實(shí)現(xiàn)了Servlet就可以在任意符合其規(guī)范的Web容器應(yīng)用服務(wù)器(Tomcat JBoss Wildfly)中運(yùn)行你的后端代碼。從而實(shí)現(xiàn)了一次編寫到處部署(面向接口編程的好處)撩满!
Servlet有哪些常見(jiàn)的接口蜒程?
Servlet接口
留給程序員去實(shí)現(xiàn)的一個(gè)重要接口,編寫業(yè)務(wù)邏輯伺帘,SQL查詢之類的
- void init(ServletConfig config)
- servlet 初始化方法昭躺,在用戶訪問(wèn)時(shí)會(huì)實(shí)例化,該方法會(huì)被首次調(diào)用伪嫁,可用于資源連接领炫、打log
- void destory()
- 對(duì)象被銷毀時(shí)調(diào)用幽歼,放一些資源關(guān)閉的一些代碼
- void service(ServletRequest req,ServletResponse res)
- 最重要的一個(gè)方法皿淋,當(dāng)請(qǐng)求到來(lái)的時(shí)候會(huì)實(shí)例出Request Response并調(diào)用該方法,常常在這里實(shí)現(xiàn)業(yè)務(wù)邏輯了
ServletConfig接口
用于初始化Servlet對(duì)象時(shí)使用做修,已由Tomcat實(shí)現(xiàn)晶伦。
- 讀取web.xml中的配置信息init-param表示碟狞,可以用于配置數(shù)據(jù)庫(kù)連接等信息。
2 . 獲取ServletContext
ServletContext接口
一個(gè)完整的webapp的應(yīng)用上下文婚陪,已由Tomcat實(shí)現(xiàn)。
啟動(dòng)時(shí)創(chuàng)建频祝,服務(wù)關(guān)閉時(shí)被摧毀泌参。可存放context-param環(huán)境變量常空、運(yùn)行時(shí)全局共享的一些數(shù)據(jù)沽一。
HttpServlet抽象類
繼承自GenericServlet(implements Servlet)的抽象類,提供了一些通用的實(shí)現(xiàn):
- ServletConfig在init時(shí)保存為引用
- 在service實(shí)現(xiàn)HTTP請(qǐng)求方式的解析和分發(fā)調(diào)用算法
- doGet漓糙、doPost等方法默認(rèn)拋出405錯(cuò)誤(不支持的請(qǐng)求方式)
- 實(shí)現(xiàn)HTTP請(qǐng)求頭的緩存信息解析
- 強(qiáng)制把ServletRequest轉(zhuǎn)換成HttpServletRequest調(diào)用service方法
HttpServletRequest接口
繼承自ServletRequest铣缠,添加了HTTP協(xié)議的接口,在service方法中使用昆禽。添加了:
- url的參數(shù)獲然韧堋(表單、url)
- 獲取remoteIp
- 獲取轉(zhuǎn)發(fā)器(res.getRequestDispatcher("/b").forward(req,res))
- 重定向(res.sendRedirect)與轉(zhuǎn)發(fā)器的區(qū)別
- getCookie
- getSession
HttpServletResponse
繼承自ServletResponse醉鳖,同樣拓展了HTTP相關(guān)的東西捡硅,如:
- sendError發(fā)送HTTP狀態(tài)碼和信息
- getOutPutStream
- addCookie
HttpSession接口
可用HttpServletRequest.getSession()獲取當(dāng)前連接的會(huì)話。
- 獲取sessionId
- 獲取過(guò)期時(shí)間
- setAttribute盗棵、getAttribute壮韭、removeAttribute存放會(huì)話數(shù)據(jù)
Cookie接口
可用HttpServletRequest.getCookie()獲取當(dāng)前連接的cookie北发,res.addCookie發(fā)送給瀏覽器cookie
- setPath,以最后的斜杠匹配喷屋,默認(rèn)為當(dāng)前uri發(fā)送(/a/b/c匹配/a/b/)
- setMaxAge琳拨,過(guò)期時(shí)間(=0直接刪除,<0不存儲(chǔ)屯曹,>0x秒失效)
運(yùn)行時(shí)接口對(duì)應(yīng)關(guān)系
- 一個(gè)Servlet對(duì)象對(duì)應(yīng)一個(gè)Config狱庇,在web.xml定義的每個(gè)servlet的配置
- 一個(gè)webapp對(duì)應(yīng)ServletContext,所有servlet共享同一個(gè)是牢,在web.xml配置整個(gè)webapp的配置
- 一個(gè)請(qǐng)求對(duì)應(yīng)HttpServletRequest僵井,HttpServletResponse,每次請(qǐng)求創(chuàng)建不同的對(duì)象
- 一個(gè)會(huì)話對(duì)應(yīng)一個(gè)HttpSession驳棱,可包含用戶的多個(gè)請(qǐng)求
各接口的生命周期批什?
Servlet/HttpServlet
- 啟動(dòng)時(shí)默認(rèn)不會(huì)被實(shí)例化(除非配置load-up-startup)
- 用戶訪問(wèn)地址
- Web容器解析出對(duì)應(yīng)uri,在容器上下文尋找對(duì)應(yīng)的servlet
- 找到則調(diào)用其service方法
- 沒(méi)找到則通過(guò)web.xml文件的配置獲取完整類型社搅,通過(guò)反射實(shí)例化
- 實(shí)例化時(shí)會(huì)執(zhí)行無(wú)參構(gòu)造方法
- 傳入ServletConfig到init方法
- 最后調(diào)用service方法
- 銷毀:web容器關(guān)閉驻债、webapp重新部署、長(zhǎng)時(shí)間無(wú)訪問(wèn)時(shí)形葬,則調(diào)用destroy()做銷毀前的準(zhǔn)備
ServletContext
解析web.xml時(shí)創(chuàng)建合呐,服務(wù)啟動(dòng)時(shí)被創(chuàng)建,關(guān)閉時(shí)銷毀笙以。
HttpServletRequest HttpServletResponse
一次請(qǐng)求對(duì)應(yīng)一個(gè)對(duì)象淌实,完成請(qǐng)求則銷毀
我該選擇哪個(gè)Servlet類去實(shí)現(xiàn)?
HttpServlet猖腕。Servlet接口定義了基本方法拆祈,GenericServlet是實(shí)現(xiàn)了部分方法的抽象類,查看源碼可知:
- 實(shí)現(xiàn)init(ServletConfig config)倘感,保存了config的引用放坏,并設(shè)計(jì)一個(gè)空的init()供重寫
- 實(shí)現(xiàn)service(ServletRequest request,ServletResponse response),提供service(HttpServletRequest request, HttpServletResponse response)供重寫老玛,避免每次進(jìn)行轉(zhuǎn)型調(diào)用
HttpServlet是繼承GenericServlet的抽象方法淤年,提供了HTTP的更多實(shí)現(xiàn),包括
- 在service方法中解析HTTP請(qǐng)求方式蜡豹,分發(fā)GET到doGet麸粮,分發(fā)POST到doPost。
- 提供doXX的默認(rèn)實(shí)現(xiàn)余素,發(fā)送405/400的錯(cuò)誤豹休,表示不支持的請(qǐng)求方式。子類需要重寫這些方法去支持(巧妙=暗酢)
- doGet方法調(diào)用前威根,進(jìn)行了緩存檢查凤巨,當(dāng)未過(guò)期時(shí)返回304 not modify 表示資源未更改
Servlet GenericServlet HttpServlet 體現(xiàn)了什么設(shè)計(jì)模式?有什么好處洛搀?
模板方法敢茁。HttpServlet是一個(gè)模板類,實(shí)現(xiàn)了核心算法骨架留美,doGet doPost 具體實(shí)現(xiàn)步驟要在子類中完成彰檬。
特點(diǎn):doXX,doYY
作用:
- 核心算法保護(hù)
- 核心算法復(fù)用
- 不改變算法前提下重新定義算法步驟的具體實(shí)現(xiàn)