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.yml
uri: 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 配置服务器的主要内容,如果未能解决你的问题,请参考以下文章

spring boot配置信息详解

如何配置Spring Boot Tomcat

×××公众号接入基本配置服务器配置 spring boot

Spring Boot 配置文件

Spring Boot 框架学习 配置并运行Spring Boot 框架

spring boot2X集成spring cloud config