标准的JSP 标记可以调用JavaBeans组件或者执行客户的请求,这大大降低了JSP开发的复杂度和维护量。JSP技术也允许你自定义taglib,其实换句话说,taglib可以看成是对JSP标记的一种扩展,正如xml是对html的一种扩展一样。taglib通常定义在tag标签库中,这种标签库存放着你自己定义的tag标签。简而言之,如果使用taglib,那么你可以设计自己的JSP标记!
%jf|efxo T*Ge67 一般来说,自定义tag标签主要用于操作隐藏对象、处理html提交表单、访问数据库或其它企业级的服务,诸如邮件和目录操作等等。自定义tag标签的使用者一般都是那些对java编程语言非常精通,而且对数据访问和企业级服务访问都非常熟悉的程序员,对于HTML设计者来说,使得他可以不去关注那些较复杂的商业逻辑,而将精力放在网页设计上。同时,它也将库开发者和库使用者进行合理分工,自定义tag标签将那些重复工作进行封装,从而大大提高了生产力,而且可以使得tag库可用于不同的项目中,完美地体现了软件复用的思想。
=
=Q*|L-g 9 `bLQd 在这篇文章中,我们主要讨论:
-OmpUv-O" Ktt(l-e + · 什么是自定义tag标签?
)+Z.J]$O- b&QI#w · 怎么使用tag标签?
+\dKe[j{g C2zKt/)A o 声明要使用的tag库
FYu30 wxBZ+UP_ o 找到与之对应的tag处理类
xzfugW vaHtWz!P o tag标签的类型
Uc,.. a{}#t} · 自定义tag标签
ps8tr:T^= 'r_Fi5[q o tag处理类
B<Cg_C ;o;ak.dTt o tag库描述
[euR<i*I# qe?Ns+j<d o tag标签示例
I`jG iqB%sIP o 带属性的tag
2!CL8hG5: $_eJ@L# o 带body的tag
S=`$w GcA|JS=> o 定义了脚本变量的tag
wL]#]DiE ob9od5Rf o 具有协作关系的tag
7F]Hq E+e),qsbO · 自定义tag标签
8yDsl So ~QZ%YA o 一个迭代tag的例子
Jy"\_Vvl 20haA0s o 一个模板tag库
yt,Ky8y1 U7g,@/Qx o tag处理类到底是怎样被调用的?
&w`Ho)P Z-_Xt^N rK}sQ4z= 什么是自定义的tag?
/CKn XU; U1fqs{> 一个自定义的tag标签是用户定义的一种JSP标记。当一个含有自定义的tag标签的JSP页面被jsp引擎编译成servlet时,tag标签被转化成了对一个称为tag处理类的对象进行的操作。于是当JSP页面被jsp引擎转化为servlet后,实际上tag标签被转化成为了对tag处理类的操作。
CK|AXz+EN ^5?|Dj 自定义tag标签有很多特色,诸如:
car|&b p/7'r · 可以在JSP页面中自定义tag标签的属性
O}2/w2n e0ni · 访问JSP页面中的所有对象
zLg$|@E& 5.oY$tb( · 可以动态地修改页面输出
:J x%K nUX3a'R · 彼此这间可以相互通信。你可以先创建一个JavaBeans组件,然后在一个tag中调用此JavaBeans组件,同时可以在另一个tag中调用它。
|yp^T m#O; 1/P · tag允许相互嵌套,可以在一个JSP页面中完成一些复杂的交互。
(]&B'1b "cjD-42 XN?my@_HpM 使用tag标签
0yMHU[):~ %z-s o?gF 7Lj:m.0O^ 本节主要描述怎样在JSP页面中使用tag标签,以及tag标签的不同类型。
n;vZY Bf+~&I#E 要使用tag标签,JSP程序员必须做2件事:
6CGk*s ![vy{U.:` · 声明此tag标签的tag库
g3Hi5[-H y@2"[fo3~ · 实现此tag标签
BXxJra/V q&NXF( 声明tag标签所在的tag库
hPGDN\#LD "s_S!;w@ 如果要使用tag标签,则应用JSP的taglib指示符来指定其tag库(注意:taglib要在在使用此tag标签之前声明)
oOubqx Z0'LD< <%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %>
mF4OLG3L0 Buq(L6P9r uri属性定义了唯一的标签库描述(以下简称TLD),它可以是直接是tld文件名或一个独一无二的名字。prefix是用来区别其它TLD中和本TLD中有重名的tag的一种手段。
E KN<KnU% K&gE4;> TLD必须以.tld作为扩展名,并且存放在当前应用的WEB-INF目录或其子目录下。你可以通过它的文件名直接引用它,也可以通过别的方式间接地引用它。
$83Qd T/%Y_.NtU 以下taglib指示符直接引用一个TLD:
,VUOsNN4\ KIWHn_ : <%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %>
-*ZQ=nomN xdaq` ^Bbt 以下的taglib指示符通过一个逻辑名称间接地引用一个TLD:
/n$R-Q P%Q'w <%@ taglib uri=”/tutorial-template” prefix=”tt” %>
HB*BL+S06 'Ce?!UO 如果是间接引用TLD的话,那你必须还要在web.xml中定义此逻辑名称与tld文件之间的映射,具体做法是在web.xml中加入一个名为taglib的元素:
d$E>bo-\ 0a@tPskV <taglib>
Eg2jexl z-"P raP <taglib-uri>/tutorial-template</taglib-uri>
v"%>ms"n I1dOMu9 <taglib-location>
Q[H4l({E g1 y@z8Z{ /WEB-INF/tutorial-template.tld
O ]-8 % K *1]P ar; </taglib-location>
4"iI3y~Gw *r9D+}Y(4 </taglib>
At[SkG}b e8xNZG; )?l7I* 实现此tag标签
Qn-nO_JL 3G^A^]h i\.(6hf+ 为了实现tag标签,你有2种方法来存放tag处理类。一、让tag处理类以.class的方式存放于当前应用的WEB-INF/class子目录下,二、如果tag处理类是以JAR包的形式存在的话,那可以放在当前应用的WEB-INF/lib目录下,如果tag处理类要在多个应用中共享,那么它就应放在jsp服务器上的common/lib目录下,对于tomcat来说,就是tomcat/common/lib目录下。
jG}nOI f8f3[O!x yw7bIcs|#b tag标签类型
*g:Dg I 2 Gb"kl.j d#ab"&$bv 自定义的tag标签遵循XML语法。它有一个开始标记和一个结束标记,有的还有body(即文本节点):
"Z&_*F.[O P+_1*lOG <tt:tag>
>>y\idg&: ]z=dRq body
B(eiRr3 T0b/txS </tt:tag>
d]sg9` JL u$UR4 !Bg^-F:N 一个不带body的tag标签如下:
Su
+<mW NQiu>Sg <tt:tag />
zNn auY?Cj'"fs ]1h9:PF 简单的tag标签
I?\P^f sdd%u~4,X 一个没有body和属性的tag标签如下:
{S@,
, h+YPyeAs <tt:simple />
&=T>($3r94 'b >3:& h{jm 带属性的tag标签
I-kK^_0mV<
j~9Y0jz_ _KyhX| 自定义标签可以有自己的属性。属性一般在开始标记中定义,语法为 attr=”value”。属性的作用相当于自定义标签的一个参数,它影响着tag处理类的行为。你可以在TLD中详细定义它。
Ar_Yl|a p -!/p# 你可以用一个String常量给一个属性赋值,也可以通过表达式给它赋值,如<%= ...%>。以struts为例,它的logic:present标签就是用的String常量来给属性赋值:
)lU ocm @|OGxQoC <loglic:present parameter = “Clear”>
!
8Ro5), cmd7-2 而另一个标签logic:iterate是用表达式来给属性赋值:
W~l.feW$i #0^a-47PA< <logci:iterate collection=”<%= bookDB.getBooks() %>”
m>!o
Yy_ c@j3L23B id=”book” type=”database.BookDetails”>
6vU%Y_n=y] ;{e'q?Y
\t&8J+% 带body的tag标签
!<X/_+G\ J~
*>pp#U 一个自定义标签可以包含其它自定义标签、脚本变量、HTML标记或其它内容。
"/taatcH IkGM~3e 在下述例子中,此JSP页面使用了struts的logic:present标签,如果些标签定义了parameter=”Clear”的属性,则将清除购物车的内容,然后打印出一条信息:
bpDlFa 3lS1WA <logic:present parameter=”Clear”>
=4!m]*y mWLi XKnb <% cart.clear(); %>
M3JV^{O/DV U:PtRSdn!b <font color=”#ff0000” size=”+2”><strong>
_tQM<~Y]u\ "0z4mQ}>N 你选择了清除购物车!
+lf`Dd3 wjOJn] </strong></font>
c2Y\bKeN O[|X=ZwR:l </logic:present>
HA&hu/mw_ ]\ZmK0q<: ,,S 2>X*L 到底是用属性还是用body来传递信息?
AJ#YjkO>] e_S,N0 如上所述,我们既可以通过属性,也可以通过body来传递信息。但一般来说,比较简单的类型,如字符串或简单表达式最好采用属性来传递信息。
(8N E'd8 d@Wze[M?0 eG.s|0` 定义脚本变量的tag标签
"412w^5[T Tg=P*HY6 所谓脚本变量,是指JSP中可以调用的变量或对象。它可由tag标签产生。以下示例阐述了一个tag标签定义了一个名为tx的由JNDI所定义的事务处理对象。脚本变量可以是ejb对象、事务、数据库连接等等:
yhnPS4DC {t]8#[lo <tt:lookup id=”tx” type=”UserTransaction” name=”java:comp/UserTransaction” />
&$~irI 6"r _Y7% <% tx.begin(); %>
a:1$i dj _ vAc/_N ...
ClPE_Cfw~ tq*6]q8c> }Cb-7/ 具有协作关系的tag标签
T*(mi{[T G) 37?A) 自定义tag标签之间可以通过共享对象来实现协作。在下述例子中,标签tag1创建了一个名为obj1的对象,在标签tag2仍可以重复使用obj。
rfh`;G5s _ZK*p+u% <tt:tag1 attr1=”obj1” value1=”value” />
/f=31<+MtF .GCJA`0h <tt:tag2 attr1=”obj1” />
4i"fHVp8 6r h#ATep 在以下这个例子当中,如果外层的tag标签创建了一个对象,那么其内层的所有tag标签都可以使用这个对象。由于这样产生的对象没有一个指定的名字,那么就可以将少重名的冲突。这个例子阐述了一系列协作的嵌套对象。
og4mLoLA sM9utR <tt:outerTag>
O6\c1ha =W gzj|Kr <tt:innerTag />
+Je%8jH }YU\}T-P </tt:outerTag>
owA.P-4 fM(~>(q& "|E'E"_1 Tag处理类
gBXoEn] {!1RlW e=[@HVr Tag处理类必须实现Tag接口或BodyTag接口,不过现在一般都流行从TagSupport或BodyTagSupport类中继承,这些类或接口都可以在javax.servlet.jsp.tagext包中找到。
hN\Q&F! xo!2GPD. 当JSP引擎看到自己的JSP页面中包含有tag标签时,它会调用doStartTag方法来处理tag标签的开头,调用doEndTag方法来处理tag标签的结束。
X'/'r.b6 ?lU(FK 下表说明不同类型的tag所需要不同的处理过程:
!2.eJ)G -^< t%{d Tag处理类的方法
q{xF7}i r( bA>L*mk Tag标签类型
}Am5b@g"$Y 所调用的方法
$OzVo&P; TALiH'w6|e 基本标签
>h$Q%w{V doStartTag, doEndTag, release
g6OPYUPg @oD2_D2 带属性的标签
NjO_Y t doStartTag, doEndTag, set/getAttribute1...N, release
1q|iw ?YF2Uc8z%2 带内容的标签
Z~;rp`P doStartTag, doEndTag, release
IJ7wUZp" e?KzT5j: 带内容的标签,且内容重复循环
qsYg%Z doStartTag, doAfterBody, doEndTag, release
DyUS^iz~o H=mFc@fh 带内容的标签,且内容与JSP交互
wVF
qkJ doStartTag, doEndTag, release, doInitBody, doAfterBody, release
LMLrH. l,UOP[j 一个tag处理类可以通过javax.servlet.jsp.PageContext来与JSP交互,通过javax.servlet.jsp.PageContext类,tag处理类可以访问JSP中的request、session和application对像。
Z4sS;k]} MIqH%W.ru 如果tag标签是互相嵌套的,那内层的tag处理类可以通过它的parent属性来访问上层的tag处理类。
"EZpTy}Ee D8WKy 一般情况都将所有的tag处理类打成了JAR的包,以便于发布。
p&
Kfy~ @=BApuer+ qCF&o7*oN Tag库描述(简称TLD)
1So`]N4 " z -tL sg4(@> Tag库是用xml语言描述的,TLD包括了tag库中所有tag标签的描述,它一般用来被jsp服务器用来校验tag的语法正确性,或者被jsp开发者用来开发新的标签。
64Tb,AL_ ?gMq:[XN TLD的文件扩展名必须为.tld,而且必须放在当前WEB应用的WEB-INF目录或其子目录中。
F;T;'!mb DbYnd%k*4 一个TLD的内容的开头必须遵守标准的XML开头,用于描述DTD和xml的版本,例如:
)OK"H^}f h%sw^;\! <?xml version="1.0" encoding="ISO-8859-1" ?>
1aPFpo! AN)r(86L <!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "
http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd">
u>*qDr*d TLD必须以<taglib>来作为它的根元素,<taglib>的子元素如下表:
"1UpoF'w ~^fb`f+% a>,Zp*V( <taglib>的子元素
VKSn \HT~ Th$xk9TK^@ Element
rkz84wDx Description
vTC{ CXTtN9N9 tlib-version
p!\GJ a", Tag库的版本
`r0lu_.$]4 G7r .Jm^q jsp-version
b)r;a5"<5 Tag库所需要的jsp的版本
lWBewnLKE C(M ?$s` short-name
4P#4RB 助记符,tag的一个别名(可选)
3jHE,5m uII! ? uri
Qm_;o( 用于确定一个唯一的tag库
|<uBJ-5 ]&tcocq display-name
$"?$r 被可视化工具(诸如Jbuilder)用来显示的名称(可选)
(U\D7ItMG .0MY$ 0s small-icon
8EBd`kiq 被可视化工具(诸如Jbuilder)用来显示的小图标(可选)
_v++NyZXx tqjjn5! large-icon
#+$PD`j 被可视化工具(诸如Jbuilder)用来显示的大图标(可选)
+x<OyjY5?] uG-S$n"7K description
3 Zwhv+CP[ 对tag库的描述(可选)
Z/ L%?zH l8e)|MSh listener
{ _Y'%Ggh 参见下面listener元素
p$` ^A &kT!GU^n tag
$9u:Ox
2 参见下面tag 元素
^mN`!+ +Eel|)Z*Q Listener元素
G2b"R{i/, i(V 一个tag库可能定义一些类做为它的事件侦听类,这些类在TLD中被称为listener 元素,jsp服务器将会实例化这些侦听类,并且注册它们。Listener元素中有一个叫listener-class的子元素,这个元素的值必须是该侦听类的完整类名。
tTh4L8fO &-m}w :j= Tag元素
QP>F *A
8~g~XUl 每个tag元素在tag库中都要指出它的名字、类名、脚本变量、tag的属性。其中脚本变量的值可以直接在TLD中定义或通过tag附加信息的类来取得。每个属性描述了这个属性是否可以省略,它的值是否可以通过<%= …%>这样的JSP语法来获得,以及属性的类型。
Rm~8n;7oOr RLcC>Z 每一个tag在TLD中对应一个tag元素,下表是tag元素的子元素:
ZvK.X*~s Xe(]4Ux Tag元素的子元素
q Ll4t/p {aUv>T"c 元素名称
We'= /! 描述
C'S_M@I= AoK;6je`K^ name
P,rLyx 独一无二的元素名
XEN-V-Z%* 9D;ono3 tag-class
r>.l^U9hJ Tag标签对应的tag处理类
Qh*}v!3Jo x'SIHV4M@Q tei-class
yV31OBC: javax.servlet.jsp.tagext.TagExtraInfo的子类,用于表达脚本变量(可选)
_Ih"*~ r/& ID,os_ T= body-content
rje;Bf Tag标签body的类型
lA`-" dTte4lh display-name
GH&5m44 被可视化工具(诸如Jbuilder)用来显示的名称(可选)
*xpPD\{k ~RZN+N small-icon
^==Tv+T9U 被可视化工具(诸如Jbuilder)用来显示的小图标(可选)
'z@]hm# -lXQQ#V
- large-icon
2X(2O':Uc 被可视化工具(诸如Jbuilder)用来显示的大图标(可选)
^N`KT yN06` = description
ch0cFF^] 此tag标签的描述
`S4G+j>u6 4ywtE}mp variable
4w]<1V 提供脚本变量的信息(同tei-class)(可选)
/AYq^ K<WowU attribute
,mz7!c9H^a Tag标签的属性名
=5:kV/p ZVit]3hd 以下章节介绍对于不同类型的tag,如何具体地实现它们。
~{N#JOY}Z h]IoH0/ tCGA3t 简单的tag
?9?o8! ?}EWfsA mxe\+j# tag处理类
<TSps!(# !>&G+R+k 简单的tag处理类必须实现Tag接口的doStartTag和doEndTag方法。当jsp引擎碰到tag标签的开头时,doStartTag被调用,因为简单的tag没有body,所以此方法将返回 SKIP_BODY。当jsp引擎碰到tag标签的结尾时,doEndTag被调用,如果余下的页面还要被计算,那它将返回EVAL_PAGE,否则将会返回SKIP_PAGE。
lLK||2d Bgai|l 以下是例子:对于标签 <tt:simple /> ,它的tag处理类实现如下:
V9%9nR!' R@`xS<`L/ % 3fpIzm public SimpleTag extends TagSupport
#G\-ftA & `V.tqZF {
`iEYq0} &v9"lR=_k public int doStartTag() throws JspException
>4HB~9dKU cBHUa}: {
j
J54<.D )0Vj\> try{
mM_gOd .'2"83f pageContext.getOut().print(“Hello.”);
|C,]-mJ G jP<6Q|5F }catch(Exception e){
}"q#"s QX_![|= throw new JspTagException(“SimpleTag: “ + e.getMessage());
u/N_62sk5 dN){w _
}
kHQn'r6 {3!A\OR return SKIP_BODY;
&?']EcU5h9 cvx"XxE, }
er>{#8 P 7dlMDHp\Y public int doEndTag()
49Y:}<Yd h,]lN'JG{ {
jT;'T$ TQvjU!> return EVAL_PAGE;
r8A'8g4cM FtWO[*# }
rAgp cp} e0#{'_C }
@#9xSs# tao9icl*`
P# ;pQC 注意:如果tag标签没有内容的话,那必须定义body-content元素为空,例如
kjSzuqB z,VXH ?.Zo <body-content>empty</body-content>
77 ?TRC Q1H.2JXr % 5BSXAc 带属性的tag标签