08-08
23

自定义标签之 开发迭代的标签库

 在没有迭代标签的时候,如果要循环输出内容到网页,我们往往这样做:
<%
    
While(iterator.hasNext())
    {
        SomeObject obj 
= (SomeObject)iterator.Next();
        out.println(obj.getComeValue());
    }
%>
上面的while就是一个迭代,如果我们要开发出这样的标签,一般需要二个开发类,一具类实现BodyTagSupport接口,另一个类扩展TagExtraInfo类。TagExtraInfo旨在提供标签运行时的信息。下面来做个实例
IterateTag.java
package eflylab;
import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.*;
import java.util.*;

public class IterateTag extends BodyTagSupport
{
    
/**
     *Tag的属性
     
*/

    
private String name;
    
//it为要迭代的对象
    private Iterator it;
    
//type表示it中对象的类型
    private String type;

    
/**
     *设置属性collection
     
*/

    
public void setCollection(Collection collection)
    
{
        
if(collection.size()>0)
        it
=collection.iterator();
    }

    
public void setName(String name)
    
{
        
this.name=name;
    }

    
public void setType(String type)
    
{
        
this.type=type;
    }

    
/**
     *如果it属性为null,那么忽略计算tagbody。
     
*/

    
public int doStartTag()throws JspTagException
    
{
        
if(it==null)
            
return SKIP_BODY;
        
else
            
return continueNext(it);
    }

    
    
public int doAfterBody()throws JspTagException
    
{
        
return continueNext(it);
    }

    
    
public int doEndTag()throws JspTagException
    
{
        
try
        
{
            
if(bodyContent!=null)
            bodyContent.writeOut(bodyContent.getEnclosingWriter());
        }

        
catch(java.io.IOException e)
        
{
        }

        
        
return EVAL_PAGE;
    }

    
/**
     *保护方法,用于把it.next()设置为pagecontext的属性
     
*/

    
protected int continueNext(Iterator it)throws JspTagException
    
{
        
if(it.hasNext())
        
{
            pageContext.setAttribute(name,it.next(),PageContext.PAGE_SCOPE);
            
return EVAL_BODY_TAG;
        }

        
else
        
{
            
return SKIP_BODY;
        }

    }

}
由于BodyTagSupport类实现了IteratorTag接口,所以在开发迭代标签时,可以直接从BodyTagSupport类继承,IterateTag就是从BodyTagSupport类继承的例子。在IterateTag中,有3个属性,它们是name,type和it。name代表了在pageContext中标识的一个属性的名字;type代表了待迭代的内容的类型;it代表了要迭代的内容。在IterateTag中必须提供这些属性的setter方法,并且在JSP中使用这些属性时必须提供对应的值。
在doStartTag方法中,如果it不为null,那么就进行第一次迭代。在continueNext方法中如果it还有下一个,那么就继续迭代,如果没有下一个了,就返回SKIP_BODY,表示不再迭代。
除了上面的标签类外,还需要开发一个表示标签信息的类,如下
iterateTEI.java
package eflylab;
import javax.servlet.jsp.tagext.*;
//TagExtraInfo用于提供一些在标签翻译时相关的信息。
public class IterateTEI extends TagExtraInfo
{
    
public IterateTEI()
    
{
        
super();
    }

    
    
public VariableInfo[] getVariableInfo(TagData data)
    
{
        
return new VariableInfo[]
        
{
            
new VariableInfo(
                data.getAttributeString(
"name"),
                data.getAttributeString(
"type"),
                
true,
                VariableInfo.NESTED
            ),
        }
;
    }

}

需要说明的是VariableInfo的几个参数,如下:
NESTED  标签中的参数在starttag到endtag之间是有效的。
AT_BEGIN  标签中的参数在标签的开始到JSP结束是有效的。
AT_END  标签中的参数在标签的结束到JSP页面的结束是有效的。

当然另外在标签的描述文件TLD中要加上这二类的描述

<tag>
      
<name>iterate</name>
      
<tag-class>eflylab.IterateTag</tag-class>
      
<tei-class>eflylab.IterateTEI</tei-class>
      
<body-content>jsp</body-content>
      
<attribute>
          
<name>collection</name>
          
<required>true</required>
          
<rtexprvalue>true</rtexprvalue>
      
</attribute>
      
<attribute>
          
<name>name</name>
          
<required>true</required>
      
</attribute>
      
<attribute>
          
<name>type</name>
          
<required>true</required>
      
</attribute>
  
</tag>
测试代码:
Company .java
Contact .java
<%@ page pageEncoding="GBK" %>
<%@ taglib uri="/demotag" prefix="mt"%> 
<% 
    eflylab.Company comp
=new eflylab.Company();
    comp.setName(
"huayuan");
    eflylab.Contact contact1
=new eflylab.Contact();
    contact1.setName(
"bar ,foo");
    contact1.setEmail(
"dd@tsinghua.eud.cn");
    contact1.setPhone(
"2975349875");
    contact1.setComment(
"java programe");
    
    eflylab.Contact contact2
=new eflylab.Contact();
    contact2.setName(
"bar ,foo");
    contact2.setEmail(
"dd@tsinghua.eud.cn");
    contact2.setPhone(
"2975349875");
    contact2.setComment(
"java programe");
    
    eflylab.Contact contact3
=new eflylab.Contact();
    contact3.setName(
"bar ,foodf");
    contact3.setEmail(
"dd@tsinghua.euddfdf.cn");
    contact3.setPhone(
"2975349875dd");
    contact3.setComment(
"java progrdfame");
    
    comp.addContact(contact1); 
    comp.addContact(contact2);  
    comp.addContact(contact3);
    request.setAttribute(
"company",comp);
%>
<html>
<head>
<title>迭代标签演示</title>
</head>
<body>
<jsp:useBean id="company" scope="request" type="eflylab.Company"/>

<font size=+2>我的一些和<b>
<jsp:getProperty name="company" property="name"/>
公司联系
</b>
</font>
<hr>
<table border=1>
<tr>
<td>姓名</td>
<td>电话</td>
<td>email</td>
<td>备注</td>
</tr>
<mt:iterate name="contact" collection="<%=company.getContacts()%>" type="eflylab.Contact">
<tr>
    
<td>
    
<jsp:getProperty name="contact" property="name"/>
    
</td>
    
<td>
    
<jsp:getProperty name="contact" property="phone"/>
    
</td>
    
<td>
    
<jsp:getProperty name="contact" property="email"/>
    
<td>
    
<jsp:getProperty name="contact" property="comment"/>
    
</td>
</tr>
</mt:iterate>
</table>
<hr>
</body>
</html>
运行:
 

[本日志由 blurxx 于 2008-08-23 02:30 PM 编辑]
文章来自: 本站原创
引用通告: 查看所有引用 | 我要引用此文章
Tags: 自定义标签 迭代 标签库
相关日志:
评论: 0 | 引用: 0 | 查看次数: 585
发表评论
昵 称:
密 码: 游客发言不需要密码.
内 容:
验证码: 验证码
选 项:
虽然发表评论不用注册,但是为了保护您的发言权,建议您注册帐号.
字数限制 1000 字 | UBB代码 开启 | [img]标签 关闭