提交 e7b09f79 编写于 作者: J Jason Song

Add RefreshScope support and ConfigServer return 304 when configuration is not changed

上级 26b171fc
package com.ctrip.apollo.biz.service; package com.ctrip.apollo.biz.service;
import com.ctrip.apollo.biz.entity.Version;
import com.ctrip.apollo.core.model.ApolloConfig; import com.ctrip.apollo.core.model.ApolloConfig;
/** /**
...@@ -15,4 +16,20 @@ public interface ConfigService { ...@@ -15,4 +16,20 @@ public interface ConfigService {
* @return * @return
*/ */
ApolloConfig loadConfig(long appId, String clusterName, String versionName); ApolloConfig loadConfig(long appId, String clusterName, String versionName);
/**
* Load Version by appId and versionName from database
* @param appId
* @param versionName
* @return
*/
Version loadVersionByAppIdAndVersionName(long appId, String versionName);
/**
* Load Config by version and clusterName from database
* @param version
* @param clusterName
* @return
*/
ApolloConfig loadConfigByVersionAndClusterName(Version version, String clusterName);
} }
...@@ -32,10 +32,21 @@ public class ConfigServiceImpl implements ConfigService { ...@@ -32,10 +32,21 @@ public class ConfigServiceImpl implements ConfigService {
@Override @Override
public ApolloConfig loadConfig(long appId, String clusterName, String versionName) { public ApolloConfig loadConfig(long appId, String clusterName, String versionName) {
Version version = versionRepository.findByAppIdAndName(appId, versionName); Version version = loadVersionByAppIdAndVersionName(appId, versionName);
if (version == null) { if (version == null) {
return null; return null;
} }
return loadConfigByVersionAndClusterName(version, clusterName);
}
@Override
public Version loadVersionByAppIdAndVersionName(long appId, String versionName) {
return versionRepository.findByAppIdAndName(appId, versionName);
}
@Override
public ApolloConfig loadConfigByVersionAndClusterName(Version version, String clusterName) {
ReleaseSnapShot releaseSnapShot = ReleaseSnapShot releaseSnapShot =
releaseSnapShotRepository.findByReleaseIdAndClusterName(version.getReleaseId(), clusterName); releaseSnapShotRepository.findByReleaseIdAndClusterName(version.getReleaseId(), clusterName);
if (releaseSnapShot == null) { if (releaseSnapShot == null) {
......
...@@ -4,5 +4,5 @@ INSERT INTO Cluster (AppId, IsDeleted, Name) VALUES (101, 0, 'default'); ...@@ -4,5 +4,5 @@ INSERT INTO Cluster (AppId, IsDeleted, Name) VALUES (101, 0, 'default');
INSERT INTO Version (AppId, IsDeleted, Name, ReleaseId) VALUES (101, 0, '1.0', 1); INSERT INTO Version (AppId, IsDeleted, Name, ReleaseId) VALUES (101, 0, '1.0', 1);
INSERT INTO Version (AppId, IsDeleted, Name, ReleaseId) VALUES (102, 0, '1.0', 2); 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"}'); 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, '{"apollo.bar":"foo"}'); INSERT INTO RELEASESNAPSHOT (ClusterName, IsDeleted, ReleaseId, Configurations) VALUES ('default', 0, 2, '{"demo.foo":"demo1", "demo.bar":"demo2"}');
...@@ -19,6 +19,7 @@ import java.io.IOException; ...@@ -19,6 +19,7 @@ import java.io.IOException;
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.*;
...@@ -66,7 +67,38 @@ public class ConfigServiceImplTest { ...@@ -66,7 +67,38 @@ public class ConfigServiceImplTest {
assertEquals(someVersionName, result.getVersion()); assertEquals(someVersionName, result.getVersion());
assertEquals(someReleaseId, result.getReleaseId()); assertEquals(someReleaseId, result.getReleaseId());
assertEquals(someMap, result.getConfigurations()); assertEquals(someMap, result.getConfigurations());
}
@Test
public void testLoadConfigWithVersionNotFound() throws Exception {
long someAppId = 1;
String someClusterName = "someClusterName";
String someVersionName = "someVersionName";
when(versionRepository.findByAppIdAndName(someAppId, someVersionName)).thenReturn(null);
ApolloConfig result = configService.loadConfig(someAppId, someClusterName, someVersionName);
assertNull(result);
verify(versionRepository, times(1)).findByAppIdAndName(someAppId, someVersionName);
}
@Test
public void testLoadConfigWithConfigNotFound() throws Exception {
long someAppId = 1;
String someClusterName = "someClusterName";
String someVersionName = "someVersionName";
long someReleaseId = 1;
Version someVersion = assembleVersion(someAppId, someVersionName, someReleaseId);
when(versionRepository.findByAppIdAndName(someAppId, someVersionName)).thenReturn(someVersion);
when(releaseSnapShotRepository.findByReleaseIdAndClusterName(someReleaseId, someClusterName)).thenReturn(null);
ApolloConfig result = configService.loadConfig(someAppId, someClusterName, someVersionName);
assertNull(result);
verify(versionRepository, times(1)).findByAppIdAndName(someAppId, someVersionName);
verify(releaseSnapShotRepository, times(1)).findByReleaseIdAndClusterName(someReleaseId, someClusterName);
} }
private Version assembleVersion(long appId, String versionName, long releaseId) { private Version assembleVersion(long appId, String versionName, long releaseId) {
......
...@@ -29,6 +29,10 @@ ...@@ -29,6 +29,10 @@
<groupId>org.springframework</groupId> <groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId> <artifactId>spring-web</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-context</artifactId>
</dependency>
<!-- end of spring --> <!-- end of spring -->
<dependency> <dependency>
<groupId>com.google.guava</groupId> <groupId>com.google.guava</groupId>
......
...@@ -4,19 +4,23 @@ import com.ctrip.apollo.client.loader.ConfigLoader; ...@@ -4,19 +4,23 @@ 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.util.ConfigUtil; import com.ctrip.apollo.client.util.ConfigUtil;
import org.springframework.beans.BeansException; import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor; import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.cloud.context.scope.refresh.RefreshScope;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware; import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.core.Ordered; import org.springframework.core.Ordered;
import org.springframework.core.PriorityOrdered; 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;
/** /**
* Client side config * Client side config manager
* *
* @author Jason Song(song_s@ctrip.com) * @author Jason Song(song_s@ctrip.com)
*/ */
...@@ -48,9 +52,27 @@ public class ApolloConfigManager implements BeanDefinitionRegistryPostProcessor, ...@@ -48,9 +52,27 @@ public class ApolloConfigManager implements BeanDefinitionRegistryPostProcessor,
*/ */
@Override @Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
registerDependentBeans(registry);
preparePropertySource(); preparePropertySource();
} }
/**
* Register beans needed for Apollo Config Client
* <li>
* - RefreshScope: used to refresh beans when configurations changes
* </li>
* <li>
* - PropertySourcesPlaceholderConfigurer: used to support placeholder configuration injection
* </li>
* @param registry
*/
private void registerDependentBeans(BeanDefinitionRegistry registry) {
BeanDefinition refreshScope = BeanDefinitionBuilder.genericBeanDefinition(RefreshScope.class).getBeanDefinition();
registry.registerBeanDefinition("refreshScope", refreshScope);
BeanDefinition propertySourcesPlaceholderConfigurer = BeanDefinitionBuilder.genericBeanDefinition(PropertySourcesPlaceholderConfigurer.class).getBeanDefinition();
registry.registerBeanDefinition("propertySourcesPlaceholderConfigurer", propertySourcesPlaceholderConfigurer);
}
/** /**
* This is executed after postProcessBeanDefinitionRegistry * This is executed after postProcessBeanDefinitionRegistry
*/ */
...@@ -58,11 +80,20 @@ public class ApolloConfigManager implements BeanDefinitionRegistryPostProcessor, ...@@ -58,11 +80,20 @@ public class ApolloConfigManager implements BeanDefinitionRegistryPostProcessor,
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
} }
/**
* Make sure this bean is called before other beans
* @return
*/
@Override @Override
public int getOrder() { public int getOrder() {
return Ordered.HIGHEST_PRECEDENCE + 1; return Ordered.HIGHEST_PRECEDENCE;
} }
/**
* Prepare property sources
* First try to load from remote
* If loading from remote failed, then fall back to local cached properties
*/
void preparePropertySource() { void preparePropertySource() {
MutablePropertySources currentPropertySources = applicationContext.getEnvironment().getPropertySources(); MutablePropertySources currentPropertySources = applicationContext.getEnvironment().getPropertySources();
if (currentPropertySources.contains(APOLLO_PROPERTY_SOURCE_NAME)) { if (currentPropertySources.contains(APOLLO_PROPERTY_SOURCE_NAME)) {
......
package com.ctrip.apollo.client.loader; package com.ctrip.apollo.client.loader;
import com.ctrip.apollo.client.loader.impl.MockConfigLoader;
import com.ctrip.apollo.client.loader.impl.RemoteConfigLoader; import com.ctrip.apollo.client.loader.impl.RemoteConfigLoader;
/** /**
...@@ -16,10 +15,6 @@ public class ConfigLoaderFactory { ...@@ -16,10 +15,6 @@ public class ConfigLoaderFactory {
return configLoaderFactory; return configLoaderFactory;
} }
public ConfigLoader getMockConfigLoader() {
return new MockConfigLoader();
}
public ConfigLoader getRemoteConfigLoader() { public ConfigLoader getRemoteConfigLoader() {
return new RemoteConfigLoader(); return new RemoteConfigLoader();
} }
......
package com.ctrip.apollo.client.loader.impl;
import com.ctrip.apollo.client.loader.ConfigLoader;
import com.google.common.collect.Maps;
import org.springframework.core.env.CompositePropertySource;
import org.springframework.core.env.MapPropertySource;
import java.util.Map;
/**
* Mock config
* @author Jason Song(song_s@ctrip.com)
*/
public class MockConfigLoader implements ConfigLoader {
private static final String PROPERTY_SOURCE_NAME = "ApolloMockConfigProperties";
@Override
public CompositePropertySource loadPropertySource() {
CompositePropertySource composite = new CompositePropertySource(PROPERTY_SOURCE_NAME);
composite.addPropertySource(mock());
return composite;
}
private MapPropertySource mock() {
Map<String, Object> source = Maps.newHashMap();
source.put("apollo.foo" ,"bar");
MapPropertySource propertySource = new MapPropertySource("mock source", source);
return propertySource;
}
}
...@@ -7,6 +7,8 @@ import org.junit.runner.RunWith; ...@@ -7,6 +7,8 @@ import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor; import org.mockito.ArgumentCaptor;
import org.mockito.Mock; 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.support.BeanDefinitionRegistry;
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;
...@@ -32,10 +34,12 @@ public class ApolloConfigManagerTest { ...@@ -32,10 +34,12 @@ public class ApolloConfigManagerTest {
private ConfigurableEnvironment env; private ConfigurableEnvironment env;
@Mock @Mock
private MutablePropertySources mutablePropertySources; private MutablePropertySources mutablePropertySources;
@Mock
private BeanDefinitionRegistry beanDefinitionRegistry;
@Before @Before
public void setUp() { public void setUp() {
apolloConfigManager = new ApolloConfigManager(); apolloConfigManager = spy(new ApolloConfigManager());
when(applicationContext.getEnvironment()).thenReturn(env); when(applicationContext.getEnvironment()).thenReturn(env);
when(env.getPropertySources()).thenReturn(mutablePropertySources); when(env.getPropertySources()).thenReturn(mutablePropertySources);
...@@ -68,4 +72,13 @@ public class ApolloConfigManagerTest { ...@@ -68,4 +72,13 @@ public class ApolloConfigManagerTest {
assertTrue(insertedPropertySource.getPropertySources().contains(somePropertySource)); assertTrue(insertedPropertySource.getPropertySources().contains(somePropertySource));
} }
@Test
public void testPostProcessBeanDefinitionRegistry() {
doNothing().when(apolloConfigManager).preparePropertySource();
apolloConfigManager.postProcessBeanDefinitionRegistry(beanDefinitionRegistry);
verify(beanDefinitionRegistry, times(2)).registerBeanDefinition(anyString(), any(BeanDefinition.class));
}
} }
package com.ctrip.apollo.server.config; package com.ctrip.apollo.configserver.config;
import org.h2.server.web.WebServlet; import org.h2.server.web.WebServlet;
import org.springframework.boot.context.embedded.ServletRegistrationBean; import org.springframework.boot.context.embedded.ServletRegistrationBean;
......
package com.ctrip.apollo.server.controller; package com.ctrip.apollo.configserver.controller;
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.model.ApolloConfig; import com.ctrip.apollo.core.model.ApolloConfig;
import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource; import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/** /**
* @author Jason Song(song_s@ctrip.com) * @author Jason Song(song_s@ctrip.com)
...@@ -16,10 +20,33 @@ public class ConfigController { ...@@ -16,10 +20,33 @@ public class ConfigController {
@Resource(name = "configService") @Resource(name = "configService")
private ConfigService configService; private ConfigService configService;
@RequestMapping(value = "/{appId}/{clusterName}/{version:.*}") @RequestMapping(value = "/{appId}/{clusterName}/{versionName:.*}")
public ApolloConfig queryConfig(@PathVariable long appId, public ApolloConfig queryConfig(@PathVariable long appId,
@PathVariable String clusterName, @PathVariable String clusterName,
@PathVariable String version) { @PathVariable String versionName,
return configService.loadConfig(appId, clusterName, version); @RequestParam(value = "releaseId", defaultValue = "-1") long clientSideReleaseId,
HttpServletResponse response) throws IOException {
Version version = configService.loadVersionByAppIdAndVersionName(appId, versionName);
if (version == null) {
response.sendError(HttpServletResponse.SC_NOT_FOUND,
String.format("Could not load version with appId: %d, versionName: %s", appId, versionName));
return null;
}
if (version.getReleaseId() == clientSideReleaseId) {
//Client side configuration is the same with server side, return 304
response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
return null;
}
ApolloConfig apolloConfig =
configService.loadConfigByVersionAndClusterName(version, clusterName);
if (apolloConfig == null) {
response.sendError(HttpServletResponse.SC_NOT_FOUND,
String.format("Could not load config with releaseId: %d, clusterName: %s", version.getReleaseId(), clusterName));
return null;
}
return apolloConfig;
} }
} }
package com.ctrip.apollo.configserver; package com.ctrip.apollo.configserver;
import com.ctrip.apollo.configserver.controller.ConfigControllerTest;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.junit.runners.Suite; import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses; import org.junit.runners.Suite.SuiteClasses;
@RunWith(Suite.class) @RunWith(Suite.class)
@SuiteClasses({ @SuiteClasses({
ConfigControllerTest.class
}) })
public class AllTests { public class AllTests {
......
package com.ctrip.apollo.configserver.controller;
import com.ctrip.apollo.biz.entity.Version;
import com.ctrip.apollo.biz.service.ConfigService;
import com.ctrip.apollo.core.model.ApolloConfig;
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.test.util.ReflectionTestUtils;
import javax.servlet.http.HttpServletResponse;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.mockito.Mockito.*;
/**
* @author Jason Song(song_s@ctrip.com)
*/
@RunWith(MockitoJUnitRunner.class)
public class ConfigControllerTest {
private ConfigController configController;
@Mock
private ConfigService configService;
@Before
public void setUp() throws Exception {
configController = new ConfigController();
ReflectionTestUtils.setField(configController, "configService", configService);
}
@Test
public void testQueryConfig() throws Exception {
ApolloConfig someApolloConfig = mock(ApolloConfig.class);
long someAppId = 1;
String someClusterName = "someClusterName";
String someVersionName = "someVersion";
long someClientSideReleaseId = 1;
long someServerSideNewReleaseId = 2;
HttpServletResponse someResponse = mock(HttpServletResponse.class);
Version someVersion = mock(Version.class);
when(configService.loadVersionByAppIdAndVersionName(someAppId, someVersionName)).thenReturn(someVersion);
when(someVersion.getReleaseId()).thenReturn(someServerSideNewReleaseId);
when(configService.loadConfigByVersionAndClusterName(someVersion, someClusterName)).thenReturn(someApolloConfig);
ApolloConfig result = configController.queryConfig(someAppId, someClusterName, someVersionName, someClientSideReleaseId, someResponse);
assertEquals(someApolloConfig, result);
verify(configService, times(1)).loadVersionByAppIdAndVersionName(someAppId, someVersionName);
verify(configService, times(1)).loadConfigByVersionAndClusterName(someVersion, someClusterName);
}
@Test
public void testQueryConfigWithVersionNotFound() throws Exception {
long someAppId = 1;
String someClusterName = "someClusterName";
String someVersionName = "someVersion";
long someClientSideReleaseId = 1;
HttpServletResponse someResponse = mock(HttpServletResponse.class);
when(configService.loadVersionByAppIdAndVersionName(someAppId, someVersionName)).thenReturn(null);
ApolloConfig result = configController.queryConfig(someAppId, someClusterName, someVersionName, someClientSideReleaseId, someResponse);
assertNull(result);
verify(someResponse, times(1)).sendError(eq(HttpServletResponse.SC_NOT_FOUND), anyString());
}
@Test
public void testQueryConfigWithApolloConfigNotFound() throws Exception {
long someAppId = 1;
String someClusterName = "someClusterName";
String someVersionName = "someVersion";
long someClientSideReleaseId = 1;
long someServerSideNewReleaseId = 2;
HttpServletResponse someResponse = mock(HttpServletResponse.class);
Version someVersion = mock(Version.class);
when(configService.loadVersionByAppIdAndVersionName(someAppId, someVersionName)).thenReturn(someVersion);
when(someVersion.getReleaseId()).thenReturn(someServerSideNewReleaseId);
when(configService.loadConfigByVersionAndClusterName(someVersion, someClusterName)).thenReturn(null);
ApolloConfig result = configController.queryConfig(someAppId, someClusterName, someVersionName, someClientSideReleaseId, someResponse);
assertNull(result);
verify(someResponse, times(1)).sendError(eq(HttpServletResponse.SC_NOT_FOUND), anyString());
}
@Test
public void testQueryConfigWithApolloConfigNotModified() throws Exception {
long someAppId = 1;
String someClusterName = "someClusterName";
String someVersionName = "someVersion";
long someClientSideReleaseId = 1;
long someServerSideReleaseId = someClientSideReleaseId;
HttpServletResponse someResponse = mock(HttpServletResponse.class);
Version someVersion = mock(Version.class);
when(configService.loadVersionByAppIdAndVersionName(someAppId, someVersionName)).thenReturn(someVersion);
when(someVersion.getReleaseId()).thenReturn(someServerSideReleaseId);
ApolloConfig result = configController.queryConfig(someAppId, someClusterName, someVersionName, someClientSideReleaseId, someResponse);
assertNull(result);
verify(someResponse, times(1)).setStatus(HttpServletResponse.SC_NOT_MODIFIED);
verify(configService, never()).loadConfigByVersionAndClusterName(any(Version.class), anyString());
}
}
package com.ctrip.apollo.server;
import com.ctrip.apollo.server.controller.ConfigControllerTest;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;
@RunWith(Suite.class)
@SuiteClasses({
ConfigControllerTest.class
})
public class AllTests {
}
package com.ctrip.apollo.server.controller;
import com.ctrip.apollo.biz.service.ConfigService;
import com.ctrip.apollo.core.model.ApolloConfig;
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.test.util.ReflectionTestUtils;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.*;
/**
* @author Jason Song(song_s@ctrip.com)
*/
@RunWith(MockitoJUnitRunner.class)
public class ConfigControllerTest {
private ConfigController configController;
@Mock
private ConfigService configService;
@Before
public void setUp() throws Exception {
configController = new ConfigController();
ReflectionTestUtils.setField(configController, "configService", configService);
}
@Test
public void testQueryConfig() throws Exception {
ApolloConfig someApolloConfig = mock(ApolloConfig.class);
long someAppId = 1;
String someClusterName = "someClusterName";
String someVersion = "someVersion";
when(configService.loadConfig(someAppId, someClusterName, someVersion)).thenReturn(someApolloConfig);
ApolloConfig result = configController.queryConfig(someAppId, someClusterName, someVersion);
assertEquals(someApolloConfig, result);
verify(configService, times(1)).loadConfig(someAppId, someClusterName, someVersion);
}
}
...@@ -4,7 +4,6 @@ import com.ctrip.apollo.client.ApolloConfigManager; ...@@ -4,7 +4,6 @@ import com.ctrip.apollo.client.ApolloConfigManager;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
/** /**
* @author Jason Song(song_s@ctrip.com) * @author Jason Song(song_s@ctrip.com)
...@@ -17,8 +16,13 @@ public class AppConfig { ...@@ -17,8 +16,13 @@ public class AppConfig {
return new ApolloConfigManager(); return new ApolloConfigManager();
} }
@Bean // @Bean
public PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() { // public PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer(); // return new PropertySourcesPlaceholderConfigurer();
} // }
//
// @Bean
// public static RefreshScope refreshScope() {
// return new RefreshScope();
// }
} }
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.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 org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value; import org.springframework.cloud.context.scope.refresh.RefreshScope;
import org.springframework.context.annotation.PropertySource; import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment; import org.springframework.core.env.Environment;
import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PathVariable;
...@@ -26,20 +26,32 @@ public class DemoController { ...@@ -26,20 +26,32 @@ public class DemoController {
@Autowired @Autowired
private Environment env; private Environment env;
@Autowired @Autowired
private ApolloConfigManager apolloConfigManager; private DemoService demoService;
//Apollo config client internal impl, not intended to be use 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();
@Value("${apollo.foo}") @Autowired
private String foo; private RefreshScope scope;
@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) {
return new Config(configName, env.getProperty(configName, "undefined")); String value;
if (configName.equals("foo")) {
value = demoService.getFoo();
} else {
value = env.getProperty(configName, "undefined");
}
return new Config(configName, value);
} }
@RequestMapping(value = "/client/registries", method = RequestMethod.GET) @RequestMapping(value = "/client/registries", method = RequestMethod.GET)
public List<ApolloRegistry> loadApolloRegistries() throws IOException { public List<ApolloRegistry> loadApolloRegistries() throws IOException {
return configUtil.loadApolloRegistries(); return configUtil.loadApolloRegistries();
} }
@RequestMapping(value = "/refresh", method = RequestMethod.POST)
public String refreshBeans() {
this.scope.refreshAll();
return "ok";
}
} }
package com.ctrip.apollo.demo.service;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Service;
/**
* @author Jason Song(song_s@ctrip.com)
*/
@Service
@RefreshScope
public class DemoService {
private String foo;
@Value("${apollo.foo}")
private void setFoo(String foo) {
this.foo = foo;
}
public String getFoo() {
return foo;
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册