跳转至

服务器端渲染技术02

11.EL表达式

11.1EL表达式介绍

  1. EL表达式全称:Expression Language,是表达式语言

  2. EL表达式主要是代替jsp页面的表达式脚本

  3. EL表达式输出数据时,比jsp的表达式脚本简洁

  4. EL表达式基本语法:${key}

底层其实走的还是jsp表达式脚本,可以理解为就是一个语法糖

11.2EL表达式快速入门

el_qs.jsp:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>el表达式的快速入门</title>
</head>
<body>
<h1>el表达式的快速入门</h1>
<%
    request.setAttribute("name","星星之火,可以燎原");
%>
<%--
    1.如果name是null,用request.getAttribute("name")返回的就是null字符串
    2.如果name是null,用el表达式返回的则是空串 ""
--%>
<h3>1.jsp 表达式脚本</h3>
名字:<%=request.getAttribute("name")%><br/>
<h3>2.el 表达式</h3>
名字:${name}<br/>
</body>
</html>

image-20221126175436250

注意:

  1. EL表达式在输出null时,输出的是空串""

  2. jsp脚本在输出null时,输出的是 “null” 字符串

image-20221126175619276

11.3EL常用输出形式

EL表达式常用输出Bean的普通属性,数组属性,List集合属性和map集合属性

应用实例

book.java:

package com.li.entity;

import java.util.Arrays;
import java.util.List;
import java.util.Map;

public class Book {
    private String name;//书名
    private String[] writer;//作者
    private List<String> reader;//读者
    private Map<String,String> topics;//评价

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String[] getWriter() {
        return writer;
    }

    public void setWriter(String[] writer) {
        this.writer = writer;
    }

    public List<String> getReader() {
        return reader;
    }

    public void setReader(List<String> reader) {
        this.reader = reader;
    }

    public Map<String, String> getTopics() {
        return topics;
    }

    public void setTopics(Map<String, String> topics) {
        this.topics = topics;
    }

    @Override
    public String toString() {
        return "Book{" +
                "name='" + name + '\'' +
                ", writer=" + Arrays.toString(writer) +
                ", reader=" + reader +
                ", topics=" + topics +
                '}';
    }
}

el_output.jsp:

<%@ page import="com.li.entity.Book" %>
<%@ page import="java.util.List" %>
<%@ page import="java.util.Map" %>
<%@ page import="java.util.ArrayList" %>
<%@ page import="java.util.HashMap" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>el表达式输出数据演示</title>
</head>
<body>
<h1>el表达式输出数据演示</h1>
<%
    //创建一个Book对象初始化,并放入相关属性
    Book book = new Book();
    book.setName("昆虫总动员");
    book.setWriter(new String[]{"jack", "tomas"});
    ArrayList<String> readers = new ArrayList<>();
    readers.add("小李");
    readers.add("小王");
    book.setReader(readers);
    //创建topics
    HashMap<String, String> topics = new HashMap<>();
    topics.put("topic1", "这是我看过的最好的动画片");
    topics.put("topic2", "不错的电影~~");
    book.setTopics(topics);

    //把book放入到request域对象中
    request.setAttribute("bookKey", book);
%>
book对象:${bookKey}<br/><br/>

book.name=${bookKey.name}<br/><br/>

<%--这里输出的是数组对象因为数组没有重写toString方法--%>
book.writer=${bookKey.writer}<br/><br/>

第一个作者book.writer[0]=${bookKey.writer[0]}<br/><br/>

<%--这里可以输出具体的值因为list底层重写了toString方法--%>
book.readers=${bookKey.reader}<br/><br/>

<%--第二个读者book.readers[1]=${bookKey.reader.get(1)}<br/>--%>
第二个读者book.readers[1]=${bookKey.reader[1]}<br/><br/>

book.topics=${bookKey.topics}<br/><br/>

<%--map不能以索引的方式来取值--%>
第一个评价=${bookKey.topics.get("topic1")}<br/><br/>

