提交 047000dc 编写于 作者: Y Yiming Liu

Merge pull request #14 from nobodyiam/apollo_client_merge

Load property source from remote config server
......@@ -4,7 +4,7 @@
<parent>
<groupId>com.ctrip.apollo</groupId>
<artifactId>apollo</artifactId>
<version>0.0.1</version>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
......
......@@ -4,12 +4,15 @@
<parent>
<groupId>com.ctrip.apollo</groupId>
<artifactId>apollo</artifactId>
<version>0.0.1</version>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>apollo-client</artifactId>
<name>Apollo Client</name>
<properties>
<java.version>1.7</java.version>
</properties>
<dependencies>
<!-- apollo -->
<dependency>
......@@ -22,6 +25,10 @@
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
</dependency>
<!-- end of spring -->
<!-- util -->
<dependency>
......@@ -29,12 +36,34 @@
<artifactId>guava</artifactId>
</dependency>
<!-- end of util -->
<!-- log -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<scope>provided</scope>
</dependency>
<!-- end of log -->
<!-- test -->
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<scope>test</scope>
</dependency>
<!-- end of test -->
</dependencies>
</project>
......@@ -2,6 +2,7 @@ package com.ctrip.apollo.client;
import com.ctrip.apollo.client.loader.ConfigLoader;
import com.ctrip.apollo.client.loader.ConfigLoaderFactory;
import com.ctrip.apollo.client.util.ConfigUtil;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
......@@ -27,7 +28,7 @@ public class ApolloConfig implements BeanDefinitionRegistryPostProcessor, Priori
private ConfigurableApplicationContext applicationContext;
public ApolloConfig() {
this.configLoader = ConfigLoaderFactory.getInstance().getMockConfigLoader();
this.configLoader = ConfigLoaderFactory.getInstance().getRemoteConfigLoader();
}
@Override
......@@ -37,10 +38,13 @@ public class ApolloConfig implements BeanDefinitionRegistryPostProcessor, Priori
String.format("ApplicationContext must implement ConfigurableApplicationContext, but found: %s", applicationContext.getClass().getName()));
}
this.applicationContext = (ConfigurableApplicationContext) applicationContext;
ConfigUtil.getInstance().setApplicationContext(applicationContext);
}
/**
* This is the first method invoked, so we could prepare the property sources here
* This is the first method invoked, so we could prepare the property sources here.
* Specifically we need to finish preparing property source before PropertySourcesPlaceholderConfigurer
* so that configurations could be injected correctly
*/
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
......
package com.ctrip.apollo.client.constants;
/**
* @author Jason Song(song_s@ctrip.com)
*/
public class Constants {
public static final String APP_ID = "appId";
public static final String VERSION = "version";
public static final String DEFAULT_VERSION_NAME = "latest-release";
}
package com.ctrip.apollo.client.loader;
import com.ctrip.apollo.client.loader.impl.MockConfigLoader;
import com.ctrip.apollo.client.loader.impl.RemoteConfigLoader;
/**
* @author Jason Song(song_s@ctrip.com)
......@@ -18,4 +19,8 @@ public class ConfigLoaderFactory {
public ConfigLoader getMockConfigLoader() {
return new MockConfigLoader();
}
public ConfigLoader getRemoteConfigLoader() {
return new RemoteConfigLoader();
}
}
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.util.ConfigUtil;
import com.ctrip.apollo.core.environment.Environment;
import com.ctrip.apollo.core.environment.PropertySource;
import com.google.common.collect.Lists;
import org.slf4j.Logger;
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.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicLong;
/**
* Load config from remote config server
*
* @author Jason Song(song_s@ctrip.com)
*/
public class RemoteConfigLoader implements ConfigLoader {
private static final String PROPERTY_SOURCE_NAME = "ApolloRemoteConfigProperties";
private static final Logger logger = LoggerFactory.getLogger(RemoteConfigLoader.class);
private final RestTemplate restTemplate;
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) {
this.restTemplate = restTemplate;
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() {
return null;
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 {
doLoadRemoteApolloConfig(apolloRegistries, composite);
} catch (Throwable throwable) {
throw new RuntimeException("Load remote property source failed", throwable);
}
return composite;
}
void doLoadRemoteApolloConfig(List<ApolloRegistry> apolloRegistries, CompositePropertySource compositePropertySource) throws Throwable {
List<Future<CompositePropertySource>> futures = Lists.newArrayList();
for (final ApolloRegistry apolloRegistry : apolloRegistries) {
futures.add(executorService.submit(new Callable<CompositePropertySource>() {
@Override
public CompositePropertySource call() throws Exception {
return loadSingleApolloConfig(apolloRegistry.getAppId(), apolloRegistry.getVersion());
}
}));
}
for (Future<CompositePropertySource> future : futures) {
try {
compositePropertySource.addPropertySource(future.get());
} catch (ExecutionException e) {
throw e.getCause();
}
}
}
CompositePropertySource loadSingleApolloConfig(String appId, String version) {
CompositePropertySource composite = new CompositePropertySource(appId + "-" + version);
Environment result =
this.getRemoteEnvironment(restTemplate, configUtil.getConfigServerUrl(), appId, configUtil.getCluster(), version);
if (result == null) {
logger.error("Loaded environment as null...");
return composite;
}
logger.info("Loaded environment: name={}, cluster={}, label={}, version={}", result.getName(), result.getProfiles(), result.getLabel(), result.getVersion());
for (PropertySource source : result.getPropertySources()) {
composite.addPropertySource(new MapPropertySource(source.getName(), source.getSource()));
}
return composite;
}
Environment getRemoteEnvironment(RestTemplate restTemplate, String uri, String name, String cluster, String release) {
logger.info("Loading environment from {}, name={}, cluster={}, release={}", uri, name, cluster, release);
String path = "/{name}/{cluster}";
Object[] args = new String[] {name, cluster};
if (StringUtils.hasText(release)) {
args = new String[] {name, cluster, release};
path = path + "/{release}";
}
ResponseEntity<Environment> response = null;
try {
// TODO retry
response = restTemplate.exchange(uri
+ path, HttpMethod.GET, new HttpEntity<Void>((Void) null), Environment.class, args);
} catch (Exception e) {
throw e;
}
if (response == null || response.getStatusCode() != HttpStatus.OK) {
return null;
}
Environment result = response.getBody();
return result;
}
}
package com.ctrip.apollo.client.model;
/**
* @author Jason Song(song_s@ctrip.com)
*/
public class ApolloRegistry {
private String appId;
private String version;
public String getAppId() {
return appId;
}
public String getVersion() {
return version;
}
public void setAppId(String appId) {
this.appId = appId;
}
public void setVersion(String version) {
this.version = version;
}
}
package com.ctrip.apollo.client.util;
import com.ctrip.apollo.client.constants.Constants;
import com.ctrip.apollo.client.model.ApolloRegistry;
import com.google.common.base.Function;
import com.google.common.base.Predicates;
import com.google.common.collect.FluentIterable;
import org.springframework.context.ApplicationContext;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.EncodedResource;
import org.springframework.core.io.support.PropertiesLoaderUtils;
import java.io.IOException;
import java.net.URL;
import java.util.Collections;
import java.util.List;
import java.util.Properties;
/**
* @author Jason Song(song_s@ctrip.com)
*/
public class ConfigUtil {
public static final String APOLLO_PROPERTY = "apollo.properties";
private static ConfigUtil configUtil = new ConfigUtil();
private ApplicationContext applicationContext;
private ConfigUtil() {
}
public static ConfigUtil getInstance() {
return configUtil;
}
public String getConfigServerUrl() {
// TODO return the meta server url based on different environments
return "http://localhost:8888";
}
public String getCluster() {
// TODO return the actual cluster
return "default";
}
public void setApplicationContext(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
public List<ApolloRegistry> loadApolloRegistries() throws IOException {
List<URL> resourceUrls =
Collections.list(Thread.currentThread().getContextClassLoader().getResources(APOLLO_PROPERTY));
List<ApolloRegistry> registries =
FluentIterable.from(resourceUrls).transform(new Function<URL, ApolloRegistry>() {
@Override
public ApolloRegistry apply(URL input) {
Properties properties = loadPropertiesFromResourceURL(input);
if (properties == null || !properties.containsKey(Constants.APP_ID)) {
return null;
}
ApolloRegistry registry = new ApolloRegistry();
registry.setAppId(properties.getProperty(Constants.APP_ID));
registry.setVersion(properties.getProperty(Constants.VERSION, Constants.DEFAULT_VERSION_NAME));
return registry;
}
}).filter(Predicates.notNull()).toList();
return registries;
}
Properties loadPropertiesFromResourceURL(URL resourceUrl) {
Resource resource = applicationContext.getResource(resourceUrl.toExternalForm());
if (resource == null || !resource.exists()) {
return null;
}
try {
return PropertiesLoaderUtils.loadProperties(new EncodedResource(resource, "UTF-8"));
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
package com.ctrip.apollo.client;
import com.ctrip.apollo.client.loader.impl.RemoteConfigLoaderTest;
import com.ctrip.apollo.client.util.ConfigUtilTest;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;
@RunWith(Suite.class)
@SuiteClasses({
ApolloConfigTest.class, RemoteConfigLoaderTest.class, ConfigUtilTest.class
})
public class AllTests {
}
......@@ -50,7 +50,7 @@ public class ApolloConfigTest {
}
@Test
public void testPreparePropertySourceSuccessful() {
public void testPreparePropertySourceSuccessfully() {
CompositePropertySource somePropertySource = mock(CompositePropertySource.class);
final ArgumentCaptor<CompositePropertySource> captor = ArgumentCaptor.forClass(CompositePropertySource.class);
......
package com.ctrip.apollo.client.loader.impl;
import com.ctrip.apollo.client.model.ApolloRegistry;
import com.ctrip.apollo.client.util.ConfigUtil;
import com.ctrip.apollo.core.environment.Environment;
import com.ctrip.apollo.core.environment.PropertySource;
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 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.web.client.RestTemplate;
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 RemoteConfigLoaderTest {
private RemoteConfigLoader remoteConfigLoader;
@Mock
private RestTemplate restTemplate;
private ConfigUtil configUtil;
@Before
public void setUp() {
configUtil = spy(ConfigUtil.getInstance());
remoteConfigLoader = spy(new RemoteConfigLoader(restTemplate, configUtil));
}
@Test
public void testLoadPropertySource() throws Exception {
ApolloRegistry someApolloRegistry = assembleSomeApolloRegistry("someAppId", "someVersion");
ApolloRegistry anotherApolloRegistry = assembleSomeApolloRegistry("anotherAppId", "anotherVersion");
CompositePropertySource somePropertySource = mock(CompositePropertySource.class);
CompositePropertySource anotherPropertySource = mock(CompositePropertySource.class);
doReturn(Lists.newArrayList(someApolloRegistry, anotherApolloRegistry)).when(configUtil).loadApolloRegistries();
doReturn(somePropertySource).when(remoteConfigLoader).loadSingleApolloConfig(someApolloRegistry.getAppId(), someApolloRegistry.getVersion());
doReturn(anotherPropertySource).when(remoteConfigLoader).loadSingleApolloConfig(anotherApolloRegistry.getAppId(), anotherApolloRegistry.getVersion());
CompositePropertySource result = remoteConfigLoader.loadPropertySource();
assertEquals(2, result.getPropertySources().size());
assertTrue(result.getPropertySources().containsAll(Lists.newArrayList(somePropertySource, anotherPropertySource)));
}
@Test
public void testLoadPropertySourceWithNoApolloRegistry() throws Exception {
doReturn(null).when(configUtil).loadApolloRegistries();
CompositePropertySource result = remoteConfigLoader.loadPropertySource();
assertTrue(result.getPropertySources().isEmpty());
}
@Test(expected = RuntimeException.class)
public void testLoadPropertySourceWithError() throws Exception {
Exception someException = mock(Exception.class);
ApolloRegistry someApolloRegistry = assembleSomeApolloRegistry("someAppId", "someVersion");
doReturn(Lists.newArrayList(someApolloRegistry)).when(configUtil).loadApolloRegistries();
doThrow(someException).when(remoteConfigLoader).loadSingleApolloConfig(someApolloRegistry.getAppId(), someApolloRegistry.getVersion());
remoteConfigLoader.loadPropertySource();
}
@Test
public void testLoadSingleApolloConfig() throws Exception {
Environment someRemoteEnv = mock(Environment.class);
String someSourceName = "someSource";
String anotherSourceName = "anotherSource";
Map<String, Object> someMap = Maps.newHashMap();
PropertySource somePropertySource = mock(PropertySource.class);
PropertySource anotherPropertySource = mock(PropertySource.class);
when(somePropertySource.getSource()).thenReturn(someMap);
when(somePropertySource.getName()).thenReturn(someSourceName);
when(anotherPropertySource.getSource()).thenReturn(someMap);
when(anotherPropertySource.getName()).thenReturn(anotherSourceName);
when(someRemoteEnv.getPropertySources()).thenReturn(Lists.newArrayList(somePropertySource, anotherPropertySource));
doReturn(someRemoteEnv).when(remoteConfigLoader).getRemoteEnvironment(any(RestTemplate.class), anyString(), anyString(), anyString(), anyString());
CompositePropertySource result = remoteConfigLoader.loadSingleApolloConfig("someAppId", "someVersion");
assertEquals(2, result.getPropertySources().size());
List<String> resultPropertySourceNames = FluentIterable.from(result.getPropertySources()).transform(new Function<org.springframework.core.env.PropertySource<?>, String>() {
@Override
public String apply(org.springframework.core.env.PropertySource<?> input) {
return input.getName();
}
}).toList();
assertTrue(resultPropertySourceNames.containsAll(Lists.newArrayList(someSourceName, anotherSourceName)));
}
private ApolloRegistry assembleSomeApolloRegistry(String someAppId, String someVersion) {
ApolloRegistry someApolloRegistry = new ApolloRegistry();
someApolloRegistry.setAppId(someAppId);
someApolloRegistry.setVersion(someVersion);
return someApolloRegistry;
}
}
package com.ctrip.apollo.client.util;
import com.ctrip.apollo.client.constants.Constants;
import com.ctrip.apollo.client.model.ApolloRegistry;
import com.google.common.collect.Lists;
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.context.ConfigurableApplicationContext;
import java.io.IOException;
import java.net.URL;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
import java.util.Properties;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
/**
* @author Jason Song(song_s@ctrip.com)
*/
@RunWith(MockitoJUnitRunner.class)
public class ConfigUtilTest {
private ConfigUtil configUtil;
@Mock
private ConfigurableApplicationContext applicationContext;
@Before
public void setUp() throws Exception {
configUtil = spy(ConfigUtil.getInstance());
configUtil.setApplicationContext(applicationContext);
}
@Test
public void testLoadApolloRegistriesSuccessfully() throws Exception {
Properties someProperties = mock(Properties.class);
preparePropertiesFromLocalResource(someProperties);
String someAppId = "someApp";
String someVersionId = "someVersion";
when(someProperties.containsKey(Constants.APP_ID)).thenReturn(true);
when(someProperties.getProperty(Constants.APP_ID)).thenReturn(someAppId);
when(someProperties.getProperty(eq(Constants.VERSION), anyString())).thenReturn(someVersionId);
List<ApolloRegistry> apolloRegistries = configUtil.loadApolloRegistries();
ApolloRegistry apolloRegistry = apolloRegistries.get(0);
assertEquals(1, apolloRegistries.size());
assertEquals(someAppId, apolloRegistry.getAppId());
assertEquals(someVersionId, apolloRegistry.getVersion());
}
@Test
public void testLoadApolloRegistriesError() throws Exception {
preparePropertiesFromLocalResource(null);
List<ApolloRegistry> apolloRegistries = configUtil.loadApolloRegistries();
assertTrue(apolloRegistries.isEmpty());
}
private void preparePropertiesFromLocalResource(Properties someProperties) throws IOException {
ClassLoader someClassLoader = mock(ClassLoader.class);
Thread.currentThread().setContextClassLoader(someClassLoader);
URL someUrl = new URL("http", "somepath/", "someFile");
Enumeration<URL> someResourceUrls = Collections.enumeration(Lists.newArrayList(someUrl));
when(someClassLoader.getResources(anyString())).thenReturn(someResourceUrls);
doReturn(someProperties).when(configUtil).loadPropertiesFromResourceURL(someUrl);
}
}
<?xml version="1.0" encoding="UTF-8"?>
<configuration monitorInterval="60">
<appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="[apollo-client][%t]%d %-5p [%c] %m%n"/>
</Console>
<Async name="Async" includeLocation="true">
<AppenderRef ref="Console" />
</Async>
</appenders>
<loggers>
<logger name="com.ctrip.apollo" additivity="false" level="trace">
<AppenderRef ref="Async" level="DEBUG"/>
</logger>
<root level="INFO">
<AppenderRef ref="Async"/>
</root>
</loggers>
</configuration>
......@@ -4,7 +4,7 @@
<parent>
<groupId>com.ctrip.apollo</groupId>
<artifactId>apollo</artifactId>
<version>0.0.1</version>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
......
package com.ctrip.apollo.server;
import com.jcraft.jsch.JSch;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.config.server.EnableConfigServer;
......@@ -9,6 +10,7 @@ import org.springframework.cloud.config.server.EnableConfigServer;
public class ConfigServerApplication {
public static void main(String[] args) {
JSch.setConfig("StrictHostKeyChecking", "no");//for git server key
SpringApplication.run(ConfigServerApplication.class, args);
}
......
spring:
cloud:
config:
server:
git:
uri: ssh://git@10.3.2.56:1022/spring-cloud-config-repo.git
server:
port: 8888
logging:
level:
org.springframework.cloud: 'DEBUG'
file: /opt/logs/apollo-configserver.log
spring:
profiles:
active: native
......@@ -4,10 +4,24 @@
<parent>
<groupId>com.ctrip.apollo</groupId>
<artifactId>apollo</artifactId>
<version>0.0.1</version>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>apollo-core</artifactId>
<name>Apollo Core</name>
<packaging>jar</packaging>
<dependencies>
<!-- json -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<!-- end of json -->
</dependencies>
</project>
package com.ctrip.apollo.core.environment;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* @author Jason Song(song_s@ctrip.com)
*/
public class Environment {
private String name;
private String[] profiles = new String[0];
private String label;
private List<PropertySource> propertySources = new ArrayList<PropertySource>();
private String version;
public Environment(String name, String... profiles) {
this(name, profiles, "master", null);
}
@JsonCreator
public Environment(@JsonProperty("name") String name,
@JsonProperty("profiles") String[] profiles,
@JsonProperty("label") String label,
@JsonProperty("version") String version) {
super();
this.name = name;
this.profiles = profiles;
this.label = label;
this.version = version;
}
public void add(PropertySource propertySource) {
this.propertySources.add(propertySource);
}
public void addFirst(PropertySource propertySource) {
this.propertySources.add(0, propertySource);
}
public List<PropertySource> getPropertySources() {
return propertySources;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getLabel() {
return label;
}
public void setLabel(String label) {
this.label = label;
}
public String[] getProfiles() {
return profiles;
}
public void setProfiles(String[] profiles) {
this.profiles = profiles;
}
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
@Override
public String toString() {
return "Environment [name=" + name + ", profiles=" + Arrays.asList(profiles) + ", label="
+ label + ", propertySources=" + propertySources + ", version=" + version + "]";
}
}
package com.ctrip.apollo.core.environment;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.Map;
/**
* @author Jason Song(song_s@ctrip.com)
*/
public class PropertySource {
private String name;
private Map<String, Object> source;
@JsonCreator
public PropertySource(@JsonProperty("name") String name, @JsonProperty("source") Map<String, Object> source) {
this.name = name;
this.source = source;
}
public String getName() {
return name;
}
public Map<String, Object> getSource() {
return source;
}
@Override
public String toString() {
return "PropertySource [name=" + name + "]";
}
}
......@@ -3,7 +3,7 @@
<parent>
<artifactId>apollo</artifactId>
<groupId>com.ctrip.apollo</groupId>
<version>0.0.1</version>
<version>0.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>apollo-demo</artifactId>
......@@ -29,6 +29,22 @@
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
......
......@@ -2,6 +2,7 @@ package com.ctrip.apollo.demo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
......@@ -13,6 +14,7 @@ import org.springframework.web.bind.annotation.RestController;
*/
@RestController
@RequestMapping("/demo")
@PropertySource("classpath:application.properties")
public class DemoController {
@Autowired
private Environment env;
......
<?xml version="1.0" encoding="UTF-8"?>
<configuration monitorInterval="60">
<appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="[apollo-demo][%t]%d %-5p [%c] %m%n"/>
</Console>
<Async name="Async" includeLocation="true">
<AppenderRef ref="Console" />
</Async>
</appenders>
<loggers>
<logger name="com.ctrip.apollo" additivity="false" level="trace">
<AppenderRef ref="Async" level="DEBUG"/>
</logger>
<root level="INFO">
<AppenderRef ref="Async"/>
</root>
</loggers>
</configuration>
......@@ -4,7 +4,7 @@
<parent>
<groupId>com.ctrip.apollo</groupId>
<artifactId>apollo</artifactId>
<version>0.0.1</version>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
......
......@@ -4,7 +4,7 @@
<parent>
<groupId>com.ctrip.apollo</groupId>
<artifactId>apollo</artifactId>
<version>0.0.1</version>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
......
......@@ -4,7 +4,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.ctrip.apollo</groupId>
<artifactId>apollo</artifactId>
<version>0.0.1</version>
<version>0.0.1-SNAPSHOT</version>
<name>Apollo</name>
<packaging>pom</packaging>
<description>Ctrip Configuration Center</description>
......@@ -90,6 +90,11 @@
<artifactId>mysql-connector-java</artifactId>
<version>5.1.38</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>19.0</version>
</dependency>
<!--for test -->
<dependency>
<groupId>com.h2database</groupId>
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册