原文地址:https://blog.csdn.net/feiyu8607/article/details/8282893

Spring中PropertyPlaceholderConfigurer这个类,它是用来解析Java Properties属性文件值,并提供在spring配置期间替换使用属性值。接下来让我们逐渐的深入其配置。

基本的使用方法是:

<bean id="propertyConfigurerForAnalysis"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>classpath:/spring/include/dbQuery.properties</value>
</property>
</bean>

其中classpath是引用src目录下的文件写法。

当存在多个Properties文件时,配置就需使用locations了:(2)

<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:/spring/include/jdbc-parms.properties</value>
<value>classpath:/spring/include/base-config.properties</value>
</list>
</property>
</bean>  

接下来我们要使用多个PropertyPlaceholderConfigurer来分散配置,达到整合多工程下的多个分散的Properties文件,其配置如下:(3)

<bean id="propertyConfigurerForProject1"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="order" value="1" />
<property name="ignoreUnresolvablePlaceholders" value="true" />
<property name="locations">
<list>
<value>classpath:/spring/include/dbQuery.properties</value>
</list>
</property>
</bean> <bean id="propertyConfigurerForProject2"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="order" value="2" />
<property name="ignoreUnresolvablePlaceholders" value="true" />
<property name="locations">
<list>
<value>classpath:/spring/include/jdbc-parms.properties</value>
<value>classpath:/spring/include/base-config.properties</value>
</list>
</property>
</bean>

其中order属性代表其加载的顺序,如果没有设置就按照加载xml文件时的顺序,而ignoreUnresolvablePlaceholders为是否忽略不可解析的Placeholder,如果配置了多个PropertyPlaceholderConfigurer,则该属性必须设置且为true,否则propertyConfigurerForProject2的properties文件不会被加载.

至此你已经了解到了如何使用PropertyPlaceholderConfigurer,如何使用多个Properties文件,以及如何配置多个PropertyPlaceholderConfigurer来分解工程中分散的Properties文件。至于PropertyPlaceholderConfigurer还有更多的扩展应用,如属性文件加密解密等方法将在之后的博文中续写。

注意事项:
(1)如果上面的dbQuery.properties与jdbc-parms.properties文件中有相同的参数配置名称,dbQuery.properties中配置的参数值不会被后面的覆盖;
(2)如果jdbc-parms.properties,base-config.properties彼此有相同参数名配置,jdbc-parms.properties中的配置的值会被覆盖;

自定义扩展PropertyPlaceholderConfigurer实现

例如:配置文件的路径,需要动态确定的,就需要自己扩展PropertyPlaceholderConfigurer的实现,自己获取文件路径,load properties文件,然后将load后的properties加入PropertyPlaceholderConfigurer

package com.common.spring.ext;

import java.util.Properties;
import java.util.Set; import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer; import com.common.exception.ApplicationException;
import com.common.util.GlobalProperties;
import com.common.util.PropertiesUtil; public class GollfPropertyPlaceholderConfigurer extends PropertyPlaceholderConfigurer { public void setGollfPropFiles(Set<String> gollfPropFiles) {
String propPath = GlobalProperties.getProperty(GlobalProperties.PROPERTIES_FOLDER_PATH); //通过其他配置获取路径
String fileSeparator = System.getProperty("file.separator"); Properties properties = new Properties();
for (String gollfPropFile : gollfPropFiles) { String nodeName = System.getProperty("weblogic.Name");
gollfPropFile = gollfPropFile.replaceAll("\\[NODE_NAME\\]", nodeName); //NODE_NAME 是根据不同weblogic server确定 String file = propPath + fileSeparator + gollfPropFile; try {
logger.info("Loading properites file from " + file);
Properties prop = PropertiesUtil.loadProperties(file); //返回properties文件
logger.debug("Properties -> " + prop);
if(prop != null) {
properties.putAll(prop);
}
} catch (Exception e) {
logger.fatal(new ApplicationException("Properties file " + gollfPropFile +
" cannot be found. All related functionalities may be unavailable", e, true));
}
} this.setProperties(properties); //关键方法,调用的PropertyPlaceholderConfigurer中的方法,
//通过这个方法将自定义加载的properties文件加入spring中
} }
 <bean id="auditJmsProperties"
class="com.common.spring.ext.GollfPropertyPlaceholderConfigurer">
<property name="gollfPropFiles">
<set>
<value>[NODE_NAME]_jms.properties</value>
</set>
</property>
</bean>

PropertyPlaceholderConfigurer中加载properties文件时,实际调用的:org.springframework.core.io.support.PropertiesLoaderSupport中的mergeProperties

Spring源码

protected Properties mergeProperties() throws IOException {
Properties result = new Properties(); if (this.localOverride) {
// Load properties from file upfront, to let local properties override.
loadProperties(result);
} if (this.localProperties != null) {
for (Properties localProp : this.localProperties) {
//将用户自定义加载的属性值,与spring加载的合并
CollectionUtils.mergePropertiesIntoMap(localProp, result);
}
} if (!this.localOverride) {
// Load properties from file afterwards, to let those properties override.
loadProperties(result);
} return result;
}

将多个properties文件中的配置加载以后合并成一个Properties对象返回.
上面的this.setProperties(properties)方法,就是设置localProperties的引用,localProperties不为空的话,将用户自定义加载的properties属性合并到Spring加载的result Properties对象中
localOverride参数:为true的话,表示用户自定义加载的属性值覆盖spring系统加载的,如果同名的话.

自定义使用注意:用户自定义方法的调用务必在spring 初始化调用PropertyPlaceholderConfigurer的mergeProperties()方法之前调用,否则配置文件就没有合并.一般就set值的时候调用.

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

