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()方法會拋出異常。