写点什么

Java 高手速成 | 图说重定向与转发

作者:TiAmo
  • 2023-02-17
    江苏
  • 本文字数:3945 字

    阅读完需:约 13 分钟

Java高手速成 | 图说重定向与转发

我们先回顾一下 Servlet 的工作原理,Servlet 的工作原理跟小猪同学食堂就餐的过程很类似。小猪同学点了烤鸡腿(要奥尔良风味的),食堂窗口的服务员记下了菜单,想了想后厨的所有厨师,然后将菜单和餐盘交给专门制作烤鸡腿的厨师,这位大厨根据菜单制作出奥尔良烤鸡腿并放进餐盘,交给窗口服务员,服务员将做好的烤鸡腿交给小猪同学,小猪同学饱餐一顿后,菜单和餐盘就都被清理掉了,模拟情景的图示如图 1 所示。


■ 图 1 Servlet 工作原理模拟情景

上述过程对应到 java 中其实就是用户通过浏览器向 Web 服务器发出 HTTP 请求,服务器选择相应的 Servlet 响应浏览器的请求,并将响应结果返回给浏览器。服务器在选择相应 Servlet 的时候会出现一些问题,如果该 Servlet 无法完成本次请求,它会怎么处理这种情况呢?在 Servlet 中有两种机制可以帮助我们解决上述问题,Servlet 工作原理解释如图 2 所示。


■ 图 2 Servlet 工作原理

如果厨师不会做这道菜怎么办呢?有两种解决方案,就是请求转发与重定向,模拟情景如图 3 所示。


■ 图 3 重定向和转发的由来

01、请求转发原理


如果小猪到饭店点了麻辣凉粉,饭店的服务员记下了菜单,把这道菜交给了面点师傅。虽然凉粉是淀粉类食品,可是这道菜面点师傅不会做,应该交给炒菜的师傅来完成这道菜,于是面点师傅将菜单还给服务员,让服务员去找炒菜的师傅。服务员知道自己搞错了之后立刻把菜单交给炒菜师傅,炒菜师傅根据菜单制作出了麻辣凉粉并放入盘中交给服务员,服务员再将做好的凉粉交给小猪同学。这种在同一个饭店更换厨师并且不需要顾客再次点菜的处理方式叫做请求转发,其模拟情景如图 4 所示。


■ 图 4 请求转发模拟情景

用户通过访问 Web 浏览器提出请求,由 Servlet 引擎创建 Servlet1 实例以及 request 和 response 对象,然后调用 Servlet1 的 service()函数响应用户请求,service 方法读取请求内容,写入响应内容,其工作原理如图 5 所示。


■ 图 5 Servlet 工作原理

在执行 service()方法时如果遇到了请求转发 forward 命令,说明当前 Servlet 处理不了用户的请求,就要立刻调整请求头为 forward 命令中请求的 Servlet2,清空响应对象的响应体,然后返回到 Servlet 引擎,请求转发中执行 service 方法的工作原理解释如图 6 所示。


■ 图 6 请求转发的工作原理图示 2

service 函数执行完毕后返回,服务器将响应结果发送到 Web 浏览器中,请求转发中 service 方法执行完毕后的工作原理解释如图 7 所示。


■ 图 7 请求转发的工作原理图示 3

02、重定向原理


可是如果饭店里的厨师都不会做小猪同学点的菜该怎么办呢?我们接下来就介绍另一种方式。如果小猪到川菜馆点了一份寿司,服务员将菜单递给厨师之后大厨发现所有的厨师都不会做寿司,于是川菜师傅将菜单还给服务员并告诉他日料馆的地址,再由川菜馆的服务员告诉小猪川菜馆做不了寿司,他应该去吃货街的日料馆。知道自己找错地方之后小猪就来到吃货街找到日料馆向服务员点了一份寿司,经过点菜,做菜,上菜的流程之后小猪终于如愿吃到了寿司。这种顾客需要到别的饭店重新提出请求的方式叫做重定向,如图 7 和 8 所示。


 ■ 图 8 重定向模拟情景 1


■ 图 9 重定向模拟情景 2

用户通过访问 Web 浏览器提出请求,由 Servlet 引擎创建 Servlet1 实例以及 request 和 response 对象,然后调用 Servlet1 的 service()函数响应用户请求,其工作原理如图 10 所示。


■图 10 Servlet 工作原理

但是若在 service 中执行到了 sendRedirect 重定向命令,说明当前 Servlet 响应不了用户的请求,需要清空响应体中已经写入的内容,将能够响应用户请求的 Servlet2 的地址写入响应体中,然后将结果返回至服务器,执行 sendRedirect 方法的工作原理如图 11 所示。


■ 图 11 重定向工作原理 1

浏览器接到包含重定向地址的响应信息后会自动重新提交请求,Servlet 引擎创建 Servlet2 实例同时创建新的 request 和 response 对象,然后调用 Servlet2 的 service()函数响应用户请求,request 和 response 方法的工作原理如图 12 所示。


■ 图 12 重定向工作原理 2

浏览器接到包含重定向地址的响应信息后会自动重新提交请求,Servlet 引擎创建 Servlet2 实例同时创建新的 request 和 response 对象,然后调用 Servlet2 的 service()函数响应用户请求,新的 Servlet 引擎执行 service 方法的工作原理如图 13 所示。


■ 图 13 重定向工作原理 3

service 方法读取请求信息,写入响应信息,执行完毕之后返回,由服务器将结果发送至浏览器。


