HttpServletResponse是專門用于HTTP協議的ServletResponse接口,它用于封裝HTTP響應消息,允許操控HTTP協議相關數據,包括響應頭和狀態碼,支持Cookies和session跟蹤,HttpServletResponse也定義了一系列用于描述各種HTTP狀態碼的常量。
WEB服務器回送給WEB客戶端的HTTP響應消息分為三部分,狀態行、響應消息頭 和 消正文(也叫實體內容)。
***WEB響應消息的響應狀態行可分為三部分:http版本、狀態代碼和一條相關的提示信息,如:HTTP/1.1 200 OK
HttpServletResponse中定義了幾個用于產生HTTP消息的響應狀態行的方法和對應各個響應狀態碼的常量。***
- 狀態碼常量:略;
- setStatus(int
status)方法:用于設置HTTP響應消息的狀態碼,并生成響應狀態行。由于響應狀態行中的狀態描述信息直接與狀態碼相關,而 HTTP
版本由服務器確定,因此,只要通過 setStatus(int
status)方法設置了狀態碼,即可實現狀態行的發送。需要注意的是,在正常情況下,Web 服務器會默認產生一個狀態碼為 200 的狀態行。 - sendError(int sc)方法:該方法用于發送表示錯誤信息的狀態碼。例如,404
狀態碼表示找不到客戶端請求的資源。response 對象提供了兩個重載的 sendError(int sc)方法,具體如下: public
public void sendError(int code) throws java.io.IOException
public void sendError(int code,String message)throws java.io.IOException
在上面重載的兩個方法中,第一個方法只發送錯誤信息的狀態碼,而第二個方法除了發送狀態碼以外,還可以增加一條用于提示說明的文本信息,該文本信息將出現在發送給客戶端的正文內容中。
Servlet 向客戶端發送的響應消息中包含響應頭字段,由于 HTTP 協議的響應頭字段有很多種,因此,HttpServletResponse 接口定義了一系列設置 HTTP 響應頭字段的方法
方法聲明 | 功能描述 |
void addIntHeader(String name,int value) | 這兩個方法都是用于設置 HTTP 協議的響應頭字段。其中,參數 name 用于指定響應頭字段的名稱,參數 value 用于指定響 應頭字段的值。不同的是,addHeader() 方法可以增加同名的響應頭字段(HTTP響應消息中允許同一名稱的頭字段出現多次),而 setHeader() 方法則會覆蓋同名的頭字段 |
void setIntHeader(String name, int value) | |
void addIntHeader(String name,int value) | 這兩個方法專門用于設置包含整數值的響應頭,避免了使用 addHeader() 與 setHeader() 方法時需要將 int 類型的設置值轉換為 String 類型的麻煩 |
void setIntHeader(String name, int value) | |
void addDataHeader(String name,long date) | 這兩個方法專門用于設置包含日期值的響應頭,HTTP響應頭中的日期通常都為GMT格式,避免了以毫秒為單位的長整數轉換為GMT時間串的麻煩 |
void setDataHeader(String name, long date) | |
void setContentLength(int len) | 設置響應中內容主體的長度。在HTTP servlet中,此方法設置HTTP Content-Length標頭。參數:len-一個整數,指定要返回給客戶端的內容的長度;設置Content-Length標頭 |
void setContentType(String type) | 該方法用于設置 Servlet 輸出內容的 MIME 類型,對于 HTTP 協議來說,就是設置 Content-Type 響應頭字段的值。例如,如果發送到客戶端的內容是 jpeg 格式的圖像數據,就需要將響應頭字段的類型設置為 image/jpeg。需要注意的是,如果響應的內容為文本,setContentType() 方法還可以設置字符編碼,如 text/html;charset = UTF-8 |
void setLocale (Locale loc) | 該方法用于設置響應消息的本地化信息。對 HTTP 來說,就是設置 Content-Language 響應頭字段和 Content-Type 頭字段中的字符集編碼部分。需要注意的是,如果 HTTP 消息沒有設置 Content-Type 頭字段,則 setLocale() 方法設置的字符集編碼不會出現在 HTTP 消息的響應頭中,如果調用 setCharacterEncoding() 或 setContentType() 方法指定了響應內 容的字符集編碼,則 setLocale() 方法將不再具有指定字符集編碼的功能 |
void setCharacterEncoding(String charset) | 該方法用于設置輸出內容使用的字符編碼,對 HTTP 協議來說,就是設置 Content-Type 頭字段中的字符集編碼部分。如果沒有設置 Content-Type 頭字段,則 setCharacterEncoding 方法設 置的字符集編碼不會出現在 HTTP 消息的響應頭中。setCharacterEncoding() 方法比 setContentType() 和 setLocale() 方法的優先權高,它的設置結果將覆蓋 setContentType() 和 setLocale() 方法所設置的字符碼表 |
響應頭消息的實用案例
- Servlet的中文輸出問題:瀏覽器接收到的中文字符并不是中文符號本身,它是某種字符集編碼數據。同一中文字符可以用多種字符編碼,而瀏覽器也要使用相應的字符集編碼才能顯示。瀏覽器顯示網頁文檔時采用的字符集編碼可以通過手工方式設置們也可在HTTP響應消息的Content-Type頭字段中指定。作為網站開發人員,應避免讓客戶手動設置瀏覽器顯示網頁所采用的字符編碼,這個通過調用setContentType方法就能實現(例如response.setContentType(“text/html;chaeset=GB2312”))。
- 讓瀏覽器定時舒心網頁或跳轉至其他網頁:HTTP協議中定義了一個Refresh頭字段,用于高速瀏覽器多少秒后自動刷新頁面。在這個設置值后加分號(;)分隔再指定一個URL地址,就能跳過去訪問URL地址的資源了。
response.setHeader(“Refresh”,“2;URL=…”). - 禁止瀏覽器緩存當前文檔內容:有三個HTTP響應頭字段都可以禁止瀏覽器緩存當前頁面,事例如下:
response.setDateHeader("Expires",0);
response.setHeader("Cache-Control","no-cache");
response.setHeader("Pragma","no-cache");
- 使用標簽模擬響應消息頭:HTML語言中專門定義了標簽的http-equiv屬性來在HTML文檔中模擬HTTP響應消息頭
發送響應消息體相關的方法
發送響應消息體相關的方法
由于在 HTTP 響應消息中,大量的數據都是通過響應消息體傳遞的,因此,ServletResponse 遵循以 I/O 流傳遞大量數據的設計理念。在發送響應消息體時,定義了兩個與輸出流相關的方法。
1)getOutputStream() 方法
該方法所獲取的字節輸出流對象為 ServletOutputStream 類型。由于 ServletOutputStream是OutputStream 的子類,它可以直接輸出字節數組中的二進制數據。因此,要想輸出二進制格式的響應正文,就需要使用 getOutputStream() 方法。
2)getWriter() 方法
該方法所獲取的字符輸出流對象為 PrintWriter 類型。由于 PrintWriter 類型的對象可以直接輸出字符文本內容,因此,要想輸出內容全部為字符文本的網頁文檔,則需要使用 getWriter() 方法。
注意1:雖然 response 對象的 getOutputStream() 和 getWriter() 方法都可以發送響應消息體,但是,它們之間互相排斥,不可同時使用,否則會發生 IllegalStateException 異常。
注意2:雖然Servlet的sercice方法結束后,Servlet引擎會檢查這兩個方法返回的輸出流對象有沒有調用close方法,沒有會幫忙調一下,但是作為Servlet開發人員最好還是把close方法加上,以便盡快釋放相關資源。
3)輸出緩存區
Servlet程序輸出的HTTP消息的響應正文不是直接發送到客戶端,而是首先被寫入到了Servlet引擎提供的輸出緩存區中,這個緩存區就跟個蓄水池似地,要等被填滿或者Servlet程序寫完了所有響應內容,緩存區的內容才會被發送到客戶端。
setBufferSize方法: 設置期望的輸出緩沖區大小
getBufferSize方法: 返回Servlet引擎實際使用的緩沖區大小
flushBuffer方法: 將輸出緩沖區內容強制輸出到客戶端
reset方法: 清空輸出緩存區的內容
isCommitted方法: 判斷是否提交到了客戶端
4)實現動態文件內容下載:當要下載的文件不是真正存在與WEB服務器的文件系統中,而是需要用一個Servlet程序臨時在服務器內存中動態產生后再傳送到客戶端。
servlet程序必須告訴瀏覽器其所輸出的內容的類型不是普通文本文件或者HTML文件,而是一個淘寶村到本地的下載文件,這就需要HttpServletResponse.setContentType方法來設置Content-Type頭字段的值為瀏覽器無法使用某種方式活著激活某種程序來處理的MIME類型,例如"application/octet-stream";
通過HttpServletResponse.setHeader方法設置Content-Disposition頭的值為"attachment;filename=文件名";
因為附件可以是各種文件類型文件,需將附件文件內容傳至客戶端,其中內容當作二進制處理,所以當調用HttpServletResponse.getOutputStream方法返回的ServletOUtputStream對象來想客戶端寫入附件內容
5)圖像訪問計數器:統計和顯示頁面的訪問次數是一個常見的WEB應用,因為在網頁每次被訪問時,頁面的訪問次數都要發生改變,所以這個功能必須通過服務器端的程序來實現。具體內容:略;
請求重定向與請求轉發
- 在Servlet程序中,有時需要調用另外一個資源來對瀏覽器的請求進行響應,這可以通過兩種方式實現:其中一種是調用RequestDispatcher.forward方法實現的請求轉發,另一種是調用HttpServletResponse.sendRedirect方法實現的請求重定向。1)1)1)1)RequestDispatcher接口:在Servlet
API中定義的接口,它定義了RequestDispatcher實例對象的方法
RequestDispatcher接口中定義了兩個方法:forward方法和include方法,分別用于將請求轉發到RequestDispatcher對象封裝的資源
和 將RequestDispatcher對象封裝進資源作為當前響應內容的一部分包含進來。
ServletContext接口中定義了獲取RequestDispatcher對象的方法:getRequestDispatcher方法、getNameDispatcher方法,具體略。 - 用include方法進行包含:略
- 用forward方法實現請求轉發:略
- 請求轉發與請求重定向的比較
RequestDispatcher.forward方法只能將請求轉發給同一個WEB應用中的組件;而HttpServletResponse.sendRedirect
方法還可以重定向到同一個站點上的其他應用程序中的資源,甚至是使用絕對URL重定向到其他站點的資源。
如果傳遞給HttpServletResponse.sendRedirect
方法的相對URL以“/”開頭,它是相對于服務器的根目錄;如果創建RequestDispatcher對象時指定的相對URL以“/”開頭,它是相對于當前WEB應用程序的根目錄。
調用HttpServletResponse.sendRedirect方法重定向的訪問過程結束后,瀏覽器地址欄中顯示的URL會發生改變,由初始的URL地址變成重定向的目標URL;調用RequestDispatcher.forward
方法的請求轉發過程結束后,瀏覽器地址欄保持初始的URL地址不變。
HttpServletResponse.sendRedirect方法對瀏覽器的請求直接作出響應,響應的結果就是告訴瀏覽器去重新發出對另外一個URL的訪問請求;RequestDispatcher.forward方法在服務器端內部將請求轉發給另外一個資源,瀏覽器只知道發出了請求并得到了響應結果,并不知道在服務器程序內部發生了轉發行為。
RequestDispatcher.forward方法的調用者與被調用者之間共享相同的request對象和response對象,它們屬于同一個訪問請求和響應過程;而HttpServletResponse.sendRedirect方法調用者與被調用者使用各自的request對象和response對象,它們屬于兩個獨立的訪問請求和響應過程。