? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?? Servlet
一.實(shí)現(xiàn)Servlet
?1、新建普通class類
?2、繼承HttpServlet類
?3、重寫service()方法
?4、配置web.xml

二. 工作原理

三. Servlet 的生命周期
Servlet 沒有 main()方法,不能獨(dú)立運(yùn)行,它的運(yùn)行完全由 Servlet 引擎來控 制和調(diào)度。 所謂生命周期,指的是 servlet 容器何時創(chuàng)建 servlet 實(shí)例、何時調(diào) 用其方法進(jìn)行請求的處理、 何時并銷毀其實(shí)例的整個過程。(此處討論默認(rèn)的生 命周期)
? 實(shí)例和初始化時機(jī)
當(dāng)請求到達(dá)容器時,容器查找該 servlet 對象是否存在,如果不存在,則會 創(chuàng)建實(shí)例并 進(jìn)行初始化。
? 就緒/調(diào)用/服務(wù)階段
有請求到達(dá)容器,容器調(diào)用 servlet 對象的 service()方法,處理請求的方法在 整個聲明周 期中可以被多次調(diào)用;?
HttpServlet 的 service()方法,會依據(jù)請求方式來調(diào)用 doGet()或者 doPost() 方法。但是, 這兩個 do 方法默認(rèn)情況下,會拋出異常,需要子類去 override。
? 銷毀時機(jī)
當(dāng)容器關(guān)閉時(應(yīng)用程序停止時),會將程序中的 Servlet 實(shí)例進(jìn)行銷毀。
上述的生命周期可以通過 Servlet 中的生命周期方法來觀察。在 Servlet 中 有三個生命周 期方法,不由用戶手動調(diào)用,而是在特定的時機(jī)有容器自動調(diào)用, 觀察這三個生命周期方法 即可觀察到 Servlet 的生命周期。?



