EL表达式和JSTL标签
在JavaWeb中,JSP技术提供9大内置对象,其中4个对象(四大作用域)用于存储数据,且可用于数据的传递。但是从四大作用域中,获取数据相对麻烦,且不利于结算,编码风格也相对不友善,因为需要在HTML页面中,使用<%%>等书写Java代码,基于这样的考虑,JavaWeb提供了EL表达式,用于弥补这个不足。EL表达式,支持从四大作用域中,获取数据,则支持简单运算,就不再使用Java代码,进行值相关操作。EL表达式,只需要是用:
${表达式}即可,语法相对简单,且更加友善。
1.EL表达式获取值
EL表达式获取值,主要是从四大作用域中获取值,且获取的顺序,分别是从小到大获取,即:优先从 pageContext --> request ----> session ----> applcation。一旦获取到数据,将不会再从下一个容器获取,如果所有的容器,都没有被获取的数据,那么则返回空字符串。注意:在Java中,若作用域中没有数据,则返回:null.如果页面显示一个null,这样很不友善。EL表达式的空字符串,一般用于搜索时的数据回显。
EL表达式主要功能是用于获取数据,其语法如下:
1.1.获取简单的数据
语法:
${key}
注意:四大作用域,存储数据的结构是一个key-value结构,所以el表达式默认使用key获取
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>EL表达式</title>
</head>
<body>
<%
//向四大作用域存储数据
pageContext.setAttribute("pageContextKey", "pageContextValue");
request.setAttribute("requestKey", "requestValue");
session.setAttribute("sessionKey", "sessionValue");
application.setAttribute("applicationKey", "applicationValue");
// 所有的容器中 都存放一样的key
//pageContext.setAttribute("dataKey", "pageContextValue");
//request.setAttribute("dataKey", "requestValue");
//session.setAttribute("dataKey", "sessionValue");
//application.setAttribute("dataKey", "applicationValue");
%>
<h1>从作用域中取值</h1>
pageContext:<%=pageContext.getAttribute("pageContextKey") %> <br>
<!-- 使用el表达式 获取值 -->
<%-- ${key} --%>
pageContext:${pageContextKey} <br>
request:${requestKey} <br>
session:${sessionKey} <br>
application:${applicationKey}<br>
<!--
若四大作用域中存储数据的key 一样
优先从pageContext获取。
若都没有则是空字符串
-->
都是dataKey 从哪取值:${dataKey}
</body>
</html>
1.2.获取JavaBean对象数据
语法:
${key.属性名}
注意:
在el表达式中,默认根据key获取的对象,是获取了对象的地址的字符串,然后可以根据key.属性名获取对应的属性值。但是,属性是私有的,在Java中,是无法根据对象.属性访问私有属性的。而el表达式,通过这样的形式获取了到了属性值,其本质不是对象直接访问属性,而是对象根据属性名,调用同名的get方法获取的属性。
基于这一点,在实际开发中,可以进行数据处理。例如:性别的值是数字,1 是男 2 是女.但是,页面上要显示男或者女.可以定义一个处理数据的get方法,然后,在页面使用el表达式,访问这个方法。
还可以处理时间等等。
示例代码:
package com.sxt.pojo;
public class User {
private Integer id;
//private String name;
private int sex;
public User() {}
public User(Integer id, String name) {
super();
this.id = id;
//this.name = name;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
System.out.println("获取 name 的属性值");
return "韩梅梅";
}
public int getSex() {
return sex;
}
public String getSexFormat() {
if(sex == 1) {
return "男";
}
if(sex == 2) {
return "女";
}
return "不详";
}
public void setSex(int sex) {
this.sex = sex;
}
// public void setName(String name) {
// this.name = name;
// }
}
<%@page import="com.sxt.pojo.User"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>EL表达式访问对象数据</title>
</head>
<body>
<%
//向作用域中添加数据
User user = new User(1001,"韩梅梅");
user.setSex(3);
request.setAttribute("userKey", user);
%>
<!-- 使用EL表达式获取对象数据 -->
获取对象:${userKey} <br>
获取对象中的id属性值:${userKey.id}<br>
获取对象中的name属性值:${userKey.name}<br>
获取对象中的sex属性值:${userKey.sex}<br>
获取对象中的sex显示的值:${userKey.sexFormat}<br>
</body>
</html>
1.3.获取Map结构的数据
语法:
${作用域中的key.map中的key}
程序示例:
<%@page import="java.util.Map"%>
<%@page import="java.util.HashMap"%>
<%@page import="com.sxt.pojo.User"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>EL表达式访问对象数据</title>
</head>
<body>
<%
Map<String,String> map = new HashMap<String,String>();
map.put("key","value");
//将map 放到作用域中
request.setAttribute("map",map);
//此时map中存储的是 user类型的值
Map<String,User> userMap = new HashMap<String,User>();
User user = new User();
user.setId(10001);
user.setSex(1);
userMap.put("user1", user);
//将map 放到作用域中
request.setAttribute("userMap",userMap);
%>
<!-- el 获取作用域中的map 对象 -->
map 对象: ${map}<br>
map中的值:${map.key}<br>
<hr>
map对象: ${userMap}<br>
map对象中的值对象:${userMap.user1}<br>
map对象中的值对象的属性值:${userMap.user1.id}<br>
map对象中的值对象的属性值:${userMap.user1.sex}<br>
map对象中的值对象的属性值:${userMap.user1.sexFormat}<br>
</body>
</html>
注意:当map中,存储数据的key值特殊时,可以使用['特殊key']的形式获取值。但是存在兼容性。
示例:
<%
Map<String,User> userMap = new HashMap<String,User>();
User user = new User();
user.setId(10001);
user.setSex(1);
userMap.put("1", user);//注意 此时使用 1 作为key el表达式是不支持
//将map 放到作用域中
request.setAttribute("userMap",userMap);
%>
map对象中的值对象:${userMap['1']}<br>
map对象中的值对象的属性值:${userMap['1'].id}<br>
1.4.获取数组结构的数据
语法:
${key[索引]}
示例:
<%@page import="java.util.List"%>
<%@page import="java.util.ArrayList"%>
<%@page import="java.util.Map"%>
<%@page import="java.util.HashMap"%>
<%@page import="com.sxt.pojo.User"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>EL表达式访问数组对象数据</title>
</head>
<body>
<%
// 创建一个数组结构容器
List<String> strs = new ArrayList<String>();
strs.add("韩梅梅");
strs.add("李磊");
strs.add("Jim");
strs.add("Lucy");
//将数据放入到作用域中
request.setAttribute("strs", strs);
List<User> users = new ArrayList<User>();
User user = new User();
user.setId(1001);
user.setSex(1);
users.add(user);//将java对象放入到list数组中
//将数据放入到作用域中
request.setAttribute("users", users);
%>
<!-- el 获取作用域中的数组 对象 -->
获取List数组结构对象:${strs}<br>
获取List中具体的元素:${strs[0]} ${strs[1]} ${strs[2]} ${strs[3]}
<!-- 数组中存储的是Java对象 -->
<hr>
获取数组中的对象:${users[0]}<br>
获取数组中对象的属性值:${users[0].id}<br>
</body>
</html>
2.EL表达式的运算
2.1.算术运算
在el表达式中,也支持算术运算符:
运算符 | 说明 |
---|---|
+ | 算术加 |
- | 算术减 |
* | 算术乘 |
/ | 算术除以 |
% | 算术取余数 |
代码示例:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>el表达式中的算术运算符</title>
</head>
<body>
<%
//将整数10 放入了作用域
request.setAttribute("m", 10);
request.setAttribute("n", 2);
%>
<p>11---加法运算:${m+1}</p>
<p>9---减法运算:${m-1}</p>
<p>20---乘法运算:${m*2}</p>
<p>5----除法运算:${m/2}</p>
<p>1----取模运算:${m%3}</p>
<hr>
<p>12---加法运算:${m+n}</p>
<p>8---减法运算:${m-n}</p>
<p>20---乘法运算:${m*n}</p>
<p>5----除法运算:${m/n}</p>
<p>0----取模运算:${m%n}</p>
</body>
</html>
2.2.关系运算
EL表达式中支持关系运算符
符号 | 等价符号 | 说明 |
---|---|---|
> | gt | 大于 |
>= | ge | 大于等于 |
< | lt | 小于 |
<= | le | 小于等于 |
== | eq | 等于 |
!= | ne | 不等于 |
代码示例:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>el表达式中的关系运算符</title>
</head>
<body>
<%
//将整数10 放入了作用域
request.setAttribute("m", 10);
request.setAttribute("n", 10);
%>
<p>false----大于运算符:${m>n}</p>
<p>true ----大于等于运算符:${m>=n}</p>
<p>false ----小于运算符:${m<n}</p>
<p>true ----小于等于运算符:${m<=n}</p>
<p>true ----等于运算符:${m==n}</p>
<p>false ----不等于运算符:${m!=n}</p>
<hr>
<p>false----大于运算符:${m gt n}</p>
<p>true ----大于等于运算符:${m ge n}</p>
<p>false ----小于运算符:${m lt n}</p>
<p>true ----小于等于运算符:${m le n}</p>
<p>true ----等于运算符:${m eq n}</p>
<p>false ----不等于运算符:${m ne n}</p>
</body>
</html>
注意:使用等价符号是,符号两边需要空格
2.3.逻辑运算
在EL表达式中,也支持逻辑运算符。
符号 | 等价符号 | 说明 |
---|---|---|
&& | and | 并且 |
|| | or | 或 |
! | not | 取反 |
代码示例:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>EL表达式逻辑运算符</title>
</head>
<body>
<p>false ---- &&运算符: ${false && true} </p>
<p>true ---- ||运算符: ${false || true} </p>
<p>true ---- !运算符: ${!false} </p>
<hr>
<p>false ---- and运算符: ${true and false} </p>
<p>true ---- or运算符: ${false or true} </p>
<p>true ---- not运算符: ${not false} </p>
</body>
</html>
2.4.三元运算
EL表达式中也支持三元运算符,语法:${表达式?值1:值2},若表达式值为true,则返回值1,否则返回值2。
语法示例:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>三元运算符</title>
</head>
<body>
<%
request.setAttribute("like", 2);
request.setAttribute("sex", 2);
%>
${5<2?"韩梅梅":"李磊"}
<!-- 使用三元运算符 为标签新增属性 -->
<input type="radio" name="sex" ${sex == 1?'checked':""} />男
<input type="radio" name="sex" ${sex == 2?'checked':""} />女
<input type="checkbox" ${like == 1?'checked':""} />篮球
</body>
</html>
2.5.empty运算符
empty运算符,用于判断字符串或者数组是一个空的数据或者null.即:当字符串为空字符串或者为null时,
当数组为空数组或者为null时,empty 都会返回true。
<%@page import="java.util.ArrayList"%>
<%@page import="java.util.List"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>empty运算符</title>
</head>
<body>
<%
String str1 = null; //此时值是null
String str2 = ""; //此时值是空字符串
List<String> list1 = null;// 此时数组为null
List<String> list2 = new ArrayList<String>();// 此时数组为空数组
%>
<p>null值的字符串:${empty str1}</p>
<p>空值的字符串:${empty str2}</p>
<p>null值的数组:${empty list1}</p>
<p>空值的数组:${empty list2}</p>
<h1>场景: 循环一个List 如果List 为空则显示没有符合条件的数据</h1>
${empty list2?"没有符合条件的数据":"存在符合条件的数据" }
</body>
</html>
3.EL表达式中内置对象
EL表达式,默认是从最小作用域,取值直到最大的作用域,如果出现作用域数据的重叠,想要精确的取到指定作用域的值,那么就需要从EL表达式中,获取对应的作用域,然后进行取值。
序 号 | 隐含对象名称 | 描 述 |
---|---|---|
1 | pageContext | 对应于JSP页面中的pageContext对象(注意:取的是pageContext 对象) |
2 | pageScope | 代表page域中用于保存属性的Map对象 |
3 | requestScope | 代表request域中用于保存属性的Map对象 |
4 | sessionScope | 代表session域中用于保存属性的Map对象 |
5 | applicationScope | 代表application域中用于保存属性的Map对象 |
6 | param | 表示一个保存了所有请求参数的Map对象 |
7 | paramValues | 表示一个保存了所有请求参数的Map对象,它对于某个请求参数, 返回的是一个string[] |
8 | header | 表示一个保存了所有http请求头字段的Map对象 |
9 | headerValues | 同上,返回string[]数组。注意:如果头里面有“-” ,例Accept Encoding,则要headerValues[“Accept-Encoding”] |
10 | cookie | 表示一个保存了所有cookie的Map对象 |
11 | initParam | 表示一个保存了所有web应用初始化参数的map对象 |
代码示例:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>EL表达式内置对象</title>
</head>
<body>
<%
pageContext.setAttribute("key", "pageValue");
request.setAttribute("key", "requestValue");
session.setAttribute("key", "sessionValue");
application.setAttribute("key", "applicationValue");
%>
<!--
以上4个作用域 都存了一个键的值为key 值为对应的值的键值对
而EL表达式 默认从pageContext 获取 所以,其他三个作用域 的值就无法获取到。
所以el表达式,提供了:
pageScope 表示pageContext 作用域
requestScope 表示request 作用域
sessionScope 表示session 作用域
applicationScope 表示 application作用域
-->
<!-- 获取pageContext对象 -->
${pageContext}<br>
<!-- 从pageContext 作用域中取值 -->
${pageScope.key} :=====>pageValue<br>
<!-- 从reuqest 作用域中取值 -->
${requestScope.key} :====>requestValue<br>
<!-- 从session 作用域中取值 -->
${sessionScope.key} :====>sessionValue<br>
<!-- 从 application 作用域中取值 -->
${applicationScope.key}:====>applicationValue<br>
<hr>
获取请求参数:${param.name}<br>
获取数组类型请求参数:${paramValues.name[0]}<br>
获取数组类型请求参数:${paramValues.name[1]}<br>
<hr>
请求头:${header.Host}<br>
请求头中数组类型值:${headerValues['Accept-Encoding'][0]} <br>
请求头中数组类型值:${headerValues['Accept-Encoding'][1]} <br>
</body>
</html>
4.EL表达式的优缺点
EL表达式,基本上可以在JSP页面中任意地方都可以进行书写。但是,其值只能支持字符串。相对于Java而言,取值更加方便。但是EL表达式,没有条件分支判断,也不支持循环。所以,若页面数据,需要进行条件分支判断,和循环处理,纯粹只靠EL表达式,是无法满足真正的需求的。需要使用JSTL进行补充。
5.JSTL
JSTL(Java server pages standarded tag library,即JSP标准标签库)是由JCP(Java community
Proces)所制定的标准规范,它主要提供给Java Web开发人员一个标准通用的标签库,并由Apache的
Jakarta小组来维护。开发人员可以利用这些标签取代JSP页面上的Java代码,从而提高程序的可读性,
降低程序的维护难度。
5.1.JSTL入门使用
JSTL是Apache的Jakarta小组维护,JSTL是属于第三方技术。所以,需要引入相关的jar包。
5.1.1.引入相关jar包
jstl-1.2.jar
standard-1.1.2.jar
5.1.2.在页面引入标签库
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
由于,jstl标签前缀一般使用c,所以也被称之为c标签。
5.1.3.使用<c:作为前缀,自动提示可用的标签。
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!-- 引入 jstl 标签库 -->
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<c:if test="${5<2}">
如果表达式的值为true,则我会显示
</c:if>
</body>
</html>
5.2.JSTL中常用标签
5.2.1.条件分支标签
<!-- 单条件分支标签 -->
语法:
<c:if test="el表达式">代码</c:if>
语法说明:
若test中el表达式的最终运算结果为true,则执行被包裹的代码
<!-- 多条件分支标签 -->
语法:
<c:choose>
<c:when test="el表达式">代码块1</c:when>
....
<c:when test="el表达式">代码块n</c:when>
<c:otherwise>代码块n+1</c:otherwise>
</c:choose>
语法解释:
执行when后面 test中的el表达式,自上而下执行,若满足条件,则运行被包裹的代码块,且后面的when标签包裹的test不再进行判定执行,若所有的test都不满足,则运行otherwise包裹的代码块。
代码示例
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!-- 引入 jstl 标签库 -->
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<c:if test="${5<2}">
如果表达式的值为true,则我会显示
</c:if>
<h1>条件分支</h1>
<h2>if条件分支</h2>
<c:if test="${5<2}">
如果表达式的值为true,则我会显示
</c:if>
<h2>多条件分支</h2>
<c:choose >
<c:when test="${10<2}"><!-- false -->
我是第23行<br>
</c:when>
<c:when test="${10<3}"><!-- false -->
我是第26行<br>
</c:when>
<c:otherwise>
我是第29行<br>
</c:otherwise>
</c:choose>
</body>
</html>
5.2.2.循环标签
循环标签:
<c:forEach begin="" end="" items="" var="" step="" varStatus=""></c:forEach>
语法:
属性 | 说明 |
---|---|
items | 代循环的数据 |
var | 指代被循环的容器中的元素 |
step | 每次循环增长的步长,默认值1 |
begin | 开始循环的下标索引 |
end | 结束循环的下标索引 |
varStatus | 指代循环的状态信息: index :当前索引 count:循环的次数 first:是否第一个 last:是否第一个 |
代码示例:
<%
List<String> strs = new ArrayList<String>();
strs.add("字符串1");
strs.add("字符串2");
strs.add("字符串3");
strs.add("字符串4");
//将数组放入作用域
request.setAttribute("strs", strs);
%>
<h1>循环配置</h1>
<!--
items="${strs}" : 指代被循环的List 从作用域中获取数组值
var="str" : 指代 list中存储的数据
step="2" : 指代每次循环增长下标基数值 默认是按1增长
begin="1" : 指开始循环的下标索引,默认是从0开始
end="2" : 结束循环的下标索引
varStatus="statu" :循环的状态信息,statu就含有当前循环的所有状态信息
index :下标索引
count :循环的次数
first :是否是第一个元素
last : 是否是第二个元素
-->
<c:forEach items="${strs}" var="str" step="1" begin="0" end="3" varStatus="statu">
${str} ${statu.index} ${statu.count} ${statu.first} ${statu.last}<br>
</c:forEach>

5.2.3.格式化标签
在实际开发中,很多时候,需要对数字,时间等等进行格式,JSTL提供了一套格式化的标签库。
可以参考:https://www.runoob.com/jsp/jsp-jstl.html
时间格式化标签
1.在页面引入jstl标签库
<%@taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
2.使用相应的时间格式化标签
<h1>时间格式化标签</h1>
<!--
value :待格式化的时间数据
pattern : 具体的格式
var : 用于表示被格式化后的字符串,可以在其它地方应用该值
-->
<%
request.setAttribute("createTime", new Date());
%>
没有格式化的时间数据:${createTime}<br>
<fmt:formatDate value="${createTime}" pattern="yyyy-MM-dd HH:mm:ss" var="formatTime" />
${formatTime}<br>
${formatTime}<br>
${formatTime}<br>
${formatTime}<br>
网友评论