JavaWeb学习笔记(十八)--EL表达式
1. EL表达式简介
EL 全名为Expression Language。EL主要作用:
- 获取数据:EL表达式主要用于替换JSP页面中的**脚本表达式,以从各种类型的 web域中检索Java对象**,获取数据。(某个web域中的对象,访问Jabvbean的属性,List集合,Map集合,数组)
- 执行运算:利用EL表达式可以在JSP页面中执行一些基本的关系运算,逻辑运算和算术运。
- 获取web开发的常用对象:EL表达式定义了一些隐式对象,利用这些隐式对象,web开发人员可以很轻松的获取对web常用对象的引用,从而获得这些对象中的数据。
- 调用Java方法:EL表达式允许用户开发自定义的EL函数,以在JSP页面中通过EL表达式调用Java类的方法。
补充说明:EL表达式中$不能嵌套,只需要在最{}外面使用一个$即可。
1.1 获取数据
使用EL表达式获取数据语法: ${标识符}
EL表达式语句在执行时,会调用pageContext.findAttribute方法,用标识符为关键字,分别从page、request、session、application四个域中查找对应的对象,找到返回响应的对象,找不到则返回“”(注意是空字符串,不是null)
EL表达式也可以很轻松的获取JavaBean的属性,获取数组、Colleciton、Map的数据。
结合JSTL的foreach标签,使用EL表达式可以很轻松的迭代各种类型的数组或集合。
如何使用JSTL核心标签:
首先需要导入JSTL的jar包,访问https://tomcat.apache.org/download-taglibs.cgi 下载如下3个Jar包,导入到JaveWeb工程中:
Impl:taglibs-standard-impl-1.2.5.jar (pgp, sha512)
Spec:taglibs-standard-spec-1.2.5.jar (pgp, sha512)
EL:taglibs-standard-jstlel-1.2.5.jar (pgp, sha512)
在JSP中引用核心标签库:
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
uri的地址可以在taglibs-standard-impl-1.2.5.jar中的c.tld的uri标签中获取,所有的核心标签也在此文件中标注说明。
举例:
package javabean; public class Person { private String name; private int personAge; private Address address; public Person() { } public Person(String name) { this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return personAge; } public void setAge(int personAge) { this.personAge = personAge; } public Address getAddress() { return address; } public void setAddress(Address address) { this.address = address; } }
package javabean; public class Address { private String city; public String getCity() { return city; } public void setCity(String city) { this.city = city; } }
<%@ page import="javabean.Person" %> <%@ page import="javabean.Address" %> <%@ page import="java.util.List" %> <%@ page import="java.util.ArrayList" %> <%@ page import="java.util.Map" %> <%@ page import="java.util.HashMap" %> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <html> <head> <title>EL表达式获取数据</title> </head> <body> <b>获取字符串:</b><br> <% request.setAttribute("data", "requestDate"); %> data=${data}<br> <hr> <% Person p = new Person(); p.setName("zhangsan"); p.setAge(18); Address address = new Address(); address.setCity("beijing"); p.setAddress(address); request.setAttribute("person", p); %> <b>获取JavaBean的属性:</b><br> name = ${person.name}<br> age = ${person.age}<br> <!--可以看到这个是根据getAge方法进行匹配的,属性名是personAge --> address = ${person.address.city} <hr> <% List<Person> personList = new ArrayList<>(); Person p1 = new Person("zhangsan"); Person p2 = new Person("lisi"); personList.add(p1); personList.add(p2); request.setAttribute("personList", personList); %> <b>获取List中的数据:</b><br> person1 name = ${personList[0].name}<br> person2 name = ${personList[1].name}<br> <hr> <b>遍历List中的数据:</b><br> <c:forEach var="p" items="${personList}"> name=${p.name}<br> </c:forEach> <hr> <% Map<String, String> map = new HashMap<>(); map.put("aaa", "aaa"); map.put("bbb", "bbb"); map.put("111", "111"); request.setAttribute("map", map); %> <b>获取Map中的数据:</b><br> ${map.aaa}<br> ${map.bbb}<br> ${map["111"]} <!-- 数字不能使点号获取,需要使用[]获取。如果出现不能用点号获取数据的情况,可使用[]获取 --> <hr> <b>遍历Map中的数据:</b><br> <c:forEach var="entry" items="${map}" > ${entry.key} = ${entry.value}<br> </c:forEach> </body> </html>
运行结果:
1.2 执行运算
语法:${运算表达式},EL支持如下运算符:
- 算数运算符: +、-、*、/、%
- 关系运算符: ==、!=、<、>、<=、>=,也可以使用eq、ne、 lt、gt、le、ge
- 逻辑运算符:&&、|| 、!,也可以使用and、or、not
- empty运算符:检查对象是否为空或者为null
- 二元表达式: 表达式? value1 : value2
- []和.号运算符
举例:
<%@ page import="java.util.ArrayList" %> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>运算符</title> </head> <body> <% request.setAttribute("username","aaa"); request.setAttribute("password","124"); %> ${username=='aaa' && password=='123' } <br/>----------------empty运算符-------------------------<br/> <% request.setAttribute("list1",null); request.setAttribute("list2",new ArrayList()); %> ${empty(list1)}<br> ${empty(list2)} <br/>----------------二元运算符-------------------------<br/> ${user!=null ? user.username : '' } <br/>----------------二元运算符(数据回显)-------------------------<br/> <% request.setAttribute("gender","male"); %> <input type="radio" name="gender" value="male" ${gender=='male'?'checked':'' }>男 <input type="radio" name="gender" vlaue="female" ${gender=='female'?'checked':'' }>女 </body> </html>
运行结果:
1.3 获取web开发的常用对象
EL表达式中定义了11个隐含对象,使用这些隐含对象可以很方便的获取web开发中的一些常见对象,并读取这些对象的数据。
语法:${隐式对象名称}
隐含对象的名称| | 描述 |
pageContext | JSP页面中的pageContext对象 |
pageScope | 代表page域中用于保存属性的Map对象 |
requestScope | 代表request域中用于保存属性的Map对象 |
sessionScope | 代表sessionScope域中用于保存属性的Map对象 |
applicationScope | 代表applicationScope域中用于保存属性的Map对象 |
param | 表示一个保存了所有请求参数的Map对象 |
paramValues | 表示一个保存了所有请求参数的Map对象,它对每个请求参数返回的是一个String[] |
header | 表示一个保存了所有请求头字段的Map对象 |
headerValues | 表示一个保存了所有请求头字段的Map对象,对每个请求头字段返回一个String[]。如果头面有"-",例如Accept-Encoding,这要使用headerValues["Accept-Encoding"] |
cookie | 表示保存了所有cookie的Map对象 |
initParam | 表示一个保存了所有web应用初始化参数的map对象 |
举例:
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>EL隐式对象</title> </head> <body> ${pageContext} <br/>----------------使用el隐式对象访问指定的域-------------------------<br/> <% pageContext.setAttribute("aa","11"); request.setAttribute("bb", "22"); session.setAttribute("cc", "33"); application.setAttribute("dd", "44"); %> ${pageScope.aa} ${requestScope.bb} ${sessionScope.cc} ${applicationScope.dd} <br/>----------------获取保存了所有请求参数的Map对象-------------------------<br/> ${param.name} 可以用于数据回显(使用reque跳转),分页的参数传递等<br> ${paramValues} ${paramValues.name[0]} ${paramValues.name[1]} <br/>----------------获取请求头-------------------------<br/> ${header.connection} ${header['Accept-Language'] }<br> ${headerValues} <br/>---------------获取cookie-------------------------<br/> ${cookie.JSESSIONID.name }<br/> ${cookie.JSESSIONID.value }<br> <br/>---------------获取web应用初始化参数---------------<br/> dbType=${initParam.dbType } </body> </html>
运行结果:
1.4 调用Java代码
EL表达式允许开发人员开发自定义函数,以调用Java类的方法。
示例:${prefix: method(params}
在EL表达式中调用的只能是Java类的静态方法
这个Java类的静态方法需要在TLD文件中描述,才可以个被EL表达式调用
EL自定义函数用于扩展EL表达式的功能,可以让EL表达式完成普通Java程序代码所能完成的功能。
1.4.1 EL函数的开发步骤:
一般来说,EL自定义函数开发与应用包括以下三个步骤:
- 编写一个Java类的静态方法
- 编写标签库描述符文件(tld),在tld文件中描述自定义函数
- 在JSP页面中导入和使用自定义函数
举例:
1. 增加一个类,并实现一个静态方法:
package com.utils; public class StringUtils { public static String addTwoString(String s1, String s2) { return s1 + s2; } }
2. 编写标签库描述符文件(tld),在tld文件中描述自定义函数
可以拷贝taglibs-standard-impl-1.2.5.jar中的fn.tld中的内容,再做适当删减。
<?xml version="1.0" encoding="UTF-8" ?> <taglib xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd" version="2.0"> <description>my functions library</description> <display-name>my functions</display-name> <tlib-version>1.1</tlib-version> <short-name>myfn</short-name> <!--定义当前文件的uri,用于在其他jsp中引用:<%@ taglib prefix="myfn" uri="/myELFunction" %> --> <uri>/myELFunction</uri> <!--使用<function>标签定义一个EL自定义函数 --> <function> <description>add two String</description> <name>addTwoString</name> <!-- 方法名称 --> <function-class>com.utils.StringUtils</function-class> <!-- 完整类名 --> <!-- 方法签名,也就是方法声明,必须致命方法的返回值类型以及各个参数的类型,各个参数之间使用逗号分隔 --> <function-signature>java.lang.String addTwoString(java.lang.String,java.lang.String)</function-signature> </function> </taglib>
3. 在JSP页面中导入和使用自定义函数
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@ taglib prefix="myfn" uri="/myELFunction" %> <html> <head> <title>调用Java方法</title> </head> <body> ${myfn:addTwoString("aaa", "bbb")} </body> </html>
运行结果:
1.4.2 开发EL函数注意事项
编写完标签库描述文件后,需要将它放置到WEB-INF目录中或者WEB-INF目录下的处理classes和lib目录之外的任意子目录中。
TLD文件中的<uri>元素用来指定该TLD文件的URI,在JSP文件中需要通过这个URI来引入该标签库描述文件。
<function>元素用于描述一个EL自定义函数,其中:
- <name>子元素用于指定EL自定义函数的名称。
- <function-class>子元素用于指定`完整的Java类名`。
- <function-signature>子元素用于指定Java类中的静态方法签名,方法签名必须指明方法的返回值类型及各个参数的类型,各个参数之间使用逗号分隔。
1.4.3 扩展:显示登录用户的另一种方式(不使用if标签)
<%@ page import="javabean.User" %> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@ taglib prefix="myfn" uri="/myELFunction" %> <html> <head> <title>主页</title> </head> <body> <% User user = new User(); user.setUsername("zhangsan"); session.setAttribute("user", user); %> <!-- el表达式中字符串不能使用+连接,需要自定义函数 --> ${user != null ? myfn:addTwoString("欢迎您:",user.username) : ''} </body> </html>
运行结果:
2. SUN公司的EL函数库
由于在JSP页面中显示数据时,经常需要对显示的字符串进行处理,SUN公司针对一些常见的处理定义了一套EL函数库供开发者使用。
在taglibs-standard-impl-1.2.5.jar的fn.tld中可以查看EL函数库的url和定义的函数。在其他JSP中导入即可使用:<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn"%>
常见函数:
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <html> <head> <title>EL函数库</title> </head> <body> <br><b>------------contains方法-----------------------</b><br> contains("abcd", "bc"): ${fn:contains("abcd", "bc")} <br>------------containsIgnoreCase方法-------------<br> containsIgnoreCase方法("abcd", "Bc"): ${fn:contains("abcd", "Bc")} <br><b>------------escapeXml方法----------------------</b><br> <c:set var="string1" value="This is first String."/> <c:set var="string2" value="This <abc>is second String.</abc>"/> 使用 escapeXml() 函数:<br> string (1) : ${fn:escapeXml(string1)}<br> string (2) : ${fn:escapeXml(string2)}<br> 不使用 escapeXml() 函数:<br> string (1) : ${string1}<br> string (2) : ${string2} <br><b>------------indexOf方法------------------------</b><br> indexOf("www.baidu.com", "."): ${fn:indexOf("www.baidu.com", ".")} <br><b>------------length方法-------------------------</b><br> <!-- length 可以用于任何对象 --> <% request.setAttribute("arr", new String[5]); request.setAttribute("str", "abcdefgh"); %> arr.length: ${fn:length(arr)}<br> str.length: ${fn:length(str)} <br><b>------------replace方法------------------------</b><br> replace("www,baidu,com", ",", "."): ${fn:replace("www,baidu,com", ",", ".")} <br><b>------------split方法--------------------------</b><br> split("2019-01-01", "-"): ${fn:split("2019-01-01", "-")} <br><b>------------join方法---------------------------</b><br> join(split("www,baidu,com"), "."): ${fn:join(fn:split("www,baidu,com", ","), ".")} <br><b>------------startsWith方法---------------------</b><br> startsWith("abcd", "ab"): ${fn:startsWith("abcd", "ab")} <br><b>------------endsWith方法-----------------------</b><br> endsWith("abcd", "bcd"): ${fn:endsWith("abcd", "bcd")} <br><b>------------substring方法----------------------</b><br> substring("0123456789", 2, 4) : ${fn:substring("0123456789", 2, 4)} substring("0123456789", 2, -1) : ${fn:substring("0123456789", 2, -1)} <br><b>------------substringAfter方法-----------------</b><br> substringAfter("2019-01-01", "-"): ${fn:substringAfter("2019-01-01", "-")} <br><b>------------substringBefore方法----------------</b><br> substringBefore("2019-01-01", "-"): ${fn:substringBefore("2019-01-01", "-")} <br><b>------------toLowerCase方法--------------------</b><br> toLowerCase("aBcD"): ${fn:toLowerCase("aBcD")} <br><b>------------toUpperCase方法--------------------</b><br> toUpperCase("aBcD"): ${fn:toUpperCase("aBcD")} <br><b>------------trim方法---------------------------</b><br> trim(" ab cd ef gh "): ${fn:trim(" ab cd ef gh ")} <br><b>---------------取出用户填写的爱好回显------------------</b><br> <% request.setAttribute("likes",new String[]{"football","sing"}); %> <input type="checkbox" name="likes" value="sing" ${fn:contains(fn:join(likes,","),"sing")?'checked':'' }>唱歌 <input type="checkbox" name="likes" value="dance" ${fn:contains(fn:join(likes,","),"dance")?'checked':'' }>跳舞 <input type="checkbox" name="likes" value="basketball" ${fn:contains(fn:join(likes,","),"basketball")?'checked':'' }>篮球 <input type="checkbox" name="likes" value="football" ${fn:contains(fn:join(likes,","),"football")?'checked':'' }>足球 </body> </html>
运行结果: