EL 表達(dá)式
使用它可以極大的便利 JSP 頁(yè)面中的數(shù)據(jù)獲取和處理
語(yǔ)法結(jié)構(gòu)
所有的 EL 都是以 ${ 為起始,以 } 為結(jié)尾?
EL 變量
${username} 表示取出某一范圍內(nèi)名稱(chēng)為 username? 的變量,因?yàn)榇藭r(shí)并沒(méi)有指定哪個(gè)范圍的 username,所以它的默認(rèn)情況下會(huì)先從 Page 范圍找,如果找不到,會(huì)依次從 Request、Session、Application 范圍,直到找到值回傳,如果沒(méi)找到,返回 null。
案例
在 testel.jsp 頁(yè)面中,首先在頭部需要注明開(kāi)啟 EL 表達(dá)式:

當(dāng)前頁(yè)面存取 session 值
1、

運(yùn)行結(jié)果:

以上取值方式等同于:

方式一針對(duì)某個(gè)范圍內(nèi)進(jìn)行查找,而方式二沒(méi)有指定,則默認(rèn)從 Page 開(kāi)始查找。
注意:
如果在存 session 的 key 里面含有特殊字符,則應(yīng)使用 [] 來(lái)取值

2、

由圖,新建一個(gè)用戶實(shí)體,分別設(shè)置屬性,并取值。
3、
提交表單數(shù)據(jù)并當(dāng)前頁(yè)面并顯示:

執(zhí)行結(jié)果:

方式一采用的以往通過(guò) JSP 內(nèi)置對(duì)象的 request 來(lái)獲取參數(shù),而方式二采用 EL 表達(dá)式來(lái)獲取,
4、

執(zhí)行結(jié)果

由結(jié)果得知,EL 可以自動(dòng)進(jìn)行類(lèi)型轉(zhuǎn)換
EL 隱含對(duì)象
與范圍有關(guān)的:
applicationScope、sessionScope、requestScope、pageScope
與輸入有關(guān)的:
param、paramValues
其他隱含對(duì)象:
cookie、header、headerValues、initParam、pageContext
對(duì)于?pageContext 對(duì)象:
即為 PageContext 類(lèi)型,但只能讀取屬性就可以一直“.”下去

由圖可以獲取相關(guān)等屬性
Empty 屬性
可以作用于一個(gè)集合,若集合不存在或者集合沒(méi)有元素,則結(jié)果為 true

自定義標(biāo)簽
概念:
用戶定義的一種自定義的 JSP 標(biāo)記,當(dāng)一個(gè)含有自定義標(biāo)簽的 JSP 頁(yè)面被 JSP 引擎編譯成 Servlet 時(shí),tag 標(biāo)簽被轉(zhuǎn)化成了對(duì)一個(gè)稱(chēng)為標(biāo)簽處理類(lèi)的對(duì)象的操作。所以,當(dāng) JSP 頁(yè)面被 JSP 引擎轉(zhuǎn)化成 Servlet 后,實(shí)際上 tag 標(biāo)簽被轉(zhuǎn)化為對(duì) tag 處理類(lèi)的操作。使用自定義標(biāo)簽可以降低 JSP 開(kāi)發(fā)的復(fù)雜度和維護(hù)量
編寫(xiě)自定義標(biāo)簽:
核心是編寫(xiě)處理類(lèi),一個(gè)標(biāo)簽對(duì)應(yīng)一個(gè)標(biāo)簽處理器類(lèi),而一個(gè)標(biāo)簽庫(kù)則是很多標(biāo)簽處理器的集合,所有標(biāo)簽處理器都要實(shí)現(xiàn) JspTag 接口,該接口中沒(méi)有定義任何方法,主要作為 Tag 和 SimpleTag 接口的父接口。
標(biāo)簽形式:
1、空標(biāo)簽:<hello/>
2、帶有屬性的空標(biāo)簽:<max num1="3" num2="5"/>
3、帶有內(nèi)容的標(biāo)簽:<greeting>hello</greeting>
4、帶有內(nèi)容和屬性的標(biāo)簽:<greeting name="tom">hello<greeting/>
編寫(xiě)步驟:
1、表寫(xiě)完成標(biāo)簽功能的 java 類(lèi)(標(biāo)簽處理器)
2、編寫(xiě)標(biāo)簽庫(kù)描述(tld)文件,在 tld 文件中對(duì)自定義標(biāo)簽進(jìn)行描述
3、在 JSP 頁(yè)面中導(dǎo)入和使用自定義標(biāo)簽
案例:
確保項(xiàng)目中已導(dǎo)入如下 jar 包:

