Java ---自定義標(biāo)簽

?????本篇文章介紹自定義標(biāo)簽,可能在工作中很少涉及到自己來(lái)定義一個(gè)標(biāo)簽庫(kù)铣卡,因?yàn)槲覀兓旧隙际鞘褂玫拇笊駥?xiě)的標(biāo)簽庫(kù)锉桑,基本上直接使用即可排霉,但是從自身的發(fā)展來(lái)看,通往高級(jí)程序員的道路上民轴,開(kāi)發(fā)框架就需要大量的使用到標(biāo)簽庫(kù)技術(shù)攻柠。本文將從以下幾個(gè)方面介紹自定義標(biāo)簽庫(kù)的基本知識(shí)點(diǎn):

  • 背景以及作用
  • 開(kāi)發(fā)簡(jiǎn)單的標(biāo)簽
  • 開(kāi)發(fā)帶屬性的標(biāo)簽
  • 開(kāi)發(fā)帶標(biāo)簽體的標(biāo)簽
  • 以頁(yè)面片段為屬性的標(biāo)簽
  • 具有動(dòng)態(tài)屬性的標(biāo)簽

一、標(biāo)簽庫(kù)有什么作用
?????自定義標(biāo)簽庫(kù)是一種優(yōu)秀的表現(xiàn)層技術(shù)杉武,之前介紹的MVC模式,我們使用jsp作為表現(xiàn)層辙售,但是jsp語(yǔ)法嵌套在html頁(yè)面轻抱,美工還是很難直接參與開(kāi)發(fā),并且jsp腳本和html代碼耦合在一起旦部,維護(hù)成本較高祈搜。我們能不能開(kāi)發(fā)一套和html風(fēng)格類(lèi)似并且能完成jsp腳本功能的標(biāo)簽來(lái)解決這種低效的協(xié)作方式呢较店?于是標(biāo)簽庫(kù)就誕生了。

這里寫(xiě)圖片描述

這是Java中標(biāo)簽規(guī)范的繼承體系容燕,實(shí)現(xiàn)Tag接口的我們叫做傳統(tǒng)式標(biāo)簽庫(kù)開(kāi)發(fā)梁呈,這種開(kāi)發(fā)模式略顯發(fā)復(fù)雜,基本已經(jīng)被SimpleTag式的簡(jiǎn)單式開(kāi)發(fā)標(biāo)簽庫(kù)給取代了蘸秘。Java中提供了一個(gè)默認(rèn)的實(shí)現(xiàn)類(lèi)SimpleTagSupport來(lái)實(shí)現(xiàn)自定義標(biāo)簽官卡,我們只要繼承此類(lèi)即可。

二醋虏、開(kāi)發(fā)一個(gè)最簡(jiǎn)單的標(biāo)簽庫(kù)
?????開(kāi)發(fā)一個(gè)自定義標(biāo)簽庫(kù)的過(guò)程如下:

  • 開(kāi)發(fā)自定義標(biāo)簽處理類(lèi)
  • 創(chuàng)建*.tld文件寻咒,每個(gè)此文件對(duì)應(yīng)一個(gè)標(biāo)簽庫(kù),標(biāo)簽庫(kù)中可以由多個(gè)標(biāo)簽
  • 在jsp頁(yè)面使用標(biāo)簽

首先我們先從自定義標(biāo)簽處理類(lèi)開(kāi)始颈嚼,正如上文所說(shuō)毛秘,這個(gè)類(lèi)只有繼承了SimpleTagSupport這個(gè)類(lèi)可以省去省去重寫(xiě)SimpleTag接口中的一些方法。我們說(shuō)個(gè)doTag()這個(gè)方法很重要阻课,這個(gè)方法類(lèi)似于我么main方法一樣叫挟,當(dāng)jsp頁(yè)面加載到我們定義的標(biāo)簽的時(shí)候就會(huì)過(guò)來(lái)調(diào)用這個(gè)方法。

public class MyTag extends SimpleTagSupport {

