第九章 EL 表达式与 JSTL 标签库
创作日期:2021-12-28
9.1 EL 表达式简介
9.1.1 什么是 EL 表达式
EL 表达式的全称为:Expression Language 是表达式语言
9.1.2 EL 表达式的作用
EL 表达式主要代替 jsp 页面中的表达式脚本在 jsp 页面中进行数据的输出,因为 EL 表达式在输出数据的时候,要比 JSP 的表达式脚本更加简介
<%-- PrintHtml.jsp --%>
<body>
<%
request.setAttribute("key", "123");
%>
JSP 表达式脚本输出 key 的值为:<%= request.getAttribute("key")%><br>
EL 表达式输出 key 的值为:${key}
</body>
9.1.3 EL 表达式搜索域数据的顺序
EL 表达式主要是在 JSP 页面中输出数据,主要是输出域对象中的数据,当四个域对象中都有相同的 key 的数据的时候,EL 表达式会按照这四个域的范围由小到大的顺序进行搜索并输出,顺序为:pageContext 域,request 域,session 域 ,application 域
<%-- PrintHtml.jsp --%>
<body>
输出优先级为:pageContext 域,request 域,session 域 ,application 域
<%
pageContext.setAttribute("key", "123");
request.setAttribute("key", "123");
session.setAttribute("key", "123");
application.setAttribute("key", "123");
%>
</body>
9.1.4 EL表达式输出属性数据
EL 表达式支持输出 Bean 的普通属性,数组属性,List 集合属性,map 集合属性
演示:
创建测试类:
package com.jsp.text;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
/**
* @Description:测试类
* @author: XFDQ.lmq
* @create: 2022-08-11 18:01
*/
public class Person {
private String name;
private Integer[] Phones;
private List<String> citys;
private Map<String,Integer> results;
public Person() {
}
public Person(String name, Integer[] phones, List<String> citys, Map<String, Integer> results) {
this.name = name;
Phones = phones;
this.citys = citys;
this.results = results;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer[] getPhones() {
return Phones;
}
public void setPhones(Integer[] phones) {
Phones = phones;
}
public List<String> getCitys() {
return citys;
}
public void setCitys(List<String> citys) {
this.citys = citys;
}
public Map<String, Integer> getResults() {
return results;
}
public void setResults(Map<String, Integer> results) {
this.results = results;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", Phones=" + Arrays.toString(Phones) +
", citys=" + citys +
", results=" + results +
'}';
}
}
<%-- EL.jsp --%>
<body>
<%
LinkedList<String> cityLinkedList = new LinkedList<>();
cityLinkedList.add("China");
cityLinkedList.add("America");
cityLinkedList.add("Canada");
HashMap<String,Integer> resultsHashMap = new HashMap<>();
resultsHashMap.put("数学",92);
resultsHashMap.put("语文",98);
resultsHashMap.put("英语",90);
Person person = new Person();
person.setName("xfdq");
person.setPhones(new Integer[]{151,159});
person.setCitys(cityLinkedList);
person.setResults(resultsHashMap);
pageContext.setAttribute("person",person);
%>
输出Person:${person}<br>
输出Person的name属性:${person.name}<br>
输出Person的phones属性:${person.phones[0]}<br>
输出Person的citys属性:${person.citys[1]}<br>
输出Person的results属性:${person.results.get("数学")}分<br>
</body>
9.2 EL 表达式的运算
语法:${ 运算表达式 },EL 表达式支持如下运算符:
9.2.1 关系运算
<body>
比较结果:${2 == 4},a 不等于 b<br>
比较结果:${2 != 4},a 不等于 b<br>
比较结果:${2 > 4},a 小于 b<br>
比较结果:${2 < 4},a 小于 b<br>
比较结果:${2 >= 4},a 小于等于 b<br>
比较结果:${2 <= 4},a 小于等于 b
</body>
9.2.2 逻辑运算
<body>
比较结果:${2 == 4 && 2 < 4},false<br>
比较结果:${2 != 4 || 2 > 4},true<br>
比较结果:${!(2 < 4)},false<br>
</body>
9.2.3 算数运算
<body>
2 + 2 = ${2+2}<br>
2 - 2 = ${2-2}<br>
2 * 2 = ${2*2}<br>
2 / 2 = ${2/2}<br>
2 % 2 = ${2%2}<br>
</body>
9.2.4 empty 运算与三元运算
- empty 运算可以判断一个数据是否为空,如果为空,则输出 true,不为空输出 false
- 值为 null 值的时候,为空
- 值为 空串 的时候,为空
- 值是 Object 类型数组,长度为零的时候
- list 集合,元素个数为零
- map 集合,元素个数为零
<body>
<%
//1.值为 null 值的时候,为空
request.setAttribute("emptyNull", null);
//2.值为 空串 的时候,为空
request.setAttribute("emptyStr", "");
//3.值是 Object 类型数组,长度为零的时候
request.setAttribute("emptyArr",new Object[]{});
//4.list 集合,元素个数为零
List<String> stringList = new LinkedList<>();
request.setAttribute("emptyList", stringList);
//5.map 集合,元素个数为零
Map<String,Integer> stringIntegerMap = new HashMap<>();
request.setAttribute("emptyMap",stringIntegerMap );
%>
${empty emptyNull},为空<br>
${empty emptyStr},为空<br>
${empty emptyArr},为空<br>
${empty emptyList},为空<br>
${empty emptyMap},为空<br>
</body>
三元运算语法:表达式1?表达式2:表达式3,如果表达式1的值为真,返回表达式2的值,如果为假返回表达式3的值
<body>
${1>2?1+2:2-1},1<br>
</body>
9.2.5 点运算和中括号运算符
- 点运算可以输出 Bean 对象中某个属性的值
- 中括号运算可以输出有序集合中某个元素的值,并且还可以输出 map 集合里包含有特殊字符的 key 值
<body>
<%
Map map = new HashMap();
map.put("bbb","bbbvalue");
map.put("a+a+a","aaavlue");
request.setAttribute("map",map);
%>
${map.bbb}
${map["a+a+a"]}
</body>
9.3 EL 表达式的 11 个隐含对象
EL 表达式中 11 个隐含对象是 EL 表达式中自己定义的,可以直接使用
9.3.1 EL 表达式获取四个特定域中的属性
- 变量:pageScope
- 类型:Map<String,Object>,作用:获取 pageContext 域中的数据
- 变量:requestScope
- 类型:Map<String,Object>,作用:获取 Request 域中的数据
- 变量:sessionScope
- 类型:Map<String,Object>,作用:获取 Session 域中的数据
- 变量:applicationScope
- 类型:Map<String,Object>,作用:获取 ServletContext 域中的数据
<body>
<%
pageContext.setAttribute("key1", "value1");
request.setAttribute("key2", "value2");
session.setAttribute("key3", "value3");
application.setAttribute("key4", "value4");
%>
pageContext 域中的数据:${pageScope.key1}<br>
Request 域中的数据:${requestScope.key2}<br>
Session 域中的数据:${sessionScope.key3}<br>
ServletContext 域中的数据:${applicationScope.key4}<br>
</body>
9.3.2 pageContext 对象的使用
- 变量:pageContext
- 类型:PageContextImpl,作用:获取 JSP 中的九大内置对象
<body>
<%--
request.getScheme():获取请求的协议
request.getServerName():获取请求的服务器 IP 或者域名
request.getServerPort():获取请求的服务器端口号
request.getContextPath():获取当前工程路径
request.getMethod():获取请求的方式(POST/GET)
request.getRemoteHost():获取客户端的 ip 地址
request.getId():获取会话的唯一标识
--%>
<%
pageContext.setAttribute("req",request);
%>
1.协议:${req.scheme} <br>
2.服务器 IP:${req.serverName} <br>
3.服务器端口: ${req.serverPort}<br>
4.获取工程路径: ${req.servletPath}<br>
5.获取请求方法: ${req.method} <br>
6.获取客户端 IP 地址: ${req.remoteHost} <br>
7.获取会话的 ID 编号: ${req.session.id}<br>
</body>
9.3.3 EL 表达式其他隐含对象的使用
- 变量:param
- 类型:Map<String,String>,作用:获取请求参数的值
- 变量:paramValues
- 类型:Map<String,String[]>,作用:获取多个请求参数的值
- 变量:header
- 类型:Map<String,String>,作用:获取请求头的信息
- 变量:headerValues
- 类型:Map<String,String[]>,作用:获取多个请求头的信息
- 变量:cookie
- 类型:Map<String,Cookie>,作用:获取当前请求的 Cookie 的值
- 变量:initParam
- 类型:Map<String,String>,作用:获取在 web.xml 中配置的 <context-param> 上下文参数
<body>
获取 Cookie 的名称:${cookie.JSESSIONID.name}<br>
获取 Cookie 的值:${cookie.JSESSIONID.value}
</body>
9.4 JSTL 标签库
9.4.1 JSTL 标签库的简介
JSTL 标签库,全称是指 JSP Standard Tag Libray JSP 标准标签库,是一个不断完善的开放源代码的 JSP 标签库,EL 表达式主要是为了替换 JSP 中的表达式脚本,而标签库是为了替换代码脚本,这样使得整个 JSP 页面变得更加简介
JSTL 由五个不同功能的标签库组成:
9.4.2 JSTL 标签库的使用步骤
- 导入 JSTL 标签库的 jar 包
- 使用 taglib 指令引入标签库
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
9.4.3 core 核心库的使用
- <c:set></c:set> 标签:可以往域中保存数据
- scope 属性:设置保存到哪个域中
- var 属性:设置域中 key
- value 属性:设置域中 key 的值
- <c:if></c:if> 标签:做 if 判断
- test 属性:设置判断条件(使用 EL 表达式)
- <c:choose><c:when><c:otherwise> 标签:多个判断条件
- test 属性:设置判断条件(使用 EL 表达式)
- <c:forEach> 标签:遍历输出
- begin 属性:设置开始的索引
- end 属性:设置结束的索引
- var 属性:设置循环的变量
<body>
<c:set scope="page" var="xfdq" value="jsb"></c:set>
xfdq:${pageScope.xfdq}<br>
<c:if test="${pageScope.xfdq != null}">
xfdq:${pageScope.xfdq}<br>
</c:if>
<%
request.setAttribute("jsb", 19);
%>
<c:choose>
<c:when test="${requestScope.jsb >20}">
<div>人多</div>
</c:when>
<c:otherwise>
<div>人少</div>
</c:otherwise>
</c:choose>
<%-- forEach:遍历 1 到 10 --%>
<c:forEach begin="1" end="10" var="i">
${i}
</c:forEach><br>
<%-- 遍历 Object 数组 --%>
<%
request.setAttribute("arr",new Integer[]{123,234,345,456,567,678,789,890});
%>
<c:forEach items="${requestScope.arr}" var="item">
${item}
</c:forEach><br>
<%-- 遍历 Map 集合 --%>
<%
HashMap map = new HashMap();
map.put("key1","aaa");
map.put("key2","bbb");
map.put("key3","ccc");
map.put("key4","ddd");
request.setAttribute("map",map);
%>
<c:forEach items="${requestScope.map}" var="entry">
${entry.key} = ${entry.value}
</c:forEach><br>
</body>
9.5 文件的上传和下载
9.5.1 文件的上传操作
- 创建 form 标签,设置 method 属性为 post 请求
- form 标签的 encType 属性值必须为 multipart/form-data 值
- 在 form 标签中使用 input type=file 添加上传的文件
- 导入 jar 包:commons-fileupload-1.3.jar
- 编写服务器代码接收,处理上传的数据
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<welcome-file-list>
<welcome-file>EL.jsp</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>UpFile</servlet-name>
<servlet-class>com.jsp.servlet.UpFile</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>UpFile</servlet-name>
<url-pattern>/upfile</url-pattern>
</servlet-mapping>
<listener>
<listener-class>com.jsp.Listener.ServletContextListenerImpl</listener-class>
</listener>
</web-app>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<form action="http://localhost:8080/Jsp_web/upfile" method="post" enctype="multipart/form-data">
用户名:<input type="text" name="userName"><br>
头像:<input type="file" name="photo"><br>
<input type="submit" value="上传">
</form>
</body>
</html>
package com.jsp.servlet;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.util.List;
/**
* @Description:文件上传与下载
* @author: XFDQ.lmq
* @create: 2022-08-06 17:38
*/
public class UpFile extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1.先判断上传的数据是否为多段数据(只有是多段的数据,才是文件上传的)
if (ServletFileUpload.isMultipartContent(req)) {
//2.创建 FileItemFactory 工厂实现类
FileItemFactory fileItemFactory = new DiskFileItemFactory();
//3.创建用于解析上传数据的工具类 ServletFileUpload 类
ServletFileUpload servletFileUpload = new ServletFileUpload(fileItemFactory);
try {
//4.解析上传的数据,得到每一个表单项 FileItem
List<FileItem> fileItems = servletFileUpload.parseRequest(req);
System.out.println(fileItems);
//5.循环判断,每一个表单项是普通类型还是上传类型
for (FileItem f : fileItems) {
if (f.isFormField()) {
//普通表单项
System.out.println("表单项的 name 属性值:" + f.getFieldName());
//参数 "utf-8" 解决乱码问题
System.out.println("表单项的 name 属性值:" + f.getString("UTF-8"));
} else {
//上传的文件
System.out.println("表单项的 name 属性值:" + f.getFieldName());
System.out.println("上传的文件名:" + f.getName());
f.write(new File("G:\\照片"+f.getName()));
}
}
} catch (Exception e) {
System.out.println(e);
}
}
}
}
9.5.2 文件的下载操作
- 获取需要下载的文件名
- 读取要下载的文件内容
- 把下载的文件内容回传给客户端
- 在回传前,通过响应头告诉客户端返回的数据类型
- 通过响应头告诉客户端收到的数据是用于下载使用
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<welcome-file-list>
<welcome-file>EL.jsp</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>UpFile</servlet-name>
<servlet-class>com.jsp.servlet.UpFile</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>UpFile</servlet-name>
<url-pattern>/upfile</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>Download</servlet-name>
<servlet-class>com.jsp.servlet.Download</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Download</servlet-name>
<url-pattern>/download</url-pattern>
</servlet-mapping>
<listener>
<listener-class>com.jsp.Listener.ServletContextListenerImpl</listener-class>
</listener>
</web-app>
package com.jsp.servlet;
import org.apache.commons.io.IOUtils;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
/**
* @Description:文件下载
* @author: XFDQ.lmq
* @create: 2022-08-16 14:45
*/
public class Download extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1.获取需要下载的文件名
String downloadFileName = "66.jpg";
//2.读取要下载的文件内容
ServletContext servletContext = getServletContext();
//3.获取要下载文件的类型
String mimeType = servletContext.getMimeType("/file/" + downloadFileName);
//4.在回传前,通过响应头告诉客户端返回的数据类型
resp.setContentType(mimeType);
//5.通过响应头告诉客户端收到的数据是用于下载使用
/*
* Content-Disposition 表示怎么处理收到的数据
* attachment 表示下载使用
* filename 表示下载的文件名
* */
resp.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("Java.jpg", "UTF-8"));
//6.获取输入流
InputStream resourceAsStream = servletContext.getResourceAsStream("/file/" + downloadFileName);
//7.获取响应的输出流
OutputStream outputStream = resp.getOutputStream();
//8.读取输入流中的全部数据,复制给输出流,输出给客户端
IOUtils.copy(resourceAsStream, outputStream);
}
}
上一节:
下一节:
本文含有隐藏内容,请 开通VIP 后查看