Swagger & Knife4j
1 Swagger介绍
(1)简介
Swagger 是一个规范和完整的框架,用于生成、描述、调用和可视化 RESTful 风格的 Web 服务(https://swagger.io/)。 它的主要作用是:
-
使得前后端分离开发更加方便,有利于团队协作
-
接口的文档在线自动生成,降低后端开发人员编写接口文档的负担
-
功能测试
Spring已经将Swagger纳入自身的标准,建立了Spring-swagger项目,现在叫Springfox。通过在项目中引入Springfox ,即可非常简单快捷的使用Swagger。
(2)SpringBoot集成Swagger
-
引入依赖,在【itheima-leadnews】模块中引入该依赖
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
-
添加一个配置类
@Configuration
@EnableSwagger2
public class SwaggerConfiguration {
@Bean
public Docket buildDocket() {
HashSet<String> strings = new HashSet<>();
strings.add("application/json");
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(buildApiInfo())
//设置返回值数据类型为json
.produces(strings)
.select()
// 要扫描的API(Controller)基础包
.apis(RequestHandlerSelectors.basePackage("com.mingye"))
.paths(PathSelectors.any())
.build();
}
private ApiInfo buildApiInfo() {
Contact contact = new Contact("Ming","","");
return new ApiInfoBuilder()
.title("Ming-管理API文档")
.description("服务api")
.contact(contact)
.version("1.0.0").build();
}
}
启动工程后访问:http://localhost:9001/swagger-ui.html
(3)Swagger常用注解
@Api:修饰整个类,描述Controller的作用
@ApiOperation:修饰类的一个方法 标识 操作信息 接口的定义
@ApiParam:单个参数的描述信息
@ApiModel:描述使用到的对象信息
@ApiModelProperty:描述使用到的对象的属性信息
@ApiResponse:HTTP响应其中1个描述
@ApiResponses:HTTP响应整体描述
@ApiIgnore:使用该注解忽略这个API
@ApiError :发生错误返回的信息
@ApiImplicitParam:一个请求参数
@ApiImplicitParams:多个请求参数的描述信息
@ApiImplicitParam属性:
属性 |
取值 |
作用 |
paramType |
|
查询参数类型 |
|
path |
以地址的形式提交数据 |
|
query |
直接跟参数完成自动映射赋值 |
|
body |
以流的形式提交 仅支持POST |
|
header |
参数在request headers 里边提交 |
|
form |
以form表单的形式提交 仅支持POST |
dataType |
|
参数的数据类型 只作为标志说明,并没有实际验证 |
|
Long |
|
|
String |
|
name |
|
接收参数名 |
value |
|
接收参数的意义描述 |
required |
|
参数是否必填 |
|
true |
必填 |
|
false |
非必填 |
defaultValue |
|
默认值 |
我们在controller中添加Swagger注解,代码如下所示:
@Api(tags = "管理")
public class AdChannelController {
}
在vo,dto或实体类中添加api相关注解:
@Data
@ApiModel(value="PageRequestDto", description="通用分页查询参数")
public class PageRequestDto implements Serializable {
@ApiModelProperty(notes = "每页大小", dataType="Long")
private Long size;
@ApiModelProperty(notes = "页码", dataType="Long")
private Long page;
public void checkParam() {
if (this.page == null || this.page < 0) {
setPage(1l);
}
if (this.size == null || this.size < 0 || this.size > 100) {
setSize(10l);
}
}
}
/**
* @version 1.0
* @description 说明
*/
@Data
@ApiModel(value="PageResultVo", description="通用分页响应结果")
public class PageResultVo<T> extends ResultVo<T> implements Serializable {
@ApiModelProperty(notes = "页码", dataType="Long")
private Long currentPage;
@ApiModelProperty(notes = "每页大小", dataType="Long")
private Long size;
@ApiModelProperty(notes = "总记录数", dataType="Long")
private Long total;
/**
* 快速构建分页结果
* @param page
* @param size
* @param total
* @param data
* @return
*/
public static <T>PageResultVo<T> pageResult(Long page, Long size, Long total, List<T> data){
PageResultVo vo = new PageResultVo();
vo.setCurrentPage(page);
vo.setSize(size);
vo.setTotal(total);
vo.setData(data);
return vo;
}
}
/**
* @version 1.0
* @description 通用响应结果
*/
@Data
@AllArgsConstructor
@ApiModel(value="ResultVo", description="通用响应结果")
public class ResultVo<T> implements Serializable {
@ApiModelProperty(notes = "响应请求域名", dataType="String")
private String host;
@ApiModelProperty(notes = "响应状态码", dataType="Integer")
private Integer code;
@ApiModelProperty(notes = "响应提示信息", dataType="String")
private String errorMessage;
@ApiModelProperty(notes = "响应数据", dataType="JSON")
private T data;
public ResultVo() {
this.code = HttpCodeEnum.SUCCESS.getCode();
}
public static ResultVo ok() {
return new ResultVo();
}
public static ResultVo ok(String msg) {
return new ResultVo(null,HttpCodeEnum.SUCCESS.getCode(),msg,null);
}
public static ResultVo ok(Object data) {
return new ResultVo(null,HttpCodeEnum.SUCCESS.getCode(),HttpCodeEnum.SUCCESS.getMessage(),data);
}
public static ResultVo error() {
return ResultVo.error(HttpCodeEnum.SERVER_ERROR);
}
public static ResultVo error(int code, String msg) {
return new ResultVo(null,code,msg,null);
}
public static ResultVo error(HttpCodeEnum enums){
return ResultVo.error(enums.getCode(),enums.getMessage());
}
public static ResultVo bizError(String msg) {
return ResultVo.error(HttpCodeEnum.SERVER_ERROR.getCode(), msg);
}
public boolean isSuccess(){
return this.code!=null&&this.code.intValue()==HttpCodeEnum.SUCCESS.getCode();
}
}
/**
* @version 1.0
* @description 频道实体类
*/
@Data
@TableName("ad_channel")
@ApiModel(description = "频道实体")
public class AdChannel {
@TableId(value = "id", type = IdType.AUTO)
@ApiModelProperty(notes = "主键id")
private Integer id;
@TableField("name")
@ApiModelProperty(notes = "名称")
private String name;
@TableField("description")
@ApiModelProperty(notes = "描述")
private String description;
@TableField("is_default")
@ApiModelProperty(notes = "是否为默认")
private Boolean isDefault;
@TableField("status")
@ApiModelProperty(notes = "是否启用")
private Boolean status;
@TableField("ord")
@ApiModelProperty(notes = "排序")
private Integer ord;
@TableField("created_time")
@ApiModelProperty(notes = "创建时间")
private Date createdTime;
}
启动admin微服务,访问地址:http://localhost:9001/swagger-ui.html
官方的注解说明如下:
https://github.com/swagger-api/swagger-core/wiki/Annotations-1.5.X
仅仅是这样,那么如果有离线需求呢?如果服务器换地方了呢?在线调试还不够完善,阅读相对麻烦,UI功能不是特别强,软件 Knife4j 做了一次增强。
2 Knife4j
(1)简介
knife4j是为Java MVC框架集成Swagger生成Api文档的增强解决方案,前身是swagger-bootstrap-ui,取名kni4j是希望它能像一把匕首一样小巧,轻量,并且功能强悍!
gitee地址:https://gitee.com/xiaoym/knife4j
官方文档:https://doc.xiaominfo.com/
效果演示:http://knife4j.xiaominfo.com/doc.html
(2)核心功能
该UI增强包主要包括两大核心功能:文档说明 和 在线调试
- 文档说明:根据Swagger的规范说明,详细列出接口文档的说明,包括接口地址、类型、请求示例、请求参数、响应示例、响应参数、响应码等信息,使用swagger-bootstrap-ui能根据该文档说明,对该接口的使用情况一目了然。
- 在线调试:提供在线接口联调的强大功能,自动解析当前接口参数,同时包含表单验证,调用参数可返回接口响应内容、headers、Curl请求命令实例、响应时间、响应状态码等信息,帮助开发者在线调试,而不必通过其他测试工具测试接口是否正确,简介、强大。
- 个性化配置:通过个性化ui配置项,可自定义UI的相关显示信息
- 离线文档:根据标准规范,生成的在线markdown离线文档,开发者可以进行拷贝生成markdown接口文档,通过其他第三方markdown转换工具转换成html或pdf,这样也可以放弃swagger2markdown组件
- 接口排序:自1.8.5后,ui支持了接口排序功能,例如一个注册功能主要包含了多个步骤,可以根据swagger-bootstrap-ui提供的接口排序规则实现接口的排序,step化接口操作,方便其他开发者进行接口对接
(3)快速集成
- 在工程中pom.xml
文件中引入
knife4j的依赖,并【删除掉原来的swagger的依赖】如下:
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
</dependency>
如果是高版本springboot已经去除掉了validation 还需要在工程中添加依赖,因为knife4j需要使用到他
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
新建Swagger的配置文件SwaggerConfiguration.java
文件,创建springfox提供的Docket分组对象,代码如下:
@Configuration
@EnableSwagger2
@EnableKnife4j
@Import(BeanValidatorPluginsConfiguration.class)
public class SwaggerConfiguration {
@Bean
public Docket buildDocket() {
HashSet<String> strings = new HashSet<>();
strings.add("application/json");
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(buildApiInfo())
//设置返回值数据类型为json
.produces(strings)
.select()
// 要扫描的API(Controller)基础包
.apis(RequestHandlerSelectors.basePackage("Ming"))
.paths(PathSelectors.any())
.build();
}
private ApiInfo buildApiInfo() {
Contact contact = new Contact("Ming","","");
return new ApiInfoBuilder()
.title("Ming-API文档")
.description("管理服务api")
.contact(contact)
.version("1.0.0").build();
}
}
以上有两个注解需要特别说明,如下表:
注解 |
说明 |
@EnableSwagger2 |
该注解是Springfox-swagger框架提供的使用Swagger注解,该注解必须加 |
@EnableKnife4j |
该注解是knife4j 提供的增强注解,Ui提供了例如动态参数、参数过滤、接口排序等增强功能,如果你想使用这些增强功能就必须加该注解,否则可以不用加 |
修改AdChannelController添加Api说明
/**
* @version 1.0
* @description 频道管理
*/
@RestController
@RequestMapping("/channel")
@Api(tags = "管理")
public class AdChannelController {
@Autowired
private AdChannelService adChannelService;
/**
* 分页查询
* @param dto
* @return
*/
@PostMapping("/list")
@ApiOperation("分页查询")
public PageResultVo pageList(@RequestBody ChannelPageRequestDto dto){
PageResultVo vo = adChannelService.pageList(dto);
return vo;
}
}
修改dto添加api说明
/**
* @version 1.0
* @description 说明
*/
@Data
@ApiModel(value="ChannelPageRequestDto", description="分页查询参数")
public class ChannelPageRequestDto extends PageRequestDto {
@ApiModelProperty(notes = "名称",dataType = "String")
private String name;
@ApiModelProperty(notes = "状态",dataType = "Integer")
private Integer status;
}
在浏览器输入地址:http://localhost:9001/doc.html