当前位置: 首页 > 面试题库 >

如何读取和复制HTTP Servlet响应输出流内容以进行日志记录

姬旭
2023-03-14
问题内容

我已经在Java网络服务器(实际上是appengine)中创建了一个过滤器,用于记录传入请求的参数。我还想记录我的网络服务器写入的结果响应。尽管我可以访问响应对象,但是我不确定如何从中获取实际的字符串/内容响应。

有任何想法吗?


问题答案:

你需要创建一个,在Filter其中ServletResponse用自定义HttpServletResponseWrapper实现包装参数,在其中覆盖getOutputStream()getWriter()并返回一个自定义ServletOutputStream实现,在该实现中你将写入的字节复制到基本抽象OutputStream#write(int b)方法中。然后,你将包装的自定义传递HttpServletResponseWrapperFilterChain#doFilter()调用,最后,你应该能够在调用之后获得复制的响应。

换句话说Filter:

@WebFilter("/*")
public class ResponseLogger implements Filter {

    @Override
    public void init(FilterConfig config) throws ServletException {
        // NOOP.
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
        if (response.getCharacterEncoding() == null) {
            response.setCharacterEncoding("UTF-8"); // Or whatever default. UTF-8 is good for World Domination.
        }

        HttpServletResponseCopier responseCopier = new HttpServletResponseCopier((HttpServletResponse) response);

        try {
            chain.doFilter(request, responseCopier);
            responseCopier.flushBuffer();
        } finally {
            byte[] copy = responseCopier.getCopy();
            System.out.println(new String(copy, response.getCharacterEncoding())); // Do your logging job here. This is just a basic example.
        }
    }

    @Override
    public void destroy() {
        // NOOP.
    }

}

习惯HttpServletResponseWrapper:

public class HttpServletResponseCopier extends HttpServletResponseWrapper {

    private ServletOutputStream outputStream;
    private PrintWriter writer;
    private ServletOutputStreamCopier copier;

    public HttpServletResponseCopier(HttpServletResponse response) throws IOException {
        super(response);
    }

    @Override
    public ServletOutputStream getOutputStream() throws IOException {
        if (writer != null) {
            throw new IllegalStateException("getWriter() has already been called on this response.");
        }

        if (outputStream == null) {
            outputStream = getResponse().getOutputStream();
            copier = new ServletOutputStreamCopier(outputStream);
        }

        return copier;
    }

    @Override
    public PrintWriter getWriter() throws IOException {
        if (outputStream != null) {
            throw new IllegalStateException("getOutputStream() has already been called on this response.");
        }

        if (writer == null) {
            copier = new ServletOutputStreamCopier(getResponse().getOutputStream());
            writer = new PrintWriter(new OutputStreamWriter(copier, getResponse().getCharacterEncoding()), true);
        }

        return writer;
    }

    @Override
    public void flushBuffer() throws IOException {
        if (writer != null) {
            writer.flush();
        } else if (outputStream != null) {
            copier.flush();
        }
    }

    public byte[] getCopy() {
        if (copier != null) {
            return copier.getCopy();
        } else {
            return new byte[0];
        }
    }

}

习惯ServletOutputStream:

public class ServletOutputStreamCopier extends ServletOutputStream {

    private OutputStream outputStream;
    private ByteArrayOutputStream copy;

    public ServletOutputStreamCopier(OutputStream outputStream) {
        this.outputStream = outputStream;
        this.copy = new ByteArrayOutputStream(1024);
    }

    @Override
    public void write(int b) throws IOException {
        outputStream.write(b);
        copy.write(b);
    }

    public byte[] getCopy() {
        return copy.toByteArray();
    }

}


 类似资料:
  • 问题内容: 我有一个要登录的Maven&Spring应用程序。我热衷于使用SLF4J。 我想将所有配置文件放入包含log4j.xml的目录{classpath} / config中,然后使用spring bean进行初始化。 例如 但是,我得到此警告,没有日志记录。 log4j:WARN找不到记录器的附加程序(org.springframework.context.support.ClassPat

  • 问题内容: 我想制作一个Servlet过滤器,该过滤器将在处理和完成响应后读取响应的内容,并以XML或PDF或其他方式返回该信息。但是我不确定如何从HttpServletResponse对象中获取任何信息。我如何获得此信息? 问题答案: 将此添加到过滤器java文件。 使用以下代码: 现在,content变量具有输出流。您也可以对二进制内容执行此操作。

  • 我想用IntelliJ IDEA2018.3.4将控制台输出记录到一个文件中。 我找到了这个答案,但是,我需要的是日志文件来记录多次运行,相反,最后一次运行会覆盖日志文件。 根据官方文档,我应该通过勾选“run/Debug Configurations”中的“Skip Content”复选框来获得连续日志记录,但我仍然只能获得日志中的最后一次运行。 我这样做对吗?还是有别的办法?

  • 徒步旅行例子 我们首先创建到应用程序的三个连接(内存池、共识和查询)(在本例中本地运行 kvstore)。 I[10-04|13:54:27.364] Starting multiAppConn module=proxy impl=multiAppConn I[10-04|13:54:27.366] Starting localClient

  • 我有一个输入流,我想将其写入HttpServletResponse。有一种方法,由于使用字节[],需要花费的时间太长 我想知道在速度和效率方面,什么可能是最好的方法。

  • 问题内容: 许多人不确定如何将Liquibase的日志记录修复到控制台或文件中。 是否可以将liquibase日志记录到slf4j? 问题答案: 有,但是有点模糊。使用SLF4J和Log4J引用修复的liquibase日志记录: 有 简单的方法 ,通过在依赖下降: 现在,前两个是您的日常日志记录框架(slf4j api和log4j实现)。这些是您对标准log4j依赖项的补充,因为它们所做的只是路由