上一篇介绍了基于annotation的分布式配置管理,但该种方式对代码的侵入性太大,我们已有很多项目需要使用该配置平台,所以不能有太多的代码侵入性,这篇来介绍下基于xml的分布式配置管理,以MysqL举例,我们项目中连接MysqL是用的spring-data-jpa。
同基于annotation的分布式配置管理一样,我们需要首先在pom中引入disconf的依赖,准备好disconf.properties文件放入到项目中resources文件夹下,修改applicationContext.xml加入相应的配置。
- 数据准备
DROP DATABASE IF EXISTS `disconf_demo`;
CREATE DATABASE `disconf_demo`;
USE `disconf_demo`;
-- ----------------------------
-- Table structure for `activity`
-- ----------------------------
DROP TABLE IF EXISTS `activity`;
CREATE TABLE `activity` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`start` date DEFAULT NULL,
`end` date DEFAULT NULL,
`launcher` varchar(256) NOT NULL,
`name` varchar(256) DEFAULT NULL,
`prize_money` int(11) DEFAULT NULL,
`type` varchar(256) NOT NULL,
`valid` bit(1) DEFAULT NULL,
`create_time` datetime DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
insert into activity values(1,'2015-01-01','2016-01-01','sms','i am test activity',10,1,'2015-01-01 12:12:12');
同样我们再新建一个disconf_demo2这个数据库,表一模一样,插入一条数据insert into activity values(1,'2015-01-01','2016-01-01','sms','change the name',10,1,'2015-01-01 12:12:12');
- xml分布式配置管理
为了使用基于xml的分布式配置管理,我们需要在applicationContext.xml中加入如下bean:
<bean id="autoReloadBean" class="com.baidu.disconf.client.addons.properties.ReloadablePropertiesfactorybean">
<property name="locations">
<list>
<value>MysqL.properties</value>
</list>
</property>
</bean>
<bean id="autoReloadConfig"
class="com.baidu.disconf.client.addons.properties.ReloadingPropertyPlaceholderConfigurer">
<property name="ignoreResourceNotFound" value="true"/>
<property name="ignoreUnresolvablePlaceholders" value="true"/>
<property name="propertiesArray">
<list>
<ref bean="autoReloadBean"/>
</list>
</property>
</bean> - 实例
上传MysqL.properties文件到disconf-web中,内容如下:
# MysqL
controller代码如下:
MysqL.driverClassName=com.MysqL.jdbc.Driver
MysqL.url=jdbc\:MysqL\://localhost/disconf_demo?characterEncoding=utf8
MysqL.username=root
MysqL.password=root
@Controller
service代码如下:
@RequestMapping("/query")
public class QueryController {
@Autowired
private MysqLService MysqLService;
@RequestMapping(value = "MysqL",method = RequestMethod.GET)
@ResponseBody
public String getMysqL() {
return this.MysqLService.getActivityName();
}
}
@Service
public class MysqLService {
@Autowired
private ActivityRepository activityRepository;
public String getActivityName() {
return this.activityRepository.findOne(1).getName();
}
}repository代码如下:
public interface ActivityRepository extends PagingAndSortingRepository<Activity,Integer> {
我们重点看下jpa的配置:
/**
* 查询状态和时间段有效的活动
*
* @param start
* @param end
* @return
*/
List<Activity> findByValidTrueAndStartBeforeAndEndAfter(Date start,Date end);
/**
* 查询有效的活动
*
* @return
*/
List<Activity> findByValidTrue();
}
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
我们可以看到,配置方式和不使用disconf一模一样,做到了无代码侵入性。
destroy-method="close" p:driverClassName="${MysqL.driverClassName}"
p:url="${MysqL.url}" p:username="${MysqL.username}"
p:password="${MysqL.password}" p:maxIdle="5" p:maxActive="40"
p:defaultAutoCommit="true" p:timeBetweenEvictionRunsMillis="3600000"
p:minEvictableIdleTimeMillis="3600000" />
<bean id="entityManagerFactory" name="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerfactorybean">
<property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
<property name="packagesToScan" value="xxx.disconf.demo.domain" />
<property name="jpaProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MysqL5InnoDBDialect</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
<prop key="hibernate.max_fetch_depth">3</prop>
<prop key="hibernate.jdbc.fetch_size">50</prop>
<prop key="hibernate.jdbc.batch_size">10</prop>
<prop key="hibernate.show_sql">false</prop>
</props>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"
p:entityManagerFactory-ref="entityManagerFactory" />
<jpa:repositories base-package="xxx.disconf.demo.repository"
entity-manager-factory-ref="entityManagerFactory"
transaction-manager-ref="transactionManager" />
<tx:annotation-driven transaction-manager="transactionManager" /> - 自动reload
我们在disconf-web上将jdbc\:MysqL\://localhost/disconf_demo?characterEncoding=utf8修改成jdbc\:MysqL\://localhost/disconf_demo2?characterEncoding=utf8,然后再去调这个接口,理论上应该返回的是
change the name,但实际上还是和之前一样。
这里我们使用的是ReloadingPropertyPlaceholderConfigurer(PropertyPlaceholderConfigurer只是托管,不会自动reload
),理论上应该会自动reload,但是实际上却没有。我们仔细看jpa的配置,disconf管理的bean是dataSource,所以当配置更新时仅仅更新了dataSource这个bean,并不会对下面的几个bean产生影响。所以自动reload了,但是我们看不到效果。
实际上像这种MysqL等连接比较重的资源,用disconf进行托管即可,不需要做到自动reload。
参考:https://github.com/knightliao/disconf/wiki