集成 Knife4j
- 前言
- Knife4j是什么
- 集成 Knife4j
- 引入 pom 依赖
- 添加基础配置
- 启动程序测试
- 完善文档信息
- 编写配置类
- 修改 UserController
- 修改 UserEntity
- 修改 BaseEntity
- 文档效果图
- swagger 界面
- knife4j 界面
前言
前面一小节我们使用postman来进行接口的调试,如果接口一多,就很不方便进行管理,也不方便调试,所以我们本小节集成一个接口文档组件Knife4j,有疑问可以查看 Knife4j 官网。
Knife4j是什么
Knife4j是一个集Swagger2 和 OpenAPI3 为一体的增强解决方案
Knife4j 是为 Java MVC 框架集成 Swagger 生成 Api 文档的增强解决方案,前身是 swagger-bootstrap-ui
,致力于 springfox-swagger
的增强 UI 实现。knife4j 为了契合微服务的架构发展,由于原来 swagger-bootstrap-ui
采用的是后端 Java 代码 + 前端 UI 混合打包的方式,在微服务架构下显的很臃肿,因此项目正式更名为 knife4j,更名后主要专注的方面如下:
- 后端 Java 代码以及前端 UI 模块进行了分离,在微服务架构下使用更加灵活
- 提供专注于 Swagger 的增强解决方案,不同于只是单纯增强前端 UI 部分
集成 Knife4j
我们参考 Knife4j 官网的教程进行集成。
因为我们的 Spring Boot 版本是 3.2.0,所以只支持 OpenAPI3 规范
- Spring Boot 3 只支持OpenAPI3规范
- Knife4j提供的starter已经引用springdoc-openapi的jar,开发者需注意避免jar包冲突
引入 pom 依赖
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId>
<version>4.3.0</version>
</dependency>
添加基础配置
引入之后,其余的配置,开发者即可完全参考springdoc-openapi的项目说明,Knife4j只提供了增强部分,如果要启用Knife4j的增强功能,可以在配置文件中进行开启
官网提供的部分配置如下,我们修改一下相关信息:
# springdoc-openapi项目配置
springdoc:
swagger-ui:
# swagger ui 路径
path: /swagger-ui.html
# 排序方式 alpha 按字母顺序
tags-sorter: alpha
operations-sorter: alpha
api-docs:
# 接口文档路径
path: /v3/api-docs
group-configs:
- group: 'sys'
paths-to-match: '/**'
packages-to-scan: com.xm.module.sys
# knife4j的增强配置,不需要增强可以不配
knife4j:
enable: true
setting:
language: zh_cn
启动程序测试
配置好了之后,我们就可以启动程序,访问我们刚才配置的路径了,这里有三个路径,我们分别用浏览器访问看看。
1、/swagger-ui.html,这是 swagger-ui 的页面,Springdoc本身也是集成了Swagger3
2、/v3/api-docs,这就是 Springdoc 的接口接口文档,可以导入到 postman 等工具中。
3、/doc.html,这是 Knife4j 的默认界面,可以理解为是 swagger-ui 的增强版,展示的内容一样,只是展示的 ui 变了。
完善文档信息
ok,我们上面只是将 Knife4j 引入到我们的项目中了,但是里面的接口信息还都是默认的,可以通过 swagger-ui 界面看到,有一个 user-controller,下面有多个接口,都是默认的名称,这样我们将文档给别人或前端,理解起来会很困难,所以我们在开发中,是要补全这些信息的,完善一份持续维护的接口文档。
所以,最后一步就是使用 OpenAPI3 的规范注解,注释各个 Spring 的 REST 接口。我们先来看看 swagger2 和 openAPI3 的注解差别。
Spwagger2和OpenApi3注解的对应关系
Swagger 2 | OpenAPI 3 | 注解位置 |
---|---|---|
@Api | @Tag(name = “接口类描述”) | Controller 类上 |
@ApiOperation | @Operation(summary = “接口方法描述”) | Controller 方法上 |
@ApiImplicitParams | @Parameters | Controller 方法上 |
@ApiImplicitParam | @Parameter(description = “参数描述”) | Controller 方法上 @Parameters 里 |
@ApiParam | @Parameter(description = “参数描述”) | Controller 方法的参数上 |
@ApiIgnore | @Parameter(hidden = true) 或 @Operation(hidden = true) 或 @Hidden | - |
@ApiModel | @Schema | DTO类上 |
@ApiModelProperty | @Schema | DTO属性上 |
编写配置类
首先添加一个配置类,配置一些项目相关的信息。
@Configuration
public class SpringDocConfig {
@Bean
public OpenAPI openApi() {
return new OpenAPI().info(
new Info().title("XM-ADMIN系统接口文档")
.version("1.0")
.description("一个数据中台项目的接口文档")
.termsOfService("http://localhost:9527/")
.contact(new Contact().name("xiaoming").url("https://github.com/shixiaomingya"))
.license(new License().name("Apache 2.0").url("http://localhost:9527/")));
}
}
修改 UserController
@Tag(name = "用户管理")
@RestController
@RequestMapping("/sys/user")
public class UserController {
@Resource
private UserService userService;
@GetMapping("/{id}")
@Operation(summary = "根据用户ID查询用户")
public UserEntity get(@PathVariable Long id) {
return userService.get(id);
}
@GetMapping("/list")
@Operation(summary = "查询全部")
public List<UserEntity> lists() {
return userService.lists();
}
@GetMapping("/page")
@Operation(summary = "分页查询")
public Page<UserEntity> page(int page, int size) {
return userService.page(PageRequest.of(page - 1, size));
}
@PostMapping
@Operation(summary = "新增用户")
public void save(@RequestBody UserEntity user) {
userService.save(user);
}
@PutMapping
@Operation(summary = "修改用户")
public void update(@RequestBody UserEntity user) {
userService.update(user);
}
@DeleteMapping("/{id}")
@Operation(summary = "根据用户ID删除用户")
public void delete(@PathVariable Long id) {
userService.delete(id);
}
}
修改 UserEntity
@Data
@Entity
@Table(name = "sys_user")
@Schema(description = "用户实体")
public class UserEntity extends BaseEntity implements Serializable {
/**
* Id 表示为表 ID
* GenerationType.IDENTITY 使用自增长主键
*/
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Schema(description = "用户ID")
private Long id;
/**
* REQUIRED 表示用户必填
*/
@Schema(description = "用户名称", requiredMode = Schema.RequiredMode.REQUIRED)
private String name;
@Schema(description = "用户昵称")
private String nickname;
@Schema(description = "用户年龄")
private Integer age;
@Schema(description = "用户邮箱")
private String email;
/**
* hidden 表示不在文档中显示该字段
*/
@Schema(description = "用户密码", requiredMode = Schema.RequiredMode.REQUIRED, hidden = true)
private String password;
}
修改 BaseEntity
@Data
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
@Schema(description = "基础实体")
public class BaseEntity {
@CreatedBy
@Column(name = "create_user", updatable = false)
@Schema(description = "创建用户")
private String createUser;
@LastModifiedBy
@Column(name = "update_user")
@Schema(description = "修改用户")
private String updateUser;
@CreatedDate
@Column(name = "create_time", updatable = false)
@Schema(description = "创建时间")
private Date createTime;
@LastModifiedDate
@Column(name = "update_time")
@Schema(description = "修改时间")
private Date updateTime;
}
文档效果图
swagger 界面
knife4j 界面