一、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. python中ones的含义和用法

    ones是numpy的一个内置函数,作用是生成参数为一的数组.英文解释: Return a new array of given shape and type, filled with ones. 例 ...

  2. Testing - 软件测试知识梳理 - 软件性能测试

    软件性能测试的基本概念 软件的性能是软件的一种非功能特性,它关注的不是软件是否能够完成特定的功能,而是软件在完成该功能时展示出来的及时性. 软件性能的指标 响应时间:是指系统对请求作出响应的时间,并且 ...

  3. Windows 10安装Python 3 7成功打印Hello World!

    Python下载 Python最新源码,二进制文档,新闻资讯等可以在Python的官网查看到: Python官网:https://www.python.org/ 你可以在以下链接中下载 Python ...

  4. webpack通过postcss-loader添加浏览器前缀

    在webpack中,我们可以很方便的使用autoprefixer来为css3属性添加不同的浏览器前缀. 首先,需要安装autoprefixer不用多说了,其次是安装postcss-loader(npm ...

  5. RPC的原理总结

    一.RPC的引入 早期单机时代,一台电脑上运行多个进程,大家各干各的,老死不相往来.假如A进程需要一个画图的功能,B进程也需要一个画图的功能,程序员就必须为两个进程都写一个画图的功能.这不是整人么?于 ...

  6. log4j学习总结

    一直使用log4j来记录日志,但是一直以来没有深入研究过log4j,最近研究了下log4j,下面总结一下: log4j配置: 1. 配置根Logger,其语法为: log4j.rootLogger = ...

  7. Docker修改默认网段

    因阿里云服务器VPC默认占用了172.16.0.0/16 网段,与Docker里的网段相同,导致Docker里无法连接VPC服务器.后来找到的解决方案是修改Docker的默认网段. 由于Docker默 ...

  8. libtorch初体验

    环境 Ubuntu -18.04.1, opencv3.4.0 ,  python 3.6,  cmake 3.5.0, pytorch 1.0. pytorch官网下载对应版本:https://py ...

  9. [转]How to Improve Entity Framework Add Performance?

    本文转自:http://entityframework.net/improve-ef-add-performance When you overuse the Add() method for mul ...

  10. Asp.Net4.5 mvc4(二) 页面创建与讲解

    一.Contorl 通过目录结构我们可以看到contorllers类的命名方式 命名规则:前缀+Controller. 在看看contorller中的action方法 using System; us ...