Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/358.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 以编程方式添加安全方案时,架构将从组件中消失_Java_Spring Boot_Openapi_Springdoc - Fatal编程技术网

Java 以编程方式添加安全方案时,架构将从组件中消失

Java 以编程方式添加安全方案时,架构将从组件中消失,java,spring-boot,openapi,springdoc,Java,Spring Boot,Openapi,Springdoc,我最近将Springfox转换为Springdoc openapi,为我的Spring Boot Rest API服务生成openapi 在我添加安全方案之前,一切都很顺利。一旦我这样做了,我的方案就不再出现,并且在SwaggerUI页面上会出现一个错误: Could not resolve reference: Could not resolve pointer: /components/schemas/Ping does not exist in document 我正在以编程方式设置配置

我最近将Springfox转换为Springdoc openapi,为我的Spring Boot Rest API服务生成openapi

在我添加安全方案之前,一切都很顺利。一旦我这样做了,我的方案就不再出现,并且在SwaggerUI页面上会出现一个错误:

Could not resolve reference: Could not resolve pointer: /components/schemas/Ping does not exist in document
我正在以编程方式设置配置,有两个组

我正在使用SpringBootV2.4.0和SpringDocOpenAPI ui v1.5.1

my pom.xml的片段:

        <dependency>
            <groupId>org.springdoc</groupId>
            <artifactId>springdoc-openapi-ui</artifactId>
            <version>1.5.1</version>
        </dependency>
        <dependency>
            <groupId>org.springdoc</groupId>
            <artifactId>springdoc-openapi-hateoas</artifactId>
            <version>1.5.1</version>
        </dependency>
        <dependency>
            <groupId>org.springdoc</groupId>
            <artifactId>springdoc-openapi-security</artifactId>
            <version>1.5.1</version>
        </dependency>
对于我的v1组,一切都很好。我的模式出现在Swagger UI页面上,我在生成的api文档的components部分看到它们

    "components": {
    "schemas": {
        "ApplicationErrorResponse": {
            ...
            }
        },
        "Ping": {
            ...
        }
    }
}
对于我的v2组,不会生成架构

    "components": {
    "securitySchemes": {
        "Access Token": {
            "type": "apiKey",
            "name": "Authorization",
            "in": "header"
        }
    }
}
知道为什么在以编程方式将安全方案添加到OpenAPI组件时不会自动扫描和添加我的模式吗?我的配置中是否缺少某些内容

这是我的控制器中的请求映射

@Operation(summary = "Verify API and backend connectivity",
        description = "Confirm connectivity to the backend, as well and verify API service is running.")
