Knife4j+gateway动态路由聚合微服务API

概述

knife4j的聚合API,其实官网有现成的例子,但包括其他能搜索到的资料都是基于静态网关的配置,我们现有的都是结合nacos实现动态网关配置,基于此留下这篇完整的教程文档
说明:本文假定你有一定的springcloud等相关知识,如没有请自行查找其他资料

基础环境

spring-boot-dependencies2.2.9.RELEASE
spring-cloud-dependenciesHoxton.SR7
spring-cloud-alibaba-dependencies2.2.3.RELEASE
knife4j2.0.9

代码

父parent

<dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-dependencies</artifactId>
        <version>${spring-boot-dependencies.version}</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>
      <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-dependencies</artifactId>
        <version>${spring-cloud-dependencies.version}</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>
      <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-alibaba-dependencies</artifactId>
        <version>${spring-cloud-alibaba-dependencies.version}</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>
       <!-- knife4j提供的微服务starter -->
      <dependency>
        <groupId>com.github.xiaoymin</groupId>
        <artifactId>knife4j-spring-boot-starter</artifactId>
        <version>${knife4j.version}</version>
      </dependency>
      <dependency>
        <groupId>com.github.xiaoymin</groupId>
        <artifactId>knife4j-micro-spring-boot-starter</artifactId>
        <version>${knife4j.version}</version>
      </dependency>
   </dependencyManagement>

springcloud 网关

pom

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

    <dependency>
      <groupId>com.alibaba.cloud</groupId>
      <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    </dependency>
    <dependency>
      <groupId>com.alibaba.cloud</groupId>
      <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
    </dependency>
        <!-- knife4j提供的微服务starter -->
    <dependency>
      <groupId>com.github.xiaoymin</groupId>
      <artifactId>knife4j-spring-boot-starter</artifactId>
    </dependency>
 </dependencies>

相关配置

  1. 动态路由配置,一般配置在nacos上,选择json格式
[
  {
    "id": "xxx",
    "order": 1,
    "predicates": [
      {
        "args": {
          "pattern": "/api/author/**"
        },
        "name": "Path"
      }
    ],
    "uri": "lb://author-service"
  }
]
  1. 网关配置,建议放在application.yml里面
spring:
  cloud:
    gateway:
      httpclient:
        # 全局的TCP连接超时时间默认时间是45秒,网络故障的时候,连接时间要等待45秒,而网络连接是同步阻塞
        connect-timeout: 2000
        # 全局的响应超时时间,网络链接后,后端服务多久不返回网关就报错 The response timeout.
        response-timeout: PT30S
        pool:
          # scg的空闲连接超时回收时间
          max-idle-time: PT1S
        websocket:
          # 1024*1024*10  上传的文件大小
          max-frame-payload-length: 10485760
      # 全局跨域配置
      #globalcors:
        #cors-configurations:
          #'[/**]': #匹配所有请求
            #allowedOrigins: "*" #跨域处理 允许所有的域
            #allowedMethods: # 支持的方法
              #- GET
              #- POST
              #- PUT
              #- DELETE
      # nacos 服务发现
      discovery:
        locator:
          lowerCaseServiceId: true
          enabled: true
      # 配置全局路由
      #default-filters:
        # 开发环境重写路由规则 该配置会影响到灰度组件,如果开启需要关闭灰度组件
        #- DevLocalRewriteRouteFilter=true
        # 签名校验
        #- SecretGatewayFilter=true

动态路由代码实现

  1. DynamicRouteService 动态路由管理服务
import org.springframework.cloud.gateway.route.RouteDefinition;

/**
 * TODO  NacosDynamicRutesService <br>
 *
 * @date: 2020/12/7 <br>
 * @author: xiaolinlin <br>
 * @since: 1.0 <br>
 * @version: 1.0 <br>
 */
public interface DynamicRouteService {

    /**
     * 新增一个route定义
     *
     * @param routeDefinition : 路由信息
     * @param manual: 控制台-手动
     * @return java.lang.String
     * @author xiaolinlin
     * @date 2020/12/7
     **/
    String addRoute(RouteDefinition routeDefinition,boolean manual);

    /**
     * 更新一个route定义
     *
     * @param routeDefinition :
     * @return java.lang.String
     * @author xiaolinlin
     * @date 2020/12/7
     **/
    String updateRoute(RouteDefinition routeDefinition);

