Servlet Response常用方法


接下來記錄一下Servlet Response相關的信息,在service方法中使用的是HttpServletResponse,它繼承自ServletResponse,擴展了Http協議相關的內容,下面簡單記錄一下它的基本用法。

response組成內容

以下是一個常見response響應的內容,它包括狀態行、響應頭、一個空行和實體內容,其中"HTTP/1.1 200 OK"就是狀態行,包括協議、狀態代號和狀態描述信息,下面有若干響應頭,空行和實體內容這里沒展示。

HTTP請求中的 常用響應頭如下:
1 Location: http://www.it315.org/index.jsp 配合302實現請求重定向
2 Server:apache tomcat 服務器類型
3 Content-Encoding: gzip 服務器發送數據的壓縮格式
4 Content-Length: 80 發送數據的長度
5 Content-Language: zh-cn 發送數據的語言環境
6 Content-Type: text/html; charset=GB2312 可接受數據格式和語言
7 Last-Modified: Tue, 11 Jul 2000 18:23:51 GMT 與請求頭的if modified頭呼應,主要跟緩存有關
8 Refresh: 1;url=http://www.it315.org 定時刷新
9 Content-Disposition: attachment;filename=aaa.zip 跟下載有關,下載文件名字aaa.zip
10 Transfer-Encoding: chunked 分塊編碼
11 Set-Cookie:SS=Q0=5Lb_nQ; path=/search
12 ETag: W/"83794-1208174400000" Etag一般和MD5配合使用,驗證文件完整性
13 Expires: -1 通知瀏覽器是否緩存當前資源,如果這個頭的值是一個以 毫秒為單位的值,就是通知瀏覽器緩存資源到指定的時間點,如果值是0或-1則是通知瀏覽器禁止緩存。
14 Cache-Control: no-cache 通知瀏覽器是否緩存的頭,no-cache代表不緩存
15 Pragma: no-cache 通知瀏覽器是否緩存的頭,no-cache代表不緩存
16 Connection: close/Keep-Alive 連接狀態
17 Date: Tue, 11 Jul 2000 18:23:51 GMT  Date可以用來判斷是否來自緩存
 
Response的方法,就是針對響應內容進行的,它可以設置狀態碼、設置響應頭,設置響應內容。

response常用方法

response提供了常用的api,有如下三類,通過它可以實現response的諸多功能。

設置狀態碼

設置狀態碼有如下API

(1)response.setStatus(int status) 設置狀態碼

(2)response.setStatus(int status,String description),java8中已經被棄用了,被標記為過時deprecated

下面設置狀態碼為404,測試。

 1 package com.boe.response;
 2 
 3 import javax.servlet.ServletException;
 4 import javax.servlet.annotation.WebServlet;
 5 import javax.servlet.http.HttpServlet;
 6 import javax.servlet.http.HttpServletRequest;
 7 import javax.servlet.http.HttpServletResponse;
 8 import java.io.IOException;
 9 
10 /**
11  * 設置狀態碼
12  */
13 @WebServlet("/ResponseDemo05")
14 public class ResponseDemo05 extends HttpServlet {
15     protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
16         //設置404
17         response.setStatus(404);
18         response.getWriter().write("Hello status");
19     }
20 
21     protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
22         doPost(request, response);
23     }
24 }

訪問頁面后發現盡管能正常訪問到資源,但是狀態碼被設置成了404。

狀態碼404

設置響應頭

設置影響頭的方法,可以影響到頁面的效果,有時候需要和上面設置狀態碼的方法配合使用,它常用的方法如下,前三個是set,后三個是add。

(1)void setHeader(String name, String value)  用給定名稱和值設置響應頭。如果已經設置了頭,則新值將重寫以前的值。containsHeader 方法可用於測試在設置其值之前頭是否存在
(2)void setDateHeader(String name, long date) 給給定名稱和日期值設置響應頭,該日期根據距歷元時間的毫秒數指定。如果已經設置了頭,則新值將重寫以前的值
(3)void setIntHeader(String name, int value) 此方法的默認行為是對包裝的響應對象調用 addIntHeader(String name, int value)。 
(4)void addHeader(String name, String value) 用給定名稱和值添加響應頭,此方法允許響應頭有多個值
(5)void addDateHeader(String name, long date) 用給定名稱和日期值添加響應頭,該日期根據距歷元時間的毫秒數指定,此方法允許響應頭有多個值
(6)void addIntHeader(String name, int value) 用給定名稱和整數值添加響應頭。此方法允許響應頭有多個值
關於API的使用,后面說功能時使用,以上常用的api就是setHeader,setDateHeader,后面response功能上面會使用這兩種方法,下面簡單了解一下setIntHeader方法,這個方法可以用在設置頁面刷新頻率,設置發送數據的長度等。
 1 package com.boe.response;
 2 
 3 import javax.servlet.ServletException;
 4 import javax.servlet.annotation.WebServlet;
 5 import javax.servlet.http.HttpServlet;
 6 import javax.servlet.http.HttpServletRequest;
 7 import javax.servlet.http.HttpServletResponse;
 8 import java.io.IOException;
 9 
