1.配置swagger使用jwt

可以通过编程式实现,也可以通过注解式实现,我这里拿注解式举例

@SpringBootConfiguration
@OpenAPIDefinition(info = @Info(title = "API", version = "v1"))
@SecurityScheme(
        name = "token",
        type = SecuritySchemeType.HTTP,
        bearerFormat = "JWT",
        scheme = "bearer")
public class OpenApiConfig {}

按照Spring官网的介绍,如果要在controller或者方法使用上述jwt认证,需要在controller或者方法级别都添加@SecurityRequirement(name = "token")这样的注解,我这边实现方式如下:

@SecurityRequirement(name = "token")
public interface SecuredRestController {}

定义如上接口,需要认证的Controller实现SecuredRestController。

2.配置自定义生成OperationId

之所以要自定义配置是由于SpringDocOpenApi生成operationId的规则是根据Controller中方法注解或者方法名生成,如果没有注解则用方法名,当多个controller中都有同名方法时候则operationId就变成method_1这种,例如update_1/update_2等等。而且每次顺序都说不是固定的,每次重启该id可能会变。不利于前端根据该文档动态生成代码。

SpringDoc中生成OperationId的逻辑在

org.springdoc.api.AbstractOpenApiResource#calculatePath(org.springframework.web.method.HandlerMethod, org.springdoc.core.fn.RouterOperation)

这个方法中生成Operation以后有个customiseOperation方法,允许对operation自定义,所以自定义一个bean即可,例如我是将operationId改成类名_方法名,这个要求同一个类中不能有同名方法。

    @Bean
    public OperationCustomizer operationCustomizer() {
        return (operation, handlerMethod) -> {
            operation.setOperationId(
                    String.format(
                            "%s_%s",
                            handlerMethod.getMethod().getDeclaringClass().getSimpleName(),
                            handlerMethod.getMethod().getName()));
            return operation;
        };
    }

3.自定义返回值解析

我们在controller返回时候有ControllerAdvice给包装返回值为固定格式的对象,openApi默认生成的文档中是不包含该包装对象的,生成返回值类型代码在如下方法中

org.springdoc.core.GenericResponseBuilder#buildApiResponses(io.swagger.v3.oas.models.Components, org.springframework.core.MethodParameter, io.swagger.v3.oas.models.responses.ApiResponses, org.springdoc.core.MethodAttributes, java.lang.String, io.swagger.v3.oas.models.responses.ApiResponse, boolean)

跟踪代码看到最终是通过

org.springdoc.core.GenericResponseBuilder#getReturnType

该方法返回的,这里的ReturnTypeParser是没有任何实现的,通过

org.springdoc.core.SpringDocConfiguration#genericReturnTypeParser

该方法初始化的,所以自定义一个ReturnTypeParser Bean即可。

实现如下:

    @Bean
    public ReturnTypeParser customReturnTypeParser() {
        return new ReturnTypeParser() {
            @Override
            public Type getReturnType(MethodParameter methodParameter) {
                Type returnType = ReturnTypeParser.super.getReturnType(methodParameter);
                Annotation[] annotations =
                        Objects.requireNonNull(methodParameter.getMethod())
                                .getDeclaringClass()
                                .getAnnotations();
                if (Arrays.stream(annotations)
                        .noneMatch(annotation -> annotation instanceof RestController)) {
                    return returnType;
                }
                if (returnType.getTypeName().equals("void")) {
                    return returnType;
                }
                return TypeUtils.parameterize(ServerResponse.class, returnType);
            }
        };
    }

其中ServerResponse就是ControllerAdvice中对返回值的包装类型。

4.SpringDocOpenApi官方文档地址

https://springdoc.org/index.html#migrating-from-springfox

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