    /**
     * 通过ID删除一个route定义
     *
     * @param id :
     * @return java.lang.String
     * @author xiaolinlin
     * @date 2020/12/7
     **/
    String deleteRoute(String id);
  1. AbstractDynamicRouteService基类实现
import com.alibaba.fastjson.JSONObject;
import java.util.ArrayList;
import java.util.List;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.event.RefreshRoutesEvent;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.cloud.gateway.route.RouteDefinitionWriter;
import org.springframework.cloud.gateway.support.NotFoundException;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.http.ResponseEntity;
import reactor.core.publisher.Mono;

/**
 * 动态路由配置抽象类<br>
 *
 * @date: 2020/12/23 <br>
 * @author: xiaolinlin <br>
 * @since: 1.0 <br>
 * @version: 1.0 <br>
 */
@Slf4j
public abstract class AbstractDynamicRouteService implements DynamicRouteService, ApplicationEventPublisherAware,
    DisposableBean {

    @Autowired
    protected RouteDefinitionWriter routeDefinitionWriter;

    protected ApplicationEventPublisher applicationEventPublisher;


    /**
     * 路由列表  TODO  分布式配置
     */
    protected static final List<String> ROUTE_LIST = new ArrayList<>();

    /**
     * 新增一个route定义
     *
     * @param routeDefinition :
     * @param manual: 是否手动配置
     * @return java.lang.String
     * @author xiaolinlin
     * @date 2020/12/7
     **/
    @Override
    public String addRoute(RouteDefinition routeDefinition, boolean manual) {
        try {
            log.debug("新增route配置:{}", JSONObject.toJSONString(routeDefinition));
            routeDefinitionWriter.save(Mono.just(routeDefinition)).subscribe();
            ROUTE_LIST.add(routeDefinition.getId());
            if (manual) {
                // 手动发布,每添加一次更新一次
                publish();
            }
        } catch (Exception e) {
            log.error("添加路由失败,当前路由信息:{},错误详情:{}", JSONObject.toJSONString(routeDefinition), e);
        }
        return "success";
    }

    /**
     * 更新一个route定义
     *
     * @param routeDefinition :
     * @return java.lang.String
     * @author xiaolinlin
     * @date 2020/12/7
     **/
    @Override
    public String updateRoute(RouteDefinition routeDefinition) {
        if (null == routeDefinition) {
            return "fail";
        }
        log.debug("更新route配置:{}", JSONObject.toJSONString(routeDefinition));
        String id = routeDefinition.getId();
        try {
            this.routeDefinitionWriter.delete(Mono.just(id));
            this.routeDefinitionWriter.save(Mono.just(routeDefinition)).subscribe();
            publish();
        } catch (Exception e) {
            log.error("更新路由信息失败,当前ID:{},错误信息:{}", id, e);
            return "fail";
        }
        return "success";
    }

    /**
     * 通过ID删除一个route定义
     *
     * @param id :
     * @return java.lang.String
     * @author xiaolinlin
     * @date 2020/12/7
     **/
    @Override
    public String deleteRoute(String id) {
        if (StringUtils.isEmpty(id)) {
            return "fail";
        }
        log.debug("触发了删除route配置,路由ID: {}", id);
        try {
            this.routeDefinitionWriter.delete(Mono.just(id))
                .then(Mono.defer(() -> Mono.just(ResponseEntity.ok().build())))
                .onErrorResume(t -> t instanceof NotFoundException, t -> Mono.just(ResponseEntity.notFound().build()))
                .subscribe();
            return "success";
        } catch (Exception e) {
            log.error("删除路由失败,当前路由ID:{},异常原因:{}", id, e);
            return "fail";
        }
    }

    /**
     * 初始化路由配置
     *
     * @param config :
     * @return void
     * @author xiaolinlin
     * @date 2020/12/7
     **/
    protected void initConfig(String config) {
        if (StringUtils.isEmpty(config)) {
            return;
        }
        List<RouteDefinition> gatewayRouteDefinitions = JSONObject
            .parseArray(config, RouteDefinition.class);
        for (RouteDefinition routeDefinition : gatewayRouteDefinitions) {
            addRoute(routeDefinition, false);
        }
        // 重新发布更新
        publish();
    }

    /**
     * 发布重新更新
     *
     * @return void
     * @author xiaolinlin
     * @date 2020/12/7
     **/
    protected void publish() {
        log.info("当前网关路径节点:{}", JSONObject.toJSONString(ROUTE_LIST));
        this.applicationEventPublisher.publishEvent(new RefreshRoutesEvent(this.routeDefinitionWriter));
    }

    /**
     * clearRoute
     *
     * @author xiaolinlin
     * @date 2020/12/7
     **/
    protected void clearRoute() {
        for (String id : ROUTE_LIST) {
            this.deleteRoute(id);
        }
        ROUTE_LIST.clear();
    }

    /**
     * Set the ApplicationEventPublisher that this object runs in.
     * <p>Invoked after population of normal bean properties but before an init
     * callback like InitializingBean's afterPropertiesSet or a custom init-method. Invoked before ApplicationContextAware's
     * setApplicationContext.
     *
     * @param applicationEventPublisher event publisher to be used by this object
     */
    @Override
    public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
        this.applicationEventPublisher = applicationEventPublisher;
    }

