简介
Swagger是一款目前世界最流行的API管理工具。目前Swagger已经形成一个生态圈,能够管理API的整个生命周期,从设计、文档到测试与部署。Swagger有几个重要特性:
- 代码侵入式注解
- 遵循YAML文档格式
- 非常适合三端(PC、iOS及Android)的API管理,尤其适合前后端完全分离的架构模式。
- 减少没有必要的文档,符合敏捷开发理念
- 功能强大
作用
- 接口的文档在线自动生成
功能测试
优点
大大减少前后端的沟通
- 方便查找和测试接口
- 提高团队的开发效率
- 方便新人了解项目
1、配置swagger
引入依赖
配置类 ```java package com.zh.upload.config;<!-- swagger -->
<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>
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import springfox.documentation.builders.ApiInfoBuilder; import springfox.documentation.builders.PathSelectors; import springfox.documentation.builders.RequestHandlerSelectors; import springfox.documentation.service.ApiInfo; import springfox.documentation.spi.DocumentationType; import springfox.documentation.spring.web.plugins.Docket; import springfox.documentation.swagger2.annotations.EnableSwagger2;
/**
- Swagger 配置文件
@author zlz1314 */ @Configuration @EnableSwagger2 public class SwaggerConfig { @Bean public Docket createRestApi() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("com.zh.upload")) //swagger搜索的包
.paths(PathSelectors.any()) //swagger路径匹配
.build();
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder() .title("文件上传文档") .description("使用FastDfs文件上传") .version("version 1.0") .build();
} } ```
启动注册中心和upload服务,访问地址:
http://localhost:9004/swagger-ui.html#/
测试上传:
确实可以哦。
2、常用注解
swagger通过在controller中声明注解,对API文档进行说明
1、@Api():用在请求的类上,表示对类的说明,也代表了这个类是swagger2的资源
参数:
tags:说明该类的作用,参数是个数组,可以填多个。
value="该参数没什么意义,在UI界面上不显示,所以不用配置"
description = "用户基本信息操作"
2、@ApiOperation():用于方法,表示一个http请求访问该方法的操作
参数:
value="方法的用途和作用"
notes="方法的注意事项和备注"
tags:说明该方法的作用,参数是个数组,可以填多个。
格式:tags={"作用1","作用2"}
(在这里建议不使用这个参数,会使界面看上去有点乱,前两个常用)
3、@ApiModel():用于响应实体类上,用于说明实体作用
参数:
description="描述实体的作用"
4、@ApiModelProperty:用在属性上,描述实体类的属性
参数:
value="用户名" 描述参数的意义
name="name" 参数的变量名
required=true 参数是否必选
5、@ApiImplicitParams:用在请求的方法上,包含多@ApiImplicitParam
6、@ApiImplicitParam:用于方法,表示单独的请求参数
参数:
name="参数ming"
value="参数说明"
dataType="数据类型"
paramType="query" 表示参数放在哪里
· header 请求参数的获取:@RequestHeader
· query 请求参数的获取:@RequestParam
· path(用于restful接口) 请求参数的获取:@PathVariable
· body(不常用)
· form(不常用)
defaultValue="参数的默认值"
required="true" 表示参数是否必须传
7、@ApiParam():用于方法,参数,字段说明 表示对参数的要求和说明
参数:
name="参数名称"
value="参数的简要说明"
defaultValue="参数默认值"
required="true" 表示属性是否必填,默认为false
8、@ApiResponses:用于请求的方法上,根据响应码表示不同响应
一个@ApiResponses包含多个@ApiResponse
9、@ApiResponse:用在请求的方法上,表示不同的响应
参数:
code="404" 表示响应码(int型),可自定义
message="状态码对应的响应信息"
10、@ApiIgnore():用于类或者方法上,不被显示在页面上
3、使用
实体类
package com.zh.upload.domain;
import io.swagger.annotations.ApiModel;
/**
* @Author: deemoHui
*/
@ApiModel("用户对象模型")
public class User {
private Long id;
private String username;
private String password;
private String email;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
controller
package com.zh.upload.controller;
import com.zh.upload.domain.User;
import io.swagger.annotations.*;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.annotations.ApiIgnore;
import javax.xml.ws.Response;
/**
* /user post 新增
* /{id} delete 删除
* /{id} put 更新
* /{id} get 根据id加载
* /list-page post 分页查询
*
* @author zlz1314
*/
@RestController
@RequestMapping("/user")
@Api(tags = {"用户管理API"})
public class UserController {
@PostMapping
@ApiOperation(value = "新增用户", notes = "新增后返回当前用户")
@ApiResponses({
@ApiResponse(code = 200, message = "返回成功", response = User.class),
@ApiResponse(code = 400, message = "参数没有填好(id==1)", response = User.class),
@ApiResponse(code = 401, message = "权限不足(id==2)", response = User.class),
})
public ResponseEntity<User> add(User user) {
if (user.getId() == 1) {
//400
return new ResponseEntity<>(user, HttpStatus.BAD_REQUEST);
} else if (user.getId() == 2) {
//401
return new ResponseEntity<>(user, HttpStatus.UNAUTHORIZED);
} else {
return ResponseEntity.ok(user);
}
}
@PutMapping
@ApiOperation(value = "修改用户", notes = "修改后返回当前用户")
@ApiResponses({
@ApiResponse(code = 200, message = "返回成功", response = User.class),
@ApiResponse(code = 400, message = "参数没有填好(id==1)", response = User.class),
@ApiResponse(code = 401, message = "权限不足(id==2)", response = User.class),
})
public ResponseEntity<User> update(User user) {
if (user.getId() == 1) {
//400
return new ResponseEntity<>(user, HttpStatus.BAD_REQUEST);
} else if (user.getId() == 2) {
//401
return new ResponseEntity<>(user, HttpStatus.UNAUTHORIZED);
} else {
return ResponseEntity.ok(user);
}
}
@DeleteMapping("/{id}")
@ApiOperation(value = "删除用户", notes = "删除后返回当前id")
@ApiResponses({
@ApiResponse(code = 200, message = "返回成功", response = User.class),
@ApiResponse(code = 400, message = "参数没有填好(id==1)", response = User.class),
@ApiResponse(code = 401, message = "权限不足(id==2)", response = User.class),
})
@ApiImplicitParam(paramType = "path", name = "id", value = "用户主键ID", required = true)
public ResponseEntity<Long> delete(@PathVariable Long id) {
if (id == 1) {
//400
return new ResponseEntity<>(id, HttpStatus.BAD_REQUEST);
} else if (id == 2) {
//401
return new ResponseEntity<>(id, HttpStatus.UNAUTHORIZED);
} else {
return ResponseEntity.ok(id);
}
}
@GetMapping("/{id}")
@ApiIgnore
public ResponseEntity<Long> toUpdate(@PathVariable Long id) {
if (id == 1) {
//400
return new ResponseEntity<>(id, HttpStatus.BAD_REQUEST);
} else if (id == 2) {
//401
return new ResponseEntity<>(id, HttpStatus.UNAUTHORIZED);
} else {
return ResponseEntity.ok(id);
}
}
@PostMapping("/list-page")
@ApiOperation(value = "分页查询", notes = "得到分页查询对象pageInfo")
@ApiImplicitParams({
@ApiImplicitParam(paramType = "query", name = "pageNum", value = "当前页",
required = false, defaultValue = "1"),
@ApiImplicitParam(paramType = "query", name = "pageSize", value = "每页行数",
required = false, defaultValue = "10")
})
public ResponseEntity<String> findByPage(
@RequestParam(defaultValue = "1", required = false) Integer pageNum,
@RequestParam(defaultValue = "10", required = false) Integer pageSize) {
return ResponseEntity.ok("find page result...");
}
}
结果
4、给账单项目加上Api文档
1、引入swagger依赖
<!-- swagger -->
<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>
2、配置类
package com.zh.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
/**
* Swagger 配置文件
*
* @author zlz1314
*/
@Configuration
@EnableSwagger2
public class SwaggerConfig {
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("com.zh"))
.paths(PathSelectors.any())
.build();
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("账单管理文档")
.description("账单管理")
.version("version 1.0")
.build();
}
}
3、修改实体类
package com.zh.bean;
import com.fasterxml.jackson.annotation.JsonIgnore;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.persistence.*;
import java.io.Serializable;
import java.util.Date;
import io.swagger.annotations.ApiModel;
/**
* @Author: deemoHui
* @Description:
* @Date Created in 2020-10-19 12:45
* @Modified By:
*/
@Table(name = "bill_")
@Data
@ApiModel("账单模型")
public class Bill implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id_")
@ApiModelProperty(value = "主键id")
private Long id;
@ApiModelProperty(value = "账单标题")
@Column(name = "title_")
private String title;
@ApiModelProperty(value = "账单创建时间")
@Column(name = "bill_time_")
private Date billTime;
@ApiModelProperty(value = "账单类型id")
@Column(name = "type_id_")
private Long typeId;
@ApiModelProperty(value = "账单的金额")
@Column(name = "price_")
private Double price;
@ApiModelProperty(value = "账单说明")
@Column(name = "explain_")
private String explain;
/**
* 类别名称
*/
@Transient
@ApiModelProperty(value = "账单类型名称")
@JsonIgnore
private String typeName;
/**
* 开始时间:用于查询
*/
@Transient
@ApiModelProperty(value = "账单起始时间")
@JsonIgnore
private Date date1;
/**
* 结束时间:用于查询
*/
@Transient
@ApiModelProperty(value = "账单结束时间")
@JsonIgnore
private Date date2;
}
这里只放一个,其他的都是类似的
4、修改controller
package com.zh.controller;
import com.zh.bean.Bill;
import com.zh.bean.BillType;
import com.zh.bean.TableData;
import com.zh.service.BillService;
import com.zh.service.TypeService;
import io.swagger.annotations.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* @Author: deemoHui
* @Description:
* @Date Created in 2020-10-19 13:05
* @Modified By:
*/
@RestController
@RequestMapping("/bill")
@RefreshScope //刷新配置
@Api(tags = {"账单管理API"})
public class BillController {
@Autowired
private TypeService typeService;
@Autowired
private BillService billService;
@Value("${test.name}")
private String name;
/**
* 查询所有的账单
* @param page
* @param limit
* @param bill
* @return
*/
@PostMapping("/list")
@ApiOperation(value = "账单列表", notes = "按条件查询后返回账单列表")
@ApiResponses({
@ApiResponse(code = 200, message = "返回成功", response = TableData.class)
})
@ApiImplicitParams({
@ApiImplicitParam(paramType = "query", name = "page", value = "当前页", defaultValue = "1"),
@ApiImplicitParam(paramType = "query", name = "limit", value = "每页行数", defaultValue = "10")
})
public TableData<Bill> list(
@RequestParam(defaultValue = "1") int page,
@RequestParam(defaultValue = "10") int limit,
@ModelAttribute Bill bill) {
List<Bill> bills = billService.list(bill, page, limit);
int count = billService.selectBillCount(bill);
return new TableData<>(0, "成功", count, bills);
}
/**
* 添加
*
* @param b
* @return
*/
@PostMapping("/add")
@ApiOperation(value = "添加账单", notes = "添加成功后返回账单列表")
@ApiResponses({
@ApiResponse(code = 200, message = "成功", response = Integer.class),
})
public Integer add(@ModelAttribute Bill b) {
int result = billService.add(b);
return result > 0 ? 1 : 0;
}
/**
* 删除
*
* @param id
* @return
*/
@GetMapping("/delete/{id}")
@ApiOperation(value = "删除账单", notes = "根据id删除账单,成功后返回账单列表")
@ApiResponses({
@ApiResponse(code = 200, message = "成功", response = Integer.class),
})
@ApiImplicitParams({
@ApiImplicitParam(paramType = "path",name = "id", value = "账单id", dataType = "long",required = true)
})
public Integer delete(@PathVariable("id") Long id) {
int delete = billService.delete(id);
return delete > 0 ? 1 : 0;
}
/**
* 修改
*
* @param id
* @return
*/
@GetMapping("/toUpdate/{id}")
@ApiOperation(value = "修改账单", notes = "根据id修改账单,跳转到修改页面,并自动填充账单信息")
@ApiResponses({
@ApiResponse(code = 200, message = "成功", response = Bill.class),
})
@ApiImplicitParams({
@ApiImplicitParam(paramType = "path",name = "id", value = "账单id", dataType = "long",required = true)
})
public Bill toUpdate(@PathVariable("id") Long id) {
Bill bill = billService.getById(id);
System.out.println("配置文件中的test.name为:" + name);
return bill;
}
/**
* 修改
*
* @param b
* @return
*/
@PostMapping("/update")
@ApiOperation(value = "修改账单", notes = "根据id修改账单,成功后跳转到账单列表")
@ApiResponses({
@ApiResponse(code = 200, message = "成功", response = Integer.class),
})
public Integer update(@ModelAttribute Bill b) {
int update = billService.update(b);
return update > 0 ? 1 : 0;
}
@GetMapping("/types")
@ApiOperation(value = "查询账单类型", notes = "查询账单类型,返回账单类型列表,用于填充类型")
@ApiResponses({
@ApiResponse(code = 200, message = "成功", response = Bill.class)
})
public List<BillType> getTypes() {
return typeService.list();
}
}
注意:
- 如果不想展示实体类某些字段在swagger上,需要在字段上加上@JsonIgnore注解
- controller类里是想表单提交,则用@ModelAttribute Bill bill)
ok,运行起来,并且访问http://localhost:9091/swagger-ui.html
运行时报错:
Illegal DefaultValue null for parameter type integer
也还能正常运行,但就是看着不爽
解决办法:忽略原版本的swagger-annotations和swagger-models,添加1.5.21版本的,也就是在原来的pom文件中添加这两个依赖就好了
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-annotations</artifactId>
<version>1.5.21</version>
</dependency>
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-models</artifactId>
<version>1.5.21</version>
</dependency
**
效果如下:
测试一下add