自定义标签

本文详细介绍如何创建自定义JSP标签,包括标签处理器类的实现、TLD文件的配置、标签的使用方法等。此外,还介绍了标签的高级用法,如带属性的标签、带标签体的标签以及有父标签的标签。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

自定义标签
1.HelloWorld
1).创建一个标签处理器类:实现SimpleTag接口
2).在WEB-INF文件夹下新建一个.tld(标签描述文件)为扩展名的xml文件,并拷入固定的部分

<?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>JSTL 1.1 core library</description>
  <display-name>JSTL core</display-name>
  <tlib-version>1.1</tlib-version>
  <short-name>c</short-name>
  <uri>http://java.sun.com/jsp/jstl/core</uri>

修改为了:

<?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">
   <!-- 描述TLD文件的 --> 
  <description>MyTag 1.0 core library</description>
  <display-name>MyTag core</display-name>
  <tlib-version>1.0</tlib-version>
 
  <!-- 建议在JSP页面上使用的标签的前缀 -->
  <short-name>zc</short-name>
  <!-- 作为tld的id,用哪个来唯一标识当前的tld文件,多个tld文件的uri不能重复,
  通过JSP页面的taglib标签的uri属性来引用 -->
  <uri>http://www.zc.com/mytag/core</uri>
  
  <!-- 描述自定义的HelloSimpleTag标签 -->
  <tag>
  <!-- 标签名:在JSP页面使用标签时的名字 -->
  <name>hello</name>
  <!-- 标签所在的全类名 -->
  <tag-class>com.zc.javaweb.tag.HelloSimpleTag</tag-class>
  <!-- 标签体的类型 -->
  <body-content>empty</body-content>
  </tag>
</taglib>

3).使用自定义标签:
使用taglib指令导入标签库描述文件:
 

   <%@ taglib uri="http://www.zc.com/mytag/core" prefix="zc"    %>

使用自定义标签:
<zc:hello/>

----------
循环遍历

<%
	//模拟Servlet中的操作
		List<Customer2> customers=new ArrayList<Customer2>();
		customers.add(new Customer2(1,"A",11));
		customers.add(new Customer2(2,"B",12));
		customers.add(new Customer2(3,"C",13));
		customers.add(new Customer2(4,"D",14));
		customers.add(new Customer2(5,"E",15));
		
		request.setAttribute("customers", customers);
	%>
	引入
	<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"  %>    
	
	<!-- 在页面上对request中的customers属性进行便遍历,打印id,name,age -->
	<c:forEach items="${requestScope.customers }" var="customer">
	--${customer.id },	${customer.name },	${customer.age }<br>
	</c:forEach>

------
2.setJspContext:一定会被JSP引擎所调用,限于doYag,把代表JSP引擎的pageContext传给标签处理器类。
代码:

private PageContext pageContext;
	//JSP引擎调用,把代表JSP页面的PageConetxt对象传入
	//PageContext可以获取JSP页面的其他8个隐含对象。
	//所以JSP页面能做的,标签处理器都可以完成
	@Override
	public void setJspContext(JspContext arg0) {
		// TODO Auto-generated method stub
		System.out.println(arg0 instanceof PageContext);
		this.pageContext=(PageContext)arg0;
	}

3.带属性的自定义标签:
1).先在标签处理器类中定义setter方法。建议把所以属性类型都设置为String类型

 

private String value;
	private String count;
	public void setValue(String value) {
		this.value = value;
	}
	public void setCount(String count) {
		this.count = count;
	}

2).在tld描述文件中描述属性

 

<!-- 描述当前标签的属性 -->
  <attribute>
  		<!-- 属性名,需和标签处理器类的setter方法定义的属性相同 -->
  		<name>value</name>
  		<!-- 该属性是否必须 -->
  		<required>true</required>
		<!-- rtexprvalue:runtime expression value:当前属性是否可以接受运行时表达式的动态值 -->
		<rtexprvalue>true</rtexprvalue>
  </attribute>
   <attribute>
  		<!-- 属性名 -->
  		<name>count</name>
  		<!-- 该属性是否必须 -->
  		<required>false</required>
		<!-- rtexprvalue:runtime expression value:当前属性是否可以接受运行时表达式的动态值 -->
		<rtexprvalue>false</rtexprvalue>
  </attribute>

 3). 在页面中使用属性,属性名同tld文件中定义的 名字。
 

	<zc:hello value="${param.name }" count="10"/>

 4).通常情况下开发简单标签直接继承SimpleTagSupport就可以了,可以直接调用其对应该getter方法得到对应的API
 源码
 

public class SimpleTagSupport implements SimpleTag {
    @Override
    public void doTag() throws JspException, IOException {
    }  
    
    private JspTag parentTag;
    @Override
    public void setParent( JspTag parent ) {
        this.parentTag = parent;
    }
    @Override
    public JspTag getParent() {
        return this.parentTag;
    }
    
