1. 程式人生 > 其它 >Servlet請求和響應

Servlet請求和響應

在Java Web中Servlet、請求和響應是最基本的三個物件,在Web容器的管理下,這三者能夠完成基本的HTTP請求處理。

Servlet的作用是為客戶提供服務。servlet的角色是接受一個客戶的請求,再返回一個響應。請求可能非常簡單,例如:給我提供一個歡迎頁面;也可能非常複雜,例如:為當前的購物車結賬,這個請求會帶一些客戶端傳來的引數,servlet需要知道自己如何使用請求中的引數,還需要知道該返回什麼樣的響應。

一、Servlet

1. Servlet受容器管理

Java Web伺服器處理使用者請求的基本過程:使用者在客戶端點選一個連結,瀏覽器會向Web應用伺服器傳送一個URL請求,該URL會指向一個servlet

;Web容器看出這個請求指向某個servlet A,就會建立兩個物件(HttpServletRequest和HttpServletResponse),並分配或建立一個執行緒,呼叫servlet A對應的service方法(上述請求和響應物件作為引數);service根據HTTP請求區分出客戶端發來的是GET還是POST請求,並呼叫對應的doGet()或doPost()方法;在doGet()或doPost()方法中進行業務邏輯的處理,處理完成後的結果通過響應物件返回寫回給客戶端。

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將請求引數作為請求體的一部分提交。

在用瀏覽器提交檔案時一定要使用doPost方式。