一、PropertyPlaceholderConfigurer

spring提供的PropertyPlaceholderConfigurer实现类能够使Bean在配置时引用外部属性文件。
PropertyPlaceholderConfigurer实现了BeanFactoryPostProcessorBean接口,因而也是一个Bean工厂后处理器。


二、PropertyPlaceholderConfigurer的使用

1、xml配置及注解方式:

      <dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.3.16.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.16.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>4.3.16.RELEASE</version>
</dependency>

pom.xml

name=zhangsan
age=23

my.properties

package test;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; public class Driver {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("my.xml");
User user = context.getBean("user", User.class);
System.out.println(user.getName());
System.out.println(user.getAge());
}
}
class User {
@Value("${name}")
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}

java 类

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
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">
<!-- spring 引入属性文件 -->
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
p:location="classpath:my.properties"
p:fileEncoding="utf-8"/>
<!-- 开启包扫描,因为User类使用到了@Value注解;包扫描不支持裸体类上的注解 -->
<context:component-scan base-package="test"/>
<!-- 使用外部属性文件值赋值 -->
<bean id="user" class="test.User" p:age="${age}"/>
</beans>

spring my.xml

PropertyPlaceholderConfigurer的其他属性:
locations:可以引入多个属性文件
fileEncoding:属性文件的编码格式
order:指定多个属性的优先级
placeholderPrefix:默认值为“${”,可以修改
placeholderSuffix:默认为“}”

除了使用<bean>声明PropertyPlaceholderConfigurer引入属性文件这种方式外,还可以使用另一种简洁的方式;但如果希望自定义一些额外的高级功能,如属性加密、使用数据库表来保存配置信息时,就必须使用<bean>声明PropertyPlaceholderConfigurer的方式

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
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">
<!-- spring 引入属性文件 -->
<context:property-placeholder location="my.properties"/>
<!-- 开启包扫描,因为User类使用到了@Value注解;包扫描不支持裸体类上的注解 -->
<context:component-scan base-package="test"/>
<!-- 使用外部属性文件值赋值 -->
<bean id="user" class="test.User" p:age="${age}"/>
</beans>

spring my.xml

2、Java配置及注解方式:

      <dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.3.16.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.16.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>4.3.16.RELEASE</version>
</dependency>

pom.xml

name=zhangsan
age=23

my.properties

package test;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext; public class Driver {
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);
User user = context.getBean("user", User.class);
System.out.println(user.getName());
System.out.println(user.getAge());
}
}
class User {
@Value("${name}")
private String name;
@Value("${age}")
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}

java类

package test;

import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource; @Configuration
@ComponentScan
public class MyConfig {
@Bean
public User user() {
return new User();
}
@Bean
public PropertyPlaceholderConfigurer PropertyPlaceholderConfigurer() {
PropertyPlaceholderConfigurer configurer = new PropertyPlaceholderConfigurer();
configurer.setLocation(new ClassPathResource("my.properties"));
return configurer;
} }

java 配置类


三、自定义PropertyPlaceholderConfigurer——支持加密

加密

如果属性信息是数据库用户名、密码等敏感信息,应该使用密文方式。虽说Web应用的客户端用户看不到服务器端的属性文件,但内部人员却可以轻易查看属性文件的内容,这样容易造成数据库访问权限的泄露。

实现

PropertyPlaceholderConfigurer类继承了PlaceholderConfigurerSupport,PlaceholderConfigurerSupport有几个protected的空实现的属性转换方法,专门用于在使用属性之前对属性值进行转换;
所以我们需要自定义PlaceholderConfigurerSupport的实现类并覆盖相应的属性转换方法来代替spring提供的PropertyPlaceholderConfigurer。

信息的加密可分为对称和非对称两种方式,前者加密后可以解密还原,而后者不可以还原;MD5是非对称加密,DES是对称加密,这里使用DES方式。DES加密解密的关键是加密密钥。

demo

      <dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.3.16.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.16.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>4.3.16.RELEASE</version>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.6</version>
</dependency>

pom.xml

name=agyo9QHJ78MfJAfVsP+M2w==
age=ArphqsQ7cdE=

my.properties

package test;