第一个评价=${bookKey.topics["topic1"]}
</body>
</html>

image-20221126183418404

11.4EL运算操作符

EL的运算操作符和java基础的操作符在概念和用法上都是一样的,只是形式上有些变化。

  1. 基本语法:${运算表达式}

  2. 关系运算

image-20221126184648121

  1. 逻辑运算

image-20221126184716846

  1. 算术运算

image-20221126184741241

应用实例

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>el运算符</title>
</head>
<body>
<h1>el运算符</h1>
<%
    request.setAttribute("num1", 90);
    request.setAttribute("num2", 30);
%>
num1+num2=${num1+num2}<br/>
num1>num2?=${num1>num2}<br/>
</body>
</html>

image-20221126185358669

11.5EL的empty运算

  1. empty运算可以判断一个数是否为空,如果为空,返回true,否则返回false
  2. 以下几种情况为空:
  3. 值为null
  4. 值为空串时
  5. 值是Object类型数据,但长度为零时
  6. list集合,元素个数为零时
  7. map集合,元素个数为零时

应用实例

<%@ page import="java.util.ArrayList" %>
<%@ page import="java.util.HashMap" %><%--
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>el empty的运算</title>
</head>
<body>
<%
    request.setAttribute("k1", null);//null
    request.setAttribute("k2", "");//空串
    request.setAttribute("k3", new Object[]{});//为空的Object数组
    request.setAttribute("k4", new ArrayList<>());//为空的list集合
    request.setAttribute("k5", new HashMap<>());//为空的map集合
%>
k1是否为空=${empty k1}<br/>
k2是否为空=${empty k2}<br/>
k3是否为空=${empty k3}<br/>
k4是否为空=${empty k4}<br/>
k5是否为空=${empty k5}<br/>
</body>
</html>

image-20221126190307314

11.6EL的三元运算

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

  2. 如果表达式1的值为真,返回表达式2的值,反之返回表达式3的值

image-20221126190610775

11.7EL的11个隐含/内置对象

image-20221126190833117

下面以pageScope,requestScope,sessionScope,applicationScope四个常用的隐含对象为例子演示。

演示el常用的四个隐含对象(域对象)

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>演示el的四个常用的隐含对象(域对象)</title>
</head>
<body>
<h2>演示el的四个常用的隐含对象(域对象)</h2>
<%
    request.setAttribute("k1", "request-k1数据");
    pageContext.setAttribute("k1", "pageContext-k1数据");
    session.setAttribute("k1", "session-k1数据");
    application.setAttribute("k1", "application-k1数据");
%>
<h3>1.jsp脚本方式获取</h3>
<%=request.getAttribute("k1")%>
<h3>2.el方式来获取域对象的数据</h3>
request域中的k1=${requestScope.k1}<br/>
pageContext域中的k1=${pageScope.k1}<br/>
session域中的k1=${sessionScope.k1}<br/>
application域中的k1=${applicationScope.k1}<br/>
</body>
</html>

image-20221126192219036

11.7.1pageContext对象的使用

  • 我们可以通过pageContext.request.xxx来获取和http协议相关的信息:

通过request对象来获取和HTTP协议相关的数据:

  1. request.getScheme() 它可以获取请求的协议
  2. request.getServerName() 获取请求的服务器 ip 或域名
  3. request.getServerPort() 获取请求的服务器端口号
  4. getContextPath() 获取当前工程路径
  5. request.getMethod() 获取请求的方式(GET 或 POST)
  6. request.getRemoteHost() 获取客户端的 ip 地址
  7. session.getId() 获取会话的唯一标识

例子

image-20221126192927968

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>pageContext 对象的使用</title>
</head>
<body>
<h1>pageContext 对象的使用</h1>
<%--
  //通过 request 对象来获取和 HTTP 协议相关的数据
  request.getScheme() 它可以获取请求的协议
  request.getServerName() 获取请求的服务器 ip 或域名
  request.getServerPort() 获取请求的服务器端口号
  getContextPath() 获取当前工程路径
  request.getMethod() 获取请求的方式GET  POST
  request.getRemoteHost() 获取客户端的 ip 地址
  session.getId() 获取会话的唯一标识
