本文转载自:http://blog.csdn.net/kobejayandy/article/details/13762043

转发

转发的原理,可以通过下图展示:

  浏览器的请求发送给组件 1,组件 1 经过一些处理之后,将 request 和 response 对象 “传递” 给组件 2,由组件 2 继续处理,然后输出响应(当然,也可以继续向其他组件 “传递”),这个传递的过程称之为 “转发”。整个过程只涉及一次浏览器和服务器之间的 “请求-响应” ,转发过程中的组件共享同一个请求 (request) 和响应 (response) 对象。

  转发的意义在于可以实现组件的 “分工”。在基于 MVC,多层结构的Web应用中,经常需要多个组件协同完成一次 “请求-响应” 工作,例如:用户要获取“设备列表信息”,提交请求至控制器组件(Servlet),该 Servlet 调用适当的 JavaBean 获取了 “设备列表” 数据然后再转发至 JSP 组件去显示信息。

  RequestDispatcher 对象封装了转发操作。通过 request 的 getRequestDispatcher(String path) 方法获得 RequestDispatcher 对象,其中 String 类型参数path 表示要转发到的地址。调用 Dispacther 对象的 forward(request, response) 方法实现转发。关于转发的具体操作,有如下几点需要注意:

  1. 转发只能在同一个应用的组件之间进行,不可以转发给其他应用的地址。
  2. 转发的地址可以用 “相对地址” 方式,也可以用 “绝对地址” 方式。但需要注意的是:用绝对地址方式时,应从应用名后 (Context path) 开始。例如:要转发到的地址为:http://192.168.5.100/tst/jsp/somewhere.jsp (其中 tst 为应用名),对应的绝对地址为:“/jsp/somewhere.jsp”。这是很好理解的,因为转发只能转到本应用内的地址,所以绝对地址是没有必要包含应用名的。
  3. 组件之间通过转发来分工协作,势必涉及数据的传递,可以通过 request 对象传递数据。request对象的 setAttribute 和 getAttribute 分别用于以 “名称-对象对” 的形式存取数据。
  4. 在一个组件转发给另外一个组件之前,通过 response 输出的响应内容是没有意义的。在转发之前的通过 out 对象输出的内容最终不会输出到浏览器,这是由于 RequestDispatcher 在转发之前清空了输出缓冲区。但如果在转发之前输出的信息超出了缓冲区,或者调用了 out 对象的 flush() 方法,此响应内容已经输出到了客户端(称之为响应信息已提交),此时如果实施转发操作会抛出运行时异常:java.lang.IllegalStateException。

重定向

重定向的含义可以由下图说明:

浏览器向某组件发出请求信息,组件向浏览器发回一个重定向响应信息,该响应信息不包含具体的数据内容,只是在响应头信息中包含了需要重定向到的地址信息,该地址可以是任何有效的 URL。浏览器收到该重定向响应后会自动的向响应信息头中所指示的地址发出请求。整个重定向的过程涉及两次 “请求-响应”。具体的重定向响应格式如下所示:

HTTP/1.1 302 Moved Temporarily
Server: Apache-Coyote/1.1
Locatio :http://192.168.5.100:8080/tst/jsp/somewhere.jsp
Content-Length: 0
Date: Mon, 30 Jun 2008 03:52:54 GMT

注意:重定向响应中包含重定向地址的部分。

重定向可以通过 response 的 sendRedirect(String url) 方法来实现,注意 String 类型的参数 url 表示重定向到的地址,需要注意的是,如果表示重定向到本应用内的一个绝对地址时,要从应用名前开始,例如:tst 应用中的某个组件要重定向到本应用内的 /jsp/somewhere.jsp,则重定向的绝对地址应该是:“/tst/jsp/somewhere.jsp” 这一点和转发中的绝对地址表示是不同的。

关于重定向的具体操作,有如下几点需要注意:

  1. 使用 response.sendRedirect 时,前面不能有 HTML 输出。
    这并不是绝对的,不能有 HTML 输出其实是指不能有 HTML 被送到了浏览器。事实上现在的 server 都有 cache 机制,一般在 8K(我是说JSP SERVER),这就意味着,除非你关闭了cache,或者你使用了out.flush() 强制刷新,那么在使用 sendRedirect 之前,有少量的HTML输出也是允许的。

  2. response.sendRedirect 之后,应该紧跟一句 return;
    我们已经知道 response.sendRedirect 是通过浏览器来做转向的,所以只有在页面处理完成后,才会有实际的动作。既然你已经要做转向了,那么后的输出还有什么意义呢?而且有可能会因为后面的输出导致转向失败。

本质区别

一句话,转发是服务器行为,重定向是客户端行为。为什么这样说呢,这就要看两个动作的工作流程:

转发过程:客户浏览器发送 http 请求 -----> web服务器接受此请求 -----> 调用内部的一个方法在容器内部完成请求处理和转发动作 -----> 将目标资源发送给客户。在这里,转发的路径必须是同一个 web 容器下的 url,其不能转向到其他的 web 路径上去,中间传递的是自己的容器内的 request。在客户浏览器路径栏显示的仍然是其第一次访问的路径,也就是说客户是感觉不到服务器做了转发的。转发行为是浏览器只做了一次访问请求。

