Servlet是服務器端程序,主要用來交互式地瀏覽和修改數據,生成動態web內容。web服務器接收到客戶端的Servlet請求后,如果檢查到已經裝載並創建了該Servlet的實例對象,則會創建一個用於封裝HTTP請求消息的HttpServletRequest對象和一個代表Http響應消息的HttpServletResponse對象,然后調用Servlet的service()方法,將請求和響應對象作為參數傳遞進去,這樣客戶端通過HttpServletRequest對象將請求發送給服務器,服務器通過HttpServletResponse對象將響應傳遞給客戶端,達到通信的目的。
1. HttpServletResponse對象介紹
HttpServletResponse是一個繼承了ServletResponse的接口,這個對象中封裝了向客戶端發送數據、發送響應頭,發送響應狀態碼的方法。查看HttpServletResponse的API,可以看到這些相關的方法。這里給出一個java EE的api幫助文檔的鏈接:https://docs.oracle.com/javaee/7/api/
1.1 負責向客戶端發送數據的相關方法
getOutputStream()方法用於返回Servlet引擎創建的字節輸出流對象,Servlet程序可以按字節形式輸出響應正文。而getWriter()方法用於返回Servlet引擎創建的字符輸出流對象,Servlet程序可以按字符形式輸出響應正文。
其實PrintWriter對象輸出字符文本內容時,它內部還是將字符串轉換成了某種字符集編碼的字節數組后再進行輸出,使用PrintWriter對象的好處就是不用編程人員自己來完成字符串到字節數組的轉換。 使用ServletOutputStream對象也能輸出內容全為文本字符的網頁文檔,但是,如果網頁文檔內容是在Servlet程序內部使用文本字符串動態拼湊和創建出來的,則需要先將字符文本轉換成字節數組后輸出。這兩個方法互相排斥,調用了其中的任何一個方法后,就不能再調用另一方法。
1.2 負責向客戶端發送響應頭的相關方法
響應頭向客戶端提供一些額外信息,比如誰在發送響應、響應者的功能,甚至與響應相關的一些特殊指令。這些頭部有助於客戶端處理響應,並在將來發起更好的請求。
1.3 負責向客戶端發送響應狀態碼的相關方法
當我們搜索一個頁面找不到時,經常出現404 NOT FOUND,這個就是通過setStatus(int sc)這個方法實現的。
1.4 響應狀態碼的常量
HttpServletResponse定義了很多狀態碼的常量(具體可以查看Servlet的API),當需要向客戶端發送響應狀態碼時,可以使用這些常量,避免了直接寫數字,常見的狀態碼對應的常量:
404:
200:
500:
2. HttpServletResponse對象常見應用
2.1 使用OutputStream流向客戶端瀏覽器輸出中文數據
在服務器端,數據是以哪個碼表輸出的,那么就要控制客戶端瀏覽器以相應的碼表打開,比如:outputStream.write("中國".getBytes("UTF-8"));使用OutputStream流向客戶端瀏覽器輸出中文,以UTF-8的編碼進行輸出,此時就要控制客戶端瀏覽器以UTF-8的編碼打開,否則顯示的時候就會出現中文亂碼,那么在服務器端如何控制客戶端瀏覽器以以UTF-8的編碼顯示數據呢?可以通過設置響應頭控制瀏覽器的行為,例如:response.setHeader("content-type", "text/html;charset=UTF-8");通過設置響應頭控制瀏覽器以UTF-8的編碼顯示數據。
示例代碼:
package myTest; import java.io.IOException; import java.io.OutputStream; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class OutputStreamDemo extends HttpServlet { private static final long serialVersionUID = 4312868947607181532L; public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //使用OutputStream流輸出中文 outputChineseByOutputStream(response); } /** * 使用OutputStream流輸出中文 * @param request * @param response * @throws IOException */ public void outputChineseByOutputStream(HttpServletResponse response) throws IOException{ String data = "使用OutputStream流向瀏覽器輸出中文"; //獲取OutputStream輸出流 OutputStream outputStream = response.getOutputStream(); //通過設置響應頭控制瀏覽器以UTF-8的編碼顯示數據,如果不加這句話,那么瀏覽器顯示的將是亂碼 response.setHeader("content-type", "text/html;charset=UTF-8"); //將字符轉換成字節數組,指定以UTF-8編碼進行轉換 byte[] dataByteArr = data.getBytes("UTF-8"); //使用OutputStream流向客戶端輸出字節數組 outputStream.write(dataByteArr); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
data.getBytes()是一個將字符轉換成字節數組的過程,這個過程中一定會去查碼表,如果是中文的操作系統環境,默認就是查找查GB2312的碼表,將字符轉換成字節數組的過程就是將中文字符轉換成GB2312的碼表上對應的數字。
配置web.xml,運行后輸出如下結果:
2.2 使用PrintWriter流向客戶端瀏覽器輸出中文數據
1. 在獲取PrintWriter輸出流之前首先使用"response.setCharacterEncoding(charset)"設置字符以什么樣的編碼輸出到瀏覽器,如:response.setCharacterEncoding("UTF-8");設置將字符以"UTF-8"編碼輸出到客戶端瀏覽器,然后再使用response.getWriter();獲取PrintWriter輸出流,這兩個步驟不能顛倒。即:
//設置將字符以"UTF-8"編碼輸出到客戶端瀏覽器 response.setCharacterEncoding("UTF-8"); //獲取PrintWriter輸出流 PrintWriter out = response.getWriter();
2. 再使用response.setHeader("content-type", "text/html;charset=字符編碼");設置響應頭,控制瀏覽器以指定的字符編碼編碼進行顯示。
//通過設置響應頭控制瀏覽器以UTF-8的編碼顯示數據(瀏覽器向客戶端輸出為UTF-8形式) response.setHeader("content-type", "text/html;charset=UTF-8");
示例代碼如下:
package myTest; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class PrintWriterDemo extends HttpServlet { private static final long serialVersionUID = 4312868947607181532L; public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //使用PrintWriter流輸出中文 outputChineseByPrintWriter(response); } /** * 使用PrintWriter流輸出中文 * @param request * @param response * @throws IOException */ public void outputChineseByPrintWriter(HttpServletResponse response) throws IOException{ String data = "使用PrintWriter流輸出中文"; //設置將字符以"UTF-8"編碼輸出到客戶端瀏覽器 response.setCharacterEncoding("UTF-8"); //獲取PrintWriter輸出流 PrintWriter out = response.getWriter(); response.setHeader("content-type", "text/html;charset=UTF-8"); //使用PrintWriter流向客戶端輸出字符 out.write(data); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
配置web.xml文件,運行后顯示結果:
對比可以看出,使用OutputStream流輸出中文時,首先要將字符轉換成字節。當需要向瀏覽器輸出字符數據時,使用PrintWriter比較方便,省去了將字符轉換成字節數組那一步。
2.3 使用OutputStream或者PrintWriter向客戶端瀏覽器輸出數字
示例代碼如下:
package myTest; import java.io.IOException; import java.io.OutputStream; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class NoDemo extends HttpServlet { private static final long serialVersionUID = 4312868947607181532L; public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //使用OutputStream輸出1到客戶端瀏覽器 outputOneByOutputStream(response); } /** * 使用OutputStream流輸出數字1 * @param request * @param response * @throws IOException */ public void outputOneByOutputStream(HttpServletResponse response) throws IOException{ response.setHeader("content-type", "text/html;charset=UTF-8"); OutputStream outputStream = response.getOutputStream(); outputStream.write("使用OutputStream流輸出數字1:".getBytes("UTF-8")); outputStream.write((1+" ").getBytes("UTF-8")); } }
關鍵在於outputStream.write((1+" ").getBytes("UTF-8")); 1+""這一步是將數字1和一個空字符串相加,這樣處理之后,數字1就變成了字符串1了,然后再將字符串1轉換成字節數組使用OutputStream進行輸出。運行結果如下:
如果使用PrintWriter流輸出數字,那么也要先將數字轉換成字符串后再輸出,代碼如下:
public void outputOneByPrintWriter(HttpServletResponse response) throws IOException{ response.setHeader("content-type", "text/html;charset=UTF-8"); response.setCharacterEncoding("UTF-8");
//獲取PrintWriter輸出流 PrintWriter out = response.getWriter(); out.write("使用PrintWriter流輸出數字1:"); out.write(1+""); }
在開發過程中,如果希望服務器輸出什么瀏覽器就能看到什么,那么在服務器端都要以字符串的形式進行輸出。
歡迎搜索微信公眾號“程序員考拉”,關注更多精彩內容!