从 Swagger 2.0 到 OpenAPI 3.0 的升级指南
为什么升级
OpenAPI 3.0提供了更强大的功能、更简洁的配置和更好的性能,同时保持了与 Swagger 2.0 的基本兼容性。本文将详细介绍升级的各个步骤,并提供代码示例。
1. 依赖管理的变化
Swagger 2.0 依赖配置
<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 依赖配置
<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 配置类
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 {@Beanpublic 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 配置类
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 {@Beanpublic 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 | @Operation 的 responses 属性 |
@ApiIgnore | @Parameter(hidden = true) |
模型注解对比
Swagger 2.0 | OpenAPI 3.0 替代方案 |
---|---|
@ApiModel | @Schema |
@ApiModelProperty | @Schema |
示例:控制器注解升级
// 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 模型定义
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 模型定义
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 安全配置
@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 安全配置
@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. 处理特殊场景
自定义扩展
// 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() {@Overridepublic String getName() {return "x-custom-info";}@Overridepublic 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 文档
// OpenAPI 3.0 分组配置
@Configuration
public class OpenAPIConfig {@Beanpublic GroupedOpenApi userApi() {return GroupedOpenApi.builder().group("users").pathsToMatch("/api/users/**").build();}@Beanpublic GroupedOpenApi productApi() {return GroupedOpenApi.builder().group("products").pathsToMatch("/api/products/**").build();}
}
7. 验证升级结果
- 访问 Swagger UI:
- 旧路径:
http://localhost:8080/swagger-ui.html
(已失效) - 新路径:
http://localhost:8080/swagger-ui/index.html
- 旧路径:
8. 常见问题与解决方案
-
依赖冲突:
- 确保移除所有
springfox
相关依赖 - 使用 Maven 的
dependency:tree
或 Gradle 的dependencies
命令检查冲突
- 确保移除所有
-
UI 无法访问:
- 确认
springdoc-openapi-starter-webmvc-ui
依赖已正确添加 - 检查是否有自定义 Web 配置拦截了
/swagger-ui/**
路径
- 确认
-
注解不生效:
- 确认使用的是
io.swagger.v3.oas.annotations
包下的注解 - 检查类路径是否存在旧版本注解
- 确认使用的是
-
性能问题:
- OpenAPI 3.0 通常比 Swagger 2.0 更快,但大型项目可能需要配置:
springdoc.api-docs.enabled=true springdoc.swagger-ui.enabled=true
- OpenAPI 3.0 通常比 Swagger 2.0 更快,但大型项目可能需要配置:
总结
从 Swagger 2.0 升级到 OpenAPI 3.0 是一个相对直接的过程,主要涉及依赖替换、配置重构和注解更新。