    private JspContext jspContext;
    @Override
    public void setJspContext( JspContext pc ) {
        this.jspContext = pc;
    }
    protected JspContext getJspContext() {
        return this.jspContext;
    }
     
    private JspFragment jspBody;
    @Override
    public void setJspBody( JspFragment jspBody ) {
        this.jspBody = jspBody;
    }
    protected JspFragment getJspBody() {
        return this.jspBody;
    }
}
 	

4.带标签体的标签:
1).若一个标签有标签体:
<zc:testJspFragment>HelloWorld</zc:testJspFragment>
在自定义标签的标签处理器中使用JspFragment对象封装标签体信息。
2).若配置了标签含有标签体,则JSP引擎会调用setJspBody()方法
把 JspFragment 传递给标签处理器类
在SimpleTagSupport中,还定义了一个getJspBody()方法,用于返回JspFragment对象。
3).JspFragment的invoke(Writer)方法:
把标签体内容从Writer中输出,若为null则等同于invoke(getJspContext().getOut()),即直接把标签体内容输出到页面上

有时,可以借助于StringWriter,可以在标签处理器类中先得到标签体的内容:

 

//1.利用StringWriter得到标签体的内容
		StringWriter sw=new StringWriter();
		bodyContent.invoke(sw);
		
		//2.把标签体的内容都变为大写
		String content =sw.toString().toUpperCase();
		
		//3.获取JSP页面的out隐含对象,输出到页面上
		getJspContext().getOut().print(content);

4).在tld文件中,使用body-content及诶单来描述标签体的类型:
<body-content>:指定标签体的类型,大部分情况下,取值为scriptless。可能取值有3种:
empty:没有标签体
scriptless:标签体可以包含el表达式和JSP动作元素,但不能包含JSP的脚本元素
tagdependent:表示标签体交由标签本身去解析处理。
若指定tagdependent,在标签体中的所有代码都会原封不动的交给标签处理器,而不是将执行结果传递给标签处理器
  <body-content>tagdependent</body-content>
5).在定义一个自定义标签:<zc:printUpper time="10" >aasadd</zc>把标签体内容转换为大写,并输出time次到
浏览器上。
6).实现forEach标签:
--两个属性:items(集合类型,collection),var(String类型)
--doTag:
*遍历tiems对应的集合,
*把正在遍历的对象放入到pageContext中,键:var 值:正在遍历的对象
*把标签体的内容直接输出到页面上。

 

 

 

	<c:forEach items="${ requestScope.customers}" var="cust">
		${pageScope.cust.id }--${cust.name }<br>
	</c:forEach>

 

5.开发有父标签的标签:
1).父标签无法获取字标签的引用,父标签仅把字标签作为标签体来使用
2).字标签可以通过getParent()方法来获取父标签的引用(需要继承SimpleTagSupport或自实现SimpleTag接口的该方法):
若字标签的却咩有父标签,JSP引擎会把代表父标签的引用setParent(JspTag  parent)赋给标签处理器
3).注意:父标签的类型是JspTag类型。该接口是一个空接口,但是来统一SimpleTag和Tag的。实际使用需要进行类型的强制转换。

 

 

子标签代码:
	@Override
	public void doTag() throws JspException, IOException {
		//1.得到父标签的引用
		JspTag parent=getParent();
		//2.获得父标签的namee属性
		ParentTag parentTag=(ParentTag)parent;
		String name=parentTag.getName();
		//3.把name值打印到JSP页面上。
		getJspContext().getOut().print("字标签输出name:"+name);
	}
父标签代码:
	private String name="ZZCC";
	public String getName() {
		return name;
	}
	@Override
	public void doTag() throws JspException, IOException {
			
		System.out.println("父标签的标签处理器类name:"+name);
		getJspBody().invoke(null);
	}

4).在tld配置文件中,无需为父标签有额外的配置。但,子标签是以标签体的形式存在的,所以父标签的
  为<body-content>scriptless</body-content>
5).实现

<c:choose>
		<c:when test="${param.age>24}">大学毕业</c:when>
		<c:when test="${param.age>20}">高中毕业</c:when>
		<c:otherwise>高中以下学历</c:otherwise>
	</c:choose>

--开发3个标签 :choose,when,otherwise
--其中when标签有一个boolean类型的属性:test
--choose是when和otherwise的父标签,when在otherwise之前使用
--在父标签choose中定义一个“全局” 的boolean类型的flag:用于判断子标签在满足条件的情况下是否执行
*若when的test为true,且when的父标签的flag也为true,则执行when的标签体(正常输出标签体的内容),
同时把flag设置为flase
*若when的test为true,且when的父标签的flag为flase,则不执行标签体。
*若flag为true,otherwise执行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值