SpringBoot集成Swagger
Web应用开发技术的发展,现在的移动端应用架构基本都选用前后端分离的开发技术了。API接口文档就成了前后端开发人员联系的纽带,变得尤为的重要,swagger是一款让你更好的API接口在线调试和自动生成API接口文档的框架。
Swagger优缺点
没有API文档工具之前,基本都是手写API文档的,如有在Word上写的,有在对应的项目目录下readme.md上写的。但是这种手写文档带来的弊端就是维护起来很困难,对于接口容易发生变化的开发者来说,维护文档的工作量实在太大了….
好在现如今市场上书写API文档的工具有很多,常见的有postman、Apifox等,但是能称之为框架的,估计也只有swagger了。
Swagger优点
- 集成方便,功能强大
- 在线调试与文档生成
Swagger缺点
- 代码耦合,需要注解支持,但不影响程序性能
导入依赖
在pom.xml中添加swagger-spring-boot-starter的依赖
<!-- swagger2-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.10.5</version>
</dependency>
<!-- 这里使用 knife4j,前身是swagger-bootstrap-ui 替代了原有丑陋的ui -->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
<version>2.0.9</version>
</dependency>
<!--升级swagger-models版本 解决警告:Illegal DefaultValue null for parameter type integer-->
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-models</artifactId>
<version>1.5.22</version>
</dependency>
Swagger常用注解
| 注解 | 说明 |
|---|---|
| @Api | 描述Controller |
| @ApiIgnore | 忽略该Controller,指不对当前类做扫描 |
| @ApiOperation | 描述Controller类中的method接口 |
| @ApiParam | 单个参数描述,与@ApiImplicitParam不同的是,他是写在参数左侧的。如(@ApiParam(name = “username”,value = “用户名”) String username) |
| @ApiModel | 描述POJO对象 |
| @ApiModelProperty | 描述POJO对象中的属性值 |
| @ApiImplicitParam | 描述单个入参信息 |
| @ApiImplicitParams | 描述多个入参信息 |
| @ApiResponse | 描述单个出参信息 |
| @ApiResponses | 描述多个出参信息 |
说明
POJO是一种“纯粹的”JavaBean,在它里面除了JavaBean规范的方法和属性没有别的东西,它只能装载数据,作为数据存储的载体,而不具有业务逻辑处理的能力。
各个注解的使用详情,请自行百度。后面会以用户登录接口为例进行详细介绍。
创建配置类,启动Swagger
Swagger 的实例 Bean 是 Docket,所以通过配置 Docket 实例来配置 Swaggger。
我们在包com.zjff.myshop.config中新建一个配置类 SwaggerConfiguration.java。参考代码如下:
package com.zjff.myshop.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.web.bind.annotation.RequestMethod;
import springfox.documentation.builders.*;
import springfox.documentation.schema.ModelRef;
import springfox.documentation.service.*;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2WebMvc;
import java.util.ArrayList;
import java.util.List;
/**
* Swagger2的接口配置
* 文档浏览器地址:http:127.0.0.1:5050/doc.html
*/
@Configuration
@EnableSwagger2WebMvc
@Profile({"dev", "test"}) //配置该bean用于开发、测试环境
public class SwaggerConfiguration {
@Bean(value = "dockerBean")
public Docket dockerBean() {
String groupName = "v1";
return new Docket(DocumentationType.SWAGGER_2) //SWAGGER_2
.apiInfo(apiInfo())
.groupName(groupName)
.select()
//这里指定Controller扫描包路径
.apis(RequestHandlerSelectors.basePackage("com.zjff.myshop.api"))
//.apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
.paths(PathSelectors.any())
.build()
.globalOperationParameters(globalOperationParameters())
.useDefaultResponseMessages(false)
.globalResponseMessage(RequestMethod.GET, responseMessageList())
.globalResponseMessage(RequestMethod.POST, responseMessageList())
.globalResponseMessage(RequestMethod.DELETE, responseMessageList());
}
//添加摘要信息
private ApiInfo apiInfo() {
return new ApiInfoBuilder().title("标题:我的商城接口文档")
.description("描述:基于swagger knife4j自动创建的接口文档,用于管理我的商城信息,具体包括用户,商品等模块...")
.termsOfServiceUrl("http://swagger.io/")
.contact(new Contact("watchping", "127.0.0.1", "watchping@163.com"))
.version("0.0.1")
.build();
}
// 设置全局参数
private List<Parameter> globalOperationParameters() {
// 添加token参数
ParameterBuilder parameterBuilder = new ParameterBuilder();
parameterBuilder
.parameterType("header")
.name("token")
.description("用户token")
.modelRef(new ModelRef("string"))
.required(false).build();
List<Parameter> parameterList = new ArrayList<Parameter>();
parameterList.add(parameterBuilder.build());
return parameterList;
}
// 自定义响应状态
private List<ResponseMessage> responseMessageList() {
ResponseMessage responseMessage500 = new ResponseMessageBuilder()
.code(500)
.message("服务器发生异常")
.build();
ResponseMessage responseMessage401 = new ResponseMessageBuilder()
.code(401)
.message("未登录")
.build();
ResponseMessage responseMessage403 = new ResponseMessageBuilder()
.code(403)
.message("资源不可用")
.build();
List<ResponseMessage> responseMessageList = new ArrayList<>();
responseMessageList.add(responseMessage500);
responseMessageList.add(responseMessage401);
responseMessageList.add(responseMessage403);
return responseMessageList;
}
}
注意
- 这里通过注解@Profile({“dev”, “test”}) 配置了在开发、测试环境启动Swagger。生成环境不建议启动Swagger,避免接口暴露存在的风险。
- 这里设置了自定义的响应状态,默认的接口响应状态信息是英文的。
- 这里设置了全局参数,一般接口的请求头部都会带有参数token的。
至此,启动 SpringBoot 项目,浏览器输入 http://localhost:5050/doc.html,选择,用户模块的用户登录接口,就可以看到它的接口文档说明。操作界面如下图:

