# SpringBoot 整合 Knife4j
# 1 什么是 Knife4j
在日常开发中,写接口文档使我们必不可少的,而 Knife4j 就是一个接口文档工具。可以看作是 Swagger 的升级版,但是界面比 Swagger 更好看,功能更丰富。
早期,swagger-boostrap-ui 是 1.x 版本,如今 swagger-bootrap-ui 到 2.x,同时也更改名字 Knife4j,适用于单体和微服务项目。
Knife4j 官方网站:https://doc.xiaominfo.com/
# 2 SpringBoot 整合 Knife4j
创建 SpringBoot 项目
引入 Knife4j 相关依赖
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
</dependency>
application.yml 配置
# knife4j 的增强配置,不需要增强可以不配
knife4j:
enable: false
setting:
language: zh_cn
配置 Knife4j 配置类
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.ParameterBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.schema.ModelRef;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.service.Parameter;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2WebMvc;
import java.util.ArrayList;
import java.util.List;
//swagger2 配置类
@Configuration
@EnableSwagger2WebMvc
public class Knife4jConfig {
@Bean
public Docket adminApiConfig(){
List<Parameter> pars = new ArrayList<>();
ParameterBuilder tokenPar = new ParameterBuilder();
tokenPar.name("token")
.description("用户token")
.defaultValue("")
.modelRef(new ModelRef("string"))
.parameterType("header")
.required(false)
.build();
pars.add(tokenPar.build());
// 添加 head 参数 end
Docket adminApi = new Docket(DocumentationType.SWAGGER_2)
.groupName("adminApi")
.apiInfo(adminApiInfo())
.select()
// 只显示 admin 路径下的页面
.apis(RequestHandlerSelectors.basePackage("com.dkx"))
.paths(PathSelectors.regex("/admin/.*"))
.build()
.globalOperationParameters(pars);
return adminApi;
}
private ApiInfo adminApiInfo(){
return new ApiInfoBuilder()
.title("后台管理系统-API文档")
.description("本文档描述了后台管理系统微服务接口定义")
.version("1.0")
.contact(new Contact("dkx", "http://dkx.com", "1851644015@qq.com"))
.build();
}
}
在 controller 类中配置注解让 Knife4j 有中文信息
- 类:Api (tags = “”)
- 方法:ApiOperation (value =“”)
@Api(tags = "角色管理接口")
@Controller
@RequestMapping("/admin/system/sysRole")
public class SysRoleController {
@Qualifier(value = "SysRoleServiceImpl")
@Autowired
private SysRoleService sysRoleService;
@ApiOperation(value = "查询所有的接口")
@RequestMapping(value = "/findAll", method = RequestMethod.GET)
@ResponseBody
public List<SysRole> findAllRole() {
List<SysRole> list = sysRoleService.list();
return list;
}
@ApiOperation(value = "逻辑删除接口")
@RequestMapping(value = "/remove", method = RequestMethod.DELETE)
@ResponseBody
public boolean removeRole(Integer id) {
boolean b = sysRoleService.removeById(id);
return b;
}
}
测试
- 启动项目
- 访问路径:localhost/doc.html
测试接口的结果
# 3、接口参数
在方法的入参参数是对象的情况下,我们进行一个假设;
假设这个对象有三个属性,分为 name,age,sex,但我们的实际上只需要前端传来该对象的‘name’值和’age’值。
那么,此时我们通过 @ApiImplicitParam 注解中的’name’属性,来指定该对象的字属性名字即可
@ApiOperation(value = "修改预测外呼参数") | |
@ApiImplicitParams(value = { | |
@ApiImplicitParam(name = "explicitNumber",value = "外显号码",dataType = "String",required = true), | |
@ApiImplicitParam(name = "fsProjectId",value = "预测外呼任务id",dataType = "String",required = true), | |
@ApiImplicitParam(name = "remarks",value = "对于该条外呼预测任务的一些备注说明",dataType = "String",required = false), | |
@ApiImplicitParam(name = "answerRate",value = "接通率",dataType = "Integer",required = true), | |
@ApiImplicitParam(name = "callDuration",value = "通话时长 单位为秒",dataType = "Long",required = true), | |
@ApiImplicitParam(name = "afterCallDuration",value = "话后整理时长 单位为秒",dataType = "Long",required = true), | |
@ApiImplicitParam(name = "skillGroupId",value = "技能组id",dataType = "String",required = true), | |
@ApiImplicitParam(name = "ivrFlowType",value = "是否按键 0:挂断前用户无需按键 1:挂断前需用户按键,并对confirmTip参数定义内容",dataType = "Integer",required = true) | |
}) | |
@PatchMapping(value = "/update") | |
public AjaxResult updateForecastOutbound(@RequestBody ForecastProject forecastProject){ | |
return forecastOutboundService.updateForecastOutbound(forecastProject); | |
} |
# 4、方法返回值
对于返回值的参数描述,则需要使用 @ApiResponses 注解,再以数组形式,在该注解里头使用 @ApiResponse 注解来对返回值进行描述。
不过和入参描述不同的是,我们对返回值的描述是以一个实体类为描述参照的;
这是因为入参参数那样可以有一个或多个,但返回值就只有一个,不过返回值,也就是对象里头有多个字段。
基于此,我们需要先在用于当作返回值类型的实体类里头,通过 @ApiModelProperty 注解对实体类的属性值进行描述,可以参考给实体类的字段添加描述。
@ApiResponse 的属性如下:
@ApiResponse | 对入参进行描述 |
---|---|
code | 响应状态码 |
message | 该响应状态码所对应的消息 |
response | 指定一个用于描述返回值类型,一般实体类。 |
@ApiResponses({ | |
@ApiResponse(code = 200,message = "ok",response = ForecastProject.class) | |
}) | |
@GetMapping(value = "/list") | |
public TableDataInfo getForecastTaskList(@RequestParam(value = "name",required = false) String name, | |
@RequestParam(value = "skillGroupId",required = false) String skillGroupId, | |
@RequestParam(value = "state",required = false) Integer state, | |
@RequestParam(value = "ivrFlowYype",required = false) Integer ivrFlowYype){ | |
startPage(); | |
List<ForecastProject> forecastProjectList = forecastOutboundService.getForecastTaskList(name,skillGroupId,state,ivrFlowYype); | |
return getDataTable(forecastProjectList); | |
} |
不知道你有注意到没,例子中,我指定的返回值类型虽然为’ForecastProject‘,但是方法中的返回值类型却是’TableDataInfo‘。
这是因为 TableDataInfo 是一个用于封装响应结果的对象,ForecastProject 的数据其实被封装在了 TableDataInfo 类中的’rows’字段。
那我们为什么不把 response 属性指定为 TableDataInfo 类呢?
这就是工作协调中要灵活多变的地方,因为你把’TableDataInfo‘类当作要描述的返回值类型去给前端调试的话,是没有意义的!
前端开发人员当然知道需要操作 TableDataInfo.rows 来取得数据,但描述具体信息的实体类到底是什么结构,它却不知道,因此当然要将具体的实体类当作返回值类型去描述。
参考:
https://www.freesion.com/article/1709510261/
https://www.cnblogs.com/h-c-g/p/11004020.html
https://blog.csdn.net/jiangyu1013/article/details/83107255
https://blog.51cto.com/u_5634409/2343942
https://blog.csdn.net/qq_25983579/article/details/104532743