本篇來說明響應對象HttpServletResponse對象的最后一點內容。
首先來看響應對象控制瀏覽器定時刷新,在我的web應用【myservlet】中創建Servlet,在該Servlet中設置響應頭,定時刷新的代碼很簡單:
response.setHeader("refresh", "3 "); //3秒刷新一次
就可告知瀏覽器3秒刷新一次網頁。當然“Refresh”響應頭還是可以定時跳轉到指定頁面,如下代碼:
response.setHeader("refresh", "3;url='/myservlet/index.jsp'");
將會在訪問我這個Servlet的3秒后訪問我的【myservlet】web應用下的index.jsp資源。
之前說過,使用<meta>標簽可以模擬響應頭,同樣在這里可以使用Servlet向客戶端寫數據時將<meta>標簽寫入響應數據實體,由瀏覽器解析后再來控制:
1 String data = "銀魂"; 2 response.setContentType("text/html;charset=UTF-8"); 3 response.getWriter().write("<meta http-equiv='refresh' content='3;url=/myservlet/index.jsp' >"); 4 response.getWriter().write(data);
這里請注意:在向響應對象寫入任何數據之前,請先設置好使用的編碼表,如果在寫入數據之后再設置編碼表則無效,例如下面代碼:
1 String data = "銀魂"; 2 response.getWriter().write(data); 3 response.setContentType("text/html;charset=UTF-8");
通過查看HttpWathch可以知道,編碼表並沒有設置成功:
把設置編碼表的代碼放置在向響應對象寫入數據也是不行的,如下:
1 String data = "銀魂"; 2 response.getWriter().write("<meta http-equiv='refresh' content='3;url=/myservlet/index.jsp' >"); 3 response.setContentType("text/html;charset=UTF-8"); 4 response.getWriter().write(data);
這樣也會設置編碼表無效,造成中文亂碼問題,所以在向響應對象寫入任何數據之前請確保先將編碼表設置好。
請求重定向:之前在http協議中學習了響應碼302和“Location”響應頭可以設置請求重定向。
一個簡單的代碼示例(web工程名為【myservlet】):
1 response.setStatus(HttpServletResponse.SC_MOVED_TEMPORARILY); //302狀態碼 2 response.setHeader("location", "/myservlet/index.jsp");
對於不太熟悉HTTP協議的編程人員來說,當然還有更快捷的方式:
1 response.sendRedirect("/myservlet/index.jsp");
驗證:在瀏覽器中的地址欄中鍵入該Servlet的地址,瀏覽器則是會跳轉至該web目錄下的index.jsp,這個可以從瀏覽器地址欄上看出。
關於請求重定向中的細節:
一次請求重定向會向服務器發送兩次請求。也就是說會產生兩次response響應對象和request請求對象;同時瀏覽器的地址欄是會發生變化的,URL將跳轉到重定向后的頁面地址。這點和轉發不同(在《Servlet的學習(五)》中說過)。
最后再回到response響應對象的getOutputStream方法和getWriter方法,這兩個方法在《Servlet的學習(七)》中已經詳細介紹了解決中文亂碼問題,那么現在我們還需要注意的是:getOutputStream方法和getWriter方法這兩個方法相互排斥,不能同時使用。否則會出現如下問題:
也許大家會瞧不起這個問題,認為不就是在一個Servlet中不要同時使用字節流和字符流嘛,注意下就好了。
問題當然不會這么簡單,比如在轉發中使用不同的IO流還是會出現這種問題的:
假設我的【myservlet】這個web工程中有兩個Servlet:ServletResponse1和ServletResponse2。
在ServletResponse1中的代碼為:
1 response.getWriter(); 2 RequestDispatcher dispatcher = this.getServletContext().getRequestDispatcher("/WEB-INF/classes/ServletResponse2"); 3 dispatcher.forward(request, response);
在ServletResponse2中的代碼為:
1 response.getOutputStream();
那么結果是直接部署出錯:
在ServletResponse1中將Response對象傳遞給ServletResponse2中,本身Response就已經調用了獲取Writer對象的方法,因此不能再在ServletResponse2中獲取OutputStream對象,所以在做轉發時要特別注意獲得IO流對象。
而將Servlet調用getOutputStream()方法后再轉發給JSP文件也是會出錯的
比如在ServletResponse1中代碼為:
1 OutputStream out = response.getOutputStream(); 2 RequestDispatcher dispatcher = this.getServletContext().getRequestDispatcher("/index.jsp"); 3 dispatcher.forward(request, response);
而訪問這個Servlet會看到:
這是因為在Servlet向JSP中寫入數據時默認使用了getWriter()方法獲取字符流,然后向JSP中寫入數據,這時如果我們在轉發JSP之前的Servlet再使用getOutputStream必然會產生沖突。如果想向JSP中傳入的必須是使用字節流才能傳輸的數據,請查驗相關解決方案。