本指南将引导您完成从Spring Cloud Config Server站起并使用配置的过程

你会建立什么

您将设置一个Config Server并构建一个客户端,该客户端在启动时会消耗配置,然后刷新配置而不重新启动客户端。

你需要什么

如何完成本指南

像大多数Spring 入门指南一样,您可以从头开始并完成每个步骤,也可以绕过您已经熟悉的基本设置步骤。无论哪种方式,您最终都可以使用工作代码。

从头开始 ,请继续进行[scratch]

跳过基础知识 ,请执行以下操作:

完成后 ,您可以根据中的代码检查结果gs-centralized-configuration/complete

从Spring Initializr开始

对于所有Spring应用程序,您应该从Spring Initializr开始。Initializr提供了一种快速的方法来提取应用程序所需的所有依赖关系,并为您完成了许多设置。

本指南需要两个应用程序。第一个应用程序(配置服务)仅需要Config Server依赖项。下图显示了为配置服务设置的Initializr:

初始化服务
上图显示了选择Maven作为构建工具的Initializr。您也可以使用Gradle。它还显示了com.examplecentralized-configuration-service分别是Group和Artifact。在本示例的其余部分中,将使用这些值。

以下清单显示了pom.xml选择Maven时创建的文件(用于配置服务):

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.1.8.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.example</groupId>
	<artifactId>centralized-configuration-service</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>centralized-configuration-service</name>
	<description>Demo project for Spring Boot</description>

	<properties>
		<java.version>1.8</java.version>
		<spring-cloud.version>Greenwich.SR3</spring-cloud.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-config-server</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>org.springframework.cloud</groupId>
				<artifactId>spring-cloud-dependencies</artifactId>
				<version>${spring-cloud.version}</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
		</dependencies>
	</dependencyManagement>

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

</project>

以下清单显示了build.gradle选择Gradle时创建的文件(用于配置服务):

plugins {
	id 'org.springframework.boot' version '2.1.8.RELEASE'
	id 'io.spring.dependency-management' version '1.0.8.RELEASE'
	id 'java'
}

group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'

repositories {
	mavenCentral()
}

ext {
	set('springCloudVersion', "Greenwich.SR3")
}

dependencies {
	implementation 'org.springframework.cloud:spring-cloud-config-server'
	testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

dependencyManagement {
	imports {
		mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
	}
}

第二个应用程序(配置客户端)需要Config Client,Spring Boot Actuator和Spring Web依赖项。下图显示了为配置客户端设置的Initializr:

初始化客户端
上图显示了选择Maven作为构建工具的Initializr。您也可以使用Gradle。它还显示了com.examplecentralized-configuration-client分别是Group和Artifact。在本示例的其余部分中,将使用这些值。

以下清单显示了pom.xml选择Maven时创建的文件(用于配置客户端):

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.1.8.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.example</groupId>
	<artifactId>centralized-configuration-client</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>centralized-configuration-client</name>
	<description>Demo project for Spring Boot</description>

	<properties>
		<java.version>1.8</java.version>
		<spring-cloud.version>Greenwich.SR3</spring-cloud.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-actuator</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-config</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>org.springframework.cloud</groupId>
				<artifactId>spring-cloud-dependencies</artifactId>
				<version>${spring-cloud.version}</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
		</dependencies>
	</dependencyManagement>

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

</project>

以下清单显示了build.gradle选择Gradle时创建的文件(用于配置客户端):

buildscript {
    ext { springBootVersion = '2.1.6.RELEASE' }
    repositories { mavenCentral() }
    dependencies { classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}") }
}

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'idea'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'

bootJar {
    baseName = 'configuration-client'
    version = '0.0.1-SNAPSHOT'
}
sourceCompatibility = 1.8
targetCompatibility = 1.8

repositories { mavenCentral() }

dependencies {
    compile('org.springframework.cloud:spring-cloud-starter-config')
    compile('org.springframework.boot:spring-boot-starter-actuator')
    compile('org.springframework.boot:spring-boot-starter-web')
    testCompile('org.springframework.boot:spring-boot-starter-test')
}

dependencyManagement {
    imports {
        mavenBom "org.springframework.cloud:spring-cloud-dependencies:Finchley.SR2"
    }
}

eclipse {
    classpath {
        containers.remove('org.eclipse.jdt.launching.JRE_CONTAINER')
        containers 'org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8'
    }
}
为了方便起见,我们提供了构建文件( pom.xml文件和一个build.gradle文件)位于项目顶部(client和service目录上方的一个目录),您可以使用该文件一次构建两个项目。我们还在那里添加了Maven和Gradle包装器。

站立配置服务器

首先,您需要一个Config Service来充当您的Spring应用程序和(通常)版本控制的配置文件存储库之间的一种中介。您可以使用Spring Cloud的@EnableConfigServer站立可以与其他应用程序通信的配置服务器。这是一个常规的Spring Boot应用程序,添加了一个注释以启用配置服务器。以下清单(来自configuration-service/src/main/java/com/example/configurationservice/ConfigurationServiceApplication.java )显示了这样的应用程序:

package com.example.configurationservice;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.config.server.EnableConfigServer;

@EnableConfigServer
@SpringBootApplication
public class ConfigurationServiceApplication {

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

Config Server需要知道要管理哪个存储库。这里有几种选择,但从基于Git的文件系统存储库开始。您可以轻松地将Config Server指向Github或GitLab存储库。在文件系统上,创建一个新目录并运行git init在里面。然后添加一个名为a-bootiful-client.properties到Git仓库。然后跑git commit在里面。稍后,您将使用一个Spring Boot应用程序连接到Config Server,该应用程序的spring.application.name属性将其标识为a-bootiful-client到配置服务器。这是Config Server知道要发送给特定客户端的配置集的方式。它将所有的值从命名的任何文件application.properties要么application.yml在Git仓库中。更具体命名的文件中的属性键(例如a-bootiful-client.properties )覆盖那些application.properties要么application.yml

添加简单的属性和值( message = Hello world )到新创建的a-bootiful-client.properties文件然后git commit改变。

通过指定来指定Git存储库的路径spring.cloud.config.server.git.uri财产configuration-service/src/main/resources/application.properties 。您还必须指定其他server.port避免在同一台计算机上同时运行该服务器和另一个Spring Boot应用程序时的端口冲突值。以下清单(来自configuration-service/src/main/resources/application.properties )显示了这样的application.properties文件:

server.port=8888

spring.cloud.config.server.git.uri=${HOME}/Desktop/config

本示例在以下位置使用基于文件的git存储库${HOME}/Desktop/config 。您可以通过创建一个新目录并运行来轻松创建一个目录git commit属性和其中的YAML文件。以下命令集可完成此工作:

$ cd ~/Desktop/config
$ find .
./.git
...
./application.yml

或者,如果您在应用程序中更改配置文件以指向它,则可以使用远程git存储库(例如Github)。

使用配置客户端从配置服务器读取配置

既然您已经启动了Config Server,则需要启动一个新的Spring Boot应用程序,该应用程序使用Config Server加载自己的配置,并刷新其配置以将更改反映到Config Server的按需更改,而无需重新启动JVM。 。为此,请添加org.springframework.cloud:spring-cloud-starter-config依赖关系,以连接到配置服务器。Spring会看到配置属性文件,就像从中加载的任何属性文件一样application.properties要么application.yml或任何其他PropertySource

引导阶段,必须从配置服务器读取应用程序的其余配置之前 ,必须先读取用于配置配置客户端的属性。指定客户的spring.application.namea-bootiful-client以及配置服务器的位置( spring.cloud.config.uri )在configuration-client/src/main/resources/bootstrap.properties ,它将比任何其他配置更早地加载。以下清单显示了该文件:

configuration-client/src/main/resources/bootstrap.properties

spring.application.name=a-bootiful-client
# N.B. this is the default:
spring.cloud.config.uri=http://localhost:8888

您还想启用/refresh端点,以演示动态配置更改。以下清单(来自configuration-client/src/main/resources/application.properties )显示了操作方法:

management.endpoints.web.exposure.include=*

客户端可以使用传统机制(例如, @ConfigurationProperties要么@Value("${…​}")或通过Environment抽象)。现在您需要创建一个Spring MVC REST控制器,该控制器返回已解析的message财产的价值。请参阅《 构建RESTful Web服务》指南,以了解有关使用Spring MVC和Spring Boot构建REST服务的更多信息。

默认情况下,在客户端启动时读取配置值,而不是再次读取。您可以通过注释以下内容来强制Bean 刷新其配置(即从Config Server中提取更新的值)。 MessageRestController使用Spring Cloud Config @RefreshScope然后触发刷新事件。以下清单(来自configuration-client/src/main/java/com/example/configurationclient/ConfigurationClientApplication.java )显示了操作方法:

package com.example.configurationclient;

import org.springframework.beans.factory.annotation.Value;
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.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@SpringBootApplication
public class ConfigurationClientApplication {

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

@RefreshScope
@RestController
class MessageRestController {

    @Value("${message:Hello default}")
    private String message;

    @RequestMapping("/message")
    String getMessage() {
        return this.message;
    }
}

测试应用

您可以通过以下方式测试端到端结果:首先启动Config Service,然后在其运行后启动客户端。在浏览器中访问客户端应用程序,网址为http://localhost:8080/message 。在那里,你应该看到Hello world在回应中。

改变message键入a-bootiful-client.properties Git存储库中的文件更改为其他内容( Hello Spring! , 也许?)。您可以通过访问来确认Config Server看到更改http://localhost:8888/a-bootiful-client/default 。您需要调用refresh Spring Boot Actuator端点,以强制客户端刷新自身并提取新值。Spring Boot的Actuator公开有关应用程序的操作端点(例如运行状况检查和环境信息)。要使用它,您必须添加org.springframework.boot:spring-boot-starter-actuator到客户端应用程序的类路径。您可以调用refresh通过发送空的HTTP执行器端点POST给客户的refresh端点: http://localhost:8080/actuator/refresh 。然后,您可以通过访问http://localhost:8080/message端点。

以下命令调用执行器的刷新命令:

$ curl localhost:8080/actuator/refresh -d {} -H "Content-Type: application/json"
我们设置management.endpoints.web.exposure.include=*使其易于测试(自Spring Boot 2.0起,默认情况下不公开Actuator端点)。默认情况下,如果未设置标志,您仍然可以通过JMX访问它们。

摘要

恭喜你!您刚刚使用Spring通过首先建立服务然后动态更新其配置来集中所有服务的配置。

也可以看看

以下指南也可能会有所帮助:

是否要编写新指南或为现有指南做出贡献?查看我们的贡献准则

所有指南均以代码的ASLv2许可证和写作的Attribution,NoDerivatives创作共用许可证发布