【发布时间】:2017-02-21 08:49:54
【问题描述】:
我正在尝试在我的应用程序中记录每个传入请求和传出响应。我使用的是 jee 6,所以我没有 ContainerRequestFilter 和 ContainerResponseFilter 类。所以我决定使用过滤器。
我用 @WebFilter("/*") 注释了一个类并实现了 Filter 接口。我成功读取了请求标头和请求正文。遇到一些困难,我还阅读了响应标头和响应正文。下面是一段代码sn-p
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 中的代码质量不是很好。现在我并不担心这个。我想知道这是否是一个正确的想法?如果那样,那么我想专注于代码质量。
【问题讨论】:
标签: jakarta-ee java-ee-6 servlet-filters