springboot整合disconf获取不到dubbo配置

star2017 1年前 ⋅ 566 阅读

背景

项目中使用了springboot框架,配置文件使用disconf来管理,在整合过程中遇到了不少问题,以此记录下。

disconf xml

在使用disconf xml配置的时候,在idea里面启动是正常的,然后很开心的打成war包,发布到测试环境,启动失败,报的错误是没有指定启动文件。

disconf If you have database settings to be loaded from a particular profile you may need to active it (no profiles are currently active).

查看application.properties,是有值的,google了一番,发现可能是加载顺序的问题,在启动一次就可以正常启动了。这样肯定是不合理的,网上说把xml换成@Configuration类,可以解决,然后决定试一试。

Configuration bean

@Configuration("disconfConfig")
@Order(Ordered.HIGHEST_PRECEDENCE)
@ImportResource(locations = {"classpath:spring/spring-sentinel.xml"})
@AutoConfigureBefore({SpringBootApplication.class, DubboAutoConfiguration.class})
public class DisconfAutoConfiguration implements EnvironmentAware {
    private ConfigurableEnvironment environment;

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

    /**
     * 设置扫描包路径
     * 初始化DisconfMgrBean
     *
     * @return DisconfMgrBean
     */
    @Bean(destroyMethod = "destroy")
    public DisconfMgrBean disconfMgrBean() {
        DisconfMgrBean disconfMgrBean = new DisconfMgrBean();
        disconfMgrBean.setScanPackage("cn.com.*");
        return disconfMgrBean;
    }

    /**
     * 二次扫描注入属性
     *
     * @return DisconfMgrBeanSecond
     */
    @Bean(initMethod = "init", destroyMethod = "destroy")
    public DisconfMgrBeanSecond disconfMgrBeanSecond() {
        return new DisconfMgrBeanSecond();
    }

    /**
     * 使用托管方式的disconf配置
     *
     * @return ReloadablePropertiesFactoryBean
     */
    @Bean("disconfUnReloadablePropertiesFactoryBean")
    public ReloadablePropertiesFactoryBean disconfUnReloadablePropertiesFactoryBean() {
        ReloadablePropertiesFactoryBean factoryBean = new ReloadablePropertiesFactoryBean();
        factoryBean.setLocation("classpath*:application.properties");
        return factoryBean;
    }

    /**
     * 当配置文件改变,不会自动reload到系统
     *
     * @param factoryBean 不会自动reload配置工厂
     * @return PropertyPlaceholderConfigurer
     * @throws IOException IOException
     */
    @Bean
    public PropertyPlaceholderConfigurer disconfPropertyPlaceholderConfigurer(
            @Qualifier("disconfUnReloadablePropertiesFactoryBean") ReloadablePropertiesFactoryBean factoryBean) throws IOException {
        PropertyPlaceholderConfigurer configurer = new PropertyPlaceholderConfigurer();
        configurer.setOrder(Ordered.HIGHEST_PRECEDENCE);
        configurer.setIgnoreResourceNotFound(true);
        configurer.setIgnoreUnresolvablePlaceholders(true);
        configurer.setProperties(factoryBean.getObject());
        addPropertiesPropertySource("disconfUnReloadableProperties", factoryBean.getObject());
        return configurer;
    }

    /**
     * 使用托管方式的disconf配置
     *
     * @return ReloadablePropertiesFactoryBean
     */
    @Bean("disconfReloadablePropertiesFactoryBean")
    public ReloadablePropertiesFactoryBean disconfReloadablePropertiesFactoryBean() {
        ReloadablePropertiesFactoryBean factoryBean = new ReloadablePropertiesFactoryBean();
        factoryBean.setLocation("classpath*:application.properties");
        return factoryBean;
    }

    /**
     * 当配置文件改变,会自动reload到系统
     *
     * @param factoryBean 会自动reload配置工厂
     * @return ReloadingPropertyPlaceholderConfigurer
     * @throws IOException IOException
     */
    @Bean
    public ReloadingPropertyPlaceholderConfigurer disconfReloadingPropertyPlaceholderConfigurer(
            @Qualifier("disconfReloadablePropertiesFactoryBean") ReloadablePropertiesFactoryBean factoryBean) throws IOException {
        ReloadingPropertyPlaceholderConfigurer configurer = new ReloadingPropertyPlaceholderConfigurer();
        configurer.setOrder(Ordered.HIGHEST_PRECEDENCE);
        configurer.setIgnoreResourceNotFound(true);
        configurer.setIgnoreUnresolvablePlaceholders(true);
        configurer.setProperties(factoryBean.getObject());
        addPropertiesPropertySource("disconfReloadableProperties", factoryBean.getObject());
        return configurer;
    }

    /**
     * 增加环境变量配置
     *
     * @param name   配置文件名
     * @param source 文件源
     */
    private void addPropertiesPropertySource(String name, Properties source) {
        PropertiesPropertySource propertiesPropertySource = new PropertiesPropertySource(name, source);
        environment.getPropertySources().addLast(propertiesPropertySource);
    }

}

换成配置类之后,上面的错误没有出现了,但是因为项目使用了dubbo,还是用xml来引入,导致第一次启动,获取不到xml里面的配置,报错如:

java.util.concurrent.ExecutionException: org.I0Itec.zkclient.exception.ZkException: Unable to connect to ${xxxx.dubbo.registry.address}:9090

第二次启动又可以获取到,这样也是不合理的。
接着就是把dubbo在xml里面的配置也使用bean来配置,示例如下:

@Configuration
@EnableDubbo
@Slf4j
@Component
public class MyDubboConfig {
    @Value("${spring.dubbo.application.name}")
    private String applicationName;
    @Value("${spring.dubbo.application.owner}")
    private String applicationOwner;
    @Value("${spring.dubbo.application.organization}")
    private String applicationOrganization;
    /**
     * 相当于此bean替代了dubbo.application.* 标签
     * @return applicationConfig
     */
    @Bean
    public ApplicationConfig applicationConfig() {
        ApplicationConfig applicationConfig = new ApplicationConfig();
        //设置应用名
        applicationConfig.setName(applicationName);
        applicationConfig.setOwner(applicationOwner);
        applicationConfig.setOrganization(applicationOrganization);
        return applicationConfig;
    }

    @Value("${xx.dubbo.address}")
    private String xxZkAddress;
    @Value("${xx.dubbo.group}")
    private String xxGroup;
    @Value("${xx.dubbo.version}")
    private String xxVersion;
    /**
     * 设置注册中心配置
     * @return
     */
    @Bean
    public RegistryConfig xxRegister() {
        RegistryConfig registryConfig = new RegistryConfig();
        registryConfig.setAddress(xxZkAddress);
        registryConfig.setProtocol("zookeeper");
        registryConfig.setCheck(false);
        return registryConfig;
    }

    @Bean("loginxxFacade")
    public LoginxxFacade loginxxFacade(ApplicationConfig applicationConfig,RegistryConfig xxRegister) {
        ReferenceConfig<LoginxxFacade> reference = new ReferenceConfig<>();
        reference.setApplication(applicationConfig);
        reference.setRegistry(xxRegister);
        reference.setInterface(LoginxxFacade.class);
        reference.setGroup(xxGroup);
        reference.setVersion(xxVersion);
        reference.setTimeout(10000);
        reference.setCheck(false);
        return reference.get();
    }
}

通过改成类之后,可以获取到值了,启动也不报错了。

logback日志

启动之后,去查看日志,发现日志目录不是在配置文件中配置的目录,发现获取不到值。部分配置:

<springProperty scope="context" name="log.path" source="logging.root"  defaultValue="${catalina.home:-./../}/logs"/>
<springProperty scope="context" name="app.name" source="spring.application.name"/>
<appender name="DEFAULT-APPENDER" class="ch.qos.logback.core.rolling.RollingFileAppender">

        <file>${log.path}/${app.name}/common-default.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <FileNamePattern>
                ${log.path}/${app.name}/common-default.log.%d{yyyy-MM-dd}
            </FileNamePattern>
            <MaxHistory>10</MaxHistory>
        </rollingPolicy>
        <encoder charset="UTF-8">
            <pattern>
                ${CONSOLE_LOG_PATTERN}
            </pattern>
        </encoder>
    </appender>

目前的解决是每个项目都设置一个默认值,如果获取不到就使用默认值。
也可以关注我的公众号:程序之声

本文为博主原创文章,未经博主允许不得转载。
更多内容请访问:IT源点

相关文章推荐

全部评论: 0

    我有话说: