14.自定義標(biāo)簽庫開發(fā)(我的JavaEE筆記)

一勇婴、 自定義標(biāo)簽簡介

自定義標(biāo)簽主要用于移除jsp頁面中的java代碼仔引。工程tag

使用自定義標(biāo)簽移除jsp頁面中的java代碼傍菇,只需要完成以下兩個(gè)步驟:
1.編寫一個(gè)實(shí)現(xiàn)tag接口的java類(標(biāo)簽處理類)台谊。
2.編寫標(biāo)簽庫描述符(tld)文件爹殊,在tld文件中對標(biāo)簽處理器類進(jìn)行描述粗仓。

二毅该、快速入門:使用標(biāo)簽輸出客戶機(jī)IP

這里我們先編寫一個(gè)tld文件(itcast.tld):

<?xml version="1.0" encoding="UTF-8"?>
<taglib version="2.1" xmlns="http://java.sun.com/xml/ns/javaee"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
        xsi:schemaLocation="http://java.sun.com/xml/ns/javaee web-jsptaglibrary_2_1.xsd">
    <tlib-version>1.0</tlib-version>
    <short-name>itcast</short-name><!-- tld文件名字 -->
    <uri>/itcast</uri><!-- 因?yàn)槲募欠旁赪EB-INF下面 -->
    <tag>
        <name>viewIP</name><!-- 給標(biāo)簽起名 -->
        <tag-class>cn.itcast.web.tag.ViewIPTag</tag-class><!-- 類的完整類名 -->
        <body-content>empty</body-content><!-- 這里是操作標(biāo)簽體,如果不用潦牛,則使用empty -->
    </tag>
</taglib>

注意:標(biāo)簽<body-content>為empty表示標(biāo)簽起始和結(jié)束之間沒有內(nèi)容眶掌。如<a ..../>,而不能是<a>...</a>巴碗。
說明:我們可以在MyEclipse中直接新建tld文件朴爬,然后填入相應(yīng)的信息:

tld.png

其中Name是文件名,Version我們選擇最高版本橡淆,Shortname一般填入文件名召噩,由于文件放在WEB-INF 下面,所以u(píng)ri地址是/itcast逸爵。

實(shí)現(xiàn)類(ViewIPTag.java)

package cn.itcast.web.tag;
import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.Tag;
//自定義標(biāo)簽類具滴,注意繼承Tag接口
public class ViewIPTag implements Tag {
    
    private PageContext pageContext;//用于保存頁面對象
    
    @Override
    public int doStartTag() throws JspException {
        HttpServletRequest request = (HttpServletRequest) pageContext.getRequest();
        //得到out隱式對象,用于輸出
        JspWriter out = pageContext.getOut();
        //得到服務(wù)器地址
        String ip = request.getRemoteAddr();
        try {
            out.write(ip);
        } catch (IOException e) {
            //這里子類不能拋出比父類還多的異常
            throw new RuntimeException(e);
        }
        return 0;
    }
    
    @Override
    public void setPageContext(PageContext arg0) {
        this.pageContext = arg0;
    }
    
    @Override
    public int doEndTag() throws JspException {
        return 0;
    }
    @Override
    public Tag getParent() {
        return null;
    }
    @Override
    public void release() {}
    @Override
    public void setParent(Tag arg0) {}
}

使用(1.jsp)

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib uri="/itcast" prefix="itcast"%><!-- 和之前使用EL標(biāo)簽一樣师倔,需要導(dǎo)入 -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>客戶機(jī)IP</title>
  </head>
  <body>
    您的IP是:<itcast:viewIP/>
    <%
        /* 等同于 */
        String ip = request.getRemoteAddr();
        out.write(ip);
     %>
  </body>
</html>

三构韵、標(biāo)簽的執(zhí)行過程

jsp引擎遇到自定義標(biāo)簽時(shí),首先創(chuàng)建標(biāo)簽處理類的實(shí)例對象趋艘,然后按照jsp規(guī)范定義的通信規(guī)則依次調(diào)用它的方法疲恢。