spring提供了一个PropertyPlaceholdConfigurer的 beanFactory后置处理器。可以将Bean配置的部分内容放到 属性文件 中,可以在Bean配置文件里使用形式为 ${var}的变量,PropertyPlaceholdConfigurer从属性文件里加载属性,并使用这些属性来替换变量。

以配置数据库连接字符串信息为例,配置如下:

<!-- 引入配置文件 -->
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:jdbc.properties" />
</bean> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="${driver}" />
<property name="url" value="${url}" />
<property name="username" value="${username}" />
<property name="password" value="${password}" />
<!-- 初始化连接大小 -->
<property name="initialSize" value="${initialSize}"></property>
<!-- 连接池最大数量 -->
<property name="maxActive" value="${maxActive}"></property>
<!-- 连接池最大空闲 -->
<property name="maxIdle" value="${maxIdle}"></property>
<!-- 连接池最小空闲 -->
<property name="minIdle" value="${minIdle}"></property>
<!-- 获取连接最大等待时间 -->
<property name="maxWait" value="${maxWait}"></property>
</bean>

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

使用spring的PropertyPlaceholderConfigurer加密properties文件中的属性

一、背景

处于安全考虑需要对.properties中的数据库用户名与密码等敏感数据进行加密。项目中使用了Spring3框架统一加载属性文件,所以最好可以干扰这个加载过程来实现对.properties文件中的部分属性进行加密。

属性文件中的属性最初始时敏感属性值可以为明文,程序第一次执行后自动加密明文为密文。

二、问题分析

  1. 扩展PropertyPlaceholderConfigurer最好的方式就是编写一个继承该类的子类。
  2. 外部设置locations时,记录全部locations信息,为加密文件保留属性文件列表。重写setLocations与setLocation方法(在父类中locations私有)
  3. 寻找一个读取属性文件属性的环节,检测敏感属性加密情况。对有已有加密特征的敏感属性进行解密。重写convertProperty方法来实现。
  4. 属性文件第一次加载完毕后,立即对属性文件中的明文信息进行加密。重写postProcessBeanFactory方式来实现。
三、代码实现
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<!-- 加密 -->
<property name="locations">
<list>
<value>classpath:db.properties</value>
</list>
</property>
<!-- 声明需要加密的属性 -->
<property name="encryptedProps">
<set>
<value>db.jdbc.username</value>
<value>db.jdbc.password</value>
<value>db.jdbc.url</value>
</set>
</property>
</bean>
package com.sgfm.test;

import com.sgfm.base.des.DESEncryptUtil;

public class Test {
private static final String SEC_KEY = "@^_^123aBcZ*"; // 主密钥
private static final String ENCRYPTED_PREFIX = "{";// 默认加密前缀
private static final String ENCRYPTED_SUFFIX = "}";// 默认加密后缀 public static void main(String[] args) throws Exception {
DESEncryptUtil dec = new DESEncryptUtil();
String encryptStr = dec.encrypt("tcp://192.168.10.242:61616", SEC_KEY);// 加密
String decryptStr = dec.decrypt("1B7328C79D9D5BC37E0636947EFEECD6E1459B4260497E31000754134655A350", SEC_KEY);// 解密 System.out.println("加密内容:" + encryptStr);
System.out.println("解密内容:" + decryptStr);
}
}
db.jdbc.driver=com.mysql.jdbc.Driver
db.jdbc.url=jdbc:mysql://localhost:3306/noah?useUnicode=true&characterEncoding=utf8
db.jdbc.username=noah
db.jdbc.password=noah
db.jdbc.driver=com.mysql.jdbc.Driver
db.jdbc.url=Encrypted:{e5ShuhQjzDZrkqoVdaO6XNQrTqCPIWv8i_VR4zaK28BrmWS_ocagv3weYNdr0WwI}
db.jdbc.username=Encrypted:{z5aneQi_h4mk4LEqhjZU-A}
db.jdbc.password=Encrypted:{v09a0SrOGbw-_DxZKieu5w}

最新文章

  1. ViewStateMode vs EnableViewState
  2. 【干货】如何通过OPC自定义接口来实现客户端数据的读取?
  3. Ugly Number
  4. windows7安装phpnow Apache非管理员权限不能操作Windows NT服务的解决方法
  5. malloc、calloc、realloc的区别
  6. lldb
  7. Call to undefined function pg_
  8. 关于 firefox 无法在 passport.csdn.net 找到该服务器
  9. Qt多工程多目录的编译案例
  10. JAVA-代理学习一之JDK实现
  11. 聊天系统Demo,增加Silverlight客户端(附源码)-- ESFramework 4.0 快速上手(09)
  12. Android学习笔记之Intent(2)
  13. 5.IP选路,动态选路
  14. java 完全二叉树的构建与四种遍历方法
  15. js实现浏览器添加收藏功能
  16. TCP层的分段和IP层的分片之间的关系 &amp; MTU和MSS之间的关系 (转载)
  17. 【js】使用javascript 实现静态网页分页效果
  18. EF There is already an open DataReader associated with this Command
  19. centos/7下安装mysql5.7
  20. grok正则

热门文章

  1. 深入理解JavaScript中的继承
  2. python + mysql 实现创建数据表
  3. spring-3-spring整合mybatis
  4. jenkins资源下载地址(软件、插件等)
  5. redis的单线程
  6. (python函数03)zip()函数
  7. js学习笔记之自调用函数、闭包、原型链
  8. Supervisord 远程命令执行漏洞(CVE-2017-11610)
  9. 媒体应用视频超分AI神器!360P视频一键转换HD
  10. 从零开始学习JAVA(入门基础)