RequestDispatcher简介

RequestDispatcher 代表请求的派发者。它有2个动作:forward 和 include 。客户端对于任何一个请求,可以根据业务逻辑需要,选择不同的处理办法:
1、请求的是谁,谁就自己处理并响应,例如请求的是一个html,则web浏览器显示的就是这个HTML的内容。
2、使用RequestDispatcher让其它的资源参与进来,协同完成的响应,这就是RequestDispatcher的主要作用。
 
RequestDispatcher 有一个特点,就是浏览器上显示的URL是最先请求的目标资源的URL,不会因为使用了forward、include方法而改变。因此forward和include的调用对于用户来说是透明的。
 
RequestDispatcher 实质是一个接口,有2个方法分别代表这2个动作。下面一 一介绍。
 
  1. public interface RequestDispatcher
  2. {
  3. public void forward(ServletRequest request, ServletResponse response)
  4. throws ServletException, IOException;
  5.  
  6. public void include(ServletRequest request, ServletResponse response)
  7. throws ServletException, IOException;
  8. }

RequestDispatcher.forward(request, response)

    这个方法将请求从一个 Servlet or JSP目标资源 上 转发到服务器上的另一个资源(servlet、JSP 文件或 HTML 文件,这些资源必须是当前Web上下文中的),让其它的资源去生成响应数据。
例如用户请求的是目标资源A,A接受到请求后,转发到B,真正产生响应数据是被转发的资源B,而A只是起个引导转发作用。浏览器的地址栏不会变,依然是A的URL。 
    这个方法可以允许被请求的目标资源做一些准备工作后,再让转发的资源去响应请求。例如下面的例子1。
 
注意事项:   
1、在目标资源中调用forward方法时,必须保证此响应没有提交。也就是不要使用 ServletResponse 对象的输出流对象,因为即便你写入了数据到响应缓冲区,最后也会被清空,如果缓冲区数据被刷新提交(out.flush),还会抛出IllegalStateException异常。
 
2、对于forward方法传递的request对象:虽然我们从调用上看,好像是将request对象传递给转动的资源上去了,但是我发现目标资源使用的request对象和转发的资源使用的request对象不是同一个request对象,因为分别从这2个request中获取RequestURL,发现是不一样的。但是在目标资源request提取的Paramter 和 Attribute   ,在转发后的资源的request对象中,依然都可以提取到,且是相同的。所以,二者只是在请求路径相关的属性上不同,其它API调用返回的都是一样的。
 
3、在forward语句的前后,都不应该有响应输出的语句,应该会被忽略。
 
 
例子1:一个简单的 MVC演示。Servlet充当控制器,转发到view层的jsp。 
User.java
  1. public class User{
  2. private String name;
  3. private int age;
  4. public String getName(){
  5. return name ;
  6. }
  7. public void setName( String name ){
  8. this .name = name ;
  9. }
  10. public int getAge() {
  11. return age ;
  12. }
  13. public void setAge( int age ){
  14. this .age = age ;
  15. }
  16. }

UsersServlet.java

  1. public class UsersServlet extends HttpServlet {
  2. private static final long serialVersionUID = 1L ;
  3.  
  4. protected void doGet (HttpServletRequest request, HttpServletResponse response) throws ServletException , IOException {
  5. /*****************一般实际开发这些用户数据都是从数据库查出来的*********/
  6. List <User > users = new ArrayList <> ();
  7. User u1 = new User () ;
  8. u1 .setAge ( 20) ;
  9. u1 .setName ( "Bob") ;
  10. User u2 = new User () ;
  11. u2 .setAge ( 21) ;
  12. u2 .setName ( "Tony") ;
  13. users .add ( u1) ;
  14. users .add ( u2) ;
  15. /*********************************************/
  16. request .setAttribute ( "users", users) ; //对request 进制预处理准备工作
  17. request .getRequestDispatcher ( "users.jsp").forward( request , response );//转发到users.jsp,让他去具体响应
  1. }
    }
 
users.jsp
  1. <%@ page contentType= "text/html; charset=UTF-8" pageEncoding ="UTF-8" trimDirectiveWhitespaces= "true"
  2. session ="true" %>
  3. <%@ taglib prefix= "c" uri = "http://java.sun.com/jsp/jstl/core" %>
  4.  
  5. <!DOCTYPE html>
  6. < html>
  7. <head>
  8. <meta http-equiv = "Content-Type" content ="text/html; charset=UTF-8">
  9. <title> 用户列表</title>
  10. </head>
  11. <body>
  12.  
  13. <p> -----------------转发到的资源users.jsp产生的响应数据------------------ </p>
  14.  
  15. < c:forEach var ="user" items= " ${users}" >
  16. 用户姓名:${user.name} 用户年龄:${user.age} <br />
  17. </ c:forEach>
  18. </body>
  19. </html>

例子2:不使用Attribute,使用Paramter向转发的资源传递参数。

虽然request对象没有setParameter方法来设置参数,但是我们可以在转发的URL后通过QueryString 的方式添加。JSP中的<jsp:foward>标签下的<jsp:param>标签就是使用的这个原理。

