一. SpringEL入门
Spring动态语言(简称SpEL) 是一个支持运行时查询和操作对象图的强大的动态语言,语法类似于EL表达式,具有诸如显示方法和基本字符串模板函数等特性.
1. 准备工作
需要导入jar包
spring-expression.jar
maven项目pom文件添加:
1 <dependency> 2 <groupId>org.springframework</groupId> 3 <artifactId>spring-expression</artifactId> 4 <version>4.3.10.RELEASE</version> 5 </dependency>
测试:
1 /** 2 * 在SpEL中,使用表达式非常简单,只需创建一个SpelExpressionParser实例即可,也就是首先创建一个SpEL *表达式解析器,然后调用ExpressionParser#parseExpression()方法对表达式进行解析,其中单引号表示 3 *String类型. 4 */ 5 public class SpelHello { 6 public static void main(String [] args){ 7 //TODO 测试SPRINGEL表达式 8 ExpressionParser parser = new SpelExpressionParser(); 9 Expression exp = parser.parseExpression("'hello'+'world'"); 10 String value = (String) exp.getValue(); 11 System.out.println(value); //helloworld 12 } 13 }
注意: SpEL被设计成一个可独立运行的模块,可以脱离Spring容器直接运行,因此只需引入SpEL的模块spring-expression即可,无须引入Spring的其他框架,接下来,在代码中就可以使用SpEL提供表达式解析类.
二.SpringEL核心接口
SpringEL的核心接口和核心类全部位于 org.springframework.expression包及其子包,以及spel.support中.
1. 核心接口介绍
ExpressionParser: 解析表达式字符串,表达式字符串是一个用单引号标注或者用转义的双引号标注的字符串.
Expression: 接口用来计算表达式字符串值
SpringEL支持一系列功能特性,比如方法调用,属性调用及构造器调用.
例如:
1 @Test 2 public void test1(){ 3 //TODO 测试SPRINGEL表达式解析函数 4 ExpressionParser parser = new SpelExpressionParser(); 5 Expression exp = parser.parseExpression("'hello'+'world'.concat('!!!')"); 6 String value = (String) exp.getValue(); 7 System.out.println(value); //输出结果helloworld!!! 8 }
2. EvaluationContext接口
示例:
1 @Test 2 public void test2(){ 3 //TODO 测试 EvaluationContext 4 User user = new User(); 5 user.setUserName("张三"); 6 user.setCredits(100); 7 ExpressionParser parser = new SpelExpressionParser(); 8 9 /** 10 * 创建一个 StandardEvaluationContext实例,指定一个跟对象作为求值目标对象,这样在求值表达式中就可以引用根 11 * 对象属性.在求值内部可以使用反射机制从注册对象中获取相应的属性. 12 */ 13 EvaluationContext context = new StandardEvaluationContext(user); 14 15 String userName = (String) parser.parseExpression("userName").getValue(context); 16 17 System.out.println(userName); 18 }
示例:
1 public class Simple { 2 public List<Boolean> booleansList = new ArrayList<Boolean>(); 3 4 }
测试:
1 @Test 2 public void test3(){ 3 //TODO 测试 EvaluationContext 4 //1 5 Simple simple = new Simple(); 6 simple.booleansList.add(true); //给Simple对象 属性的集合中添加一个值 7 //2 8 StandardEvaluationContext simpleContext = new StandardEvaluationContext(simple); 9 ExpressionParser parser = new SpelExpressionParser(); 10 //3 11 Expression expression = parser.parseExpression("booleansList[0]"); 12 //4 13 expression.setValue(simpleContext,"false"); 14 //5 15 Boolean bl = simple.booleansList.get(0); 16 System.out.println("bl---->"+bl); //输出结果: b1 - false 17 }
-
-
创建StandardEvaluationContext的内部使用反射机制创建Simple操作对象.
-
创建SpEL表达式
-
给SpEL表达式设置操作上下文对象. 以及设置对应的值
-
获取修改后的结果!
三. SpEL基础表达式
文本表达式支持字符串,日期,数字(正数,实数及十六进制数),布尔类型及null,其中字符串需使用单引号或者反斜杠+双引号包含起来,如" 'String类型' " , " "String类型" ",单引号字符可使用 " ' " 表示.
test:
1 @Test 2 public void test4(){ 3 //TODO SpEL基本类型解析 4 ExpressionParser parser = new SpelExpressionParser(); 5 //1.解析字符串 6 String hellworld =(String) parser.parseExpression(""hello world"").getValue(); 7 //2.解析双精度浮点 8 double doubleNumber = (Double) parser.parseExpression("3.1415926").getValue(); 9 //3.解析整数 10 int maxValue = (Integer) parser.parseExpression("0xFFFFFF").getValue(); 11 //4.解析boolean类型 12 boolean value = (Boolean) parser.parseExpression("true").getValue(); 13 //5.解析空值 14 Object nullValue = parser.parseExpression("null").getValue(); System.out.println(hellworld+doubleNumber+maxValue+value+nullValue); 15 16 }
2. 对象属性解析
在SpringEL中,可使用类似 "xxx.yyy.zzz" 的对象属性路径轻松的访问对象属性值.
1 public class Place { 2 private String city; 3 public Place(String city) { 4 this.city = city; 5 } 6 public String getCity() { 7 return city; 8 } 9 public void setCity(String city) { 10 this.city = city; 11 } 12 }
创建User类:
1 public class User { 2 private String userName; 3 private Integer credits; 4 private Place place; 5 public Place getPlace() { 6 return place; 7 } 8 public void setPlace(Place place) { 9 this.place = place; 10 } 11 public String getUserName() { 12 return userName; 13 } 14 public void setUserName(String userName) { 15 this.userName = userName; 16 } 17 public Integer getCredits() { 18 return credits; 19 } 20 public void setCredits(Integer credits) { 21 this.credits = credits; 22 } 23 }
测试:
1 @Test 2 public void test5(){ 3 //TODO 获取对象属性值 4 User user = new User(); 5 user.setCredits(100); 6 user.setUserName("王老五"); 7 user.setPlace(new Place("葫芦岛")); 8 //构建SpEL解析上下文 9 ExpressionParser parser = new SpelExpressionParser(); 10 EvaluationContext context = new StandardEvaluationContext(user); 11 //基本属性值获取 12 String username = (String)parser.parseExpression("userName").getValue(context); 13 System.out.println("username = " + username); 14 //支持运算 15 int credits = (Integer)parser.parseExpression("credits+10").getValue(context); 16 System.out.println("credits = " + credits); 17 //获取嵌套对象属性值 18 String city = (String)parser.parseExpression("place.city").getValue(context); 19 System.out.println("city = " + city); 20 21 }
3. 数组,集合类型解析
在SpEL中,支持数组,集合类型解析.数组支持标准Java语言创建方法,如"new int []{1,2,3}".List支持大括号括起来的内容,数据项之间用逗号隔开,如 "{1,2,3,4,5}", "{{'a','b'},{'c','d'}}".目前SpEL还不支持多维数组初始化,如 "new int[2][3]
1 @Test 2 public void test6(){ 3 //TODO 测试数组集合解析 4 ExpressionParser parser = new SpelExpressionParser(); 5 EvaluationContext context = new StandardEvaluationContext(user); 6 //数组获取 7 int [] array1 = (int[]) parser.parseExpression("new int[]{1,2,3}").getValue(); 8 System.out.println(Arrays.toString(array1)); 9 //集合获取 10 List list = (List) parser.parseExpression("{1,2,3,4}").getValue(); 11 12 List tList = (List) parser.parseExpression("{{123,456},{789,111}}").getValue(); 13 14 System.out.println(list+" "+tList); 15 //Map数据操作 16 Map map= (Map) parser.parseExpression("{username:'tom',age:11}").getValue(); 17 List mList = (List) parser.parseExpression("{{username:"aaa"},{username:'zhanfsan'}}").getValue(); 18 System.out.println("mList = " + mList+" "+map); 19 20 } 21 //输出结果 22 [1, 2, 3] 23 [1, 2, 3, 4] 24 [[123, 456], [789, 111]] 25 mList = [{username=aaa}, {username=zhanfsan}] 26 {username=tom, age=11}
4. 方法解析
在SpEL中,方法调用支持Java可访问的方法,包括对象方法,静态方法,支持可变方法参数;还可以使用String类型的所有可访问的方法,如String#substring()
修改User类:
1 public class User { 2 private String userName; 3 private Integer credits; 4 private Place place; 5 public String [] arr; 6 /** 7 * 添加三个方法 使用spel调用 8 * 共有方法 9 * 静态方法 10 * 私有方法 11 */ 12 public Boolean method1(String value){ 13 return value.equalsIgnoreCase("admin") ; 14 } 15 public static Boolean method2(String value){ 16 return value.equalsIgnoreCase("admin"); 17 } 18 private Boolean method3(String value){ 19 return value.equalsIgnoreCase("admin") 20 } 21 //setter getter 22 }
测试:
1 @Test 2 public void test7(){ 3 //TODO 测试SPEL调用方法 4 User user = new User(); 5 EvaluationContext context = new StandardEvaluationContext(user); 6 ExpressionParser parser = new SpelExpressionParser(); 7 //调用String方法 8 String sbString = parser.parseExpression("'Spring'.substring(2)").getValue(String.class); 9 System.out.println("sbString = " + sbString); 10 Integer index = parser.parseExpression("'Spring'.indexOf('p')").getValue(Integer.class); 11 System.out.println("index = " + index); 12 //调用实例方法 13 //共有方法 14 boolean method1 = (Boolean) parser.parseExpression("method1('123')").getValue(context); 15 System.out.println(method1); 16 17 //静态方法 18 boolean method2 = (Boolean) parser.parseExpression("method2('admin')").getValue(context); 19 System.out.println(method2); 20 /** 结果集 21 sbString = ring 22 index = 1 23 false 24 true 25 */ 26 //私有方法 27 boolean method3 = (Boolean) parser.parseExpression("method3('aaa')").getValue(context); 28 System.out.println("method3 = " + method3); 29 //此处报错 30 }
5. 操作符解析
SpEL提供了丰富的操作符解析,支持关系操作付符,逻辑操作符号,算术运算操作符等...
关系操作符:
1 @Test 2 public void test8(){ 3 //测试运算符 4 ExpressionParser parser = new SpelExpressionParser(); 5 Boolean value = parser.parseExpression("2==2").getValue(Boolean.class); 6 System.out.println("value = " + value); 7 Integer sum = parser.parseExpression("2+2").getValue(Integer.class); 8 System.out.println("sum = " + sum); 9 /** 10 * 输出结果: value = true sum = 4 11 */ 12 }
1 User user = new User(); 2 EvaluationContext context = new StandardEvaluationContext(user); 3 //setValue方法赋值 4 ExpressionParser parser = new SpelExpressionParser(); 5 parset.parsetEcpression("userName").setValue(context,"userName");
1 //表达式直接赋值 2 User user = new User(); 3 EvaluationContext context = new StandardEvaluationContext(user); 4 //setValue方法赋值 5 ExpressionParser parser = new SpelExpressionParser(); 6 parset.parsetEcpression("userName='userName对应的值'").setValue(context);
四. 在Spring中使用SpEL
1. 基于XML配置
1 <bean id="xx" name="xx" class="xx.xx.xx" p:age="#{T(java.lang.Math).random()*100 }"/>
通过SpEL提供的T类型操作符,直接调java.lang.Math的静态方法来生成一个随机数.
1 <bean id="b1" name="xx" class="com.itqf.spring.bean.User"></bean> 2 <!-- id b2 引用 b1 --> 3 <bean id="b2" name="xxx" class="xx.xx.xx"> 4 <property name="userName" value="#{b1.userName }"></property> 5 </bean>
虽然ORM的框架已经成熟丰富,但是JDBC的灵活,直接的特性,依然让他拥有自己的用武之地,如在完全依赖查询模型动态产生查询语句的综合查询系统中,Hibernaye,MyBatis,JPA等框架都无法使用,这里JDBC是唯一的选择.
1. JdbcTemplate入门
1.1 创建项目
引入jar包
pom.xml:
1 <dependencies> 2 <dependency> 3 <groupId>junit</groupId> 4 <artifactId>junit</artifactId> 5 <version>3.8.1</version> 6 <scope>test</scope> 7 </dependency> 8 9 <dependency> 10 <groupId>aopalliance</groupId> 11 <artifactId>aopalliance</artifactId> 12 <version>1.0</version> 13 </dependency> 14 15 <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver --> 16 <dependency> 17 <groupId>org.aspectj</groupId> 18 <artifactId>aspectjweaver</artifactId> 19 <version>1.8.10</version> 20 </dependency> 21 <!-- https://mvnrepository.com/artifact/org.springframework/spring-aspects --> 22 <dependency> 23 <groupId>org.springframework</groupId> 24 <artifactId>spring-aspects</artifactId> 25 <version>4.3.7.RELEASE</version> 26 </dependency> 27 <dependency> 28 <groupId>org.springframework</groupId> 29 <artifactId>spring-aop</artifactId> 30 <version>4.3.10.RELEASE</version> 31 </dependency> 32 <dependency> 33 <groupId>org.springframework</groupId> 34 <artifactId>spring-context-support</artifactId> 35 <version>4.3.11.RELEASE</version> 36 </dependency> 37 38 <dependency> 39 <groupId>org.springframework</groupId> 40 <artifactId>spring-context</artifactId> 41 <version>4.3.10.RELEASE</version> 42 </dependency> 43 <dependency> 44 <groupId>org.springframework</groupId> 45 <artifactId>spring-core</artifactId> 46 <version>4.3.10.RELEASE</version> 47 </dependency> 48 49 <dependency> 50 <groupId>org.springframework</groupId> 51 <artifactId>spring-beans</artifactId> 52 <version>4.3.10.RELEASE</version> 53 </dependency> 54 55 <dependency> 56 <groupId>org.springframework</groupId> 57 <artifactId>spring-expression</artifactId> 58 <version>4.3.10.RELEASE</version> 59 </dependency> 60 61 <!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc --> 62 <dependency> 63 <groupId>org.springframework</groupId> 64 <artifactId>spring-jdbc</artifactId> 65 <version>4.3.9.RELEASE</version> 66 </dependency> 67 <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java --> 68 <dependency> 69 <groupId>mysql</groupId> 70 <artifactId>mysql-connector-java</artifactId> 71 <version>5.1.38</version> 72 </dependency> 73 <dependency> 74 <groupId>commons-logging</groupId> 75 <artifactId>commons-logging</artifactId> 76 <version>1.1.2</version> 77 </dependency> 78 79 <dependency> 80 <groupId>log4j</groupId> 81 <artifactId>log4j</artifactId> 82 <version>1.2.14</version> 83 </dependency> 84 85 <dependency> 86 <groupId>mysql</groupId> 87 <artifactId>mysql-connector-java</artifactId> 88 <version>5.1.38</version> 89 </dependency> 90 91 <!-- https://mvnrepository.com/artifact/commons-dbcp/commons-dbcp --> 92 <dependency> 93 <groupId>commons-dbcp</groupId> 94 <artifactId>commons-dbcp</artifactId> 95 <version>1.4</version> 96 </dependency> 97 98 <!-- https://mvnrepository.com/artifact/org.springframework/spring-test --> 99 <dependency> 100 <groupId>org.springframework</groupId> 101 <artifactId>spring-test</artifactId> 102 <version>4.3.10.RELEASE</version> 103 <scope>test</scope> 104 </dependency> 105 106 <!-- https://mvnrepository.com/artifact/com.mchange/mchange-commons-java --> 107 <dependency> 108 <groupId>com.mchange</groupId> 109 <artifactId>mchange-commons-java</artifactId> 110 <version>0.2.11</version> 111 </dependency> 112 113 <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot --> 114 <dependency> 115 <groupId>org.springframework.boot</groupId> 116 <artifactId>spring-boot</artifactId> 117 <version>1.5.7.RELEASE</version> 118 </dependency> 119 <!-- https://mvnrepository.com/artifact/com.mchange/c3p0 --> 120 <dependency> 121 <groupId>com.mchange</groupId> 122 <artifactId>c3p0</artifactId> 123 <version>0.9.5.2</version> 124 </dependency> 125 <dependency> 126 <groupId>org.springframework</groupId> 127 <artifactId>spring-tx</artifactId> 128 <version>4.3.9.RELEASE</version> 129 </dependency>
导入日志:log4j.properties
1.2 创建数据库
数据库名: springjdbc
创建角色表:
1 CREATE TABLE `role` ( 2 `rid` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '角色id', 3 `rname` VARCHAR(20) NOT NULL COMMENT '角色名', 4 `alias` VARCHAR(20) NOT NULL COMMENT '角色别名', 5 PRIMARY KEY (`rid`) 6 ) 7 8 INSERT INTO role (rid,rname,alias) 9 VALUES(1,'admin','系统管理员'),(2,'dispatcher','调度员');
1.3 测试代码
1 @Test 2 public void test1() throws Exception { 3 //TODO 测试jdbcTemplate简单使用 4 //1.创建c3p0链接池 5 ComboPooledDataSource dataSource = new ComboPooledDataSource(); 6 dataSource.setDriverClass("com.mysql.jdbc.Driver"); dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/springjdbc"); 7 dataSource.setUser("root"); 8 dataSource.setPassword("111"); 9 //创建jdbcTemplate对象 10 JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); 11 //创建sql语句 12 String sql = "insert into role (rid , rname ,alias) value (? , ?,?);"; 13 jdbcTemplate.update(sql,"3","visitor","游客"); 14 }
2. Spring管理JdbcTemplate
1 public class Role { 2 private Integer cid; 3 private String rname; 4 private String alias; 5 //setter getter 6 }
1 public interface RoleDao { 2 3 //增 4 void save(Role role); 5 6 //删除 7 void delete(Integer id); 8 9 //改 10 void update(Role role); 11 12 //查 13 Role getById(Integer id); 14 15 //查 16 int getTotalCount(); 17 18 //查 19 List<Role> getAll(); 20 21 }
3. 创建RoleDaoImpl.java
创建数据源(连接池),JdbcTemplate,RoleDao交给Spring容器管理(IOC)
注意: 可以自己在RoleDaoImpl中添加 JdbcTemplate变量,如果不自动装载记得添加变量的set方法,
标准的操作,我们可以让RoleDaoImpl 继承 JdbcDaoSupport, 因为(org.springframework.jdbc.core.support.JdbcDaoSupport)类提供了JdbcTemplate对象以及对应的获取和设置方法.不用自己在实现类中添加JdbcTemplate变量
1 JdbcTemplate // Spring操作数据模板类(工具类) 2 3 JdbcTemplate.update(sql,ArgsObj....); //DML 4 JdbcTemplate.execute(sql) //DDL DCL 5 //DQL 查询单个 6 jdbcTemplate.queryForObject(String var1, RowMapper<T> var2, Object... var3); 7 RowWapper<T> 将结果封装的处理器; 得到Result解析成实体类对象即可! 8 9 //查询所有 10 jdbcTemplate.query(String var1, RowMapper<T> var2, Object... var3);
RoleDaoImple代码:
1 public class RoleDaoImpl extends JdbcDaoSupport implements RoleDao { 2 3 4 public void save(Role role) { 5 //TODO 插入数据 6 String sql = "INSERT INTO role (rname,alias) value (?,?) ;"; 7 getJdbcTemplate().update(sql,role.getRname(),role.getAlias()); 8 } 9 10 public void delete(Integer id) { 11 //TODO 根据id删除 12 String sql = "delete from role where rid = ? ;"; 13 getJdbcTemplate().update(sql,id); 14 } 15 16 public void update(Role role) { 17 //TODO 修改role信息 18 String sql="update role set rname = ? , alias = ? where rid = ? ;" ; 19 getJdbcTemplate().update(sql,role.getRname(),role.getAlias(),role.getRid()); 20 } 21 22 public Role getById(Integer id) { 23 24 String sql = "select * from role where rid = ? ;"; 25 26 //直接查询 27 // Role role = getJdbcTemplate().queryForObject(sql, new Object[]{id}, Role.class); 28 Role role = (Role) getJdbcTemplate().queryForObject(sql, new Object[]{id}, new RowMapper<Object>() { 29 30 public Object mapRow(ResultSet resultSet, int index) throws SQLException { 31 //将一行数据解析成一个java对象 32 33 return mapRowHandler(resultSet); 34 } 35 }); 36 37 return role; 38 } 39 40 public int getTotalCount() { 41 42 String sql = "select count(*) from role ;"; 43 44 Integer count = getJdbcTemplate().queryForObject(sql,Integer.class); 45 46 return count; 47 } 48 49 //查询所有 50 public List<Role> getAll() { 51 52 String sql = "select * from role"; 53 54 List<Role> list = getJdbcTemplate().query(sql, new RowMapper<Role>() { 55 public Role mapRow(ResultSet resultSet, int i) throws SQLException { 56 57 return mapRowHandler(resultSet); 58 } 59 }); 60 61 return list; 62 } 63 64 private Role mapRowHandler(ResultSet resultSet) throws SQLException{ 65 Role role = new Role(); 66 role.setRid(resultSet.getInt("rid")); 67 role.setRname(resultSet.getString("rname")); 68 role.setAlias(resultSet.getString("alias")); 69 return role; 70 } 71 72 73 }
4. 创建数据库配置文件
文件名:db.properties
1 jdbc.jdbcUrl=jdbc:mysql://localhost:3306/springjdbc 2 jdbc.driverClass=com.mysql.jdbc.Driver 3 jdbc.user=root 4 jdbc.password=xxx
5.编写IOC配置
文件名:applicationContext.xml
位置:src下 / maven项目 resources文件夹下
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xmlns:context="http://www.springframework.org/schema/context" 5 xmlns:p="http://www.springframework.org/schema/p" 6 xsi:schemaLocation=" 7 http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd 8 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!-- bean definitions here --> 9 <context:component-scan base-package="com.itqf.spring"></context:component-scan> 10 <context:property-placeholder location="db.properties"></context:property-placeholder> 11 <bean name="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" p:jdbcUrl="${jdbc.jdbcUrl}" 12 p:driverClass="${jdbc.driverClass}" 13 p:user="root" 14 p:password="xxxx" 15 /> 16 17 <!-- bean jdbcTemplate --> 18 <bean name="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> 19 20 <property name="dataSource" ref="dataSource"/> 21 </bean> 22 23 24 <bean name="roleDao" class="spring.dao.impl.RoleDaoImpl"> 25 <property name="jdbcTemplate" ref="jdbcTemplate"/> 26 </bean> 27 28 </beans>
测试:
1 @Test 2 public void test2(){ 3 //TODO 测试使用配置文件 4 5 ApplicationContext context =new ClassPathXmlApplicationContext("applicationContext.xml"); 6 RoleDao dao = context.getBean("roleDao", RoleDaoImpl.class); 7 8 Role byId = dao.getById(2); 9 System.out.println(byId); 10 11 List<Role> all = dao.getAll(); 12 13 System.out.println("all = " + all); 14 }