diff --git a/disconf-client/pom.xml b/disconf-client/pom.xml index 524931042..e36ccec2f 100644 --- a/disconf-client/pom.xml +++ b/disconf-client/pom.xml @@ -145,6 +145,20 @@ test + + + com.netflix.curator + curator-test + 1.0.20 + test + + + com.netflix.curator + curator-framework + 1.0.20 + test + + diff --git a/disconf-client/src/main/java/com/baidu/disconf/client/store/processor/impl/DisconfStoreFileProcessorImpl.java b/disconf-client/src/main/java/com/baidu/disconf/client/store/processor/impl/DisconfStoreFileProcessorImpl.java index 2eed72c01..dbb133008 100644 --- a/disconf-client/src/main/java/com/baidu/disconf/client/store/processor/impl/DisconfStoreFileProcessorImpl.java +++ b/disconf-client/src/main/java/com/baidu/disconf/client/store/processor/impl/DisconfStoreFileProcessorImpl.java @@ -213,6 +213,13 @@ public void inject2Store(String fileName, DisconfValue disconfValue) { Object value = keMap.get(fileItem).getFieldValueByType(object); keMap.get(fileItem).setValue(value); + /** 在first scan的时候就给static的属性赋值,这样在所有的类的static块里也能正确获取到这些static属性的值, + * 如果放到second scan才给static的属性赋值,因为那时所有的类都加载结束了,init()的时候才会执行second scan, + * 那时类的static块也已经执行完了,就会出现static块里取不到相应的值 + * */ + if (keMap.get(fileItem).isStatic()) { + keMap.get(fileItem).setValue4StaticFileItem(value); + } } catch (Exception e) { LOGGER.error("inject2Store filename: " + fileName + " " + e.toString(), e); diff --git a/disconf-client/src/main/java/com/baidu/disconf/client/store/processor/impl/DisconfStoreItemProcessorImpl.java b/disconf-client/src/main/java/com/baidu/disconf/client/store/processor/impl/DisconfStoreItemProcessorImpl.java index 0dfd1ef6b..c9f7d3b34 100644 --- a/disconf-client/src/main/java/com/baidu/disconf/client/store/processor/impl/DisconfStoreItemProcessorImpl.java +++ b/disconf-client/src/main/java/com/baidu/disconf/client/store/processor/impl/DisconfStoreItemProcessorImpl.java @@ -184,6 +184,13 @@ public void inject2Store(String key, DisconfValue disconfValue) { Object newValue = disconfCenterItem.getFieldValueByType(disconfValue.getValue()); disconfCenterItem.setValue(newValue); + /** 在first scan的时候就给static的属性赋值,这样在所有的类的static块里也能正确获取到这些static属性的值, + * 如果放到second scan才给static的属性赋值,因为那时所有的类都加载结束了,init()的时候才会执行second scan, + * 那时类的static块也已经执行完了,就会出现static块里取不到相应的值 + * */ + if (disconfCenterItem.isStatic()) { + disconfCenterItem.setValue4StaticFileItem(newValue); + } } catch (Exception e) { LOGGER.error("key: " + key + " " + e.toString(), e); diff --git a/disconf-client/src/test/java/com/baidu/disconf/client/test/DisconfMgrTestCase.java b/disconf-client/src/test/java/com/baidu/disconf/client/test/DisconfMgrTestCase.java index 38a35ebcf..3db82fb90 100644 --- a/disconf-client/src/test/java/com/baidu/disconf/client/test/DisconfMgrTestCase.java +++ b/disconf-client/src/test/java/com/baidu/disconf/client/test/DisconfMgrTestCase.java @@ -1,38 +1,40 @@ package com.baidu.disconf.client.test; -import java.util.HashSet; -import java.util.Set; - -import org.junit.Assert; -import org.junit.Test; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.ApplicationContext; -import org.springframework.context.ApplicationContextAware; - import com.baidu.disconf.client.DisconfMgr; import com.baidu.disconf.client.DisconfMgrBean; -import com.baidu.disconf.client.core.DisconfCoreFactory; -import com.baidu.disconf.client.core.DisconfCoreMgr; -import com.baidu.disconf.client.core.impl.DisconfCoreMgrImpl; -import com.baidu.disconf.client.fetcher.FetcherFactory; -import com.baidu.disconf.client.fetcher.FetcherMgr; import com.baidu.disconf.client.store.DisconfStoreProcessorFactory; import com.baidu.disconf.client.store.inner.DisconfCenterHostFilesStore; -import com.baidu.disconf.client.support.registry.Registry; import com.baidu.disconf.client.support.utils.StringUtil; import com.baidu.disconf.client.test.common.BaseSpringMockTestCase; import com.baidu.disconf.client.test.model.ConfA; import com.baidu.disconf.client.test.model.ServiceA; import com.baidu.disconf.client.test.model.StaticConf; import com.baidu.disconf.client.test.scan.inner.ScanPackTestCase; -import com.baidu.disconf.client.test.watch.mock.WatchMgrMock; import com.baidu.disconf.client.usertools.DisconfDataGetter; -import com.baidu.disconf.client.watch.WatchMgr; +import com.baidu.disconf.core.common.constants.Constants; +import com.baidu.disconf.core.common.json.ValueVo; +import com.baidu.disconf.core.common.utils.GsonUtils; +import com.baidu.disconf.core.common.zookeeper.ZookeeperMgr; +import com.baidu.disconf.core.test.restful.RemoteMockServer; +import com.netflix.curator.framework.CuratorFramework; +import com.netflix.curator.framework.CuratorFrameworkFactory; +import com.netflix.curator.framework.state.ConnectionState; +import com.netflix.curator.framework.state.ConnectionStateListener; +import com.netflix.curator.retry.ExponentialBackoffRetry; +import com.netflix.curator.test.TestingServer; +import org.junit.Assert; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; -import mockit.Mock; -import mockit.MockUp; +import java.util.HashSet; +import java.util.Set; + +import static com.baidu.disconf.core.test.restful.RemoteMockServer.*; +import static com.github.tomakehurst.wiremock.client.WireMock.*; /** * 一个Demo示例, 远程的下载服务器使用WireMOck, Watch模块使用Jmockit @@ -55,28 +57,20 @@ public class DisconfMgrTestCase extends BaseSpringMockTestCase implements Applic @Test public void demo() { - - // - // mock up factory method - // - new MockUp() { - - @Mock - public DisconfCoreMgr getDisconfCoreMgr(Registry registry) throws Exception { - - FetcherMgr fetcherMgr = FetcherFactory.getFetcherMgr(); - - // Watch 模块 - final WatchMgr watchMgr = new WatchMgrMock().getMockInstance(); - watchMgr.init("", "", true); - - // registry - DisconfCoreMgr disconfCoreMgr = new DisconfCoreMgrImpl(watchMgr, fetcherMgr, - registry); - - return disconfCoreMgr; - } - }; + try { + // 使用curator模拟zk + TestingServer server = new TestingServer(ZOO_PORT); + CuratorFramework client = CuratorFrameworkFactory.newClient(server.getConnectString(), new ExponentialBackoffRetry(1000, 3)); + client.getConnectionStateListenable().addListener(new ConnectionStateListener() { + @Override + public void stateChanged(CuratorFramework curatorFramework, ConnectionState connectionState) { + System.out.println("连接状态:" + connectionState.name()); + } + }); + } catch (Exception e) { + e.printStackTrace(); + Assert.assertTrue(false); + } // // 正式测试 @@ -89,6 +83,7 @@ public DisconfCoreMgr getDisconfCoreMgr(Registry registry) throws Exception { LOGGER.info(String.valueOf("varA: " + confA.getVarA())); LOGGER.info(String.valueOf("varA2: " + confA.getVarA2())); LOGGER.info(String.valueOf("varAA: " + serviceA.getVarAA())); + LOGGER.info(String.valueOf("varAAStatic: " + serviceA.getVarAAStatic())); LOGGER.info("================ BEFORE DISCONF =============================="); @@ -115,15 +110,56 @@ public DisconfCoreMgr getDisconfCoreMgr(Registry registry) throws Exception { LOGGER.info(String.valueOf("varA: " + confA.getVarA())); Assert.assertEquals(new Long(1000), confA.getVarA()); + // 修改配置文件的值 + stubFor(get(urlEqualTo(RemoteMockServer.FILE_URL)) + .willReturn(aResponse().withHeader("Content-Type", "text/html;charset=UTF-8") + .withHeader("Content-Disposition", + "attachment; filename=" + RemoteMockServer.FILE_NAME).withStatus(200) + .withBody(FILE_CONTENT_NEW.getBytes()))); + // 通知zk + ZookeeperMgr.getInstance().writePersistentUrl(ZOO_FILE_UPDATE_PATH, GsonUtils.toJson(FILE_CONTENT_NEW)); + + Thread.sleep(1000); + + // 获取修改后的值 + LOGGER.info(String.valueOf("varA new: " + confA.getVarA())); + Assert.assertEquals(new Long(9999), confA.getVarA()); + LOGGER.info(String.valueOf("varA2: " + confA.getVarA2())); Assert.assertEquals(new Long(2000), confA.getVarA2()); LOGGER.info(String.valueOf("varAA: " + serviceA.getVarAA())); Assert.assertEquals(new Integer(1000).intValue(), serviceA.getVarAA()); + // 修改配置项的值 + ValueVo valueVo = new ValueVo(); + valueVo.setMessage(""); + valueVo.setStatus(Constants.OK); + valueVo.setValue(RemoteMockServer.DEFAULT_ITEM_VALUE_NEW); + stubFor(get(urlEqualTo(RemoteMockServer.ITEM_URL)) + .willReturn(aResponse().withHeader("Content-Type", RemoteMockServer.CONTENT_TYPE).withStatus(200) + .withBody(GsonUtils.toJson(valueVo)))); + // 通知zk + ZookeeperMgr.getInstance().writePersistentUrl(ZOO_ITEM_UPDATE_PATH, RemoteMockServer.DEFAULT_ITEM_VALUE_NEW); + + Thread.sleep(1000); + + // 获取修改后的值 + LOGGER.info(String.valueOf("varAA new: " + serviceA.getVarAA())); + Assert.assertEquals(new Integer(8888).intValue(), serviceA.getVarAA()); + + LOGGER.info(String.valueOf("varAAStatic: " + serviceA.getVarAAStatic())); + Assert.assertEquals(new Integer(2001).intValue(), serviceA.getVarAAStatic()); + + LOGGER.info(String.valueOf("varBBStatic: " + serviceA.getVarBBStatic())); + Assert.assertEquals(new Integer(3001).intValue(), serviceA.getVarBBStatic()); + LOGGER.info(String.valueOf("static var: " + StaticConf.getStaticvar())); Assert.assertEquals(new Integer(50).intValue(), StaticConf.getStaticvar()); + LOGGER.info(String.valueOf("static var: " + StaticConf.getStaticvar3())); + Assert.assertEquals(new Integer(4001).intValue(), StaticConf.getStaticvar3()); + testDynamicGetter(); LOGGER.info("================ AFTER DISCONF =============================="); @@ -138,13 +174,13 @@ public DisconfCoreMgr getDisconfCoreMgr(Registry registry) throws Exception { private void testDynamicGetter() { Assert.assertEquals(DisconfDataGetter.getByFile("confA.properties").get("confa.varA").toString(), - "1000"); + "9999"); Assert.assertEquals(DisconfDataGetter.getByItem("keyA").toString(), - "1000"); + "8888"); Assert.assertEquals(DisconfDataGetter.getByFileItem("confA.properties", "confa.varA").toString(), - "1000"); + "9999"); } public ApplicationContext getApplicationContext() { diff --git a/disconf-client/src/test/java/com/baidu/disconf/client/test/model/ServiceA.java b/disconf-client/src/test/java/com/baidu/disconf/client/test/model/ServiceA.java index 3fdd3c35f..35b884fd1 100644 --- a/disconf-client/src/test/java/com/baidu/disconf/client/test/model/ServiceA.java +++ b/disconf-client/src/test/java/com/baidu/disconf/client/test/model/ServiceA.java @@ -23,6 +23,20 @@ public class ServiceA { public static final String keyA = "keyA"; + /** + * 2. 用于静态方式获取的分布式配置项
+ */ + private static int varAAStatic = 20; + + public static final String staticKeyA = "staticKeyA"; + + /** + * 3. 用于静态方式获取的分布式配置项,且没有setter方法,用于测试反射 + */ + private static int varBBStatic = 30; + + public static final String staticKeyB = "staticKeyB"; + @Autowired private ConfA confA; @@ -43,4 +57,17 @@ public void setVarAA(int varAA) { this.varAA = varAA; } + @DisconfItem(key = ServiceA.staticKeyA) + public static int getVarAAStatic() { + return varAAStatic; + } + + public static void setVarAAStatic(int varAAStatic) { + ServiceA.varAAStatic = varAAStatic; + } + + @DisconfItem(key = ServiceA.staticKeyB) + public static int getVarBBStatic() { + return varBBStatic; + } } diff --git a/disconf-client/src/test/java/com/baidu/disconf/client/test/model/StaticConf.java b/disconf-client/src/test/java/com/baidu/disconf/client/test/model/StaticConf.java index 13c5aef90..2d006769a 100644 --- a/disconf-client/src/test/java/com/baidu/disconf/client/test/model/StaticConf.java +++ b/disconf-client/src/test/java/com/baidu/disconf/client/test/model/StaticConf.java @@ -16,6 +16,9 @@ public class StaticConf { private static double staticvar2 = 50; + // 用于测试没有setter方法的静态配置文件 + private static int staticvar3 = 60; + @DisconfFileItem(name = "staticvar", associateField = "staticvar") public static int getStaticVar() { return staticvar; @@ -41,4 +44,9 @@ public static double getStaticvar2() { public static void setStaticvar2(double staticvar2) { StaticConf.staticvar2 = staticvar2; } + + @DisconfFileItem(name = "staticvar3", associateField = "staticvar3") + public static int getStaticvar3() { + return staticvar3; + } } diff --git a/disconf-client/src/test/java/com/baidu/disconf/client/test/scan/inner/ScanPackTestCase.java b/disconf-client/src/test/java/com/baidu/disconf/client/test/scan/inner/ScanPackTestCase.java index abfc2b03e..973595068 100644 --- a/disconf-client/src/test/java/com/baidu/disconf/client/test/scan/inner/ScanPackTestCase.java +++ b/disconf-client/src/test/java/com/baidu/disconf/client/test/scan/inner/ScanPackTestCase.java @@ -48,7 +48,7 @@ public void scan() { LOGGER.info("=============DISCONF FILE ITEM==================="); Set methods = scanModel.getDisconfFileItemMethodSet(); ScanPrinterUtils.printFileItemMethod(methods); - Assert.assertEquals(6, methods.size()); + Assert.assertEquals(7, methods.size()); Assert.assertEquals(4, scanModel.getDisconfFileClassSet().size()); // disconf file item @@ -60,7 +60,7 @@ public void scan() { LOGGER.info("=============DISCONF ITEM==================="); methods = scanModel.getDisconfItemMethodSet(); ScanPrinterUtils.printFileItemMethod(methods); - Assert.assertEquals(1, methods.size()); + Assert.assertEquals(3, methods.size()); // Active backup LOGGER.info("=============DISCONF ACTIVE BACKUP==================="); diff --git a/disconf-core/src/test/java/com/baidu/disconf/core/test/common/BaseCoreTestCase.java b/disconf-core/src/test/java/com/baidu/disconf/core/test/common/BaseCoreTestCase.java index 195e98384..f4c9ad01f 100644 --- a/disconf-core/src/test/java/com/baidu/disconf/core/test/common/BaseCoreTestCase.java +++ b/disconf-core/src/test/java/com/baidu/disconf/core/test/common/BaseCoreTestCase.java @@ -59,6 +59,28 @@ private static void setupRemoteData() { .willReturn(aResponse().withHeader("Content-Type", RemoteMockServer.CONTENT_TYPE).withStatus(200) .withBody(GsonUtils.toJson(valueVo)))); + // + // 静态配置项 + // + ValueVo valueVoStatic = new ValueVo(); + valueVoStatic.setMessage(""); + valueVoStatic.setStatus(Constants.OK); + valueVoStatic.setValue(RemoteMockServer.DEFAULT_STATIC_ITEM_VALUE); + stubFor(get(urlEqualTo(RemoteMockServer.STATIC_ITEM_URL)) + .willReturn(aResponse().withHeader("Content-Type", RemoteMockServer.CONTENT_TYPE).withStatus(200) + .withBody(GsonUtils.toJson(valueVoStatic)))); + + // + // 静态配置项2,用于测试没有setter方法的配置项 + // + ValueVo valueVoStatic2 = new ValueVo(); + valueVoStatic2.setMessage(""); + valueVoStatic2.setStatus(Constants.OK); + valueVoStatic2.setValue(RemoteMockServer.DEFAULT_STATIC_ITEM_VALUE_2); + stubFor(get(urlEqualTo(RemoteMockServer.STATIC_ITEM_URL_2)) + .willReturn(aResponse().withHeader("Content-Type", RemoteMockServer.CONTENT_TYPE).withStatus(200) + .withBody(GsonUtils.toJson(valueVoStatic2)))); + // // 配置文件 // diff --git a/disconf-core/src/test/java/com/baidu/disconf/core/test/restful/RemoteMockServer.java b/disconf-core/src/test/java/com/baidu/disconf/core/test/restful/RemoteMockServer.java index 19b9d942f..0ec6df27b 100644 --- a/disconf-core/src/test/java/com/baidu/disconf/core/test/restful/RemoteMockServer.java +++ b/disconf-core/src/test/java/com/baidu/disconf/core/test/restful/RemoteMockServer.java @@ -23,6 +23,7 @@ public class RemoteMockServer { "/api/config/file?version=1_0_0_0&app=disconf_testcase&env=rd&key=confA.properties&type=0"; public static final String FILE_NAME = "confA.properties"; public static final String FILE_CONTENT = "confa.varA=1000\r\nconfa.varA2=2000"; + public static final String FILE_CONTENT_NEW = "confa.varA=9999\r\nconfa.varA2=2000"; // // 空配置文件 @@ -37,7 +38,7 @@ public class RemoteMockServer { public static final String STATIC_FILE_URL = "/api/config/file?version=1_0_0_0&app=disconf_testcase&env=rd&key=staticConf.properties&type=0"; public static final String STATIC_FILE_NAME = "staticConf.properties"; - public static final String STATIC_FILE_CONTENT = "staticvar=50\r\nstaticvar2=100"; + public static final String STATIC_FILE_CONTENT = "staticvar=50\r\nstaticvar2=100\r\nstaticvar3=4001"; // // 非注解 方式1 @@ -64,6 +65,21 @@ public class RemoteMockServer { "/api/config/item?version=1_0_0_0&app=disconf_testcase&env=rd&key=keyA&type=1"; public static final String CONTENT_TYPE = "application/json"; public static final String DEFAULT_ITEM_VALUE = "1000"; + public static final String DEFAULT_ITEM_VALUE_NEW = "8888"; + + // + // 静态配置项 + // + public static final String STATIC_ITEM_URL = + "/api/config/item?version=1_0_0_0&app=disconf_testcase&env=rd&key=staticKeyA&type=1"; + public static final String DEFAULT_STATIC_ITEM_VALUE = "2001"; + + // + // 静态配置项 + // + public static final String STATIC_ITEM_URL_2 = + "/api/config/item?version=1_0_0_0&app=disconf_testcase&env=rd&key=staticKeyB&type=1"; + public static final String DEFAULT_STATIC_ITEM_VALUE_2 = "3001"; // public static final String LOCAL_DOWNLOAD_DIR = "./disconf/download"; @@ -74,7 +90,11 @@ public class RemoteMockServer { // zoo // public static final String ZOO_URL = "/api/zoo/hosts"; - public static final String ZOO_HOSTS = "127.0.0.1:8581,127.0.0.1:8582,127.0.0.1:8583"; + public static final int ZOO_PORT = 8581; + public static final String ZOO_HOSTS = "127.0.0.1:" + ZOO_PORT; public static final String ZOO_PREFIX_URL = "/api/zoo/prefix"; public static final String ZOO_PREFIX_VALUE = "/disconf"; + + public static final String ZOO_FILE_UPDATE_PATH = ZOO_PREFIX_VALUE + "/disconf_testcase_1_0_0_0_rd/file/confA.properties"; + public static final String ZOO_ITEM_UPDATE_PATH = ZOO_PREFIX_VALUE + "/disconf_testcase_1_0_0_0_rd/item/keyA"; }