Taglib 原理和實現:第四章 迴圈的Tag
1。問題:在request裡的 People 物件,有個屬性叫 men ,men 是一個Collection ,有許多個man 。現在,把 collection裡的man的名字都顯示出來
顯然,這是一個巢狀Tag的問題。有三個Tag互相作用:最外層的Tag找到People物件,中間的Tag取得Collection,子Tag負責列印。
例如:
<diego:withObject value="${people}">
<diego:withCollection property="men">
<diego:elementout property="name"/>
</diego:withCollection>
</diego:withObject>
思路如下:
1.編寫WithObjectTag,負責從El表示式中取得物件
2.編寫WithCollectionTag,負責從物件中取得 Collection ,遍歷 Collection ,每遍歷一次 Collection ,執行一次body
3.編寫ElementoutTag ,把 Collection 中每個men物件的 name 打印出來
2. 完整程式如下:
在上例的diegoyun.vo包內,編寫 People 類
package diegoyun.vo;
import java.util.Collection;
public class People
{
private Collection men = null;
public Collection getMen()
{
return men;
}
public void setMen(Collection men)
{
this.men = men;
}
}
編寫 withObject ,這是從request裡取得People物件的最外層Tag
package diegoyun;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.BodyTagSupport;
import org.apache.taglibs.standard.lang.support.ExpressionEvaluatorManager;
public class WithObjectTag extends BodyTagSupport
{
private Object value = null;
public Object getValue()
{
return value;
}
public void setValue(Object value)throws JspException
{
this.value = ExpressionEvaluatorManager.evaluate(
"value", value.toString(), Object.class, this, pageContext);
}
public int doStartTag()
{
return EVAL_BODY_INCLUDE;
}
public int doEndTag()throws JspException
{
return EVAL_PAGE;
}
}
編寫WithCollectionTag,該Tag負責取得Collection,並遍歷執行子Tag
package diegoyun;
import java.util.Collection;
import java.util.Iterator;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.BodyTagSupport;
import org.apache.commons.beanutils.PropertyUtils;
public class WithCollectionTag extends BodyTagSupport {
private Object element = null;
private Collection list = null;
private Iterator iterator = null;
public Object getElement() {
return element;
}
public void setProperty(String property) throws JspException {
//取得父Tag物件,並且得到Collection
WithObjectTag parent = (WithObjectTag) getParent();
if (parent == null)
throw new JspException("parent tag is null");
try {
Object propertyValue = PropertyUtils.getProperty(parent.getValue(),
property);
this.list = (Collection) propertyValue;
if (list == null)
throw new JspException("Collection is null");
} catch (Exception e) {
throw new JspException(e);
}
}
public int doStartTag() throws JspException {
//設定第一個元素,然後執行子Tag
iterator = list.iterator();
if (iterator.hasNext())
element = iterator.next();
return EVAL_BODY_INCLUDE;
}
public int doAfterBody() {
if (iterator.hasNext()) {
//如果還存在子元素,設定子元素,並且再次執行子Tag
//迴圈由此而來
//否則不再執行子Tag
element = iterator.next();
return EVAL_BODY_AGAIN;
}
else
return EVAL_PAGE;
}
}
編寫 ElementOutputTag
package diegoyun;
import java.io.IOException;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.TagSupport;
import org.apache.commons.beanutils.PropertyUtils;
public class ElementOutputTag extends TagSupport
{
private Object propertyValue = null;
public void setProperty(String property)throws JspException
{
WithCollectionTag parent = (WithCollectionTag)getParent();
if(parent == null)
throw new JspException("parent tag is null");
try
{
//判斷上層tag中是否存在該屬性名稱,如果存在,取得屬性值,否則報錯
propertyValue = PropertyUtils.getProperty(parent.getElement(), property);
}
catch (Exception e)
{
throw new JspException(e);
}
}
public int doEndTag()throws JspException
{
try
{
//簡單的把值列印到jsp頁面
pageContext.getOut().print(propertyValue);
}
catch (IOException e)
{
throw new JspException(e);
}
return EVAL_PAGE;
}
}
編寫tld
<!--WithObjectTag-->
<tag>
<name>withObject</name>
<tag-class>diegoyun.WithObjectTag</tag-class>
<body-content>JSP</body-content>
<attribute>
<name>value</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
<!--WithCollectionTag-->
<tag>
<name>withCollection</name>
<tag-class>diegoyun.WithCollectionTag</tag-class>
<body-content>JSP</body-content>
<attribute>
<name>property</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
<!--ElementOutputTag-->
<tag>
<name>elementout</name>
<tag-class>diegoyun.ElementOutputTag</tag-class>
<body-content>empty</body-content>
<attribute>
<name>property</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
編寫jsp
<%@ page language="java" %>
<%@ page import="diegoyun.vo.*"%>
<%@ page import="java.util.*"%>
<%@ taglib uri="/WEB-INF/tlds/diego.tld" prefix="diego"%>
<html>
<body bgcolor="#FFFFFF">
<%
Collection c = new ArrayList();
Man man1 = new Man();
man1.setName("diego");
c.add(man1);
Man man2 = new Man();
man2.setName("Zidane");
c.add(man2);
Man man3 = new Man();
man3.setName("Rui");
c.add(man3);
People p =new People();
p.setMen(c);
request.setAttribute("people",p);
%>
Test loop tag:
<br>
<diego:withObject value="${people}">
<diego:withCollection property="men">
<diego:elementout property="name"/>
<br>
</diego:withCollection>
</diego:withObject>
</body>
</html>
執行,則可以看到:
Test loop tag:
diego
Zidane
Rui