Java Web 从入门到退坑 —— 第九章 EL表达式&JSTL标签库
By -gregPerlinLi-
1. EL 表达式
1.1. 什么是 EL 表达式,EL 表达式的作用
EL 表达式的全称是:Expression Language
是表达式语言。
EL 表达式的作用:
EL 表达式主要是用于替代 jsp 页面中的表达式脚本,在 jsp 页面中进行数据的输出,因为 EL 表达式在输出数据的时候要比 jsp 的表达式脚本要简洁很多
EL 表达式输出的格式是:${ Expression }
EL 表达式在输出 null
值的时候,输出的是空串,jsp 表达式脚本输出 null
值的时候,输出的是 null
字符串。
示例代码:
<body>
<%
request.setAttribute("key", "value");
%>
Expression script output: <%=request.getAttribute("key") == null ? "" : request.getAttribute("key") %> <br/>
EL Expression output: ${ key } <br/>
</body>
1.2. EL 表达式搜索域数据的顺序
EL 表达式主要是在 jsp 页面中输出数据。
主要是输出域对象中的数据
当四个域中都有相同的 key
数据的时候,EL 表达式会按照四个域的从小到大的顺序进行搜索,找到后进行输出:
pageContext >> request >> session >> application
示例代码:
<body>
<%
// The same key data is saved in all four domains
pageContext.setAttribute("key", "pageContext");
request.setAttribute("key", "request");
session.setAttribute("key", "session");
application.setAttribute("key", "application");
%>
${ key }
</body>
1.3. EL 表达式输出 Bean
的普通属性,数组属性。List
集合属性,map
集合属性
示例代码:
Person.java
public class Person {
// 1. Output the general properties, array properties, List set and Map set properties in the person class
private String name;
private String[] phones;
private List<String> cities;
private Map<String, Object> map;
private final int age = 18;
public Person() {
}
public Person(String name, String[] phones, List<String> cities, Map<String, Object> map) {
this.name = name;
this.phones = phones;
this.cities = cities;
this.map = map;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String[] getPhones() {
return phones;
}
public void setPhones(String[] phones) {
this.phones = phones;
}
public List<String> getCities() {
return cities;
}
public void setCities(List<String> cities) {
this.cities = cities;
}
public Map<String, Object> getMap() {
return map;
}
public void setMap(Map<String, Object> map) {
this.map = map;
}
public int getAge() {
return age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", phones=" + Arrays.toString(phones) +
", cities=" + cities +
", map=" + map +
", age=" + age +
'}';
}
}
c.jsp
<body>
<%
Person person = new Person();
person.setName("XingMing");
person.setPhones(new String[]{"13624887499", "18688886666", "18699998888"});
List<String> cities = new ArrayList<String>();
cities.add("Beijing");
cities.add("Shanghai");
cities.add("Guangzhou");
cities.add("Shenzhen");
person.setCities(cities);
Map<String, Object> map = new HashMap<>();
map.put("key1", "value1");
map.put("key2", "value2");
map.put("key3", "value3");
map.put("key4", "value4");
map.put("key5", "value5");
person.setMap(map);
request.setAttribute("person", person);
%>
Output Person: ${ person } <br/>
Output Name: ${ person.name } <br/>
Output Phones: ${ person.phones[0] }, ${ person.phones[1] }, ${ person.phones[2] } <br/>
Output Cities: ${ person.cities } <br/>
Output City 1: ${ person.cities[0] } <br/>
Output Maps: ${ person.map } <br/>
Output the value of key in Map: ${ person.map.key1 } <br/>
Output Age: ${ person.age } <br/>
</body>
注意⚠️: EL 表达式中的输出属性值其实是利用了 Bean
的 Get
方法来实现的。
1.4. EL 表达式 —— 运算
语法:${ OperationalExpression }
EL 表达式支持如下运算符:
1.4.1. 关系运算
关系运算符 | 说明 | 范例 | 结果 |
---|---|---|---|
== 或 eq |
等于 | ${ 5 == 5 } 或 ${ 5 eq 5 } |
true |
!= 或 ne |
不等于 | ${ 5 != 5 } 或 ${ 5 ne 5 } |
false |
< 或 lt |
小于 | ${ 3 < 5 } 或 ${ 3 lt 5 } |
true |
> 或 gt |
大于 | ${ 2 == 10 } 或 ${ 2 gt 10 } |
false |
<= 或 le |
小于等于 | ${ 5 == 12 } 或 ${ 5 le 12 } |
true |
>= 或 ge |
大于等于 | ${ 3 == 5 } 或 ${ 3 ge 5 } |
false |
1.4.2. 逻辑运算
逻辑运算符 | 说明 | 范例 | 结果 |
---|---|---|---|
&& 或 and |
与运算 | ${ 12 == 12 && 12 < 11 } 或 ${ 12 eq 12 and 12 lt 11 } |
false |
` | 或 or` |
或运算 | |
! 或 not |
取反运算 | ${ !true } 或 ${ not true } |
false |
1.4.3. 算术运算
算术运算符 | 说明 | 范例 | 结果 |
---|---|---|---|
+ |
加法 | ${ 12 + 18 } |
30 |
- |
减法 | ${ 18 - 8 } |
10 |
* |
乘法 | ${ 12 * 12 } |
144 |
/ 或 div |
除法 | ${ 144 / 12 } 或 ${ 144 div 12 } |
12 |
% 或 mod |
取模 | ${ 144 % 10 } 或 ${ 144 mod 10 } |
4 |
1.4.4. empty
运算
empty
运算可以判断一个数据是否为空,如果为空,则输出 true
,不为空输出false
。
以下几种情况为空:
1. 值为 null
的时候为空
2. 值为空串的时候为空
3. 值是 Object
类型数组,长度为零的时候为空
4. List
集合元素个数为零的时候为空
5. Map
集合元素个数为零的时候为空
1.4.5. 三元运算
${ Expression1 ? Expression2 : Expression3 }
如果表达式1的值为真,返回表达式2的值,如果表达式1的值为假,返回表达式3的值
示例:
${ 12 != 12 ? "Equal" : "Unequal" }
1.4.6. .
点运算和 []
中括号运算
.
点运算可以输出 Bean
对象中某个属性的值。
[]
中括号运算可以输出有序集合中某个元素的值。
中括号运算还可以输出 Map
集合中 key
里含有特殊字符的 key
的值。
示例:
${ map.["a.a.a"] }
${ map.['b+b+b'] }
1.4.7. EL 表达式的 11 个隐含对象
EL 表达式中 11 个隐含对象,是 EL 表达式自己定义的,可以直接使用。
变量 | 类型 | 作用 |
---|---|---|
pageContext |
pageContextImpl |
它可以获取 jsp 中的九大内置对象 |
pageScope |
Map<String, Object> |
它可以获取 pageContext 域中的数据 |
requestScope |
Map<String, Object> |
它可以获取 request 域中的数据 |
sessionScope |
Map<String, Object> |
它可以获取 session 域中的数据 |
applicationScope |
Map<String, Object> |
它可以获取 application 域中的数据 |
param |
Map<String, String> |
它可以获取请求参数的值 |
paramValues |
Map<String, String[]> |
它可以获取请求参数的值(获取多个值的时候使用) |
header |
Map<String, String> |
它可以获取请求头的信息 |
headerValues |
Map<String, String[]> |
它可以获取请求头的信息(它可以获取多个值的情况) |
cookie |
Map<String, Cookie> |
它可以获取当前请求的 Cookie 信息 |
initParm |
Map<String, String> |
它可以获取 web.xml 中配置的 <context-param> 上下文参数 |
1. 获取四个特定域中的属性
pageScope
➞ pageContext
域
requestScope
➞ requestConotext
域
sessionScope
➞ sessionContext
域
applicationScope
➞ servletContext
域
示例代码:
<body>
<%
pageContext.setAttribute("key", "pageContext");
request.setAttribute("key", "request");
session.setAttribute("key", "session");
application.setAttribute("key", "application");
%>
${ pageScope.key } <br/>
${ requestScope.key } <br/>
${ sessionScope.key } <br/>
${ applicationScope.key } <br/>
</body>
2. pageContext
对象的使用
常用于:
I 协议
II 服务器 ip
III 服务器端口
IV 获取工程路径
V 获取请求方法
VI 获取客户端 ip
地址
VII 获取会话饿 id
编号
示例代码:
方法1:
<body>
1. Agreement: ${ pageContext.request.scheme } <br/>
2. Server IP address: ${ pageContext.request.getServerName() } <br/>
3. Server port: ${ pageContext.request.getServerPort() } <br/>
4. Get project path: ${ pageContext.request.getContextPath() } <br/>
5. Get request method: ${ pageContext.request.getMethod() } <br/>
6. Get client IP address: ${ pageContext.request.getRemoteHost() } <br/>
7. Get session ID number: ${ pageContext.session.getId() } <br/>
</body>
方法2:
<body>
<%
pageContext.setAttribute("req", request);
pageContext.setAttribute("ses", session)
%>
1. Agreement: ${ req.scheme } <br/>
2. Server IP address: ${ req.getServerName() } <br/>
3. Server port: ${ req.getServerPort() } <br/>
4. Get project path: ${ req.getContextPath() } <br/>
5. Get request method: ${ req.getMethod() } <br/>
6. Get client IP address: ${ req.getRemoteHost() } <br/>
7. Get session ID number: ${ ses.getId() } <br/>
</body>
3. EL 表达式其他隐含对象的使用
变量 | 类型 | 作用 |
---|---|---|
param |
Map<String, String> |
它可以获取请求参数的值 |
paramValues |
Map<String, String[]> |
它可以获取请求参数的值(获取多个值的时候使用) |
示例代码:
请求地址:
http://localhost:8080/EL_JSTL/otherElObj.jsp?username=gregPerlinLi&password=root&hobby=java&hobby=cpp&hobby=python
<body>
Username: ${ param.username } <br/>
Password: ${ param.password } <br/>
Hobby: ${ paramValues.hobby[0] }, ${ paramValues.hobby[1] }, ${ paramValues.hobby[2] } <br/>
</body>
变量 | 类型 | 作用 |
---|---|---|
header |
Map<String, String> |
它可以获取请求头的信息 |
headerValues |
Map<String, String[]> |
它可以获取请求头的信息(它可以获取多个值的情况) |
示例代码:
<body>
Header: ${ header } <br/>
User-Agent: ${ header["User-Agent"] } <br/>
Connection: ${ header["Connection"] } <br/>
User-Agent: ${ headerValues["User-Agent"][0] } <br/>
</body>
变量 | 类型 | 作用 |
---|---|---|
cookie |
Map<String, Cookie> |
它可以获取当前请求的 Cookie 信息 |
示例代码:
<body>
Cookie: ${ cookie } <br/>
Cookie name: ${ cookie.JSESSIONID.name } <br/>
Cookie value: ${ cookie.JSESSIONID.value } <br/>
</body>
变量 | 类型 | 作用 |
---|---|---|
initParm |
Map<String, String> |
它可以获取 web.xml 中配置的 <context-param> 上下文参数 |
示例代码:
web.xml
<context-param>
<param-name>username</param-name>
<param-value>gregPerlinLi</param-value>
</context-param>
<context-param>
<param-name>url</param-name>
<param-value>jdbc:mysql://localhost:3306/test</param-value>
</context-param>
otherElObj.jsp
<body>
Initialize parameter: ${ initParam } <br/>
Initialize username: ${ initParam.username } <br/>
Initialize url: ${ initParam.url } <br/>
</body>
2. JSTL 标签库(重点)
JSTL 标签库的全称是 JSP Standard Tag Library
jsp 标准标签库,是一个不断完善的开放源代码的 jsp 标签库。
EL 表达式主要是为了替代 jsp 中的表达式脚本,而 JSTL 则是为了替换 jsp 中的代码脚本,这样使得整个 jsp 页面变得更加简洁。
JSTL 由5个不同的标签库组成
功能范围 | URI | 前缀 |
---|---|---|
核心标签库(重点) | http://java.sum/com/jsp/jst/core | c |
格式化 | http://java.sum/com/jsp/jst/fmt | fmt |
函数 | http://java.sum/com/jsp/jst/functions | fn |
数据库(不使用) | http://java.sum/com/jsp/jst/sql | sql |
XML(不使用) | http://java.sum/com/jsp/jst/xml | x |
在 jsp 中使用 taglib
指令引入标签库
CORE
标签库
<%@ taglib prefix="c" uri="http://java.sum/com/jsp/jst/core" %>
XML
标签库
<%@ taglib prefix="x" uri="http://java.sum/com/jsp/jst/xml" %>
FMT
标签库
<%@ taglib prefix="fmt" uri="http://java.sum/com/jsp/jst/fmt" %>
SQL
标签库
<%@ taglib prefix="sql" uri="http://java.sum/com/jsp/jst/sql" %>
FUNCTIONS
标签库
<%@ taglib prefix="fn" uri="http://java.sum/com/jsp/jst/functions" %>
2.1. JSTL 标签库的使用步骤
1. 先导入 JSTL 标签库的 jar
包
2. 使用 taglib
指令引入标签库
2.2. CORE
核心库的使用
2.2.1. <c:set/>
标签
作用:set
标签可以往域中保存数据
示例代码:
<body>
<%--
<c:set/>
fieldObject.setAtribute(key, value)
scope: Set which domain to save to
page --> pageContext field (default)
request --> request field
session --> session field
application --> application field
var: Set the key
value: Set the value
--%>
Before: ${ requestScope.abc } <br/>
<C:set scope="request" var="abc" value="abcValue" />
After: ${ requestScope.abc } <br/>
</body>
2.2.2. <c:if/>
标签
作用: 可以用来做 if
判断
示例代码:
<body>
<%--
<c:if/>
test: Conditions of judgment (using EL expression to output)
--%>
<c:if test="${ 12 == 12 }">
<h1>12 == 12</h1>
</c:if>
<br/>
<c:if test="${ 12 != 12 }">
<h1>12 != 12</h1>
</c:if>
</body>
2.2.3. <c:choice> <c:when> <c:otherwise>
标签
作用: 多路判断,与 switch...case...default
非常接近
注意⚠️:
1. 标签里不能使用 HTML 注释,要使用 jsp 注释。
2. when
标签的父标签一定要是 choice
标签,想做多路判断的时候一定要先写 choice
标签。
示例代码:
<body>
<%--
<c:choice> <c:when> <c:otherwise>
choice: Start choosing judgment
when: Every judgment
test --> The value of the current judgment
otherwise: The rest situation
Attention: 1. HTML comments cannot be used in tags. Instead, use JSP annotations.
2. The parent of the when tag must be the choice tag, when you want to make multi-channel judgment, you must first write the choice tag.
--%>
<%
request.setAttribute("height", "195");
%>
<c:choose>
<c:when test="${ requestScope.height >= 190 }">
<h1>You are a giant!</h1>
</c:when>
<c:when test="${ requestScope.height >= 180 }">
<h2>You are quite tall</h2>
</c:when>
<c:when test="${ requestScope.height >= 180 }">
<h3>You are quite tall</h3>
</c:when>
<c:when test="${ requestScope.height >= 170 }">
<h4>it 's not bad</h4>
</c:when>
<c:otherwise>
<h5>The situation that lower than 170</h5><br/>
<c:choose>
<c:when test="${ requestScope.height >= 160 }">
<h5>Taller than 160</h5>
</c:when>
<c:when test="${ requestScope.height >= 150 }">
<h5>Taller than 150</h5>
</c:when>
<c:when test="${ requestScope.height >= 140 }">
<h5>Taller than 140</h5>
</c:when>
<c:otherwise>
<h5>Lower than 140</h5>
</c:otherwise>
</c:choose>
</c:otherwise>
</c:choose>
</body>
2.2.4. <c:forEach/>
标签
作用: 遍历输出使用
示例代码:
<body>
<%--
1. Traverse from 1 to 100 and output
begin: Set start index
end: Set end index
step: Step value of traversal
var: Variable of the loop (It is also the data currently being traversed)
varStatus: The state of the data currently traversed
for( int i = 1; i <= 10; i++ ) {}
--%>
<table>
<c:forEach begin="1" end="10" var="i">
<tr>
<td>The ${ i } row</td>
</tr>
</c:forEach>
</table>
<hr/>
<%--
2. Traversing object array
items: Traversal data source (traversal collection)
var: Data currently traversed
for( Object : arr ) {}
--%>
<%
request.setAttribute("array", new String[]{"13622887499", "13112224356", "13766543245"});
%>
<c:forEach items="${ requestScope.array }" var="item">
${ item } <br/>
</c:forEach>
<hr/>
<%--
3. Traversing the List collection
--%>
<%
List<Student> studentList = new ArrayList<Student>();
for (int i = 1; i <= 10; i++) {
studentList.add(new Student(i, "username" + i, "pass" + i, 18 + i, "phone" + i));
}
request.setAttribute("student", studentList);
%>
<table>
<tr>
<th>ID</th>
<th>Name</th>
<th>Password</th>
<th>Age</th>
<th>Phone</th>
</tr>
<c:forEach items="${ requestScope.student }" var="student">
<tr>
<td>${ student.id }</td>
<td>${ student.username }</td>
<td>${ student.password }</td>
<td>${ student.age }</td>
<td>${ student.phone }</td>
</tr>
</c:forEach>
</table>
<hr/>
<%--
4. Traversing the Map collection
for( Map.Entry<String, Object> entry : map.entrySet() ) {}
--%>
<%
Map<String, Object> map = new HashMap<String, Object>();
map.put("key1", "value1");
map.put("key2", "value2");
map.put("key3", "value3");
map.put("key4", "value4");
map.put("key5", "value5");
request.setAttribute("map", map);
%>
<table>
<tr>
<th>Map</th>
<th>Key</th>
<th>Value</th>
<th>Operation</th>
</tr>
<c:forEach items="${ requestScope.map }" var="entry">
<tr>
<td>${ entry }</td>
<td>${ entry.key }</td>
<td>${ entry.value }</td>
<td>Delete, Update</td>
</tr>
</c:forEach>
</table>
</body>