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


    这里是weihubeats,觉得文章不错可以关注公众号小奏技术,文章首发。拒绝营销号,拒绝标题党

    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
    
    • 1
    @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");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

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

    然后调用接口就能获取到我们配置中的属性了
    在这里插入图片描述

    Spring Cloud自定义配置文件获取

    在了解了上面的原理及基本使用之后我们可以就可以自定义配置文件了。核心思路就是通过读取文件然后加载到PropertySource中去。
    而Spring Cloud刚好提供类这方面的扩展,Spring Cloud 提供了PropertySourceLocator接口供我们加载自定义配置成PropertySource
    在这里插入图片描述

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

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

    1. 引入依赖

    	<properties>
            <project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
            <maven.compiler.source>1.8maven.compiler.source>
            <maven.compiler.target>1.8maven.compiler.target>    
            <spring-cloud.version>2021.0.2spring-cloud.version>
            <spring-boot.version>2.7.0spring-boot.version>
    
        properties>
    
    		<dependency>
                <groupId>org.springframework.cloudgroupId>
                <artifactId>spring-cloud-contextartifactId>
            dependency>
            <dependency>
                <groupId>org.springframework.cloudgroupId>
                <artifactId>spring-cloud-starterartifactId>
            dependency>
            <dependency>
                <groupId>org.springframework.cloudgroupId>
                <artifactId>spring-cloud-starter-bootstrapartifactId>
            dependency>
            <dependency>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-starter-webartifactId>
            dependency>
    		
    		<dependencyManagement>
            <dependencies>
                <dependency>
                    <groupId>org.springframework.bootgroupId>
                    <artifactId>spring-boot-dependenciesartifactId>
                    <version>${spring-boot.version}version>
                    <type>pomtype>
                    <scope>importscope>
                dependency>
                <dependency>
                    <groupId>org.springframework.cloudgroupId>
                    <artifactId>spring-cloud-dependenciesartifactId>
                    <version>${spring-cloud.version}version>
                    <type>pomtype>
                    <scope>importscope>
                dependency>      
            dependencies>
    
        dependencyManagement>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45

    注意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);
    	}
    	
    	
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    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());
    			}
    		}
    	}
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75

    2.3 自定义配置Bean config

    @Configuration(proxyBeanMethods = false)
    public class ZouConfiguration {
    
    	@Bean
    	public ZouJsonPropertySourceLocator zouJsonPropertySourceLocator(){
    		return new ZouJsonPropertySourceLocator();
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    2.4 定义BootstrapConfiguration配置

    resources 添加spring.factories配置文件

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

    3. 测试

    这里简单定义一个我们自己的配置文件zou.json
    在这里插入图片描述

    {
      "name": "xiaozou"
    }
    
    • 1
    • 2
    • 3

    定义一个测试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");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    在这里插入图片描述
    可以看到我们自定义配置是生效了的

    总结

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

  • 相关阅读:
    python-(6-4-3)爬虫---re解析案例
    Pytorch实战教程(二)-PyTorch基础
    智慧公厕是智慧城市公共厕所形态的新一代技术支撑
    21.过拟合和欠拟合示例
    数据治理的数字画像
    机器人技术概述_1.机器人的概念及定义和发展历程
    应该继续学习编程,还是学数控?
    RabbitMQ的六种工作模式
    备受以太坊基金会青睐的 Hexlink,构建亿级用户涌入 Web3的入口
    【axios三部曲】一、使用axios
  • 原文地址:https://blog.csdn.net/qq_42651904/article/details/125735915