10 /**
11  * 設置使用setIntHeader方法
12  */
13 @WebServlet("/ResponseDemo06")
14 public class ResponseDemo06 extends HttpServlet {
15     protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
16         //設置刷新
17         /* response.setIntHeader("Refresh",2);
18         response.getWriter().write("<font color='blue' size='10px'>this is setIntHeader method"+"+"+Math.random()*100+"</font>");*/
19         //設置發送數據長度,一個英文字符代表1個長度
20         response.setIntHeader("Content-Length",10);
21         response.getWriter().write("I come from china");
22 
23     }
24 
25     protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
26         doPost(request, response);
27     }
28 }

實際效果,會每隔2秒刷新一次頁面,這里沒有截取gif,使用兩張貼圖記錄一下。

另外setIntHeader里如果設置Content-length,還可以控制輸出到頁面的數據長度,發現輸出到頁面的實際長度被截取了。

設置響應消息

有兩種方法可以設置響應消息,如下。

(1)ServletOutputStream getOutputStream() 
(2)PrintWriter getWriter()  
上文中的response.getWriter().write("Hello status"),就使用了PrintWriter。

response常用功能

response常用功能有請求重定向、控制緩存、頁面刷新等。

請求重定向

請求重定向的原理就是設置狀態碼為302,並且在響應頭里設置location的路徑,就可以實現重定向,也可以直接使用現成api來實現。

 1 package com.boe.response;
 2 
 3 import javax.servlet.ServletException;
 4 import javax.servlet.annotation.WebServlet;
 5 import javax.servlet.http.HttpServlet;
 6 import javax.servlet.http.HttpServletRequest;
 7 import javax.servlet.http.HttpServletResponse;
 8 import java.io.IOException;
 9 
10 /**
11  * 請求重定向
12  */
13 @WebServlet("/ResponseDemo02")
14 public class ResponseDemo02 extends HttpServlet {
15     protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
16         //原理實現
17         //設置狀態碼
18         response.setStatus(302);
19         //設置消息頭
20         response.setHeader("Location","http://www.baidu.com");
21 
22         //api實現
23         //以上代碼等效如下代碼
24         //response.sendRedirect("http://www.baidu.com");
25     }
26 
27     protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
28         doPost(request, response);
29     }
30 }

訪問ResponseDemo02后頁面跳轉到百度,重定向的地址是會改變的。

控制緩存

控制緩存有三個api可以使用,可以通過設置影響頭的Cache-Control、Pragma和Expires來控制,參考前面對響應頭的介紹和如下代碼。

 1 package com.boe.response;
 2 
 3 import javax.servlet.ServletException;
 4 import javax.servlet.annotation.WebServlet;
 5 import javax.servlet.http.HttpServlet;
 6 import javax.servlet.http.HttpServletRequest;
 7 import javax.servlet.http.HttpServletResponse;
 8 import java.io.IOException;
 9 import java.util.Date;
10 
11 /**
12  * 瀏覽器緩存的設置
13  */
14 @WebServlet("/ResponseDemo04")
15 public class ResponseDemo04 extends HttpServlet {
16     protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
17         //設置不使用緩存
18         /*public void setDateHeader(String name, long date)
19         用給定名稱和日期值設置響應頭。該日期根據距歷元時間的毫秒數指定。如果已經設置了頭,則新值將重寫以前的值。
20         containsHeader 方法可用於測試在設置其值之前頭是否存在。*/
21         //方式1
22         if(response.containsHeader("Expires")){
23             response.setDateHeader("Expires",-1);
24         }
25         //方式2
26         response.setHeader("Cache-Control","no-cache");
27         //方式3
28         response.setHeader("Pragma","no-cache");
29 
30         Date date=new Date();
31         String time = date.toLocaleString();
32         //設置使用緩存
33         //response.setDateHeader("Expires",System.currentTimeMillis()+1000*60*60*1);//1 hour
34         //response.setHeader("Cache-Control","max-age=60");//60 s
35 
36         response.getWriter().write("<font color='blue'>"+time+"</font>");
37 
38 
39     }
40 
41     protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
42         doPost(request, response);
43     }
44 }

當不使用緩存時,每次刷新一下頁面,就會打印新的時間,這里就不展示了。當設置完使用緩存,在緩存的壽命范圍內,時間都不會變的,目前在IE和火狐瀏覽器測試可以,chrome沒有效果。

頁面刷新 

頁面刷新可以設置響應頭的Refresh,里面一個時間參數單位為秒,一個刷新后頁面的url地址,注意使用url,這個可以用在注冊后隔幾秒跳轉到主頁這種場景。以下代碼就是實現訪問ResponseDemo03請求后,等待3秒會刷新進入百度主頁的功能。

 1 package com.boe.response;
 2 
 3 import javax.servlet.ServletException;
 4 import javax.servlet.annotation.WebServlet;
 5 import javax.servlet.http.HttpServlet;
 6 import javax.servlet.http.HttpServletRequest;
 7 import javax.servlet.http.HttpServletResponse;
 8 import java.io.IOException;
 9 
