Servlet是和平臺(tái)無(wú)關(guān)的服務(wù)器端組件戏罢,運(yùn)行在Servlet容器中班利。Servlet容器負(fù)責(zé)Servlet和客戶的通信以及調(diào)用Servlet的方法,Servlet和客戶的通信采用“請(qǐng)求/響應(yīng)”的模式眯娱。
Servlet可完成的功能:
- 創(chuàng)建并返回基于客戶請(qǐng)求的動(dòng)態(tài)HTML頁(yè)面
- 創(chuàng)建可嵌入到現(xiàn)有HTML頁(yè)面中的部分HTML頁(yè)面
- 與其他服務(wù)器資源進(jìn)行通信
Tomcat就是Servlet容器
- 可以用來(lái)創(chuàng)建Servlet铣墨,并調(diào)用Servlet的相關(guān)生命周期方法
Servlet生命周期方法:
- 構(gòu)造器方法:第一次請(qǐng)求Servlet時(shí),創(chuàng)建Servlet的實(shí)例嗽上,調(diào)用構(gòu)造器(只被調(diào)用一次)
- init方法:只被調(diào)用一次次舌,創(chuàng)建好實(shí)例后立即被調(diào)用,用于初始化當(dāng)前Servlet
- service方法:被多次調(diào)用兽愤,每次請(qǐng)求都會(huì)調(diào)用service方法彼念,實(shí)際用于響應(yīng)請(qǐng)求的
- destroy方法:只被嗲用一次挪圾,在當(dāng)前Servlet所在的web應(yīng)用被卸載前調(diào)用,用于釋放當(dāng)前Servlet所占用的資源
<load-on-startup>1</load-on-startup>
這個(gè)標(biāo)簽參數(shù)可以指定Servlet被創(chuàng)建的時(shí)機(jī)
- 配置在Servlet節(jié)點(diǎn)中
- 若為負(fù)數(shù)逐沙,則在第一次請(qǐng)求時(shí)被創(chuàng)建哲思,若為0或正數(shù),則在當(dāng)前web應(yīng)用被Servlet容器加載時(shí)創(chuàng)建實(shí)例吩案,且數(shù)越小越早被創(chuàng)建
ServletConfig:保存了Servlet的各項(xiàng)配置也殖,并且可以獲取ServletContex對(duì)象
ServletContext:
- 可以由ServletConfig獲取
- 代表當(dāng)前web應(yīng)用,可以認(rèn)為ServletCOntext是當(dāng)前web應(yīng)用的一個(gè)大管家
- 獲取當(dāng)前web應(yīng)用的某一個(gè)文件的絕對(duì)路徑,文件在服務(wù)器上的路徑务热,而不是部署前的路徑
getRealPath() - 獲取當(dāng)前web應(yīng)用名稱
getContextPath() - 獲取當(dāng)前web應(yīng)用的某一個(gè)文件對(duì)應(yīng)的輸入流
getResourceAsStream(String path):path的/為當(dāng)前應(yīng)用的根目錄
HTTP的會(huì)話方式:
- 建立連接
- 發(fā)出請(qǐng)求信息
- 回送響應(yīng)信息
- 斷開連接
Get請(qǐng)求和Post請(qǐng)求
- 在瀏覽器地址欄輸入某個(gè)URL地址或單繼網(wǎng)頁(yè)上的一個(gè)超鏈接時(shí)佛舱,瀏覽器發(fā)出的HTTP請(qǐng)求為GET
- 如果網(wǎng)頁(yè)中的form表單元素的method屬性被設(shè)置為GET脊僚,瀏覽器提交這個(gè)form表單時(shí)生成的HTTP請(qǐng)求為GET
- 使用GET方式傳送的數(shù)據(jù)量一般限制在1kb以下
Post方式傳遞參數(shù)
- post請(qǐng)求方式主要用于向web服務(wù)器端程序提交form表單中的數(shù)據(jù),form表單的mehtod設(shè)置為post
- post方式將各個(gè)表單字段元素及其數(shù)據(jù)作為http消息的實(shí)體內(nèi)容發(fā)送給web服務(wù)器,傳送的數(shù)據(jù)量要比使用get方式傳送的數(shù)據(jù)量大得多
響應(yīng)狀態(tài)碼含義: - 200:請(qǐng)求成功
- 302:請(qǐng)求重定向
- 304:請(qǐng)求資源沒有改變瑞你,訪問(wèn)本地緩存
- 404:請(qǐng)求資源不存在遍膜,通常是用戶路徑編寫錯(cuò)誤捷雕,也可能是服務(wù)器資源已經(jīng)刪除
- 500:服務(wù)器內(nèi)部錯(cuò)誤叁鉴,通常程序拋異常
Java反射機(jī)制
- 在運(yùn)行狀態(tài)中,對(duì)于任意一個(gè)類江醇,都能夠知道這個(gè)類的所有屬性和方法濒憋。
- 對(duì)于任意一個(gè)對(duì)象,都能夠調(diào)用他的任意一個(gè)方法和屬性
- 想要使用反射陶夜,必須獲取字節(jié)碼文件
獲取字節(jié)碼文件的方式
- Object類的getClass方法
- 靜態(tài)屬性 class
- class類中靜態(tài)方法forName
反射中獲取私有屬性
- getDeclaredField()
- setAccessable(true)
反射中獲取私有方法
- getDeclaredMethod()
- setAccessable(true)
Servlet中的init()方法和destroy()方法
- init()方法:在Servlet創(chuàng)建的時(shí)候調(diào)用凛驮,也可以通過(guò)配置在服務(wù)器一啟動(dòng)就開始調(diào)用。具體方法是:在web.xml中配置選項(xiàng)条辟,<load-on-startup>標(biāo)簽可以設(shè)置優(yōu)先級(jí)黔夭,填寫數(shù)字代表優(yōu)先級(jí)
- service方法():每一次請(qǐng)求的的時(shí)候進(jìn)行調(diào)用,每次發(fā)送請(qǐng)求都會(huì)調(diào)用service方法()羽嫡;
- destroy()方法:當(dāng)servlet被銷毀的時(shí)候調(diào)用本姥,當(dāng)服務(wù)器關(guān)閉的時(shí)候調(diào)用
Servlet訪問(wèn)流程
init()方法參數(shù)介紹
public void init(ServletConfig servletConfig) throws ServletException {
}
servletConfig 可以獲取一些配置信息
1.可以獲取Servlet名稱 web.xml
2.獲取web.xml中的初始化參數(shù)
3.獲取ServletContext
url-patten匹配形式
- 完全匹配
就是在web.xml中的url-patten必須跟要在地址欄寫的完全一致才可以
目錄匹配
類似于導(dǎo)包時(shí)候的 .*,只要在前面寫好目錄,不管具體的文件是什么杭棵,最終都能訪問(wèn)到目錄下的servlet
- 擴(kuò)展名匹配
// *.myxq
只要擴(kuò)展名是.myxq結(jié)尾的都可以被訪問(wèn)到
url-patten缺省值與靜態(tài)資源的訪問(wèn)流程
- 如果都沒有匹配到url-patten,就會(huì)找缺省婚惫,缺省的名稱就是<servletname>對(duì)應(yīng)的Servlet。<url-pattern>/</url-pattern>
靜態(tài)資源加載過(guò)程
- 在path后面寫的靜態(tài)資源名稱index.html或者其他的.html他都是會(huì)找url-pattern當(dāng)中有沒有匹配的內(nèi)容
- 如果有魂爪,就加載對(duì)應(yīng)的servlet先舷,如果沒有就自己到配置當(dāng)中找缺省的url-pattern
- 如果自己配置文件當(dāng)中沒有缺省的,就會(huì)找全局配置缺省的url-pattern
- 在全局配置當(dāng)中有一個(gè)缺省的url-pattern甫窟, 對(duì)應(yīng)的default的Servlet
- defaultServlet內(nèi)部會(huì)到當(dāng)前訪問(wèn)的工程根目錄當(dāng)中去找對(duì)應(yīng)的名稱的靜態(tài)資源密浑,如果有,就把里面的內(nèi)容逐行輸出粗井,響應(yīng)給瀏覽器
- 如果沒有,就會(huì)報(bào)404錯(cuò)誤
使用注解創(chuàng)建Servlet
@WebServlet("/myServlet)
- 這個(gè)相當(dāng)于一個(gè)注解
- 相當(dāng)于在代碼上添加了一個(gè)小插件
- 貼上這個(gè)注解以后,就不用再去做配置文件浇衬,系統(tǒng)自動(dòng)做
- 括號(hào)當(dāng)中的內(nèi)容就是url-pattern的內(nèi)容懒构,要在地址欄當(dāng)中path后面跟的內(nèi)容
doGet()方法
- 當(dāng)get請(qǐng)求時(shí)會(huì)調(diào)用該方法
doPost()方法
- 當(dāng)post請(qǐng)求時(shí)會(huì)調(diào)用該方法
當(dāng)一個(gè)Servlet類繼承自HttpServlet時(shí),如果復(fù)寫了父類的Service方法耘擂,那么不管是通過(guò)post方式提交請(qǐng)求還是get方式提交請(qǐng)求胆剧,都會(huì)直接調(diào)用Service方法。即醉冤,一旦寫了Service方法秩霍,就不會(huì)調(diào)用doPost和doGet方法。
ServletContext對(duì)象
- 代表web應(yīng)用的上下文對(duì)象蚁阳,一個(gè)web應(yīng)用只有一個(gè)ServletContext對(duì)象
- 里面封裝的都是web應(yīng)用信息
- 一個(gè)ServletContext對(duì)應(yīng)一個(gè)應(yīng)用
生命周期 - 服務(wù)器啟動(dòng)就會(huì)被創(chuàng)建
- 服務(wù)器關(guān)閉銷毀
如何獲得上下文
- 通過(guò)init()方法當(dāng)中一個(gè)參數(shù)ServletConfig來(lái)獲取
@Override
public void init(ServletConfig config) throws ServletException {
ServletContext servletContext=config.getServletContext();
System.out.println(servletContext);
}
ServletContext 獲取文件路徑
ServletContext context=this.getServletContext();
String realPath =context.getRealPath("WEB-INF/b.txt");
System.out.println(realpath);
//使用類加載器铃绒,獲取字節(jié)碼的路徑
//到字節(jié)碼目錄中加載資源
String path=OneServlet.class.getClassLoader().getResource("");
System.out.println(path);
ServletContext是一個(gè)域?qū)ο螅侵改軌虼鎯?chǔ)數(shù)據(jù)
- 作用范圍:整個(gè)web應(yīng)用螺捐,所有的web資源都i可以進(jìn)行存取數(shù)據(jù)颠悬,數(shù)據(jù)是可以共享的
如何王ServletContext里面寫數(shù)據(jù): - contex.setAttribute(String name,Object object)
取數(shù)據(jù)
- context.getAttribute(String name)
刪除指定值
- context.removeAttribute(String name)
只要是一個(gè)域?qū)ο螅锩娑加羞@幾個(gè)方法
Response對(duì)象
學(xué)習(xí)response主要就是學(xué)習(xí)通過(guò)response設(shè)置響應(yīng)行定血,響應(yīng)頭赔癌,響應(yīng)體
response響應(yīng)過(guò)程:
- 發(fā)送一個(gè)請(qǐng)求時(shí),會(huì)找到tomcat引擎
- 引擎會(huì)找到相應(yīng)的web應(yīng)用澜沟,并且會(huì)創(chuàng)建request對(duì)象和response對(duì)象
- 找到應(yīng)用后灾票,會(huì)執(zhí)行應(yīng)用的web.xml再去根據(jù)url-pattern的內(nèi)容創(chuàng)建Servlet對(duì)象
- 并且會(huì)調(diào)用Servlet對(duì)象的service方法,并且把創(chuàng)建的request對(duì)象和response對(duì)象傳入到方法當(dāng)中
- 拿到response對(duì)象后茫虽,可以往響應(yīng)當(dāng)中寫入一些自己給客戶端的內(nèi)容
- 寫的內(nèi)容是存到一個(gè)response緩沖區(qū)當(dāng)中
- 當(dāng)方法執(zhí)行結(jié)束之后铝条,tomcat就會(huì)從response緩沖區(qū)當(dāng)中取出數(shù)據(jù)
設(shè)置響應(yīng)行
- response.setState(int code) 設(shè)置狀態(tài)碼
設(shè)置響應(yīng)頭
-
主要有add和set兩個(gè)方法
image.png
response重定向
- 訪問(wèn)兩次服務(wù)器,第一次是人為的去訪問(wèn)席噩,第二次是自動(dòng)訪問(wèn)
- 瀏覽器地址兩次發(fā)生了變化
設(shè)置重定向
response.setHeader("location","另一個(gè)servlet");
另一種重定向方法
response.sendRedirect("另一個(gè)servlet");
定時(shí)刷新也是一種重定向
response.setHeader("refresh","另一個(gè)servlet")
設(shè)置響應(yīng)體
- 通過(guò)write方法
response.getWrite().write(要寫的內(nèi)容)
默認(rèn)情況下寫的中文內(nèi)容會(huì)亂碼班缰,因?yàn)閷懙膬?nèi)容在存到緩沖區(qū)中使用的是ISO8859編碼,不支持中文悼枢。
如何解決中文亂碼問(wèn)題
在存之前設(shè)置存放的編碼埠忘,response.setCharacterEncoding
告知瀏覽器使用的是utf-8編碼
緩沖區(qū)及瀏覽器都有自己的編碼格式,當(dāng)更改了緩沖區(qū)編碼方式仍然出現(xiàn)中文亂碼時(shí)馒索,應(yīng)該更改瀏覽器的編碼方式莹妒。
//設(shè)置緩沖區(qū)的編碼格式
resp.setCharacterEncoding("utf-8");
//在響應(yīng)中主動(dòng)告訴瀏覽器通過(guò)什么樣的編碼格式接受
resp.setHeader("Content-Type","text/html;charset=UTF-8");
上述兩行代碼可以通過(guò)如下一行代碼替換
response.setContentType("text/html;charset=UTF-8");
設(shè)置編碼格式要在設(shè)置內(nèi)容之前完成,
- 通過(guò)outputstream方法可以完成讀取圖片等媒體資源
主要就是文件讀取操作绰上,需要注意的一點(diǎn)就是對(duì)文件的訪問(wèn)操作旨怠,通過(guò)文件名訪問(wèn)文件時(shí),文件的路徑在idea中需要注意蜈块,通過(guò)idea做動(dòng)態(tài)網(wǎng)站鉴腻,文件位置并非放置在tomcat瀏覽器中迷扇,而是在下圖中的左側(cè)out文件夾下,也就是說(shuō)爽哎,通過(guò)getRealPath獲取到的路徑是E:\project\javaproject\ThirdWeb\out\artifacts\ThirdWeb_war_exploded
所以通過(guò)getRealPath獲取路徑之后蜓席,想直接訪問(wèn)靜態(tài)資源,可以把資源直接放在_war_exploded根目錄下面
getWrite()和outputstream不能同時(shí)存在课锌。
下載文件
通過(guò)a標(biāo)簽
直接使用a標(biāo)簽可以下載文件厨内,但是下載的文件只能是壓縮文件等,圖片和mp4等類型的文件是不能夠下載下來(lái)的渺贤,當(dāng)點(diǎn)擊下載這些文件時(shí)雏胃,瀏覽器會(huì)去解析這些文件。通過(guò)發(fā)送請(qǐng)求的方式下載文件
該方式不能識(shí)別出所有的文件類型志鞍,因此需要設(shè)置文件類型瞭亮。
設(shè)置下載文件類型
- 設(shè)置mimeType
- 告訴瀏覽器以附件的形式打開
@WebServlet("/DownloadServlet2")
public class DownloadServlet2 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String name=req.getParameter("filename");
String path = this.getServletContext().getRealPath(name);
System.out.println(path);
String mimeType = this.getServletContext().getMimeType(name);
//設(shè)置mimetype
resp.setContentType(mimeType);
//告訴瀏覽器以附件的形式打開
resp.setHeader("Content-Disposition","attachment;filename="+name);
//根據(jù)path加載文件
FileInputStream in = new FileInputStream(path);
ServletOutputStream servletOutputStream = resp.getOutputStream();
byte[] buffer = new byte[1024];
int len=0;
while ((len=in.read(buffer))!=-1) {
servletOutputStream.write(buffer);
}
in.close();
}
}
Request
-
請(qǐng)求行
1.獲取請(qǐng)求方式
request.getMethod();
2.請(qǐng)求資源url uri
request.getRequestURL();
request.getRequestURI();
下圖中第一個(gè)是URL
第二個(gè)是URI
image.png
3.獲取get請(qǐng)求參數(shù)
request.getQueryString();
這里獲取到的都是請(qǐng)求的參數(shù)信息
image.png
4.獲取當(dāng)前web應(yīng)用名稱
request.getContentPath();
獲取到的是當(dāng)前工程的名字
請(qǐng)求頭
1.獲取所有請(qǐng)求頭名稱
Enumeration<String> headerNames=request.getHeaderNames();
while(headerNames.hasMoreElements())
System.out.println("name="+headerNames.nextElements());
請(qǐng)求體
1.獲取一個(gè)值
request.getParameterValue();
2.獲取多個(gè)值
request.getParameterValues();
3.獲取所有請(qǐng)求參數(shù)名稱
request.getParameterNames();
4.獲取所有請(qǐng)求參數(shù)
request.getParameterMap();
get和post方式如何選擇
1.發(fā)送的參數(shù)不需要寫到數(shù)據(jù)庫(kù)用get方式
2.發(fā)送的參數(shù)需要保存到數(shù)據(jù)庫(kù)用post
renquest請(qǐng)求轉(zhuǎn)發(fā)
請(qǐng)求轉(zhuǎn)發(fā)跟重定向的區(qū)別在于,請(qǐng)求轉(zhuǎn)發(fā)是直接通過(guò)一個(gè)找另一個(gè)述雾,不需要返回再重新找街州。
實(shí)現(xiàn)轉(zhuǎn)發(fā)
1.通過(guò)請(qǐng)求對(duì)象獲取一個(gè)轉(zhuǎn)發(fā)器request.getRequestDispatcher(String path)
返回一個(gè)RequestDispatcher
2.通過(guò)轉(zhuǎn)發(fā)器進(jìn)行轉(zhuǎn)發(fā)
調(diào)用轉(zhuǎn)發(fā)器的forward()方法進(jìn)行轉(zhuǎn)發(fā)
disp.forward(req,rep)
request域?qū)ο?br> 1.在一次請(qǐng)求過(guò)程當(dāng)中存在的且共享
客戶端地址與服務(wù)器端地址
- 客戶端地址
客戶端訪問(wèn)服務(wù)器使用的地址
服務(wù)器外部地址
寫的時(shí)候要寫上web應(yīng)用的名稱/應(yīng)用名稱/資源 - 服務(wù)器地址
服務(wù)內(nèi)部當(dāng)中使用的地址
不需要寫web應(yīng)用名稱/資源名稱
cookie與Session
會(huì)話技術(shù)
什么是會(huì)話
- 用戶點(diǎn)開一個(gè)瀏覽器
- 點(diǎn)擊多個(gè)超鏈接,訪問(wèn)多個(gè)web資源
- 再關(guān)閉瀏覽器玻孟,整個(gè)過(guò)程稱之為一個(gè)會(huì)話
解決什么問(wèn)題
- 保持各個(gè)客戶端自己的數(shù)據(jù)
- 存臨時(shí)數(shù)據(jù)
Session技術(shù)
Session域當(dāng)一個(gè)瀏覽器訪問(wèn)服務(wù)器創(chuàng)建唆缴,關(guān)閉服務(wù)器或過(guò)期時(shí),銷毀Session域?qū)ο蟆?br>
將數(shù)據(jù)存儲(chǔ)到服務(wù)器黍翎,安全性相對(duì)好面徽,增加服務(wù)器壓力
會(huì)為每個(gè)客戶端都創(chuàng)建一塊內(nèi)存空間存儲(chǔ)客戶的數(shù)據(jù),但客戶端需要每次都攜帶一個(gè)標(biāo)識(shí)ID去服務(wù)器中尋找屬于自己的內(nèi)存空間匣掸。所以說(shuō)Sesssion的實(shí)現(xiàn)是基于Cookie趟紊。Session需要借助于Cookie存儲(chǔ)客戶的唯一性標(biāo)識(shí)JSESSIONID。
獲取Session對(duì)象
//方法內(nèi)部判斷該客戶端是否在服務(wù)器端已經(jīng)存在Session
//有則不創(chuàng)建碰酝,否則新創(chuàng)建session對(duì)象
HttpSession session=request.getSession();
String id=session.getId();
Session對(duì)象生命周期
創(chuàng)建:第一次執(zhí)行request.getSession()時(shí)創(chuàng)建
銷毀:
- 服務(wù)器關(guān)閉時(shí)
- session過(guò)期或者失效(默認(rèn)30分鐘) 霎匈,從不操作服務(wù)器端的資源開始計(jì)時(shí)
- 手動(dòng)銷毀session(session.invalidate())
cookie技術(shù)
數(shù)據(jù)存儲(chǔ)在客戶端本地,減少服務(wù)器端壓力送爸,安全性不好铛嘱,客戶端可以清除cookie
服務(wù)器如何把cookie寫給客戶端
- 創(chuàng)建cookie(會(huì)以響應(yīng)頭的形式發(fā)送給客戶端;只能存儲(chǔ)非中文的字符串)
Cookie cookie=new Cookie(String cookieName,String cookieValue) - 向客戶端發(fā)送cookie
response.addCookie(cookie名稱) - 訪問(wèn)
- cookie默認(rèn)存儲(chǔ)時(shí)間
- 設(shè)置cookie的攜帶路徑
- 刪除cookie
默認(rèn)cookie的生命周期是會(huì)話級(jí)別袭厂,打開瀏覽器和關(guān)閉瀏覽器為一次會(huì)話墨吓,如果不設(shè)置持久化時(shí)間,cookie會(huì)存儲(chǔ)在瀏覽器內(nèi)存纹磺,瀏覽器關(guān)閉帖烘,cookie信息銷毀
設(shè)置cookie的持久化時(shí)間需要在發(fā)送cookie之前進(jìn)行。cookie.setMaxAge(60); 單位時(shí)間是秒橄杨,過(guò)期cookie自動(dòng)銷毀
- 設(shè)置cookie的攜帶路徑
意思是在訪問(wèn)某一個(gè)資源時(shí)秘症,要不要先攜帶cookie信息
如果不設(shè)置攜帶路徑照卦,默認(rèn)情況下會(huì)在訪問(wèn)創(chuàng)建cookie的web資源相同的路徑都攜帶cookie信息(比如創(chuàng)建cookie的servlet文件在一個(gè)目錄下,那么在servlet的上級(jí)文件目錄中的所有web資源都會(huì)存在該cookie信息)
設(shè)置路徑方式
cookie.setPath(String path); - cookie.setPath("/CookiePro/cookieServlet") 只有訪問(wèn)該servlet才攜帶cookie信息
- cookie.setPath("/CookiePao") 只要在該工程下历极,都會(huì)攜帶cookie信息
- cookie.setPath("/"); 只要訪問(wèn)該服務(wù)器窄瘟,都會(huì)攜帶cookie信息
刪除cookie:創(chuàng)建一個(gè)重名的cookie衷佃,設(shè)置cookie的存活時(shí)間為0
服務(wù)器如何獲取客戶端攜帶的cookie
- 通過(guò)request對(duì)象的getCookie()方法
- 獲取的是所有的cookie
- 進(jìn)行遍歷趟卸,找出自己名稱的那一個(gè)