首页 > 解决方案 > Spring REST 控制器不支持的媒体类型或没有处理程序

问题描述

如果我有这样的弹簧 REST 控制器

@PostMapping( 
    value = "/configurations",
    consumes = MediaType.APPLICATION_JSON_VALUE,
    produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseStatus(HttpStatus.CREATED)
public CreateConfigurationResponse createConfiguration(
    @RequestBody @Valid @NotNull final CreateConfigurationRequest request) {
    // do stuff
}

并且客户端在标头中使用错误的媒体类型调用此端点,Accept然后 spring 抛出一个HttpMediaTypeNotAcceptableException. 然后我们的异常处理程序捕获它并构造一个Problem(rfc-7807) 错误响应

@Order(Ordered.HIGHEST_PRECEDENCE)
@ControllerAdvice
public class HttpMediaTypeExceptionHandler extends BaseExceptionHandler {

    @ExceptionHandler(HttpMediaTypeNotAcceptableException.class)
    public ResponseEntity<Problem> notAcceptableMediaTypeHandler(final HttpMediaTypeNotAcceptableException ex,
        final HttpServletRequest request) {

    final Problem problem = Problem.builder()
        .withType(URI.create("...."))
        .withTitle("unsupported media type")
        .withStatus(Status.NOT_ACCEPTABLE)
        .withDetail("...error stuff..")
        .build();

    return new ResponseEntity<>(problem, httpStatus);
}

但是由于Problem错误响应应该使用媒体类型发回,因此application/problem+jsonspring 将其视为不可接受的媒体类型并HttpMediaTypeExceptionHandler再次调用异常处理程序并说该媒体类型是不可接受的。

在 Spring 中有没有办法停止第二个循环进入异常处理程序,即使接受标头不包含application/problem+json媒体类型,它也只会返回它?

标签: springexception-handling

解决方案


奇怪的是,当我从这里更改 return 语句时它开始工作:

return new ResponseEntity<>(problem, httpStatus);

对此:

return ResponseEntity
        .status(httpStatus)
        .contentType(MediaType.APPLICATION_PROBLEM_JSON)
        .body(problem);

我不确定这是如何使它工作的,但确实如此。


推荐阅读