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/

springboot配置文件自定义为json格式_第1张图片

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

网址

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

springboot配置文件自定义为json格式_第2张图片

推荐使用 yml 文件格式

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

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

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

springboot解析配置文件源码解析

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

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

  • 自动装配

  • 内置服务器 tomcat

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

加载配置文件的方法入口

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

加载配置文件解析器

ConfigFileApplicationListener.java

springboot配置文件自定义为json格式_第3张图片

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

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

springboot配置文件自定义为json格式_第4张图片

springboot配置文件自定义为json格式_第5张图片

PropertySourceLoader.java 接口

public interface PropertySourceLoader {

    /**
    获取文件的扩展名 , 即获取配置文件的后缀名
    比如 yaml , yml , properties
    */
	String[] getFileExtensions();

	/**
	加载配置文件属性到 PropertySouce
	/*
	List> load(String name, Resource resource) throws IOException;

}

查看 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();
	}

}

自定义实现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));
    }
}

springboot SPI机制自定义解析类

META-INF/spring.factories

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

定义application.json文件

{
  "server.port":4444,
  "user.userName": "测试是否会中文乱码",
  "user.age": 18
}

测试

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

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

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

@Component
public class UserTestValue {
    @Value("${user.userName}")
    public String userName;
    @Value("${user.age}")
    public String age;
}

测试获取属性

@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);
    }
}

控制台打印

测试 @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)

你可能感兴趣的:(框架源码和设计模式,springboot,spring,boot,json,java)