從 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 是一個相對直接的過程,主要涉及依賴替換、配置重構和注解更新。