春季阅读请求正文两次 [英] Spring reading request body twice

查看:67
本文介绍了春季阅读请求正文两次的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在春季,我有一个控制器,其端点如下:

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.

  1. HttpServletRequest注入到createStuff中,在此处读取正文并记录:
  1. Inject HttpServletRequest into createStuff, 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.

  1. 使用自定义HandlerInterceptorAdapter,该自定义HandlerInterceptorAdapter在调用实际处理程序之前将记录原始JSON.
  1. 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.

  1. 我考虑过但尚未实现的另一个选项将以某种方式迫使Spring使用我的自定义实现HttpServletRequest,该实现将缓存输入流并允许对其进行多次读取.我不知道这是否可行,我找不到任何文档或示例!

  1. 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