Spring 应用中 Swagger 2.0 迁移 OpenAPI 3.0 详解:配置、注解与实践

从 Swagger 2.0 到 OpenAPI 3.0 的升级指南

为什么升级

OpenAPI 3.0提供了更强大的功能、更简洁的配置和更好的性能,同时保持了与 Swagger 2.0 的基本兼容性。本文将详细介绍升级的各个步骤,并提供代码示例。

1. 依赖管理的变化

Swagger 2.0 依赖配置

xml 复制代码
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger2</artifactId>
    <version>2.9.2</version>
</dependency>
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger-ui</artifactId>
    <version>2.9.2</version>
</dependency>

OpenAPI 3.0 依赖配置

xml 复制代码
<dependency>
    <groupId>org.springdoc</groupId>
    <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
    <version>2.2.0</version>
</dependency>

关键变化:

  • 从多个 springfox 依赖简化为单一的 springdoc 依赖
  • 自动集成 Swagger UI 和 OpenAPI 规范生成
  • 无需手动管理多个依赖版本

2. 配置类的重构

Swagger 2.0 配置类

java 复制代码
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

@Configuration
@EnableSwagger2
public class SwaggerConfig {

    @Bean
    public Docket api() {
        return new Docket(DocumentationType.SWAGGER_2)
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.example.controller"))
                .paths(PathSelectors.any())
                .build()
                .apiInfo(apiInfo());
    }

    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title("Swagger 2.0 API")
                .description("API documentation using Swagger 2.0")
                .version("1.0.0")
                .build();
    }
}

OpenAPI 3.0 配置类

java 复制代码
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Info;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class OpenAPIConfig {

    @Bean
    public OpenAPI customOpenAPI() {
        return new OpenAPI()
                .info(new Info()
                        .title("OpenAPI 3.0 API")
                        .description("API documentation using OpenAPI 3.0")
                        .version("1.0.0"));
    }
}

关键变化:

  • 移除了 @EnableSwagger2 注解
  • 不再需要手动配置 Docket 和选择器
  • 使用 OpenAPI 类直接定义 API 元数据
  • 自动扫描控制器和模型,无需指定包路径

3. 注解系统的升级

控制器注解对比

Swagger 2.0 OpenAPI 3.0 替代方案
@Api @Tag
@ApiOperation @Operation
@ApiParam @Parameter
@ApiResponses @Operationresponses 属性
@ApiIgnore @Parameter(hidden = true)

模型注解对比

Swagger 2.0 OpenAPI 3.0 替代方案
@ApiModel @Schema
@ApiModelProperty @Schema

示例:控制器注解升级

java 复制代码
// Swagger 2.0 控制器
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/api/users")
@Api(value = "User Management API", description = "Operations related to users")
public class UserControllerV2 {

    @ApiOperation(value = "Retrieve a user by ID", response = User.class)
    @GetMapping("/{id}")
    public User getUserById(
        @ApiParam(value = "User ID", required = true) 
        @PathVariable Long id
    ) {
        return userService.findById(id);
    }
}

// OpenAPI 3.0 控制器
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/api/users")
@Tag(name = "User Management API", description = "Operations related to users")
public class UserControllerV3 {

    @Operation(
        summary = "Retrieve a user by ID",
        description = "Returns a single user identified by the provided ID"
    )
    @GetMapping("/{id}")
    public User getUserById(
        @Parameter(description = "User ID", required = true) 
        @PathVariable Long id
    ) {
        return userService.findById(id);
    }
}

4. 数据模型注解的更新

Swagger 2.0 模型定义

java 复制代码
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;

@ApiModel(description = "Represents a user in the system")
public class User {

    @ApiModelProperty(value = "Unique identifier for the user", example = "1")
    private Long id;

    @ApiModelProperty(value = "User's full name", example = "John Doe")
    private String name;

    @ApiModelProperty(value = "User's email address", example = "john@example.com")
    private String email;
}

OpenAPI 3.0 模型定义

java 复制代码
import io.swagger.v3.oas.annotations.media.Schema;

public class User {

    @Schema(description = "Unique identifier for the user", example = "1", required = true)
    private Long id;

    @Schema(description = "User's full name", example = "John Doe", minLength = 2)
    private String name;

    @Schema(description = "User's email address", example = "john@example.com", format = "email")
    private String email;
}

