九、EL表达式&JSTL标签库&文件上传下载
1、EL表达式
1.1、什么是EL表达式,EL表达式的作用?
1、内容
1、EL表达式的全称为:expression Language 是表达式语言
2、作用:主要是代替jsp页面中的表达式脚本在jsp页面中进行数据的输出
3、EL表达式在输出数据的时候,比jsp表达式脚本简洁
4、EL表达式的格式:${表达式内容}
5、EL表达式在输出null值的时候,输出的是空串。jsp表达式输出null值的时候,输出的是null字符串
2、例子

1.2、EL表达式搜索域数据的顺序
1、内容
1、EL表达式主要是在jsp页面中输出数据
2、主要是输出域对象中的数据
3、当四个域都有相同的key数据时,EL表达式会按照四个域的从小到大的顺序去进行搜索,找到就输出。
2、例子

1.3、EL表达式输出Bean的属性和集合属性
1、需求
1、输出Persion类中的普通属性,数组属性。list集合属性和map集合属性
2、代码
1、Persion类
package com.qt.pojo;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
public class Person {
private String name;
private String[] phone;
private List<String> cities;
private Map<String,Object> map;
//get和set方法、构造器我这里省略要写的
public int getAge(){
return 18;
}
}
2、页面代码.jsp

1.4、EL表达式——运算
1、格式:${ 运算表达式 }
1、关系运算
1、内容

2、逻辑运算
1、内容

3、算数运算
1、内容

4、Empty运算
1、内容
(1)、empty运算可以判断一个数据是否为空,如果为空,则输出true,不为空输出false
2、以下情况为空:
(1)值为null值的时候,为空
(2)值为空串的时候,为空
(3)值是Object类型数组,长度为0的时候
(4)list集合,元素个数为0
(5)map集合,元素个数为0
3、例子

5、三元运算
1、和java一样
2、格式:表达式1?表达式2:表达式3
3、例子
${12==12?"涛哥帅啊":"涛哥不帅"}
6、"."运算和[]中括号运算符
1、.运算,可以输出Bean对象中的某个属性值
2、[]中括号运算,可以输出有序集合中的某个元素,要加脚标
3、[]中括号运算,可以输出map集合中key含有特殊字符的key对应的值
4、例子

1.5、EL表达式的11个隐含对象
1、EL表达式中的11个隐含对象,是EL表达式中自己定义的,可以直接使用
1、内容
| 变量 | 类型 | 作用 |
|---|---|---|
| pageContext | PageContextImpl | 它可以获取jsp中的九大内置对象 |
| pageScope | Map<String,Object> | 它可以获取PageContext域中的数据 |
| requestScope | Map<String,Object> | 获取Request域中的数据 |
| sessionScope | Map<String,Object> | 获取Session域中的数据 |
| applicationScope | 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中配置的\ |
2、EL获取四个特定域中的属性
1、内容

2、例子

3、pageContext对象的使用
1、协议
2、服务器
3、服务器端口号
4、获取工程路径
5、获取请求方法
6、获取客户端ip地址
7、获取回话的id编号
8、使用jsp表达式函数获取(例子)

9、使用EL表达式获取(例子)

10、一般EL表达式 .后跟着scheme,就相当于调用jsp中的getScheme()方法,所以比jsp方便。
4、表达式其他隐含对象的使用
1、param和paramValues对象的例子

2、header和headerValues对象的例子

3、cookie对象的例子

4、initParam对象的例子

2、JSTL标签库
2.1、介绍以及引用
1、JSTL标签库介绍
1、全称是JSP Standard Tag Library JSP标准标签库。
2、作用:主要是为了替换代码脚本。使得脚本更整洁
3、JSTL五个不同功能的标签库

2、JSTL标签库的使用步骤
1、引入jstl标签库的jar包

2、使用taglib指令引入标签库

