spring cloud gateway聚合swagger2
项目spring cloud基于 Greenwich.SR2, spring boot基于2.1.6.RELEASE
使用swagger可以生成api文档,让我们不再编写api文档,而且还自带调试功能,当然需要自己添加注解丰富文档的内容,单体服务使用swagger相信对大家来说都是没有问题的,下面将简单介绍单体服务使用swagger,以及使用gateway聚合swagger,由于swagger-ui的界面并不是那么还看,所以ui界面使用swagger-bootstrap-ui,一款界面优美的swagger-ui,现在使用了前后端分离,改名叫:knife4j
文档:https://doc.xiaominfo.com/guide/useful.html
新版本我感觉文档还有待完善,感兴趣的可以去看看
单个服务使用swagger
加配置:
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>swagger-bootstrap-ui</artifactId>
<version>1.9.5</version>
</dependency>
添加配置文件,名字随便取:
@Configuration
@EnableSwagger2
@EnableSwaggerBootstrapUI
public class SwaggerConfig {
@Bean
public Docket docket() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.withClassAnnotation(Api.class))
.paths(PathSelectors.any())
.build();
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("TEST-PROVIDER1")
.description("服务提供者一")
.version("1.0")
.contact(new Contact("xx", "", "aaa@qq.com"))
.build();
}
}
放行:
@Slf4j
@Configuration
public class WebAppConfig extends WebMvcConfigurationSupport {
@Autowired
private GlobalRequestHandler globalRequestHandler;
/**
* 处理开启全局异常拦截之后的问题
* @param registry
*/
@Override
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/swagger-ui.html")
.addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**")
.addResourceLocations("classpath:/META-INF/resources/webjars/");
registry.addResourceHandler("/doc.html")
.addResourceLocations("classpath:/META-INF/resources/");
super.addResourceHandlers(registry);
}
/**
* 注册拦截器
* @param registry
*/
@Override
protected void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(this.globalRequestHandler) //注册改拦截器
.addPathPatterns("/**") //表示拦截所有的请求,
.excludePathPatterns("/swagger-resources/**", "/webjars/**", "/v2/**", "/swagger-ui.html/**"); //排除 swagger 拦截
}
}
@EnableSwagger2:开启swagger2
@EnableSwaggerBootstrapUI:开启swagger-bootstrap-ui的增强文档,视情况而定,需要就添加不需要就不添加
其他没啥,网上对于这些的解释一大堆,值得注意的一点是扫描包哪里配置的是Api.class,会扫描所有带有api注解的controller,试想当你的扫描包不再一个目录是怎么办,之前在网上找的方法,但那个代码有个方法过时了,然后就自己和同事研究,个人觉得这个挺好的。
然后访问 ip:端口/doc.html就ok
gateway
我们开发不可能就只有一个服务,所以需要聚合所有的服务的文档
同理加配置:
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>swagger-bootstrap-ui</artifactId>
<version>1.9.5</version>
</dependency>
添加配置,因为gate是基于webflux,swagger的资源接口应该是基于web的,所以我们需要自己配置资源接口
@RestController
@RequestMapping("/swagger-resources")
public class SwaggerHandler {
@Autowired(required = false)
private SecurityConfiguration securityConfiguration;
@Autowired(required = false)
private UiConfiguration uiConfiguration;
private final SwaggerResourcesProvider swaggerResources;
@Autowired
public SwaggerHandler(SwaggerResourcesProvider swaggerResources) {
this.swaggerResources = swaggerResources;
}
@GetMapping("/configuration/security")
public Mono<ResponseEntity<SecurityConfiguration>> securityConfiguration() {
return Mono.just(new ResponseEntity<>(
Optional.ofNullable(securityConfiguration).orElse(SecurityConfigurationBuilder.builder().build()), HttpStatus.OK));
}
@GetMapping("/configuration/ui")
public Mono<ResponseEntity<UiConfiguration>> uiConfiguration() {
return Mono.just(new ResponseEntity<>(
Optional.ofNullable(uiConfiguration).orElse(UiConfigurationBuilder.builder().build()), HttpStatus.OK));
}
@GetMapping("")
public Mono<ResponseEntity> swaggerResources() {
return Mono.just((new ResponseEntity<>(swaggerResources.get(), HttpStatus.OK)));
}
}
对每个接口不了解的直接布起来后在使用接口访问便知
然后我们需要修改他的路由,取到所有的服务api文档,大概思路是去注册中心取到所有的服务,然后添上文档通用的后缀/v2/api-docs获取文档
@Component
@Primary
public class SwaggerProvider implements SwaggerResourcesProvider {
/**
* swagger的api json文档路径
*/
public static final String API_URI = "/v2/api-docs";
/**
* Eureka发现功能的方法的名字,注册的服务会加入这个前缀
*/
public static final String EUREKA_SUB_PFIX = "CompositeDiscoveryClient_";
/**
* 服务发现的路由处理器
*/
private final DiscoveryClientRouteDefinitionLocator routeLocator;
public SwaggerProvider(DiscoveryClientRouteDefinitionLocator routeLocator) {
this.routeLocator = routeLocator;
}
@Override
public List<SwaggerResource> get() {
List<SwaggerResource> resources = new ArrayList<>();
List<String> routes = new ArrayList<>();
//从DiscoveryClientRouteDefinitionLocator 中取出routes,构造成swaggerResource
routeLocator.getRouteDefinitions().subscribe(routeDefinition -> {
resources.add(swaggerResource(
//获取id(服务注册的id)
routeDefinition.getId()
//去除CompositeDiscoveryClient_前缀
.substring(EUREKA_SUB_PFIX.length()),
//获取路由定义信息列表
routeDefinition.getPredicates()
//获取路径信息PredicateDefinition{name='Path', args={pattern=/byb-provider2/**}}
.get(0)
.getArgs()
//将pattern中的/**替换为服务swagger文档路径
.get("pattern")
.replace("/**", API_URI)));
});
//for是我自己写的过滤没有api文档的代码,自己视情况添加
for (SwaggerResource swaggerResource : resources) {
//获取所有服务的文档uri
String uri = swaggerResource.getUrl();
//获取服务名
String serverName = uri.replace(API_URI, "");
//拼接url
String url = "http://regist.byb.com:38001/eureka/apps"+serverName;
//获取RestTemplate实例
RestTemplate restTemplate = new RestTemplate();
HttpHeaders httpHeaders = new HttpHeaders();
//添加请求头
httpHeaders.add("Content-Type", "application/json");
httpHeaders.add("Accept", "application/json");
//请求体
HttpEntity<String> httpEntity = new HttpEntity<String>(null,httpHeaders);
//发送请求获取响应
ResponseEntity<String> responseEntity = restTemplate.exchange(url, HttpMethod.GET, httpEntity, String.class);
String response = responseEntity.getBody();
//解析json
JSONObject jsonObject;
jsonObject = JSONObject.parseObject(response);
String str1 = jsonObject.getString("application");
jsonObject = JSONObject.parseObject(str1);
String str2 = jsonObject.getString("instance");
JSONArray jsonArray = JSONObject.parseArray(str2);
String str3 = jsonArray.getString(0);
jsonObject = JSONObject.parseObject(str3);
String serverUrl = jsonObject.getString("homePageUrl");
if (null != serverUrl && !"".equals(serverUrl)) {
//拼接服务api文档的url
String serverApi = serverUrl + "v2/api-docs";
//发送请求
try {
URL url1 = new URL(serverApi);
HttpURLConnection httpUrlConn = (HttpURLConnection) url1.openConnection();
//设置连接超时时间
httpUrlConn.setConnectTimeout(1000);
//获取返回码
int code = httpUrlConn.getResponseCode();
if (code != 200) {
resources.remove(swaggerResource);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
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;
}
}
具体信息注释已经写的很完善了,同理访问ip:端口/doc.html即可访问,左上角即可切换项目,for循环是我自己添加的,用于排除没有api文档的微服务,不需要直接删除即可。
有问题下方沟通,我应该没有写漏东西。。。
附上swagger的详细注解 –
https://blog.csdn.net/zlhmeng/article/details/100524382
上一篇: 23种设计模式之模板方法模式(12)
下一篇: C/C++算法设计实验报告(源代码)
推荐阅读
-
springcloud gateway聚合swagger2的方法示例
-
详解spring cloud构建微服务架构的网关(API GateWay)
-
Spring Cloud Gateway入门解读
-
详解spring cloud整合Swagger2构建RESTful服务的APIs
-
阿里Sentinel支持Spring Cloud Gateway的实现
-
Spring Cloud GateWay 路由转发规则介绍详解
-
Spring Cloud Gateway网关XSS过滤Filter
-
详解spring cloud构建微服务架构的网关(API GateWay)
-
Spring Cloud Gateway入门解读
-
详解spring cloud整合Swagger2构建RESTful服务的APIs