• springboot配置文件自定义为json格式


    springboot配置文件自定义为json格式

    草稿

    springboot默认的配置文件格式

    ​ properties

    ​ yaml

    springboot-cli 默认生成脚手架项目默认配置文件格式是 properties

    源码解析

    ConfigFile…Listener

    ​ 两种配置文件的解析类

    ​ 选择策略

    自定义实现思路

    ​ 1.实现接口

    ​ 2.自动装配 SPI 机制

    springboot配置文件回顾

    springboot配置文件默认支持两种文件格式 , ymlproperties

    springboot-cli 创建项目默认使用的是 (application.properties) properties格式的文件

    网址:

    https://start.spring.io/

    image-20221027121301519

    另外介绍一个网站也可以生成 springboot 脚手架项目

    网址

    https://start.aliyun.com/bootstrap.html

    image-20221027121436557

    推荐使用 yml 文件格式

    1.因为很多开源项目都是使用的 yml 格式

    2.好多开源的中间件配置文件也是使用的 yml 格式

    3.yml 比 properties 看上去更简洁 , 更有层次感

    springboot解析配置文件源码解析

    我认为 springboot 对于 spring 做的增强有一下几点:

    • 增加了很多监听器以及监听事件

    • 自动装配

    • 内置服务器 tomcat

    配置文件解析就是基于 监听器 实现的

    加载配置文件的方法入口

    public ConfigurableApplicationContext run(String... args) {
    		...
                // 加载配置文件的方法入口
    			ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
    			....
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    加载配置文件解析器

    ConfigFileApplicationListener.java

    image-20221027123152290

    加载默认的两个文件解析器

    文件解析器通过 SPI 机制 , 在 spring-factories 文件中

    image-20221027123535596

    image-20221027123715172

    PropertySourceLoader.java 接口

    public interface PropertySourceLoader {
    
        /**
        获取文件的扩展名 , 即获取配置文件的后缀名
        比如 yaml , yml , properties
        */
    	String[] getFileExtensions();
    
    	/**
    	加载配置文件属性到 PropertySouce
    	/*
    	List> load(String name, Resource resource) throws IOException;
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    查看 PropertiesPropertySourceLoader.java, 并解释说明方法

    public class PropertiesPropertySourceLoader implements PropertySourceLoader {
    
    	private static final String XML_FILE_EXTENSION = ".xml";
    
        /**
        加载 properties 格式的配置文件
        */
    	@Override
    	public String[] getFileExtensions() {
    		return new String[] { "properties", "xml" };
    	}
    
        /**
        加载配置文件内容
        */
    	@Override
    	public List<PropertySource<?>> load(String name, Resource resource) throws IOException {
    		Map<String, ?> properties = loadProperties(resource);
    		if (properties.isEmpty()) {
    			return Collections.emptyList();
    		}
    		return Collections
    				.singletonList(new OriginTrackedMapPropertySource(name, Collections.unmodifiableMap(properties), true));
    	}
    
    	@SuppressWarnings({ "unchecked", "rawtypes" })
    	private Map<String, ?> loadProperties(Resource resource) throws IOException {
    		String filename = resource.getFilename();
    		if (filename != null && filename.endsWith(XML_FILE_EXTENSION)) {
    			return (Map) PropertiesLoaderUtils.loadProperties(resource);
    		}
    		return new OriginTrackedPropertiesLoader(resource).load();
    	}
    
    }
    
    • 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

    自定义实现json格式配置文件解析器

    实现 PropertySourceLoader 接口

    JsonPropertySourceLoader.java

    package com.example.config;
    
    
    import com.alibaba.fastjson2.JSON;
    import com.alibaba.fastjson2.JSONObject;
    import org.apache.commons.logging.Log;
    import org.apache.commons.logging.LogFactory;
    import org.springframework.boot.env.PropertySourceLoader;
    import org.springframework.core.env.MapPropertySource;
    import org.springframework.core.env.PropertySource;
    import org.springframework.core.io.Resource;
    
    import java.io.IOException;
    import java.nio.ByteBuffer;
    import java.nio.channels.ReadableByteChannel;
    import java.util.Collections;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    public class JsonPropertySourceLoader implements PropertySourceLoader {
    
        private static final Log logger = LogFactory.getLog(JsonPropertySourceLoader.class);
        
        @Override
        public String[] getFileExtensions() {
    //这个方法表明这个类支持解析以json结尾的配置文件
            return new String[]{"json"};
        }
    
        @Override
        public List<PropertySource<?>> load(String name, Resource resource) throws IOException {
    
            ReadableByteChannel readableByteChannel = resource.readableChannel();
    
            ByteBuffer byteBuffer = ByteBuffer.allocate((int) resource.contentLength());
    
            //将文件内容读到 ByteBuffer 中
            readableByteChannel.read(byteBuffer);
            //将读出来的字节转换成字符串
            String content = new String(byteBuffer.array());
            // 将字符串转换成 JSONObject
            JSONObject jsonObject = JSON.parseObject(content);
    
            Map<String, Object> map = new HashMap<>(jsonObject.size());
            //将 json 的键值对读出来,放入到 map 中
            for (String key : jsonObject.keySet()) {
                map.put(key, jsonObject.getString(key));
            }
            logger.info("自定义实现 PropertySourceLoader 接口 , 重写 load 方法");
            return Collections.singletonList(new MapPropertySource("jsonPropertySource", map));
        }
    }
    
    
    • 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

    springboot SPI机制自定义解析类

    META-INF/spring.factories

    org.springframework.boot.env.PropertySourceLoader=\
    com.example.config.JsonPropertySourceLoader
    
    • 1
    • 2

    定义application.json文件

    {
      "server.port":4444,
      "user.userName": "测试是否会中文乱码",
      "user.age": 18
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    测试

    • 测试springboot自动装配的属性是否生效

    • 测试自定义属性注入是否生效

    定义自定义属性注入测试类

    @Component
    public class UserTestValue {
        @Value("${user.userName}")
        public String userName;
        @Value("${user.age}")
        public String age;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    测试获取属性

    @SpringBootApplication
    public class SpringbootDemoApplication {
    
        public static void main(String[] args) {
            ApplicationContext ac = SpringApplication.run(SpringbootDemoApplication.class, args);
            UserTestValue userTestValue = ac.getBean(UserTestValue.class);
            /**
             * 测试 @Value 注解
             * 不需要 javabean 实现 set/get 方法
             */
            System.out.println("测试 @Value 注解**********************************");
            System.out.println("user.userName = " + userTestValue.userName);
            System.out.println("user.age = " + userTestValue.age);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    控制台打印

    测试 @Value 注解**********************************
    user.userName = 测试是否会中文乱码
    user.age = 18

    ****************************");
    System.out.println("user.userName = " + userTestValue.userName);
    System.out.println("user.age = " + userTestValue.age);
    }
    }

    
    控制台打印
    
    > 测试 @Value 注解**********************************
    > user.userName = 测试是否会中文乱码
    > user.age = 18
    
    ![image-20221027142032730](https://img-blog.csdnimg.cn/img_convert/4933ef4c7ecdac5c6a5443358aa80496.png)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
  • 相关阅读:
    “罪魁祸首”已找到,微软回应修改 MIT 开源项目作者版权声明
    Hadoop3.0大数据处理学习2(HDFS)
    前端如何处理后端一次性传来的10w条数据
    JVM 堆外内存查看方法
    加拿大海运专线怎么选?加拿大海运专线有哪些费用
    opencv 没办法控制焦距怎么办?来试一下 pyuvc 吧
    【Three.js】第十二章 Materials 材质
    NLP之基于Seq2Seq的单词翻译
    c++11 多线程支持 条件变量(condition_variable)(一)
    项目管理到底管的是什么?
  • 原文地址:https://blog.csdn.net/shaoming314/article/details/127551665