每個服務都有自己的介面,通過Swagger來管理介面文件。在服務較多的時候我們希望有一個統一的入口來進行文件的檢視,這個時候可以在zuul中進行文件的聚合顯示。
下面來看下具體的整合步驟以及採坑記錄。Cloud版本:Finchley.SR2, Boot版本:2.0.6
加入Swagger的依賴:
<!-- Swagger -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
複製程式碼
增加聚合程式碼:
@EnableSwagger2
@Component
@Primary
public class DocumentationConfig implements SwaggerResourcesProvider {
@Autowired
private DiscoveryClient discoveryClient;
@Value("${spring.application.name}")
private String applicationName;
@Override
public List<SwaggerResource> get() {
List<SwaggerResource> resources = new ArrayList<>();
// 排除自身,將其他的服務新增進去
discoveryClient.getServices().stream().filter(s -> !s.equals(applicationName)).forEach(name -> {
resources.add(swaggerResource(name, "/" + name + "/v2/api-docs", "2.0"));
});
return resources;
}
private SwaggerResource swaggerResource(String name, String location, String version) {
SwaggerResource swaggerResource = new SwaggerResource();
swaggerResource.setName(name);
swaggerResource.setLocation(location);
swaggerResource.setSwaggerVersion(version);
return swaggerResource;
}
}
複製程式碼
我這邊直接用DiscoveryClient 獲取服務列表進行聚合,當然你也可以固定寫上你的服務列表,或者對接配置中心都可以。
其實除了DiscoveryClient 獲取服務列表,我們也可以根據zuul中路由的配置來獲取,可以使用RouteLocator 來操作。方式很多,用哪種都可以。
正常情況下上面的整合步驟沒任何問題,今天有朋友在星球提問,說自己的業務服務加了context-path,Zull中聚合的Swagger文件無法顯示,因為路徑錯了,少了配置的context-path。效果如下圖:
也就是說在進行資源新增的時候需要將context-path加進去,也就是需要改動下面的程式碼:
resources.add(swaggerResource(name, "/" + name + "/v2/api-docs", "2.0"));
複製程式碼
最簡單的就是加一個配置,配置好每個服務對應的context-path,這樣在這裡直接拼接上去就完事了。但這樣顯得有點低端呀,哈哈。
DiscoveryClient 是很強大的,我們可以用DiscoveryClient 來獲取Eureka中的資訊,此時我有了一個想法,那就是業務服務將自身的context-path放入Eureka的metadata-map中,然後Zuul中聚合的時候從metadata-map中獲取context-path就行了。
業務服務加配置:
server.servlet.context-path=/yinjihuan
eureka.instance.metadata-map.context-path=${server.servlet.context-path}
複製程式碼
Zull中改造:
@Override
public List<SwaggerResource> get() {
List<SwaggerResource> resources = new ArrayList<>();
// 排除自身,將其他的服務新增進去
discoveryClient.getServices().stream().filter(s -> !s.equals(applicationName)).forEach(name -> {
Optional<ServiceInstance> instanceOptional = discoveryClient.getInstances(name).stream().findFirst();
if (instanceOptional.isPresent() && instanceOptional.get().getMetadata().containsKey("context-path")) {
String contexPath = instanceOptional.get().getMetadata().get("context-path");
resources.add(swaggerResource(name, "/" + name + contexPath + "/v2/api-docs", "2.0"));
} else {
resources.add(swaggerResource(name, "/" + name + "/v2/api-docs", "2.0"));
}
});
return resources;
}
複製程式碼
這樣就完美解決了增加context-path導致的問題,加入星球我們一起學習吧。