参考下面两篇文章完成

微服务聚合Swagger文档,这波操作是真的香!

基于Spring Cloud Gateway | knife4j

集成步骤

  1. maven的引入

    <dependency>
        <groupId>com.github.xiaoymin</groupId>
        <artifactId>knife4j-spring-boot-starter</artifactId>
    </dependency>
    
  2. 配置文件

    package com.dp.quality.gateway.config;
    
    import lombok.AllArgsConstructor;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.cloud.gateway.config.GatewayProperties;
    import org.springframework.cloud.gateway.route.RouteLocator;
    import org.springframework.cloud.gateway.support.NameUtils;
    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;
    
    /**
     * Swagger资源配置
     * Created by macro on 2020/7/9.
     */
    @Slf4j
    @Component
    @Primary
    @AllArgsConstructor
    public class SwaggerResourceConfig implements SwaggerResourcesProvider {
    
        private final RouteLocator routeLocator;
        private final GatewayProperties gatewayProperties;
    
        @Override
        public List<SwaggerResource> get() {
            List<SwaggerResource> resources = new ArrayList<>();
            List<String> routes = new ArrayList<>();
            //获取所有路由的ID
            routeLocator.getRoutes().subscribe(route -> routes.add(route.getId()));
            //过滤出配置文件中定义的路由->过滤出Path Route Predicate->根据路径拼接成api-docs路径->生成SwaggerResource
            gatewayProperties.getRoutes().stream().filter(routeDefinition -> routes.contains(routeDefinition.getId())).forEach(route -> {
                route.getPredicates().stream()
                        .filter(predicateDefinition -> ("Path").equalsIgnoreCase(predicateDefinition.getName()))
                        .forEach(predicateDefinition -> resources.add(swaggerResource(route.getId(),
                                predicateDefinition.getArgs().get(NameUtils.GENERATED_NAME_PREFIX + "0")
                                        .replace("**", "v2/api-docs"))));
            });
    
            return resources;
        }
    
        private SwaggerResource swaggerResource(String name, String location) {
            log.info("name:{},location:{}", name, location);
            SwaggerResource swaggerResource = new SwaggerResource();
            swaggerResource.setName(name);
            swaggerResource.setLocation(location);
            swaggerResource.setSwaggerVersion("2.0");
            return swaggerResource;
        }
    }
    
  3. rest类

    package com.dp.quality.gateway.rest;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.http.HttpStatus;
    import org.springframework.http.ResponseEntity;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RestController;
    import reactor.core.publisher.Mono;
    import springfox.documentation.swagger.web.*;
    
    import java.util.Optional;
    
    /**
     * 自定义Swagger的各个配置节点
     * Created by macro on 2020/7/9.
     */
    @RestController
    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;
        }
    
        /**
         * Swagger安全配置,支持oauth和apiKey设置
         */
        @GetMapping("/swagger-resources/configuration/security")
        public Mono<ResponseEntity<SecurityConfiguration>> securityConfiguration() {
            return Mono.just(new ResponseEntity<>(
                    Optional.ofNullable(securityConfiguration).orElse(SecurityConfigurationBuilder.builder().build()), HttpStatus.OK));
        }
    
        /**
         * Swagger UI配置
         */
        @GetMapping("/swagger-resources/configuration/ui")
        public Mono<ResponseEntity<UiConfiguration>> uiConfiguration() {
            return Mono.just(new ResponseEntity<>(
                    Optional.ofNullable(uiConfiguration).orElse(UiConfigurationBuilder.builder().build()), HttpStatus.OK));
        }
    
        /**
         * Swagger资源配置,微服务中这各个服务的api-docs信息
         */
        @GetMapping("/swagger-resources")
        public Mono<ResponseEntity> swaggerResources() {
            return Mono.just((new ResponseEntity<>(swaggerResources.get(), HttpStatus.OK)));
        }
    }
    

遇见问题

<aside> 💡 在集成Spring Cloud Gateway网关的时候,会出现没有basePath的情况(即定义的例如/user、/order等微服务的前缀),这个情况在使用zuul网关的时候不会出现此问题,因此,在Gateway网关需要添加一个Filter实体Bean,代码如下:

</aside>

  1. 聚合后没有前缀,查询knife4j官网后发现一短话(看上面)

  2. 之后按步骤加了过滤但是发现加错位置,

    spring:
      profiles:
        active: dev
      application:
        name: dp-gateway
      cloud:
        gateway:
          discovery:
            locator:
              enabled: false
              lowerCaseServiceId: true
          routes:
          - id: api-server
            uri: lb://dp-api-server
            predicates:
              - Path=/api/**
            filters:
              - SwaggerHeaderFilter
              - StripPrefix=1
              - RequestTime=true
          - id: search-server
            uri: lb://dp-search
            predicates:
              - Path=/search/**
            filters:
              - SwaggerHeaderFilter
              - StripPrefix=1
              - RequestTime=true
          - id: user-server
            uri: lb://dp-user
            predicates:
              - Path=/user/**
            filters:
              - SwaggerHeaderFilter
              - StripPrefix=1
              - RequestTime=true