一,Swagger2介绍
Swagger2 是一种 API 文档生成工具,主要用于 描述、消费和可视化 RESTful Web 服务。它能根据你的后端代码(通常是 Spring Boot 项目中的 Controller)自动生成交互式文档页面,方便前端查看接口、参数、返回值,甚至直接在线测试接口。
核心作用:
- 自动生成 API 文档 不需要手动写 markdown 或 word 文档,Swagger 自动根据代码注解生成文档。
- 在线可视化文档页面(Swagger UI) 支持在浏览器中展示接口列表、请求参数、返回示例等,还能在线调试接口。
- 统一团队接口沟通 前后端对接口结构和字段定义一目了然,减少沟通成本。
Swagger2 的发展背景
| 年份 | 阶段 / 事件 | 说明 |
|---|---|---|
| ~2010 | Swagger 项目创建 | Wordnik 内部项目,解决接口文档不一致的问题。 |
| 2011 | Swagger 开源 | 包含规范 + UI + 代码生成器。 |
| 2014 | Swagger 1.x 被广泛使用 | 但文档能力有限,规范结构不清晰。 |
| 2015 | Swagger 2.0 发布 | 重写规范,正式成为 OpenAPI 2.0。Swagger2 即基于此。 |
| 2015 | Swagger 捐献给 Linux Foundation | 形成 OpenAPI Initiative(OAI)。 |
| 2017 | OpenAPI 3.0 发布 | 新规范支持更多高级特性,替代 Swagger2。 |
| 2021 | OpenAPI 3.1 发布 | 完全兼容 JSON Schema,推动行业标准化。 |
Springfox
Springfox 是一个用于在 Spring(尤其是 Spring Boot)中集成 Swagger 的开源项目,核心目标是:
- 自动将 Spring Controller 中的注解翻译成 Swagger2 文档(OpenAPI 2.0)
- 简单说:Springfox 就是 Spring Boot + Swagger2 的桥梁。
二,Swagger2快速入门
-
添加 Maven 依赖
<dependencies> <!-- 核心依赖 --> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.9.2</version> </dependency> <!-- Swagger UI 页面 --> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>2.9.2</version> </dependency> </dependencies> -
编写 Swagger 配置类
@Configuration @EnableSwagger2 public class SwaggerConfig { @Bean public Docket createRestApi() { return new Docket(DocumentationType.SWAGGER_2) .apiInfo(apiInfo()) .select() .apis(RequestHandlerSelectors.basePackage("com.example.controller")) .paths(PathSelectors.any()) .build(); } private ApiInfo apiInfo() { return new ApiInfoBuilder() .title("示例项目接口文档") .description("用于展示 Swagger2 基本用法") .version("1.0") .build(); } } -
给 Controller 添加注解
@RestController @RequestMapping("/api") @Api(tags = "用户接口") // 用于 UI 展示分组 public class UserController { @GetMapping("/user") @ApiOperation("获取用户信息") public User getUser() { return new User("Alice", 20); } @PostMapping("/user") @ApiOperation("新增用户") public String addUser(@RequestBody User user) { return "添加成功: " + user.getName(); } } -
启动项目并访问
启动 Spring Boot 项目后,访问:
- 文档页面:
http://localhost:8080/swagger-ui.html - 接口数据:
http://localhost:8080/v2/api-docs
- 文档页面:
-
注意事项
从 Spring Boot 2.6 开始默认使用
PathPatternParser替代了AntPathMatcher,而 Springfox 不兼容,需加上这个配置:# application.yml spring: mvc: pathmatch: matching-strategy: ant_path_matcher
三,Swagger2相关注解
3.1 接口类注解
接口注解:作用于 Controller类
@Api
-
位置:标注在 Controller 类上。
-
作用:用于描述整个类的用途。
-
常用属性:
属性名 说明 value接口的大致说明(可选) tags分组标签(推荐用这个) description详细描述(可选) position控制 Controller 在 UI 中的显示顺序
示例
@Api(tags = "用户管理接口", description = "提供用户的增删改查 API")
@RestController
public class UserController { ... }
跨组显示接口
Swapper默认是按照每个Controller类来分组显示接口的,如果其中一个Controller执行需要另外其他组的Controller接口配合,这个时候就需要我们支持显示其他分组信息。
有两种写法:
-
ApiOperation中tags参数
@DeleteMapping("/delete/{id}") @ApiOperation(value="删除用户",tags={"用户管理","员工管理"}) public int deleteUser(@PathVariable("id") int id){ return userService.removeById(id)?1:0; }这样这个方法既可以在员工管理组显示也可以在用户管理组显示
-
多个不同接口同时指向一个不存在的组
@DeleteMapping("/delete/{id}") @ApiOperation(value="删除用户",tags="不存在的组") public int deleteUser(@PathVariable("id") int id){ return userService.removeById(id)?1:0; }Swapper会新建一个分组来展示这些接口的信息
3.2 方法注解
方法注解:作用于接口方法
@ApiOperation
-
位置:标注在接口方法上。
-
作用:说明接口的功能。
-
常用属性:
属性名 说明 value接口方法的简要描述 notes补充说明(可选) httpMethod请求方式(GET/POST 等,可选)
示例:
@ApiOperation(value = "根据 ID 查询用户", notes = "输入用户 ID,返回用户详细信息")
@GetMapping("/{id}")
public User getUserById(@PathVariable Long id) { ... }
@ApiImplicitParams + @ApiImplicitParam
-
位置:用于描述接口方法参数(尤其是非实体类参数)。
-
作用:补充参数信息,Swagger 才能显示出来。
-
常用属性:
属性名 说明 name参数名 value参数说明 required是否必填 paramType参数类型( query、path、body、header、form)dataType参数数据类型(如 string,int)
示例:
@ApiImplicitParams({
@ApiImplicitParam(name = "id", value = "用户ID", required = true, paramType = "path", dataType = "Long"),
@ApiImplicitParam(name = "token", value = "登录令牌", required = false, paramType = "header", dataType = "String")
})
@GetMapping("/{id}")
public User getUser(@PathVariable Long id, @RequestHeader String token) { ... }
3.3 模型注解
模型注解:作用于实体类
@ApiModel
- 位置:标注在实体类(Java Bean)上。
- 作用:描述一个数据模型类。
java复制编辑@ApiModel(description = "用户实体类")
public class User {
...
}
@ApiModelProperty
- 位置:标注在实体类的字段上。
- 作用:描述字段含义、是否必填、示例值等。
示例:
@ApiModelProperty(value = "用户ID", example = "1001", required = true)
private Long id;
@ApiModelProperty(value = "用户名", example = "Tom", required = true)
private String name;
| 属性名 | 说明 |
|---|---|
value | 字段说明 |
required | 是否必填 |
example | 示例值 |
hidden | 是否隐藏该字段 |
3.4 其他注解
@ApiResponse / @ApiResponses
- 用于说明接口的响应信息(HTTP状态码、返回说明等)。
@ApiResponses({
@ApiResponse(code = 200, message = "操作成功"),
@ApiResponse(code = 400, message = "请求参数错误"),
@ApiResponse(code = 500, message = "服务器内部错误")
})
四,Swagger2配置类
Swagger接口文档主要有四个部分构成:
- 分组信息
- 分组描述信息
- 接口描述信息
- 实体类信息
4.1 基础配置模板
@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()) // 文档基本信息
.enable(true) // 是否启用 Swagger(默认 true)
.groupName("默认分组") // 分组名称
.securitySchemes(securitySchemes()) // 全局认证方案(如 Token)
.securityContexts(securityContexts()); // 安全上下文
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("API 文档")
.description("Spring Boot 集成 Swagger2 示例")
.version("1.0")
.contact(new Contact("作者", "https://example.com", "contact@example.com"))
.license("Apache 2.0")
.licenseUrl("https://www.apache.org/licenses/LICENSE-2.0.html")
.build();
}
}
4.2 核心配置项详解
4.2.1 接口扫描规则
-
指定扫描的包路径
.apis(RequestHandlerSelectors.basePackage("com.example.controller")) -
其他扫描规则:
any():扫描所有接口。none():不扫描任何接口。withClassAnnotation(Controller.class):扫描带有@Controller注解的类。withMethodAnnotation(GetMapping.class):扫描带有@GetMapping注解的方法。
4.2.2 路径过滤规则
-
允许所有路径
.paths(PathSelectors.any()) -
其他规则:
none():不匹配任何路径。ant("/api/**"):匹配/api/开头的路径。regex("/.*"):通过正则表达式匹配路径。
4.2.3 文档信息(ApiInfo)
| 配置项 | 作用 | 示例 |
|---|---|---|
title | 文档标题 | .title("用户管理 API") |
description | 文档描述 | .description("用户增删改查接口") |
version | API 版本号 | .version("1.0.0") |
contact | 作者联系信息 | .contact(new Contact("John", "https://example.com", "john@example.com")) |
license | 许可证名称 | .license("Apache 2.0") |
licenseUrl | 许可证链接 | .licenseUrl("https://example.com/license") |
4.2.4 分组配置
多分组配置
@Bean
public Docket userApi() {
return new Docket(DocumentationType.SWAGGER_2)
.groupName("用户接口")
.select()
.apis(RequestHandlerSelectors.basePackage("com.example.user"))
.build();
}
@Bean
public Docket orderApi() {
return new Docket(DocumentationType.SWAGGER_2)
.groupName("订单接口")
.select()
.apis(RequestHandlerSelectors.basePackage("com.example.order"))
.build();
}
4.2.5 全局参数(如 Token 认证)
@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())
// 配置全局认证方案
.securitySchemes(securitySchemes()) // 定义认证类型
.securityContexts(securityContexts()); // 定义认证范围
}
/**
* 定义认证方案:使用 API Key(Token)
*/
private List<ApiKey> securitySchemes() {
return Arrays.asList(
new ApiKey("Authorization", "Authorization", "header")
);
}
/**
* 定义认证范围:哪些接口需要认证
*/
private List<SecurityContext> securityContexts() {
return Arrays.asList(
SecurityContext.builder()
.securityReferences(defaultAuth()) // 关联认证方案
.forPaths(PathSelectors.any()) // 对所有路径生效
.build()
);
}
/**
* 关联认证方案和权限作用域
*/
private List<SecurityReference> defaultAuth() {
AuthorizationScope[] scopes = new AuthorizationScope[]{
new AuthorizationScope("global", "全局权限")
};
return Arrays.asList(
new SecurityReference("Authorization", scopes)
);
}
// 其他配置(如 apiInfo())省略...
}
securitySchemes():定义认证类型
-
ApiKey参数说明:new ApiKey(name, keyName, passAs)参数 作用 示例值 name认证方案名称(自定义) "Authorization"keyName请求头/参数的键名 "Authorization"passAs参数位置( header/query)"header"示例:
new ApiKey("Authorization", "Authorization", "header")效果:在请求头中添加
Authorization: xxx。
securityContexts():定义认证范围
-
SecurityContext配置项:SecurityContext.builder() .securityReferences(defaultAuth()) // 关联认证方案 .forPaths(PathSelectors.ant("/api/**")) // 仅对 /api/ 开头的路径生效 .build()securityReferences: 关联securitySchemes中定义的认证方案。forPaths: 指定哪些路径需要认证(如PathSelectors.any()表示所有路径)。
defaultAuth():关联认证方案和作用域
-
SecurityReference:将认证方案与权限作用域绑定。new SecurityReference("Authorization", new AuthorizationScope[]{ ... })- 第一个参数:必须与
securitySchemes中定义的name一致。 - 第二个参数:定义权限作用域(一般保留默认即可)。
- 第一个参数:必须与
4.2.6 自定义响应模型
Docket docket = new Docket(DocumentationType.SWAGGER_2)
.useDefaultResponseMessages(false) // 禁用默认响应码描述
.globalResponseMessage(RequestMethod.GET, Arrays.asList(
new ResponseMessageBuilder()
.code(500)
.message("服务器内部错误")
.responseModel(new ModelRef("Error")) // 关联错误模型
.build()
));
4.3 高级配置
4.3.1 自定义 Host 和 Path
Docket docket = new Docket(DocumentationType.SWAGGER_2)
.host("api.example.com") // 指定 Host
.pathMapping("/v1"); // 统一添加路径前缀
4.3.2 禁用默认响应码
Docket docket = new Docket(DocumentationType.SWAGGER_2)
.useDefaultResponseMessages(false); // 关闭 200、401 等默认响应描述
4.4 生产环境优化
4.4.1 动态启用 Swagger
根据 Profile 控制是否启用 Swagger:
@Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.enable(!"prod".equals(env.getProperty("spring.profiles.active"))); // 生产环境关闭
}
4.4.2 结合 Spring Security 权限控制
限制访问 Swagger UI 路径:
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/swagger-ui.html", "/v2/api-docs").hasRole("ADMIN"); // 仅管理员可访问
}
}
五,整合bootstrap-ui框架
Swagger2最带的UI框架太丑了而且不是中文的,阅读不方便,这边将其替换成bootstrap-ui框架
步骤:
-
在依赖中将swagger-ui替换成bootstrap-ui
<dependency> <groupId>com.github.xiaoymin</groupId> <artifactId>swagger-bootstrap-ui</artifactId> <version>1.9.6</version> </dependency> -
在Swagger配置类中放行资源
@EnableWebMvc public class SpringMVCConfig implements WebMvcConfigurer { @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/webjars/**") .addResourceLocations("classpath:/META-INF/resources/webjars/"); registry.addResourceHandler("/doc.html") .addResourceLocations("classpath:/META-INF/resources/"); } } -
访问:
http://localhost:8080/doc.html
需要注意的是,如果开启了其他拦截器,过滤器也必须方行这些静态资源和url