在 tag 包下新建?HelloSimpleTag 標(biāo)簽處理器類(lèi)并實(shí)現(xiàn)?SimpleTag

然后在 WEB-INF 下新建 mytag.tld 配置文件

頭部信息與 core 一致
<taglib xmlns="http://java.sun.com/xml/ns/j2ee"
? ? ? ? xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
? ? ? ? xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"
? ? ? ? version="2.0">
完成以上步驟后在 JSP 引用該 tag

通過(guò)引用,可以對(duì)照 mytag.tld 的配置文件說(shuō)明。
重啟 tomcat

通過(guò)運(yùn)行結(jié)果可以看出,執(zhí)行了?HelloSimpleTag 里的?setJspContext 方法和?doTag 方法。
實(shí)現(xiàn) SimpleTag 接口的標(biāo)簽處理類(lèi)的生命周期:
1、setJspContext
JSP 引擎將代表 JSP 頁(yè)面的 pageContext 對(duì)象傳遞給標(biāo)簽處理器對(duì)象
2、setParent
JSP 引擎將父標(biāo)簽處理器對(duì)象傳遞給當(dāng)前標(biāo)簽處理器對(duì)象。只有存在父標(biāo)簽時(shí),JSP 引擎才會(huì)調(diào)用該方法
3、setXXX?
設(shè)置標(biāo)簽屬性,只要定義屬性才調(diào)用該方法
4、setJspBody?
若存在標(biāo)簽體,JSP 引擎將把標(biāo)簽體封裝成一個(gè) JspFragment 對(duì)象,調(diào)用?setJspBody 方法將 JspFragment 對(duì)象傳遞給標(biāo)簽處理器對(duì)象,若標(biāo)簽體為空?setJspBody? 將不會(huì)被 JSP 引擎調(diào)用
5、doTag
容器調(diào)用標(biāo)簽處理器對(duì)象的 doTag 方法執(zhí)行標(biāo)簽邏輯
對(duì)于?setJspContext,在方法里把 jspContext 對(duì)象賦予全局變量 pageContext,這樣就能獲取到 JSP 中的所有隱含對(duì)象。
編寫(xiě)帶屬性的標(biāo)簽
首先,在 tld 配置文件下添加如下內(nèi)容

注:rtexprvalue 表示的是 runtime expression value
然后在?HelloSimpleTag 類(lèi)下添加兩個(gè)成員變量 value 和 count 用來(lái)接收參數(shù),強(qiáng)烈建議使用 String 類(lèi)型的參數(shù),并且實(shí)現(xiàn)兩者的 set 方法。

接著在 doTag 里面獲取參數(shù),并且進(jìn)行邏輯處理

最后在 JSP 里面引用標(biāo)簽

如果是接收動(dòng)態(tài)值可以這么寫(xiě)

