spring阅读请求正文两次
问题内容:
在spring,我有一个带有端点的控制器,如下所示:
@RequestMapping(method = RequestMethod.POST)
@ResponseStatus(HttpStatus.CREATED)
@ResponseBody
public OutputStuff createStuff(@RequestBody Stuff stuff) {
//my logic here
}
这样,如果对此端点执行POST,请求主体中的JSON将自动反序列化到我的模型(Stuff
)。问题是,我只需要记录即将传入的原始JSON!我尝试了不同的方法。
- 注射
HttpServletRequest
入createStuff
读体内有和日志:
码:
@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
。所以我会得到一个错误,因为我无法两次读取相同的输入流。
- 使用
HandlerInterceptorAdapter
将在调用实际处理程序之前记录原始JSON的自定义。
代码(部分):
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已经被读取!因此,我将再次获得例外。
-
我考虑过但尚未实现的另一个选项是以某种方式迫使Spring使用我的自定义实现,
HttpServletRequest
该实现将缓存输入流并允许对其进行多次读取。我不知道这是否可行,我找不到任何文档或示例! -
还有一种选择是不读取
Stuff
我的端点,而是将请求正文读取为String
,将其记录下来,然后反序列化为Stuff
使用ObjectMapper
或类似的东西。我也不喜欢这个想法。
有没有我没有提到和/或不知道的更好的解决方案?我将不胜感激。我正在使用最新版本的SpringBoot。
问题答案:
如何在文件中记录HttpRequest和HttpResponse?,spring提供了AbstractRequestLoggingFilter,可用于记录请求。
在此处找到
AbstractRequestLoggingFilter
API文档