记录 HttpRequest 参数和请求正文
我正在尝试为我的网络应用程序创建请求日志。我正在使用Spring 3。 0.
我实现了一个扩展 HandlerInterceptorAdapter 的类,并使用 preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) 来拦截请求。
在该方法中,我希望能够记录请求正文(我的参数是直接写入请求正文的 XML 中的对象),为此我使用 request.getReader();
问题是 - 稍后当 spring 控制器尝试读取请求时,我将收到一个 IllegalStateException
。
有办法做我想做的事吗?
I am trying to create a request log for my web app. I am using Spring 3.
0.
I implemented a class extending HandlerInterceptorAdapter
and used the preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
to intercept the request.
In the method i want to be able to log the request body (my parameters are objects in XML that are written directly to the request body), and for that i use request.getReader();
The problem is - later on I will get an IllegalStateException
when the spring controller tries to read the request.
Is there a way to do what I intend?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
您可以使用过滤器来做到这一点。请求参数很容易处理。
然而处理请求体会困难得多
并且需要包装 servlet 请求,请参阅: HttpServletRequest。
您需要查看传入请求有多大,并决定是否要将请求正文存储为 tmp 文件或字符串。
您将需要使用您的文件或用于日志记录的已保存字符串覆盖 ServetRequest.getInputStream()。
如果请求正文很大,我建议将输入流放入缓冲输入流中,然后读取正文的开头。
You can do this with a filter. The request parameters are easy to handle.
However dealing with the request body will be much more difficult
and will require wrapping the servlet request see: HttpServletRequest.
You will need to look how big the incoming request is and decide whether you want to store the request body as a tmp file or string.
You will need to override ServetRequest.getInputStream() with your file or saved string that used for logging.
If the request body is huge I recommend putting the input stream into a buffered input stream and then reading the start of the body.
Spring 有一个现成的过滤器可以为您执行此操作 - 请参阅 这个答案。
请注意,使用此解决方案时,仅在请求处理完成并且应用程序已读取请求正文后才会记录请求正文。
Spring has a ready filter to do that for you - see usage of
AbstractRequestLoggingFilter
and its subclasses described in this answer.Be aware that when using this solution, the request body will be logged only after the request processing is complete and the body has been read by your application.
小请求的简单实现。不要将其用于多部分请求。
Simple implementation for small requests. Don't use it for multipart request.
使用
TeeInputStream
。这会同时写入两个流:源输入流和一些输出流。只需重写请求包装器中的 ServletInputStream 并从 TeeInputStream 读取即可。然后,您可以在调用chain.doFilter()
后从输出流中读取:This can be accomplished fairly easily using
TeeInputStream
. This writes to two streams at once: the source input stream, and some output stream. Simply override theServletInputStream
in the request wrapper, and read from theTeeInputStream
. You can then read from the output stream after callingchain.doFilter()
: