使用tld文件自定义jsp标签库

目录

一,标签库描述文件(tld文件)

二,标签处理类

三,在JSP页面中使用自定义的标签

四,举个例子


通过Java的TagSupport类或者BodyTagSupport类,和配套的tld文件,可以定义自己的jsp标签。

TagSupport类和BodyTagSupport类在jsp-api.jar中,这个jar包在tomcat的lib目录下有,maven里面也有。

 

一,标签库描述文件(tld文件)

tld的全名:Tag Library Descriptor

tld文件是一个XML文件,是自定义标签库的配置文件。

这个文件应该放在web项目的WEB-INF目录下,或其子目录下,如果放在其他位置,需要在web.xml文件中做配置。

 

下面是一个简单的标签库描述文件的例子:

myFirstTag.tld




    1.0
    1.2
    testTagLib
    /test-tags
    "自定义标签"
    
        TagA
        com.mytest.TagA
        jsp
        这个一个标签
        
            attributeA
            true
            true
            属性A
        
    
    
        TagB
        com.mytest.TagB
        jsp
        这个一个标签
        
            attributeA
            true
            true
            属性A
        
    

文件的主体是元素,其中的元素有:

,taglib版本

,jsp版本

,标签库名字

,标签库地址,在页面使用标签库时会用到

,描述

,具体的标签列表,可以配置多个

 

其中的元素,每个元素代表一个自定义的标签,可以有这些子元素:

,标签名字,在页面使用标签时会用到

,标签处理类

,empty、scriptless、JSP、tagdependent

,标签描述,可以配置多个

,标签参数列表,可以配置多个

 

其中的元素,每个元素代表一个属性,可以有这些子元素:

,属性名字,在页面使用标签时会用到

,是否必填,只能是true或false

,全称Run-time Expression Value,是否支持EL表达式,只能是true或false。如果设置为true,在页面可以用这种写法:attributeA="<%=name>"

,属性描述

 

二,标签处理类

标签处理类是在描述文件中用元素标识出的java类,这个类可以选择继承javax.servlet.jsp.tagext.TagSupport类或javax.servlet.jsp.tagext.BodyTagSupport类,其中BodyTagSupport是TagSupport的子类。

如果选择继承TagSupport类,可以重写以下方法:

public int doStartTag()

public int doEndTag()

public int doAfterBody()

如果选择继承BodyTagSupport类,可以额外重写以下方法:

public void setBodyContent(BodyContent b)

public void doInitBody()

 

下面分别介绍这几个方法:

doStartTag()

这是在java开始处理头标签时执行的方法,可以在这里构造将要输出到页面的代码,或者做其他的处理。

这个方法的返回值是int,有以下选择:

1,EVAL_BODY_INCLUDE。

这个静态变量在javax.servlet.jsp.tagext.Tag接口中,实际值是1。

这个返回值表示正常加载标签的body(也就是标签的innerHTML)。

2,SKIP_BODY。

这个静态变量在javax.servlet.jsp.tagext.Tag接口中,实际值是0。

这个返回值表示不会加载标签的body。一般情况下doStargTag()方法返回这个值后将执行doEndTag()方法。

3,EVAL_BODY_BUFFERED。

这个静态变量在javax.servlet.jsp.tagext.BodyTag接口中,实际值是2。

只有处理类继承了BodyTagSupport时可以使用(详见下面的类继承关系图)。

这个返回值用来在后面的代码中处理标签的body。当使用这个返回值时,Java会构造一个BodyContent对象,并把标签的body载入这个对象。

另外,BodyContent对象内部也有一个JspWriter,可以用BodyContent对对象的body进行处理。是否可以修改body是BodyTagSupport和TagSupport最大的区别。

注意:如果使用了这个返回值并重写了相关方法,需要在代码中显式写明body部分的加载,否则body只会写入BodyContent对象而不会加载到页面。

 

doEndTag()

这是在java开始处理尾标签时执行的方法,这个方法中也可以构造将要输出到页面的代码,或者其他处理。

这个方法的返回值是int,有以下选择:

1,EVAL_PAGE。

这个静态变量在javax.servlet.jsp.tagext.Tag接口中,实际值是6。

这个返回值表示继续加载此标签之后的页面代码。

2,SKIP_PAGE。

这个静态变量在javax.servlet.jsp.tagext.Tag接口中,实际值是5。

这个返回值表示不再继续加载此标签之后的页面代码,直接将jsp现有已经处理完的页面代码发送给客户端。

没有想到什么情况下用得着这个返回值。

 

doAfterBody()

这个方法在doStartTag()方法返回EVAL_BODY_INCLUDE并且加载完标签的body后加载。

这个方法的返回值是int,有以下选择:

1,EVAL_BODY_AGAIN。

这个静态变量在javax.servlet.jsp.tagext.IterationTag接口中,实际值是5。

这个返回值表示再次加载标签的body。

按照执行顺序,再次加载一次body之后会再次执行这个方法,注意不要写成死循环。

2,SKIP_BODY。

同doStartTag()方法的同名返回值。

java不会再加载标签的body,向后执行。一般情况下后面将执行doEndTag()方法。

 

setBodyContent(BodyContent b)

这个方法是在调用doStartTag()方法,并返回EVAL_BODY_BUFFERED之后调用的。BodyTagSupport子类专用。

