参考SpringBoot整合Swagger2,再也不用维护接口文档了!
参考swagger2 注解说明 ( @ApiImplicitParams )
程序猿们都讨厌两件事:写接口文档、别人不写接口文档
我觉得这大概就是swagger2诞生的原因吧
整合
创建一个SpringBoot项目,加入swagger2的依赖
<!--swagger2-->
<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>
新建一个config包,在此包下新建一个类SwaggerConfig
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.Contact;
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)
.pathMapping("/")
.select()
.apis(RequestHandlerSelectors.basePackage("com.thz.swagger2_demo.controller"))
.paths(PathSelectors.any())
.build().apiInfo(new ApiInfoBuilder()
.title("SpringBoot整合Swagger")
.description("SpringBoot整合Swagger,详细信息......")
.version("9.0")
.contact(new Contact("我的CSDN","https://blog.csdn.net/m0_49558851","qwer@gmail.com"))
.license("The Apache License")
.licenseUrl("http://www.baidu.com")
.build());
}
}
到这里就配置好了,我们启动项目访问 http://localhost:8080/swagger-ui.html 能看到如下页面就说明配置成功
测试
为了测试我们需要连接一下数据库,在pom.xml中加入
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.3</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
创建表并插入数据
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` int(32) NOT NULL AUTO_INCREMENT,
`userName` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
`passWord` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
`realName` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 14 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES (1, 'admin', '123456', '管理员');
INSERT INTO `user` VALUES (3, 'qwe', '123', '管理员');
INSERT INTO `user` VALUES (9, 'thzthz', '123', '管理员');
INSERT INTO `user` VALUES (10, 'thz', '123', '管理员');
INSERT INTO `user` VALUES (11, 'dasd', 'sdas', '管理员');
INSERT INTO `user` VALUES (12, 'qdasd', 'adas', '管理员');
SET FOREIGN_KEY_CHECKS = 1;
先贴出目录结构
application.properties
server.port=8080
spring.datasource.username=root
spring.datasource.password=151415
spring.datasource.url=jdbc:mysql://localhost:3306/springbootdemo?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=UTC
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
mybatis.mapper-locations=classpath:mapper/*Mapper.xml
mybatis.type-aliases-package=com.thz.swagger2_demo.entity
在启动类上加注解
@MapperScan("com.thz.swagger2_demo.mapper") //扫描的mapper
user.java
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.io.Serializable;
/**
* (User)实体类
*
* @author makejava
* @since 2020-08-04 15:51:11
*/
@ApiModel
public class User implements Serializable {
private static final long serialVersionUID = 381278290366482529L;
@ApiModelProperty(value = "ID")
private Integer id;
@ApiModelProperty(value = "用户名")
private String username;
@ApiModelProperty(value = "密码")
private String password;
@ApiModelProperty(value = "身份")
private String realname;
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;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getRealname() {
return realname;
}
public void setRealname(String realname) {
this.realname = realname;
}
}
UserMapper.java
/**
* (User)表数据库访问层
*
* @author makejava
* @since 2020-08-04 15:51:12
*/
@Component
public interface UserMapper{
/**
* 通过ID查询单条数据
*
* @param id 主键
* @return 实例对象
*/
User queryById(Integer id);
/**
* 查询指定行数据
*
* @param offset 查询起始位置
* @param limit 查询条数
* @return 对象列表
*/
List<User> queryAllByLimit(@Param("offset") int offset, @Param("limit") int limit);
/**
* 通过实体作为筛选条件查询
*
* @param user 实例对象
* @return 对象列表
*/
List<User> queryAll(User user);
/**
* 新增数据
*
* @param user 实例对象
* @return 影响行数
*/
int insert(User user);
/**
* 修改数据
*
* @param user 实例对象
* @return 影响行数
*/
int update(User user);
/**
* 通过主键删除数据
*
* @param id 主键
* @return 影响行数
*/
int deleteById(Integer id);
}
UserMapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.thz.swagger2_demo.mapper.UserMapper">
<resultMap type="com.thz.swagger2_demo.entity.User" id="UserMap">
<result property="id" column="id" jdbcType="INTEGER"/>
<result property="username" column="userName" jdbcType="VARCHAR"/>
<result property="password" column="passWord" jdbcType="VARCHAR"/>
<result property="realname" column="realName" jdbcType="VARCHAR"/>
</resultMap>
<!--查询单个-->
<select id="queryById" resultMap="UserMap">
select
id, userName, passWord, realName
from springbootdemo.user
where id = #{id}
</select>
<!--查询指定行数据-->
<select id="queryAllByLimit" resultMap="UserMap">
select
id, userName, passWord, realName
from springbootdemo.user
limit #{offset}, #{limit}
</select>
<!--通过实体作为筛选条件查询-->
<select id="queryAll" resultMap="UserMap">
select
id, userName, passWord, realName
from springbootdemo.user
<where>
<if test="id != null">
and id = #{id}
</if>
<if test="username != null and username != ''">
and userName = #{username}
</if>
<if test="password != null and password != ''">
and passWord = #{password}
</if>
<if test="realname != null and realname != ''">
and realName = #{realname}
</if>
</where>
</select>
<!--新增所有列-->
<insert id="insert" keyProperty="id" useGeneratedKeys="true">
insert into springbootdemo.user(userName, passWord, realName)
values (#{username}, #{password}, #{realname})
</insert>
<!--通过主键修改数据-->
<update id="update">
update springbootdemo.user
<set>
<if test="username != null and username != ''">
userName = #{username},
</if>
<if test="password != null and password != ''">
passWord = #{password},
</if>
<if test="realname != null and realname != ''">
realName = #{realname},
</if>
</set>
where id = #{id}
</update>
<!--通过主键删除-->
<delete id="deleteById">
delete from springbootdemo.user where id = #{id}
</delete>
</mapper>
UserService.java
package com.thz.swagger2_demo.service;
import com.thz.swagger2_demo.entity.User;
import java.util.List;
/**
* (User)表服务接口
*
* @author makejava
* @since 2020-08-04 15:51:15
*/
public interface UserService {
/**
* 通过ID查询单条数据
*
* @param id 主键
* @return 实例对象
*/
User queryById(Integer id);
/**
* 查询多条数据
*
* @param offset 查询起始位置
* @param limit 查询条数
* @return 对象列表
*/
List<User> queryAllByLimit(int offset, int limit);
/**
* 新增数据
*
* @param user 实例对象
* @return 实例对象
*/
User insert(User user);
/**
* 修改数据
*
* @param user 实例对象
* @return 实例对象
*/
User update(User user);
/**
* 通过主键删除数据
*
* @param id 主键
* @return 是否成功
*/
boolean deleteById(Integer id);
}
UserServiceImpl.java
package com.thz.swagger2_demo.service.impl;
import com.thz.swagger2_demo.mapper.UserMapper;
import com.thz.swagger2_demo.entity.User;
import com.thz.swagger2_demo.service.UserService;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;
/**
* (User)表服务实现类
*
* @author makejava
* @since 2020-08-04 15:51:16
*/
@Service("userService")
public class UserServiceImpl implements UserService {
@Resource
private UserMapper userMapper;
/**
* 通过ID查询单条数据
*
* @param id 主键
* @return 实例对象
*/
@Override
public User queryById(Integer id) {
return this.userMapper.queryById(id);
}
/**
* 查询多条数据
*
* @param offset 查询起始位置
* @param limit 查询条数
* @return 对象列表
*/
@Override
public List<User> queryAllByLimit(int offset, int limit) {
return this.userMapper.queryAllByLimit(offset, limit);
}
/**
* 新增数据
*
* @param user 实例对象
* @return 实例对象
*/
@Override
public User insert(User user) {
this.userMapper.insert(user);
return user;
}
/**
* 修改数据
*
* @param user 实例对象
* @return 实例对象
*/
@Override
public User update(User user) {
this.userMapper.update(user);
return this.queryById(user.getId());
}
/**
* 通过主键删除数据
*
* @param id 主键
* @return 是否成功
*/
@Override
public boolean deleteById(Integer id) {
return this.userMapper.deleteById(id) > 0;
}
}
UserController
/**
* (User)表控制层
*
* @author makejava
* @since 2020-08-04 15:51:16
*/
@RestController
@RequestMapping("user")
@Api(tags = "用户管理相关接口")
public class UserController {
/**
* 服务对象
*/
@Resource
private UserService userService;
/**
* 通过主键查询单条数据
*
* @param id 主键
* @return 单条数据
*/
@GetMapping("selectOne")
@ApiOperation("通过主键查询单条用户数据")
@ApiImplicitParams(@ApiImplicitParam(name = "id",value = "用户主键值",dataType = "Integer",defaultValue = "1"))
public User selectOne(@RequestParam(defaultValue = "1") Integer id) {
return this.userService.queryById(id);
}
@PostMapping("/")
@ApiOperation("添加用户的接口")
public User addUser(@RequestBody User user) {
return userService.insert(user);
}
@GetMapping("/")
@ApiOperation("根据id查询用户的接口")
@ApiImplicitParam(name = "id", value = "用户id", defaultValue = "99", required = true)
public User getUserById(@PathVariable Integer id) {
User user = new User();
user.setId(id);
return user;
}
@PutMapping("/{id}")
@ApiOperation("根据id更新用户的接口")
public User updateUserById(@RequestBody User user) {
return userService.update(user);
}
@DeleteMapping("/{id}")
@ApiOperation("根据id删除用户的接口")
public String deleteUserById(Integer id){
Boolean flag = userService.deleteById(id);
if (flag){
return "success";
}else {
return "fail";
}
}
}
准备工作都做好了,接下来我们再次访问 http://localhost:8080/swagger-ui.html#/ 可以看到页面变成了这样
展开之后我们可以看到上面是接口说明,下面是User对象的说明
我们测试一下其中一个接口
我们输入查询参数并执行
我们可以看到请求的url和responsebody里面都有了我们期望的结果,查出了数据
再试一试新增
去数据库看一下,的确是新增进去了
注释说明
最后说一下swagger2的注释,首先是在实体类中添加的注释
添加在类上的@ApiModel
添加在成员属性上的@ApiModelProperty(value = “用户名”)
这两个注解帮助我们看到了如下效果
UserController中的注释
@Api:用在请求的类上,表示对类的说明
tags="说明该类的作用,可以在UI界面上看到的注解"
value="该参数没什么意义,在UI界面上也看到,所以不需要配置"
@ApiOperation:用在请求的方法上,说明方法的用途、作用
value="说明方法的用途、作用"
notes="方法的备注说明"
@ApiImplicitParams:用在请求的方法上,表示一组参数说明
@ApiImplicitParam:用在@ApiImplicitParams注解中,指定一个请求参数的各个方面
name:参数名
value:参数的汉字说明、解释
required:参数是否必须传
paramType:参数放在哪个地方
· header --> 请求参数的获取:@RequestHeader
· query --> 请求参数的获取:@RequestParam
· path(用于restful接口)--> 请求参数的获取:@PathVariable
· body(不常用)
· form(不常用)
dataType:参数类型,默认String,其它值dataType="Integer"
defaultValue:参数的默认值
@ApiResponses:用在请求的方法上,表示一组响应
@ApiResponse:用在@ApiResponses中,一般用于表达一个错误的响应信息
code:数字,例如400
message:信息,例如"请求参数没填好"
response:抛出异常的类
@ApiModel:用于响应类上,表示一个返回响应数据的信息
(这种一般用在post创建的时候,使用@RequestBody这样的场景,
请求参数无法使用@ApiImplicitParam注解进行描述的时候)
@ApiModelProperty:用在属性上,描述响应类的属性