上一节我们讲了,简单自定义标签的使用,如果没有了解的看官,可以自行 简单自定义标签,事实上,在实际开发过程中简单自定义标签不能满足我们的需求,比如,我们要对标签体进行迭代,根据条件对标签体进行相应的处理,这个时候我们就要学习复杂自定义标签的使用。这编我们按下面的思路讲复杂自定标签
- 怎么样实现复杂自定标签。
- 自定义标签实战一:循环打印时间
- 自定义标签实战二:if-else标签
1,怎么样实现复杂自定义标签
继承BodyTagSupport类或实现BodyTag接口
public class MyTag extends BodyTagSupport {
@Override
public int doAfterBody() throws JspException {
// TODO Auto-generated method stub
return super.doAfterBody();
}
@Override
public int doEndTag() throws JspException {
// TODO Auto-generated method stub
return super.doEndTag();
}
@Override
public void doInitBody() throws JspException {
// TODO Auto-generated method stub
super.doInitBody();
}
@Override
public int doStartTag() throws JspException {
// TODO Auto-generated method stub
return super.doStartTag();
}
@Override
public BodyContent getBodyContent() {
// TODO Auto-generated method stub
return super.getBodyContent();
}
@Override
public JspWriter getPreviousOut() {
// TODO Auto-generated method stub
return super.getPreviousOut();
}
@Override
public void release() {
// TODO Auto-generated method stub
super.release();
}
@Override
public void setBodyContent(BodyContent b) {
// TODO Auto-generated method stub
super.setBodyContent(b);
}
}
setPageContext() 将所在jsp页面的pageContext注入进来,目的是为了在后面的 方法中可以访问到jsp页面对象的pageContext属性。
setParent() 设置此标签的父标签。
doStartTag() 在开始标签属性设置后调用,如果返回SKIP_BODY则忽略标签之中的内容,如果返回EVAL_BODY_INCLUDE则将标签体的内
容进行输出。
setBodyContent() 设置当前的BodyContent。
doInitBody() 在计算BodyContent时需要进行一些初始化,就在这个方法中进行。
doAfterBody() 如果返回EVAL_BODY_AGEIN,表示继续计算一次BodyTag;
返回EVAL_BODY_INCLUDE则将标签体的内容进行输出;
返回EVAL_BODY_BUFFERED,它将对主体进行计算,并输出到缓冲区(注:此处是缓冲区并非直接输出到客户端,需要我
们手动(this.bodyContent.getEnclosingWriter().write(this.bodyContent.getString());)进行输出客户端的调用,否则主内
直到返回SKIP_BODY才继续执行doEndTag()。
doEndTag() 在结束标签之前调用,返回SKIP_PAGE跳过整个jsp页面后面的输出,返回EVAL_PAGE执行页面余下部分。
release() 生命周期结束时调用,释放标签程序占用的任何资源.。
为了方便各位看官,下面给出更为直观的流程图:
2. 自定义标签实战一:循环打印时间
标签类定义
public class KateLoopTag extends BodyTagSupport
{
int counts;//counts为迭代的次数。
public KateLoopTag ()
{
super();
}
/**
*设置counts属性。这个方法由容器自动调用。
*/
public void setCounts(int c)
{
this.counts=c;
}
/**
*覆盖doStartTag方法
*/
public int doStartTag() throws JspTagException
{
System.out.println("doStartTag");
if(counts>0)
{
return EVAL_BODY_TAG;
}
else
{
return SKIP_BODY;
}
}
/**
*覆盖doAfterBody方法
*/
public int doAfterBody() throws JspTagException
{
System.out.println("doAfterBody"+counts);
if(counts>1)
{
counts--;
return EVAL_BODY_AGAIN;
}
else
{
return SKIP_BODY;
}
}
/**
*覆盖doEndTag方法
*/
public int doEndTag() throws JspTagException
{
System.out.println("doEndTag");
try
{
if(bodyContent != null)
{
bodyContent.writeOut(bodyContent.getEnclosingWriter());
}
}
catch(java.io.IOException e)
{
throw new JspTagException("IO Error: " + e.getMessage());
}
return EVAL_PAGE;
}
public void doInitBody() throws JspTagException{
System.out.println("doInitBody");
}
public void setBodyContent(BodyContent bodyContent)
{
System.out.println("setBodyContent");
this.bodyContent=bodyContent;
}
}
TLD文件定义
在WEB-INF/tag下面创建kzTag.tld文件
<tag>
<name>loop</name>
<tag-class>com.kz.KateLoopTag</tag-class>
<!-- 如果没有标签体,设置empty , 如果有标签休必须设置JSP -->
<body-content>JSP</body-content>
<attribute>
<!-- 这个是我们资源源文件中的属性,同时源文件中必须要有setCounts(int counts)方法 -->
<name>counts</name>
<!-- 必需要给定 -->
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
测试
**
<%@ taglib uri="/WEB-INF/tag/kzTag.tld" prefix="bodytag" %>
<html>
<head>
<title>body tag</title>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
</head>
<body>
<HR>
<bodytag:loop counts="5">
现在的时间是: <%=new java.util.Date()%><BR>
</bodytag:loop>
<HR>
</BODY>
</HTML>
3. 自定义标签实战二:if-else标签
在jsp中是没有类似java中,if-else if- else这样的逻辑判断,今天我们就用自定义标签的形式来实现
if标签类的实现
/**
* 自定义if elseif else 标签
* @author 凯舟.陈超
* @date 2013-6-22 下午9:38:45
* @modifyNote
* @version 1.0
*/
public class TmIfTag extends BodyTagSupport {
/**
* serialVersionUID
*/
private static final long serialVersionUID = 1L;
private String body = null; // 用于存放成功条件后的内容
private boolean subtagSucceeded;
private boolean test;
public TmIfTag() {
super();
init();
}
@Override
public void release() {
super.release();
init();
}
@Override
public int doStartTag() throws JspException {
if (test) {
this.succeeded();
}
/*return EVAL_BODY_INCLUDE;计算标签体内容直接输出到客户端
* 计算标签体内容并输出到缓冲区,必须通过 body = bodyContent.getString().trim();获取缓存区内容
* 然后通过pageContext.getOut().write(内容) 输出到页面。
*/
return EVAL_BODY_BUFFERED;
}
@Override
public int doEndTag() throws JspException {
try {
if (subtagSucceeded){
String body2 = getBody();
pageContext.getOut().write(body2);
}
} catch (IOException e) {
throw new JspException("IOError while writing the body: "
+ e.getMessage(), e);
}
init();
return super.doEndTag();
}
public void setBody() {
if (body == null) {
body = bodyContent.getString().trim();
}
}
private String getBody() {
if (body == null)
return bodyContent.getString().trim();
else
return body;
}
/**
* 子条件判断成功
*/
public void succeeded() {
subtagSucceeded = true;
}
/**
* 是否已经执行完毕
*
* @return
*/
public boolean isSucceeded() {
return subtagSucceeded;
}
private void init() {
test = false;
subtagSucceeded = false;
body = null;
}
public void setTest(boolean test) {
this.test = test;
}
}
else-if标签类的实现
public class TmElseIfTag extends BodyTagSupport{
/**
* serialVersionUID
*/
private static final long serialVersionUID = 1L;
private boolean test;
public TmElseIfTag() {
super();
init();
}
@Override
public int doStartTag() throws JspException {
Tag parent = getParent();
if(parent==null || !(parent instanceof TmIfTag)){
throw new JspTagException("else tag must inside if tag");
}
TmIfTag ifTag = (TmIfTag)parent;
if(ifTag.isSucceeded()){
// 已经有执行成功的条件,保存之前的html
ifTag.setBody();
}else if(test){ // 当前条件为true,之前无条件为true
ifTag.succeeded();
// 则清除之前的输出
String body3 = ifTag.getBodyContent().getString();
ifTag.getBodyContent().clearBody();
}
return EVAL_BODY_BUFFERED;
}
@Override
public void release() {
super.release();
init();
}
private void init() {
test = false;
}
public void setTest(boolean test) {
this.test = test;
}
}
else标签类的实现
public class TmElseTag extends BodyTagSupport{
/**
* serialVersionUID
*/
private static final long serialVersionUID = 1L;
public void release() {
super.release();
}
public int doStartTag() throws JspException {
Tag parent = getParent();
if(parent==null || !(parent instanceof TmIfTag)){
throw new JspTagException("else tag must inside if tag");
}
TmIfTag ifTag = (TmIfTag)parent;
if(ifTag.isSucceeded()){
// 已经有执行成功的条件,保存之前的html
ifTag.setBody();
}else{
// 之前没有的判断没有成功条件,则清除之前的输出
ifTag.getBodyContent().clearBody();
ifTag.succeeded();
}
return EVAL_BODY_BUFFERED;
}
}
TLD文件
在WEB-INF/tag下面创建kz.tld文件
<tag>
<description>if标签</description>
<name>if</name>
<tag-class>com.kz.tag.TmIfTag</tag-class>
<!-- 如果没有标签体,设置empty , 如果有标签休必须设置JSP -->
<body-content>JSP</body-content>
<attribute>
<name>test</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
<tag>
<description>elseif标签</description>
<name>elseif</name>
<tag-class>com.kz.tag.TmElseIfTag</tag-class>
<!-- 如果没有标签体,设置empty , 如果有标签休必须设置JSP -->
<body-content>empty</body-content>
<attribute>
<name>test</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
<tag>
<description>else标签</description>
<name>else</name>
<tag-class>com.kz.tag.TmElseTag</tag-class>
<!-- 如果没有标签体,设置empty , 如果有标签休必须设置JSP -->
<body-content>empty</body-content>
</tag>
jsp测试使用
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@taglib uri="/WEB-INF/tag/kz.tld" prefix="kz"%>
<kz:if test="${1==2}">
我是if
<kz:elseif test="${1==1}"/>
我是else if
</kz:if>
超全面的测试IT技术课程,0元立即加入学习!有需要的朋友戳:
腾讯课堂测试技术学习地址