greetingAttname="<%=username%>“/>
3、带有标签体的标签
格式:
<前缀:
标签名>
标签体
前缀:
标签名>
例如:
greetingBodyTag>
<%=hr%>:
<%=min%>:
<%=sec%>
greetingBodyTag>
4、既带有属性又有标签体的标签
格式:
<前缀:
标签名属性1=“值1”属性2=“值2”…>
标签体
前缀:
标签名>
例如:
greetingAttname="<%=username%>">
现在时间是:
<%=hr%>:
<%=min%>:
<%=sec%>
greetingAtt>
要注意的是,一个自定义标签包含超始标记和结束标记;在起始标记中是可设置自定义标签属性的;在自定义标签的起始标记和结束标记之间还可以有标签体;自定义标签按照以下顺序执行:
起始标记->标签体->结束标记。
16.3.3自定义标签的工作原理及相关概念
自定义标签实际上是一个实现了特定接口的Java类,它封装了一些常用功能,在运行时被相应的代码所替换。
如图16-1所示:
图16-1自定义标签的工作原理示意图
为了方便后续的学习,给出一些概念的定义。
标签(Tag):
让JSP页面实现特定功能,通过标签可以使JSP网页变得简洁并且易于维护,是一种XML元素,它的名称和属性都对大小写敏感;
标签库(Taglibrary):
由一系列功能相似、逻辑上互相联系的标签构成的集合,同一个标签库的“前缀”相同;
标签库描述文件(TagLibraryDescriptor):
是一个XML文件,它提供了标签库中类和JSP中对标签引用的映射关系,也是一个配置文件,与web.xml类似;
标签处理类(TagHandleClass):
是一个Java类,这个类继承了TagSupport(或BodyTagSupport)类,也可能实现了Tag或其子接口,通过该类可以自已定义JSP标签的具体功能。
16.3.4自定义标签相关API
自定义标签相关的类与接口位于javax.servlet.jsp.tagext包中,具体结构如图16-2所示。
图16-2自定义标签相关的类与接口
说明:
1、JsPTag是Tag和SimpleTag接口的父接口,是一个标记接口,不包含任何属性和方法;
2、Tag接口中的方法和常量:
setPageContext()方法:
负责设置页面的pageContext;
setParent()方法:
负责设置父标签;
doStartTag()方法:
遇到自定义标签的开始标记时去调用标签处理类的方法,返回值为EVAL_BODY_INCLUDE(表示标签体要执行,执行结果放在当前输出流中)、SKIP_BODY(不执行标签体);
doEndTag()方法:
遇到自定义标签的结束标记时去调用标签处理类的方法,返回值:
EVAL_PAGE(Jsp页面的剩余内容将继续执行)、SKIP_PAGE(Jsp页面的剩余内容不执行)。
doAfterBody()方法:
是IterationTag接口增加的方法,在执行完标签体后调用,如果没有标签体,该方法将不会调用。
该方法的返回值是:
SKIP_BODY、EVAL_BODY_AGAIN(重复执行标签体);
setBodyContent()方法:
是BodyTag接口中设置bodyContent属性的方法,以备后面获取标签体内容;只有在doStartTag()返回EVAL_BODY_BUFFERED才执行;
doInitBody()方法:
在setBodyContent()方法之后,执行标签体之前调用,为标签体的执行做准备;只有在doStartTag()返回EVAL_BODY_BUFFERED才执行;
3、TagSupport类实现IterationTag接口,利用它可简化标签处理类的创建;
4、BodyTagSupport类实现BodyTag接口,利用它可简化有关标签体处理类的创建。
16.4实验内容及步骤
1、创建greeting/>标签,该标签的功能是能根据系统时间,可以显示不同的问候语,如Goodmorning(afternoon、evening、night等)。
(1)新建Web项目,项目结构如图16-3所示;
图16-3项目结构图
(2)创建GreetingTagHandler类作为标签的处理类。
因为标签greeting/>是空标签,只需要
实现doEndTag()方法即可,返回EVAL_PAGE后继续剩余页面的执行。
源代码:
//带属性的简单标签处理类
packagemyjctl;
importjavax.servlet.jsp.*;
importjavax.servlet.jsp.tagext.*;
importjava.util.*;
importjava.io.*;
publicclassGreetingAttributeTagHandlerextendsTagSupport{
//标签有一个属性:
name
privateStringname;
publicStringgetName(){
returnname;
}
publicvoidsetName(Stringname){
this.name=name;
}
publicintdoStartTag()throwsJspTagException{
Calendarcalendar=Calendar.getInstance();
inthr=calendar.get(Calendar.HOUR_OF_DAY);
intmin=calendar.get(Calendar.MINUTE);
intsec=calendar.get(Calendar.SECOND);
Stringshowtime=",现在时间是:
"+hr+":
"+min+":
"+sec;
try{
if(hr<12){
pageContext.getOut().write("Goodmonrning,"+getName()+showtime);
}elseif(hr<16){
pageContext.getOut().write("Goodafternoon,"+getName()+showtime);
}elseif(hr<19){
pageContext.getOut().write("Goodevening,"+getName()+showtime);
}else{
pageContext.getOut().write("Goodnight,"+getName()+showtime);
}
}catch(IOExceptione){
thrownewJspTagException(
"Fatalerror:
greeetingtagcouldnotwritetotheoutputstream.");
}
returnEVAL_BODY_INCLUDE;
}
publicintdoEndTag()throwsJspTagException{
returnEVAL_PAGE;
}
}
(3)在如图16-4的目录中新建标签库描述(TLD)文件,命名为greeting.tld;
图16-4TLD文件存放路径
源代码:
xmlversion="1.0"encoding="UTF-8"?
>
1.0
simple
greetingAtt
myjctl.GreetingAttributeTagHandler
JSP
name
true
true
(4)在web.xml文件中配置标签库信息;
源代码:
xmlversion="1.0"encoding="UTF-8"?
>
xmlns="
xmlns:
xsi="http:
//www.w3.org/2001/XMLSchema-instance"
xsi:
schemaLocation="
index.jsp
/CustomTags
/WEB-INF/tlds/greeting.tld
(5)在项目中新建login.jsp。
源代码:
<%@pagelanguage="java"import="java.util.*"pageEncoding="utf-8"%>
登录页面
登录能获取时间、日期
请输入您的姓名:
(6)在项目中新建simple_attribute.jsp,应用上面定制的simple标签。
源代码:
<%@pagelanguage="java"import="java.util.*"pageEncoding="utf-8"%>
<%@pagecontentType="text/html;charset=utf-8"%>
<%@tagliburi="/CustomTags"prefix="simple"%>
简单自定义标签带属性例子