增强功能:

  • 支持更丰富的 format 选项(如 email, date, uuid 等)
  • 直接在 @Schema 中定义约束条件(如 minLength, maxLength
  • 更好的与 JSON Schema 集成

5. 安全配置的升级

Swagger 2.0 安全配置

java 复制代码
@Bean
public Docket api() {
    return new Docket(DocumentationType.SWAGGER_2)
        .securitySchemes(Arrays.asList(apiKey()))
        .securityContexts(Arrays.asList(securityContext()));
}

private ApiKey apiKey() {
    return new ApiKey("JWT", "Authorization", "header");
}

private SecurityContext securityContext() {
    return SecurityContext.builder()
        .securityReferences(defaultAuth())
        .forPaths(PathSelectors.regex("/api/.*"))
        .build();
}

private List<SecurityReference> defaultAuth() {
    AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
    AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
    authorizationScopes[0] = authorizationScope;
    return Arrays.asList(new SecurityReference("JWT", authorizationScopes));
}

OpenAPI 3.0 安全配置

java 复制代码
@Bean
public OpenAPI customOpenAPI() {
    return new OpenAPI()
        .info(new Info().title("API").version("1.0.0"))
        .components(new Components()
            .addSecuritySchemes("bearerAuth", 
                new SecurityScheme()
                    .type(SecurityScheme.Type.HTTP)
                    .scheme("bearer")
                    .bearerFormat("JWT")
            )
        )
        .addSecurityItem(new SecurityRequirement().addList("bearerAuth"));
}

关键改进:

  • 简化的安全方案定义
  • 支持更多安全类型(如 OAuth2、OpenID Connect)
  • 更清晰的安全要求声明

6. 处理特殊场景

自定义扩展

java 复制代码
// Swagger 2.0 自定义扩展
@Bean
public Docket customImplementation() {
    return new Docket(DocumentationType.SWAGGER_2)
        .extensions(customVendorExtensions());
}

private List<VendorExtension> customVendorExtensions() {
    List<VendorExtension> extensions = new ArrayList<>();
    VendorExtension<String> extension = new VendorExtension() {
        @Override
        public String getName() {
            return "x-custom-info";
        }

        @Override
        public String getValue() {
            return "This is a custom extension";
        }
    };
    extensions.add(extension);
    return extensions;
}

// OpenAPI 3.0 自定义扩展
@Bean
public OpenAPI customOpenAPI() {
    return new OpenAPI()
        .info(new Info()
            .title("API")
            .version("1.0.0")
            .addExtension("x-custom-info", "This is a custom extension")
        );
}

分组 API 文档

java 复制代码
// OpenAPI 3.0 分组配置
@Configuration
public class OpenAPIConfig {

    @Bean
    public GroupedOpenApi userApi() {
        return GroupedOpenApi.builder()
            .group("users")
            .pathsToMatch("/api/users/**")
            .build();
    }

    @Bean
    public GroupedOpenApi productApi() {
        return GroupedOpenApi.builder()
            .group("products")
            .pathsToMatch("/api/products/**")
            .build();
    }
}

7. 验证升级结果

  1. 访问 Swagger UI
    • 旧路径:http://localhost:8080/swagger-ui.html(已失效)
    • 新路径:http://localhost:8080/swagger-ui/index.html

8. 常见问题与解决方案

  1. 依赖冲突

    • 确保移除所有 springfox 相关依赖
    • 使用 Maven 的 dependency:tree 或 Gradle 的 dependencies 命令检查冲突
  2. UI 无法访问

    • 确认 springdoc-openapi-starter-webmvc-ui 依赖已正确添加
    • 检查是否有自定义 Web 配置拦截了 /swagger-ui/** 路径
  3. 注解不生效

    • 确认使用的是 io.swagger.v3.oas.annotations 包下的注解
    • 检查类路径是否存在旧版本注解
  4. 性能问题

    • OpenAPI 3.0 通常比 Swagger 2.0 更快,但大型项目可能需要配置:

      properties 复制代码
      springdoc.api-docs.enabled=true
      springdoc.swagger-ui.enabled=true

总结

从 Swagger 2.0 升级到 OpenAPI 3.0 是一个相对直接的过程,主要涉及依赖替换、配置重构和注解更新。

相关推荐
二向箔reverse7 分钟前
Selenium 启动的浏览器自动退出问题分析
java·开发语言·数据库
泉城老铁14 分钟前
Spring Boot + Vue 实现 DeepSeek 对话效果详细步骤
前端·vue.js·后端
库库林_沙琪马23 分钟前
[特殊字符] Spring Boot 常用注解全解析:20 个高频注解 + 使用场景实例
java·spring boot·后端
flying robot32 分钟前
小结:Spring MVC 的 XML 的经典配置方式
xml·spring·mvc
Re27542 分钟前
什么是自旋锁理解自旋锁:原理、优缺点与应用场景
后端
知其然亦知其所以然1 小时前
面试被问 G1 GC 懵了?记住这几点就能完美回答!
java·后端·面试
能工智人小辰1 小时前
二刷 黑马点评 秒杀优化
java·开发语言
杨小扩1 小时前
夯实基础:配置Java开发环境JDK与构建工具Maven
java·开发语言·maven
开开心心_Every1 小时前
免费PDF文件格式转换工具
java·智能手机·pdf·word·batch·java-zookeeper
佛祖让我来巡山1 小时前
【Spring三级缓存解密】如何优雅解决循环依赖难题
spring·循环依赖·三级缓存