spring cloud 整合knife4j 增强swagger

一. 介绍

Knife4j一直致力于将目前的Ui提供给更多的平台或者别的语言使用而努力,经过这么长时间的发展,Knife4j提供的轻量级聚合中间件终于诞生了,自2.0.8版本开始,Knife4j 提供了knife4j-aggregation-spring-boot-starter组件,该组件是一个基于Spring Boot系统的starter,他提供了以下几种能力:

  • 最轻量级、最简单、最方便的聚合OpenApi规范的中间件
  • 让所有的基于Spring Boot的Web体系拥有了轻松聚合OpenApi的能力
  • 提供4种模式供开发者选择
    • 基于本地静态JSON文件的方式聚合OpenAPI
    • 基于云端HTTP接口的方式聚合
    • 基于Eureka注册中心的方式聚合
    • 基于Nacos注册中心的方式聚合
  • 基于该starter发布了Docker镜像,跨平台与语言让开发者基于此Docker镜像轻松进行聚合OpenAPI规范
  • 完美兼容所有Spring Boot版本,没有兼容性问题
  • 开发者可以彻底放弃基于Zuul、Spring Cloud Gateway等复杂的聚合方式
  • 兼容OpenAPI2规范以及OpenAPI3规范

二. 实际使用

1. 普通微服务引入

  • 只需要引入knife4j 核心包,不需要引入ui
    1. <dependency>
    2. <groupId>com.github.xiaoymin</groupId>
    3. <artifactId>knife4j-micro-spring-boot-starter</artifactId>
    4. </dependency>

2. 网关层引入

  • 网关层引入knife4j 核心 + ui 进行统一管理
    1. <dependency>
    2. <groupId>com.github.xiaoymin</groupId>
    3. <artifactId>knife4j-spring-boot-starter</artifactId>
    4. </dependency>

3. 普通微服务配置

  • micro-cloud项目通过 micro-starter-web 统一引入配置,减少不需要的操作,请求头根据实际项目进行修改
    ```java /**

    • @ClassName SwaggerConfig
    • TODO: 类文件简单描述
    • @Author: 小白
    • @UpdateUser: 小白
    • @Version: 1.0.0 */ @Configuration @AllArgsConstructor //@Profile({“!prod”}) @EnableSwagger2 @EnableConfigurationProperties(SwaggerProperty.class) public class SwaggerConfig {

      private final SwaggerProperty swaggerProperties;

      // 定义分隔符 private static final String splitor = “;”; @Bean public Docket createRestApi() { /**

      1. * 这是为了我们在用 swagger 测试接口的时候添加头部信息
      2. */

      List pars = new ArrayList(); ParameterBuilder tokenPar = new ParameterBuilder(); tokenPar.name(“Access-Token”).description(“swagger测试用(模拟Access-Token传入)非必填 header”).modelRef(new ModelRef(“string”)).parameterType(“header”).required(false); /**

      1. * 多个的时候 就直接添加到 pars 就可以了
      2. */

      pars.add(tokenPar.build()); return new Docket(DocumentationType.SWAGGER_2)

      1. .apiInfo(apiInfo())
      2. .select()
      3. .apis(RequestHandlerSelectors.withClassAnnotation(Api.class))
      4. .paths(PathSelectors.any())
      5. .build()
      6. .globalOperationParameters(pars)
      7. .enable(swaggerProperties.isEnabled())
      8. ;

      }

      private ApiInfo apiInfo() { return new ApiInfoBuilder()

      1. .title(swaggerProperties.getTitle())
      2. .description(swaggerProperties.getDescription())
      3. .termsOfServiceUrl("")
      4. .version(swaggerProperties.getApiVersion())
      5. .build();

      }

  1. public static Predicate<RequestHandler> basePackage(final String basePackage) {
  2. return input -> declaringClass(input).transform(handlerPackage(basePackage)).or(true);
  3. }
  4. private static Function<Class<?>, Boolean> handlerPackage(final String basePackage) {
  5. return input -> {
  6. // 循环判断匹配
  7. for (String strPackage : basePackage.split(splitor)) {
  8. boolean isMatch = input.getPackage().getName().startsWith(strPackage);
  9. if (isMatch) {
  10. return true;
  11. }
  12. }
  13. return false;
  14. };
  15. }
  16. private static Optional<? extends Class<?>> declaringClass(RequestHandler input) {
  17. return Optional.fromNullable(input.declaringClass());
  18. }

}

  1. - swagger 配置文件
  2. ```java
  3. /**
  4. * @ClassName SwaggerProperty
  5. * TODO: 自定义swagger配置
  6. * @Author: 小白
  7. * @UpdateUser: 小白
  8. * @Version: 1.0.0
  9. */
  10. @Data
  11. @ConfigurationProperties(prefix = "micro.swagger2")
  12. public class SwaggerProperty {
  13. /**
  14. * 是否启用swagger,生产环境建议关闭
  15. */
  16. private boolean enabled;
  17. /**
  18. * 文档标题
  19. */
  20. private String title;
  21. /**
  22. * 文档描述
  23. */
  24. private String description;
  25. /**
  26. * 客户端ID
  27. */
  28. private String clientId;
  29. /**
  30. * 客户端密钥
  31. */
  32. private String clientSecret;
  33. /**
  34. * 客户端授权范围
  35. */
  36. private String scope;
  37. /**
  38. * 获取token
  39. */
  40. private String accessTokenUri;
  41. /**
  42. * 认证地址
  43. */
  44. private String userAuthorizationUri;
  45. /**
  46. * 文档版本
  47. * */
  48. private String apiVersion;
  49. }
  • 项目配置文件中,写入配置参数
    1. micro:
    2. swagger2:
    3. enabled: true
    4. title: 用户后台管理
    5. api-version: v1
    6. description: 用户后台管理