1.jsp引擎實(shí)例化標(biāo)簽處理類之后,將調(diào)用setPageContext方法將jsp頁面的pageContext對象傳遞給標(biāo)簽處理器瓷胧,標(biāo)簽處理器以后可以通過這個(gè)pageContext對象與jsp頁面進(jìn)行通信显拳。

2.setPageContext方法執(zhí)行完后,web容器接著調(diào)用setParent方法將當(dāng)前標(biāo)簽的父標(biāo)簽傳遞給當(dāng)前標(biāo)簽處理器搓萧,如果當(dāng)前標(biāo)簽沒有父標(biāo)簽杂数,則傳遞給setParent方法的參數(shù)值為null。

3.調(diào)用了setPageContext方法和setParent方法之后瘸洛,web容器執(zhí)行到自定義標(biāo)簽的開始標(biāo)簽時(shí)揍移,就會(huì)調(diào)用標(biāo)簽處理器的doStartTag方法。

4.web容器執(zhí)行完自定義標(biāo)簽的標(biāo)簽體之后货矮,就會(huì)接著去執(zhí)行自定義標(biāo)簽的結(jié)束標(biāo)簽羊精,此時(shí),web容器就會(huì)調(diào)用doEndTag方法。

5.通常web容器執(zhí)行完自定義標(biāo)簽后喧锦,標(biāo)簽處理器會(huì)駐留在內(nèi)存中读规,為其它請求服務(wù),直至停止web應(yīng)用時(shí)燃少,web容器才會(huì)調(diào)用release方法束亏。

自定義標(biāo)簽功能擴(kuò)展

開發(fā)人員在編寫jsp頁面時(shí),經(jīng)常還需要在頁面中引入一些邏輯阵具。例如:
(1)控制jsp頁面某一部分內(nèi)容是否執(zhí)行
(2)控制整個(gè)jsp頁面是否執(zhí)行
(3)控制jsp頁面內(nèi)容重復(fù)執(zhí)行
(4)修改jsp頁面內(nèi)容輸出

自定義標(biāo)簽除了可以移除jsp頁面的java代碼碍遍,也可以實(shí)現(xiàn)以上功能。

例:控制jsp頁面某一部分內(nèi)容是否執(zhí)行
TagDemo1.java

package cn.itcast.web.tag;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.Tag;
import javax.servlet.jsp.tagext.TagSupport;;
public class TagDemo1 extends TagSupport {

    @Override
    public int doStartTag() throws JspException {
        //return Tag.EVAL_BODY_INCLUDE;//返回此常量則會(huì)執(zhí)行標(biāo)簽體
        return Tag.SKIP_BODY;//如果要跳過標(biāo)簽體阳液,則使用此常量
        
    }
}

itcast.tld中

<tag>
  <name>demo1</name>
  <tag-class>cn.itcast.web.tag.TagDemo1</tag-class>
  <body-content>JSP</body-content>
</tag>

注意:此處<body-content>為JSP怕敬,必須是大寫,表示標(biāo)簽之間有內(nèi)容帘皿。內(nèi)容接受所遇jsp語法东跪,當(dāng)然這里我們只是表示標(biāo)簽之間有內(nèi)容,而內(nèi)容執(zhí)行不執(zhí)行依據(jù)所定義的類鹰溜。當(dāng)然還可以是tagdependent和scriptless虽填,但用的不多,此處不再詳述曹动。

注意:此處我們繼承的是TagSupport類斋日,因?yàn)槊看卫^承Tag接口需要實(shí)現(xiàn)很多用不到的方法,于是這里我們繼承此默認(rèn)實(shí)現(xiàn)類可以簡便一些墓陈。關(guān)于Tag接口的繼承關(guān)系如下圖:

JspTag接口.JPG

使用(2.jsp)

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib uri="/itcast" prefix="itcast"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>控制jsp頁面某一部分內(nèi)容是否執(zhí)行</title>
  </head>
  <body>
    <itcast:demo1>
        xxx
    </itcast:demo1>
  </body>
</html>

使用這個(gè)標(biāo)簽就表示xxx不會(huì)被執(zhí)行恶守。當(dāng)然具體怎樣控制我們可以在類中進(jìn)行細(xì)化。