--%>
<hr/>
协议: ${ pageContext.request.scheme }<br>
服务器 ip:${ pageContext.request.serverName }<br>
服务器端口:${ pageContext.request.serverPort }<br>
工程路径:${ pageContext.request.contextPath }<br>
请求方法:${ pageContext.request.method }<br>
客户端 ip 地址:${ pageContext.request.remoteHost }<br>
会话 id :${ pageContext.session.id }<br>

<h3>使用 jsp 表达式脚本获取如上信息</h3>
ip 地址: <%=request.getRemoteHost() %><br>
会话 id <%=request.getRequestedSessionId()%><br>
...

<h3>使用 el 表达式形式获取信息-简化写法</h3>
<%
    //可以将request对象放到pageContext属性中,通过key可以很方便地取出,从而简化写法
    pageContext.setAttribute("req", request);
%>
ip 地址: ${req.remoteHost} <br>
获取请求方法: ${req.method} <br>
客户端 ip 地址:${ req.remoteHost }<br>
...
</body>
</html>

image-20221126193731450

12.JSTL

12.1JSTL介绍

  1. JSTL(Java server pages standarded tag library,即JSP标准标签库。

  2. EL表达式是为了替换jsp中的表达式脚本,JSTL是为了替换代码脚本<%%>,这样可以使jsp页面变得更加简洁。

  3. JSTL由五个标签库组成:

image-20221126194224976

  1. 使用JSTL,需要导入相关的jar包:

下载连接:https://tomcat.apache.org/download-taglibs.cgi

image-20221126195131691

12.2快速入门

  1. 将两个jar包直接复制粘贴到web应用程序的WEB-INF\lib目录下,add as library

image-20221126195318622

  1. 在jsp页面的引入标签,要放在文件第一行

image-20221126195629830

  1. 导入jstl jar包后,要重新发布web工程,否则不识别jstl
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>jstl的快速入门</title>
</head>
<body>
<h1>jstl的快速入门</h1>
<%--
    1.c: if ...标签类似
    2.if(10>2){
        out.println("xxx")
    }
--%>
<c:if test="${10>2}">
    <h2>10>2成立~~~</h2>
</c:if>
</body>
</html>

image-20221126200823058

12.3core核心库

12.3.1标签

例子:

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

  1. 等价于 域对象.setAttribute(key,value);
  2. scope 属性设置保存到哪个域
  3. page表示PageContext域(默认值)
  4. request表示Request域
  5. session表示Session域
  6. application表示ServletContext域
  7. var 属性设置 key 是什么
  8. value 属性设置值

例子

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>c:set标签的使用</title>
</head>
<body>
<h1>c:set标签的使用</h1>
<%
    //原来的写法
    //request.setAttribute("email","tomas@qq.com");
%>
<%--jstl的写法--%>
<c:set scope="request" var="name" value="tomas"> </c:set>

<%--c:set-name的值${name} 或者--%>
c:set-name的值:${requestScope.name}
</body>
</html>

image-20221126203603115

12.3.2标签

例子:

<c:if />

  1. if标签用来做if判断
  2. test属性表示判断的条件(用EL表达式输出)

例子

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>c:if标签使用</title>
</head>
<body>
<h2>c:if标签使用</h2>
<c:set scope="request" var="num1" value="20"/>
<c:set scope="request" var="num2" value="10"/>
<c:if test="${num1>num2}">
    <h3>${num1}>${num2}</h3>
</c:if>
</body>
</html>

image-20221126204707838

12.3.3标签

介绍:多路判断。跟switch...case...default非常接近

例子

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>c:choose标签的使用</title>
</head>
<body>
<%
    request.setAttribute("scope", 59);

    pageContext.setAttribute("k1", "pageContext-k1");
    request.setAttribute("k1", "request-k1");
    session.setAttribute("k1", "session-k1");
    application.setAttribute("k1", "application-k1");
%>
<%--如果这样写${requestScope.scope} 就是明确指定从request域对象取出数据  --%>
<%--如果这样写${scope} 就按照下面的域范围从小到大的开始找
        pageContext ->request-> session->application
  --%>
k1=${k1}
<hr>
<h1>c:choose标签的使用</h1>
<c:choose>
    <c:when test="${requestScope.scope > 80}">
        <h3>${scope}-成绩优秀!</h3>
    </c:when>
    <c:when test="${requestScope.scope > 60}">
        <h3>${scope}-成绩及格!</h3>
    </c:when>
    <c:otherwise>
        <h3>${scope}-成绩不及格,继续努力!</h3>
    </c:otherwise>
</c:choose>
</body>
</html>

image-20221126210844648

12.3.4标签

介绍:c:forEach标签用来遍历输出,主要有4种形式

  • 普通遍历输出i到j
  • 遍历数组
  • 遍历Map
  • 遍历List

例子

<%@ page import="java.util.HashMap" %>
<%@ page import="java.util.ArrayList" %>
<%@ page import="com.li.entity.Monster" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>c:forEach标签</title>
</head>
<body>
<h1>c:forEach标签</h1>
<hr>
<h2>第一种遍历方式:从i到j</h2>
<ul>
    <%--
        1.遍历1到5
        2.begin属性设置开始的索引end属性设置结束的索引
        3.var属性表示循环的变量也就是当前正在遍历到的数据
        4.等价于 for(int i = 1; i < = 5; i++){}
        5.默认情况情况下i的值每次会递增 1
        6.可以使用step属性来设置增量
     --%>
    <c:forEach begin="1" end="5" var="i">
        <li>排名=${i}</li>
    </c:forEach>
</ul>
<hr>
<h2>第二种遍历方式:遍历数组</h2>
<%
    request.setAttribute("sports", new String[]{"打篮球", "乒乓球"});
%>
<%--
    1.item属性指定要遍历的集合/数组
    2.var 自定义变量每次取出的数据会存放到该变量中
    3.等价于 for(Object item:arr){}
    相当于每循环一次就在items指定的数组中
    取出一个数据存放到var自定义的变量中
    直至取完数据就退出循环
    --%>
<c:forEach items="${requestScope.sports}" var="sp">
    运动名称=${sp}<br/>
</c:forEach>
<hr>
<h2>第三种遍历方式:遍历Map</h2>
<%
    HashMap<String, Object> map = new HashMap<>();
    map.put("key1", "北京");
    map.put("key2", "上海");
    map.put("key3", "天津");
    request.setAttribute("cities", map);
%>
<%--
    1.item遍历的map集合
    2.var遍历到的数据
    3.entry.key取出key
    4.entry.value取出值
--%>
<c:forEach items="${requestScope.cities}" var="city">
    城市信息=${city.key}--${city.value}<br/>
</c:forEach>

<hr>
<h2>第四种遍历方式:遍历List</h2>
<%
    ArrayList<Monster> monsters = new ArrayList<>();
    monsters.add(new Monster(100, "小妖怪", "巡山的"));
    monsters.add(new Monster(200, "大妖怪", "做饭的"));
    monsters.add(new Monster(300, "老妖怪", "打扫位置的"));
    request.setAttribute("monsters", monsters);
%>
<%--
    items 表示遍历的集合
    var 表示遍历到的数据
    begin 表示遍历的开始索引值 , 0 开始计算
    end 表示结束的索引值
    step 属性表示遍历的步长值
    varStatus 属性表示当前遍历到的数据的状态,可以得到 step,begin,end 等属性值
--%>
<c:forEach items="${requestScope.monsters}" var="monster">
    妖怪信息=${monster.id}-${monster.name}-${monster.skill}<br/>
</c:forEach>
</body>
</html>

image-20221126215316493

13.练习

需求分析:使用jsp+servlet+jstl+el完成查询-显示案例,需求如下:

  1. 点击超链接,可以显示所有的妖怪信息
  2. 要求显示的数据在servlet中准备,并放入到request域对象中
  3. 扩展,如果要求增加根据薪水sal条件过滤,怎么处理?

image-20221126215708667 image-20221126215721462

练习

思路:通过query.jsp将查询条件传到queryServlet,在servlet中判断符合条件的数据,并放到request域中,通过请求转发到显示页面view.jsp中,在view页面通过jstl循环标签显示。

思路二:过滤的条件可以在view中通过jstl的if标签中判断,通过servlet将过滤条件发送给view

query.jsp:

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%--
  Created by IntelliJ IDEA.
  User: li
  Date: 2022/11/27
  Time: 0:07
  Version: 1.0
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>query</title>
</head>
<body>
<h1>查询妖怪</h1>
<form action="/jsp/queryServlet" method="post">
    请输入查询的最低工资:<input type="text" name="sal"/><br/><br/>
    <input type="submit" value="点击查询"/>
</form>
</body>
</html>

QueryServlet:

package com.li.servlet;

import com.li.entity.Monster;
import com.utils.WebUtils;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
import java.util.ArrayList;

@WebServlet(name = "QueryServlet", urlPatterns = "/queryServlet")
public class QueryServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("QueryServlet was run...");
        //所有妖怪的数据
        ArrayList<Monster> allMonsters = new ArrayList<>();
        allMonsters.add(new Monster(100, "小妖怪", "巡山的", 345.7));
        allMonsters.add(new Monster(200, "大妖怪", "做饭的", 1345.7));
        allMonsters.add(new Monster(300, "老妖怪", "打扫位置的", 11345.7));

        //获取筛选条件
        String selectSal = request.getParameter("sal");
        //String转成double
        double selectNum = WebUtils.parseDouble(selectSal, 0);
        //筛选
        //用来放筛选数据的list
        ArrayList<Monster> vaildMonsters = new ArrayList<>();
        for (Monster monster : allMonsters) {
            if (monster.getSal() >= selectNum) {
                vaildMonsters.add(monster);
            }
        }
        //将合法数据放到域对象中
        request.setAttribute("vaildMonsters", vaildMonsters);
        //请求转发到显示页面
        request.getRequestDispatcher("/hw/view.jsp").forward(request, response);
    }
}

Monster:

package com.li.entity;

public class Monster {
    private Integer id;
    private String name;
    private String skill;
    private double sal;

    public Monster(Integer id, String name, String skill, double sal) {
        this.id = id;
        this.name = name;
        this.skill = skill;
        this.sal = sal;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSkill() {
        return skill;
    }

    public void setSkill(String skill) {
        this.skill = skill;
    }

    public double getSal() {
        return sal;
    }

    public void setSal(double sal) {
        this.sal = sal;
    }

    @Override
    public String toString() {
        return "Monster{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", skill='" + skill + '\'' +
                ", sal=" + sal +
                '}';
    }
}

WebUtils:

package com.utils;

public class WebUtils {
    public static double parseDouble(String strNum, int defaultVal) {
        try {
            return Double.parseDouble(strNum);
        } catch (NumberFormatException e) {
            System.out.println(strNum + "不能转成整数");
        }
        return defaultVal;
    }
}

view.jsp:

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%--
  Created by IntelliJ IDEA.
  User: li
  Date: 2022/11/27
  Time: 0:13
  Version: 1.0
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>view</title>
</head>
<body>
<h1>显示妖怪信息</h1>
<table border="1px" width="300px">
    <tr>
        <td>id</td>
        <td>name</td>
        <td>job</td>
        <td>sal</td>
    </tr>
    <c:forEach items="${requestScope.vaildMonsters}" var="monster">
        <tr>
            <td>${monster.id}</td>
            <td>${monster.name}</td>
            <td>${monster.skill}</td>
            <td>${monster.sal}</td>
        </tr>
    </c:forEach>
</table>
</body>
</html>

image