`
foryougeljh
  • 浏览: 116557 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

自定义标签库

 
阅读更多

自定义标记的创建步骤
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>


分享到:
评论

相关推荐

    jsp自定义标签库实现数据列表显示

    在JavaServer Pages (JSP) 开发中,自定义标签库是提高代码可重用性和模块化的重要手段。本文将详细讲解如何利用JSP自定义标签库实现数据列表的显示,以及涉及到的相关技术。 首先,`UserListTag.java` 是自定义...

    原创-自定义标签库制作

    ### 自定义标签库制作详解 #### 一、引言 自定义标签库是Java Server Pages (JSP) 技术中的一个重要组成部分,它允许开发者创建可重用的、功能丰富的HTML标签,这些标签可以像标准HTML标签一样在JSP页面中使用。...

    jsp自定义标签库学习

    在Java服务器页面(JSP)开发中,自定义标签库是一种强大的工具,它允许开发者创建可重用的组件,提高代码的可读性和维护性。本教程将深入讲解JSP自定义标签库的学习,包括其原理、配置以及如何创建和使用自定义标签...

    jsp自定义标签库注意事项

    【jsp自定义标签库注意事项】 在Java服务器页面(JSP)开发中,自定义标签库是一种强大的工具,它能够帮助开发者创建可重用的代码片段,提高代码的可读性和可维护性。以下是对JSP自定义标签库的详细解释和使用注意...

    JavaWeb-12:自定义标签库开发&JSTL标签库

    在JavaWeb开发中,自定义标签库和JSTL(JavaServer Pages Standard Tag Library)是两个重要的组件,它们极大地提高了代码的可读性和可维护性。本教程将深入探讨这两个主题,帮助开发者更好地理解和应用它们。 一、...

    jsp自定义标签库问答集锦.

    ### jsp自定义标签库知识点详解 #### 一、什么是jsp自定义标签? 1. **概念**:JSP 自定义标签是一种将复杂的功能封装成一个简单的标签的方式,它允许开发者创建可重用的代码组件,这些组件可以在 JSP 页面中像...

    jsp自定义标签库

    **JSP自定义标签库详解** 在JavaServer Pages (JSP) 技术中,自定义标签库(Custom Tag Libraries)是一种强大的特性,允许开发者创建可重用的、封装复杂功能的标签,使得JSP页面更加简洁易读。这篇内容将深入探讨...

    自定义标签库(自己写)

    自己写的自定义标签库,实现JSTL常用的功能。

    Taglib自定义标签库

    ### Taglib自定义标签库详解 #### 一、Taglib简介与作用 Taglib,即Tag Library(标签库),是JavaServer Pages (JSP) 技术中的一个重要组成部分,允许开发者创建可重用的定制标签,这些标签可以封装复杂的业务...

    第15章 自定义标签库

    第15章 自定义标签库,js的p基础知识

    jsp通过自定义标签库实现数据列表显示的方法.docx

    ### JSP通过自定义标签库实现数据列表显示的方法 #### 一、引言 在Web开发中,JSP(JavaServer Pages)作为一种广泛使用的服务器端技术,为动态网页的创建提供了强大的支持。为了提高开发效率和代码的复用性,...

    自定义tld标签库源码加视频

    【自定义TLD标签库源码加视频】这个主题涵盖了Java服务器端开发中的一个重要概念——自定义标签库(Tag Library)及其源代码分析。在Java Web应用开发中,TLD(Tag Library Descriptor)文件用于定义自定义JSP标签,...

    jsp2.0 自定义标签和自定标签函数

    在JSP页面中,通过`指令`引入自定义标签库,并使用`属性...&lt;/tag-name&gt;`的格式调用自定义标签。 **二、自定义标签函数** 自定义标签函数是在JSP 2.0中引入的一种新的特性,它允许开发者像使用EL(Expression ...

    ThinkPHP分组下自定义标签库实例

    本文实例讲述了ThinkPHP分组下自定义标签库的实现方法。分享给大家供大家参考。具体如下: 自定义标签库应该位于ThinkPHP\\Extend\\Driver\\TagLib目录下 1 新建标签类库文件名为TagLibBlog.class.php。 2 编辑刚才...

    struts实现自定义标签

    二、创建自定义标签库 1. 创建 Tag 类:首先,我们需要创建一个 Java 类,该类继承自 `org.apache.struts.taglib.Tag` 或其子类,例如 `org.apache.struts.taglib.bean.WriteTag`。在这个类中,我们将定义标签的...

    由浅到深详细讲解JSP自定义标签

    本文将深入讲解JSP自定义标签的相关概念、格式、处理过程以及创建和使用自定义标签库的基本步骤。 1. 基本概念: - **标签**:JSP标签是XML元素,用于简化JSP页面,使其更易读且支持多语言版本。标签名和属性区分...

Global site tag (gtag.js) - Google Analytics