import java.security.Key;
import java.security.SecureRandom; import javax.crypto.Cipher;
import javax.crypto.KeyGenerator; import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder; public class DESUtils {
// 指定DES加密解密所用的密钥
private static Key key;
private static String KEY_STR = "myKey";
static {
try {
KeyGenerator generator = KeyGenerator.getInstance("DES");
generator.init(new SecureRandom(KEY_STR.getBytes()));
key = generator.generateKey();
generator = null;
} catch (Exception e) {
throw new RuntimeException(e);
}
} /**
* 对字符串进行DES加密,返回Base64编码的加密字符串
*/
public static String getEncryptString(String str) {
BASE64Encoder base64en = new BASE64Encoder();
try {
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) {
throw new RuntimeException(e);
}
} /**
* 对Base64编码的加密字符串进行DES解密,返回解密后的字符串
*/
public static String getDecryptString(String str) {
BASE64Decoder base64De = new BASE64Decoder();
try {
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) {
throw new RuntimeException(e);
} } /**
* 对入参的字符串加密,并打印密文
*/
public static void main(String[] args) throws Exception {
args = new String[]{"zhangsan", "23"};
if (args == null || args.length < 1) {
System.out.println("请输入要加密的字符,用空格分隔.");
} else {
for (String arg : args) {
System.out.println(arg + ":" + getEncryptString(arg));
}
} //System.out.println(getDecryptString("WnplV/ietfQ="));
//System.out.println(getDecryptString("gJQ9O+q34qk="));
}
}

DESUtils.java

package test;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext; public class Driver {
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);
User user = context.getBean("user", User.class);
System.out.println(user.getName());
System.out.println(user.getAge());
}
}
class User {
@Value("${name}")
private String name;
@Value("${age}")
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}

Driver.java

package test;

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

public class MyPropertyPlaceholderConfigurer extends PropertyPlaceholderConfigurer {
// 需要解密的属性
private String[] encryptPropNames ={"name","age"}; // 解密
@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;
}
} /**
* 判断是否是加密的属性
*/
private boolean isEncryptProp(String propertyName){
for(String encryptPropName:encryptPropNames){
if(encryptPropName.equals(propertyName)){
return true;
}
}
return false;
}
}

自定义属性文件加载器

package test;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource; @Configuration
@ComponentScan // 因为用到了@Value注解,所以需要开启扫描
public class MyConfig {
@Bean
public User user() {
return new User();
}
// @Bean
//// public PropertyPlaceholderConfigurer PropertyPlaceholderConfigurer() {
//// PropertyPlaceholderConfigurer configurer = new PropertyPlaceholderConfigurer();
//// configurer.setLocation(new ClassPathResource("my.properties"));
//// return configurer;
//// }
@Bean
public MyPropertyPlaceholderConfigurer encryptPropertyPlaceholderConfigurer() {
MyPropertyPlaceholderConfigurer configurer = new MyPropertyPlaceholderConfigurer();
configurer.setLocation(new ClassPathResource("my.properties"));
return configurer;
}
}

java配置类


四、属性文件引用属性文件的属性值

Spring允许在xml、java类中使用${xxx}、@Value("${xxx}")引用属性值,也允许在属性文件中使用${xxx}引用其它属性文件的属性值
name=lisi
age=${age}

my.properties

age=18

my2.properties

package test;

import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource; @Configuration
public class MyConfig {
@Bean
public User user() {
return new User();
}
@Bean
public PropertyPlaceholderConfigurer PropertyPlaceholderConfigurer() {
PropertyPlaceholderConfigurer configurer = new PropertyPlaceholderConfigurer();
configurer.setLocations(new ClassPathResource[] {new ClassPathResource("my.properties"),
new ClassPathResource("my2.properties")});
return configurer;
}
}

MyConfig.java

  