如果重新新建了 tag 類(lèi),只需在 tld 配置文件里面重新添加 tag 標(biāo)簽,并進(jìn)行屬性的說(shuō)明
通常情況下,開(kāi)發(fā)簡(jiǎn)單標(biāo)簽直接繼承?SimpleTagSupport 就可以,可以直接調(diào)用其對(duì)應(yīng)的 getter 方法得到對(duì)應(yīng)的 API
編寫(xiě)帶標(biāo)簽體的自定義標(biāo)簽
1、在自定義標(biāo)簽的標(biāo)簽處理器中使用 JspFragment 對(duì)象封裝標(biāo)簽體信息
2、若配置了標(biāo)簽含有標(biāo)簽體,則 JSP 引擎會(huì)調(diào)用 setJspBody() 方法把 JspFragment 傳遞給標(biāo)簽處理類(lèi),在 SImpleTagSupport 中還定義了一個(gè) getJspBody() 方法,用于返回 JspFragment 對(duì)象
3、JspFragment 的 invoke(writer)方法:把標(biāo)簽體內(nèi)容從 Writer 中輸出,若為 null,則等同于 invoke(getJspContext().getOut()),即直接把標(biāo)簽體內(nèi)容輸出到頁(yè)面上
4、在 tld 文件中,使用 body-content 節(jié)點(diǎn)來(lái)描述標(biāo)簽體的類(lèi)型:
empty:沒(méi)有標(biāo)簽體
scriptless:標(biāo)簽體可以包含 el 表達(dá)式和 JSP 動(dòng)作元素,但不能包含 JSP 的腳本元素
說(shuō)明:

由圖,第一種屬于 el 表達(dá)式,第二種表示 JSP 腳本元素。
tagdependent:表示標(biāo)簽體交由標(biāo)簽本身去解析處理,若指定?tagdependent,在標(biāo)簽體中的所有代碼都會(huì)原封不動(dòng)的交給標(biāo)簽處理器,而不是將執(zhí)行結(jié)果傳遞給標(biāo)簽處理器
大部分情況下,類(lèi)型取值為?scriptless

如圖,獲取標(biāo)簽體的內(nèi)容,并轉(zhuǎn)換成大寫(xiě)打印在頁(yè)面上
編寫(xiě)帶父標(biāo)簽的自定義標(biāo)簽
編寫(xiě)一個(gè)父標(biāo)簽?TestParentTag,并編寫(xiě)一個(gè)子標(biāo)簽?TestSonTag,在 JSP 引用的時(shí)候,父標(biāo)簽在控制臺(tái)打印信息,子標(biāo)簽作為父標(biāo)簽的標(biāo)簽體在頁(yè)面上顯示父標(biāo)簽的內(nèi)容
TestParentTag:

TestSonTag:

tld 配置:

JSP 引用:

運(yùn)行結(jié)果:

通過(guò)案例可以得出:
1、父標(biāo)簽無(wú)法獲取子標(biāo)簽的引用,父標(biāo)簽僅把子標(biāo)簽作為標(biāo)簽體來(lái)使用
2、子標(biāo)簽可以通過(guò) getParent() 來(lái)獲取父標(biāo)簽的引用(需繼承 SimpleTagSupport 或?qū)崿F(xiàn) SimpleTag 接口的該方法),若子標(biāo)簽的確有父標(biāo)簽,JSP 引擎會(huì)把代表父標(biāo)簽的引用通過(guò) setParent(JspTag parent) 賦給標(biāo)簽處理器
3、父標(biāo)簽的類(lèi)型是 JspTag 類(lèi)型,該 JspTag 接口為空接口,用來(lái)統(tǒng)一?SimpleTag 和 Tag 的,簡(jiǎn)單標(biāo)簽和傳統(tǒng)標(biāo)簽
4、在 tld 配置文件中,不需要為父標(biāo)簽有額外的配置,但子標(biāo)簽是以標(biāo)簽體的形式存在的,所以父標(biāo)簽的 body-content 需要設(shè)置為?scriptless
JSTL fn 函數(shù)
為了簡(jiǎn)化在 JSP 頁(yè)面操作字符串,JSTL 中提供了一套 EL 自定義函數(shù),這些自定義函數(shù)包含了 JSP 頁(yè)面經(jīng)常用到的字符串操作
使用方法如下:

如圖,在頭部引用函數(shù)的聲明,然后通過(guò)?${fun:contains("name", "a")} 來(lái)操作字符串
以上為本人的一些學(xué)習(xí)筆記,如有出錯(cuò)歡迎指正,陸續(xù)更新?。?!