swaage2升级knife4j springcloud+nacos+gateway配置 聚合所有的Swagger微服务文档

为什么要升级到knife4j 新功能有什么 有个很关键的一个功能 聚合Swagger微服务文档 再也不用打开多个文档页面了 并且优化了ui页面.
本文章主要讲解 springcloud+nacos+gateway架构继承knife4j.

环境依赖 gateway maven knife4j依赖

 
 <properties>
        <knife4j.version>2.0.8</knife4j.version>
        <swagger.version>1.5.21</swagger.version>
    </properties>

        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
      <dependency>
            <groupId>com.github.xiaoymin</groupId>
            <artifactId>knife4j-micro-spring-boot-starter</artifactId>
            <version>${knife4j.version}</version>
            <exclusions>
                <exclusion>
                    <groupId>io.springfox</groupId>
                    <artifactId>springfox-swagger2</artifactId>
                </exclusion>
            </exclusions>
      </dependency>
         <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
        <dependency>
            <groupId>com.github.xiaoymin</groupId>
            <artifactId>knife4j-spring-boot-starter</artifactId>
            <version>${knife4j.version}</version>
        </dependency>
        <dependency>
            <groupId>io.swagger</groupId>
            <artifactId>swagger-models</artifactId>
            <version>${swagger.version}</version>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-common</artifactId>
            <version>2.9.2</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>

gateway配置文件swagger  3个配置类


package org.com.app.config.swagger;

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;


/**
 * @author xiaoymin
 * 2020年10月29日 18:38:01
 */
@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("/swagger-resources")
    public Mono<ResponseEntity> swaggerResources() {
        return Mono.just((new ResponseEntity<>(swaggerResources.get(), HttpStatus.OK)));
    }
}
/*
 * Copyright (C) 2018 Zhejiang xiaominfo Technology CO.,LTD.
 * All rights reserved.
 * Official Web Site: http://www.xiaominfo.com.
 * Developer Web Site: http://open.xiaominfo.com.
 */

package org.com.app.config.swagger;

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;

/***
 *
 * @since:swagger-bootstrap-ui 1.0
 * @author fsl
 * 2019/05/04 12:38
 */
@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<>();
        routeLocator.getRoutes().subscribe(route -> routes.add(route.getId()));
        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;
    }
}

package org.com.app.config.swagger;

import org.apache.commons.lang.StringUtils;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;


/**
 * @author fsl
 * @description: SwaggerHeaderFilter
 * @date 2019-06-0310:47
 */
@Component
public class SwaggerHeaderFilter extends AbstractGatewayFilterFactory {
    private static final String HEADER_NAME = "X-Forwarded-Prefix";

    private static final String URI = "/v2/api-docs";

    @Override
    public GatewayFilter apply(Object config) {
        return (exchange, chain) -> {
            ServerHttpRequest request = exchange.getRequest();
            String path = request.getURI().getPath();
            if (!StringUtils.endsWithIgnoreCase(path,URI )) {
                return chain.filter(exchange);
            }
            String basePath = path.substring(0, path.lastIndexOf(URI));
            ServerHttpRequest newRequest = request.mutate().header(HEADER_NAME, basePath).build();
            ServerWebExchange newExchange = exchange.mutate().request(newRequest).build();
            return chain.filter(newExchange);
        };
    }
}

服务接口配置

package org.com.app.config.swagger2;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.bind.annotation.RequestMethod;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.builders.ResponseMessageBuilder;
import springfox.documentation.service.*;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.contexts.SecurityContext;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

import java.util.ArrayList;
import java.util.List;

@Configuration
@EnableSwagger2
public class Swagger2Configuration {
    //api接口包扫描路径
    @Value("${swagger.scanbasepackage}")
    private String swaggerScanBasePackage;
    @Value("${swagger.title}")
    private String title;
    @Value("${swagger.description}")
    private String description;
    public static final String VERSION = "1.0.0";
    @Bean
    public Docket apiDocumentApi() {
        List<ResponseMessage> responseMessageList = new ArrayList<>();
        responseMessageList.add(new ResponseMessageBuilder().code(403).message("账号未登录").build());
        responseMessageList.add(new ResponseMessageBuilder().code(401).message("客户端编号或者是秘钥错误").build());
        responseMessageList.add(new ResponseMessageBuilder().code(500).message("服务器异常").build());
        return new Docket(DocumentationType.SWAGGER_2)
                .globalResponseMessage(RequestMethod.GET, responseMessageList)
                .globalResponseMessage(RequestMethod.POST, responseMessageList)
                .globalResponseMessage(RequestMethod.PUT, responseMessageList)
                .globalResponseMessage(RequestMethod.DELETE, responseMessageList)
                .apiInfo(apiInfo())
                .select()
                .apis(RequestHandlerSelectors.basePackage(swaggerScanBasePackage))
                .paths(PathSelectors.any()) // 可以根据url路径设置哪些请求加入文档,忽略哪些请求
                .build().securitySchemes(setHeaderToken()).securityContexts(securityContexts());
    }

