Writers and OutputStreams in Java EE applications and filters

空扰寡人 提交于 2019-12-13 12:18:35

问题


I've recently encountered the following exception...

java.lang.IllegalStateException: Cannot obtain Writer because OutputStream is already in use

I understand the nature of the exception; namely the code can use a Writer or OutputStream but never both in the same request. How is code further down the stack supposed to handle the case where one already exists? OR is there a design/arch pattern that can avoid this problem in the first place?

Example; consider a 3rd party filter that decorates the output of a request and it gets an OutputStream. How is a filter or a servlet that needs to work with a Writer supposed to "know" that an OutputStream was already opened and should it care? The converse is also a valid Q.


回答1:


I'll attempt to address the more specific question raised in your example:

consider a 3rd party filter that decorates the output of a request and it gets an OutputStream. How is a filter or a servlet that needs to work with a Writer supposed to "know" that an OutputStream was already opened and should it care?

The Servlet API also disallows the use of both Writer and OutputStream when populating the response, as indicated in the API documentation for the ServletResponse.getWriter() method:

Either this method or getOutputStream() may be called to write the body, not both.

If a filter (third party or otherwise) wants to write to the response, especially after servlet(s) have generated it, it ought to assume that

  • the servlet has used either the Writer or the OutputStream to populate the response.
  • the servlet would have invoked the close() method on the Writer or the OutputStream object.

To account for this, the filter must create a HttpServletResponseWrapper instance, pass it downstream to the servlet for population, read it back in again, and then populate the actual container-managed HttpServletResponse object.

The above would also hold good if the filter were to populate the response first (before the request is processed further). It should perform the population on the actual HttpServletResponse object, pass a wrapper downstream, and then write the contents of the wrapper to the actual object.




回答2:


The design approach is surprisingly easy:

  • Do not use Java code (scriptlets) in JSP. This implicitly triggers getWriter().
  • Do not write anything to the response in a Servlet when you're going to forward to a JSP.

In other words, if you adhere the MVC ideology, there's basically nothing to worry about.




回答3:


Another approach is to design the Filter so that it uses the Writer or OutputStream depending on a configuration setting in the web.xml. Then configure the Filter according to Servlet that it is filtering requests for.



来源:https://stackoverflow.com/questions/6330288/writers-and-outputstreams-in-java-ee-applications-and-filters

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!