zoukankan      html  css  js  c++  java
  • Spring PropertyPlaceholderConfigurer 自定义扩展

    原文地址: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}
  • 相关阅读:
    sql小练习
    登录测试点
    游戏签到
    移动端和pc端微信加入群聊
    小说
    微信语言输入
    linux tar压缩解压缩命令详解
    linux使用nginx配置web服务器
    FFmpeg 视频处理入门教程
    Git学习
  • 原文地址:https://www.cnblogs.com/daxiong225/p/13943738.html
Copyright © 2011-2022 走看看