例:控制整個(gè)jsp頁面是否執(zhí)行
itcast.tld

    <tag>
        <name>demo2</name>
        <tag-class>cn.itcast.web.tag.TagDemo2</tag-class>
        <body-content>empty</body-content>
    </tag>

TagDemo2.java

package cn.itcast.web.tag;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.Tag;
import javax.servlet.jsp.tagext.TagSupport;
public class TagDemo2 extends TagSupport {

    @Override
    public int doEndTag() throws JspException {
        return Tag.SKIP_PAGE;//此常量表示結(jié)束標(biāo)簽后買年余下的jsp頁面不會(huì)執(zhí)行
        //return Tag.EVAL_PAGE;//此常量表示會(huì)執(zhí)行
    }
    
}

3.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib uri="/itcast" prefix="itcast"%>

<itcast:demo2/><!-- 即控制結(jié)束標(biāo)簽后面的jsp內(nèi)容是否執(zhí)行 -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>控制整個(gè)jsp頁面是否執(zhí)行</title>
  </head>
  <body>
    
  </body>
</html>

例:控制jsp頁面內(nèi)容重復(fù)執(zhí)行
itcast.tld

    <tag>
        <name>demo3</name>
        <tag-class>cn.itcast.web.tag.TagDemo3</tag-class>
        <body-content>JSP</body-content>
    </tag>

TagDemo3

package cn.itcast.web.tag;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.IterationTag;
import javax.servlet.jsp.tagext.Tag;
import javax.servlet.jsp.tagext.TagSupport;
public class TagDemo3 extends TagSupport {
    
    int x = 5;
    
    @Override
    public int doAfterBody() throws JspException {
        x--;
        //注意:控制標(biāo)簽體重復(fù)執(zhí)行的時(shí)候需要的常量需要的不是Tag常量跛蛋,而是IterationTag常量
        if(x > 0){
            return IterationTag.EVAL_BODY_AGAIN;
        }else{
            return IterationTag.SKIP_BODY;
        }
    }

    @Override
    public int doStartTag() throws JspException {
        //注意:要想重復(fù)執(zhí)行熬的,則首先要讓標(biāo)簽體執(zhí)行才行
        return Tag.EVAL_BODY_INCLUDE;
    }   
}

itcast.tld

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib uri="/itcast" prefix="itcast"%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>控制頁面重復(fù)執(zhí)行</title>
  </head>
  <body>
    <itcast:demo3>
        這里的頁面內(nèi)容將重復(fù)執(zhí)行
    </itcast:demo3>
  </body>
</html>

例:修改jsp頁面內(nèi)容輸出
itcast.tld

    <tag>
        <name>demo4</name>
        <tag-class>cn.itcast.web.tag.TagDemo4</tag-class>
        <body-content>JSP</body-content>
    </tag>

TagDemo4

package cn.itcast.web.tag;
import java.io.IOException;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.BodyTag;
import javax.servlet.jsp.tagext.BodyTagSupport;
import javax.servlet.jsp.tagext.Tag;
public class TagDemo4 extends BodyTagSupport {

    @Override
    public int doEndTag() throws JspException {
        //得到標(biāo)簽體內(nèi)容字符串
        String content = this.getBodyContent().getString();
        //將標(biāo)簽體內(nèi)容改為大寫
        String result = content.toUpperCase();
        //得到out輸入對象
        try {
            this.pageContext.getOut().write(result);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return Tag.EVAL_PAGE;//表示標(biāo)簽體余下的內(nèi)容還要輸出
    }

    @Override
    public int doStartTag() throws JspException {
        //要想修改標(biāo)簽體,則下面必須返回此常量
        return BodyTag.EVAL_BODY_BUFFERED;
    }   
}

5.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib uri="/itcast" prefix="itcast"%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>修改標(biāo)簽體內(nèi)容</title>
  </head>
  <body>
    <itcast:demo4>
        aaa
    </itcast:demo4>
  </body>
</html>

得到的輸出結(jié)果是AAA赊级。
最后,其實(shí)上面是一種很傳統(tǒng)的方式岔绸,使用起來并不方便理逊,一般我們很少使用。

四盒揉、簡單標(biāo)簽

由于傳統(tǒng)標(biāo)簽使用三個(gè)標(biāo)簽接口來完成不同的功能晋被,顯得過于繁瑣,不利于標(biāo)簽技術(shù)的推廣刚盈,sun公司為降低標(biāo)簽技術(shù)的學(xué)習(xí)難度羡洛,在jsp2.0中定義了一個(gè)更為簡單、便于編寫和調(diào)用的SimpleTag接口來實(shí)現(xiàn)標(biāo)簽的功能藕漱。實(shí)現(xiàn)SimpleTag接口的標(biāo)簽通常稱為簡單標(biāo)簽欲侮。簡單標(biāo)簽定義了5個(gè)方法:

  • setJspContext方法:用于把jsp頁面的pageContext對象傳遞給標(biāo)簽處理器對象崭闲;
  • setParentgetParent方法:前者用于把父標(biāo)簽處理器對象傳遞給當(dāng)前處理器對象。后者用于獲得當(dāng)前標(biāo)簽的父標(biāo)簽處理器對象威蕉。
  • setJspBody:用于把代表標(biāo)簽體的JspFragment對象傳遞給標(biāo)簽處理器對象刁俭。
  • doTag方法:用于完成所有的標(biāo)簽邏輯,包括輸出韧涨、迭代牍戚、修改標(biāo)簽體內(nèi)容等。在doTag方法中可以拋出javax.servlet.jsp.SkipPageException異常虑粥,用于通知web容器不再執(zhí)行jsp頁面中位于結(jié)束標(biāo)記后面的內(nèi)容如孝,這等效于在傳統(tǒng)標(biāo)簽的doEndTag方法中返回Tag.SKIP_PAGE的情況。

1.SimpleTag接口方法的執(zhí)行順序

(1)當(dāng)web容器準(zhǔn)備開始執(zhí)行標(biāo)簽時(shí)娩贷,會(huì)調(diào)用如下方法完成標(biāo)簽的初始化:

  • 1.web容器調(diào)用標(biāo)簽處理器對象的setJspContext方法暑竟,將代表jsp頁面的pageContext對象傳遞給標(biāo)簽處理器對象。
  • 2.web容器調(diào)用標(biāo)簽處理器對象的setParent方法育勺,將父標(biāo)簽處理器對象傳遞給這個(gè)標(biāo)簽處理器對象但荤。注意:只有在標(biāo)簽存在父標(biāo)簽的情況下,web容器才會(huì)調(diào)用此方法涧至。
  • 3.如果調(diào)用標(biāo)簽時(shí)設(shè)置了屬性腹躁,容器將調(diào)用每個(gè)屬性對應(yīng)的setter方法把屬性值傳遞給標(biāo)簽處理器對象。如果標(biāo)簽的屬性值是EL表達(dá)式或腳本表達(dá)式南蓬,則web容器首先計(jì)算表達(dá)式的值纺非,然后把值傳遞給標(biāo)簽處理器對象。
  • 4.如果簡單標(biāo)簽有標(biāo)簽體赘方,容器將調(diào)用setJspBody方法把代表標(biāo)簽體的JspFragment對象傳遞進(jìn)來烧颖。

(2)執(zhí)行標(biāo)簽時(shí):
容器調(diào)用標(biāo)簽處理器的doTag方法,開發(fā)人員在方法體內(nèi)通過操作JspFragment對象窄陡,就可以實(shí)現(xiàn)是否執(zhí)行炕淮、迭代、修改標(biāo)簽體的目的跳夭。當(dāng)然是先得到此對象涂圆。

2.JspFragment類

  • javax.servlet.jsp.tagext.JspFragment類是jsp2.0中定義的,它的實(shí)例對象代表jsp頁面中的一段符合jsp語法規(guī)范的jsp片段币叹,這段jsp片段中不能包含jsp腳本元素润歉。