03、请求转发和重定向


实现请求转发的方式:

(1)得到 RequestDispatcher 对象:RequestDispatcher dispatcher=

request.getRequestDispatcher("a.jsp");

(2)转发 dispatcher.forward (request,response);

实现重定向的方式:

重定向 response.sendRedirect("a.jsp");

RequestDispatcher.forward 方法只能在同一个 Web 应用程序内的资源之间转发请求。

sendRedirect 方法还可以重定向到同一个站点上的其他应用程序中的资源,甚至是使用绝对 URL 重定向到其他站点的资源。

案例 1: 中用判断三角形的三边是否满足构成三角形的条件来实现请求转发和重定向,通过 Example1_b_triangle_judge.jsp 页面输入三角形的三标,然后提交到相应的 Servlet 进行处理和逻辑的判断,在 Servlet 代码中获取来自 JSP 页面的三边数据信息,若三边不构成三角形或者输入的三边均小于 0 则会重定向到初始页面,即 Example1_b_triangle_judge.jsp 页面重新输入数据信息,若三边满足构成三角形的条件则会转发到 Example1_c_triangle_judge_show.jsp 页面,并在该页面中输出三边的边长和面积。

注意:

web.xml <servlet><servlet-name>triangleServlet</servlet-name><servlet-class>com.programs.Example1_a_triangleServlet</servlet-class></servlet><servlet-mapping><servlet-name>triangleServlet</servlet-name><url-pattern>/triangle_judge</url-pattern></servlet-mapping> Example1_a_triangleServlet.java
复制代码

JSP 页面提交的目的地址对应的 Servlet 需要与 Web.xml 文件中的<url-pattern>相对应,而不是<servlet-name>对应。

@WebServlet(name = "triangleServlet")public class Example1_a_triangleServlet extends HttpServlet {    @Override    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {        String sidea = request.getParameter("sidea");        String sideb = request.getParameter("sideb");        String sidec = request.getParameter("sidec");        int sideA = Integer.parseInt(sidea);        int sideB = Integer.parseInt(sideb);        int sideC = Integer.parseInt(sidec);        if (sideA < 0 || sideB < 0 || sideC < 0 ||                (sideA + sideB <= sideC || sideB + sideC <= sideA || sideA + sideC <= sideB)) {            response.sendRedirect("Example1_b_triangle_judge.jsp");        } else {            RequestDispatcher dispatcher = request.getRequestDispatcher("Example1_c_triangle_judge_show.jsp");            dispatcher.forward(request, response);//请求转发        }    }     @Override    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {        doPost(request,response);    }} Example1_b_triangle_judge.jsp <%@ page contentType="text/html;charset=UTF-8" language="java" %><html><head><title>三角形判断</title></head><body><form action="triangle_judge"><p>使用三角形案例实现转发和重定向</p><b>输入边长a:</b><input type="text" name="sidea"><br><b>输入边长b:</b><input type="text" name="sideb"><br><b>输入边长c:</b><input type="text" name="sidec"><br><input type="submit" value="提交"></form></body></html> Example1_c_triangle_judge_show.jsp <%@ page contentType="text/html;charset=UTF-8" language="java" %><html><head><title>符合三角形</title></head><body><h3>这是请求转发得到的界面</h3><p>输入的三角形三边满足构成三角形的条件</p><%    String sidea = request.getParameter("sidea");    String sideb = request.getParameter("sideb");    String sidec = request.getParameter("sidec");%><p>三边分别为:<%= sidea%>、<%= sideb%>、<%= sidec%></p><%    int sideA = Integer.parseInt(sidea);    int sideB = Integer.parseInt(sideb);    int sideC = Integer.parseInt(sidec);    double p = (sideA + sideB + sideC) / 2.0;    double area = Math.sqrt(p * (p - sideA) * (p - sideB) * (p - sideC));%>其面积为<%= area%></body></html>
复制代码

 请求转发和重定向的案例页面显示如图 14、15、16、17 所示,当输入的三边满足构成三角形条件时,转发到显示页面并输出三角形各边信息和三角形的面积,若不满足构成三角形条件时,则重定向到初始页面中。


 ■ 图 14 请求转发和重定向案例 6_6 初始化页面显示


■ 图 15 请求转发和重定向案例 6_6 提交页面显示


■ 图 16 请求转发和重定向案例 6_6 转发页面显示


■ 图 17 请求转发和重定向案例 6_6 重定向页面显示


04、重定向与转发区别


第一:资源使用范围不一样。请求转发的转发对象只能是当前 Web 应用程序的服务器中的资源;重定向不仅可以在同一服务器中使用,还可以将请求重定向到其他 Web 服务器;

第二:请求响应的次数不一样,请求转发只需要一次请求与响应过程,重定向需要两次请求与响应过程;

第三:请求转发的 URL 地址栏是不变,因为只有一次请求与响应,重定向会改变地址栏,因为有两次请求与响应过程;

第四:请求转发的两个 Servlet 实例共用请求响应对象,重定向需要创建两次请求与响应对象。


发布于: 刚刚阅读数: 3
用户头像

TiAmo

关注

有能力爱自己,有余力爱别人! 2022-06-16 加入

CSDN全栈领域优质创作者;阿里云创作者社区专家博主、技术博主、星级博主、阿里云ACE;华为云享专家;

评论

发布
暂无评论
Java高手速成 | 图说重定向与转发_Java_TiAmo_InfoQ写作社区