Commit ac5ba9e0 by nobodyiam

add RefreshScope demo

parent 3381b33e
......@@ -86,6 +86,11 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
<!-- for refresh scope demo -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-context</artifactId>
</dependency>
<!-- required for spring 3.1.0 -->
<dependency>
<groupId>cglib</groupId>
......
package com.ctrip.framework.apollo.demo.spring.bean;
import com.ctrip.framework.apollo.Config;
import com.ctrip.framework.apollo.model.ConfigChange;
import com.ctrip.framework.apollo.model.ConfigChangeEvent;
import com.ctrip.framework.apollo.spring.annotation.ApolloConfig;
import com.ctrip.framework.apollo.spring.annotation.ApolloConfigChangeListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
/**
* @author Jason Song(song_s@ctrip.com)
*/
public class XmlBean implements InitializingBean {
private static final Logger logger = LoggerFactory.getLogger(XmlBean.class);
private int timeout;
private int batch;
@ApolloConfig
private Config config;
@ApolloConfig("FX.apollo")
private Config anotherConfig;
public void setTimeout(int timeout) {
this.timeout = timeout;
logger.info("Setting timeout to {}", timeout);
}
public void setBatch(int batch) {
this.batch = batch;
logger.info("Setting batch to {}", batch);
}
@Override
public void afterPropertiesSet() throws Exception {
logger.info("Keys for config: {}", config.getPropertyNames());
logger.info("Keys for anotherConfig: {}", anotherConfig.getPropertyNames());
}
@ApolloConfigChangeListener("application")
private void someChangeHandler(ConfigChangeEvent changeEvent) {
logger.info("[someChangeHandler]Changes for namespace {}", changeEvent.getNamespace());
for (String key : changeEvent.changedKeys()) {
ConfigChange change = changeEvent.getChange(key);
logger.info("[someChangeHandler]Change - key: {}, oldValue: {}, newValue: {}, changeType: {}",
change.getPropertyName(), change.getOldValue(), change.getNewValue(),
change.getChangeType());
}
}
@ApolloConfigChangeListener({"application", "FX.apollo"})
private void anotherChangeHandler(ConfigChangeEvent changeEvent) {
logger.info("[anotherChangeHandler]Changes for namespace {}", changeEvent.getNamespace());
for (String key : changeEvent.changedKeys()) {
ConfigChange change = changeEvent.getChange(key);
logger.info("[anotherChangeHandler]Change - key: {}, oldValue: {}, newValue: {}, changeType: {}",
change.getPropertyName(), change.getOldValue(), change.getNewValue(),
change.getChangeType());
}
}
}
package com.ctrip.framework.apollo.demo.spring.bean;
package com.ctrip.framework.apollo.demo.spring.common.bean;
import com.ctrip.framework.apollo.Config;
import com.ctrip.framework.apollo.model.ConfigChange;
......
package com.ctrip.framework.apollo.demo.spring.bean;
package com.ctrip.framework.apollo.demo.spring.common.bean;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
......
package com.ctrip.framework.apollo.demo.spring.common.bean;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
/**
* This bean is annotated with @RefreshScope so that it can be 'refreshed' at runtime
* @author Jason Song(song_s@ctrip.com)
*/
@RefreshScope
@Component("refreshScopeBean")
public class RefreshScopeBean {
private static final Logger logger = LoggerFactory.getLogger(RefreshScopeBean.class);
@Value("${timeout:200}")
private int timeout;
@Value("${batch:100}")
private int batch;
/**
* this method will be called when the bean is first initialized, and when it is 'refreshed' as well
*/
@PostConstruct
void initialize() {
logger.info("timeout is {}", timeout);
logger.info("batch is {}", batch);
}
@Override
public String toString() {
return String.format("[RefreshScopeBean] timeout: %d, batch: %d", timeout, batch);
}
}
package com.ctrip.framework.apollo.demo.spring.config;
package com.ctrip.framework.apollo.demo.spring.common.config;
import com.ctrip.framework.apollo.spring.annotation.EnableApolloConfig;
......
package com.ctrip.framework.apollo.demo.spring.config;
package com.ctrip.framework.apollo.demo.spring.common.config;
import com.ctrip.framework.apollo.demo.spring.bean.NormalBean;
import com.ctrip.framework.apollo.demo.spring.common.bean.NormalBean;
import com.ctrip.framework.apollo.spring.annotation.EnableApolloConfig;
import org.springframework.beans.factory.annotation.Value;
......
package com.ctrip.framework.apollo.demo.spring.common.refresh;
import com.ctrip.framework.apollo.Config;
import com.ctrip.framework.apollo.ConfigChangeListener;
import com.ctrip.framework.apollo.demo.spring.common.bean.RefreshScopeBean;
import com.ctrip.framework.apollo.model.ConfigChangeEvent;
import com.ctrip.framework.apollo.spring.annotation.ApolloConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.cloud.context.scope.refresh.RefreshScope;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
/**
* To refresh the config bean when config is changed
*
* @author Jason Song(song_s@ctrip.com)
*/
@Component
public class ApolloRefreshConfig implements ConfigChangeListener {
private static final Logger logger = LoggerFactory.getLogger(ApolloRefreshConfig.class);
@ApolloConfig
private Config config;
@ApolloConfig("FX.apollo")
private Config anotherConfig;
@Autowired
private RefreshScope refreshScope;
@Autowired
@Qualifier("refreshScopeBean")
private RefreshScopeBean refreshScopeBean;
@PostConstruct
private void init() {
logger.info(refreshScopeBean.toString());
config.addChangeListener(this);
anotherConfig.addChangeListener(this);
}
@Override
public void onChange(ConfigChangeEvent changeEvent) {
logger.info("refreshScopeBean before refresh {}", refreshScopeBean.toString());
//could also call refreshScope.refreshAll();
refreshScope.refresh("refreshScopeBean");
logger.info("refreshScopeBean after refresh {}", refreshScopeBean.toString());
}
}
package com.ctrip.framework.apollo.demo.spring;
import com.ctrip.framework.apollo.demo.spring.bean.AnnotatedBean;
import com.ctrip.framework.apollo.demo.spring.config.AppConfig;
package com.ctrip.framework.apollo.demo.spring.javaConfigDemo;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
......@@ -12,8 +9,8 @@ import java.util.Scanner;
*/
public class AnnotationApplication {
public static void main(String[] args) {
new AnnotationConfigApplicationContext(
AppConfig.class.getPackage().getName(), AnnotatedBean.class.getPackage().getName());
new AnnotationConfigApplicationContext("com.ctrip.framework.apollo.demo.spring.common",
"com.ctrip.framework.apollo.demo.spring.javaConfigDemo");
onKeyExit();
}
......
package com.ctrip.framework.apollo.demo.spring.javaConfigDemo.config;
import org.springframework.cloud.autoconfigure.RefreshAutoConfiguration;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
/**
* to support RefreshScope
* @author Jason Song(song_s@ctrip.com)
*/
@Configuration
@Import(RefreshAutoConfiguration.class)
public class RefreshScopeConfig {
}
package com.ctrip.framework.apollo.demo.spring;
import com.ctrip.framework.apollo.demo.spring.config.SampleRedisConfig;
package com.ctrip.framework.apollo.demo.spring.springBootDemo;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.context.annotation.Bean;
import java.util.Scanner;
/**
* @author Jason Song
* @author Jason Song(song_s@ctrip.com)
*/
@SpringBootApplication
@SpringBootApplication(scanBasePackages = {"com.ctrip.framework.apollo.demo.spring.common",
"com.ctrip.framework.apollo.demo.spring.springBootDemo"
})
public class SpringBootSampleApplication {
@Bean
public SampleRedisConfig sampleRedisConfig() {
return new SampleRedisConfig();
}
public static void main(String[] args) {
new SpringApplicationBuilder(SpringBootSampleApplication.class).run(args);
......
package com.ctrip.framework.apollo.demo.spring.config;
package com.ctrip.framework.apollo.demo.spring.springBootDemo.config;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
/**
* @author Jason Song
* @author Jason Song(song_s@ctrip.com)
*/
@ConfigurationProperties(prefix = "redis.cache")
@Component
public class SampleRedisConfig {
private static final Logger logger = LoggerFactory.getLogger(SampleRedisConfig.class);
......
package com.ctrip.framework.apollo.demo.spring;
package com.ctrip.framework.apollo.demo.spring.xmlConfigDemo;
import org.springframework.context.support.ClassPathXmlApplicationContext;
......
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:apollo="http://www.ctrip.com/schema/apollo"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.ctrip.com/schema/apollo http://www.ctrip.com/schema/apollo.xsd">
<apollo:config order="10"/>
<apollo:config namespaces="FX.apollo" order="11"/>
<bean class="com.ctrip.framework.apollo.demo.spring.bean.XmlBean">
<property name="timeout" value="${timeout:200}"/>
<bean class="com.ctrip.framework.apollo.demo.spring.common.bean.NormalBean">
<property name="batch" value="${batch:100}"/>
</bean>
<!-- to support RefreshScope -->
<bean class="org.springframework.cloud.autoconfigure.RefreshAutoConfiguration"/>
<context:component-scan
base-package="com.ctrip.framework.apollo.demo.spring.common.bean,com.ctrip.framework.apollo.demo.spring.common.refresh"/>
</beans>
target/
.mvn
mvnw
mvnw.cmd
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
### NetBeans ###
nbproject/private/
build/
nbbuild/
dist/
nbdist/
.nb-gradle/
\ No newline at end of file
# apollo-spring-boot-sample
Demo project for Spring Boot Apollo
Spring Boot整合携程Apollo配置中心
## 客户端maven配置
* apollo-client(必须)
```xml
<dependency>
<groupId>com.ctrip.framework.apollo</groupId>
<artifactId>apollo-client</artifactId>
<version>0.8.0</version>
</dependency>
```
* spring-boot-starter-actuator 和 spring-cloud-context
```xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-context</artifactId>
<version>1.2.2.RELEASE</version>
</dependency>
```
注意:
1、`apollo-client`为必须配置
2、`spring-boot-starter-actuator``spring-cloud-context`为可选配置。仅在使用`Spring Cloud``@RefreshScope`时所需
# 参考文档
https://github.com/ctripcorp/apollo/wiki/
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>net.ameizi</groupId>
<artifactId>apollo-spring-boot-sample</artifactId>
<version>1.0</version>
<packaging>jar</packaging>
<name>Apollo Spring Boot Sample</name>
<description>Demo project for Spring Boot Apollo</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-context</artifactId>
<version>1.2.2.RELEASE</version>
</dependency>
<dependency>
<groupId>com.ctrip.framework.apollo</groupId>
<artifactId>apollo-client</artifactId>
<version>0.8.0</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>0.4.13</version>
<configuration>
<imageName>${project.artifactId}</imageName>
<dockerDirectory>src/main/docker</dockerDirectory>
<resources>
<resource>
<targetPath>/</targetPath>
<directory>${project.build.directory}</directory>
<include>${project.build.finalName}.jar</include>
</resource>
</resources>
</configuration>
</plugin>
</plugins>
</build>
</project>
FROM openjdk:8-jre-alpine
MAINTAINER ameizi <sxyx2008@163.com>
VOLUME /tmp
RUN echo "http://mirrors.aliyun.com/alpine/v3.6/main" > /etc/apk/repositories \
&& echo "http://mirrors.aliyun.com/alpine/v3.6/community" >> /etc/apk/repositories \
&& apk update upgrade \
&& apk add --no-cache tzdata \
&& ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
&& echo "Asia/Shanghai" > /etc/timezone
ADD *.jar app.jar
RUN sh -c 'touch /app.jar' \
&& mkdir -p /opt/settings \
&& echo "env=DEV" > /opt/settings/server.properties
ENV JAVA_OPTS=""
EXPOSE 9090
ENTRYPOINT [ "sh", "-c", "java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /app.jar" ]
\ No newline at end of file
package net.ameizi;
import com.ctrip.framework.apollo.spring.annotation.EnableApolloConfig;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @EnableApolloConfig要和@Configuration一起使用,不然不会生效。
*/
@Configuration
@EnableApolloConfig
public class ApolloConfigSample {
@Bean
public JavaConfigSample javaConfigSample(){
return new JavaConfigSample();
}
@Bean
public ConfigurationPropertiesSample configurationPropertiesSample() {
return new ConfigurationPropertiesSample();
}
}
package net.ameizi;
import com.ctrip.framework.apollo.Config;
import com.ctrip.framework.apollo.ConfigService;
import com.ctrip.framework.apollo.model.ConfigChange;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@SpringBootApplication
@RestController
public class Application {
@Autowired
private JavaConfigSample javaConfigSample;
@Autowired
private ConfigurationPropertiesSample configurationPropertiesSample;
private Config config = ConfigService.getAppConfig();
// 监听属性值变化
{
config.addChangeListener(changeEvent -> {
System.out.println("Changes for namespace " + changeEvent.getNamespace());
for (String key : changeEvent.changedKeys()) {
ConfigChange change = changeEvent.getChange(key);
System.out.println(String.format("Found change - key: %s, oldValue: %s, newValue: %s, changeType: %s", change.getPropertyName(), change.getOldValue(), change.getNewValue(), change.getChangeType()));
}
});
}
/**
* 使用apollo client api获取配置文件,apollo管控台修改配置后,实时更新
* @return
*/
@GetMapping("/clientapi")
public Sample apolloApiClient(){
int timeout = config.getIntProperty("sample.timeout",0);
int size = config.getIntProperty("sample.size",0);
return Sample.builder().timeout(timeout).size(size).build();
}
/**
* Java Config方式,JavaConfigSample内部使用了Config API,属性值的修改会立即生效
* @return
*/
@GetMapping("/javaconfig")
public JavaConfigSample commonProperties(){
return javaConfigSample;
}
/**
* Spring Boot ConfigurationProperties方式,
* ConfigurationPropertiesSample内部没有使用Config API,但因为使用了@RefreshScope注解,执行/refresh端点时会刷新属性的值
* @return
*/
@RefreshScope
@GetMapping("/configuration")
public ConfigurationPropertiesSample configurationPropertiesSample(){
return configurationPropertiesSample;
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
package net.ameizi;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* 使用Spring Boot ConfigurationProperties方式
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@ConfigurationProperties(prefix = "redis.cache")
public class ConfigurationPropertiesSample {
private int expireSeconds;
private int commandTimeout;
}
package net.ameizi;
import com.ctrip.framework.apollo.Config;
import com.ctrip.framework.apollo.model.ConfigChange;
import com.ctrip.framework.apollo.model.ConfigChangeEvent;
import com.ctrip.framework.apollo.spring.annotation.ApolloConfig;
import com.ctrip.framework.apollo.spring.annotation.ApolloConfigChangeListener;
import org.springframework.beans.factory.annotation.Value;
/**
* 使用Java Config方式
* 使用@ApolloConfig自动注入Config对象
* 使用@ApolloConfigChangeListener自动注入ConfigChangeListener对象
* 当监听到属性值发生变化后使用Config API修改属性值
*/
public class JavaConfigSample {
/**
* @ApolloConfig用来自动注入Config对象
*/
@ApolloConfig
private Config config;
@Value("${timeout:100}")
private int timeout;
private int batch;
@Value("${batch:200}")
public void setBatch(int batch) {
this.batch = batch;
}
/**
* @ApolloConfigChangeListener用来自动注册ConfigChangeListener
*/
@ApolloConfigChangeListener
private void someOnChange(ConfigChangeEvent changeEvent) {
changeEvent.changedKeys().forEach(key ->{
ConfigChange change = changeEvent.getChange(key);
System.out.println(String.format("Found change - key: %s, oldValue: %s, newValue: %s, changeType: %s", change.getPropertyName(), change.getOldValue(), change.getNewValue(), change.getChangeType()));
});
if (changeEvent.isChanged("batch")) {
batch = config.getIntProperty("batch", 200);
}
}
public int getTimeout() {
return config.getIntProperty("timeout",100);
}
public int getBatch() {
return this.batch;
}
}
package net.ameizi;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.boot.context.properties.ConfigurationProperties;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@ConfigurationProperties(prefix = "sample")
public class Sample {
private int timeout;
private int size;
}
\ No newline at end of file
app.id=apollo-spring-boot-sample
\ No newline at end of file
server.port=9090
management.security.enabled=false
\ No newline at end of file
......@@ -101,7 +101,6 @@
<module>apollo-portal</module>
<module>apollo-assembly</module>
<module>apollo-demo</module>
<module>apollo-spring-boot-sample</module>
</modules>
<dependencyManagement>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment