Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
wrr-cat
apollo
提交
49c1b308
apollo
项目概览
wrr-cat
/
apollo
与 Fork 源项目一致
从无法访问的项目Fork
通知
2
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
apollo
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
49c1b308
编写于
3月 23, 2016
作者:
J
Jason Song
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Add refresh config support and refactor
上级
51978dd6
变更
23
显示空白变更内容
内联
并排
Showing
23 changed file
with
866 addition
and
201 deletion
+866
-201
apollo-biz/src/main/resources/import.sql
apollo-biz/src/main/resources/import.sql
+1
-0
apollo-client/src/main/java/com/ctrip/apollo/client/ApolloConfigManager.java
...ain/java/com/ctrip/apollo/client/ApolloConfigManager.java
+38
-15
apollo-client/src/main/java/com/ctrip/apollo/client/enums/PropertyChangeType.java
...ava/com/ctrip/apollo/client/enums/PropertyChangeType.java
+21
-0
apollo-client/src/main/java/com/ctrip/apollo/client/loader/ConfigLoader.java
...ain/java/com/ctrip/apollo/client/loader/ConfigLoader.java
+5
-6
apollo-client/src/main/java/com/ctrip/apollo/client/loader/ConfigLoaderFactory.java
...a/com/ctrip/apollo/client/loader/ConfigLoaderFactory.java
+22
-1
apollo-client/src/main/java/com/ctrip/apollo/client/loader/ConfigLoaderManager.java
...a/com/ctrip/apollo/client/loader/ConfigLoaderManager.java
+190
-0
apollo-client/src/main/java/com/ctrip/apollo/client/loader/impl/AbstractConfigLoader.java
...ctrip/apollo/client/loader/impl/AbstractConfigLoader.java
+35
-0
apollo-client/src/main/java/com/ctrip/apollo/client/loader/impl/InMemoryConfigLoader.java
...ctrip/apollo/client/loader/impl/InMemoryConfigLoader.java
+15
-0
apollo-client/src/main/java/com/ctrip/apollo/client/loader/impl/LocalFileConfigLoader.java
...trip/apollo/client/loader/impl/LocalFileConfigLoader.java
+15
-0
apollo-client/src/main/java/com/ctrip/apollo/client/loader/impl/RemoteConfigLoader.java
...m/ctrip/apollo/client/loader/impl/RemoteConfigLoader.java
+38
-93
apollo-client/src/main/java/com/ctrip/apollo/client/model/ApolloRegistry.java
...in/java/com/ctrip/apollo/client/model/ApolloRegistry.java
+11
-0
apollo-client/src/main/java/com/ctrip/apollo/client/model/PropertyChange.java
...in/java/com/ctrip/apollo/client/model/PropertyChange.java
+52
-0
apollo-client/src/main/java/com/ctrip/apollo/client/model/PropertySourceReloadResult.java
...ctrip/apollo/client/model/PropertySourceReloadResult.java
+44
-0
apollo-client/src/main/java/com/ctrip/apollo/client/util/ConfigUtil.java
...rc/main/java/com/ctrip/apollo/client/util/ConfigUtil.java
+1
-1
apollo-client/src/test/java/com/ctrip/apollo/client/AllTests.java
...lient/src/test/java/com/ctrip/apollo/client/AllTests.java
+3
-1
apollo-client/src/test/java/com/ctrip/apollo/client/ApolloConfigManagerTest.java
...java/com/ctrip/apollo/client/ApolloConfigManagerTest.java
+49
-10
apollo-client/src/test/java/com/ctrip/apollo/client/loader/ConfigLoaderManagerTest.java
...m/ctrip/apollo/client/loader/ConfigLoaderManagerTest.java
+198
-0
apollo-client/src/test/java/com/ctrip/apollo/client/loader/impl/RemoteConfigLoaderTest.java
...rip/apollo/client/loader/impl/RemoteConfigLoaderTest.java
+65
-37
apollo-configservice/src/main/java/com/ctrip/apollo/configservice/controller/ConfigController.java
...rip/apollo/configservice/controller/ConfigController.java
+2
-5
apollo-core/src/main/java/com/ctrip/apollo/core/dto/ApolloConfig.java
...src/main/java/com/ctrip/apollo/core/dto/ApolloConfig.java
+23
-1
apollo-demo/src/main/java/com/ctrip/apollo/demo/controller/DemoController.java
...java/com/ctrip/apollo/demo/controller/DemoController.java
+8
-5
apollo-demo/src/main/webapp/s/scripts/app.js
apollo-demo/src/main/webapp/s/scripts/app.js
+21
-19
apollo-demo/src/main/webapp/s/templates/list.html
apollo-demo/src/main/webapp/s/templates/list.html
+9
-7
未找到文件。
apollo-biz/src/main/resources/import.sql
浏览文件 @
49c1b308
...
@@ -6,3 +6,4 @@ INSERT INTO Version (AppId, IsDeleted, Name, ReleaseId) VALUES (102, 0, '1.0', 2
...
@@ -6,3 +6,4 @@ INSERT INTO Version (AppId, IsDeleted, Name, ReleaseId) VALUES (102, 0, '1.0', 2
INSERT
INTO
RELEASESNAPSHOT
(
ClusterName
,
IsDeleted
,
ReleaseId
,
Configurations
)
VALUES
(
'default'
,
0
,
1
,
'{"apollo.foo":"bar", "apollo.bar":"foo"}'
);
INSERT
INTO
RELEASESNAPSHOT
(
ClusterName
,
IsDeleted
,
ReleaseId
,
Configurations
)
VALUES
(
'default'
,
0
,
1
,
'{"apollo.foo":"bar", "apollo.bar":"foo"}'
);
INSERT
INTO
RELEASESNAPSHOT
(
ClusterName
,
IsDeleted
,
ReleaseId
,
Configurations
)
VALUES
(
'default'
,
0
,
2
,
'{"demo.foo":"demo1", "demo.bar":"demo2"}'
);
INSERT
INTO
RELEASESNAPSHOT
(
ClusterName
,
IsDeleted
,
ReleaseId
,
Configurations
)
VALUES
(
'default'
,
0
,
2
,
'{"demo.foo":"demo1", "demo.bar":"demo2"}'
);
INSERT
INTO
RELEASESNAPSHOT
(
ClusterName
,
IsDeleted
,
ReleaseId
,
Configurations
)
VALUES
(
'default'
,
0
,
3
,
'{"apollo.foo":"another bar", "apollo.bar_new":"foo"}'
);
apollo-client/src/main/java/com/ctrip/apollo/client/ApolloConfigManager.java
浏览文件 @
49c1b308
package
com.ctrip.apollo.client
;
package
com.ctrip.apollo.client
;
import
com.ctrip.apollo.client.loader.ConfigLoader
;
import
com.ctrip.apollo.client.loader.ConfigLoaderFactory
;
import
com.ctrip.apollo.client.loader.ConfigLoaderFactory
;
import
com.ctrip.apollo.client.loader.ConfigLoaderManager
;
import
com.ctrip.apollo.client.model.PropertyChange
;
import
com.ctrip.apollo.client.model.PropertySourceReloadResult
;
import
com.ctrip.apollo.client.util.ConfigUtil
;
import
com.ctrip.apollo.client.util.ConfigUtil
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.beans.BeansException
;
import
org.springframework.beans.BeansException
;
import
org.springframework.beans.factory.config.BeanDefinition
;
import
org.springframework.beans.factory.config.BeanDefinition
;
import
org.springframework.beans.factory.config.ConfigurableListableBeanFactory
;
import
org.springframework.beans.factory.config.ConfigurableListableBeanFactory
;
...
@@ -19,6 +23,7 @@ import org.springframework.core.PriorityOrdered;
...
@@ -19,6 +23,7 @@ import org.springframework.core.PriorityOrdered;
import
org.springframework.core.env.CompositePropertySource
;
import
org.springframework.core.env.CompositePropertySource
;
import
org.springframework.core.env.MutablePropertySources
;
import
org.springframework.core.env.MutablePropertySources
;
import
java.util.List
;
import
java.util.concurrent.atomic.AtomicReference
;
import
java.util.concurrent.atomic.AtomicReference
;
/**
/**
...
@@ -27,19 +32,18 @@ import java.util.concurrent.atomic.AtomicReference;
...
@@ -27,19 +32,18 @@ import java.util.concurrent.atomic.AtomicReference;
* @author Jason Song(song_s@ctrip.com)
* @author Jason Song(song_s@ctrip.com)
*/
*/
public
class
ApolloConfigManager
implements
BeanDefinitionRegistryPostProcessor
,
PriorityOrdered
,
ApplicationContextAware
{
public
class
ApolloConfigManager
implements
BeanDefinitionRegistryPostProcessor
,
PriorityOrdered
,
ApplicationContextAware
{
p
ublic
static
final
String
APOLLO_PROPERTY_SOURCE_NAME
=
"ApolloConfigProperties"
;
p
rivate
static
final
Logger
logger
=
LoggerFactory
.
getLogger
(
ApolloConfigManager
.
class
)
;
private
static
AtomicReference
<
ApolloConfigManager
>
singletonProtector
=
new
AtomicReference
<
ApolloConfigManager
>();
private
static
AtomicReference
<
ApolloConfigManager
>
singletonProtector
=
new
AtomicReference
<
ApolloConfigManager
>();
private
ConfigLoader
configLoad
er
;
private
ConfigLoader
Manager
configLoaderManag
er
;
private
ConfigurableApplicationContext
applicationContext
;
private
ConfigurableApplicationContext
applicationContext
;
private
RefreshScope
scope
;
private
CompositePropertySource
currentPropertySource
;
public
ApolloConfigManager
()
{
public
ApolloConfigManager
()
{
if
(!
singletonProtector
.
compareAndSet
(
null
,
this
))
{
if
(!
singletonProtector
.
compareAndSet
(
null
,
this
))
{
throw
new
IllegalStateException
(
"There should be only one ApolloConfigManager instance!"
);
throw
new
IllegalStateException
(
"There should be only one ApolloConfigManager instance!"
);
}
}
this
.
configLoader
=
ConfigLoaderFactory
.
getInstance
().
getRemoteConfigLoad
er
();
this
.
configLoader
Manager
=
ConfigLoaderFactory
.
getInstance
().
getConfigLoaderManag
er
();
}
}
@Override
@Override
...
@@ -97,23 +101,42 @@ public class ApolloConfigManager implements BeanDefinitionRegistryPostProcessor,
...
@@ -97,23 +101,42 @@ public class ApolloConfigManager implements BeanDefinitionRegistryPostProcessor,
}
}
/**
/**
* Prepare property sources
* Initialize property sources
* First try to load from remote
* If loading from remote failed, then fall back to local cached properties
*/
*/
void
initializePropertySource
()
{
void
initializePropertySource
()
{
currentPropertySource
=
loadPropertySource
();
//TODO stop application from starting when config cannot be loaded?
CompositePropertySource
result
=
this
.
configLoaderManager
.
loadPropertySource
();
updateEnvironmentPropertySource
(
result
);
}
private
void
updateEnvironmentPropertySource
(
CompositePropertySource
currentPropertySource
)
{
MutablePropertySources
currentPropertySources
=
applicationContext
.
getEnvironment
().
getPropertySources
();
MutablePropertySources
currentPropertySources
=
applicationContext
.
getEnvironment
().
getPropertySources
();
if
(
currentPropertySources
.
contains
(
currentPropertySource
.
getName
()))
{
if
(
currentPropertySources
.
contains
(
currentPropertySource
.
getName
()))
{
currentPropertySources
.
remove
(
currentPropertySource
.
getName
());
currentPropertySources
.
replace
(
currentPropertySource
.
getName
(),
currentPropertySource
);
return
;
}
}
currentPropertySources
.
addFirst
(
currentPropertySource
);
currentPropertySources
.
addFirst
(
currentPropertySource
);
}
}
CompositePropertySource
loadPropertySource
()
{
public
List
<
PropertyChange
>
updatePropertySource
()
{
CompositePropertySource
compositePropertySource
=
new
CompositePropertySource
(
APOLLO_PROPERTY_SOURCE_NAME
);
PropertySourceReloadResult
result
=
this
.
configLoaderManager
.
reloadPropertySource
();
compositePropertySource
.
addPropertySource
(
configLoader
.
loadPropertySource
());
if
(
result
.
hasChanges
())
{
return
compositePropertySource
;
updateEnvironmentPropertySource
(
result
.
getPropertySource
());
refreshBeans
();
}
return
result
.
getChanges
();
}
private
void
refreshBeans
()
{
if
(
this
.
scope
==
null
)
{
this
.
scope
=
applicationContext
.
getBean
(
"refreshScope"
,
RefreshScope
.
class
);
}
if
(
this
.
scope
==
null
)
{
logger
.
error
(
"Could not get refresh scope object, skip refresh beans"
);
}
this
.
scope
.
refreshAll
();
}
}
}
}
apollo-client/src/main/java/com/ctrip/apollo/client/enums/PropertyChangeType.java
0 → 100644
浏览文件 @
49c1b308
package
com.ctrip.apollo.client.enums
;
/**
* @author Jason Song(song_s@ctrip.com)
*/
public
enum
PropertyChangeType
{
NEW
(
"New"
),
MODIFIED
(
"Modified"
),
DELETED
(
"Deleted"
);
private
String
type
;
PropertyChangeType
(
String
type
)
{
this
.
type
=
type
;
}
public
String
getType
()
{
return
type
;
}
}
apollo-client/src/main/java/com/ctrip/apollo/client/loader/ConfigLoader.java
浏览文件 @
49c1b308
package
com.ctrip.apollo.client.loader
;
package
com.ctrip.apollo.client.loader
;
import
org.springframework.core.env.CompositePropertySource
;
import
com.ctrip.apollo.client.model.ApolloRegistry
;
import
com.ctrip.apollo.core.dto.ApolloConfig
;
/**
/**
* @author Jason Song(songs_ctrip.com)
* @author Jason Song(songs_ctrip.com)
*/
*/
public
interface
ConfigLoader
{
public
interface
ConfigLoader
{
/**
ApolloConfig
loadApolloConfig
(
ApolloRegistry
apolloRegistry
,
ApolloConfig
previous
);
* Load property source for client use
* @return property source
void
setFallBackLoader
(
ConfigLoader
configLoader
);
*/
CompositePropertySource
loadPropertySource
();
}
}
apollo-client/src/main/java/com/ctrip/apollo/client/loader/ConfigLoaderFactory.java
浏览文件 @
49c1b308
package
com.ctrip.apollo.client.loader
;
package
com.ctrip.apollo.client.loader
;
import
com.ctrip.apollo.client.loader.impl.InMemoryConfigLoader
;
import
com.ctrip.apollo.client.loader.impl.LocalFileConfigLoader
;
import
com.ctrip.apollo.client.loader.impl.RemoteConfigLoader
;
import
com.ctrip.apollo.client.loader.impl.RemoteConfigLoader
;
import
com.ctrip.apollo.client.util.ConfigUtil
;
import
org.springframework.web.client.RestTemplate
;
/**
/**
* @author Jason Song(song_s@ctrip.com)
* @author Jason Song(song_s@ctrip.com)
...
@@ -15,7 +19,24 @@ public class ConfigLoaderFactory {
...
@@ -15,7 +19,24 @@ public class ConfigLoaderFactory {
return
configLoaderFactory
;
return
configLoaderFactory
;
}
}
public
ConfigLoader
getLocalFileConfigLoader
()
{
ConfigLoader
configLoader
=
new
LocalFileConfigLoader
();
return
configLoader
;
}
public
ConfigLoader
getInMemoryConfigLoader
()
{
ConfigLoader
inMemoryConfigLoader
=
new
InMemoryConfigLoader
();
inMemoryConfigLoader
.
setFallBackLoader
(
getLocalFileConfigLoader
());
return
inMemoryConfigLoader
;
}
public
ConfigLoader
getRemoteConfigLoader
()
{
public
ConfigLoader
getRemoteConfigLoader
()
{
return
new
RemoteConfigLoader
();
ConfigLoader
remoteConfigLoader
=
new
RemoteConfigLoader
(
new
RestTemplate
(),
ConfigUtil
.
getInstance
());
// remoteConfigLoader.setFallBackLoader(getInMemoryConfigLoader());
return
remoteConfigLoader
;
}
public
ConfigLoaderManager
getConfigLoaderManager
()
{
return
new
ConfigLoaderManager
(
getRemoteConfigLoader
(),
ConfigUtil
.
getInstance
());
}
}
}
}
apollo-client/src/main/java/com/ctrip/apollo/client/loader/ConfigLoaderManager.java
0 → 100644
浏览文件 @
49c1b308
package
com.ctrip.apollo.client.loader
;
import
com.ctrip.apollo.client.enums.PropertyChangeType
;
import
com.ctrip.apollo.client.model.ApolloRegistry
;
import
com.ctrip.apollo.client.model.PropertyChange
;
import
com.ctrip.apollo.client.model.PropertySourceReloadResult
;
import
com.ctrip.apollo.client.util.ConfigUtil
;
import
com.ctrip.apollo.core.dto.ApolloConfig
;
import
com.google.common.collect.Lists
;
import
com.google.common.collect.Maps
;
import
com.google.common.collect.Sets
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.core.env.CompositePropertySource
;
import
org.springframework.core.env.MapPropertySource
;
import
java.io.IOException
;
import
java.util.Collections
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Set
;
import
java.util.concurrent.*
;
import
java.util.concurrent.atomic.AtomicLong
;
/**
* @author Jason Song(song_s@ctrip.com)
*/
public
class
ConfigLoaderManager
{
public
static
final
String
APOLLO_PROPERTY_SOURCE_NAME
=
"ApolloConfigProperties"
;
private
static
final
Logger
logger
=
LoggerFactory
.
getLogger
(
ConfigLoaderManager
.
class
);
private
ConfigLoader
configLoader
;
private
ConfigUtil
configUtil
;
private
final
ExecutorService
executorService
;
private
final
AtomicLong
counter
;
private
Map
<
ApolloRegistry
,
ApolloConfig
>
currentApolloRegistryConfigCache
;
private
Map
<
ApolloRegistry
,
ApolloConfig
>
previousApolloRegistryConfigCache
;
private
List
<
ApolloRegistry
>
apolloRegistries
;
public
ConfigLoaderManager
(
ConfigLoader
configLoader
,
ConfigUtil
configUtil
)
{
this
.
configLoader
=
configLoader
;
this
.
configUtil
=
configUtil
;
this
.
counter
=
new
AtomicLong
();
this
.
executorService
=
Executors
.
newFixedThreadPool
(
5
,
new
ThreadFactory
()
{
@Override
public
Thread
newThread
(
Runnable
r
)
{
Thread
thread
=
new
Thread
(
r
,
"ConfigLoaderManager-"
+
counter
.
incrementAndGet
());
return
thread
;
}
});
this
.
currentApolloRegistryConfigCache
=
Maps
.
newConcurrentMap
();
}
public
CompositePropertySource
loadPropertySource
()
{
try
{
apolloRegistries
=
configUtil
.
loadApolloRegistries
();
}
catch
(
IOException
e
)
{
throw
new
RuntimeException
(
"Load apollo config registry failed"
,
e
);
}
return
loadPropertySourceWithApolloRegistries
(
apolloRegistries
);
}
public
PropertySourceReloadResult
reloadPropertySource
()
{
CompositePropertySource
composite
=
loadPropertySourceWithApolloRegistries
(
apolloRegistries
);
List
<
ApolloConfig
>
previous
=
Lists
.
newArrayList
(
this
.
previousApolloRegistryConfigCache
.
values
());
List
<
ApolloConfig
>
current
=
Lists
.
newArrayList
(
this
.
currentApolloRegistryConfigCache
.
values
());
return
new
PropertySourceReloadResult
(
composite
,
calcPropertyChanges
(
previous
,
current
));
}
/**
* Load property source with apollo registries provided
* Should not be invoked in parallel since there are some operations like create/destroy cache,
* writing to files etc.
* @param apolloRegistries
* @return
*/
private
synchronized
CompositePropertySource
loadPropertySourceWithApolloRegistries
(
List
<
ApolloRegistry
>
apolloRegistries
)
{
resetApolloRegistryConfigCache
();
CompositePropertySource
composite
=
new
CompositePropertySource
(
APOLLO_PROPERTY_SOURCE_NAME
);
if
(
apolloRegistries
==
null
||
apolloRegistries
.
isEmpty
())
{
logger
.
warn
(
"No Apollo Registry found!"
);
return
composite
;
}
try
{
List
<
ApolloConfig
>
apolloConfigList
=
loadApolloConfigs
(
apolloRegistries
);
Collections
.
sort
(
apolloConfigList
);
for
(
ApolloConfig
apolloConfig
:
apolloConfigList
)
{
composite
.
addPropertySource
(
new
MapPropertySource
(
assemblePropertySourceName
(
apolloConfig
),
apolloConfig
.
getConfigurations
()));
}
return
composite
;
}
catch
(
Throwable
throwable
)
{
throw
new
RuntimeException
(
"Load apollo configs failed"
,
throwable
);
}
}
List
<
PropertyChange
>
calcPropertyChanges
(
List
<
ApolloConfig
>
previous
,
List
<
ApolloConfig
>
current
)
{
Map
<
String
,
Object
>
previousMap
=
collectConfigurations
(
previous
);
Map
<
String
,
Object
>
currentMap
=
collectConfigurations
(
current
);
Set
<
String
>
previousKeys
=
previousMap
.
keySet
();
Set
<
String
>
currentKeys
=
currentMap
.
keySet
();
Set
<
String
>
commonKeys
=
Sets
.
intersection
(
previousKeys
,
currentKeys
);
Set
<
String
>
newKeys
=
Sets
.
difference
(
currentKeys
,
commonKeys
);
Set
<
String
>
removedKeys
=
Sets
.
difference
(
previousKeys
,
commonKeys
);
List
<
PropertyChange
>
changes
=
Lists
.
newArrayList
();
for
(
String
newKey
:
newKeys
)
{
changes
.
add
(
new
PropertyChange
(
newKey
,
null
,
currentMap
.
get
(
newKey
),
PropertyChangeType
.
NEW
));
}
for
(
String
removedKey
:
removedKeys
)
{
changes
.
add
(
new
PropertyChange
(
removedKey
,
previousMap
.
get
(
removedKey
),
null
,
PropertyChangeType
.
DELETED
));
}
for
(
String
commonKey
:
commonKeys
)
{
if
(
previousMap
.
get
(
commonKey
).
equals
(
currentMap
.
get
(
commonKey
)))
{
continue
;
}
changes
.
add
(
new
PropertyChange
(
commonKey
,
previousMap
.
get
(
commonKey
),
currentMap
.
get
(
commonKey
),
PropertyChangeType
.
MODIFIED
));
}
return
changes
;
}
Map
<
String
,
Object
>
collectConfigurations
(
List
<
ApolloConfig
>
apolloConfigs
)
{
Collections
.
sort
(
apolloConfigs
);
Map
<
String
,
Object
>
configMap
=
Maps
.
newHashMap
();
for
(
int
i
=
apolloConfigs
.
size
()
-
1
;
i
>
-
1
;
i
--)
{
configMap
.
putAll
(
apolloConfigs
.
get
(
i
).
getConfigurations
());
}
return
configMap
;
}
List
<
ApolloConfig
>
loadApolloConfigs
(
List
<
ApolloRegistry
>
apolloRegistries
)
throws
Throwable
{
List
<
Future
<
ApolloConfig
>>
futures
=
Lists
.
newArrayList
();
for
(
final
ApolloRegistry
apolloRegistry
:
apolloRegistries
)
{
futures
.
add
(
executorService
.
submit
(
new
Callable
<
ApolloConfig
>()
{
@Override
public
ApolloConfig
call
()
throws
Exception
{
return
loadSingleApolloConfig
(
apolloRegistry
);
}
}));
}
List
<
ApolloConfig
>
apolloConfigList
=
Lists
.
newArrayList
();
for
(
Future
<
ApolloConfig
>
future
:
futures
)
{
try
{
ApolloConfig
result
=
future
.
get
();
if
(
result
==
null
)
{
continue
;
}
apolloConfigList
.
add
(
result
);
}
catch
(
ExecutionException
e
)
{
throw
e
.
getCause
();
}
}
return
apolloConfigList
;
}
ApolloConfig
loadSingleApolloConfig
(
ApolloRegistry
apolloRegistry
)
{
ApolloConfig
result
=
configLoader
.
loadApolloConfig
(
apolloRegistry
,
getPreviousApolloConfig
(
apolloRegistry
));
if
(
result
==
null
)
{
logger
.
error
(
"Loaded config null..."
);
return
null
;
}
logger
.
info
(
"Loaded config: {}"
,
result
);
updateCurrentApolloConfigCache
(
apolloRegistry
,
result
);
return
result
;
}
void
resetApolloRegistryConfigCache
()
{
this
.
previousApolloRegistryConfigCache
=
currentApolloRegistryConfigCache
;
this
.
currentApolloRegistryConfigCache
=
Maps
.
newConcurrentMap
();
}
ApolloConfig
getPreviousApolloConfig
(
ApolloRegistry
apolloRegistry
)
{
return
previousApolloRegistryConfigCache
.
get
(
apolloRegistry
);
}
void
updateCurrentApolloConfigCache
(
ApolloRegistry
apolloRegistry
,
ApolloConfig
apolloConfig
)
{
currentApolloRegistryConfigCache
.
put
(
apolloRegistry
,
apolloConfig
);
}
private
String
assemblePropertySourceName
(
ApolloConfig
apolloConfig
)
{
return
String
.
format
(
"%d-%s-%s-%d"
,
apolloConfig
.
getAppId
(),
apolloConfig
.
getCluster
(),
apolloConfig
.
getVersion
(),
apolloConfig
.
getReleaseId
());
}
}
apollo-client/src/main/java/com/ctrip/apollo/client/loader/impl/AbstractConfigLoader.java
0 → 100644
浏览文件 @
49c1b308
package
com.ctrip.apollo.client.loader.impl
;
import
com.ctrip.apollo.client.loader.ConfigLoader
;
import
com.ctrip.apollo.client.model.ApolloRegistry
;
import
com.ctrip.apollo.core.dto.ApolloConfig
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
/**
* @author Jason Song(song_s@ctrip.com)
*/
public
abstract
class
AbstractConfigLoader
implements
ConfigLoader
{
private
static
final
Logger
logger
=
LoggerFactory
.
getLogger
(
AbstractConfigLoader
.
class
);
private
ConfigLoader
fallback
;
@Override
public
ApolloConfig
loadApolloConfig
(
ApolloRegistry
apolloRegistry
,
ApolloConfig
previous
)
{
try
{
return
doLoadApolloConfig
(
apolloRegistry
,
previous
);
}
catch
(
Throwable
e
)
{
if
(
this
.
fallback
==
null
)
{
throw
new
RuntimeException
(
String
.
format
(
"Load Apollo Config failed - %s"
,
apolloRegistry
.
toString
()),
e
);
}
logger
.
error
(
"Load Config via {} failed, try to use its fallback {} to load"
,
getClass
().
getSimpleName
(),
fallback
.
getClass
().
getSimpleName
(),
e
);
return
this
.
fallback
.
loadApolloConfig
(
apolloRegistry
,
previous
);
}
}
protected
abstract
ApolloConfig
doLoadApolloConfig
(
ApolloRegistry
apolloRegistry
,
ApolloConfig
previous
);
@Override
public
void
setFallBackLoader
(
ConfigLoader
configLoader
)
{
this
.
fallback
=
configLoader
;
}
}
apollo-client/src/main/java/com/ctrip/apollo/client/loader/impl/InMemoryConfigLoader.java
0 → 100644
浏览文件 @
49c1b308
package
com.ctrip.apollo.client.loader.impl
;
import
com.ctrip.apollo.client.model.ApolloRegistry
;
import
com.ctrip.apollo.core.dto.ApolloConfig
;
/**
* @author Jason Song(song_s@ctrip.com)
*/
public
class
InMemoryConfigLoader
extends
AbstractConfigLoader
{
@Override
protected
ApolloConfig
doLoadApolloConfig
(
ApolloRegistry
apolloRegistry
,
ApolloConfig
previous
)
{
return
null
;
}
}
apollo-client/src/main/java/com/ctrip/apollo/client/loader/impl/LocalConfigLoader.java
→
apollo-client/src/main/java/com/ctrip/apollo/client/loader/impl/Local
File
ConfigLoader.java
浏览文件 @
49c1b308
package
com.ctrip.apollo.client.loader.impl
;
package
com.ctrip.apollo.client.loader.impl
;
import
com.ctrip.apollo.client.
loader.ConfigLoader
;
import
com.ctrip.apollo.client.
model.ApolloRegistry
;
import
org.springframework.core.env.CompositePropertySource
;
import
com.ctrip.apollo.core.dto.ApolloConfig
;
/**
/**
* Load config from local backup file
* Load config from local backup file
* @author Jason Song(song_s@ctrip.com)
* @author Jason Song(song_s@ctrip.com)
*/
*/
public
class
LocalConfigLoader
implements
ConfigLoader
{
public
class
LocalFileConfigLoader
extends
AbstractConfigLoader
{
private
static
final
String
PROPERTY_SOURCE_NAME
=
"ApolloLocalConfigProperties"
;
@Override
@Override
public
CompositePropertySource
loadPropertySource
(
)
{
public
ApolloConfig
doLoadApolloConfig
(
ApolloRegistry
apolloRegistry
,
ApolloConfig
previous
)
{
return
null
;
return
null
;
}
}
}
}
apollo-client/src/main/java/com/ctrip/apollo/client/loader/impl/RemoteConfigLoader.java
浏览文件 @
49c1b308
package
com.ctrip.apollo.client.loader.impl
;
package
com.ctrip.apollo.client.loader.impl
;
import
com.ctrip.apollo.client.loader.ConfigLoader
;
import
com.ctrip.apollo.client.model.ApolloRegistry
;
import
com.ctrip.apollo.client.model.ApolloRegistry
;
import
com.ctrip.apollo.client.util.ConfigUtil
;
import
com.ctrip.apollo.client.util.ConfigUtil
;
import
com.ctrip.apollo.core.dto.ApolloConfig
;
import
com.ctrip.apollo.core.dto.ApolloConfig
;
import
com.google.common.collect.
List
s
;
import
com.google.common.collect.
Map
s
;
import
org.slf4j.Logger
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.core.env.CompositePropertySource
;
import
org.springframework.core.env.MapPropertySource
;
import
org.springframework.http.HttpEntity
;
import
org.springframework.http.HttpEntity
;
import
org.springframework.http.HttpMethod
;
import
org.springframework.http.HttpMethod
;
import
org.springframework.http.HttpStatus
;
import
org.springframework.http.HttpStatus
;
...
@@ -16,126 +13,74 @@ import org.springframework.http.ResponseEntity;
...
@@ -16,126 +13,74 @@ import org.springframework.http.ResponseEntity;
import
org.springframework.util.StringUtils
;
import
org.springframework.util.StringUtils
;
import
org.springframework.web.client.RestTemplate
;
import
org.springframework.web.client.RestTemplate
;
import
java.io.IOException
;
import
java.util.Map
;
import
java.util.List
;
import
java.util.concurrent.*
;
import
java.util.concurrent.atomic.AtomicLong
;
/**
/**
* Load config from remote config server
* Load config from remote config server
*
*
* @author Jason Song(song_s@ctrip.com)
* @author Jason Song(song_s@ctrip.com)
*/
*/
public
class
RemoteConfigLoader
implements
ConfigLoader
{
public
class
RemoteConfigLoader
extends
AbstractConfigLoader
{
private
static
final
String
PROPERTY_SOURCE_NAME
=
"ApolloRemoteConfigProperties"
;
private
static
final
Logger
logger
=
LoggerFactory
.
getLogger
(
RemoteConfigLoader
.
class
);
private
static
final
Logger
logger
=
LoggerFactory
.
getLogger
(
RemoteConfigLoader
.
class
);
private
final
RestTemplate
restTemplate
;
private
final
RestTemplate
restTemplate
;
private
final
ConfigUtil
configUtil
;
private
final
ConfigUtil
configUtil
;
private
final
ExecutorService
executorService
;
private
final
AtomicLong
counter
;
public
RemoteConfigLoader
()
{
this
(
new
RestTemplate
(),
ConfigUtil
.
getInstance
());
}
public
RemoteConfigLoader
(
RestTemplate
restTemplate
,
ConfigUtil
configUtil
)
{
public
RemoteConfigLoader
(
RestTemplate
restTemplate
,
ConfigUtil
configUtil
)
{
this
.
restTemplate
=
restTemplate
;
this
.
restTemplate
=
restTemplate
;
this
.
configUtil
=
configUtil
;
this
.
configUtil
=
configUtil
;
this
.
counter
=
new
AtomicLong
();
this
.
executorService
=
Executors
.
newFixedThreadPool
(
5
,
new
ThreadFactory
()
{
@Override
public
Thread
newThread
(
Runnable
r
)
{
Thread
thread
=
new
Thread
(
r
,
"RemoteConfigLoader-"
+
counter
.
incrementAndGet
());
return
thread
;
}
});
}
@Override
public
CompositePropertySource
loadPropertySource
()
{
CompositePropertySource
composite
=
new
CompositePropertySource
(
PROPERTY_SOURCE_NAME
);
List
<
ApolloRegistry
>
apolloRegistries
;
try
{
apolloRegistries
=
configUtil
.
loadApolloRegistries
();
}
catch
(
IOException
e
)
{
throw
new
RuntimeException
(
"Load apollo config registry failed"
,
e
);
}
if
(
apolloRegistries
==
null
||
apolloRegistries
.
isEmpty
())
{
logger
.
warn
(
"No Apollo Registry found!"
);
return
composite
;
}
}
try
{
ApolloConfig
getRemoteConfig
(
RestTemplate
restTemplate
,
String
uri
,
String
cluster
,
ApolloRegistry
apolloRegistry
,
ApolloConfig
previousConfig
)
{
doLoadRemoteApolloConfig
(
apolloRegistries
,
composite
);
long
appId
=
apolloRegistry
.
getAppId
();
}
catch
(
Throwable
throwable
)
{
String
version
=
apolloRegistry
.
getVersion
();
throw
new
RuntimeException
(
"Load remote property source failed"
,
throwable
);
}
return
composite
;
}
void
doLoadRemoteApolloConfig
(
List
<
ApolloRegistry
>
apolloRegistries
,
CompositePropertySource
compositePropertySource
)
throws
Throwable
{
List
<
Future
<
MapPropertySource
>>
futures
=
Lists
.
newArrayList
();
for
(
final
ApolloRegistry
apolloRegistry
:
apolloRegistries
)
{
futures
.
add
(
executorService
.
submit
(
new
Callable
<
MapPropertySource
>()
{
@Override
public
MapPropertySource
call
()
throws
Exception
{
return
loadSingleApolloConfig
(
apolloRegistry
.
getAppId
(),
apolloRegistry
.
getVersion
());
}
}));
}
for
(
Future
<
MapPropertySource
>
future
:
futures
)
{
try
{
MapPropertySource
result
=
future
.
get
();
if
(
result
==
null
)
{
continue
;
}
compositePropertySource
.
addPropertySource
(
result
);
}
catch
(
ExecutionException
e
)
{
throw
e
.
getCause
();
}
}
}
MapPropertySource
loadSingleApolloConfig
(
long
appId
,
String
version
)
{
ApolloConfig
result
=
this
.
getRemoteConfig
(
restTemplate
,
configUtil
.
getConfigServerUrl
(),
appId
,
configUtil
.
getCluster
(),
version
);
if
(
result
==
null
)
{
logger
.
error
(
"Loaded config null..."
);
return
null
;
}
logger
.
info
(
"Loaded config: {}"
,
result
);
return
new
MapPropertySource
(
assemblePropertySourceName
(
result
),
result
.
getConfigurations
());
}
private
String
assemblePropertySourceName
(
ApolloConfig
apolloConfig
)
{
return
String
.
format
(
"%d-%s-%s-%d"
,
apolloConfig
.
getAppId
(),
apolloConfig
.
getCluster
(),
apolloConfig
.
getVersion
(),
apolloConfig
.
getReleaseId
());
}
ApolloConfig
getRemoteConfig
(
RestTemplate
restTemplate
,
String
uri
,
long
appId
,
String
cluster
,
String
version
)
{
logger
.
info
(
"Loading config from {}, appId={}, cluster={}, version={}"
,
uri
,
appId
,
cluster
,
version
);
logger
.
info
(
"Loading config from {}, appId={}, cluster={}, version={}"
,
uri
,
appId
,
cluster
,
version
);
String
path
=
"config/{appId}/{cluster}"
;
String
path
=
"/config/{appId}/{cluster}"
;
Object
[]
args
=
new
String
[]
{
String
.
valueOf
(
appId
),
cluster
};
Map
<
String
,
Object
>
paramMap
=
Maps
.
newHashMap
();
paramMap
.
put
(
"appId"
,
appId
);
paramMap
.
put
(
"cluster"
,
cluster
);
if
(
StringUtils
.
hasText
(
version
))
{
if
(
StringUtils
.
hasText
(
version
))
{
args
=
new
String
[]
{
String
.
valueOf
(
appId
),
cluster
,
version
};
path
=
path
+
"/{version}"
;
path
=
path
+
"/{version}"
;
paramMap
.
put
(
"version"
,
version
);
}
}
ResponseEntity
<
ApolloConfig
>
response
=
null
;
if
(
previousConfig
!=
null
)
{
path
=
path
+
"?releaseId={releaseId}"
;
paramMap
.
put
(
"releaseId"
,
previousConfig
.
getReleaseId
());
}
ResponseEntity
<
ApolloConfig
>
response
;
try
{
try
{
// TODO retry
// TODO retry
response
=
restTemplate
.
exchange
(
uri
response
=
restTemplate
.
exchange
(
uri
+
path
,
HttpMethod
.
GET
,
new
HttpEntity
<
Void
>((
Void
)
null
),
ApolloConfig
.
class
,
args
);
+
path
,
HttpMethod
.
GET
,
new
HttpEntity
<
Void
>((
Void
)
null
),
ApolloConfig
.
class
,
paramMap
);
}
catch
(
Exception
e
)
{
}
catch
(
Throwable
e
)
{
throw
e
;
throw
e
;
}
}
if
(
response
==
null
||
response
.
getStatusCode
()
!=
HttpStatus
.
OK
)
{
if
(
response
==
null
)
{
throw
new
RuntimeException
(
"Load apollo config failed, response is null"
);
}
if
(
response
.
getStatusCode
()
==
HttpStatus
.
NOT_MODIFIED
)
{
return
null
;
return
null
;
}
}
if
(
response
.
getStatusCode
()
!=
HttpStatus
.
OK
)
{
throw
new
RuntimeException
(
String
.
format
(
"Load apollo config failed, response status %s"
,
response
.
getStatusCode
()));
}
ApolloConfig
result
=
response
.
getBody
();
ApolloConfig
result
=
response
.
getBody
();
return
result
;
return
result
;
}
}
@Override
protected
ApolloConfig
doLoadApolloConfig
(
ApolloRegistry
apolloRegistry
,
ApolloConfig
previous
)
{
ApolloConfig
result
=
this
.
getRemoteConfig
(
restTemplate
,
configUtil
.
getConfigServerUrl
(),
configUtil
.
getCluster
(),
apolloRegistry
,
previous
);
//When remote server return 304, we need to return the previous result
return
result
==
null
?
previous
:
result
;
}
}
}
apollo-client/src/main/java/com/ctrip/apollo/client/model/ApolloRegistry.java
浏览文件 @
49c1b308
package
com.ctrip.apollo.client.model
;
package
com.ctrip.apollo.client.model
;
import
com.google.common.base.MoreObjects
;
/**
/**
* @author Jason Song(song_s@ctrip.com)
* @author Jason Song(song_s@ctrip.com)
*/
*/
...
@@ -22,4 +24,13 @@ public class ApolloRegistry {
...
@@ -22,4 +24,13 @@ public class ApolloRegistry {
public
void
setVersion
(
String
version
)
{
public
void
setVersion
(
String
version
)
{
this
.
version
=
version
;
this
.
version
=
version
;
}
}
@Override
public
String
toString
()
{
return
MoreObjects
.
toStringHelper
(
this
)
.
omitNullValues
()
.
add
(
"appId"
,
appId
)
.
add
(
"version"
,
version
)
.
toString
();
}
}
}
apollo-client/src/main/java/com/ctrip/apollo/client/model/PropertyChange.java
0 → 100644
浏览文件 @
49c1b308
package
com.ctrip.apollo.client.model
;
import
com.ctrip.apollo.client.enums.PropertyChangeType
;
/**
* @author Jason Song(song_s@ctrip.com)
*/
public
class
PropertyChange
{
private
String
propertyName
;
private
Object
oldValue
;
private
Object
newValue
;
private
PropertyChangeType
changeType
;
public
PropertyChange
(
String
propertyName
,
Object
oldValue
,
Object
newValue
,
PropertyChangeType
changeType
)
{
this
.
propertyName
=
propertyName
;
this
.
oldValue
=
oldValue
;
this
.
newValue
=
newValue
;
this
.
changeType
=
changeType
;
}
public
String
getPropertyName
()
{
return
propertyName
;
}
public
void
setPropertyName
(
String
propertyName
)
{
this
.
propertyName
=
propertyName
;
}
public
Object
getOldValue
()
{
return
oldValue
;
}
public
void
setOldValue
(
Object
oldValue
)
{
this
.
oldValue
=
oldValue
;
}
public
Object
getNewValue
()
{
return
newValue
;
}
public
void
setNewValue
(
Object
newValue
)
{
this
.
newValue
=
newValue
;
}
public
PropertyChangeType
getChangeType
()
{
return
changeType
;
}
public
void
setChangeType
(
PropertyChangeType
changeType
)
{
this
.
changeType
=
changeType
;
}
}
apollo-client/src/main/java/com/ctrip/apollo/client/model/PropertySourceReloadResult.java
0 → 100644
浏览文件 @
49c1b308
package
com.ctrip.apollo.client.model
;
import
com.google.common.collect.Lists
;
import
org.springframework.core.env.CompositePropertySource
;
import
java.util.List
;
/**
* @author Jason Song(song_s@ctrip.com)
*/
public
class
PropertySourceReloadResult
{
private
CompositePropertySource
propertySource
;
private
List
<
PropertyChange
>
changes
;
public
PropertySourceReloadResult
(
CompositePropertySource
propertySource
)
{
this
.
propertySource
=
propertySource
;
changes
=
Lists
.
newArrayList
();
}
public
PropertySourceReloadResult
(
CompositePropertySource
propertySource
,
List
<
PropertyChange
>
changes
)
{
this
.
propertySource
=
propertySource
;
this
.
changes
=
changes
;
}
public
CompositePropertySource
getPropertySource
()
{
return
propertySource
;
}
public
void
setPropertySource
(
CompositePropertySource
propertySource
)
{
this
.
propertySource
=
propertySource
;
}
public
List
<
PropertyChange
>
getChanges
()
{
return
changes
;
}
public
void
setChanges
(
List
<
PropertyChange
>
changes
)
{
this
.
changes
=
changes
;
}
public
boolean
hasChanges
()
{
return
!
changes
.
isEmpty
();
}
}
apollo-client/src/main/java/com/ctrip/apollo/client/util/ConfigUtil.java
浏览文件 @
49c1b308
...
@@ -33,7 +33,7 @@ public class ConfigUtil {
...
@@ -33,7 +33,7 @@ public class ConfigUtil {
public
String
getConfigServerUrl
()
{
public
String
getConfigServerUrl
()
{
// TODO return the meta server url based on different environments
// TODO return the meta server url based on different environments
return
"http://localhost
:8888
"
;
return
"http://localhost"
;
}
}
public
String
getCluster
()
{
public
String
getCluster
()
{
...
...
apollo-client/src/test/java/com/ctrip/apollo/client/AllTests.java
浏览文件 @
49c1b308
package
com.ctrip.apollo.client
;
package
com.ctrip.apollo.client
;
import
com.ctrip.apollo.client.loader.ConfigLoaderManagerTest
;
import
com.ctrip.apollo.client.loader.impl.RemoteConfigLoaderTest
;
import
com.ctrip.apollo.client.loader.impl.RemoteConfigLoaderTest
;
import
com.ctrip.apollo.client.util.ConfigUtilTest
;
import
com.ctrip.apollo.client.util.ConfigUtilTest
;
import
org.junit.runner.RunWith
;
import
org.junit.runner.RunWith
;
...
@@ -8,7 +9,8 @@ import org.junit.runners.Suite.SuiteClasses;
...
@@ -8,7 +9,8 @@ import org.junit.runners.Suite.SuiteClasses;
@RunWith
(
Suite
.
class
)
@RunWith
(
Suite
.
class
)
@SuiteClasses
({
@SuiteClasses
({
ApolloConfigManagerTest
.
class
,
RemoteConfigLoaderTest
.
class
,
ConfigUtilTest
.
class
ApolloConfigManagerTest
.
class
,
ConfigLoaderManagerTest
.
class
,
RemoteConfigLoaderTest
.
class
,
ConfigUtilTest
.
class
})
})
public
class
AllTests
{
public
class
AllTests
{
...
...
apollo-client/src/test/java/com/ctrip/apollo/client/ApolloConfigManagerTest.java
浏览文件 @
49c1b308
package
com.ctrip.apollo.client
;
package
com.ctrip.apollo.client
;
import
com.ctrip.apollo.client.loader.ConfigLoader
;
import
com.ctrip.apollo.client.loader.ConfigLoaderManager
;
import
com.ctrip.apollo.client.model.PropertyChange
;
import
com.ctrip.apollo.client.model.PropertySourceReloadResult
;
import
org.junit.After
;
import
org.junit.After
;
import
org.junit.Before
;
import
org.junit.Before
;
import
org.junit.BeforeClass
;
import
org.junit.Test
;
import
org.junit.Test
;
import
org.junit.runner.RunWith
;
import
org.junit.runner.RunWith
;
import
org.mockito.ArgumentCaptor
;
import
org.mockito.ArgumentCaptor
;
...
@@ -11,6 +12,7 @@ import org.mockito.Mock;
...
@@ -11,6 +12,7 @@ import org.mockito.Mock;
import
org.mockito.runners.MockitoJUnitRunner
;
import
org.mockito.runners.MockitoJUnitRunner
;
import
org.springframework.beans.factory.config.BeanDefinition
;
import
org.springframework.beans.factory.config.BeanDefinition
;
import
org.springframework.beans.factory.support.BeanDefinitionRegistry
;
import
org.springframework.beans.factory.support.BeanDefinitionRegistry
;
import
org.springframework.cloud.context.scope.refresh.RefreshScope
;
import
org.springframework.context.ApplicationContext
;
import
org.springframework.context.ApplicationContext
;
import
org.springframework.context.ConfigurableApplicationContext
;
import
org.springframework.context.ConfigurableApplicationContext
;
import
org.springframework.core.env.CompositePropertySource
;
import
org.springframework.core.env.CompositePropertySource
;
...
@@ -18,10 +20,11 @@ import org.springframework.core.env.ConfigurableEnvironment;
...
@@ -18,10 +20,11 @@ import org.springframework.core.env.ConfigurableEnvironment;
import
org.springframework.core.env.MutablePropertySources
;
import
org.springframework.core.env.MutablePropertySources
;
import
org.springframework.test.util.ReflectionTestUtils
;
import
org.springframework.test.util.ReflectionTestUtils
;
import
java.util.Collections
;
import
java.util.List
;
import
java.util.concurrent.atomic.AtomicReference
;
import
java.util.concurrent.atomic.AtomicReference
;
import
static
org
.
junit
.
Assert
.
assertEquals
;
import
static
org
.
junit
.
Assert
.
assertEquals
;
import
static
org
.
junit
.
Assert
.
assertTrue
;
import
static
org
.
mockito
.
Mockito
.*;
import
static
org
.
mockito
.
Mockito
.*;
/**
/**
...
@@ -31,7 +34,7 @@ import static org.mockito.Mockito.*;
...
@@ -31,7 +34,7 @@ import static org.mockito.Mockito.*;
public
class
ApolloConfigManagerTest
{
public
class
ApolloConfigManagerTest
{
private
ApolloConfigManager
apolloConfigManager
;
private
ApolloConfigManager
apolloConfigManager
;
@Mock
@Mock
private
ConfigLoader
configLoad
er
;
private
ConfigLoader
Manager
configLoaderManag
er
;
@Mock
@Mock
private
ConfigurableApplicationContext
applicationContext
;
private
ConfigurableApplicationContext
applicationContext
;
@Mock
@Mock
...
@@ -40,6 +43,8 @@ public class ApolloConfigManagerTest {
...
@@ -40,6 +43,8 @@ public class ApolloConfigManagerTest {
private
MutablePropertySources
mutablePropertySources
;
private
MutablePropertySources
mutablePropertySources
;
@Mock
@Mock
private
BeanDefinitionRegistry
beanDefinitionRegistry
;
private
BeanDefinitionRegistry
beanDefinitionRegistry
;
@Mock
private
RefreshScope
scope
;
@Before
@Before
public
void
setUp
()
{
public
void
setUp
()
{
...
@@ -49,7 +54,8 @@ public class ApolloConfigManagerTest {
...
@@ -49,7 +54,8 @@ public class ApolloConfigManagerTest {
when
(
env
.
getPropertySources
()).
thenReturn
(
mutablePropertySources
);
when
(
env
.
getPropertySources
()).
thenReturn
(
mutablePropertySources
);
apolloConfigManager
.
setApplicationContext
(
applicationContext
);
apolloConfigManager
.
setApplicationContext
(
applicationContext
);
ReflectionTestUtils
.
setField
(
apolloConfigManager
,
"configLoader"
,
configLoader
);
ReflectionTestUtils
.
setField
(
apolloConfigManager
,
"configLoaderManager"
,
configLoaderManager
);
ReflectionTestUtils
.
setField
(
apolloConfigManager
,
"scope"
,
scope
);
}
}
@After
@After
...
@@ -66,21 +72,20 @@ public class ApolloConfigManagerTest {
...
@@ -66,21 +72,20 @@ public class ApolloConfigManagerTest {
}
}
@Test
@Test
public
void
test
Prepar
ePropertySourceSuccessfully
()
{
public
void
test
Initializ
ePropertySourceSuccessfully
()
{
CompositePropertySource
somePropertySource
=
mock
(
CompositePropertySource
.
class
);
CompositePropertySource
somePropertySource
=
mock
(
CompositePropertySource
.
class
);
final
ArgumentCaptor
<
CompositePropertySource
>
captor
=
ArgumentCaptor
.
forClass
(
CompositePropertySource
.
class
);
final
ArgumentCaptor
<
CompositePropertySource
>
captor
=
ArgumentCaptor
.
forClass
(
CompositePropertySource
.
class
);
when
(
configLoader
.
loadPropertySource
()).
thenReturn
(
somePropertySource
);
when
(
configLoader
Manager
.
loadPropertySource
()).
thenReturn
(
somePropertySource
);
apolloConfigManager
.
initializePropertySource
();
apolloConfigManager
.
initializePropertySource
();
verify
(
configLoader
,
times
(
1
)).
loadPropertySource
();
verify
(
configLoader
Manager
,
times
(
1
)).
loadPropertySource
();
verify
(
mutablePropertySources
,
times
(
1
)).
addFirst
(
captor
.
capture
());
verify
(
mutablePropertySources
,
times
(
1
)).
addFirst
(
captor
.
capture
());
final
CompositePropertySource
insertedPropertySource
=
captor
.
getValue
();
final
CompositePropertySource
insertedPropertySource
=
captor
.
getValue
();
assertEquals
(
ApolloConfigManager
.
APOLLO_PROPERTY_SOURCE_NAME
,
insertedPropertySource
.
getName
());
assertEquals
(
insertedPropertySource
,
somePropertySource
);
assertTrue
(
insertedPropertySource
.
getPropertySources
().
contains
(
somePropertySource
));
}
}
@Test
@Test
...
@@ -92,4 +97,38 @@ public class ApolloConfigManagerTest {
...
@@ -92,4 +97,38 @@ public class ApolloConfigManagerTest {
verify
(
beanDefinitionRegistry
,
times
(
2
)).
registerBeanDefinition
(
anyString
(),
any
(
BeanDefinition
.
class
));
verify
(
beanDefinitionRegistry
,
times
(
2
)).
registerBeanDefinition
(
anyString
(),
any
(
BeanDefinition
.
class
));
}
}
@Test
public
void
testUpdatePropertySourceWithChanges
()
throws
Exception
{
PropertySourceReloadResult
somePropertySourceReloadResult
=
mock
(
PropertySourceReloadResult
.
class
);
CompositePropertySource
somePropertySource
=
mock
(
CompositePropertySource
.
class
);
List
<
PropertyChange
>
someChanges
=
mock
(
List
.
class
);
when
(
somePropertySourceReloadResult
.
hasChanges
()).
thenReturn
(
true
);
when
(
somePropertySourceReloadResult
.
getPropertySource
()).
thenReturn
(
somePropertySource
);
when
(
somePropertySourceReloadResult
.
getChanges
()).
thenReturn
(
someChanges
);
when
(
configLoaderManager
.
reloadPropertySource
()).
thenReturn
(
somePropertySourceReloadResult
);
List
<
PropertyChange
>
result
=
apolloConfigManager
.
updatePropertySource
();
assertEquals
(
someChanges
,
result
);
verify
(
scope
,
times
(
1
)).
refreshAll
();
}
@Test
public
void
testUpdatePropertySourceWithNoChange
()
throws
Exception
{
PropertySourceReloadResult
somePropertySourceReloadResult
=
mock
(
PropertySourceReloadResult
.
class
);
CompositePropertySource
somePropertySource
=
mock
(
CompositePropertySource
.
class
);
List
<
PropertyChange
>
emptyChanges
=
Collections
.
emptyList
();
when
(
somePropertySourceReloadResult
.
hasChanges
()).
thenReturn
(
false
);
when
(
somePropertySourceReloadResult
.
getPropertySource
()).
thenReturn
(
somePropertySource
);
when
(
somePropertySourceReloadResult
.
getChanges
()).
thenReturn
(
emptyChanges
);
when
(
configLoaderManager
.
reloadPropertySource
()).
thenReturn
(
somePropertySourceReloadResult
);
List
<
PropertyChange
>
result
=
apolloConfigManager
.
updatePropertySource
();
assertEquals
(
emptyChanges
,
result
);
verify
(
scope
,
never
()).
refreshAll
();
}
}
}
apollo-client/src/test/java/com/ctrip/apollo/client/loader/ConfigLoaderManagerTest.java
0 → 100644
浏览文件 @
49c1b308
package
com.ctrip.apollo.client.loader
;
import
com.ctrip.apollo.client.enums.PropertyChangeType
;
import
com.ctrip.apollo.client.model.ApolloRegistry
;
import
com.ctrip.apollo.client.model.PropertyChange
;
import
com.ctrip.apollo.client.model.PropertySourceReloadResult
;
import
com.ctrip.apollo.client.util.ConfigUtil
;
import
com.ctrip.apollo.core.dto.ApolloConfig
;
import
com.google.common.base.Function
;
import
com.google.common.collect.FluentIterable
;
import
com.google.common.collect.Lists
;
import
com.google.common.collect.Maps
;
import
com.google.common.collect.ObjectArrays
;
import
org.junit.Before
;
import
org.junit.Test
;
import
org.junit.runner.RunWith
;
import
org.mockito.Mock
;
import
org.mockito.runners.MockitoJUnitRunner
;
import
org.springframework.core.env.CompositePropertySource
;
import
org.springframework.core.env.MapPropertySource
;
import
org.springframework.core.env.PropertySource
;
import
org.springframework.test.util.ReflectionTestUtils
;
import
java.util.List
;
import
java.util.Map
;
import
static
org
.
junit
.
Assert
.
assertEquals
;
import
static
org
.
junit
.
Assert
.
assertTrue
;
import
static
org
.
mockito
.
Mockito
.*;
/**
* @author Jason Song(song_s@ctrip.com)
*/
@RunWith
(
MockitoJUnitRunner
.
class
)
public
class
ConfigLoaderManagerTest
{
private
ConfigLoaderManager
configLoaderManager
;
@Mock
private
ConfigLoader
configLoader
;
@Mock
private
ConfigUtil
configUtil
;
@Before
public
void
setUp
()
{
configLoaderManager
=
spy
(
new
ConfigLoaderManager
(
configLoader
,
configUtil
));
}
@Test
public
void
testLoadPropertySource
()
throws
Exception
{
long
someAppId
=
100
;
long
anotherAppId
=
101
;
ApolloRegistry
someApolloRegistry
=
assembleSomeApolloRegistry
(
someAppId
,
"someVersion"
);
ApolloRegistry
anotherApolloRegistry
=
assembleSomeApolloRegistry
(
anotherAppId
,
"anotherVersion"
);
ApolloConfig
someApolloConfig
=
mock
(
ApolloConfig
.
class
);
ApolloConfig
anotherApolloConfig
=
mock
(
ApolloConfig
.
class
);
Map
<
String
,
Object
>
someMap
=
mock
(
Map
.
class
);
Map
<
String
,
Object
>
anotherMap
=
mock
(
Map
.
class
);
when
(
someApolloConfig
.
getAppId
()).
thenReturn
(
someAppId
);
when
(
someApolloConfig
.
getAppId
()).
thenReturn
(
anotherAppId
);
when
(
configUtil
.
loadApolloRegistries
()).
thenReturn
(
Lists
.
newArrayList
(
someApolloRegistry
,
anotherApolloRegistry
));
doReturn
(
someApolloConfig
).
when
(
configLoaderManager
).
loadSingleApolloConfig
(
someApolloRegistry
);
doReturn
(
anotherApolloConfig
).
when
(
configLoaderManager
).
loadSingleApolloConfig
(
anotherApolloRegistry
);
when
(
someApolloConfig
.
getConfigurations
()).
thenReturn
(
someMap
);
when
(
anotherApolloConfig
.
getConfigurations
()).
thenReturn
(
anotherMap
);
CompositePropertySource
result
=
configLoaderManager
.
loadPropertySource
();
assertEquals
(
2
,
result
.
getPropertySources
().
size
());
List
<
Map
<
String
,
Object
>>
resultMaps
=
FluentIterable
.
from
(
result
.
getPropertySources
()).
transform
(
new
Function
<
PropertySource
<?>,
Map
<
String
,
Object
>>()
{
@Override
public
Map
<
String
,
Object
>
apply
(
PropertySource
<?>
input
)
{
return
(
Map
<
String
,
Object
>)
input
.
getSource
();
}
}).
toList
();
assertTrue
(
resultMaps
.
containsAll
(
Lists
.
newArrayList
(
someMap
,
anotherMap
)));
}
@Test
(
expected
=
RuntimeException
.
class
)
public
void
testLoadPropertySourceWithError
()
throws
Exception
{
Exception
someException
=
mock
(
Exception
.
class
);
long
someAppId
=
100
;
ApolloRegistry
someApolloRegistry
=
assembleSomeApolloRegistry
(
someAppId
,
"someVersion"
);
when
(
configUtil
.
loadApolloRegistries
()).
thenReturn
(
Lists
.
newArrayList
(
someApolloRegistry
));
doThrow
(
someException
).
when
(
configLoaderManager
).
loadSingleApolloConfig
(
someApolloRegistry
);
configLoaderManager
.
loadPropertySource
();
}
@Test
public
void
testLoadApolloConfigsWithNoApolloRegistry
()
throws
Exception
{
when
(
configUtil
.
loadApolloRegistries
()).
thenReturn
(
null
);
CompositePropertySource
result
=
configLoaderManager
.
loadPropertySource
();
assertTrue
(
result
.
getPropertySources
().
isEmpty
());
}
@Test
public
void
testLoadSingleApolloConfig
()
throws
Exception
{
ApolloConfig
someApolloConfig
=
mock
(
ApolloConfig
.
class
);
Map
<
String
,
Object
>
someMap
=
Maps
.
newHashMap
();
long
someAppId
=
100
;
ApolloRegistry
someApolloRegistry
=
assembleSomeApolloRegistry
(
someAppId
,
"someVersion"
);
ApolloConfig
previousConfig
=
null
;
doReturn
(
null
).
when
(
configLoaderManager
).
getPreviousApolloConfig
(
someApolloRegistry
);
when
(
someApolloConfig
.
getConfigurations
()).
thenReturn
(
someMap
);
when
(
configLoader
.
loadApolloConfig
(
someApolloRegistry
,
previousConfig
)).
thenReturn
(
someApolloConfig
);
ApolloConfig
result
=
configLoaderManager
.
loadSingleApolloConfig
(
someApolloRegistry
);
assertEquals
(
someMap
,
result
.
getConfigurations
());
}
@Test
public
void
testReloadPropertySource
()
throws
Exception
{
long
someAppId
=
100
;
ApolloRegistry
someApolloRegistry
=
assembleSomeApolloRegistry
(
someAppId
,
"someVersion"
);
ApolloConfig
someApolloConfig
=
mock
(
ApolloConfig
.
class
);
Map
<
String
,
Object
>
someMap
=
mock
(
Map
.
class
);
List
<
PropertyChange
>
someChanges
=
mock
(
List
.
class
);
ReflectionTestUtils
.
setField
(
configLoaderManager
,
"apolloRegistries"
,
Lists
.
newArrayList
(
someApolloRegistry
));
doReturn
(
someApolloConfig
).
when
(
configLoaderManager
).
loadSingleApolloConfig
(
someApolloRegistry
);
when
(
someApolloConfig
.
getAppId
()).
thenReturn
(
someAppId
);
when
(
someApolloConfig
.
getConfigurations
()).
thenReturn
(
someMap
);
doReturn
(
someChanges
).
when
(
configLoaderManager
).
calcPropertyChanges
(
anyList
(),
anyList
());
PropertySourceReloadResult
result
=
configLoaderManager
.
reloadPropertySource
();
assertEquals
(
1
,
result
.
getPropertySource
().
getPropertySources
().
size
());
assertEquals
(
someChanges
,
result
.
getChanges
());
List
<
Map
<
String
,
Object
>>
resultMaps
=
FluentIterable
.
from
(
result
.
getPropertySource
().
getPropertySources
()).
transform
(
new
Function
<
PropertySource
<?>,
Map
<
String
,
Object
>>()
{
@Override
public
Map
<
String
,
Object
>
apply
(
PropertySource
<?>
input
)
{
return
(
Map
<
String
,
Object
>)
input
.
getSource
();
}
}).
toList
();
assertTrue
(
resultMaps
.
containsAll
(
Lists
.
newArrayList
(
someMap
)));
}
@Test
public
void
testCalcPropertyChanges
()
throws
Exception
{
long
someAppId
=
1
;
Map
<
String
,
Object
>
someConfig
=
Maps
.
newHashMap
();
someConfig
.
put
(
"key1"
,
"val1"
);
someConfig
.
put
(
"key2"
,
"val2"
);
Map
<
String
,
Object
>
anotherConfig
=
Maps
.
newHashMap
();
anotherConfig
.
put
(
"key1"
,
"val11"
);
anotherConfig
.
put
(
"key3"
,
"val3"
);
List
<
ApolloConfig
>
previous
=
Lists
.
newArrayList
(
assembleApolloConfig
(
someAppId
,
someConfig
));
List
<
ApolloConfig
>
current
=
Lists
.
newArrayList
(
assembleApolloConfig
(
someAppId
,
anotherConfig
));
List
<
PropertyChange
>
changes
=
configLoaderManager
.
calcPropertyChanges
(
previous
,
current
);
assertEquals
(
3
,
changes
.
size
());
List
<
String
>
changeResult
=
FluentIterable
.
from
(
changes
).
transform
(
new
Function
<
PropertyChange
,
String
>()
{
@Override
public
String
apply
(
PropertyChange
input
)
{
return
String
.
format
(
"%s-%s"
,
input
.
getPropertyName
(),
input
.
getChangeType
());
}
}).
toList
();
assertTrue
(
changeResult
.
containsAll
(
Lists
.
newArrayList
(
"key1-"
+
PropertyChangeType
.
MODIFIED
,
"key2-"
+
PropertyChangeType
.
DELETED
,
"key3-"
+
PropertyChangeType
.
NEW
)));
}
ApolloConfig
assembleApolloConfig
(
long
appId
,
Map
<
String
,
Object
>
configurations
)
{
String
someCluster
=
"someCluster"
;
String
someVersion
=
"someVersion"
;
long
someReleaseId
=
1
;
ApolloConfig
config
=
new
ApolloConfig
(
appId
,
someCluster
,
someVersion
,
someReleaseId
);
config
.
setConfigurations
(
configurations
);
return
config
;
}
private
ApolloRegistry
assembleSomeApolloRegistry
(
long
someAppId
,
String
someVersion
)
{
ApolloRegistry
someApolloRegistry
=
new
ApolloRegistry
();
someApolloRegistry
.
setAppId
(
someAppId
);
someApolloRegistry
.
setVersion
(
someVersion
);
return
someApolloRegistry
;
}
}
apollo-client/src/test/java/com/ctrip/apollo/client/loader/impl/RemoteConfigLoaderTest.java
浏览文件 @
49c1b308
...
@@ -12,11 +12,16 @@ import org.mockito.Mock;
...
@@ -12,11 +12,16 @@ import org.mockito.Mock;
import
org.mockito.runners.MockitoJUnitRunner
;
import
org.mockito.runners.MockitoJUnitRunner
;
import
org.springframework.core.env.CompositePropertySource
;
import
org.springframework.core.env.CompositePropertySource
;
import
org.springframework.core.env.MapPropertySource
;
import
org.springframework.core.env.MapPropertySource
;
import
org.springframework.http.HttpEntity
;
import
org.springframework.http.HttpMethod
;
import
org.springframework.http.HttpStatus
;
import
org.springframework.http.ResponseEntity
;
import
org.springframework.web.client.RestTemplate
;
import
org.springframework.web.client.RestTemplate
;
import
java.util.Map
;
import
java.util.Map
;
import
static
org
.
junit
.
Assert
.
assertEquals
;
import
static
org
.
junit
.
Assert
.
assertEquals
;
import
static
org
.
junit
.
Assert
.
assertNull
;
import
static
org
.
junit
.
Assert
.
assertTrue
;
import
static
org
.
junit
.
Assert
.
assertTrue
;
import
static
org
.
mockito
.
Mockito
.*;
import
static
org
.
mockito
.
Mockito
.*;
...
@@ -29,6 +34,8 @@ public class RemoteConfigLoaderTest {
...
@@ -29,6 +34,8 @@ public class RemoteConfigLoaderTest {
@Mock
@Mock
private
RestTemplate
restTemplate
;
private
RestTemplate
restTemplate
;
private
ConfigUtil
configUtil
;
private
ConfigUtil
configUtil
;
@Mock
private
ResponseEntity
<
ApolloConfig
>
someResponse
;
@Before
@Before
public
void
setUp
()
{
public
void
setUp
()
{
...
@@ -37,57 +44,78 @@ public class RemoteConfigLoaderTest {
...
@@ -37,57 +44,78 @@ public class RemoteConfigLoaderTest {
}
}
@Test
@Test
public
void
testLoad
PropertySource
()
throws
Exception
{
public
void
testLoad
ApolloConfig
()
throws
Exception
{
long
someAppId
=
100
;
String
someServerUrl
=
"http://someUrl"
;
long
anotherAppId
=
101
;
String
someCluster
=
"some cluster"
;
Apollo
Registry
someApolloRegistry
=
assembleSomeApolloRegistry
(
someAppId
,
"someVersion"
);
Apollo
Config
apolloConfig
=
mock
(
ApolloConfig
.
class
);
ApolloRegistry
anotherApolloRegistry
=
assembleSomeApolloRegistry
(
anotherAppId
,
"anotherVersion"
)
;
long
someAppId
=
1
;
MapPropertySource
somePropertySource
=
mock
(
MapPropertySource
.
class
);
ApolloRegistry
apolloRegistry
=
assembleSomeApolloRegistry
(
someAppId
,
"someVersion"
);
MapPropertySource
anotherPropertySource
=
mock
(
MapPropertySource
.
class
)
;
ApolloConfig
previousConfig
=
null
;
doReturn
(
Lists
.
newArrayList
(
someApolloRegistry
,
anotherApolloRegistry
)).
when
(
configUtil
).
loadApolloRegistries
(
);
when
(
configUtil
.
getConfigServerUrl
()).
thenReturn
(
someServerUrl
);
doReturn
(
somePropertySource
).
when
(
remoteConfigLoader
).
loadSingleApolloConfig
(
someApolloRegistry
.
getAppId
(),
someApolloRegistry
.
getVersion
()
);
when
(
configUtil
.
getCluster
()).
thenReturn
(
someCluster
);
doReturn
(
a
notherPropertySource
).
when
(
remoteConfigLoader
).
loadSingleApolloConfig
(
anotherApolloRegistry
.
getAppId
(),
anotherApolloRegistry
.
getVersion
());
doReturn
(
a
polloConfig
).
when
(
remoteConfigLoader
)
.
getRemoteConfig
(
restTemplate
,
someServerUrl
,
someCluster
,
apolloRegistry
,
previousConfig
);
CompositePropertySource
result
=
remoteConfigLoader
.
loadPropertySource
();
ApolloConfig
result
=
remoteConfigLoader
.
loadApolloConfig
(
apolloRegistry
,
previousConfig
);
assertEquals
(
2
,
result
.
getPropertySources
().
size
());
assert
True
(
result
.
getPropertySources
().
containsAll
(
Lists
.
newArrayList
(
somePropertySource
,
anotherPropertySource
))
);
assert
Equals
(
apolloConfig
,
result
);
}
}
@Test
@Test
public
void
testLoadPropertySourceWithNoApolloRegistry
()
throws
Exception
{
public
void
testGetRemoteConfig
()
throws
Exception
{
doReturn
(
null
).
when
(
configUtil
).
loadApolloRegistries
();
long
someAppId
=
1
;
String
someServerUrl
=
"http://someServer"
;
String
someClusterName
=
"someCluster"
;
String
someVersionName
=
"someVersion"
;
ApolloConfig
someApolloConfig
=
mock
(
ApolloConfig
.
class
);
ApolloRegistry
apolloRegistry
=
assembleSomeApolloRegistry
(
someAppId
,
someVersionName
);
ApolloConfig
previousConfig
=
null
;
CompositePropertySource
result
=
remoteConfigLoader
.
loadPropertySource
();
when
(
someResponse
.
getStatusCode
()).
thenReturn
(
HttpStatus
.
OK
);
when
(
someResponse
.
getBody
()).
thenReturn
(
someApolloConfig
);
when
(
restTemplate
.
exchange
(
anyString
(),
eq
(
HttpMethod
.
GET
),
any
(
HttpEntity
.
class
),
eq
(
ApolloConfig
.
class
),
anyMap
())).
thenReturn
(
someResponse
);
assertTrue
(
result
.
getPropertySources
().
isEmpty
());
ApolloConfig
result
=
remoteConfigLoader
.
getRemoteConfig
(
restTemplate
,
someServerUrl
,
someClusterName
,
apolloRegistry
,
previousConfig
);
assertEquals
(
someApolloConfig
,
result
);
}
}
@Test
(
expected
=
RuntimeException
.
class
)
@Test
(
expected
=
RuntimeException
.
class
)
public
void
testLoadPropertySourceWithError
()
throws
Exception
{
public
void
testGetRemoteConfigWithServerError
()
throws
Exception
{
Exception
someException
=
mock
(
Exception
.
class
);
long
someAppId
=
1
;
long
someAppId
=
100
;
String
someServerUrl
=
"http://someServer"
;
ApolloRegistry
someApolloRegistry
=
assembleSomeApolloRegistry
(
someAppId
,
"someVersion"
);
String
someClusterName
=
"someCluster"
;
doReturn
(
Lists
.
newArrayList
(
someApolloRegistry
)).
when
(
configUtil
).
loadApolloRegistries
();
String
someVersionName
=
"someVersion"
;
ApolloRegistry
apolloRegistry
=
assembleSomeApolloRegistry
(
someAppId
,
someVersionName
);
doThrow
(
someException
).
when
(
remoteConfigLoader
).
loadSingleApolloConfig
(
someApolloRegistry
.
getAppId
(),
someApolloRegistry
.
getVersion
());
ApolloConfig
previousConfig
=
null
;
HttpStatus
someErrorCode
=
HttpStatus
.
INTERNAL_SERVER_ERROR
;
remoteConfigLoader
.
loadPropertySource
();
when
(
someResponse
.
getStatusCode
()).
thenReturn
(
someErrorCode
);
when
(
restTemplate
.
exchange
(
anyString
(),
eq
(
HttpMethod
.
GET
),
any
(
HttpEntity
.
class
),
eq
(
ApolloConfig
.
class
),
anyMap
())).
thenReturn
(
someResponse
);
remoteConfigLoader
.
getRemoteConfig
(
restTemplate
,
someServerUrl
,
someClusterName
,
apolloRegistry
,
previousConfig
);
}
}
@Test
@Test
public
void
testLoadSingleApolloConfig
()
throws
Exception
{
public
void
testGetRemoteConfigWith304Response
()
throws
Exception
{
ApolloConfig
someApolloConfig
=
mock
(
ApolloConfig
.
class
);
long
someAppId
=
1
;
Map
<
String
,
Object
>
someMap
=
Maps
.
newHashMap
();
String
someServerUrl
=
"http://someServer"
;
String
someClusterName
=
"someCluster"
;
String
someVersionName
=
"someVersion"
;
ApolloRegistry
apolloRegistry
=
assembleSomeApolloRegistry
(
someAppId
,
someVersionName
);
ApolloConfig
previousConfig
=
null
;
when
(
someResponse
.
getStatusCode
()).
thenReturn
(
HttpStatus
.
NOT_MODIFIED
);
when
(
restTemplate
.
exchange
(
anyString
(),
eq
(
HttpMethod
.
GET
),
any
(
HttpEntity
.
class
),
eq
(
ApolloConfig
.
class
),
anyMap
())).
thenReturn
(
someResponse
);
when
(
someApolloConfig
.
getConfigurations
()).
thenReturn
(
someMap
);
ApolloConfig
result
=
remoteConfigLoader
.
getRemoteConfig
(
restTemplate
,
someServerUrl
,
someClusterName
,
apolloRegistry
,
previousConfig
);
doReturn
(
someApolloConfig
).
when
(
remoteConfigLoader
).
getRemoteConfig
(
any
(
RestTemplate
.
class
),
anyString
(),
anyLong
(),
anyString
(),
anyString
());
long
someAppId
=
100
;
assertNull
(
result
);
MapPropertySource
result
=
remoteConfigLoader
.
loadSingleApolloConfig
(
someAppId
,
"someVersion"
);
assertEquals
(
someMap
,
result
.
getSource
());
}
}
private
ApolloRegistry
assembleSomeApolloRegistry
(
long
someAppId
,
String
someVersion
)
{
private
ApolloRegistry
assembleSomeApolloRegistry
(
long
someAppId
,
String
someVersion
)
{
...
...
apollo-configservice/src/main/java/com/ctrip/apollo/configservice/controller/ConfigController.java
浏览文件 @
49c1b308
...
@@ -3,10 +3,7 @@ package com.ctrip.apollo.configservice.controller;
...
@@ -3,10 +3,7 @@ package com.ctrip.apollo.configservice.controller;
import
com.ctrip.apollo.biz.entity.Version
;
import
com.ctrip.apollo.biz.entity.Version
;
import
com.ctrip.apollo.biz.service.ConfigService
;
import
com.ctrip.apollo.biz.service.ConfigService
;
import
com.ctrip.apollo.core.dto.ApolloConfig
;
import
com.ctrip.apollo.core.dto.ApolloConfig
;
import
org.springframework.web.bind.annotation.PathVariable
;
import
org.springframework.web.bind.annotation.*
;
import
org.springframework.web.bind.annotation.RequestMapping
;
import
org.springframework.web.bind.annotation.RequestParam
;
import
org.springframework.web.bind.annotation.RestController
;
import
javax.annotation.Resource
;
import
javax.annotation.Resource
;
import
javax.servlet.http.HttpServletResponse
;
import
javax.servlet.http.HttpServletResponse
;
...
@@ -21,7 +18,7 @@ public class ConfigController {
...
@@ -21,7 +18,7 @@ public class ConfigController {
@Resource
(
name
=
"configService"
)
@Resource
(
name
=
"configService"
)
private
ConfigService
configService
;
private
ConfigService
configService
;
@RequestMapping
(
value
=
"/{appId}/{clusterName}/{versionName:.*}"
)
@RequestMapping
(
value
=
"/{appId}/{clusterName}/{versionName:.*}"
,
method
=
RequestMethod
.
GET
)
public
ApolloConfig
queryConfig
(
@PathVariable
long
appId
,
public
ApolloConfig
queryConfig
(
@PathVariable
long
appId
,
@PathVariable
String
clusterName
,
@PathVariable
String
clusterName
,
@PathVariable
String
versionName
,
@PathVariable
String
versionName
,
...
...
apollo-core/src/main/java/com/ctrip/apollo/core/dto/ApolloConfig.java
浏览文件 @
49c1b308
...
@@ -4,12 +4,13 @@ import com.fasterxml.jackson.annotation.JsonCreator;
...
@@ -4,12 +4,13 @@ import com.fasterxml.jackson.annotation.JsonCreator;
import
com.fasterxml.jackson.annotation.JsonProperty
;
import
com.fasterxml.jackson.annotation.JsonProperty
;
import
com.google.common.base.MoreObjects
;
import
com.google.common.base.MoreObjects
;
import
java.util.Comparator
;
import
java.util.Map
;
import
java.util.Map
;
/**
/**
* @author Jason Song(song_s@ctrip.com)
* @author Jason Song(song_s@ctrip.com)
*/
*/
public
class
ApolloConfig
{
public
class
ApolloConfig
implements
Comparable
<
ApolloConfig
>
{
private
long
appId
;
private
long
appId
;
...
@@ -21,6 +22,8 @@ public class ApolloConfig {
...
@@ -21,6 +22,8 @@ public class ApolloConfig {
private
long
releaseId
;
private
long
releaseId
;
private
int
order
;
@JsonCreator
@JsonCreator
public
ApolloConfig
(
@JsonProperty
(
"appId"
)
long
appId
,
public
ApolloConfig
(
@JsonProperty
(
"appId"
)
long
appId
,
@JsonProperty
(
"cluster"
)
String
cluster
,
@JsonProperty
(
"cluster"
)
String
cluster
,
...
@@ -57,6 +60,14 @@ public class ApolloConfig {
...
@@ -57,6 +60,14 @@ public class ApolloConfig {
return
releaseId
;
return
releaseId
;
}
}
public
int
getOrder
()
{
return
order
;
}
public
void
setOrder
(
int
order
)
{
this
.
order
=
order
;
}
@Override
@Override
public
String
toString
()
{
public
String
toString
()
{
return
MoreObjects
.
toStringHelper
(
this
)
return
MoreObjects
.
toStringHelper
(
this
)
...
@@ -68,4 +79,15 @@ public class ApolloConfig {
...
@@ -68,4 +79,15 @@ public class ApolloConfig {
.
add
(
"configurations"
,
configurations
)
.
add
(
"configurations"
,
configurations
)
.
toString
();
.
toString
();
}
}
@Override
public
int
compareTo
(
ApolloConfig
o
)
{
if
(
o
==
null
||
this
.
getOrder
()
>
o
.
getOrder
())
{
return
1
;
}
if
(
o
.
getOrder
()
>
this
.
getOrder
())
{
return
-
1
;
}
return
0
;
}
}
}
apollo-demo/src/main/java/com/ctrip/apollo/demo/controller/DemoController.java
浏览文件 @
49c1b308
package
com.ctrip.apollo.demo.controller
;
package
com.ctrip.apollo.demo.controller
;
import
com.ctrip.apollo.client.ApolloConfigManager
;
import
com.ctrip.apollo.client.model.ApolloRegistry
;
import
com.ctrip.apollo.client.model.ApolloRegistry
;
import
com.ctrip.apollo.client.model.PropertyChange
;
import
com.ctrip.apollo.client.util.ConfigUtil
;
import
com.ctrip.apollo.client.util.ConfigUtil
;
import
com.ctrip.apollo.demo.model.Config
;
import
com.ctrip.apollo.demo.model.Config
;
import
com.ctrip.apollo.demo.service.DemoService
;
import
com.ctrip.apollo.demo.service.DemoService
;
...
@@ -27,11 +29,12 @@ public class DemoController {
...
@@ -27,11 +29,12 @@ public class DemoController {
private
Environment
env
;
private
Environment
env
;
@Autowired
@Autowired
private
DemoService
demoService
;
private
DemoService
demoService
;
//Apollo config client internal impl, not intended to be used by application, only for this test page
//Apollo config client internal impl, not intended to be used by application, only for this test page
!
private
ConfigUtil
configUtil
=
ConfigUtil
.
getInstance
();
private
ConfigUtil
configUtil
=
ConfigUtil
.
getInstance
();
//ApolloConfigManager, not intended to be used by application, only for this test page!
@Autowired
@Autowired
private
RefreshScope
scope
;
private
ApolloConfigManager
apolloConfigManager
;
@RequestMapping
(
value
=
"/config/{configName:.*}"
,
method
=
RequestMethod
.
GET
)
@RequestMapping
(
value
=
"/config/{configName:.*}"
,
method
=
RequestMethod
.
GET
)
public
Config
queryConfig
(
@PathVariable
String
configName
)
{
public
Config
queryConfig
(
@PathVariable
String
configName
)
{
...
@@ -49,8 +52,8 @@ public class DemoController {
...
@@ -49,8 +52,8 @@ public class DemoController {
}
}
@RequestMapping
(
value
=
"/refresh"
,
method
=
RequestMethod
.
POST
)
@RequestMapping
(
value
=
"/refresh"
,
method
=
RequestMethod
.
POST
)
public
String
refreshBeans
()
{
public
List
<
PropertyChange
>
refreshBeans
()
{
this
.
scope
.
refreshAll
();
List
<
PropertyChange
>
changes
=
this
.
apolloConfigManager
.
updatePropertySource
();
return
"ok"
;
return
changes
;
}
}
}
}
apollo-demo/src/main/webapp/s/scripts/app.js
浏览文件 @
49c1b308
...
@@ -7,11 +7,11 @@
...
@@ -7,11 +7,11 @@
]);
]);
app
.
controller
(
'
DemoController
'
,
function
(
$scope
,
$http
,
$modal
,
toastr
)
{
app
.
controller
(
'
DemoController
'
,
function
(
$scope
,
$http
,
$modal
,
toastr
)
{
//
var NONE = "none";
var
NONE
=
"
none
"
;
this
.
registries
=
{};
this
.
registries
=
{};
this
.
configQuery
=
{};
this
.
configQuery
=
{};
//
this.refreshResult = NONE;
this
.
refreshResult
=
NONE
;
this
.
injectedConfigValue
=
''
;
this
.
injectedConfigValue
=
''
;
var
self
=
this
;
var
self
=
this
;
...
@@ -46,24 +46,26 @@
...
@@ -46,24 +46,26 @@
});
});
};
};
//this.refreshConfig = function() {
this
.
refreshConfig
=
function
()
{
// $http.post("refresh")
$http
.
post
(
"
demo/refresh
"
)
// .success(function(data) {
.
success
(
function
(
data
)
{
// self.assembleRefreshResult(data);
self
.
assembleRefreshResult
(
data
);
// })
})
// .error(function(data, status) {
.
error
(
function
(
data
,
status
)
{
// toastr.error((data && data.msg) || 'Refresh config failed');
toastr
.
error
((
data
&&
data
.
msg
)
||
'
Refresh config failed
'
);
// });
});
//
//};
//this.assembleRefreshResult = function(changedPropertyArray) {
};
// if(!changedPropertyArray || !changedPropertyArray.length) {
// this.refreshResult = NONE;
this
.
assembleRefreshResult
=
function
(
changedPropertyArray
)
{
// return;
if
(
!
changedPropertyArray
||
!
changedPropertyArray
.
length
)
{
// }
this
.
refreshResult
=
NONE
;
// this.refreshResult = changedPropertyArray.join(',');
return
;
//};
}
this
.
refreshResult
=
_
.
map
(
changedPropertyArray
,
function
(
propertyChange
)
{
return
propertyChange
.
propertyName
+
'
(
'
+
propertyChange
.
changeType
+
'
)
'
;
});
};
this
.
loadRegistries
();
this
.
loadRegistries
();
...
...
apollo-demo/src/main/webapp/s/templates/list.html
浏览文件 @
49c1b308
...
@@ -70,12 +70,14 @@
...
@@ -70,12 +70,14 @@
</form>
</form>
</div>
</div>
<!--<div id="refresh-config-wrapper">-->
<div
id=
"refresh-config-wrapper"
>
<!--<h3>Refresh Config:</h3>-->
<h3>
Refresh Config:
</h3>
<!--<button type="button" class="btn btn-primary" ng-click="demoCtrl.refreshConfig()">Refresh Config</button>-->
<button
type=
"button"
class=
"btn btn-primary"
ng-click=
"demoCtrl.refreshConfig()"
>
Refresh
<!--<div id="refresh-result">-->
Config
<!--<strong>Changed Properties:</strong> {{demoCtrl.refreshResult}}-->
</button>
<!--</div>-->
<div
id=
"refresh-result"
>
<!--</div>-->
<strong>
Changed Properties:
</strong>
{{demoCtrl.refreshResult}}
</div>
</div>
</div>
</div>
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录