AimServlet.java

  1. public class AimServlet extends HttpServlet {
  2. private static final long serialVersionUID = 1L ;
  3.  
  4. protected void doGet( HttpServletRequest request , HttpServletResponse response) throws ServletException , IOException {
  5.  
  6. request .getRequestDispatcher ( "foo.jsp?num=1") . forward( request , response );
  7. }
  8. }

foo.jsp

  1. <%@ page contentType= "text/html; charset=UTF-8" pageEncoding ="UTF-8" trimDirectiveWhitespaces= "true"
  2. session ="true" %>
  3. <%@ taglib prefix= "c" uri = "http://java.sun.com/jsp/jstl/core" %>
  4.  
  5. <! DOCTYPE html>
  6. <html>
  7. <head>
  8. <meta http-equiv = "Content-Type" content ="text/html; charset=UTF-8">
  9. <title> 标题</title>
  10. </head>
  11. <body>
  12.  
  13. 通过forward传递过来的参num=${param.num}
  14.  
  15. </body>
  16. </html>

RequestDispatcher.include(request, response)

   此方法用于包含响应中某个资源(servlet、JSP 页面和 HTML 文件)的内容。
调用者指定一个被包含的资源,将这个包含的资源(JSP,Servlet,HTML)的响应数据包含到自己的响应体中。被包含的数据是在服务器上经过运行产生的,因此是动态包含,而不同于JSP中的include指令,它是JSP转译期的静态包含,类似于C语言中的宏一样。
 
 
这个过程实质是用一个相同的Request再请求一次被包含的资源,将被包含的资源的响应数据包含到原本的资源中去,构成它的响应数据的一部分。

注意事项:

1、被包含者不能设置ServletResponse的响应状态和响应头(否则并不会产生效果),因为这些都是包含者做的事,被包含者只需要产生响应数据解可以了。

2、不同于 forward中的request的传递特性:在被包含的资源中从request中获取请求路径相关的信息,发现依然是原始请求的路径,也就是浏览器地址栏相关的路径,也就是说被包含的资源获得的request对象的路径属性和原始请求资源的路径一样(见下面的例子1)。其它的API调用也是一样的(Attribute 和Parameter)。

例子1

TargetServlet.java

  1. public class TargetServlet extends HttpServlet {
  2. private static final long serialVersionUID = 1L ;
  3. protected void doGet( HttpServletRequest request , HttpServletResponse response) throws ServletException , IOException {
  4.  
  5. response .setContentType ( "text/html;charset=utf-8" );
  6. PrintWriter out = response .getWriter () ;
  7.  
  8. out .println ( "----------来自TargetServlet的告白----------------<br />" ) ;
  9. out .print ( "我偷懒了,下面的响应数据并不是我自己产生的,而是包含的其它资源产生的<br/>" ) ;
  10. request .getRequestDispatcher ( "test.jsp") . include( request , response );
  11.  
  12. out .flush () ;
  13. out .close () ;
  14. }
  15. }

test.jsp

  1. <%@ page contentType= "text/html; charset=UTF-8" pageEncoding = "UTF-8" trimDirectiveWhitespaces = "true"
  2. session = "false"
  3. %>
  4.  
  5. <p> ------------------------来自test.jsp的告白-------------------------- </p>
  6. <p> 我输出的响应数据将被其它的资源包含 </p>
  7. 请的URL是 <%= request.getRequestURL().toString() %> ,可以看出客户端真正请求的不是我,我只是幕后工作者。
  8. <p> 但我很开心,因为响应给客户端的数据一部分来自于我 </p>

例子2:通过包含路径后追加QueryString来向被包含资源传递参数,以及通过request.setAttribute传递属性。

同样, JSP中的<jsp:include>标签下的<jsp:param>标签就是通过在含路径后追加QueryString达到的传递参数的效果。

  1. public class TargetServlet extends HttpServlet {
  2. private static final long serialVersionUID = 1L ;
  3. protected void doGet( HttpServletRequest request , HttpServletResponse response) throws ServletException , IOException {
  4.  
  5. response .setContentType ( "text/html;charset=utf-8" );
  6. PrintWriter out = response .getWriter () ;
  7.  
  8. out .println ( "----------来自TargetServlet的告白----------------<br />" ) ;
  9. out .print ( "我偷懒了,下面的响应数据并不是我自己产生的,而是包含的其它资源产生的<br/>" ) ;
  10.  
  11. request .setAttribute ( "sharedatt", "I`m shared attribute") ;
  12.  
  13. request .getRequestDispatcher ( "test.jsp?sharedparam=Im-shared-parameter" ). include (request , response ) ;
  14.  
  15. out .flush () ;
  16. out .close () ;
  17. }
  18. }
  1. <%@ page contentType= "text/html; charset=UTF-8" pageEncoding = "UTF-8" trimDirectiveWhitespaces = "true"
  2. session = "false"
  3. %>
  4.  
  5. <p> ------------------------来自test.jsp的告白-------------------------- </p>
  6. <p> 我输出的响应数据将被其它的资源包含 </p>
  7. <p> 从request中提取共享的属性Attribute : <%= request.getAttribute("s haredatt") %>
  8. <p> 从request中提取共享的参数Parameter : <%= request.getParameter("sharedparam" ) %>

