转发

Web应用在响应客户端的一个请求时,有可能响应过程很复杂,需要多个Web组件共同协作,才能生成响应结果。此时,可以使用转发技术。

转发的理解:在同一个web应用内部,一个组件将未完成的任务转发给另外一个组件,由另外一个组件进行后续的处理并生成响应结果。

最常见的情况是一个Servlet完成了业务逻辑的处理,将数据展现交给一个JSP来完成。

转发的编程

1. request.setAttribute(String name,Object obj) //绑定要转发的数据
2. request.getRequestDispatcher(String path).forward(request,response) //转发
3. request.getAttribute(String name) //在另外一个组件中取出前一个web组件带过来的数据
转发的特点

1. 一件事情未完成
2. 转发的目的地,只能是同一个应用内部
3. 转发时,浏览器地址栏的地址没有发生变化
4. 转发涉及的组件之间,可以共享同一个request和response.

下面简单地以两个Servlet组件之间的转发为例:

CheckServlet转发到OutputServlet,为两个Servlet映射的url分别为check和output,代码如下:

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);//绑定数据
		
		PrintWriter pw=response.getWriter();
		
		RequestDispatcher rd=request.getRequestDispatcher("/output");//得到转发器
		
		pw.println("output from CheckServlet before forwarding request");
		System.out.println("output from CheckServlet before forwarding request");
		
		rd.forward(request, response);
		
		pw.println("output from CheckServlet after forwarding request");
		System.out.println("output from CheckServlet after forwarding request");
		
	}

}

public class OutputServlet extends HttpServlet {

	public void service(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		String message=(String)request.getAttribute("msg");
		PrintWriter pw=response.getWriter();
		
		pw.println(message);
		pw.close();
	}

}
在浏览器地址栏里输入:http://localhost:8080/dispatcher/check,回车,得到:

输出的内容只有please input username。这就是说,CheckServlet里的

pw.println("output from CheckServlet before forwarding request");
rd.forward(request, response);
pw.println("output from CheckServlet after forwarding request");
pw所生成的响应是不会发送到客户端的。即只有最后的目标组件生成的响应才会被发送到客户端。

我们再来看看CheckServlet里的这部分代码:

pw.println("output from CheckServlet before forwarding request");
System.out.println("output from CheckServlet before forwarding request");
		
rd.forward(request, response);
		
pw.println("output from CheckServlet after forwarding request");
System.out.println("output from CheckServlet after forwarding request");


我们同时看看刚才的访问时控制台输出的内容:


所以可以知道,源组件CheckServlet在rd.forward(request,response)之后的代码也会被执行。事实上,这一点和重定向是一致的。重定向中,在response.sendRedirect(String location)之后的代码也会被执行。

我们来看看rd.forward(request,response)方法的处理流程:

1. 清空用于存放响应正文数据的缓冲区
2. 如果目标组件为Servlet或JSP,就调用他们的service方法,把该方法产生的响应结果发送到客户端;如果目标组件为文件系统中的静态html文件,就读取文档中的数据并把它发送到客户端。
从rd.forward(request,response)方法的处理流程可以看出,转发具有以下特点:

1. 由于forward方法先清空用于存放响应正文数据的缓冲区,因此Servlet源组件生成的响应结果不会被发送到客户端,只有目标组件生成的响应结果才会被发送到客户端。
2. 如果源组件在进行转发之前,已经提交了响应结果(例如调用ServletResponse的flushBuffer()方法,或者调用与ServletResponse关联的输出流的close()方法),那么forward方法会抛出IllegalStateException.为了避免该异常,不应该在源组件中提交响应结果。





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值