Java Series - Four Ways of Spring Loading Configuration Items

The default spring version in this article is spring5

  • 1 Spring loads the yml file
  • 2 spring loads the properties file
  • 3 spring loads system disk files
  • 4 Spring loads the xml file
  • 5 Java reads properties configuration file based on InputStream

The spring framework loads configuration by default:

  • The files named application.yml and application.properties under resources applicationwill be loaded into the container Container by spring by default
    . If they have duplicate configuration items, they will be merged by default, and application.properties has a higher priority. The following LoadYmlTest.javaare Detailed explanation

Example:

# application.yml 
user:
  userName: ifredom_name
  age: 30  # 定义了属性 age
# application.properties 
# 也定义了属性 age
user.age=99
user.sex=2
package com.example.commonmybatisplus.config;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;

/**
 * 配置类
 * spring默认规则:自动将 resources 下名称为 application 的 yml 和 properties 文件加载为bean
 * 注意: 一定要有 get 和 set 方法,此处通过 @Data 注解注入
 */
@Data
@Configuration
@ConfigurationProperties(prefix = "user")
public class LoadPropertySourceYmlConfig {
    
    
    private String userName;
    private int sex;
    private int age;
}
package com.example.commonmybatisplus.PropertySourceTest;

import com.example.commonmybatisplus.config.LoadPropertySourceYmlConfig;
import com.example.commonmybatisplus.entity.UserEntity;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.core.env.Environment;

/**
 * 测试
 * 从结果可知: age的值为99,证明了 properties的优先级高于yml
 * 事实上,spring最早支持 properties 类型文件,后来才支持的yml,所以为了兼容
 * 一定是 properties > yml 优先级。
 * 即便将来又出现了 XXX.abc 文件
 * 那么为了兼容,永远时最早支持的优先级更高,也就是 properties > yml >abc
 */
@SpringBootTest
public class LoadYmlTest {
    
    
    @Autowired
    private LoadPropertySourceYmlConfig ymlConfig;

    @Test
    public void testYml() {
    
    

        String name = ymlConfig.getUserName();
        int sex = ymlConfig.getSex();
        int age = ymlConfig.getAge();

        System.out.println(name); // ifredom
        System.out.println(sex);  // 2
        System.out.println(age);  // 99
    }
}

1. Spring loads the yml file

The above has demonstrated how to load the default application.yml in the default way, but a better way is to separate our custom configuration into a separate file.
For example, when we develop WeChat public accounts and small programs, we need to use configuration. At this time, the configuration should be an additional file independently. (Here the demo is loaded as a List)

There are 3 steps in total:

  1. Create configuration filewechat-config.yml
  2. Define the configuration class LoadPropertySourceYmlConfigto load the data in yml (specify the loader of the configuration class) (because the default loader of the spring configuration class is the PropertiesLoader loader, we need to customize the yml loader. You can check the annotation @PropertySource source code yourself
    )
  3. Custom configuration class loader YamlSourceFactory, inheriting the default configuration class constructor provided by SpringDefaultPropertySourceFactory
  4. test

Example:

# main/resources/chat-config.yml

#微信小程序的appid
appid: app-xxx
#微信小程序的Secret
secret: secretxxx
#微信小程序消息服务器配置的token
token: token-xxx
#微信小程序消息服务器配置的EncodingAESKey
aesKey: aesKey-xxx

wx:
  configs:
    #微信小程序的appid
    - appid: app1
      #微信小程序的Secret
      secret: secret1
      #微信小程序消息服务器配置的token
      token: token1
      #微信小程序消息服务器配置的EncodingAESKey
      aesKey: aesKey1

      #微信小程序的appid
    - appid: appid2
      #微信小程序的Secret
      secret: secret2
      #微信小程序消息服务器配置的token
      token: token2
      #微信小程序消息服务器配置的EncodingAESKey
      aesKey: aesKey2

def-my-var1: 定义配置属性var1
def-my-var2: 定义配置属性var2

It should be noted here that the above configuration file is wx.configs, so in the configuration class, configs with the same name must also be used to receive

package com.example.commonmybatisplus.config;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.io.support.PropertySourceFactory;
import org.springframework.stereotype.Component;

