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 表达式会按照四个域的从小到大的排序去进行搜索,找到就进行输出。
<body>
<%
pageContext.setAttribute("key", "pageContext");
request.setAttribute("key", "request");
session.setAttribute("key", "session");
application.setAttribute("key", "application");
%>
${ key } <%-- 从域范围最小开始向上查找对应 key 值,若找到则直接返回 key 对应的 value 值 --%>
</body> 例(用 EL 表达式输出 Bean 的普通属性、数组属性、List 集合属性、map 集合属性):
<body>
<%
String name = "Tom";
String[] phones = new String[]{"100", "110", "119"};
List<String> hobbys = new ArrayList<>();
hobbys.add("C++");
hobbys.add("Java");
hobbys.add("Python");
Map<String, String> cities = new HashMap<>();
cities.put("key1", "Bejing");
cities.put("key.1", "ChengDu");
cities.put("key3", "FuJian");
Person p = new Person(name, phones, hobbys, cities);
pageContext.setAttribute("p", p);
%>
输出 Person 对象:${ p } <br />
输出 Person 的 name 属性:${ p.name } <br />
输出 Person 的 Phones 数组属性:${ p.phones} <br />
输出 Person 的 Phones 数组的元素值:${ p.phones[2] } <br />
素材 Person 的 List 集合: ${ p.hobbys } <br />
输出 Person 的 List 集合中的个别元素值:${ p.hobbys[1] } <br />
输出 Person 的 Map 集合: ${ p.cities } <br />
输出 Person 的 Map 集合中某个 key 的值:${ p.cities.key3 }, ${ p.cities["key1"] }, ${p.cities["key.1"]} <br />
</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 的属性方法:
域变量名.keypageContext 对象获取以下属性示例:
<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 标签库
<%@ 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" %>JSTL 常见标签的使用
设置四个域对象中的值:
<c:set scope="page|request|session|application" val="属性名" value="属性值" />if 判断标签:
<c:if test="判断的条件(EL表达式)"> 输出的内容 </c:if>`多路判断标签(类似 switch ... case ... default ...):
<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 遍历标签:
普通数值的遍历:
<c:forEach begin="开始索引值" end="结束值" step="步长" var="循环的遍历变量" varStatus="表示当前遍历到的数据状态"> 循环内容 </c:forEach>Object 数组对象、Map、List 集合的遍历:
<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 添加上传的文件
编写服务器代码接收,处理上传的数据
// 这里设置浏览器页面和服务器的编码一致,保证传输数据不会出现乱码 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. 文件的下载
获取要下载的文件名
读取要下载的文件内容
将文件类型告诉给浏览器
通过响应头告诉浏览器返回给浏览器的内容是用于下载使用的
将文件内容回传给浏览器
String 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