5.1  概述

5.1.1  概述

Spring表达式语言全称为“Spring Expression Language”,缩写为“SpEL”,类似于Struts2x中使用的OGNL表达式语言,能在运行时构建复杂表达式、存取对象图属性、对象方法调用等等,并且能与Spring功能完美整合,如能用来配置Bean定义。

表达式语言给静态Java语言增加了动态功能。

SpEL是单独模块,只依赖于core模块,不依赖于其他模块,可以单独使用。

5.1.2  能干什么

表达式语言一般是用最简单的形式完成最主要的工作,减少我们的工作量。

SpEL支持如下表达式:

一、基本表达式:字面量表达式、关系,逻辑与算数运算表达式、字符串连接及截取表达式、三目运算及Elivis表达式、正则表达式、括号优先级表达式;

二、类相关表达式:类类型表达式、类实例化、instanceof表达式、变量定义及引用、赋值表达式、自定义函数、对象属性存取及安全导航表达式、对象方法调用、Bean引用;

三、集合相关表达式:内联List、内联数组、集合,字典访问、列表,字典,数组修改、集合投影、集合选择;不支持多维内联数组初始化;不支持内联字典定义;

四、其他表达式:模板表达式。

注:SpEL表达式中的关键字是不区分大小写的。

5.2  SpEL基础

5.2.1  HelloWorld

首先准备支持SpEL的Jar包:“org.springframework.expression-3.0.5.RELEASE.jar”将其添加到类路径中。

SpEL在求表达式值时一般分为四步,其中第三步可选:首先构造一个解析器,其次解析器解析字符串表达式,在此构造上下文,最后根据上下文得到表达式运算后的值。

让我们看下代码片段吧:

package cn.javass.spring.chapter5;
import junit.framework.Assert;
import org.junit.Test;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
public class SpELTest {
@Test
public void helloWorld() {
ExpressionParser parser = new SpelExpressionParser();
Expression expression =
parser.parseExpression("('Hello' + ' World').concat(#end)");
EvaluationContext context = new StandardEvaluationContext();
context.setVariable("end", "!");
Assert.assertEquals("Hello World!", expression.getValue(context));
}
}

  

接下来让我们分析下代码:

1)创建解析器:SpEL使用ExpressionParser接口表示解析器,提供SpelExpressionParser默认实现;

2)解析表达式:使用ExpressionParser的parseExpression来解析相应的表达式为Expression对象。

3)构造上下文:准备比如变量定义等等表达式需要的上下文数据。

4)求值:通过Expression接口的getValue方法根据上下文获得表达式值。

是不是很简单,接下来让我们看下其具体实现及原理吧。

5.2.3  SpEL原理及接口

SpEL提供简单的接口从而简化用户使用,在介绍原理前让我们学习下几个概念:

一、表达式:表达式是表达式语言的核心,所以表达式语言都是围绕表达式进行的,从我们角度来看是“干什么”;

二、解析器:用于将字符串表达式解析为表达式对象,从我们角度来看是“谁来干”;

三、上下文:表达式对象执行的环境,该环境可能定义变量、定义自定义函数、提供类型转换等等,从我们角度看是“在哪干”;

四、根对象及活动上下文对象:根对象是默认的活动上下文对象,活动上下文对象表示了当前表达式操作的对象,从我们角度看是“对谁干”。

理解了这些概念后,让我们看下SpEL如何工作的呢,如图5-1所示:

图5-1 工作原理

1)首先定义表达式:“1+2”;

2)定义解析器ExpressionParser实现,SpEL提供默认实现SpelExpressionParser;

2.1)SpelExpressionParser解析器内部使用Tokenizer类进行词法分析,即把字符串流分析为记号流,记号在SpEL使用Token类来表示;

2.2)有了记号流后,解析器便可根据记号流生成内部抽象语法树;在SpEL中语法树节点由SpelNode接口实现代表:如OpPlus表示加操作节点、IntLiteral表示int型字面量节点;使用SpelNodel实现组成了抽象语法树;

