Servlet的service()方法是由Servlet容器来调用的,用户不能在一个Servlet对象中直接调用另一个Servlet对象的servie()方法,因为一个Servlet对象无法得到另一个Servlet对象的引用。
但是web应用在响应客户端的一个请求时,有可能响应过程很复杂,需要多个web组件共同协作(参见上一节——动态生成图像)。尽管Servlet对象无法直接调用另一个Servlet对象的service()方法,但Servlet规范为Web组件之间的协作提供了两种途径:
Servlet(源组件)先对客户请求做一些预处理操作,然后把请求转发给其他Web组件(目标组件)来完成包括生成响应结果在内的后续操作;
Servlet(源组件)把其他Web组件(目标组件)生成的响应结果包含到自身的响应结果中;
该接口表示请求分发器,
Modifier and Type | Method and Description |
---|---|
void |
forward(ServletRequest request, ServletResponse response)
Forwards a request from a servlet to another resource (servlet, JSP file, or HTML file) on the server.
|
void |
include(ServletRequest request, ServletResponse response)
Includes the content of a resource (servlet, JSP page, HTML file) in the response.
|
当Servlet源组件调用RequestDispatcher的forward或include方法时,都要把当前的ServletRequest对象和ServletResponse对象作为参数传给forward或include方法,这使得源组件和目标组件共享同一个ServletRequest对象和ServletResponse对象。
Servlet可以通过两个两种方式得到RequestDispatcher对象:
如下实例:源servlet —— ForwardSourceServlet;目标servlet —— ForwardDestinationServlet;
package com.gof.test.servlet; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.http.HttpServlet; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.ServletContext; import javax.servlet.RequestDispatcher; public class ForwardSourceServlet extends HttpServlet { /** * */ private static final long serialVersionUID = 7412912720309987937L; @Override public void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { String username = req.getParameter("username"); String message = null; if (username == null){ message = "Please input username."; }else{ message = "Hello " + username; } // add attribute to request req.setAttribute("msg", message); // forward the request to ForwardDestinationServlet ServletContext context = getServletContext(); RequestDispatcher dispatcher = context.getRequestDispatcher("/forwarddest"); // try to output something into response PrintWriter out = res.getWriter(); out.println("Output from ForwardSourceServlet before forwarding request"); if (dispatcher != null){ dispatcher.forward(req, res); } out.println("Output from ForwardSourceServlet after forwarding request"); out.close(); } }
package com.gof.test.servlet; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.GenericServlet; import javax.servlet.RequestDispatcher; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class ForwardDestinationServlet extends HttpServlet { /** * */ private static final long serialVersionUID = 7412912720309987937L; @Override public void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { String message = (String)req.getAttribute("msg"); PrintWriter out = res.getWriter(); out.println(message); out.close(); } }
在web.xml中注册:
<!-- Forward request --> <!-- test url = http://localhost:8080/base-webapp/forwardsrc?username=New User --> <servlet> <servlet-name>forwardsrc</servlet-name> <servlet-class>com.gof.test.servlet.ForwardSourceServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>forwardsrc</servlet-name> <url-pattern>/forwardsrc</url-pattern> </servlet-mapping> <servlet> <servlet-name>forwarddest</servlet-name> <servlet-class>com.gof.test.servlet.ForwardDestinationServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>forwarddest</servlet-name> <url-pattern>/forwarddest</url-pattern> </servlet-mapping>
访问如下URL:
http://localhost:8080/base-webapp/forwardsrc?username=New User
修改1:
在调用forward方法之前调用flush()/close()方法,将会抛出一个IllegalStateException异常;同时,目标组件中的内容不会输出:只会输出源组件前面输出的内容:
修改2:
将获取RequestDispatcher的方法参数path改为“forwarddest”,抛出IllegalArgumentException,提示参数没有以“/”开头。
修改3:
将获取RequestDispatcher的方法改为:
RequestDispatcher dispatcher = req.getRequestDispatcher("forwarddest");
可以正常运行。
如下示例:源组件 —— IncludeSourceServlet;目标组件 —— includeheader.html,IncludeDestinationServlet,includefooter.html:
package com.gof.test.servlet; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.http.HttpServlet; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.ServletContext; import javax.servlet.RequestDispatcher; public class IncludeSourceServlet extends HttpServlet { protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException{ resp.setContentType("text/html"); PrintWriter out = resp.getWriter(); out.println("<html><header><title>Include Test</title></header>"); out.println("<body>"); ServletContext context = getServletContext(); RequestDispatcher headDispatcher = context.getRequestDispatcher("/includeheader.html"); RequestDispatcher bodyDispatcher = context.getRequestDispatcher("/includedest"); RequestDispatcher footDispatcher = context.getRequestDispatcher("/includefooter.html"); headDispatcher.include(req, resp); bodyDispatcher.include(req, resp); footDispatcher.include(req, resp); out.println("</body></html>"); out.close(); } }
includeheader.html
<br/> This is from includeheader.html <br/>
package com.gof.test.servlet; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.http.HttpServlet; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.ServletContext; import javax.servlet.RequestDispatcher; public class IncludeDestinationServlet extends HttpServlet { protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException{ PrintWriter out = resp.getWriter(); out.println("<br/>This is from IncludeDestinationServlet<br/>"); } }
includefooter.html
<br/> This is from includefooter.html <br/>
在web.xml中注册:
<!-- Include request --> <!-- test url = http://localhost:8080/base-webapp/includesrc --> <servlet> <servlet-name>includesrc</servlet-name> <servlet-class>com.gof.test.servlet.IncludeSourceServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>includesrc</servlet-name> <url-pattern>/includesrc</url-pattern> </servlet-mapping> <servlet> <servlet-name>includedest</servlet-name> <servlet-class>com.gof.test.servlet.IncludeDestinationServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>includedest</servlet-name> <url-pattern>/includedest</url-pattern> </servlet-mapping>
在浏览器中访问如下的URL:
http://localhost:8080/base-webapp/includesrc
结果如下: