Swagger接口分组配置详解与实战技巧助你轻松管理API文档提升团队协作效率

引言:为什么需要接口分组?
在现代软件开发中,API文档是团队协作的核心资产。随着项目规模扩大,一个系统可能包含数十甚至上百个接口,如果所有接口都堆砌在一个页面中,开发者将面临巨大的信息过载问题。
接口分组
正是解决这一痛点的关键技术。
想象一个场景:你的团队正在开发一个电商平台,包含用户管理、商品管理、订单处理、支付集成等多个模块。如果所有接口都混杂在一起,前端开发者查找”用户登录”接口时,需要在数百个接口中逐一浏览,效率极低。通过合理的分组策略,我们可以将接口按业务模块、版本、访问权限等维度进行组织,让文档结构清晰、易于检索。
本文将深入探讨Swagger(OpenAPI)中接口分组的配置方法,从基础概念到高级技巧,并提供完整的代码示例和实战经验,帮助你构建专业级的API文档管理体系。
一、Swagger接口分组基础概念
1.1 什么是接口分组?
在Swagger中,
接口分组
是指通过特定的配置方式,将具有相同特征的接口归类到同一个文档组中。每个分组可以拥有独立的标题、描述、版本号等元数据,最终在Swagger UI界面上以标签页的形式呈现。
1.2 分组的核心价值
提升可读性
:将相关接口集中展示,降低认知负担
便于维护
:模块化管理,修改不影响其他模块
权限控制
:不同分组可以配置不同的访问权限
版本管理
:支持多版本API并存
团队协作
:不同团队负责不同分组,职责清晰
二、Spring Boot集成Swagger分组配置
2.1 基础环境准备
首先,我们需要在项目中集成Swagger。以Spring Boot为例,添加以下依赖:




io.springfox
springfox-swagger2
2.9.2



io.springfox
springfox-swagger-ui
2.9.2


注意
:Springfox已停止维护,新项目建议使用SpringDoc OpenAPI(详见第五节)
2.2 创建基础配置类
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.service.Contact;
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 defaultApi() {
return new Docket(DocumentationType.SWAGGER_2)
.groupName(“default”)
.select()
.apis(RequestHandlerSelectors.basePackage(“com.example.project.controller”))
.paths(PathSelectors.any())
.build()
.apiInfo(apiInfo());
}

