swagger 实现版本的动态配置

先上效果图:

swagger版本控制
不同版本的接口在不同的swagger版本分组中,我们通过在请求接口上添加自定义注解来对请求接口的版本分组;然后在构建 Docket 时,基于注解的值执行不同的处理逻辑,参考下面代码的 buildDocketWithGroupName 方法。


之前的版本配置是通过如下的代码的:

@Configuration
@EnableSwagger2
@EnableWebMvc
public class SwaggerConfig {

    //默认版本的接口api-docs分组
    @Bean
    public Docket vDefault() {
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(buildApiInf())
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.gysoft"))//controller路径
                .paths(PathSelectors.any())
                .build();
    }

    @Bean
    public Docket vInfo210() {
        return buildDocketWithGroupName(ApiVersionConstant.INFO_V210);
    }

    @Bean
    public Docket vInfo220() {
        return buildDocketWithGroupName(ApiVersionConstant.INFO_V220);
    }

    @Bean
    public Docket vInfo230() {
        return buildDocketWithGroupName(ApiVersionConstant.INFO_V230);
    }

    @Bean
    public Docket v100() {
        return buildDocketWithGroupName(ApiVersionConstant.INFO_V100);
    }

    @Bean
    public Docket v201() {
        return buildDocketWithGroupName(ApiVersionConstant.INFO_V201);
    }


    private ApiInfo buildApiInf() {
        return new ApiInfoBuilder()
                .title("接口列表")
                .termsOfServiceUrl("http://127.0.0.1:8080/swagger-ui.html")
                .description("springmvc swagger 接口测试")
                .version("1.0.0")
                .build();
    }

    private Docket buildDocketWithGroupName(String groupName) {
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(buildApiInf())
                .groupName(groupName)
                .select()
                .apis(input -> {
                    if (input.getHandlerMethod().hasMethodAnnotation(ApiVersion.class)) {
                        ApiVersion apiVersion = input.getHandlerMethod().getMethodAnnotation(ApiVersion.class);
                        if (apiVersion.group() != null && apiVersion.group().length != 0) {
                            if (Arrays.asList(apiVersion.group()).contains(groupName)) {
                                return true;
                            }
                        }
                        if (apiVersion.value() != null && apiVersion.value().length != 0) {
                            if (Arrays.asList(apiVersion.value()).contains(groupName)) {
                                return true;
                            }
                        }

                    }
                    ApiVersion clzzApiVersion = input.getHandlerMethod().getBeanType().getAnnotation(ApiVersion.class);
                    if (clzzApiVersion != null) {
                        if (clzzApiVersion.group() != null && clzzApiVersion.group().length != 0) {
                            if (Arrays.asList(clzzApiVersion.group()).contains(groupName)) {
                                return true;
                            }
                        }
                        if (clzzApiVersion.value() != null && clzzApiVersion.value().length != 0) {
                            if (Arrays.asList(clzzApiVersion.value()).contains(groupName)) {
                                return true;
                            }
                        }
                    }
                    return false;
                })//controller路径
                .paths(PathSelectors.any())
                .build();
    }

}

可以看出每在ApiVersionConstant 中增加一个版本(即一个常量值),我们需要在 Spring 中注册一个对应的 Docket;这也太不方便了,既然 Spring 的 bean 可以在编程时动态注入,那么就能解决这个问题了。修改代码如下:

@Configuration
@EnableSwagger2
@EnableWebMvc
public class SwaggerConfig implements InitializingBean {

    @Autowired
    private ApplicationContext applicationContext;

    //默认版本的接口api-docs分组
    @Bean
    public Docket vDefault() {
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(buildApiInf())
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.gysoft"))//controller路径
                .paths(PathSelectors.any())
                .build();
    }

    private ApiInfo buildApiInf() {
        return new ApiInfoBuilder()
                .title("接口列表")
                .termsOfServiceUrl("http://127.0.0.1:8080/swagger-ui.html")
                .description("springmvc swagger 接口测试")
                .version("1.0.0")
                .build();
    }

    private Docket buildDocketWithGroupName(String groupName) {
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(buildApiInf())
                .groupName(groupName)
                .select()
                .apis(input -> {
                    if (input.getHandlerMethod().hasMethodAnnotation(ApiVersion.class)) {
                        ApiVersion apiVersion = input.getHandlerMethod().getMethodAnnotation(ApiVersion.class);
                        if (apiVersion.group() != null && apiVersion.group().length != 0) {
                            if (Arrays.asList(apiVersion.group()).contains(groupName)) {
                                return true;
                            }
                        }
                        if (apiVersion.value() != null && apiVersion.value().length != 0) {
                            if (Arrays.asList(apiVersion.value()).contains(groupName)) {
                                return true;
                            }
                        }

                    }
                    ApiVersion clzzApiVersion = input.getHandlerMethod().getBeanType().getAnnotation(ApiVersion.class);
                    if (clzzApiVersion != null) {
                        if (clzzApiVersion.group() != null && clzzApiVersion.group().length != 0) {
                            if (Arrays.asList(clzzApiVersion.group()).contains(groupName)) {
                                return true;
                            }
                        }
                        if (clzzApiVersion.value() != null && clzzApiVersion.value().length != 0) {
                            if (Arrays.asList(clzzApiVersion.value()).contains(groupName)) {
                                return true;
                            }
                        }
                    }
                    return false;
                })//controller路径
                .paths(PathSelectors.any())
                .build();
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        // 根据ApiConstantVersion构造 docket
        Class<ApiVersionConstant> clzz = ApiVersionConstant.class;
        Field[] declaredFields = clzz.getDeclaredFields();
        // 动态注入bean
        AutowireCapableBeanFactory autowireCapableBeanFactory = applicationContext.getAutowireCapableBeanFactory();
        if(autowireCapableBeanFactory instanceof DefaultListableBeanFactory){
            DefaultListableBeanFactory capableBeanFactory = (DefaultListableBeanFactory) autowireCapableBeanFactory;
            for (Field declaredField : declaredFields) {
                AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().setFactoryMethodOnBean("buildDocketWithGroupName", "swaggerConfig")
                        .addConstructorArgValue(declaredField.get(ApiVersionConstant.class)).getBeanDefinition();
                capableBeanFactory.registerBeanDefinition(declaredField.getName(), beanDefinition);
            }
        }
    }
}

值得一提的是,我们这里通过注解来识别对应接口所属版本,具体实现参考方法:buildDocketWithGroupName。注解可以在 controller 上,也可以在它的方法上,方法上的优先级大于 controller上的版本注解优先级。注解在 controller 上默认当前类下的所有方法都属于这一版本。


下面是注解类的代码:

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
public @interface ApiVersion {

    /**
     * 接口版本号(对应swagger中的group)
     *
     * @return String[]
     */
    String[] group() default {};

    /**
     * 接口版本号(对应swagger中的value)
     *
     * @return String[]
     */
    String[] value() default {};

}

这里还有个优化可以做掉,那就是 apiInfo 应该针对不同版本使用不同的值,也就是 buildApiInf 方法。

如果你觉得我的文章对你有所帮助的话,欢迎关注我的公众号。赞!我与风来
认认真真学习,做思想的产出者,而不是文字的搬运工。错误之处,还望指出!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值