自定义标签必须实现下面三个接口中的一个:Tag、IterationTag、BodyTag
1.Tag
如果要实现这个接口,可以通过扩展TagSupport这个类,来写自己需要的方法,而不需要把Tag接口中的所有方法实现。
Tag接口的方法:
doStartTag()、doEndTag()、getParent()、setParent()、release()、setPageContext()
在Tag类代码中不能像jsp一样,直接使用out隐含对象,他有一个对象可以使用pageContext,通过它的getOut()方法可以得到out对象。在标签内部,访问任何的隐含对象,都是通过调用pageContext的set方法。
2.IterationTag
IterationTag接口与Tag接口类似,用于当一个自定义标签需要重复计算它的代码体的情况下。它扩展Tag接口并实现了一个新的方法doAfterBody()来实现循环,这个方法只有从doStartTag()返回EVAL_BODY_INCLUDE时才被调用。在执行doAfterBody()方法时,如果返回的是EVAL_BODY_AGAIN,那么将再次执行doAfterBody()方法,直到doAfterBody()返回的是SKIP_BODY或者EVAL_BODY_INCLUDE。
3.BodyTag
BodyTag接口扩展了IterationTag并提供了对代码体内容进行操作的功能。就是在计算代码体的时候可以对已经形成的代码体进行修改。BodyContent对象就是用来保存对自定义标签体计算的结果。它有一个新方法doInitBody(),这个方法只有在doStartTag()方法返回EVAL_BODY_BUFFERED时才调用,此时它将创建一个BodyContent对象保存结果。
扩展自定义标签:
添加属性
首先要在tld文件中加入一个属性元素,然后在java文件中需要定义这个属性以及它的的setter方法。属性<attribute>元素有四个子元素分别是<name>、<required>、<rtexprvalue>、<description>,这里<rtexprvalue>表示的是属性是否接受scriptlet表达式的计算结果,默认情况下为false,即只能接受静态值。
添加变量
可以在tld文件中给自定义标签加入一个<variable>元素,它的子元素包括<name-given>表示保存变量的名字,<variable-class>表示变量的java类型,<declared>用boolean表示这个变量是否为新的,<scope>表示变量的使用范围(AT_BEGIN表示从起始标签起,AT_END表示从终止标签后,NESTED表示起始标签和终止标签之间)。定义了变量之后,需要在java文件中把这个变量用pageContext.setAttribute("",object);这里key值应该就是变量对外的名字。
使用TagExtraInfo(TEI)类
这个对象中有两类对象可以使用,TagData(保存标签属性的信息)、VariableInfo(描述代码变量)
一段TagExtraInfo类代码实例:
public VariableInfo[] getVariableInfo(TagData data) {
String variableName = data.getAttributeString("name");
VariableInfo vi =
new VariableInfo(variableName,"String []", true, VariableInfo.AT_END);
VariableInfo[] tagVariables = new VariableInfo[1];
tagVariables[0] = vi;
return tagVariables;
}
可以通过TagData类的getAttributeString方法得到某个属性的值,还有另外一个方法getAttribute也是得到某个属性的值不过返回的是一个对象。而getVariableInfo方法必须返回一个VariableInfo数组。除此之外,还需要在tld中的元素定义<tag-class>后加入一个<tei-class>元素,说明TEI类的全称。
pageContext对象中含有的方法包括:getOut();getPage();getRequest();getResponse();getServletConfig();getServletContext();getSession();
Tag接口中的返回常数意义:
EVAL_BODY_INCLUDE:告诉服务器正文的内容,并把这些内容送入输出流
SKIP_BODY:告诉服务器不要处理正文内容
EVAL_PAGE:让服务器继续执行页面
SKIP_PAGE:让服务器不要处理剩余的页面
EVAL_BODY_AGAIN:让服务器继续处理正文内容,只有doAfterBody方法可以返回
EVAL_BODY_BUFFERED:BodyTag接口的字段,在doStartTag()返回
EVAL_BODY_INCLUDE、SKIP_BODY一般由doStartTag()返回,而EVAL_PAPGE、SKIP_PAGE由doEndTag()返回。
在调用doStartTag()方法之前其实标记还调用了其他两个方法:setPageContext()和setParent();所以在后面的方法中可以使用pageContext和parent对象,如果需要的话。
让自定义标签在页面中创建对象时必须使用一个标准的JSP对象TagExtraInfo类,它可以创建脚本变量还可以在编译的时候对标签进行检验,TEI类仅可以生成由setAttribute方法存储在PageContext对象中的变量,而并不是单独生成变量。
通过TEI类定义脚本变量可以让使用者自己定义在页面中使用对象的名称。
除了使用TEI类方法之外,还可以简单的在TLD中定义一个<variable>对象来使用自定义对象,用法如下:
<variable>
<name-from-attribute>name</name-from-attribute>
<variable-class>String []</variable-class>
<declare>true</declare>
<scope>AT_END</scope>
</variable>
对于variable的子元素,<name-from-attribute>指的是创建的变量名称从属性name中来取得,当然也可以通过<name-given>元素来限制变量的名称。注意这两个元素是互斥的。
一个扩展BodyTagSupport的自定义标记的生命周期如下:
1.创建标记
2.调用Setter方法
3.调用doStartTag()方法
4.调用setBodyContent()方法
5.调用InitBody()方法
6.处理标记的Body
7.doAfterBody();根据返回值,如果为EVAL_BODY_AGAIN,继续执行6,如果不是,执行8
8.调用doEndTag()方法
9.判断标记是否需要重用,如果要,执行4;否则执行release()方法。
TagSupport类的方法findAncestorWithClass()方法可以用来查找指定的父类,它有两个参数一个为本身的类名,还有一个就是要查找的父类的名称,如果没有返回null;例如ParentTag parent = (ParentTag) this.findAncestorWithClass(this,ParentTag.class);
自定义标记的验证方法:
JSP1.1
TEI类可以在编译时刻检验自己的标记,这个类中有一个isValid()方法,如果TLD中为这个标记定义了这个TEI类,那么网页在编译的时候将会调用这个方法,并且会传入一个包含属性具体内容的参数TagData。(在JSP1.2中同样有效)
JSP1.2
JSP1.2中引入一个新的标记检验方法,定义了一个新类TagLibraryValidator,并且可以由此派生出检验标志的类,大多数情况下仅使用这个类的validate()方法,它有三个参数:prefix(在taglib指令中定义的前缀);uri(TLD文件中的URI);page(JSP页的PageData XML版本),validate()方法返回值为null时表示验证成功,否则返回的String类型将是一个错误信息。
当validator在TLD文件中定义时,它应该放在<tag>元素定义的外面,因为它是用来处理验证标记库中的所有标记的。
<validator><validator-class></validator-class></validator>。
比较JSP1.2和JSP1.1中的方法:
TagLibraryValidator比TEI类更全面,可以用来检测整个网页,而不仅仅是标记本身,可以用来处理标记间的合作,并且这种方法可以用来通知程序员错误出在哪里,但是同时它的方法也比TEI类的方法复杂多了,因为它需要遍历整个XML版本的JSP(完成getAttributeValue方法)。
JSP1.2中的TryCatchFinally接口:
这个接口主要是用于当自定义标记出现异常时释放自定义标记中的资源使用的,它定义了两个方法:
public void doCatch(Throwable t);(当doStartTag,doInitBody,doAfterBody,doEndTag方法出现异常时会调用这个方法)
piblic void doFinally();(当doEndTag被调用后,无论是否出现异常都会调用这个方法,就像程序中的finally块,可以用来释放资源)
在JSP1.2中,可以通过在tld文件中加入一个元素<uri></uri>来指定自己的在taglib指令中使用的名称,然后把这个tld文件与Manifest.mf一起放在META-INF目录中,那么在页面中就可以非常方便地导入这些tld。
编写自定义标记的原则:
1.使用脚本变量(允许设计者为脚本变量起名、将脚本变量的数量减到最小、使用一个组合脚本对象和存取函数即使用JavaBean)
2.当设计相互协作的标记时应该尽量避免创建一套新的语言,应当尽量使用脚本变量
3.编写代码而不是内容,不要在自定义标记中产生HTML,这样会失去通用性
分享到:
相关推荐
在 Struts 中,我们可以通过实现 `org.apache.struts.taglib.Tag` 接口来创建自定义标签。 二、创建自定义标签库 1. 创建 Tag 类:首先,我们需要创建一个 Java 类,该类继承自 `org.apache.struts.taglib.Tag` 或...
总结,Struts2的自定义标签实例涉及到以下几个关键步骤:创建标签实现类、定义标签描述符、在JSP中使用标签以及处理标签逻辑。通过这种方式,我们可以构建强大的视图层组件,使代码更易于理解和维护,同时提升应用的...
在Struts2中,可以通过实现`com.opensymphony.xwork2.util.ValueStackAware`接口创建自定义标签,让标签能够访问值栈中的数据。Spring框架也有自己的标签库,如Spring Taglib,可以简化JSP页面中的Spring Bean引用。...
4. 标签处理类(Tag Handle Class):处理类是Java类,通常继承自TagSupport或实现了SimpleTag接口,负责实现自定义标签的功能。 二、自定义JSP标签的格式: 1. 使用自定义标签需要指定标签库的前缀(Prefix),前缀...
在Struts2中,自定义拦截器需要继承`com.opensymphony.xwork2.interceptor.Interceptor`接口,并实现其三个方法:`void destroy()`、`void init()` 和 `String doIntercept(ActionInvocation invocation)`。...
除了预定义的标签外,Struts2还允许开发者根据需求自定义标签。通过实现Struts2的标签接口并注册到配置文件中,开发者可以创建自己的标签库,扩展框架的功能。 六、使用和调试 在实际项目中,开发者可以将`struts2-...
- **标签处理器类**:这是自定义标签的实际实现部分,通常是一个实现了`javax.servlet.jsp.tagext.SimpleTagSupport`或`javax.servlet.jsp.tagext.TagSupport`接口的Java类。在这个类中,开发者可以编写具体的业务...
3. **标签库(JAR文件)**:通常,TLD和标签处理类被打包到一个JAR文件中,这个JAR文件包含了自定义标签库的所有资源。 ### 三、创建自定义JSP标签 1. **创建标签处理类**:根据需求,创建一个Java类,并实现`Tag`或...
如果需要,我们可以创建自定义标签库以增强视图的表现力。 7. **异常处理**:Struts提供了全局异常处理机制,通过配置文件定义全局错误页面或者自定义异常处理器,可以统一处理程序中的异常。 8. **国际化与本地化...
例如,下面展示了这个接口的基本结构: ```java public interface Validator<T> { void setDefaultMessage(String message); String getDefaultMessage(); String getMessage(Object object); void ...
Struts2还允许我们自定义标签,以满足特定需求。通过实现`TagSupport`接口或继承已有的标签类,我们可以扩展Struts2的标签库。 七、实战应用 在实际项目中,Struts2标签可以帮助我们快速构建界面,减少硬编码,提高...
SSH框架整合通用模板是开发人员为了提高开发效率和代码复用性而设计的一种架构模式,主要涉及Spring、Struts2和Hibernate三个核心组件。SSH框架的整合提供了模型-视图-控制器(MVC)的设计模式,使得业务逻辑、数据...
在Struts2框架中,我们可以创建一个自定义标签库,包含用于分页的TLD(Tag Library Descriptor)文件,定义标签的属性如当前页码、每页显示条数等。然后,编写对应的Action类,该类将处理分页逻辑,包括计算总页数、...
本文档旨在为初学者提供一个简单的自定义标签示例,帮助理解其基本原理及实现过程。 #### 二、自定义标签的基本类型 自定义标签主要分为两大类: 1. **简单标签**:这类标签不对标签体(即开始标签和结束标签之间...
在集成SSH时,我们需要配置相关的XML文件,如struts.xml、spring.xml和hibernate.cfg.xml,确保这三个框架能够协同工作。 在分页抽象业务层的创建中,我们通常会设计一个基类,包含分页参数(如当前页、每页条数)...
#### 三、Struts2的拦截器技术 - **拦截器的基本概念**: - 拦截器是在Action执行前后的一系列处理程序,用于实现横切关注点(如日志记录、权限控制等)。 - Struts2默认提供了许多内置拦截器,例如`defaultStack...
此外,它可能还会讲解如何进行视图层的渲染,包括JSP页面的使用以及Struts2自定义标签的应用。 "struts2-tags-API.chm"则专门针对Struts2的标签库进行详解。Struts2的标签库丰富多样,包括显示数据的标签(如`s:...
实现自定义标签的方式有三种: - **标签处理程序**:通过Java类实现,扩展Tag、IterationTag或BodyTag接口。 - **标签文件**:包含JSP元素的文本文件,使用特殊的标准动作。 - **标签库描述符**:XML文件,描述标签...
- `org.apache.struts2.views.jsp`: JSP标签库相关代码,提供了诸如、等标签的实现。 5. **Struts2的其他特性** - **动态方法调用(Dynamic Method Invocation, DMI)**: 允许通过URL直接调用Action的方法,提高...
6. JSP页面通过Struts自定义标签库显示Model中的数据,形成视图。 7. 视图渲染后,响应结果返回给用户。 SSH框架的优势在于分工明确,各司其职,提高了开发效率,降低了维护成本。Struts专注于表现层的控制,Spring...