EL——表达式语言
一、了解表达式语言
在JSP中为了实现动态内容,需要编写很多Java代码,但是不鼓励使用态多的Java代码,因为这样会降低jsp页面的可读性,前端代码与Java代码混合大大降低了可读性。为了解决这个问题,就出现了EL——表达式语言。
表达式语言最初源自于jsp标准标签库(JSTL)的一部分,用于在不使用脚本、声明或者表达式的情况下,在jsp页面中渲染。
二、EL的基本语法
在页面渲染的时候,被JSP引擎解析和执行。发现EL后在继续执行其他页面部分之前执行它。
${expr}
美元符号和开始/结束花括号定义了EL的边界。
可以用转义符“\”将表达式转义,jsp解释器不降它认定为表达式。
\${not an EL expression}
三、使用EL语法
EL语法是弱类型,并且包含了很多内建的隐式类型转换,表达式的主要规则是执行后要产生某个值,不能在表达式中声明变量、执行赋值语句或者不产生结果的操作。
1、保留关键字
true、false、null、instanceof、empty、div、mod、and、or、not、eq、ne、lt、gt、le、ge。
2、运算符优先级按照优先级排列
第一种:[]和“.”
${myCollection[“key”].memberName[“anotherKey”]}
这两个运算符是用来访问对象中的方法,或者遍历列表用。相当于java中的“.”。
第二种:()
括号会改变执行次序。
第三种:负号“-”、not、!和empty
第四种:数学运算符(优先级排列在一行的为同一级,从左到右执行)
×、/、div、%、和mod
+、 -
+=(在EL表达式中代表字符串连接符)
< 、 >、<=、>=、
== 、!=
&&
||
···?·· :··
->(lambda表达式操作符)
=
注:①在EL表达式中可以同时使用多个表达式,中间用“;”隔开,但是只有最后一个表达式的值会被保留下来。
②EL表达式将使用“==”操作符测试对象是否相等,而不是调用equals方法,并且在EL中无法测试两个引用是否相同。
3、字面量
字面量是一个新的叫法,可以将它理解为变量。
①字符串字面量
EL中字符串字面量可以用双引号或者单引号引起来。
在JSP标签中使用EL表达式字符串字面量,特性值两边的引号会和字面量两边的 引号发生冲突,解决方法是一、使用不同 的引号类型,二、将字面量的引号转义
<c:url value= “${“Value”}”/> //无效
<c:url value= ‘${‘value’}’/> //无效
<c:url value= “${‘value’}”> //有效
<c:url value= “${\‘value\’}”> //有效
②数值字面量
EL语言是弱类型,会自动识别其中的字面量类型,并转换至相应的类型,而且只允许十进制的字面量,字面量必须是连续的。
③原生字面量
char、byte、short
④集合自变量
集合:{1,2,‘three’,4} HashSet<Object>
列表:[1,2,’three’,[x,y],] ArrayList<Object>
Map:{‘one’:1,’two’:2} HashMap<Object,Object>
4、对象属性和方法
一个例子说明
访问属性:
${shirt.size},shirt是一个JavaBean,
相当于:shirt.getSize()
访问方法:
${shirt.getSize()}
5、静态字段和方法访问
使用完全限制的类名,接着是点符,再接着字段或方法名。如果JSP page已经导 入该类,就不用使用完全限制类名。只可以读取不可以修改。还可以调用类的构造方法,它将返回一个该类的实例。
${java.lang.Integer.MAX_VALUE}
${Integer.MAX_VALUE}
${com.wrox.User(‘firt’).fisrtName} //访问构造方法
${int:reverse(42)}
6、集合
EL可以使用点和括号操作符轻松的访问集合。
注:点操作符访问时,键名必须是java中的标识符。不可以将列表的索引当做属 性然后通过点操作符访问。集合和队列不能通过EL访问,只能遍历。
${list[0]}
${list[“0”]}
${empty set} //检查是否为空。
7、使用隐式的EL变量
如果访问的变量重名但是作用域不同那么他将访问所有作用域中优先级别最高的。
PageContext, 唯一一个不是Map的隐式变量。
pageScope,
requestScope,
sessionScope,
applicationScope,
header,
initParam, 应用程序中ServletContext实例的所有上下文参数。
Cookie
8、lambda表达式
lambda表达式就是一个匿名的函数。
格式:表达式参数 -> 表达式
例:a->a + 5
意思是:将a变量的值加5
(a,b)->a+b
${((a,b)->a+b)(4,7)}
该表达式的结果是11,将4和7分别赋给a和b然后进行相加。
${v = (a,b)-> a+b;v(3,5)}
lambda表达式还可以作为参数传入,下一小节中将会看到。
9、使用流API访问集合
流API的基础是所有Collection中存在的无参stream方法,该方法返回java.util.stream.Stream类的对象,该对象可以过滤和操作集合的副本。
在流中的操作并不会改变原来的集合。
一、中间操作
1、过滤流
作用:见名知意,过滤出自己想要的信息
使用:过滤流操作接受一个谓词参数(一个lambda)表达式,该表达式返回一个布尔值并接受一个类型为流的泛型类型的参数。
${books.stream().filter(b->b.author == “Simth”)}
谓词:b->b.author == “Simth”;
结果返回,该流中通过lambda验证为真的所有图书。
2、操作值
ForEeach();
使用forEach操作流中的值。接收一个作用于流中所有元素的lambda表达式。对流中的值进行操作。
3、对流进行排序
实例:${books.stream().sorted(b1,b2) ->b1.title.compareTo(b2.title)}
按照标题对书进行排序。
4、限制流的大小
通过limit和substream操作可以限制流的元素数。
Limit:去掉一部分元素所剩余的元素。
Substream:可以指定开始索引和结束索引
${books.stream().limit(10)}
${books.stream().substream(10,20)}
5、转换流
可以将符合条件的流转换成另外一种表现形式
${books.stream().map([b->b.title,b.author])}
将返回一个包含书名和作者的列表。
二、终结操作
所谓终结操作就是在中间操作的基础上将流进行最终操作
1、返回集合
例:${books.stream().map(b->b.title).toArray()};
将流中的元素保存在列表中。
2、使用聚集函数
和返回集合使用方法类似,最后使用聚集函数对流中元素进行操作。如:
${books.stream().map(b->b.price()).min()} 筛选出价格最低的书。
3、返回第一个值
应用findFirst操作可以返回结果流中的第一个元素。
${books.stream().filter(b->b.author == “Smith”).findFirst()}