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

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

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

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

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

這里我們先編寫一個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><!-- 因為文件是放在WEB-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 下面,所以uri地址是/itcast。

實現(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>客戶機IP</title>
  </head>
  <body>
    您的IP是:<itcast:viewIP/>
    <%
        /* 等同于 */
        String ip = request.getRemoteAddr();
        out.write(ip);
     %>
  </body>
</html>

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

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

1.jsp引擎實例化標(biāo)簽處理類之后,將調(diào)用setPageContext方法將jsp頁面的pageContext對象傳遞給標(biāo)簽處理器,標(biāo)簽處理器以后可以通過這個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)簽時,就會調(diào)用標(biāo)簽處理器的doStartTag方法。

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

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

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

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

自定義標(biāo)簽除了可以移除jsp頁面的java代碼,也可以實現(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;//返回此常量則會執(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類,因為每次繼承Tag接口需要實現(xiàn)很多用不到的方法,于是這里我們繼承此默認(rèn)實現(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>

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

例:控制整個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頁面不會執(zhí)行
        //return Tag.EVAL_PAGE;//此常量表示會執(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>控制整個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í)行的時候需要的常量需要的不是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。
最后,其實上面是一種很傳統(tǒng)的方式,使用起來并不方便,一般我們很少使用。

四、簡單標(biāo)簽

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

  • 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)簽時,會調(diào)用如下方法完成標(biāo)簽的初始化:

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

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

2.JspFragment類

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

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

3.invoke方法詳解

JspFragment.invoke方法是JspFragment最重要的方法,利用這個方法可以控制是否執(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)容將會別重復(fù)執(zhí)行;
  • 3.若想在標(biāo)簽處理器中修改標(biāo)簽體內(nèi)容,只需在調(diào)用invoke方法時指定一個可取出結(jié)果數(shù)據(jù)的輸出流對象(StringWriter),讓標(biāo)簽體的執(zhí)行結(jié)果輸出到該輸出流對象中,然后從該輸出流對象中取出數(shù)據(jù)進(jìn)行修改后再輸出到目標(biāo)設(shè)備,即可達(dá)到修改標(biāo)簽體的目的。

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

例:使用簡單標(biāo)簽實現(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,因為新版的標(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)簽實現(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();//得到一個輸出流
        jf.invoke(sw);//注意:要想修改標(biāo)簽體內(nèi)容個必須先執(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)容輸出到我們自己定義的一個流中,然后我們從流中拿到數(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 {
        //只要此方法拋出這個異常,那么余下的頁面將不會執(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>

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

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

  • 要想讓一個自定義標(biāo)簽具有屬性,通常要完成兩個任務(wù):
    在標(biāo)簽處理器中編寫每個屬性對應(yīng)的setter方法
    在tld文件中描述標(biāo)簽的屬性
  • 為自定義標(biāo)簽定義屬性時,每個屬性都必須按照javaBean的屬性命名方式,在標(biāo)簽處理器中定義屬性名對應(yīng)的setter方法,用來接收jsp頁面調(diào)用自定義標(biāo)簽時傳遞進(jìn)來的屬性值。例如,屬性url,在標(biāo)簽處理器類中就要定義相應(yīng)的setUrl(String url)方法。
  • 在標(biāo)簽處理器中定義相應(yīng)的set方法后,jsp引擎在解析執(zhí)行開始標(biāo)簽前,也就是調(diào)用doStartTag方法前,會調(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><!-- 這表示此屬性是必須的 -->
            <!-- 此屬性是否是一個運行時表達(dá)式,若為false則只能是靜態(tài)的值,一般都是true -->
            <rtexprvalue>true</rtexprvalue>
            <type>java.lang.Integer</type><!-- 這個屬性是規(guī)定參數(shù)的java屬性,如果不正確則報錯 -->
        </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{
    //這里注意:我們頂一個的是一個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,則這里可以是一個表達(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)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1.什么是JSP (1)jsp全稱是Java Server Pages,它和Servlet技術(shù)一樣都是sun公司定...
    yjaal閱讀 3,853評論 5 99
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法,類相關(guān)的語法,內(nèi)部類的語法,繼承相關(guān)的語法,異常的語法,線程的語...
    子非魚_t_閱讀 34,898評論 18 399
  • 一、JSP基礎(chǔ) 1.1什么是JSP JSP(Java ServerPage)是Java服務(wù)器端動態(tài)頁面技術(shù)。是su...
    晨星資源閱讀 1,281評論 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閱讀 802評論 0 0
  • 三更夜闖歸家路,履間落地碎土音, 樹遮月破照裂云,輕扣聽蟈哼待應(yīng)。 垂頭無端嘴生風(fēng),唇開紅漫滿舌腥, 門扉小隙黑無...
    葡萄美酒閱讀 161評論 0 0

友情鏈接更多精彩內(nèi)容