Java系列 - Spring 加载配置项的四种方式

Java系列 - Spring 加载配置项的四种方式

本文默认 spring 版本是 spring5

1 spring 加载 yml 文件2 spring 加载 properties 文件3 spring 加载 系统磁盘 文件4 spring 加载 xml 文件5 Java 基于 InputStream 读取 properties 配置文件

spring框架默认加载配置:

resources 下的文件名称为application的 application.yml 以及 application.properties, 默认会被spring加载到容器 Container

中,如果他们有重复的配置项,会被默认合并,并且 application.properties优先级更高. 下面的 LoadYmlTest.java 有详细解释

示例:

# 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 加载 yml 文件

上面已经通过默认的方式演示了如何加载默认的application.yml,但是更好的写法是,将我们自定义的配置独立为一个单独的文件。

比如我们开发微信公众号,小程序开发时,就需要用到配置,此时的配置就应该独立为一个额外的文件。(此处将演示加载为 List)

一共有3步:

创建配置文件 wechat-config.yml定义配置类 LoadPropertySourceYmlConfig,用来加载yml中的数据 (指定配置类的加载器) (因为 spring 配置类的默认加载器是 PropertiesLoader加载器,所以我们需要自定义 yml

加载器。可以自行查看注解 @PropertySource 源码)自定义配置类加载器 YamlSourceFactory,继承Spring提供的默认配置类构造器 DefaultPropertySourceFactory测试

示例:

# 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

这里需要注意,在上面的配置文件中是 wx.configs, 因此在配置类中,也必须用同名的 configs 来接收

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 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> sources = new YamlPropertySourceLoader().load(resource.getResource().getFilename(), resource.getResource());

return sources.get(0);

}

}

测试结果

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 ifredomvip@gmail.com

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

}

}

2. spring 加载 properties 文件

从上一步我们已经知道了, spring 默认使用 properties 文件的加载器。因此,我们可以少一步构造加载器

创建配置文件 alibaba-config.properties定义配置类 LoadPropertySourceConfig,用来加载yml中的数据测试

# 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;

}

测试:

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 ifredomvip@gmail.com

* @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() {

}

}

细心的同学应该发现了,在配置文件中定义的是ali-yun中间明明有一个短横线,读取属性的时候怎么没了?

这是因为 Spring 配置加载器类对诸如 空格, 下划线, 短横线, 大小写都做了替空处理,也就是:配置文件是不分大小写的;

并且 下划线,短横线也会忽略: user_name -> username, pass-word -> password.因此取名你可以很随意

3. spring 加载 系统磁盘 (properties)文件

有时候我们会需要加载其他项目下的数据库,而配置文件并不在当前项目路劲下,因此需要指定文件路径。

磁盘路径可以是相对路径,绝对路径,也可以通过系统属性值指定变量

相对路径,文件在应用根目录下:@PropertySource(value = {"file:project1.properties"})

相对路径,文件在应用根目录下:@PropertySource(value = {"file:./project1.properties"})

绝对路径,在指定的路径下:@PropertySource(value = {"file:D:\\project\\project1.properties"})

通过系统属性值指定变量:@PropertySource(value = {"file:${user.dir}/project1.properties"})

由于加载xml文件还需要对xml文件进行解析,此处不做讲解。仅仅使用 properties 文件做例子。 示例:

# 位于D盘下的配置文件 D:\project1.properties

driverClassName=com.mysql.cj.jdbc.Driver

url="https://www.ifredom.com"

username="ifredom"

password="123456"

由于配置文件没有前缀,因此 配置类 必须使用@Value()进行映射

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 加载 xml 文件

创建一个xml文件:applicationContext.xml,并在其中定义一个bean通过 ApplicationContext 来加载读取xml文件

不再推介使用 xml 来读取文件了,过于复杂

示例:

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 ">

@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 基于 InputStream 读取 properties 配置文件

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

}

}

------ 如果文章对你有用,感谢动动小手 >>>点赞 | 收藏 <<<

相关推荐