Web服務(wù)器收到客戶(hù)端的http請(qǐng)求,會(huì)針對(duì)每一次請(qǐng)求,分別創(chuàng)建一個(gè)用于代表請(qǐng)求的request對(duì)象、和代表響應(yīng)的response對(duì)象。request和response對(duì)象即然代表請(qǐng)求和響應(yīng),那我們要獲取客戶(hù)機(jī)提交過(guò)來(lái)的數(shù)據(jù),只需要找request對(duì)象就行了。要向客戶(hù)機(jī)輸出數(shù)據(jù),只需要找response對(duì)象就行了。
使用OutputStream流向客戶(hù)端瀏覽器輸出中文數(shù)據(jù)使用OutputStream流輸出中文注意問(wèn)題:
在服務(wù)器端,數(shù)據(jù)是以哪個(gè)碼表輸出的,那么就要控制客戶(hù)端瀏覽器以相應(yīng)的碼表打開(kāi),比如:outputStream.write("中國(guó)".getBytes("UTF-8"));使用OutputStream流向客戶(hù)端瀏覽器輸出中文,以UTF-8的編碼進(jìn)行輸出,此時(shí)就要控制客戶(hù)端瀏覽器以UTF-8的編碼打開(kāi),否則顯示的時(shí)候就會(huì)出現(xiàn)中文亂碼,那么在服務(wù)器端如何控制客戶(hù)端瀏覽器以以UTF-8的編碼顯示數(shù)據(jù)呢?可以通過(guò)設(shè)置響應(yīng)頭控制瀏覽器的行為,例如:response.setHeader("content-type", "text/html;charset=UTF-8");通過(guò)設(shè)置響應(yīng)頭控制瀏覽器以UTF-8的編碼顯示數(shù)據(jù)。
public class ResponseDemo01 extends HttpServlet { PRivate static final long serialVersionUID = 4312868947607181532L; public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { outputChineseByOutputStream(response);//使用OutputStream流輸出中文 } /** * 使用OutputStream流輸出中文 * @param request * @param response * @throws IOException */ public void outputChineseByOutputStream(HttpServletResponse response) throws IOException{ /**使用OutputStream輸出中文注意問(wèn)題: * 在服務(wù)器端,數(shù)據(jù)是以哪個(gè)碼表輸出的,那么就要控制客戶(hù)端瀏覽器以相應(yīng)的碼表打開(kāi), * 比如:outputStream.write("中國(guó)".getBytes("UTF-8"));//使用OutputStream流向客戶(hù)端瀏覽器輸出中文,以UTF-8的編碼進(jìn)行輸出 * 此時(shí)就要控制客戶(hù)端瀏覽器以UTF-8的編碼打開(kāi),否則顯示的時(shí)候就會(huì)出現(xiàn)中文亂碼,那么在服務(wù)器端如何控制客戶(hù)端瀏覽器以以UTF-8的編碼顯示數(shù)據(jù)呢? * 可以通過(guò)設(shè)置響應(yīng)頭控制瀏覽器的行為,例如: * response.setHeader("content-type", "text/html;charset=UTF-8");//通過(guò)設(shè)置響應(yīng)頭控制瀏覽器以UTF-8的編碼顯示數(shù)據(jù) */ String data = "中國(guó)"; OutputStream outputStream = response.getOutputStream();//獲取OutputStream輸出流 response.setHeader("content-type", "text/html;charset=UTF-8");//通過(guò)設(shè)置響應(yīng)頭控制瀏覽器以UTF-8的編碼顯示數(shù)據(jù),如果不加這句話(huà),那么瀏覽器顯示的將是亂碼 /** * data.getBytes()是一個(gè)將字符轉(zhuǎn)換成字節(jié)數(shù)組的過(guò)程,這個(gè)過(guò)程中一定會(huì)去查碼表, * 如果是中文的操作系統(tǒng)環(huán)境,默認(rèn)就是查找查GB2312的碼表, * 將字符轉(zhuǎn)換成字節(jié)數(shù)組的過(guò)程就是將中文字符轉(zhuǎn)換成GB2312的碼表上對(duì)應(yīng)的數(shù)字 * 比如: "中"在GB2312的碼表上對(duì)應(yīng)的數(shù)字是98 * "國(guó)"在GB2312的碼表上對(duì)應(yīng)的數(shù)字是99 */ /** * getBytes()方法如果不帶參數(shù),那么就會(huì)根據(jù)操作系統(tǒng)的語(yǔ)言環(huán)境來(lái)選擇轉(zhuǎn)換碼表,如果是中文操作系統(tǒng),那么就使用GB2312的碼表 */ byte[] dataByteArr = data.getBytes("UTF-8");//將字符轉(zhuǎn)換成字節(jié)數(shù)組,指定以UTF-8編碼進(jìn)行轉(zhuǎn)換 outputStream.write(dataByteArr);//使用OutputStream流向客戶(hù)端輸出字節(jié)數(shù)組 } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); }}
使用PrintWriter流輸出中文注意問(wèn)題:
在獲取PrintWriter輸出流之前首先使用"response.setCharacterEncoding(charset)"設(shè)置字符以什么樣的編碼輸出到瀏覽器,如:response.setCharacterEncoding("UTF-8");設(shè)置將字符以"UTF-8"編碼輸出到客戶(hù)端瀏覽器,然后再使用response.getWriter();獲取PrintWriter輸出流,這兩個(gè)步驟不能顛倒,如下:
response.setCharacterEncoding("UTF-8");//設(shè)置將字符以"UTF-8"編碼輸出到客戶(hù)端瀏覽器 /** * PrintWriter out = response.getWriter();這句代碼必須放在response.setCharacterEncoding("UTF-8");之后 * 否則response.setCharacterEncoding("UTF-8")這行代碼的設(shè)置將無(wú)效,瀏覽器顯示的時(shí)候還是亂碼 */ PrintWriter out = response.getWriter();//獲取PrintWriter輸出流然后再使用response.setHeader("content-type", "text/html;charset=字符編碼");設(shè)置響應(yīng)頭,控制瀏覽器以指定的字符編碼編碼進(jìn)行顯示,例如:
//通過(guò)設(shè)置響應(yīng)頭控制瀏覽器以UTF-8的編碼顯示數(shù)據(jù),如果不加這句話(huà),那么瀏覽器顯示的將是亂碼response.setHeader("content-type", "text/html;charset=UTF-8");除了可以使用response.setHeader("content-type", "text/html;charset=字符編碼");設(shè)置響應(yīng)頭來(lái)控制瀏覽器以指定的字符編碼編碼進(jìn)行顯示這種方式之外,還可以用如下的方式來(lái)模擬響應(yīng)頭的作用
/** * 多學(xué)一招:使用HTML語(yǔ)言里面的<meta>標(biāo)簽來(lái)控制瀏覽器行為,模擬通過(guò)設(shè)置響應(yīng)頭控制瀏覽器行為 * response.getWriter().write("<meta http-equiv='content-type' content='text/html;charset=UTF-8'/>"); * 等同于response.setHeader("content-type", "text/html;charset=UTF-8"); */ response.getWriter().write("<meta http-equiv='content-type' content='text/html;charset=UTF-8'/>");public class ResponseDemo01 extends HttpServlet { private static final long serialVersionUID = 4312868947607181532L; public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { outputChineseByPrintWriter(response);//使用PrintWriter流輸出中文 } /** * 使用PrintWriter流輸出中文 * @param request * @param response * @throws IOException */ public void outputChineseByPrintWriter(HttpServletResponse response) throws IOException{ String data = "中國(guó)"; //通過(guò)設(shè)置響應(yīng)頭控制瀏覽器以UTF-8的編碼顯示數(shù)據(jù),如果不加這句話(huà),那么瀏覽器顯示的將是亂碼 //response.setHeader("content-type", "text/html;charset=UTF-8"); response.setCharacterEncoding("UTF-8");//設(shè)置將字符以"UTF-8"編碼輸出到客戶(hù)端瀏覽器 /** * PrintWriter out = response.getWriter();這句代碼必須放在response.setCharacterEncoding("UTF-8");之后 * 否則response.setCharacterEncoding("UTF-8")這行代碼的設(shè)置將無(wú)效,瀏覽器顯示的時(shí)候還是亂碼 */ PrintWriter out = response.getWriter();//獲取PrintWriter輸出流 /** * 多學(xué)一招:使用HTML語(yǔ)言里面的<meta>標(biāo)簽來(lái)控制瀏覽器行為,模擬通過(guò)設(shè)置響應(yīng)頭控制瀏覽器行為 * out.write("<meta http-equiv='content-type' content='text/html;charset=UTF-8'/>"); * 等同于response.setHeader("content-type", "text/html;charset=UTF-8"); */ out.write("<meta http-equiv='content-type' content='text/html;charset=UTF-8'/>"); out.write(data);//使用PrintWriter流向客戶(hù)端輸出字符 } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); }}使用OutputStream或者PrintWriter向客戶(hù)端瀏覽器輸出數(shù)字 public class ResponseDemo01 extends HttpServlet { private static final long serialVersionUID = 4312868947607181532L; public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { outputOneByOutputStream(response);//使用OutputStream輸出1到客戶(hù)端瀏覽器 } /** * 使用OutputStream流輸出數(shù)字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流輸出數(shù)字1:".getBytes("UTF-8")); outputStream.write(1); } }運(yùn)行上面代碼顯示的結(jié)果如下:

運(yùn)行的結(jié)果和我們想象中的不一樣,數(shù)字1沒(méi)有輸出來(lái),下面我們修改一下上面的outputOneByOutputStream方法的代碼,修改后的代碼如下:
/** * 使用OutputStream流輸出數(shù)字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流輸出數(shù)字1:".getBytes("UTF-8")); //outputStream.write(1); outputStream.write((1+"").getBytes()); }1+""這一步是將數(shù)字1和一個(gè)空字符串相加,這樣處理之后,數(shù)字1就變成了字符串1了,然后再將字符串1轉(zhuǎn)換成字節(jié)數(shù)組使用OutputStream進(jìn)行輸出,此時(shí)看到的結(jié)果如下:

這次可以看到輸出來(lái)的1了,這說(shuō)明了一個(gè)問(wèn)題:在開(kāi)發(fā)過(guò)程中,如果希望服務(wù)器輸出什么瀏覽器就能看到什么,那么在服務(wù)器端都要以字符串的形式進(jìn)行輸出。
文件下載文件下載功能是web開(kāi)發(fā)中經(jīng)常使用到的功能,使用HttpServletResponse對(duì)象就可以實(shí)現(xiàn)文件的下載,文件下載功能的實(shí)現(xiàn)思路:
1.獲取要下載的文件的絕對(duì)路徑
2.獲取要下載的文件名
3.設(shè)置content-disposition響應(yīng)頭控制瀏覽器以下載的形式打開(kāi)文件
4.獲取要下載的文件輸入流
5.創(chuàng)建數(shù)據(jù)緩沖區(qū)
6.通過(guò)response對(duì)象獲取OutputStream流
7.將FileInputStream流寫(xiě)入到buffer緩沖區(qū)
8.使用OutputStream將緩沖區(qū)的數(shù)據(jù)輸出到客戶(hù)端瀏覽器
/** * @author gacl * 文件下載 */public class ResponseDemo02 extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { downloadFileByOutputStream(response);//下載文件,通過(guò)OutputStream流 } /** * 下載文件,通過(guò)OutputStream流 * @param response * @throws FileNotFoundException * @throws IOException */ private void downloadFileByOutputStream(HttpServletResponse response) throws FileNotFoundException, IOException { //1.獲取要下載的文件的絕對(duì)路徑 String realPath = this.getServletContext().getRealPath("/download/1.JPG"); //2.獲取要下載的文件名 String fileName = realPath.substring(realPath.lastIndexOf("http://")+1); //3.設(shè)置content-disposition響應(yīng)頭控制瀏覽器以下載的形式打開(kāi)文件 response.setHeader("content-disposition", "attachment;filename="+fileName);//設(shè)置content-disposition響應(yīng)頭控制瀏覽器以下載的形式打開(kāi)文件,中文文件名要使用URLEncoder.encode方法進(jìn)行編碼,否則會(huì)出現(xiàn)文件名亂碼 //response.setHeader("content-disposition", "attachment;filename="+URLEncoder.encode(fileName, "UTF-8")); //4.獲取要下載的文件輸入流 InputStream in = new FileInputStream(realPath); int len = 0; //5.創(chuàng)建數(shù)據(jù)緩沖區(qū) byte[] buffer = new byte[1024]; //6.通過(guò)response對(duì)象獲取OutputStream流 OutputStream out = response.getOutputStream(); //7.將FileInputStream流寫(xiě)入到buffer緩沖區(qū) while ((len = in.read(buffer)) > 0) { //8.使用OutputStream將緩沖區(qū)的數(shù)據(jù)輸出到客戶(hù)端瀏覽器 out.write(buffer,0,len); } in.close(); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); }}文件下載注意事項(xiàng):編寫(xiě)文件下載功能時(shí)推薦使用OutputStream流,避免使用PrintWriter流,因?yàn)镺utputStream流是字節(jié)流,可以處理任意類(lèi)型的數(shù)據(jù),而PrintWriter流是字符流,只能處理字符數(shù)據(jù),如果用字符流處理字節(jié)數(shù)據(jù),會(huì)導(dǎo)致數(shù)據(jù)丟失。
生成隨機(jī)圖片用作驗(yàn)證碼生成圖片主要用到了一個(gè)BufferedImage類(lèi)
public class ResponseDemo03 extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setHeader("refresh", "5");//設(shè)置refresh響應(yīng)頭控制瀏覽器每隔5秒鐘刷新一次 //1.在內(nèi)存中創(chuàng)建一張圖片 BufferedImage image = new BufferedImage(80, 20, BufferedImage.TYPE_INT_RGB); //2.得到圖片 //Graphics g = image.getGraphics(); Graphics2D g = (Graphics2D)image.getGraphics(); g.setColor(Color.WHITE);//設(shè)置圖片的背景色 g.fillRect(0, 0, 80, 20);//填充背景色 //3.向圖片上寫(xiě)數(shù)據(jù) g.setColor(Color.BLUE);//設(shè)置圖片上字體的顏色 g.setFont(new Font(null, Font.BOLD, 20)); g.drawString(makeNum(), 0, 20); //4.設(shè)置響應(yīng)頭控制瀏覽器瀏覽器以圖片的方式打開(kāi) response.setContentType("image/jpeg");//等同于response.setHeader("Content-Type", "image/jpeg"); //5.設(shè)置響應(yīng)頭控制瀏覽器不緩存圖片數(shù)據(jù) response.setDateHeader("expries", -1); response.setHeader("Cache-Control", "no-cache"); response.setHeader("Pragma", "no-cache"); //6.將圖片寫(xiě)給瀏覽器 ImageIO.write(image, "jpg", response.getOutputStream()); } /** * 生成隨機(jī)數(shù)字 * @return */ private String makeNum(){ Random random = new Random(); String num = random.nextInt(9999999)+""; StringBuffer sb = new StringBuffer(); for (int i = 0; i < 7-num.length(); i++) { sb.append("0"); } num = sb.toString()+num; return num; } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); }}運(yùn)行結(jié)果如下:

response.setDateHeader("expries", -1);response.setHeader("Cache-Control", "no-cache");response.setHeader("Pragma", "no-cache");設(shè)置http響應(yīng)頭控制瀏覽器定時(shí)刷新網(wǎng)頁(yè)(refresh) response.setHeader("refresh", "5");//設(shè)置refresh響應(yīng)頭控制瀏覽器每隔5秒鐘刷新一次通過(guò)response實(shí)現(xiàn)請(qǐng)求重定向 請(qǐng)求重定向指:一個(gè)web資源收到客戶(hù)端請(qǐng)求后,通知客戶(hù)端去訪(fǎng)問(wèn)另外一個(gè)web資源,這稱(chēng)之為請(qǐng)求重定向。
應(yīng)用場(chǎng)景:用戶(hù)登陸,用戶(hù)首先訪(fǎng)問(wèn)登錄頁(yè)面,登錄成功后,就會(huì)跳轉(zhuǎn)到某個(gè)頁(yè)面,這個(gè)過(guò)程就是一個(gè)請(qǐng)求重定向的過(guò)程
實(shí)現(xiàn)方式:response.sendRedirect(String location),即調(diào)用response對(duì)象的sendRedirect方法實(shí)現(xiàn)請(qǐng)求重定向
sendRedirect內(nèi)部的實(shí)現(xiàn)原理:使用response設(shè)置302狀態(tài)碼和設(shè)置location響應(yīng)頭實(shí)現(xiàn)重定向
public class ResponseDemo04 extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { /** * 1.調(diào)用sendRedirect方法實(shí)現(xiàn)請(qǐng)求重定向, * sendRedirect方法內(nèi)部調(diào)用了 * response.setHeader("Location", "/javaWeb_HttpServletResponse_Study_20140615/index.jsp"); * response.setStatus(HttpServletResponse.SC_FOUND);//設(shè)置302狀態(tài)碼,等同于response.setStatus(302); */ response.sendRedirect("/JavaWeb_HttpServletResponse_Study_20140615/index.jsp"); //2.使用response設(shè)置302狀態(tài)碼和設(shè)置location響應(yīng)頭實(shí)現(xiàn)重定向?qū)崿F(xiàn)請(qǐng)求重定向 //response.setHeader("Location", "/JavaWeb_HttpServletResponse_Study_20140615/index.jsp"); //response.setStatus(HttpServletResponse.SC_FOUND);//設(shè)置302狀態(tài)碼,等同于response.setStatus(302); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); }}web工程中URL地址的推薦寫(xiě)法 在JavaWeb開(kāi)發(fā)中,只要是寫(xiě)URL地址,那么建議最好以"/"開(kāi)頭,也就是使用絕對(duì)路徑的方式,那么這個(gè)"/"到底代表什么呢?可以用如下的方式來(lái)記憶"/":如果"/"是給服務(wù)器用的,則代表當(dāng)前的web工程,如果"/"是給瀏覽器用的,則代表webapps目錄。
"/"代表當(dāng)前web工程的常見(jiàn)應(yīng)用場(chǎng)景①.ServletContext.getRealPath(String path)獲取資源的絕對(duì)路徑
/*** 1.ServletContext.getRealPath("/download/1.JPG")是用來(lái)獲取服務(wù)器上的某個(gè)資源,* 那么這個(gè)"/"就是給服務(wù)器用的,"/"此時(shí)代表的就是web工程 * ServletContext.getRealPath("/download/1.JPG")表示的就是讀取web工程下的download文件夾中的1.JPG這個(gè)資源* 只要明白了"/"代表的具體含義,就可以很快寫(xiě)出要訪(fǎng)問(wèn)的web資源的絕對(duì)路徑*/this.getServletContext().getRealPath("/download/1.JPG");②.在服務(wù)器端forward到其他頁(yè)面
/** * 2.forward * 客戶(hù)端請(qǐng)求某個(gè)web資源,服務(wù)器跳轉(zhuǎn)到另外一個(gè)web資源,這個(gè)forward也是給服務(wù)器用的, * 那么這個(gè)"/"就是給服務(wù)器用的,所以此時(shí)"/"代表的就是web工程 */ this.getServletContext().getRequestDispatcher("/index.jsp").forward(request, response);③.使用include指令或者<jsp:include>標(biāo)簽引入頁(yè)面
<%@include file="/jspfragments/head.jsp" %><jsp:include page="/jspfragments/demo.jsp" />"/"代表webapps目錄的常見(jiàn)應(yīng)用場(chǎng)景
①.使用sendRedirect實(shí)現(xiàn)請(qǐng)求重定向
response.sendRedirect("/JavaWeb_HttpServletResponse_Study_20140615/index.jsp");服務(wù)器發(fā)送一個(gè)URL地址給瀏覽器,瀏覽器拿到URL地址之后,再去請(qǐng)求服務(wù)器,所以這個(gè)"/"是給瀏覽器使用的,此時(shí)"/"代表的就是webapps目錄,"/JavaWeb_HttpServletResponse_Study_20140615/index.jsp"這個(gè)地址指的就是"webapps/JavaWeb_HttpServletResponse_Study_20140615/index.jsp"
response.sendRedirect("/項(xiàng)目名稱(chēng)/文件夾目錄/頁(yè)面");這種寫(xiě)法是將項(xiàng)目名稱(chēng)寫(xiě)死在程序中的做法,不靈活,萬(wàn)一哪天項(xiàng)目名稱(chēng)變了,此時(shí)就得改程序,所以推薦使用下面的靈活寫(xiě)法:
response.sendRedirect(request.getContextPath()+"/index.jsp");
request.getContextPath()獲取到的內(nèi)容就是"/JavaWeb_HttpServletResponse_Study_20140615",這樣就比較靈活了,使用request.getContextPath()代替"/項(xiàng)目名稱(chēng)",推薦使用這種方式,靈活方便!
②.使用超鏈接跳轉(zhuǎn)
<a href="${pageContext.request.contextPath}/index.jsp">跳轉(zhuǎn)到首頁(yè)</a>③.Form表單提交
<form action="${pageContext.request.contextPath}/servlet/CheckServlet" method="post"> <input type="submit" value="提交"></form>④.js腳本和CSS樣式文件的引用
<%--使用絕對(duì)路徑的方式引用js腳本--%><script type="text/Javascript" src="${pageContext.request.contextPath}/js/index.js"></script><%--${pageContext.request.contextPath}與request.getContextPath()寫(xiě)法是得到的效果是一樣的--%><script type="text/javascript" src="<%=request.getContextPath()%>/js/login.js"></script><%--使用絕對(duì)路徑的方式引用css樣式--%><link rel="stylesheet" href="${pageContext.request.contextPath}/css/index.css" type="text/css"/>response細(xì)節(jié)問(wèn)題
getOutputStream和getWriter方法分別用于得到輸出二進(jìn)制數(shù)據(jù)、輸出文本數(shù)據(jù)的ServletOuputStream、Printwriter對(duì)象。getOutputStream和getWriter這兩個(gè)方法互相排斥,調(diào)用了其中的任何一個(gè)方法后,就不能再調(diào)用另一方法。 Servlet程序向ServletOutputStream或PrintWriter對(duì)象中寫(xiě)入的數(shù)據(jù)將被Servlet引擎從response里面獲取,Servlet引擎將這些數(shù)據(jù)當(dāng)作響應(yīng)消息的正文,然后再與響應(yīng)狀態(tài)行和各響應(yīng)頭組合后輸出到客戶(hù)端。Serlvet的service方法結(jié)束后,Servlet引擎將檢查getWriter或getOutputStream方法返回的輸出流對(duì)象是否已經(jīng)調(diào)用過(guò)close方法,如果沒(méi)有,Servlet引擎將調(diào)用close方法關(guān)閉該輸出流對(duì)象。
我是天王蓋地虎的分割線(xiàn)參考:http://m.survivalescaperooms.com/xdp-gacl/p/3791993.html
新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注