EL和JSTL表达式的使用
1、EL表达式介绍
EL的全称为Expression Language,即表达式语言,它是JSP内置的表达式语言。EL的用法比较的简单,就是用 ${ 标识符 } 包起来的语句。我们一般用它来读取数据【如:${username}
】或者 执行运算【也就是基本的关系运算、逻辑运算和算术运算如:${username==null}
】。使用EL表达式最大的特点就是使用很方便,例如获取用户名 ${username}
。
EL表达式的特点:
- 可以自动对获取的数据进行数据类型的转换
- 若通过EL获取的数据为null,则在页面中什么都不显示
- EL一般使用访问属性的方式访问数据
下面对比一下在JSP中获取该属性,如下:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>EL表达式的使用</title>
</head>
<body>
<%
//在session中设置值
session.setAttribute("username","唐浩荣");
//JSP方式获取session中的值
String username = (String) session.getAttribute("username");
//方式一
out.println("JSP方式一获取:"+username);
%>
<br>
<%--方式二--%>
<%= "JSP方式二获取:"+ username%>
<hr>
<%--EL方式获取session中的值--%>
EL方式获取:${username}
</body>
</html>
运行结果如下:
两者相比,可以发现我们之前在JSP中写Java代码必须写在<% %>里面,并且取值代码比较繁琐。而EL表达式可以使我们的取值代码更加简洁方便。
EL表达式除了提供上面这种方式获取数据之外,还提供了其它两种运算符来存取数据:
- 对象 . 属性
- 对象[ "属性名" ]
其中 对象[ "属性名" ] 可以访问集合或者是数组的元素、Bean的属性,但是必须保证需要取得对象的那个属性有相对应的setXxx和getXxx方法才行,因为它是根据setXxx和getXxx方法来获取的,你可以【Ctrl+鼠标左键】选中属性试一试。下面是这两种EL表达式的使用举例:
①、对象 . 属性的使用:
${sessionScope.user.username}
//等价于
${sessionScope.user["username"]}
②、对象[ "属性名" ] 的使用(点和[ ] 可以混合使用)
${sessionScope.user[0].username}
2、EL表达式中的11个隐式对象
在上面看到的sessionScope是EL表达式提供的隐含对象,大家已经知道在JSP中有9个隐含对象(就是9个内置对象),而EL也有自己的隐含对象。EL隐含对象总共有11个(pageScope、requestScope、sessionScope、applicationScope、param 、paramValues、header、headerValues、initParam、cookie、pageContext),不过我们只简单看以下这四个:
EL隐含对象 | 作用 | JSP对象 |
---|---|---|
pageScope | 获取pageContext域对象中的数据 | pageContext |
requestScope | 获取request域对象中的数据 | request |
sessionScope | 获取session域对象中的数据 | session |
applicationScope | 获取application域对象中的数据 | application |
在EL表达式从这四个域中获得某个值的格式为:${xxxScope.key}
;等价于<%xxx.getAttribute(“username”)%>
。而如果我们不指定作用域,直接${username}的话,默认会按照作用域的范围从小到大(page->request->session->application)依次查找,直到找到application为止。如果四个作用域中都没有则返回空字符串(注意:不是null,而是" "),然后什么都不显示。
补充:param和paramValues
①、param的作用:获取请求中的参数,格式:${param.请求参数名}
,等价于:request.getParameter("请求参数名")
②、paramValues的作用:获取多个同名的请求参数,格式:${paramValues.请求参数名}
,等价于request.getParameterValues("请求参数名"),例如:
<a href="${pageContext.request.contextPath}/testParam.jsp?username=admin&hobby=a&hobby=b">testParam.jsp</a>
username:${param.username}<br>
hobby:${paramValues.hobby[0]},${paramValues.hobby[1]}
2、EL表达式的运算
EL的运算符和Java中的运算符基本一致,优先级也相同,但是加号(+)运算符不再是连接了,而是真正的加法运算。
①、四则运算符
四则运算符 | 说明 | 举例 | 结果 |
---|---|---|---|
+ | 加 | ${5+5} |
10 |
- | 减 | ${5-5} |
0 |
* | 乘 | ${5*5} |
25 |
÷ | 除 | ${5÷5} |
1.0 |
②、关系运算符
关系运算符 | 说明 | 举例 | 结果 |
---|---|---|---|
== 或 eq | 等于 | ${5==5}或${5 eq 5} |
true |
!= 或 ne | 不等于 | ${5!=5}或${5 ne 5} |
false |
< 或 lt | 小于 | ${3<5}或${3 lt 5} |
true |
> 或 gt | 大于 | ${3>5}或${3 gt 5} |
false |
<= 或 le | 小于等于 | ${3<=5}或${3 le 5} |
true |
>= 或 ge | 大于等于 | ${3>=5}或${3 ge 5} |
false |
③、逻辑运算符
逻辑运算符 | 说明 | 示例 | 结果 |
---|---|---|---|
&& 或 and | 交集 | ${A && B}或${A and B} |
true/false |
|| 或 or | 并集 | `${A | |
! 或 not | 非 | ${!A}或${not A} |
true/false |
④、empty运算符
该运算用来来检查对象是否为null(空),例如:${empty A}
或者${!empty A}
。
在默认使用empty(不是!empty)的情况下:
- 如果A为null时,返回true,否则返回false。
- 如果A不存在时,返回true,否则返回false。
- 如果A为空字符串时,返回true,否则返回false。
- 如果A为空数组时,返回true,否则返回false。
- 如果A为空的Map时,返回true,否则返回false。
- 如果A为空的Collection时,返回true,否则返回false。
⑤、三元表达式
三元表达式格式为:${user!=null?user.username :" "}。如果?前面结果为true则选择前面的数据,否则选择后面的。
3、JSTL表达式介绍
JSTL标签库(JavaSeverPages Standard Tag Libary)的使用是为弥补HTML标签的不足,规范自定义标签的使用而诞生的。使用JSLT标签的目的就是不希望在JSP页面中出现Java逻辑代码。所以说它和EL一样,也是为了简化我们的JSP代码。JSTL一般与EL表达式结合使用,其中EL表达式多用于取值操作,而JSTL则可以方便我们对集合进行遍历,对数据进行判断等操作。
JSTL标签库可分为5类:
- 核心标签(用得最多)
- 格式化标签(I18N,日期等格式化标签)
- SQL标签(SQL标签,很少使用)
- XML标签(几乎不用)
- JSTL函数(EL函数)
JSTL的核心标签库标签共14个,这些标签能够完成JSP页面的基本功能,减少编码工作。从功能上可以分为4类:表达式控制标签、流程控制标签、循环标签、URL操作标签。
- 表达式控制标签:out标签、set标签、remove标签、catch标签。
- 流程控制标签:if标签、choose标签、when标签、otherwise标签。
- 循环标签:forEach标签、forTokens标签。
- URL操作标签:import标签、url标签、redirect标签、param标签。
首先要使用JSTL就得先下载并且导入相应的包。首先打开这个网站:Standard Taglib。然后选择最新版的JSTL,点击download
可以发现目前最新版本是1.2.5,将下面前两个jar包下载后导入到项目中即可。不会的可以参考这篇博客:IDEA创建一个JavaWeb项目
注意:我们必须要把下载的前两个包拷贝粘贴进WEB-INF下的lib目录中,通过Project Structure(Idea的操作)确保jar包已经引入,否则我们JSTL标签会报错,甚至是JSP访问不了或者报500报错。
然后我们在JSP页面添加标签的引用就可以使用JSTL标签了。引入JSTL的核心标签库如下:
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
- uri:指定引入的标签库的路径
- prefix:设置标签库中标签的前缀,解决标签重名的问题
当然此时也可以发现其他的标签库:
引入格式如下所示:
<%--JSTL 核心标签--%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%--JSTL 格式化标签--%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%--JSTL SQL标签--%>
<%@ taglib prefix="sql" uri="http://java.sun.com/jsp/jstl/sql" %>
<%--JSTL XMLb标签--%>
<%@ taglib prefix="x" uri="http://java.sun.com/jsp/jstl/xml" %>
<%--JSTL 函数标签--%>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
由于核心标签是使用最多的,所以只介绍核心标签库的使用,而且只介绍常用的。
4、JSTL的核心标签库
4.1、普通标签
①、<c:out>标签:用于将结果输出。类似于JSP中的<%= %>表达式,或者是EL表达式$\ expression }。
<%--取值--%>
<c:out value="${userName}"></c:out>
内部属性介绍:
- value:设置要输出到页面的数据,要使用EL表达式
- default:设置一个默认值,当value所设置的EL表达式的值为null时,则将default所对应的值输出到页面
- escapeXml:设置输出到页面中的内容是否转义,默认值为true,表示转义,即原样输出;若设置为false,表示不转义,输出到页面中的内容会被浏览器解析
②、<c:set>标签:用于把某一个对象存在指定的域范围内,或者将某一个对象存储到Map或者JavaBean对象中。
<%--设值--%>
<c:set var="userName" value="tanghaorong" scope="session"></c:set>
内部属性介绍:
- var:设置共享数据的属性名
- value:设置共享数据的属性值
- scope:设置共享数据的域对象的范围,若不指定域对象的范围,则默认在pageContext域对象中共享数据,scope="page(默认)|request|session|application"
③、<c:remove>标签:相较于<c:set>,作用是移除范围域中的变量。
<%--删除userName变量--%>
<c:remove var="userName"></c:remove>
内部属性介绍:
- var:要删除的域对象中共享数据的属性名
- scope:要删除共享数据的域对象的范围,
- scope="page|request|session|application",若不指定scope,则删除所有域对象中以var的值作为属性名的数据
④、<c:catch>标签:用于捕获在嵌套在标签体中的内容抛出的异常,并将异常信息保存到变量中。
<c:catch var="exception">
int i=5/0;
</c:catch>
<c:out value="${exception}"/>
<%--此句相当于exception.getMessage--%>
<c:out value="${exception.message}"/>
如果嵌套的代码出现异常,异常对象会被捕获,并且保持到var变量中,该变量总是有page范围,如果没有发生异常,则var所表示的范围变量将移除。而如果没有指定var属性,异常只是被简单捕获,但异常信息不会被保存。
4.2、条件标签(重要)
①、<c:if>标签:和程序中的if语句作用相同,用来实现条件控制,但是没else功能。
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE HTML>
<html>
<head>
<title>JSTL的if标签示例</title>
</head>
<body>
<%
//在session中设置值
session.setAttribute("score",70);
%>
<c:if test="${score>60}">
<span>恭喜!及格了</span>
</c:if>
</body>
</html>
若为条件为true,则打印中间的数据,当然我们也可以使用var变量来声明。
<c:if test="testCondition" [var="varName"] [scope="{page|request|session|application}"]>
标签体内容
</c:if>
其中参数说明:
- test属性用于存放判断的条件,一般使用EL表达式来编写。
- var属性用来存放判断的结果,类型为true或false。
- scopes属性用来指定var属性存放的范围。
②、<c:choose>、<c:when>和<c:otherwise>标签:这三个标签通常一起使用,<c:choose>标签作为<c:when>和<c:otherwise>标签的父标签来使用。类似于程序中if-else,其中<c:when>表示if,<c:otherwise>表else。
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE HTML>
<html>
<head>
<title>JSTL的if-else标签示例</title>
</head>
<body>
<%
//在session中设置值
session.setAttribute("score",50);
%>
<c:choose>
<c:when test="${score>60}">
<span>恭喜!及格了</span>
</c:when>
<c:otherwise>
<span>不好意思!不及格</span>
</c:otherwise>
</c:choose>
</body>
</html>
4.3、循环标签(非常重要)
①、<c:forEach>标签:该标签根据循环条件遍历集合(Collection)中的元素。
<c:forEach>标签的语法:
<c:forEach
var=”name”
items=”Collection”
[varStatus=”StatusName”]
[begin=”begin”]
[end=”end”]
[step=”step”]>
主体内容
</c:forEach>
其中参数说明:
- var设定变量名用于存储从集合中取出元素。
- items指定要遍历的集合。
- varStatus设定变量名,该变量用于存放集合中元素的信息。其中varStatus有4个状态:index:当前循环的索引值、count:环的次数、frist:否为第一个位置、last:否为最后一个位置。
- begin、end用于指定遍历的起始位置和终止位置(可选),默认下标从0开始。
- step指定循环的步长,默认值为1。
forEach标签迭代集合举例(需要创建一个User,其中就两个属性,userName和age):
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ page import="com.thr.User" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE HTML>
<html>
<head>
<title>JSTL的迭代标签示例</title>
</head>
<body>
<%
List<User> users = new ArrayList<>();
users.add(0,new User("张三",20));
users.add(1,new User("李四",21));
users.add(2,new User("王五",22));
users.add(3,new User("赵六",23));
users.add(4,new User("孙七",24));
users.add(5,new User("周八",25));
users.add(6,new User("吴九",26));
users.add(7,new User("郑十",27));
//在session中设置值
session.setAttribute("users",users);
%>
<c:out value="输出整个迭代的信息:"/><br>
<c:forEach var="user" items="${users}" varStatus="userS">
<span>姓名:${user.userName}--年龄:${user.age}</span><br>
</c:forEach>
<br><br><br><br>
<c:out value="输出其它属性信息:"/><br>
<c:forEach var="user" items="${users}" varStatus="userStatus" begin="4" end="6" step="1">
<hr>
计数:${userStatus.count} <br>
步长:${userStatus.step} <br>
开始位置: ${userStatus.begin} <br>
结束位置:${userStatus.end} <br>
下标:${userStatus.index} <br>
是否是第一个:${userStatus.first} <br>
是否是最后一个:${userStatus.last}<br>
</c:forEach>
</body>
</html>
②、<c:forTokens>标签:该标签用于浏览字符串,并根据指定的字符将字符串截取。
<c:forTokens>标签的语法:
<c:forTokens items=”strigOfTokens”
delims=”delimiters”
[var=”name”]
[begin=”begin”]
[end=”end”]
[step=”len”]
[varStatus=”statusName”] >
主体内容
</c:forTokens>
其中参数说明:
- items指定被迭代的字符串。
- delims指定使用的分隔符。
- var指定用来存放遍历到的成员。
- begin指定遍历的开始位置(int型从取值0开始)。
- end指定遍历结束的位置(int型,默认集合中最后一个元素)。
- step遍历的步长(大于0的整型)。
- varStatus存放遍历到的成员的状态信息。
forTokens使用范例:
<%@ page language="java" pageEncoding="UTF-8" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE HTML>
<html>
<head>
<title>JSTL的forTokens标签实例</title>
</head>
<body>
<c:out value="根据一个分隔符截取:"/><hr>
<c:forTokens items="123-4567-8910" delims="-" var="tel">
<c:out value="${tel}"></c:out><br/>
</c:forTokens>
<br/><br/><br/>
<c:out value="根据多个分隔符截取:"/><hr>
<c:forTokens var="str" items="太阳、星星、月亮;地球|火星" delims="、;|">
<c:out value="${str}"></c:out><br/>
</c:forTokens>
<br/><br/><br/>
<c:out value="输出其它属性信息:"/><br><hr>
<c:forTokens items="1*2*3*4*5*6*7"
delims="*"
begin="1"
end="3"
var="n"
varStatus="s">
数字 <c:out value="${n}"/> 的四种属性:<br>
所在位置,即索引:<c:out value="${s.index}"/><br>
总共已迭代的次数:<c:out value="${s.count}"/><br>
是否为第一个位置:<c:out value="${s.first}"/><br>
是否为最后一个位置:<c:out value="${s.last}"/><br>
<hr>
</c:forTokens>
</body>
</html>
注意:如果未设定截取分隔符(即delims属性未设置值)或在字符串中没有找到匹配的分隔符,那么在显示的时候会除去匹配的分隔符,而未匹配的则会继续在页面中显示。