Javaweb動態(tài)開發(fā)最重要的Servlet詳解

一.導入方式
由于jdk中沒有servlet對應的jar包,所以需要咱們手動引入,有兩種方式:
1.可以采取向lib目錄導入servlet-api的jar包的方式
2.在maven項目中設置如下坐標,并添加相關依賴到依賴庫中即可(推薦使用這種,在maven里選擇webapp的骨架建立項目會自動給你配置好web.xml文件)
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
版本號可以自己定,依賴范圍要配置成provided,否則會和其他jar包沖突
二.Servlet生命周期
原生的Servlet項目都是實現(xiàn)Servlet接口,功能都是通過實現(xiàn)這個接口或者繼承HttpServlet來完成的,其實在IDEA里重寫方法的過程中所對應的順序就是他的生命周期,以下面為例:

按照每一個方法翻譯而來的字面意思,流程是:
初始化——得到服務配置——服務——獲取服務信息——銷毀,簡言之,就是一個從初始化到服務再到消亡的過程。
初始化階段:
public void init(ServletConfig servletConfig)
當服務器啟動,讀取web.xml文件的過程中,Tomcat加載 Servlet,加載完成后,Servlet 容器會創(chuàng)建一個 Servlet 實例 并調用 init()方法,init()方法只會調用一次,這個沒什么好解析的,就是面向對象中類特性的體現(xiàn)
服務階段:
public void service(ServletRequest servletRequest, ServletResponse servletResponse)
這個方法的形參里有兩個ServletRequest和ServletResponse類型的接口,翻譯過來就是服務請求、服務響應,Tomcat啟動時自動裝載某些 servlet,并在 Servlet 容器啟動后,瀏覽器首次向 Servlet 發(fā)送請求,發(fā)送的請求和響應作為參數(shù)就傳到了service方法對應的形參里進行處理??戳艘幌耲dk的源碼,發(fā)現(xiàn)兩個接口下面都有很多的抽象方法,至于請求和響應在底層是怎樣執(zhí)行的源碼里啥都沒寫,目前還不知道(推測是個底層驅動)
消亡階段:
public void destroy()
從圖中規(guī)定的順序不難看出,執(zhí)行到最后的方法也就預示著Servlet的生命即將結束
在JDK的源碼中,Servlet接口下的destory()沒有方法體,應該也是和啟動線程的start0()方法類似被開發(fā)者封裝簡化了
完整流程演示:
@WebServlet("/demo1")
public class SevDemo1 implements Servlet {
@Override
public void init(ServletConfig servletConfig) throws ServletException {System.out.println("我在初始化~~~");}
@Override
public ServletConfig getServletConfig() {return null;}
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("hello world!!!!");}
@Override
public String getServletInfo() {return null;}
@Override
public void destroy() {System.out.println("我走了,拜拜~~~");}
}
控制臺打印的信息很好地反映了執(zhí)行情況:

至于public ServletConfig getServletConfig()和public String getServletInfo()在實現(xiàn)接口后重寫的方法中默認返回的是null,應該是兩個起補充作用的方法
三.繼承HttpServlet
在實際開發(fā)中采用繼承HttpServlet類的方式開發(fā)Servlet程序更加方便,因為實現(xiàn)接口重寫那麼多方法是真的麻煩,而通過繼承的方式就可以根據(jù)需要選擇性的重寫doGe()或doPost()方法就簡單很多,比如
public class HttpDemo extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("執(zhí)行 doGet()...");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("執(zhí)行 doPost()...");
}
}
至于方法體里寫什么內容就要看對應的業(yè)務場景了
氣氛烘托到這里了就不得不說一下GET和POST的區(qū)別了
GET&POST
以前老師是教我這樣理解的——我把一封信放在信封里郵寄出去,我可以選擇密封或者不密封,而這就會導致信的內容會不會被別人看到,若是前者則對應POST,后者就對應GET

當然,這只是抽象層面,而從具體方面來看:
1.從功能上來講,get是從服務器上獲取數(shù)據(jù),post是向服務器傳送數(shù)據(jù)
2.從報文上來講,在不帶參數(shù)時區(qū)別就單純是第一行方法名不同,而在帶參數(shù)時GET方法的參數(shù)放在請求頭URL中,POST方法的參數(shù)放在請求體BODY中 注:GET方法的參數(shù)寫在?后,用&分割
3.從安全性來講,其實他們都不安全,因為http是明文傳輸(在網頁按F12進入開發(fā)者模式發(fā)現(xiàn)兩種方式都能看到數(shù)據(jù)信息)。但是這張圖應該很生動形象也能反映一些問題,相比較之下POST還是比GET安全,因為數(shù)據(jù)在地址欄不可見,哈哈哈
四.Servlet相關性質(八股文)
1.Servlet 是一個供其他 Java 程序(Servlet 引擎)調用的 Java 類,不能獨立運行
2.對于每次訪問請求,Servlet 引擎都會創(chuàng)建一個新的 HttpServletRequest 請求對象和一個 新的 HttpServletResponse 響應對象,然后將這兩個對象作為參數(shù)傳遞給它調用的 Servlet 的 service()方法,service 方法再根據(jù)請求方式分別調用 doXXX 方法
3.針對瀏覽器的多次 Servlet 請求,通常情況下,服務器只會創(chuàng)建一個 Servlet 實例對象, 也就是說 Servlet 實例對象一旦創(chuàng)建,它就會駐留在內存中,為后續(xù)的其它請求服務,直至 web 容器退出/或者 redeploy 該 web 應用,servlet 實例對象才會銷毀
4.如果在<servlet>元素中配置了一個<load-on-startup>元素,那么 WEB 應用程序在啟動時, 就會裝載并創(chuàng)建 Servlet 的實例對象、以及調用 Servlet 實例對象的 init()方法
5.在 Servlet 的整個生命周期內,init 方法只被調用一次。而對每次請求都導致 Servlet 引 擎調用一次 servlet 的 service 方法
——ps:刷dy整理出來的
五.Request&Response

