Swagger 3.0 + Knife4j 入门到实战:Spring Boot API 文档搭建、注解详解与生产环境安装

Swagger 3.0 与 Knife4j

摘要:本文介绍 Swagger 3.0 与 Knife4j 的入门知识。文档详解常用注解(如 @Tag、@Operation、@Schema 等),提供实体类与控制器示例,还涵盖 API 分组、全局参数配置,以及生产环境关闭 Swagger 的方法,同时列举常见问题及解决办法与学习资源。

1. 什么是 Swagger 和 Knife4j?

Swagger 3.0

Swagger 是一个规范和完整的框架,用于生成、描述、调用和可视化 RESTful 风格的 Web 服务。Swagger 3.0(也称为 OpenAPI 3.0)是其最新版本,提供了更强大的功能和更简洁的语法。

Knife4j

Knife4j 是一款基于 Swagger 的增强工具,为 Java 开发者提供了更加友好的 API 文档界面和更多实用功能。它封装了 Swagger 的底层实现,让开发者能更简单地在 Spring Boot 项目中集成 Swagger。

knife4j-openapi3-jakarta-spring-boot-starter:4.5.0 是适用于 Jakarta EE 规范(替代传统的 JEE)的 Spring Boot starter,简化了 Swagger 3.0 在 Spring Boot 项目中的集成。

2. 环境准备

开发环境要求

  • JDK 11 或更高版本
  • Spring Boot 2.7.x 或 3.x
  • Maven 或 Gradle 构建工具

3. 快速开始

3.1 创建 Spring Boot 项目并添加依赖

Maven 项目(pom.xml)

<dependencies>
  <!-- Spring Boot Web 依赖 -->
    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!-- Knife4j OpenAPI3 Jakarta 依赖 -->
      <dependency>
      <groupId>com.github.xiaoymin</groupId>
      <artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId>
      <version>4.5.0</version>
      </dependency>
    </dependencies>

Gradle 项目(build.gradle)

dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'com.github.xiaoymin:knife4j-openapi3-jakarta-spring-boot-starter:4.5.0'
}

3.2 基本配置

创建配置类:

@Configuration
public class SwaggerConfig {
@Bean
public OpenAPI customOpenAPI() {
return new OpenAPI()
// API 基本信息
.info(new Info()
.title("我的 API 文档")  // 标题
.description("这是一个使用 Knife4j 和 Swagger 3.0 构建的 API 文档示例")  // 描述
.version("1.0.0")  // 版本
// 联系人信息
.contact(new Contact()
.name("开发者")
.email("developer@example.com")
.url("https://www.example.com"))
// 许可证信息
.license(new License()
.name("Apache 2.0")
.url("https://www.apache.org/licenses/LICENSE-2.0")));
}
}

3.3 启动应用并访问文档

  1. 创建 Spring Boot 启动类:
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
  1. 启动应用后,访问 Knife4j 文档界面:
    • 地址:http://localhost:8080/doc.html
    • 你将看到 Knife4j 提供的友好 API 文档界面

4. 常用注解详解

Swagger 3.0 提供了一系列注解来描述 API,以下是常用注解的说明:

4.1 类级别注解

@Tag

用于描述控制器类的作用

@Tag(name = "用户管理", description = "用户的增删改查操作")
@RestController
@RequestMapping("/users")
public class UserController {
// ...
}

4.2 方法级别注解

@Operation

用于描述接口方法的作用

@Operation(summary = "获取用户列表", description = "查询所有用户信息")
@GetMapping
public List<User> getUsers() {
  // ...
  }
@Parameter

用于描述方法参数

@Operation(summary = "获取用户详情", description = "根据ID查询用户信息")
@GetMapping("/{id}")
public User getUserById(
@Parameter(description = "用户ID", required = true, example = "1")
@PathVariable Long id
) {
// ...
}
@ApiResponses 和 @ApiResponse

用于描述接口的响应信息

@Operation(summary = "删除用户", description = "根据ID删除用户")
@ApiResponses({
@ApiResponse(responseCode = "200", description = "删除成功"),
@ApiResponse(responseCode = "404", description = "用户不存在")
})
@DeleteMapping("/{id}")
public String deleteUser(@PathVariable Long id) {
// ...
}

4.3 实体类注解

@Schema

用于描述实体类或其属性

@Schema(description = "用户实体类")
public class User {
@Schema(description = "用户ID", example = "1")
private Long id;
@Schema(description = "用户名", example = "张三", required = true)
private String name;
@Schema(description = "用户年龄", example = "25", minimum = "0", maximum = "120")
private Integer age;
// getter 和 setter 方法
}

4.4 用注解和核心属性

