IT兄弟連 JavaWeb教程 請求轉發案例
- 2019 年 10 月 5 日
- 筆記
版權聲明:本文為部落客原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接和本聲明。
本文鏈接:https://blog.csdn.net/ITXDL123/article/details/90089723
CheckServlet類與OutputServlet類之間為請求轉發關係。在web.xml文件中,為CheckServlet映射的URL為"/check",為OutputServlet映射的URL為"/outout"。
public class CheckServlet extends HttpServlet{
public void service(HttpServletRequest request,
HttpServletResponse response)throws ServletException,IOException{
String username = request.getParameter("username");
String message = null;
if(username == null){
message = "Please input username.";
}else{
message = "Hello," + username;
}
// request.setAttribute("msg",message);
// servletContext context = getServletContext();
RequestDispatcher dispatcher =
request.getRequestDispatcher ("output");
PrintWriter out = response.getWriter();
out.println("Output from CheckServlet before forwarding request");
System.out.println(
"Output from CheckServlet before forwarding request");
// out.close();
dispatcher.forward(request,response);
out.println("Output from CheckServlet after forward request.");
System.out.println(
"Output from CheckServlet after forwarding request.");
}
}
public class OutputServlet extends HttpServlet{
public void service(HttpServletRequest request,
HttpServletResponse response)thrwos ServletException,IOException{
String message = (String)request.getAttribute("msg");
PrintWriter out = response.getWriter();
out.println(message);
out.close();
}
}
CheckServlet先檢查客戶端是否提供了username請求參數,再根據此生成一條消息,用變數message表示,接下來把這條消息作為屬性保存到ServletRequest對象中,再把請求轉發給OutputServlet。與請求轉發相關的程式碼為:
RequestDispatcher dispatcher = request.getRequestDispatcher("output");
dispatcher.forward(request,response);
以上dispatcher.forward(request,response)方法的處理流程如下。
● 清空用於存放響應正文數據的緩衝區。
● 如果目標組件為Servlet或JSP,就調用它們的service()方法,把該方法產生的響應結果發送到客戶端;如果目標組件為文件系統中的靜態HTML文檔,就讀取文檔中的數據並把它發送到客戶端。

轉發流程圖
從Dispatcher.forward(request,response)方法的處理流程可以看出,請求轉發具有以下特點。
由於forward()方法先清空用於存放響應正文數據的緩衝區,因此Servlet源組件生成的響應結果不會被發送到客戶端,自由目標組件生成的響應結果才會被發送到客戶端。
如果源組件在進行請求轉發之前,已經提交了響應結果(例如調用ServletResponse的flushBuffer()方法,或者調用與ServletResponse關聯的輸出流的close()方法),那麼forward()方法會拋出IllegalStateException。為了避免該異常,不應該在源組件中提交響應結果。
案例中的OutputServlet類作為轉發目標組件,先從ServletRequest對象中讀取msg屬性,然後把它作為響應結果發送到客戶端。下面按照如下步驟演示本案例:
1.通過瀏覽器訪問http://localhost:8080/helloapp/check,其中helloapp是項目名稱,/check是請求路徑,瀏覽器中會出現"Please input username"。
CheckServlet負責生成消息,而OutputServlet負責把消息發送給客戶端。由此可見,CheckServlet與OutputServlet既分工明確,各行其職,又緊密協作,來響應同一個客戶請求。
CheckServlet在調用dispatcher.forward(request,response)方法之前和之後,都試圖向瀏覽器以及伺服器的控制台輸出一些數據:
out.println("Output from CheckServlet before forwarding request");
System.out.println("Output from CheckServlet before forwarding request");
dispatcher.forward(request,response);
out.println("Output from CheckServlet after forward request.");
System.out.println("Output from CheckServlet after forwarding request.");
從瀏覽器中顯示的頁面可以看出,CheckServlet作為源組件,它所生成的響應結果不會被發送到客戶端。
此外,在Tomcat伺服器的控制台,會顯示調用forward()方法之前及之後的System.out.println()語句的列印結果。由此可見,在Servlet源組件中調用forward()方法之後的程式碼也會被執行。
2.修改CheckServlet類的程式碼,在CheckServlet類中調用forward()方法之前先關閉輸出流:
out.close();
dispatcher.forward(request,response);
再次通過瀏覽器訪問CheckServlet,瀏覽器端僅接收到了由CheckServlet輸出的內容:
Output from CheckServlet before forward request;
這是因為CheckServlet的out.close()方法先把CheckServlet輸出的內容提交給客戶端,然後再關閉輸出流。接下來調用forward()方法會拋出異常。