一.前后端分离的特点
前后端分离是的前端与后端之间的职责更加明确
后台: 负责业务处理
前端: 负责显示逻辑
在这种情况下,前端和后端可以分别交付给专业的开发人员去做,所以是必须要定义前后端直接的对接
接口,否则各自为是则项目无法集成,这时就需要一个文档来定义统一的接口。
二.在没有swagger之前
在没有swagger之间,我们可以使用word,excel等功能来书写接口定义文档,但又有一个弊端,即:
在接口发送改变时需要及时的同步接口文档,否则实际的接口与接口文档不相符,则接口文件就失去了
作用,甚至会起到反作用。
三.swagger的作用
根据在代码中使用自定义的注解来生成接口文档,这个在前后端分离的项目中很重要。这样做的好处是
在开发接口时可以通过swagger将接口文档定义好,同时也方便以后的维护。
四.swagger的优点
号称时最流行的API框架
接口文档在线生成,避免同步的麻烦
可以支持在线对接口执行测试
支持多语言
五.集成swagger
5.1 新建springboot项目
使用集成开发工具创建一个springboot工程
5.2 集成swagger
1.pom.xml
<!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger2<!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger2 -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>swagger</artifactId>
<version>2.9.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger-ui -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
2.编写swagger配置类
package com.ycx.swagger.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.bind.annotation.RestController;
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;
@Configuration
@EnableSwagger2
public class SwaggerConfig {
@Bean
public Docket createRestApi(){
return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.withClassAnnotation(RestController.class))
.paths(PathSelectors.ant("/**")) //项目名
.build();
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("SwaggerDemoAPIDOC")
.description("SwaggerDemoAPIDOC")
.version("1.0")
.termsOfServiceUrl("https://www.baidu.com").build();
}
}
注意:SpringBoot与swagger2的版本对应关系,否则项目是启动不成功的,这里的版本对应关系如下
5.3 开发一个controller用于测试
package com.ycx.swagger.web;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.Map;
//@Api(tags = {"这是swagger入门类","作用2"})
@Api(tags = "这是swagger入门类")
@RestController
@RequestMapping("/swagger")
public class HelloController {
// @ApiOperation(value = "", tags = "swagger入门方法")
@ApiOperation(value = "swagger入门方法")
@GetMapping("/hello")
public Map<String,Object> hello(){
Map<String,Object> map = new HashMap<>();
map.put("code",200);
map.put("msg","响应成功!!!");
return map;
}
}
5.4 启动服务,验证集成效果
服务启动后,访问:http://localhost:8080/swagger-ui.html
说明集成成功
6.swagger常用注解
注解 | 位置 | 作用 | 参数 |
@Api | 类 | 标识这个类是swagger的资源 | tags:说明该类的作用,参数是个数组,可 以填多个。 |
value="该参数没什么意义,在UI界面上不显示,所以不用配置" | |||
description = "用户基本信息操作" | |||
@ApiOperation | 方法 | 表示一个http请求的操作 | value="方法的用途和作用" |
notes="方法的注意事项和备注" | |||
tags:说明该方法的作用,参数是个数组,可以填多 个。 | |||
格式:tags={"作用1","作用2"} | |||
@ApiParam | 方法,参数 | 对参数使用说明(如:说明 或是否必填等) | value="用户名" 描述参数的意义 |
name="name" 参数的变量名 | |||
required=true 参数是否必选 | |||
@ApiModel | 类 | 表示对类进行说明,用于参 数用实体类接收,一般用在 DTO上 | description="描述实体的作用" |
@ApiModelProperty | 方法,字段 | 表示对model属性的说明 | value="用户名" 描述参 数的意义 |
name="name" 参数的变量名 | |||
required=true 参数是否必选 | |||
@ApiIgnore | 类,方法,参数 | 表示这个方法或者类被忽略 | 无 |
@ApiImplicitParams | 方法 | 包含多@ApiImplicitParam | |
@ApiImplicitParam | 方法 | 表示单独的请求参数 | name="参数名称" |
value="参数说明" | |||
dataType="数据类型" | |||
paramType="query" 表示参数放在哪里 | |||
defaultValue="参数的默认值" | |||
required="true" 表示参数是否必须传 |
paramType="query"的解释如下
header 请求参数的获取:@RequestHeader
query 请求参数的获取:@RequestParam
path(用于restful接口) 请求参数的获取:@PathVariable
body(不常用)
form(不常用)
更全面的信息可以参考官方说明文档:
https://docs.swagger.io/swagger-core/apidocs/index.html
- swagger使用综合案例
package com.ycx.swagger.web;
import com.ycx.swagger.dto.User;
import io.swagger.annotations.*;
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
import java.util.Map;
@RestController
@RequestMapping("/swagger/api")
@Api(tags = "swagger所有注解的讲解")
public class SwaggerController {
@ApiOperation(value = "欢迎信息")
@GetMapping("/hello")
@ApiImplicitParams({
@ApiImplicitParam(name = "name", value = "名称", dataType = "string", paramType = "query", required = true),
@ApiImplicitParam(name = "msg", value="消息", dataType = "string", paramType = "query", required = true)
})
public Object hello(String name, String msg) {
Map<String, Object> map = new HashMap<>();
map.put("code", 200);
map.put("msg", "操作成功");
map.put("info",name+":"+msg);
return map;
}
@PostMapping("/register")
@ApiOperation("注册用户接口")
@ApiResponses({
@ApiResponse(code = 5001001,message = "错误1"),
@ApiResponse(code = 5001002,message = "错误2"),
@ApiResponse(code = 5001003,message = "错误3")
})
public Object register(User user) {
Map<String, Object> map = new HashMap<>();
map.put("code", 5001002);
map.put("msg", "操作成功");
map.put("info",user);
return map;
}
@PutMapping("/edit")
@ApiOperation("修改用户信息")
public Object edit(@RequestBody User user) {
Map<String, Object> map = new HashMap<>();
map.put("code", 200);
map.put("msg", "操作成功");
map.put("info",user);
return map;
}
@DeleteMapping("/delete/{id}")
@ApiOperation("删除用户")
@ApiImplicitParam(name = "id", value="用户ID", dataType = "string", paramType = "path", required = true)
public Object delete(@PathVariable("id") String id) {
Map<String, Object> map = new HashMap<>();
map.put("code", 200);
map.put("msg", "操作成功");
map.put("info",id);
return map;
}
}
package com.ycx.swagger.dto;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
@ApiModel(description = "用户信息")
public class User {
@ApiModelProperty(value = "用户名", name="name", required = true)
private String name;
@ApiModelProperty(value = "密码", name="passwd", required = true)
private String passwd;
}
- 会议OA之swagger
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.7</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.ycx</groupId>
<artifactId>minoa</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>minoa</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<fastjson.version>1.2.70</fastjson.version>
<jackson.version>2.9.8</jackson.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.44</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>${fastjson.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger2 -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger-ui -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.3.2</version>
<dependencies>
<!--使用Mybatis-generator插件不能使用太高版本的mysql驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
</dependencies>
<configuration>
<overwrite>true</overwrite>
</configuration>
</plugin>
</plugins>
</build>
</project>
2.swagger的整合配置类
package com.ycx.minoa.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.bind.annotation.RestController;
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;
@Configuration
@EnableSwagger2
public class SwaggerConfig {
@Bean
public Docket createRestApi(){
return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.withClassAnnotation(RestController.class))
.paths(PathSelectors.ant("/**")) //项目名
.build();
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("SwaggerDemoAPIDOC")
.description("SwaggerDemoAPIDOC")
.version("1.0")
.termsOfServiceUrl("https://www.baidu.com").build();
}
}
注意:此时SpringBoot (2.7.7) 版本与swagger2 (2.9.2) 的版本不兼容,需要添加application.yml相关配置
3.application.yml
spring:
mvc:
pathmatch:
matching-strategy: ant_path_matcher
4.web层接口服务提供
package com.ycx.minoa.wxcontroller;
import io.swagger.annotations.Api;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@Api(tags = "会议OA接口开发测试")
@RestController
public class HelloController {
@GetMapping("/hello")
public String hello(){
return "hello";
}
}
@Api(tags = "会议OA小程序接口列表")
@RestController
@RequestMapping("/wx/home")
public class WxHomeController {
@Autowired
private InfoMapper infoMapper;
@ApiOperation("会议OA首页数据加载")
@GetMapping("/index")
public Object index(@RequestBody Info info) {
List<Info> infoList = infoMapper.list(info);
Map<Object, Object> data = new HashMap<Object, Object>();
data.put("infoList",infoList);
return ResponseUtil.ok(data);
}
}
package com.ycx.minoa.model;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.util.Date;
@ApiModel(description = "会议信息")
public class Info {
@ApiModelProperty(value = "会议ID", name="id", required = false)
private Long id;
@ApiModelProperty(value = "会议标题", name="title", required = false)
private String title;
@ApiModelProperty(value = "会议内容", name="content", required = false)
private String content;
@ApiModelProperty(value = "参与者", name="canyuze", required = false)
private String canyuze;
@ApiModelProperty(value = "列席人员", name="liexize", required = false)
private String liexize;
@ApiModelProperty(value = "主持人", name="zhuchiren", required = false)
private String zhuchiren;
@ApiModelProperty(value = "会议地点", name="location", required = false)
private String location;
@ApiModelProperty(value = "会议开始时间", name="starttime", required = false)
private Date starttime;
@ApiModelProperty(value = "会议结束时间", name="endtime", required = false)
private Date endtime;
@ApiModelProperty(value = "附件", name="fujian", required = false)
private String fujian;
@ApiModelProperty(value = "会议状态", name="state", required = false)
private Integer state;
@ApiModelProperty(value = "审批人", name="auditperson", required = false)
private String auditperson;
@ApiModelProperty(value = "审批时间", name="audittime", required = false)
private Date audittime;
@ApiModelProperty(value = "会议座位图片", name="seatpic", required = false)
private String seatpic;
@ApiModelProperty(value = "备注", name="remark", required = false)
private String remark;
public Info(Long id, String title, String content, String canyuze, String liexize, String zhuchiren, String location, Date starttime, Date endtime, String fujian, Integer state, String auditperson, Date audittime, String seatpic, String remark) {
this.id = id;
this.title = title;
this.content = content;
this.canyuze = canyuze;
this.liexize = liexize;
this.zhuchiren = zhuchiren;
this.location = location;
this.starttime = starttime;
this.endtime = endtime;
this.fujian = fujian;
this.state = state;
this.auditperson = auditperson;
this.audittime = audittime;
this.seatpic = seatpic;
this.remark = remark;
}
public Info() {
super();
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getCanyuze() {
return canyuze;
}
public void setCanyuze(String canyuze) {
this.canyuze = canyuze;
}
public String getLiexize() {
return liexize;
}
public void setLiexize(String liexize) {
this.liexize = liexize;
}
public String getZhuchiren() {
return zhuchiren;
}
public void setZhuchiren(String zhuchiren) {
this.zhuchiren = zhuchiren;
}
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
public Date getStarttime() {
return starttime;
}
public void setStarttime(Date starttime) {
this.starttime = starttime;
}
public Date getEndtime() {
return endtime;
}
public void setEndtime(Date endtime) {
this.endtime = endtime;
}
public String getFujian() {
return fujian;
}
public void setFujian(String fujian) {
this.fujian = fujian;
}
public Integer getState() {
return state;
}
public void setState(Integer state) {
this.state = state;
}
public String getAuditperson() {
return auditperson;
}
public void setAuditperson(String auditperson) {
this.auditperson = auditperson;
}
public Date getAudittime() {
return audittime;
}
public void setAudittime(Date audittime) {
this.audittime = audittime;
}
public String getSeatpic() {
return seatpic;
}
public void setSeatpic(String seatpic) {
this.seatpic = seatpic;
}
public String getRemark() {
return remark;
}
public void setRemark(String remark) {
this.remark = remark;
}
}
5.测试结果