1标签(Tag):
标签是一种XML元素,通过标签可以使JSP网页变得简洁并且易于维护,还可以方便地实现同一个JSP文件支持多种语言版本。由于标签是XML元素,所以它的名称和属性都是大小写敏感。
标签库(Tag library):
由一系列功能相似、逻辑上互相联系的标签构成的集合称为标签库。
标签库描述文件(Tag Library Descriptor):
标签库描述文件是一个XML文件,这个文件提供了标签库中类和JSP中对标签引用的映射关系。它是一个配置文件,和web.xml是类似的。
标签处理类(Tag Handle Class):
标签处理类是一个Java类,这个类继承了TagSupport或者扩展了SimpleTag接口,通过这个类可以实现自定义JSP标签的具体功能。
2自定义JSP标签的处理过程:
JSP文件中引入标签库:
<% @ taglib prefix="taglibprefix" uri="tagliburi"%>
JSP页面中通过taglibprefix来使用标签库标签。uri的取值为web.xml中<taglib-uri>/myTag</taglib-uri>的值。
Web容器根据JSP页面中的"taglibprefix",获得声明中的taglib的uri属性值
Web容器根据uri属性在web.xml找到对应的元素
<taglib>
<taglib-uri>/myTag</taglib-uri>
<taglib-location>/WEB-INF/myTag.tld</taglib-location>
</taglib>
<taglib-uri>对应tld文件中标签库中的<uri>的值,<taglib-location>指出tld文件的位置。
Web容器根据元素的值从WEB-INF/目录下找到对应的.tld文件
从.tld文件中找到与tagname对应的元素
从元素中获得对应的元素的值
Web容器根据元素的值创建相应的tag handle class的实例
Web容器调用这个实例的doStartTag/doEndTag方法完成相应的处理
3两种标签:
javax.servlet.jsp.tagext.Tag
javax.servlet.jsp.tagext.BodyTag
有标签体的标签必须实现 BodyTag 接口。
<jsptag:map scope="session" name=“tagMap”>
body
</jsptag:map>
也可能没有标签体:
<jsptag:map/>
无标签体的简单标签可以实现 Tag 接口。
4创建和使用一个Tag Library的基本步骤:
创建标签的处理类(Tag Handler Class)
创建标签库描述文件(Tag Library Descriptor File)
在web.xml文件中配置元素。
在JSP文件中引入标签库。
如何创建标签库描述文件(Tag Library Descriptor File)
标签库描述文件,简称TLD,采用XML文件格式,定义了用户的标签库。TLD文件中的元素可以分成3类:
标签库元素,标签元素,标签属性元素。
标签库元素用来设定标签库的相关信息,它的常用属性有:
shortname: 指定Tag Library默认的前缀名(prefix)
uri: 设定Tag Library的惟一访问标识符
标签元素用来定义一个标签,包含在标签库元素中。它的常见属性有:
name: 设定Tag的名字
tagclass: 设定Tag的处理类
bodycontent: 设定标签的主体(body)内容,bodycontent的取值有:
tagdependent:标签体内容 直接被写入BodyContent,由自定义标签类来进行处理,而不被JSP容器解释。如下:
<test:myList>
select name,age from users
</test:myList>
JSP:接受所有JSP语法,如定制的或内部的tag、scripts、静态HTML、脚本元素、JSP指令和动作。如:
<my:test>
<%=request.getProtocol()%>
</my:test>
empty:空标记,即起始标记和结束标记之间没有内容。
下面几种写法都是有效的,
<test:mytag />
<test:mytag uname="Tom" />
<test:mytag></test:mytag>
scriptless: 接受文本、EL和JSP动作
标签属性元素用来定义标签的属性,包含在标签元素中。它的常见属性有:
name:属性名称
required:属性是否必需的,默认为false
rtexprvalue:属性值是否可以为request-time表达式,也就是类似于<%=…% >的表达式。
rtexprvalue设置为true,表示标签体支持运行时的表达式取值,如果为false则表示标签体为一个静态文本,默认情况下设置为true。
如果标签元素中设置了属性,则在标签处理类里提供该属性相应的set方法。
例如:WEB-INF\tlds\test.tld
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<taglib xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
version="2.0"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd">
<description><![CDATA["To make it easier to access dynamic data;"]]></description>
<display-name>Dgzz Tags</display-name>
<tlib-version>6</tlib-version>
<short-name>test</short-name> //标签库名,也称为前缀。比如“<c:out value=""/>” 里的“c”
<uri>/WEB-INF/tlds/test</uri> //在jsp页面上引用的路径
<tag> //标签
<name>out</name> //定义标签的名 例如“<test:out attrName=""/>“里的"out”,
<tag-class>gdufs.tags.OutputTag</tag-class> //指出标签处理程序类 记着带包名
<body-content>empty</body-content> //如果没有标签体,设置empty , 如果有标签体必须设置JSP
<attribute>
<name>name</name>//属性名字。例如<test:out attrName=""/>里的attrName。名字可任意取,只要标签处理类里提供相应的set方法即可。
<required>false</required> //是否必填属性
<rtexprvalue>false</rtexprvalue> //是否支持运行时表达式取值就是是否可以是${}方式传值。"
</attribute>
</tag>
</taglib>
5如何创建标签处理类:
引入必需的资源。
继承TagSupport类并覆盖doStartTag()/doEndTag()方法(TagSupport类实现了Tag接口)。
TagSupport类简介:
处理标签的类必须扩展javax.servlet.jsp.TagSupport
TagSupport类的主要属性:
parent属性:代表嵌套了当前标签的上层标签的处理类。
pageContext属性:代表Web应用中的javax.servlet.jsp.PageContext对象。
JSP容器在调用doStartTag或者doEndTag方法前,会先调用setPageContext和setParent方法,设置pageContext和parent。因此在标签处理类中可以直接访问pageContext变量。
在TagSupport的构造方法中不能访问pageContext成员变量,因为此时JSP容器还没有调用setPageContext方法对pageContext进行初始化。
TagSupport处理标签的方法:
public int doStartTag() throws JspException
public int doEndTag() throws JspException
doStartTag:当JSP容器遇到自定义标签的起始标志,就会调用doStartTag()方法。doStartTag()方法返回一个整数值,用来决定程序的后续流程。
Tag.SKIP_BODY:跳过了开始和结束标签之间的代码
Tag.EVAL_BODY_INCLUDE:表示标签之间的内容被正常执行
doEndTag:但JSP容器遇到自定义标签的结束标志,就会调用doEndTag()方法。doEndTag()方法也返回一个整数值,用来决定程序后续流程。
Tag.SKIP_PAGE:表示立刻停止执行网页,网页上未处理的静态内容和JSP程序均被忽略任何已有的输出内容立刻返回到客户的浏览器上。
Tag.EVAL_PAGE:表示按照正常的流程继续执行JSP网页。
例如:
public int doEndTag() throws JspException
{
try {
.......
} catch (Exception e) { throw new JspException(e); }
return EVAL_PAGE; //EVAL_PAGE 表示tag已处理完毕,返回jsp页面
}
6下面是一个自定义标签的简单示例:
首先我们创建一个标签处理类继承自TagSupport :
package action;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.TagSupport;
public class MyTLD extends TagSupport {
private String name=null; //对应tld中属性,
public void setName(String name) {
this.name = name;
}
public int doEndTag() throws JspException
{
try {
JspWriter out = pageContext.getOut(); //如何输出到jsp页面
out.print("Hello! " + name);
} catch (Exception e) { throw new JspException(e); }
return EVAL_PAGE; //EVAL_PAGE 表示tag已处理完毕,返回jsp页面
}
}
然后我们再创建标签库描述文件(WEB-INF/tlds/mytld.tld)
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!--设定标签库-->
<taglib xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
version="2.0"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd">
<description><![CDATA["To make it easier to access dynamic data;"]]></description>
<display-name>Dgzz Tags</display-name>
<tlib-version>6</tlib-version>
<!--指定Tag Library默认的前缀名(prefix)-->
<short-name>test</short-name>
<!--设定Tag Library的惟一访问标识符,taglib下面只能有一个uri-->
<uri>/testTLD</uri>
<!--设定标签-->
<tag>
<!--设定标签名称-->
<name>out</name>
<!--设定标签处理类-->
<tag-class>action.MyTLD</tag-class>
<body-content>empty</body-content>
<!--设定标签属性-->
<attribute>
<name>name</name>
<required>false</required>
<rtexprvalue>false</rtexprvalue>
</attribute>
</tag>
</taglib>
然后web.xml中进行配置:
<jsp-config>
<taglib>
<taglib-location>/WEB-INF/tlds/mytld.tld</taglib-location>
<taglib-uri>/testTLD</taglib-uri>
</taglib>
</jsp-config>
最后在JSP中引入标签库并使用:
<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix ="t" uri = "/testTLD" %>
<html>
<body>
/*使用自定义标签库/testTLD中的out标签,并给标签的name属性赋值*/
Test Tag: <t:out name="TEST"/>
</body>
</html>
注意我们也可以不再web.xml进行配置,那么我们在JSP页面必须给出uri关于tld的文件完整路径如:
<%@ taglib prefix ="t" uri = "/WEB-INF/tlds/mytld.tld" %>
7带标签体的标签
要开发带标签体的标签,可实现BodyTag接口,也可从BodyTag接口的实现类BodyTagSupport继承,为简化开发,推荐从BodyTagSupport类继承开发。
编写标签对应的实现类时,需要重载BodyTagSupport类几个方法:doStartTag(), setBodyContent(), doInitBody(), doAfterBody(), doEndTag(),他们执行顺序如下:
doStartTag()→doInitBody()→setBodyContent()→doAfterBody()→doEndTag()。
doStartTag,返回SKIP_BODY 、EVAL_BODY_INCLUDE、EVAL_BODY_AGAIN/EVAL_BODY_BUFFERED
doInitBody,做标签一些初始化工作,无返回值。
setBodyContent方法,在doInitBody之后执行,使用setBodyContent得到JSP页面中标签体之间内容。
doAfterBody方法,最终必须返回SKIP_BODY ,否则可能导致OutOfMemoryError。
doEndTag方法,返回SKIP_PAGE/EVAL_PAGE。
注意其中的 doInitBody/setBodyContent 方法在自定义标签实现了 BodyTag 接口或继承BodyTagSupport才可以使用 。
doStartTag()方法可返回EVAL_BODY_INCLUDE或SKIP_BODY,如果返回EVAL_BODY_ INCLUDE则继续执行;如果返回SKIP_BODY则接下来的doInitBody(),setBodyContent(), doAfterBody()三个方法不会被执行,而直接执行doEndTag()方法。
setBodyContent()方法用于设置标签体内容,如果在此之前要作一些初始化工作,则在doInitBody()方法中完成。
标签体内容执行完后,会调用doAfterBody()方法,此方法可返回EVAL_BODY_TAG, SKIP_BODY, EVAL_PAGE或SKIP_PAGE。如果返回EVAL_BODY_TAG则会再次设置标签体内容,直到返回SKIP_BODY;如果返回EVAL_PAGE则标签体执行完后会继续执行JSP页面中接下来的部分;如果返回SKIP_PAGE,则JSP页面的后续内容将不再执行。
8SimpleTag标签
JSP2.0中为了简化标签的复杂性,增加了制作Simple Tag的标签类SimpleTagSupport类。SimpleTagSupport类是实现SimpleTag接口的。它只需要实现一个doTag()方法即可,而不需要一堆回传值。例如:
package action;
import java.io.IOException;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.SimpleTagSupport;
public class mytld2 extends SimpleTagSupport
{
private String kehu;
public void setKehu(String kehu)
{
this.kehu = kehu;
}
public void doTag() throws JspException,IOException{
JspWriter out=this.getJspContext().getOut();
out.println("this is SimpleTagSupport:"+kehu);
}
}
其对应的tld文件如下:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<taglib xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
version="2.0"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd">
<description><![CDATA["To make it easier to access dynamic data;"]]></description>
<display-name>Dgzz Tags</display-name>
<tlib-version>6</tlib-version>
<short-name>mytld</short-name>
<uri>/mytld></uri>
<tag>
<name>out</name>
<tag-class>action.mytld2</tag-class>
<body-content>empty</body-content>
<attribute>
<name>kehu</name>
<required>false</required>
<rtexprvalue>false</rtexprvalue>
</attribute>
</tag>
</taglib>
SimpleTag标签与带标签体的标签
package action;
import java.io.IOException;
import java.io.StringWriter;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.JspFragment;
import javax.servlet.jsp.tagext.SimpleTagSupport;
public class mytld3 extends SimpleTagSupport
{
public void doTag() throws JspException,IOException{
//fragment封装了标签体
JspFragment fragment=this.getJspBody();
JspWriter out=this.getJspContext().getOut();
StringWriter sout=new StringWriter();
//将标签体的内容写到指定的输出流,如果取值为null表示写入预设的getJspContext.getOut()取得的输出流对象
//这里我们将它指定到StringWriter字符输出流中。
fragment.invoke(sout);
String msg=sout.toString();
out.println(msg+"(body in String writer)");
}
}
对应的tld文件(mytld3.tld)如下:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<taglib xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
version="2.0"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd">
<description><![CDATA["To make it easier to access dynamic data;"]]></description>
<display-name>Dgzz Tags</display-name>
<tlib-version>6</tlib-version>
<short-name>bodytld</short-name>
<uri>/bodytld</uri>
<tag>
<name>showBody</name>
<tag-class>action.mytld3</tag-class>
<!-- tagdependent:标签体内容 直接被写入BodyContent,由自定义标签类来进行处理,而不被JSP容器解释 -->
<body-content>tagdependent</body-content>
</tag>
</taglib>
然后再web.xml中配置该tld
<taglib>
<taglib-location>/WEB-INF/tlds/mytld3.tld</taglib-location>
<taglib-uri>/bodytld</taglib-uri>
</taglib>
在jsp中应用该标签
<%@ taglib prefix ="t3" uri = "/bodytld" %>
....
<t3:showBody>
select * from Table
</t3:showBody>
运行结果如下:
select * from Table (body in String writer)
**********JspWriter与PrintWriter的区别:**********
JspWriter可以在JSP页面中直接用out对象输出.可以用pageContext.getOut();得到JspWriter对象.
PrintWriter在JSP页面中必须用response.getWriter();方法得到其对象.二者作用域不同.
不管JspWriter与PrintWriter在程序中的顺序怎么样,始终先会输出PrintWriter中的数据然后再输出JspWriter中的数据.
*********web.xml配置标签<taglib>***************
如果是头是这样的<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
直接在后面加上
<taglib>
<taglib-uri>/testTLD</taglib-uri>
<taglib-location>/WEB-INF/struts-logic.tld</taglib-location>
</taglib>
如果头是这样的
<web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.4" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
在后面加上
<jsp-config>
<taglib>
<taglib-uri>/testTLD</taglib-uri>
<taglib-location>/WEB-INF/validator-user.tld</taglib-location>
</taglib>
</jsp-config>
注意
web.xml中的<taglib-uri>/testTLD</taglib-uri>
tld文件中的<uri>/testTLD</uri>
jsp文件中的<%@ taglib prefix ="t" uri = "/testTLD" %>
这三个地方的uri是一致的。
**************************
一个tld中可以放置多个自定义标签
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<taglib xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
version="2.0"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd">
<description><![CDATA["To make it easier to access dynamic data;"]]></description>
<display-name>oode Tags</display-name>
<tlib-version>6</tlib-version>
<short-name>grant</short-name>
<uri>/grantTag</uri>
<!-- grant标签 -->
<tag>
<name>grant</name>
<tag-class>oode.pub.tag.GrantTag</tag-class>
<body-content>JSP</body-content>
<attribute>
<name>menuCode</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
<!-- switch标签 -->
<tag>
<name>switch</name>
<tag-class>oode.pub.tag.SwitchTag</tag-class>
<body-content>empty</body-content>
<attribute>
<name>type</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>value</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
</taglib>
web.xml配置:
<jsp-config>
<taglib>
<taglib-uri>/grantTag</taglib-uri>
<taglib-location>/WEB-INF/tlds/grantTag.tld</taglib-location>
</taglib>
</jsp-config>
在JSP用引入:<%@ taglib prefix ="oode" uri = "/grantTag" %>
<oode:switch type="menuLevel" value="${data.level}"/>
<oode:grant menuCode="0-cml-dly-0t1-maa">
<span onclick="showUpdateMenu(‘${data.menuID}‘)">修改</span>
</oode:grant>
10JSP自定义标签
原文:http://blog.csdn.net/bin71722/article/details/51915678