2.3)对外提供Expression接口来简化表示抽象语法树,从而隐藏内部实现细节,并提供getValue简单方法用于获取表达式值;SpEL提供默认实现为SpelExpression;

3)定义表达式上下文对象(可选),SpEL使用EvaluationContext接口表示上下文对象,用于设置根对象、自定义变量、自定义函数、类型转换器等,SpEL提供默认实现StandardEvaluationContext;

4)使用表达式对象根据上下文对象(可选)求值(调用表达式对象的getValue方法)获得结果。

接下来让我们看下SpEL的主要接口吧:

1)ExpressionParser接口:表示解析器,默认实现是org.springframework.expression.spel.standard包中的SpelExpressionParser类,使用parseExpression方法将字符串表达式转换为Expression对象,对于ParserContext接口用于定义字符串表达式是不是模板,及模板开始与结束字符:

public interface ExpressionParser {
Expression parseExpression(String expressionString);
Expression parseExpression(String expressionString, ParserContext context);
}

  来看下示例:

@Test
public void testParserContext() {
ExpressionParser parser = new SpelExpressionParser();
ParserContext parserContext = new ParserContext() {
@Override
public boolean isTemplate() {
return true;
}
@Override
public String getExpressionPrefix() {
return "#{";
}
@Override
public String getExpressionSuffix() {
return "}";
}
};
String template = "#{'Hello '}#{'World!'}";
Expression expression = parser.parseExpression(template, parserContext);
Assert.assertEquals("Hello World!", expression.getValue());
}

  

在此我们演示的是使用ParserContext的情况,此处定义了ParserContext实现:定义表达式是模块,表达式前缀为“#{”,后缀为“}”;使用parseExpression解析时传入的模板必须以“#{”开头,以“}”结尾,如"#{'Hello '}#{'World!'}"。

默认传入的字符串表达式不是模板形式,如之前演示的Hello World。

2)EvaluationContext接口:表示上下文环境,默认实现是org.springframework.expression.spel.support包中的StandardEvaluationContext类,使用setRootObject方法来设置根对象,使用setVariable方法来注册自定义变量,使用registerFunction来注册自定义函数等等。

3)Expression接口:表示表达式对象,默认实现是org.springframework.expression.spel.standard包中的SpelExpression,提供getValue方法用于获取表达式值,提供setValue方法用于设置对象值。

了解了SpEL原理及接口,接下来的事情就是SpEL语法了。

spring3: 表达式5.2 SpEL基础的更多相关文章

  1. 开涛spring3(5.1&5.2) - Spring表达式语言 之 5.1 概述 5.2 SpEL基础

    5.1  概述 5.1.1  概述 Spring表达式语言全称为“Spring Expression Language”,缩写为“SpEL”,类似于Struts2x中使用的OGNL表达式语言,能在运行 ...

  2. Spring表达式语言 之 5.1 概述 5.2 SpEL基础(拾叁)

    5.1  概述 5.1.1  概述 Spring表达式语言全称为"Spring Expression Language",缩写为"SpEL",类似于Struts ...

  3. spring3表达式语言(SpEL)

    使用SpEl进行表达式操作,基本操作如下: <!--第一步,构建解析 --> ExpressionParser parser = new SpelExpressionParser(); & ...

  4. Spring3表达式语言(SpEL)学习笔记

    最新地址请访问:http://leeyee.github.io/blog/2011/06/19/spring-expression-language Spring Excpression Langua ...

  5. Spring基础13——Spring表达式语言:SpEL

    1.SpEL简介 Spring表达式语言(简称SpEL):是一个支持运行时查询和操作对象图的强大的表达式语言.语法上类似于EL:SpEL使用#{...}作为界定符,所有在大框号中的字符都将被认为是Sp ...

  6. Spring3 表达式语言(SpEL)介绍

    转载自:http://iyiguo.net/blog/2011/06/19/spring-expression-language/ 下一版本 项目需要使用到SpEL ,做一个保存.

  7. Spring表达式语言之SpEL

    •Spring 表达式语言(简称SpEL):是一个支持运行时查询和操作对象图的强大的表达式语言. •语法类似于 EL:SpEL 使用 #{…} 作为定界符,所有在大框号中的字符都将被认为是 SpEL ...

  8. Spring表达式语言:SpEL

    1.Spring表达式语言(简称:SpEL):是一个支持运行时查询和操作对象图的强大的表达式语言. 2.语法类似于EL:SpEL使用#{...}作为定界符,所有在大括号内的字符都被认为是SpEL. 3 ...

  9. JavaWeb之 JSP:内置对象,EL表达式,JSP标签基础

    JSP的内置对象 什么是JSP的内置对象呢? 在JSP页面进行编程的时候,如果我们要使用一些对象,如:HttpSession,ServletConfig,ServletContext这些对象,如果每次 ...

