自定义标记的创建步骤
1.标记处理类的创建
2.自定义标记库的创建
3.自定义标记库的配置
4.自定义标记的使用
正文标签
—— 即对在开始和结束标签之间的内容进行操作的,
标签必须实现 BodyTag 接口。
简单标签
—— 不对其正文操作的标签称为 ,简单标签可以实现 Tag 接口
简单标签
第 1 步:创建一个实现了 Tag 接口的标签处理程序
Tag 接口定义了标签处理程序和 JSP 页实现类之间的基本协议。它定义了在标签开始和结束时调用的生存周期和方法。 为了编写标签处理程序,必须实现 Tag 接口。
int doStartTag() throws JspException 处理开始标签
int doEndTag() throws JspException 处理结束标签
Tag getParent()/void setParent(Tag t) 获得/设置标签的父标签
void setPageContext(PageContext pc) pageContext 属性的 setter 方法
void release() 释放获得的所有资源
TagSupport
通过继承 TagSupport 来实现 Tag 接口
在默认情况下,TagSupport 实现了 doStartTag() 以使它返回 SKIP_BODY
常量,表示将不对标签正文进行判断
。 此外,在默认情况下,doEndTag() 方法返回 EVAL_PAGE
,它表示 JSP 运行时引擎应当对页面的其余部分进行判断。
最后TagSupport 实现了 release(),它设置 pageContext 及其父元素为 null。
TagSupport 类还实现了 IterationTag 接口和 doAfterBody(),这样它就返回 SKIP_BODY。
第 2 步:创建一个 TLD 文件
TLD 文件通常保存在 Web 应用程序的 WEB-INF 目录,并在 web.xml 文件中声明。它们一般用 .tld 扩展名结束。
TLD 文件的根元素是 taglib。taglib 描述了一个 标签库 —— 即一组标签/标签处理程序对。
tlib-version 元素对应于标签库版本。
jsp-version 对应于标签库所依赖的 JSP 技术的版本。
short-name 元素定义了 IDE 和其他开发工具可以使用的标签库的简单名。
taglib 元素包含许多 tag 元素,标签库中每一个标签有一个 tag 元素
。
tag 元素用于将自定义标签映射到它们的自定义标签处理程序。
<name>
<tag-class>
<body-content>
第 3 步:在标签处理程序 Java 类中创建属性
第 4 步:在 TLD 文件中定义属性
<attribute>
name 元素指定属性的名字。
required 元素指定属性是否是必需的(默认值是 false)。
rtexprvalue 属性值是否可以为JSP表达式(类似于<%=…% >的表达式)。
第 5 步:实现 doStartTag() 方法
标签开始时调用 doStartTag() 方法
如果 doStartTag() 返回 SKIP_BODY,那么将不处理标签正文。
如果它返回一个 EVAL_BODY_INCLUDE,那么将处理正文。
<
%@taglib
prefix="my" uri="/mytag"%>
"/mytag"对应于web.xml文件中的<taglib-uri>/mytag</taglib-uri>
<my:hello/>
"my"对应于taglib指令的prefix属性值,"hello"对应于TLD文件中<tag>标记的<name>hello</name>
带属性的标记定义
标记处理类中的属性声明
标记库描述文件中的属性描述
带标记体内容的标记定义
BodyTagSuppport类
doAfterBody()方法
BodyContent类
getString()方法,标记处理类中获取标记体内容对象
简单标记定义
SimpleTagSupport类
doTag()方法
getJspContext()方法
getJspBody()方法
JspFragment类
invoke()方法
<tag>
<name>max</name>
<tag-class>tag.MaxTag</tag-class>
<body-content>empty</body-content>
<attribute>
<name>num1</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>num2</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
<taglib>
<taglib-uri>/mytag</taglib-uri>
<taglib-location>/WEB-INF/tlds/MyTaglib.tld</taglib-location>
</taglib>
如果在JSP的taglib指令中直接指定TLD文件的位置,不需要在web.xml中声明标记库的位置
<
%@taglib
uri="/WEB-INF/tlds/MyTaglib.tld" prefix="my"%>
带标记体内容的自定义标记
BodyTagSupport类-提供处理标记体的方法
常用方法:
BodyContent getBodyContent()-获取标记体对象
BodyContent类-标记体内容的输出流类,扩展于JSPWriter类
常用方法:
String getString()-以字符串形式返回标记体
JspWriter getEnclosingWriter()-获取对标记体进行写操作的流对象
创建标记处理类
要处理标记体,必须实现BodyTag接口,BodyTagSupport实现了该接口
在TLD文件中添加<tag>标记
使用自定义标记
要处理标记体,则doStartTag() 方法的返回值必须是EVAL_BODY_BUFFERED
要重复处理标记体,还需要改写doAfterBody()方法,该方法的返回值必须是EVAL_BODY_AGAIN,否则返回SKIP_BODY
doEndTag()方法中对标记体进行处理
public class GreetTag extends BodyTagSupport {
private int count=0;
public int doStartTag() throws JspException {
return EVAL_BODY_BUFFERED;
}
public int doAfterBody() throws JspException{
if(count<1){
count++;
return this.EVAL_BODY_AGAIN;
}
return this.SKIP_BODY;
}
public int doEndTag() throws JspException {
try {
this.pageContext.getOut().write(this.bodyContent.getString());
} catch (IOException ex) {
ex.printStackTrace();
}
return EVAL_PAGE;
}
}
<tag>
<name>greet</name>
<tag-class>tag.GreetTag</tag-class>
<body-content>JSP</body-content>
</tag>
简单标记类定义的一般步骤
从SimpleTagSupport类继承
改写doTag()方法,处理开始和结束标记
使用getJspContext()方法获取Jsp页面上下文对象
调用该对象的getOut()方法可以获取输出流对象
使用getJspBody()方法获取JspFragment对象
调用该对象的invoke()方法输出标记体内容
public class MySimpleTag extends SimpleTagSupport {
private String name;
public void setName(String name){
this.name=name;
}
public void doTag() throws JspException {
try {
this.getJspContext().getOut().write(name+",");
JspFragment f=getJspBody();
if (f != null) f.invoke(null);
} catch (IOException ex) {
}
}
}
<tag>
<name>welcome</name>
<tag-class>tag.MySimpleTag</tag-class>
<body-content>tagdependent</body-content>
<attribute>
<name>name</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
<body-content>tagdependent</body-content>表示标记体内容由标记自己去处理,不支持JSP脚本元素的使用
开发带标签体的标签
要开发带标签体的标签,可实现BodyTag接口,也可从BodyTag接口的实现类BodyTagSupport继承,为简化开发,推荐从BodyTagSupport类继承开发。
编写标签对应的实现类时,需要重载BodyTagSupport类几个方法:
doStartTag(), setBodyContent(), doInitBody(), doAfterBody(), doEndTag(),
他们执行顺序:
doStartTag()→doInitBody()→setBodyContent()→doAfterBody()→doEndTag()
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页面的后续内容将不再执行。
开发带标签体的标签
BodyTag.java
package body;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.BodyTagSupport;
public class bodyTag extends BodyTagSupport{
private int countNum=0;//循环显示时间的次数
private int currentNum=1;//当前执行次数
public int getCountNum() {
return countNum;
}
public void setCountNum(int countNum) {
this.countNum = countNum;
this.currentNum=1;
}
//----标签开始时调用此方法-------
public int doStartTag(){
try{
JspWriter out=pageContext.getOut();
out.print("标签开始了:");
if(countNum>0)
return EVAL_BODY_TAG;
else
return SKIP_BODY;
}catch(Exception e){
System.out.println(e);
return SKIP_BODY;
}
}
//----标签体执行完后调用此方法----
public int doAfterBody(){
try{
JspWriter out=pageContext.getOut();
out.print("第"+currentNum+"次执行标签体。标签体执行完毕");
if(countNum>1){//如果还需要执行标签体
countNum--;
currentNum++;
return EVAL_BODY_TAG;
}else
return SKIP_BODY;
}catch(Exception e){
System.out.println(e);
return SKIP_BODY;
}
}
//----标签结束时调用此方法-------
public int doEndTag(){
try{
JspWriter out=pageContext.getOut();
//----输出标签体的内容----
bodyContent.writeOut(bodyContent.getEnclosingWriter());
out.print("标签结束了。");
}catch(Exception e){
System.out.println(e);
}
return EVAL_PAGE;
}
}
开发嵌套的标签
开发迭代的标签
Tag 中定义:
SKIP_BODY隐含0 :不处理标签体,直接调用doEndTag()方法
EVAL_BODY_INCLUDE隐含1:解析标签体,但绕过 doInitBody () 和 setBodyContent () 方法
SKIP_PAGE隐含5 :不解析标签后面的JSP内容
EVAL_PAGE隐含6:解析标签后,继续解析标签后面的JSP内容
IterationTag 中定义:
EVAL_BODY_AGAIN = 2;
BodyTag 中定义:
EVAL_BODY_BUFFERED = 2; // 将会再一次调用doAferBody方法直到返回SKIP_BODY
在doAferBody中返回SKIP_BODY,表示终止标记正文处理;
若返回的是 EVAL_BODY_BUFFERED ,将会再一次调用doAferBody方法,重新处理标记正文,直到返回SKIP_BODY为止。
Tag 方法
可返回的静态常量
doStartTag
SKIP_BODY 不处理标签体,直接调用doEndTag()方法
EVAL_BODY_INCLUDE解析标签体,但绕过 doInitBody () 和 setBodyContent () 方法
EVAL_BODY_AGAIN
EVAL_BODY_BUFFERED 将会再一次调用doAferBody方法
doInitBody
做标签一些初始化工作,无返回值
setBodyContent
在 doInitBody 之后执行,使用setBodyContent得到JSP页面中标签体之间内容
doAfterBody
最终必须返回SKIP_BODY ,否则可能导致OutOfMemoryError,可参考上面①
doEndTag
SKIP_PAGE/EVAL_PAGE
public int doAfterBody() throws JspException {
try {
this.pageContext.getOut().write("<br>");
} catch (IOException e) {
e.printStackTrace();
}
if(cou>1){
cou–;
return this.EVAL_BODY_AGAIN;
}else{
return this.SKIP_BODY; // 最终必须返回SKIP_BODY
}
}
body-content :
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动作。如上述②使用<body-content> scriptless </body-content> 则报错,具体可参考后面附源码。
3. Taglib的部署
简单部署
方式一
编写tld文件,并且放置到WEB-INF目录或创建子目录,然后在JSP中,使用taglib指令,指定URI即可:
<%@ taglib prefix=”topxp” uri=”/WEB-INF/mytaglib.tld” %>
这个指令,直接指向一个tld文件。
方式二
也可以在web.xml中用taglib-uri和taglib-location标记来定义它的URI和位置的映射,然后在JSP中指定URI的时候,
就直接使用在web.xml中定义的URI即可,这个就不举例子了。
打包部署
你也可以将taglib打成jar包,这个时候,你的taglib描述文件(tld文件),必须被放置在jar文件内的META-INF目录(或子目录)下。你可以在这个目录下,放置多个tld文件。
如果将taglib打包,这个jar包必须被放置在web-inf/lib目录下。在jar包的meta-inf目录下的tld文件,都可以被自动发现,不需要显式的定义其位置。
JSP使用方式一:用URI直接指定jar文件的位置
Jsp中可以使用下面的指令来指定tld文件的位置:
<%@ taglib prefix=”topxp” uri=”/WEB-INF/lib/topxptaglib.jar” %>
在这种情况下,因为没有直接指定tld文件的位置,所以,tld文件必须遵守一定的命名规则。规则就是:
Tld文件必须命名为:taglib.tld。这样,在meta-inf目录下,只能放置一个tld文件,无法支持多个tld文件。
JSP使用方式二:使用定制的URI
如果需要在一个jar包中包含多个tld文件,你必须使用某种方式来区分这些tld文件,这种方式就是:
在tld文件中,用<uri>标记来区别不同的tld文件
。如,可以加入下面的<uri>标记进topxptaglib.jar中的tld文件:<uri>
/my_tags
</uri>
在我们的例子中,假设命名为topxp.tld,下面就是topxp.tld文件的内容,请注意添加了<uri>标记:
<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["系统自定义标签"]]></description>
<display-name>"Custom Tags"</display-name>
<tlib-version>1.0</tlib-version>
<short-name>myTag</short-name>
<uri>/my_tags</uri>
<tag>
<name>out</name>
<tag-class>org.topxp.taglib.OutTag</tag-class>
<body-content>empty</body-content>
<attribute>
<name>name</name>
<required>false</required>
<rtexprvalue>false</rtexprvalue>
</attribute>
</tag>
</taglib>
分享到:
相关推荐
在JavaServer Pages (JSP) 开发中,自定义标签库是提高代码可重用性和模块化的重要手段。本文将详细讲解如何利用JSP自定义标签库实现数据列表的显示,以及涉及到的相关技术。 首先,`UserListTag.java` 是自定义...
### 自定义标签库制作详解 #### 一、引言 自定义标签库是Java Server Pages (JSP) 技术中的一个重要组成部分,它允许开发者创建可重用的、功能丰富的HTML标签,这些标签可以像标准HTML标签一样在JSP页面中使用。...
在Java服务器页面(JSP)开发中,自定义标签库是一种强大的工具,它允许开发者创建可重用的组件,提高代码的可读性和维护性。本教程将深入讲解JSP自定义标签库的学习,包括其原理、配置以及如何创建和使用自定义标签...
【jsp自定义标签库注意事项】 在Java服务器页面(JSP)开发中,自定义标签库是一种强大的工具,它能够帮助开发者创建可重用的代码片段,提高代码的可读性和可维护性。以下是对JSP自定义标签库的详细解释和使用注意...
在JavaWeb开发中,自定义标签库和JSTL(JavaServer Pages Standard Tag Library)是两个重要的组件,它们极大地提高了代码的可读性和可维护性。本教程将深入探讨这两个主题,帮助开发者更好地理解和应用它们。 一、...
### jsp自定义标签库知识点详解 #### 一、什么是jsp自定义标签? 1. **概念**:JSP 自定义标签是一种将复杂的功能封装成一个简单的标签的方式,它允许开发者创建可重用的代码组件,这些组件可以在 JSP 页面中像...
**JSP自定义标签库详解** 在JavaServer Pages (JSP) 技术中,自定义标签库(Custom Tag Libraries)是一种强大的特性,允许开发者创建可重用的、封装复杂功能的标签,使得JSP页面更加简洁易读。这篇内容将深入探讨...
自己写的自定义标签库,实现JSTL常用的功能。
### Taglib自定义标签库详解 #### 一、Taglib简介与作用 Taglib,即Tag Library(标签库),是JavaServer Pages (JSP) 技术中的一个重要组成部分,允许开发者创建可重用的定制标签,这些标签可以封装复杂的业务...
第15章 自定义标签库,js的p基础知识
### JSP通过自定义标签库实现数据列表显示的方法 #### 一、引言 在Web开发中,JSP(JavaServer Pages)作为一种广泛使用的服务器端技术,为动态网页的创建提供了强大的支持。为了提高开发效率和代码的复用性,...
【自定义TLD标签库源码加视频】这个主题涵盖了Java服务器端开发中的一个重要概念——自定义标签库(Tag Library)及其源代码分析。在Java Web应用开发中,TLD(Tag Library Descriptor)文件用于定义自定义JSP标签,...
在JSP页面中,通过`指令`引入自定义标签库,并使用`属性...</tag-name>`的格式调用自定义标签。 **二、自定义标签函数** 自定义标签函数是在JSP 2.0中引入的一种新的特性,它允许开发者像使用EL(Expression ...
本文实例讲述了ThinkPHP分组下自定义标签库的实现方法。分享给大家供大家参考。具体如下: 自定义标签库应该位于ThinkPHP\\Extend\\Driver\\TagLib目录下 1 新建标签类库文件名为TagLibBlog.class.php。 2 编辑刚才...
二、创建自定义标签库 1. 创建 Tag 类:首先,我们需要创建一个 Java 类,该类继承自 `org.apache.struts.taglib.Tag` 或其子类,例如 `org.apache.struts.taglib.bean.WriteTag`。在这个类中,我们将定义标签的...
本文将深入讲解JSP自定义标签的相关概念、格式、处理过程以及创建和使用自定义标签库的基本步骤。 1. 基本概念: - **标签**:JSP标签是XML元素,用于简化JSP页面,使其更易读且支持多语言版本。标签名和属性区分...