本文主要讲述spring如何读取外部配置文件比如properties。

【1】PropertyPlaceholderConfigurer

① 读取方式

在xml配置文件里配置 Bean 时, 有时需要在 Bean 的配置里混入系统部署的细节信息(例如: 文件路径, 数据源配置信息等),而这些部署细节实际上需要和 Bean 配置相分离。

Spring 提供了一个 PropertyPlaceholderConfigurer 的 BeanFactory 后置处理器, 这个处理器允许用户将 Bean 配置的部分内容外移到属性文件中。

可以在 Bean 配置文件里使用形式为 ${var} 的变量:

  • PropertyPlaceholderConfigurer 从属性文件里加载属性, 并使用这些属性来替换变量;
  • Spring 还允许在xml文件中使用 ${propName},以实现属性之间的相互引用。

如这里读取外部的jdbc.properties。

Spring2.0的配置方式

<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<!--这个是为了防止中文乱码-->
<property name="fileEncoding" value="UTF-8"/>
<property name="locations">
<!--use list to get more inf-->
<list>
<value>classpath:jdbc.properties</value>
</list>
</property>
</bean>

Spring2.5以后的简写配置方式

<context:property-placeholder location="classpath:jdbc.properties"/>

② ​​PropertyPlaceholderConfigurer​

该类最终父类为PropertiesLoaderSupport,主要属性如下所示:

public abstract class PropertiesLoaderSupport {

/** Logger available to subclasses */
protected final Log logger = LogFactory.getLog(getClass());

protected Properties[] localProperties;

protected boolean localOverride = false;

private Resource[] locations;

private boolean ignoreResourceNotFound = false;

private String fileEncoding;

private PropertiesPersister propertiesPersister = new DefaultPropertiesPersister();
//...
}

支持使用​​${propertyName}​​引用properties等配置文件中的属性

<bean id="datasource" class="com.mchange.v2.c3p0.ComboPooledDataSource"  >
<property name="user" value="${user}"></property>
<property name="password" value="${password}"></property>
<property name="jdbcUrl" value="${jdbcUrl}"></property>
<property name="driverClass" value="${driverClass}"></property>
</bean>

Spring 还允许在属性文件中使用 ${propName},以实现属性之间的相互引用。


【2】Java读取properties文件

① 基于ClassLoder读取配置文件

注意:该方式只能读取类路径下的配置文件。

Properties properties = new Properties();
// 使用ClassLoader加载properties配置文件生成对应的输入流
InputStream in = PropertiesMain.class.getClassLoader().getResourceAsStream("jdbc.properties");
// 使用properties对象加载输入流
properties.load(in);
//获取key对应的value值
properties.getProperty(String key);

② 基于 InputStream 读取配置文件

该方式的优点在于可以读取任意路径下的配置文件,缺点在于一般你需要指定一个绝对路径。

Properties properties = new Properties();
// 使用InPutStream流读取properties文件
BufferedReader bufferedReader = new BufferedReader(new FileReader("E:/jdbc.properties"));
properties.load(bufferedReader);
// 获取key对应的value值
properties.getProperty(String key);

③ 通过 java.util.ResourceBundle 类来读取

通过 ​​ResourceBundle.getBundle()​​ 静态方法来获取(ResourceBundle是一个抽象类),这种方式来获取properties属性文件不需要加.properties后缀名,只需要文件名即可

//假设jdbc.properties在类根路径下-src根目录下
ResourceBundle resource = ResourceBundle.getBundle("jdbc");
String value= resource.getString("key");

通过这种方式读取值的时候中文会乱码,解决方案有两种。

  • 手动进行解码编码,如下所示:
new String(rb.getString("kefureply_festival").getBytes("ISO-8859-1"),"GBK")
  • properties中的中文进行Unicode转码,如下所示:
a=/u7535/u89c6/u673a

④ 工具类PropertiesUtil

package com.jane.cutover.common;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.util.Properties;

/**
* Created by jianggc at 2022/2/16.
*/
public class PropertiesUtil {

private static final Logger logger= LoggerFactory.getLogger(PropertiesUtil.class);

/**
* 根据文件完整路径,从XXX.properties中读取某个key
* @param filePath
* @param key
* @return
*/
public static String readWholePath(String filePath,String key){
try {
Properties properties = new Properties();
// 使用InPutStream流读取properties文件
BufferedReader bufferedReader = new BufferedReader(new FileReader(filePath));
properties.load(bufferedReader);
// 获取key对应的value值
return properties.getProperty( key);
} catch (Exception e) {
logger.error(e.getMessage(),e);
}
return null;
}

/**
* 根据文件输入流,读取某个key
* @param inputStream
* @param key
* @return
*/
public static String readByInputStream(InputStream inputStream, String key){
try {
Properties properties = new Properties();
// 使用InPutStream流读取properties文件
InputStreamReader streamReader = new InputStreamReader(inputStream,"UTF-8");
BufferedReader bufferedReader = new BufferedReader(streamReader);
properties.load(bufferedReader);
// 获取key对应的value值
return properties.getProperty( key);
} catch (Exception e) {
logger.error(e.getMessage(),e);
}
return null;
}

/**
* 读取classpath下的某个XXXX.properties的某个key
* @param fileName application.properties
* @param key
* @return
*/
public static String readClassPathFile(String fileName, String key){
try {
Properties properties = new Properties();
// 使用InPutStream流读取properties文件
InputStream inputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream(fileName);
InputStreamReader streamReader = new InputStreamReader(inputStream,"UTF-8");
BufferedReader bufferedReader = new BufferedReader(streamReader);
properties.load(bufferedReader);
// 获取key对应的value值
return properties.getProperty( key);
} catch (Exception e) {
logger.error(e.getMessage(),e);
}
return null;
}

public static void main(String[] args){

InputStream stream =Thread.currentThread().getContextClassLoader().getResourceAsStream("application.properties");
String byInputStream = readByInputStream(stream, "com.jane.file");
System.out.println("stream---com.jane.file--"+byInputStream);

String readClassPathFile = readClassPathFile("application.properties", "com.jane.file");
System.out.println("application.properties---readClassPathFile--"+byInputStream);
}

}

参考博文:项目不同位置文件读取