zoukankan      html  css  js  c++  java
  • 【Spring Cloud】Spring Cloud之自定义@SpringCloudProfile注解实现@Profile注解的功能

    一、为什么会想到定义@SpringCloudProfile这样的注解

    首页提一下@Profile注解:它主要用与Spring Boot多环境配置中,指定某个类只在指定环境中生效,比如swagger的配置只允许开发和测试环境开发,线上需要禁止使用。

    使用@Profile进行如下配置:

    @Configuration
    @EnableSwagger2
    @Profile({"dev", "test"})
    public class Swagger2Config { @Bean public Docket docket() { return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()).select() //当前包路径 .apis(RequestHandlerSelectors.basePackage("com.zbq.springbootbase.controller")) .paths(PathSelectors.any()).build(); } //构建api文档的详细信息函数 private ApiInfo apiInfo() { return new ApiInfoBuilder() //页面标题 .title("springboot-base-frame,使用Swagger2构建RESTful API") //创建人 .contact(new Contact("张波清", "756623607@qq.com", "")) //版本号 .version("1.0") //描述 .description("API 描述") .build(); } }

    但是在Spring Cloud中由于使用了配置中心,导致启动项目时没有指定spring.profiles.active属性导致@Profile注解失效,原因就是@Profile通过获取环境变量中spring.profiles.active属性值,与注解中设置的值进行比较,包含就生效。

    所有在Spring Cloud中需要换一个环境变量来实现,正好有spring.cloud.config.profile这个变量,该变量用于指定读取配置中心那个环境配置的,一般有这些值,dev、test、prod

    二、自定义@SpringCloudProfile注解的实现

    1)定义@SpringCloudProfile注解

    /**
     * @author zhangboqing
     * @date 2019/11/12
     */
    @Target({ElementType.TYPE, ElementType.METHOD})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Conditional(SpringCloudProfileCondition.class)
    public @interface SpringCloudProfile {
    
        /**
         * The set of profiles for which the annotated component should be registered.
         */
        String[] value();
    
    }

    2)实现SpringCloudProfileCondition类,用于条件匹配

    /**
     * @author zhangboqing
     * @date 2019/11/12
     */
    public class SpringCloudProfileCondition implements Condition {
    
        public static final String ACTIVE_PROFILES_PROPERTY_NAME = "spring.cloud.config.profile";
    
        @Override
        public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
            MultiValueMap<String, Object> attrs = metadata.getAllAnnotationAttributes(SpringCloudProfile.class.getName());
            if (attrs != null) {
                for (Object value : attrs.get("value")) {
                    if (acceptsProfiles(context,(String[]) value)) {
                        return true;
                    }
                }
                return false;
            }
            return true;
        }
    
        public boolean acceptsProfiles(ConditionContext context,String... profiles) {
            Assert.notEmpty(profiles, "Must specify at least one profile");
            for (String profile : profiles) {
                if (StringUtils.hasLength(profile) && profile.charAt(0) == '!') {
                    if (!isProfileActive(context,profile.substring(1))) {
                        return true;
                    }
                }
                else if (isProfileActive(context,profile)) {
                    return true;
                }
            }
            return false;
        }
    
        protected boolean isProfileActive(ConditionContext context,String profile) {
            validateProfile(profile);
            String property = context.getEnvironment().getProperty(ACTIVE_PROFILES_PROPERTY_NAME);
            return property.equals(profile);
        }
    
        protected void validateProfile(String profile) {
            if (!StringUtils.hasText(profile)) {
                throw new IllegalArgumentException("Invalid profile [" + profile + "]: must contain text");
            }
            if (profile.charAt(0) == '!') {
                throw new IllegalArgumentException("Invalid profile [" + profile + "]: must not begin with ! operator");
            }
        }
    }
  • 相关阅读:
    react组件销毁中清理异步操作和取消请求
    只要一行代码,实现五种 CSS 经典布局
    vue中如何安装sass,sass安装命令
    每日总结
    每日总结
    每日总结
    每周总结
    每日总结
    每日总结
    每日总结
  • 原文地址:https://www.cnblogs.com/756623607-zhang/p/11846205.html
Copyright © 2011-2022 走看看