首页 > 解决方案 > SpringBoot 和 ProtoBuf:如何通过在响应正文中添加错误来使 HTTP 400s 更有用?

问题描述

我们用于ProtobufJsonFormatHttpMessageConverter将 JSON 请求正文解析为 REST 端点中的原型:

  @Bean
  ProtobufHttpMessageConverter protobufHttpMessageConverter() {
    return new ProtobufJsonFormatHttpMessageConverter(
        JsonFormat.parser(), JsonFormat.printer().includingDefaultValueFields());
  }

在请求中,假设有一个枚举,如果值中有错字,例如,

{
     "type": "ELEPHAANT"
}

我得到HTTP 400一个空的响应,控制台有:

DEBUG o.s.w.s.DispatcherServlet - POST "/foo-search", parameters={}
DEBUG o.s.w.s.m.m.a.RequestMappingHandlerMapping - Mapped to com.foobar.MasterController#sample(SampleRequest)
DEBUG o.s.w.s.m.m.a.ServletInvocableHandlerMethod - Could not resolve parameter [0] in public com.foobar.models.ResponseOuterClass$SampleResponse com.foobar.MasterController.Sample(com.foobar.models.SampleRequestOuterClass$SampleRequest): I/O error while reading input message; nested exception is com.google.protobuf.InvalidProtocolBufferException: Invalid enum value: ELEPHAANT for enum type: SampleRequest.Filter.Type
DEBUG o.s.w.s.m.m.a.ExceptionHandlerExceptionResolver - Using @ExceptionHandler com.foobar.advice.ExceptionHandlerAdvice#handleException(Exception, WebRequest)
DEBUG o.s.w.s.m.m.a.HttpEntityMethodProcessor - No match for [*/*], supported: []
DEBUG o.s.w.s.m.m.a.ExceptionHandlerExceptionResolver - Resolved [org.springframework.http.converter.HttpMessageNotReadableException: I/O error while reading input message; nested exception is com.google.protobuf.InvalidProtocolBufferException: Invalid enum value: ELEPHAANT for enum type: ObtSampleRequest.Filter.Type]
DEBUG o.s.w.s.DispatcherServlet - Completed 400 BAD_REQUEST

控制台日志中的问题很清楚:

Invalid enum value: ELEPHAANT for enum type: ObtSampleRequest.Filter.Type

我可以通过包含上述信息以某种方式使响应正文更有用吗?

标签: javaspringspring-bootprotocol-buffersprotobuf-java

解决方案


你可以想出一个@RestControllerAdvice

@RestControllerAdvice
public class MyAdvice {

    @ExceptionHandler(HttpMessageNotReadableException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public String handle(HttpMessageNotReadableException e) {
       return e.getMessage(); // or return a nice error object with the nested exception's msg
  }

}

推荐阅读