2016-11-04 68 views
0

Spring允许在中定义@ExceptionHandlers春季返回JSON HTTP 406(NOT_ACCEPTABLE)

我已经为HTTP 400,404,405,...定义了很多其他ExceptionHandlers ...但HTTP 406(NOT_ACCEPTABLE)的ExceptionHandler似乎不起作用。处理程序被触发,我检查了日志中的结果,但没有使用。

我的目标是它返回一个带有JSON主体的HTTP 406。

变1

@ResponseStatus(HttpStatus.NOT_ACCEPTABLE) 
@ExceptionHandler(HttpMediaTypeNotAcceptableException.class) 
public ErrorDTO requestMethodNotSupported(final HttpMediaTypeNotAcceptableException e) { 
    final ErrorDTO dto = new ErrorDTO(HttpStatus.NOT_ACCEPTABLE, "http.media_not_acceptable"); 
    return dto; 
} 

变2

@ExceptionHandler(HttpMediaTypeNotAcceptableException.class) 
public ResponseEntity<ErrorDTO> requestMethodNotSupported2(final HttpMediaTypeNotAcceptableException e) { 
    final ErrorDTO dto = new ErrorDTO(HttpStatus.NOT_ACCEPTABLE, "http.media_not_acceptable"); 
    return ResponseEntity.status(HttpStatus.NOT_ACCEPTABLE).contentType(MediaType.APPLICATION_JSON_UTF8).body(dto); 
} 

但我总是从Tomcat类似这样的HTML响应:

HTTP状态406 -

类型:状态报告

消息:

描述:由 该请求所标识的资源仅能够产生根据该请求“接受” 头与 特性不能接受的应答。

代替

{ “的errorCode”:406, “的errorMessage”: “http.media_not_acceptable” }

请求报头:

  • 接受:申请/东西 - 即,不能待本

实际响应报头:

  • 的Content-Type:text/html的

预期的 - 响应报头:

  • Content-Type:application/json

我知道我可以简单地“修复”由客户端发送的Accept-Header,但是如果服务器不知道如何响应,则应该始终以JSON响应。

我使用Spring 4.3.3.RELEASE和Jackson 2.8.4。

回答

0

终于让我找到了一个解决方案:

而不是返回一个序列化的对象只是直接返回的字节数。

private final ObjectMapper objectMapper = new ObjectMapper(); 

@ExceptionHandler(HttpMediaTypeNotAcceptableException.class) 
public ResponseEntity<byte[]> requestMethodNotSupported(HttpMediaTypeNotAcceptableException e) { 
    Object response = ...; 
    try { 
     return ResponseEntity.status(HttpStatus.NOT_ACCEPTABLE) 
       .contentType(MediaType.APPLICATION_JSON_UTF8) 
       .body(objectMapper.writeValueAsBytes(response)); 
    } catch (Exception subException) { 
     // Should never happen!!! 
     subException.addSuppressed(e); 
     throw subException; 
    } 
} 

编辑:

正如你可以创建自定义HttpMessageConverter<ErrorResponse>ErrorResponse对象的替代品。

  • 转到您或创建WebMvcConfigurerAdapter#extendMessageConverters(converters)
  • 一个IMPL选择一个HttpMessageConverter,它能够创建您预期的结果/内容类型。
  • 把它包在某种程度上符合下列条件:
    • getSupportedMediaTypes()返回MediaType.ALL
    • canRead()返回false
    • canWrite()回报仅供ErrorResponse
    • write()真设定强制CT和转发您的预期内容类型到封装的转换器。
  • 将你的包装添加到转换器列表。
    • 如果添加为第一要素则总是返回您预期的结果(强制)
      • 要求:JSON,返回:强制CT
      • 要求:XML,返回:强制CT
      • 要求:图像,返回:强制CT
    • 如果添加为最后一个元素,那么它只会返回结果作为您的预期结果,如果没有其他匹配的转换器(回退)
      • 要求:JSON,返回:JSON
      • 要求:XML,返回:XML
      • 要求:图像,返回:强制CT