  • web容器在處理簡單標(biāo)簽的標(biāo)簽體時(shí),會(huì)把標(biāo)簽體內(nèi)容用一個(gè)JspFragment對象表示颈抚,并調(diào)用標(biāo)簽處理對象的setJspBody方法把JspFragment對象傳遞給標(biāo)簽處理器對象踩衩。JspFragment類中定義了兩個(gè)方法,如下所示:
    getJspContext方法:用于返回代表調(diào)用頁面的JspContext對象。
    invoke方法:用于執(zhí)行JspFragment對象所代表的jsp代碼片段驱富;參數(shù)out用于指定將JspFragment對象的執(zhí)行結(jié)果寫入到哪個(gè)輸出流對象中锚赤,如果傳遞給參數(shù)out值為null,則將執(zhí)行結(jié)果寫入到JspContext.getOut方法返回的輸出流對象中萌朱。(即寫給瀏覽器)宴树。

3.invoke方法詳解

JspFragment.invoke方法是JspFragment最重要的方法,利用這個(gè)方法可以控制是否執(zhí)行和輸出標(biāo)簽體的內(nèi)容晶疼、是否迭代執(zhí)行標(biāo)簽體的內(nèi)容或?qū)?biāo)簽體的執(zhí)行結(jié)果進(jìn)行修改后再輸出酒贬。例如:

  • 1.在標(biāo)簽處理器中如果沒有調(diào)用JspFragment.invoke方法,其結(jié)果就相當(dāng)于忽略標(biāo)簽體的內(nèi)容翠霍;
  • 2.在標(biāo)簽處理器中重復(fù)調(diào)用JspFragment.invoke方法锭吨,則標(biāo)簽體內(nèi)容將會(huì)別重復(fù)執(zhí)行;
  • 3.若想在標(biāo)簽處理器中修改標(biāo)簽體內(nèi)容寒匙,只需在調(diào)用invoke方法時(shí)指定一個(gè)可取出結(jié)果數(shù)據(jù)的輸出流對象(StringWriter)零如,讓標(biāo)簽體的執(zhí)行結(jié)果輸出到該輸出流對象中,然后從該輸出流對象中取出數(shù)據(jù)進(jìn)行修改后再輸出到目標(biāo)設(shè)備锄弱,即可達(dá)到修改標(biāo)簽體的目的考蕾。

4.使用簡單標(biāo)簽實(shí)現(xiàn)之前傳統(tǒng)標(biāo)簽完成的例子

例:使用簡單標(biāo)簽實(shí)現(xiàn)控制標(biāo)簽體是否執(zhí)行
WebRoot/WEB-INF/simpletag.tld

<?xml version="1.0" encoding="UTF-8"?>
<taglib version="2.1" xmlns="http://java.sun.com/xml/ns/javaee"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee web-jsptaglibrary_2_1.xsd">
 <tlib-version>1.0</tlib-version>
 <short-name>simpleitcast</short-name>
 <uri>/simpleitcast</uri>
 
    <tag>
        <name>demo1</name>
        <tag-class>cn.itcast.web.simpletag.SimpleTagDemo1</tag-class>
        <!-- 這里注意:在簡單標(biāo)簽中不允許使用JSP,因?yàn)樾掳娴臉?biāo)簽技術(shù)不允許在標(biāo)簽體中使用
        腳本代碼会宪,比如<%%>這樣的肖卧,scriptless表示無腳本 -->
        <body-content>scriptless</body-content>
    </tag>
</taglib>

SimpleTagDemo1

package cn.itcast.web.simpletag;
import java.io.IOException;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.JspFragment;
import javax.servlet.jsp.tagext.SimpleTagSupport;
//使用簡單標(biāo)簽控制標(biāo)簽體是否執(zhí)行
public class SimpleTagDemo1 extends SimpleTagSupport {
    //簡單標(biāo)簽使用此方法完成所有的業(yè)務(wù)邏輯
    @Override
    public void doTag() throws JspException, IOException {
        //得到JspFragment對象,即得到一段jsp片段
        JspFragment jf = this.getJspBody();
        //得到pageContext對象
        PageContext pageContext = (PageContext) this.getJspContext();
        jf.invoke(pageContext.getOut());
        //jf.invoke(null);//此行代碼表示默認(rèn)執(zhí)行上面兩行代碼掸鹅,表示默認(rèn)傳遞給瀏覽器
    }   
}

WebRoot/simpletag/1.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib uri="/simpleitcast" prefix="itcast"%><!-- 這里我們前綴還是使用itcast -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>使用簡單標(biāo)簽實(shí)現(xiàn)控制標(biāo)簽體是否執(zhí)行</title>
  </head>
  <body>
    <itcast:demo1>
    xxxx
    </itcast:demo1>
  </body>