4. 网关层统一配置

  1. @GetMapping("/swagger-resources/configuration/security")
  2. public Mono<ResponseEntity<SecurityConfiguration>> securityConfiguration() {
  3. return Mono.just(new ResponseEntity<>(
  4. Optional.ofNullable(securityConfiguration).orElse(SecurityConfigurationBuilder.builder().build()), HttpStatus.OK));
  5. }
  6. @GetMapping("/swagger-resources/configuration/ui")
  7. public Mono<ResponseEntity<UiConfiguration>> uiConfiguration() {
  8. return Mono.just(new ResponseEntity<>(
  9. Optional.ofNullable(uiConfiguration).orElse(UiConfigurationBuilder.builder().build()), HttpStatus.OK));
  10. }
  11. @GetMapping("/swagger-resources")
  12. public Mono<ResponseEntity> swaggerResources() {
  13. return Mono.just((new ResponseEntity<>(swaggerResources.get(), HttpStatus.OK)));
  14. }

}

  1. - SwaggerHeaderFilter
  2. ```java
  3. /**
  4. * @link https://gitee.com/xiaoym/swagger-bootstrap-ui-demo/blob/master/knife4j-spring-cloud-gateway/service-doc/src/main/java/com/xiaominfo/swagger/service/doc/config/SwaggerHeaderFilter.java
  5. * @auth xianrui
  6. * @date 2021-02-25 16:29
  7. */
  8. @Component
  9. public class SwaggerHeaderFilter extends AbstractGatewayFilterFactory {
  10. private static final String HEADER_NAME = "X-Forwarded-Prefix";
  11. private static final String URI = "/v2/api-docs";
  12. @Override
  13. public GatewayFilter apply(Object config) {
  14. return (exchange, chain) -> {
  15. ServerHttpRequest request = exchange.getRequest();
  16. String path = request.getURI().getPath();
  17. if (!StringUtils.endsWithIgnoreCase(path,URI )) {
  18. return chain.filter(exchange);
  19. }
  20. String basePath = path.substring(0, path.lastIndexOf(URI));
  21. ServerHttpRequest newRequest = request.mutate().header(HEADER_NAME, basePath).build();
  22. ServerWebExchange newExchange = exchange.mutate().request(newRequest).build();
  23. return chain.filter(newExchange);
  24. };
  25. }
  26. }

@Slf4j @Component @Primary @AllArgsConstructor public class SwaggerResourceConfig implements SwaggerResourcesProvider {

  1. private final RouteLocator routeLocator;
  2. private final GatewayProperties gatewayProperties;
  3. @Override
  4. public List<SwaggerResource> get() {
  5. List<SwaggerResource> resources = new ArrayList<>();
  6. List<String> routes = new ArrayList<>();
  7. routeLocator.getRoutes().subscribe(route -> routes.add(route.getId()));
  8. gatewayProperties.getRoutes().stream().filter(routeDefinition -> routes.contains(routeDefinition.getId())).forEach(route -> {
  9. route.getPredicates().stream()
  10. .filter(predicateDefinition -> ("Path").equalsIgnoreCase(predicateDefinition.getName()))
  11. .forEach(predicateDefinition -> resources.add(swaggerResource(route.getId(),
  12. predicateDefinition.getArgs().get(NameUtils.GENERATED_NAME_PREFIX + "0")
  13. .replace("**", "v2/api-docs"))));
  14. });
  15. return resources;
  16. }
  17. private SwaggerResource swaggerResource(String name, String location) {
  18. log.info("name:{},location:{}",name,location);
  19. SwaggerResource swaggerResource = new SwaggerResource();
  20. swaggerResource.setName(name);
  21. swaggerResource.setLocation(location);
  22. swaggerResource.setSwaggerVersion("2.0");
  23. return swaggerResource;
  24. }

} ```

5. 效果

第六章 spring cloud 整合knife4j 增强swagger - 图1

接口文档

第六章 spring cloud 整合knife4j 增强swagger - 图2

请求参数、响应参数指定

第六章 spring cloud 整合knife4j 增强swagger - 图3

接口调试

第六章 spring cloud 整合knife4j 增强swagger - 图4

离线文档导出,可选择不同格式

第六章 spring cloud 整合knife4j 增强swagger - 图5