gpt4 book ai didi

jakarta-ee - 如何使用保留请求正文和响应正文的 servlet 过滤器记录请求和响应?

转载 作者:行者123 更新时间:2023-12-04 01:51:09 27 4
gpt4 key购买 nike

我正在尝试在我的应用程序中记录每个传入请求和传出响应。我使用的是 jee 6,所以我没有 ContainerRequestFilter 和 ContainerResponseFilter 类。所以我决定使用过滤器。

我用 @WebFilter("/*") 注释了一个类并实现了 Filter 接口(interface)。我成功读取了请求 header 和请求正文。遇到一些困难,我还阅读了响应 header 和响应正文。下面是一个代码片段

MyHttpServletResponseWrapper wrapper = new MyHttpServletResponseWrapper((HttpServletResponse) response);
chain.doFilter(request, wrapper);

MyHttpServletResponseWrapper 类
public class MyHttpServletResponseWrapper extends HttpServletResponseWrapper {
private StringWriter sw = new StringWriter();
public MyHttpServletResponseWrapper(HttpServletResponse response) { super(response); }

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

public ServletOutputStream getOutputStream() {
return new ServletOutputStream (){
public void write(int B) { sw.append((char) B); }
};
}

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

记录响应后,我将响应写回输出流,以便客户端可以接收响应。下面是代码
logResponse(wrapper);
response.getOutputStream().write(wrapper.getCopy().getBytes());

我无法理解的是,如何在读取请求体后将其放回输入流中。

在 Jersey 等标准 API 中,有一种方便的方法可以使用 setEntityInputStream(inputStream) 将其放回原处

我如何使用标准的 Java ServletOutputStream api 来做到这一点。

我不是想重新发明轮子。我试图避免使用 Jersey,以便我的代码可以轻松迁移到新的 jee 版本。另外我想了解像 Jersey 这样的 API 是如何做到的。

要阅读正文的回复,我阅读了以下链接,但它对我不起作用。 Container 抛出异常,说 writer 已经获得。

Capture and log the response body

附言

我想我想出了如何设置输入流。下面是一些代码
MyRequestWrapper requestwrapper = new MyRequestWrapper((HttpServletRequest) request);

chain.doFilter(requestwrapper, wrapper);

MyRequestWrapper 类
public class MyRequestWrapper extends HttpServletRequestWrapper {
String body;
int counter;
public MyRequestWrapper(HttpServletRequest request) { super(request); }

public void setBody(String body) { this.body = body;}

public ServletInputStream getInputStream() {
return new ServletInputStream() {
public interest read() throws IOException {
if(counter >=body.length()) return -1;
return body.charAt(counter++);
}
};
}
}

我知道重写的 getInputStream 和 getOutputStream 中的代码质量不是很好。现在我并不担心这个。我想知道这是否是一个正确的想法?如果那样的话,那么我想专注于代码质量。

最佳答案

/** I know its too late but it can be helpfull for others as well. **//
import java.io.IOException;
import java.io.UnsupportedEncodingException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.util.ContentCachingRequestWrapper;
import org.springframework.web.util.ContentCachingResponseWrapper;

public class ApiIOLoggerFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) {}
@Override
public void destroy() {}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
if (request instanceof HttpServletRequest && response instanceof HttpServletResponse) {
ContentCachingRequestWrapper requestWrapper = new ContentCachingRequestWrapper((HttpServletRequest) request);
ContentCachingResponseWrapper responseWrapper = new ContentCachingResponseWrapper((HttpServletResponse) response);
try {
chain.doFilter(requestWrapper, responseWrapper);
} finally {
performRequestAudit(requestWrapper);
performResponseAudit(responseWrapper);
}
} else {
chain.doFilter(request, response);
}
}

private void performRequestAudit(ContentCachingRequestWrapper requestWrapper) {
if (requestWrapper != null && requestWrapper.getContentAsByteArray() != null && requestWrapper.getContentAsByteArray().length > 0) {
logger.info("\n Headers:: {} \n Request Body:: {}", new ServletServerHttpRequest((HttpServletRequest)requestWrapper.getRequest()).getHeaders(),
getPayLoadFromByteArray(requestWrapper.getContentAsByteArray(), requestWrapper.getCharacterEncoding()));
}
}

private void performResponseAudit(ContentCachingResponseWrapper responseWrapper)
throws IOException {
if (responseWrapper != null && responseWrapper.getContentAsByteArray() != null
&& responseWrapper.getContentAsByteArray().length > 0) {
logger.info("Response Body:: {}", getPayLoadFromByteArray(responseWrapper.getContentAsByteArray(),
responseWrapper.getCharacterEncoding()));
} else {
performErrorResponseAudit(responseWrapper);
}
responseWrapper.copyBodyToResponse();
}

private void performErrorResponseAudit(ContentCachingResponseWrapper responseWrapper) {
logger.warn("HTTP Error Status Code::" + responseWrapper.getStatus());
}

private String getPayLoadFromByteArray(byte[] requestBuffer, String charEncoding) {
String payLoad = "";
try {
payLoad = new String(requestBuffer, charEncoding);
} catch (UnsupportedEncodingException unex) {
payLoad = "Unsupported-Encoding";
}
return payLoad;
}

}

关于jakarta-ee - 如何使用保留请求正文和响应正文的 servlet 过滤器记录请求和响应?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40000507/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com