Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
A
apollo
Project
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
openSource
apollo
Commits
90513a19
Commit
90513a19
authored
Jul 25, 2016
by
Jason Song
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
refactor code and add json config file controller
parent
a1e4690d
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
155 additions
and
24 deletions
+155
-24
ConfigFileController.java
...apollo/configservice/controller/ConfigFileController.java
+75
-17
ConfigFileControllerTest.java
...lo/configservice/controller/ConfigFileControllerTest.java
+37
-5
ConfigFileControllerIntegrationTest.java
...vice/integration/ConfigFileControllerIntegrationTest.java
+43
-2
No files found.
apollo-configservice/src/main/java/com/ctrip/framework/apollo/configservice/controller/ConfigFileController.java
View file @
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
;
}
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
assembleCacheKey
(
ConfigFileOutputFormat
outputFormat
,
String
appId
,
String
clusterName
,
String
namespace
,
String
dataCenter
)
{
List
<
String
>
keyParts
=
Lists
.
newArrayList
(
appId
,
clusterName
,
namespace
);
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
View file @
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
);
...
...
@@ -135,6 +137,36 @@ public class ConfigFileControllerTest {
}
@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"
;
String
anotherWatchKey
=
"anotherWatchKey"
;
...
...
apollo-configservice/src/test/java/com/ctrip/framework/apollo/configservice/integration/ConfigFileControllerIntegrationTest.java
View file @
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
(
...
...
@@ -78,6 +83,42 @@ 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
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
)
public
void
testConfigChanged
()
throws
Exception
{
ResponseEntity
<
String
>
response
=
restTemplate
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment