JavaWeb第七天

该文档是:JavaWeb学习

博客连接:https://www.loveuluo.cn

日期:2020-12-13

1. 什么是EL表达式,EL表达式的作用

EL 表达式的全称是:Expresion Language。是表达式语言。
EL 表达式的什么作用:EL 表达式主要是代替 jsp 页面中的表达式脚本在 jsp 页面中进行数据的输出。
因为 EL 表达式在输出数据的时候,要比 jsp 的表达式脚本要简洁很多。

image-20201213111116631

EL 表达式的格式是:${表达式}
EL 表达式在输出 nul 值的时候,输出的是空串。jsp 表达式脚本输出 nul 值的时候,输出的是 nul 字符串。

2. EL表达式搜索域数据的顺序

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

image-20201213111205109

3. EL 表达式输出 Bean 的普通属性,数组属性。List 集合属性,map 集合属性

需求—输出 Person 类中普通属性,数组属性。list 集合属性和 map 集合属性。

Person 类:

image-20201213111331502

输出的代码:

image-20201213111403822

4. EL 表达式—运算

语法:${ 运算表达式 } , EL 表达式支持如下运算符:

4.1 关系运算

image-20201213111501323

4.2 逻辑运算

image-20201213111512330

4.3 算数运算

image-20201213111555027

4.4 empty 运算

empty 运算可以判断一个数据是否为空,如果为空,则输出 true,不为空输出 false。
以下几种情况为空:
1、值为 nul 值的时候,为空
2、值为空串的时候,为空
3、值是 Object 类型数组,长度为零的时候
4、list 集合,元素个数为零
5、map 集合,元素个数为零

代码测试:

image-20201213111623309

4.5 三元运算

表达式 1?表达式 2:表达式 3
如果表达式 1 的值为真,返回表达式 2 的值,如果表达式 1 的值为假,返回表达式 3 的值。

示例:

image-20201213111708004

4.6 “.”点运算 和 [] 中括号运算符

.点运算,可以输出 Bean 对象中某个属性的值。
[]中括号运算,可以输出有序集合中某个元素的值。
并且[]中括号运算,还可以输出 map 集合中 key 里含有特殊字符的 key 的值。

image-20201213111930902

5. EL 表达式的 11 个隐含对象

变量类型作用
pageContextPageContextImpl它可以获取 jsp 中的九大内置对象
pageScopeMap<String,Object>它可以获取 pageContext 域中的数据
requestScopeMap<String,Object>它可以获取 Request 域中的数据
seionScopeMap<String,Object>它可以获取 Session 域中的数据
applicationScopeMap<String,Object>它可以获取 ServletContext 域中的数据
paramMap<String,String>它可以获取请求参数的值
paramValuesMap<String,String[]>它也可以获取请求参数的值,获取多个值的时候使用。
headerMap<String,String>它可以获取请求头的信息
headerValuesMap<String,String[]>它可以获取请求头的信息,它可以获取多个值的情况
cookieMap<String,Cookie>它可以获取当前请求的 Cookie 信息
initParamMap<String,String>它可以获取在 web.xml 中配置的<context-param>上下文参数

5.1 EL 获取四个特定域中的属性

image-20201213112449197

代码测试:

image-20201213112421173

5.2 pageContex 对象的使用

image-20201213112438725

代码测试:

image-20201213112521127

5.3 EL 表达式其他隐含对象的使用

parm和paramValues:

image-20201213112559142

header和headerValues:

image-20201213112629935

cookie:

image-20201213112645596

initParam:

image-20201213112711576

6. JSTL 标签库

JSTL 标签库 全称是指 JSPtandar Tag Libray JSP 标准标签库。是一个不断完善的开放源代码的 JSP 标签库。
EL 表达式主要是为了替换 jsp 中的表达式脚本,而标签库则是为了替换代码脚本。这样使得整个 jsp 页面变得更佳简洁。

JSTL 由五个不同功能的标签库组成:

image-20201213155013406

在jsp标签库中使用 taglib指令引入标签库:

image-20201213155113077

7. JSTL 标签库的使用步骤

image-20201213155135457

8. core 核心库使用

8.1 <c:set />(使用很少)

作用:set 标签可以往域中保存数据

image-20201213155209641

8.2 <c:if />