import java.util.List;

/**
 * 注意:factory的值,为接下来自定义的加载器
 */
@Data
@Configuration
@PropertySource(value = "classpath:wechat-config.yml", factory = YamlSourceFactory.class)
@ConfigurationProperties(prefix = "wx")
public class LoadPropertySourceYmlConfig {
    
    

    private List<Config> configs;

    @Data
    public static class Config {
    
    
        private String appid;
        private String secret;
        private String token;
        private String aesKey;
    }

    private String appid;
    private String secret;
    private String token;
    private String aesKey;
}
// 自定义记载器
package com.example.commonmybatisplus.config;

import org.springframework.boot.env.YamlPropertySourceLoader;
import org.springframework.core.env.PropertySource;
import org.springframework.core.io.support.DefaultPropertySourceFactory;
import org.springframework.core.io.support.EncodedResource;

import java.io.IOException;
import java.util.List;

public class YamlSourceFactory extends DefaultPropertySourceFactory {
    
    
    @Override
    public PropertySource<?> createPropertySource(String name, EncodedResource resource) throws IOException {
    
    
        // 这里使用Yaml配置加载类来读取yml文件信息
        List<PropertySource<?>> sources = new YamlPropertySourceLoader().load(resource.getResource().getFilename(), resource.getResource());
        return sources.get(0);
    }
}

Test Results

package com.example.commonmybatisplus.PropertySourceTest;

import com.example.commonmybatisplus.config.LoadPropertySourceYmlConfig;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.List;

/**
 * @Author [email protected]
 * @Date 2022/6/15 10:40
 * @Version 1.0.0
 * @Description
 **/
@SpringBootTest
public class LoadYmlTest {
    
    
    @Autowired
    private LoadPropertySourceYmlConfig ymlConfig;

    @Test
    public void testYml() {
    
    

        String appidXXX = ymlConfig.getAppid();
        String secretXXX = ymlConfig.getSecret();
        System.out.println("单独的属性配置---appidXXX: " + appidXXX);
        System.out.println("单独的属性配置---secretXXX: " + secretXXX);

        // 以下演示 配置项作为 List
        List<LoadPropertySourceYmlConfig.Config> configs = ymlConfig.getConfigs();
        // 迭代 List 每一项
        for (LoadPropertySourceYmlConfig.Config config : configs) {
    
    
            System.out.println("属性作为List: " + config);
        }

        // 获取List种的某一项
        LoadPropertySourceYmlConfig.Config configFirst = configs.get(0);
        String appidFirst = configFirst.getAppid();
        System.out.println("List的第一项: " + configFirst);
        System.out.println("List的第一项的其中一个属性: " + appidFirst);

        LoadPropertySourceYmlConfig.Config configSecond = configs.get(1);
        String secretSecond = configSecond.getSecret();
        System.out.println("List的第二项: " + configSecond);
        System.out.println("List的第二项的其中一个属性: " + secretSecond);
    }
}

insert image description here

2. Spring loads the properties file

We already know from the previous step that spring uses the loader of the properties file by default. Therefore, we can construct the loader in one less step

  1. Create configuration filealibaba-config.properties
  2. Define the configuration class LoadPropertySourceConfigto load the data in yml
  3. test
# main/resources/alibaba-config.properties
ali-yun.username="ifredom"
ali-yun.password="123456"
ali-yun.blog="http://www.ifredom.com"
package com.example.commonmybatisplus.config;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;

@Data
@Configuration
@PropertySource("classpath:alibaba-config.properties")
@ConfigurationProperties(prefix = "aliyun")
public class LoadPropertySourceConfig {
    
    

    private String username;
    private String password;
    private String blog;
}

test:

package com.example.commonmybatisplus.PropertySourceTest;

import com.example.commonmybatisplus.config.LoadPropertySourceConfig;
import com.example.commonmybatisplus.config.LoadPropertySourceYmlConfig;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.List;

/**
 * @Author [email protected]
 * @Date 2022/6/15 10:40
 * @Version 1.0.0
 * @Description
 **/
@SpringBootTest
public class LoadYmlTest {
    
    
    @Autowired
    private LoadPropertySourceYmlConfig ymlConfig;

