SpringCloud Eureka+Gateway 聚合 swagger2/knife4j

SpringCloud Eureka + Gateway 微服务 聚合 swagger2/knife4j,网上很多使用方法,但因为版本出现各种问题,这里记录一下代码最少的方式。

环境说明

本次配置的是父子工程

  • Spring Boot - 2.2.0.RELEASE
  • Spring Cloud - Hoxton.RELEASE
  • 注册中心 Eureka - 2.2.0.RELEASE
  • 网关依赖 GateWay - 2.2.0.RELEASE

Eureka + Gateway 聚合 swagger2/knife4j

父级pom.xml

    <modules>
        <module>eureka</module>
        <module>gateway</module>
        <module>system</module>
        <module>business</module>
        <module>doc</module>
    </modules>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.2.RELEASE</version>
        <relativePath />
    </parent>
    
    <dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>${spring-cloud.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>

        <!-- 集成 swagger2 -->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>2.10.5</version>
        </dependency>

        <!-- 集成 knife4j -->
        <dependency>
            <groupId>com.github.xiaoymin</groupId>
            <artifactId>knife4j-spring-boot-starter</artifactId>
            <version>2.0.9</version>
        </dependency>
        
        # 你自己的依赖包...
    </dependencies>
</dependencyManagement>

1、Eureka 模块配置

eureka 依赖包 pom.xml

<dependencies>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
    </dependency>
    
    # 你自己的依赖包...
</dependencies>

eureka 配置文件,使用默认端口:8761

# application.properties
# 配置 server
server.port=8761
server.servlet.context-path=/
server.tomcat.uri-encoding=utf-8

# 配置 Eureka
eureka.client.fetch-registry=false
eureka.client.register-with-eureka=false

# 模块名称
spring.application.name=eureka

启动文件 EurekaApplication.java

@EnableEurekaServer
@SpringBootApplication
public class EurekaApplication {
    public static void main(String[] args) {
        SpringApplication.run(EurekaApplication.class, args);
    }
}

2、GateWay 模块配置

说明一下:GateWay模块,是为了生产环境使用,Doc模块,只在本地使用,所以Doc模块也会集成gateway,所以这一步可以省略!

gateWay 依赖包 pom.xml

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
        
        # 你自己的依赖包...
    </dependencies>

gateway 配置文件,路由转发uri使用负载均衡的方式

# 配置 server
server.port=9000
server.servlet.context-path=/

# 配置 Eureka
eureka.client.service-url.defaultZone=http://localhost:8761/eureka/

# 模块名称
spring.application.name=gateway

# 路由转发
spring.cloud.gateway.routes[0].id=system
spring.cloud.gateway.routes[0].uri=lb:://system
#spring.cloud.gateway.routes[0].uri=http://127.0.0.1:9001
spring.cloud.gateway.routes[0].predicates[0].name=Path
spring.cloud.gateway.routes[0].predicates[0].args[0]=/system/**

# 路由转发
spring.cloud.gateway.routes[1].id=business
spring.cloud.gateway.routes[1].uri=lb://business
#spring.cloud.gateway.routes[1].uri=http://127.0.0.1:9002
spring.cloud.gateway.routes[1].predicates[0].name=Path
spring.cloud.gateway.routes[1].predicates[0].args[0]=/business/**

启动文件,添加注解@EnableEurekaClient

# GatewayApplication.java
@EnableEurekaClient
@SpringBootApplication
public class GatewayApplication {
    public static void main(String[] args) {
        SpringApplication.run(GatewayApplication.class, args);
    }
}

3、System 模块配置

system 依赖包 pom.xml,(business模块依赖一样)

<dependencies>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>
    
    <!-- 集成 swagger2 -->
    <dependency>
        <groupId>io.springfox</groupId>
        <artifactId>springfox-swagger2</artifactId>
    </dependency>
    
    <!-- 集成 knife4j -->
    <dependency>
        <groupId>com.github.xiaoymin</groupId>
        <artifactId>knife4j-spring-boot-starter</artifactId>
    </dependency>
    
    # 你自己的依赖包...
</dependencies>

system配置文件

注意区分 portcontext-path

# application.properties
# 配置 server
server.port=9001
server.servlet.context-path=/system

# 配置 Eureka
eureka.client.service-url.defaultZone=http://localhost:8761/eureka/

# 模块名称
spring.application.name=system

# 配置 knife4j(不写会报错)
knife4j.enable=true

system配置Java类

注意区分 groupNamebasePackage

# Swagger2Config.java
@Configuration
@EnableSwagger2WebMvc
public class Swagger2Config {

    private final OpenApiExtensionResolver openApiExtensionResolver;

    @Autowired
    public Swagger2Config(OpenApiExtensionResolver openApiExtensionResolver) {
        this.openApiExtensionResolver = openApiExtensionResolver;
    }

    @Bean
    public Docket webApiConfig() {
        String groupName = "system";
        Docket docket = new Docket(DocumentationType.SWAGGER_2)
                .groupName(groupName)
                .apiInfo(apiInfo())
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.*.system"))
                .paths(PathSelectors.any())
                .build()
                .extensions(openApiExtensionResolver.buildExtensions(groupName));
        return docket;
    }

    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title("System 接口")
                .description("Restful 风格接口")
                .version("0.0.1")
                .build();
    }
}

启动文件,添加注解@EnableEurekaClient

# SystemApplication.java
@EnableEurekaClient
@SpringBootApplication
public class SystemApplication {
    public static void main(String[] args) {
        SpringApplication.run(SystemApplication.class, args);
    }
}

完成以上步骤,子项目集成knife4j完毕

  • 访问:http://127.0.0.1:9001/system/doc.html
  • 访问:http://127.0.0.1:9002/business/doc.html

4、Business 模块配置

  • business 依赖包 pom.xml
  • business 配置文件
  • business 配置Java类
  • 启动文件,添加注解

这几步参考system模块配置,此处省略…

5、Doc 模块配置

doc 依赖包 pom.xml

<dependencies>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-gateway</artifactId>
    </dependency>

    <!-- 集成 knife4j -->
    <dependency>
        <groupId>com.github.xiaoymin</groupId>
        <artifactId>knife4j-spring-boot-starter</artifactId>
    </dependency>

    # 你自己的依赖包...
</dependencies>

doc配置文件,两种格式:propertiesyml

#application.properties

# 配置 Server
server.port=9003
server.servlet.context-path=/

# 配置 Eureka
eureka.client.service-url.defaultZone=http://localhost:8761/eureka/

# 模块名称
spring.application.name=doc

spring.cloud.gateway.discovery.locator.enabled=false
spring.cloud.gateway.discovery.locator.lowerCaseServiceId=true

# 路由转发
spring.cloud.gateway.routes[0].id=system
spring.cloud.gateway.routes[0].uri=lb://system
spring.cloud.gateway.routes[0].predicates[0].name=Path
spring.cloud.gateway.routes[0].predicates[0].args[0]=/system/**

# 路由转发
spring.cloud.gateway.routes[1].id=business
spring.cloud.gateway.routes[1].uri=lb://business
spring.cloud.gateway.routes[1].predicates[0].name=Path
spring.cloud.gateway.routes[1].predicates[0].args[0]=/business/**

# 配置 knife4j
knife4j.enableAggregation=true

knife4j.eureka.enable=true
knife4j.eureka.serviceUrl=http://localhost:8761/eureka/

knife4j.eureka.routes[0].name=系统模块
knife4j.eureka.routes[0].serviceName=system
knife4j.eureka.routes[0].servicePath=/system
knife4j.eureka.routes[0].location=/v2/api-docs?group=system

knife4j.eureka.routes[1].name=业务模块
knife4j.eureka.routes[1].serviceName=business
knife4j.eureka.routes[1].servicePath=/business
knife4j.eureka.routes[1].location=/v2/api-docs?group=business
# application.yml
# 配置 server
server:
  port: 9003
  servlet:
    context-path: /

# 配置 Eureka
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/

# 配置 Spring
spring:
  application:
    name: doc
  cloud:
    gateway:
      discovery:
        locator:
          enabled: false 
          lowerCaseServiceId: true
      routes:
        - id: system
          uri: lb://system
          predicates:
            - name: Path
              args[0]: /system/**
        - id: business
          uri: lb://business
          predicates:
            - name: Path
              args[0]: /business/**

# 配置 knife4j
knife4j:
  enableAggregation: true
  eureka:
    enable: true
    serviceUrl: http://localhost:8761/eureka/
    routes:
      - name: 系统模块
        serviceName: system
        servicePath: /system
        location: /v2/api-docs?group=system

      - name: 业务模块
        serviceName: business
        servicePath: /business
        location: /v2/api-docs?group=business

doc配置 创建两个Java类

#SwaggerResourceConfig.java

@Component
@Primary
public class SwaggerResourceConfig implements SwaggerResourcesProvider {

    private static final Logger LOG = LoggerFactory.getLogger(SwaggerResourceConfig.class);

    // swagger2默认后缀
    private static final String Swagger2URL = "/v2/api-docs";

    // 网关名称
    @Value("${spring.application.name}")
    private String self;

    // 网关路由
    private final RouteLocator routeLocator;

    @Autowired
    public SwaggerResourceConfig(RouteLocator routeLocator) {
        this.routeLocator = routeLocator;
    }

    @Override
    public List<SwaggerResource> get() {
        List<SwaggerResource> resources = new ArrayList<SwaggerResource>();
        List<String> routeHosts = new ArrayList<>();

        routeLocator.getRoutes().filter(route -> route.getUri().getHost() != null)
                .filter(route -> !self.equals(route.getUri().getHost()))
                .subscribe(route -> routeHosts.add(route.getUri().getHost()));

        Set<String> dealed = new HashSet<>();

        // gateway.discovery.locator.enabled 必须为false
        // 否则gateway.routes项不生效
        
        routeHosts.forEach(instance -> {
            // 通过负载均衡寻找对应主机
            // serviceId/v2/api-docs
            String url = "/" + instance + Swagger2URL + "?group=" + instance;

            if (!dealed.contains(url)) {
                dealed.add(url);
                resources.add(swaggerResource(url, instance));
            }
        });

        return resources;
    }

    private SwaggerResource swaggerResource(String url, String name) {
        LOG.info("url:{}, instance:{}", url, name);
        SwaggerResource swaggerResource = new SwaggerResource();
        swaggerResource.setUrl(url);
        swaggerResource.setName(name);
        swaggerResource.setSwaggerVersion("2.0");
        return swaggerResource;
    }
}
# SwaggerHandler.java

@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;
    }

    @GetMapping("/swagger-resources/configuration/security")
    public Mono<ResponseEntity<SecurityConfiguration>> securityConfiguration() {
        return Mono.just(new ResponseEntity<>(
                Optional.ofNullable(securityConfiguration).orElse(SecurityConfigurationBuilder.builder().build()), HttpStatus.OK));
    }

    @GetMapping("/swagger-resources/configuration/ui")
    public Mono<ResponseEntity<UiConfiguration>> uiConfiguration() {
        return Mono.just(new ResponseEntity<>(
                Optional.ofNullable(uiConfiguration).orElse(UiConfigurationBuilder.builder().build()), HttpStatus.OK));
    }

    @GetMapping({"", "/csrf", "/swagger-resources"})
    public Mono<ResponseEntity> swaggerResources() {
        return Mono.just((new ResponseEntity<>(swaggerResources.get(), HttpStatus.OK)));
    }
}

启动文件,添加注解@EnableEurekaClient

@EnableEurekaClient
@SpringBootApplication
public class DocApplication {
    public static void main(String[] args) {
        SpringApplication.run(DocApplication.class, args);
    }
}

子项目 正常访问

  • http://127.0.0.1:9001/system/doc.html
  • http://127.0.0.1:9002/business/doc.html

通过网关 访问子项目

  • http://127.0.0.1:9003/system/doc.html
  • http://127.0.0.1:9003/business/doc.html

聚合访问

  • http://127.0.0.1:9003/doc.html
  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值