標籤:響應 aam jedis sm3 attach sum ongl kali jdk
Web伺服器收到用戶端的http請求,會針對每一次請求,分別建立一個用於代表請求的request對象、和代表響應的response對象。
request和response對象即然代表請求和響應,那我們要擷取客戶機提交過來的資料,只需要找request對象就行了。要向客戶機輸出資料,只需要找response對象就行了。
一、HttpServletResponse對象介紹
HttpServletResponse對象代表格服務器的響應。這個對象中封裝了向用戶端發送資料、發送回應標頭,發送響應狀態代碼的方法。查看HttpServletResponse的API,可以看到這些相關的方法。
1.1、負責向用戶端(瀏覽器)發送資料的相關方法
1.2、負責向用戶端(瀏覽器)發送回應標頭的相關方法
1.3、負責向用戶端(瀏覽器)發送響應狀態代碼的相關方法
1.4、響應狀態代碼的常量
HttpServletResponse定義了很多狀態代碼的常量(具體可以查看Servlet的API),當需要向用戶端發送響應狀態代碼時,可以使用這些常量,避免了直接寫數字,常見的狀態代碼對應的常量:
狀態代碼404對應的常量
狀態代碼200對應的常量
狀態代碼500對應的常量
二、HttpServletResponse對象常見應用 2.1、使用OutputStream流向用戶端瀏覽器輸出中文資料
使用OutputStream流輸出中文注意問題:
在伺服器端,資料是以哪個碼錶輸出的,那麼就要控制用戶端瀏覽器以相應的碼錶開啟,比如:outputStream.write("中國".getBytes("UTF-8"));使用OutputStream流向用戶端瀏覽器輸出中文,以UTF-8的編碼進行輸出,此時就要控制用戶端瀏覽器以UTF-8的編碼開啟,否則顯示的時候就會出現中文亂碼,那麼在伺服器端如何控制用戶端瀏覽器以以UTF-8的編碼顯示資料呢?可以通過設定回應標頭控制瀏覽器的行為,例如:response.setHeader("content-type", "text/html;charset=UTF-8");通過設定回應標頭控制瀏覽器以UTF-8的編碼顯示資料。
範例:使用OutputStream流向用戶端瀏覽器輸出"中國"這兩個漢字
1 package gacl.response.study; 2 3 import java.io.IOException; 4 import java.io.OutputStream; 5 import javax.servlet.ServletException; 6 import javax.servlet.http.HttpServlet; 7 import javax.servlet.http.HttpServletRequest; 8 import javax.servlet.http.HttpServletResponse; 9 10 public class ResponseDemo01 extends HttpServlet {11 12 private static final long serialVersionUID = 4312868947607181532L;13 14 public void doGet(HttpServletRequest request, HttpServletResponse response)15 throws ServletException, IOException {16 outputChineseByOutputStream(response);//使用OutputStream流輸出中文17 }18 19 /**20 * 使用OutputStream流輸出中文21 * @param request22 * @param response23 * @throws IOException 24 */25 public void outputChineseByOutputStream(HttpServletResponse response) throws IOException{26 /**使用OutputStream輸出中文注意問題:27 * 在伺服器端,資料是以哪個碼錶輸出的,那麼就要控制用戶端瀏覽器以相應的碼錶開啟,28 * 比如:outputStream.write("中國".getBytes("UTF-8"));//使用OutputStream流向用戶端瀏覽器輸出中文,以UTF-8的編碼進行輸出29 * 此時就要控制用戶端瀏覽器以UTF-8的編碼開啟,否則顯示的時候就會出現中文亂碼,那麼在伺服器端如何控制用戶端瀏覽器以以UTF-8的編碼顯示資料呢?30 * 可以通過設定回應標頭控制瀏覽器的行為,例如:31 * response.setHeader("content-type", "text/html;charset=UTF-8");//通過設定回應標頭控制瀏覽器以UTF-8的編碼顯示資料32 */33 String data = "中國";34 OutputStream outputStream = response.getOutputStream();//擷取OutputStream輸出資料流35 response.setHeader("content-type", "text/html;charset=UTF-8");//通過設定回應標頭控制瀏覽器以UTF-8的編碼顯示資料,如果不加這句話,那麼瀏覽器顯示的將是亂碼36 /**37 * data.getBytes()是一個將字元轉換成位元組數組的過程,這個過程中一定會去查碼錶,38 * 如果是中文的作業系統環境,預設就是尋找查GB2312的碼錶,39 * 將字元轉換成位元組數組的過程就是將中文字元轉換成GB2312的碼錶上對應的數字40 * 比如: "中"在GB2312的碼錶上對應的數字是9841 * "國"在GB2312的碼錶上對應的數字是9942 */43 /**44 * getBytes()方法如果不帶參數,那麼就會根據作業系統的語言環境來選擇轉換碼錶,如果是中文作業系統,那麼就使用GB2312的碼錶45 */46 byte[] dataByteArr = data.getBytes("UTF-8");//將字元轉換成位元組數組,指定以UTF-8編碼進行轉換47 outputStream.write(dataByteArr);//使用OutputStream流向用戶端輸出位元組數組48 }49 50 public void doPost(HttpServletRequest request, HttpServletResponse response)51 throws ServletException, IOException {52 doGet(request, response);53 }54 55 }
運行結果如下:
用戶端瀏覽器接收到資料後,就按照回應標頭上設定的字元編碼來解析資料,如下所示:
2.2、使用PrintWriter流向用戶端瀏覽器輸出中文資料
使用PrintWriter流輸出中文注意問題:
在擷取PrintWriter輸出資料流之前首先使用"response.setCharacterEncoding(charset)"設定字元以什麼樣的編碼輸出到瀏覽器,如:response.setCharacterEncoding("UTF-8");設定將字元以"UTF-8"編碼輸出到用戶端瀏覽器,然後再使用response.getWriter();擷取PrintWriter輸出資料流,這兩個步驟不能顛倒,如下:
1 response.setCharacterEncoding("UTF-8");//設定將字元以"UTF-8"編碼輸出到用戶端瀏覽器2 /**3 * PrintWriter out = response.getWriter();這句代碼必須放在response.setCharacterEncoding("UTF-8");之後4 * 否則response.setCharacterEncoding("UTF-8")這行代碼的設定將無效,瀏覽器顯示的時候還是亂碼5 */6 PrintWriter out = response.getWriter();//擷取PrintWriter輸出資料流
然後再使用response.setHeader("content-type", "text/html;charset=字元編碼");設定回應標頭,控制瀏覽器以指定的字元編碼編碼進行顯示,例如:
1 //通過設定回應標頭控制瀏覽器以UTF-8的編碼顯示資料,如果不加這句話,那麼瀏覽器顯示的將是亂碼2 response.setHeader("content-type", "text/html;charset=UTF-8");
除了可以使用response.setHeader("content-type", "text/html;charset=字元編碼");設定回應標頭來控制瀏覽器以指定的字元編碼編碼進行顯示這種方式之外,還可以用如下的方式來類比回應標頭的作用
1 /**2 * 多學一招:使用HTML語言裡面的<meta>標籤來控制瀏覽器行為,類比通過設定回應標頭控制瀏覽器行為3 *response.getWriter().write("<meta http-equiv=‘content-type‘ content=‘text/html;charset=UTF-8‘/>");4 * 等同於response.setHeader("content-type", "text/html;charset=UTF-8");5 */6 response.getWriter().write("<meta http-equiv=‘content-type‘ content=‘text/html;charset=UTF-8‘/>");
範例:使用PrintWriter流向用戶端瀏覽器輸出"中國"這兩個漢字
1 package gacl.response.study; 2 3 import java.io.IOException; 4 import java.io.OutputStream; 5 import java.io.PrintWriter; 6 import javax.servlet.ServletException; 7 import javax.servlet.http.HttpServlet; 8 import javax.servlet.http.HttpServletRequest; 9 import javax.servlet.http.HttpServletResponse;10 11 public class ResponseDemo01 extends HttpServlet {12 13 private static final long serialVersionUID = 4312868947607181532L;14 15 public void doGet(HttpServletRequest request, HttpServletResponse response)16 throws ServletException, IOException {17 outputChineseByPrintWriter(response);//使用PrintWriter流輸出中文18 }19 20 /**21 * 使用PrintWriter流輸出中文22 * @param request23 * @param response24 * @throws IOException 25 */26 public void outputChineseByPrintWriter(HttpServletResponse response) throws IOException{27 String data = "中國";28 29 //通過設定回應標頭控制瀏覽器以UTF-8的編碼顯示資料,如果不加這句話,那麼瀏覽器顯示的將是亂碼30 //response.setHeader("content-type", "text/html;charset=UTF-8");31 32 response.setCharacterEncoding("UTF-8");//設定將字元以"UTF-8"編碼輸出到用戶端瀏覽器33 /**34 * PrintWriter out = response.getWriter();這句代碼必須放在response.setCharacterEncoding("UTF-8");之後35 * 否則response.setCharacterEncoding("UTF-8")這行代碼的設定將無效,瀏覽器顯示的時候還是亂碼36 */37 PrintWriter out = response.getWriter();//擷取PrintWriter輸出資料流38 /**39 * 多學一招:使用HTML語言裡面的<meta>標籤來控制瀏覽器行為,類比通過設定回應標頭控制瀏覽器行為40 * out.write("<meta http-equiv=‘content-type‘ content=‘text/html;charset=UTF-8‘/>");41 * 等同於response.setHeader("content-type", "text/html;charset=UTF-8");42 */43 out.write("<meta http-equiv=‘content-type‘ content=‘text/html;charset=UTF-8‘/>");44 out.write(data);//使用PrintWriter流向用戶端輸出字元45 }46 47 public void doPost(HttpServletRequest request, HttpServletResponse response)48 throws ServletException, IOException {49 doGet(request, response);50 }51 }
當需要向瀏覽器輸出字元資料時,使用PrintWriter比較方便,省去了將字元轉換成位元組數組那一步。
2.3、使用OutputStream或者PrintWriter向用戶端瀏覽器輸出數字
比如有如下的代碼:
1 package gacl.response.study; 2 3 import java.io.IOException; 4 import java.io.OutputStream; 5 import java.io.PrintWriter; 6 7 import javax.servlet.ServletException; 8 import javax.servlet.http.HttpServlet; 9 import javax.servlet.http.HttpServletRequest;10 import javax.servlet.http.HttpServletResponse;11 12 public class ResponseDemo01 extends HttpServlet {13 14 private static final long serialVersionUID = 4312868947607181532L;15 16 public void doGet(HttpServletRequest request, HttpServletResponse response)17 throws ServletException, IOException {18 19 outputOneByOutputStream(response);//使用OutputStream輸出1到用戶端瀏覽器20 21 }22 23 /**24 * 使用OutputStream流輸出數字125 * @param request26 * @param response27 * @throws IOException 28 */29 public void outputOneByOutputStream(HttpServletResponse response) throws IOException{30 response.setHeader("content-type", "text/html;charset=UTF-8");31 OutputStream outputStream = response.getOutputStream();32 outputStream.write("使用OutputStream流輸出數字1:".getBytes("UTF-8"));33 outputStream.write(1);34 }35 36 }
運行上面代碼顯示的結果如下:
啟動並執行結果和我們想象中的不一樣,數字1沒有輸出來,下面我們修改一下上面的outputOneByOutputStream方法的代碼,修改後的代碼如下:
1 /** 2 * 使用OutputStream流輸出數字1 3 * @param request 4 * @param response 5 * @throws IOException 6 */ 7 public void outputOneByOutputStream(HttpServletResponse response) throws IOException{ 8 response.setHeader("content-type", "text/html;charset=UTF-8"); 9 OutputStream outputStream = response.getOutputStream();10 outputStream.write("使用OutputStream流輸出數字1:".getBytes("UTF-8"));11 //outputStream.write(1);12 outputStream.write((1+"").getBytes());13 }
1+""這一步是將數字1和一個Null 字元串相加,這樣處理之後,數字1就變成了字串1了,然後再將字串1轉換成位元組數組使用OutputStream進行輸出,此時看到的結果如下:
這次可以看到輸出來的1了,這說明了一個問題:在開發過程中,如果希望伺服器輸出什麼瀏覽器就能看到什麼,那麼在伺服器端都要以字串的形式進行輸出。
如果使用PrintWriter流輸出數字,那麼也要先將數字轉換成字串後再輸出,如下:
1 /** 2 * 使用PrintWriter流輸出數字1 3 * @param request 4 * @param response 5 * @throws IOException 6 */ 7 public void outputOneByPrintWriter(HttpServletResponse response) throws IOException{ 8 response.setHeader("content-type", "text/html;charset=UTF-8"); 9 response.setCharacterEncoding("UTF-8");10 PrintWriter out = response.getWriter();//擷取PrintWriter輸出資料流11 out.write("使用PrintWriter流輸出數字1:");12 out.write(1+"");13 } 2.4、檔案下載
檔案下載功能是web開發中經常使用到的功能,使用HttpServletResponse對象就可以實現檔案的下載
檔案下載功能的實現思路:
1.擷取要下載的檔案的絕對路徑
2.擷取要下載的檔案名稱
3.設定content-disposition回應標頭控制瀏覽器以下載的形式開啟檔案
4.擷取要下載的檔案輸入資料流
5.建立資料緩衝區
6.通過response對象擷取OutputStream流
7.將FileInputStream流寫入到buffer緩衝區
8.使用OutputStream將緩衝區的資料輸出到用戶端瀏覽器
範例:使用Response實現檔案下載
1 package gacl.response.study; 2 import java.io.FileInputStream; 3 import java.io.FileNotFoundException; 4 import java.io.FileReader; 5 import java.io.IOException; 6 import java.io.InputStream; 7 import java.io.OutputStream; 8 import java.io.PrintWriter; 9 import java.net.URLEncoder;10 import javax.servlet.ServletException;11 import javax.servlet.http.HttpServlet;12 import javax.servlet.http.HttpServletRequest;13 import javax.servlet.http.HttpServletResponse;14 /**15 * @author gacl16 * 檔案下載17 */18 public class ResponseDemo02 extends HttpServlet {19 20 public void doGet(HttpServletRequest request, HttpServletResponse response)21 throws ServletException, IOException {22 downloadFileByOutputStream(response);//下載檔案,通過OutputStream流23 }24 25 /**26 * 下載檔案,通過OutputStream流27 * @param response28 * @throws FileNotFoundException29 * @throws IOException30 */31 private void downloadFileByOutputStream(HttpServletResponse response)32 throws FileNotFoundException, IOException {33 //1.擷取要下載的檔案的絕對路徑34 String realPath = this.getServletContext().getRealPath("/download/1.JPG");35 //2.擷取要下載的檔案名稱36 String fileName = realPath.substring(realPath.lastIndexOf("\\")+1);37 //3.設定content-disposition回應標頭控制瀏覽器以下載的形式開啟檔案38 response.setHeader("content-disposition", "attachment;filename="+fileName);39 //4.擷取要下載的檔案輸入資料流40 InputStream in = new FileInputStream(realPath);41 int len = 0;42 //5.建立資料緩衝區43 byte[] buffer = new byte[1024];44 //6.通過response對象擷取OutputStream流45 OutputStream out = response.getOutputStream();46 //7.將FileInputStream流寫入到buffer緩衝區47 while ((len = in.read(buffer)) > 0) {48 //8.使用OutputStream將緩衝區的資料輸出到用戶端瀏覽器49 out.write(buffer,0,len);50 }51 in.close();52 }53 54 public void doPost(HttpServletRequest request, HttpServletResponse response)55 throws ServletException, IOException {56 doGet(request, response);57 }58 }
運行結果如下所示:
範例:使用Response實現中文檔案下載
下載中文檔案時,需要注意的地方就是中文檔案名稱要使用URLEncoder.encode方法進行編碼(URLEncoder.encode(fileName, "字元編碼")),否則會出現檔案名稱亂碼。
1 package gacl.response.study; 2 import java.io.FileInputStream; 3 import java.io.FileNotFoundException; 4 import java.io.FileReader; 5 import java.io.IOException; 6 import java.io.InputStream; 7 import java.io.OutputStream; 8 import java.io.PrintWriter; 9 import java.net.URLEncoder;10 import javax.servlet.ServletException;11 import javax.servlet.http.HttpServlet;12 import javax.servlet.http.HttpServletRequest;13 import javax.servlet.http.HttpServletResponse;14 /**15 * @author gacl16 * 檔案下載17 */18 public class ResponseDemo02 extends HttpServlet {19 20 public void doGet(HttpServletRequest request, HttpServletResponse response)21 throws ServletException, IOException {22 downloadChineseFileByOutputStream(response);//下載中文檔案23 }24 25 /**26 * 下載中文檔案,中文檔案下載時,檔案名稱要經過URL編碼,否則會出現檔案名稱亂碼27 * @param response28 * @throws FileNotFoundException29 * @throws IOException30 */31 private void downloadChineseFileByOutputStream(HttpServletResponse response)32 throws FileNotFoundException, IOException {33 String realPath = this.getServletContext().getRealPath("/download/張家界國家森林公園.JPG");//擷取要下載的檔案的絕對路徑34 String fileName = realPath.substring(realPath.lastIndexOf("\\")+1);//擷取要下載的檔案名稱35 //設定content-disposition回應標頭控制瀏覽器以下載的形式開啟檔案,中文檔案名稱要使用URLEncoder.encode方法進行編碼,否則會出現檔案名稱亂碼36 response.setHeader("content-disposition", "attachment;filename="+URLEncoder.encode(fileName, "UTF-8"));37 InputStream in = new FileInputStream(realPath);//擷取檔案輸入資料流38 int len = 0;39 byte[] buffer = new byte[1024];40 OutputStream out = response.getOutputStream();41 while ((len = in.read(buffer)) > 0) {42 out.write(buffer,0,len);//將緩衝區的資料輸出到用戶端瀏覽器43 }44 in.close();45 }46 47 public void doPost(HttpServletRequest request, HttpServletResponse response)48 throws ServletException, IOException {49 doGet(request, response);50 }51 }
運行結果如下所示:
檔案下載注意事項:編寫檔案下載功能時推薦使用OutputStream流,避免使用PrintWriter流,因為OutputStream流是位元組流,可以處理任意類型的資料,而PrintWriter流是字元流,只能處理字元資料,如果用字元流處理位元組資料,會導致資料丟失。
範例:使用PrintWriter流下載檔案
1 package gacl.response.study; 2 import java.io.FileInputStream; 3 import java.io.FileNotFoundException; 4 import java.io.FileReader; 5 import java.io.IOException; 6 import java.io.InputStream; 7 import java.io.OutputStream; 8 import java.io.PrintWriter; 9 import java.net.URLEncoder;10 import javax.servlet.ServletException;11 import javax.servlet.http.HttpServlet;12 import javax.servlet.http.HttpServletRequest;13 import javax.servlet.http.HttpServletResponse;14 /**15 * @author gacl16 * 檔案下載17 */18 public class ResponseDemo02 extends HttpServlet {19 20 public void doGet(HttpServletRequest request, HttpServletResponse response)21 throws ServletException, IOException {22 downloadFileByPrintWriter(response);//下載檔案,通過PrintWriter流23 }24 25 /**26 * 下載檔案,通過PrintWriter流,雖然也能夠實現下載,但是會導致資料丟失,因此不推薦使用PrintWriter流下載檔案27 * @param response28 * @throws FileNotFoundException29 * @throws IOException30 */31 private void downloadFileByPrintWriter(HttpServletResponse response)32 throws FileNotFoundException, IOException {33 String realPath = this.getServletContext().getRealPath("/download/張家界國家森林公園.JPG");//擷取要下載的檔案的絕對路徑34 String fileName = realPath.substring(realPath.lastIndexOf("\\")+1);//擷取要下載的檔案名稱35 //設定content-disposition回應標頭控制瀏覽器以下載的形式開啟檔案,中文檔案名稱要使用URLEncoder.encode方法進行編碼36 response.setHeader("content-disposition", "attachment;filename="+URLEncoder.encode(fileName, "UTF-8"));37 FileReader in = new FileReader(realPath);38 int len = 0;39 char[] buffer = new char[1024];40 PrintWriter out = response.getWriter();41 while ((len = in.read(buffer)) > 0) {42 out.write(buffer,0,len);//將緩衝區的資料輸出到用戶端瀏覽器43 }44 in.close();45 }46 47 public void doPost(HttpServletRequest request, HttpServletResponse response)48 throws ServletException, IOException {49 doGet(request, response);50 }51 }
運行結果如下:
正常彈出下載框,此時我們點擊【儲存】按鈕將檔案下載下來,如下所示:
可以看到,只下載了5.25MB,而這張圖片的原始大小卻是
這說明在下載的時候資料丟失了,所以下載不完全,所以這張圖片雖然能夠正常下載下來,但是卻是無法開啟的,因為丟失掉了部分資料,如下所示:
所以使用PrintWriter流處理位元組資料,會導致資料丟失,這一點千萬要注意,因此在編寫下載檔案功能時,要使用OutputStream流,避免使用PrintWriter流,因為OutputStream流是位元組流,可以處理任意類型的資料,而PrintWriter流是字元流,只能處理字元資料,如果用字元流處理位元組資料,會導致資料丟失。
http://www.cnblogs.com/xdp-gacl/p/3789624.html
javaweb學習總結(七)——HttpServletResponse對象(一)