Spring-使用外部属性文件01
- 导读
- 概述
- PropertyPlaceholderConfigurer属性文件
- 实例
- 使用PropertyPlaceholderConfigurer属性文件
- PropertyPlacerholderConfigurer的其他属性
- locations
- fileEncoding
- order
- placeholderPrefix
- placeholderSuffix
- PropertyPlacerholderConfigurer的其他属性
- 使用contextproperty-placehoder引用属性文件
- 基于注解及基于JAVA类的配置中引用属性
- 实例
- 注意事项
导读
Spring-使用外部属性文件01
Spring-使用加密的属性文件02
Spring-属性文件自身的引用03
概述
在进行数据源或者邮件服务器等资源配置时,用户可以直接在Spring配置文件中配置用户名、密码、连接信息等,但是有一种更好的方法是将这些配置信息独立到一个外部属性文件中,并在Spring配置文件中通过形如${user}
、${password}
的占位符引用属性文件中的属性项。
通过这种方式配置拥有两个明显的好处
- 减少维护的工作量
- 部署更加简单
Spring提供了一个PropertyPlaceholderConfigurer,它能够使Bean在配置时引用外部属性文件。
PropertyPlaceholderConfigurer实现了BeanFactoryPostProcessorBean接口,因而也是一个Bean工厂后处理器.
PropertyPlaceholderConfigurer属性文件
代码已托管到Github—> https://github.com/yangshangwei/SpringMaster
实例
maven项目
一种不太好的写法
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"><property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/><property name="url" value="jdbc:oracle:thin:@172.25.246.11:1521:xgj"/><property name="username" value="cctb"/><property name="password" value="xgj2017"/></bean>
从上面的配置文件中,我们可以看到驱动器类名、JDBC的URL以及数据库的用户名和密码都写在了XML中。部署的时候,如果需要改动数据库的配置信息,需要先找到这个xml,然后修改,不是特别方便。
根据实际应用的最佳实践,我们可以将这些信息抽取到一个配置文件中,取名为 jdbc.priperties (随意取名)
我们先看下jdbc.priperties的配置文件
jdbc.properties
jdbc.driverClassName=oracle.jdbc.driver.OracleDriver
jdbc.url=jdbc:oracle:thin:@172.25.246.11:1521:xgj
jdbc.username=cctb
jdbc.password=xgj2017
属性文件可以定义多个属性,每个属性都有一个属性名和属性值组成,二者用“=”隔开。
使用PropertyPlaceholderConfigurer属性文件
下面通过PropertyPlaceholderConfigurer引入jdbc.properties属性文件,调整数据源Bean的配置,为了测试,我们引入了JdbcTemplate
beans.xml
<?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.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"><!-- 扫描类包,将标注Spring注解的类自动转化Bean,同时完成Bean的注入 --><context:component-scan base- package="com.xgj.ioc.propertyplacehoder"/><!-- 引入JDBC属性文件 --><bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"p:location="classpath:spring/jdbc.properties"p:fileEncoding="utf-8"/><!-- 通过属性名引用属性值 --> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"destroy-method="close"p:driverClassName="${jdbc.driverClassName}"p:url="${jdbc.url}"p:username="${jdbc.username}"p:password="${jdbc.password}"/><!-- 配置Jdbc模板 --><bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"p:dataSource-ref="dataSource" /></beans>
通过PropertyPlaceholderConfigurer的location属性引入属性文件,这样在Bean定义的时候就可以引用属性文件中的属性了。
然后通过${jdbc.driverClassName}等占位符来引用jdbc.properties中的属性,这样部署人员仅需要关注jdbc.properties这个配置文件即可,无需关心Spring的配置文件。
测试:
我们数据库中temp_user表有一条记录,我们来模拟登录查询
PropertyPlaceHoderTest.java
package com.xgj.ioc.propertyplacehoder;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;@Component
public class PropertyPlaceHoderTest {private final static String MATCH_COUNT_SQL = " SELECT count(*) FROM temp_user "+ " WHERE user_name =? and password=? ";private JdbcTemplate jdbcTemplate;@Autowiredpublic void setJdbcTemplate(JdbcTemplate jdbcTemplate) {this.jdbcTemplate = jdbcTemplate;}/*** * *@Title: getMatchCount* *@Description: 根据用户名和密码判断用户是否存在* *@param username*@param password* *@return: int*/public int getMatchCount(String username, String password) {return jdbcTemplate.queryForObject(MATCH_COUNT_SQL, new Object[] {username, password }, Integer.class);}/*** * *@Title: main* *@Description: 测试* *@param args* *@return: void*/public static void main(String[] args) {// 加载Spring配置文件ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:com/xgj/ioc/propertyplacehoder/beans.xml");// 获取通过注解标注的BeanPropertyPlaceHoderTest propertyPlaceHoderTest = ctx.getBean("propertyPlaceHoderTest", PropertyPlaceHoderTest.class);// 调用方法int count = propertyPlaceHoderTest.getMatchCount("xgj", "123456");System.out.println("匹配的用户数量:" + count);}
}
运行结果:
PropertyPlacerholderConfigurer的其他属性
locations
如果只有一个属性文件,则直接使用location属性指定即可,如果有多个属性文件,则可以通过locations属性进行设置,可以像配置list一样配置locations属性。
list的配置参考 Spring-注入参数详解-[集合类型属性]
fileEncoding
属性文件的编码格式,Spring默认使用操作系统默认编码读取属性文件,如果属性文件使用了特殊编码,则需要通过该属性显式指定。
order
如果配置配置文件中定义了多个PropertyPlacehoderConfigurer,则通过该属性指定优先顺序。
placeholderPrefix
上面的案例,我们使用${jdbc.driverClassName}引用属性文件中的属性项, 其中, ${
为默认的占位符前缀,可修改
placeholderSuffix
占位符后缀,默认为 }
使用context:property-placehoder引用属性文件
可以使用context命名空间定义属性文件,相比传统的PropertyPlaceholderConfigurer配置,这种方式更优雅
<!-- 引入JDBC属性文件<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"p:location="classpath:spring/jdbc.properties"p:fileEncoding="utf-8"/> --><!-- 使用context命名空间,同上面的Bean等效。 --><context:property-placeholder location="classpath:spring/jdbc.properties" />
但是有个缺点: 如果想自定义一些额外的高级功能,比如属性加密、使用数据库表保存配置信息等,则必须扩展PropertyPlaceholderConfigurer的类并使用Bean的配置方式。
基于注解及基于JAVA类的配置中引用属性
在基于XML的配置文件中,通过${propName}的形式引用属性值,类似的,基于注解的Bean可以通过@Value注解为Bean的成员变量或者方法入参自动注入容器已有的属性。同样的基于JAVA类注解@Configuration的类的引用属性的方式和基于注解配置的引用方式是完全一样的,不再赘述。
实例
package com.xgj.ioc.propertyplacehoder.annotation;import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;@Component
public class MyDataSource {private String driveClassName;private String url;private String userName;private String password;/*** * *@Title: setDriveClassName* *@Description: 注入jdbc.driverClassName的值 (也可以直接在属性上注入)* *@param driveClassName* *@return: void*/@Value("${jdbc.driverClassName}")public void setDriveClassName(String driveClassName) {this.driveClassName = driveClassName;}@Value("${jdbc.url}")public void setUrl(String url) {this.url = url;}@Value("${jdbc.username}")public void setUserName(String userName) {this.userName = userName;}@Value("${jdbc.password}")public void setPassword(String password) {this.password = password;}/*** * *@Title: getDriveClassName* *@Description: 获取driveClassName* *@return* *@return: String*/public String getDriveClassName() {System.out.println("getDriveClassName:" + driveClassName);return driveClassName;}public String getUrl() {System.out.println("getUrl:" + url);return url;}public String getUserName() {System.out.println("getUserName:" + userName);return userName;}public String getPassword() {System.out.println("getPassword:" + password);return password;}}
测试类
package com.xgj.ioc.propertyplacehoder.annotation;import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class AnnotationTest {public static void main(String[] args) {ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:com/xgj/ioc/propertyplacehoder/beans.xml");MyDataSource myDataSource = ctx.getBean("myDataSource",MyDataSource.class);myDataSource.getDriveClassName();myDataSource.getUrl();myDataSource.getUserName();myDataSource.getPassword();}
}
运行结果
注意事项
使用的过程中,一定要确保所引用的属性值在属性文件中存在且数值匹配,否则会造成Bean创建错误。
比如我们修改一下注入的属性@Value(“${jdbc.driverClassName1}”)
Error creating bean with name ‘myDataSource’: Injection of autowired dependencies failed; …..
2017-08-06 18:23:17,692 INFO [main] (AbstractApplicationContext.java:583) - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@7fae1081: startup date [Sun Aug 06 18:23:17 BOT 2017]; root of context hierarchy
2017-08-06 18:23:17,767 INFO [main] (XmlBeanDefinitionReader.java:317) - Loading XML bean definitions from class path resource [com/xgj/ioc/propertyplacehoder/beans.xml]
2017-08-06 18:23:18,398 WARN [main] (AbstractApplicationContext.java:551) - Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'myDataSource': Injection of autowired dependencies failed; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'jdbc.driverClassName1' in value "${jdbc.driverClassName1}"
Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'myDataSource': Injection of autowired dependencies failed; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'jdbc.driverClassName1' in value "${jdbc.driverClassName1}"at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:372)at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1264)at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553)at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:761)at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:867)at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543)at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139)at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:83)at com.xgj.ioc.propertyplacehoder.annotation.AnnotationTest.main(AnnotationTest.java:9)
Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'jdbc.driverClassName1' in value "${jdbc.driverClassName1}"at org.springframework.util.PropertyPlaceholderHelper.parseStringValue(PropertyPlaceholderHelper.java:174)at org.springframework.util.PropertyPlaceholderHelper.replacePlaceholders(PropertyPlaceholderHelper.java:126)at org.springframework.core.env.AbstractPropertyResolver.doResolvePlaceholders(AbstractPropertyResolver.java:236)at org.springframework.core.env.AbstractPropertyResolver.resolveRequiredPlaceholders(AbstractPropertyResolver.java:210)at org.springframework.context.support.PropertySourcesPlaceholderConfigurer$2.resolveStringValue(PropertySourcesPlaceholderConfigurer.java:172)at org.springframework.beans.factory.support.AbstractBeanFactory.resolveEmbeddedValue(AbstractBeanFactory.java:831)at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1086)at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1066)at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredMethodElement.inject(AutowiredAnnotationBeanPostProcessor.java:659)at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:366)... 13 more
Spring-使用外部属性文件01相关推荐
- Spring使用外部属性文件
一.在 Spring Config 文件中配置 Bean 时,有时候需要在 Bean 的配置里添加 系统部署的细节信息, 如文件路径,数据源配置信息.而这些部署细节实际上需要在配置文件外部来定义. 二 ...
- Spring使用外部属性文件以及常见错误(内附大量图片,很有借鉴意义)
一.在 Spring Config 文件中配置 Bean 时,有时候需要在 Bean 的配置里添加 系统部署的细节信息,如文件路径,数据源配置信息.而这些部署细节实际上需要在配置文件外部来定义. 二. ...
- Spring_Bean的作用域---和使用外部属性文件
<!-- 使用 bean的scope属性来配置bean的作用域 singleton:默认值.容器初始时创建bean实例,在整个容器的生命周期内只创建这一个bean单例 prototype:原型的 ...
- 通过外部文件覆盖打包的Spring应用程序属性文件
开发Spring应用程序时,最常见的用例是您希望拥有多个版本的配置属性,具体取决于要部署到的位置,例如,数据库URL或功能标志可能是特定于dev,qa,production等环境的. 像大多数Spri ...
- 8.Spring学习笔记_使用外部属性文件(by尚硅谷_佟刚)
使用外部属性文件 在配置文件里配置 Bean 时, 有时需要在 Bean 的配置里混入系统部署的细节信息(例如: 文件路径, 数据源配置信息等). 而这些部署细节实际上需要和 Bean 配置相分离 S ...
- 实验12:引用外部属性文件★(spring管理连接池);
实验12:引用外部属性文件★ dbconfig.properties 文件
- [Spring5]IOC容器_Bean管理XML方式_外部属性文件
IOC操作Bean管理(外部属性文件) 1.直接配置数据库信息 (1)配置德鲁伊druid连接池 (2)引入德鲁伊druid连接池依赖jar包 <!--直接配置连接池--><bean ...
- IOC操作Bean管理XML方式(外部属性文件)
目录 IOC操作Bean管理XML方式(外部属性文件) 前情引入: 实验演示: 1.直接配置数据库信息 (1)配置德鲁伊连接池 (2)引入德鲁伊连接池jar包 (3)创建一个bean6.xml配置文件 ...
- Spring-Bean配置-使用外部属性文件(转)
Spring-Bean配置-使用外部属性文件 所以可以通过@value注解获取配置文件的key-value,生成一个配置文件bean.用以在代码中直接使用bean的方式. •在配置文件里配置Bean时 ...
最新文章
- Web前端开发人员和设计师必读文章推荐【系列七】
- 关于深度学习的小知识点
- backbone.js学习笔记
- CCF关于暂停NOIP竞赛的公告
- leetcode 107 --- 二叉树程序遍历 ii
- c语言超长整数加法计算,两个超长正整数的加法
- 剑指Offer值数字在排序数组中出现的次数
- CSS flex 布局 一些基本属性应用
- 帆软按钮Javascript给某个单元格赋值(例:逻辑删除)
- 教育大数据采集机制与关键技术研究
- 经验模态分解 及其衍生算法
- 小程序-实现 tab-及多个列表选项切换
- Base64中文乱码解决方法
- python3 分句
- 南京大学计算机考研考试大纲,南京大学计算机技术(专业学位)研究生考试科目和考研参考书目...
- java rmi端口_RMI IP绑定和端口固定
- 智慧城市篇 | 数字孪生智慧排水管网管理平台
- 发送测试电子邮件消息 响应服务器 550,Microsoft SMTP 服务器在第三方测试中可能显示为能够接受并中继电子邮件...
- 中国商用清洁机器人产业“十四五”规划展望及项目可行性分析报告2021-2027年
- 洋葱omall是什么