spring-使用外部属性文件及加密解密文件属性

本文介绍Spring框架中如何使用属性文件进行配置,包括PropertyPlaceholderConfigurer的基本使用、属性文件的加密及解密方法、属性文件间的相互引用及引用Bean属性值的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

s1.使用PropertyPlaceholderConfiguer属性文件

1.jdbc.properties文件

driverClassName=com.mysql.jdbc.Driver
url:jdbc:mysql://localhost:3306/testdb
username=root
password=123

2.xml文件引入属性文件

<!-- 引入配置文件 -->
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfiguer"
    p:location="class:jdbc.preperties"
    p:fileEncoding="utf-8"/>

<!-- 使用属性值 -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"
    p:driverClassName="${drverClassName}"
    p:url="${url}"
    p:username="${userName}"
    p:password="${password}"/>

3.PropertyPlaceholderConfigurer其他属性

  • locations:配置多个配置文件(配置 list 一样)
  • fileEncoding:编码格式
  • order:如歌配置多个PropertyPlaceholderConfigurer,通过该属性指定优先顺序
  • placeholderPrefix:指定占位符前缀,默认为“${”
  • placeholderSuffix:占位符后缀,默认为“}”
<bean id="propertyPlaceholderConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">     
    <property name="locations">     
        <list>     
             <value>classpath:/opt/demo/config/demo-db.properties</value> 
             <value>classpath:/opt/demo/config/demo-db2.properties</value> 
        </list>     
    </property>     
</bean>  

4.使用”<”context:property-placeholder”>”引入属性文件

//这种方式比较优雅,但如果想要配置日他额外高级属性,如属性加密,使用数据库保存配置信息等,必须使用扩展的PropertyPlaceholderConfigurer类并使用bean配置方式
<context:property-placeholder location="class:jdbc.properties"/>

//引入多个配置文件 逗号分隔
<context:property-placeholder 
    location="classpath:constants.properties ,
              classpath:constants_new.properties"
    fileEncoding="utf-8"
/>

5.在基于注解的java类配置中引用属性

@Component
public class Test{
//@Value注解可以为Bean注入一个字面量,也可通过@Value("#{proName}")形式注入值
    @Value("com.mysql.jdbc.Driver")
    private String driverClassName;

    @Value("${url}")
    private String url;
}

s2.对属性文件加密

PropertyPlaceholderConfigurer继承自PropertyResourceConfigurer类,后者有几个protected方法用于对属性使用之前对属性列表中的属性进行转换。

  • void convertProperties(Properties props):属性文件中的所有属性值都封装在props中,覆盖此方法,可以对所有属性值进行转换
  • String convertProperty(String propertyName,String property Value):在加载属性文件并读取文件属性值时,都会调用此方法,进行转换处理
  • String convertPropertyValue(String orginalValue):和上一个方法类似,只不过没有传入属性名

1.加密解密工具类(DES对称加密)

package com.gdy.util;


import lombok.extern.log4j.Log4j;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import java.security.Key;
import java.security.SecureRandom;

/**
 * des 加解密方法
 */
@Log4j
public class DESUtils {

    private static Key key;

    /**
     * 对str进行DES加密
     * @param str  加密的字符串
     * @param key_str 加密的秘钥
     * @return 加密后的字符串
     */
    public static String getEncryptString(String str,String key_str) {
        BASE64Encoder base64en = new BASE64Encoder();
        try {
            setKey2(key_str);
            byte[] strBytes = str.getBytes("UTF8");
            Cipher cipher = Cipher.getInstance("DES");
            cipher.init(Cipher.ENCRYPT_MODE, key);
            byte[] encryptStrBytes = cipher.doFinal(strBytes);
            return base64en.encode(encryptStrBytes);
        } catch (Exception e) {
            log.warn("字符串des加密失败:"+e);
            throw new RuntimeException(e);
        }
    }

    /**
     * 对str进行DES解密
     * @param str 解密的 字符串
     * @param key_str 解密的秘钥
     * @return 解密后的字符串
     */
    public static String getDecryptString(String str,String key_str) {
        BASE64Decoder base64De = new BASE64Decoder();
        try {
            setKey2(key_str);
            byte[] strBytes = base64De.decodeBuffer(str);
            Cipher cipher = Cipher.getInstance("DES");
            cipher.init(Cipher.DECRYPT_MODE, key);
            byte[] decryptStrBytes = cipher.doFinal(strBytes);
            return new String(decryptStrBytes, "UTF8");
        } catch (Exception e) {
            log.warn("字符串des解密失败:"+e);
            throw new RuntimeException(e);
        }
    }


    //Linux 系统下正常运行
    public static void setKey2(String strKey) {
        try {
            SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
            DESKeySpec keySpec = new DESKeySpec(strKey.getBytes("utf-8"));
            key = keyFactory.generateSecret(keySpec);
        } catch (Exception e) {
            e.printStackTrace();
        }finally{

        }
    }


