本文转载自: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. JMS开发(一):基础理论认知

    JMS全称是Java Message Service.其是JavaEE技术规范中的一个重要组成部分,是一种企业消息处理的规范.它的作用就像一个智能交换机,它负责路由分布式应用中各个组件所发出的消息. ...

  2. FPGA静态时序分析——IO口时序(Input Delay /output Delay)

    1.1  概述 在高速系统中FPGA时序约束不止包括内部时钟约束,还应包括完整的IO时序约束和时序例外约束才能实现PCB板级的时序收敛.因此,FPGA时序约束中IO口时序约束也是一个重点.只有约束正确 ...

  3. PostgreSQL的 initdb 源代码分析之十八

    继续分析: setup_conversion(); 展开: 其实质是: 运行命令:"/home/pgsql/project/bin/postgres" --single -F -O ...

  4. git 与 github 最简单的用法

    今天发现cygwin里已经装了git,所以顺便测试一下git是怎么用的. 大概最简单的用法是这样的: 1.在github创建一个repository.复制右边那个 HTTPS clone URL 2. ...

  5. spring读取properties的方法

    首先在配置文件中配置PropertyPlaceholderConfigurer 单个配置文件: <bean id="propertyConfigurer" class=&qu ...

  6. Java和C#在面向对象上语法的区别

    做了几年了开发一直没有总结什么,回到了家乡的小城做了一名培训班的教员,教授软件开发的知识.细小的知识从头细细嚼来,别有一番滋味.或是以前遗漏的太多,或是确实没有系统的学习过,教学生的过程中自己也对教材 ...

  7. Android短信彩信收发流程(应用层)

    下图为ComposeMessageActivity中confirmSendMessageIfNeeded部分的信息发送流程.主要以接收者有效性的确认为主,然后转向sendMessage方法进行发送. ...

  8. Python dictionary implementation

    Python dictionary implementation http://www.laurentluce.com/posts/python-dictionary-implementation/ ...

  9. 进程间通信之popen和pclose函数

    常见的操作是创建一个管道连接到另一个进程,然后读其输出或向其输入端发送数据,为此,标准I/O库提供了两个函数popen和pclose.这两个函数实现的操作是:创建一个管道,调用fork产生一个子进程, ...

  10. Line Search and Quasi-Newton Methods

    Gradient Descent 机器学习中很多模型的参数估计都要用到优化算法,梯度下降是其中最简单也用得最多的优化算法之一.梯度下降(Gradient Descent)[3]也被称之为最快梯度(St ...