EL 表达式、JSTL 标签库、文件上传与下载
EL 表达式、JSTL 标签库、文件上传与下载
EL 表达式 与 JSTL 标签库
EL 表达式
EL 表达式概述以及它的作用
EL 表达式的全称是:Expression Language,即 表达式语言。
EL 表达式的作用:主要是为了替代 jsp 页面中的表达式脚本在 jsp 页面中进行数据输出。因为 EL 表达式在输出数据的时候,要比 jsp 的表达式脚本要简洁很多。
EL 表达式的格式: ${ 表达式 }
EL 表达式在输出 null 值的时候,输出的是空串。 jsp 表达式脚本输出 null 值的时候,输出的是 null 字符串。
EL 表达式的搜索域的顺序
EL 表达式主要是在 jsp 页面中进行数据输出,而且主要是输出域中对象的数据。
当 jsp 四大域对象都有相同 key 属性时,EL 表达式会按照四个域的从小到大的排序去进行搜索,找到就进行输出。
1 | <body> |
例(用 EL 表达式输出 Bean 的普通属性、数组属性、List 集合属性、map 集合属性):
1 | <body> |
EL 表达式的运算
语法格式:${ 运算表达式 }
,EL表达式支持如下运算符:
关系运算符
关系运算符 说 明 范 例 结果 == 或 eq 等于 ${ 5 == 5 } 或 ${ 5 eq 5 } ture != 或 ne 不等于 ${ 5 !=5 } 或${ 5 ne 5 } false < 或 lt 小于 ${ 3 < 5 } 或${ 3 lt 5 } true &rt; 或 gt 大于 ${ 2 > 10 } 或${ 2 gt 10 } false ≤ 或 le 小于等于 ${ 5 <= 12 } 或${ 5 le 12 } true ≥ 或 ge 大于等于 ${ 3 >= 5 } 或${ 3 ge 5 } false 逻辑运算符
关系运算符 说 明 范 例 结果 && 或 and 与运算 ${ 12 == 12 && 12 < 11 } 或 ${ 12 == 12 and 12 < 11 } false || 或 or 或运算 ${ 12 == 12 || 12 < 11 } 或 ${ 12 == 12 or 12 < 11 } true ! 或 not 取反运算 ${ !true } 或 ${not true } false 算数运算符
关系运算符 说 明 范 例 结果 + 加法 ${ 12 + 18 } 30 - 减法 ${ 18 - 8 } 10 * 乘法 ${ 12 * 12 } 144 / 或 div 除法 ${ 144 / 12 } 或 ${ 144 div 12 } 12 % 或 mod 取模 ${ 144 % 10 } 或 ${ 144 mod 10 } 4 empty 运算
empty 运算可以判断是否未空,如果为空,则输出 ture,不为空则输出 false。
以下几种情况为空:
- 值为 null 值时
- 值为 空串 时
- 值是 Object 类型数组,长度为 0 时
- list 集合、map 集合元素个数为 0 时
三元运算
格式:
表达式1 ? 表达式2 : 表达式3
如果表达式 1 的值为真,返回表达式 2 的值,如果表达式 1 的值为假,返回表达式 3 的值。
示例:
${ 12 == 12 ? "Yes!" : "No!" }
“.” 运算 和 “[]” 中括号运算
“.” 运算,可以输出 Bean 对象中的某个属性的值。
“[]” 运算,可以输出有序集合中某个元素的值。并且该运算符可以输出 map 中 key 含有特殊字符的 key 值。
EL 表达式中的 11 个隐含对象
EL 表达式中 11 个隐含对象,是 EL 表达式中自己定义的,可以直接使用。
变量名 | 类型 | 作用 |
---|---|---|
pageContext | PageContextImpl | 它可以获取 jsp 中的九大内置对象 |
pageScope | Map < String,Object > | 它可以获取 pageContext 域中的数据 |
requestScope | Map < String,Object > | 它可以获取 Request 域中的数据 |
sessionScope | Map < String,Object > | 它可以获取 Session 域中的数据 |
aplicationScope | Map < String,Object > | 它可以获取 ServletContext 域中的数据 |
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 中配置的 |
获取 jsp 四个域对象 pageScope、requestScope、sessionScope、aplicationScope 的属性方法:**
域变量名.key
**pageContext 对象获取以下属性示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18<body>
<%
pageContext.setAttribute("req", request);
%>
协议:${req.scheme} <br />
工程路径:${req.contextPath} <br />
请求方法:${req.method} <br />
客户端 IP:${req.remoteHost} <br />
服务器 IP:${req.serverName} <br />
服务器端口号:${req.serverPort} <br />
会话的 ID 编号:${req.session.id} <br />
</body>
JSTL 标签库
JSTL 标签库的作用以及组成
JSTL 标签库的全称是 JSP Standard Tag Library JSP 标准标签库,是一个不断完善的开放源代码的 JSP 标签库。
EL 表达式主要是为了替换 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 |
JSTL 标签库的使用
使用 JSTL 标签库需要导入 JSTL 标签库的 jar 包以及在 jsp 标签库中使用 taglib 指令引入标签库,如下对应标签库标签:
CORE 标签库
1 | <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> |
XML 标签库
1 | <%@ taglib prefix="x" uri="http://java.sun.com/jsp/jstl/xml" %> |
FMT 标签库
1 | <%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> |
SQL 标签库
1 | <%@ taglib prefix="sql" uri="http://java.sun.com/jsp/jstl/sql" %> |
FUNCTIONS 标签库
1 | <%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> |
JSTL 常见标签的使用
设置四个域对象中的值:
1
<c:set scope="page|request|session|application" val="属性名" value="属性值" />
if 判断标签:
1
<c:if test="判断的条件(EL表达式)"> 输出的内容 </c:if>`
多路判断标签(类似 switch … case … default …):
1
2
3
4
5
6
7
8
9
10
11
12<c:choose>
<c:when test="EL表达式判断条件1">
条件1成立执行内容
</c:when>
<c:when test="EL表达式判断条件2">
条件2成立执行内容
</c:when>
...
<c:otherwise>
when 中条件都不成立执行 otherwise 中的语句
</c:otherwise>
</c:choose>forEach 遍历标签:
普通数值的遍历:
1
2
3<c:forEach begin="开始索引值" end="结束值" step="步长" var="循环的遍历变量" varStatus="表示当前遍历到的数据状态">
循环内容
</c:forEach>Object 数组对象、Map、List 集合的遍历:
1
2
3<c:forEach items="EL表达式获取到的数组" var="循环的遍历变量名" varStatus="表示当前遍历到的数据状态">
循环内容
</c:forEach>
文件的上传与下载
1. 上传与下载常用 API
上传常用
可以使用第三方 jar 包,进行对上传到服务器的数据进行解析:
commons-fileupload.jar (依赖 commons-io.jar )
在 commons-fileupload 和 commons-io 包中常用的类与其方法:
ServletFileUpload 类:用于解析上传的数据
`boolean ServletFileUpload.isMultipartContext(HttpServletRequest request)`
用于判断当前上传的数据格式是否是多段格式。true 表示为当前数据是多段数据,反之亦然。
`public List<FileItem> parseRequest(HttpServletRequest request)`
解析上传的数据
FileItem 类:表示每个表单项
`boolean FileItem.isFormField()`
判断当前这个表单项,是否是普通的表单项,还是上传文件的表单项。true 表示前者,false 表示后者
`String FileItem.getFieldName()`
获取表单项的 name 属性值
`String FileItem.getString()`
获取当前表单项的值
`String FileItem.getName()`
获取上传的文件名
`void FileItem.write(file)`
将上传的文件写到参数 file 所指向的硬盘位置
下载常用
servletContext.getMimeType()
获取下载的文件类型
response.setContentType()
告诉浏览器下载的文件数据类型
response.setHeader()
将参数 “Content-Disposition” 与 “attachement; fileName=” + fileName 传入,告诉浏览器这是下载操作
response.getOutputStream()
获取服务器响应的输出流
servletContext.getResourceAsStream()
获取服务器上文件内容的文件输入流
2. 文件的上传
要有一个 form 标签,并且 method 属性值为 post 请求(get 请求有长度限制,所以一般使用 post 请求)
form 标签的 encType 属性值必须为 multipart/form-data 值(表示提交的数据,以多段的数据进行拼接)
在 form 标签中使用 input type = file 添加上传的文件
编写服务器代码接收,处理上传的数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34// 这里设置浏览器页面和服务器的编码一致,保证传输数据不会出现乱码
resp.setContentType("text/html; charset=UTF-8");
// 判断上传的数据是否是多段数据
if (ServletFileUpload.isMultipartContent(req)){
// 创建 FileItemFactory 工厂实现类
FileItemFactory fileItemFactory = new DiskFileItemFactory();
// 创建用于解析上传数据的 ServletFileUpload 工具类
ServletFileUpload servletFileUpload = new ServletFileUpload(fileItemFactory);
try {
// 解析上传的数据得到每一个表单项
List<FileItem> list = servletFileUpload.parseRequest(req);
PrintWriter writer = resp.getWriter();
// 判断表单项是否为普通表单项还是文件上传表单项
for (FileItem item : list){
if (item.isFormField()){
String fieldName = item.getFieldName();
String value = item.getString("UTF-8");
writer.print(fieldName + " = " + value);
} else {
// 获取文件名,上传文件到 File 指向的位置
String fileName = item.getName();
item.write(new File("D://" + fileName));
writer.print("上传成功!");
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
3. 文件的下载
获取要下载的文件名
读取要下载的文件内容
将文件类型告诉给浏览器
通过响应头告诉浏览器返回给浏览器的内容是用于下载使用的
将文件内容回传给浏览器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19String path = "/file/";
// 1. 获取要下载的文件名
String fileName = req.getParameter("fileName");
// 2. 读取要下载的文件内容
ServletContext servletContext = getServletContext();
InputStream resourceAsStream = servletContext.getResourceAsStream(path + fileName);
// 3. 将文件类型返回给浏览器
String mimeType = servletContext.getMimeType(path + fileName);
System.out.println("文件类型为:" + mimeType);
resp.setContentType(mimeType);
// 4. 通过响应头告诉浏览器,返回的内容是用于下载使用的
resp.setHeader("Content-Disposition", "attachment;fileName="+ fileName);
// 5. 将文件内容会传给浏览器
ServletOutputStream outputStream = resp.getOutputStream();
IOUtils.copy(resourceAsStream, outputStream); // 用 commons-io 包下的 IOUtils