Swagger 是一个规范和完整的框架,用于生成、描述、调用和可视化 RESTful 风格的 Web 服务的接口文档。
目前的项目基本都是前后端分离,后端为前端提供接口的同时,还需同时提供接口的说明文档。但我们的代码总是会根据实际情况来实时更新,这个时候有可能会忘记更新接口的说明文档,造成一些不必要的问题。
用人话说,swagger就是帮你写接口说明文档的。
纯粹后端的java开发人员,不编写页面代码, 只需要写接口( 这里的接口不是java中的interface )
在SpringMVC的控制层Controller类的方法里, 不写转页( 包括 内部转, 重定向 ),
都是通过 @ResponseBody, 返回JSON格式的数据
所以 Controller 类上的注解由@Controller, 改为 @RestController ( @Controller + @ResponseBody )
接口就是制定一个协议, 给前端开发人员调用后端功能的参考. 可能包括的内容 :
协议 | 介绍 |
---|---|
http 还是 https | https请求需要SSL证书 |
请求名 | url 或者 uri |
请求方式 | get, post, put, delete等等 |
参数列表 | 包括类型和传值方式 |
返回类型 | 返回格式, 状态码, 错误消息, 数据 |
例如:
模块名称: 用户登录
请求方式: post
请求名: /login/auth
参数
参数名 | 类型 | 说明 | 是否必须 |
---|---|---|---|
username | String(20) | 用户名 | 是 |
password | String(20) | 密码 | 是 |
remember | Interger | 记住我, 1-记住,0-不记住, 默认按0处理 | 否 |
返回:
{
code: 200,
msg: 'success',
data: {
userId: 1,
userName: 王小二,
sex: 1
}
}
或者
{
code: 1001,
msg: '用户名不能为空',
data: null
}
**如果是由后端人员来维护这些信息, 有个非常大的缺点, **
就是如果对这个方法做了修改, 例如添加了一个新的参数, 则需要修改这个接口文档.
基于这个缺点, 诞生了一个技术, 接口文档自动生成工具-swagger
即, 整个接口文档内容, 不需要手动编写了, 而是通过程序自动生成
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import lombok.Data;
@Data
public class Result {
private Integer code; // 数字代码 如: 成功 200;
private String msg; // "错误描述"
private Object data; // 数据 {}
public Result() {
this.code = 200;
this.msg = "success";
}
public static Result error() {
return error(500, "未知异常,请联系管理员");
}
public static Result error(String msg) {
return error(500, msg);
}
public static Result error(int code, String msg) {
Result r = new Result();
r.code = code;
r.msg = msg;
return r;
}
public static Result ok(String msg) {
Result r = new Result();
r.msg = msg;
return r;
}
public static Result ok() {
return new Result();
}
public Result data(Object data) {
Result r = new Result();
r.data = data;
return r;
}
/**
* 把map里key为data的数据转换成某个类型的数据
* @param typeReference
* @param
* @return
*/
public <T> T getData(TypeReference<T> typeReference) {
Object obj = this.getData();
String json = JSON.toJSONString(obj);
T t = JSON.parseObject(json, typeReference);
return t;
}
public <T> T getData(String key, TypeReference<T> typeReference) {
Object obj = this.getData();
String json = JSON.toJSONString(obj);
T t = JSON.parseObject(json, typeReference);
return t;
}
}
最少要求包含3个属性,可以很多
{
code: 200, //"数字代码"
msg: "错误描述",
data: {} //数据
}
<dependency>
<groupId>io.springfoxgroupId>
<artifactId>springfox-swagger2artifactId>
<version>2.9.2version>
dependency>
<dependency>
<groupId>io.springfoxgroupId>
<artifactId>springfox-swagger-uiartifactId>
<version>2.9.2version>
<exclusions>
<exclusion>
<groupId>io.swaggergroupId>
<artifactId>swagger-annotationsartifactId>
exclusion>
<exclusion>
<groupId>io.swaggergroupId>
<artifactId>swagger-modelsartifactId>
exclusion>
exclusions>
dependency>
<dependency>
<groupId>io.swaggergroupId>
<artifactId>swagger-annotationsartifactId>
<version>1.5.21version>
dependency>
<dependency>
<groupId>io.swaggergroupId>
<artifactId>swagger-modelsartifactId>
<version>1.5.21version>
dependency>
主要配置Swagger2注解的扫描路径
次要配置一些说明信息
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;
@Configuration
@EnableSwagger2
public class Swagger2Config {
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("com.yuan")) //这个是重点
.paths(PathSelectors.any())
.build();
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("接口文档标题")
.description("文档内容描述")
.termsOfServiceUrl("http://www.baidu.com")
.version("1.0")
.build();
}
}
apis(RequestHandlerSelectors.basePackage("com.yuan"
))
表示swagger2的注解, 必须写在com.yuan的同级包或者子包里, 否则不识别
例如 : 启动类或者当前配置类
@EnableSwagger2
/swagger-ui.html
<dependency>
<groupId>com.github.caspar-chengroupId>
<artifactId>swagger-ui-layerartifactId>
<version>1.1.3version>
dependency>
请求路径
/docs.html
<dependency>
<groupId>com.github.xiaoymingroupId>
<artifactId>swagger-bootstrap-uiartifactId>
<version>1.9.6version>
dependency>
请求路径
/doc.html
swagger api注解
这一部分除了,下面列出的注解外,还包括上面所介绍的RequestHandlerSelectors和PathSelectors的几种方法及含义。
@Api: *用于类,标识这个类是swagger的资源
@ApiIgnore: 用于类,忽略该 Controller,指不对当前类做扫描
@ApiOperation: *用于方法,描述 Controller类中的 method接口
@ApiParam: *用于参数,单个参数描述,与 @ApiImplicitParam不同的是,他是写在参数左侧的。如( @ApiParam(name="userName",value="用户名")String userName)
@ApiModel: 用于类,表示对类进行说明,用于参数用实体类接收
@ApiProperty: 用于方法,字段,表示对model属性的说明或者数据操作更改
@ApiModelProperty
@ApiImplicitParam: *用于方法,表示单独的请求参数
@ApiImplicitParams: *用于方法,包含多个 @ApiImplicitParam
@ApiResponse: 用于方法,描述单个出参信息
@ApiResponses: 用于方法,包含多个@ApiResponse
@ApiError: 用于方法,接口错误所返回的信息
swagger不会参与业务开发,和业务代码是完全解耦的, 没有任何耦合
原始代码
@RestController
public class LoginController {
@PostMapping(value = "/user/login1")
public Result login1(String userName, String password){
System.out.println("userName = " + userName);
System.out.println("password = " + password);
return Result.ok();
}
}
swagger的注解只是给你的类, 方法, 参数, 属性添加注释而已.
@Api(tags = "用户管理")
// @ApiOperation(value = "方法名称", tags = "分组标记-与 @Api的tags属性对应", notes = "方法说明")
@ApiOperation("用户登录1")
@ApiImplicitParams({
@ApiImplicitParam(name = "userName", value = "账号", required = true)
})
@RestController
@Api(tags = "用户管理" )
public class LoginController {
@ApiOperation("用户登录1")
@ApiImplicitParams({
@ApiImplicitParam(name = "userName", value = "账号", required = true)
})
@PostMapping(value = "/user/login1")
public Result login1(String userName, @ApiIgnore String password){
System.out.println("userName = " + userName);
System.out.println("password = " + password);
return Result.ok();
}
@ApiOperation("用户登录2")
@PostMapping(value = "/user/login2")
public Result login2( @ApiParam(name = "userName", value = "账号", required = true) String userName
, @ApiIgnore String password){
System.out.println("userName = " + userName);
System.out.println("password = " + password);
return Result.ok();
}
}
这样可以打开浏览器进行
@ApiModel
public class SysUser implements Serializable {}
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
public class SysUser {
private Integer userId;
@ApiModelProperty(hidden = true) //隐藏属性
private Integer userStatus;
@ApiModelProperty(value = "账号", required = true) //设置参数注释
private String userName;
}
REST(英文:Representational State Transfer,简称REST)描述了一个架构样式的网络系统,比如 web 应用程序。
通常 get 查询 post 添加 put/patch 修改 delete 删除
在接口系统里, 不要只写@RequestMapping(value = “/user/{id}”), 同时要指明请求方式 method
@RequestMapping("/query")
// @RequestMapping(value = "/query", method = RequestMethod.GET)
// @RequestMapping(value = "/query", method = RequestMethod.POST)
// @RequestMapping(value = "/query", method = RequestMethod.PUT)
// @RequestMapping(value = "/query", method = RequestMethod.PATCH)
// @RequestMapping(value = "/query", method = RequestMethod.DELETE)
// @GetMapping("/query")
// @PostMapping("/query")
// @PutMapping("/query")
// @PatchMapping("/query")
// @DeleteMapping("/query")
SpringMVC 路径 传参
URL?param=value
接值
@RequestParam("param")
URL/abc/kkk
接值
请求URL
@RequestMapping("/loginOne/{param1}/{param2}")
参数接值
@PathVariable("param1") String abc, @PathVariable("param2") String kkk
页面发出请求
http://localhost:8080/loginOne/admin
controller 代码
@RequestMapping("/loginOne/{userName}")
public String loginOne(@PathVariable("userName") String userName){
System.out.println("userName = " + userName);
return "success";
}
封装 对象(json)
参数接值
@RequestBody
paramType:表示参数放在哪个地方
类型 | 解释 |
---|---|
header | 指该参数需在请求头传参, 请求参数的获取:@RequestHeader(代码中接收注解) |
query | 指该参数需在请求URL传参 , 请求参数的获取:@RequestParam(代码中接收注解) |
path | 指该参数为路径参数, (用于restful接口)–>请求参数的获取:@PathVariable(代码中接收注解) |
body | 指该参数需在请求JSON传参, 请求参数的获取:@RequestBody(代码中接收注解) |
form | (不常用) |
@GetMapping("getList")
@ApiOperation("列表查询接口")
@ApiImplicitParams({
@ApiImplicitParam(name = "pageNum", value = "当前页码,默认1", example = "1",
paramType = "query", dataType = "int", required = false),
@ApiImplicitParam(name = "pageSize", value = "每页显示条数,默认10", example = "10",
paramType = "query", dataType = "int", required = false)
})
public Result getList(
@RequestParam(value = "pageNum", required = false, defaultValue = "1")Integer pageNum,
@RequestParam(value = "pageSize", required = false, defaultValue = "10" )Integer pageSize) {
System.out.println("pageNum = " + pageNum);
System.out.println("pageSize = " + pageSize);
return Result.ok();
}
@GetMapping("delete/{id}")
@ApiOperation("删除接口")
@ApiImplicitParams({
@ApiImplicitParam(name = "id", value = "主键", example = "10086",
paramType = "path", dataType = "long" , required = true)
})
public Result delete(@PathVariable("id") Long id) {
System.out.println("id = " + id);
return Result.ok();
}
@PostMapping(value = "add")
@ApiOperation("添加接口")
@ApiImplicitParams({
@ApiImplicitParam(name = "userId", value = "用户主键", example = "10086",
paramType = "form", required = true),
@ApiImplicitParam(name = "userName", value = "用户名称", example = "王小二",
paramType = "form", required = true)
})
public Result add(SysUser user ) {
System.out.println("user = " + user);
return Result.ok();
}
@ApiOperation(value = "上传文件接口",notes = "上传文件接口")
@ApiImplicitParams({
@ApiImplicitParam(name = "userId",value = "用户ID",
paramType = "query",required = true,dataType = "int")
})
@PostMapping(value = "/uplode/one", headers = "content-type=multipart/form-data")
public Result uplode(HttpServletRequest request,@RequestParam(value = "userId", required = true) String userId,
@RequestParam(value = "file", required = true) MultipartFile file) {
System.out.println("file = " + file.getOriginalFilename());
return Result.ok().data(file.getOriginalFilename());
}
只能 bootstrap版主题 或者 postman 可以进行测试
@ApiOperation(value = "多文件上传",notes = "多文件上传")
@ApiImplicitParams({
@ApiImplicitParam(name = "files",value = "多个文件",paramType = "formData",allowMultiple=true, required = true, dataType = "file"),
@ApiImplicitParam(name = "userId",value = "用户ID",paramType = "query",required = true,dataType = "int")
})
@PostMapping(value = "/uplode/files", headers = "content-type=multipart/form-data")
public Result uplode(HttpServletRequest request,@RequestParam(value = "userId", required = true) String userId,
@RequestParam(value = "files", required = true) MultipartFile[] files) {
System.out.println("files[0] = " + files[0].getOriginalFilename());
return Result.ok();
}
指该参数需在请求JSON传参
只需要在参数前面加入注解@RequestBody即可. 但是一定要记住, 这个注解在参数里只能使用1次.
@PutMapping( value="/update", produces = {"application/json;charset=UTF-8"})
@ApiOperation(value = "更新数据接口", notes = "测试requestBody")
public Result update(@RequestBody SysUser user) {
System.out.println("user = " + user);
return Result.ok();
}
{ "userId":1, "userName":"王小二" }
@PutMapping( value="/update2", produces = {"application/json;charset=UTF-8"})
@ApiImplicitParams({
@ApiImplicitParam(paramType="body", name="userId", value="用户主键", dataTypeClass = Integer.class, required = true),
@ApiImplicitParam(paramType="body", name = "userName" , value = "账号" ,dataType = "string", example = "", required = false)
})
@ApiOperation(value = "更新数据接口2", notes = "测试requestBody")
public Result update2(HttpServletRequest request, Integer userId, String userName) throws IOException {
InputStream in = request.getInputStream();
System.out.println("userId = " + userId);
System.out.println("userName = " + userName);
return Result.ok();
}
{ "userId":1, "userName":"王小二" }
post请求中使用@modelAttribute接收参数,在swagger-ui文档中paramterType 是query
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
@ApiModel("用户描述")
@Data
public class SysUser implements Serializable {
private Integer userId;
@ApiModelProperty(hidden = true) //隐藏属性
private Integer userStatus;
@ApiModelProperty(value = "账号", required = true) //设置参数注释
private String userName;
}
@PostMapping("/edit")
@ApiOperation("修改接口")
public Result edit( @ApiParam(value="用户",required=true) @ModelAttribute SysUser user) {
System.out.println("user = " + user);
return Result.ok();
}
@DeleteMapping("/delsForArray")
@ApiOperation("基于数组删除")
@ApiImplicitParams({
})
public Result delsForArray(@RequestParam(value = "ids") @ApiParam(value = "删除Id数组")Integer[] ids) {
System.out.println("ids = " + Arrays.toString(ids));
return Result.ok();
}
@ApiOperation("基于List删除" )
@ApiImplicitParams({})
@DeleteMapping("/delsForList")
public Result save(@RequestParam(value = "idList") @ApiParam(value = "删除Id列表") List<Integer> idList) {
System.out.println("idList = " + idList);
return Result.ok();
}