这是一个自动化生成接口文档的工具,非常好用!

它使用起来非常简单呀,加些注释就可以了,这里展示它的使用过程!以后再写项目的时候,直接加上它就行了。

这里直接用最新的Swagger3好了。

导入依赖

<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-boot-starter</artifactId>
    <version>3.0.0</version>
    </dependency>

编写配置类

开启Swagger,则需要在该配置类上加上@EnableOpenApi

@EnableOpenApi
@Configuration
public class Swagger3Config implements WebMvcConfigurer {
	//...
}	

它有一个叫做Docket,把它注册进去。

@Bean
public Docket docket() {
    //返回文档摘要信息
    return new Docket(DocumentationType.OAS_30)
            .apiInfo(apiInfo());
}

点进去Docket的源码(如下段),会发现它让你选文档类型,现在我们选的就是OAS_30

public static final DocumentationType SWAGGER_12 = new DocumentationType("swagger", "1.2");
public static final DocumentationType SWAGGER_2 = new DocumentationType("swagger", "2.0");
public static final DocumentationType OAS_30 = new DocumentationType("openApi", "3.0");

还可以配置一些文档信息,它是在apiInfo()下面的,所以接下来我们需要创建一个实例,具体的代码如下,其实它源码里面也有列举,我们跟着改改就行了。
(当然,不配置的话也可以的,因为有默认值。)

image.png
这里加个小彩蛋吧,多人协作的时候,可以在docket实例那里再.groupName("xxx"),这样增加一个组名,这样就能划分小组嘛,每个人一个小组,这样就不会乱。

当然,要这样做的话,你需要多个Docket实例,不过也就写个@bean的事。只需要点击右上角的下拉框就能看到它的分组。

运行

现在可以看到结果了。

访问地址:http://localhost:8080/swagger-ui/index.html

PS:这个也可以改,在application.yml中可以作如下配置:

springfox:
  documentation:
    swagger-ui:
      base-url: /doc

然而它还是很鸡肋,因为改了之后就变成了http://localhost:8080/doc/swagger-ui/index.html,更长了……我希望它能变短一些,这样就方便访问。

/**
 * Base url for swagger-ui. For e.g. setting it to /documentation will put swagger-ui
 * at /documentation/swagger-ui/index.html
 */
private String baseUrl = "";

image.png

嗯。。非常简洁,现在是啥东西都没写,只有一个默认的error页面,还有一些ModelAndView,下面开始再写些东西,看看它的作用。

配置扫描接口

在我们准备写接口前,我们需要让swagger知道我们的接口、实体类放在哪,它才能扫描到嘛。

要配置这些信息,还得回到docket中。
image.png

apis()

这里只是展示一下用法吧,比如

  • 想要扫描到我controller下的接口,可以:

.apis(RequestHandlerSelectors.basePackage("com.tanjiaming99.controller"))

  • 想要扫描到上添加@RestController注解的接口

.apis(RequestHandlerSelectors.withClassAnnotation(RestController.class))

  • 想要扫描到方法上添加@GetMapping注解的接口

.apis(RequestHandlerSelectors.withMethodAnnotation(GetMapping.class))

  • 扫描所有

.apis(RequestHandlerSelectors.any())

  • 不扫描

.apis(RequestHandlerSelectors.any())

用的话,就是前面那些常用了,可以直接配一个大的路径,然后让它自己扫描里面的……

    @Bean
    public Docket docket() {
        //返回文档摘要信息
        return new Docket(DocumentationType.OAS_30)
                .apiInfo(apiInfo())
                .select()
//                .apis(RequestHandlerSelectors.basePackage("com.tanjiaming99.controller"))
//                .apis(RequestHandlerSelectors.withClassAnnotation(RestController.class))
//                .apis(RequestHandlerSelectors.withMethodAnnotation(GetMapping.class))
//                .apis(RequestHandlerSelectors.any())
                .apis(RequestHandlerSelectors.none())
                .build();
    }

paths()

这个是路径扫描,比如只有经过/user这个路径的才会被扫描进来。
这里可以写的就这几个,看看就懂了。

image.png


把所有的都配成any(),就是扫描所有的接口or模型,然后就开始模拟开发吧。

使用

终于来到激动人心的时候了。
其实前面的啥啥配置那些,只要写好一次,以后就不用动了,或者需要有什么变动的时候再改改就行(比如多环境配置、多用户组等等……)

下面这些才是使用的核心(但是还是挺简单的,不难,就那么几个接口。。。)

观察,然后模仿就行,以后有更加灵活多变的用法的时候再更新。

  • 实体类,可以理解为pojo、entity、model、dto、vo……
    • @ApiModel():作用在模型上。
    • @ApiModelProperty():作用在模型的属性上
@ApiModel("用户实体类")
@AllArgsConstructor
public class User {
    @ApiModelProperty("用户名")
    private String username;

    @ApiModelProperty("用户密码")
    private String password;
}
  • 接口,可以理解为controller……
    • @Api():作用在模块类上,可以简单地就用在controller上
    • @ApiOperation():作用在模块类上的各个方法上,就是接口方法了,一个一个地请求。
@Api(tags = "UserController模块")
@RestController
public class UserController {

    @ApiOperation("/user接口")
    @GetMapping("/user")
    public User user(@ApiParam(required = true, value = "用户名") String name) {
        return new User(name, "这是一个密码");
    }
}

然后运行,就如下图所示。

image.pngimage.png

重点是,它除了可以对接接口参数外,还能在上面测试!!!
(Postman是什么,我不认识它了【x】)
直接在上面写参数,然后确认,就能测试到你这个接口是否正确,非常方便团队开发,前后端交接再也没有问题了~
image.png

小补充

我百度搜资料的时候,发现它还有一些高级用法,比如对接口进行分类啊、对开发人员进行分组这些,这个应该也很快会遇到了,不用急……

下面有一个多参数标识的东西,我感觉还挺有意思,摘录一段。

@GetMapping("/test")
public String testParams(@RequestParam Map<String, String> map) {
    StringBuilder sb = new StringBuilder();
    map.entrySet().stream().map(s -> sb.append(s.getKey()).append(" ").append(s.getValue()).append("\r\n")).toArray();
    return sb.toString();
}

需要前端传一个map,这个就难办了,因为不知道你这个map需要什么内容,以前的话可能是协商好文档,但是这难免会有差错。

image20210731153829266.png

(这些都是什么鬼???)

然后呢,我们加一点小细节。

@ApiOperation("测试一下多参数")
@ApiImplicitParams({
        @ApiImplicitParam(name = "username", value = "用户名", dataTypeClass = String.class, paramType = "query", example = "张三"),
        @ApiImplicitParam(name = "password", value = "用户密码", dataTypeClass = String.class, paramType = "query", example = "12345"),
        @ApiImplicitParam(name = "phone", value = "手机号", dataTypeClass = String.class, paramType = "query", example = "13523338888"),
        @ApiImplicitParam(name = "comment", value = "评论", dataTypeClass = String.class, paramType = "query", example = "这是一只张三。")
})
@GetMapping("/test")
public String testParams(@RequestParam @ApiIgnore Map<String, String> map) {
    StringBuilder sb = new StringBuilder();
    map.entrySet().stream().map(s -> sb.append(s.getKey()).append(" ").append(s.getValue()).append("\r\n")).toArray();
    System.out.println(sb.toString());
    return sb.toString();
}

结果:

image.png

这样就非常容易协商了,这也是这个文档的魔力所在呀。

下面摘录一下,大概就是这样了。

@ApiImplicitParams:用在请求的方法上,表示一组参数说明
@ApiImplicitParam:用在@ApiImplicitParams注解中,指定一个请求参数的各个方面
name:参数名
value:参数的汉字说明、解释
required:参数是否必须传
paramType:参数放在哪个地方
· header --> 请求参数的获取:@RequestHeader
· query --> 请求参数的获取:@RequestParam
· path(用于restful接口)--> 请求参数的获取:@PathVariable
· div(不常用)
· form(不常用)
dataType:参数类型,默认String,其它值dataType="Integer"
defaultValue:参数的默认值

发现的小bug

这里写一个小bug,就是刚刚配置完之后,发现实体类中居然是看不到东西,把下面那张图的红框内容去掉的样子就是。
image.png

不知道是什么原因,百度了说什么名字大小写不规范,其实我这个很规范啊,也没啥错误的。

然后我改了改在实体类上的这个
@ApiModel(value = "用户实体类", description = "存的是与数据库对应的用户实体类对象")

一开始把它删了,它那里就变成了User(而不是用户实体类),然后里面的参数出来了!!!我以为是我没有指定字段(像上面那样显式地写value="xxx"),结果发现,我再把它加回去的时候,它又正常了……
然后我又清清缓存,它还是这样……
所以我就删了它,然后再加上,它就正常了,这不就跟“重启一下”没啥差别吗,汗。