javascript
Head First JSP---随笔八(传统标记)
傳統標記處理器
也許我們很幸運,我們的公司采用了JSP 2.0。但也可能很糟糕,用的是2.0以前的版本。
Tag處理器API
我們只要擴展其中一個類就行了。
一個非常小傳統標記處理器
這個例子太極除了,它與SimpleTag處理器的doTag()方法幾乎沒有什么區別。
有兩個方法的傳統標記處理器
標記有體時:簡單標記和傳統標記的比較
這里思考一個問題:如果我們要循環一個體呢?這里是return,我們該如何做呢?后面有答案!
傳統標記的生命周期是不同的
這樣的生命周期很有意思。
傳統標記生命周期取決于返回值
doStartTag()和doEndTag()方法返回一個int。這個int告訴容器下一步要做什么。
對于doStartTag(),容器的問題是“我該計算體嗎?”。
對于doEndTag(),容器的問題是“我要繼續計算調用頁面的余下部分嗎?”。
如圖:
IterationTag允許體重復執行
TagSupport的UML:
通過重寫doAfterBody()方法達到重復執行體的功能。
例子:
簡單標記實現:
傳統標記實現:
TagSupport的默認返回值
如果沒有覆蓋返回一個整數的TagSupport生命周期方法,要當心TagSupport方法實現返回的默認值。
需要注意的點,給你一個例子
要注意,doAfterBody()方法在已經處理一次體后才開始運行,看看上面的調用“流程圖”。
這里還要注意:容器可以重用傳統標記處理器,也就是說,我們要注意全局變量。
實例
還記得第三章的啤酒案例嗎?現在來實現動態獲取!
開發環境:
初始化頁面(init.jsp):
<%@ page import="java.util.*" %>> <html> <body><% List<String> optionsList = new ArrayList<String>();optionsList.add("light");optionsList.add("amber");optionsList.add("brown");optionsList.add("dark");getServletContext().setAttribute("colorList", optionsList);%><jsp:forward page="beer.jsp"/> </body> </html>我們的表單頁面(beer.jsp):
<%@ taglib prefix="formTags" uri="http://example.com/tags/forms" %> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <html> <body><form method="post" action="SelectBeer.do"><p>Select beer characteristics:</p>Color:<c:catch><formTags:select name="color" size="1"optionsList="${applicationScope.colorList}"/><br><br></c:catch><input type="submit" value="submit"></form> </body> </html>我們的簡單標記處理器類(SelectTagHandler.java):
package com.example.taglib;import java.io.IOException; import java.util.List;import javax.servlet.jsp.JspException; import javax.servlet.jsp.JspWriter; import javax.servlet.jsp.PageContext; import javax.servlet.jsp.tagext.SimpleTagSupport;public class SelectTagHandler extends SimpleTagSupport{private List<String> optionsList;private String name;private int size;public void setOptionsList(List<String> optionsList) {this.optionsList = optionsList;}public void setName(String name) {this.name = name;}public void setSize(int size) {this.size = size;}@Overridepublic void doTag() throws JspException, IOException {PageContext pageContext = (PageContext) getJspContext();JspWriter out = pageContext.getOut();out.println("<select name='"+name+"' size='"+size+"'>");for(int i=0;i<optionsList.size();i++) {String s = optionsList.get(i);out.println("<option value='"+s+"'> "+s+" </option>");}out.println("</select>");} }我們的標記文件(demo.tld):
<?xml version="1.0" encoding="ISO-8859-1" ?> <!DOCTYPE taglibPUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN""http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_2.dtd"><taglib><tlib-version>1.2</tlib-version><jsp-version>1.2</jsp-version><short-name>Forms Taglib</short-name><uri>http://example.com/tags/forms</uri><description>An example tab library of replacements for the HTML form tags.</description><tag><name>select</name><tag-class>com.example.taglib.SelectTagHandler</tag-class><body-content>empty</body-content><attribute><name>optionsList</name><type>java.util.List</type><required>true</required><rtexprvalue>true</rtexprvalue></attribute><attribute><name>name</name><required>true</required><rtexprvalue>true</rtexprvalue></attribute><attribute><name>size</name><required>true</required><rtexprvalue>true</rtexprvalue></attribute></tag> </taglib>我們的部署文件(DD):
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns="http://java.sun.com/xml/ns/javaee"xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"id="WebApp_ID" version="3.0"><welcome-file-list><welcome-file>init.jsp</welcome-file></welcome-file-list></web-app>實驗結果:
select標記還不完善
我們HTML的<select>標記有更多的屬性。
我們需要在標記處理器類添加些能夠設置它們的方法:
看完之后…呵呵,tld也要配置這些屬性。太恐怖了!!
幸好!JSP規范專門針對這個目的提供了一個API,那就是我們的DynamicAttributes接口。
標記處理器代碼使用DynamicAttribute接口
使用3張圖搞定這個部分:
首先看看setXxx()該如何解決(因為這里是鍵/值對,所以用HashMap是最好的選擇,當然也可以用別的):
接下來是doTag()方法:
最后是TLD中的配置:
最后就完成了。這簡直是神器!
這里指出:這個接口對傳統標記也是適用的。
標記文件的dynamic-attributes
這里要注意,tagAttrs是一個頁面作用域變量。
一個實例:
首先是.tag文件:
<%@ tag body-content="empty" dynamic-attributes="tagAttrs"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <c:forEach var="attr" items="${tagAttrs}">${attr.key} = ${attr.value} </c:forEach>其次是測試的.jsp文件:
<%@ taglib prefix="myTags" tagdir="/WEB-INF/tags" %> <html> <body><myTags:header name="123" value="111"/> </body> </html>實驗結果:
帥呆了!!
DynamicAttributes接口的要點
如果要訪問體內容!
如果我們能直接訪問具體的體內容,就可以做很多事情了,比如在表達式中使用體內容,或者以某種方式過濾或修改。為此可以擴展BodyTagSupport而不是TagSupport,這樣你就能訪問BodyTag接口方法。
基于BodyTag,你會獲得兩個新方法
注意:默認值改變為EVAL_BODY_BUFFERED。
還有一個需要注意的地方(如果沒有體,需要return SKIP_BODY):
傳統標記方法的生命周期返回值
標記可以調用其父標記
SimpleTag和Tag都有一個getParent()方法(注意返回值存在區別)。
簡單標記的父標記可以是傳統標記
簡單標記的父標記可以是傳統標記的原因,是因為Tag is-like-a JspTag。因此,簡單標記不能是傳統標記的父標記。
父標記從子標記獲取信息
我們知道,只有getParent()方法而沒有getChild()方法,也就是說,只能獲取到父標記不能得到子標記。那我們如何獲取到信息呢?
一個例子:
這樣就很巧妙的讓父標記知道子標記的信息。下面是測試:
結果與我們想象的一樣。
得到一個任意的祖先
使用findAncestorWithClass()方法向上查找到一個特定的祖先,返回第一個找到的祖先(也就是如果這顆樹有多個我們要查找的節點,返回深度最深的節點并且這個節點是this的祖先)。
簡單標記和傳統標記的重要區別
使用標記處理器的PageContext API(復習)
本章完。。
總結
以上是生活随笔為你收集整理的Head First JSP---随笔八(传统标记)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 宠物次元经济专题分析2020
- 下一篇: Head First JSP---随笔九