Spring REST Controller不支持的媒体类型或没有处理程序

时间:2019-03-02 00:45:37

标签: spring exception-handling

如果我有一个像这样的spring 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+json发送回去,因此弹簧将其视为不可接受的媒体类型,并再次调用HttpMediaTypeExceptionHandler异常处理程序并说该媒体类型是不可接受的。

Spring中是否有一种方法可以停止第二个循环进入异常处理程序,即使accept标头不包含application/problem+json媒体类型,它仍然会返回该值?

1 个答案:

答案 0 :(得分:0)

奇怪的是,当我从以下命令更改return语句时,它开始工作:

return new ResponseEntity<>(problem, httpStatus);

对此:

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

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