处理空请求正文(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 消息对象的默认实例。
我有一个 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 消息对象的默认实例。