Spring Boot 是否更改Sping Boot 中问题详细信息API的默认“类型”?

uinbv5nw  于 2023-02-04  发布在  Spring
关注(0)|答案(1)|浏览(390)

我使用的是Sping Boot 3.x,我有一个控制器定义如下:

@RestController
@RequestMapping(path = ["/my-controller"])
@Validated
class MyController {
    private val log = loggerFor<MyController>()

    @PutMapping("/{something}", consumes = [APPLICATION_JSON_VALUE])
    @ResponseStatus(code = HttpStatus.NO_CONTENT)
    fun test(
        @PathVariable("something") something: String,
        @Valid @RequestBody someDto: SomeDTO
    ) {
        log.info("Received $someDto")
    }
}

data class SomeDTO(val myBoolean: Boolean)

我还在application.yaml文件中启用了问题详细信息(RFC 7807):

spring:
  mvc:
    problemdetails:
      enabled: true

当我向/my-controller/hello发出一个请求(在本例中我使用rest assured),其中的json主体(故意)与预期数据不匹配(myBooleannot 一个有效的布尔值):

Given {
    port(<port>)
    contentType(JSON)
    body("""{ "myBoolean" : "not a boolean"}""")
    log().all()
} When {
    put("/my-controller/hello")
} Then {
    log().all().
    statusCode(400)
}

响应正文如下所示:

{
    "type": "about:blank",
    "title": "Bad Request",
    "status": 400,
    "detail": "Failed to read request",
    "instance": "/my-controller/hello"
}

我的问题是,如何将默认的typeabout:blank更改为其他值?

l7mqbcuq

l7mqbcuq1#

您需要按如下方式定义@ControllerAdvice:

@ControllerAdvice
public class GlobalExceptionHandler extends ResponseEntityExceptionHandler {

  @ExceptionHandler(Exception.class)
  public ResponseEntity<Problem> handleAllExceptions(Exception ex, WebRequest request) {
    return ResponseEntity.of(
              Optional.of(
                Problem.builder()
                  .withType(URI.create("https://foobar.com/problem-definitions/blah"))
                  .withTitle("Bad Request")
                  .withDetail(ex.getMessage())
                  .withStatus(Status.BAD_REQUEST)
                  .build()
              ));  
    }

}
它为您的示例返回以下内容:

{
    "type": "https://foobar.com/problem-definitions/blah",
    "title": "Bad Request",
    "status": 400,
    "detail": "Type definition error: [simple type, class com.example.demo.web.LanguageController$SomeDTO]; nested exception is com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `com.example.demo.web.LanguageController$SomeDTO`: non-static inner classes like this can only by instantiated using default, no-argument constructor\n at [Source: (org.springframework.util.StreamUtils$NonClosingInputStream); line: 1, column: 3]"
}

我使用了以下依赖项:

<dependency>
    <groupId>org.zalando</groupId>
    <artifactId>problem-spring-web-starter</artifactId>
    <version>0.28.0-RC.0</version>
</dependency>

注意ProblemDetail是Spring框架6。Spring 6中的实现如下所示:

@ControllerAdvice
public class GlobalExceptionHandler extends ResponseEntityExceptionHandler {

    @ExceptionHandler(Exception.class)
    public ResponseEntity<ProblemDetail> handleAllExceptions(Exception ex, WebRequest request) {
    ProblemDetail problemDetail = ProblemDetail.forStatusAndDetail(HttpStatus.BAD_REQUEST, ex.getMessage());
    problemDetail.setType(URI.create("https://foobar.com/problem-definitions/blah"));
    problemDetail.setInstance(URI.create("https://instance"));
    return ResponseEntity.of(Optional.of(problemDetail));
}

相关问题