Servlet请求转发与重定向的详细介绍

请求转发

请求的转发,是服务器内部的独立行为,客户端用户是不可见的。出于复杂的业务需求或架构的需要,一个请求进入后,可能需要多个servlet配合完成。请求在一个servlet中完成处理后,就调用RequestDispatcher,将请求转发到下一个servlet,直至最后一个servlet处理完,响应给客户端。

在这里插入图片描述

RequestDispatcher 接口

javax.servlet 包中定义了一个 RequestDispatcher 接口,RequestDispatcher 对象由 Servlet 容器创建,用于封装由路径所标识的 Web 资源。利用 RequestDispatcher 对象可以把请求转发给其他的 Web 资源。

Servlet 可以通过 2 种方式获得 RequestDispatcher 对象:

  1. 调用 ServletContext 的 getRequestDispatcher(String path) 方法,参数 path 指定目标资源的路径,必须为绝对路径;

  2. 调用 ServletRequest 的 getRequestDispatcher(String path) 方法,参数 path 指定目标资源的路径,可以为绝对路径,也可以为相对路径。

    绝对路径是指以符号“/”开头的路径,“/”表示当前 Web 应用的根目录。相对路径是指相对当前 Web 资源的路径,不以符号“/”开头。

返回值类型方法功能描述
voidforward(ServletRequest request,ServletResponse response)将请求转发给另一个 Web 资源
voidinclude(ServletRequest request,ServletResponse response)将其他的资源作为当前响应内容包含进来

请求转发的特点

  1. 请求转发是应用内部行为,不支持跨域访问,只能跳转到当前应用中的资源。
  2. 请求转发之后,浏览器地址栏中的 URL 不会发生变化,用户无感。
  3. 参与请求转发的 Web 资源之间共享同一 request 对象和 response 对象。
  4. 由于 forward() 方法会先清空 response 缓冲区,因此只有转发到最后一个 Web 资源时,生成的响应才会被发送到客户端。

转发请求间的传值

通过request请求域的属性设置、读取方法实现。

转发示例

@WebServlet("/a")
public class AServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("this is AServlet");
        resp.getWriter().println("this is AServlet");
        //请求转发
        req.getRequestDispatcher("/b").forward(req,resp);
    }
}
@WebServlet("/b")
public class BServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("this is BServlet");
        resp.getWriter().println("this is BServlet");
    }
}

在这里插入图片描述

重定向

重定向是服务端与客户端共同协商后的行为。服务端收到请求后,直接告知浏览器,我(窗口a)这边不接待了请前往窗口b,于是,客户端又跑到窗口b终于办成。客户端发出的第一个请求,响应回来的是302状态码,同时响应标头里面还有Location:XXX/b,浏览器看到302就知道要再重新发起下一个请求,请求地址就是响应标头里面的Location指定的值。

在这里插入图片描述

response.sendRedirect()方法

HttpServletResponse 接口中的sendRedirect 方法,可以实现重定向。

返回值类型方法描述
voidsendRedirect(String location)返回状态码为 302 的响应结果,让浏览器访问新的 URL(响应标头参数 location 表示重定向的URL)。若指定的 URL 是相对路径,Servlet 容器会将相对路径转换为绝对路径。

重定向的特点

完全是通过两次请求完成,但是,重定向的过程由浏览器自动完成,重定向时请求头部的Referer会携带上值(必须通过点击浏览器中的超级链接,直接输入无值)。

重定向示例

@WebServlet("/re")
public class CRedirect extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("this is CRedirect");
        resp.getWriter().println("this is CRedirect");
        String s=req.getServletContext().getContextPath();
        resp.sendRedirect(s+"/b");
    }
}
@WebServlet("/d")
public class DServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        System.out.println("this is DServlet");
        resp.getWriter().println("this is DServlet");
        resp.getWriter().println("<a href='http://localhost:7070/ServletDemo_war_exploded/b' >测试Referer</a>");
    }
}


@WebServlet("/b")
public class BServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("this is BServlet");

        //这里有一个小问题要说明下。
        //Referer  的正确英语拼法是referrer 。由于早期HTTP规范的拼写错误,为了保持向后兼容就将错就错了。其它网络技术的规范企图修正此问题,使用正确拼法,所以目前拼法不统一。还有它第一个字母是大写。
        String referer = req.getHeader("Referer");

        // 通过点击浏览器中的链接跳转到b是有值,302过来的没有值
        // 点击d页面的超级链接先到a,a转发到b,referer内容为 d
        //点击d 页面的超链接直接到b,refer内容为d
        //浏览器中直接输入a,a转发到b,referer为null
        System.out.println("Referer: "+referer);

        resp.getWriter().println("this is BServlet");
    }
}

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

请求转发与重定向的区别

区别请求转发重定向
浏览器地址栏 URL 是否发生改变
是否支持跨域跳转
请求与响应的次数一次请求和一次响应两次请求和两次响应
是否共享 request 对象和 response 对象
传值能通过 request 域对象传递数据不能通过 request 域对象传递数据,可通过queryString传值
速度相对要快相对要慢
行为类型服务器行为服务端与客户端协商后行为
  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值