请求转送Request Dispatching

假如Servlet无法回应用户的请求,必要时可以将这个请求转交给其他Servlet处理,这个动作称为“Request Dispatching”(请求转送)。在SCWCD认证考试中,您应该注意本节所整理的两种“请求转送”方式,例如ServletRequest.getRequestDispatcher()与ServletContext.getRequestDispatcher()方法有何异同。

2.5.1  ServletRequest接口所提供的“请求转送”方法

n         ServletRequest.getRequestDispatcher()方法
在javax.servlet.ServletRequest接口内定义了一个getRequestDispatcher()方法,其方法标记式为:

public RequestDispatcher getRequestDispatcher(String path)

getRequestDispatcher()方法需传入一个字符串,表示被转送的Servlet位置(可以是绝对路径或相对路径)。此方法将回传一个RequestDispatcher对象。接着您可以利用javax.servlet.RequestDispatcher接口所定义的forward()或include()方法来转送HTTP请求。

笔者以实例来说明“请求转送”的基本步骤。

(1)       当Servlet A收到用户的HTTP请求时,准备将这个HTTP请求转送给Servlet B。

(2)       在Servlet A的doXXX()方法内调用getRequestDispatcher()方法,并指定Servlet B所在位置,例如:

String path = "/servlet/ServletB";

RequestDispatcher rd = request.getRequestDispatcher(path);


(3)       取得RequestDispatcher对象后,再利用forward()或include()方法来转送HTTP请求。无论调用哪个方法都必须传入HttpServletRequest与HttpServletResponse对象,例如:


rd.forward(request, response);


rd.include(request, response);


n         RequestDispatcher.forward()方法
RequestDispatcher接口所定义的forward()方法可以将HTTP请求转送给其他Web资源(例如Servlet、JSP或HTML)进行处理,并产生HTTP回应。

调用forward()方法时必须注意下列两点:

n           在HTTP回应被“确认”(committed)以前才能调用forward()方法(这里的“确认”是指将HTTP回应的内容主体送回用户端),否则将拋出IllegalStateException异常。

n           调用forward()方法后,原先存放在HttpResponse对象中的内容将会自动被清除(本章稍后的实例演练2-3将探讨此议题)。

n         RequestDispatcher.include()方法
RequestDispatcher接口的include()方法与forward()方法非常类似,惟一的不同在于:利用include()方法将HTTP请求转送给其他Servlet后,被调用的Servlet虽然可以处理这个HTTP请求,但是最后的主导权仍然是在原来的Servlet。换言之,被调用的Servlet如果产生任何HTTP回应,将会并入原来的HttpResponse对象。

2.5.2  ServletContext接口所提供的“请求转送”方法

n         ServletContext.getRequestDispatcher()方法
除了ServletRequest接口外,javax.servlet.ServletContext接口也提供一个getRequestDispatcher()方法,其方法标记式为:

public RequestDispatcher getRequestDispatcher(String path)

getRequestDispatcher()方法将回传一个RequestDispatcher对象,您可以用这个对象来转送HTTP请求。值得注意的是,传入ServletContext.getRequestDispatcher()方法的路径名称必须以 “/” 开头,这里的 “/” 代表Web应用程序的起始位置(context root)。

以下是两个合法的ServletContext.getRequestDispatcher()使用范例。


String path = "/Servlet/ServletB";

RequestDispatcher rd = getServletContext().getRequestDispatcher(path);

rd.forward(request, response);




String path = "/Servlet/ServletB";

ServletContext sc = getServletContext();

RequestDispatcher rd = sc.getRequestDispatcher(path);

rd.forward(request, response);




下面这个范例却是不合法的。

String path = "../index.html";

RequestDispatcher rd = getServletContext().getRequestDispatcher(path);

rd.forward(request, response);




在第三个范例中,path变量设定为“../index.html”,因此无法调用ServletContext接口的getRequestDispatcher()方法。在这种情况下,您必须改用ServletRequest接口所提供的getRequestDispatcher()方法,例如:


String path = "../index.html";

RequestDispatcher rd = request.getRequestDispatcher(path);

rd.forward(request, response);




n         getNamedDispatcher()方法
ServletContext接口还提供了另一个getNamedDispatcher()方法,其方法标记式为:

public RequestDispatcher getNamedDispatcher(String name)


此方法与getRequestDispatcher()方法类似,也会传回一个RequestDispatcher对象,由此可转送HTTP请求。不同之处在于:传入getNamedDispatcher()方法的字符串并非Servlet或JSP的路径,而是其名称。

以下是getNamedDispatcher()方法的使用范例:



ServletContext sc = getServletContext();

RequestDispatcher rd = sc.getNamedDispatcher("ServletB");

rd.forward(request, response);



上例准备将HTTP请求转送给ServletB,问题是一个Web应用程序说不定包含好几个ServletB(位于不同组件包内),为此,您可以在web.xml内定义ServletB究竟是哪个类或是位于哪个组件包内,例如:



<servlet>

<servlet-name>ServletB</servlet-name>

<servlet-class>scwcd.ch02.ServletB</servlet-class>

</servlet>




这样一来,getNamedDispatcher()方法才能确定ServletB的真实位置为scwcd.ch02.ServletB,然后传回RequestDispatcher对象。关于此议题,在本书第3章还会深入讨论。

你可能感兴趣的:(html,Web,jsp,servlet)