1、EL表达式
EL的全称为Expression Language,即表达式语言。EL的用法比较的简单,就是用 ${ 标识符 } 包起来的语句。我们一般用它来读取数据(如:${ username } )或者执行运算(也就是基本的关系运算、逻辑运算和算术运算如:${username==null})。使用EL表达式最大的特点就是使用很方便,例如获取用户名 ${ username } ,下面对比一下在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方法才行。下面是这两种EL表达式的使用举例:
对象 . 属性的使用:
${sessionScope.user.username} //等价于 ${sessionScope.user["username"]}
[ ]的使用(点和[ ] 可以混合使用):
${sessionScope.user[0].username}
上面看到的sessionScope的EL表达式提供的隐含对象,在JSP中有9个隐含对象(就是9个内置对象),而EL也有自己的隐含对象。EL隐含对象总共有11个(pageScope、requestScope、sessionScope、applicationScope、param 、paramValues、header、headerValues、initParam、cookie、pageContext),不过我们只简单看以下这四个:
EL隐含对象 | JSP对象 |
pageScope | page |
requestScope | request |
sessionScope | session |
applicationScope | application |
EL表达式从这四个域中获得某个值的格式:${ xxxScope . key};等价于<%xxx.getAttribute(“username”)%>。而如果我们不指定作用域,直接${username}的话,默认会按照作用域的范围从小到大(page->request->session->application)依次查找,直到找到application为止。如果四个作用域中都没有则返回空字符串(注意:不是null,而是””),然后什么都不显示。
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 || B}或${A or B} | true/false |
! 或 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" %>
当然此时也可以发现其他的标签库:
引入格式如下所示:
<%--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的核心标签库
①、普通标签
(1)、<c:out>标签:用于将结果输出。类似于JSP中的<%= %>表达式,或者是EL表达式${ expression }。
<%--取值--%> <c:out value="${userName}"></c:out>
(2)、<c:set>标签:用于把某一个对象存在指定的域范围内,或者将某一个对象存储到Map或者JavaBean对象中。
<%--设值--%> <c:set var="userName" value="tanghaorong" scope="session"></c:set>
其中var="变量名" value="值" scope="保存在哪个作用域(page、request、session、application)。
(3)、<c:remove>标签:相较于<c:set>,作用是移除范围域中的变量。
<%--删除userName变量--%> <c:remove var="userName"></c:remove>
(4)、<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属性,异常只是被简单捕获,但异常信息不会被保存。
②、条件标签(重要)
(1)、<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属性存放的范围。
(2)、<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>
③、循环标签(非常重要)
(1)、<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>
(2)、<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属性未设置值)或在字符串中没有找到匹配的分隔符,那么在显示的时候会除去匹配的分隔符,而未匹配的则会继续在页面中显示。