天天看点

JSTL自定义标签 1. 自定义标签简介 2. 一个简单实例 4. 简单标签 5. 带属性的标签 6. JSTL案例 7.  打包标签库 8.  JSTL常用标签库

版权声明:尊重博主原创文章,转载请注明出处哦~http://blog.csdn.net/eson_15/article/details/51264254

        这节我们总结一下jstl自定义标签相关内容。

        1)编写一个实现tag接口的java类(标签处理类);

        2)编写标签库描述符(tld)文件,在tld文件中对标签处理类进行描述。

        我们写一个简单的实例来快速理解自定义标签:输出客户机的ip。按照上面描述的两个步骤,我们首先编写一个实现tag接口的java类:

JSTL自定义标签 1. 自定义标签简介 2. 一个简单实例 4. 简单标签 5. 带属性的标签 6. JSTL案例 7.  打包标签库 8.  JSTL常用标签库

public class viewiptag implements tag {  

    private pagecontext pagecontext;      

    @override  

    public int dostarttag() throws jspexception {  

        httpservletrequest request = (httpservletrequest)pagecontext.getrequest(); //获取request  

        jspwriter out = pagecontext.getout(); //获取out</span>  

        string ip = request.getremoteaddr(); //通过request获取客户机的ip  

        try {  

            out.write(ip); //写到浏览器  

        } catch (ioexception e) {  

            throw new runtimeexception(e);  

        }         

        return 0;  

    }     

    public int doendtag() throws jspexception {  

    }  

