使用外部属性文件
在配置文件里配置 Bean 时, 有时需要在 Bean 的配置里混入系统部署的细节信息 (例如: 文件路径, 数据源配置信息等). 而这些部署细节实际上需要和 Bean 配置相分离 Spring 提供了一个 PropertyPlaceholderConfigurer 的 BeanFactory 后置处理器 , 这个处理器允许用户将 Bean 配置的部分内容外移到属性文件 中. 可以在 Bean 配置文件里使用形式为 ${var}
的变量, PropertyPlaceholderConfigurer 从属性文件里加载属性, 并使用这些属性来替换变量. Spring 还允许在属性文件中使用 ${propName}
,以实现属性之间的相互引用。
连数据库示例,本地要有数据库且开启。 新建个包,com.liudehua,新建个Main.java:1
2
3
4
5
6
7
public class Main {
public static void main(String[] args) throws SQLException {
ApplicationContext ctx = new ClassPathXmlApplicationContext("beans-properties.xml");
DataSource dataSource = (DataSource)ctx.getBean("dataSource");
System.out.println(dataSource.getConnection());
}
}
新建个beans-properties.xml配置文件:1
2
3
4
5
6
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="user" value="root"></property>
<property name="password" value="123456"></property>
<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
<property name="jdbcUrl" value="jdbc:mysql:///test"></property>
</bean>
注意:这里我又踩坑了。后台报异常Connections could not be acquired from the underlying database!
,遂百度,得知可能是以下几点造成的:
1.驱动配置有误:driver=com.mysql.jdbc.Driver
2.数据库连接地址有误
3.密码或帐号有误
4.数据库未启动或无权访问
5.项目未引入对应的驱动jar包mysql-connector-java-5.1.6-bin.jar 和c3p0-0.9.1.2.jar
6.mysql root没有远程访问的权限,需要增加权限,增加权限的步骤如下:进入mysql数据库:grant all privileges on . to ‘root’@’%’ identified by ‘root’ with grant option;flush privileges; 后来,我想可能是我参数写错了,仔细找,发现确实拼错了,改之启动还是一样的错,然后看看第4点,嗯,我电脑上没有数据库。。。
没数据库没关系,可以装,后面的接着学。部署数据库连接的基本信息最好是拿出来,放到一个属性文件里面。 src下新建一个属性文件,db.properties:1
2
3
4
user=root
password=123456
driverClass=com.mysql.jdbc.Driver
jdbcUrl=jdbc:mysql:///test
注意:本地mysql必须有一个名为test的数据库
接下来引用该属性文件。 修改beans-properties.xml代码:1
2
3
4
5
6
7
8
9
<!-- 导入属性文件 -->
<context:property-placeholder location="classpath:db.properties"/>
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<!-- 使用外部化属性文件的属性 -->
<property name="user" value="${user}"></property>
<property name="password" value="${password}"></property>
<property name="driverClass" value="${driverClass}"></property>
<property name="jdbcUrl" value="${jdbcUrl}"></property>
</bean>
Spring表达式语言:SpEL
Spring 表达式语言(简称SpEL):是一个支持运行时查询和操作对象图的强大的表达式语言。 语法类似于 EL:SpEL 使用 #{…} 作为定界符,所有在大框号中的字符都将被认为是 SpEL SpEL 为 bean 的属性进行动态赋值提供了便利 通过 SpEL 可以实现:
通过 bean 的 id 对 bean 进行引用
调用方法以及引用对象中的属性
计算表达式的值
正则表达式的匹配
字面量的表示:
整数:<property name="count" value="#{5}"/>
小数:<property name="frequency" value="#{89.7}"/>
科学计数法:<property name="capacity" value="#{1e4}"/>
String可以使用单引号或者双引号作为字符串的定界符号:<property name=“name” value="#{'Chuck'}"/>
或 <property name='name' value='#{"Chuck"}'/>
Boolean:<property name="enabled" value="#{false}"/>
引用 Bean、属性和方法 1.引用其他对象:1
2
<!-- 通过value属性和SpEL配置bean之间的关系 -->
<property name="prefix" value="#{prefixGenerator}"></property>
2.引用其他对象的属性:1
2
<!-- 通过value属性和SpEL配置suffix属性值为另一个bean的suffix的属性值 -->
<property name="suffix" value="#{sequenceGenerator2.suffix}"></property>
3.调用其他方法,还可以链式操作:1
2
3
4
<!-- 通过value属性和SpEL配置suffix属性值为另一个bean的方法的返回值 -->
<property name="suffix" value="#{sequenceGenerator2.toString}"></property>
<!-- 方法的连缀 -->
<property name="suffix" value="#{sequenceGenerator2.toString.toUpperCase()}" />
4.调用静态方法或静态属性:通过 T() 调用一个类的静态方法,它将返回一个 Class Object,然后再调用相应的方法或属性:1
<property name="initValue" value="#{T(java.lang.Math).PI}" />
SpEL支持的运算符号 1.算数运算符:+, -, *, /, %, ^:1
2
3
4
5
6
<property name="adjustedAmount" value="#{counter.total + 2}" />
<property name="adjustedAmount" value="#{counter.total - 2}" />
<property name="circumference" value="#{2 * T(java.lang.Math).PI * circle.radius}" />
<property name="average" value="#{counter.total / counter.count}" />
<property name="remainder" value="#{counter.total % counter.count}" />
<property name="area" value="#{T(java.lang.Math).PI * circle.radius ^ 2}" />
2.加号还可以用作字符串连接:1
<constructor-arg value="#{performer.firstname + ' ' + performer.lastname}"/>
3.比较运算符: <, >, ==, <=, >=, lt, gt, eq, le, ge1
<property name="equal" value="#{counter.total == 100}" />
4.逻辑运算符号: and, or, not, |1
2
3
<property name="largeCircle" value="#{shape.kind == 'circle' and shape.perimeter gt 10000}" />
<property name="outOfStock" value="#{!product.available}" />
<property name="outOfStock" value="#{not product.available}" />
5.if-else 运算符:?: (ternary), ?: (Elvis)1
<constructor-arg value="#{songSelector.selectSong()=='Jingle Bells' ? 'pinao':'Jingle Bells'}" />
6.if-else 的变体1
<constructor-arg value="#{kenny.song ?:'Greensleeves'}" />
7.正则表达式:matches1
<constructor-arg value="#{admin.email matches '[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,4}'}" />