Swagger文档Knife4J文档Docket分栏分组优化,改为配置文件

Swagger文档Knife4J文档Docket分栏分组优化,改为配置文件

​ Swagger快速调试接口还是很方便的,Knife4J的美化包后的Swagger文档页面更加舒适,但是当接口非常多时,找起来就很不方便,所以有了Docket分栏分组,但是需要手动在Swagger配置Bean里添加各种Docket配置,非常不方便,所以写了个简单的配置功能注解,用于从配置文件中读取实现自动Docket分栏。

先看使用效果:

一、Springboot启动类上添加编写的自定义注解@EnableSwaggerDocket

可选参数enableEnv用于控制Swagger文档在哪些环境启用,不传递默认在dev和test环境打开,其他环境文档将不显示。


@SpringBootApplication
@EnableSwaggerDocket(enableEnv = {"dev", "test", "default", "local"})
public class TestSwaggerApplication {
    public static void main(String[] args) {
       SpringApplication.run(TestSwaggerApplication.class, args);
    }
}

二、在启动配置文件如bootstrap.yamlapplication.yaml中添加以下配置:

swagger:
  docket-config:
    dockets:
      - id: education
        groupName: 教育培训责任
        basePackage: com.chabits.api.education
      - id: safety
        groupName: 安全管理责任
        basePackage: com.chabits.api.safety
      - id: committee
        groupName: 专委会责任
        basePackage: com.chabits.api.committee

注意id不可重复,否则会被覆盖,groupName即分栏名称,basePackage是接口所在包名,包下面的所有接口都会被添加到该分栏。

三、启动项目,访问文档地址,切换Docket查看效果

在这里插入图片描述

下面贴自定义注解@EnableSwaggerDocket实现代码:

package com.chabits.common.annotations;

import io.swagger.annotations.ApiOperation;
import lombok.Data;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.context.properties.bind.BindResult;
import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.env.Environment;
import org.springframework.core.env.Profiles;
import org.springframework.core.type.AnnotationMetadata;
import springfox.documentation.RequestHandler;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;

import java.lang.annotation.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.Predicate;

/**
 * 开启Swagger Docket分栏
 *
 * @author Q**
 * @date 2024/01/03
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(EnableSwaggerDocket.SwaggerDocketRegister.class)
public @interface EnableSwaggerDocket {

    /**
     * 根据环境控制Swagger文档显示 <br />
     * 默认仅在 {@code dev/test} 环境显示文档, 其他环境不显示
     * 语法同 {@link Profiles#of(String...)}
     */
    String[] enableEnv() default {"dev", "test"};

    class SwaggerDocketRegister implements ImportBeanDefinitionRegistrar, EnvironmentAware {
        private Environment env;

        /**
         * 扫描 {@code swagger.docket-config} 配置 动态创建Docket <br />
         * 创建默认Docket 默认扫描所有标记了{@link ApiOperation}注解的接口
         *
         * @see SwaggerDocketAutoConfiguration
         */
        @Override
        public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
            Map<String, Object> attributes = importingClassMetadata.getAnnotationAttributes(EnableSwaggerDocket.class.getName());
            if (attributes != null) {
                String[] enableEnvs = (String[]) attributes.get("enableEnv");
                boolean enable = env.acceptsProfiles(Profiles.of(enableEnvs));
                registryDocket(registry, "defaultDocket", "Knife4J 接口文档", "default", RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class), enable);

                BindResult<SwaggerDocketAutoConfiguration> bind = Binder.get(env).bind("swagger.docket-config", SwaggerDocketAutoConfiguration.class);
                bind.ifBound(docketConfiguration -> {
                    if (docketConfiguration.dockets != null && docketConfiguration.dockets.size() > 0) {
                        docketConfiguration.dockets.forEach(docketConfig -> registryDocket(registry, docketConfig, enable));
                    }
                });
            }
        }


        private void registryDocket(BeanDefinitionRegistry registry, SwaggerDocketAutoConfiguration.DocketConfig docketConfig, boolean enable) {
            this.registryDocket(registry, docketConfig.getId(), docketConfig.getGroupName(), docketConfig.getGroupName(), RequestHandlerSelectors.basePackage(docketConfig.getBasePackage()), enable);
        }

        /**
         * 注入Docket到清单
         */
        private void registryDocket(BeanDefinitionRegistry registry, String id, String title, String groupName, Predicate<RequestHandler> selector, boolean enable) {
            BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(GroupByDocket.class)
                    .addConstructorArgValue(title)
                    .addConstructorArgValue(groupName)
                    .addConstructorArgValue(selector)
                    .addConstructorArgValue(enable);
            registry.registerBeanDefinition("SwaggerDocket" + id, builder.getBeanDefinition());
        }

        @Override
        public void setEnvironment(Environment environment) {
            this.env = environment;
        }

    }

    @Data
    @EnableConfigurationProperties(SwaggerDocketAutoConfiguration.class)
    @ConfigurationProperties(prefix = "swagger.docket-config")
    class SwaggerDocketAutoConfiguration {

        private List<DocketConfig> dockets = new ArrayList<>();

        @Data
        public static class DocketConfig {
            private String id;
            private String groupName;
            private String basePackage;
        }
    }

    class GroupByDocket extends Docket {

        public GroupByDocket(String title, String groupName, Predicate<RequestHandler> selector, boolean enable) {
            super(DocumentationType.SWAGGER_2);
            super.enable(enable)
                    .apiInfo(new ApiInfoBuilder()
                            .title(title)
                            .description(title + "相关API")
                            .version("1.0")
                            .build()
                    ).groupName(groupName)
                    .select()
                    .apis(selector)
                    .paths(PathSelectors.any())
                    .build();
        }
    }
}

注:如果希望写配置文件有提示,或者看idea标红烦人,可以引入spring官方的配置处理器,生成配置规约文件。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-configuration-processor</artifactId>
</dependency>

maven中引入后清理并重新打包后,就会在写yaml时有提示了:
提示效果
其实主要是打包后生成了这个东西:
配置规约

  • 8
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值