    @Override
    public void doTag() throws JspException, IOException {
        getJspContext().getOut().write("hello walker");
    }
}

這是一個(gè)簡(jiǎn)單的標(biāo)簽處理類(lèi)限煞,具體的細(xì)節(jié)暫時(shí)不用關(guān)心抹恳,只需要知道,它負(fù)責(zé)向jsp頁(yè)面輸出字符串即可晰骑。下面我們看看第二步适秩,創(chuàng)建*tld文件。這個(gè)文件我們沒(méi)有必要重新寫(xiě)一遍硕舆,到Tomcat服務(wù)器上的webapps/examples/WEB-INF/jsp2中復(fù)制一個(gè)過(guò)來(lái)秽荞,修改名字存放到我們的項(xiàng)目中WEB-INF的任意子路徑下。刪除一些標(biāo)簽成如下內(nèi)容:


這里寫(xiě)圖片描述

我們看到這是一個(gè)XML文件抚官,根元素為taglib扬跋,而taglib主要有以下幾個(gè)子元素:

  • description //描述信息
  • tlib-version //指定標(biāo)簽庫(kù)的版本號(hào),基本不用我們操心
  • short-name //指定標(biāo)簽庫(kù)的短名字凌节,也是沒(méi)什么用
  • uri //這是一個(gè)重要的子元素钦听,是該標(biāo)簽庫(kù)的唯一標(biāo)識(shí)
  • tag //看名字就知道,這是定義標(biāo)簽的子元素倍奢,很重要

?????對(duì)于taglib這個(gè)根元素朴上,我們主要關(guān)心他下面的uri和tag兩個(gè)子元素,一個(gè)標(biāo)簽庫(kù)可以由多個(gè)標(biāo)簽卒煞,也就是可以有多個(gè)tag標(biāo)簽痪宰。關(guān)于tag標(biāo)簽,主要有以下幾個(gè)子元素:

  • description //描述信息
  • name //該標(biāo)簽的唯一標(biāo)識(shí),很重要
  • tag-class //指定了處理該標(biāo)簽的類(lèi)衣撬,也就是使用該標(biāo)簽誰(shuí)給我返回結(jié)果
  • body-content //標(biāo)簽體乖订,后面詳說(shuō),很重要
  • attribute //屬性具练,后面介紹乍构,很重要

對(duì)于以上標(biāo)簽大家可能已經(jīng)知道什么意思,但是具體用在什么地方可能不清楚扛点,本小節(jié)的最后會(huì)綜合三個(gè)步驟自定義一個(gè)簡(jiǎn)單的標(biāo)簽哥遮。接下來(lái)介紹在jsp頁(yè)面是如何使用標(biāo)簽。
?????使用標(biāo)簽庫(kù)也是有兩個(gè)步驟占键,首先導(dǎo)入標(biāo)簽庫(kù)昔善,然后引用標(biāo)簽。我們使用taglib編譯指令導(dǎo)入標(biāo)簽庫(kù)畔乙,具體格式如下:

<%@ taglib uri="tld文件中指定的唯一標(biāo)識(shí)" prefix="指定標(biāo)簽前綴"%>

我們看到這個(gè)導(dǎo)入標(biāo)簽庫(kù)的編譯指令主要有兩個(gè)屬性君仆,一個(gè)是用于定位我們已經(jīng)寫(xiě)好的標(biāo)簽庫(kù),定位的方法就是讀取每個(gè)tld文件中的URI元素的值牲距,prefix用于指定我們使用標(biāo)簽時(shí)的前綴返咱,等用的時(shí)候就很容易理解了,現(xiàn)在解釋反而不容易說(shuō)清楚牍鞠。我們使用標(biāo)簽的格式如下:

<剛剛指定的前綴 :標(biāo)簽名 />

標(biāo)簽名就是我們標(biāo)簽庫(kù)中每個(gè)tag都會(huì)有的name的值咖摹,這指定了該語(yǔ)句是引用的那個(gè)標(biāo)簽。下面我們通過(guò)具體的例子直觀(guān)感受下难述。

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib uri="mytid" prefix="mytags"%>
<html>
  <head>
    <title></title>
  </head>
  <body>
    <mytags:hello />
  </body>
