版本:
SpringBoot:3.3.3
Knife4j:4.5.0创建时间:2024-10-08
一、官网
Knife4j 的 SpringBoot3 官方说明文档:
https://doc.xiaominfo.com/docs/quick-start#spring-boot-3
springdoc官网:https://springdoc.org/
二、Knife4j - 基本使用
依赖
<dependency><groupId>com.github.xiaoymin</groupId><artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId><version>4.5.0</version></dependency>
效果
引入此依赖后,运行应用,此时接口文档页面已经能够打开。
访问接口文档地址:http://ip:port/doc.html
比如,在本地运行的端口号为 9003 的应用,接口文档访问地址为:http://localhost:9003/doc.html
Knife页面
http://localhost:9003/doc.html
Swagger页面
http://localhost:9003/swagger-ui/index.html
三、生产环境关闭接口文档
官网说明
https://doc.xiaominfo.com/docs/features/accessControl
配置
knife4j:# 开启增强配置enable: true# 标识是否生产环境:true-生产环境关闭文档,false-显示文档production: true
效果
访问接口文档页面,会提示:You do not have permission to access this page
Knife页面
http://localhost:9003/doc.html
Swagger页面
http://localhost:9003/swagger-ui/index.html
查询接口文档(JSON格式)的 API 接口
http://localhost:9003/v3/api-docs
四、配置文件(可选)
springdoc和Knife4j配置
# springdoc-openapi项目配置
springdoc:swagger-ui:path: /swagger-ui.htmltags-sorter: alphaoperations-sorter: alphaapi-docs:path: /v3/api-docsgroup-configs:- group: '默认分组'paths-to-match: '/**'packages-to-scan: com.example
# knife4j的增强配置,不需要增强可以不配
knife4j:enable: truesetting:language: zh_cnenable-footer: false
接口排序,按照 接口路径
字母顺序排序。
五、配置接口文档描述信息(主页)
接口文档描述信息,配置效果:
@Bean注册OpenAPI
接口文档中 主页(基本信息)
的配置,需要通过Java代码写配置类。
package com.example.knife4j.config;import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Contact;
import io.swagger.v3.oas.models.info.Info;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class Knife4jConfig {@Beanpublic OpenAPI openAPI() {return new OpenAPI().info(new Info().title("Knife4j示例项目").description("Knife4j示例项目接口文档的详细描述").version("V1.0.0").contact(new Contact().name("宋冠巡")));}}
springdoc的官网文档:
@OpenAPIDefinition注解
package com.example.knife4j.config;import io.swagger.v3.oas.annotations.OpenAPIDefinition;
import io.swagger.v3.oas.annotations.info.Contact;
import io.swagger.v3.oas.annotations.info.Info;@OpenAPIDefinition(info = @Info(title = "Knife4j示例项目", description = "Knife4j示例项目接口文档的详细描述", version = "V1.0.0", contact = @Contact(name = "宋冠巡")))
public class OpenAPIConfig {
}
springdoc的官网文档:
六、OpenAPI3注解
使用OpenAPI3的规范注解,注释接口和数据模型,示例代码如下。
接口注解
package com.example.knife4j.web.user.controller;import com.example.hello_common.model.vo.UserVo;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.time.LocalDate;
import java.time.LocalDateTime;@Slf4j
@RestController
@RequestMapping("/users")
@Tag(name = "用户管理")
public class UserController {@GetMapping("/{id}")@Operation(summary = "查询用户")@Parameter(name = "id", description = "用户ID", example = "1234567890123456789")public UserVo getUserById(@PathVariable String id) {UserVo vo = new UserVo();vo.setId(id);vo.setName("张三");vo.setMobilePhone("18612345678");vo.setEmail("zhangsan@example.com");vo.setBeginTime(LocalDateTime.of(2024, 1, 1, 8, 30, 0));vo.setEndTime(LocalDateTime.of(2024, 12, 31, 17, 0, 0));vo.setBeginDate(LocalDate.of(2024, 1, 1));vo.setEndDate(LocalDate.of(2024, 12, 31));return vo;}}
数据模型注解
package com.example.hello_common.model.vo;import io.swagger.v3.oas.annotations.media.ExampleObject;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;import java.time.LocalDate;
import java.time.LocalDateTime;@Data
@Schema(name = "用户VO")
public class UserVo {@Schema(description = "用户ID", example = "1234567890123456789")private String id;@Schema(description = "姓名", example = "张三")private String name;@Schema(description = "手机号码", example = "18612345678")private String mobilePhone;@Schema(description = "电子邮箱", example = "zhangsan@example.com")private String email;@Schema(description = "开始时间", example = "2024-01-01 08:30:00")private LocalDateTime beginTime;@Schema(description = "结束时间", example = "2024-12-31 17:00:00")private LocalDateTime endTime;@Schema(description = "开始日期", example = "2024-01-01")private LocalDate beginDate;@Schema(description = "结束日期", example = "2024-12-31")private LocalDate endDate;}
接口文档效果
七、附录
UserController
package com.example.knife4j.web.user.controller;import com.example.hello_common.exception.BusinessException;
import com.example.hello_common.model.param.UserParam;
import com.example.hello_common.model.vo.UserVo;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;@Slf4j
@RestController
@RequestMapping("/users")
@Tag(name = "用户管理")
public class UserController {@PostMappingpublic void addUser(@RequestBody UserParam param) {log.info("新增用户。param={}", param);boolean isNameExists = generateMockUsers().stream().anyMatch(user -> user.getName() != null && user.getName().equals(param.getName()));if (isNameExists) {throw new BusinessException(String.format("用户名[%s]已存在", param.getName()));}}@DeleteMapping("/{id}")public void deleteUser(@PathVariable String id) {log.info("删除用户。id={}", id);boolean isIdExists = generateMockUsers().stream().anyMatch(user -> user.getId() != null && user.getId().equals(id));if (!isIdExists) {throw new BusinessException("用户ID不存在");}}@PutMapping("/{id}")public void editUser(@PathVariable String id, @RequestBody UserParam param) {log.info("编辑用户。id={},param={}", id, param);boolean isIdExists = generateMockUsers().stream().anyMatch(user -> user.getId() != null && user.getId().equals(id));if (!isIdExists) {throw new BusinessException("用户ID不存在");}}@GetMapping("/{id}")@Operation(summary = "查询用户")@Parameter(name = "id", description = "用户ID", example = "1234567890123456789")public UserVo getUserById(@PathVariable String id) {UserVo vo = new UserVo();vo.setId(id);vo.setName("张三");vo.setMobilePhone("18612345678");vo.setEmail("zhangsan@example.com");vo.setBeginTime(LocalDateTime.of(2024, 1, 1, 8, 30, 0));vo.setEndTime(LocalDateTime.of(2024, 12, 31, 17, 0, 0));vo.setBeginDate(LocalDate.of(2024, 1, 1));vo.setEndDate(LocalDate.of(2024, 12, 31));return vo;}@GetMappingpublic List<UserVo> listUsers() {return generateMockUsers();}private List<UserVo> generateMockUsers() {List<UserVo> list = new ArrayList<>();UserVo vo = new UserVo();vo.setId("1234567890123456789");vo.setName("张三");vo.setMobilePhone("18612345678");vo.setEmail("zhangsan@qq.com");vo.setBeginTime(LocalDateTime.of(2024, 1, 1, 8, 30, 0));vo.setEndTime(LocalDateTime.of(2024, 12, 31, 17, 0, 0));vo.setBeginDate(LocalDate.of(2024, 1, 1));vo.setEndDate(LocalDate.of(2024, 12, 31));list.add(vo);UserVo vo2 = new UserVo();vo2.setId("1234567890123456781");vo2.setName("李四");vo2.setMobilePhone("13412345678");vo2.setEmail("lisi@example.com");vo.setBeginTime(LocalDateTime.of(2024, 1, 1, 8, 30, 0));vo.setEndTime(LocalDateTime.of(2024, 12, 31, 17, 0, 0));vo.setBeginDate(LocalDate.of(2024, 1, 1));vo.setEndDate(LocalDate.of(2024, 12, 31));list.add(vo2);return list;}}
UserVo
package com.example.hello_common.model.vo;import io.swagger.v3.oas.annotations.media.ExampleObject;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;import java.time.LocalDate;
import java.time.LocalDateTime;@Data
@Schema(name = "用户VO")
public class UserVo {@Schema(description = "用户ID", example = "1234567890123456789")private String id;@Schema(description = "姓名", example = "张三")private String name;@Schema(description = "手机号码", example = "18612345678")private String mobilePhone;@Schema(description = "电子邮箱", example = "zhangsan@example.com")private String email;@Schema(description = "开始时间", example = "2024-01-01 08:30:00")private LocalDateTime beginTime;@Schema(description = "结束时间", example = "2024-12-31 17:00:00")private LocalDateTime endTime;@Schema(description = "开始日期", example = "2024-01-01")private LocalDate beginDate;@Schema(description = "结束日期", example = "2024-12-31")private LocalDate endDate;}
八、参考
Knife4j 生产环境关闭接口文档 doc.html,亲测有效!
Gitee - 关闭Knife4j