EL表达式、JSTL标签库、文件上传和下载

一、EL表达式

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

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

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

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>

    <%
        request.setAttribute("key","值");
    %>
    表达式脚本输出的key的值是:<%=request.getAttribute("key1")==null?"":request.getAttribute("key1")%><br/>
    EL表达式输出key的值是:${key1}
</body>
</html>

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

EL表达式主要是在jsp页面中输出数据,主要是输出域对象中的数据

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

<body>
        <%
            //往四个域中都保存了相同的key的数据
            pageContext.setAttribute("key","pageContext");
            request.setAttribute("key","request");
            session.setAttribute("key","session");
            application.setAttribute("key","application");
        %>
        ${key}

</body>

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

查找的不是Bean类中的属性,而是该属性对应的get方法

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

<body>
        <%
            Person person = new Person();
            person.setName("阿");
            person.setPhones(new String[]{"1888888888","100000000","1999999999"});

            ArrayList<String> cities = new ArrayList<>();
            cities.add("北京");
            cities.add("上海");
            cities.add("广州");
            cities.add("深圳");
            person.setCities(cities);

            HashMap<String, Object> map = new HashMap<>();
            map.put("key1","value1");
            map.put("key2","value2");
            map.put("key3","value3");
            map.put("key4","value4");
            person.setMap(map);

            // 把person放入进域中
            pageContext.setAttribute("per",person);
        %>

        输出person:${ per }<br/>
        输出person的name属性:${ per.name }<br/>
        输出person的phones数组属性值:${ per.phones[2] }<br/>
        输出person的cities集合中的元素值:${ per.cities }<br/>
        输出person的cities集合中的某一个元素值:${ per.cities[0] }<br/>
        输出person的map集合中的元素值:${ per.map }<br/>

        输出person的map集合中的某一个元素值:${ per.map.key1 }<br/>
        <%--下面的可以实现同样的输出,对于含有特殊字符,例如“。” --%>
        输出person的map集合中的某一个元素值:${ per.map["key1"] }<br/>
</body>

4、EL表达式- - -运算

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

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

4) empty运算:

empty运算可以判断一个数据是否为空,如果为空,则输出true,不为空输出false。

以下几种情况为空:

① 值为null值得时候
② 值为空串得时候
③ 值是Object类型数组,长度为零得时候
④ list集合,元素个数为零
⑤ map集合,元素个数为零
<body>

    <%
        // ① 值为null值得时候
        request.setAttribute("emptyNull",null);
        // ② 值为空串得时候
        request.setAttribute("emptyStr","");
        // ③ 值是Object类型数组,长度为零得时候
        request.setAttribute("emptyArr",new Object[]{});
        // ④ list集合,元素个数为零
        ArrayList<Object> list = new ArrayList<>();
        request.setAttribute("emptyList",list);
        // ⑤ map集合,元素个数为零
        HashMap<String, Object> map = new HashMap<>();
        request.setAttribute("emptyMap",map);
    %>

    ${ empty emptyNull } <br/>
    ${ empty emptyStr } <br/>
    ${ empty emptyArr } <br/>
    ${ empty emptyList } <br/>
    ${ empty emptyMap } <br/>

</body>

5)三元运算:

表达式1 ? 表达式2:表达式3

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

6)".“点运算和”[]"中括号运算符:

.运算,可以输出Bean对象中某个属性的值;
[]运算,可以输出有序集合中某个元素的值;
并且[]运算符,还可以输出map集合中key里含有特殊字符的key的值。
<body>
        <%
            HashMap<String, Object> map = new HashMap<>();
            map.put("aaa","aaaValue");
            map.put(".bbb","bbbValue");
            map.put("!c+c*c","cccValue");

            request.setAttribute("map",map);
        %>

        ${ map.aaa}  <br/>
        <%--使用第二种输出方式---[],避免识别错误,不能输出的问题--%>
        ${ map[".bbb"]} <br/>
        ${ map["!c+c*c"]} <br/>
</body>

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

EL表达式种11个隐含对象,是EL表达式种自己定义的,可以直接使用。
在这里插入图片描述
1EL获取四个特定域中的属性

在这里插入图片描述

<body>
        <%
            pageContext.setAttribute("key1","pageContext1");
            pageContext.setAttribute("key2","pageContext2");
            request.setAttribute("key2","request2");
            session.setAttribute("key2","session2");
            application.setAttribute("key2","application2");
        %>
        <%--只选择key2会,优先输出范围最小的一个,即:pageContext2--%>
        ${ pageScope.key2 } <br/>
        ${ requestScope.key2 }<br/>
        ${ sessionScope.key2 }<br/>
        ${ applicationScope.key2 }<br/>
</body>

2pageContext对象的使用

在这里插入图片描述

<body>
    <%--
    request.getScheme()获取请求的协议
    request.getserverName()获取请求的服务器ip或域名
    request.getserverPort()获取请求的服务器端口号
    request.getContextPath()获取当前工程路径
    request.getMethod()获取请求的方法(GET/Post)
    request.getRemoteHost()获取客户端的ip地址
    session.getid()获取会话的id编号
    --%>
    <%=request.getScheme()%> <br/>
    <%--默认找getxxx方法--%>
    1、协议:${ pageContext.request.scheme} <br/>
    2、服务器ip:${ pageContext.request.serverName}  <br/>
    3、服务器端口: ${ pageContext.request.serverPort}   <br/>
    4、获取工程路径:${ pageContext.request.contextPath}   <br/>
    5、获取请求方法: ${ pageContext.request.method}  <br/>
    6、获取客户端ip地址: ${ pageContext.request.remoteHost}   <br/>
    7、获取会话的id编号: ${ pageContext.session.id}   <br/>
</body>

3param、paramValues对象获取请求参数的使用

paramValues获取的是某一个对象数组,要输出值,需要索引。(用于多个值

<body>
        输出请求参数username的值:${ param.username }<br/>
        输出请求参数username的值:${ paramValues.username[0] }<br/>
</body>

请求地址栏:

http://localhost:8080/09_EL_JSTL/other_el_obj.jsp?username=168

输出:

输出请求参数username的值:168
输出请求参数username的值:168

4header、paramValues对象获取请求头的使用

<body>
        输出请求头【User-Agent】的值:${header["User-Agent"]}<br/>
        输出请求头【Connection】的值:${header.Connection}<br/>
        输出请求头【User-Agent】的值:${headerValues["User-Agent"][0]}<br/>
</body>

请求地址栏:

http://localhost:8080/09_EL_JSTL/other_el_obj.jsp?username=168

输出:

输出请求头【User-Agent】的值:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.66 Safari/537.36
输出请求头【Connection】的值:keep-alive
输出请求头【User-Agent】的值:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.66 Safari/537.36

5cookie对象的使用

<body>
        <%--cookie.JSESSIONID获取cookie对象--%>
        
        ${ cookie }<br/>
        ${ cookie.JSESSIONID }<br/>
        获取Cookie的名称:${ cookie.JSESSIONID.name }<br/>
        获取Cookie的值:${ cookie.JSESSIONID.value }
</body>

请求地址栏:

http://localhost:8080/09_EL_JSTL/other_el_obj.jsp?username=168

输出:

{JSESSIONID=jakarta.servlet.http.Cookie@387b7001, Idea-1012b08a=jakarta.servlet.http.Cookie@28d30e0c}
jakarta.servlet.http.Cookie@387b7001
获取Cookie的名称:JSESSIONID
获取Cookie的值:B16A363CAD52B4CB23D308D9A9AC0175

6initParam对象的使用

<body>
		${ initParam }<br/>
        输出&lt;Context-param&gt;username的值:${ initParam.username }<br/>
        输出&lt;Context-param&gt;url的值:${ initParam.url}<br/>
</body>

请求地址栏:

http://localhost:8080/09_EL_JSTL/other_el_obj.jsp?username=168

输出:

{url=jdbc:mysql:///test, username=root}
输出<Context-param>username的值:root
输出<Context-param>username的值:jdbc:mysql:///test

二、JSTL标签库

JSTL标签库,全称是指JSP Standard Tag Library 是一个不断完善的开放源代码的JSP标签库。

EL表达式主要是为了替换jsp中的表达式脚本,而标签库则是为了替换代码脚本。这样使得整个jsp页面更加简洁。

在这里插入图片描述
在这里插入图片描述

2.1 JSTL标签库的使用步骤

1)先导入jstl标签库的jar包。

taglibs-standard-impl-1.2.1.jar
taglibs-standard-spec-1.2.1.jar

Tomcat10版本是需要导入下面两个:
jakarta.servlet.jsp.jstl-2.0.0.jar
jakarta.servlet.jsp.jstl-api-2.0.0.jar

2)第二部,使用taglib指令引入标签库

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

2.2 core核心库使用

