请求转发+请求包含+request域对象

什么是请求转发

请求转发实现了服务器内部的资源跳转

请求转发的特点

一次请求,一次响应。一个请求对象必然对应一个响应对象。

Web应用内部(服务器内部)的资源跳转,浏览器感受不到变化,地址栏不会发生变化

请求转发实现服务器内部资源跳转

在demo4中

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //获取调度器,利用调度器实现转发
        request.getRequestDispatcher("/RequestDemo5").forward(request,response);
    }

在demo5中

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.getWriter().write("here is RequestDemo5!");
    }

浏览器中输入:http://localhost/demo/RequestDemo4

在这里插入图片描述

既然是服务器内部,那么path路径直接写/资源名即可。

请求转发与数据冲刷

ok,请求转发还是比较清晰的,现在有个新需求,如果我想现在demo4页面上显示一段数据,转发到demo5,再显示另外一段数据,该如何实现呢?

如果此时在demo4中先写入数据,再转发会发生什么现象呢?

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //再转发之前写入cache
        response.getWriter().write("cache");
        //获取调度器,利用调度器实现转发
        request.getRequestDispatcher("/RequestDemo5").forward(request,response);
    }

demo5不变,再次访问http://localhost/demo/RequestDemo4,会看到以下结果,并不能看到cache。

在这里插入图片描述

这是因为,如果在请求转发之前response缓冲区中还存在数据,请求转发时将会将缓冲区清空。

那如果我写入之后,直接调用response.flushBuffer();将数据先冲刷到浏览器上显示,而后再转发是不是就解决问题了呢?试试修改demo4,demo5不变。

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //再转发之前写入cache
        response.getWriter().write("cache");

        //调用flushBuffer方法冲刷缓冲区
        response.flushBuffer();
        //获取调度器,利用调度器实现转发
        request.getRequestDispatcher("/RequestDemo5").forward(request,response);
    }

再次访问,出现了以下状况:

在这里插入图片描述

调用flushBuffer()方法冲刷response缓冲区会造成一次响应操作,又因为请求转发模型中一次请求将会对应一次响应,导致请求转发的响应就无法实现。同理,如果再请求转发之后再冲刷,会导致冲刷操作无法执行。

请求转发语句前后正常执行

demo4:

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //再转发之前写入cache
        response.getWriter().write("cache");

        System.out.println("demo4 start");
        //获取调度器,利用调度器实现转发
        request.getRequestDispatcher("/RequestDemo5").forward(request,response);

        System.out.println("demo4 end");
        //调用flushBuffer方法冲刷缓冲区
        response.flushBuffer();
    }

demo5:

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("demo5 start");
        response.getWriter().write("here is RequestDemo5!");
        System.out.println("demo5 end");
    }

当访问demo4时,控制台将会输出以下结果:

demo4 start
demo5 start
demo5 end
demo4 end

可见,转发前后语句正常执行,且按照一定顺序执行。

请求转发可以多重转发

在demo5中转发到demo6,前面代码不变:

request.getRequestDispatcher("/RequestDemo6").forward(request,response);

demo6中:

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("demo6 start");
        response.getWriter().write("here is demo6");
        System.out.println("demo6 end");
    }

最后访问demo4,结果如下:

在这里插入图片描述

控制台输出:

demo4 start
demo5 start
demo6 start
demo6 end
demo5 end
demo4 end

在这里插入图片描述

请求包含

突然想到刚才的需求,两个页面的内容都要显示,咋办呢?请求包含(include)!

demo4中

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //再转发之前写入demo4
        response.getWriter().write("demo4 ");
        //获取调度器,利用调度器实现转发
        request.getRequestDispatcher("/RequestDemo5").include(request,response);
    }

demo5中

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.getWriter().write("demo5");
    }

此时需求即完成。

在这里插入图片描述

域对象是啥

在一个域内,实现数据共享的对象,如上request对象在服务器接收请求时创建,在服务器内部多次转发,在同一条请求链上,多个Servlet资源共享request,request就是一个域对象。

本质上,数据共享由对象map的属性名和属性值实现,因此我们可以看到需要关于Attribute的方法。

域对象相关方法

实现:在demo7中设置属性及属性值,在demo8中获取值。

/**
 * @auther Summerday
 *
 * request域对象
 */
@WebServlet("/RequestDemo7")
public class RequestDemo7 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        //向域中添加数据
        request.setAttribute("message","hello,i'm demo7");
        request.setAttribute("name","summerday");
        request.setAttribute("age",18);
        //转发
        request.getRequestDispatcher("/index.jsp").forward(request,response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }
}
/**
 * @auther Summerday
 */
@WebServlet("/RequestDemo8")
public class RequestDemo8 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //获取全部域属性的名称
        Enumeration<String> names = request.getAttributeNames();
        while(names.hasMoreElements()){
            String s = names.nextElement();
            //获取指定名称的域属性
            String value = (String) request.getAttribute(s);
            System.out.println(s+">>"+value);
        }
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }
}

在这里插入图片描述

域对象的生命周期

一次请求开始时,request对象将会被创建,在请求链(可能包含多次转发)结束的时候,request对象将销毁,而这个请求链的范围就是request域对象的作用范围。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值