</html>
<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>A tag library exercising SimpleTag handlers.</description>
    <tlib-version>1.0</tlib-version>
    <short-name>SimpleTagLibrary</short-name>
    <uri>mytid</uri>

    <tag>
        <description>Outputs a colored tile</description>
        <name>hello</name>
        <tag-class>Test.MyTag</tag-class>
        <body-content>empty</body-content>
    </tag>

</taglib>
public class MyTag extends SimpleTagSupport {

    @Override
    public void doTag() throws JspException, IOException {
        getJspContext().getOut().write("hello walker");
    }
}

結(jié)果如下:


這里寫(xiě)圖片描述

?????這就完成了一個(gè)最簡(jiǎn)單的標(biāo)簽庫(kù)的定義和使用的過(guò)程萤晴,首先我們?cè)趇ndex.jsp頁(yè)面通過(guò)URI引入mytag標(biāo)簽庫(kù),指定了使用該標(biāo)簽庫(kù)的前綴為mytags胁后,然后<mytags:hello />引用name為hello的tag標(biāo)簽店读,然而在加載這條語(yǔ)句的時(shí)候會(huì)通過(guò)我們的tag中指定的處理類(lèi),找到它并執(zhí)行攀芯,最后通過(guò)此標(biāo)簽處理類(lèi)想我們的jsp頁(yè)面輸出了一個(gè)字符串屯断。以上就是一個(gè)最簡(jiǎn)單的自定義標(biāo)簽的過(guò)程,為了更好的理解后續(xù)的較復(fù)雜的自定義標(biāo)簽方式侣诺,上述內(nèi)容值得感受體會(huì)殖演。

三、開(kāi)發(fā)帶屬性的標(biāo)簽
?????假如我們通過(guò)攔截器獲取了從數(shù)據(jù)庫(kù)查出來(lái)的一個(gè)結(jié)果集年鸳,我們此處希望調(diào)用標(biāo)簽來(lái)將結(jié)果集以表格的形式輸出來(lái)趴久,此時(shí)我們的這個(gè)結(jié)果集又該如何傳到標(biāo)簽處理類(lèi)中呢?這時(shí)我們可以使用屬性搔确。具體看代碼:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib uri="mytid" prefix="mytag"%>
<html>
  <head>
    <title></title>
  </head>
  <body>
  <%
    HashMap<String,Integer> maps = new HashMap<String, Integer>();
    maps.put("李四",53);
    maps.put("張三",23);
    maps.put("walker",22);
    pageContext.setAttribute("map",maps);
  %>
      <table>
        <mytag:hello map="map"/>
      </table>
  </body>
</html>
<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>A tag library exercising SimpleTag handlers.</description>
    <tlib-version>1.0</tlib-version>
    <short-name>SimpleTagLibrary</short-name>
    <uri>mytid</uri>

    <tag>
        <description>Outputs a colored tile</description>
        <name>hello</name>
        <tag-class>Test.MyTag</tag-class>
        <body-content>empty</body-content>
        <attribute>
            <name>map</name>
            <required>true</required>
            <fragment>true</fragment>
        </attribute>
    </tag>

</taglib>
public class MyTag extends SimpleTagSupport {

    private String map;
    public String getMap(){
        return this.map;
    }
    public void setMap(String map){
        this.map = map;
    }
    @Override
    public void doTag() throws JspException, IOException {
        HashMap<String,Integer> maps = (HashMap<String,Integer>)(getJspContext().getAttribute(map));
        Object[] array = maps.keySet().toArray();

        for (String str : maps.keySet()){
            getJspContext().getOut().write("<tr>");
            getJspContext().getOut().write("<td>");
            getJspContext().getOut().write(str);
            getJspContext().getOut().write("</td>");
            getJspContext().getOut().write("<td>");
            getJspContext().getOut().write(""+maps.get(str));
            getJspContext().getOut().write("</td>");
            getJspContext().getOut().write("</tr>");
        }
    }
}
這里寫(xiě)圖片描述

