Spring 返回 HTTP 406 的 JSON (NOT_ACCEPTABLE)

2024-03-30

Spring允许定义@ExceptionHandlers代替@RestControllerAdvice.

我已经定义了很多其他的ExceptionHandlers其中适用于 HTTP 400、404、405...但是,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 -

类型:状态报告

message:

描述: 标识的资源 该请求只能生成响应 根据“接受”请求,特性不可接受 标头。

代替

{ “错误代码”:406, “errorMessage”:“http.media_not_acceptable” }

请求标头:

  • 接受:应用程序/不能存在的东西

实际响应标头:

  • 内容类型:text/html

预期响应标头:

  • 内容类型:application/json

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

我使用 Spring 4.3.3.RELEASE 和 Jackson 2.8.4。


最后我找到了一个解决方案:

不返回可序列化对象,而是直接返回字节。

private final ObjectMapper objectMapper = new ObjectMapper();

@ExceptionHandler(HttpMediaTypeNotAcceptableException.class)
public ResponseEntity<byte[]> mediaTypeNotAcceptable(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;
    }
}

EDIT:

作为替代方案,您可以创建自定义HttpMessageConverter<ErrorResponse>为您ErrorResponse object.

  • 转到您的或创建一个 implWebMvcConfigurerAdapter#extendMessageConverters(converters)
  • Pick a HttpMessageConverter能够创建您预期的结果/内容类型。
  • Wrap it in a way to fulfill the following conditions:
    • getSupportedMediaTypes()回报MediaType.ALL
    • canRead()返回假
    • canWrite()仅返回 true 对于您ErrorResponse
    • write()设置强制 CT 并将您期望的内容类型转发到包装的转换器。
  • Add your wrapper to the converters list.
    • If added as first element then it will always return your expected result (forced)
      • 请求:json,返回:强制CT
      • 请求:xml,返回:强制CT
      • 请求:图像,返回:强制CT
    • If added as last element then it will only return the result as your expected result, if there was no other matching converter (fallback)
      • 请求:json,返回:json
      • 请求:xml,返回:xml
      • 请求:图像,返回:强制CT
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Spring 返回 HTTP 406 的 JSON (NOT_ACCEPTABLE) 的相关文章

随机推荐