Swagger2

一, 什么是Swagger? 能干什么?

Swagger 是一个规范和完整的框架,用于生成、描述、调用和可视化 RESTful 风格的 Web 服务的接口文档。

目前的项目基本都是前后端分离,后端为前端提供接口的同时,还需同时提供接口的说明文档。但我们的代码总是会根据实际情况来实时更新,这个时候有可能会忘记更新接口的说明文档,造成一些不必要的问题。

用人话说,swagger就是帮你写接口说明文档的。

1, 前后端分离的项目

前后端分离式开发
在这里插入图片描述

纯粹后端的java开发人员,不编写页面代码, 只需要写接口( 这里的接口不是java中的interface )

在SpringMVC的控制层Controller类的方法里, 不写转页( 包括 内部转, 重定向 ),

都是通过 @ResponseBody, 返回JSON格式的数据

所以 Controller 类上的注解由@Controller, 改为 @RestController ( @Controller + @ResponseBody )

2, 什么是接口

​ 接口就是制定一个协议, 给前端开发人员调用后端功能的参考. 可能包括的内容 :

协议介绍
http 还是 httpshttps请求需要SSL证书
请求名url 或者 uri
请求方式get, post, put, delete等等
参数列表包括类型和传值方式
返回类型返回格式, 状态码, 错误消息, 数据

3, 举例说明

例如:

模块名称: 用户登录

请求方式: post

请求名: /login/auth

参数

参数名类型说明是否必须
usernameString(20)用户名
passwordString(20)密码
rememberInterger记住我, 1-记住,0-不记住, 默认按0处理

返回:

{
    code: 200,
    msg: 'success',
    data: {
        userId: 1,
        userName: 王小二,
        sex: 1
    }
}

或者

{
    code: 1001,
    msg: '用户名不能为空',
    data: null
}

**如果是由后端人员来维护这些信息, 有个非常大的缺点, **

就是如果对这个方法做了修改, 例如添加了一个新的参数, 则需要修改这个接口文档.

基于这个缺点, 诞生了一个技术, 接口文档自动生成工具-swagger

即, 整个接口文档内容, 不需要手动编写了, 而是通过程序自动生成

4, 返回JSON格式



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 <T>
     * @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: {} 	//数据
}

二, swagger2的使用

1, 引入依赖包

<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>
    <exclusions>
        <exclusion>
            <groupId>io.swagger</groupId>
            <artifactId>swagger-annotations</artifactId>
        </exclusion>
        <exclusion>
            <groupId>io.swagger</groupId>
            <artifactId>swagger-models</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>io.swagger</groupId>
    <artifactId>swagger-annotations</artifactId>
    <version>1.5.21</version>
</dependency>
<dependency>
    <groupId>io.swagger</groupId>
    <artifactId>swagger-models</artifactId>
    <version>1.5.21</version>
</dependency>

2, 加入Swagger2的配置类

主要配置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的同级包或者子包里, 否则不识别

3, 开启swagger2, 添加下面的注解到全局配置类上(

例如 : 启动类或者当前配置类

@EnableSwagger2

三, 换主题

1, 默认界面的请求路径

/swagger-ui.html

2, layer主题

<dependency>
    <groupId>com.github.caspar-chen</groupId>
    <artifactId>swagger-ui-layer</artifactId>
    <version>1.1.3</version>
</dependency>

请求路径

/docs.html

3, bootstrap版主题

<dependency>
    <groupId>com.github.xiaoymin</groupId>
    <artifactId>swagger-bootstrap-ui</artifactId>
    <version>1.9.6</version>
</dependency>

请求路径

/doc.html

四, 使用Swagger2的注解

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的注解只是给你的类, 方法, 参数, 属性添加注释而已.

1, 给控制层添加注释

@Api(tags = "用户管理")

2, 控制层的方法添加中文注释

// @ApiOperation(value = "方法名称", tags = "分组标记-与 @Api的tags属性对应", notes = "方法说明")
@ApiOperation("用户登录1")

3,给参数加注释

@ApiImplicitParams({
       @ApiImplicitParam(name = "userName", value = "账号", required = true)
})

4, 隐藏一个参数, 用@ApiIgnore

5, 添加完成

@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();
    }
}

这样可以打开浏览器进行

6, 给类里的属性添加注释

6.1 给类加一个注解
@ApiModel
public class SysUser implements Serializable {}
6.2 给属性添加注解
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;

}

五, RestFul风格

0, RESTFUL是一种网络应用程序的设计风格和开发方式

REST(英文:Representational State Transfer,简称REST)描述了一个架构样式的网络系统,比如 web 应用程序。

通常 get 查询 post 添加 put/patch 修改 delete 删除

1, 选择请求方式

在接口系统里, 不要只写@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")

2.1, 传统方式接值 方式

SpringMVC 路径 传参

URL?param=value  

接值

@RequestParam("param")

2.2, 路径传参

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";
    }

2.3, 对象传参

封装 对象(json)

参数接值

@RequestBody

六, 参数类型说明

paramType:表示参数放在哪个地方

类型解释
header指该参数需在请求头传参, 请求参数的获取:@RequestHeader(代码中接收注解)
query指该参数需在请求URL传参 , 请求参数的获取:@RequestParam(代码中接收注解)
path指该参数为路径参数, (用于restful接口)–>请求参数的获取:@PathVariable(代码中接收注解)
body指该参数需在请求JSON传参, 请求参数的获取:@RequestBody(代码中接收注解)
form(不常用)

1, query 类型

    @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();
    }

2, path 类型

    @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();
    }

3, form 类型 (1)

  @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();
    }

4, form 类型 (2) 带文件上传

4.1,上传单一文件
@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());
    }
4.2,上传多个文件

只能 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();
    }

5, body参数 (1)

指该参数需在请求JSON传参

5.1, 接值

只需要在参数前面加入注解@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();
    }
5.2, 传值
{ "userId":1, "userName":"王小二" }

在这里插入图片描述

6, body参数 (2)

6.1, 接值

    @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();
    }

6.2, 传值
{ "userId":1, "userName":"王小二" }

在这里插入图片描述

7, 通过 @ModelAttribute 接值

post请求中使用@modelAttribute接收参数,在swagger-ui文档中paramterType 是query

7.1, 实体类加注解
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;
}

7.2, controller中接值

    @PostMapping("/edit")
    @ApiOperation("修改接口")
    public Result edit( @ApiParam(value="用户",required=true) @ModelAttribute  SysUser user) {
        System.out.println("user = " + user);

        return Result.ok();
    }

7.3, 传值

在这里插入图片描述

8, 传递集合

8.1, 通过Array数组 controller中接值
	@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();
    }
8.2, 通过List controller中接值
    @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();
    }
8.3, 传值 通过 , 分隔

在这里插入图片描述

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