我們首先先從index.jsp頁(yè)面看起彼棍,首先我們定義了一個(gè)HashMap用來(lái)存放一個(gè)簡(jiǎn)單的個(gè)人信息已添,鍵為姓名值為年齡。最后我們?cè)O(shè)置共享范圍為當(dāng)前page滥酥。然后<mytag:hello map="map"/>,這里的map=“map”畦幢,第一個(gè)map是屬性名坎吻,第二個(gè)只是一個(gè)字符串。下面進(jìn)入到tld頁(yè)面看宇葱,這個(gè)頁(yè)面基本沒(méi)有什么改動(dòng)瘦真,只是多了個(gè)attribute元素,attribute中有幾個(gè)子元素黍瞧,第一個(gè)是name指定這個(gè)屬性的唯一標(biāo)識(shí)诸尽,第二個(gè)required指定該屬性是否是必須屬性。第三個(gè)fragment指定該屬性是否支持jsp腳本印颤。主要關(guān)心name這個(gè)元素您机。這個(gè)值和jsp頁(yè)面調(diào)用標(biāo)簽時(shí)使用的屬性名必須一樣,并且這個(gè)屬性值還必須和標(biāo)簽處理類(lèi)中的私有屬性名一樣年局,這就是為了jsp頁(yè)面的屬性值能夠自動(dòng)的傳入到標(biāo)簽處理類(lèi)的屬性中际看,我們看這個(gè)標(biāo)簽處理類(lèi)
?????這個(gè)類(lèi)定義了私有屬性map,和我們的tld文件中的屬性名是一致的矢否。getJspContext().getAttribute(map)仲闽,首先是獲得了調(diào)用該標(biāo)簽的jsp頁(yè)面的pageContext,這就是方法getJspContext的返回值僵朗,因?yàn)槲覀冊(cè)趈sp頁(yè)面設(shè)置了一個(gè)共享數(shù)據(jù)(maps)赖欣,于是我們同名名字獲取該對(duì)象,這里的map就是我們的私有屬性验庙,他的值被自動(dòng)賦值了顶吮,具體的值就是jsp頁(yè)面?zhèn)魅氲膮?shù)。后面的代碼就很簡(jiǎn)單了壶谒,循環(huán)輸出數(shù)據(jù)到j(luò)sp頁(yè)面上云矫。
?????稍微理一下思路,這種帶屬性的標(biāo)簽使用其實(shí)和無(wú)屬性差不多汗菜,都是先引入了標(biāo)簽庫(kù)让禀,加載標(biāo)簽的的時(shí)候通過(guò)URI找到對(duì)應(yīng)的標(biāo)簽庫(kù),只不過(guò)這次將一個(gè)字符串賦值給了tld中attribute元素中名為map的屬性陨界,然后跳向?qū)?yīng)的標(biāo)簽處理類(lèi)巡揍,順便把map屬性的值自動(dòng)賦值處理類(lèi)中的私有屬性,然后執(zhí)行輸出代碼菌瘪。其中需要注意的是屬性名一定要統(tǒng)一腮敌,另外阱当,如果標(biāo)簽的屬性值是8種基本數(shù)據(jù)類(lèi)型,那么在JSP頁(yè)面在傳遞字符串時(shí)糜工,JSP引擎會(huì)自動(dòng)轉(zhuǎn)換成相應(yīng)的類(lèi)型弊添,但如果標(biāo)簽的屬性值是復(fù)合數(shù)據(jù)類(lèi)型,那么JSP引擎是無(wú)法自動(dòng)轉(zhuǎn)換的捌木。對(duì)于傳遞非基本數(shù)據(jù)類(lèi)型的操作油坝,后續(xù)文章會(huì)介紹。