选择侧边栏的调试项后,也可以对接口进行在线调式,操作界面如下图:

这里显示的是一个已完成项目的Swagger接口,下面以用户登录接口为例,就实现过程进行详细介绍。
用户登录接口为例详细介绍
1.用户登录接口请求参数POJO类
在包com.zjff.myshop.api.front.form中新建用于接收前端表单传入的接口入参LoginForm.java
package com.zjff.myshop.api.front.form;
import io.swagger.annotations.ApiModelProperty;
import javax.validation.constraints.NotEmpty;
import lombok.Data;
import java.io.Serializable;
/**
* 用户登录
*/
@Data
public class LoginForm implements Serializable {
@ApiModelProperty(value = "用户名", position = 1, required = true)
@NotEmpty(message = "用户名不能为空")
private String name;
@ApiModelProperty(value = "用户密码", position = 2, required = true)
@NotEmpty(message = "密码不能为空")
private String password;
}
提示
- 接口用到的传入请求参数POJO类建议都定义在form包中
- @ApiModelProperty 用于描述对象的属性
- @NotEmpty 用户属性数据校验
2.用户登录接口返回参数POJO类
在包com.zjff.myshop.api.front.vo中新建用于返回给前端的接口出参UserLoginVO.java
package com.zjff.myshop.api.front.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
@Data
@ApiModel("用户登录返回数据")
public class UserLoginVO implements Serializable {
@ApiModelProperty(value = "用户id", position = 1)
private Integer id;
@ApiModelProperty(value = "用户Name", position = 2)
private String name;
@ApiModelProperty(value = "用户头像", position = 3)
private String avatar;
@ApiModelProperty(value = "Token", position = 4)
private String token;
}
提示
- 接口用到的返回参数POJO类建议都定义在vo包中
- @ApiModel 用于描述对象
3.用户登录接口控制类
在包com.zjff.myshop.api.front中新建用于前端应用的用户接口控制类UserController.java
package com.zjff.myshop.api.front;
import cn.dev33.satoken.stp.StpUtil;
import com.zjff.myshop.api.front.form.LoginForm ;
import com.zjff.myshop.api.front.vo.UserLoginVO;
import com.zjff.myshop.entity.User;
import com.zjff.myshop.service.UserService;
import com.zjff.myshop.util.BeanUtils;
import com.zjff.myshop.util.Result;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.validation.Valid;
@Api(value = "v1", tags = "02.用户模块")
@RestController
@RequestMapping("/app/v1/user")
public class UserController {
private static final Logger logger = LoggerFactory.getLogger(UserController.class);
@Resource
private UserService userService;
/**
* 用户登录
*/
@ApiOperation(value = "用户登录", notes = "返回用户id、token")
@ApiImplicitParam(name = "form", value = "用户登录请求参数", dataType = "LoginForm", required = true)
@PostMapping("/login")
public Result<UserLoginVO> login(@RequestBody @Valid LoginForm form) {
User user = userService.login(form.getName(), form.getPassword());
Integer userId = user.getId();
//客户端注册用户登录
StpUtil.login(userId, "Mobile");
String token = StpUtil.getTokenValue();
UserLoginVO userLoginVO = new UserLoginVO();
BeanUtils.copyProperties(user, userLoginVO);
userLoginVO.setToken(token);
return Result.ok(userLoginVO);
}
}
提示
- 用于前端应用的用户接口控制类建议都定义在api.front包中
- @ApiOperation 用于描述接口
- @ApiImplicitParam 用户描述接口请求参数
- @Valid 用户参数校验
接下来,继续介绍该控制类用的其他类。
4.用户接口控制类用到的其他类说明
4.1用户实体类User.java
package com.zjff.myshop.entity;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.util.Date;
@Data
public class User {
private Integer id;//编号
private String name;//用户名
private String password;//密码
private String salt;//加密佐料
private Boolean gender;//性别
private String email;//邮箱
private String phone;//手机号
private String avatar;//头像
private String nickName;//昵称
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date createTime;//创建时间
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date updateTime;//更新时间
private String remark;//备注
}
4.2接口数据统一返回类Result.java
package com.zjff.myshop.util;
import cn.hutool.core.util.StrUtil;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
@Data
public class Result<T> implements Serializable {
private static final long serialVersionUID = 1L;
//业务码,比如成功、失败、权限不足等 code,可自行定义
@ApiModelProperty(value = "返回码",position = 1)
private int code;
//返回信息,后端在进行业务处理后返回给前端一个提示信息,可自行定义
@ApiModelProperty(value = "返回信息",position = 2)
private String message;
//数据结果,泛型,可以是列表、单个对象、数字、布尔值等
@ApiModelProperty(value = "返回数据",position = 3)
private T data;
public Result() {
}
public Result(int code, String message) {
this.code = code;
this.message = message;
}
private static final String DEFAULT_OK_MESSAGE = "成功";
private static final String DEFAULT_ERROR_MESSAGE = "失败";
private static final int RESULT_OK = 200;
private static final int RESULT_ERROR = 500;
public static <T> Result<T> ok() {
Result<T> result = new Result<>();
result.setCode(RESULT_OK);
result.setMessage(DEFAULT_OK_MESSAGE);
return result;
}
public static <T> Result<T> ok(String message) {
Result<T> result = new Result<>();
result.setCode(RESULT_OK);
result.setMessage(message);
return result;
}
public static <T> Result<T> ok(T data) {
Result<T> result = new Result<>();
result.setCode(RESULT_OK);
result.setMessage(DEFAULT_OK_MESSAGE);
result.setData(data);
return result;
}
public static <T> Result<T> error() {
Result<T> result = new Result<>();
result.setCode(RESULT_ERROR);
result.setMessage(DEFAULT_ERROR_MESSAGE);
return result;
}
}
4.3自封装的Bean工具类BeanUtils.java
package com.zjff.myshop.util;
import cn.hutool.core.bean.BeanUtil;
public class BeanUtils {
public static Object copyProperties(Object source, Object target, String... ignoreProperties) {
if (source == null) {
return target;
}
BeanUtil.copyProperties(source, target, ignoreProperties);
return target;
}
}
4.4用户认证模块Sa-token
用户登录、生成token,这里用的是第三方认证模块Sa-Token中的工具类StpUtil,要使用Sa-Token,先在pom.xml中导入依赖
<!--Sa-Token 权限认证核心库 在线文档:http://sa-token.dev33.cn/ -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-spring-boot-starter</artifactId>
<version>1.26.0</version>
</dependency>
StpUtil.login()、StpUtil.getTokenValue()的具体使用请参考官方文档。
Sa-Token 官网: 在线文档
关于项目中Sa-Token的详细使用,我会另起一篇博文介绍的。
2148

被折叠的 条评论
为什么被折叠?



