<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    溫馨提示:您的每一次轉載,體現了我寫此文的意義!!!煩請您在轉載時注明出處http://m.tkk7.com/sxyx2008/謝謝合作!!!

    雪山飛鵠

    溫馨提示:您的每一次轉載,體現了我寫此文的意義!!!煩請您在轉載時注明出處http://m.tkk7.com/sxyx2008/謝謝合作!!!

    BlogJava 首頁 新隨筆 聯系 聚合 管理
      215 Posts :: 1 Stories :: 674 Comments :: 0 Trackbacks

    自定義標簽庫并不是 JSP 2 才出現的,JSP 1.1 版中已經增加了自定義標簽庫規范,自定義標簽庫是一種非常優秀的表現層組件技術。通過使用自定義標簽庫,可以在簡單的標簽中封裝復雜的功能。

    為什么要使用自定義標簽呢?主要是為了取代丑陋的 JSP 腳本。在 HTML 頁面中插入 JSP 腳本有如下幾個壞處:

    • JSP 腳本非常丑陋,難以閱讀。
    • JSP 腳本和 HTML 代碼混雜,維護成本高。
    • HTML 頁面中嵌入 JSP 腳本,導致美工人員難以參與開發。

    出于以上三點的考慮,我們需要一種可在頁面中使用的標簽,這種標簽具有和 HTML 標簽類似的語法,但由可以完成 JSP 腳本的功能——這種標簽就是 JSP 自定義標簽。

    在 JSP1.1 規范中開發自定義標簽庫比較復雜,JSP 2 規范簡化了標簽庫的開發,在 JSP 2 中開發標簽庫只需如下幾個步驟:

    1. 開發自定義標簽處理類;
    2. 建立一個 *.tld 文件,每個 *.tld 文件對應一個標簽庫,每個標簽庫對應多個標簽;
    3. 在 JSP 文件中使用自定義標簽。

    開發自定義標簽類

    標簽庫和實際開發

    標簽庫是非常重要的技術,通常來說,初學者、普通開發人員自己開發標簽庫的機會很少,但如果希望成為高級程序員,或者希望開發通用框架,就需要大量開發自定義標簽了。所有的 MVC 框架,如 Struts 2、SpringMVC、JSF 等都提供了豐富的自定義標簽。

    當我們在 JSP 頁面使用一個簡單的標簽時,底層實際上由標簽處理類提供支持,從而可以使用簡單的標簽來封裝復雜的功能,從而使團隊更好地協作開發(能讓美工人員更好地參與 JSP 頁面的開發)。

    早期 JSP 自定義標簽類開發過程略微復雜一些,但 JSP 2 已經簡化了這個過程,它只要自定義標簽類都必須繼承一個父類:javax.servlet.jsp.tagext.SimpleTagSupport,除此之外,JSP 自定義標簽類還有如下要求。

    • 如果標簽類包含屬性,每個屬性都有對應的 getter 和 setter 方法。
    • 重寫 doTag() 方法,這個方法負責生成頁面內容。

    下面開發一個最簡單的自定義標簽,該標簽負責在頁面上輸出 HelloWorld。

    // 標簽處理類,繼承 SimpleTagSupport 父類
    public class HelloWorldTag extends SimpleTagSupport 
    { 
        // 重寫 doTag 方法,該方法在標簽結束生成頁面內容
        public void doTag()throws JspException, 
            IOException 
        { 
            // 獲取頁面輸出流,并輸出字符串
            getJspContext().getOut().write("Hello World"); 
        } 
    } 
    

    上面這個標簽處理類非常簡單,它繼承了 SimpleTagSupport 父類,并重寫 doTag() 方法,而 doTag() 方法則負責輸出頁面內容。該標簽沒有屬性,因此無須提供 setter 和 getter 方法。


    建立 TLD 文件

    TLD 是 Tag Library Definition 的縮寫,即標簽庫定義,文件的后綴是 tld,每個 TLD 文件對應一個標簽庫,一個標簽庫中可包含多個標簽,TLD 文件也稱為標簽庫定義文件。

    標簽庫定義文件的根元素是 taglib,它可以包含多個 tag 子元素,每個 tag 子元素都定義一個標簽。通常我們可以到 Web 容器下復制一個標簽庫定義文件,并在此基礎上進行修改即可。例如 Tomcat6.0,在 webapps\examples\WEB-INF\jsp2 路徑下包含了一個 jsp2-example-taglib.tld 文件,這就是示范用的標簽庫定義文件。

    將該文件復制到 Web 應用的 WEB-INF/ 路徑,或 WEB-INF 的任意子路徑下,并對該文件進行簡單修改,修改后的 mytaglib.tld 文件代碼如下:

    <?xml version="1.0" encoding="GBK"?>
    <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 web-jsptaglibrary_2_0.xsd"
        version="2.0">
        <tlib-version>1.0</tlib-version>
        <short-name>mytaglib</short-name>
        <!-- 定義該標簽庫的URI -->
        <uri>http://www.crazyit.org/mytaglib</uri>
        <!-- 定義第一個標簽 -->
        <tag>
            <!-- 定義標簽名 -->
            <name>helloWorld</name>
            <!-- 定義標簽處理類 -->
            <tag-class>lee.HelloWorldTag</tag-class>
            <!-- 定義標簽體為空 -->
            <body-content>empty</body-content>
        </tag>
    </taglib>
    

    上面標簽庫定義文件也是一個標準的 XML 文件,該 XML 文件的根元素是 taglib 元素,因此我們每次編寫標簽庫定義文件都直接添加該元素即可。

    taglib 下有三個子元素:

    • tlib-version:指定該標簽庫實現的版本,這是一個作為標識的內部版本號,對程序沒有太大的作用。
    • short-name:該標簽庫的默認短名,該名稱通常也沒有太大的用處。
    • uri:這個屬性非常重要,它指定該標簽庫的 URI,相當于指定該標簽庫的唯一標識。如上粗體字代碼所示,JSP 頁面中使用標簽庫時就是根據該 URI 屬性來定位標簽庫的。

    除此之外,taglib 元素下可以包含多個 tag 元素,每個 tag 元素定義一個標簽,tag 元素下至少應包含如下三個子元素:

    • name:該標簽庫的名稱,這個屬性很重要,JSP 頁面中就是根據該名稱來使用此標簽的。
    • tag-class:指定標簽的處理類,毋庸置疑,這個屬性非常重要,指定了標簽由哪個 Java 類來處理。
    • body-content:這個屬性也很重要,它指定標簽體內容。該元素的值可以是如下幾個:
      • tagdependent:指定標簽處理類自己負責處理標簽體。
      • empty:指定該標簽只能作用空標簽使用。
      • scriptless:指定該標簽的標簽體可以是靜態 HTML 元素,表達式語言,但不允許出現 JSP 腳本。
      • JSP:指定該標簽的標簽體可以使用 JSP 腳本。

    實際上由于 JSP 2 規范不再推薦使用 JSP 腳本,所以 JSP 2 自定義標簽的標簽體中不能包含 JSP 腳本。所以實際上 body-content 元素的值不可以是 JSP。

    定義了上面的標簽庫定義文件后,將標簽庫文件放在 Web 應用的 WEB-INF 路徑,或任意子路徑下,Java Web 規范會自動加載該文件,則該文件定義的標簽庫也將生效。


    使用標簽庫

    在 JSP 頁面中確定指定標簽需要 2 點:

    • 標簽庫 URI:確定使用哪個標簽庫。
    • 標簽名:確定使用哪個標簽。

    使用標簽庫分成以下兩個步驟:

    1. 導入標簽庫:使用 taglib 編譯指令導入標簽庫,就是將標簽庫和指定前綴關聯起來。
    2. 使用標簽:在 JSP 頁面中使用自定義標簽。

    taglib 的語法格式如下:

    <%@ taglib uri="tagliburi" prefix="tagPrefix" %> 
    

    其中 uri 屬性確定標簽庫的 URI,這個 URI 可以確定一個標簽庫。而 prefix 屬性指定標簽庫前綴,即所有使用該前綴的標簽將由此標簽庫處理。

    使用標簽的語法格式如下:

    <tagPrefix:tagName tagAttribute=”tagValue” … > 
    	<tagBody/> 
    </tagPrefix:tagName> 
    

    如果該標簽沒有標簽體,則可以使用如下語法格式:

    <tagPrefix:tagName tagAttribute=”tagValue” … /> 
    

    上面使用標簽的語法里都包含了設置屬性值,前面我們介紹的 HelloWorldTag 標簽沒有任何屬性,所以使用該標簽只需用 <mytag:helloWorld/> 即可。其中 mytag 是 taglib 指令為標簽庫指定的前綴,而 helloWorld 是標簽名。

    下面是使用 helloWorld 標簽的 JSP 頁面代碼:

    <%@ page contentType="text/html; charset=GBK"%>
    <!-- 導入標簽庫,指定mytag前綴的標簽,
    	由http://www.crazyit.org/mytaglib的標簽庫處理 -->
    <%@ taglib uri="http://www.crazyit.org/mytaglib" prefix="mytag"%>
    <html>
    <head>
    <title>自定義標簽示范</title>
    </head>
    <body bgcolor="#ffffc0">
    <h2>下面顯示的是自定義標簽中的內容</h2>
    <!-- 使用標簽 ,其中mytag是標簽前綴,根據taglib的編譯指令,
    	mytag前綴將由http://www.crazyit.org/mytaglib的標簽庫處理 -->
    <mytag:helloWorld/><BR>
    </body>
    </html>
    

    上面頁面中第一行粗體字代碼指定了 http://www.crazyit.org/mytaglib 標簽庫的前綴為 mytag,第二行粗體字代碼表明使用 mytag 前綴對應標簽庫里的 helloWorld 標簽。瀏覽該頁面將看到如圖 1 所示效果:


    圖 1. 簡單標簽
    圖 1. 簡單標簽

    帶屬性的標簽

    前面的簡單標簽既沒有屬性,也沒有標簽體,用法、功能都比較簡單。實際上還有如下兩種常用的標簽:

    • 帶屬性的標簽。
    • 帶標簽體的標簽。

    正如前面介紹的,帶屬性標簽必須為每個屬性提供對應的 setter 和 getter 方法。帶屬性標簽的配置方法與簡單標簽也略有差別,下面介紹一個帶屬性標簽的示例:

    public class QueryTag extends SimpleTagSupport
    {
        //標簽的屬性
        private String driver;
        private String url;
        private String user;
        private String pass;
        private String sql;
        //執行數據庫訪問的對象 
        private Connection conn = null;
        private Statement stmt = null;
        private ResultSet rs = null;
        private ResultSetMetaData rsmd = null;
        //標簽屬性driver的setter方法
        public void setDriver(String driver) {
            this.driver = driver; 
        }
            //標簽屬性url的setter方法
        public void setUrl(String url) {
            this.url = url; 
        }
            //標簽屬性user的setter方法
        public void setUser(String user) {
            this.user = user; 
        }
            //標簽屬性pass的setter方法
        public void setPass(String pass) {
            this.pass = pass; 
        }
            //標簽屬性driver的getter方法
        public String getDriver() {
            return (this.driver); 
        }
            //標簽屬性url的getter方法
        public String getUrl() {
            return (this.url); 
        }
            //標簽屬性user的getter方法
        public String getUser() {
            return (this.user); 
        }
            //標簽屬性pass的getter方法
        public String getPass() {
            return (this.pass); 
        }
            //標簽屬性sql的getter方法
        public String getSql() {
            return (this.sql); 
        }
            //標簽屬性sql的setter方法
        public void setSql(String sql) {
            this.sql = sql; 
        }
        public void doTag()throws JspException,
            IOException
        {
               try
            {
                //注冊驅動
                Class.forName(driver);
                //獲取數據庫連接
                conn = DriverManager.getConnection(url,user,pass);
                //創建Statement對象
                stmt = conn.createStatement();
                //執行查詢
                rs = stmt.executeQuery(sql);
                rsmd = rs.getMetaData();
                //獲取列數目
                int columnCount = rsmd.getColumnCount();
                //獲取頁面輸出流
                Writer out = getJspContext().getOut();
                //在頁面輸出表格
                out.write("<table border='1' bgColor='9999cc' width='400'>");
                //遍歷結果集
                while (rs.next())
                {
                    out.write("<tr>");
                    //逐列輸出查詢到的數據
                    for (int i = 1 ; i <= columnCount ; i++ )
                    {
                        out.write("<td>");
                        out.write(rs.getString(i));
                        out.write("</td>");
                    }
                    out.write("</tr>");
                }
            }
            catch(ClassNotFoundException cnfe)
            {
                cnfe.printStackTrace();
                throw new JspException("自定義標簽錯誤" + cnfe.getMessage());
            }
            catch (SQLException ex)
            {
                ex.printStackTrace();
                throw new JspException("自定義標簽錯誤" + ex.getMessage());
            }
            finally
            {
                //關閉結果集
                try
                {
                    if (rs != null)
                        rs.close();
                    if (stmt != null)
                        stmt.close();
                    if (conn != null)
                        conn.close();
                }
                catch (SQLException sqle)
                {
                    sqle.printStackTrace();
                }
            }
        }
    }
    

    上面這個標簽稍微復雜一點,它包含了 5 個屬性,如程序中粗體字代碼所示,則程序需要為這 5 個屬性提供 setter 和 getter 方法。

    該標簽輸出的內容依然由 doTag() 方法決定,該方法會根據 SQL 語句查詢數據庫,并將查詢結果顯示在當前頁面中。

    對于有屬性的標簽,需要為 tag 元素增加 attribute 子元素,每個 attribute 子元素定義一個屬性,attribue 子元素通常還需要指定如下幾個子元素:

    • name:設置屬性名,子元素的值是字符串內容。
    • required:設置該屬性是否為不需屬性,該子元素的值是 true 或 false。
    • fragment:設置該屬性是否支持 JSP 腳本、表達式等動態內容,子元素的值是 true 或 false。

    為了配置上面的 QueryTag 標簽,我們需要在 mytaglib.tld 文件中增加如下配置片段:

    <!-- 定義第二個標簽 -->
    <tag>
        <!-- 定義標簽名 -->
        <name>query</name>
        <!-- 定義標簽處理類 -->
        <tag-class>lee.QueryTag</tag-class>
        <!-- 定義標簽體為空 -->
        <body-content>empty</body-content>
        <!-- 配置標簽屬性:driver -->
        <attribute>
            <name>driver</name> 
            <required>true</required>
            <fragment>true</fragment>
        </attribute>
        <!-- 配置標簽屬性:url -->
        <attribute>
            <name>url</name> 
            <required>true</required>
            <fragment>true</fragment>
        </attribute>
        <!-- 配置標簽屬性:user -->
        <attribute>
            <name>user</name> 
            <required>true</required>
            <fragment>true</fragment>
        </attribute>
        <!-- 配置標簽屬性:pass -->
        <attribute>
            <name>pass</name> 
            <required>true</required>
            <fragment>true</fragment>
        </attribute>
        <!-- 配置標簽屬性:sql -->
        <attribute>
            <name>sql</name> 
            <required>true</required>
            <fragment>true</fragment>
        </attribute>
    </tag>
    

    上面 5 行粗體字代碼分別為該標簽配置了 driver、url、user、pass 和 sql 等 5 個屬性,并指定這 5 個屬性都是必填屬性、而且屬性值支持動態內容。

    配置完畢后,就可在頁面中使用標簽,先導入標簽庫,然后使用標簽。使用標簽的 JSP 頁面片段如下:

    <!-- 導入標簽庫,指定mytag前綴的標簽,
        由http://www.crazyit.org/mytaglib的標簽庫處理 -->
    <%@ taglib uri="http://www.crazyit.org/mytaglib" prefix="mytag"%>
    ...
    <!-- 其他HTML內容 -->
    <!-- 使用標簽 ,其中mytag是標簽前綴,根據taglib的編譯指令,
        mytag前綴將由http://www.crazyit.org/mytaglib的標簽庫處理 -->
    <mytag:query
        driver="com.mysql.jdbc.Driver"
        url="jdbc:mysql://localhost:3306/javaee"
        user="root"
        pass="32147"
        sql="select * from newsinf"/>
    

    在瀏覽器中瀏覽該頁面,效果如圖 2 所示。


    圖 2. 使用帶屬性的標簽執行查詢
    圖 2. 使用帶屬性的標簽執行查詢

    圖 2 中看到從數據庫里查詢到 2 條記錄,當然這也需要底層 javaee 數據庫里包含 newsinf 數據表,且該數據表里包含這兩條記錄才行。

    在 JSP 頁面中只需要使用簡單的標簽,即可完成“復雜”的功能:執行數據庫查詢,并將查詢結果在頁面上以表格形式顯示。這也正是自定義標簽庫的目的——以簡單的標簽,隱藏復雜的邏輯。

    當然,并不推薦在標簽處理類中訪問數據庫,因為標簽庫是表現層組件,它不應該包含任何業務邏輯實現代碼,更不應該執行數據庫訪問,它只應該負責顯示邏輯。


    帶標簽體的標簽

    帶標簽體的標簽,可以在標簽內嵌入其他內容(包括靜態的 HTML 內容和動態的 JSP 內容),通常用于完成一些邏輯運算,例如判斷和循環等。下面以一個迭代器標簽為示例,介紹帶標簽體標簽的開發過程。

    一樣先定義一個標簽處理類,該標簽處理類的代碼如下:

    public class IteratorTag extends SimpleTagSupport
    {
        //標簽屬性,用于指定需要被迭代的集合
        private String collection;
        //標簽屬性,指定迭代集合元素,為集合元素指定的名稱
        private String item;
        //collection屬性的setter和getter方法
        public void setCollection(String collection)
        {
            this.collection = collection;
        }
        public String getCollection()
        {
            return this.collection;
        }
        //item屬性的setter和getter方法
        public void setItem(String item)
        {
            this.item = item;
        }
        public String getItem()
        {
            return this.item;
        }
        //標簽的處理方法,簡單標簽處理類只需要重寫doTag方法
        public void doTag() throws JspException, IOException
        {
            //從page scope中獲取屬性名為collection的集合
            Collection itemList = (Collection)getJspContext().
                getAttribute(collection);
            //遍歷集合
            for (Object s : itemList)
            {
                //將集合的元素設置到page 范圍
                getJspContext().setAttribute(item, s );
                //輸出標簽體
                getJspBody().invoke(null);
            }
        }
    }
    

    上面標簽處理類與前面處理類并沒有太大的不同,該處理類包含 2 個屬性,并為這兩個屬性提供了 setter 和 getter 方法。標簽處理類的 doTag 方法首先從 page 范圍內獲取了指定名稱的 Collection 對象,然后遍歷 Collection 對象的元素,每次遍歷都調用了 getJspBody() 方法,如程序中粗體字代碼所示,該方法返回該標簽所包含的標簽體:JspFragment 對象,執行該對象的 invoke() 方法,即可輸出標簽體內容。該標簽的作用是:遍歷指定集合,每遍歷一個集合元素,即輸出標簽體一次。

    因為該標簽的標簽體不為空,配置該標簽時指定 body-content 為 scriptless,該標簽的配置代碼片段如下代碼所示:

    <!-- 定義第三個標簽 -->
    <tag>
        <!-- 定義標簽名 -->
        <name>iterator</name>
        <!-- 定義標簽處理類 -->
        <tag-class>lee.IteratorTag</tag-class>
        <!-- 定義標簽體支持JSP腳本 -->
        <body-content>scriptless</body-content>
        <!-- 配置標簽屬性:collection -->
        <attribute>
            <name>collection</name> 
            <required>true</required>
            <fragment>true</fragment>
        </attribute>
        <!-- 配置標簽屬性:item -->
        <attribute>
            <name>item</name> 
            <required>true</required>
            <fragment>true</fragment>
        </attribute>
    </tag>
    

    上面配置片段中粗體字代碼指定該標簽的標簽體可以是靜態 HTML 內容,也可以是表達式語言。

    為了測試在 JSP 頁面中使用該標簽的效果,我們首先把一個 List 對象設置成 page 范圍的屬性,然后使用該標簽來迭代輸出 List 集合的全部元素。

    JSP 頁面代碼如下:

    <%@ page import="java.util.*"%>
    <%@ page contentType="text/html; charset=GBK"%>
    <!-- 導入標簽庫,指定mytag前綴的標簽,
        由http://www.crazyit.org/mytaglib的標簽庫處理 -->
    <%@ taglib uri="http://www.crazyit.org/mytaglib" prefix="mytag"%>
    <html>
        <head>
            <title>帶標簽體的標簽-迭代器標簽</title>
        </head>
        <body>
            <h2>帶標簽體的標簽-迭代器標簽</h2>
            <hr>
            <%
            //創建一個List對象
            List<String> a = new ArrayList<String>();
            a.add("hello");
            a.add("world");
            a.add("java");
            //將List對象放入page范圍內
            pageContext.setAttribute("a" , a);
            %>
            <table border="1" bgcolor="aaaadd" width="300">
            <!-- 使用迭代器標簽,對a集合進行迭代 -->
            <mytag:iterator collection="a" item="item">
                <tr>
                    <td>${pageScope.item}</td>
                <tr>
            </mytag:iterator>
            </table>
        </body>
    </html>
    

    上面頁面代碼中粗體字代碼即可實現通過 iterator 標簽來遍歷指定集合,瀏覽該頁面即看到如圖 3 所示界面:


    圖 3. 帶標簽體的標簽
    圖 3. 帶標簽體的標簽

    圖 3 顯示了使用 iterator 標簽遍歷集合元素的效果,從 iteratorTag.jsp 頁面的代碼來看,使用 iterator 標簽遍歷集合元素比使用 JSP 腳本遍歷集合元素要優雅得多,這就是自定義標簽的魅力。

    實際上 JSTL 標簽庫提供了一套功能非常強大標簽,例如普通的輸出標簽,像我們剛剛介紹的迭代器標簽,還有用于分支判斷的標簽等等,JSTL(JSP 標準標簽庫)都有非常完善的實現。除此之外,Apache 下還有一套 DisplayTags 的標簽庫實現,做得也非常不錯。
    本文轉自:http://www.ibm.com/developerworks/cn/java/j-lo-jsp2tag/index.html

    posted on 2011-07-14 16:06 雪山飛鵠 閱讀(408) 評論(0)  編輯  收藏 所屬分類: other
    主站蜘蛛池模板: 久久亚洲av无码精品浪潮| 无码不卡亚洲成?人片| 亚洲国产精品久久久久久| caoporm超免费公开视频| 亚洲国产婷婷综合在线精品| 羞羞漫画页面免费入口欢迎你| 亚洲av高清在线观看一区二区| MM1313亚洲国产精品| 一本色道久久88亚洲综合| 免费国产黄网站在线观看动图| 免费观看国产精品| jizz免费在线观看| 亚洲乱码中文字幕久久孕妇黑人| 成人免费乱码大片A毛片| 国产V亚洲V天堂无码久久久| 免费国产午夜高清在线视频| 中文字幕亚洲精品资源网| 亚洲免费黄色网址| 亚洲中文字幕乱码一区| 免费看小12萝裸体视频国产| 国产特黄一级一片免费 | 国产成人精品免费视频大全五级| 亚洲va中文字幕| 久久久亚洲精品蜜桃臀| 色猫咪免费人成网站在线观看| 99久久国产亚洲综合精品| 亚洲最大av无码网址| 久久永久免费人妻精品| 亚洲色图激情文学| 久久久久国产亚洲AV麻豆| 自拍偷自拍亚洲精品情侣| 亚洲精品免费视频| 亚洲熟妇AV一区二区三区浪潮| 免费在线观看你懂的| 在线看片免费人成视频福利| 亚洲专区中文字幕| 亚洲国产婷婷综合在线精品| 日本免费网站视频www区| 男女啪啪免费体验区| 亚洲影院在线观看| 国产一区二区三区在线免费|