當(dāng)一個(gè) Web 資源收到客戶端的請(qǐng)求后,如果希望服務(wù)器通知另外一個(gè)資源處理請(qǐng)求,那么這時(shí)可以通過(guò) RequestDispatcher 接口的實(shí)例對(duì)象實(shí)現(xiàn)。ServletRequest 接口中定義了一個(gè)獲取 RequestDispatcher 對(duì)象的方法,如表 1 所示。
表 1 獲取 RequestDispatcher 對(duì)象的方法
|
方法聲明 |
功能描述 |
|---|---|
|
RequestDispatcher getRequestDispatcher (String path) |
返回封裝了某條路徑所指定資源的 RequestDispatcher 對(duì)象。其中,參數(shù) path 必須以“/”開頭,用于表示當(dāng)前 Web 應(yīng)用的根目錄。需要注意的是,WEB-INF 目錄中的內(nèi)容對(duì) RequestDispatcher 對(duì)象也是可見的。因此,傳遞給 getRequestDispatcher(String path) 方法的資源可以是 WEB-INF 目錄中的文件 |
獲取到 RequestDispatcher 對(duì)象后,最重要的工作就是通知其他 Web 資源處理當(dāng)前的 Servlet 請(qǐng)求,為此,RequestDispatcher 接口定義了兩個(gè)相關(guān)方法,如表 2 所示。
表 2 RequestDispatcher 接口的方法
|
方法聲明 |
功能描述 |
|---|---|
|
forward(ServletRequest request,ServletResponse response) |
該方法用于將請(qǐng)求從一個(gè) Servlet 傳遞給另一個(gè) Web 資源。在 Servlet 中,可以對(duì)請(qǐng)求做一個(gè)初步處理,然后通過(guò)調(diào)用這個(gè)方法,將請(qǐng)求傳遞給其他資源進(jìn)行響應(yīng)。需要注意的是,該方法必須在響應(yīng)提交給客戶端之前被調(diào)用,否則將拋出 IllegalStateException 異常 |
|
include(ServletRequest request,ServletResponse response) |
該方法用于將其他的資源作為當(dāng)前響應(yīng)內(nèi)容包含進(jìn)來(lái) |
請(qǐng)求轉(zhuǎn)發(fā)
在 RequestDispatcher 接口中,forward() 方法可以實(shí)現(xiàn)請(qǐng)求轉(zhuǎn)發(fā),include() 方法可以實(shí)現(xiàn)請(qǐng)求包含,本節(jié)將以請(qǐng)求轉(zhuǎn)發(fā)為例,講解 forward() 方法的使用。
在 Servlet 中,如果當(dāng)前 Web 資源不想處理請(qǐng)求,則可以通過(guò) forward() 方法將當(dāng)前請(qǐng)求傳遞給其他的 Web 資源進(jìn)行處理,這種方式稱為請(qǐng)求轉(zhuǎn)發(fā)。請(qǐng)求轉(zhuǎn)發(fā)的工作原理如圖 1 所示。
從圖 1 中可以看出,當(dāng)客戶端訪問 Servlet1 時(shí),可以通過(guò) forward() 方法將請(qǐng)求轉(zhuǎn)發(fā)給其他 Web 資源,其他 Web 資源處理完請(qǐng)求后,直接將響應(yīng)結(jié)果返回到客戶端。
了解了 forward() 方法的工作原理后,下面通過(guò)案例演示 forward() 方法的使用。在 servletDemo02 項(xiàng)目的 com.mengma.request 包中創(chuàng)建一個(gè)名為 RequestForwardServlet 的 Servlet 類,該類使用 forword() 方法將請(qǐng)求轉(zhuǎn)發(fā)到一個(gè)新的 Servlet 頁(yè)面,如下所示。

圖 1 forward() 方法的工作原理
package com.mengma.servlet;
import java.io.IOException;
import javax.servlet.*;
import javax.servlet.http.*;
public class RequestForwardServlet extends HttpServlet {
public void doGet(HttpServletRequest request,HttpServletResponse response)throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
request.setAttribute("username", "張三"); // 將數(shù)據(jù)存儲(chǔ)到request對(duì)象中
RequestDispatcher dispatcher = request.getRequestDispatcher("/ResultServlet");
dispatcher.forward(request,response);
}
public void doPost(HttpServletRequest request,HttpServletResponse response)throws ServletException,IOException {
doGet(request,response);
}
}
在 RequestForwardServlet 中,通過(guò)使用 forward() 方法,將當(dāng)前 Servlet 的請(qǐng)求轉(zhuǎn)發(fā)到 ResultServlet 頁(yè)面,在 com.mengma.request 包中編寫一個(gè)名為 ResultServlet 的 Servlet 類,該類用于獲取 RequestForwardServlet 類中存儲(chǔ)在 request 對(duì)象中的數(shù)據(jù)并輸出,ResultServlet 類的代碼實(shí)現(xiàn)如下所示。
package com.mengma.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class ResultServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
PrintWriter out = response.getWriter();
String username = (String) request.getAttribute("username");
if (username != null) {
out.println("用戶名:" + username + "<br/>");
}
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
啟動(dòng) Tomcat 服務(wù)器,在瀏覽器的地址欄中輸入地址 http://localhost:8080/servletDemo02/RequestForwardServlet 訪問 RequestForwardServlet,瀏覽器的顯示結(jié)果如圖 2 所示。

圖 2 運(yùn)行結(jié)果
從圖 2 中可以看出,地址欄中顯示的仍然是 RequestForwardServlet 的請(qǐng)求路徑,但是瀏覽器卻顯示出了 ResultServlet 中要輸出的內(nèi)容。這是因?yàn)檎?qǐng)求轉(zhuǎn)發(fā)是發(fā)生在服務(wù)器內(nèi)部的行為,從 RequestForwardServlet 到 ResultServlet 屬于一次請(qǐng)求,在一次請(qǐng)求中是可以使用 request 屬性進(jìn)行數(shù)據(jù)共享的。