</html>

這里我們是允許標(biāo)簽體中的內(nèi)容進(jìn)行輸出執(zhí)行塞帐。輸出xxxx。當(dāng)然如果我們不想讓標(biāo)簽體執(zhí)行巍沙,那就不寫

PageContext pageContext = (PageContext) this.getJspContext();
jf.invoke(pageContext.getOut());

或不寫jf.invoke(null);葵姥。

例:控制標(biāo)簽體重復(fù)執(zhí)行
simpletag.tld

    <tag>
        <name>demo2</name>
        <tag-class>cn.itcast.web.simpletag.SimpleTagDemo2</tag-class>
        <body-content>scriptless</body-content>
    </tag>

SimpleTagDemo2

package cn.itcast.web.simpletag;
import java.io.IOException;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.JspFragment;
import javax.servlet.jsp.tagext.SimpleTagSupport;
//控制標(biāo)簽體重復(fù)執(zhí)行多次
public class SimpleTagDemo2 extends SimpleTagSupport{

    @Override
    public void doTag() throws JspException, IOException {
        JspFragment jf = this.getJspBody();
        for(int i = 0; i < 10; i++){
            jf.invoke(null);
        }
    }
}

2.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib uri="/simpleitcast" prefix="itcast"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>控制標(biāo)簽體重復(fù)執(zhí)行多次</title>
  </head>
  <body>
    <itcast:demo2>
    xxxx
    </itcast:demo2>
  </body>
</html>

例:修改標(biāo)簽體中的內(nèi)容
simpletag.tld

    <tag>
        <name>demo3</name>
        <tag-class>cn.itcast.web.simpletag.SimpleTagDemo3</tag-class>
        <body-content>scriptless</body-content>
    </tag>

SimpleTagDemo3

package cn.itcast.web.simpletag;
import java.io.IOException;
import java.io.StringWriter;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.JspFragment;
import javax.servlet.jsp.tagext.SimpleTagSupport;
//修改標(biāo)簽體中的內(nèi)容
public class SimpleTagDemo3 extends SimpleTagSupport{

    @Override
    public void doTag() throws JspException, IOException {
        JspFragment jf = this.getJspBody();
        StringWriter sw = new StringWriter();//得到一個(gè)輸出流
        jf.invoke(sw);//注意:要想修改標(biāo)簽體內(nèi)容個(gè)必須先執(zhí)行標(biāo)簽體
        //得到標(biāo)簽體內(nèi)容
        String content = sw.getBuffer().toString();
        content = content.toUpperCase();//將標(biāo)簽體中的字符串變?yōu)榇髮?        
        PageContext pageContext = (PageContext) this.getJspContext();
        pageContext.getOut().write(content);//輸出
        
    }
}

3.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib uri="/simpleitcast" prefix="itcast"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>使用簡單標(biāo)簽修改標(biāo)簽體內(nèi)容</title>
  </head>
  <body>
    <itcast:demo3>
    aaa
    </itcast:demo3>
  </body>
</html>

說明:這里執(zhí)行是先讓標(biāo)簽體執(zhí)行,然后讓內(nèi)容輸出到我們自己定義的一個(gè)流中句携,然后我們從流中拿到數(shù)據(jù)榔幸,修改之后再輸出給瀏覽器。

例:控制余下jsp頁面是否執(zhí)行
simpletag.tld

    <tag>
        <name>demo4</name>
        <tag-class>cn.itcast.web.simpletag.SimpleTagDemo4</tag-class>
        <body-content>scriptless</body-content>
    </tag>

SimpleTagDemo4

package cn.itcast.web.simpletag;
import java.io.IOException;
import java.io.StringWriter;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.SkipPageException;
import javax.servlet.jsp.tagext.JspFragment;
import javax.servlet.jsp.tagext.SimpleTagSupport;
//控制標(biāo)簽體之后余下頁面是否執(zhí)行
public class SimpleTagDemo4 extends SimpleTagSupport{