Java构造了BodyContent对象之后调用这个方法把BodyContent对象传给处理类,BodyTagSupport类中这个方法里面只有一行:

this.bodyContent = b;

如果重写了这个方法,至少也要把这行加上,否则无法使用BodyContent对象。

该方法没有返回值。

 

doInitBody()

该方法在调用setBodyContent(BodyContent b)方法后执行,可以对body进行一些初始化工作。BodyTagSupport子类专用。

BodyTagSupport类中这个方法里面没有代码。

这个方法没有返回值。

 

上述类和接口的关系图大概是这样的:

使用tld文件自定义jsp标签库_第1张图片

 

当java处理标签时,根据返回值的不同,方法的调用顺序大概是这样的:

使用tld文件自定义jsp标签库_第2张图片

 

三,在JSP页面中使用自定义的标签

1,在JSP页面中,首先要引用标签库:

<%@ taglib prefix="t" uri="/test-tags"%>

prefix是标签前缀,和标签库中的不一定相同。

uri参数和标签库中的必须相同。

2,引用了标签库之后,就可以使用自定义的标签了:

         number2:

上面的例子就是有body的标签,body就是

number2:

这一部分,通过调整方法的返回值可以控制该部分是否显示。

 

四,举个例子

1,首先是tld标签描述文件

myFirstTag.tld




    1.0
    1.2
    testTagLib
    /test-tags
    "自定义标签"
    
        TagA
        com.mytest.TagA
        jsp
        这是一个标签
        
            attributeA
            true
            true
            属性A
        
    
    
        TagB
        com.mytest.TagB
        jsp
        这是一个标签
        
            attributeA
            true
            true
            属性A
        
    

在这个描述文件中定义了两个标签,TagA和TagB

 

2,标签TagA的处理类TagA.java

TagA.java

package com.mytest;

import java.io.IOException;

import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.BodyContent;
import javax.servlet.jsp.tagext.BodyTagSupport;
import javax.servlet.jsp.tagext.TagSupport;

public class TagA extends BodyTagSupport{
	
	private static final long serialVersionUID = 1L;
	
	protected String attributeA;

	public String getAttributeA() {
		return attributeA;
	}

	public void setAttributeA(String attributeA) {
		this.attributeA = attributeA;
	}
	
	@Override
	public int doStartTag(){
		JspWriter w=this.pageContext.getOut();
		StringBuffer sb = new StringBuffer();
		sb.append("
"); sb.append("number1:
"); try { w.print(sb.toString()); w.flush(); } catch (IOException e) { e.printStackTrace(); } if("extra".equals(attributeA)){ return EVAL_BODY_INCLUDE; // return EVAL_BODY_BUFFERED; }else{ return SKIP_BODY; } } @Override public void setBodyContent(BodyContent bodyContent) { System.out.println("setBodyContent..."); this.bodyContent = bodyContent; } @Override public void doInitBody() throws javax.servlet.jsp.JspException { }; @Override public int doAfterBody() throws javax.servlet.jsp.JspException { String a=""; if(this.bodyContent!=null&&a.equals("")){ String html=this.bodyContent.getString(); System.out.println(html); return SKIP_BODY; }else{ return SKIP_BODY; } } @Override public int doEndTag(){ JspWriter w=this.pageContext.getOut(); StringBuffer sb = new StringBuffer(); sb.append("
"); sb.append("
"); try { w.print(sb.toString()); w.flush(); } catch (IOException e) { e.printStackTrace(); } if("extra".equals(attributeA)){ return EVAL_PAGE; }else{ return SKIP_PAGE; } } }

这个类重写了doStartTag(),doEndTag()和doAfterBody()等方法,其中doAfterBody()方法里面没写什么东西,和父类的原方法保持一致。

这个处理类的功能是把自定义的标签写成了一个form表单,并添加了名为number1的文本框,当属性attributeA等于extra时显示number2文本框,并且正常加载标签后面的网页内容,否则不会显示number2文本框,并且立即结束页面加载,发送给客户端。

 

3,JSP页面

testTagPage.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="testTagLib" uri="/test-tags"%>



TestTagPage


extra

	number2:

number3:


no extra number2: number3:

这个页面显示出来是这样的:

使用tld文件自定义jsp标签库_第3张图片

分析一下:

当java第一次加载TagA标签时(分隔线上面部分),属性attributeA等于extra,

doStartTag()方法返回值是EVAL_BODY_INCLUDE,表示正常加载body部分的页面代码,

doEndTag()方法返回值是EVAL_PAGE,表示正常加载标签后面的内容,所以第二个TagA标签才得以加载。

当java第二次加载TagA标签时(分隔线下面部分),属性attributeA等于noextra,

doStartTag()方法返回值是SKIP_BODY,表示不会加载body部分的页面代码,

doEndTag()方法返回值是SKIP_PAGE,表示不会加载标签后面的内容,所以第二个TagA标签后面的number3标签和标签都没有加载。

浏览器实际收到的页面代码是这样的:







TestTagPage





extra

number1:
         number2:
number3:
no extra
number1:

 

以上就是自定义JSP标签的介绍,通过此功能可以组建自己更强大更高效的标签库。

你可能感兴趣的:(Java)