您的位置:首页 > 编程语言 > Java开发

【Java.Web】Servlet —— 请求的转发和包含

2014-10-03 03:43 811 查看

请求的转发和包含

Servlet的service()方法是由Servlet容器来调用的,用户不能在一个Servlet对象中直接调用另一个Servlet对象的servie()方法,因为一个Servlet对象无法得到另一个Servlet对象的引用

但是web应用在响应客户端的一个请求时,有可能响应过程很复杂,需要多个web组件共同协作(参见上一节——动态生成图像)。尽管Servlet对象无法直接调用另一个Servlet对象的service()方法,但Servlet规范为Web组件之间的协作提供了两种途径:

请求转发

Servlet(源组件)先对客户请求做一些预处理操作,然后把请求转发给其他Web组件(目标组件)来完成包括生成响应结果在内的后续操作;

请求包含

Servlet(源组件)把其他Web组件(目标组件)生成的响应结果包含到自身的响应结果中;

请求转发 V.S. 请求包含

对于转发和包含,源组件和目标组件处理的都是同一个客户请求;源组件和目标组件共享同一个ServletRequest和ServletResponse对象
对于转发和包含,目标组件都可以为Servlet,JSP或HTML文档
对于转发和包含,都依赖与javax.servlet.RequestDispatcher接口

javax.servlet.RequestDispatcher接口

该接口表示请求分发器,

Methods

Modifier and TypeMethod 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.
forward()方法

forward()方法的处理流程如下:(1)清空用于存放响应正文数据的缓冲区;(2)如果目标组件为Servlet或JSP,就调用它们的service()方法,把该方法产生的响应结果发送到客户端,如果目标组件为文件系统中的静态html文档,就读去文档中的数据并把它发送到客户端。
由于forward()方法先清空用于存放响应正文数据的缓冲区,因此servlet源组件生成的响应结果不会被发送到客户端,只有目标组件生成的结果才会被发送到客户端;
如果源组件在进行请求转发之前,已经提交了响应结果(例如调用了flushBuffer方法,或者close()方法),那么forward()方法会抛出IllegalStateException。为了避免该异常,不应该在源组件中提交响应结果。

include()方法

包含与转发相比,源组件与被包含的目标组件的输出数据都会被添加到响应结果中
在目标组件中对响应状态代码或者响应头所做的修改都会被忽略

当Servlet源组件调用RequestDispatcher的forward或include方法时,都要把当前的ServletRequest对象和ServletResponse对象作为参数传给forward或include方法,这使得源组件和目标组件共享同一个ServletRequest对象和ServletResponse对象。

Servlet可以通过两个两种方式得到RequestDispatcher对象:

调用ServletContext的getRequestDispatcher(String path)方法,path参数指定目标组件的路径

path参数必须为绝对路径;绝对路径,就是以符号“/”开头的路径,“/”表示当前Web应用的URL路口

调用ServletRequest的getRequestDispatcher(String path)方法,path参数指定目标组件的路径

path参数既可以为绝对路径,也可以为相对路径;相对路径,就是相对于当前Servlet组件的路径,不以“/”开头

请求转发

如下实例:源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


结果如下:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: