介绍
Knife4j是一种增强解决方案,可用于在Java MVC框架中集成Swagger生成API文档。它的前身是Swagger-bootstrap-ui,而取名为Knife4j是因为它像一把小巧轻量且功能强大的匕首一样。底层是对Springfox进行封装,因此用法与Springfox一致,但界面进行了优化。
Knife4j的核心功能包括:
-
自动生成接口文档:Knife4j可以自动扫描应用程序中的所有接口,并生成对应的API文档。
-
接口在线调试:Knife4j提供了一个方便的在线调试工具,可以直接在文档中测试接口调用并查看接口返回结果。
-
接口描述:使用Knife4j,您可以很容易地为您的API添加描述和注释,这些信息可以帮助用户更好地理解您的API功能和使用方式。
-
身份验证和授权:Knife4j支持常见的身份验证和授权方案,比如OAuth、JWT和基本身份验证。
-
参数校验:Knife4j可以自动验证API请求参数的正确性,确保您的API安全可靠。
引入
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
<version>2.0.1</version>
</dependency>
案例
实体类上的使用
package cn.rqz.entity;
@ApiModel(value = "用户实体",description = "描述")
@Data //lombok
public class User {
@ApiModelProperty(value = "主键")
private int id;
@ApiModelProperty(value = "姓名")
private String name;
@ApiModelProperty(value = "年龄")
private int age;
@ApiModelProperty(value = "地址")
private String address;
}
控制器上的使用
package cn.rqz.controller.user;
@RestController
@RequestMapping("/user")
@Api(tags = "用户控制器")
public class UserController {
@GetMapping("/getUsers")
@ApiOperation(value = "查询所有用户", notes = "查询所有用户信息")
public List<User> getAllUsers() {
User user = new User();
user.setId(100);
user.setName("itcast");
user.setAge(20);
user.setAddress("bj");
List<User> list = new ArrayList<>();
list.add(user);
return list;
}
@PostMapping("/save")
@ApiOperation(value = "新增用户", notes = "新增用户信息")
public String save(@RequestBody User user) {
return "OK";
}
@PutMapping("/update")
@ApiOperation(value = "修改用户", notes = "修改用户信息")
public String update(@RequestBody User user) {
return "OK";
}
@DeleteMapping("/delete")
@ApiOperation(value = "删除用户", notes = "删除用户信息")
public String delete(int id) {
return "OK";
}
@ApiImplicitParams({
@ApiImplicitParam(name = "pageNum", value = "页码",
required = true, type = "Integer"),
@ApiImplicitParam(name = "pageSize", value = "每页条数",
required = true, type = "Integer"),
})
@ApiOperation(value = "分页查询用户信息")
@GetMapping(value = "page/{pageNum}/{pageSize}")
public String findByPage(@PathVariable Integer pageNum,
@PathVariable Integer pageSize) {
return "OK";
}
}
创建配置属性类
/*
*配置属性类,用于封装接口文档相关属性,从配置文件读取信息封装成当前对象
*/
@Data
@ConfigurationProperties(prefix = "pinda.swagger")
public class SwaggerProperties {
private String title = "在线文档"; //标题
private String group = ""; //自定义组名
private String description = "在线文档"; //描述
private String version = "1.0"; //版本
private Contact contact = new Contact(); //联系人
private String basePackage = "cn.rqz.controller"; //swagger会解析的包路径
private List<String> basePath = new ArrayList<>(); //swagger会解析的url规则
private List<String> excludePath = new ArrayList<>();//在basePath基础上需要排除的url规则
private Map<String, DocketInfo> docket = new LinkedHashMap<>(); //分组文档
public String getGroup() {
if (group == null || "".equals(group)) {
return title;
}
return group;
}
@Data
public static class DocketInfo {
private String title = "在线文档"; //标题
private String group = ""; //自定义组名
private String description = "在线文档"; //描述
private String version = "1.0"; //版本
private Contact contact = new Contact(); //联系人
private String basePackage = ""; //swagger会解析的包路径
private List<String> basePath = new ArrayList<>(); //swagger会解析的url规则
private List<String> excludePath = new ArrayList<>();//在basePath基础上需要排除的url
public String getGroup() {
if (group == null || "".equals(group)) {
return title;
}
return group;
}
}
@Data
public static class Contact {
private String name = "pinda"; //联系人
private String url = ""; //联系人url
private String email = ""; //联系人email
}
}
application.yml文件配置(分组)
server:
port: 7788
pinda:
swagger:
enabled: true #是否启用swagger
docket:
user:
title: 用户模块
base-package: cn.rqz.controller.user
menu:
title: 菜单模块
base-package: cn.rqz.controller.menu
application.yml文件配置(不分组)
server:
port: 7788
pinda:
swagger:
enabled: true #是否启用swagger
title: test模块
base-package: cn.rqz.controller
创建配置类
@Configuration
@EnableConfigurationProperties(SwaggerProperties.class)
@EnableSwagger2
//通过yml配置文件的enabled来控制是否生效
@ConditionalOnProperty(name = "pinda.swagger.enabled", havingValue = "true", matchIfMissing = true)
public class SwaggerAutoConfiguration implements BeanFactoryAware {
@Autowired
SwaggerProperties swaggerProperties;
private BeanFactory beanFactory;
@Bean
@ConditionalOnMissingBean
public List<Docket> createRestApi() {
ConfigurableBeanFactory configurableBeanFactory = (ConfigurableBeanFactory) beanFactory;
List<Docket> docketList = new LinkedList<>();
// 没有分组
if (swaggerProperties.getDocket().isEmpty()) {
Docket docket = createDocket(swaggerProperties);
configurableBeanFactory.registerSingleton(swaggerProperties.getTitle(), docket);
docketList.add(docket);
return docketList;
}
// 分组创建
for (String groupName : swaggerProperties.getDocket().keySet()) {
SwaggerProperties.DocketInfo docketInfo = swaggerProperties.getDocket().get(groupName);
ApiInfo apiInfo = new ApiInfoBuilder()
//页面标题
.title(docketInfo.getTitle())
//创建人
.contact(new Contact(docketInfo.getContact().getName(), docketInfo.getContact().getUrl(), docketInfo.getContact().getEmail()))
//版本号
.version(docketInfo.getVersion())
//描述
.description(docketInfo.getDescription()).build();
// base-path处理
// 当没有配置任何path的时候,解析/**
if (docketInfo.getBasePath().isEmpty()) {
docketInfo.getBasePath().add("/**");
}
List<Predicate<String>> basePath = new ArrayList<>();
for (String path : docketInfo.getBasePath()) {
basePath.add(PathSelectors.ant(path));
}
// exclude-path处理
List<Predicate<String>> excludePath = new ArrayList<>();
for (String path : docketInfo.getExcludePath()) {
excludePath.add(PathSelectors.ant(path));
}
Docket docket = new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo).groupName(docketInfo.getGroup()).select()
//为当前包路径
.apis(RequestHandlerSelectors.basePackage(docketInfo.getBasePackage())).paths(Predicates.and(Predicates.not(Predicates.or(excludePath)), Predicates.or(basePath))).build();
configurableBeanFactory.registerSingleton(groupName, docket);
docketList.add(docket);
}
return docketList;
}
//构建 api文档的详细信息
private ApiInfo apiInfo(SwaggerProperties swaggerProperties) {
return new ApiInfoBuilder()
//页面标题
.title(swaggerProperties.getTitle())
//创建人
.contact(new Contact(swaggerProperties.getContact().getName(), swaggerProperties.getContact().getUrl(), swaggerProperties.getContact().getEmail()))
//版本号
.version(swaggerProperties.getVersion())
//描述
.description(swaggerProperties.getDescription()).build();
}
//创建接口文档对象
private Docket createDocket(SwaggerProperties swaggerProperties) {
//API 基础信息
ApiInfo apiInfo = apiInfo(swaggerProperties);
// base-path处理
// 当没有配置任何path的时候,解析/**
if (swaggerProperties.getBasePath().isEmpty()) {
swaggerProperties.getBasePath().add("/**");
}
List<Predicate<String>> basePath = new ArrayList<>();
for (String path : swaggerProperties.getBasePath()) {
basePath.add(PathSelectors.ant(path));
}
// exclude-path处理
List<Predicate<String>> excludePath = new ArrayList<>();
for (String path : swaggerProperties.getExcludePath()) {
excludePath.add(PathSelectors.ant(path));
}
return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo).groupName(swaggerProperties.getGroup()).select().apis(RequestHandlerSelectors.basePackage(swaggerProperties.getBasePackage())).paths(Predicates.and(Predicates.not(Predicates.or(excludePath)), Predicates.or(basePath))).build();
}
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = beanFactory;
}
}
访问地址
http://域名:端口/doc.html