注解名称适用范围作用描述常用属性及解释
@Tag类(控制器)描述控制器的整体功能,用于对接口进行分类- name:控制器名称(必填,如 “用户管理”)- description:控制器功能描述(如 “用户的增删改查操作”)
@Operation方法(接口)描述单个接口的功能、用途和细节- summary:接口简要说明(如 “获取用户列表”)- description:接口详细描述(如 “查询所有用户信息”)- hidden:是否隐藏接口(默认 false,设为 true 则不显示在文档中)
@Parameter方法参数描述接口的单个参数(如路径参数、请求参数)- name:参数名称- description:参数描述- required:是否必填(默认 false)- example:参数示例值- in:参数位置(如 “path” 路径参数、“query” 查询参数,默认自动推断)
@Parameters方法用于包含多个 @Parameter 注解,批量描述参数- 无单独属性,内部包含多个 @Parameter 注解
@ApiResponses方法用于包含多个 @ApiResponse 注解,批量描述接口的响应结果- 无单独属性,内部包含多个 @ApiResponse 注解
@ApiResponse@ApiResponses 内部描述接口的单个响应状态(如 HTTP 状态码对应的结果)- responseCode:HTTP 响应状态码(如 “200” 成功、“404” 未找到)- description:响应描述- content:响应内容类型(结合 @Content 使用,指定返回数据结构)
@Content@ApiResponse 内部描述响应的内容类型和数据结构- mediaType:响应媒体类型(如 “application/json”)- schema:响应数据结构(结合 @Schema 指定实体类)
@Schema实体类 / 实体属性描述实体类或其属性的元信息(用于定义请求 / 响应的数据结构)- description:类或属性的描述- required:属性是否必填(默认 false)- example:属性示例值- format:属性格式(如 “email”、“date”)- minimum/maximum:数值类型的最小 / 最大值(如年龄的 0-120)
@RequestBody方法参数描述请求体参数(通常用于 POST/PUT 请求的 JSON 参数)- description:请求体描述- required:是否必填(默认 true)- content:请求体内容(结合 @Content 和 @Schema 指定实体类)
@OpenAPIDefinition配置类 / 应用全局定义 API 文档的元信息(如标题、版本等,可替代配置类中的 OpenAPI Bean)- info:API 基本信息(结合 @Info 使用,包含标题、版本等)- servers:API 服务器地址(如开发 / 生产环境地址)
@Info@OpenAPIDefinition 内部定义 API 的基本信息(标题、版本、联系人等)- title:API 标题- version:API 版本- description:API 描述- contact:联系人信息(结合 @Contact)- license:许可证信息(结合 @License)
@Contact@Info 内部定义 API 的联系人信息- name:联系人姓名- email:联系人邮箱- url:联系人网址
@License@Info 内部定义 API 的许可证信息- name:许可证名称(如 “Apache 2.0”)- url:许可证地址
@SecurityScheme配置类定义安全方案(如 Token 认证)- name:安全方案名称- type:安全类型(如 “HTTP”)- scheme:认证方案(如 “bearer”)- bearerFormat:令牌格式(如 “JWT”)- in:令牌位置(如 “header”)

5. 完整示例

下面是一个包含控制器、实体类的完整示例:

@Schema(description = "用户实体类")
public class User {
@Schema(description = "用户ID", example = "1")
private Long id;
@Schema(description = "用户名", example = "张三", required = true)
private String name;
@Schema(description = "用户年龄", example = "25", minimum = "0", maximum = "120")
private Integer age;
@Schema(description = "用户邮箱", example = "zhangsan@example.com", format = "email")
private String email;
// 构造方法
public User() {}
public User(String name, Integer age, String email) {
this.name = name;
this.age = age;
this.email = email;
}
// getter 和 setter 方法
}

用户控制器示例:

