`

关于jetty和webx对于HttpServletResponse getWriter和getOutputStream的处理

    博客分类:
  • java
 
阅读更多

这个异常经过在jetty的一个简单程序的测试验证,确定问题及分析如下:


这个程序在使用response输出结果时,先调用response的getWriter获得PrintWrite对象后输出内容,然后再调用getOutputStream方法获得outputStream对象后输出二进制内容,然后就跑出上面那个异常了。

这两个方法在jetty容易中是这么处理:
org.eclipse.jetty.server.Response继承自j2ee里面的HttpServletResponse.java类
org.eclipse.jetty.server.Response.java类里面

    public ServletOutputStream getOutputStream() throws IOException
    {
        if (_outputState!=NONE && _outputState!=STREAM)    如果状态为WRITER状态,则抛出异常
            throw new IllegalStateException("WRITER");

        _outputState=STREAM;         把response状态改为STREAM流状态
        return _connection.getOutputStream();
    }

  public PrintWriter getWriter() throws IOException
    {
        if (_outputState!=NONE && _outputState!=WRITER)  如果状态为STREAM,则抛出异常
            throw new IllegalStateException("STREAM");

        /* if there is no writer yet */
        if (_writer==null)
        {
            /* get encoding from Content-Type header */
            String encoding = _characterEncoding;

            if (encoding==null)
            {
                /* implementation of educated defaults */
                if(_mimeType!=null)
                    encoding = null; // TODO getHttpContext().getEncodingByMimeType(_mimeType);

                if (encoding==null)
                    encoding = StringUtil.__ISO_8859_1;

                setCharacterEncoding(encoding);
            }

            /* construct Writer using correct encoding */
            _writer = _connection.getPrintWriter(encoding);
        }
        _outputState=WRITER;             把response状态改为WRITER状态,
        return _writer;
    }

也就是说在j2ee,web应用里面不能同时打开PrintWriter和OutputStream,否则就是抛出上面那个异常。

jetty的response里面有三种状态:
    public static final int
        NONE=0,  未调用getPrintWriter和getOutputStream之前的默认状态
        STREAM=1,  二进制流状态  调用getOutputStream之后的状态
        WRITER=2;   字符流状态
  

解决方法:
   1.在应用中只使用一个,要么都用getPrintWriter,要么都用getOutputStream。
   2.在webx 中的com.alibaba.citrus.service.requestcontext.buffered.impl.BufferedResponseImpl.java类中有下面这么解决方案:
  
    /**
     * 取得输出流。
     * 
     * @return response的输出流
     * @throws IOException 输入输出失败
     */
    @Override
    public ServletOutputStream getOutputStream() throws IOException {
        if (stream != null) {
            return stream;
        }

        if (writer != null) {
            // 如果getWriter方法已经被调用,则将writer转换成OutputStream
            // 这样做会增加少量额外的内存开销,但标准的servlet engine不会遇到这种情形,
            // 只有少数servlet engine需要这种做法(resin)。
            if (writerAdapter != null) {
                return writerAdapter;
            } else {
                log.debug("Attampt to getOutputStream after calling getWriter.  This may cause unnecessary system cost.");
                writerAdapter = new WriterOutputStream(writer, getCharacterEncoding());
                return writerAdapter;
            }
        }

        if (buffering) {
            // 注意,servletStream一旦创建,就不改变,
            // 如果需要改变,只需要改变其下面的bytes流即可。
            if (bytesStack == null) {
                bytesStack = new Stack<ByteArrayOutputStream>();
            }

            ByteArrayOutputStream bytes = new ByteArrayOutputStream();

            bytesStack.push(bytes);
            stream = new BufferedServletOutputStream(bytes);

            log.debug("Created new byte buffer");
        } else {
            stream = super.getOutputStream();
        }

        return stream;
    }

    /**
     * 取得输出字符流。
     * 
     * @return response的输出字符流
     * @throws IOException 输入输出失败
     */
    @Override
    public PrintWriter getWriter() throws IOException {
        if (writer != null) {
            return writer;
        }

        if (stream != null) {
            // 如果getOutputStream方法已经被调用,则将stream转换成PrintWriter。
            // 这样做会增加少量额外的内存开销,但标准的servlet engine不会遇到这种情形,
            // 只有少数servlet engine需要这种做法(resin)。
            if (streamAdapter != null) {
                return streamAdapter;
            } else {
                log.debug("Attampt to getWriter after calling getOutputStream.  This may cause unnecessary system cost.");
                streamAdapter = new PrintWriter(new OutputStreamWriter(stream, getCharacterEncoding()), true);
                return streamAdapter;
            }
        }

        if (buffering) {
            // 注意,servletWriter一旦创建,就不改变,
            // 如果需要改变,只需要改变其下面的chars流即可。
            if (charsStack == null) {
                charsStack = new Stack<StringWriter>();
            }

            StringWriter chars = new StringWriter();

            charsStack.push(chars);
            writer = new BufferedServletWriter(chars);

            log.debug("Created new character buffer");
        } else {
            writer = super.getWriter();
        }

        return writer;
    }


  所以在我们自己的应用中就不要再调用完j2ee的原生response的getPrintWriter之后再调用原生的getOutputStream(),或者调用原生的response的getOutputStream之后再调用getPrintWriter。
 

<!--[endif]-->

  • 大小: 127.7 KB
分享到:
评论

相关推荐

    jetty相关的全部jar包

    jetty-security-9.4.8.v20171121.jar,jetty-io-9.4.8.v20171121.jar,jetty-continuation-9.4.8.v20171121.jar,jetty-client-9.4.8.v20171121.jar,jetty-jmx-9.4.8.v20171121.jar,jetty-plus-9.4.8.v20171121....

    Java Eclipse ee集合jetty和配置

    Java Eclipse ee集合jetty和配置

    《Jetty6_指南书》

    网络上有一些关于jetty的资料,但过去陈旧且 不具有系统性,导致很多人误解jetty的功能,国外目前也没有关于jetty的书籍,所以那些搞翻译的人也没有翻译来源,故决定写一本关于jetty6 的书,以推广jetty在国内的使用...

    linux和windows版本的tomcat和jetty

    本压缩包包含了不同平台——windows以及linux最新的tomcat版本,(包含:tomcat-5.5.36、tomcat-6.0.37、tomcat-7.0.47)。 和jetty-distribution-9.0.6.v20130930。 供java web开发人员去下载

    Jetty和tomcat比较.docx

    1. Tomcat和Jetty都是一种Servlet引擎,他们都支持标准的servlet规范和JavaEE的规范。     不同点: 1. 架构比较 Jetty的架构比Tomcat的更为简单 Jetty的架构是基于Handler来实现的,主要的扩展功能都可以用...

    eclipse jetty插件run-jetty-run-1.3.3

    eclipse jetty插件,从...下载run-jetty-run.zip文件,解压后再编写个links文件丢到eclipse的dropins目录下即可,省去了使用eclipse update方式安装的麻烦。 link文件样例如: path=d:\\eclipse_plugins\\run-jetty-run

    Jetty多版本软件包

    Jetty软件包内容: jetty-distribution-9.4.51.v20230217.tar.gz jetty-distribution-9.4.51.v20230217.zip jetty-home-10.0.15.tar.gz jetty-home-10.0.15.zip jetty-home-11.0.15.tar.gz jetty-home-11.0.15.zip ...

    myeclipse中jetty和svn检出的插件

    myeclipse中jetty和svn检出的插件,包括使用说明等,也可以私聊我,发资源。

    Jetty cometd(Continuation)学习笔记

    Jetty是一个纯Java实现的开源Servlet容器,Jetty也可以作为HTTP服务器和HTTP客户端,Jetty仪器轻巧,稳定和高性能而著称,完全可以胜任企业级Servlet容器的要求。Jetty允许Apache Licence 2.0或者Eclipse Public ...

    jetty6 指南书

    jetty是什么 jetty配置 jetty使用 jetty嵌入 jetty启动 jetty部署 jetty教程 jetty嵌入式 jetty

    jetty嵌入式服务器必须的jar包

    jetty嵌入式服务器开发所必须的jar包,本人使用jetty版本为6.1.3,jar包总数为9个,来自jetty:commons-el-1.0.jar,jasper-compiler-5.5.15,jasper-compiler-jdt-5.5.15.jar,jasper-runtime-5.5.15.jar,jetty-...

    jetty相关所有jar包

    jetty相关所有jar包,包含jar包: jetty-continuation-8.1.15.v20140411,jetty-http-8.1.15.v20140411,jetty-io-8.1.15.v20140411,jetty-security-8.1.15.v20140411,jetty-server-8.1.15.v20140411,jetty-util-8.1.15...

    maven集成jetty所需jar包maven-jetty-plugin,多版本

    maven集成jetty必须jar包maven-jetty-plugin,内含多个版本

    Jetty中文手册

    下载和安装Jetty 如何安装一个Jetty包 如何配置Jetty – 主要文档 如何运行Jetty 用JConsole监控Jetty 如何使用Jetty开发 Jetty HelloWorld教程 Jetty和Maven HelloWorld教程 Jetty(6)入门 (www.itjungle.com) Jetty...

    jetty 9.2.24

    Jetty是一个纯粹的基于Java的网页服务器和Java Servlet容器。 尽管网页服务器通常用来为人们呈现文档,但是Jetty通常在较大的软件框架中用于计算机与计算机之间的通信。 Jetty作为Eclipse基金会的一部分,是一个自由...

    jetty服务器 jetty-distribution-7.3.0.v20110203

    jetty服务器jetty-distribution-7.3.0.v20110203

    Jetty配置支持https

    Jetty配置支持HTTPS以及受信网站证书生成方式

    jetty 9.4.9

    jetty 9.4.9, jetty 容器是轻便型容器,启动速度的确可以 ,附带有servlet-api.jar 和jsp-api.jar 两个jar包

    jetty 学习资料合集

    jetty 学习资料合集 jetty 学习资料合集 jetty 学习资料合集 jetty 学习资料合集

    websocket+tomcat+jetty+netty

    websocket+tomcat+jetty+netty

Global site tag (gtag.js) - Google Analytics