    @Autowired
    private LoadPropertySourceConfig propertyConfig;

    @Test
    public void testProperty() {
    
    
        String username = propertyConfig.getUsername();
        String password = propertyConfig.getPassword();
        String blog = propertyConfig.getBlog();
        System.out.println("单独的属性配置---username: " + username);
        System.out.println("单独的属性配置---password: " + password);
        System.out.println("单独的属性配置---blog: " + blog);
    }

    @Test
    public void testYml() {
    
    
    }
}

Careful students should have discovered that ali-yunthere is a short horizontal line in the middle defined in the configuration file. Why did it disappear when reading the properties?
This is because the Spring configuration loader class 空格, 下划线, 短横线, 大小写has done blank processing for such things, that is: configuration files are case-insensitive;
and underscores and dashes will also be ignored: user_name -> username, pass-word -> password. So you can name it freely

3. Spring loads the system disk (properties) file

Sometimes we need to load databases under other projects, but the configuration file is not under the current project path, so we need to specify the file path.

  • The disk path can be a relative path, an absolute path, or a variable specified by a system property value
    • Relative path, the file is in the application root directory:@PropertySource(value = {"file:project1.properties"})
    • Relative path, the file is in the application root directory:@PropertySource(value = {"file:./project1.properties"})
    • Absolute path, under the specified path:@PropertySource(value = {"file:D:\\project\\project1.properties"})
    • Variables are specified via system property values:@PropertySource(value = {"file:${user.dir}/project1.properties"})

Since loading the xml file also requires parsing the xml file, no explanation is given here. Just use the properties file as an example. Example:

#  位于D盘下的配置文件 D:\project1.properties
driverClassName=com.mysql.cj.jdbc.Driver
url="https://www.ifredom.com"
username="ifredom"
password="123456"

Since configuration files do not have a prefix, configuration classes must be @Value()mapped with

package com.example.commonmybatisplus.config;

import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;

@Data
@Configuration
@PropertySource(value = {
    
    "file:D:\\project1.properties"})
public class LoadDiskConfig {
    
    
    @Value("driverClassName")
    private String driverClassName;
    @Value("url")
    private String url;
    @Value("username")
    private String username;
    @Value("password")
    private String password;
}

/**
 * 测试
 */
@SpringBootTest
public class LoadYmlTest {
    
    
    @Autowired
    private LoadDiskConfig diskConfig;

    @Test
    public void testDisk() {
    
    
        String username = diskConfig.getUsername();
        String url = diskConfig.getUrl();
        System.out.println(username);
        System.out.println(url);
    }
}

4 Spring loads the xml file

  1. Create an xml file: applicationContext.xml, and define a bean in it
  2. ApplicationContextLoad and read xml files by

It is no longer recommended to use xml to read files, it is too complicated
Example:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd ">

    <bean id="blog" name="author" class="com.example.commonmybatisplus.entity.UserEntity">
        <property name="id" value="1"/>
        <property name="name" value="ifredom"/>
        <property name="age" value="30"/>
    </bean>
</beans>

@Data
public class UserEntity {
    
    
    private Long id;
    private String name;
    private int sex;
    private int age;
}


@SpringBootTest
public class LoadYmlTest {
    
    

    @Test
    public void testXml() {
    
    
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserEntity author = context.getBean("author", UserEntity.class);
        System.out.println(author.getName());
    }
}

5 Java reads properties configuration file based on InputStream

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.List;
import java.util.Properties;

@SpringBootTest
public class LoadYmlTest {
    
    

    @Test
    public void testInputStream() throws IOException {
    
    

        Properties properties = new Properties();
        // 使用InPutStream流读取properties文件
        BufferedReader bufferedReader = new BufferedReader(new FileReader("D:/project1.properties"));
        properties.load(bufferedReader);
        // 获取key对应的value值
        String driverClassName = properties.getProperty("driverClassName");
        String username = properties.getProperty("username");
        System.out.println(driverClassName);
        System.out.println(username);
    }
}

------ If the article is useful to you, thank you for moving your hands >>> Like| Favorite<<<

Guess you like

Origin blog.csdn.net/win7583362/article/details/125299127