    private List<ApiKey> setHeaderToken() {
        List<ApiKey> list=new ArrayList<>();
        list.add(new ApiKey("Authorization", "Authorization", "header"));
        return list;
    }

    private List<SecurityContext> securityContexts() {
        List<SecurityContext> securityContexts=new ArrayList<>();
        securityContexts.add(
                SecurityContext.builder()
                        .securityReferences(defaultAuth())
                        .forPaths(PathSelectors.any())
                        .build());
        return securityContexts;
    }

    List<SecurityReference> defaultAuth() {
        AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
        AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
        authorizationScopes[0] = authorizationScope;
        List<SecurityReference> securityReferences=new ArrayList<>();
        securityReferences.add(new SecurityReference("Authorization", authorizationScopes));
        return securityReferences;
    }

    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .contact("12345联系人")
                .title(title) //设置文档的标题
                .description(description) // 设置文档的描述
                .version(VERSION) // 设置文档的版本信息-> 1.0.0 Version information
                .build();
    }
}

网关配置文件


spring:
  application:
    name: gateway-service
  cloud:
    nacos: # 注册中心
      discovery:
        server-addr: localhost:8848
        namespace: ${nacosNameSpace}
    gateway:
      httpclient:
        connect-timeout: 1000
        response-timeout: 2s
      discovery:
        locator:
          #启用DiscoveryClient网关集成,实现服务的发现
          enabled: true
      #配置网关路由转发规则
      routes:
      - id: act-router
        uri: lb://account-service
        predicates:
          - Path=/act/**
      - id: mkt-router
        uri: lb://market-service
        predicates:
          - Path=/mkt/**
      - id: auth-router
        uri: lb://auth-service
        predicates:
          - Path=/auth/**






knife4j:
  enableAggregation: true
  nacos:
    enable: true
    serviceUrl: http:// ${spring.cloud.nacos.discovery.server-addr}/nacos/
    namespace: ${spring.cloud.nacos.discovery.namespace}

    routes:
      - name: 订单服务
        serviceName: account-service
        groupName: default
        namespaceId: cst
        location: /v2/api-docs?group=default
        swaggerVersion: 2.0
        servicePath: /act
      - name: market服务
        serviceName: market-service
        groupName: default
        namespaceId: cst
          #        clusters: test
        location: /v2/api-docs?group=default
        swaggerVersion: 2.0
        servicePath: /mkt
      - name: auth服务
        serviceName: auth-service
        groupName: default
        namespaceId: cst
          #        clusters: test
        location: /v2/api-docs?group=default
        swaggerVersion: 2.0
        servicePath: /auth

knife4j.nacos.enable:将该属性设置为true,则代表启用nacos模式
knife4j.nacos.serviceUrl:nacos注册中心的地址
knife4j.nacos.routeAuth:该属性是一个公共Basic验证属性(可选),如果开发者提供的OpenAPI规范的服务需要以Basic验证进行鉴权访问,那么可以配置该属性,如果配置该属性,则该模式下所有配置的Routes节点接口都会以Basic验证信息访问接口
knife4j.nacos.routeAuth.enable:是否启用Basic验证
knife4j.nacos.routeAuth.usernae:Basic用户名
knife4j.nacos.routeAuth.password:Basic密码
knife4j.nacos.routes:需要聚合的服务集合(必选),可以配置多个
knife4j.nacos.routes.name:服务名称(显示名称,最终在Ui的左上角下拉框进行显示),如果该属性不配置,最终Ui会显示serviceName
knife4j.nacos.routes.serviceName:nacos注册中心的服务名称
knife4j.nacos.routes.groupName:Nacos分组名称,非必须,开发者根据自己的实际情况进行配置
knife4j.nacos.routes.namespaceId:命名空间id,非必须,开发者根据自己的实际情况进行配置
knife4j.nacos.routes.clusters:集群名称,多个集群用逗号分隔,非必须,开发者根据自己的实际情况进行配置
knife4j.nacos.routes.uri:该服务的接口URI资源,如果是HTTPS,则需要完整配置
knife4j.nacos.routes.location::具体资源接口地址,最终Knife4j是通过注册服务uri+location的组合路径进行访问
knife4j.nacos.routes.swaggerVersion:版本号,默认是2.0,可选配置
knife4j.nacos.routes.servicePath:该属性是最终在Ui中展示的接口前缀属性,提供该属性的目的也是因为通常开发者在以Gateway等方式聚合时,需要一个前缀路径来进行转发,而最终这个前缀路径会在每个接口中进行追加
knife4j.nacos.routes.routeAuth:如果该Route节点的接口开启了Basic,并且和公共配置的Basic不一样,需要单独配置
knife4j.nacos.routes.routeAuth.enable:是否启用Basic验证
knife4j.nacos.routes.routeAuth.usernae:Basic用户名
knife4j.nacos.routes.routeAuth.password:Basic密码

你可能感兴趣的:(java,gateway,cloud,swagger2,java,spring)