一、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. kubernetes集群搭建(4):node节点安装

    下列所有操作需要在所有node节点上操作,并注意红色部分的修改 1.node节点不需要安装etcd来存储相关信息 yum -y install flannel kubernetes 2.修改flann ...

  2. Introduction to CELP Coding

    Speex is based on CELP, which stands for Code Excited Linear Prediction. This section attempts to in ...

  3. [EXP]Microsoft Windows MSHTML Engine - "Edit" Remote Code Execution

    # Exploit Title: Microsoft Windows (CVE-2019-0541) MSHTML Engine "Edit" Remote Code Execut ...

  4. 理解数据库连接池和ThreadLocal实现的事务控制

    我发现 不少人 误解了这两者. csdn上也有人提出过这种疑问: http://bbs.csdn.net/topics/250061733 经过查阅资料和认真分析,我特说明一下这两者概念上的区别. 我 ...

  5. 高手速成android开源项目【View篇】

    主要介绍那些不错个性化的View,包括ListView.ActionBar.Menu.ViewPager.Gallery.GridView.ImageView.ProgressBar及其他如Dialo ...

  6. IT人如何打造个性化的个人网站(在线简历)

    前言 众所周知,IT行业人员在求职时,如果拥有自己的技术博客和个人网站多少是可以加些分的,因为这也是IT人的技术证明之一.内容丰富的技术博客就不必多少了,往往技术博客大神市场上多是供不应求的,而且技术 ...

  7. [TensorFlow] Creating Custom Estimators in TensorFlow

    Welcome to Part 3 of a blog series that introduces TensorFlow Datasets and Estimators. Part 1 focuse ...

  8. 实验吧 php

    Once More 题目地址:http://ctf5.shiyanbar.com/web/more.php 打开直接有源码: <?php if (isset ($_GET['password'] ...

  9. [NOI 2017]游戏

    Description 题库链接 小 L 计划进行 \(n\) 场游戏,每场游戏使用一张地图,小 L 会选择一辆车在该地图上完成游戏. 小 L 的赛车有三辆,分别用大写字母 A.B.C 表示.地图一共 ...

  10. asp.net mvc5轻松实现插件式开发

    在研究Nopcommece项目代码的时候,发现Nop.Admin是作为独立项目开发的,但是部署的时候却是合在一起的,感觉挺好 这里把他这个部分单独抽离出来, 主要关键点: 确保你的项目是MVC5 而不 ...