Servlet的學習之Response響應對象(3)


  本篇來說明響應對象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中傳入的必須是使用字節流才能傳輸的數據,請查驗相關解決方案。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM