Spring Boot、Spring Cloud 自定义配置文件(如何整合配置中心)

简介: Spring Boot配置在spring中我们都知道所有配置定义在配置文件 application.yml 中我们就可以通过注解获取到。Spring 中对所有配置管理都有一个统一的上层接口Environment实现类图

Spring Boot配置

在spring中我们都知道所有配置定义在配置文件 application.yml 中我们就可以通过注解获取到。

Spring 中对所有配置管理都有一个统一的上层接口

  • Environment

实现类图

网络异常,图片无法展示
|

可以看到实现类是非常多的。不过实际所有的配置获取都是封装在最上层的接口 PropertyResolver 中的

网络异常,图片无法展示
|

这里需要注意的是 PropertyResolver 的核心实现类
PropertySourcesPropertyResolver

网络异常,图片无法展示
|


PropertySourcesPropertyResolver
中拥有的 PropertySources 最后使用的也还是 PropertySource 类,通过遍历 PropertySource 集合

网络异常,图片无法展示
|

PropertySource 最终是通过拥有一个泛型T source获取最终的属性

网络异常,图片无法展示
|

所以这里可以看到我们所有的资源都是一个 PropertySource

需要注意的是,PropertySource之间是有优先级顺序的,如果有一个Key在多个 PropertySource 中都存在,那么在前面的 PropertySource 优先。

大致获取的原理这里引用apollo的一张图

网络异常,图片无法展示
|

这张图就是比较清晰的

简单测试使用

spring boot 版本 2.6.8

yaml 配置一个name属性

name: 1214
@RestController
public class EnvironementController {
    @Autowired
    Environment environment;
  @Value("${name}")
    private String name;
    @GetMapping("/name")
    public String env(){
        System.out.println(name);
        return environment.getProperty("name");
    }
}

无论是使用 @Value 还是 Environment 都能获取到我们的自定义属性

然后调用接口就能获取到我们配置中的属性了

网络异常,图片无法展示
|

Spring Cloud自定义配置文件获取

在了解了上面的原理及基本使用之后我们可以就可以自定义配置文件了。核心思路就是通过读取文件然后加载到 PropertySource 中去。

而Spring Cloud刚好提供类这方面的扩展,Spring Cloud 提供了 PropertySourceLocator 接口供我们加载自定义配置成 PropertySource

网络异常,图片无法展示
|

我们这里只需要实现locate即可

按这个方式我们来自定义配置试试

1. 引入依赖

<properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>    
        <spring-cloud.version>2021.0.2</spring-cloud.version>
        <spring-boot.version>2.7.0</spring-boot.version>
    </properties>
    <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-context</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-bootstrap</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring-boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <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>

注意spring Cloud 2020版本后需要手动引入依赖
spring-cloud-starter-bootstrap

2. 自定义配置

2.1 自定义PropertySource,这里我们直接使用Spring 提供的MapPropertySource

package com.zou.config;
import java.util.Map;
import org.springframework.core.env.MapPropertySource;
/**
 *@author : wh
 *@date : 2022/7/12 09:54
 *@description:
 */
public class ZouMapPropertySource extends MapPropertySource {
  /**
   * Create a new {@code MapPropertySource} with the given name and {@code Map}.
   *
   * @param name   the associated name
   * @param source the Map source (without {@code null} values in order to get
   *               consistent {@link #getProperty} and {@link #containsProperty} behavior)
   */
  public ZouMapPropertySource(String name, Map<String, Object> source) {
    super(name, source);
  }
}

2.2 自定义PropertySourceLocator

package com.zou.config;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.boot.json.JsonParser;
import org.springframework.boot.json.JsonParserFactory;
import org.springframework.cloud.bootstrap.config.PropertySourceLocator;
import org.springframework.core.annotation.Order;
import org.springframework.core.env.Environment;
import org.springframework.core.env.PropertySource;
/**
 * @author : wh
 * @date : 2022/7/12 09:56
 * @description:
 */
@Order(0)
public class ZouJsonPropertySourceLocator implements PropertySourceLocator {
  @Override
  public PropertySource<?> locate(Environment environment) {
    return new ZouMapPropertySource
        ("ZouMapPropertySource", mapPropertySource());
  }
  private Map<String, Object> mapPropertySource() {
    Map<String, Object> result = new HashMap<>();
    JsonParser parser = JsonParserFactory.getJsonParser();
    Map<String, Object> fileMap = parser.parseMap(readFile());
    processNestMap("", result, fileMap);
    return result;
  }
  /**
   * 读取配置文件 zou.json
   *
   * @return
   */
  private String readFile() {
    List<String> lines;
    try {
      lines = Files.readAllLines(Paths.get("src/main/resources/zou.json"), StandardCharsets.UTF_8);
    }
    catch (IOException e) {
      throw new RuntimeException(e);
    }
    StringBuilder sb = new StringBuilder();
    for (String line : lines) {
      sb.append(line);
    }
    return sb.toString();
  }
  private void processNestMap(String prefix, Map<String, Object> result, Map<String, Object> fileMap) {
    if (prefix.length() > 0) {
      prefix += ".";
    }
    for (Map.Entry<String, Object> entrySet : fileMap.entrySet()) {
      if (entrySet.getValue() instanceof Map) {
        processNestMap(prefix + entrySet.getKey(), result, (Map<String, Object>) entrySet.getValue());
      }
      else {
        result.put(prefix + entrySet.getKey(), entrySet.getValue());
      }
    }
  }
}

2.3 自定义配置Bean config

@Configuration(proxyBeanMethods = false)
public class ZouConfiguration {
  @Bean
  public ZouJsonPropertySourceLocator zouJsonPropertySourceLocator(){
    return new ZouJsonPropertySourceLocator();
  }
}

2.4 定义BootstrapConfiguration配置

resources 添加 spring.factories 配置文件

org.springframework.cloud.bootstrap.BootstrapConfiguration=\
com.zou.config.ZouConfiguration

3. 测试

这里简单定义一个我们自己的配置文件 zou.json

网络异常,图片无法展示
|

{
  "name": "xiaozou"
}

定义一个测试controller

@RestController
@RequestMapping("test/v1")
public class ZouController {
  @Autowired
    Environment environment;
    @Value("${name:1}")
    private String name;
    @GetMapping("/name")
    public String env(){
        System.out.println(name);
        return environment.getProperty("name");
    }
}

网络异常,图片无法展示
|

可以看到我们自定义配置是生效了的

Spring Cloud 整合自定义配置还是比较容易的,核心还是自定义一个
ZouJsonPropertySourceLocator
然后加载 PropertySource 到Spring中。这里我们整合的是本地文件,其实如果要整合远程配置中心也是类似的,只不过获取文件就不是读取本地配置文件,而是通过http读取远程配置文件然后构造出一个 PropertySource 放入Spring容器中。后续有机会我们对 nacos 整合 Spring Cloud 源码进行分析

相关文章
|
2月前
|
负载均衡 监控 Java
Spring Cloud Gateway 全解析:路由配置、断言规则与过滤器实战指南
本文详细介绍了 Spring Cloud Gateway 的核心功能与实践配置。首先讲解了网关模块的创建流程,包括依赖引入(gateway、nacos 服务发现、负载均衡)、端口与服务发现配置,以及路由规则的设置(需注意路径前缀重复与优先级 order)。接着深入解析路由断言,涵盖 After、Before、Path 等 12 种内置断言的参数、作用及配置示例,并说明了自定义断言的实现方法。随后重点阐述过滤器机制,区分路由过滤器(如 AddRequestHeader、RewritePath、RequestRateLimiter 等)与全局过滤器的作用范围与配置方式,提
Spring Cloud Gateway 全解析:路由配置、断言规则与过滤器实战指南
|
2月前
|
Java 关系型数据库 MySQL
Spring Boot自动配置:魔法背后的秘密
Spring Boot 自动配置揭秘:只需简单配置即可启动项目,背后依赖“约定大于配置”与条件化装配。核心在于 `@EnableAutoConfiguration` 注解与 `@Conditional` 系列条件判断,通过 `spring.factories` 或 `AutoConfiguration.imports` 加载配置类,实现按需自动装配 Bean。
|
2月前
|
人工智能 Java 开发者
【Spring】原理解析:Spring Boot 自动配置
Spring Boot通过“约定优于配置”的设计理念,自动检测项目依赖并根据这些依赖自动装配相应的Bean,从而解放开发者从繁琐的配置工作中解脱出来,专注于业务逻辑实现。
|
1月前
|
前端开发 Java 应用服务中间件
《深入理解Spring》 Spring Boot——约定优于配置的革命者
Spring Boot基于“约定优于配置”理念,通过自动配置、起步依赖、嵌入式容器和Actuator四大特性,简化Spring应用的开发与部署,提升效率,降低门槛,成为现代Java开发的事实标准。
|
1月前
|
JavaScript Java Maven
【SpringBoot(二)】带你认识Yaml配置文件类型、SpringMVC的资源访问路径 和 静态资源配置的原理!
SpringBoot专栏第二章,从本章开始正式进入SpringBoot的WEB阶段开发,本章先带你认识yaml配置文件和资源的路径配置原理,以方便在后面的文章中打下基础
273 3
|
2月前
|
缓存 Java 应用服务中间件
Spring Boot配置优化:Tomcat+数据库+缓存+日志,全场景教程
本文详解Spring Boot十大核心配置优化技巧,涵盖Tomcat连接池、数据库连接池、Jackson时区、日志管理、缓存策略、异步线程池等关键配置,结合代码示例与通俗解释,助你轻松掌握高并发场景下的性能调优方法,适用于实际项目落地。
536 5
|
2月前
|
传感器 Java 数据库
探索Spring Boot的@Conditional注解的上下文配置
Spring Boot 的 `@Conditional` 注解可根据不同条件动态控制 Bean 的加载,提升应用的灵活性与可配置性。本文深入解析其用法与优势,并结合实例展示如何通过自定义条件类实现环境适配的智能配置。
182 0
探索Spring Boot的@Conditional注解的上下文配置
|
3月前
|
安全 算法 Java
在Spring Boot中应用Jasypt以加密配置信息。
通过以上步骤,可以在Spring Boot应用中有效地利用Jasypt对配置信息进行加密,这样即使配置文件被泄露,其中的敏感信息也不会直接暴露给攻击者。这是一种在不牺牲操作复杂度的情况下提升应用安全性的简便方法。
981 10
|
8月前
|
负载均衡 Dubbo Java
Spring Cloud Alibaba与Spring Cloud区别和联系?
Spring Cloud Alibaba与Spring Cloud区别和联系?
|
9月前
|
人工智能 SpringCloudAlibaba 自然语言处理
SpringCloud Alibaba AI整合DeepSeek落地AI项目实战
在现代软件开发领域,微服务架构因其灵活性、可扩展性和模块化特性而受到广泛欢迎。微服务架构通过将大型应用程序拆分为多个小型、独立的服务,每个服务运行在其独立的进程中,服务与服务间通过轻量级通信机制(通常是HTTP API)进行通信。这种架构模式有助于提升系统的可维护性、可扩展性和开发效率。
3027 2

热门文章

最新文章