SpringCloudBus实现配置文件动态刷新

SpringCloudBus实现配置文件动态刷新


1、流程图

SpringCloudBus实现配置文件动态刷新_第1张图片
要做到自动刷新配置文件,必须是文件修改之后,可以通知给客户端,我这里选择RabbitMQ作为消息队列,让服务端和客户端可以通信

RabbitMQ可自行百度安装

2、Spring Cloud Bus 实现配置文件动态刷新,步骤如下:

  1. 提交代码,利用 Git 的 WebHooks 触发 POST 请求给 bus-refresh
  2. Server端接收到请求并发送给 Spring Cloud Bus
  3. Spring Cloud Bus 接到消息并通知给客户端
  4. 客户端接收到通知,请求Server端获取最新配置(全部客户端均获取到最新的配置)

3、项目

3.1 eureka-server

创建注册中心项目(这里不做详细说明,重点是 Spring Cloud Bus)

3.2 config-server

3.2.1 引入POM文件

Spring Boot 版本 2.0.1.RELEASE
spring Cloud 版本 Finchley.RC1
这里版本必须对应,否则会有问题(可自行调试)

<parent>
	<groupId>org.springframework.bootgroupId>
	<artifactId>spring-boot-starter-parentartifactId>
	<version>2.0.1.RELEASEversion>
	<relativePath/> 
parent>

<properties>
	<project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
	<project.reporting.outputEncoding>UTF-8project.reporting.outputEncoding>
	<java.version>1.8java.version>
	<spring-cloud.version>Finchley.RC1spring-cloud.version>
properties>

<dependencies>
	<dependency>
		<groupId>org.springframework.cloudgroupId>
		<artifactId>spring-cloud-config-serverartifactId>
	dependency>

	<dependency>
		<groupId>org.springframework.cloudgroupId>
		<artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>
	dependency>

	<dependency>
		<groupId>org.springframework.bootgroupId>
		<artifactId>spring-boot-starter-testartifactId>
		<scope>testscope>
	dependency>

	<dependency>
		<groupId>org.springframework.cloudgroupId>
		<artifactId>spring-cloud-starter-bus-amqpartifactId>
	dependency>

	<dependency>
		<groupId>org.springframework.cloudgroupId>
		<artifactId>spring-cloud-config-monitorartifactId>
	dependency>

	<dependency>
		<groupId>org.projectlombokgroupId>
		<artifactId>lombokartifactId>
	dependency>

dependencies>

<dependencyManagement>
	<dependencies>
		<dependency>
			<groupId>org.springframework.cloudgroupId>
			<artifactId>spring-cloud-dependenciesartifactId>
			<version>${spring-cloud.version}version>
			<type>pomtype>
			<scope>importscope>
		dependency>
	dependencies>
dependencyManagement>

<build>
	<plugins>
		<plugin>
			<groupId>org.springframework.bootgroupId>
			<artifactId>spring-boot-maven-pluginartifactId>
		plugin>
	plugins>
build>

<repositories>
	<repository>
		<id>spring-milestonesid>
		<name>Spring Milestonesname>
		<url>https://repo.spring.io/milestoneurl>
		<snapshots>
			<enabled>falseenabled>
		snapshots>
	repository>
repositories>

3.2.2 启动类

@EnableConfigServer
@EnableEurekaClient
@SpringBootApplication
public class MichaelSpicaConfigServerApplication {

	public static void main(String[] args) {
		SpringApplication.run(MichaelSpicaConfigServerApplication.class, args);
	}
}

注意 @EnableConfigServer@EnableEurekaClient

3.2.3 过滤器

@Slf4j
@Component
public class CustometFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest httpServletRequest = (HttpServletRequest)servletRequest;
        String url = new String(httpServletRequest.getRequestURI());
        //只过滤/actuator/bus-refresh请求
        if (!url.endsWith("/bus-refresh")) {
            filterChain.doFilter(servletRequest, servletResponse);
            return;
        }
        //使用HttpServletRequest包装原始请求达到修改post请求中body内容的目的
        CustometRequestWrapper requestWrapper = new CustometRequestWrapper(httpServletRequest);

        filterChain.doFilter(requestWrapper, servletResponse);
    }

    @Override
    public void destroy() {

    }
}
public class CustometRequestWrapper extends HttpServletRequestWrapper {

    public CustometRequestWrapper(HttpServletRequest request) {
        super(request);
    }

    @Override
    public ServletInputStream getInputStream() throws IOException {
        byte[] bytes = new byte[0];
        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
        return new ServletInputStream() {
            @Override
            public boolean isFinished() {
                return byteArrayInputStream.read() == -1 ? true:false;
            }

            @Override
            public boolean isReady() {
                return false;
            }

            @Override
            public void setReadListener(ReadListener readListener) {

            }

            @Override
            public int read() throws IOException {
                return byteArrayInputStream.read();
            }
        };
    }
}

3.2.4 配置文件(application.yml)

spring:
  application:
    name: michael-spica-config-server
  cloud:
    config:
      server:
        git: #Gitee/Github
          uri: https://gitee.com/xxx/config-repo.git
          username: ***
          password: ***
          basedir: D:\project\michael\michael-spica-config-server\basedir
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8762/eureka/ #服务注册与发现
management:
  endpoints:
    web:
      exposure:
        include: "*" #暴露所有接口

项目启动后:
SpringCloudBus实现配置文件动态刷新_第2张图片
登录RabbitMQ:
SpringCloudBus实现配置文件动态刷新_第3张图片
可以看到已经创建一个消息队列

3.3 config-client

3.3.1 引入POM文件

<parent>
	<groupId>org.springframework.bootgroupId>
	<artifactId>spring-boot-starter-parentartifactId>
	<version>2.0.1.RELEASEversion>
	<relativePath/> 
parent>

<properties>
	<project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
	<project.reporting.outputEncoding>UTF-8project.reporting.outputEncoding>
	<java.version>1.8java.version>
	<spring-cloud.version>Finchley.RC1spring-cloud.version>
properties>

<dependencies>
	<dependency>
		<groupId>org.springframework.cloudgroupId>
		<artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>
	dependency>
	<dependency>
		<groupId>org.springframework.bootgroupId>
		<artifactId>spring-boot-starter-testartifactId>
		<scope>testscope>
	dependency>
	<dependency>
		<groupId>org.springframework.bootgroupId>
		<artifactId>spring-boot-starter-webartifactId>
	dependency>
	<dependency>
		<groupId>org.projectlombokgroupId>
		<artifactId>lombokartifactId>
	dependency>
	<dependency>
		<groupId>org.springframework.cloudgroupId>
		<artifactId>spring-cloud-config-clientartifactId>
	dependency>
	<dependency>
		<groupId>org.springframework.cloudgroupId>
		<artifactId>spring-cloud-starter-bus-amqpartifactId>
	dependency>
dependencies>

<dependencyManagement>
	<dependencies>
		<dependency>
			<groupId>org.springframework.cloudgroupId>
			<artifactId>spring-cloud-dependenciesartifactId>
			<version>${spring-cloud.version}version>
			<type>pomtype>
			<scope>importscope>
		dependency>
	dependencies>
dependencyManagement>

<build>
	<plugins>
		<plugin>
			<groupId>org.springframework.bootgroupId>
			<artifactId>spring-boot-maven-pluginartifactId>
		plugin>
	plugins>
build>

<repositories>
	<repository>
		<id>spring-milestonesid>
		<name>Spring Milestonesname>
		<url>https://repo.spring.io/milestoneurl>
		<snapshots>
			<enabled>falseenabled>
		snapshots>
	repository>
repositories>

3.3.2 启动类

@SpringBootApplication
@EnableEurekaClient
public class MichaelSpicaOrderApplication {

    public static void main(String[] args) {
        SpringApplication.run(MichaelSpicaOrderApplication.class, args);
    }
}

3.3.3 配置文件(bootstrap.yml)

spring:
  application:
    name: order #对应服务名
  cloud:
    config:
      discovery:
        enabled: true
        service-id: CONFIG-SERVER #实例名
      profile: qa #环境
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8762/eureka/

项目启动后:
SpringCloudBus实现配置文件动态刷新_第4张图片
刷新RabbitMQ:
SpringCloudBus实现配置文件动态刷新_第5张图片

4、测试

修改远程Git库的配置文件:
SpringCloudBus实现配置文件动态刷新_第6张图片
手动刷新
在这里插入图片描述

4.1 读取配置文件

注意@RefreshScope注解(那里需要刷新在那里添加)

两种方式**(项目中通常使用“第二种”方式)**:
第一种:

@RestController
@RequestMapping("/env")
@RefreshScope
public class EnvController {

    @Value("${env}")
    private String env;

    @GetMapping("/print")
    public String print(){
        return env;
    }
}

第二种:

@Data
@Component
@ConfigurationProperties("girl")
@RefreshScope
public class GirlConfig {
    private String name;
    private Integer age;
}

4.2 通过访问接口进行测试

@RestController
@RequestMapping("/girl")
public class GirlController {

    @Autowired
    private GirlConfig girlConfig;

    @GetMapping("/print")
    public String print() {
        return "name:" + girlConfig.getName() + " age:" + girlConfig.getAge();
    }
}

4.2.1 访问接口

SpringCloudBus实现配置文件动态刷新_第7张图片

5、WebHooks 设置

SpringCloudBus实现配置文件动态刷新_第8张图片
URL需要一个外网可以访问的域名(可以用花生壳内网穿透)
每次PUSH代码,都会更新配置文件

你可能感兴趣的:(SpringCloud)