1)<c:set/>

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

    <%--
    <c:set/>
        作用:set标签可以往域中保存数据

        域对象.setAttribute(key,value);
        scope属性设置保存到哪个域
            page表示PageContext(默认值)
            request表示Request
            session表示Session
            application表示ServletContext
        var属性设置key是多少
        value属性设置值
    --%>
    
    保存之前:${requestScope.abc}<br/>
        <c:set scope="request" var="abc" value="abcValue"/>
    保存之后:${requestScope.abc}<br/>
</body>

2)<c:if/>

作用:用来作判断
<body>

    <%--if标签作判断,test属性表示判断的条件(使用EL表达式输出)--%>
    
    <c:if test="${12==12}">
        <h1>12等于12</h1>
    </c:if>

</body>

3)<c:choose> <c:when> <c:otherwise>

作用:多路判断,跟switch...case...default非常接近
<body>

  <%--<c:choose> <c:when> <c:otherwise>

	作用:多路判断,跟switch...case...default非常接近
        choose标签开始选择判断
        when标签标识每一种判断情况
            test属性表示当前这种判断情况的值
        otherwise标签标识剩下的情况
	--%>

    <%
        request.setAttribute("height","185");
    %>

    <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>
            <h2>啊这...</h2>
        </c:otherwise>
    </c:choose>


</body>

4)<c:forEach/>

作用:遍历输出使用

遍历输出1到10

<body>
        <%--1、遍历输出110
            begin属性设置开始的索引
            end属性设置结束的索引
            var属性表示循环的变量(也是当前正在遍历到的数据)
            for(int i=1;i<10;i++)

        --%>
        <c:forEach begin="0" end="10" var="i">
            ${ i }
        </c:forEach>

        <table border="1" bgcolor="#adff2f">
            <c:forEach begin="0" end="10" var="i">
                <tr>
                    <td>第${i}</td>
                </tr>
            </c:forEach>
        </table>
</body>

遍历Object数组

<body>
<%--2、遍历Object数组
            for(Object:arr)
            item 表示遍历的数据源(便利的集合)
            var表示当前遍历到的数据
        --%>
        <%
            request.setAttribute("arr",new String[]{"11111111111","22222222222","33333333333"});
        %>

        <c:forEach items="${requestScope.arr}" var="item">
            ${item} <br/>
        </c:forEach>
</body>

遍历Map集合

<body>
<%
            HashMap<String, Object> map = new HashMap<>();
            map.put("key1","value1");
            map.put("key2","value2");
            map.put("key3","value3");
            //for (Map.Entry<String,Object> entry:map.entrySet()){
            //}
            request.setAttribute("map",map);
        %>
        <c:forEach items="${requestScope.map}" var="entry">
            <h5>${entry}</h5>
            <h4>${entry.key}</h4>
            <h3>${entry.value}</h3>
        </c:forEach>
</body>

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

<body>
<%--遍历List集合- - -list中存放Student类,有属性:编号,用户名,密码,年龄,电话信息--%>
        <%
            ArrayList<Student> studentList = new ArrayList<>();
            for (int i=0;i<10;i++){
                studentList.add(new Student(i,"username"+i,"pass"+i,18+i,"phone"+i));
            }
            request.setAttribute("stus",studentList);
        %>
        <table>
            <tr>
                <th width="1">编号</th>
                <th>用户名</th>
                <th>密码</th>
                <th>年龄</th>
                <th>电话</th>
                <th>操作</th>
            </tr>
       <c:forEach begin="2" end="7" step="2" varStatus="status" items="${requestScope.stus}" var="stu">
            <tr>
                <td>${stu.id}</td>
                <td>${stu.name}</td>
                <td>${stu.password}</td>
                <td>${stu.age}</td>
                <td>${stu.phone}</td>
                <td>${status}</td>
            </tr>
        </c:forEach>
        </table>
</body>

forEach总结:

items表示遍历的数据源
begin属性设置开始的索引
end属性设置结束的索引
var属性表示循环的变量(也是当前正在遍历到的数据)
step属性表示遍历的步长值
varStatus属性表示当前遍历到的数据的状态

Status实现了LoopTagStatus接口,故也具有以下方法。
在这里插入图片描述

三、文件的上传和下载