四.請求亂碼解決
?request 屬于接收客戶端的參數(shù),所以必然有其默認(rèn)的語言編碼,主要是由于在解析過程中默認(rèn)使用的編碼方式為 ISO-8859-1(此編碼不支持中文),所以解析時一定會出現(xiàn)亂碼。
?? 要想解決這種亂碼問題,需要設(shè)置 request 中的編碼方式,告訴服務(wù)器以何種方式來解析數(shù)據(jù)?;蛘咴诮邮盏絹y碼數(shù)據(jù)以后,再通過相應(yīng)的編碼格式還原。
?POST請求:Tomcat8及以上和Tomcat7及以下版本都會亂碼
?GET請求:Tomcat8及以上不會亂碼,Tomcat7及以下會亂碼
方案一:
?設(shè)置請求的編碼 (只針對于POST請求有效,必須在接收所有的數(shù)據(jù)之前設(shè)定)
?request.setCharacterEncoding("UTF-8");
?方案二:
?new String(request.getParameter("參數(shù)名").getBytes("ISO-8859-1"),"UTF-8");
?無論是GET請求還是POST請求都適用。一次只能處理一個參數(shù)
五.請求轉(zhuǎn)發(fā)
請求轉(zhuǎn)發(fā),是一種服務(wù)器的行為.
當(dāng)客戶端請求到達(dá)后,服務(wù)器進(jìn)行轉(zhuǎn)發(fā),此時會將請求對象進(jìn)行保存,地址欄中的 URL 地址不會改變
得到響應(yīng)后,服務(wù)器端再將響應(yīng)發(fā)送給客戶端,從始至終只有一個請求發(fā)出。
實(shí)現(xiàn)方式如下,達(dá)到多個資源協(xié)同響應(yīng)的效果
request.getRequestDispatcher("請求的地址").forward(request,response);
六.request作為域?qū)ο?br>
通過該對象可以在一個請求中傳遞數(shù)據(jù),作用范圍:在一次請求中有效,即服務(wù)器跳轉(zhuǎn)有效。
request.setAttribute():設(shè)置域?qū)ο髢?nèi)容;
request.getAttribute(String name):獲取域?qū)ο髢?nèi)容;
request.removeAttribute(String name): 刪除域?qū)ο髢?nèi)容。
request 域?qū)ο笾械臄?shù)據(jù)在一次請求中有效,則經(jīng)過請求轉(zhuǎn)發(fā),request 域中的數(shù)據(jù)依然 存在,則在請求轉(zhuǎn)發(fā)的過程中可以通過 request 來傳輸/共享數(shù)據(jù)。
七.響應(yīng)數(shù)據(jù)
?接收到客戶端請求后,可以通過 HttpServletResponse 對象直接進(jìn)行響應(yīng),響應(yīng)時需要獲取輸出流,
?有兩種形式 :
?getWriter()獲取字符流(只能響應(yīng)回字符);
?getOutputStream()獲取字節(jié)流(能響應(yīng)一切數(shù)據(jù))。
?響應(yīng)回的數(shù)據(jù)到客戶端被瀏覽器解析。
?注意:兩者不能同時使用。
八.亂碼解決
如果響應(yīng)的內(nèi)容中含有中文,則有可能出現(xiàn)亂碼。
這是因?yàn)榉?wù)器響應(yīng)的數(shù)據(jù)也會經(jīng)過網(wǎng)絡(luò)傳輸,服務(wù)器端有一種編碼方式,在客戶端也存在一種編碼方式,當(dāng)兩端使用的編碼方式不同時則出現(xiàn)亂碼。
getWriter()的字符亂碼
對于 getWriter()獲取到的字符流,響應(yīng)中文必定出亂碼,由于服務(wù)器端在進(jìn)行編碼時默認(rèn)會使用 ISO-8859-1 格式的編碼,該編碼方式并不支持中文。
所以要解決該種亂碼只能在服務(wù)器端告知服務(wù)器使用一種能夠支持中文的編碼格式,
比如我們通常用的“UTF-8” resp.setCharacterEncoding("UTF-8");,
此時還只完成了一半的工作,要保證數(shù)據(jù)正確顯示,還需要指定客戶端的解碼方式
resp.setHeader("content-type", "text/html;charset=UTF-8");,
和服務(wù)器一致。兩端指定編碼后,亂碼就解決了。
一句話:保證發(fā)送端和接收端的編碼一致
getOutputStream()字節(jié)亂碼
對于 getOutputStream()方式獲取到的字節(jié)流,響應(yīng)中文時,由于本身就是傳輸?shù)淖止?jié), 所以此時可能出現(xiàn)亂碼,也可能正確顯示,這就看人品了^_^。
當(dāng)服務(wù)器端給的字節(jié)恰好和客戶端使用的編碼方式一致時則文本正確顯示,否則出現(xiàn)亂碼。
無論如何我們都應(yīng)該準(zhǔn)確掌握服務(wù)器和客戶端使用的是那種編碼格式,以確保數(shù)據(jù)正確顯示。指定客戶端和服務(wù)器使用的編碼方式一致即可 。
總結(jié):
亂碼的原因:
1、客戶端和服務(wù)端編碼不一致
2、編碼不支持中文
解決方案:
保證客戶端和服務(wù)端編碼一致且支持中文
response.setContentType("text/html;charset=UTF-8");
九.請求轉(zhuǎn)發(fā)和重定向
1、只有一次請求,request作用域中的數(shù)據(jù)可以共享
2、瀏覽器地址欄不發(fā)生改變
?3、服務(wù)端行為
?4、跳轉(zhuǎn)的絕對地址可以定位到站點(diǎn)名后
?只能請求轉(zhuǎn)發(fā)到當(dāng)前項(xiàng)目下的資源?
?重定向的區(qū)別
?1、有兩次請求,request作用域中的數(shù)據(jù)不可以共享
?2、瀏覽器地址欄發(fā)生改變
?3、客戶端行為
?4、跳轉(zhuǎn)的絕對地址可以定位到http://后面
?重定向可以定位到任意資源?
?請求轉(zhuǎn)發(fā)和重定向不能同時使用?
?路徑問題
?相對路徑
?路徑的前面不要加任何符號,一般情況下代表的是: "http://localhost:8080/站點(diǎn)名/"
?絕對路徑
?1、以http://開頭的,完整的絕對路徑,可以跨域,可以訪問任何資源
?2、以"/"開頭,只能訪問當(dāng)前項(xiàng)目下的資源
?請求轉(zhuǎn)發(fā)和重定向的"/"代表的含義:
?1、請求轉(zhuǎn)發(fā)(服務(wù)端跳轉(zhuǎn)):"http://localhost:8080/站點(diǎn)名/"
?2、重定向(客戶端跳轉(zhuǎn)):"http://localhost:8080/"
客戶端跳轉(zhuǎn):
?表單提交、超鏈接跳轉(zhuǎn)、地址欄直接收入、重定向
服務(wù)端跳轉(zhuǎn):
?請求轉(zhuǎn)發(fā)
HttpServletRequest的常用方法:
setCharacterEncoding(“編碼方式”);
? 設(shè)置請求內(nèi)容的編碼方式(這句話必須在獲取任何請求參數(shù)值之前)
String getParameter(“參數(shù)名”);
用來獲取請求參數(shù)(表單,URL重寫)的值(參數(shù)名通常是表單元素的name屬性值)
HttpServletResponse的常用方法:
setCharacterEncoding(“編碼方式”);?
? 設(shè)置響應(yīng)內(nèi)容的編碼方式得到向客戶端瀏覽器輸出HTML內(nèi)容的字符流對象
?PrintWriter getWriter();
得到向客戶端瀏覽器輸出HTML內(nèi)容的字符流對象
?sendRedirect(“URL地址”);
客戶端瀏覽器重定向(命令客戶端跳轉(zhuǎn))也簡稱為:客戶端跳轉(zhuǎn),外部(在服務(wù)器之外)跳轉(zhuǎn)。
十、重定向
1)什么是重定向?
服務(wù)器向?yàn)g覽器發(fā)送一個狀態(tài)碼302及一個location消息頭(值是一個地址,稱之為重定向地址),
瀏覽器收到后,會立即向 location所指向的地址發(fā)送請求。
2)如何重定向
response.sendRedirect(String url); 其中,url是重定向的地址。
3)編程要注意的問題
? ?? ???????? a、重定向之前,不能夠有out.close()或者out.flush()操作。(否則會報(bào)錯)
?? 有out.close或者out.flus時,請求經(jīng)處理后要把處理結(jié)果打包響應(yīng)給瀏覽器。
?? 而response.sendRect也是對瀏覽器請求的響應(yīng),這樣就造成了一次請求兩次響應(yīng),不符合規(guī)范.
? ?? ???????? b、重定向之前,如果response對象緩存有數(shù)據(jù),則這些數(shù)據(jù)會被清空。
重定向后,只發(fā)送一個重定向地址,不會發(fā)送實(shí)體內(nèi)容。所以response對象會清空。
?? response對象里裝的是返回給瀏覽器的實(shí)體內(nèi)容。
4)重定向的特點(diǎn)
? ?? ???????? 重定向的地址是任意的
? ?? ???????? 重定向之后,瀏覽器地址欄的地址變成了location所指定的地址