@Tag(name = "用户管理", description = "用户的增删改查操作")
@RestController
@RequestMapping("/users")
public class UserController {
// 模拟数据库存储
private static final ConcurrentMap<Long, User> userMap = new ConcurrentHashMap<>();
  private static final AtomicLong idGenerator = new AtomicLong(1);
  // 初始化一些测试数据
  static {
  userMap.put(idGenerator.getAndIncrement(), new User("张三", 25, "zhangsan@example.com"));
  userMap.put(idGenerator.getAndIncrement(), new User("李四", 30, "lisi@example.com"));
  }
  @Operation(summary = "获取用户列表", description = "查询所有用户信息")
  @GetMapping
  public List<User> getUsers() {
    return new ArrayList<>(userMap.values());
      }
      @Operation(summary = "获取用户详情", description = "根据ID查询用户信息")
      @ApiResponses({
      @ApiResponse(responseCode = "200", description = "查询成功",
      content = @Content(schema = @Schema(implementation = User.class))),
      @ApiResponse(responseCode = "404", description = "用户不存在")
      })
      @GetMapping("/{id}")
      public ResponseEntity<User> getUserById(
        @Parameter(description = "用户ID", required = true, example = "1")
        @PathVariable Long id) {
        User user = userMap.get(id);
        if (user == null) {
        return ResponseEntity.notFound().build();
        }
        return ResponseEntity.ok(user);
        }
        @Operation(summary = "创建用户", description = "新增用户信息")
        @PostMapping
        public User createUser(
        @Parameter(description = "用户信息", required = true)
        @RequestBody User user) {
        Long id = idGenerator.getAndIncrement();
        user.setId(id);
        userMap.put(id, user);
        return user;
        }
        @Operation(summary = "更新用户", description = "根据ID更新用户信息")
        @PutMapping("/{id}")
        public ResponseEntity<User> updateUser(
          @Parameter(description = "用户ID", required = true, example = "1")
          @PathVariable Long id,
          @Parameter(description = "更新后的用户信息", required = true)
          @RequestBody User user) {
          if (!userMap.containsKey(id)) {
          return ResponseEntity.notFound().build();
          }
          user.setId(id);
          userMap.put(id, user);
          return ResponseEntity.ok(user);
          }
          @Operation(summary = "删除用户", description = "根据ID删除用户")
          @ApiResponses({
          @ApiResponse(responseCode = "200", description = "删除成功"),
          @ApiResponse(responseCode = "404", description = "用户不存在")
          })
          @DeleteMapping("/{id}")
          public ResponseEntity<Void> deleteUser(
            @Parameter(description = "用户ID", required = true, example = "1")
            @PathVariable Long id) {
            if (!userMap.containsKey(id)) {
            return ResponseEntity.notFound().build();
            }
            userMap.remove(id);
            return ResponseEntity.ok().build();
            }
            }

6. 高级配置

6.1 配置 API 分组

当项目较大时,可以将 API 进行分组管理:

@Configuration
public class SwaggerGroupConfig {
// 用户管理 API 分组
@Bean
public OpenAPI userAPI() {
return new OpenAPI()
.info(new Info()
.title("用户管理 API")
.description("用户相关的所有接口")
.version("1.0.0"));
}
// 订单管理 API 分组
@Bean
public OpenAPI orderAPI() {
return new OpenAPI()
.info(new Info()
.title("订单管理 API")
.description("订单相关的所有接口")
.version("1.0.0"));
}
}

然后在控制器上指定所属分组:

@Tag(name = "用户管理", description = "用户的增删改查操作")
@RestController
@RequestMapping("/users")
@OpenAPIDefinition(openapi = @OpenAPIDefinitionRef(ref = "#/components/schemas/userAPI"))
public class UserController {
// ...
}

6.2 全局参数配置

可以配置全局参数,如令牌(Token):

@Configuration
public class SwaggerGlobalParamConfig {
@Bean
public OpenAPI customOpenAPI() {
// 定义安全方案
SecurityScheme securityScheme = new SecurityScheme()
.type(SecurityScheme.Type.HTTP)
.scheme("bearer")
.bearerFormat("JWT")
.in(SecurityScheme.In.HEADER)
.name("Authorization");
// 添加安全要求
SecurityRequirement securityRequirement = new SecurityRequirement().addList("bearerAuth");
return new OpenAPI()
.info(new Info().title("带全局Token的API文档").version("1.0.0"))
.components(new Components().addSecuritySchemes("bearerAuth", securityScheme))
.addSecurityItem(securityRequirement);
}
}

7. 生产环境关闭 Swagger

在生产环境中,我们通常需要关闭 Swagger 文档以提高安全性:

7.1 通过配置文件控制

# application.yml
spring:
profiles:
active: dev
---
# application-dev.yml
knife4j:
enable: true
---
# application-prod.yml
knife4j:
enable: false

7.2 通过注解控制

@Configuration
@Profile({"dev", "test"}) // 只在开发和测试环境生效
public class SwaggerConfig {
// ...
}

8. 常见问题及解决方法

  1. 访问 doc.html 出现 404 错误

    • 检查依赖是否正确引入
    • 检查是否有拦截器拦截了请求,需要放行 /doc.html/webjars/** 等路径
  2. 注解不生效

    • 检查注解是否导入正确(Swagger 3.0 的注解在 io.swagger.v3.oas.annotations 包下)
    • 确保配置类被 Spring 扫描到
  3. 实体类属性不显示

    • 确保实体类有 getter 和 setter 方法
    • 检查是否使用了正确的 @Schema 注解

9. 学习资源推荐

  1. 官方文档

  2. 相关教程

    • Spring Boot 集成 Swagger 的官方指南
    • Knife4j 的 GitHub 仓库示例
  3. 工具

通过以上内容,你应该已经掌握了 Swagger 3.0 和 Knife4j 的基本使用方法。建议结合实际项目进行练习,逐步熟悉各种注解和配置选项,以提高 API 文档的质量和开发效率。

posted on 2025-09-30 16:45  ljbguanli  阅读(38)  评论(0)    收藏  举报