private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title(“项目API文档”)
.description(“提供完整的接口文档说明”)
.contact(new Contact(“张三”, “http://example.com”, “zhangsan@example.com”))
.version(“1.0.0”)
.build();
}
}
2.3 按业务模块分组
这是最常见的分组方式,将不同业务功能的接口分开管理。
@Configuration
@EnableSwagger2
public class SwaggerGroupConfig {

/**
* 用户管理模块分组
*/
@Bean
public Docket userApi() {
return new Docket(DocumentationType.SWAGGER_2)
.groupName(“用户管理”)
.select()
// 只扫描user包下的controller
.apis(RequestHandlerSelectors.basePackage(“com.example.project.controller.user”))
.paths(PathSelectors.any())
.build()
.apiInfo(new ApiInfoBuilder()
.title(“用户管理API”)
.description(“用户注册、登录、信息管理等相关接口”)
.version(“1.0.0”)
.build());
}

/**
* 商品管理模块分组
*/
@Bean
public Docket productApi() {
return new Docket(DocumentationType.SWAGGER_2)
.groupName(“商品管理”)
.select()
.apis(RequestHandlerSelectors.basePackage(“com.example.project.controller.product”))
.paths(PathSelectors.any())
.build()
.apiInfo(new ApiInfoBuilder()
.title(“商品管理API”)
.description(“商品增删改查、分类管理等相关接口”)
.version(“1.0.0”)
.build());
}

/**
* 订单管理模块分组
*/
@Bean
public Docket orderApi() {
return new Docket(DocumentationType.SWAGGER_2)
.groupName(“订单管理”)
.select()
.apis(RequestHandlerSelectors.basePackage(“com.example.project.controller.order”))
.paths(PathSelectors.any())
.build()
.apiInfo(new ApiInfoBuilder()
.title(“订单管理API”)
.description(“订单创建、支付、查询等相关接口”)
.version(“1.0.0”)
.build());
}
}
2.4 按接口版本分组
对于需要维护多版本API的场景,版本分组非常有用。
@Configuration
@EnableSwagger2
public class VersionedSwaggerConfig {

/**
* V1版本分组 – 已发布且稳定运行的接口
*/
@Bean
public Docket v1Api() {
return new Docket(DocumentationType.SWAGGER_2)
.groupName(“v1.0”)
.select()
.apis(RequestHandlerSelectors.withClassAnnotation(Api.class))
.paths(PathSelectors.regex(“/api/v1/.*”)) // 只匹配v1路径
.build()
.apiInfo(new ApiInfoBuilder()
.title(“API文档 v1.0”)
.description(“稳定版本,生产环境使用”)
.version(“1.0.0”)
.build());
}

/**
* V2版本分组 – 开发中的新版本
*/
@Bean
public Docket v2Api() {
return new Docket(DocumentationType.SWAGGER_2)
.groupName(“v2.0”)
.select()
.apis(RequestHandlerSelectors.withClassAnnotation(Api.class))
.paths(PathSelectors.regex(“/api/v2/.*”)) // 只匹配v2路径
.build()
.apiInfo(new ApiInfoBuilder()
.title(“API文档 v2.0”)
.description(“开发版本,包含最新功能”)
.version(“2.0.0”)
.build());
}
}
2.5 按访问权限分组
根据接口的访问权限进行分组,适用于内部系统和对外API的分离。
@Configuration
@EnableSwagger2
public class SecuritySwaggerConfig {

/**
* 内部API分组 – 需要登录权限
*/
@Bean
public Docket internalApi() {
return new Docket(DocumentationType.SWAGGER_2)
.groupName(“内部API”)
.select()
.apis(RequestHandlerSelectors.basePackage(“com.example.project.controller.internal”))
.paths(PathSelectors.any())
.build()
.apiInfo(new ApiInfoBuilder()
.title(“内部API文档”)
.description(“需要员工账号登录才能访问的接口”)
.version(“1.0.0”)
.build())
// 设置安全方案
.securitySchemes(Arrays.asList(apiKey()));
}

/**
* 公开API分组 – 无需认证
*/
@Bean
public Docket publicApi() {
return new Docket(DocumentationType.SWAGGER_2)
.groupName(“公开API”)
.select()
.apis(RequestHandlerSelectors.basePackage(“com.example.project.controller.public”))
.paths(PathSelectors.any())
.build()
.apiInfo(new ApiInfoBuilder()
.title(“公开API文档”)
.description(“开放给第三方合作伙伴的接口”)
.version(“1.0.0”)
.build());
}

private ApiKey apiKey() {
return new ApiKey(“JWT”, “Authorization”, “header”);
}
}
三、接口分组实战技巧
3.1 使用自定义注解实现智能分组
创建自定义注解,让分组逻辑更优雅:
// 自定义分组注解
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface ApiGroup {
String value(); // 分组名称
String description() default “”; // 分组描述
String version() default “1.0.0”; // 分组版本
}

// 在Controller上使用注解
@RestController
@RequestMapping(“/api/user”)
@ApiGroup(value = “用户管理”, description = “用户相关接口”)
public class UserController {
// …
}

