伺服器端渲染技術02 11.EL表達式 11.1EL表達式介紹 EL表達式全稱:Expression Language,是表達式語言 EL表達式主要是代替jsp頁面的表達式腳本 EL表達式輸出數據時,比jsp的表達式腳本簡潔 EL表達式基本語法:${key} 底層其實走的還是jsp表達式腳本,可以理 ...
伺服器端渲染技術02
11.EL表達式
11.1EL表達式介紹
-
EL表達式全稱:Expression Language,是表達式語言
-
EL表達式主要是代替jsp頁面的表達式腳本
-
EL表達式輸出數據時,比jsp的表達式腳本簡潔
-
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](https://liyuelian.oss-cn-shenzhen.aliyuncs.com/imgs/image-20221126175436250.png)
註意:
-
EL表達式在輸出null時,輸出的是空串""
-
jsp腳本在輸出null時,輸出的是 “null” 字元串
![image-20221126175619276](https://liyuelian.oss-cn-shenzhen.aliyuncs.com/imgs/image-20221126175619276.png)
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](https://liyuelian.oss-cn-shenzhen.aliyuncs.com/imgs/image-20221126183418404.png)
11.4EL運算操作符
EL的運算操作符和java基礎的操作符在概念和用法上都是一樣的,只是形式上有些變化。
-
基本語法:
${運算表達式}
-
關係運算
-
邏輯運算
-
算術運算
應用實例
<%@ 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](https://liyuelian.oss-cn-shenzhen.aliyuncs.com/imgs/image-20221126185358669.png)
11.5EL的empty運算
- empty運算可以判斷一個數是否為空,如果為空,返回true,否則返回false
- 以下幾種情況為空:
- 值為null
- 值為空串時
- 值是Object類型數據,但長度為零時
- list集合,元素個數為零時
- 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](https://liyuelian.oss-cn-shenzhen.aliyuncs.com/imgs/image-20221126190307314.png)
11.6EL的三元運算
-
表達式1?表達式2:表達式3
-
如果表達式1的值為真,返回表達式2的值,反之返回表達式3的值
11.7EL的11個隱含/內置對象
下麵以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](https://liyuelian.oss-cn-shenzhen.aliyuncs.com/imgs/image-20221126192219036.png)
11.7.1pageContext對象的使用
-
我們可以通過pageContext.request.xxx來獲取和http協議相關的信息:
通過request對象來獲取和HTTP協議相關的數據:
- request.getScheme() 它可以獲取請求的協議
- request.getServerName() 獲取請求的伺服器 ip 或功能變數名稱
- request.getServerPort() 獲取請求的伺服器埠號
- getContextPath() 獲取當前工程路徑
- request.getMethod() 獲取請求的方式(GET 或 POST)
- request.getRemoteHost() 獲取客戶端的 ip 地址
- session.getId() 獲取會話的唯一標識
例子
![image-20221126192927968](https://liyuelian.oss-cn-shenzhen.aliyuncs.com/imgs/image-20221126192927968.png)
<%@ 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](https://liyuelian.oss-cn-shenzhen.aliyuncs.com/imgs/image-20221126193731450.png)
12.JSTL
12.1JSTL介紹
-
JSTL(Java server pages standarded tag library,即JSP標準標簽庫。
-
EL表達式是為了替換jsp中的表達式腳本,JSTL是為了替換代碼腳本<%%>,這樣可以使jsp頁面變得更加簡潔。
-
JSTL由五個標簽庫組成:
-
使用JSTL,需要導入相關的jar包:
12.2快速入門
-
將兩個jar包直接複製粘貼到web應用程式的WEB-INF\lib目錄下,add as library
-
在jsp頁面的引入標簽,要放在文件第一行
-
導入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](https://liyuelian.oss-cn-shenzhen.aliyuncs.com/imgs/image-20221126200823058.png)
12.3core核心庫
12.3.1<c:set />標簽
例子:<c:set scope="request" var="k1" value="v1"/>
<c:set/>
set標簽可以往域中保存數據
- 等價於
域對象.setAttribute(key,value);
- scope 屬性設置保存到哪個域
- page表示PageContext域(預設值)
- request表示Request域
- session表示Session域
- application表示ServletContext域
- var 屬性設置 key 是什麼
- 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","[email protected]");
%>
<%--jstl的寫法--%>
<c:set scope="request" var="name" value="tomas"> </c:set>
<%--c:set-name的值:${name} 或者--%>
c:set-name的值:${requestScope.name}
</body>
</html>
![image-20221126203603115](https://liyuelian.oss-cn-shenzhen.aliyuncs.com/imgs/image-20221126203603115.png)
12.3.2<c:if />標簽
例子:<c:if test="10>2">hello< /c:if>
<c:if />
- if標簽用來做if判斷
- 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](https://liyuelian.oss-cn-shenzhen.aliyuncs.com/imgs/image-20221126204707838.png)
12.3.3<c:choose >標簽
介紹:多路判斷。跟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](https://liyuelian.oss-cn-shenzhen.aliyuncs.com/imgs/image-20221126210844648.png)
12.3.4<c:forEach />標簽
介紹: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](https://liyuelian.oss-cn-shenzhen.aliyuncs.com/imgs/image-20221126215316493.png)
13.練習
需求分析:使用jsp+servlet+jstl+el完成查詢-顯示案例,需求如下:
- 點擊超鏈接,可以顯示所有的妖怪信息
- 要求顯示的數據在servlet中準備,並放入到request域對象中
- 擴展,如果要求增加根據薪水sal條件過濾,怎麼處理?
練習
思路:
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](https://img2022.cnblogs.com/blog/2192446/202211/2192446-20221127011015248-1971956260.gif)