    public tag getparent() {  

        return null;  

    public void release() {  

    public void setpagecontext(pagecontext arg0) {        

        this.pagecontext = arg0;  

    public void setparent(tag arg0) {  

}  

        写好了java类,我们来编写标签库描述符(tld)文件,在web-inf目录下新建一个tld文件,在tld文件中对标签处理器类进行描述:

JSTL自定义标签 1. 自定义标签简介 2. 一个简单实例 4. 简单标签 5. 带属性的标签 6. JSTL案例 7.  打包标签库 8.  JSTL常用标签库

<?xml version="1.0" encoding="utf-8" ?>  

<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>/test</uri>  <!--为该标签配一个uri-->  

    <tag>  

    <name>viewip</name> <!-- 为标签处理器类配一个标签名 -->  

    <tag-class>web.tag.viewiptag</tag-class>  

    <body-content>empty</body-content>  

    </tag>  

</taglib>  

        这样我们在jsp页面中就可以导入并使用自定义标签了:

JSTL自定义标签 1. 自定义标签简介 2. 一个简单实例 4. 简单标签 5. 带属性的标签 6. JSTL案例 7.  打包标签库 8.  JSTL常用标签库

<%@ page language="java" import="java.util.*" pageencoding="utf-8"%>  

<%@ taglib uri="/test" prefix="test"%>  <!--uri与tld文件中配的uri相同-->  

<!doctype html public "-//w3c//dtd html 4.01 transitional//en">  

<html>  

  <head>    

    <title>输出客户机的ip</title>  

  </head>  

  <body>  

    您的ip是:<test:viewip/>  

    <!--该标签相当于执行下面脚本代码-->  

    <%   

        string ip = request.getremoteaddr();  

        out.write(ip);  

    %>         

  </body>  

</html>  

        到这里,应该就能清楚了自定义标签的定义和配置了。我们来分析一下执行顺序:jsp引擎首先通过uri和viewip标签名去找tld文件,在tld中通过viewip找到viewiptag类,该类中,首先调用setpagecontext方法把页面的pagecontext传递进来,再调用setparent把父标签传递进来(没有则不传),至此完成了标签的初始化工作。然后调用dostarttag和doendtag方法,开始和结束标签,最后调用release方法释放标签,运行时所占的资源。

3. 自定义标签功能扩展

        开发人员在编写jsp页面时,经常还需要在页面中引入一些逻辑,如:

        控制jsp页面某一部分内容是否执行;

        控制整个jsp页面是否执行;

        控制jsp页面内容重复执行;

        修改jsp页面内容输出。

        即:自定义标签除了可以移除jsp页面的java代码外,还可以实现以上功能。下面我们一个个来分析:

1)控制jsp页面某一部分内容是否执行

        新建一个标签处理类tagdemo1继承tagsupport类(tagsupport类已经实现了tag接口,不用直接去实现了),dostarttag方法中可以通过不同的返回值类控制标签体是否执行。返回tag.eval_body_include表示执行标签体内容,返回tag.skip_body表示不执行。

JSTL自定义标签 1. 自定义标签简介 2. 一个简单实例 4. 简单标签 5. 带属性的标签 6. JSTL案例 7.  打包标签库 8.  JSTL常用标签库

//控制标签体是否执行  

public class tagdemo1 extends tagsupport {  

//      return tag.skip_body;//不执行标签体内容  

        return tag.eval_body_include; //执行标签体内容  

         然后在文件中配置好:

JSTL自定义标签 1. 自定义标签简介 2. 一个简单实例 4. 简单标签 5. 带属性的标签 6. JSTL案例 7.  打包标签库 8.  JSTL常用标签库

<tag>  

    <name>demo1</name>  

    <tag-class>web.tag.tagdemo1</tag-class>  

    <body-content>jsp</body-content> <!--jsp表示标签体内容为jsp-->  

</tag>  

        这样即可在jsp页面中可以根据标签处理类dostarttag方法的返回值控制标签体内容是否执行。

 2)控制整个jsp页面是否执行

        同样地,doendtag方法中可以通过不同的返回值类控制下面的jsp页面是否执行。返回tag.eval_page表示执行下面的jsp页面内容,返回tag.skip_page表示不执行。如下:

JSTL自定义标签 1. 自定义标签简介 2. 一个简单实例 4. 简单标签 5. 带属性的标签 6. JSTL案例 7.  打包标签库 8.  JSTL常用标签库

//控制jsp页面是否执行  

public class tagdemo2 extends tagsupport {  

//      return tag.skip_page;//不执行jsp页面  

        return tag.eval_page;//执行jsp页面  

    }         

3)控制jsp页面内容重复执行

        控制页面内容重复执行的话tag接口就无法满足了,需要实现它的子接口iterationtag接口,该接口中有个doafterbody方法来决定是否重复执行标签体内容。如果该方法返回iterationtag.eval_body_again则继续执行,如果返回iterationtag.skip_body则结束重复并跳转到doendtag()方法执行了。不过不用直接去实现iterationtag接口,tagsupport类也实现了该接口,所以只要让标签处理类继承tagsupport类即可。需要注意的是除了覆盖doafterbody方法外,还得覆盖dostarttag方法并返回tag.eval_body_include。因为只有允许标签体执行才能重复执行。如下:

JSTL自定义标签 1. 自定义标签简介 2. 一个简单实例 4. 简单标签 5. 带属性的标签 6. JSTL案例 7.  打包标签库 8.  JSTL常用标签库

//控制页面内容重复执行  

public class tagdemo3 extends tagsupport {  

    int i = 5;  

    public int doafterbody() throws jspexception {  

        i--;  

        if(i >= 0)   

            return iterationtag.eval_body_again;  

        else  

            return iterationtag.skip_body;  

        return tag.eval_body_include;  

4)修改jsp页面内容输出

        修改jsp页面内容输出的话iterationtag接口就无法满足了,需要实现它的子接口bodytag接口,该接口增加了两个方法:doinitbody()和setbodycontent(bodycontent b)方法。如果dostarttag方法返回bodytag.eval_body_buffered,则bodycontent对象就会被jsp翻译过后的servlet创建,即得到标签体对象。在doendtag方法里对标签内容进行修改,可以通过this.getbodycontent().getstring()拿到转成string的标签体内容,然后对该内容进行修改,再将结果result通过this.pagecontext().getout().write(result)进行输出,在doendtag方法里返回tag.eval_page。然后jsp翻译过的servlet再把该bodycontent对象传递给setbodycontent方法完成修改。所以我们只需要覆盖dostarttag和doendtag方法即可。该接口已经有个默认实现类bodytagsupport,编写标签处理类直接继承这个类即可。如下:

JSTL自定义标签 1. 自定义标签简介 2. 一个简单实例 4. 简单标签 5. 带属性的标签 6. JSTL案例 7.  打包标签库 8.  JSTL常用标签库

//修改标签内容  

public class tagdemo4 extends bodytagsupport {  

        return bodytag.eval_body_buffered;  

        //拿到标签体  

        string content = this.getbodycontent().getstring();  

        string result = content.touppercase();  

            this.pagecontext.getout().write(result);  

        }  

        return tag.eval_page;  

    }             

        注:以上扩展功能的知识点在jsp2.0后已经被淘汰掉了,会有一个新的简单标签(simpletag)接口可以更方便的实现。但是以上的知识点在struts框架中还在使用。在学struts框架的标签库会遇到。下面我们来看一看简单标签的相关内容。

        简单标签接口simpletag与上面提到的标签接口不同,simpletag标签提供了一个简单的dotag()方法代替了dostarttag和doendtag方法。所有标签的逻辑、迭代、计算等等都在这个方法中运行。因此simpletag接口也可以替代bodytag接口。该接口中有以下方法:

JSTL自定义标签 1. 自定义标签简介 2. 一个简单实例 4. 简单标签 5. 带属性的标签 6. JSTL案例 7.  打包标签库 8.  JSTL常用标签库

void dotag()  

jsptag getparent()  

void setjspbody(jspfragment jspbody):把标签体通过该方法传递进来,我们可以在dotag方法中拿到jspbody对象即拿到了标签体,然后可以对标签体做想做的事。包括上面所有功能  

void setjspcontext(jspcontext pc)  

void setparent(jsptag parent)  

        jspcontext是pagecontext的父类,执行顺序:jsp引擎首先通过uri和viewip标签名去找tld文件,在tld中通过viewip找到viewiptag类,该类中,首先调用setjspcontext方法把页面的pagecontext传递进来,再调用setparent把父标签传递进来(没有则不传),然后再调用setjspbody方法,把代表标签体的jspfragment对象传递进去,至此完成了标签的初始化工作。然后开始执行标签,即调用dotag方法。下面我们使用简单标签扩展上面的功能。

 1)控制jsp页面某一部分内容是否执行      

JSTL自定义标签 1. 自定义标签简介 2. 一个简单实例 4. 简单标签 5. 带属性的标签 6. JSTL案例 7.  打包标签库 8.  JSTL常用标签库

public class simpletagdemo1 extends simpletagsupport {  

