Servlet請求和響應
在Java Web中Servlet、請求和響應是最基本的三個物件,在Web容器的管理下,這三者能夠完成基本的HTTP請求處理。
Servlet的作用是為客戶提供服務。servlet的角色是接受一個客戶的請求,再返回一個響應。請求可能非常簡單,例如:給我提供一個歡迎頁面;也可能非常複雜,例如:為當前的購物車結賬,這個請求會帶一些客戶端傳來的引數,servlet需要知道自己如何使用請求中的引數,還需要知道該返回什麼樣的響應。
一、Servlet
1. Servlet受容器管理
Java Web伺服器處理使用者請求的基本過程:使用者在客戶端點選一個連結,瀏覽器會向Web應用伺服器傳送一個URL請求,該URL會指向一個servlet
2. Servlet的生命週期
在容器啟動時,XXXServlet在JVM的管理下被例項化為一個物件,這時候它還不是servlet,需要在容器的管理下呼叫init()方法進行初始化,獲得ServletConfig和ServletContext物件的引用後,才稱為一個真正的Servlet。
1)init()
-
何時呼叫?servlet例項建立後,並在servlet能為客戶請求提供服務之前,容器需要通過init方法初始化servlet。
-
作用?初始化servlet例項,使之獲得web容器的相關資訊
-
是否會被覆蓋?有可能
2)service()
-
何時呼叫?當一個客戶請求到來時,容器會建立(或從執行緒池分配一個執行緒),並呼叫servlet的service方法
-
作用?這個方法會確定HTTP方法(GET or POST),並呼叫對應的servlet方法——doGet或doPost;
-
是否會被覆蓋?可以,但是不會
3)doGet()或doPost()
-
何時呼叫?
-
作用?具體的業務邏輯
-
是否會被覆蓋?至少要覆蓋其中之一
關鍵點:每個請求都在一個單獨的執行緒中執行!
3. Servlet的繼承體系
-
servlet介面:javax.servlet.Servlet,表示所有的Servlet都有這5個方法,其中init、service和destroy三個方法和servlet的生命週期有關;
-
GenericServlet:javax.servlet.GenericServlet,這是一個抽象類,它實現了開發者需要的大部分基本servlet方法,大多數servlet的“servlet行為”都來自這個類;
-
HttpServlet:javax.servlet.http.HttpServlet,這也是一個抽象類,它實現了自己的service()方法,處理servlet的HTTP特性(service方法不僅僅只處理HTTP請求)。
-
MyTestServlet:這是開發者自己編寫的處理類,一般只需要實現doGet()和doPost()方法。
二、請求和響應
1. ServletRequest的繼承體系
HttpServletRequest的API與HTTP有關,例如:Cookie、首部(Header)和會話(Session)等;
2. ServletResponse的繼承體系
ServletResponse(響應)也是類似,用於幫助servlet給客戶端返回處理結果,而HttpServletResponse增加了HTTP相關的內容(例如:錯誤、cookie和首部)等API。
HttpServletRequest和HttpServletResponse這些都是servlet規範裡指定的介面,而web容器開發商(例如tomcat)會負責實現這些介面,例如:HttpServletResponseWrapper和ApplicationHttpResponse等,作為開發者,我們只需要知道,在處理doGet()和doPost方法時,容器會給這個方法傳HttpServletRequest和HttpServletResponse兩個引數。
3. GET和POST的區別
-
POST方法有請求體
-
GET方法的查詢引數直接跟在URL後面,不夠安全;
-
GET請求可以建立書籤,POST請求則不能
-
GET請求是冪等的,POST請求不是(GET請求僅僅用於查詢一些資料,POST請求則用於在伺服器上更新資料),在業務上會遇到既需要POST請求,又需要保證請求冪等的情況(例如庫存扣減),這種情況需要我們出具對應的實現方案。參見:
4. HTTP請求的API
-
getHeader(),可以獲取首部資訊,例如request.getHeader("User-Agent")可以獲取客戶端的平臺和瀏覽器資訊。
-
getIntHeader(),如果首部資訊中的“key/value”對中的value是int型別的,可以使用這個方法直接獲取值而不需要顯式型別轉換
-
getCookies(),可以獲取與請求相關的cookie
-
getSession(),可以獲取與請求相關的會話
-
getMethod(),可以獲取http方法
-
getInputStream(),可以獲取請求的輸入流
-
求,可以獲取查詢字串中的資料、對於POST請求,可以獲取請求體中的資料
-
getRemotePort(),獲取客戶端的埠號
-
getServerPort(),獲取服務端接受請求的埠號(請求一開始傳送服務端的哪個埠?)
-
getLocalPort(),獲取服務端處理請求的埠號(請求最後是傳送到服務端的哪個埠?)
5. HTTP響應的API
大多數情況下,使用響應只是為了向客戶發回資料。會對響應呼叫兩個方法:setContentType()和getWriter()。在此之後,可以將HTML或其他內容寫入到流。不過,你也可以使用響應設定首部、傳送錯誤或增加Cookie。
-
setContentType(),設定響應返回的MIME型別
-
getOutputStream(),獲取HTTP輸出位元組流
-
getWriter(),獲取HTTP輸出字元流
-
addCookie(Cookie cookie),給響應首部中增加cookie物件,注意這裡不是增加“key/value”對
-
addHeader(),在響應首部中新增一個“key/value”對
-
setHeader(),在響應首部中設定一個“key/value”對;和addHeader()的區別是,如果響應首部中已經有對應的key存在,setHeader()會覆蓋現有的值,而addHeder()會新增一個“key/value”對,使用時需要注意;
-
encodeRedirectURL(),對包含session ID的URL進行編碼。使用場景:在瀏覽器不支援使用cookie跟蹤會話時,可以使用URL重寫(即將URL重定向到另一個URL,而這個URL的後面會帶上session id傳給客戶端,這個URL在返回給客戶端之前需要經過編碼)
6. 重定向和請求派發
-
重定向是讓瀏覽器訪問新的URL完成工作,使用者會在瀏覽器位址列看到新的URL;
-
請求派發是服務端的工作,是當前servlet委託另外的servlet完成請求,並給客戶端發回響應,使用者的瀏覽器位址列的URL沒有改變;
總結:在客服端訪問jsp,提交表單,通過配置檔案xml找到Servlet,伺服器例項化該Servlet,並執行其doGet方法。此外在表單屬性中,可以設定提交方式為method=doPost。在Servlet類中做相應修改,即可實現doPost方式提交請求。doGet和doPost的區別在於:
1、從表現形式上看,用doGet會在位址列顯示請求引數,而doPost不會。
2、本質上,是因為這兩種方式對請求的封裝方式不同,doGet將引數作為請求url的一部分直接提交,而doPost將請求引數作為請求體的一部分提交。