一、什么是 Swagger
Swagger是一组围绕 OpenAPI 规范构建的开源工具,可帮助您设计、构建、记录和使用 REST API。主要的 Swagger 工具包括:
Swagger Editor – 基于浏览器的编辑器,您可以在其中编写 OpenAPI 规范。
Swagger UI – 将 OpenAPI规范呈现为交互式 API 文档。
swagger2于17年停止维护,现在最新的版本为 Swagger3(Open Api3)。
二、什么是knife4j
knife4j是为Java MVC框架集成Swagger生成Api文档的增强解决方案,前身是swagger-bootstrap-ui
,取名kni4j是希望她能像一把匕首一样小巧,轻量,并且功能强悍!
三、依赖引入
- springfox引入方式
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
<version>3.0.0</version>
</dependency>
- knife4j引入方式
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
<version>3.0.3</version>
</dependency>
- 引入美化bootstrap-UI
<!-- 引入swagger-bootstrap-ui包 -->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>swagger-bootstrap-ui</artifactId>
<version>1.8.5</version>
</dependency>
四、Swagger注解详解
- 使用 swagger3 注解代替 swagger2对应表
- swagger3注解详解
@Api
@Api 注解用于标注一个Controller(Class)
。在默认情况下,Swagger-Core只会扫描解析具有@Api注解的类,而会自动忽略其他类别资源(JAX-RS endpoints,Servlets等等)的注解
。
属性名称 | 备注 |
---|---|
value | url的路径值 |
tags | 如果设置这个值、value的值会被覆盖 |
description | 对api资源的描述 |
basePath | 基本路径可以不配置 |
position | 如果配置多个Api 想改变显示的顺序位置 |
produces | For example, “application/json, application/xml” |
consumes | For example, “application/json,application/xml” |
protocols | Possible values: http, https, ws, wss. |
authorizations | 高级特性认证时配置 |
hidden | 配置为true 将在文档中隐藏 |
实例:
@Controller
@RequestMapping(value = "/api/pet", produces = {APPLICATION_JSON_VALUE, APPLICATION_XML_VALUE})
@Api(value = "/pet", description = "Operations about pets")
public class PetController {}
@ApiOperation
@ApiOperation 注解在用于对一个操作或HTTP方法进行描述。具有相同路径的不同操作会被归组为同一个操作对象
。不同的HTTP请求方法及路径组合构成一个唯一操作。
属性 | 描述 |
---|---|
value | url的路径值 |
tags | 如果设置这个值、value的值会被覆盖 |
description | 对api资源的描述 |
basePath | 基本路径可以不配置 |
position | 如果配置多个Api 想改变显示的顺序位置 |
produces | For example, “application/json, application/xml” |
consumes | For example, “application/json, application/xml” |
protocols | Possible values: http, https, ws, wss. |
authorizations | 高级特性认证时配置 |
hidden | 配置为true 将在文档中隐藏 |
response | 返回的对象 |
responseContainer | 这些对象是有效的 “List”, “Set” or “Map”.,其他无效 |
httpMethod | “GET”, “HEAD”, “POST”, “PUT”, “DELETE”, “OPTIONS” and “PATCH” |
code | http的状态码 默认 200 |
extensions | 扩展属性 |
@RequestMapping(value = "/order/{orderId}", method = GET)
@ApiOperation(
value = "Find purchase order by ID",
notes = "For valid response try integer IDs with value <= 5 or > 10. Other values will generated exceptions",
response = Order.class,
tags = { "Pet Store" })
public ResponseEntity<Order> getOrderById(@PathVariable("orderId") String orderId)
throws NotFoundException {
Order order = storeData.get(Long.valueOf(orderId));
if (null != order) {
return ok(order);
} else {
throw new NotFoundException(404, "Order not found");
}
}
@ApiParam
@ApiParam作用于请求方法的参数上
,定义api参数的注解。
属性 | 描述 |
---|---|
name | 属性名称 |
value | 属性值 |
defaultValue | 默认属性值 |
allowableValues | 可以不配置 |
required | 是否属性必填 |
access | 不过多描述 |
allowMultiple | 默认为false |
hidden | 隐藏该属性 |
example | 举例子 |
public ResponseEntity<Order> getOrderById(
@ApiParam(value = "ID of pet that needs to be fetched", allowableValues = "range[1,5]", required = true)
@PathVariable("orderId") String orderId)
public DataResult<ZonesEiaPlanPageInfoVO> detail(@RequestParam("id") @ApiParam(value = "主键", required = true) String id) {}
@ApiImplicitParams、@ApiImplicitParam
@ApiImplicitParams、@ApiImplicitParam也可以定义参数
.
- @ApiImplicitParams:用在请求的方法上,
包含一组参数说明
- @ApiImplicitParam:
对单个参数的说明
属性 | 描述 |
---|---|
name | 参数名 |
value | 参数的说明、描述 |
required | 参数是否必须必填 |
paramType | 参数放在哪个地方 query --> 请求参数的获取:@RequestParam header --> 请求参数的获取:@RequestHeader path(用于restful接口)–> 请求参数的获取:@PathVariable body(请求体)–> @RequestBody User user form(普通表单提交) |
dataType | 参数类型,默认String,其它值dataType=“Integer” |
defaultValue | 参数的默认值 |
@ApiImplicitParams({
@ApiImplicitParam(name="mobile",value="手机号",required=true,paramType="form"),
@ApiImplicitParam(name="password",value="密码",required=true,paramType="form"),
@ApiImplicitParam(name="age",value="年龄",required=true,paramType="form",dataType="Integer")
})
@PostMapping("/login")
public JsonResult login(@RequestParam String mobile, @RequestParam String password,
@RequestParam Integer age){
//...
return JsonResult.ok(map);
}
@ApiResponses、@ApiResponse
@ApiResponses、@ApiResponse进行方法返回对象的说明
。
主要属性:
属性 | 描述 |
---|---|
code | 数字,例如400 |
message | 信息,例如"请求参数没填好" |
response | 返回的类 |
@ApiResponses({
@ApiResponse(code = 200, message = "请求成功",response = RestMessage .class),
@ApiResponse(code = 400, message = "请求参数没填好",response = RestMessage .class),
@ApiResponse(code = 404, message = "请求路径没有或页面跳转路径不对",response = RestMessage .class)
})
@ResponseBody
@RequestMapping("/list")
public JsonResult list(@RequestParam String userId) {
...
return JsonResult.ok().put("page", pageUtil);
}
@ApiModel、@ApiModelProperty
- @ApiModel
用于描述一个Model的信息(这种一般用在post创建的时候,使用@RequestBody这样的场景,请求参数无法使用@ApiImplicitParam注解进行描述的时候)
。- @ApiModelProperty
用来描述一个Model的属性
。
@ApiModel属性 | 描述 |
---|---|
value | 默认 为模型提供一个替代名称 |
description | 描述 |
referencey | 指定对相应类型定义的引用,覆盖指定的任何其他元数据 |
@ApiModelProperty属性 | 描述 |
---|---|
value | 默认 字段说明 |
name | 重写属性名字 |
dataType | 重写属性类型 |
required | 是否必填 |
example | 举例说明 |
hidden | 配置为true将在文档中隐藏 |
@ApiModel(description= "返回响应数据")
@Data
public class RestMessage implements Serializable{
@ApiModelProperty(value = "是否成功",required=true)
private boolean success=true;
@ApiModelProperty(value = "错误码")
private Integer errCode;
@ApiModelProperty(value = "提示信息")
private String message;
@ApiModelProperty(value = "数据")
private Object data;
}
- 注:
@ApiImplicitParam 跟 @ApiParam 两个注解的区别
@ApiParam和@ApiImplicitParam的功能是相同的,但是@ApiImplicitParam的适用范围更广。在非JAX-RS的场合(比如使用servlet提供HTTP接口),只能使用@ApiImplicitParam进行参数说明。
我认为,这是因为接口并不显式展示入参的名称,所以没有地方去使用@ApiParam,只能在接口的方法声明上方写@ApiImplicitParam
五、详细例子
配置文件加上@EnableOpenApi、@Configuration
会自动开启配置,启动类不需要加任何注解
@EnableOpenApi//该注解是Springfox-swagger框架提供的使用Swagger注解,该注解必须加
@EnableKnife4j//该注解是knife4j提供的增强注解,Ui提供了例如动态参数、参数过滤、接口排序等增强功能,如果你想使用这些增强功能就必须加该注解,否则可以不用加
@Configuration
public class SwaggerConfig {
/**
* 接口构建器
*
* @return
*/
@Bean
public Docket docket() {
return new Docket(DocumentationType.OAS_30).apiInfo(apiInfo())
//用来创建该API的基本信息,展示在文档的页面中(自定义展示的信息)
.apiInfo(apiInfo())
//设置哪些接口暴露给Swagger展示
.select()
// (第一种方式)扫描所有有注解的api,用这种方式更灵活
.apis( RequestHandlerSelectors.withMethodAnnotation( ApiOperation.class ) )
// (第二种方式)扫描指定包中的swagger注解
.apis(RequestHandlerSelectors.basePackage("com.swagger_knife4j.swagger4j.controller"))//构建API
// (第三种方式)扫描所有
.apis(RequestHandlerSelectors.any())
.paths( PathSelectors.any() )
.paths(PathSelectors.any())
.build()
.groupName("XimenesChen")
.enable(true);
}
/**
* 添加摘要信息
* 创建该API的基本信息(这些基本信息会展现在文档页面中)
* 访问地址:http://项目实际地址/swagger-ui.html
*/
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("整合knife-4j,swaggerui基本注解")//标题
.description("整合knife-4j,swaggerui基本注解-描述")//描述
.contact(new Contact("cxm", "https://mp.csdn.net/mp_blog/manage/article?spm=1001.2014.3001.5114", "cristianoxm@qq.com"))
.version("V2.05")
.build();
}
}
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Data
@ApiModel("common-result")
public class Result<T> {
@ApiModelProperty(value = "返回状态码")
private Integer code;
@ApiModelProperty(value = "返回信息")
private String message;
@ApiModelProperty(value = "返回实体信息")
private T data;
}
@EnableOpenApi//该注解是Springfox-swagger框架提供的使用Swagger注解,该注解必须加
@EnableKnife4j//该注解是knife4j提供的增强注解,Ui提供了例如动态参数、参数过滤、接口排序等增强功能,如果你想使用这些增强功能就必须加该注解,否则可以不用加
@Configuration
public class SwaggerConfig {
/**
* 接口构建器
*
* @return
*/
@Bean
public Docket docket() {
return new Docket(DocumentationType.OAS_30).apiInfo(apiInfo())
//用来创建该API的基本信息,展示在文档的页面中(自定义展示的信息)
.apiInfo(apiInfo())
//设置哪些接口暴露给Swagger展示
.select()
// (第一种方式)扫描所有有注解的api,用这种方式更灵活
.apis( RequestHandlerSelectors.withMethodAnnotation( ApiOperation.class ) )
// (第二种方式)扫描指定包中的swagger注解
.apis(RequestHandlerSelectors.basePackage("com.swagger_knife4j.swagger4j.controller"))//构建API
// (第三种方式)扫描所有
.apis(RequestHandlerSelectors.any())
.paths( PathSelectors.any() )
.paths(PathSelectors.any())
.build()
.groupName("XimenesChen")
.enable(true);
}
/**
* 添加摘要信息
* 创建该API的基本信息(这些基本信息会展现在文档页面中)
* 访问地址:http://项目实际地址/swagger-ui.html
*/
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("整合knife-4j,swaggerui基本注解")//标题
.description("整合knife-4j,swaggerui基本注解-描述")//描述
.contact(new Contact("cxm", "https://mp.csdn.net/mp_blog/manage/article?spm=1001.2014.3001.5114", "cristianoxm@qq.com"))
.version("V2.05")
.build();
}
}
@Api(tags = "技术学习规划表-控制器")//@Api:用在类上,说明该类的作用
@RestController
@RequestMapping("/skillStudyPlan")
public class SkillStudyPlanController {
@ApiOperation("插入技术学习规划")//@ApiOperation:注解来给API增加方法说明
@PostMapping("insertPlan")
@ApiResponses({
@ApiResponse(code = 200, message = "请求成功",response = Result.class),
@ApiResponse(code = 400, message = "404错误",response = Result.class),
@ApiResponse(code = 404, message = "路径不存在",response = Result.class)
})
public Result<ResponseB> insertPlan(@ApiParam @RequestBody(required = false) SkillStudyPlanDTO skillStudyPlanDTO) {
ResponseB build = ResponseB.builder().message("ss").code(200).data("data").build();
System.out.println(skillStudyPlanDTO);
return new Result<>(200,"ok",build);
}
@ApiOperation("查询所有技术学习规划")
@GetMapping("selectAll")
public String selectAll(@RequestParam String name,@RequestParam(required = false) Integer age) {
System.out.print(name);
System.out.print(age);
return "success";
}
@PostMapping("pageHelp")
@ApiOperation(value = "分页获取标签列表")
@ApiImplicitParams({
@ApiImplicitParam(name="pageNo",value="请求页数",required = false,dataType="Integer",paramType="query"
),
@ApiImplicitParam(name="pageSize",value="请求页大小",required = false,dataType="Integer",paramType="query"),
})
//header:请求头
//query:?param=value的形式
//path:路径,Restful风格接口
//body:请求体
//form:以form表单的形式提交
@ApiResponses({
@ApiResponse(code = 200, message = "请求成功",response = Result.class),
@ApiResponse(code = 400, message = "请求参数没填好",response = Result.class),
@ApiResponse(code = 404, message = "请求路径没有或页面跳转路径不对",response = Result.class)
})
public Result<ResponseA> pageHelp(@RequestParam Integer pageNo, @RequestParam Integer pageSize){
ResponseA build = ResponseA.builder().message("ss").code(200).data("data").build();
return new Result<>(200,"ok",build);
}
}
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
@ApiModel("SkillStudyPlanDTO实体类")
public class SkillStudyPlanDTO {
@ApiModelProperty("SkillStudyPlanDTO.name属性")
private String name;
@ApiModelProperty("SkillStudyPlanDTO.age属性")
private Integer age;
}