您的位置:首页 > 其它

Servlet 转发、包含和重定向

2013-11-27 00:10 274 查看
首先说说转发和包含吧。Web应用在响应客户端的一个请求的时候,可能需要多个Web组件共同协作,才能完成最终的响应结果。在旧版本的ServletAPI中,ServletContext接口可以使用getServlet(name)根据参数给定的名字,返回相应的Servlet对象的引用,但是从ServletAPI2.1开始,这个方法就被废弃,如果再使用它时,总是会返回null,也就是说现在一个Servlet对象已经无法再直接获取另一个Servlet对象的引用了。

但是现在的Servlet规范为Web组件之间的协作提供了另外两种途径:
1、转发:请求转发,是获得请求的Servlet原组件对请求做了一定预处理之后,将请求转发给其他的Web组件(目标组件)来完成包括生成相应结果在内的后续操作;
2、包含:获得请求的Servlet元组件将其他Web组件(目标组件)生成的响应结果包含到自身的响应结果中去。
这两种方法具有以下共同特点:
1、原组件和目标组件处理的都是同一个客户请求,两者共享同一个ServletRequest和ServletResponse对象;
2、两者的目标组件都可以是Servlet、jsp或者html;
3、两者都依赖javax.servlet.RequestDispatcher接口,分别对应forward和include方法。

下面说一下如何获得这个RequestDispatcher对象。有两种方法:
1、使用ServletContext接口的getRequestDispatcher(String absolutePath)方法
2、使用ServletRequest接口的getRequestDispatcher(String relativeorabsolutePath)方法
两者区别就在路径上,前者必须绝对路径,必须以"/"符号开头,相对路径不以其作为开头。

和getAttribute和getParameter方法一起,讲讲如何使用转发,以及要注意什么,看看代码:

//使用context来获取RequestDispatcher
ServletContext context = getServletContext();
RequestDispatcher dispatcher = context.getRequestDispatcher("/output");
//使用request来获取
RequestDispatcher dispatcher = request.getRequestDispatcher("output");
//
//接下来可以对request和response先进行一些初始操作,但是response的操作在原组件是无效的,目标组件才有效
request.setAttribute("msg", message); //使用的是服务器间的参数设置,为什么呢?因为转发是服务器进行的操作,而不是客户端进行的操作。其实也没有太大关系啦,主要是要提一下setAttribute的事情
//对于response无效的事情,这里提一点,一般用response会获取它的Writer用来打印信息,如果要把原组件的操作生效,就要关闭response的writer,但是接下来的forword就会弹出IllegalStateException错误,因为关闭response的writer就已经提交了response,forward后的response是已提交状态,不能再次提交
//
//然后就是跳转了
dispatcher.forward(request, response);
//跳转之后的任何代码都不会被执行
请注意dispatcher.forward(request, response);方法的处理流程是这样的:
1)清空用于存放response响应正文的缓冲区,所以说在原组件中对response进行的操作都不会有作用;
2)如果目标的组件是Servlet或者jsp的时候,会调用他们的service方法,把该方法产生的响应结果发送到客户端;如果是静态的html文件,就直接读取文档数据并发送到客户端。

然后说说包含,和转发不一样的是,包含是由原组件返回的,包含的目标组件的内容会被添加到相应结果中,但是目标组件中对response进行的状态码和响应头的修改都会被忽略:

RequestDispatcher headDispatcher = context.getRequestDispatcher("/header.htm");
RequestDispatcher greetDispatcher = context.getRequestDispatcher("/greet");
RequestDispatcher footerDispatcher = context.getRequestDispatcher("/footer.htm");
xxxDispatcher.include(request, response);
。。。
。。。
out.println(。。。)
out.close;
该说说重定向了。重定向的代码比较简单,使用HttpServletResponse接口的sendRedirect(String location)方法。
重定向的运作流程是这样的:
1、客户在浏览器中输入特定的URL,访问服务器端某个组件;
2、服务器端接收请求,返回一个状态码为302的响应结果,让浏览器再请求另一个Web组件,这个组件可能在同一个Web服务器上,也可以不在一个服务器上;
3、浏览器收到响应结果后,立刻就自动请求另一个Web组件;
4、浏览器接收到另一个来自Web组件的响应结果。
Servlet重定向的特点是:
1、原组件生成的响应结果是不会被发送到客户端的,因为sendRedirect方法一律返回302,客户端最后收到的是目标Web组件的响应结果;
2、同转发一样,如果原组件在重定向之前提交了response,则sendRedirect方法会抛出IllegalStateException;
3、重定向之后的代码块也会被执行,当然这点forward也是;
4、原组件和目标组件不会共享同一个ServletRequest对象,所以不会共享请求范围内的共享数据,也就是说getAttribute两者是不同的;
5、目标组件可以不是当前Web服务器上的,可以是Internet上任意一个有效的网页。

最后说一下转发和重定向的区别:
1.转发在服务器端完成的;重定向是在客户端完成的

★2.转发的速度快;重定向速度慢3.转发的是同一次请求;重定向是两次不同请求★4.转发不会执行转发后的代码;重定向会执行重定向之后的代码★5.转发地址栏没有变化;重定向地址栏有变化6.转发必须是在同一台服务器下完成;重定向可以在不同的服务器下完成3
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: