如何清除Java HttpServletResponse的屏幕输出

时间:2009-12-29 07:09:02

标签: java servlets

我正在使用servletResponse.getWriter()。write(String)写入浏览器窗口。

但是如何清除之前由其他类似写入调用写入的文本?

4 个答案:

答案 0 :(得分:4)

简短的回答是,你不能 - 一旦浏览器收到回复,就无法收回回复。 (除非有某种方法异常停止HTTP响应以使客户端重新加载页面,或者某种程度的东西。)

在某种意义上,响应可以被“清除”的最后一个位置是使用ServletResponse.reset方法,根据Servlet Specification,它将重置servlet响应的缓冲区。

但是,这个方法似乎也有一个问题,因为它只有在ServletOutputStreamflush方法没有提交缓冲区(即发送给客户端)时才会起作用。 / p>

答案 1 :(得分:2)

你做不到。最好的方法是写入缓冲区(StringWriter / StringBuilder),然后您可以随时替换写入的数据。只有当您确切知道响应是什么时,您才能将缓冲区的内容写入响应。

同样的问题,并且有理由以这种方式编写响应,而不是使用某些视图技术来输出,如JSP,Velocity,FreeMarker等?

答案 2 :(得分:1)

如果您需要立即解决问题,可以通过增加响应缓冲区的大小来解决此设计问题 - 您必须阅读应用程序服务器的文档以确定是否可行。但是,如果您的站点流量达到峰值,此解决方案将无法扩展,因为您很快就会遇到内存不足问题。

没有视图技术可以保护您免受此问题的影响。在开始编写响应之前,您应该设计应用程序以确定要向用户显示的内容。这意味着提前完成所有数据库访问和业务逻辑。这是我在复杂的系统设计中看到的一个常见问题,它使用懒惰地访问数据库的代理对象。例如。如果从您的视图层访问,ORM与实体关系是坏消息!关于在渲染页面的3/4路上发生的异常,你无能为力。

考虑到这一点,可能会有一些方法通过AJAX注入页面重定向。有没有人听说过这样的解决方案?

祝你好好重新设计你的设计!

答案 3 :(得分:0)

我知道这篇文章很老了,但只是想分享我对此的看法。

我想你实际上可以使用FilterServletResponseWrapper来包装响应并将其传递给链。

也就是说,你可以在包装器类中有一个输出流并写入它而不是写入原始响应的输出流...你可以随时清除包装器的输出流,你可以最终写入完成处理后,原始响应的输出流。

例如,

public class MyResponseWrapper extends HttpServletResponseWrapper {
    protected ByteArrayOutputStream baos = null;
    protected ServletOutputStream stream = null;
    protected PrintWriter writer = null;
    protected HttpServletResponse origResponse = null;

    public MyResponseWrapper( HttpServletResponse response ) {
      super( response );
      origResponse = response;
    }


    public ServletOutputStream getOutputStream()
      throws IOException {
      if( writer != null ) {
        throw new IllegalStateException( "getWriter() has already been " +
                                   "called for this response" );
      }

      if( stream == null ) {
        baos = new ByteArrayOutputStream();
        stream = new MyServletStream(baos);
      }

      return stream;
    }

  public PrintWriter getWriter()
    throws IOException {
      if( writer != null ) {
        return writer;
      }

      if( stream != null ) {
        throw new IllegalStateException( "getOutputStream() has already " +
                                   "been called for this response" );
      }

      baos = new ByteArrayOutputStream();
      stream = new MyServletStream(baos);
      writer = new PrintWriter( stream );

      return writer;
    }

    public void commitToResponse() {
      origResponse.getOutputStream().write(baos.toByteArray());
      origResponse.flush();
    }

    private static class MyServletStream extends ServletOutputStream {
       ByteArrayOutputStream baos;

       MyServletStream(ByteArrayOutputStream baos) {
         this.baos = baos;
       }

       public void write(int param) throws IOException {
         baos.write(param);
       }
    }
    //other methods you want to implement
  }