    @Override
    public void doTag() throws JspException, IOException {
        //只要此方法拋出這個(gè)異常务甥,那么余下的頁面將不會(huì)執(zhí)行
        throw new SkipPageException();
    }
}

4.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib uri="/simpleitcast" prefix="itcast"%>
<itcast:demo4/>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>控制余下標(biāo)簽體不再執(zhí)行</title>
  </head>
  <body>
    aaa
  </body>
</html>

可以看到此功能很容易實(shí)現(xiàn)牡辽。

5.開發(fā)帶屬性的標(biāo)簽

  • 要想讓一個(gè)自定義標(biāo)簽具有屬性,通常要完成兩個(gè)任務(wù):
    在標(biāo)簽處理器中編寫每個(gè)屬性對應(yīng)的setter方法
    在tld文件中描述標(biāo)簽的屬性
  • 為自定義標(biāo)簽定義屬性時(shí)敞临,每個(gè)屬性都必須按照javaBean的屬性命名方式,在標(biāo)簽處理器中定義屬性名對應(yīng)的setter方法麸澜,用來接收jsp頁面調(diào)用自定義標(biāo)簽時(shí)傳遞進(jìn)來的屬性值挺尿。例如,屬性u(píng)rl,在標(biāo)簽處理器類中就要定義相應(yīng)的setUrl(String url)方法编矾。
  • 在標(biāo)簽處理器中定義相應(yīng)的set方法后熟史,jsp引擎在解析執(zhí)行開始標(biāo)簽前,也就是調(diào)用doStartTag方法前窄俏,會(huì)調(diào)用set屬性方法為標(biāo)簽設(shè)置屬性蹂匹。

例:通過屬性控制標(biāo)簽體執(zhí)行的次數(shù)
simpletag.tld

    <tag>
        <name>demo5</name>
        <tag-class>cn.itcast.web.simpletag.SimpleTagDemo5</tag-class>
        <body-content>scriptless</body-content>
        <attribute>
            <name>count</name>
            <required>true</required><!-- 這表示此屬性是必須的 -->
            <!-- 此屬性是否是一個(gè)運(yùn)行時(shí)表達(dá)式,若為false則只能是靜態(tài)的值凹蜈,一般都是true -->
            <rtexprvalue>true</rtexprvalue>
            <type>java.lang.Integer</type><!-- 這個(gè)屬性是規(guī)定參數(shù)的java屬性限寞,如果不正確則報(bào)錯(cuò) -->
        </attribute>
    </tag>

SimpleTagDemo5

package cn.itcast.web.simpletag;
import java.io.IOException;
import java.io.StringWriter;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.SkipPageException;
import javax.servlet.jsp.tagext.JspFragment;
import javax.servlet.jsp.tagext.SimpleTagSupport;
//通過屬性控制標(biāo)簽體的執(zhí)行
public class SimpleTagDemo5 extends SimpleTagSupport{
    //這里注意:我們頂一個(gè)的是一個(gè)int類型的,但是標(biāo)簽中我們使用的是字符串類型仰坦,
    //這里引擎幫我們進(jìn)行了轉(zhuǎn)換履植,但是只支持八種基本類型的轉(zhuǎn)換
    private int count;
    public void setCount(int count ){
        this.count = count;
    }

    @Override
    public void doTag() throws JspException, IOException {
        for(int i = 0; i < count; i++){
            this.getJspBody().invoke(null);
        }
    }
}

5.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib uri="/simpleitcast" prefix="itcast"%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>通過屬性控制標(biāo)簽體執(zhí)行次數(shù)</title>
  </head>
  <body>
    <!-- 如果在配置文件中rtexprvalue為true,則這里可以是一個(gè)表達(dá)式 -->
    <itcast:demo5 count="5">
    xxx
    </itcast:demo5>
  </body>
</html>

**注意:引擎只能轉(zhuǎn)換八種基本類型數(shù)據(jù)悄晃,而不能轉(zhuǎn)換復(fù)雜類型數(shù)據(jù)玫霎,如日期類型。但入股我們一定要傳入復(fù)雜類型的話一般有兩種方式:

      <%
        Data date = new Date();
        request.setAttribute("date", date);
     %>
     <itcast:demo6 date="${date}">
     xxx
     </itcast:demo6>

