Форма ответа журнала (HTML) из HttpServletResponse с использованием Spring MVC HandlerInterceptorAdapter

Я пытаюсь войти (просто для того, чтобы просто написать для простоты) окончательный визуализированный HTML, который будет возвращен HttpServletResponse. (т.е. тело). С этой целью я использую HandlerInterceptorAdapter из Spring MVC следующим образом:

public class VxmlResponseInterceptor extends HandlerInterceptorAdapter {
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println(response.toString());
    }
}

Это работает как ожидалось, и я вижу заголовки HTTP-ответа в консоли. Мой вопрос в том, есть ли относительно простой способ зарегистрировать весь орган ответа (то есть конечный визуализированный HTML) на консоль, не прибегая к выполнению прыгающих гнезд с помощью PrintWriters, OutputStream и т.п.

Спасибо заранее.

Ответ 1

Это лучше сделать с помощью сервлета Filter, а не Spring HandlerInterceptor, по той причине, что a Filter разрешено заменять объекты запроса и/или ответа, и вы можете использовать этот механизм для подстановки ответа с помощью обертки, которая регистрирует вывод ответа.

Это будет связано с написанием подкласса HttpServletResponseWrapper, переопределяя getOutputStream (и, возможно, также getWriter()). Эти методы будут возвращать реализации OutputStream/PrintWriter, которые отфильтровывают поток ответов в журнале, в дополнение к отправке в исходное место назначения. Простой способ сделать это - TeeOutputStream из Apache Commons IO, но это не сложно реализовать самостоятельно.

Вот пример того, что вы могли бы сделать, используя Spring GenericFilterBean и DelegatingServletResponseStream, а также TeeOutputStream, чтобы облегчить задачу:

public class ResponseLoggingFilter extends GenericFilterBean {

   @Override
   public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
      HttpServletResponse responseWrapper = loggingResponseWrapper((HttpServletResponse) response);     
      filterChain.doFilter(request, responseWrapper);
   }

   private HttpServletResponse loggingResponseWrapper(HttpServletResponse response) {
      return new HttpServletResponseWrapper(response) {
         @Override
         public ServletOutputStream getOutputStream() throws IOException {
            return new DelegatingServletOutputStream(
               new TeeOutputStream(super.getOutputStream(), loggingOutputStream())
            );
         }
      };
   }

   private OutputStream loggingOutputStream() {
      return System.out;
   }
}

Это записывает все в STDOUT. Если вы хотите войти в файл, это станет более сложным, что бы убедиться, что потоки закрыты и так далее, но принцип остается тем же.

Ответ 2

Если вы используете (или рассматриваете) logback в качестве своей рамки ведения журнала, есть уже хороший сервлет-фильтр, который точно выполняет что. Ознакомьтесь с разделом TeeFilter в документации.

Ответ 3

Я искал способ регистрации полного HTTP-запроса/ответа на некоторое время и обнаружил, что он был решен для меня в Tomcat 7 RequestDumperFilter. Он работает как рекламируемый из контейнера Tomcat 7. Если вы хотите использовать его в Jetty, класс работает отлично автономно или, как я, копировал и адаптировался к конкретным потребностям моей среды.

Ответ 4

Я сделал небольшую библиотеку spring-mvc-logger, доступную через центральный центр maven.

Добавить в pom.xml:

<dependency>
    <groupId>com.github.isrsal</groupId>
    <artifactId>spring-mvc-logger</artifactId>
    <version>0.2</version>
</dependency>

Добавить в web.xml:

<filter>
    <filter-name>loggingFilter</filter-name>
    <filter-class>com.github.isrsal.logging.LoggingFilter</filter-class>
</filter>

<filter-mapping>
    <filter-name>loggingFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

Добавить в log4j.xml:

<logger name="com.github.isrsal.logging.LoggingFilter">
    <level value="DEBUG"/>
</logger>