读书人

javaee-RequestDispatcher 种相关源代

发布时间: 2012-07-04 19:33:55 作者: rapoo

javaee-RequestDispatcher 类相关源代码

1.RequestDispatcher

?

? ?RequestDispatcher对象可以通过ServletContext对象的getRequestDispatcher方法获取,如下。

?

 public abstract RequestDispatcher getRequestDispatcher(String paramString); public abstract RequestDispatcher getNamedDispatcher(String paramString);
?

关于RequestDispatcher的源代码(源代码反编译自apache-tomcat-6.0.16下的servlet-api.jar)如下所示:

?

?

package javax.servlet;import java.io.IOException;public abstract interface RequestDispatcher{  public abstract void forward(ServletRequest paramServletRequest, ServletResponse paramServletResponse)    throws javax.servlet.ServletException, IOException;  public abstract void include(ServletRequest paramServletRequest, ServletResponse paramServletResponse)    throws javax.servlet.ServletException, IOException;}
?

?

1.1 include

?

? ?include方法的使用示例如下:

?

package org.it315.ch5.inc;import java.io.IOException;import java.io.PrintWriter;import javax.servlet.RequestDispatcher;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;public class IncludingServlet extends HttpServlet {public void service(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {response.setContentType("text/html;charset=gb2312");// response.setContentType("text/html;charset=iso8859-1");PrintWriter out = response.getWriter();String china = "中国";out.println("china:" + china + "<br>");RequestDispatcher rd = getServletContext().getRequestDispatcher("/IncludedServlet?p1=" + china);out.println("start including:" + "<br>");rd.include(request, response);out.println("end including" + "<br>");}}
?

被引入(include)的servlet代码如下:

?

?

package org.it315.ch5.inc;import java.io.*;import javax.servlet.*;import javax.servlet.http.*;public class IncludedServlet extends HttpServlet {public void service(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {// response.setContentType("text/html;charset=GB2312");// response.setContentType("text/html;charset=iso8859-1");// response.setCharacterEncoding("GB2312");// response.setCharacterEncoding("iso8859-1");response.setContentType("text/html;charset=GB2312");//由于被IncludingServlet所include,所以不在起作用PrintWriter out = response.getWriter();out.println("中国" + "<br>");out.println("URI:(这里的request应该是调用者的request)" + request.getRequestURI()+ "<br>");out.println("QueryString(**注意这里**):" + request.getQueryString()+ "<br>");out.println("parameter p1:" + request.getParameter("p1") + "<br>");}}
?

?

对于的web.xml配置如下:

?

?

<!-- begin --><servlet><servlet-name>IncludedServlet</servlet-name><servlet-class>org.it315.ch5.inc.IncludedServlet</servlet-class></servlet><servlet-mapping><servlet-name>IncludedServlet</servlet-name><url-pattern>/ch5/IncludedServlet</url-pattern></servlet-mapping><!--end  --><!-- begin --><servlet><servlet-name>IncludingServlet</servlet-name><servlet-class>org.it315.ch5.inc.IncludingServlet</servlet-class></servlet><servlet-mapping><servlet-name>IncludingServlet</servlet-name><url-pattern>/ch5/IncludingServlet</url-pattern></servlet-mapping><!--end  -->
?

页面通过以下html访问即可。

?

?

 <a href="IncludingServlet" >including,此时被引入的servlet——IncludedServlet并获得不到参数。</a> <br/> <a href="IncludingServlet?p1=test测试" >including传参数,此时被引入的servlet类IncludedServlet可以获得到参数</a>

?

分析:

?

? ?为什么调用IncludingServlet,并在IncludingServlet中加入

?

RequestDispatcher rd = getServletContext().getRequestDispatcher("/IncludedServlet?p1=" + china);
??

?

? ?确在IncludingServlet中确得不到参数呢??(这也命中注定“<jsp:include page="../common/nav.jsp?flag=1" />”这种方式传递参数是不可行的)

?

? ?这是因为:?includingServlet 和IncludingServlet使用的是一个HttpServletRequest对象和一个IncludedServlet对象。上面的方法并没有重新创建一个Request请求,虽然他的外表极为相像

?

?

1.2?forward

?

? ? mvc控制器所仰仗的就是该方法,学习了forward和过滤器,相信就可以实现自己的mvc了。

?

forward的使用示例代码如下:

?

调用者

?

?

package org.it315.ch5.forward;import java.io.*;import javax.servlet.*;import javax.servlet.http.*;public class ForwardingServlet extends HttpServlet {public void service(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {response.setContentType("text/html;charset=UTF-8");// 禁止浏览器缓存,以免影响实验效果response.setDateHeader("Expires", 0);response.setHeader("Cache-Control", "no-cache");response.setHeader("Pragma", "no-cache");PrintWriter out = response.getWriter();// 下面这些输出,将会在调用rd.forward(request, response);方法后被web容器清空out.println("before forward");// 这些输错// 用于将缓冲区中的内容强制刷新到客户端,如果调用了rd.forward(request, response)则抛出异常。// response.flushBuffer();String china = "中国";// 不同于rd.include(request, response),该参数值可以成功的传递过去。另外,这里是ch5开头的,是从web应用路径径算起的。RequestDispatcher rd = getServletContext().getRequestDispatcher("/ch5/ForwardedServlet?p1="+ java.net.URLEncoder.encode(china, "GB2312"));/** * 与rd.include(request, response)不同,调用rd.forward(request, response)方法后, * web容器首先会清空“响应体内容” */rd.forward(request, response);// 由于之前调用了rd.forward(request, response)方法,下面的输出将会被忽略out.println("after forwarding");System.out.println("after forwarding");}}
?

?

被调用者

?

?

package org.it315.ch5.forward;import java.io.*;import javax.servlet.*;import javax.servlet.http.*;public class ForwardedServlet extends HttpServlet {public void service(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {/*** * 与被include不同,被forward时,下面的response.setContentType将会覆盖调用者的response. * setContentType。 * 不过前提是,在调用setContentType()方法之前没有调用response.getWriter()方法。 */response.setContentType("text/html;charset=GB2312");PrintWriter out = response.getWriter();/* * String basePath = request.getScheme() + "://"+ * request.getServerName() + ":" + request.getServerPort() + * request.getRequestURI(); out.println("<base href=\"" + basePath + * "\">"); */out.println("<a href='ForwardedServlet'>访问自己</a><br>");out.println("URI:" + request.getRequestURI() + "<br>");out.println("QueryString:" + request.getQueryString() + "<br>");out.println("URL:" + request.getRequestURL() + "<br>");String p1 = request.getParameter("p1");String chP1 = null;if (p1 != null) {chP1 = new String(p1.getBytes("iso8859-1"), "GB2312");}out.println("parameter p1:" + chP1 + "<br>");}}
?

?

对应的web.xml配置如下:

?

?

<!--ForwardTest  begin --><servlet><servlet-name>ForwardingServlet</servlet-name><servlet-class>org.it315.ch5.forward.ForwardingServlet</servlet-class></servlet><servlet-mapping><servlet-name>ForwardingServlet</servlet-name><url-pattern>/ch5/ForwardingServlet</url-pattern></servlet-mapping> <servlet><servlet-name>ForwardedServlet</servlet-name><servlet-class>org.it315.ch5.forward.ForwardedServlet</servlet-class></servlet><servlet-mapping><servlet-name>ForwardedServlet</servlet-name><url-pattern>/ch5/ForwardedServlet</url-pattern></servlet-mapping><!--ForwardTest  end  -->

?

?

访问链接:http://localhost:8080/Test_servlet/ForwardedServlet

?

?

1.3 include和forward的区别

?

1.3.1 相同点

? ? a.这两个方法都来自RequestDispatcher 类(嘿嘿,被人抽)

? ? b.这两个方法都是在服务端执行,这不同于HttpServletResponse中的sendRedirect(String paramString)方法(sendRedirect方法是通过发送“消息头”,让浏览器去重新指定的)。

? ? c.调用者和被调用者用的都是一组HttpServletResponse和HttpServletRequest对象,并未创建新的对象。

? ? d.访问路径没有变化

? ? e.都只能访问当前web应用中的资源,不同于HttpServletResponse中的sendRedirect(String paramString)。

?

?

?

?

?

1.3.2不同点

? ? a.include将是被调用的页面和调用的页面显示在一起;而forward后,只会显示被调用者的页面。

? ? b.include不会传递在?getRequestDispatcher?方法中添加的参数,如下:

?

RequestDispatcher rd = getServletContext().getRequestDispatcher("/*Servlet?p1=" + china);
?

不过你可以通过在调用者上加入参数以达到目的,前面有讲;而forward可以通过getRequestDispatcher?方法传递参数。

?

? ?c.include中,被调用的servlet将调用response.setContentType("text/html;charset=GB2312");等方法将不会起作用。forward中,被调用的servlet将调用response.setContentType("text/html;charset=GB2312");将会冲掉调用者servlet的设置(前提是调用者中没有使用response.getWriter();)。

?

? ?d.实际上,include中不调用PrintWriter out = response.getWriter();是一个很诧异的行为;而在forward中调用PrintWriter out = response.getWriter();确实一个很250的行为,毕竟forward主要用于跳转javaee-RequestDispatcher 种相关源代码

?

?

? ?e.访问路径差别,对于代码

?

RequestDispatcher rd = getServletContext().getRequestDispatcher("/ch5/testServlet);
?

? ?foward访问的是: web应用路径/ch5/testServlet。即:?

?

?

http://localhost:8080/Test_servlet/ch5/testServlet?

?

?

? ? 而include访问的路径则是:当前路径/ch5/testServlet。例如,如果调用者本身的路径为“http://localhost:8080/Test_servlet/ch5/IncludingServlet”。那么访问的路径将等同为:

?

?

http://localhost:8080/Test_servlet/ch5/ch5/testServlet?

?

参考:《深入体验Java_Web开发内幕-核心基础\》

?

?

?

……

读书人网 >软件架构设计

热点推荐