场景
当微服务中集成了swagger时,gateway中的过滤器也会对其进行过滤,经常会应该一些检验规则导致无法访问。
我这是增加了服务的权限校验,导致无法访问swagger相应路径,虽然增加了免校验规则,但由于相关页面较多,这种方式显得较为笨重。
PS:filter中的忽略规则自行处理。可参考SpringCloud:Gateway网关中自定义过滤器
方法1:忽略路径
将下列路径跳过校验即可访问swagger的资源。
token:
rules:
ignore: #需要过滤的路径
- /**/swagger-ui.html
- /**/swagger-resources/**
- /**/swagger-resources
- /**/v2/api-docs
- /**/swagger-resources/configuration/ui
方法2: 聚合显示
在gateway中增加swagger,集成相应的接口
- 引入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>
- 重写swagger获取服务源的get方法
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Component;
import springfox.documentation.swagger.web.SwaggerResource;
import springfox.documentation.swagger.web.SwaggerResourcesProvider;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* @description: 获取具体服务apidocs
* @author: lizz
* @date: 2020/4/28 11:01
*/
@Component
public class GwSwaggerResourceProvider implements SwaggerResourcesProvider {
/**
* swagger2默认的url后缀
*/
private static final String SWAGGER2URL = "/v2/api-docs";
/**
* 网关应用名称
* 配置集成的服务,名称与gateway中route的Path一致,用于拼接路径访问后端服务的swagger路径
* 如:swagger.serivces = rider,user
*/
@Value("${swagger.serivces}")
private List<String> swaggerServices;
@Override
public List<SwaggerResource> get() {
List<SwaggerResource> resources = new ArrayList<>();
List<String> routeHosts = new ArrayList<>();
// 记录已经添加过的server,存在同一个应用注册了多个服务在nacos上
Set<String> dealed = new HashSet<>();
swaggerServices.forEach(instance -> {
// 拼接url,样式为/serviceId/v2/api-info,当网关调用这个接口时,会自动通过负载均衡寻找对应的主机
String url = "/swagger/" + instance + SWAGGER2URL;
if (!dealed.contains(url)) {
dealed.add(url);
SwaggerResource swaggerResource = new SwaggerResource();
swaggerResource.setUrl(url);
swaggerResource.setName(instance);
resources.add(swaggerResource);
}
});
return resources;
}
}
- 重写swagger的数据接口
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Profile;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import springfox.documentation.swagger.web.*;
import java.util.List;
/**
* @description: swagger访问页面
* 限制dev和test环境下访问
* @author: lizz
* @date: 2020/4/28 11:02
*/
@RestController
@RequestMapping("/swagger-resources")
@Profile({"dev","test"})
public class SwaggerResourceController {
private GwSwaggerResourceProvider swaggerResourceProvider;
@Autowired
public SwaggerResourceController(GwSwaggerResourceProvider swaggerResourceProvider) {
this.swaggerResourceProvider = swaggerResourceProvider;
}
@RequestMapping(value = "/configuration/security")
public ResponseEntity<SecurityConfiguration> securityConfiguration() {
return new ResponseEntity<>(SecurityConfigurationBuilder.builder().build(), HttpStatus.OK);
}
@RequestMapping(value = "/configuration/ui")
public ResponseEntity<UiConfiguration> uiConfiguration() {
return new ResponseEntity<>(UiConfigurationBuilder.builder().build(), HttpStatus.OK);
}
@RequestMapping
public ResponseEntity<List<SwaggerResource>> swaggerResources() {
return new ResponseEntity<>(swaggerResourceProvider.get(), HttpStatus.OK);
}
}
- 因为需要访问服务的api-docs接口,因此需要对该接口进行忽略,在gateway过滤规则中增加。
token: ignore: - /**/api-docs
效果
访问服务网关的swagger-ui.html页面即可,如:http://ip:port/swagger-ui.html,在select a spec选择想看的服务即可。