if 标签用来做 if 判断。

image-20201213155231435

8.3 <c:choose> <c:when> <c:otherwise>标签

作用:多路判断。跟 switch . case . default 非常接近

image-20201213155327546

8.4 <c:forEach />

作用:遍历输出使用。

8.4.1 遍历 1 到 10,输出

示例代码:

image-20201213155415058

8.4.2 遍历 Object 数组

示例代码:

image-20201213155436369

8.4.3 遍历 Map 集合

示例代码:

image-20201213155453306

8.4.4 遍历 List 集合

list 中存放 Student 类,有属性:编号,用户名,密码,年龄,电话信息

Student 类:

image-20201213155614802

示例代码:

image-20201213155631097

其中的varStatus(这是个类实现了LoopTagStatus接口) 的状态的方法有:

image-20201213155725162

9.文件上传和下载功能(重要)

9.1 为什么要用文件上传和下载

文件的上传和下载,是非常见的功能。很多的系统中,或者软件中都经常使用文件的上传和下载。
比如:Q 头像,就使用了上传。
邮箱中也有附件的上传和下载功能。
OA 系统中审批有附件材料的上传。

9.2 文件的上传介绍

1、要有一个 form 标签,method=post 请求
2、form 标签的 encType 属性值必须为 multipart/form-dat 值
3、在 form 标签中使用 inputype=file 添加上传的文件
4、编写服务器代码(Servlet 程序)接收,处理上传的数据。

encType=multipart/form-dat 表示提交的数据,以多段(每一个表单项一个数据段)的形式进行拼接,然后以二进制流的形式发送给服务器

代码简单实现:

页面:

image-20201214102050954

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <%--这里必须加上 enctype="multipart/form-data" 这个属性,否则服务器接收不到数据只是单纯的文件的名称。--%>
     <form method="post" action="http://localhost:8080/08_jsp/uploadServlet" enctype="multipart/form-data">
         用户名:<input type="text" name="username"><br>
         头像:<input type="file" name="photo">
         <input type="submit" value="上传">
     </form>
</body>
</html>

Servlet程序代码:

public class UploadServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //System.out.println(request.getParameter("username"));
        //System.out.println(request.getParameter("photo"));
        //因为表单上有enctype="multipart/form-data"这个属性,不能再直接使用getParameter接受,要开一个流来接受。
        ServletInputStream inputStream = request.getInputStream(); //得到一个InputStream读取流
        byte[] bytes=new byte[1024]; //创建一个byte数组 一次读这些进去
        int read = 0;
        while ((read = inputStream.read(bytes))!=-1){ //返回的是读取的数量,如果读的时候没有任何一个值,会返回-1,返回-1时结束循环。*/
            System.out.print(new String(bytes,0,read));//将数组的二进制内容转换为字符串 起始值0,转换的数量为read也就是读取到的数量
        }
    }
}

输出的结果(下边会介绍里边的结果分别代表什么和如何处理这些二进制数据):

image-20201214102243189

9.3 文件上传,HTPP 协议的说明

这里的一段数据的开始对应的就是上边输出的结果。

image-20201214102613951

9.4 comons-fileupload.jar 常用 API 介绍说明

这个jar包可以用来处理二进制数据等等操作..

comons-fileupload.jar 需要依赖 comons-io.jar 这个包,所以两个包我们都要引入。

第一步,就是需要导入两个 jar 包:
comons-fileupload-1.21.jar
comons-io1.4jar

comons-fileupload.jar 和 comons-io.jar 包中,我们常用的类有哪些?

image-20201214103208580

9.5 使用fileupload类库完成文件上传

页面:

image-20201214105754243

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <%--这里必须加上 enctype="multipart/form-data" 这个属性,否则服务器接收不到数据只是单纯的文件的名称。--%>
     <form method="post" action="http://localhost:8080/08_jsp/uploadServlet" enctype="multipart/form-data">
         用户名:<input type="text" name="username"><br>
         头像:<input type="file" name="photo">
         <input type="submit" value="上传">
     </form>
</body>
</html>

Servlet程序代码:

