Bri*_*asa 15 java servlets jax-rs jersey
我正在尝试在JAX-RS ExceptionMapper中检索请求的主体.到目前为止,这是我的代码:
@Provider @Componenet
public class BaseExceptionMapper implements ExceptionMapper<Exception> {
@Context private HttpServletRequest request;
@Override
public Response toResponse(Exception ex) {
// Trying to retrieve request body for logging throws an error
String requestBody = IOUtils.toString(request.getInputStream());
}
}
Run Code Online (Sandbox Code Playgroud)
所以我的困境是我无法获取日志记录的请求体,因为servlet API不允许你多次为请求调用request.getInputStream()/ request.getReader()(并且JAX-RS显然是在调用它解析请求).有谁知道是否有办法做我想做的事情?
小智 11
这个问题有点老了,但答案仍然可以帮助别人.我的例子也取决于Commons-Io.
您可以创建ContainerRequestFilter并使用TeeInputStream代理/复制原始InputStream:
@Provider
@Priority(Priorities.ENTITY_CODER)
public class CustomRequestWrapperFilter implements ContainerRequestFilter {
@Override
public void filter(ContainerRequestContext requestContext)
throws IOException {
ByteArrayOutputStream proxyOutputStream = new ByteArrayOutputStream();
requestContext.setEntityStream(new TeeInputStream(requestContext.getEntityStream(), proxyOutputStream));
requestContext.setProperty("ENTITY_STREAM_COPY", proxyOutputStream);
}
}
Run Code Online (Sandbox Code Playgroud)
并在ExceptionMapper中使用@Inject和javax.inject.Provider来获取注入的ContainerRequest.
ExceptionMapper看起来像这样:
@Provider
public class BaseExceptionMapper implements ExceptionMapper<Exception> {
@Inject
private javax.inject.Provider<ContainerRequest> containerRequestProvider;
@Override
public Response toResponse(Exception exception) {
ByteArrayOutputStream bos = (ByteArrayOutputStream) containerRequestProvider
.get().getProperty("ENTITY_STREAM_COPY");
String requestBody = bos.toString();
...
}
}
Run Code Online (Sandbox Code Playgroud)
当我还使用了@Component注释时,没有使用我的ExceptionMapper.我认为@Provider就足够了.
一种可能的解决方案是使用 servlet 过滤器并包装请求,这允许您拦截对请求输入流的读取调用。伪代码示例(取决于commons-io):
import org.apache.commons.io.output.StringBuilderWriter;
import org.apache.commons.io.input.TeeInputStream;
class MyHttpRequest extends HttpServletRequestWrapper {
private StringBuilderWriter myString = new StringBuilderWriter();
private InputStream myIn;
public MyHttpRequest(HttpServletRequest request) {
super(request);
myIn = new TeeInputStream(request.getInputStream(), myString);
}
@Override public ServletInputStream getInputStream()
throws java.io.IOException {
// this will need an extra wrapper to compile
return myIn;
}
public String getRequestBody() {
return myString.toString();
}
}
Run Code Online (Sandbox Code Playgroud)
筛选:
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
MyHttpRequest wrapper = new MyHttpRequest((HttpServletRequest) request);
chain.doFilter(wrapper, response, chain);
}
Run Code Online (Sandbox Code Playgroud)
映射器:
@Context private HttpServletRequest request;
@Override public Response toResponse(Exception ex) {
String body = "";
if (this.request instanceof MyHttpRequest) {
body = ((MyHttpRequest)request).getRequestBody()
}
}
Run Code Online (Sandbox Code Playgroud)
您需要一个包装类ServletInputStream,您可以在此处找到示例实现:修改 HttpServletRequest body
| 归档时间: |
|
| 查看次数: |
8388 次 |
| 最近记录: |