?????為了篇幅不過(guò)于長(zhǎng)刨裆,還剩下的內(nèi)容留在下篇澈圈,如有錯(cuò)誤,望指出帆啃!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末瞬女,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子努潘,更是在濱河造成了極大的恐慌诽偷,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,744評(píng)論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件疯坤,死亡現(xiàn)場(chǎng)離奇詭異渤刃,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)贴膘,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,505評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén)卖子,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人刑峡,你說(shuō)我怎么就攤上這事洋闽。” “怎么了突梦?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,105評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵诫舅,是天一觀(guān)的道長(zhǎng)。 經(jīng)常有香客問(wèn)我宫患,道長(zhǎng)刊懈,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,242評(píng)論 1 292
  • 正文 為了忘掉前任娃闲,我火速辦了婚禮虚汛,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘皇帮。我一直安慰自己卷哩,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,269評(píng)論 6 389
  • 文/花漫 我一把揭開(kāi)白布属拾。 她就那樣靜靜地躺著将谊,像睡著了一般冷溶。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上尊浓,一...
    開(kāi)封第一講書(shū)人閱讀 51,215評(píng)論 1 299
  • 那天逞频,我揣著相機(jī)與錄音,去河邊找鬼栋齿。 笑死虏劲,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的褒颈。 我是一名探鬼主播,決...
    沈念sama閱讀 40,096評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼励堡,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼谷丸!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起应结,我...
    開(kāi)封第一講書(shū)人閱讀 38,939評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤刨疼,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后鹅龄,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體揩慕,經(jīng)...
    沈念sama閱讀 45,354評(píng)論 1 311
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,573評(píng)論 2 333
  • 正文 我和宋清朗相戀三年扮休,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了迎卤。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,745評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡玷坠,死狀恐怖蜗搔,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情八堡,我是刑警寧澤樟凄,帶...
    沈念sama閱讀 35,448評(píng)論 5 344
  • 正文 年R本政府宣布,位于F島的核電站兄渺,受9級(jí)特大地震影響缝龄,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜挂谍,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,048評(píng)論 3 327
  • 文/蒙蒙 一叔壤、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧口叙,春花似錦百新、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,683評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)仗哨。三九已至,卻和暖如春铅辞,著一層夾襖步出監(jiān)牢的瞬間厌漂,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,838評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工斟珊, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留苇倡,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,776評(píng)論 2 369
  • 正文 我出身青樓囤踩,卻偏偏與公主長(zhǎng)得像旨椒,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子堵漱,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,652評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • 上篇文章的最后综慎,我們自定義了一個(gè)帶屬性的標(biāo)簽,并使用它完成了一個(gè)簡(jiǎn)單的案例勤庐。其實(shí)到這我們已經(jīng)可以看出來(lái)示惊,前端jsp...
    Single_YAM閱讀 418評(píng)論 0 1
  • 一、 自定義標(biāo)簽簡(jiǎn)介 自定義標(biāo)簽主要用于移除jsp頁(yè)面中的java代碼愉镰。工程(tag) 使用自定義標(biāo)簽移除jsp頁(yè)...
    yjaal閱讀 800評(píng)論 1 4
  • 1什么是JSTLJSTL是apache對(duì)EL表達(dá)式的擴(kuò)展(也就是說(shuō)JSTL依賴(lài)EL)米罚,JSTL是標(biāo)簽語(yǔ)言!JSTL...
    TY_閱讀 373評(píng)論 0 1
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語(yǔ)法丈探,類(lèi)相關(guān)的語(yǔ)法录择,內(nèi)部類(lèi)的語(yǔ)法,繼承相關(guān)的語(yǔ)法碗降,異常的語(yǔ)法糊肠,線(xiàn)程的語(yǔ)...
    子非魚(yú)_t_閱讀 31,624評(píng)論 18 399
  • 學(xué)業(yè)工作 最重要:4月中旬答辯 很重要:畢業(yè)前學(xué)會(huì)橋梁抗震的基本理論和Midas的計(jì)算方法 重要:報(bào)到前熟悉一遍橋...
    橋梁狗的日常閱讀 221評(píng)論 0 2