public class UploadServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        //1.先判断上传的数据是否多段数据(只有是多段的数据(enctype="multipart/form-data"),才是文件上传的)
        if (ServletFileUpload.isMultipartContent(request)){
            //创建 FileItemFactory 工厂实现类
            FileItemFactory fileItemFactory =new DiskFileItemFactory();
            //创建用于解析上传数据的工具类 ServletFileUpload 类
            ServletFileUpload servletFileUpload=new ServletFileUpload(fileItemFactory);
            try {
                //2.解析上传的数据,得到每一个表单项 FileItem
                List<FileItem> list = servletFileUpload.parseRequest(request);
                //3.循环判断,每一个表单项,是普通类型,还是上传的文件
                for (FileItem fileItem : list) {
                    if (fileItem.isFormField()){ //3.1如果是普通表单项要做的操作
                        System.out.println("表单项的 name 属性值:"+fileItem.getFieldName());
                        //参数 UTF-8 解决乱码问题
                        System.out.println("表单项的 value 属性值:"+fileItem.getString("UTF-8"));
                    }else { //3.2如果是上传的文件的话那么进行上传到服务器的某个磁盘操作
                        System.out.println("表单项的 name 属性值:" + fileItem.getFieldName());
                        System.out.println("上传的文件名:" + fileItem.getName());
                        //将文件写到服务器的某个磁盘下
                        fileItem.write(new File("F:\\" + fileItem.getName())); //写到F盘下,文件名和上传的文件名一致
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

输出的结果:

image-20201214110012692

image-20201214110042923

9.6 文件下载

image-20201214112125981

image-20201214111131398

图片文件所在目录:

image-20201214123844239

文件下载代码示例:

public class DownServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 1 、获取要下载的文件名
        String downloadFileName = "2.jpg"; //这里因为是演示所以直接指定文件为2.jpg
        // 2 、读取要下载的文件内容 ( 通过 ServletContext 对象可以读取 )
        ServletContext servletContext = getServletContext();
        // 获取要下载的文件类型
        String mimeType = servletContext.getMimeType("/file/" + downloadFileName);
        System.out.println(" 下载的文件类型:" + mimeType);
        // 3 、在回传前,通过响应头告诉客户端返回的数据类型
        resp.setContentType(mimeType);
        // 4 、还要告诉客户端收到的数据是用于下载使用(还是使用响应头,如果不增加这个的话会直接把图片显示在客户端上)
        // Content-Disposition 响应头,表示收到的数据怎么处理
        // attachment 表示附件,表示下载使用
        // filename= 表示指定下载的文件名
        resp.setHeader("Content-Disposition","attachment; filename="+downloadFileName)//下载名也可以随意指定,不一定要和原名相同
        /**
        * / 斜杠被服务器解析表示地址为 http://ip:prot/ 工程名 / 映射 到代码的 Web 目录
        */
        InputStream resourceAsStream = servletContext.getResourceAsStream("/img/" + downloadFileName);
        // 获取响应的输出流
        OutputStream outputStream = resp.getOutputStream();
        // 5 、把下载的文件内容回传给客户端
        // 读取输入流中全部的数据,复制给输出流,输出给客户端
        IOUtils.copy(resourceAsStream,outputStream); //使用IOUtils工具类简化了操作
    }
}

输出结果:

这是没有加上(resp.setHeader("Content-Disposition", "attachment; filename=" + downloadFileName);)指定为下载使用的时候:

image-20201214123418160

加上的时候(自动变成下载):

image-20201214123537482

9.7 附件中文名乱码问题解决方案

9.7.1 方案一:URLEncoder 解决 IE 和谷歌浏览器的 附件中文名问题

image-20201214124247937

9.7.2 方案二:BASE64 编解码 解决 火狐浏览器的附件中文名问题

image-20201214124312668

BASE64 编解码操作:

image-20201214124323270

因为火狐使用的是 BASE64 的编解码方式还原响应中的汉字。所以需要使用 BASE64Encoder 类进行编码操作。

image-20201214124350722

9.7.3 方案三:把方案一方案二结合使用

那么我们如何解决上面两种不同编解码方式呢。我们只需要通过判断请求头中 User-Agent 这个请求头携带过来的浏览器信息即可判断出是什么浏览器。

如下:

image-20201214124455146

最后修改:2020 年 12 月 16 日 08 : 21 PM
如果觉得我的文章对你有用,请随意赞赏