RequestContext中的buffered与lazy-commit服务

(1)<buffered>与<lazy-commit>关系

              1.什么是提交

                        当浏览器向服务器发出请求,服务器就会返回一个Response响应。每个Response分为2部分:headers和content。

                        在服务器应用响应Request的过程中都可以向浏览器输出Response的内容。然而,已经输出到浏览器的内容,是不可以修改的;还没有输出的内容,还有改变的余地。这个输出的过程称为提交

              2.引起提交的方法

                        在servlet API中,下列操作可能导致Response被提交

response.sendError()

response.sendRedirect()

response.flushBuffer()

response.setContentLength() 或者response.setHeader("Content-Length", length)

response输出流被写入并达到内部buffer的最大值(例如:8KB)

              3.使用lazy-commit和buffered的原因

                        一旦Response被提交,headers就不能改变了,这时如果还没有写入cookie,那么基于cookie的session就无法实现了

                        而且如果想像在webx中layout嵌套screen,则必须把screen的内容缓存起来才能够拼在一起(用servlet的角度解释就是,layout的输出和screen的输出不在同一个servlet中)。一般servlet中输出页面:

public class MyScreenOrControl {
    @Autowired
    private HttpServletResponse response;

    public void execute() throws IOException {
        PrintWriter out = response.getWriter();

        out.println("<p>hello world</p>");
    }
}
                         可以看出,如果想实现嵌套,则必须将另一个页面的内容缓存起来,这就是buffered的功能。另外为了防止提交的太快,即页面还没拼在一起就提交了,所以需要lazy-commit的功能

(2)<buffered>

               1.作用

                        缓存Response中的内容。也就是将Response中的内容先不返回,先暂存起来

               2.配置

                         在/WEB-INF/webx.xml

<services:request-contexts xmlns="http://www.alibaba.com/schema/services/request-contexts">
    <buffered />
    ...
</services:request-contexts>

               3.页面嵌套原理

                         如一个screen中嵌套了control,那么control内容写入output stream后先不提交,而是缓存起来;

                        接着执行screen的代码,将内容写入output stream,写入时发现其中引用了control的内容,那么就会把缓存的control的内容取出来,放入screen的内容中


               4.关闭buffered

                        有些时候也需要关闭buffered,否则会对性能有很大影响。

                        比如:动态生成大文件的时候。这种需求有如下的特点:

                                    1)数据量大——有时候可以达到几兆:把这么多数据放在内容中,必然会导致服务器性能下降

                                    2)没有layout/screen/control页面嵌套的需求。所以不需要buffered来帮忙

                                    3)不用修改session

                        像这种需求都不用buffered来延迟提交,甚至越早提交越好——甚至可以在文件还未完全生成的时候就开始向用户浏览器输出,边输出边下载

                        如下例:动态生成120M的pdf文件然后下载。每生成1M数据就故意暂停半秒

public class MyDocument {
    @Autowired
    private BufferedRequestContext buffered;

    @Autowired
    private HttpServletResponse response;

    public void execute() throws Exception {
        buffered.setBuffering(false);

        response.setContentType("application/pdf");
        response.setHeader("Content-Disposition", "attachment; filename=\"mydocument.pdf\"");

        OutputStream out = response.getOutputStream();

        for (int m = 0; m < 120; m++) {
            for (int k = 0; k < 1024; k++) {
                for (int b = 0; b < 1024; b++) {
                    out.write((byte) b);
                }
            }

            // 每生成1M,暂停半秒
            Thread.sleep(500);
        }
    }
}
                      如果不关闭buffered,那么用户点击之后,要过1分多钟之后才会弹出下载提示,这显然是不可接受的;另外文件至少会占用120M内存,严重影响服务器性能
                      而如果关闭buffered,就会解决上面2个问题:

                         1)用户点击下载链接,浏览器立即提示保存文件

                         2)边生成数据边下载,生成数据时间是一分钟,那么下载时间也是一分钟

                         3)生成的数据立即输出,不会占用过多内存


(3)<lazy-commit>

               1.作用

                        拦截Response中的可能引起提交的方法,将提交延迟到Request context本身被提交的时候

               2.注意

                        <lazy-commit>与<buffered>必须配合使用才能完全实现延迟提交。因为如果输出流中数据超过内部缓存最大值就会提交,而现在把数据放在buffer中,就不会出现这种情况

               3.配置

                        在/WEB-INF/webx.xml中

<services:request-contexts xmlns="http://www.alibaba.com/schema/services/request-contexts">
    <lazy-commit />
    ...
</services:request-contexts>


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值