微服务gateway聚合swagger文档解决

时间:2024-10-09 20:36:14

gateway网关聚合swagger2文档,由于gateway网关需要排除spring-web依赖,使用的是webFlux,故需要对swagger做一些配置

 

如下在对应的地方排除web依赖:

  1. <exclusions>
  2. <exclusion>
  3. <groupId></groupId>
  4. <artifactId>spring-boot-starter-web</artifactId>
  5. </exclusion>
  6. </exclusions>

增加swagger依赖:这个依赖包括了ui和swagger

  1. <!--knife4j版本的swagger-->
  2. <dependency>
  3. <groupId></groupId>
  4. <artifactId>knife4j-spring-boot-starter</artifactId>
  5. <version>2.0.4</version>
  6. </dependency>

微服务通用模块中增加自定义注册swagger模块文档: 只有当配置了swagger扫描的服务会自动生成文档

  1. package .blog_config.config;
  2. import ;
  3. import ;
  4. import ;
  5. import ;
  6. import ;
  7. import ;
  8. import .annotation.Bean;
  9. import .annotation.Configuration;
  10. import ;
  11. import .annotation.ResourceHandlerRegistry;
  12. import .annotation.WebMvcConfigurer;
  13. import ;
  14. import ;
  15. import ;
  16. import ;
  17. import ;
  18. import ..EnableSwagger2;
  19. import ;
  20. /**
  21. * 文档配置
  22. */
  23. @Configuration
  24. @ConditionalOnProperty(name = "")
  25. @EnableSwagger2
  26. public class Knife4jConfig implements EnvironmentAware, WebMvcConfigurer {
  27. private String basePackage;
  28. private String createName;
  29. private String serviceName;
  30. private String description;
  31. @Bean
  32. public Docket createRestApi() {
  33. return new Docket(DocumentationType.SWAGGER_2)
  34. .apiInfo(new ApiInfoBuilder()
  35. //.title("swagger-bootstrap-ui-demo RESTful APIs")
  36. .description(this.description)
  37. .termsOfServiceUrl("/")
  38. .contact(this.createName)
  39. .version("2.0")
  40. .build())
  41. //分组名称
  42. .groupName(this.serviceName)
  43. .select()
  44. //这里指定Controller扫描包路径,从配置文件中读取
  45. .apis((this.basePackage))
  46. .paths(())
  47. .build();
  48. }
  49. @Override
  50. public void setEnvironment(Environment environment) {
  51. Iterable<ConfigurationPropertySource> sources = ConfigurationPropertySources.get(environment);
  52. Binder binder = new Binder(sources);
  53. BindResult<Properties> bindResult = ("swagger", Properties.class);
  54. Properties properties= bindResult.get();
  55. this.basePackage = ("basepackage");
  56. this.createName = ("");
  57. this.serviceName = ("");
  58. this.description = ("");
  59. }
  60. @Override
  61. public void addResourceHandlers(ResourceHandlerRegistry registry) {
  62. ("").addResourceLocations("classpath:/META-INF/resources/");
  63. ("").addResourceLocations("classpath:/META-INF/resources/");
  64. ("/webjars*").addResourceLocations("classpath:/META-INF/resources/webjars/");
  65. }
  66. }

