从 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 |
@Operation 的 responses 属性 |
@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. 验证升级结果
- 访问 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 更快,但大型项目可能需要配置:
propertiesspringdoc.api-docs.enabled=true springdoc.swagger-ui.enabled=true
-
总结
从 Swagger 2.0 升级到 OpenAPI 3.0 是一个相对直接的过程,主要涉及依赖替换、配置重构和注解更新。