Как я могу прочитать поток вывода HttpServletReponses?

Я хочу создать фильтр сервлета, который будет читать содержимое ответа после его обработки и завершения и возвращать эту информацию в формате XML или PDF или что-то еще. Но я не уверен, как получить какую-либо информацию из объекта HttpServletResponse. Как я могу получить эту информацию?


person DyreSchlock    schedule 31.03.2009    source источник


Ответы (4)


Добавьте это в java-файл фильтра.

static class MyHttpServletResponseWrapper 
  extends HttpServletResponseWrapper {

  private StringWriter sw = new StringWriter(BUFFER_SIZE);

  public MyHttpServletResponseWrapper(HttpServletResponse response) {
    super(response);
  }

  public PrintWriter getWriter() throws IOException {
    return new PrintWriter(sw);
  }

  public ServletOutputStream getOutputStream() throws IOException {
    throw new UnsupportedOperationException();
  }

  public String toString() {
    return sw.toString();
  }
}

Используйте следующий код:

HttpServletResponse httpResponse = (HttpServletResponse) response;
MyHttpServletResponseWrapper wrapper = 
  new MyHttpServletResponseWrapper(httpResponse);

chain.doFilter(request, wrapper);

String content = wrapper.toString();

Переменная содержимого теперь имеет выходной поток. Вы также можете сделать это для двоичного содержимого.

person Community    schedule 31.03.2009
comment
Да, я думаю, что использование Servlet Reponse Wrapper и захват вывода, когда он написан, - это лучший способ сделать это. - person DyreSchlock; 02.04.2009
comment
Однако код, обрабатывающий запрос, использует выходной поток. Можно использовать TeeOutputStream. ( commons.apache.org/io/apidocs /org/apache/commons/io/output/ ) - person DyreSchlock; 02.04.2009
comment
какое разумное значение BUFFER_SIZE? - person asgs; 02.09.2015
comment
Создал LoggingFilter реализует фильтр, зарегистрировал его, использую свой код и он не работает, просто emtry строки на выходе. Не могли бы вы показать полный (завершенный) код версии? - person user2602807; 13.10.2017

Теперь у Spring есть функция для этого. Все, что вам нужно сделать, это использовать [ContentCachingResponseWrapper], у которого есть метод public byte[] getContentAsByteArray().

Предлагаю сделать WrapperFactory, который позволит сделать его настраиваемым, использовать ли ResponseWrapper по умолчанию или ContentCachingResponseWrapper.

person omilus    schedule 14.04.2017

Я мало знаю, что вы можете получить данные из объекта HttpServletResponse как такового. Возможно, имеет смысл структурировать ваше приложение таким образом, чтобы запросы передавались соответствующим обработчикам и передавались с объектами передачи данных, из которых вы можете построить соответствующий окончательный ответ. Таким образом, вы никогда не изменяете более одного объекта ответа и не должны читать из него.

Я знаю, что это не прямой ответ, но именно так я бы и задал вопрос.

person Stefan Kendall    schedule 31.03.2009
comment
В конце концов, я бы сделал то же самое и поставил бы себя в положение, когда мне не нужно было бы читать ответ. Но на самом деле обработка запросов, которую я использую, довольно черная, и с ней нельзя испортить:/ - person DyreSchlock; 31.03.2009

Я не верю, что вы обязательно можете это сделать, учитывая, что запись в выходной поток может привести к тому, что данные будут сброшены на клиент до того, как какие-либо фильтры сервлета будут вызваны после заполнения. Как предполагает iftrue, рекомендуется использовать другую архитектуру, чтобы сгенерировать ваш XML (скажем), а затем регенерировать в любом желаемом формате вывода.

РЕДАКТИРОВАТЬ: прочитав ваш ответ на публикацию iftrue, если вы действительно не можете вмешиваться в текущую обработку, возможно, вам требуется сервлет для проксирования вашего запроса, захватите вывод из исходного вывода, а затем при необходимости имитировать. Очень противно, однако :-(

person Brian Agnew    schedule 31.03.2009