• 【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");
            }
        }
    }
  • 相关阅读:
    如何防止表单重复提交
    二、编程题
    Java 基础测试题
    常见异常
    Hibernate工作原理及为什么要用?
    简述拦截器的工作原理以及你在项目中使用过哪些自定义拦截器。
    拦截器和过滤器的区别
    浏览器默认样式
    数组去重
    数组排序
  • 原文地址:https://www.cnblogs.com/756623607-zhang/p/11846205.html
Copyright © 2020-2023  润新知