    public static void main(String[] args) {
        String key = "111";
        String key2 = "111";
        System.out.println(getEncryptString(key,key2));
        String key3 = "";
       // System.out.println(getDecryptString(key3,key2).trim());


    }

}

2.加密配置文件 jdbc.properties

driverClassName=com.mysql.jdbc.Driver
url:jdbc:mysql://localhost:3306/testdb
username=WnplV/ietfQ=
password=gJQ9O+q34qk=

3.扩展PropertyPlaceholderConfigurer,覆盖String convertProperty(String propertyName,String propertyValue)方法,对userName和password解密

package com.smart.placeholder;

import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;

public class EncryptPropertyPlaceholderConfigurer extends PropertyPlaceholderConfigurer {

    /**需要解密的属性key*/ 
    private String[] encryptPropNames ={"userName","password"};

    @Override
    protected String convertProperty(String propertyName, String propertyValue) {       
        if(isEncryptProp(propertyName)){
            String decryptValue = DESUtils.getDecryptString(propertyValue);
            System.out.println(decryptValue);
            return decryptValue;
        }else{
            return propertyValue;
        }
    }

    /**
     * 判断是否是加密的属性
     * @param propertyName
     * @return
     */
    private boolean isEncryptProp(String propertyName){
        for(String encryptPropName:encryptPropNames){
            if(encryptPropName.equals(propertyName)){
                return true;
            }
        }
        return false;
    }
}

4.使用传统的配置方式

<?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:p="http://www.springframework.org/schema/p"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
         http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
         http://www.springframework.org/schema/context
         http://www.springframework.org/schema/context/spring-context-4.0.xsd">
    <!--1.使用传统的PropertyPlaceholderConfigurer引用属性文件  -->
<!--    <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
            p:fileEncoding="utf-8">
        <property name="locations">
            <list>
                <value>classpath:com/smart/placeholder/jdbc.properties</value>
            </list>
        </property>
    </bean>-->

    <!--2.使用context命名空间的配置引用属性文件  -->
<!--    <context:property-placeholder
            location="classpath:com/smart/placeholder/jdbc.properties" file-encoding="utf8"/>
        <bean id="utf8" class="java.lang.String">
            <constructor-arg value="utf-8"></constructor-arg>
        </bean>-->

    <!--3.使用加密版的属性文件  -->
    <bean class="com.smart.placeholder.EncryptPropertyPlaceholderConfigurer"
        p:location="classpath:com/smart/placeholder/jdbc.properties"
        p:fileEncoding="utf-8"/>

    <context:component-scan base-package="com.smart.placeholder"/>

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
        destroy-method="close" 
        p:driverClassName="${driverClassName}" 
        p:url="${url}"
        p:password="${password}" />


</beans>

s3.属性文件自身的引用

db=testdb
url=jdbc:mysql://localhost:3306/${db}

s4.引用Bean的属性值

有时配置文件的属性不适合放在配置文件中,如集群部署的时候,希望能动态的调整属性,spring提供了#{beanName.beanProp}的方式引用另一个Bean的值

public class SysConfig{

    private int sessionTimeOut;
    private int maxtabPageNum;
    private DataSource dataSource;

    //模拟充数据库中查找属性值
    public void initFromDB(){
        this.sessionTimeOut = 30;
        this.maxtabPageNum = 10;
    }

    public int getSessionTimeOut(){
        return sessioinTimeOut;
    }

    public int getMaxtabPagNum(){
        return maxtabPagNum;
    }

    public void setDataSource(DataSource dataSource){
        this.dataSource = dataSource;
    }
}

在xml配置文件中,先将SysConfig定义成一个Bean,通过#{beanName.beanProp}引入属性值

<?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:p="http://www.springframework.org/schema/p"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
         http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
         http://www.springframework.org/schema/context
         http://www.springframework.org/schema/context/spring-context-4.0.xsd">
    <context:property-placeholder
         location="classpath:com/smart/placeholder/jdbc.properties"/>

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
        destroy-method="close" 
        p:driverClassName="${driverClassName}" 
        p:url="${url}"
        p:username="${userName}" 
        p:password="${password}"/>

    <bean id="sysConfig" class="com.smart.beanprop.SysConfig"
          init-method="initFromDB"
          p:dataSource-ref="dataSource"/>

    <bean class="com.smart.beanprop.ApplicationManager"
        p:maxTabPageNum="#{sysConfig.maxTabPageNum}"
        p:sessionTimeout="#{sysConfig.sessionTimeout}"/>        
</beans>

java注解通过@Value(“#{beanName.beanProp}”)引入属性值

public class ApplicationManager(){
    @Value("${SysConfig.sessionTimeOut}")
    private int sessionTimeOut
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值