spring 使用外部属性文件的更多相关文章

  1. Spring 使用外部属性文件配置

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

  2. Spring使用外部属性文件

    一.在 Spring Config 文件中配置 Bean 时,有时候需要在 Bean 的配置里添加 系统部署的细节信息, 如文件路径,数据源配置信息.而这些部署细节实际上需要在配置文件外部来定义. 二 ...

  3. Spring 应用外部属性文件 配置 context 错误

    在Spring配置文件中出现通配符的匹配很全面, 但无法找到元素 'context:property-placeholder' 的声明这个错误,其实主要是我们在引入命名空间时没有正确引入它的DTD解析 ...

  4. Spring_Bean的作用域---和使用外部属性文件

    <!-- 使用 bean的scope属性来配置bean的作用域 singleton:默认值.容器初始时创建bean实例,在整个容器的生命周期内只创建这一个bean单例 prototype:原型的 ...

  5. Spring - 配置Bean - 自动装配 关系 作用域 引用外部属性文件

    1 Autowire自动装配1.1 使用:只需在<bean>中使用autowire元素<bean id="student" class="com.kej ...

  6. [原创]java WEB学习笔记99:Spring学习---Spring Bean配置:自动装配,配置bean之间的关系(继承/依赖),bean的作用域(singleton,prototype,web环境作用域),使用外部属性文件

    本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...

  7. Spring(十):Spring配置Bean(三)Bean的作用域、使用外部属性文件

    Bean的作用域: 支持四种配置,分别是singleton,prototype,request,session. singleton 默认情况下在spring confinguration xml文件 ...

  8. Spring基础12——使用外部属性文件

    1.使用外部属性文件 在配置文件里配置Bean时,有时需要在Bean的配置文件里引入系统部署的细节信息(例如:文件的路径.数据源配置信息等),而这些部署细节实际上需要和bean配置相分离,因为我们修改 ...

  9. 十八 Spring的JDBC模板:引入外部属性文件

    配置外部属性文件 配置文件里引入属性文件,两种方式 第一种: 第二种: 引入属性文件的值: 测试: <?xml version="1.0" encoding="UT ...

随机推荐

  1. Java序列化技术即将被废除!!!

    我们的对象并不只是存在内存中,还需要传输网络,或者保存起来下次再加载出来用,所以需要Java序列化技术.Java序列化技术正是将对象转变成一串由二进制字节组成的数组,可以通过将二进制数据保存到磁盘或者 ...

  2. 课程四(Convolutional Neural Networks),第四 周(Special applications: Face recognition & Neural style transfer) —— 3.Programming assignments:Face Recognition for the Happy House

    Face Recognition for the Happy House Welcome to the first assignment of week 4! Here you will build ...

  3. wxformbuilder在python如何使用

    1使用builder 创建界面并进行布局 2选择python选项 得到相应代码 将代码保存在 一个py文件里面 创建一个新的入口文件 main.py import wx import UIfile c ...

  4. Xcode 8.X Command Line Tools

    Summary Step 1. Upgrade Your System to macOS Sierra Step 2. Open the Terminal Application Step 3. Is ...

  5. 我们自研的那些Devops工具

    随着云技术以及容器技术的崛起,人肉运维的时代结束了 2018年为了解决日常运维中的痛点以及更高效的推进运维工作,我们自研并完善了几个工具系统,这些系统无一例外的帮我们节约了时间,提高了效率,这篇文章将 ...

  6. Tomcat启动时项目重复加载的问题

    最近在项目开发测试的时候,发现Tomcat启动时项目重复加载,导致资源初始化两次的问题  导致该问题的原因: 如下图:在Eclipse中将Server Locations设置为“Use Tomcat ...

  7. FFmpeg编解码处理2-编解码API详解

    本文为作者原创,转载请注明出处:https://www.cnblogs.com/leisure_chn/p/10584925.html FFmpeg编解码处理系列笔记: [0]. FFmpeg时间戳详 ...

  8. bootstrap知识笔记

    .nav>.active>a{ background-color:#0088cc; color:#fff; } /*! * Bootstrap v3.3.7 (http://getboot ...

  9. [转]TFS2010 Team Project Collections

    本文转自:https://www.cnblogs.com/shanyou/archive/2010/04/14/1712252.html Team Foundation Server 2010有一个改 ...

  10. 关于SVN 操作 提示文件已过时,请先update

    提示文件已过时,请先update 错误产生原因:修改文件前没有先update,从svn获取该文件的最新版本. 解决方法:备份你修改后的文件,通过Revert恢复到服务器版本后,再比较之前备份的文件,进 ...