为什么要统一管理接口文档?
在一般的web项目开发中,如果是前后端分离项目的话,那么肯定会需要一份具体的接口文档,方便前端开发人员在不知道接口的具体地址、参数、返回值的情况下查看,那么这个时候就有问题了,后台的人员一般都是抗拒写文档的,写文档这辈子是不可能的了,所以就衍生出了Swagger这种生成文档的框架。而且Swagger的集成方式也能让大多数开发人员接受,所以很多开发团队都习惯使用Swagger生成所需的接口文档,一般的单项目中集成Swagger使用和查看文档都特别简单,因为一个项目顶多也就一个接口文档,那么如果是用在Cloud中呢,生产者的接口文档该怎么处理?不同生产者的接口文档地址分别是什么?查看不同接口的文档还需要重新切换各自的网址?这个时候就需要一个大哥站出来统一一下各个生产者所生成的接口文档了。
具体步骤:
1. 接口生产者配置
接口生产者的@Api注释部分按正常写就行了,例
需要注意的是SwaggerConfig.java的配置,要在原来的基础上改造成下面的样子,其中注意ApiInfo 中的contact要与其他模块和管理者的配置保持一致。
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
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.swagger.web.UiConfiguration;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
@Configuration
@EnableSwagger2
public class SwaggerConfig {
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("com.base.service"))
//basePage就是具体要扫描的包,有swagger注解的方法就生成到文档里面去
.apis(RequestHandlerSelectors.withClassAnnotation(Api.class))
.apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
.paths(PathSelectors.any())
.build();
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("测试模块api")
.description("测试模块接口文档说明")
//contact配置需要与其他模块和管理者保持一致
.contact(new Contact("wdq", "", ""))
.version("1.0")
.build();
}
@Bean
public UiConfiguration uiConfig() {
return new UiConfiguration(null, "list", "alpha", "schema",
UiConfiguration.Constants.DEFAULT_SUBMIT_METHODS, false, true, 60000L);
}
}
2. 接口管理者配置
接口管理者的配置一般是写在zuul的服务上,步骤呢首先在pom需要引入两个jar
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<!--文档页面使用bootstrap风格ui-->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>swagger-bootstrap-ui</artifactId>
<version>1.8.7</version>
</dependency>
然后配置文件SwaggerConfig.java
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
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 SwaggerConfig {
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo());
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("说明文档")
.description("接口说明文档")
.termsOfServiceUrl("")
//注意contact需要与提供者的配置一致
.contact(new Contact("wdq","",""))
.version("1.0")
.build();
}
}
和 SwaggerResourcesProvider.java,后者的配置主要是在请求各个模块的文档时对请求路径重新组装,起到转发的作用
import org.springframework.cloud.netflix.zuul.filters.Route;
import org.springframework.cloud.netflix.zuul.filters.RouteLocator;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;
import springfox.documentation.swagger.web.SwaggerResource;
import springfox.documentation.swagger.web.SwaggerResourcesProvider;
import java.util.ArrayList;
import java.util.List;
/**
* 主要就是在请求各个模块的文档时对请求路径重新组装,起到转发的作用
*/
@Component
@Primary
public class GatewaySwaggerResourcesProvider implements SwaggerResourcesProvider {
private final RouteLocator routeLocator;
public GatewaySwaggerResourcesProvider(RouteLocator routeLocator) {
this.routeLocator = routeLocator;
}
@Override
public List<SwaggerResource> get() {
List<SwaggerResource> resources = new ArrayList<>();
List<Route> routes = routeLocator.getRoutes();
for (Route route:routes) {
resources.add(swaggerResource(route.getId(), route.getFullPath().replace("**", "v2/api-docs")));
}
return resources;
}
private SwaggerResource swaggerResource(String name, String location) {
SwaggerResource swaggerResource = new SwaggerResource();
swaggerResource.setName(name);
swaggerResource.setLocation(location);
swaggerResource.setSwaggerVersion("2.0");
return swaggerResource;
}
}
到这最基本的配置就已经完成了,紧接着访问文档中心看一下效果如何
额,确实比原始的ui好看多了,在这个页面的左上角可以查看到生态里所有的服务id,选择对应的服务就能查看对应的接口文档了,差不多就是想要的效果了,在原来的基础上还有了几个实用的小功能,比如离线文档、全局参数配置、实体类说明的统一展示等。