EL表达式与JSTL标签库
1.EL表达式
1.1 什么是EL表达式?
EL表达式全称是: Expression Language(表达式语言)
EL表达式的作用: EL表达式作为替代Jsp中的表达式脚本对页面进行数据输出
因为EL表达式在输出数据的时候,要比jsp的表达式要简洁很多
下面做个比较代码:
<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<!DOCTYPE html>
<html>
<head><title>JSP - Hello World</title></head>
<body>
<%
pageContext.setAttribute("key","pageContext");
%>
<%--表达式脚本--%>
<%=pageContext.getAttribute("key")%>
<%--EL表达式--%>
${ key }
</body>
</html>
当域数据的对象值为空时
表达式脚本输出: null
EL表达式: (空串)
总结:
如果数据为空,在用户看来表达式脚本输出的null就是它的值,
而EL表达式输出空串表示没有值,这样是最好的
1.2 EL表达式搜素域数据的顺序
EL表达式主要是在Jsp页面中输出域数据
当4个域数据都持有相同的域对象时,EL表达式会按照域数据的范围从小到大的进行匹配,找到就输出
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%--EL表达式搜素域数据的顺序--%>
<%
pageContext.setAttribute("key","pageContext");
request.setAttribute("key","request");
session.setAttribute("key","session");
application.setAttribute("key","application");
%>
<%--EL表达式格式: ${ 表达式 } --%>
${ key }
<jsp:forward page="el2.jsp"></jsp:forward>
</body>
</html>
当使用EL表达式${ key }
它会按域数据从小到大的优先级进行匹配,将匹配的key的值输出到页面上
1.3 EL表达式输出Bean类的普通属性、数组属性、List集合属性、Map集合属性
我们要通过EL表达式输出JavaBean类的属性,就需要先创建JavaBean对象
1、创建Person类为例
2、普通属性: String name
3、数组属性: String[ ] phone
4、List集合属性: List cities
5、Map集合属性: Map<String,String>map
6、创建类的get、set方法、toString方法、带参.无参构造器
Jsp代码
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%
Person p = new Person();
p.setName("Sanchez");
p.setPhone(new String[]{"12345667889,18725534688"});
ArrayList<String> arrList = new ArrayList<>();
arrList.add("广州");
arrList.add("珠江");
arrList.add("长江");
p.setCities(arrList);
HashMap<String,String> map = new HashMap<>();
map.put("key1","value1");
map.put("key2","value2");
map.put("key3","value3");
p.setMap(map);
request.setAttribute("person", p);
%>
通过域数据获取普通属性值: ${person.name}<br/>
通过域数据获取数组中每个下标元素: ${person.phone[1]}<br/>
通过域数据获取List集合的值: ${person.cities}<br/>
通过域数据获取List集合的某个值: ${person.cities[2]}<br/>
通过域数据获取Map集合的值: ${person.map}<br/>
通过域数据获取Map集合的某个值: ${person.map.get("key1")}<br/>
</body>
</html>
注意: 当我们调用
${person.name}
,实际上EL表达式是获取person实例的getName()方法,从而输出到页面上
当我们访问页面时候输出的结果:
1.4 EL表达式运算符
语法: ${ 运算表达式 } , EL支持以下运算符:
a) 关系运算
关系运算符 | 说明 | 范例 | 结果 |
---|---|---|---|
== 或 eq | 等于 | ${ 5 == 5 } 或 ${ 5 eq 5 } | true |
!= 或 ne | 不等于 | ${ 5 != 5 } 或 ${ 5 ne 5 } | false |
< 或 lt | 小于 | ${2<10} 或 ${2 lt 10} | true |
> 或 gt | 大于 | ${2>10} 或 ${2 gt 10} | false |
<= 或 le | 小于等于 | ${5<=12} 或 ${5 le 12} | true |
>= 或 ge | 大于等于 | ${3>=5} 或 ${3 ge 5} | false |
b) 逻辑运算
逻辑运算符 | 说明 | 范例 | 结果 |
---|---|---|---|
&& 或 and | 与运算 | ${12==12&&5!=5} 或 ${12==12 and 5!=5} | false |
| 或 or | 或运算 | ${12==12||5!=5} 或 ${12==12 or 5!=5} | true |
! 或 not | 取反运算 | ${!(12==12)} 或 ${not(12==12)} | false |
c) 算数运算
算术运算符 | 说明 | 范例 | 结果 |
---|---|---|---|
+ | 加法 | ${12+18} | 30 |
- | 减法 | ${12-18} | -6 |
* | 乘法 | ${12*18} | 216 |
/ 或 div | 除法 | ${6/2} 或 ${6 div 2} | 3 |
% 或 mod | 取模 | ${12 % 2} 或 ${12 mod 2} | 2 |
d) empty运算
empty运算能够判断一个数据是否为空,如果为空输出true,不为空输出false
以下几种情况为空:
1、值为null的时候
2、值为""(空串)时候
3、值是Object类型数组,长度为0时
4、值是list集合,元素个数为0时
5、值是map集合,元素个数为0时
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%--empty运算符测试--%>
<%
//当域数据为null时
request.setAttribute("emptyNull",null);
//当域数据为 空串 时
request.setAttribute("emptyStr","");
//当域数据为 Object类型数组,长度为0时
request.setAttribute("emptyObjArr",new Object[]{});
//当域数据为 List集合,元素个数为0时
request.setAttribute("emptyList",new ArrayList<>());
//当域数据为 Map集合,元素个数为0时
request.setAttribute("emptyMap",new HashMap<>());
%>
${empty emptyNull}
${empty emptyStr}
${empty emptyObjArr}
${empty emptyList}
${empty emptyMap}
</body>
</html>
e) 三元运算
表达式 1 ? 表达式 2 : 表达式 3
如果表达式 1 的值为真,返回表达式 2 的值,如果表达式 1 的值为假,返回表达式 3 的值。
示例: ${ 12==12 ? “12是12” : “12不是12” }
.
点运算 和 []
中括号运算符
1、.
点运算,可以输出 Bean 对象中某个属性的值。
2、[]
中括号运算,可以输出有序集合中某个元素的值。
3、并且[]
中括号运算,还可以输出 map 集合中 key 里含有特殊字符的 key 的值。
<body>
<%
Map<String,Object> map = new HashMap<String, Object>();
map.put("a.a.a", "aaaValue");
map.put("b+b+b", "bbbValue");
map.put("c-c-c", "cccValue");
request.setAttribute("map", map);
%>
${ map['a.a.a'] } <br>
${ map["b+b+b"] } <br>
${ map['c-c-c'] } <br>
</body>
1.5 EL表达式隐含对象
EL表达式中含有11个隐含对象,这些都是EL表达式自定义的
变量 | 类型 | 作用 |
---|---|---|
pageContext | PageContextImpl | 可以获取Jsp的9大内置对象 |
pageScope | Map<Strinig,Object> | 可以获取pageContext域中的数据 |
requestScope | Map<Strinig,Object> | 可以获取Request域中的数据 |
sessionScope | Map<Strinig,Object> | 可以获取Session域中的数据 |
applicationScope | Map<Strinig,Object> | 可以获取ServletContext域中的数据 |
param | Map<Strinig,Object> | 可以获取请求参数 |
paramValues | Map<Strinig,Object[ ]> | 可以获取请求参数,获取多个值 |
header | Map<Strinig,Object> | 可以获取请求头信息 |
headerValues | Map<Strinig,Object[ ]> | 可以获取请求头信息,获取多个值 |
cookie | Map<Strinig,Cookie> | 可以获取当前请求的cookie信息 |
initParam | Map<Strinig,String> | 可以获取web.xml中配置的<context-param>上下文参数 |
1.6 EL表达式获取4个域中的特定属性
EL中的隐含的4个域对象对应的Jsp的4个域对象
pageScope ===> PageContext域
requestScope ===> Request域
sessionScope ===> Session域
applicationScope ===> ServletContext域
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%--如在4个不同的域数据中定义了相同名字的key, 如何获取某一个域对象中的value--%>
<%
pageContext.setAttribute("key","pageContext");
request.setAttribute("key","request");
session.setAttribute("key","session");
application.setAttribute("key","application");
%>
获取pageContext域的value: ${pageScope.key}<br/>
获取request域的value: ${requestScope.key}<br/>
获取session域的value: ${sessionScope.key}<br/>
获取application域的value: ${applicationScope.get("key")}<br/>
</body>
</html>
当我们访问这个jsp页面后,测试结果为:
pageContext 对象的使用
1、协议:${ pageContext.request.scheme }
2、服务器 ip:${ pageContext.request.serverName }
3、服务器端口:${ pageContext.request.serverPort }
4、获取工程路径:${ pageContext.request.contextPath }
5、获取请求方法:${ pageContext.request.method }
6、获取客户端 ip 地址:${ pageContext.request.remoteHost }
7、获取会话的 id 编号: ${ pageContext.session.id }
<body>
<%--
request.getScheme() 它可以获取请求的协议
request.getServerName() 获取请求的服务器 ip 或域名
request.getServerPort() 获取请求的服务器端口号
getContextPath() 获取当前工程路径
request.getMethod() 获取请求的方式(GET 或 POST)
request.getRemoteHost() 获取客户端的 ip 地址
session.getId() 获取会话的唯一标识
--%>
<%
pageContext.setAttribute("req", request);
%>
<%=request.getScheme() %> <br>
1.协议: ${ req.scheme }<br>
2.服务器 ip:${ pageContext.request.serverName }<br>
3.服务器端口:${ pageContext.request.serverPort }<br>
4.获取工程路径:${ pageContext.request.contextPath }<br>
5.获取请求方法:${ pageContext.request.method }<br>
6.获取客户端 ip 地址:${ pageContext.request.remoteHost }<br>
7.获取会话的 id 编号:${ pageContext.session.id }<br>
</body>
2. JSTL标签库
2.1 什么是JSTL标签库?
JSTL全称: JSP Standard Tag Library JSP标准标签库,是一个不断完善的开源代码,Jsp标签库
我们已经学过了EL表达式,它是作为Jsp中替代表达式脚本进行数据输出
那么这个JSTL标签库就是专门用来替代Jsp中的代码脚本的,这样使的Jsp中的代码编写更加简洁
JSTL是由五个不同功能组成的标签库
功能范围 | URI | 前缀 |
---|---|---|
核心标签库–重点 | http://java.sun.com/jsp/jstl/core | c |
格式化 | http://java.sun.com/jsp/jstl/fmt | fmt |
函数 | http://java.sun.com/jsp/jstl/functions | fn |
数据库(不适用) | http://java.sun.com/jsp/jstl/sql | sql |
XML | http://java.sun.com/jsp/jstl/xml | x |
在 jsp 标签库中使用 taglib 指令引入标签库
CORE 标签库
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
XML 标签库
<%@ taglib prefix="x" uri="http://java.sun.com/jsp/jstl/xml" %>
FMT 标签库
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
SQL 标签库
<%@ taglib prefix="sql" uri="http://java.sun.com/jsp/jstl/sql" %>
FUNCTIONS 标签库
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
2.2 JSTL如何使用
1、先导入JSTL标签库的jar包
taglibs-standard-impl-1.2.1.jar
taglibs-standard-spec-1.2.1.jar
2、使用taglib指令引入标签库
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
3、core核心库的使用
a. set标签: <c:set scope="" var="" value="" />
<body>
存储前: ${ requestScope.key1 }
<%--<:set/> 标签,能够存储域数据
scope属性设置保存到那个域中
page 表示PageContext域
request 表示Request域
session 表示Session域
application 表示ServletContext域
var属性设置key是多少
value属性设置值是多少
--%>
<c:set scope="request" var="key1" value="value1"/>
存储前: ${ requestScope.key1 }
</body>
b. if标签: <c:if test=${ 表达式 }>EL表达式或标签</c:if>
test属性中使用EL表达式处理
if标签用来做判断
<c:if test="${ 12 == 12 }">
<%-- 当满足条件时输出--%>
<h1>12等于12</h1>
</c:if>
c. choose标签: <c:choose><c:when><c:otherwise>
如果我们要实现if
的多分支判断, 在这里只能使用 <c:choose><c:when><c:otherwise>标签
,但它与switch...case
更相似
<body>
<%
request.setAttribute("height",140);
%>
<br/>
<c:choose>
<%-- test属性中使用EL表达式处理 --%>
<c:when test="${requestScope.height > 190}">
我的身高足足有: ${ requestScope.height }
</c:when>
<c:when test="${requestScope.height > 180}">
身高一般般,只有: ${ requestScope.height }
</c:when>
<c:when test="${requestScope.height > 170}">
太矮了,只有: ${ requestScope.height }
</c:when>
<%-- <c:other>相当于switch...case中的default关键字,当上面的条件都不满足时,会执行<c:other> --%>
<c:otherwise>
<br/>不够长,再大点
</c:otherwise>
</c:choose>
</body>
d. forEach遍历标签: <c:forEach begin="" end="" var=""></c:forEach>
遍历0到10
<%--
在Java中的for循环遍历操作:
for(int i = 0; i < 10; i++){
}
而JSTL标签库使用<c:forEach begin="0" end="10" var="i"></c:forEach>
begin属性: 起始值
end属性: 结束值,遍历包含这个值,相当于 <=
var属性: 变量名
forEach它会自增的进行遍历
--%>
<c:forEach begin="0" end="10" var="i">
${i}
</c:forEach>
遍历Object数组
<%
request.setAttribute("str",new String[]{"123437","abcd1234"});
%>
<%--遍历Object数组
相当于for(Object o : arr)
items属性: 要遍历的数据源
var属性: 变量名
--%>
<c:forEach items="${ requestScope.str }" var="item">
${ item }
</c:forEach>
遍历Map集合
<%--遍历Map集合--%>
<%
HashMap<String,String> map = new HashMap();
map.put("key1","value1");
map.put("key2","value2");
map.put("key3","value3");
request.setAttribute("map",map);
%>
<c:forEach items="${ requestScope.map }" var="map">
${ map.key } = ${ map.value }<br/>
</c:forEach>
遍历List集合、forEach标签所有属性的作用
<%--遍历List集合--%>
<%
List<Student> list = new ArrayList<Student>();
for (int i = 1; i < 10; i++) {
list.add(new Student("Morty"+i,"I like asshole"+i,14+i ,"1866889543"+i ));
}
request.setAttribute("list",list);
%>
<table style="border: 1px pink solid" width="500" cellspacing="0">
<tr>
<td>编号</td>
<td>用户名</td>
<td>密码</td>
<td>年龄</td>
<td>电话</td>
<td>操作</td>
</tr>
<%
/* <c:forEach所有属性的作用
items属性: 要遍历的数据源
begin属性: 起始值
end属性: 结束值,包含最后一个值 等价于 <=
step属性: 表示遍历的步长数
var属性: 表示变量值
varStatus属性: 表示当前遍历到的数据状态的变量名,通过(.方法)获取以下方法
current: 表示当前遍历到当前下标的toString方法
count: 表示遍历到的个数
step: 表示遍历的step属性的值
begin: 表示begin属性的值
end: 表示end属性的值
first: 返回boolean类型, 表示是否是遍历的第1个下标元素
end: 返回boolean类型, 表示是否是遍历的最后的下标元素
index: 返回当前下标
*/
%>
<c:forEach items="${ requestScope.list }" begin="2" end="9" step="2" var="p" varStatus="s">
<tr>
<td>${ s.count }</td>
<td>${ p.username }</td>
<td>${ p.password }</td>
<td>${ p.age }</td>
<td>${ p.phone }</td>
<td> 删除 </td>
</tr>
</c:forEach>
</table>