背景
项目中使用了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源点
注意:本文归作者所有,未经作者允许,不得转载