1.背景
- 1.开发过程中大量nei需要录入,定义各种数据模型也很麻烦,尤其是当字段属性比较多的时候
- 2.当接口后期修改后,出入参其实已经发生了很大的变化,未能及时更新nei,导致nei数据不准,给后期维护造成困扰,同时,nei的复用率较低
- 3.开发自测不太方便,每次使用postman还得录入一堆的参数,效率低
3.效果
- controller代码写完,接口文档也随之生成,可以一键导出到nei,不用再次录入
- 实时更新,只要代码一更新,swagger实时更新,可以直接一键导入,更新nei
演示效果:
项目启动,打开网址:http://127.0.0.1:8080/swagger-ui.html
3.接入姿势
3.1引入依赖
maven依赖
<!--swagger-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
<exclusions>
<exclusion>
<groupId>io.swagger</groupId>
<artifactId>swagger-models</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-models</artifactId>
<version>1.5.22</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
gradle依赖
implementation('io.springfox:springfox-swagger2:2.9.2') {
exclude group: 'io.swagger', module: 'swagger-models'
}
implementation('io.springfox:springfox-swagger-ui:2.9.2')
implementation 'io.swagger:swagger-models:1.5.21'
3.2配置
下面提供三种方式,基础版(一般不需要任何鉴权的可以使用,满足绝大部分场景)、全局参数版(自动为每一个接口添加一个相同的参数)、鉴权版(提供token鉴权)
3.2.1基础版
package com.wupx.config;
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.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
@Configuration
@EnableSwagger2
public class Swagger2Configuration {
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
// swagger 文档扫描的包
.apis(RequestHandlerSelectors.basePackage("com.wupx.controller"))
.paths(PathSelectors.any())
.build();
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("测试接口列表")
.description("Swagger2 接口文档")
.version("v1.0.0")
.contact(new Contact("neteaxe", "https://www.icourse163.org", "11111@qq.com"))
.license("Apache License, Version 2.0")
.licenseUrl("http://www.apache.org/licenses/LICENSE-2.0.html")
.build();
}
}
3.2.2全局参数版
package com.wupx.config;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ParameterBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.schema.ModelRef;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
import java.sql.Timestamp;
import java.util.Collections;
@Configuration
@EnableSwagger2
public class SwaggerConfig {
@Bean
public Docket api(@Value("${super-students.swagger.enabled}") boolean enabled) {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(new ApiInfo(
"courseStudents",
"学生管理系统",
"2.0.0",
null,
null,
null,
null,
Collections.emptyList()
))
.enable(enabled)
.select()
.apis(RequestHandlerSelectors.any())
.paths(PathSelectors.any())
.build()
.directModelSubstitute(Timestamp.class, Long.class)
.globalOperationParameters(Lists.newArrayList(
new ParameterBuilder()
.name("_testAccount")
.description("测试账号(权限验证用)")
.modelRef(new ModelRef("string"))
.parameterType("query")
.required(true)
.defaultValue("stormluke1130@163.com")
.build()
))
.consumes(ImmutableSet.of("application/json"))
.produces(ImmutableSet.of("application/json"))
.useDefaultResponseMessages(false);
}
}
3.2.3鉴权版
package com.zjgsu.xxxy.config;
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.service.ApiKey;
import springfox.documentation.service.AuthorizationScope;
import springfox.documentation.service.SecurityReference;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.contexts.SecurityContext;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
import java.util.ArrayList;
import java.util.List;
@Configuration
@EnableSwagger2
public class Swagger2Config {
@Bean
public Docket createRestApi(){
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
//为当前包下controller生成API文档
.apis(RequestHandlerSelectors.basePackage("com.zjgsu.xxxy.controller"))
.paths(PathSelectors.any())
.build()
//添加登录认证
.securitySchemes(securitySchemes())
.securityContexts(securityContexts());
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("api swagger document")
.description("前后端联调swagger api 文档")
.version("1.0.1")
.build();
}
private List<ApiKey> securitySchemes() {
//设置请求头信息
List<ApiKey> result = new ArrayList<>();
ApiKey apiKey = new ApiKey("Authorization", "Token", "header");
result.add(apiKey);
return result;
}
private List<SecurityContext> securityContexts() {
//设置需要登录认证的路径
List<SecurityContext> result = new ArrayList<>();
result.add(getContextByPath("/*/.*"));
return result;
}
private SecurityContext getContextByPath(String pathRegex){
return SecurityContext.builder()
.securityReferences(defaultAuth())
.forPaths(PathSelectors.regex(pathRegex))
.build();
}
private List<SecurityReference> defaultAuth() {
List<SecurityReference> result = new ArrayList<>();
AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
authorizationScopes[0] = authorizationScope;
result.add(new SecurityReference("Authorization", authorizationScopes));
return result;
}
}
3.3NEI导入swagger
点击打开,保存这个json文件
直接在nei中选择swagger导入
注意点:
1.导入的时候可以选择导入哪些接口,不想导入的可以不勾选
2.如果接口过多,勾选比较麻烦,可以在 类 或 方法 上面加入@ApiIgnore 注解,这样swagger扫描的时候就会将其忽略
3.4核心注解使用
@Api 类名
作用于类上。控制整个类生成接口信息的内容。
tags:类的名称。可以有多个值,多个值表示多个副本
@RestController
@RequestMapping(value = "/person")
@Api(tags = "人员控制器")
public class PersonController {
}
@ApiOperation 方法名
作用于方法上,对方法进行总体描述。
value:接口描述
@PostMapping("/postReq")
@ApiOperation(value = "接口描述")
public String postReq(){
return "postReq";
}
@ApiParam 单个入参说明注释
写在方法参数前面。用于对参数进行描述或说明是否为必填项等说明。
value:参数描述
@PostMapping("/postReq")
@ApiOperation(value = "接口描述")
public String postReq(
@ApiParam(value = "新增用户时提供的姓名") String name,
@ApiParam(value = "新增用户时提供的地址")String address){
return "postReq";
}
@ApiModel 数据模型类注释
作用于类上,主要应用于实体类Model,也就是说整个注解一般都是写在实体类上。
description:描述
@ApiModelProperty 数据模型属性注释
可以用在方法或属性上。用于当对象作为参数时定义这个字段的内容。
value:描述
name:重写属性名
required:是否是必须的
example:示例内容
hidden:是否隐藏
/**
* 这是一些返回或者请求的数据体,如果想要swagger中看到每个字段的注释
* 或者
* 想要在导入NEI的时候自动加上每个字段的注释
* 需要在属性上加入@ApiModelProperty的注解
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@ApiModel(description = "测试DTO")
public class DemoDto {
@ApiModelProperty(value = "字段一")
private String id;
@ApiModelProperty(value = "字段二")
private String name;
}
@ApiIgnore 忽略方法或者类
用于方法或类或参数上,表示整个方法或类被忽略。
4.代码示例