重定向过程:客户浏览器发送 http 请求 -----> web 服务器接受后发送 302 状态码响应及对应新的 location 给客户浏览器 -----> 客户浏览器发现是 302 响应,则自动再发送一个新的 http 请求,请求 url 是新的 location地址 -----> 服务器根据此请求寻找资源并发送给客户。在这里 location 可以重定向到任意 URL,既然是浏览器重新发出了请求,则就没有什么 request 传递的概念了。在客户浏览器路径栏显示的是其重定向的路径,客户可以观察到地址的变化的。重定向行为是浏览器做了至少两次的访问请求的。

Servlet & JSP - 转发与重定向的区别的更多相关文章

  1. Servlet中转发和重定向的区别

    Servlet中页面的跳转有两种方式:转发和重定向. 1.转发和重定向的区别 ①转发是服务器行为,重定向是客户端行为. ②转发是浏览器发生了一次请求,重定向至少是两次请求. ③转发地址栏中的url不会 ...

  2. servlet之转发与重定向的区别

    转发(服务器端跳转):  一次请求 <jsp:forward> request.getRequestDispatcher("new.jsp").forward(requ ...

  3. jsp转发与重定向的区别

    1.转发的实现其实很简单,使用request的getRequestDispatch()方法得到RequestDispatch对象,然后在括号里放转发的地址,然后用这个对象调用forward()方法,里 ...

  4. JSP转发和重定向的区别

    重定向: response.sendRedirect("地址");         a. 页面地址显示最终页面         b. 不可向后传递参数         c. 跳到外 ...

  5. Servlet转发和重定向的区别

    附上视频教学的一张图: 区别: 1.转发产生一次请求,一次响应: 重定向产生2次请求 两次响应 2.转发客户端不可见的: 重定向客户端是可以察觉的. 3.转发时候url不变: 重定向URL会改变 案例 ...

  6. servlet(jsp)中的重定向和转发

    servlet(jsp)中的重定向和转发 由一个servlet(jsp)从内部转向还有一个servlet(jsp)有两种方式:转发和重定向. 转发:是由一个web组件(servlet)将未完毕的处理交 ...

  7. jsp内置对象 转发与重定向的区别

    jsp 内置对象  转发与重定向的比较 重定向和转发有一个重要的不同:当使用转发时,JSP容器将使用一个内部的方法来调用目标页面,新的页面继续处理同一个请求,而浏览器将不会知道这个过程. 与之相反,重 ...

  8. SERVLET API中转发与重定向的区别?

    SERVLET API中转发与重定向的区别? 1.转发(forward方法) 转发仅是容器中控制权的转向,在客户端浏览器地址栏中不会显示出转向后的地址. 转发是服务器请求资源,服务器直接访问目标地址的 ...

  9. Java中转发与重定向的区别

        转发与重定向的区别 转发是服务器行为,重定向是客户端行为 1.转发在服务器端完成的:重定向是在客户端完成的2.转发的速度快:重定向速度慢3.转发的是同一次请求:重定向是两次不同请求4.转发不会 ...

随机推荐

  1. TypeScript学习笔记(四):函数

    这篇笔记我们来看看TypeScript中的函数. 函数类型 在JavaScript中存在两种定义函数的方法,如下: //命名函数 function add(x, y) { return x+y; } ...

  2. Unity3D之UGUI学习笔记(二):Rect Transform与Anchor

    Rect Transform 我们都知道,Unity3D中所有的GameObject都必须要携带一个Transform组件,且该组件无法移除,那么作为UI显示的GameObject则不是携带Trans ...

  3. 一款多浏览器兼容的javascript多级下拉菜单

    这个多级下拉菜单的脚本大小不到2K,带有动画效果,可以方便地支持多个实例,并且能良好兼容WordPress系统wp_list_cats和wp_list_pages生成的多级列表.要初始化一个菜单,只需 ...

  4. Js面向对象和数据类型内存分配(转)

    一 Js基本数据类型以及内存情况 1 Undefined Undefined类型只有一个值undefined,在使用了声明但未初始化的变量的时候,这个变量值就是undefined 1 var hi; ...

  5. Minesweeper PC/UVa IDs: 110102/10189, Popularity: A,Success rate: high Level: 1

    #include<cstdio> #include<iostream> #include<string> #include<algorithm> #in ...

  6. Xdebug的使用

    1.http://www.cnblogs.com/mo-beifeng/articles/2446142.html 2.http://www.cnblogs.com/ximu/articles/200 ...

  7. SQL性能优化工具TKPROF

     全名为Trace Kernel Profile,用来格式化跟踪文件,是一个命令行工具. 主要的格式例如以下: tkprof tracefile outputfile - tracefile:要分 ...

  8. 【转】Ruby入门教程(一)

    1. Ruby环境搭建 在Windows下,搭建Ruby环境,比较简单的方法是在“RubyInstaller”上下载一个合适的版本(D瓜哥使用的是最新版),直接安装就可以了. 另外,吐槽两句,网上有人 ...

  9. Oracle使用goldengate分别向Oracle和mysql双路的单向复制

    一.Oracle分别向Oracle和mysql双路的单向复制是在: ORACLE-mysql的单向复制基础上做的.http://blog.csdn.net/q947817003/article/det ...

  10. Sales_item例子

    Sales_item.h #ifndef SALES_ITEM_H #define SALES_ITEM_H #include<iostream> #include<string&g ...