Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
wrr-cat
apollo
提交
90513a19
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,发现更多精彩内容 >>
提交
90513a19
编写于
7月 25, 2016
作者:
J
Jason Song
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
refactor code and add json config file controller
上级
a1e4690d
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
159 addition
and
28 deletion
+159
-28
apollo-configservice/src/main/java/com/ctrip/framework/apollo/configservice/controller/ConfigFileController.java
...apollo/configservice/controller/ConfigFileController.java
+79
-21
apollo-configservice/src/test/java/com/ctrip/framework/apollo/configservice/controller/ConfigFileControllerTest.java
...lo/configservice/controller/ConfigFileControllerTest.java
+37
-5
apollo-configservice/src/test/java/com/ctrip/framework/apollo/configservice/integration/ConfigFileControllerIntegrationTest.java
...vice/integration/ConfigFileControllerIntegrationTest.java
+43
-2
未找到文件。
apollo-configservice/src/main/java/com/ctrip/framework/apollo/configservice/controller/ConfigFileController.java
浏览文件 @
90513a19
...
...
@@ -11,6 +11,7 @@ import com.google.common.collect.HashMultimap;
import
com.google.common.collect.Lists
;
import
com.google.common.collect.Multimap
;
import
com.google.common.collect.Multimaps
;
import
com.google.gson.Gson
;
import
com.ctrip.framework.apollo.biz.entity.ReleaseMessage
;
import
com.ctrip.framework.apollo.biz.message.ReleaseMessageListener
;
...
...
@@ -19,11 +20,9 @@ import com.ctrip.framework.apollo.configservice.util.NamespaceUtil;
import
com.ctrip.framework.apollo.configservice.util.WatchKeysUtil
;
import
com.ctrip.framework.apollo.core.ConfigConsts
;
import
com.ctrip.framework.apollo.core.dto.ApolloConfig
;
import
com.ctrip.framework.apollo.core.dto.ApolloConfigNotification
;
import
com.ctrip.framework.apollo.core.utils.PropertiesUtil
;
import
com.dianping.cat.Cat
;
import
org.hibernate.cache.spi.CacheKey
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.beans.factory.annotation.Autowired
;
...
...
@@ -35,12 +34,9 @@ import org.springframework.web.bind.annotation.RequestMapping;
import
org.springframework.web.bind.annotation.RequestMethod
;
import
org.springframework.web.bind.annotation.RequestParam
;
import
org.springframework.web.bind.annotation.RestController
;
import
org.springframework.web.context.request.async.DeferredResult
;
import
java.io.IOException
;
import
java.io.StringWriter
;
import
java.util.ArrayList
;
import
java.util.Collection
;
import
java.util.List
;
import
java.util.Properties
;
import
java.util.Set
;
...
...
@@ -53,18 +49,20 @@ import javax.servlet.http.HttpServletResponse;
*/
@RestController
@RequestMapping
(
"/configfiles"
)
public
class
ConfigFileController
implements
ReleaseMessageListener
{
public
class
ConfigFileController
implements
ReleaseMessageListener
{
private
static
final
Logger
logger
=
LoggerFactory
.
getLogger
(
ConfigFileController
.
class
);
private
static
final
Joiner
STRING_JOINER
=
Joiner
.
on
(
ConfigConsts
.
CLUSTER_NAMESPACE_SEPARATOR
);
private
static
final
long
MAX_CACHE_SIZE
=
50
*
1024
*
1024
;
// 50MB
private
static
final
long
EXPIRE_AFTER_WRITE
=
10
;
private
final
HttpHeaders
responseHeaders
;
private
static
final
long
EXPIRE_AFTER_WRITE
=
30
;
private
final
HttpHeaders
propertiesResponseHeaders
;
private
final
HttpHeaders
jsonResponseHeaders
;
private
final
ResponseEntity
<
String
>
NOT_FOUND_RESPONSE
;
private
Cache
<
String
,
String
>
localCache
;
private
final
Multimap
<
String
,
String
>
watchedKeys2CacheKey
=
Multimaps
.
synchronizedSetMultimap
(
HashMultimap
.
create
());
private
final
Multimap
<
String
,
String
>
cacheKey2WatchedKeys
=
Multimaps
.
synchronizedSetMultimap
(
HashMultimap
.
create
());
private
static
final
Gson
gson
=
new
Gson
();
@Autowired
private
ConfigController
configController
;
...
...
@@ -103,23 +101,60 @@ public class ConfigFileController implements ReleaseMessageListener{
}
})
.
build
();
responseHeaders
=
new
HttpHeaders
();
responseHeaders
.
add
(
"Content-Type"
,
"text/plain;charset=UTF-8"
);
propertiesResponseHeaders
=
new
HttpHeaders
();
propertiesResponseHeaders
.
add
(
"Content-Type"
,
"text/plain;charset=UTF-8"
);
jsonResponseHeaders
=
new
HttpHeaders
();
jsonResponseHeaders
.
add
(
"Content-Type"
,
"application/json;charset=UTF-8"
);
NOT_FOUND_RESPONSE
=
new
ResponseEntity
<>(
HttpStatus
.
NOT_FOUND
);
}
@RequestMapping
(
value
=
"/{appId}/{clusterName}/{namespace:.+}"
,
method
=
RequestMethod
.
GET
)
public
ResponseEntity
<
String
>
queryConfigAsFile
(
@PathVariable
String
appId
,
public
ResponseEntity
<
String
>
queryConfigAsProperties
(
@PathVariable
String
appId
,
@PathVariable
String
clusterName
,
@PathVariable
String
namespace
,
@RequestParam
(
value
=
"dataCenter"
,
required
=
false
)
String
dataCenter
,
@RequestParam
(
value
=
"ip"
,
required
=
false
)
String
clientIp
,
HttpServletResponse
response
)
throws
IOException
{
String
result
=
queryConfig
(
ConfigFileOutputFormat
.
PROPERTIES
,
appId
,
clusterName
,
namespace
,
dataCenter
,
clientIp
,
response
);
if
(
result
==
null
)
{
return
NOT_FOUND_RESPONSE
;
}
return
new
ResponseEntity
<>(
result
,
propertiesResponseHeaders
,
HttpStatus
.
OK
);
}
@RequestMapping
(
value
=
"/json/{appId}/{clusterName}/{namespace:.+}"
,
method
=
RequestMethod
.
GET
)
public
ResponseEntity
<
String
>
queryConfigAsJson
(
@PathVariable
String
appId
,
@PathVariable
String
clusterName
,
@PathVariable
String
namespace
,
@RequestParam
(
value
=
"dataCenter"
,
required
=
false
)
String
dataCenter
,
@RequestParam
(
value
=
"ip"
,
required
=
false
)
String
clientIp
,
HttpServletResponse
response
)
throws
IOException
{
String
result
=
queryConfig
(
ConfigFileOutputFormat
.
JSON
,
appId
,
clusterName
,
namespace
,
dataCenter
,
clientIp
,
response
);
if
(
result
==
null
)
{
return
NOT_FOUND_RESPONSE
;
}
return
new
ResponseEntity
<>(
result
,
jsonResponseHeaders
,
HttpStatus
.
OK
);
}
String
queryConfig
(
ConfigFileOutputFormat
outputFormat
,
String
appId
,
String
clusterName
,
String
namespace
,
String
dataCenter
,
String
clientIp
,
HttpServletResponse
response
)
throws
IOException
{
//strip out .properties suffix
namespace
=
namespaceUtil
.
filterNamespaceName
(
namespace
);
//TODO add clientIp as key parts?
String
cacheKey
=
assembleCacheKey
(
appId
,
clusterName
,
namespace
,
dataCenter
);
String
cacheKey
=
assembleCacheKey
(
outputFormat
,
appId
,
clusterName
,
namespace
,
dataCenter
);
String
result
=
localCache
.
getIfPresent
(
cacheKey
);
...
...
@@ -131,11 +166,19 @@ public class ConfigFileController implements ReleaseMessageListener{
response
);
if
(
apolloConfig
==
null
||
apolloConfig
.
getConfigurations
()
==
null
)
{
return
NOT_FOUND_RESPONSE
;
return
null
;
}
switch
(
outputFormat
)
{
case
PROPERTIES:
Properties
properties
=
new
Properties
();
properties
.
putAll
(
apolloConfig
.
getConfigurations
());
result
=
PropertiesUtil
.
toString
(
properties
);
break
;
case
JSON:
result
=
gson
.
toJson
(
apolloConfig
.
getConfigurations
());
break
;
}
Properties
properties
=
new
Properties
();
properties
.
putAll
(
apolloConfig
.
getConfigurations
());
result
=
PropertiesUtil
.
toString
(
properties
);
localCache
.
put
(
cacheKey
,
result
);
logger
.
debug
(
"adding cache for key: {}"
,
cacheKey
);
...
...
@@ -153,13 +196,14 @@ public class ConfigFileController implements ReleaseMessageListener{
Cat
.
logEvent
(
"ConfigFile-Cache-Hit"
,
cacheKey
);
}
return
new
ResponseEntity
<>(
result
,
responseHeaders
,
HttpStatus
.
OK
);
return
result
;
}
String
assembleCacheKey
(
String
appId
,
String
clusterName
,
String
namespace
,
String
dataCenter
)
{
List
<
String
>
keyParts
=
Lists
.
newArrayList
(
appId
,
clusterName
,
namespace
);
String
assembleCacheKey
(
ConfigFileOutputFormat
outputFormat
,
String
appId
,
String
clusterName
,
String
namespace
,
String
dataCenter
)
{
List
<
String
>
keyParts
=
Lists
.
newArrayList
(
outputFormat
.
getValue
(),
appId
,
clusterName
,
namespace
);
if
(!
Strings
.
isNullOrEmpty
(
dataCenter
))
{
keyParts
.
add
(
dataCenter
);
}
...
...
@@ -187,4 +231,18 @@ public class ConfigFileController implements ReleaseMessageListener{
localCache
.
invalidate
(
cacheKey
);
}
}
enum
ConfigFileOutputFormat
{
PROPERTIES
(
"properties"
),
JSON
(
"json"
);
private
String
value
;
ConfigFileOutputFormat
(
String
value
)
{
this
.
value
=
value
;
}
public
String
getValue
()
{
return
value
;
}
}
}
apollo-configservice/src/test/java/com/ctrip/framework/apollo/configservice/controller/ConfigFileControllerTest.java
浏览文件 @
90513a19
...
...
@@ -5,6 +5,8 @@ import com.google.common.collect.ImmutableMap;
import
com.google.common.collect.Lists
;
import
com.google.common.collect.Multimap
;
import
com.google.common.collect.Sets
;
import
com.google.common.reflect.TypeToken
;
import
com.google.gson.Gson
;
import
com.ctrip.framework.apollo.biz.entity.ReleaseMessage
;
import
com.ctrip.framework.apollo.biz.message.Topics
;
...
...
@@ -21,7 +23,7 @@ import org.springframework.http.HttpStatus;
import
org.springframework.http.ResponseEntity
;
import
org.springframework.test.util.ReflectionTestUtils
;
import
java.
util.List
;
import
java.
lang.reflect.Type
;
import
java.util.Map
;
import
java.util.Set
;
...
...
@@ -81,7 +83,7 @@ public class ConfigFileControllerTest {
}
@Test
public
void
testQueryConfigAs
File
()
throws
Exception
{
public
void
testQueryConfigAs
Properties
()
throws
Exception
{
String
someKey
=
"someKey"
;
String
someValue
=
"someValue"
;
String
anotherKey
=
"anotherKey"
;
...
...
@@ -93,7 +95,7 @@ public class ConfigFileControllerTest {
String
cacheKey
=
configFileController
.
assembleCacheKey
(
someAppId
,
someClusterName
,
someNamespace
,
someDataCenter
);
.
assembleCacheKey
(
ConfigFileController
.
ConfigFileOutputFormat
.
PROPERTIES
,
someAppId
,
someClusterName
,
someNamespace
,
someDataCenter
);
Map
<
String
,
String
>
configurations
=
ImmutableMap
.
of
(
someKey
,
someValue
,
anotherKey
,
anotherValue
);
...
...
@@ -108,7 +110,7 @@ public class ConfigFileControllerTest {
ResponseEntity
<
String
>
response
=
configFileController
.
queryConfigAs
File
(
someAppId
,
someClusterName
,
someNamespace
,
someDataCenter
,
.
queryConfigAs
Properties
(
someAppId
,
someClusterName
,
someNamespace
,
someDataCenter
,
someClientIp
,
someResponse
);
assertEquals
(
2
,
watchedKeys2CacheKey
.
size
());
...
...
@@ -124,7 +126,7 @@ public class ConfigFileControllerTest {
ResponseEntity
<
String
>
anotherResponse
=
configFileController
.
queryConfigAs
File
(
someAppId
,
someClusterName
,
someNamespace
,
someDataCenter
,
.
queryConfigAs
Properties
(
someAppId
,
someClusterName
,
someNamespace
,
someDataCenter
,
someClientIp
,
someResponse
);
assertEquals
(
response
,
anotherResponse
);
...
...
@@ -134,6 +136,36 @@ public class ConfigFileControllerTest {
someResponse
);
}
@Test
public
void
testQueryConfigAsJson
()
throws
Exception
{
String
someKey
=
"someKey"
;
String
someValue
=
"someValue"
;
Gson
gson
=
new
Gson
();
Type
responseType
=
new
TypeToken
<
Map
<
String
,
String
>>(){}.
getType
();
String
someWatchKey
=
"someWatchKey"
;
Set
<
String
>
watchKeys
=
Sets
.
newHashSet
(
someWatchKey
);
Map
<
String
,
String
>
configurations
=
ImmutableMap
.
of
(
someKey
,
someValue
);
ApolloConfig
someApolloConfig
=
mock
(
ApolloConfig
.
class
);
when
(
configController
.
queryConfig
(
someAppId
,
someClusterName
,
someNamespace
,
someDataCenter
,
"-1"
,
someClientIp
,
someResponse
)).
thenReturn
(
someApolloConfig
);
when
(
someApolloConfig
.
getConfigurations
()).
thenReturn
(
configurations
);
when
(
watchKeysUtil
.
assembleAllWatchKeys
(
someAppId
,
someClusterName
,
someNamespace
,
someDataCenter
))
.
thenReturn
(
watchKeys
);
ResponseEntity
<
String
>
response
=
configFileController
.
queryConfigAsJson
(
someAppId
,
someClusterName
,
someNamespace
,
someDataCenter
,
someClientIp
,
someResponse
);
assertEquals
(
HttpStatus
.
OK
,
response
.
getStatusCode
());
assertEquals
(
configurations
,
gson
.
fromJson
(
response
.
getBody
(),
responseType
));
}
@Test
public
void
testHandleMessage
()
throws
Exception
{
String
someWatchKey
=
"someWatchKey"
;
...
...
apollo-configservice/src/test/java/com/ctrip/framework/apollo/configservice/integration/ConfigFileControllerIntegrationTest.java
浏览文件 @
90513a19
...
...
@@ -2,6 +2,8 @@ package com.ctrip.framework.apollo.configservice.integration;
import
com.google.common.collect.ImmutableMap
;
import
com.google.common.collect.Lists
;
import
com.google.common.reflect.TypeToken
;
import
com.google.gson.Gson
;
import
com.ctrip.framework.apollo.biz.entity.Namespace
;
import
com.ctrip.framework.apollo.core.ConfigConsts
;
...
...
@@ -13,6 +15,7 @@ import org.springframework.http.HttpStatus;
import
org.springframework.http.ResponseEntity
;
import
org.springframework.test.context.jdbc.Sql
;
import
java.lang.reflect.Type
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.concurrent.TimeUnit
;
...
...
@@ -30,6 +33,8 @@ public class ConfigFileControllerIntegrationTest extends AbstractBaseIntegration
private
String
somePublicNamespace
;
private
String
someDC
;
private
String
someDefaultCluster
;
private
Gson
gson
=
new
Gson
();
private
Type
mapResponseType
=
new
TypeToken
<
Map
<
String
,
String
>>(){}.
getType
();
@Before
public
void
setUp
()
throws
Exception
{
...
...
@@ -44,7 +49,7 @@ public class ConfigFileControllerIntegrationTest extends AbstractBaseIntegration
@Test
@Sql
(
scripts
=
"/integration-test/test-release.sql"
,
executionPhase
=
Sql
.
ExecutionPhase
.
BEFORE_TEST_METHOD
)
@Sql
(
scripts
=
"/integration-test/cleanup.sql"
,
executionPhase
=
Sql
.
ExecutionPhase
.
AFTER_TEST_METHOD
)
public
void
testQueryConfigAs
File
()
throws
Exception
{
public
void
testQueryConfigAs
Properties
()
throws
Exception
{
ResponseEntity
<
String
>
response
=
restTemplate
.
getForEntity
(
"{baseurl}/configfiles/{appId}/{clusterName}/{namespace}"
,
String
.
class
,
...
...
@@ -60,7 +65,7 @@ public class ConfigFileControllerIntegrationTest extends AbstractBaseIntegration
@Sql
(
scripts
=
"/integration-test/test-release.sql"
,
executionPhase
=
Sql
.
ExecutionPhase
.
BEFORE_TEST_METHOD
)
@Sql
(
scripts
=
"/integration-test/test-release-public-dc-override.sql"
,
executionPhase
=
Sql
.
ExecutionPhase
.
BEFORE_TEST_METHOD
)
@Sql
(
scripts
=
"/integration-test/cleanup.sql"
,
executionPhase
=
Sql
.
ExecutionPhase
.
AFTER_TEST_METHOD
)
public
void
testQueryPublicConfigAs
File
()
throws
Exception
{
public
void
testQueryPublicConfigAs
Properties
()
throws
Exception
{
ResponseEntity
<
String
>
response
=
restTemplate
.
getForEntity
(
...
...
@@ -75,6 +80,42 @@ public class ConfigFileControllerIntegrationTest extends AbstractBaseIntegration
assertTrue
(
result
.
contains
(
"k2=someDC-v2"
));
}
@Test
@Sql
(
scripts
=
"/integration-test/test-release.sql"
,
executionPhase
=
Sql
.
ExecutionPhase
.
BEFORE_TEST_METHOD
)
@Sql
(
scripts
=
"/integration-test/cleanup.sql"
,
executionPhase
=
Sql
.
ExecutionPhase
.
AFTER_TEST_METHOD
)
public
void
testQueryConfigAsJson
()
throws
Exception
{
ResponseEntity
<
String
>
response
=
restTemplate
.
getForEntity
(
"{baseurl}/configfiles/json/{appId}/{clusterName}/{namespace}"
,
String
.
class
,
getHostUrl
(),
someAppId
,
someCluster
,
someNamespace
);
String
result
=
response
.
getBody
();
Map
<
String
,
String
>
configs
=
gson
.
fromJson
(
response
.
getBody
(),
mapResponseType
);
assertEquals
(
HttpStatus
.
OK
,
response
.
getStatusCode
());
assertEquals
(
"v2"
,
configs
.
get
(
"k2"
));
}
@Test
@Sql
(
scripts
=
"/integration-test/test-release.sql"
,
executionPhase
=
Sql
.
ExecutionPhase
.
BEFORE_TEST_METHOD
)
@Sql
(
scripts
=
"/integration-test/test-release-public-dc-override.sql"
,
executionPhase
=
Sql
.
ExecutionPhase
.
BEFORE_TEST_METHOD
)
@Sql
(
scripts
=
"/integration-test/cleanup.sql"
,
executionPhase
=
Sql
.
ExecutionPhase
.
AFTER_TEST_METHOD
)
public
void
testQueryPublicConfigAsJson
()
throws
Exception
{
ResponseEntity
<
String
>
response
=
restTemplate
.
getForEntity
(
"{baseurl}/configfiles/json/{appId}/{clusterName}/{namespace}?dataCenter={dateCenter}"
,
String
.
class
,
getHostUrl
(),
someAppId
,
someDefaultCluster
,
somePublicNamespace
,
someDC
);
String
result
=
response
.
getBody
();
Map
<
String
,
String
>
configs
=
gson
.
fromJson
(
response
.
getBody
(),
mapResponseType
);
assertEquals
(
HttpStatus
.
OK
,
response
.
getStatusCode
());
assertEquals
(
"override-someDC-v1"
,
configs
.
get
(
"k1"
));
assertEquals
(
"someDC-v2"
,
configs
.
get
(
"k2"
));
}
@Test
@Sql
(
scripts
=
"/integration-test/test-release.sql"
,
executionPhase
=
Sql
.
ExecutionPhase
.
BEFORE_TEST_METHOD
)
@Sql
(
scripts
=
"/integration-test/cleanup.sql"
,
executionPhase
=
Sql
.
ExecutionPhase
.
AFTER_TEST_METHOD
)
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录