java web--自定義jstl標簽
1、 自定義標簽
1). HelloWorld
①. 創建一個標簽處理器類: 實現 SimpleTag 接口.
②. 在 WEB-INF 文件夾下新建一個 .tld(標簽庫描述文件) 為擴展名的 xml 文件. 並拷入固定的部分: 並對
description, display-name, tlib-version, short-name, uri 做出修改
<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">
<description>JSTL 1.1 core library</description>
<display-name>JSTL core</display-name>
<tlib-version>1.1</tlib-version>
<short-name>c</short-name>
<uri>http://java.sun.com/jsp/jstl/core</uri>
</taglib>
③. 在 tld 文件中描述自定義的標簽:
<!-- 描述自定義的 HelloSimpleTag 標簽 -->
<tag>
<!-- 標簽的名字: 在 JSP 頁面上使用標簽時的名字 -->
<name>hello</name>
<!-- 標簽所在的全類名 -->
<tag-class>com.atguigu.javaweb.tag.HelloSimpleTag</tag-class>
<!-- 標簽體的類型 -->
<body-content>empty</body-content>
</tag>
④. 在 JSP 頁面上使用自定義標簽:
> 使用 taglib 指令導入標簽庫描述文件: <%@taglib uri="http://www.atguigu.com/mytag/core" prefix="atguigu" %>
> 使用自定義的標簽: <atguigu:hello/>
2). setJspContext: 一定會被 JSP 引擎所調用, 先於 doTag, 把代表 JSP 引擎的 pageContext 傳給標簽處理器類.
private PageContext pageContext;
@Override
public void setJspContext(JspContext arg0) {
System.out.println(arg0 instanceof PageContext);
this.pageContext = (PageContext) arg0;
}
3). 帶屬性的自定義標簽:
①. 先在標簽處理器類中定義 setter 方法. 建議把所有的屬性類型都設置為 String 類型.
private String value;
private String count;
public void setValue(String value) {
this.value = value;
}
public void setCount(String count) {
this.count = count;
}
②. 在 tld 描述文件中來描述屬性:
<!-- 描述當前標簽的屬性 -->
<attribute>
<!-- 屬性名, 需和標簽處理器類的 setter 方法定義的屬性相同 -->
<name>value</name>
<!-- 該屬性是否被必須 -->
<required>true</required>
<!-- rtexprvalue: runtime expression value
當前屬性是否可以接受運行時表達式的動態值 -->
<rtexprvalue>true</rtexprvalue>
</attribute>
③. 在頁面中使用屬性, 屬性名同 tld 文件中定義的名字.
<atguigu:hello value="${param.name }" count="10"/>
4). 通常情況下開發簡單標簽直接繼承 SimpleTagSupport 就可以了. 可以直接調用其對應的 getter 方法得到對應的 API
public class SimpleTagSupport implements SimpleTag{
public void doTag()
throws JspException, IOException{}
private JspTag parentTag;
public void setParent( JspTag parent ) {
this.parentTag = parent;
}
public JspTag getParent() {
return this.parentTag;
}
private JspContext jspContext;
public void setJspContext( JspContext pc ) {
this.jspContext = pc;
}
protected JspContext getJspContext() {
return this.jspContext;
}
private JspFragment jspBody;
public void setJspBody( JspFragment jspBody ) {
this.jspBody = jspBody;
}
protected JspFragment getJspBody() {
return this.jspBody;
}
}
2. JSTL:
1)*. c:out 主要用於對特殊字符進行轉換. 真正進行輸出時, 建議使用 c:out, 而不是使用 EL
2)*. c:set: 可以為域賦屬性值。 而對域對象中的 JavaBean 的屬性賦值用的並不多.
3). c:remove: 移除指定域對象的指定屬性值(較少使用, 即便移除也是在 Servlet 中完成)
4)*. c:if: 在頁面上對現實的內容進行過濾, 把結果存儲到域對象的屬性中. 但不靈活, 會被其他的自定義標簽所取代.
5). c:choose, c:when, c:otherwise: 作用同上, 但麻煩, 不靈活.
6)*. c:forEach: 對集合進行遍歷的. 常用!
7). c:forTokens: 處理字符串, 類似於 String 累的 split() 方法(知道即可)
8). c:import: 導入頁面到當前頁面的. (了解)
9). c:redirect: 當前頁面進行重定向的. (使用較少)
10)*. c:url: 產生一個 URL 的, 可以進行 URL 重寫, 變量值編碼, 較為常用.
3. 開發有父標簽的標簽:
1). 父標簽無法獲取子標簽的引用, 父標簽僅把子標簽作為標簽體來使用.
2). 子標簽可以通過 getParent() 方法來獲取父標簽的引用(需繼承 SimpleTagSupport 或自實現 SimpleTag 接口的該方法):
若子標簽的確有父標簽, JSP 引擎會把代表父標簽的引用通過 setParent(JspTag parent) 賦給標簽處理器
3). 註意: 父標簽的類型是 JspTag 類型. 該接口是一個空接口, 但是來統一 SimpleTag 和 Tag 的. 實際使用需要進行類型的強制轉換.
4). 在 tld 配置文件中, 無需為父標簽有額外的配置. 但, 子標簽是是以標簽體的形式存在的, 所以父標簽的
<body-content></body-content> 需設置為 scriptles
5). 實現
<c:choose>
<c:when test="${param.age > 24}">大學畢業</c:when>
<c:when test="${param.age > 20}">高中畢業</c:when>
<c:otherwise>高中以下...</c:otherwise>
</c:choose>
> 開發 3 個標簽: choose, when, otherwise
> 其中 when 標簽有一個 boolean 類型的屬性: test
> choose 是 when 和 otherwise 的父標簽
> when 在 otherwise 之前使用
> 在父標簽 choose 中定義一個 "全局" 的 boolean 類型的 flag: 用於判斷子標簽在滿足條件的情況下是否執行.
* 若 when 的 test 為 true, 且 when 的父標簽的 flag 也為 true, 則執行 when 的標簽體(正常輸出標簽體的內容),
同時把 flag 設置為 false
* 若 when 的 test 為 true, 且 when 的父標簽的 flag 為 false, 則不執行標簽體.
* 若 flag 為 true, otherwise 執行標簽體.
4. 帶標簽體的自定義標簽:
1). 若一個標簽有標簽體:
<atguigu:testJspFragment>abcdefg</atguigu:testJspFragment>
在自定義標簽的標簽處理器中使用 JspFragment 對象封裝標簽體信息.
2). 若配置了標簽含有標簽體, 則 JSP 引擎會調用 setJspBody() 方法把 JspFragment 傳遞給標簽處理器類
在 SimpleTagSupport 中還定義了一個 getJspBody() 方法, 用於返回 JspFragment 對象.
3). JspFragment 的 invoke(Writer) 方法: 把標簽體內容從 Writer 中輸出, 若為 null,
則等同於 invoke(getJspContext().getOut()), 即直接把標簽體內容輸出到頁面上
有時, 可以 借助於 StringWriter, 可以在標簽處理器類中先得到標簽體的內容:
//1. 利用 StringWriter 得到標簽體的內容.
StringWriter sw = new StringWriter();
bodyContent.invoke(sw);
//2. 把標簽體的內容都變為大寫
String content = sw.toString().toUpperCase();
4). 在 tld 文件中, 使用 body-content 節點來描述標簽體的類型:
<body-content>: 指定標簽體的類型, 大部分情況下, 取值為 scriptless。可能取值有 3 種:
empty: 沒有標簽體
scriptless: 標簽體可以包含 el 表達式和 JSP 動作元素,但不能包含 JSP 的腳本元素
tagdependent: 表示標簽體交由標簽本身去解析處理。
若指定 tagdependent,在標簽體中的所有代碼都會原封不動的交給標簽處理器,而不是將執行結果傳遞給標簽處理器
<body-content>tagdependent</body-content
5. 定義一個自定義標簽: <atguigu:printUpper time="10">abcdefg</atguigu>
把標簽體內容轉換為大寫, 並輸出 time 次到 瀏覽
6. 實現 forEach 標簽:
> 兩個屬性: items(集合類型, Collection), var(String 類型)
> doTag:
* 遍歷 items 對應的集合
* 把正在遍歷的對象放入到 pageContext 中, 鍵: var, 值: 正在遍歷的對象.
* 把標簽體的內容直接輸出到頁面上.
<c:forEach items="${requestScope.customers }" var="cust2">
${pageScope.cust2.id } -- ${cust2.name } <br>
</c:forEach>
<atguigu:saveAsFile src="d:\\haha.txt">
abcde
</atguigu>
java web--自定義jstl標簽