为JSP编写自定义标签(1)

鉴于JSP1.x和JSP2.x自定义标签机制不同,这里先写JSP1.x。

任何一个标签都对应一个Java类,该类必须实现了Tag接口。JSP中遇到一个标签后,将通过一个tld文件查找该标签的实现类,并运行该类的相关方法。

先来看Tag接口,源代码如下:

public interface Tag
{
    // 跳过标签体
    public final static int SKIP_BODY = 0;
    // 执行标签体内部的代码
    public final static int EVAL_BODY_INCLUDE = 1;
    // 不继续执行标签后面的代码
    public final static int SKIP_PAGE = 5;
    // 继续执行标签后面的代码
    public final static int EVAL_PAGE = 6;
    
    // 注释JSP的pageContext对象
    void setPageContext(PageContext pageContext);
    // 注释标签的父标签
    void setParent(Tag parent);
    Tag getParent();
    // 进入标签时被执行
    int doStartTag() throws JspException;
    // 退出标签时被执行
    int doEndTag() throws JspException;
    // 在关闭Web应用的时候被容器调用
    void release();
}

多数情况下不直接使用Tag接口,而是使用TagSupport类,所需要做的只有实现doStartTag()和doEndTag()方法。

Tag类写好后,还需要在tld(Tag Library Descriptor 标签库描述文件)中配置,以实现标签与实现类的映射。

如果tld文件在WEB-INF/下面,Tomcat会自动加载tld文件中的标签库,否则需要配置web.xml(之前一篇博客专门记录了这个知识点),例如:

<jsp-config>
    <taglib>
        <taglib-uri>http://www.loverabbit.com/tags</taglib-uri>
        <taglib-location>/WEB-INF/somewhere/taglib.tld</taglib-location>
    </taglib>
</jsp-config>
也可以直接在JSP中指定实际路径(这样的缺点显而易见,不灵活~)

<%@ taglib uri="/WEB-INF/somewhere/taglib.tld" prefix="Love" %>

示例:




带标签体的自定义标签,如果要显示标签体,则tld文件中的bodycontent属性不为empty,并且doStartTag()方法返回EVAL_BODY_INCLUDE。

对标签体进行分析,要使用BodyTag接口。如果doStartTag()方法返回EVAL_BODY_BUFFERED,则不会输出标签体,而是通过setBodyContent()方法注释到标签类里,然后使用getBodyContent()方法得到标签体的内容。


根据上一个示例小改动了下,结果如下:


如果想要多次使用标签体的内容,可以设置doAfterBody()的返回值为EVAL_BODY_AGAIN,注意,如果一直是此返回值,则会是死循环。

package my;

import java.io.IOException;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.BodyTagSupport;
import javax.servlet.jsp.tagext.TagSupport;

public class Rabbit extends BodyTagSupport
{
	private String name;
	private int age;
	private int i;

	public void setAge(int age)
	{
		this.age = age;
	}

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

	@Override
	public int doStartTag() throws JspException
	{
		i = 0;
		return super.doStartTag();
	}

	@Override
	public int doAfterBody() throws JspException
	{
		i++;
		if(i < 3)
		{
			try
			{
				this.pageContext.getOut().println("  " + i + "  love  ");
			}
			catch (IOException e)
			{
				e.printStackTrace();
			}
			return EVAL_BODY_AGAIN;
		}
		else
		{
			return SKIP_BODY;
		}
	}

	@Override
	public int doEndTag() throws JspException
	{
		try
		{
			String jsp = this.getBodyContent().getString();
			this.pageContext.getOut().println("name is " + name + "   age is " + age + "   JspContent is " + jsp + "   ");
		}
		catch (Exception e)
		{
			System.out.println("***************");
		}
		return EVAL_PAGE;
	}
}



最后是“带动态属性的自定义标签”,不是很理解,把示例贴出来:

package my;

import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.DynamicAttributes;
import javax.servlet.jsp.tagext.TagSupport;

public class DynamicAttributeTag extends TagSupport implements DynamicAttributes
{

	private static final long serialVersionUID = -1477571708507488373L;

	private Map<String, Double> map = new HashMap<String, Double>();

	@Override
	public int doEndTag() throws JspException
	{

		JspWriter out = pageContext.getOut();

		double min = 0, max = 0;

		for (Double d : map.values())
		{
			min = Math.min(d, min);
			max = Math.max(d, max);
		}

		StringBuffer buffer = new StringBuffer();

		buffer.append("<table>");

		for (Entry<String, Double> entry : map.entrySet())
		{
			buffer.append("<tr>");
			buffer.append("<td>" + entry.getKey() + "</td>");
			buffer.append("<td><img src='vote.gif' height='10' width='");
			buffer.append((entry.getValue() - min) / (max - min + 1) * 200 + 50);
			buffer.append("' /> " + entry.getValue() + "</td>");
			buffer.append("</tr>");
		}

		buffer.append("</table>");

		try
		{
			out.write(buffer.toString());
		}
		catch (Exception e)
		{
		}

		return super.doEndTag();
	}

	@Override
	public void setDynamicAttribute(String uri, String key, Object value) throws JspException
	{

		map.put(key, Double.parseDouble((String) value));
	}
}

// end





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值