相信无论是前端还是后端开发,都或多或少地被接口文档折磨过。前端经常抱怨后端给的接口文档与实际情况不一致。后端又觉得编写及维护接口文档会耗费不少精力,经常来不及更新。
你只需要按照Swagger的规范去定义接口及接口相关的信息。再通过Swagger衍生出来的一系列项目和工具,就可以做到生成各种格式的接口文档,生成多种语言的客户端和服务端的代码,以及在线接口调试页面等等。
开发新版本或者迭代版本的时候,只需要更新Swagger描述文件,就可以自动生成接口文档和客户端服务端代码,做到调用端代码、服务端代码以及接口文档的一致性。
通过在项目中引入Swagger,可以扫描相关的代码,生成该描述文件,进而生成与代码一致的接口文档和客户端代码。这种通过代码生成接口文档的形式,在后面需求持续迭代的项目中,显得尤为重要和高效。
下面介绍SpringBoot整合Swagger生成API文档的过程
新建一个SpringBoot工程springboot-swagger2
引入相关的Maven依赖
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>io.springfoxgroupId>
<artifactId>springfox-swagger2artifactId>
<version>2.6.1version>
dependency>
<dependency>
<groupId>io.springfoxgroupId>
<artifactId>springfox-swagger-uiartifactId>
<version>2.6.1version>
dependency>
<dependency>
<groupId>org.mybatis.spring.bootgroupId>
<artifactId>mybatis-spring-boot-starterartifactId>
<version>2.1.0version>
dependency>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>druidartifactId>
<version>1.1.10version>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<scope>runtimescope>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
dependencies>
在数据库中建立测试的表,SQL脚本如下
DROP TABLE IF EXISTS `t_user`;
CREATE TABLE `t_user` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`username` varchar(255) NOT NULL,
`password` varchar(255) DEFAULT NULL,
`age` int(11) DEFAULT NULL,
`birthday` datetime DEFAULT NULL,
`comment` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4;
新建Mybatis配置文件 resources\mybatis\config.xml
<configuration>
<settings>
<setting name="mapUnderscoreToCamelCase" value="true" />
settings>
<typeAliases>
<typeAlias alias="Integer" type="java.lang.Integer" />
<typeAlias alias="Long" type="java.lang.Long" />
<typeAlias alias="HashMap" type="java.util.HashMap" />
<typeAlias alias="LinkedHashMap" type="java.util.LinkedHashMap" />
<typeAlias alias="ArrayList" type="java.util.ArrayList" />
<typeAlias alias="LinkedList" type="java.util.LinkedList" />
typeAliases>
configuration>
修改配置文件application.properties为application.yml,并添加下面的配置项
server:
port: 8081
spring:
datasource:
url: jdbc:mysql://localhost:3306/test?useSSL=false&serverTimezone=UTC
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
mybatis:
config-location: classpath:mybatis/config.xml
mapper-locations: classpath*:mybatis/mapper/**/*.xml
新建Swagger2的配置类
package com.kangswx.springbootswagger2.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;
@Configuration
public class Swagger2 {
/**
* 生成API对象
* @return
*/
@Bean
public Docket createRestApi(){
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
//controller包的路径,生成controller对应的API文档
.apis(RequestHandlerSelectors .basePackage("com.kangswx.springbootswagger2.controller"))
.paths(PathSelectors.any())
.build();
}
/**
* 生成API描述信息
* @return
*/
public ApiInfo apiInfo(){
return new ApiInfoBuilder()
.title("Spring整合Swagger2的API")
.description("简单优雅的rest风格,https://blog.csdn.net/kangswx")
.termsOfServiceUrl("https://blog.csdn.net/kangswx")
.version("1.0")
.build();
}
}
新建User的实体类
import java.io.Serializable;
import java.util.Date;
public class User implements Serializable {
private Integer id;
private String username;
private String password;
private Integer age;
private Date birthday;
private String comment;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username == null ? null : username.trim();
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password == null ? null : password.trim();
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public String getComment() {
return comment;
}
public void setComment(String comment) {
this.comment = comment == null ? null : comment.trim();
}
}
新增UserMapper接口
import com.kangswx.springbootswagger2.entity.User;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;
@Repository
@Mapper
public interface UserMapper {
int deleteByPrimaryKey(Integer id);
int insert(User record);
int insertSelective(User record);
User selectByPrimaryKey(Integer id);
int updateByPrimaryKeySelective(User record);
int updateByPrimaryKey(User record);
}
新增UserMapper配置文件(resources\mybatis\mapper\UserMapper.xml)
<mapper namespace="com.kangswx.springbootswagger2.mapper.UserMapper" >
<resultMap id="BaseResultMap" type="com.kangswx.springbootswagger2.entity.User" >
<id column="id" property="id" jdbcType="INTEGER" />
<result column="username" property="username" jdbcType="VARCHAR" />
<result column="password" property="password" jdbcType="VARCHAR" />
<result column="age" property="age" jdbcType="INTEGER" />
<result column="birthday" property="birthday" jdbcType="TIMESTAMP" />
<result column="comment" property="comment" jdbcType="VARCHAR" />
resultMap>
<sql id="Base_Column_List" >
id, username, password, age, birthday, comment
sql>
<select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.Integer" >
select
<include refid="Base_Column_List" />
from t_user
where id = #{id,jdbcType=INTEGER}
select>
<delete id="deleteByPrimaryKey" parameterType="java.lang.Integer" >
delete from t_user
where id = #{id,jdbcType=INTEGER}
delete>
<insert id="insert" parameterType="com.kangswx.springbootswagger2.entity.User" >
insert into t_user (id, username, password,
age, birthday, comment
)
values (#{id,jdbcType=INTEGER}, #{username,jdbcType=VARCHAR}, #{password,jdbcType=VARCHAR},
#{age,jdbcType=INTEGER}, #{birthday,jdbcType=TIMESTAMP}, #{comment,jdbcType=VARCHAR}
)
insert>
<insert id="insertSelective" parameterType="com.kangswx.springbootswagger2.entity.User" >
insert into t_user
<trim prefix="(" suffix=")" suffixOverrides="," >
<if test="id != null" >
id,
if>
<if test="username != null" >
username,
if>
<if test="password != null" >
password,
if>
<if test="age != null" >
age,
if>
<if test="birthday != null" >
birthday,
if>
<if test="comment != null" >
comment,
if>
trim>
<trim prefix="values (" suffix=")" suffixOverrides="," >
<if test="id != null" >
#{id,jdbcType=INTEGER},
if>
<if test="username != null" >
#{username,jdbcType=VARCHAR},
if>
<if test="password != null" >
#{password,jdbcType=VARCHAR},
if>
<if test="age != null" >
#{age,jdbcType=INTEGER},
if>
<if test="birthday != null" >
#{birthday,jdbcType=TIMESTAMP},
if>
<if test="comment != null" >
#{comment,jdbcType=VARCHAR},
if>
trim>
insert>
<update id="updateByPrimaryKeySelective" parameterType="com.kangswx.springbootswagger2.entity.User" >
update t_user
<set >
<if test="username != null" >
username = #{username,jdbcType=VARCHAR},
if>
<if test="password != null" >
password = #{password,jdbcType=VARCHAR},
if>
<if test="age != null" >
age = #{age,jdbcType=INTEGER},
if>
<if test="birthday != null" >
birthday = #{birthday,jdbcType=TIMESTAMP},
if>
<if test="comment != null" >
comment = #{comment,jdbcType=VARCHAR},
if>
set>
where id = #{id,jdbcType=INTEGER}
update>
<update id="updateByPrimaryKey" parameterType="com.kangswx.springbootswagger2.entity.User" >
update t_user
set username = #{username,jdbcType=VARCHAR},
password = #{password,jdbcType=VARCHAR},
age = #{age,jdbcType=INTEGER},
birthday = #{birthday,jdbcType=TIMESTAMP},
comment = #{comment,jdbcType=VARCHAR}
where id = #{id,jdbcType=INTEGER}
update>
mapper>
新增UserService接口
import com.kangswx.springbootswagger2.entity.User;
public interface UserService {
User getByid(Integer id);
int updateUser(User user);
int deleteUserById(Integer id);
int addUser(User user);
}
新增UserServiceImpl实现类
import com.kangswx.springbootswagger2.entity.User;
import com.kangswx.springbootswagger2.mapper.UserMapper;
import com.kangswx.springbootswagger2.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserMapper userMapper;
@Override
public User getByid(Integer id) {
return userMapper.selectByPrimaryKey(id);
}
@Override
public int updateUser(User user) {
return userMapper.updateByPrimaryKeySelective(user);
}
@Override
public int deleteUserById(Integer id) {
return userMapper.deleteByPrimaryKey(id);
}
@Override
public int addUser(User user) {
return userMapper.insert(user);
}
}
新增UserController,并为每个接口添加Swagger注解信息
import com.kangswx.springbootswagger2.entity.JsonData;
import com.kangswx.springbootswagger2.entity.User;
import com.kangswx.springbootswagger2.service.UserService;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api/v1/user")
public class UserController {
@Autowired
private UserService userService;
/**
* 查询接口
* @param id
* @return
*/
//ApiOperation生成的接口的API描述信息
@ApiOperation(value = "查询用户信息", notes = "根据url的id来查询用户详细信息")
//ApiImplicitParam生成的接口参数的API描述信息
@ApiImplicitParam(name="id", value = "用户的id", required = true, dataType = "int", paramType = "path")
@GetMapping(value = "{id}")
public Object getById(@PathVariable int id){
User user = userService.getByid(id);
return JsonData.buildSuccess(user);
}
/**
* 修改接口
* @param user
* @return
*/
//ApiOperation生成的接口的API描述信息
@ApiOperation(value = "修改用户信息", notes = "根据传入对象的非空字段值和id修改用户信息")
//ApiImplicitParam生成的接口参数的API描述信息
@ApiImplicitParam(name = "user", value = "用户对象", required = true, dataType = "Json", paramType = "body")
@PutMapping()
public Object updateUserById(@RequestBody User user){
int ret = userService.updateUser(user);
JsonData jsonData = null;
if(ret > 0){
jsonData = JsonData.buildSuccess("修改成功");
} else {
jsonData = JsonData.buildError("修改失败");
}
return jsonData;
}
/**
* 添加接口
* @param user
* @return
*/
//ApiOperation生成的接口的API描述信息
@ApiOperation(value = "新增用户", notes = "将传入的用户对象添加到数据库")
//ApiImplicitParam生成的接口参数的API描述信息
@ApiImplicitParam(name = "user", value = "用户对象", required = true, dataType = "Json", paramType = "body")
@PostMapping()
public Object addUser(@RequestBody User user){
int ret = userService.addUser(user);
JsonData jsonData = null;
if(ret > 0){
jsonData = JsonData.buildSuccess("添加成功");
} else {
jsonData = JsonData.buildError("添加失败");
}
return jsonData;
}
/**
* 删除接口
* @param id
* @return
*/
//ApiOperation生成的接口的API描述信息
@ApiOperation(value = "删除用户", notes = "根据url的id来删除数据库中对应的用户")
//ApiImplicitParam生成的接口参数的API描述信息
@ApiImplicitParam(name="id", value = "用户的id", required = true, dataType = "int", paramType = "path")
@DeleteMapping("{id}")
public Object deleteUser(@PathVariable int id){
int ret = userService.deleteUserById(id);
JsonData jsonData = null;
if(ret > 0){
jsonData = JsonData.buildSuccess("删除成功");
} else {
jsonData = JsonData.buildError("删除失败");
}
return jsonData;
}
}
在启动类上添加MapperScan和EnableSwagger2的注解
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
@MapperScan(basePackages = "com.kangswx.springbootswagger2.mapper")
@SpringBootApplication
@EnableSwagger2 //启动Swagger2
public class SpringbootSwagger2Application {
public static void main(String[] args) {
SpringApplication.run(SpringbootSwagger2Application.class, args);
}
}
启动SpringBoot项目,并访问 http://localhost:8081/swagger-ui.html
会看到Swagger生成的API文档
进行简单的测试,测试查询接口
输入id的参数后,点击Try it out!就会看到查询的结果
测试添加
点击Try it out!,返回结果为
测试删除
返回结果为
至此,所有的功能测试正常, 上面的代码详见 SpringBoot整合Swagger2实现自动生成API