    @Override
    public void destroy() throws Exception {
        ROUTE_LIST.clear();
    }
}
  1. nacos实现
import com.alibaba.nacos.api.NacosFactory;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.config.listener.Listener;
import com.alibaba.nacos.api.exception.NacosException;
import xxx.AbstractDynamicRouteService;
import java.util.Properties;
import java.util.concurrent.Executor;
import javax.annotation.PostConstruct;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Service;

/**
 * 动态网关调整<br>
 *
 * @date: 2020/12/7 <br>
 * @author: xiaolinlin <br>
 * @since: 1.0 <br>
 * @version: 1.0 <br>
 */
@Service
@RefreshScope
@Slf4j
public class NacosDynamicRoutesImpl extends AbstractDynamicRouteService {

    // nacos 的配置信息
    /// private NacosConfigProperties nacosConfigProperties;

    /**
     * nacos服务地址
     *
     *
     *
     *
     *
     */
    @Value("${spring.cloud.nacos.server-addr}")
    private String serverAddr;
    /**
     * namespace
     */
    @Value("${spring.cloud.nacos.discovery.namespace}")
    private String nameSpace;

    /**
     * 配置组
     */
    @Value("${spring.cloud.nacos.config.discovery.group:DEFAULT_GROUP}")
    private String gourpId;

    /**
     * 动态路由dataID,JSON格式, 重点关注这里,nacos上的名称
     */
    @Value("${spring.cloud.nacos.config.route-data-id:xiaogj-youli-platform-gateway-route}")
    private String routeDataId;

    /**
     * 初始化启动监听nacos配置
     *
     * @return void
     * @author xiaolinlin
     * @date 2020/12/7
     **/
    @PostConstruct
    public void dynamicRouteByNacosListener() {
        log.info("gateway route init...");
        try {
            Properties properties = new Properties();
            properties.setProperty("serverAddr", serverAddr);
            properties.setProperty("namespace", nameSpace);
            ConfigService configService = NacosFactory.createConfigService(properties);
            String config = configService.getConfig(routeDataId, gourpId, 5000);
            // 初次初始化
            initConfig(config);
            // 动态更新
            configService.addListener(routeDataId, gourpId, new Listener() {
                @Override
                public Executor getExecutor() {
                    return null;
                }

                @Override
                public void receiveConfigInfo(String configInfo) {
                    clearRoute();
                    try {
                        log.info("配置发生了变更,变更网关配置内容:{}", configInfo);
                        initConfig(configInfo);
                    } catch (Exception e) {
                        log.warn("本次配置更新失败,错误详情:", e);
                    }
                }
            });
        } catch (NacosException e) {
            log.error("监听网关路由配置异常,错误信息:", e);
        }
    }
}

swagger 代码部分

  1. SwaggerHandler
import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Mono;
import springfox.documentation.swagger.web.SecurityConfiguration;
import springfox.documentation.swagger.web.SecurityConfigurationBuilder;
import springfox.documentation.swagger.web.SwaggerResourcesProvider;
import springfox.documentation.swagger.web.UiConfiguration;
import springfox.documentation.swagger.web.UiConfigurationBuilder;

/**
 * swagger <br>
 *
 * @date: 2021/9/22 <br>
 * @author: llxiao <br>
 * @since: 1.0 <br>
 * @version: 1.0 <br>
 */
@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));
    }

    @SuppressWarnings("rawtypes")
    @GetMapping("")
    public Mono<ResponseEntity> swaggerResources() {
        return Mono.just((new ResponseEntity<>(swaggerResources.get(), HttpStatus.OK)));
    }
}
  1. SwaggerProvider 主要是用于适配nacos动态路由
import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSON;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.handler.predicate.PredicateDefinition;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.cloud.gateway.route.RouteDefinitionRepository;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.config.ResourceHandlerRegistry;
import org.springframework.web.reactive.config.WebFluxConfigurer;
import reactor.core.publisher.Flux;
import springfox.documentation.swagger.web.SwaggerResource;
import springfox.documentation.swagger.web.SwaggerResourcesProvider;

/**
 * 聚合系统接口<br>
 *
 * @date: 2021/9/22 <br>
 * @author: llxiao <br>
 * @since: 1.0 <br>
 * @version: 1.0 <br>
 */
@Slf4j
@Component
@Primary
@AllArgsConstructor
public class SwaggerProvider implements SwaggerResourcesProvider, WebFluxConfigurer {

    /**
     * Swagger2默认的url后缀
     */
    public static final String SWAGGER2URL = "/v2/api-docs";

    /**
     * 网关路由
     */
    ///@Autowired
    ///private RouteLocator routeLocator;

    /**
     * yml方式获取路由服务
     */
    ///@Autowired
    ///private GatewayProperties gatewayProperties;

    /**
     * 使用动态路由,获取到指定的路由规则
     */
    @Autowired
    private RouteDefinitionRepository routeDefinitionRepository;

    /**
     * 聚合其他服务接口
     *
     * @return java.util.List<springfox.documentation.swagger.web.SwaggerResource>
     * @author llxiao
     * @date 2022/3/30
     **/
    @Override
    public List<SwaggerResource> get() {

        //接口资源列表
        List<SwaggerResource> resourceList = new ArrayList<>();

        //服务名称列表
        Set<String> routeHosts = new HashSet<>();

        // 去重,多负载服务只添加一次
        Set<String> existsServer = new HashSet<>();

        // 动态网关方式获取路由  nacos动态网关
        Flux<RouteDefinition> routeDefinitions = routeDefinitionRepository.getRouteDefinitions();
        routeDefinitions.subscribe(routeDefinition -> {
            List<PredicateDefinition> predicates = routeDefinition.getPredicates();
            if (CollectionUtil.isNotEmpty(predicates)) {
                String host = routeDefinition.getUri().getHost();
                routeHosts.add(host);
                String url = "/" + host + SWAGGER2URL;
                if (!existsServer.contains(url)) {
                    existsServer.add(url);
                    SwaggerResource swaggerResource = new SwaggerResource();
                    swaggerResource.setUrl(url);
                    swaggerResource.setName(host);
                    resourceList.add(swaggerResource);
                }

            }
        });
        log.info("网关服务地址列表:{}", JSON.toJSONString(routeHosts));
        return resourceList;
    }

    private SwaggerResource swaggerResource(String name, String location) {
        SwaggerResource swaggerResource = new SwaggerResource();
        swaggerResource.setName(name);
        swaggerResource.setLocation(location);
        swaggerResource.setSwaggerVersion("2.0");
        return swaggerResource;
    }

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        /** swagger-ui 地址 */
        registry.addResourceHandler("/swagger-ui/**")
            .addResourceLocations("classpath:/META-INF/resources/webjars/springfox-swagger-ui/");
        //favicon.ico
        registry.addResourceHandler("/favicon.ico")
            .addResourceLocations("classpath:/static/");
    }
}
  1. SwaggerHeaderFilter 可选,按需添加
import org.apache.commons.lang3.StringUtils;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.web.server.ServerWebExchange;

/**
 * SwaggerHeaderFilter <br>
 *
 * @date: 2022/3/31 <br>
 * @author: llxiao <br>
 * @since: 1.0 <br>
 * @version: 1.0 <br>
 */
@SuppressWarnings("ALL")
@Configuration
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)) {
                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);
            } else {
                return chain.filter(exchange);
            }
        };
    }
}

微服务Knife4j引用公共组件

  1. pom
<dependencies>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-autoconfigure</artifactId>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-web</artifactId>
      <scope>provided</scope>
    </dependency>

    <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
    </dependency>

    <dependency>
      <groupId>com.github.xiaoymin</groupId>
      <artifactId>knife4j-spring-boot-starter</artifactId>
    </dependency>
  </dependencies>
  1. 代码部分
    2.1. Knife4jConfig 相关配置
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;

/**
 * Knife4jConfig <br>
 *
 * @date: 2021/11/26 <br>
 * @author: llxiao <br>
 * @since: 1.0 <br>
 * @version: 1.0 <br>
 */
@Data
@Configuration
@ConfigurationProperties(prefix = "knife.swagger")
public class Knife4jConfig {

    private String version;
    private String basePackage;
    private String title;
    private String description;
    private String contactName;
    private Boolean enabled;
    private String termsOfServiceUrl = "https://xxx.com";

}

2.2. Knife4jConfiguration 核心实现

import java.util.ArrayList;
import java.util.List;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.bind.annotation.RequestMethod;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.ParameterBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.builders.ResponseMessageBuilder;
import springfox.documentation.schema.ModelRef;
import springfox.documentation.service.Contact;
import springfox.documentation.service.Parameter;
import springfox.documentation.service.ResponseMessage;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2WebMvc;

/**
 * Knife4jConfiguration <br>
 *
 * @date: 2021/11/26 <br>
 * @author: llxiao <br>
 * @since: 1.0 <br>
 * @version: 1.0 <br>
 */
@Configuration
@ComponentScan(basePackages = "com.xx.swagger")
@EnableSwagger2WebMvc
@Slf4j
public class Knife4jConfiguration {

    @Bean(value = "defaultApi2")
    public Docket defaultApi2(Knife4jConfig knife4jConfig) {
        // 自定义统一错误码返回 -需要自行修改,仅供参考
        List<ResponseMessage> responseMessageList = new ArrayList<>();
        for (XXXCommonExceptionCode value : XXXCommonExceptionCode.values()) {
            ResponseMessage build = new ResponseMessageBuilder().code(value.getCode()).message(value.getMsg()).responseModel(
                new ModelRef(value.getMsg())).build();
            responseMessageList.add(build);
        }

        // 自定义通用header 定义  -需要自行修改,仅供参考
        List<Parameter> parameters = new ArrayList<>();
        parameters.add(new ParameterBuilder()
            .name("Auth-Token")
            .description("我是描述")
            .modelRef(new ModelRef("string"))
            .parameterType("header")
            .required(false)
            .build());
        log.info("Knife4j 加载完成....");
        return new Docket(DocumentationType.SWAGGER_2)
            // 自定义错误码
            .globalResponseMessage(RequestMethod.GET, responseMessageList)
            .globalResponseMessage(RequestMethod.POST, responseMessageList)
            .globalResponseMessage(RequestMethod.PUT, responseMessageList)
            .globalResponseMessage(RequestMethod.DELETE, responseMessageList)
            // header参数定义
            .globalOperationParameters(parameters)
            .apiInfo(new ApiInfoBuilder()
                .title(knife4jConfig.getTitle())
                .description(knife4jConfig.getDescription())
                .termsOfServiceUrl(knife4jConfig.getTermsOfServiceUrl())
                .contact(new Contact(knife4jConfig.getContactName(), "", ""))
                .version(knife4jConfig.getVersion())
                .build())
            //分组名称
            // .groupName(knife4jConfig.getVersion())
            .select()
            //这里指定Controller扫描包路径
            .apis(RequestHandlerSelectors.basePackage(knife4jConfig.getBasePackage()))
            .paths(PathSelectors.any())
            .build();
    }
}

2.2.3 EnabledKnife4j 使用注解开启

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.context.annotation.Import;

/**
 * EnabledCustomSwagger2 <br>
 *
 * @date: 2022/3/30 <br>
 * @author: llxiao <br>
 * @since: 1.0 <br>
 * @version: 1.0 <br>
 */
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import({Knife4jConfiguration.class})
public @interface EnabledKnife4j {

}

2.2.4 配置参考

 knife:
   swagger:
     version: 1.0
     basePackage: com.xx.controller
     title: 标题
     description: 描述
     contactName: 联系人
     enabled: true

2.2.5 微服务端引入上述代码和配置,并在主启动类中添加@EnabledKnife4j注解即可

打开使用

http://gateway网关地址/doc.htm

  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值