OpenApi 文档与 spring-doc 结合 ResponseBodyAdvice
OpenApi documentation with spring-doc in combination with ResponseBodyAdvice
我有一个简单的休息API,我正在测试 springdoc swagger 文档。
其余控制器:
@RestController
public class UserController {
private final UserService userService;
public UserController(final UserService userService) {
this.userService = userService;
}
@PostMapping("/users")
@PreAuthorize("hasAuthority('create:user')")
public ResponseEntity<UserDto> create(final @RequestBody @Valid CreateUserCommand command) {
return ResponseEntity
.status(HttpStatus.CREATED)
.body(userService.create(command));
}
}
然后我将所有 API 响应对象包装在 ResponseControllerAdvice 中:
@RestControllerAdvice
public class CustomResponseBodyAdvice implements ResponseBodyAdvice<Object> {
@Override
public boolean supports(final @NotNull MethodParameter returnType,
final @NotNull Class<? extends HttpMessageConverter<?>> converterType) {
return true;
}
@Override
public Object beforeBodyWrite(final Object body,
final @NotNull MethodParameter returnType,
final @NotNull MediaType selectedContentType,
final @NotNull Class<? extends HttpMessageConverter<?>> selectedConverterType,
final @NotNull ServerHttpRequest request,
final @NotNull ServerHttpResponse response) {
if (body instanceof ResponseEnvelope || body instanceof Resource) {
return body;
}
if (body instanceof final ResponseEntity<?> responseEntity) {
response.setStatusCode(responseEntity.getStatusCode());
}
return ResponseEnvelope.builder().success(true).result(body).build();
}
但我正在努力寻找一种方法让 Springdoc 考虑到这个 ResponseEnvelope 包装器对象。有什么想法吗?
使用 Spring 启动 2.6.2 + Java 17:
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-ui</artifactId>
<version>1.6.4</version>
</dependency>
我想要的:
{
"status": "OK",
"result": {
"username": "johndoe"
}
}
我得到的:
{
"username": "johndoe"
}
使用 OperationCustomizer 接口修复了它:
@Configuration
class ApiDocsOperationCustomizer implements OperationCustomizer {
@Override
public Operation customize(Operation operation,
HandlerMethod handlerMethod) {
final Content content = operation.getResponses().get("200").getContent();
content.keySet().forEach(mediaTypeKey -> {
final MediaType mediaType = content.get(mediaTypeKey);
mediaType.schema(this.customizeSchema(mediaType.getSchema()));
});
return operation;
}
private Schema<?> customizeSchema(final Schema<?> objSchema) {
final Schema<?> wrapperSchema = new Schema<>();
wrapperSchema.addProperties("success", new BooleanSchema()._default(true));
wrapperSchema.addProperties("result", objSchema);
return wrapperSchema;
}}
我有一个简单的休息API,我正在测试 springdoc swagger 文档。 其余控制器:
@RestController
public class UserController {
private final UserService userService;
public UserController(final UserService userService) {
this.userService = userService;
}
@PostMapping("/users")
@PreAuthorize("hasAuthority('create:user')")
public ResponseEntity<UserDto> create(final @RequestBody @Valid CreateUserCommand command) {
return ResponseEntity
.status(HttpStatus.CREATED)
.body(userService.create(command));
}
}
然后我将所有 API 响应对象包装在 ResponseControllerAdvice 中:
@RestControllerAdvice
public class CustomResponseBodyAdvice implements ResponseBodyAdvice<Object> {
@Override
public boolean supports(final @NotNull MethodParameter returnType,
final @NotNull Class<? extends HttpMessageConverter<?>> converterType) {
return true;
}
@Override
public Object beforeBodyWrite(final Object body,
final @NotNull MethodParameter returnType,
final @NotNull MediaType selectedContentType,
final @NotNull Class<? extends HttpMessageConverter<?>> selectedConverterType,
final @NotNull ServerHttpRequest request,
final @NotNull ServerHttpResponse response) {
if (body instanceof ResponseEnvelope || body instanceof Resource) {
return body;
}
if (body instanceof final ResponseEntity<?> responseEntity) {
response.setStatusCode(responseEntity.getStatusCode());
}
return ResponseEnvelope.builder().success(true).result(body).build();
}
但我正在努力寻找一种方法让 Springdoc 考虑到这个 ResponseEnvelope 包装器对象。有什么想法吗?
使用 Spring 启动 2.6.2 + Java 17:
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-ui</artifactId>
<version>1.6.4</version>
</dependency>
我想要的:
{
"status": "OK",
"result": {
"username": "johndoe"
}
}
我得到的:
{
"username": "johndoe"
}
使用 OperationCustomizer 接口修复了它:
@Configuration
class ApiDocsOperationCustomizer implements OperationCustomizer {
@Override
public Operation customize(Operation operation,
HandlerMethod handlerMethod) {
final Content content = operation.getResponses().get("200").getContent();
content.keySet().forEach(mediaTypeKey -> {
final MediaType mediaType = content.get(mediaTypeKey);
mediaType.schema(this.customizeSchema(mediaType.getSchema()));
});
return operation;
}
private Schema<?> customizeSchema(final Schema<?> objSchema) {
final Schema<?> wrapperSchema = new Schema<>();
wrapperSchema.addProperties("success", new BooleanSchema()._default(true));
wrapperSchema.addProperties("result", objSchema);
return wrapperSchema;
}}