對于這些內部方法來說我覺得會用API就行
1.HttpServletRequest
HttpServletRequest 表示請求過來的信息:
公共接口類HttpServletRequest繼承自ServletRequest??蛻舳藶g覽器發(fā)出的請求被封裝成為一個HttpServletRequest對象。對象包含了客戶端請求信息包括請求的地址,請求的參數(shù),提交的數(shù)據(jù),上傳的文件客戶端的ip甚至客戶端操作系統(tǒng)都包含在其內。
還是面向對象那一套,封裝成類后調用里面的方法,部分常用方法如下:
| public String getAuthType() | 返回這個請求的身份驗證模式 |
|---|---|
| public Cookie[ ] getCookies() | 返回一個數(shù)組,該數(shù)組包含這個請求中當前的所有cookie |
| public long getDateHeader(String name) | 返回指定的請求頭域的值,這個值被轉換成一個精確到毫秒的長整數(shù) |
| public String getHeader(String name) | 返回一個請求頭域的值。(譯者注:與上一個方法不同的是,該方法返回一個字符串) |
2.HttpServletResponse
HttpServletResponse 表示所有響應的信息,需要設置返回給客戶端的信息,通過 HttpServletResponse 對象來進行設置即可,會用幾個核心API就夠了
| addHeader(String name,String value) | 將指定的名字和值加入到響應的頭信息中 |
|---|---|
| encodeURL(String url) | 編碼指定的URL |
| setStatus(int sc) | 給當前響應設置狀態(tài)碼 |
| setHeader(String name,String value) | 將給出的名字和值設置響應的頭部 |
六.請求轉發(fā)模型
先前在網頁中輸出hello java!只是一次請求對應一個Servlet,瀏覽器——Tomcat——Servlet沒有實現(xiàn)請求的轉發(fā),而在真實環(huán)境中網站不可能只進行一次交互,往往需要在一次請求中使用到多個servlet完成

1.一個 web 資源收到客戶端請求后,通知服務器去調用另外 一個 web 資源進行處理
2. HttpServletRequest 對象(也叫 Request 對象)提供了一個 getRequestDispatcher 方法,該 方法返回一個 RequestDispatcher 對象,調用這個對象的 forward 方法可以實現(xiàn)請求轉發(fā)

3. request 對象同時也是一個域對象,開發(fā)人員通過 request 對象在實現(xiàn)轉發(fā)時,把數(shù)據(jù) 通過 request 對象帶給其它 web 資源處理
在實際場景中,用戶輸入信息提交后得到反饋這一過程就是典型的請求轉發(fā),就像這樣:
第一個Servlet里的情況
@WebServlet("/demo2")
public class Sevdemo2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("這里是demo2~~");
//存儲數(shù)據(jù)
req.setAttribute("懶羊羊","你好!");
//請求轉發(fā)
req.getRequestDispatcher("/demo3").forward(req,resp);
}
}
第二個Servlet里的情況
@WebServlet("/demo3")
public class Sevdemo3 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("這里是demo3~~");
Object msg= req.getAttribute("懶羊羊");
System.out.println(msg);
}
}
當我啟動Tomcat來訪問demo2時:

實現(xiàn)了請求的轉發(fā)!
既然是一個Servlet轉發(fā)給另一個Servlet,且是部署在同一個Tomcat中,那就說明不能訪問當前web工程外的資源、同一次 HTTP 請求中,進行多次轉發(fā),仍然是一次 HTTP 請求
七.請求重定向
和請求轉發(fā)比較類似,請求重定向指:一個 web 資源收到客戶端請求后,通知客戶端去訪問另外一個 web 資源,這稱之為請求重定向,還是通過API調方法來實現(xiàn),基本流程如下:

首先通過setStatus()設置響應狀態(tài)碼,然后setHeader(“location”,“http://www.taobao.com”)設置新地址
就實現(xiàn)了請求重定向
@WebServlet("/demo2")
public class Sevdemo2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("這里是demo2~~");
//設置響應狀態(tài)碼
resp.setStatus(302);
//設置新地址
resp.setHeader("location","http://www.taobao.com")
}
}
還有第二種方法,其實和這也大同小異
到這里動態(tài)web的核心Servlet就介紹完了
內容以及配圖都是作者原創(chuàng),若是覺得不錯的話可以三連一下,懶羊羊蟹蟹你~
到此這篇關于Javaweb動態(tài)開發(fā)最重要的Servlet詳解的文章就介紹到這了,更多相關Javaweb Servlet內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
解析ConcurrentHashMap: put方法源碼分析
ConcurrentHashMap是由Segment數(shù)組結構和HashEntry數(shù)組結構組成。Segment的結構和HashMap類似,是一種數(shù)組和鏈表結構,今天給大家普及java面試常見問題---ConcurrentHashMap知識,一起看看吧2021-06-06
詳解eclipse創(chuàng)建maven項目實現(xiàn)動態(tài)web工程完整示例
這篇文章主要介紹了詳解eclipse創(chuàng)建maven項目實現(xiàn)動態(tài)web工程完整示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-12-12
Java數(shù)據(jù)結構及算法實例:快速計算二進制數(shù)中1的個數(shù)(Fast Bit Counting)
這篇文章主要介紹了Java數(shù)據(jù)結構及算法實例:快速計算二進制數(shù)中1的個數(shù)(Fast Bit Counting),本文直接給出實現(xiàn)代碼,代碼中包含詳細注釋,需要的朋友可以參考下2015-06-06