// 配置类自动扫描带注解的Controller
@Configuration
@EnableSwagger2
public class SmartSwaggerConfig {

@Bean
public List createDockets() {
// 扫描所有带@ApiGroup注解的Controller
// 根据注解值自动创建分组
// 实现代码略…
}
}
3.2 动态分组配置
将分组配置放在配置文件中,便于动态调整:
# application.yml
swagger:
groups:
– name: “用户管理”
base-package: “com.example.project.controller.user”
description: “用户相关接口”
version: “1.0.0”
– name: “商品管理”
base-package: “com.example.project.controller.product”
description: “商品相关接口”
version: “1.0.0”
– name: “订单管理”
base-package: “com.example.project.controller.order”
description: “订单相关接口”
version: “1.0.0”
@Configuration
@EnableSwagger2
public class DynamicSwaggerConfig {

@Autowired
private SwaggerProperties swaggerProperties;

@Bean
public List createDockets() {
List dockets = new ArrayList<>();

for (SwaggerGroup group : swaggerProperties.getGroups()) {
Docket docket = new Docket(DocumentationType.SWAGGER_2)
.groupName(group.getName())
.select()
.apis(RequestHandlerSelectors.basePackage(group.getBasePackage()))
.paths(PathSelectors.any())
.build()
.apiInfo(new ApiInfoBuilder()
.title(group.getName() + ” API”)
.description(group.getDescription())
.version(group.getVersion())
.build());

dockets.add(docket);
}

return dockets;
}
}
3.3 按请求方法分组
将GET、POST等不同请求方法的接口分开:
@Configuration
@EnableSwagger2
public class MethodBasedGroupConfig {

/**
* 查询接口分组(GET)
*/
@Bean
public Docket queryApi() {
return new Docket(DocumentationType.SWAGGER_2)
.groupName(“查询接口”)
.select()
.apis(RequestHandlerSelectors.withMethodAnnotation(GetMapping.class))
.paths(PathSelectors.any())
.build()
.apiInfo(new ApiInfoBuilder()
.title(“查询接口文档”)
.description(“所有查询类接口”)
.version(“1.0.0”)
.build());
}

/**
* 操作接口分组(POST/PUT/DELETE)
*/
@Bean
public Docket operationApi() {
return new Docket(DocumentationType.SWAGGER_2)
.groupName(“操作接口”)
.select()
.apis(RequestHandlerSelectors.withMethodAnnotation(PostMapping.class)
.or(RequestHandlerSelectors.withMethodAnnotation(PutMapping.class))
.or(RequestHandlerSelectors.withMethodAnnotation(DeleteMapping.class)))
.paths(PathSelectors.any())
.build()
.apiInfo(new ApiInfoBuilder()
.title(“操作接口文档”)
.description(“所有增删改类接口”)
.version(“1.0.0”)
.build());
}
}
3.4 组合条件分组
使用复杂的组合条件实现精确分组:
@Configuration
@EnableSwagger2
public class ComplexGroupConfig {

/**
* 高级查询接口 – 内部系统使用
*/
@Bean
public Docket advancedQueryApi() {
return new Docket(DocumentationType.SWAGGER_2)
.groupName(“高级查询”)
.select()
// 组合条件:特定包 + GET方法 + 特定路径
.apis(RequestHandlerSelectors.basePackage(“com.example.project.controller.query”)
.and(RequestHandlerSelectors.withMethodAnnotation(GetMapping.class)))
.paths(PathSelectors.regex(“/api/advanced/.*”))
.build()
.apiInfo(new ApiInfoBuilder()
.title(“高级查询API”)
.description(“复杂查询和统计接口”)
.version(“1.0.0”)
.build());
}

/**
* 文件上传接口分组
*/
@Bean
public Docket fileUploadApi() {
return new Docket(DocumentationType.SWAGGER_2)
.groupName(“文件管理”)
.select()
.apis(RequestHandlerSelectors.withMethodAnnotation(PostMapping.class))
.paths(PathSelectors.regex(“/api/file/.*”))
.build()
.apiInfo(new ApiInfoBuilder()
.title(“文件管理API”)
.description(“文件上传、下载、管理接口”)
.version(“1.0.0”)
.build())
// 文件上传需要特殊配置
.useDefaultResponseMessages(false)
.globalResponseMessage(RequestMethod.POST,
Arrays.asList(new ResponseMessageBuilder()
.code(200)
.message(“上传成功”)
.responseModel(new ModelRef(“Result”))
.build()));
}
}
四、高级配置与优化技巧
4.1 分组间的共享配置
使用Builder模式提取公共配置:
@Configuration
@EnableSwagger2
public class SharedConfigSwaggerConfig {

/**
* 创建基础Docket构建器,提取公共配置
*/
private Docket.DocketBuilder baseDocketBuilder() {
return new Docket(DocumentationType.SWAGGER_2)
.useDefaultResponseMessages(false) // 禁用默认响应
.globalOperationParameters(getGlobalParameters()) // 全局参数
.securitySchemes(Arrays.asList(apiKey())); // 安全方案
}

/**
* 分组1
*/
@Bean
public Docket group1() {
return baseDocketBuilder()
.groupName(“分组1”)
.select()
.apis(RequestHandlerSelectors.basePackage(“com.example.group1”))
.paths(PathSelectors.any())
.build()
.apiInfo(createApiInfo(“分组1”, “描述信息”));
}

/**
* 分组2
*/
@Bean
public Docket group2() {
return baseDocketBuilder()
.groupName(“分组2”)
.select()
.apis(RequestHandlerSelectors.basePackage(“com.example.group2”))
.paths(PathSelectors.any())
.build()
.apiInfo(createApiInfo(“分组2”, “描述信息”));
}

private List getGlobalParameters() {
ParameterBuilder parameterBuilder = new ParameterBuilder();
parameterBuilder.name(“traceId”)
.description(“请求追踪ID”)
.modelRef(new ModelRef(“string”))
.parameterType(“header”)
.required(false);
return Arrays.asList(parameterBuilder.build());
}

private ApiInfo createApiInfo(String title, String description) {
return new ApiInfoBuilder()
.title(title)
.description(description)
.version(“1.0.0”)
.build();
}

private ApiKey apiKey() {
return new ApiKey(“JWT”, “Authorization”, “header”);
}
}
4.2 分组的条件过滤
使用Predicate实现动态条件过滤:
@Configuration
@EnableSwagger2
public class ConditionalGroupConfig {

@Bean
public List conditionalDockets() {
// 根据环境变量决定是否启用某些分组
String env = System.getProperty(“spring.profiles.active”, “dev”);

List dockets = new ArrayList<>();

// 基础分组(所有环境都有)
dockets.add(createBaseDocket());

// 开发环境额外分组
if (“dev”.equals(env)) {
dockets.add(createDebugDocket());
dockets.add(createTestDocket());
}

// 生产环境只保留核心分组
if (“prod”.equals(env)) {
dockets.add(createCoreDocket());
}

return dockets;
}

private Docket createBaseDocket() {
return new Docket(DocumentationType.SWAGGER_2)
.groupName(“基础API”)
.select()
.apis(RequestHandlerSelectors.basePackage(“com.example.project.controller.base”))
.paths(PathSelectors.any())
.build()
.apiInfo(new ApiInfoBuilder()
.title(“基础API”)
.description(“核心业务接口”)
.version(“1.0.0”)
.build());
}

private Docket createDebugDocket() {
return new Docket(DocumentationType.SWAGGER_2)
.groupName(“调试API”)
.select()
.apis(RequestHandlerSelectors.basePackage(“com.example.project.controller.debug”))
.paths(PathSelectors.any())
.build()
.apiInfo(new ApiInfoBuilder()
.title(“调试API”)
.description(“开发调试专用接口”)
.version(“1.0.0”)
.build());
}

private Docket createTestDocket() {
return new Docket(DocumentationType.SWAGGER_2)
.groupName(“测试API”)
.select()
.apis(RequestHandlerSelectors.basePackage(“com.example.project.controller.test”))
.paths(PathSelectors.any())
.build()
.apiInfo(new ApiInfoBuilder()
.title(“测试API”)
.description(“自动化测试专用接口”)
.version(“1.0.0”)
.build());
}

private Docket createCoreDocket() {
return new Docket(DocumentationType.SWAGGER_2)
.groupName(“核心API”)
.select()
.apis(RequestHandlerSelectors.basePackage(“com.example.project.controller.core”))
.paths(PathSelectors.any())
.build()
.apiInfo(new ApiInfoBuilder()
.title(“核心API”)
.description(“生产环境核心接口”)
.version(“1.0.0”)
.build());
}
}
4.3 分组的性能优化
当接口数量庞大时,需要优化扫描性能:
@Configuration
@EnableSwagger2
public class PerformanceOptimizedConfig {

/**
* 使用更精确的路径匹配,避免扫描所有路径
*/
@Bean
public Docket optimizedUserApi() {
return new Docket(DocumentationType.SWAGGER_2)
.groupName(“用户API”)
.select()
.apis(RequestHandlerSelectors.basePackage(“com.example.project.controller.user”))
// 精确路径匹配,只扫描/api/user开头的路径
.paths(PathSelectors.ant(“/api/user/**”))
.build()
.apiInfo(new ApiInfoBuilder()
.title(“用户API”)
.description(“用户管理接口”)
.version(“1.0.0”)
.build());
}

/**
* 排除特定路径,减少扫描范围
*/
@Bean
public Docket excludedPathsApi() {
return new Docket(DocumentationType.SWAGGER_2)
.groupName(“排除路径API”)
.select()
.apis(RequestHandlerSelectors.basePackage(“com.example.project.controller”))
.paths(PathSelectors.ant(“/api/**”)
.and(PathSelectors.not(PathSelectors.ant(“/api/internal/**”)))
.and(PathSelectors.not(PathSelectors.ant(“/api/test/**”))))
.build()
.apiInfo(new ApiInfoBuilder()
.title(“排除路径API”)
.description(“排除内部和测试接口”)
.version(“1.0.0”)
.build());
}

/**
* 使用缓存提升性能
*/
@Bean
public Docket cachedApi() {
return new Docket(DocumentationType.SWAGGER_2)
.groupName(“缓存API”)
.select()
.apis(RequestHandlerSelectors.basePackage(“com.example.project.controller”))
.paths(PathSelectors.any())
.build()
.apiInfo(new ApiInfoBuilder()
.title(“缓存API”)
.description(“启用缓存的接口文档”)
.version(“1.0.0”)
.build())
// 启用缓存
.enableCaching(true);
}
}
4.4 分组与权限控制集成
结合Spring Security实现分组级别的权限控制:
@Configuration
@EnableSwagger2
public class SecurityIntegratedConfig {

@Bean
public Docket adminApi() {
return new Docket(DocumentationType.SWAGGER_2)
.groupName(“管理后台API”)
.select()
.apis(RequestHandlerSelectors.basePackage(“com.example.project.controller.admin”))
.paths(PathSelectors.any())
.build()
.apiInfo(new ApiInfoBuilder()
.title(“管理后台API”)
.description(“需要管理员权限的接口”)
.version(“1.0.0”)
.build())
.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.ant(“/api/admin/**”))
.build();
}

List defaultAuth() {
AuthorizationScope authorizationScope = new AuthorizationScope(“global”, “accessEverything”);
AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
authorizationScopes[0] = authorizationScope;
return Arrays.asList(new SecurityReference(“JWT”, authorizationScopes));
}
}
五、SpringDoc OpenAPI(新一代方案)
5.1 为什么选择SpringDoc?
Springfox已停止维护,
SpringDoc
是官方推荐的替代方案,具有以下优势:
活跃的社区支持
更好的性能
支持OpenAPI 3.0规范
更简洁的配置
5.2 SpringDoc基础配置


org.springdoc
springdoc-openapi-ui
1.6.14

import io.swagger.v3.oas.annotations.OpenAPIDefinition;
import io.swagger.v3.oas.annotations.info.Info;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Contact;
import io.swagger.v3.oas.models.info.License;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
@OpenAPIDefinition(info = @Info(
title = “项目API文档”,
version = “1.0.0”,
description = “完整的API文档说明”,
contact = @Contact(name = “张三”, email = “zhangsan@example.com”),
license = @License(name = “MIT”)
))
public class SpringDocConfig {

@Bean
public OpenAPI customOpenAPI() {
return new OpenAPI()
.info(new io.swagger.v3.oas.models.info.Info()
.title(“项目API文档”)
.version(“1.0.0”)
.description(“完整的API文档说明”)
.contact(new io.swagger.v3.oas.models.info.Contact()
.name(“张三”)
.email(“zhangsan@example.com”))
.license(new io.swagger.v3.oas.models.info.License()
.name(“MIT”)
.url(“https://opensource.org/licenses/MIT”)));
}
}
5.3 SpringDoc分组配置
SpringDoc使用
GroupedOpenApi
进行分组,配置更简洁:
import io.swagger.v3.oas.models.OpenAPI;
import org.springdoc.core.GroupedOpenApi;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class SpringDocGroupConfig {

/**
* 用户管理分组
*/
@Bean
public GroupedOpenApi userApi() {
return GroupedOpenApi.builder()
.group(“用户管理”)
.pathsToMatch(“/api/user/**”)
.addOpenApiCustomizer(openApi -> {
openApi.getInfo().setTitle(“用户管理API”);
openApi.getInfo().setDescription(“用户相关接口”);
})
.build();
}

/**
* 商品管理分组
*/
@Bean
public GroupedOpenApi productApi() {
return GroupedOpenApi.builder()
.group(“商品管理”)
.pathsToMatch(“/api/product/**”)
.addOpenApiCustomizer(openApi -> {
openApi.getInfo().setTitle(“商品管理API”);
openApi.getInfo().setDescription(“商品相关接口”);
})
.build();
}

/**
* 订单管理分组
*/
@Bean
public GroupedOpenApi orderApi() {
return GroupedOpenApi.builder()
.group(“订单管理”)
.pathsToMatch(“/api/order/**”)
.addOpenApiCustomizer(openApi -> {
openApi.getInfo().setTitle(“订单管理API”);
openApi.getInfo().setDescription(“订单相关接口”);
})
.build();
}

/**
* 按包名分组
*/
@Bean
public GroupedOpenApi packageBasedGroup() {
return GroupedOpenApi.builder()
.group(“包分组”)
.packagesToScan(“com.example.project.controller.user”)
.build();
}

/**
* 复杂路径匹配分组
*/
@Bean
public GroupedOpenApi complexPathGroup() {
return GroupedOpenApi.builder()
.group(“复杂分组”)
.pathsToMatch(“/api/v1/**”, “/api/v2/user/**”)
.pathsToExclude(“/api/v1/internal/**”)
.build();
}
}
5.4 SpringDoc高级分组技巧
@Configuration
public class SpringDocAdvancedConfig {

/**
* 版本分组
*/
@Bean
public List versionedGroups() {
List groups = new ArrayList<>();

// V1版本
groups.add(GroupedOpenApi.builder()
.group(“v1.0”)
.pathsToMatch(“/api/v1/**”)
.addOpenApiCustomizer(openApi -> {
openApi.getInfo().setVersion(“1.0.0”);
openApi.getInfo().setDescription(“稳定版本”);
})
.build());

// V2版本
groups.add(GroupedOpenApi.builder()
.group(“v2.0”)
.pathsToMatch(“/api/v2/**”)
.addOpenApiCustomizer(openApi -> {
openApi.getInfo().setVersion(“2.0.0”);
openApi.getInfo().setDescription(“开发版本”);
})
.build());

return groups;
}

/**
* 动态分组 – 从配置文件读取
*/
@Bean
public List dynamicGroups(SpringDocProperties properties) {
return properties.getGroups().stream()
.map(groupConfig -> GroupedOpenApi.builder()
.group(groupConfig.getName())
.pathsToMatch(groupConfig.getPaths().toArray(new String[0]))
.addOpenApiCustomizer(openApi -> {
openApi.getInfo().setTitle(groupConfig.getName());
openApi.getInfo().setDescription(groupConfig.getDescription());
openApi.getInfo().setVersion(groupConfig.getVersion());
})
.build())
.collect(Collectors.toList());
}
}

// 配置类
@ConfigurationProperties(prefix = “springdoc.groups”)
public class SpringDocProperties {
private List groups = new ArrayList<>();

public static class GroupConfig {
private String name;
private List paths;
private String description;
private String version;
// getters and setters
}
}
六、实战案例:电商平台API文档管理
6.1 项目背景
假设我们正在开发一个电商平台,包含以下模块:
用户模块
:注册、登录、个人信息管理
商品模块
:商品查询、分类、评价
订单模块
:下单、支付、物流
后台管理
:数据统计、用户管理、商品管理
6.2 完整分组配置
@Configuration
@EnableSwagger2
public class ECommerceSwaggerConfig {

/**
* 用户模块分组
*/
@Bean
public Docket userApi() {
return new Docket(DocumentationType.SWAGGER_2)
.groupName(“用户模块”)
.select()
.apis(RequestHandlerSelectors.basePackage(“com.ecommerce.controller.user”))
.paths(PathSelectors.ant(“/api/user/**”))
.build()
.apiInfo(new ApiInfoBuilder()
.title(“用户模块API”)
.description(“用户注册、登录、信息管理”)
.contact(new Contact(“技术团队”, “https://ecommerce.com”, “tech@ecommerce.com”))
.version(“1.0.0”)
.license(“商业授权”)
.build())
.securitySchemes(Arrays.asList(apiKey()));
}

/**
* 商品模块分组
*/
@Bean
public Docket productApi() {
return new Docket(DocumentationType.SWAGGER_2)
.groupName(“商品模块”)
.select()
.apis(RequestHandlerSelectors.basePackage(“com.ecommerce.controller.product”))
.paths(PathSelectors.ant(“/api/product/**”))
.build()
.apiInfo(new ApiInfoBuilder()
.title(“商品模块API”)
.description(“商品查询、分类、评价”)
.version(“1.0.0”)
.build());
}

/**
* 订单模块分组
*/
@Bean
public Docket orderApi() {
return new Docket(DocumentationType.SWAGGER_2)
.groupName(“订单模块”)
.select()
.apis(RequestHandlerSelectors.basePackage(“com.ecommerce.controller.order”))
.paths(PathSelectors.ant(“/api/order/**”))
.build()
.apiInfo(new ApiInfoBuilder()
.title(“订单模块API”)
.description(“下单、支付、物流”)
.version(“1.0.0”)
.build())
.securitySchemes(Arrays.asList(apiKey()));
}

/**
* 后台管理分组 – 需要管理员权限
*/
@Bean
public Docket adminApi() {
return new Docket(DocumentationType.SWAGGER_2)
.groupName(“后台管理”)
.select()
.apis(RequestHandlerSelectors.basePackage(“com.ecommerce.controller.admin”))
.paths(PathSelectors.ant(“/api/admin/**”))
.build()
.apiInfo(new ApiInfoBuilder()
.title(“后台管理API”)
.description(“数据统计、用户管理、商品管理”)
.version(“1.0.0”)
.build())
.securitySchemes(Arrays.asList(apiKey()))
.securityContexts(Arrays.asList(adminSecurityContext()));
}

/**
* 公开API分组 – 无需认证
*/
@Bean
public Docket publicApi() {
return new Docket(DocumentationType.SWAGGER_2)
.groupName(“公开API”)
.select()
.apis(RequestHandlerSelectors.basePackage(“com.ecommerce.controller.public”))
.paths(PathSelectors.ant(“/api/public/**”))
.build()
.apiInfo(new ApiInfoBuilder()
.title(“公开API”)
.description(“商品浏览、搜索等公开接口”)
.version(“1.0.0”)
.build());
}

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

private SecurityContext adminSecurityContext() {
return SecurityContext.builder()
.securityReferences(defaultAuth())
.forPaths(PathSelectors.ant(“/api/admin/**”))
.build();
}

List defaultAuth() {
AuthorizationScope authorizationScope = new AuthorizationScope(“global”, “accessEverything”);
AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
authorizationScopes[0] = authorizationScope;
return Arrays.asList(new SecurityReference(“JWT”, authorizationScopes));
}
}
6.3 接口示例代码
@RestController
@RequestMapping(“/api/user”)
@Api(tags = “用户模块”)
public class UserController {

@PostMapping(“/register”)
@ApiOperation(value = “用户注册”, notes = “新用户注册接口”)
@ApiImplicitParams({
@ApiImplicitParam(name = “username”, value = “用户名”, required = true, dataType = “String”),
@ApiImplicitParam(name = “password”, value = “密码”, required = true, dataType = “String”),
@ApiImplicitParam(name = “email”, value = “邮箱”, required = true, dataType = “String”)
})
@ApiResponse(code = 200, message = “注册成功”, response = UserVO.class)
public Result register(@RequestBody UserDTO userDTO) {
// 实现逻辑
return Result.success(userService.register(userDTO));
}

@PostMapping(“/login”)
@ApiOperation(value = “用户登录”, notes = “用户登录获取Token”)
@ApiImplicitParams({
@ApiImplicitParam(name = “username”, value = “用户名”, required = true, dataType = “String”),
@ApiImplicitParam(name = “password”, value = “密码”, required = true, dataType = “String”)
})
@ApiResponse(code = 200, message = “登录成功”, response = LoginVO.class)
public Result login(@RequestBody LoginDTO loginDTO) {
// 实现逻辑
return Result.success(userService.login(loginDTO));
}

@GetMapping(“/info”)
@ApiOperation(value = “获取用户信息”, notes = “获取当前登录用户的信息”)
@ApiImplicitParam(name = “userId”, value = “用户ID”, required = true, dataType = “Long”, paramType = “header”)
@ApiResponse(code = 200, message = “查询成功”, response = UserVO.class)
public Result getUserInfo(@RequestHeader(“userId”) Long userId) {
// 实现逻辑
return Result.success(userService.getUserInfo(userId));
}
}
6.4 配置文件优化
# application.yml
springdoc:
api-docs:
enabled: true
path: /v3/api-docs
swagger-ui:
path: /swagger-ui.html
enabled: true
# 自定义分组配置
groups:
– name: 用户模块
display-name: 用户模块
paths-to-match: /api/user/**
– name: 商品模块
display-name: 商品模块
paths-to-match: /api/product/**
– name: 订单模块
display-name: 订单模块
paths-to-match: /api/order/**
– name: 后台管理
display-name: 后台管理
paths-to-match: /api/admin/**
– name: 公开API
display-name: 公开API
paths-to-match: /api/public/**
# 全局配置
info:
title: 电商平台API文档
version: 1.0.0
description: 提供完整的电商系统接口文档
contact:
name: 技术团队
email: tech@ecommerce.com
七、最佳实践与团队协作建议
7.1 分组命名规范
使用中文分组名
:便于团队成员理解
保持一致性
:统一的命名风格
避免过长
:简洁明了,如”用户管理”而非”用户管理模块接口”
7.2 文档维护流程
/**
* 文档版本管理示例
*/
@RestController
@RequestMapping(“/api/v1/user”)
@Api(tags = “用户管理”, description = “版本1.0 – 2024-01-01发布”)
public class UserV1Controller {
// 稳定版本接口
}

@RestController
@RequestMapping(“/api/v2/user”)
@Api(tags = “用户管理”, description = “版本2.0 – 开发中”)
public class UserV2Controller {
// 新版本接口
}
7.3 团队协作规范
代码审查
:新增接口必须包含完整的Swagger注解
定期同步
:每周同步一次文档到Confluence或Wiki
自动化测试
:使用Swagger Codegen生成客户端代码进行测试
权限管理
:生产环境禁用Swagger UI或限制访问IP
7.4 常见问题解决
问题1:分组不显示
// 检查包路径是否正确
// 确保Controller类上有@Api注解
// 确认Docket配置的paths匹配正确
问题2:性能慢
// 使用精确的路径匹配,避免PathSelectors.any()
// 限制扫描的包范围
// 考虑使用SpringDoc(性能更好)
问题3:多环境配置
// 使用@Profile注解控制不同环境的分组
@Profile({“dev”, “test”})
@Bean
public Docket debugApi() {
// 调试环境分组
}
八、总结
通过本文的详细讲解,你应该已经掌握了Swagger接口分组的核心技术和实战技巧。记住以下关键点:
分组是提升文档可读性的关键
:按业务模块、版本、权限等维度组织
SpringDoc是未来趋势
:建议新项目使用SpringDoc替代Springfox
配置要灵活
:使用动态配置、自定义注解等高级技巧
团队协作很重要
:建立规范的文档维护流程
合理的接口分组不仅能提升开发效率,还能降低沟通成本,是构建高质量API文档的基石。希望本文的实战技巧能帮助你在实际项目中游刃有余!