Spring Boot 配置服务器
Posted
技术标签:
【中文标题】Spring Boot 配置服务器【英文标题】:Spring boot config server 【发布时间】:2014-12-20 09:11:50 【问题描述】:我一直在尝试掌握位于此处的 :https://github.com/spring-cloud/spring-cloud-config,在更彻底地阅读了文档之后,我能够解决我的大部分问题。但是,我确实必须为基于文件的 PropertySourceLocator 编写一个附加类
/*
* Copyright 2013-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.config.client;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Iterator;
import java.util.Properties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.core.env.PropertiesPropertySource;
import org.springframework.core.env.PropertySource;
import org.springframework.util.StringUtils;
/**
* @author Al Dispennette
*
*/
@ConfigurationProperties("spring.cloud.config")
public class ConfigServiceFilePropertySourceLocator implements PropertySourceLocator
private Logger logger = LoggerFactory.getLogger(ConfigServiceFilePropertySourceLocator.class);
private String env = "default";
@Value("$spring.application.name:'application'")
private String name;
private String label = name;
private String basedir = System.getProperty("user.home");
@Override
public PropertySource<?> locate()
try
return getPropertySource();
catch (IOException e)
logger.error("An error ocurred while loading the properties.",e);
return null;
/**
* @throws IOException
*/
private PropertySource getPropertySource() throws IOException
Properties source = new Properties();
Path path = Paths.get(getUri());
if(Files.isDirectory(path))
Iterator<Path> itr = Files.newDirectoryStream(path).iterator();
String fileName = null!=label||StringUtils.hasText(label)?label:name+".properties";
logger.info("Searching for ",fileName);
while(itr.hasNext())
Path tmpPath = itr.next();
if(tmpPath.getFileName().getName(0).toString().equals(fileName))
logger.info("Found file: ",fileName);
source.load(Files.newInputStream(tmpPath));
return new PropertiesPropertySource("configService",source);
public String getUri()
StringBuilder bldr = new StringBuilder(basedir)
.append(File.separator)
.append(env)
.append(File.separator)
.append(name);
logger.info("loading properties directory: ",bldr.toString());
return bldr.toString();
public String getName()
return name;
public void setName(String name)
this.name = name;
public String getEnv()
return env;
public void setEnv(String env)
this.env = env;
public String getLabel()
return label;
public void setLabel(String label)
this.label = label;
public String getBasedir()
return basedir;
public void setBasedir(String basedir)
this.basedir = basedir;
然后我将它添加到 ConfigServiceBootstrapConfiguration.java
@Bean
public PropertySourceLocator configServiceFilePropertySource(
ConfigurableEnvironment environment)
ConfigServiceFilePropertySourceLocator locator = new ConfigServiceFilePropertySourceLocator();
String[] profiles = environment.getActiveProfiles();
if (profiles.length==0)
profiles = environment.getDefaultProfiles();
locator.setEnv(StringUtils.arrayToCommaDelimitedString(profiles));
return locator;
最后这达到了我想要的效果。 现在我很想知道这是否是我应该做的,或者我是否仍然缺少某些东西,而这已经被处理了,我只是错过了。
*****编辑戴夫要求的信息******
如果我取出文件属性源加载器并使用
更新 bootstrap.ymluri: file://$user.home/resources
示例应用程序在启动时抛出以下错误:
ConfigServiceBootstrapConfiguration : Could not locate PropertySource: Object of class [sun.net.www.protocol.file.FileURLConnection] must be an instance of class java.net.HttpURLConnection
这就是为什么我认为需要额外的课程。就测试用例而言,我相信您正在谈论 SpringApplicationEnvironmentRepositoryTests.java 并且我同意创建环境有效,但作为一个整体,当 uri 协议为“文件”时,应用程序似乎没有按预期运行。
******其他编辑*******
这就是我理解它的工作原理: 示例项目依赖于 spring-cloud-config-client 工件,因此具有对 spring-cloud-config-server 工件的传递依赖。 客户端工件中的 ConfigServiceBootstrapConfiguration.java 创建一个 ConfigServicePropertySourceLocator 类型的属性源定位器 bean。 配置客户端工件中的 ConfigServicePropertySourceLocator.java 有注解 @ConfigurationProperties("spring.cloud.config") 并且属性uri存在于该类中,因此在bootstrap.yml文件中设置了spring.cloud.config.uri。
我相信 quickstart.adoc 中的以下声明强化了这一点:
当它运行时,它将从 端口 8888 上的默认本地配置服务器(如果它正在运行)。修改 您可以更改配置服务器的位置的启动行为 使用
bootstrap.properties
(如application.properties
,但对于 应用程序上下文的引导阶段),例如---- spring.cloud.config.uri:http://myconfigserver.com
此时,JGitEnvironmentRepository bean 是如何被使用并寻找到 github 的连接的。 我假设由于 uri 是在 ConfigServicePropertySourceLocator 中设置的属性,因此任何有效的 uri 协议都可以用于指向某个位置。 这就是为什么我使用 'file://' 协议认为服务器会获取 NativeEnvironmentRepository。
所以在这一点上,我确定我要么缺少某些步骤,要么需要添加文件系统属性源定位器。
我希望这更清楚一点。
全栈:
java.lang.IllegalArgumentException: Object of class [sun.net.www.protocol.file.FileURLConnection] must be an instance of class java.net.HttpURLConnection
at org.springframework.util.Assert.isInstanceOf(Assert.java:339)
at org.springframework.util.Assert.isInstanceOf(Assert.java:319)
at org.springframework.http.client.SimpleClientHttpRequestFactory.openConnection(SimpleClientHttpRequestFactory.java:182)
at org.springframework.http.client.SimpleClientHttpRequestFactory.createRequest(SimpleClientHttpRequestFactory.java:140)
at org.springframework.http.client.support.HttpAccessor.createRequest(HttpAccessor.java:76)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:541)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:506)
at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:448)
at org.springframework.cloud.config.client.ConfigServicePropertySourceLocator.locate(ConfigServicePropertySourceLocator.java:68)
at org.springframework.cloud.bootstrap.config.ConfigServiceBootstrapConfiguration.initialize(ConfigServiceBootstrapConfiguration.java:70)
at org.springframework.boot.SpringApplication.applyInitializers(SpringApplication.java:572)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:303)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:952)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:941)
at sample.Application.main(Application.java:20)
【问题讨论】:
我想这取决于您想要实现的目标。这是针对应用程序还是针对其他应用程序将使用的库?无论如何你不应该改变ConfigServiceBootstrapConfiguration
,但很难理解其意图是什么。
嗨 Dave,文档说我可以更改引导属性/yaml 中的 URI,因此我将其更改为使用 file:///my/file/path。这给出了一个错误,指出该文件不是受支持的协议。最后,我希望实现的是一个共享的配置服务器,但配置文件位于配置服务器所在框的文件夹中。然后,我创建的其他 spring boot 应用程序将连接到 cofig 服务器,就像它们在 git repo 时一样。我希望这是有道理的。
单元测试使用“file:”作为远程存储库,所以它应该可以工作。您必须显示堆栈跟踪或其他东西来诊断问题。另请注意,除非文件系统是共享的,否则您将拥有 SPOF。
嗨@DaveSyer,主帖中的编辑是否提供了足够的信息或者您想要更多信息?
这实际上不是堆栈跟踪。并且配置文件不是 Spring Cloud 配置文件(“uri”无论如何都没有绑定到配置服务器中的任何内容)。也许你可以扩大一点?
【参考方案1】:
我昨天读了这个帖子,它缺少一个重要的信息
如果不想用git作为repository,那么需要配置spring cloud server有spring.profiles.active=native
查看 spring-config-server 代码以了解它 org.springframework.cloud.config.server.NativeEnvironmentRepository
spring:
application:
name: configserver
jmx:
default_domain: cloud.config.server
profiles:
active: native
cloud:
config:
server:
file :
url : <path to config files>
【讨论】:
【参考方案2】:我刚遇到同样的问题。我希望配置服务器从本地文件系统而不是 git 存储库加载属性。以下配置适用于 Windows。
spring:
profiles:
active: native
cloud:
config:
server:
native:
searchLocations: file:C:/springbootapp/properties/
假设属性文件在C:/springbootapp/properties/下
更多信息请参考Spring Cloud Documentation和Configuring It All Out
【讨论】:
【参考方案3】:我想我有基于你最后的 cmets 的最终解决方案 在我添加的 configserver.yml 中
spring.profiles.active: file
spring.cloud.config.server.uri: file://$user.home/resources
在我添加的 ConfigServerConfiguration.java 中
@Configuration
@Profile("file")
protected static class SpringApplicationConfiguration
@Value("$spring.cloud.config.server.uri")
String locations;
@Bean
public SpringApplicationEnvironmentRepository repository()
SpringApplicationEnvironmentRepository repo = new SpringApplicationEnvironmentRepository();
repo.setSearchLocations(locations);
return repo;
我可以通过以下方式查看属性:
curl localhost:8888/bar/default
curl localhost:8888/foo/development
【讨论】:
以上是关于Spring Boot 配置服务器的主要内容,如果未能解决你的问题,请参考以下文章