接下來記錄一下Servlet Response相關的信息,在service方法中使用的是HttpServletResponse,它繼承自ServletResponse,擴展了Http協議相關的內容,下面簡單記錄一下它的基本用法。
response組成內容
以下是一個常見response響應的內容,它包括狀態行、響應頭、一個空行和實體內容,其中"HTTP/1.1 200 OK"就是狀態行,包括協議、狀態代號和狀態描述信息,下面有若干響應頭,空行和實體內容這里沒展示。
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 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,還可以控制輸出到頁面的數據長度,發現輸出到頁面的實際長度被截取了。
設置響應消息
有兩種方法可以設置響應消息,如下。
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");
修改后瀏覽器能正常顯示中文。