在网关服务中增加转发处理逻辑:

  1. package .blog_gateway.;
  2. import ;
  3. import .blog_common.;
  4. import .blog_common.;
  5. import .blog_gateway.;
  6. import .blog_gateway.;
  7. import ;
  8. import 44j;
  9. import 4.CollectionUtils;
  10. import .factory.;
  11. import ;
  12. import ;
  13. import ;
  14. import ;
  15. import ;
  16. import ;
  17. import .*;
  18. /**
  19. *
  20. */
  21. @Slf4j
  22. @Component
  23. @Primary
  24. @AllArgsConstructor
  25. public class SwaggerResourceConfig implements SwaggerResourcesProvider {
  26. @Autowired
  27. private ApiDocConfig apiDocConfig;
  28. @Autowired
  29. private RouteLocator routeLocator;
  30. @Autowired
  31. private TRouteDAO tRouteDAO;
  32. /**
  33. * 当请求文档服务时会调用这个接口,这里扩展我们转发逻辑和定义的文档名称
  34. * @return
  35. */
  36. @Override
  37. public List<SwaggerResource> get() {
  38. List<SwaggerResource> resources = new ArrayList<>();
  39. List<String> routes = new ArrayList<>();
  40. // 取出gateway的route
  41. ().subscribe(route -> {
  42. // 根据文档提供者过滤
  43. if (().contains(()))
  44. routes.add(());
  45. });
  46. // 结合配置的route-路径(Path),和route过滤,只获取有效的route节点
  47. //查询数据库中所有的路由信息
  48. List<TRoute> routeList = Optional
  49. .ofNullable(())
  50. .orElse(());
  51. if ((routeList)) {
  52. for (TRoute route : routeList) {
  53. if (routes.contains(())) {
  54. if((())){
  55. List<RoutePredicateVo> routePredicateVoList = ((), RoutePredicateVo.class);
  56. try {
  57. if ((routePredicateVoList)) {
  58. String genKey;
  59. RoutePredicateVo routePredicateVo = ().filter(routePredicate -> ().containsKey(NameUtils.GENERATED_NAME_PREFIX + "0")).findFirst().orElse(null);
  60. if (routePredicateVo != null) {
  61. genKey = ().get(NameUtils.GENERATED_NAME_PREFIX + "0").replace("/**", "/v2/api-docs?group=blog_admin");
  62. resources.add(swaggerResource((), genKey,"2.0"));
  63. }
  64. }
  65. } catch (Exception e) {
  66. log.error((), e);
  67. }
  68. }
  69. }
  70. }
  71. }
  72. return resources;
  73. }
  74. private SwaggerResource swaggerResource(String name, String location, String version) {
  75. SwaggerResource swaggerResource = new SwaggerResource();
  76. (name);
  77. (location);
  78. (version);
  79. return swaggerResource;
  80. }
  81. }

由于再gateway中不能使用@EnableSwagger等注解(因为它默认是spring mvc),故需要我们自定义给定访问controller,如下

  1. package .blog_gateway.controller;
  2. import .annotation.Autowired;
  3. import ;
  4. import ;
  5. import .annotation.GetMapping;
  6. import .annotation.RequestMapping;
  7. import .annotation.RestController;
  8. import ;
  9. import .*;
  10. import ;
  11. /**
  12. * 因为Gateway里没有配置SwaggerConfig,而运行Swagger-ui又需要依赖一些接口 ,同时使用gateway后(用到了webFlux排除掉了web),不能引入@EnableSwagger等注解,故自定义swagger的接口
  13. * 因为Swagger暂不支持webflux项目,所以Gateway里不能配置SwaggerConfig
  14. */
  15. @RestController
  16. @RequestMapping("/swagger-resources")
  17. public class SwaggerHandler {
  18. @Autowired(required = false)
  19. private SecurityConfiguration securityConfiguration;
  20. @Autowired(required = false)
  21. private UiConfiguration uiConfiguration;
  22. private final SwaggerResourcesProvider swaggerResources;
  23. @Autowired
  24. public SwaggerHandler(SwaggerResourcesProvider swaggerResources) {
  25. this.swaggerResources = swaggerResources;
  26. }
  27. @GetMapping("/configuration/security")
  28. public Mono<ResponseEntity<SecurityConfiguration>> securityConfiguration() {
  29. return (new ResponseEntity<>(
  30. (securityConfiguration).orElse(().build()), ));
  31. }
  32. @GetMapping("/configuration/ui")
  33. public Mono<ResponseEntity<UiConfiguration>> uiConfiguration() {
  34. return (new ResponseEntity<>(
  35. (uiConfiguration).orElse(().build()), ));
  36. }
  37. @GetMapping("")
  38. public Mono<ResponseEntity> swaggerResources() {
  39. return ((new ResponseEntity<>(swaggerResources.get(), )));
  40. }
  41. }

 

 

我的动态网关是配置在数据库中的:

在每个文档服务中配置,请求的路径:这是自定义swagger拉取接口的路径,默认是/v2/api-docs

 

  1. springfox:
  2. documentation:
  3. swagger:
  4. v2:
  5. path: /blog/v2/api-docs

原因是swagger会调用如下的接口(swagger源码):

可以看到,是会优先读取你自定义的配置路径的,如果没有则默认它自己的路径:

我们测试下文档路径

ui页面如下

这篇博客不是网站的解决方案,只是指出关键点,具体可以查看我的项目地址,分支是dev-nacos

 

/banjuanliunian/mock_blog

有问题欢迎指出