    //用简单标签使用这个方法完成所有业务逻辑  

    public void dotag() throws jspexception, ioexception {  

        //得到代表标签体的jspfragment  

        jspfragment jf = this.getjspbody();  

//      pagecontext pagecontext = (pagecontext)this.getjspcontext();    //获得pagecontext      

//      jf.invoke(pagecontext.getout());//将输出流放到invoke方法中,写给浏览器  

        jf.invoke(null);//null默认写给浏览器。不调用该方法即不运行标签体  

}<span style="font-family:microsoft yahei;">  

</span>  

          在simple.tld文件中配置如下(与上面的基本一样的):

JSTL自定义标签 1. 自定义标签简介 2. 一个简单实例 4. 简单标签 5. 带属性的标签 6. JSTL案例 7.  打包标签库 8.  JSTL常用标签库

    <uri>/simpleitcast</uri>  

        <name>demo1</name>   

        <tag-class>web.simpletag.simpletagdemo1</tag-class>  

        <body-content>scriptless</body-content>  

JSTL自定义标签 1. 自定义标签简介 2. 一个简单实例 4. 简单标签 5. 带属性的标签 6. JSTL案例 7.  打包标签库 8.  JSTL常用标签库

public class simpletagdemo4 extends simpletagsupport {  

        throw new skippageexception();//抛出个skippageexception异常即不会执行下面的jsp页面,否则会执行  