或者:

    <itcast:demo6 date="<%=date %>">
    xxx
    </itcast:demo6>

最后我們給出屬性配置中的一些標(biāo)簽:

1.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末妈橄,一起剝皮案震驚了整個(gè)濱河市庶近,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌眷蚓,老刑警劉巖鼻种,帶你破解...
    沈念sama閱讀 216,470評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異溪椎,居然都是意外死亡普舆,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,393評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門校读,熙熙樓的掌柜王于貴愁眉苦臉地迎上來沼侣,“玉大人,你說我怎么就攤上這事歉秫《曷澹” “怎么了?”我有些...
    開封第一講書人閱讀 162,577評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵雁芙,是天一觀的道長轧膘。 經(jīng)常有香客問我,道長兔甘,這世上最難降的妖魔是什么谎碍? 我笑而不...
    開封第一講書人閱讀 58,176評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮洞焙,結(jié)果婚禮上蟆淀,老公的妹妹穿的比我還像新娘拯啦。我一直安慰自己,他們只是感情好熔任,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,189評(píng)論 6 388
  • 文/花漫 我一把揭開白布褒链。 她就那樣靜靜地躺著,像睡著了一般疑苔。 火紅的嫁衣襯著肌膚如雪甫匹。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,155評(píng)論 1 299
  • 那天惦费,我揣著相機(jī)與錄音兵迅,去河邊找鬼。 笑死趁餐,一個(gè)胖子當(dāng)著我的面吹牛喷兼,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播后雷,決...
    沈念sama閱讀 40,041評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼季惯,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了臀突?” 一聲冷哼從身側(cè)響起勉抓,我...
    開封第一講書人閱讀 38,903評(píng)論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎候学,沒想到半個(gè)月后藕筋,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,319評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡梳码,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,539評(píng)論 2 332
  • 正文 我和宋清朗相戀三年隐圾,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片掰茶。...
    茶點(diǎn)故事閱讀 39,703評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡暇藏,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出濒蒋,到底是詐尸還是另有隱情盐碱,我是刑警寧澤,帶...
    沈念sama閱讀 35,417評(píng)論 5 343
  • 正文 年R本政府宣布沪伙,位于F島的核電站瓮顽,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏围橡。R本人自食惡果不足惜暖混,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,013評(píng)論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望翁授。 院中可真熱鬧儒恋,春花似錦善绎、人聲如沸黔漂。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,664評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽炬守。三九已至牧嫉,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間减途,已是汗流浹背酣藻。 一陣腳步聲響...
    開封第一講書人閱讀 32,818評(píng)論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留鳍置,地道東北人辽剧。 一個(gè)月前我還...
    沈念sama閱讀 47,711評(píng)論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像税产,于是被迫代替她去往敵國和親怕轿。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,601評(píng)論 2 353

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

  • 1.什么是JSP (1)jsp全稱是Java Server Pages辟拷,它和Servlet技術(shù)一樣都是sun公司定...
    yjaal閱讀 3,648評(píng)論 5 99
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法撞羽,類相關(guān)的語法,內(nèi)部類的語法衫冻,繼承相關(guān)的語法诀紊,異常的語法,線程的語...
    子非魚_t_閱讀 31,622評(píng)論 18 399
  • 一隅俘、JSP基礎(chǔ) 1.1什么是JSP JSP(Java ServerPage)是Java服務(wù)器端動(dòng)態(tài)頁面技術(shù)邻奠。是su...
    晨星資源閱讀 1,147評(píng)論 0 6
  • 主要內(nèi)容: 防盜鏈 開發(fā)if標(biāo)簽 開發(fā)if else標(biāo)簽 開發(fā)foreach標(biāo)簽 開發(fā)HTML轉(zhuǎn)義的標(biāo)簽 打包標(biāo)簽...
    yjaal閱讀 739評(píng)論 0 0
  • 三更夜闖歸家路,履間落地碎土音为居, 樹遮月破照裂云碌宴,輕扣聽蟈哼待應(yīng)。 垂頭無端嘴生風(fēng)颜骤,唇開紅漫滿舌腥唧喉, 門扉小隙黑無...
    葡萄美酒閱讀 144評(píng)論 0 0