自定义标签库
来源:互联网 发布:数据中立性 编辑:程序博客网 时间:2024/06/05 22:47
自定义标记的创建步骤
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>
- 自定义标签库 循环标签
- JSTL标签库,自定义标签
- JSP 自定义标签库
- 自定义标签库
- 自定义jstl标签库
- Jsp 自定义标签库
- 自定义标签库
- 自定义标签库
- 自定义标签库开发
- 自定义标签库开发
- 自定义标签库开发
- 自定义标签库开发
- JSP自定义标签库
- 自定义标签库-demo
- 打包自定义标签库
- 自定义标签库
- JSP自定义标签库
- JSP自定义标签库
- struts2 异常处理总结
- 网页数据采集
- 工作生活计划 2010.12.28 - 2011.1.2
- Eclipse3.6 SVN plugin installation---subversive
- SqlPersistenceService持久化数据库
- 自定义标签库
- __attribute__
- 验证控件的使用 (转)
- asp.net生成html静态页的多种方法(续)
- windows下 xdebug+WinCacheGrind安装配置及Zend studio 下xdebug调试
- 虚拟机网卡不见了怎么办
- 項目實施文檔寫作框架
- android开发时 使用android layout editor 打开xml时eclipse自动关闭
- cygwin的bash错误:$'/r': command not found [caca]