        tld文件中的配置略,跟上面一样的……不再赘述。

JSTL自定义标签 1. 自定义标签简介 2. 一个简单实例 4. 简单标签 5. 带属性的标签 6. JSTL案例 7.  打包标签库 8.  JSTL常用标签库

//控制标签体执行10次  

public class simpletagdemo<span style="font-family:microsoft yahei;">3</span> extends simpletagsupport {  

        for(int i = 0; i < 10; i++) {  

            jf.invoke(null);  

JSTL自定义标签 1. 自定义标签简介 2. 一个简单实例 4. 简单标签 5. 带属性的标签 6. JSTL案例 7.  打包标签库 8.  JSTL常用标签库

//将标签体内容改成大写  

public class simpletagdemo3 extends simpletagsupport {  

        stringwriter sw = new stringwriter();  

        jf.invoke(sw);//不要invoke到浏览器,先invoke到自己的流里,然后修改修改再输出  

        string content = sw.getbuffer().tostring();//获得标签体的string内容  

        content = content.touppercase();  

        pagecontext pagecontext = (pagecontext)this.getjspcontext();  

        pagecontext.getout().write(content);//再将流输出给浏览器  

        自定义标签可以定义一个或多个属性,这样在jsp页面中应用自定义标签时就可以设置这些属性的值,通过这些属性为标签处理器传递参数信息,从而提供标签的灵活性和复用性。想要让一个自定义标签具有属性,通常需要完成两个任务即可:

        1)在标签处理器中编写每个属性对应的setter方法

        2)在tld文件中描述标签的属性

        为自定义标签定义属性时,每个属性都必须按照javabean的属性命名方式,在标签处理器中定义属性名对应的setter方法,用来接收jsp页面调用自定义标签时传递进来的属性值。例如属性url,在标签处理器类中就要定义相应的seturl(string url)方法。在标签处理器中定义相应的set方法后,jsp引擎在解析执行开始标签前,也就是调用dostarttag方法前,会调用set属性方法,为标签设置属性。我们看下面的例子:

JSTL自定义标签 1. 自定义标签简介 2. 一个简单实例 4. 简单标签 5. 带属性的标签 6. JSTL案例 7.  打包标签库 8.  JSTL常用标签库

//通过属性控制标签体的执行次数  

public class simpletagdemo5 extends simpletagsupport {  

    public int count; //<itcast:demo5 count="6"  