3.1 文件的上传介绍(重点

① 要有一个form标签,method=post请求
② form标签的encType属性值必须为multipart/form-data(表示提交的数据,以多段[每一个表单项是一个数据段]的形式进行拼接,然后以二进制流的形式发送给服务器)
③ 在form标签中使用input type=file添加上传的文件
④ 编写服务器代码(Servlet程序)接收,处理上传的数据

upload,jsp代码如下:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<form action="http://localhost:8080/09_EL_JSTL/uploadServlet" 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>

UploadServlet服务器程序接受、处理上传的数据:

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

    }

    //用来处理上传的数据
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //System.out.println("文件上传过来了");
        //客户端是流的形式进行发送的,因此只能以流的形式进行接受
        ServletInputStream inputStream = request.getInputStream();

        // 利用缓冲区一次读到
        byte[] buffer = new byte[1024000];
        int read = inputStream.read(buffer);
        System.out.println(new String(buffer,0,read));

    }
}

在这里插入图片描述


3.2 commons-fileupload.jar常用API介绍说明

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

包内常用类

ServletFileUpload类,用于解析上传的数据
FileItem类,表示每一个表单项

在这里插入图片描述
在这里插入图片描述
解析收到的内容:

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

    }

    //用来处理上传的数据
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1、先判断上传的数据是否多段数据(只有多段的数据,才是文件上传的)
        if (ServletFileUpload.isMultipartContent(request)){
            // 创建FileItemFactory工厂实现类
            DiskFileItemFactory fileItemFactory = new DiskFileItemFactory();
            // 创建用于解析上传数据的工具类ServletFileUpload类
            ServletFileUpload servletFileUpload = new ServletFileUpload(fileItemFactory);
            //解析上传的数据,得到每一个表单项FileItem
            try {
                List<FileItem> list = servletFileUpload.parseRequest((RequestContext) request);
                //循环判断,每一个表单项,是普通类型,还是上传的文件
                for (FileItem fileItem:list){
                    if (fileItem.isFormField()){
                        //普通表单项

                        System.out.println("表单项的name属性值:"+fileItem.getFieldName());
                        // 参数UTF-8解决乱码问题
                        System.out.println("表单项的value属性值:"+fileItem.getString("UTF-8"));
                    }else {
                        //上传的文件
                        System.out.println("表单项的name属性值:"+fileItem.getFieldName());
                        System.out.println("上传的文件名:"+fileItem.getName());

                        try {
                            fileItem.write(new File("d:\\"+fileItem.getName()));
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                }
            } catch (FileUploadException e) {
                e.printStackTrace();
            }
        }
    }
}

3.3 文件的下载介绍(重点

具体流程:
在这里插入图片描述
其中用到了commons-io-2.8.0.jar包中的IOUtils类来方便读取数据。

注意

	还要告诉客户端收到的数据是用于下载使用(还是使用响应头)
    // Content-Disposition响应头,表示收到的数据怎么处理
    // attachment表示附件(下载使用)
    //filename=表示指定下载的文件名
    //url编码是把汉字转换成为%xx%xx的格式(十六进制)IE和谷歌用的是UTF-8编码,
public class Download extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)throws SecurityException, IOException{
        //1、获取要下载的文件名
        String downloadFileName="6.jpg";

        //2、读取要下载的文件内容(通过ServletContext对象可以读取)
        ServletContext servletContext=getServletContext();
        // 获取要下载的文件类型
        String mimeType = servletContext.getMimeType("/file/" + downloadFileName);
        System.out.println("下载的文件类型"+mimeType);
        //4、在回传前,通过响应头告诉客户端返回的数据类型
        response.setContentType(mimeType);

        //5、还要告诉客户端收到的数据是用于下载使用(还是使用响应头)
        // Content-Disposition响应头,表示收到的数据怎么处理
        // attachment表示附件(下载使用)
        //filename=表示指定下载的文件名
        //url编码是把汉字转换成为%xx%xx的格式(十六进制)
        response.setHeader("Content-Disposition","attachment;filename="+ URLEncoder.encode("真好.jpg","UTF-8"));


        /* /斜杠被服务器解析为http://ip:port/工程名/ 映射到代码的web目录*/
        InputStream resourceAsStream = servletContext.getResourceAsStream("/file/" + downloadFileName);

        //3、把下载的文件内容回传给客户端
        //获取相应的输出流
        ServletOutputStream outputStream = response.getOutputStream();
        //读取输入流中的全部数据,赋值给输出流,输出给客户端
        IOUtils.copy(resourceAsStream,outputStream);
        
    }
}

火狐浏览器要使用BASE64编解码处理

举例操作如下:
在这里插入图片描述
具体实现内容如下:
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值