@OkResponse
@GetMapping(value = API_VERSION_2 + "/ping", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Ping> getPingV2(HttpServletRequest request) {

我的v1映射的定义与此类似。

因此,当仅依赖OpenApiCustomiser创建OpenAPI时,扫描的组件似乎会被忽略,或者至少会被自定义程序中指定的组件覆盖(我也可以通过编程方式添加所有模式,但维护起来会非常麻烦)

将我的配置更改为以下解决了我的问题:

@Bean
public OpenAPI customOpenAPI() {
    final String securitySchemeName = "Access Token";
    return new OpenAPI()
            .addSecurityItem(new SecurityRequirement().addList(securitySchemeName))
            .components(new Components().addSecuritySchemes(securitySchemeName, new SecurityScheme()
                    .type(SecurityScheme.Type.APIKEY)
                    .in(SecurityScheme.In.HEADER)
                    .name(HttpHeaders.AUTHORIZATION)))
            .info(apiInfo());
}

@Bean
public GroupedOpenApi apiV1() {
    String[] paths = {"/v1/**"};
    String[] packagesToScan = {"com.test.controller"};
    return GroupedOpenApi.builder()
            .group("v1")
            .packagesToScan(packagesToScan)
            .pathsToMatch(paths)
            .addOpenApiCustomiser(buildV1OpenAPI())
            .build();
}

@Bean
public GroupedOpenApi apiV2() {
    String[] paths = {"/v2/**"};
    String[] packagesToScan = {"com.test.controller"};
    return GroupedOpenApi.builder()
            .group("v2")
            .packagesToScan(packagesToScan)
            .pathsToMatch(paths)
            .addOpenApiCustomiser(buildV2OpenAPI())
            .build();
}

public OpenApiCustomiser buildV1OpenAPI() {
    return openApi -> openApi.info(openApi.getInfo().version("v1"));
}

public OpenApiCustomiser buildV2OpenAPI() {
    return openApi -> openApi.info(openApi.getInfo().version("v2"));
}

// Describe the apis
private Info apiInfo() {
    return new Info()
            .title("Title")
            .description("API Description.");
}
虽然这在技术上也会将授权按钮和安全方案添加到v1组中,但可以忽略它,因为这些API端点无论如何都不安全(内部API,它们应该很快就会消失)


无论如何,这可能是一个更好的解决方案,因为组之间的信息基本相同。

您不应该创建新组件,而应该修改它们:

public OpenApiCustomiser buildV2OpenAPI() {
    final String securitySchemeName = "Access Token";
    return openApi -> {
        openApi.info(apiInfo().version("v2"))
            .addSecurityItem(new SecurityRequirement().addList(securitySchemeName));
        
        openApi.getComponents().addSecuritySchemes(securitySchemeName, new SecurityScheme()
            .type(SecurityScheme.Type.APIKEY)
            .in(SecurityScheme.In.HEADER)
            .name(HttpHeaders.AUTHORIZATION));

        return openApi;
    
    };
}
@Bean
public OpenAPI customOpenAPI() {
    final String securitySchemeName = "Access Token";
    return new OpenAPI()
            .addSecurityItem(new SecurityRequirement().addList(securitySchemeName))
            .components(new Components().addSecuritySchemes(securitySchemeName, new SecurityScheme()
                    .type(SecurityScheme.Type.APIKEY)
                    .in(SecurityScheme.In.HEADER)
                    .name(HttpHeaders.AUTHORIZATION)))
            .info(apiInfo());
}

@Bean
public GroupedOpenApi apiV1() {
    String[] paths = {"/v1/**"};
    String[] packagesToScan = {"com.test.controller"};
    return GroupedOpenApi.builder()
            .group("v1")
            .packagesToScan(packagesToScan)
            .pathsToMatch(paths)
            .addOpenApiCustomiser(buildV1OpenAPI())
            .build();
}

@Bean
public GroupedOpenApi apiV2() {
    String[] paths = {"/v2/**"};
    String[] packagesToScan = {"com.test.controller"};
    return GroupedOpenApi.builder()
            .group("v2")
            .packagesToScan(packagesToScan)
            .pathsToMatch(paths)
            .addOpenApiCustomiser(buildV2OpenAPI())
            .build();
}

public OpenApiCustomiser buildV1OpenAPI() {
    return openApi -> openApi.info(openApi.getInfo().version("v1"));
}

public OpenApiCustomiser buildV2OpenAPI() {
    return openApi -> openApi.info(openApi.getInfo().version("v2"));
}

// Describe the apis
private Info apiInfo() {
    return new Info()
            .title("Title")
            .description("API Description.");
}
public OpenApiCustomiser buildV2OpenAPI() {
    final String securitySchemeName = "Access Token";
    return openApi -> {
        openApi.info(apiInfo().version("v2"))
            .addSecurityItem(new SecurityRequirement().addList(securitySchemeName));
        
        openApi.getComponents().addSecuritySchemes(securitySchemeName, new SecurityScheme()
            .type(SecurityScheme.Type.APIKEY)
            .in(SecurityScheme.In.HEADER)
            .name(HttpHeaders.AUTHORIZATION));

        return openApi;
    
    };
}