swagger之API接口版本控制+demo案例

springboot整合swagger配置在之前的文章已经写过了,此篇是基于已整合swagger后的,关于版本控制的配置和demo案例。

文章地址:swagger2 注解详解+使用案例

版本控制思路:

此demo是基于swagger的group进行版本控制,对接口URL无侵入,版本对接口地址无影响。

相关操作和注意项:

  1. 无新增依赖jar包;
  2. 新增自定义版本注解ApiVersion ;
  3. 新增版本号定义(常量或枚举值都行);
  4. 手动实例化Docket对象,并注入到spring容器;
  5. 相关解释都在代码注释里;

自定义版本注解

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

    /**
     * 分组名(即版本号)
     *
     * @return
     */
    String[] value() default CustomVersion.VERSION_1;

}

版本号

public interface CustomVersion {
    String VERSION_1 = "v1";
    String VERSION_2 = "v2";
}

无版本控制的配置

通过@Configuration + @Bean注解直接自动注入到spring容器中。

    @Bean
    public Docket docketDefault() {
        // 设置要显示swagger的环境
        // 通过 enable() 接收此参数判断是否要显示
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                //不展示默认的Response信息
                .useDefaultResponseMessages(false)
                //默认为default
                .groupName("all")
                // 配置是否启用Swagger,如果是false,在浏览器将无法访问
//                 .enable(false)
                // 通过.select()方法,去配置扫描接口,RequestHandlerSelectors配置如何扫描接口
                .select()
                //配置你想在那个controller层生产接口文档
                .apis(RequestHandlerSelectors.basePackage("ai.ecarx.data.syn.controller"))
                // 配置如何通过path过滤,即这里只扫描请求以 /search 开头的接口
//                .paths(PathSelectors.ant("/search/**"))
                .build();
    }

版本控制的配置(重点)

通过继承 InitializingBean 类,自动执行手动将Docket实例注入spring容器中。

@Configuration
public class SwaggerConfig implements InitializingBean {

    @Autowired
    private ApplicationContext applicationContext;
    public Docket docketVersion(String groupName){
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                .useDefaultResponseMessages(false)
                .groupName(groupName)
                .select()
                //版本控制
                .apis(
                        method -> {
                            // 每个方法会进入这里进行判断并归类到不同分组,**请不要调换下面两段代码的顺序,在方法上的注解有优先级**
                            // 该方法上标注了版本
                            Optional<ApiVersion> methodAnnotation = method.findAnnotation(ApiVersion.class);
                            if (methodAnnotation.isPresent()) {
                                return Arrays.asList(methodAnnotation.get().value()).contains(groupName);
                            }
                            // controller上标注了版本
                            Optional<ApiVersion> controllerAnnotation = method.findControllerAnnotation(ApiVersion.class);
                            if (controllerAnnotation.isPresent()) {
                                return Arrays.asList(controllerAnnotation.get().value()).contains(groupName);
                            }
                            return false;
                        })
                .build();
    }

    /**
     * 动态得创建Docket bean
     *
     * @throws Exception
     */
    @Override
    public void afterPropertiesSet() throws Exception {
        // ApiConstantVersion 里面定义的每个变量会成为一个docket
        Class<CustomVersion> clazz = CustomVersion.class;
        Field[] declaredFields = clazz.getDeclaredFields();

        // 动态注入bean
        AutowireCapableBeanFactory autowireCapableBeanFactory = applicationContext.getAutowireCapableBeanFactory();
        if (autowireCapableBeanFactory instanceof DefaultListableBeanFactory) {

            DefaultListableBeanFactory capableBeanFactory = (DefaultListableBeanFactory) autowireCapableBeanFactory;
            for (Field declaredField : declaredFields) {

                // 要注意 "工厂名和方法名",意思是用这个bean的指定方法创建docket
                AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder
                        .genericBeanDefinition()
                        //此处的swaggerConfig首字母要小写否则报找不到bean的方法
                        .setFactoryMethodOnBean("docketVersion", "swaggerConfig")
                        .addConstructorArgValue(declaredField.get(CustomVersion.class)).getBeanDefinition();
                capableBeanFactory.registerBeanDefinition(declaredField.getName(), beanDefinition);
            }
        }

    }

    /**
     * 配置文档信息
     */
    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .version("1.0")
                .title("swagger API")
                .description("接口描述")
                .build();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值