10 /**
11  * 定時刷新
12  */
13 @WebServlet("/ResponseDemo03")
14 public class ResponseDemo03 extends HttpServlet {
15     protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
16         //3 秒
17         response.setHeader("Refresh","3;url=http://www.baidu.com");
18     }
19     protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
20         doPost(request, response);
21     }
22 }

response亂碼處理

涉及到響應,勢必可能會有服務器和瀏覽器編解碼不一致的問題,並會產生亂碼,接下來使用字節流和字符流發送數據,查看亂碼情況,使用如下基准代碼進行調試,根據測試條件做調整即可。

 1 package com.boe.response;
 2 
 3 import javax.servlet.ServletException;
 4 import javax.servlet.annotation.WebServlet;
 5 import javax.servlet.http.HttpServlet;
 6 import javax.servlet.http.HttpServletRequest;
 7 import javax.servlet.http.HttpServletResponse;
 8 import java.io.IOException;
 9 
10 /**
11  * 響應字節流和字符流的亂碼處理
12  */
13 @WebServlet("/ResponseDemo01")
14 public class ResponseDemo01 extends HttpServlet {
15     protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
16         //1 字節流
17         System.out.println(response.getCharacterEncoding());
18         //ISO-8859-1 tomcat默認的字符編碼,針對字符流,對字節流無影響
19         //response.getOutputStream().write("china".getBytes());
20         //getByte()默認使用平台的字符編碼,即GBK,而瀏覽器默認使用GBK解碼,因此沒有亂碼
21         //response.getOutputStream().write("中國".getBytes());
22         /**
23          * 一般瀏覽器都會設置utf-8解碼,這里需指定服務器編碼方式為utf-8,設置瀏覽器解碼也是utf-8
24          */
25         //通知瀏覽器使用utf-8來解碼
26         /*response.setHeader("Content-Type","text/html;charset=utf-8");
27         response.getOutputStream().write("中國".getBytes("utf-8"));*/
28 
29         //2 字符流
30         //默認使用iso-8859-1將字符流轉變成字節流,底層由Tomcat服務器來完成,會使用Tomcat默認的字符集
31         //通知服務端發送數據時字符集utf-8
32         //response.setCharacterEncoding("utf-8");
33         //如果告訴瀏覽器使用何種字符集,則這句可以不用寫,服務會在發送數據自動采用瀏覽器設置的字符集
34         //通知瀏覽器指定utf-8讀取
35         //response.setHeader("Content-Type","text/html;charset=utf-8");
36 
37         //也可以用如下api
38         //response.setContentType("text/html;charset=utf-8");
39         //response.getWriter().write("我是英文");
40     }
41 
42     protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
43         doPost(request, response);
44     }
45 }

字節流發送數據

使用字節流發送數據使用ServletOutputStream的write方法,使用發現在不設置任何編碼格式的情況下,瀏覽器能正常顯示中文,並沒有亂碼產生,通過查看響應頭發現也沒有指定Content-Type。

這是因為用getByte方法得到字節數組時,使用的是平台默認的字符集,即GBK,而當不指定瀏覽器解碼字符集時也是使用平台默認的字符集GBK,兩者一致因此沒有產生亂碼。

一般瀏覽器會使用utf-8來解碼,因此需要使用如下代碼指定瀏覽器的解碼字符集,以及服務器的編碼字符集均為utf-8。

1 response.setHeader("Content-Type","text/html;charset=utf-8");
2 response.getOutputStream().write("中國".getBytes("utf-8"))

修改后發現響應頭里有指定Content-Type。

字符流發送數據

使用字符流發送數據使用PrintWriter的write方法,在不設置字符集的情況下,發現'我是英文'四個字顯示四個問號,產生了亂碼問題。

這是因為字符流本質上還是會轉化為字節流,當服務器不指定字符編碼時,會默認使用tomcat的字符編碼,即iso-8859-1,而瀏覽器不指定解碼時默認使用GBK,因此會產生亂碼,另外iso-8859-1是單字節編碼無法表示中文,'我是英文'最后返回給瀏覽器3f 3f 3f 3f,顯示四個問號。

想要解決亂碼問題也是通過統一編碼方式,服務端使用setCharacterEncoding的方法指定,瀏覽器字符集有兩種方法指定,兩種都可以,本質上就是設置響應頭里的Content-Type。

1 //默認使用iso-8859-1將字符流轉變成字節流,底層由Tomcat服務器來完成,會使用Tomcat默認的字符集
2 //通知服務端發送數據時字符集utf-8
3 //response.setCharacterEncoding("utf-8");
4 //如果告訴瀏覽器使用何種字符集,則這句可以不用寫,服務會在發送數據自動采用瀏覽器設置的字符集
5 //通知瀏覽器指定utf-8讀取
6 //response.setHeader("Content-Type","text/html;charset=utf-8");
7  
8 //也可以用如下api
9 //response.setContentType("text/html;charset=utf-8");

修改后瀏覽器能正常顯示中文。

 
參考博文:
(2) https://www.jianshu.com/p/da01a20a515e 分塊編碼Transfer-Encoding
(5) https://www.jianshu.com/p/53fbd4d91a31 utf-8,gbk2312,iso-8859-1字符集
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM