春季阅读请求正文两次 [英] Spring reading request body twice
问题描述
在春季,我有一个控制器,其端点如下:
In spring I have a controller with an endpoint like so:
@RequestMapping(method = RequestMethod.POST)
@ResponseStatus(HttpStatus.CREATED)
@ResponseBody
public OutputStuff createStuff(@RequestBody Stuff stuff) {
//my logic here
}
这样,如果在此终结点上执行POST,则请求正文中的JSON将自动反序列化为我的模型(Stuff
).问题是,我只需要记录即将传入的原始JSON!我尝试了不同的方法.
This way if doing a POST on this endpoint, the JSON in request body will be automatically deserialized to my model (Stuff
). The problem is, I just got a requirement to log the raw JSON as it is coming in! I tried different approaches.
- 将
HttpServletRequest
注入到createStuff
中,在此处读取正文并记录:
- Inject
HttpServletRequest
intocreateStuff
, read the body there and log:
代码:
@RequestMapping(method = RequestMethod.POST)
@ResponseStatus(HttpStatus.CREATED)
@ResponseBody
public OutputStuff createStuff(@RequestBody Stuff stuff, HttpServletRequest req) {
StringBuilder sb = new StringBuilder();
req.getReader().getLines().forEach(line -> {
sb.append(line);
});
//log sb.toString();
//my logic here
}
此问题是,当我执行此操作时,将已经执行了读取器的InputStream来将JSON反序列化为Stuff
.所以我会得到一个错误,因为我无法两次读取相同的输入流.
The problem with this is that by the time I execute this, the reader's InputStream would have already been executed to deserialize JSON into Stuff
. So I will get an error because I can't read the same input stream twice.
- 使用自定义
HandlerInterceptorAdapter
,该自定义HandlerInterceptorAdapter
在调用实际处理程序之前将记录原始JSON.
- Use custom
HandlerInterceptorAdapter
that would log raw JSON before the actual handler is called.
代码(部分代码):
public class RawRequestLoggerInterceptor extends HandlerInterceptorAdapter {
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
StringBuilder sb = new StringBuilder();
req.getReader().getLines().forEach(line -> {
sb.append(line);
});
//log sb.toString();
return true;
}
}
此问题的原因是,到对stuff
的反序列化发生时,来自请求的InputStream已经被读取!因此,我将再次获得例外.
The problem with this tho is, that by the time the deserialization to stuff
happens, the InputStream from the request would have been read already! So I would get an exception again.
-
我考虑过但尚未实现的另一个选项将以某种方式迫使Spring使用我的自定义实现
HttpServletRequest
,该实现将缓存输入流并允许对其进行多次读取.我不知道这是否可行,我找不到任何文档或示例!
Another option I considered, but not implemented yet, would be somehow forcing Spring to use my custom implementation of
HttpServletRequest
that would cache the input stream and allow multiple read of it. I have no idea if this is doable tho and I can't find any documentation or examples of that!
另一种选择是不读取端点上的Stuff
,而是将请求正文读取为String
,将其记录下来,然后使用ObjectMapper
等将其反序列化为Stuff
.我也不喜欢这个想法.
Yet another option would be not to read Stuff
on my endpoint, but rather read the request body as String
, log it and then deserialize it to Stuff
using ObjectMapper
or something like that. I do not like this idea either tho.
有没有我未提及和/或不知道的更好的解决方案?我将不胜感激.我正在使用SpringBoot的最新版本.
Are there better solutions, that I did not mention and/or am not aware of? I would appreciate help. I am using the latest release of SpringBoot.
推荐答案
As referenced in this post: How to Log HttpRequest and HttpResponse in a file?, spring provides the AbstractRequestLoggingFilter you can use to log the request.
AbstractRequestLoggingFilter API文档,在这里找到
AbstractRequestLoggingFilter API Docs, found here
这篇关于春季阅读请求正文两次的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!