欢迎转载,请注明出处:www.cnblogs.com/lulipro

为了获得更好的阅读体验,请访问原博客地址。

限于本人水平,如果文章和代码有表述不当之处,还请不吝赐教。

代码钢琴家

关于RequestDispatcher的原理的更多相关文章

  1. JavaWeb——关于RequestDispatcher的原理

    RequestDispatcher简介 RequestDispatcher 代表请求的派发者.它有2个动作:forward 和 include .客户端对于任何一个请求,可以根据业务逻辑需要,选择不同 ...

  2. 【Servlet】关于RequestDispatcher的原理

    RequestDispatcher简介 RequestDispatcher 代表请求的派发者.它有2个动作:forward 和 include .客户端对于任何一个请求,可以根据业务逻辑需要,选择不同 ...

  3. Tomcat 的 ErrorPage 实现原理分析

    使用Tomcat,一定见到过404,500的时候,见到过Tomcat提供的错误页面,例如请求的资源找不到的时候,响应状态码为404,这个时候的错误页面是这样的: 这些错误页面是 如何生成及定位展示的  ...

  4. Spring MVC中DispatcherServlet工作原理探究

    转:http://blog.csdn.net/zhouyuqwert/article/details/6853730 下面类图将主要的类及方法抽离出来,以便查看方便,根据类的结构来说明整个请求是如何工 ...

  5. HttpServletResponse HttpServletRequest RequestDispatcher

    HttpServletResponse HttpServletRequest RequestDispatcher 07. 五 / J2EE / 没有评论   一.以字节为单位向客户端发送中文数据1.服 ...

  6. SpringMVC——使用RequestDispatcher.include()和HttpServletResponseWrapper动态获取jsp输出内容

    介绍本篇内容前,先抛出我遇到的问题或者说是需求!(精读阅读本篇可能花费您15分钟,略读需5分钟左右) 一:需求说明 有一个Controller有两个方法 第一个方法通过指定的路径和参数去渲染jsp内容 ...

  7. Nginx原理和配置总结

    一:前言 Nginx是一款优秀的HTTP服务器和反向代理服务器,除却网上说的效率高之类的优点,个人的切身体会是Nginx配置确实简单而且还好理解,和redis差不多,比rabbitmq好理解太多了: ...

  8. 【spring】- springmvc 工作原理

    原理 本质是将DispatcherServlet及关联的Spring上下文环境的初始化工作织入Servlet的生命周期内,将外部WEB请求转换为Spring Bean能处理的形式,然后将处理后的结果借 ...

  9. Velocity工作原理解析和优化

    在MVC开发模式下,View离不开模板引擎,在Java语言中模板引擎使用得最多是JSP.Velocity和FreeMarker,在MVC编程开发模式中,必不可少的一个部分是V的部分.V负责前端的页面展 ...

随机推荐

  1. 前端框架之bootstrap

    一.bootstrap按钮 1.按钮 <button class="btn btn-default">按钮</button><button class ...

  2. (转)Java多线程之Lock的使用 (待整理)

    import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util ...

  3. Objective-C 使用核心动画CAAnimation实现动画

    先来看看效果吧 整个核心动画就不多做介绍了,随便一搜就能有很多很详细的解释,主要使用以下四种 CABasicAnimation //经典动画 CAKeyframeAnimation //关键帧动画 C ...

  4. helpers.bulk时 action_request_validation_exception 异常

    语言Python 在开发时,批量插入ES,出现了action_request_validation_exception异常.我的代码是这样的 action = { } helpers.bulk(es, ...

  5. java对Microsoft Document的操作--->对Excel的操作

    起初,自己想对网站上爬取一些数据来写到Excel表格中,便在网上找了找java操作Excel接口,了解到Apache的POI接口可以对微软的文档进行操作,WIKI搜索的结果如下, HSSF - 提供读 ...

  6. Redis-简单实现星形主从配置

    高级参考(https://www.zhihu.com/question/21419897) 简单应用场景 现在配置redis 星形 集群, 有三台服务器, 怎样实现? 复制redis.conf两份, ...

  7. 使用纯css3写出来的表情包 (^v^)

    效果如图所示: 不多说,我们直接一个一个来写出,主要列出每个表情的结构,样式我们统一写出,基本全部会用到,颜色以及结构可以根据自己的需求来调整.(里面可是没有一张图片的哦) 页面预览:http://2 ...

  8. hdu--2084--dp--数塔

    #include<iostream> #include<cstring> using namespace std; ; }; void dp(int,int); int n; ...

  9. HDU 6097---Mindis(二分)

    题目链接 Problem Description The center coordinate of the circle C is O, the coordinate of O is (0,0) , ...

  10. jQuery基础知识总结二

     * DOM操作 *1 基本操作 * html() - 等价于innerHTML属性 * text() - 等价于textContent属性 * val() - 等价于value属性 * attr() ...