处理空请求正文(protobuf3 编码)

Handling empty request body (protobuf3 encoded)

我有一个 Spring 引导应用程序 运行。 Requests/responses 发送 protobuf (Protobuf3) 编码。

我的(简化的)REST 控制器:

@RestController
public class ServiceController {
    @RequestMapping(value = "/foo/{userId}", method = RequestMethod.POST)
    public void doStuff(@PathVariable int userId, @RequestBody(required = false) Stuff.Request pbRequest) {
        // Do stuff
    }
}

我的(简化的)protobuf3 架构:

syntax = "proto3";

message Request {
    int32 data = 1;
}

我的内容协商可用的配置:

@Configuration
public class ProtobufConfig {
    @Bean
    ProtobufHttpMessageConverter protobufHttpMessageConverter() {
        return new ProtobufHttpMessageConverter();
    }
}

只要请求正文设置了一些字节,一切都会正常进行。但是如果只发送默认值,protobuf 不会写入任何字节。一旦我收到包含 data = 0 的请求消息,生成的字节就是空的。在应用程序端,请求主体是 null,不会被转换为 protobuf 消息(如果请求主体设置为 required = true,它甚至会抛出异常)。 ProtobufHttpMessageConverter 根本不处理 HTTP 输入消息。有办法处理吗?

我找到了处理它的方法。但它使用反射,这真的是我不想拥有的东西:

@ControllerAdvice
public class RequestBodyAdviceChain implements RequestBodyAdvice {

    @Override
    public boolean supports(MethodParameter methodParameter, Type type,
            Class< ? extends HttpMessageConverter< ? >> aClass) {
        return true;
    }

    @Override
    public Object handleEmptyBody(Object body, HttpInputMessage httpInputMessage, MethodParameter methodParameter,
            Type type, Class< ? extends HttpMessageConverter< ? >> aClass) {
        try {
            Class<?> cls = Class.forName(type.getTypeName());
            Method m = cls.getMethod("getDefaultInstance");
            return m.invoke(null);
        } catch (Exception e) {
            e.printStackTrace();
        }

        return body;
    }

    @Override
    public HttpInputMessage beforeBodyRead(HttpInputMessage httpInputMessage, MethodParameter methodParameter,
            Type type, Class< ? extends HttpMessageConverter< ? >> aClass) throws IOException {
        return httpInputMessage;
    }

    @Override
    public Object afterBodyRead(Object body, HttpInputMessage httpInputMessage, MethodParameter methodParameter, Type type,
            Class< ? extends HttpMessageConverter< ? >> aClass) {
        return body;
    }
}

因此,在主体为空的情况下,我创建了 protobuf 消息对象的默认实例。