    public void setcount(int count) {//自动将属性传进来  

        this.count = count;  

        for(int i = 0; i < count; i++){  

            this.getjspbody().invoke(null);  

         tld文件中配置如下:

JSTL自定义标签 1. 自定义标签简介 2. 一个简单实例 4. 简单标签 5. 带属性的标签 6. JSTL案例 7.  打包标签库 8.  JSTL常用标签库

    <name>demo5</name>   

    <tag-class>web.simpletag.simpletagdemo5</tag-class>  

    <body-content>scriptless</body-content>         

    <attribute>  

        <name>count</name>  

        <required>true</required>  

        <rtexprvalue>true</rtexprvalue>  <!-- true的话jsp中该属性只可以为表达式,false只能为静态值 -->  

        <type>java.lang.integer</type>  <!-- 指明参数的类型 -->  

    </attribute>  

        在jsp页面中就可以使用标签

JSTL自定义标签 1. 自定义标签简介 2. 一个简单实例 4. 简单标签 5. 带属性的标签 6. JSTL案例 7.  打包标签库 8.  JSTL常用标签库

<itcast:demo5 count="4">  

    xxxx  

</itcast>  

        xxxx被输出4次

        我们来用自定义jstl标签开发一个防盗链的标签:如果客户端直接访问http://localhost:8080/example/test.jsp,会被阻止,先跳转到主页index.jsp,再访问1.jsp

JSTL自定义标签 1. 自定义标签简介 2. 一个简单实例 4. 简单标签 5. 带属性的标签 6. JSTL案例 7.  打包标签库 8.  JSTL常用标签库

public class referertag extends simpletagsupport {  

    private string site;  

    private string page;  

    public void setsite(string site) {  

        this.site = site;  

    public void setpage(string page) {  

        this.page = page;  

        //看来访者是从哪个页面来的  

        httpservletrequest request = (httpservletrequest)pagecontext.getrequest();  

        string referer = request.getheader("referer");//得到是从哪个页面来的  

        //判断是否从自己的主页过来的  

        if(referer == null || !referer.startswith(site)) {  

            httpservletresponse response = (httpservletresponse)pagecontext.getresponse();  

            string webroot = request.getcontextpath(); //example  

            if(page.startswith(webroot))  

                response.sendredirect(page);  

            else  

                response.sendredirect(webroot + page);  

            //重定向后,控制保护的页面不要执行  

            throw new skippageexception();  

        看一下index.jsp页面:

JSTL自定义标签 1. 自定义标签简介 2. 一个简单实例 4. 简单标签 5. 带属性的标签 6. JSTL案例 7.  打包标签库 8.  JSTL常用标签库

  <head>  

    <title>my jsp 'index.jsp' starting page</title>   

  </head>    

    this is my jsp page. <br>  

    <a href="${pagecontext.request.contextpath }/test.jsp">内容</a> <!--掉转到1.jsp-->  

       再看一下test.jsp:

JSTL自定义标签 1. 自定义标签简介 2. 一个简单实例 4. 简单标签 5. 带属性的标签 6. JSTL案例 7.  打包标签库 8.  JSTL常用标签库

<%@ taglib uri="/simpleitcast" prefix="it"%>  

<it:referer site="http://localhost:8080/" page="/index.jsp"/>  

  <head>     

    <title>防盗链</title>        

    这是内容  

        既然我们可以自定义标签,那我们定义好的标签如何打包供其他工程使用呢?这在开发中是很重要的。我们按照下列步骤来打包自定义标签库:

        a. 新建一个普通java project,将原来开发标签库工程的src目录下的标签处理类全部拷贝过来;

        b. 在工程下新建一个lib目录,把jsp和servlet两个jar包(jsp-api.jar和servlet-api.jar)拷贝进来(在tomcat目录\lib下);

        c. 选中这两个jar包,右击->build path->add to path,变成两个"奶瓶状"即可;

        d. 在工程下新建一个meta-inf目录,将标签的配置文件(tld文件)考进来;

        e. 将整个工程导出:export->选择java->jar file->next->右边的classpath和project不用打钩,然后选择导出目录即可导出。

        这样标签库的jar包就打包好了。

        再新建一个web project,将刚刚打包好的jar包拷贝到web-inf\lib下,这样在web-inf下新建一个jsp文件,在该文件里就可以通过taglib导入刚刚的jar包了,然后使用自己开发的标签了。

        <c:out>标签用于输出一段文本内容到pagecontext对象当前保存的"out"对象中,即:将内容输出给浏览器。该标签有三个属性可选,value属性指定要输出的内容;escapexml指定是否将<、>、&、`等特殊字符进行html编码转换后再进行输出,默认为true;default属性指定如果value属性的值为null时所输出的默认值。该标签主要用于escapexml属性和default属性

        <c:set>标签用于把某一个对象存在指定的域范围内,或者设置web域中的java.util.map类型的属性对象或javabean类型的属性对象的属性。有如下属性:

        value:用于指定属性的值;

        scope:用于指定属性所在的web域;

        var:用于指定要设置的web域属性的名称;

        target:用于指定要设置属性的对象,这个对象必须是javabean对象或者java.util.map对象;

        property:用于指定当前为对象设置的属性名称。

JSTL自定义标签 1. 自定义标签简介 2. 一个简单实例 4. 简单标签 5. 带属性的标签 6. JSTL案例 7.  打包标签库 8.  JSTL常用标签库

<!-- c:set标签 :向web域中存数据,向map或bean中存数据-->  

<c:set var="data" value="xxx" scope="page"/>  

${pagescope.data }  

<%   

    map map = new hashmap();  

    request.setattribute("map", map);  

%>  

<c:set property="data" value="yyy" target="${map }" />  

${map.data }  

<c:set property="name" value="eson_15" target="${person }"/>  

${person.name }  

        <c:remove>标签用于删除各种web域中的属性:

JSTL自定义标签 1. 自定义标签简介 2. 一个简单实例 4. 简单标签 5. 带属性的标签 6. JSTL案例 7.  打包标签库 8.  JSTL常用标签库

<c:remove var="varname" [scope="{page|request|session|application}"]/>  

        <c:if>标签可以判断是否执行标签体

JSTL自定义标签 1. 自定义标签简介 2. 一个简单实例 4. 简单标签 5. 带属性的标签 6. JSTL案例 7.  打包标签库 8.  JSTL常用标签库

<c:if test="${user==null}" var="result" scope="page">  

    xxx  

</c:if>  

        如果test中的表达式为真则执行标签体,另外将test的值保存在page域中,保存参数为result,可以通过${result}获取保存的值。

        标签用于构造条件判断语句

JSTL自定义标签 1. 自定义标签简介 2. 一个简单实例 4. 简单标签 5. 带属性的标签 6. JSTL案例 7.  打包标签库 8.  JSTL常用标签库

<c:choose>  

    <c:when test="${count == 0}">  

        对不起,没有符合您要求的记录  

    </c:when>  

    <c:otherwise>  

        符合您要求的记录共有${count}条  

    </c:otherwise>  

</c:choose>  

        <c:foreach>标签用于对一个集合对象中的元素进行循环迭代操作,或者按指定的次数重复迭代执行标签体中的内容。它有如下属性:

        var属性:指定当前迭代到的元素保存到page域中的属性名称;

        items属性:将要迭代的集合对象;

        begin属性:如果指定items属性,就从集合中的第begin个元素开始迭代,begin的索引值从0开始编号;如果没有指定items属性,就从begin指定的值开始迭代,直到end值结束。

        step属性:指定迭代的步长。

JSTL自定义标签 1. 自定义标签简介 2. 一个简单实例 4. 简单标签 5. 带属性的标签 6. JSTL案例 7.  打包标签库 8.  JSTL常用标签库

<!-- c:foreach标签 -->  

<c:foreach var="num" begin="1" end="10" step="1">   

${num }  <!-- 输出1-10 -->  

</c:foreach> <br>  

    list list = arrays.aslist("1","2");  

    request.setattribute("list", list);  

<c:foreach var="index" begin="0" end="${fn.length(list) }">  

${list[index] }  

</c:foreach>  

<c:foreach var="index" items="${list}">  

${index}  

        在jsp页面进行url的相关操作时,经常用在url地址后面附加一些参数。<c:param>标签可以嵌套在<c:import>、<c:url>或<c:redirect>标签内,为这些标签所使用的url地址附加参数。<c:param>标签在为一个url地址附加参数时,将自动对参数值进行url编码,例如,如果传递的参数为“中国”,则将其转换为"%d6%d0%b9%fa"后再附加到url地址后面,这也就是使用<c:param>标签的最大好处。如:<c:param name="name" value="value"/>

        value属性:指定要构造的url;

        var属性:指定将构造出的url结果保存到web域中的属性名称

        scope属性:指定将构造出的url结果保存到那个web域中

JSTL自定义标签 1. 自定义标签简介 2. 一个简单实例 4. 简单标签 5. 带属性的标签 6. JSTL案例 7.  打包标签库 8.  JSTL常用标签库

<!-- c:url标签(重点) -->  

<a href="<c:url value="/servlet/servletdemo1"/>">点点</a>  

<c:url value="/servlet/servletdemo2" var="servletdemo2"><!-- 如果没有var,则会把地址直接打给浏览器 -->  

    <c:param name="name" value="中国"/> <!-- 中国两个字已经被url编码了 -->  

    <c:param name="password" value="我是一个"></c:param>  

</c:url>  

<a href="${servletdemo2}">点点</a>  

        <c:redirect>标签用于实现请求重定向。

        url属性:指定要转发或重定向到的目标资源的url地址;

       context:当要使用相对路径重定向到同一个服务器下的其他web应用程序中的资源时,context属性指定其他web应用程序的名称。

       关于jstl部分的内容暂时就总结到这吧,如有错误之处,欢迎留言指正~

_____________________________________________________________________________________________________________________________________________________

-----乐于分享,共同进步!