2017-03-03 143 views
1

我有一个Spring Boot应用程序正在运行。请求/响应发送protobuf(Protobuf3)编码。处理空请求体(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,它甚至会引发异常)。 HTTP输入消息根本没有被ProtobufHttpMessageConverter处理。有办法处理吗?

回答

1

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

@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消息对象的默认实例。