Writers и OutputStreams в приложениях и фильтрах Java EE - PullRequest
1 голос
/ 13 июня 2011

Недавно я обнаружил следующее исключение ...

java.lang.IllegalStateException: не удается получить Writer, поскольку OutputStream уже используется

Я понимаюхарактер исключения;а именно код может использовать Writer или OutputStream, но никогда оба в одном запросе.Как код, находящийся ниже по стеку, должен обрабатывать случай, когда он уже существует?ИЛИ Есть ли шаблон дизайна / арки, который может избежать этой проблемы?

Пример;рассмотрим сторонний фильтр, который украшает выходные данные запроса и получает OutputStream.Как фильтр или сервлет, который должен работать с Writer, должен «знать», что OutputStream уже открыт, и должно ли это заботиться?Обратное также является действительным Q.

Ответы [ 3 ]

2 голосов
/ 13 июня 2011

Я попытаюсь ответить на более конкретный вопрос, поднятый в вашем примере:

Рассмотрим сторонний фильтр, который украшает выходные данные запроса и получает OutputStream. Как фильтр или сервлет, который должен работать с Writer, должен «знать», что OutputStream уже открыт, и должно ли это заботиться?

Servlet API также запрещает использование Writer и OutputStream при заполнении ответа, как указано в документации API для метода ServletResponse.getWriter () :

Либо этот метод, либо getOutputStream () могут быть вызваны для записи тела, а не оба.

Если фильтр (сторонний или другой) хочет записать ответ, особенно после того, как сервлеты его сгенерировали, он должен предположить, что

  • сервлет использовал либо Writer, либо OutputStream для заполнения ответа.
  • сервлет вызвал бы метод close() для Writer или объекта OutputStream.

Чтобы учесть это, фильтр должен создать экземпляр HttpServletResponseWrapper , передать его вниз по потоку в сервлет для заполнения, снова прочитать его, а затем заполнить фактический объект HttpServletResponse, управляемый контейнером.

Вышесказанное также было бы в силе, если бы фильтр сначала заполнил ответ (до дальнейшей обработки запроса). Он должен выполнить заполнение фактического объекта HttpServletResponse, передать обертку вниз по течению, а затем записать содержимое обертки в фактический объект.

2 голосов
/ 13 июня 2011

Подход к дизайну удивительно прост:

  • Не используйте код Java ( scriptlets ) в JSP. Это неявно вызывает getWriter().
  • Не пишите ничего в ответе в сервлете, когда вы собираетесь пересылать в JSP.

Другими словами, если вы придерживаетесь идеологии MVC, вам не о чем беспокоиться.

0 голосов
/ 13 июня 2011

Другой подход заключается в разработке Filter таким образом, чтобы он использовал Writer или OutputStream в зависимости от параметра конфигурации в web.xml. Затем настройте Filter в соответствии с Servlet, для которого он фильтрует запросы.

...