2.2、core核心库的使用
1、\ 使用
1、作用:set标签可以往域中保存数据
2、例子
保存之前:${requestScope.abc}<br>
<c:set scope="request" var="abc" value="我是大哥"/>
保存之后:${requestScope.abc}<br>
3、page表示设置PageContext域(默认值)
4、var属性:设置key值
5、value属性:设置value值
2、\ 使用
1、作用:if标签用来做if判断语句
2、例子
<c:if test="${12==12}">
<h1>12等于12</h1>
</c:if>
3、test属性:表示判断条件(使用EL表达式)
3、\\\使用
1、作用:多路判断
2、和switch...case...default非常接近
3、例子
<%
request.setAttribute("height",151);
%>
<c:choose>
<c:when test="${requestScope.height>190}">
<h2>我是小巨人</h2>
</c:when>
<c:when test="${requestScope.height>180}">
<h2>是河南人</h2>
</c:when>
<c:when test="${requestScope.height>170}">
<h2>我是普通人</h2>
</c:when>
<c:when test="${requestScope.height>160}">
<h2>我是好人</h2>
</c:when>
<c:otherwise>
<c:choose>
<c:when test="${requestScope.height>150}">
<h2>我是个人</h2>
</c:when>
</c:choose>
</c:otherwise>
</c:choose>
4、choose标签:开始选择判断
5、when标签:表示每一种判断(类似case)
6、test属性:当前判断情况的值
7、otherwise标签:剩下的情况(default)
8、注意
(1)标签内不能使用html注释,要用jsp的
(2)when标签库的父标签一定要是choose标签
4、\ 作用
1、作用:遍历输出
2、遍历1-10,输出(例子)
<%-- 遍历1——10输出
begin属性:设置开始变量
end属性:设置结束变量
var 属性表示循环的变量(也是当前正在遍历到的数据)
--%>
<table border="1">
<c:forEach begin="1" end="10" var="i">
<tr>
<td>第${i}行</td>
</tr>
</c:forEach>
</table>
3、遍历Object数组
<%--
遍历Object数组
for(Object item:arr)
item 表示遍历的数据源(遍历的集合)
var 表示当前遍历到的数据
--%>
<%
request.setAttribute("arr",new String[]{"123456","7714813246","10086"});
%>
<c:forEach items="${requestScope.arr}" var="item">
${item}<br>
</c:forEach>
4、遍历Map 集合
<%
Map<String,Object> map = new HashMap<>();
map.put("key1","value1");
map.put("key2","value2");
map.put("key3","value3");
map.put("key4","value4");
request.setAttribute("map",map);
%>
<c:forEach items="${requestScope.map}" var="entry">
<h1>${entry.key}=${entry.value}</h1>
</c:forEach>
5、遍历 List 集合---list 中存放 Student 类,有属性:编号,用户名,密码,年龄, 电话信息
(1)String类
public class Student {
// 编号,用户名,密码,年龄,电话信息
private Integer id;
private String name;
private String password;
private Integer age;
private String phone;
get和set和构造器和toString方法省略(自己写)
(2)jsp代码
<%--
遍历list集合
编号,用户名,密码,年龄,电话信息
--%>
<%
List<Student> studentList = new ArrayList<>();
for(int i=1;i<=10;i++){
studentList.add(new Student(i,"username"+i,"password"+i,18+i,"message"+i));
}
request.setAttribute("stus",studentList);
%>
<table border="1">
<tr>
<th>编号</th>
<th>用户名</th>
<th>密码</th>
<th>年龄</th>
<th>电话信息</th>
<th>操作</th>
</tr>
<%-- item 表示遍历的集合
var 表示遍历的数据
begin表示遍历的开始索引值
end 表示遍历结束的索引值
step 属性表示遍历的步长值,相关的i++,默认是1
varStatus 属性表示当前遍历到的数据的状态
--%>
<c:forEach begin="2" end="7" step="1" varStatus="status" items="${requestScope.stus}" var="stu">
<%-- <hr>--%>
<tr>
<td>${stu.id}</td>
<td>${stu.name}</td>
<td>${stu.password}</td>
<td>${stu.age}</td>
<td>${stu.phone}</td>
<td>${stu.phone}</td>
<td>${status}</td>
<td>删除、修改</td>
</tr>
${stu}
</c:forEach>
</table>
3、文件上传和下载
3.1、文件上传的介绍
1、要求
1、要有一个form标签,method=post请求
2、form标签的encType属性值必须为multipart/form-data值
3、在form标签中使用input type=file 添加上传文件
4、编写服务器代码(Servlet)程序接收,处理上传的数据
5、multipart/form-data表示提交数据,以多段(每一个表单项一个数据段)的形式进行拼接,然后以二进制流的形式发送给服务器
3.2、文件上传,HTTP协议的说明
1、内容

3.3、commons-fileupload.jar 常用 API 介绍说
1、操作
1、需要导入两个jar包

2、该jar包中的常用类
| 类和方法 | 作用 |
|---|---|
| ServletFileUpload | 解析上传数据 |
| FileItem | 表示每一个表单项 |
| boolean ServletFileUpload.isMultipartContent(HttpServletRequest request) | 判断当前上传数据格式是否为多段式 |
| public List\ |
解析上传的数据 |
| boolean FileItem.isFormField() | 判断当前这个表单项,是否是普通的表单项。还是上传的文件类型。 true 表示普通类型的表单项 false 表示上传的文件类型 |
| String FileItem.getFieldName() | 获取表单项的 name 属性值 |
| String FileItem.getString() | 获取当前表单项的值。 |
| String FileItem.getName(); | 获取上传的文件名 |
| void FileItem.write( file ); | 将上传的文件写到 参数 file 所指向抽硬盘位置 。 |
3、Fileupload类的使用(例子)
1、jsp页面代码
<form action="http://localhost:8080/09_EL_JSTL/uploadServlet" method="post" enctype="multipart/form-data">
用户名:<input type="text" name="username"/><br>
头像:<input type="file" id="photo"/><br>
<input type="submit" name="sub" value="上传"/><br>
</form>
2、servlet代码
package com.qt.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.ServletInputStream;
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;
public class UploadServlet extends HttpServlet {
/**
* 用来处理文件上传数据
* @param req
* @param resp
* @throws ServletException
* @throws IOException
*/
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// System.out.println("文件上传了");
//// System.out.println(req.getParameter("username"));
// ServletInputStream inputStream = req.getInputStream();
// byte[] buffer = new byte[102400000];
// int read = inputStream.read(buffer);
// System.out.println( new String(buffer,0,read));
// 判断文件上传的数据是否是多端数据(只有多端数据,才是文件上传的)
if(ServletFileUpload.isMultipartContent(req)){
// 创建FileItemFactory工厂实现类
FileItemFactory fileItemFactory = new DiskFileItemFactory();
// 创建用语解析上传数据的工具类ServletFileUpload
ServletFileUpload servletFileUpload = new ServletFileUpload(fileItemFactory);
try {
// 解析上传的数据,得到每个表单项FileItem
List<FileItem> list = servletFileUpload.parseRequest(req);
// 循环判断,每个表单项,是普通类型,还是文件上传类型
for (FileItem fileItem :list){
if(fileItem.isFormField()){
// 普通表单项
System.out.println("表单项的name属性:"+fileItem.getFieldName());
System.out.println("表单项的value属性:"+fileItem.getString("UTF-8"));
}else {
// 上传 文件
System.out.println("表单的name属性值:"+fileItem.getFieldName());
System.out.println("上传的文件名:"+fileItem.getName());
fileItem.write(new File("E:\\"+fileItem.getName()));
}
}
}catch (Exception e){
e.printStackTrace();
}
}
}
}
3.4、文件下载
1、下载的常用AIP
1、内容

2、response.setHeader("Content-Disposition", "attachment; fileName=1.jpg");
(1)这个响应头告诉浏览器。这是需要下载的。
(2) attachment 表示附件,也就是下载的一个文件。
(3)fileName=后面, 表示下载的文件名。
3.5、attachment 附件解决中文乱码问题的方案
1、URLEncoder 解决 IE 和谷歌浏览器的 附件中 文名问题
1、使用的是IE浏览器或者谷歌浏览器
2、例子
resp.setHeader("Content-Disposition","attachment;filename="+ URLEncoder.encode("大美女.jpg","UTF-8"));
//Content-Disposition:表示收到的数据怎么处理
// attachment:表示附件,表示下载使用
// filename:设置文件名字,默认是使用英文
// URL编码是把汉字转化为%xx%xx的格式
2、BASE64 编解码 解决 火狐浏览器的附件中文名问题
1、使用BASE64 编解码需要导包
2、格式

3、解决浏览器兼容问题方案(例子)
