Swagger介绍及使用
Swagger介绍及使用
解决前后端联调接口文档问题,当项目更新时,接口文档更新不上,会导致联调出现问题,好的接口文档会加快开发效率,加快前后端联调的速度,当接口更新时,接口文档也能实时更新
目前Swagger在Sping中更名为SpringFox
Swagger Codegen: 通过Codegen 可以将描述文件生成html格式和cwiki形式的接口文档,同时也能生成多钟语言的服务端和客户端的代码。支持通过jar包,docker,node等方式在本地化执行生成。也可以在后面的Swagger Editor中在线生成。
Swagger UI:提供了一个可视化的UI页面展示描述文件。接口的调用方、测试、项目经理等都可以在该页面中对相关接口进行查阅和做一些简单的接口请求。该项目支持在线导入描述文件和本地部署UI项目。
Swagger Editor: 类似于markendown编辑器的编辑Swagger描述文件的编辑器,该编辑支持实时预览描述文件的更新效果。也提供了在线编辑器和本地部署编辑器两种方式。
Swagger Inspector: 感觉和postman差不多,是一个可以对接口进行测试的在线版的postman。比在Swagger UI里面做接口请求,会返回更多的信息,也会保存你请求的实际请求参数等数据。
Swagger Hub:集成了上面所有项目的各个功能,你可以以项目和版本为单位,将你的描述文件上传到Swagger Hub中。在Swagger Hub中可以完成上面项目的所有工作,需要注册账号,分免费版和收费版。
Springfox Swagger: Spring 基于swagger规范,可以将基于SpringMVC和Spring Boot项目的项目代码,自动生成JSON格式的描述文件。本身不是属于Swagger官网提供的,在这里列出来做个说明,方便后面作一个使用的展开。
总结
其实归根到底,使用Swagger,就是把相关的信息存储在它定义的描述文件里面(yml或json格式),再通过维护这个描述文件可以去更新接口文档,以及生成各端代码。而Springfox-swagger,则可以通过扫描代码去生成这个描述文件,连描述文件都不需要再去维护了。所有的信息,都在代码里面了。代码即接口文档,接口文档即代码。
链接:https://www.jianshu.com/p/349e130e40d5
在pom文件中引入swagger的pom和swagger-ui的jar包
示例
<dependency>
//Swagger核心jar
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
//SwaggerUI界面
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
使用springfox-swagger-ui的界面
国人开发适合自己人用的增强UI界面
文档地址
pom
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
<version>2.0.2</version>
</dependency>
经过测试发现使用knife4j中创建多个分支后去掉默认分支,就是在创建docket时不指定groupName,访问会发生Knife4j文档请求异常经分析,knife4j打开swagger页面后先进行访问default的分支,因为我们没有创建,所以会报异常问题,如果想解决这个问题创建defaultDocket,另一中方式就是指定访问swagger时访问第一个Docket。。。。。。。。。。。。。。。。。。。springfox-swagger-ui不会出现这个问题
关于使用
添加完相关依赖后需要进行对我们的接口进行配置,创建SwaggerConfig的Java文件进行对我的项目进行相关配置
示例:
@Configuration
@EnableSwagger2
public class SwaggerConfig {
@Bean
public Docket createTestApi() {
return new Docket(DocumentationType.SWAGGER_2).groupName("sdd")
.apiInfo(getTestApiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("com.tang.controller"))
.paths(PathSelectors.ant("/test/*"))
.build();
}
private ApiInfo getTestApiInfo(){
return new ApiInfoBuilder().title("测试Controller").description("关于测试的方法").license("1.0.0").licenseUrl("www.baidu.com").build();
}
@Bean
public Docket createDefaultDocker() {
Ordering<ApiDescription> ordering = new Ordering<ApiDescription>() {
@Override
public int compare(ApiDescription apiDescription, ApiDescription t1) {
return 0;
}
};
return new Docket(DocumentationType.SWAGGER_2).groupName("ddddd").apiDescriptionOrdering()
.apiInfo(getDefaultDocker())
.select()
.apis(RequestHandlerSelectors.basePackage("com.tang.controller"))
.paths(PathSelectors.ant("/test/*"))
.build();
}
private ApiInfo getDefaultDocker(){
return new ApiInfoBuilder().title("defaultController").description("关于测试的方法").license("1.0.0").licenseUrl("www.baidu.com").build();
}
}
Docket相当于一个接口分支,我们将指定的接口归类到该分支下,创建一个Docket相当于一个类
ApiInfo对象,该对象用来描述Docket的详细信息,如
ApiInfo对象的创建
new ApiInfoBuilder()
//设置标题
.title("测试Controller")
//设置描述
.description("关于测试的方法").
//设置版本号
license("1.0.0").
//设置联系人
contact(new Contact("汤梦玮","www.baidu.com","15634486605")).
//设置版本相关地址
licenseUrl("www.baidu.com")
//不知道
.termsOfServiceUrl("test")
.build();
关于创建Docket对象的相关操作
return new Docket(DocumentationType.SWAGGER_2)
//创建接口分支名称
.groupName("sdd")
//维护Docket的详情信息
.apiInfo(getTestApiInfo())
//执行接口筛选
.select()
//扫描指定包
.apis(RequestHandlerSelectors.basePackage("com.tang.controller"))
//指定路径
.paths(PathSelectors.ant("/test/*"))
//创建
.build();
关于处接口添加的注解
@RestController
@RequestMapping("/test2")
//对当前Controller对象的描述
@Api(tags = "Test2",value = "Test2的接口")
public class Test2Controller {
//对当前接口的描述,如果添加了tag会在当前的接口分组下出现重复的接口
@ApiOperation("test2tttt")
@GetMapping("/t2")
//该注解是对请求参数的描述
@ApiImplicitParams({
@ApiImplicitParam(name = "name",value = "名字"),
@ApiImplicitParam(name = "age",value = "年龄")
})
public String test2(@RequestParam String name,@RequestParam String age){
return "Test2";
}
@ApiOperation("ApiModleProperties测试")
@PostMapping("/t2-2")
public Sutdent test2_2(@RequestBody Sutdent sutdent){
return sutdent;
}
}
关于Post请求需要对请求对象进行解释的注解,该情况可以更形象的去描述请求体的具体含义
//该注解为对对象的描述
@ApiModel(value = "学生")
public class Sutdent implements Serializable {
private static final long serialVersionUID = 2490174377334991255L;
//该注解为对对象属性的描述
//name指定的时属性名称,value指定的时属性含义
@ApiModelProperty(name = "name",value = "姓名")
private String name;
@ApiModelProperty(name = "age",value = "年龄")
private String age;
}
关于权限认证:在请求头中传递添加heard参数
@Bean
public Docket createTestApi() {
return new Docket(DocumentationType.SWAGGER_2).groupName("sdd")
.apiInfo(getTestApiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("com.tang.controller"))
.paths(PathSelectors.ant("/test/*"))
.build().securitySchemes(securitySchemes()).securityContexts(securityContexts());
}
private List<SecurityContext> securityContexts() {
List<SecurityContext> securityContexts=new ArrayList<>();
securityContexts.add(
SecurityContext.builder()
.securityReferences(defaultAuth())
.forPaths(PathSelectors.regex("^(?!auth).*$"))
.build());
return securityContexts;
}
List<SecurityReference> defaultAuth() {
AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
authorizationScopes[0] = authorizationScope;
List<SecurityReference> securityReferences=new ArrayList<>();
securityReferences.add(new SecurityReference("Authorization", authorizationScopes));
return securityReferences;
}
private List<ApiKey> securitySchemes() {
List<ApiKey> apiKeys = new ArrayList<>();
apiKeys.add(new ApiKey("token", "token", "header"));
return apiKeys;
}
关于线上与线下的文档暴露问题
目前又两种方式在不同的环境中将创建Docket时对Docket的属性进行一系列的设置
第一种方式
return new Docket(DocumentationType.SWAGGER_2).groupName("ddddd")
.apiInfo(getDefaultDocker())
//将Docket关闭
.enable(false)
第二种方式
new Docket(DocumentationType.SWAGGER_2).groupName("sdd")
.apiInfo(getTestApiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("com.tang.controller"))
//指定路径设置为都不生效,将所有接口路径都关闭
.paths(PathSelectors.none())
下一篇: 安装torch0.4.1的神坑