随机推荐

  1. 高德js API moveAlong 函数的一个错误解决

    使用覆盖物之一:点标记,让点标记沿着固定的路线移动. API 提供了现成的函数 moveAlong() 开始以为 实现移动很简单:分两部 1.准备好经纬度数组 2.调用moveAlong()函数.按照 ...

  2. 服务器端Session和客户端Session(和Cookie区别)

    Session其实分为客户端Session和服务器端Session. 当用户首次与Web服务器建立连接的时候,服务器会给用户分发一个 SessionID作为标识.SessionID是一个由24个字符组 ...

  3. Python菜鸟之路:Django 数据验证之钩子和Form表单验证

    一.钩子功能提供的数据验证 对于数据验证,django会执行 full_clean()方法进行验证.full_clean验证会经历几个步骤,首先,对于model的每个字段进行正则验证,正则验证通过后, ...

  4. PHP数组遍历详解

    一.PHP数组简介 1.PHP数组的分类 按照下标的不同分为关联数组和索引数组①索引数组:下标从0开始依次增长②关联数组:下标为字符串格式,每个下标字符串与数组的值一一对应,(有点像对象的键值对) 下 ...

  5. pip 查看已安装模块、卸载指定模块、安装指定版本模块

    操作背景 最近使用 pandas+numpy+plotly 画heatmap(热力图),来处理股票数据,语法.步骤都没问题,但到画图那一步老是报错,且 plotly 版本为3.1.0: 最后找到原因, ...

  6. 《深入理解Linux网络技术内幕》阅读笔记 --- 路由表

    路由表基本概念 1.路由是由多个不同的数据结构的组合来描述的,每个数据结构代表路由信息的不同部分.例如,一个fib_node对应一个单独的子网,一个fib_alias对应一条路由.这样做的原因是只需通 ...

  7. gevent For the Working Python Developer

    Gevent指南   gevent程序员指南 由Gevent社区编写 gevent是一个基于libev的并发库.它为各种并发和网络相关的任务提供了整洁的API. 介绍 贡献者 核心部分 Greenle ...

  8. Django-1版本的路由层、Django的视图层和模板层

    一.Django-1版本的路由层(URLconf) URL配置(URLconf)就像Django所支撑网站的目录.它的本质是URL与要为该URL调用的视图函数之间的映射表:我们就是以这种方式告诉Dja ...

  9. Python井字游戏

    import sys def print_board(): for i in range(3): for j in range(3): print map[2 - i][j], if j != 2: ...

  10. fopen() r+、w+属性详解

    r+具有读写属性,从文件头开始写,保留原文件中没有被覆盖的内容: w+具有读写属性,写的时候如果文件存在,会被清空,从头开始写. r 打开只读文件,该文件必须存在. r+ 打开可读写的文件,该文件必须 ...