社区应用 最新帖子 精华区 社区服务 会员列表 统计排行 社区论坛任务 迷你宠物
  • 2953阅读
  • 1回复

一篇介绍JSP标签库很详细的文章,可以做为参考手册

级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
标准的JSP 标记可以调用JavaBeans组件或者执行客户的请求,这大大降低了JSP开发的复杂度和维护量。JSP技术也允许你自定义taglib,其实换句话说,taglib可以看成是对JSP标记的一种扩展,正如xml是对html的一种扩展一样。taglib通常定义在tag标签库中,这种标签库存放着你自己定义的tag标签。简而言之,如果使用taglib,那么你可以设计自己的JSP标记! ROc`BH=  
@=Fi7M  
一般来说,自定义tag标签主要用于操作隐藏对象、处理html提交表单、访问数据库或其它企业级的服务,诸如邮件和目录操作等等。自定义tag标签的使用者一般都是那些对java编程语言非常精通,而且对数据访问和企业级服务访问都非常熟悉的程序员,对于HTML设计者来说,使得他可以不去关注那些较复杂的商业逻辑,而将精力放在网页设计上。同时,它也将库开发者和库使用者进行合理分工,自定义tag标签将那些重复工作进行封装,从而大大提高了生产力,而且可以使得tag库可用于不同的项目中,完美地体现了软件复用的思想。 %o w^dzW  
p fT60W[m  
在这篇文章中,我们主要讨论: x\\~SGd  
ycAKK?O*  
· 什么是自定义tag标签? a9U_ug58  
tPfFqqT  
· 怎么使用tag标签? )]43R   
g(ogXA1  
o 声明要使用的tag库 v [njdP  
3c3OG.H$8  
o 找到与之对应的tag处理类 <F=9*.@D   
'CR)`G_'[  
o tag标签的类型 mQ~:Y  
W# US#<9Y  
· 自定义tag标签 Te,$M3|  
9 QC.TG@  
o tag处理类 ;GGK`V  
'gso'&Uaj  
o tag库描述 uz3 0_aH  
sEc;!L  
o tag标签示例 %~xGkk"I  
#Q"O4 b:8  
o 带属性的tag FFKGd/:!  
\ I`p|&vG  
o 带body的tag 3)=c]@N0  
\G |%Zw|  
o 定义了脚本变量的tag MV>$BW  
]3iH[,KU3  
o 具有协作关系的tag 1O/ g&u  
zj{r^D$  
· 自定义tag标签 {eS|j=  
MrRaU x6z  
o 一个迭代tag的例子 dt}_D={Be  
Zw1U@5}A  
o 一个模板tag库 M]]pTU((  
@`36ku  
o tag处理类到底是怎样被调用的? "= / f$Xf  
_aWl]I){5  
>Z.\J2wM<j  
什么是自定义的tag? eLD|A=X?  
KhbYr$  
一个自定义的tag标签是用户定义的一种JSP标记。当一个含有自定义的tag标签的JSP页面被jsp引擎编译成servlet时,tag标签被转化成了对一个称为tag处理类的对象进行的操作。于是当JSP页面被jsp引擎转化为servlet后,实际上tag标签被转化成为了对tag处理类的操作。 . Dg*\ h  
GB7/x*u   
自定义tag标签有很多特色,诸如: Q]/Uq~m C  
aGZi9O7G}  
· 可以在JSP页面中自定义tag标签的属性 3r+.N  
nC1zzFFJ  
· 访问JSP页面中的所有对象 (~~w7L s  
RDqFL.-S  
· 可以动态地修改页面输出 tCG76LH  
t"072a  
· 彼此这间可以相互通信。你可以先创建一个JavaBeans组件,然后在一个tag中调用此JavaBeans组件,同时可以在另一个tag中调用它。 a|7a_s4(  
SMH<'F7i  
· tag允许相互嵌套,可以在一个JSP页面中完成一些复杂的交互。 2 {Vcb  
1 rs&74-  
jnB~sbyA  
使用tag标签 KJ2Pb"s  
&fa5laJb  
yS(}:'`r  
本节主要描述怎样在JSP页面中使用tag标签,以及tag标签的不同类型。 !~]<$WZV  
5{e,L>H<  
要使用tag标签,JSP程序员必须做2件事: RwI[R)k  
gD`>Twa&6  
· 声明此tag标签的tag库 Fs_]RfG  
YKmsQ(q`N  
· 实现此tag标签 azQD>  
0|&\'{  
声明tag标签所在的tag库 8lF\v/vN  
jHXwOJq %  
如果要使用tag标签,则应用JSP的taglib指示符来指定其tag库(注意:taglib要在在使用此tag标签之前声明) (Rt7%{*  
mm[2wfTE  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> %p^.|Me7  
YOr:sb   
uri属性定义了唯一的标签库描述(以下简称TLD),它可以是直接是tld文件名或一个独一无二的名字。prefix是用来区别其它TLD中和本TLD中有重名的tag的一种手段。 F!zP<A "  
W14F  
TLD必须以.tld作为扩展名,并且存放在当前应用的WEB-INF目录或其子目录下。你可以通过它的文件名直接引用它,也可以通过别的方式间接地引用它。 ,GWNL m\5  
ZF7IL  
以下taglib指示符直接引用一个TLD: L(T12s  
Yim<>. !  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> >_OYhgs1w  
css64WX^0c  
以下的taglib指示符通过一个逻辑名称间接地引用一个TLD: g V5zSudW  
D8&`R  
<%@ taglib uri=”/tutorial-template” prefix=”tt” %>  j~j jX  
-=s(l.?Hm5  
如果是间接引用TLD的话,那你必须还要在web.xml中定义此逻辑名称与tld文件之间的映射,具体做法是在web.xml中加入一个名为taglib的元素: e:H26SW  
tCxF~L@  
<taglib> p G1WXbqW  
m,C1J%{^  
<taglib-uri>/tutorial-template</taglib-uri> d8-A*W[  
F  
<taglib-location> jZ`;Cy\<B  
v>z tB,,9  
/WEB-INF/tutorial-template.tld 76hOB@  
3 rLTF\  
</taglib-location> `w I/0  
!Z VU,b>  
</taglib> _iNq"8>2  
WJ<^E"^  
(=D&A<YX  
实现此tag标签 s .Wdxh  
-*5Rnx|Y{  
.920{G?l5  
为了实现tag标签,你有2种方法来存放tag处理类。一、让tag处理类以.class的方式存放于当前应用的WEB-INF/class子目录下,二、如果tag处理类是以JAR包的形式存在的话,那可以放在当前应用的WEB-INF/lib目录下,如果tag处理类要在多个应用中共享,那么它就应放在jsp服务器上的common/lib目录下,对于tomcat来说,就是tomcat/common/lib目录下。 bR@p<;G|  
=X.LA%Sf=u  
qC F5~;7  
tag标签类型 [Nn`l,  
}neY<{z  
c'/l,k  
自定义的tag标签遵循XML语法。它有一个开始标记和一个结束标记,有的还有body(即文本节点): |5Xq0nvCe  
U9b?i$  
<tt:tag> ~4"qV_M  
WA dCF-S  
body 4pw6bK,s2\  
quY:pqG38q  
</tt:tag> ca+5=+X7  
 {o(j^@  
F:x [  
一个不带body的tag标签如下: ;a:[8Yi  
H":oNpfb  
<tt:tag /> 2UGsYQn  
4apL4E"r  
II6CHjW`;  
简单的tag标签 x _c[B4Tw  
MEB it  
一个没有body和属性的tag标签如下: cnTaJ/o  
vWAL^?HUP  
<tt:simple /> I`NjqyTW  
"DYJ21Ut4  
U&O: _>~  
带属性的tag标签 N-lkYL-%\j  
9 (QJT}qC  
j?'GZ d"B  
自定义标签可以有自己的属性。属性一般在开始标记中定义,语法为 attr=”value”。属性的作用相当于自定义标签的一个参数,它影响着tag处理类的行为。你可以在TLD中详细定义它。 98^V4maR:  
t!RiUZAo  
你可以用一个String常量给一个属性赋值,也可以通过表达式给它赋值,如<%= ...%>。以struts为例,它的logic:present标签就是用的String常量来给属性赋值: 5\z `-)  
SdD6 ~LS  
<loglic:present parameter = “Clear”> wI(M^8F_Mf  
Xh56T^,2  
而另一个标签logic:iterate是用表达式来给属性赋值: ;!yQ  
Gz .|]:1  
<logci:iterate collection=”<%= bookDB.getBooks() %>” 6j ~#[  
2}8v(%s p  
id=”book” type=”database.BookDetails”> GSH>7!.#  
oq}'}`lw"  
!qG7V:6  
带body的tag标签 s{1sE)_  
Jv^h\~*jH  
一个自定义标签可以包含其它自定义标签、脚本变量、HTML标记或其它内容。 .V,@k7U,V  
FSND>\>  
在下述例子中,此JSP页面使用了struts的logic:present标签,如果些标签定义了parameter=”Clear”的属性,则将清除购物车的内容,然后打印出一条信息: KCs[/]  
R17?eucZ  
<logic:present parameter=”Clear”> h $2</J"  
0Vx.nUQ  
<% cart.clear(); %> yqPdl1{Qr=  
B {>7-0  
<font color=”#ff0000” size=”+2”><strong> ZHa"isl$e  
u?C#4  
你选择了清除购物车! wb0L.'jyR)  
WlU0:(d  
</strong></font> VVlr*`  
q<M2,YrbAI  
</logic:present> n rjE.+v  
a |X a3E  
ui?  
到底是用属性还是用body来传递信息? PUUwv_  
r]6C  
如上所述,我们既可以通过属性,也可以通过body来传递信息。但一般来说,比较简单的类型,如字符串或简单表达式最好采用属性来传递信息。 RCpR3iC2  
jnn}V~L  
W)bLSL]`E  
定义脚本变量的tag标签 ueUuJxq)  
7j-4TY~  
所谓脚本变量,是指JSP中可以调用的变量或对象。它可由tag标签产生。以下示例阐述了一个tag标签定义了一个名为tx的由JNDI所定义的事务处理对象。脚本变量可以是ejb对象、事务、数据库连接等等: {tWf  
[@.!~E)P  
<tt:lookup id=”tx” type=”UserTransaction” name=”java:comp/UserTransaction” /> ')cMiX\v  
;=MU';o  
<% tx.begin(); %> y+NN< EY@  
`x*Pof!Io  
... o4Om}]Ti  
c24dSNJg,  
d$1@4r  
具有协作关系的tag标签 ,5h)x"s  
I`!<9OTBj  
自定义tag标签之间可以通过共享对象来实现协作。在下述例子中,标签tag1创建了一个名为obj1的对象,在标签tag2仍可以重复使用obj。 6^`1\ #f  
F'21jy&  
<tt:tag1 attr1=”obj1” value1=”value” /> K|[*t~59  
2GDD!w#!j  
<tt:tag2 attr1=”obj1” /> 'd9INz.  
)?anOD[  
在以下这个例子当中,如果外层的tag标签创建了一个对象,那么其内层的所有tag标签都可以使用这个对象。由于这样产生的对象没有一个指定的名字,那么就可以将少重名的冲突。这个例子阐述了一系列协作的嵌套对象。 HMNLa*CL'  
H*PSR  
<tt:outerTag> eceP0x  
fumm<:<CLO  
<tt:innerTag /> U2W|:~KM  
SHfy".A6.0  
</tt:outerTag> \XZ/v*d0  
ds<2I,t  
``hf=`We  
Tag处理类 RMdk:YvBg  
asppRL||  
 "y}--  
Tag处理类必须实现Tag接口或BodyTag接口,不过现在一般都流行从TagSupport或BodyTagSupport类中继承,这些类或接口都可以在javax.servlet.jsp.tagext包中找到。 I=`U7Bis"  
V@g'#= {r  
当JSP引擎看到自己的JSP页面中包含有tag标签时,它会调用doStartTag方法来处理tag标签的开头,调用doEndTag方法来处理tag标签的结束。 )6Fok3u  
uxr #QA  
下表说明不同类型的tag所需要不同的处理过程: S4_YT@VD%  
a .k.n<  
Tag处理类的方法 f*?]+rz  
},{$*f[  
Tag标签类型 rX2.i7i,  
所调用的方法 yPb"V  
!$gR{XH$]  
基本标签 GjvOM y  
doStartTag, doEndTag, release N 5lDS  
I&x=;   
带属性的标签 9y"@(  
doStartTag, doEndTag, set/getAttribute1...N, release 0AL=S$B)  
p8Qk 'F=h  
带内容的标签 fHx*e'eA  
doStartTag, doEndTag, release vdc\R?  
gCB |DY  
带内容的标签,且内容重复循环 @niHl  
doStartTag, doAfterBody, doEndTag, release Swig;`  
s"r*YlSp"  
带内容的标签,且内容与JSP交互 G3Hx! YW  
doStartTag, doEndTag, release, doInitBody, doAfterBody, release 286jI7T  
,l\- xSM  
一个tag处理类可以通过javax.servlet.jsp.PageContext来与JSP交互,通过javax.servlet.jsp.PageContext类,tag处理类可以访问JSP中的request、session和application对像。 L>Fa^jq5  
86=}ZGWd  
如果tag标签是互相嵌套的,那内层的tag处理类可以通过它的parent属性来访问上层的tag处理类。 _-K2/6zy  
 iu=7O  
一般情况都将所有的tag处理类打成了JAR的包,以便于发布。 , /Z%@-rF  
8e1UmM[  
0ypNUG}   
Tag库描述(简称TLD) ymhtX6]  
qN9(S:_Px  
-=)H{  
Tag库是用xml语言描述的,TLD包括了tag库中所有tag标签的描述,它一般用来被jsp服务器用来校验tag的语法正确性,或者被jsp开发者用来开发新的标签。 }C"%p8=HM  
V^bwXr4f  
TLD的文件扩展名必须为.tld,而且必须放在当前WEB应用的WEB-INF目录或其子目录中。 6 ob@[ @  
p>v$FiV2N  
一个TLD的内容的开头必须遵守标准的XML开头,用于描述DTD和xml的版本,例如: 3M[! N  
ZbW17@b  
<?xml version="1.0" encoding="ISO-8859-1" ?> dy%;W%  
; F"g$_D0  
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd"> *&^Pj%DX  
TLD必须以<taglib>来作为它的根元素,<taglib>的子元素如下表: B" 1c  
yg<R=$n,Q  
rr],DGg+B]  
<taglib>的子元素 /~%&vpF-L  
IL#"~D?  
Element hF~n)oQ  
Description `ts$(u.w  
k8&;lgO '  
tlib-version HdUQCugxx:  
Tag库的版本 Fo5FNNiID  
X9W@&zQ  
jsp-version ]8_NZHld  
Tag库所需要的jsp的版本 5H<m$K4z  
6 $4[gcL'  
short-name Hw}Xbp[y  
助记符,tag的一个别名(可选) ?jv/TBZX4  
@zW]2 c  
uri K7_UP&`=J  
用于确定一个唯一的tag库 +SR+gE\s0  
P^ ~yzI  
display-name _7Ju  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) ] vHF~|/-  
> PRFWO  
small-icon ;#W2|'HD  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) 24 'J  
z% ?+AM)P  
large-icon @e.C"@G  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) X:"i4i[}{9  
Cn34b_Sbd  
description |.: q  
对tag库的描述(可选) RB7tmJ c  
G:<aB  
listener RLjc&WhzXu  
参见下面listener元素 :'X&bn  
>C>.\  
tag ? =Z?6fw  
参见下面tag 元素 UmP/h@8  
@1roe G  
Listener元素 pK>N-/?a  
Cw3 a0u  
一个tag库可能定义一些类做为它的事件侦听类,这些类在TLD中被称为listener 元素,jsp服务器将会实例化这些侦听类,并且注册它们。Listener元素中有一个叫listener-class的子元素,这个元素的值必须是该侦听类的完整类名。 ?=sDM& '  
:%=Xm   
Tag元素 @Md/Q~>  
hR?{3d#x2  
每个tag元素在tag库中都要指出它的名字、类名、脚本变量、tag的属性。其中脚本变量的值可以直接在TLD中定义或通过tag附加信息的类来取得。每个属性描述了这个属性是否可以省略,它的值是否可以通过<%= …%>这样的JSP语法来获得,以及属性的类型。 iHM%iUV  
hn G Z=  
每一个tag在TLD中对应一个tag元素,下表是tag元素的子元素: e'NJnPO  
me$Z~/Akm  
Tag元素的子元素 AlaW=leTe  
 JYI,N  
元素名称 {UI+$/v#  
描述 N)X3XTY  
IVY]EkEG~  
name Woy m/[i  
独一无二的元素名 I^-Sb=j?Z  
Q~ w|#  
tag-class Rsm^Z!sn  
Tag标签对应的tag处理类 Vx u0F]%  
tCH!my_  
tei-class L ca}J&x]^  
javax.servlet.jsp.tagext.TagExtraInfo的子类,用于表达脚本变量(可选) v0{i0%d,?  
W:2( .?  
body-content kiaw4_  
Tag标签body的类型 Ty?cC**  
q6luUx,@m  
display-name *Hn8)x}E  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) _ ]ip ajT  
D#C~pdp  
small-icon 7&)bJ@1U  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) +{.WQA}z\  
P/eeC"  
large-icon VscE^'+  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) H/ HMm{4  
Ax7[;|2  
description lTgjq:mn  
此tag标签的描述 IM'r8 V  
~q.F<6O  
variable p8O2Z? \  
提供脚本变量的信息(同tei-class)(可选) (y~TL*B  
mO7]9 p  
attribute +~$ ]} %  
Tag标签的属性名 EW OVx*l  
sY&IquK^  
以下章节介绍对于不同类型的tag,如何具体地实现它们。 B~ GbF*j  
! n@KU!&k  
N =}A Z{$  
简单的tag 83_h J  
013x8!i  
[}=B8#Jl-C  
tag处理类 e X|m  
f}P3O3Yv&  
简单的tag处理类必须实现Tag接口的doStartTag和doEndTag方法。当jsp引擎碰到tag标签的开头时,doStartTag被调用,因为简单的tag没有body,所以此方法将返回 SKIP_BODY。当jsp引擎碰到tag标签的结尾时,doEndTag被调用,如果余下的页面还要被计算,那它将返回EVAL_PAGE,否则将会返回SKIP_PAGE。 6A-|[(NS  
uo 8YP<q  
以下是例子:对于标签 <tt:simple /> ,它的tag处理类实现如下: jV1.Yz (`  
EV%gF   
wlqksG[B  
public SimpleTag extends TagSupport \Gvm9M  
cdT7 @  
{ .Yn_*L+4*  
kn 4`Fa;)O  
public int doStartTag() throws JspException g8% &RG  
#q=Efn'  
{ +a+Om73B2  
^hM4j{|&M  
try{ dUZ ,m9u  
Zb>?8  
pageContext.getOut().print(“Hello.”); <\^8fn   
O_7|C\]  
}catch(Exception e){ aX'*pK/-  
_Y;W0Z  
throw new JspTagException(“SimpleTag: “ + e.getMessage()); YU'E@t5  
sUQ@7sTj  
} ?0SJfh  
hHnYtq  
return SKIP_BODY; 9W2Vo [(  
 x'<X!gw  
} + [mk<pQ  
?Z/V~,  
public int doEndTag() b3, _(;A!  
H*CW1([  
{ 0 M[EEw3  
8<Av@9 *}  
return EVAL_PAGE; j A%u 5V  
/*mI<[xb  
} /h3RmUy   
h S&R(m  
} + cN8Y}V  
.aQ \jA  
(O3nL.  
注意:如果tag标签没有内容的话,那必须定义body-content元素为空,例如 2P0*NQ   
F={a;Dvrn  
<body-content>empty</body-content> UP,c|  
83#mB:^R  
4H&+dR I"  
带属性的tag标签
评价一下你浏览此帖子的感受

精彩

感动

搞笑

开心

愤怒

无聊

灌水
级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
只看该作者 1 发表于: 2007-01-01
tag处理类 $=4QO  
^ [@ ,  
对于tag标签的每个属性,你必须依照JavaBeans规范来定义其属性,以及get和set方法。以struts的logic:present 标签为例, /%^#8<=|U  
'D1xh~  
<logic:present parameter=”Clear”> /j.9$H'y  
;:NJCuG  
与此相应,此tag处理类应有如下方法和定义: Q\Vgl(;lX  
gg2( 5FPP  
w\O;!1iU  
protected String parameter = null; 4o[{>gW  
"^GGac.  
public String getParameter() \'O"~W  
)Pv%#P-<  
{ k8zI(5.>  
6Z"X}L,*  
return this.parameter; }N52$L0[  
^iV)MTT  
} A.w.rVDD  
qIT@g"%}t  
public void setParameter(String parameter) X"%gQ.1|{j  
)9]PMA?u  
{ 1$h,m63)  
vnuN6M{  
this.parameter = parameter; Ig{0Z">  
f3y=Wxk[  
} c-sfg>0^  
5Gm_\kd  
c7H^$_^=  
注意:如果你的属性名为id,而且你的tag处理类是从TagSupport类继承的,那你就不需要定义它的属性和set和get方法,因为他们早已在TagSupport被定义过了。 y?3; 06y|  
K{+2G&i  
Attribute元素 KMax$  
fp"W[S|uL  
对于tag标签的每个属性,你必须定义它是否必须的,它的值是否可以用诸如<%= …%>的表达式来获得,以及它的类型(可选),如果不指定它的类型,那就默认为是java.lang.String类型。如果rtexprvalue元素被定义为true或yes,那么在type元素中就定义了attribute的返回类型。 4#Jg9o   
S,8e lKH4  
<attribute> p5*EA x  
=7UsVn#o  
<name>attr1</name> ^S; -fYW2  
2GG2jky{/  
<required>true|false|yes|no</required> TWX.D`W  
=?8@#]G+  
<rtexprvalue>true|false|yes|no</rtexprvalue> 2&cT~ZX&'  
m9;SrCN_  
<type>attribute的返回类型(只用当rtexprvalue为真是才有效)</type> v`T c}c '  
Zv{'MIv&v  
</attribute> wC'Szni  
-mh3DhJ,  
如果tag的某个属性不是必须的,那tag处理类会自动提供一个缺省值。 *{5fq_  
(/$^uWj  
例如,在logic:present这个tag标签中定义了一个属性叫parameter,但它不是必须的,而且它可以被诸如<%= …%>的表达式来赋值。 RxQ*  
E"IZ6)Q  
<tag> Dw"\/p:-3  
;n;p@Uu[ b  
<name>present</name> Q/Rqa5LI:  
#5uOx(>  
<tag-class>org.apache.struts.taglib.logic.PresentTag</tag-class> uXiN~j &Be  
?e?!3Bx;EM  
<body-content>JSP</body-content> t_1L L >R  
/x *3}oI  
3XNCAb2  
DHRlWQox  
<attribute> * v#o  
;kKyksxlD  
<name>parameter</name> yf,z$CR  
^B^9KEjTz  
<required>false</required> }6ldjCT/,  
Vjpy~iP4B  
<rtexprvalue>true</rtexprvalue> n=q 76W\  
7xR\kL.,  
</attribute> G#$-1"!`  
_yT Ed"$  
!<F3d`a  
?V=CB,^  
</tag> Iu6   
1Z&(6cDY8M  
TcoB,Kdce  
属性元素的校验 glw+l'@  
2`-Bs  
,]D,P  
有关于tag标签的有效值可以从tag库的说明文档中获得,当JSP页面被编译时,jsp引擎会强制性地参照TLD中定义的规则进行检查。 w!XD/j N  
=EsavN  
还有一个方法也可以进行属性元素的校验,就是先继承类TagExtraInfo,然后调用它的isValid方法。这个类同时也起到提供tag中定义的脚本变量信息的作用。 (;,sc$H]  
s#GLJl\E_P  
IsValid方法通过TagData对象来传递属性信息,它包括着tag的所有的属性名-值的信息。由于校验发生在运行时刻,因此这个属性的值将被赋值为TagData.REQUEST_TIME_VALUE。 !'I8:v&D  
d_P` qA  
例如tag标签<tt:twa attr1=”value1” />在TLD中定义如下: nr#|b`J]  
u%!@(eKM-  
<attribute> 'c~4+o4co  
& 5R&k0i r  
<name>attr1</name> +cRn%ioVi  
[N'h%1]\  
<required>true</required> t#yuOUg  
3(UVg!t  
<rtexprvalue>true</rtexprvalue> V VCZ9MVJ  
uw8f ~:LT  
</attribute> y)<q /  
2A!FDr~cdT  
]_$[8#kg  
这个定义说明了attr1能在运行期间被赋值。 `H+ lPM66  
4&iCht =  
以下的isValid方法检查attr1属性的值是否属于Boolean类型。注意由于attr1能在运行刻被赋值,那么isValid方法必须检查tag用户是否对此tag进行了运行时刻赋值。 Z30A{6}  
"wc<B4"  
")25 qZae  
Public class TwaTEI extends TagExtraInfo S|}L&A  
 AOx[  
{ v-Sd*( 6  
6w77YTJ  
public boolean isValid(Tagdata data) cc3 4e  
*lb<$E]="!  
{ >-c8q]()ly  
K,UMqAmk  
Object o = data.getAttribute(“attr1”); F:ELPs4"  
.G\7cZ  
If(o != null && o != TagData.REQUEST_TIME_VALUE) :E?V.  
#A.@i+Zv  
{ tf G@&&%9  
fc@A0Hf  
if( ( (String)o).toLowerCase().equals(“true”) || &m vSiyKX  
WF"k[2  
((String)o).toLowerCase().equals(“false”) ) DV{=n C  
?X;RLpEc|A  
return true; [00m/fT6  
$od7;%  
else %XTI-B/K  
x)VJFuqy  
return false; 3uMy]HUQ  
DTs;{c  
} }~q5w{_n  
']oQ]Yx0  
else [Nq*BrzF  
2?i7 UvV  
return true; L0]_X#s>#  
1 {)Q[#l  
} %>s |j'{  
azU"G(6y?+  
} Y^]rMK/;  
O H7FkR  
=w^M{W.w  
带body的tag  S[QrS 7  
jFb?b6b  
mBC+6(5V  
tag处理类 YbLW/E\T  
v8D C21pb  
y?!"6t7&  
如果tag标签含有内容,那处理方式会略微有些不同,而且还要视tag处理类是否要与body交互的情况而定。如果要与body交互,那我们认为tag处理类要可能要对body进行操作。 4.(4x&  
*|l/6!WM  
Tag处理类不与body交互 CQ2jP G*py  
< 7$1kGlA  
如果tag处理类不与body交互,tag处理类应该实现Tag接口或从TagSupport中派生,如果body要被计算,那么doStartTag方法应返回 EVAL_BODY_INCLUDE,否则应返回SKIP_BODY。 YoE3<[KD(  
]R? 4{t4  
如果tag处理类要对body反复运算,则它应该实现IterationTag或从TagSupport中派生。如果tag处理类认为body还未计算完的话,那它的doStartTag方法和doAfterBody方法必须返回EVAL_BODY_AGAIN。 O9p|a%o  
L8n|m!MOD  
Tag处理类与body交互 qY#6SO`_iy  
~_ a-E  
如果tag处理类与body交互,那tag处理类应实现BodyTag接口或从BodyTagSupport中派生。这种tag处理类一般要实现doInitBody和doAfterBody方法。 $]8Q(/mbK  
Qci]i)s$js  
Body允许一些方法来读写它的内容。Tag处理类可以调用body内容的getString或getReader方法来从body中提取信息,也可用 writeOut(out) 方法来将body的内容写入到out对象中。其中out对象通过tag处理类的getPreviousOut方法来获得。 RT5T1K08I  
!%>7Dw(kt  
如果body的内容需要被计算,那么doStartTag方法必须返回EVAL_BODY_BUFFERED,否则,它将返回 SKIP_BODY。 bN88ua}k{  
|Ds=)S" K  
doInitBody 方法 A(N4N  
1&$ nVQ  
此方法在body内容已经设好,但未被计算之前被调用。你可以根据不同的body内容来制定初始化策略。 XZwK6F)L  
c"xK`%e  
doAfterBody方法 \(T /O~b2  
,=N.FS  
此方法在body内容已被计算后进行调用。 k+4#!.HX^  
Cls%M5MH  
和doStartTag方法一样,doAfterBody方法返回一个指示符指示是否要继续计算body,如果要继续计算,则doAfterBody应返回EVAL_BODY_BUFFERED,否则,它应返回SKIP_BODY。 07$o;W@  
'3H_wd  
release 方法 (tQc  
l@:0e]8|o  
tag处理类调用此方法将它的状态重置为初始状态,并释放所有的私有资源。 G#1GXFDO{  
PxE3K-S)G  
\|ao`MMaD<  
以下的例子读取body的内容(其中含有一条sql语句),然后将它传递给一个对象,让它进行查询。由于此处body不须重新计算,所以doAfterBody会返回SKIP_BODY。 9k=3u;$v  
v9UD%@tZ  
:j`s r  
Public class QueryTag extends BodyTagSupport ~v"L!=~G;a  
m4yL@d,Yw  
{ '%`:+]!  
fxIf|9Qi`  
public int doAfterBody() throws JspTagException {zFMmPid  
bYPKh  
{ 'P}0FktP`  
(4EI-e*6  
BodyContent bc = getBodyContent(); 3yXY.>'  
k$7Jj-+~  
//将body的内容以字符串的格式提取出来 {}Za_(Y,]  
s|ITsz0,td  
String query = bc.getString(); b_):MQ1{  
4'Zp-k?5`  
//清除body d`6 ' Z  
V470C@  
bc.clearBody(); +t;7tQDVB  
Xs?o{]Fe  
try{ "wHFN>5B  
8e|%M  
Statement stmt = connection.createStatement(); :a)u&g@G  
H7j0K~U0  
Result result = stmt.executeQuery(query); 4a]P7fx-  
&! ?eL  
}catch(SQLException e){ <"|,"hA  
GM<-&s!Uj  
throw new JspTagException(“queryTag: “ + e.getMessage() ); 1sH& sGy7  
V$?SR44>nH  
return SKIP_BODY; 8&aq/4:q0  
J)C/u{o  
} Tu7QCr5*  
l/awS!Q/nF  
} O8.5}>gDn.  
i7>tU=  
xZv#Es%#  
body-content元素 pV"R|{#V  
N8FF3}> g  
VU d\QR-  
由于tag可能会有body,你必须用body-content元素来指定body内容的类型: baK$L;Xo:  
"FKOaQ%IH  
<body-content>JSP|tagdependent</body-content> I.k *GW  
.VzT:4-<Q"  
1y4  
如果body的内容是定制的或内部的tag、脚本元素、或HTML广本,则归类为JSP类型。其他的类型,比如上面代码所述的?D?D将sql statement类传给 query tag的这种类型应该标为tagdependent。 <A'$%`6m  
0_t`%l=  
注意:实际上body-content的值并不影响tag处理类对body内容的处理,它仅仅是被tag编辑工具用来描述此body的内容。 {!dVDf_  
^ovR7+V  
abLnI =W`  
用tags定义脚本变量 uU25iDn  
Z/;aT -N  
I(0~n,=j  
tag处理类 iW /}#  
9p2&) kb6  
cjIh}:| '  
tag处理类负责创建或设置页面中定义的脚本变量,用pageContext.setAttribute(name,value,scope)或pageContext.setAttribute(name,value)方法来实现。一般来说,tag处理类通过脚本变量的名称来获取它,脚本变量的名称一般可用get方法来获得。 {,~3.5u   
6f*CvW  
如果脚本变量的值依赖于tag处理类中的上下文中某一对象,那它可用pageContext.getAttribute(name,scope)方法来找到那个对象。一般的处理过程是tag处理类先找到脚本变量,再对其进行处理,然后用pageContext.setAttribute(name,object)的方法来设置它的新值。 & 9 ?\b7  
w)Qp?k d  
对象的生存周期(scope)如下表: 2('HvH]k  
Np0u,t%vs  
对象的生存周期表 /d<P-!fK  
*w&Y$8c(  
名字 <yFu*(Q  
可访问范围 X*Prll(  
生存周期  'CkIz"Wd  
'y3!fN =h  
page Fun^B;GA:  
当前页面 vOpK Np  
一直有效,除非页面向客户提交响应或重定向到一个新页面 7s{GbU\  
<<R*2b  
request b`O'1r\Y;  
当前页面或当前页面重定向到的页面 DZ PPJ2}  
一直有效,除非页面向客户提交响应 r? E)obE  
p2$P:!Y)  
session }@+:\   
当前页面或在同一浏览器窗口中的页面 ~1vDV>dpE  
一直有效,除非关闭当前浏览器、超时、网络故障 [^98fAlz6  
7Da`   
application EA]U50L(  
整个web应用程序的所有请求 d,n 'n  
一直有效,除非发生网络故障、服务器故障 &@Be2!%'9K  
Y\?"WGL)p  
提供关于脚本变量的信息 >e[i5  
(jl D+Y_  
以下示例定义了一个名为“book”的脚本变量,用来访问程序中关于书的信息: 6MMOf\   
OA"q[s  
<bean:define id=”book” name=”bookDB” property=”bookDetails” type=”database.BookDetails” /> JB[~;nLlC  
czRFMYE  
<font color=”red” size=”+2” > hp-<2i^"!  
oEKvl3Hz_  
<%= messages.getString(“CartRemoved”) %> 4 VW[E1<  
#Kex vP&*  
<strong><jsp:getProperty name=”book” property=”title” /></strong> orMwAV  
aH/ k Ua  
</font> FSW_<%  
X!dYdWw*m  
当包含此tag的JSP页面被编译时,jsp引擎会自动生成关于此book的同步的代码(同步可以避免几个客户同时访问此book时造成的冲突),要生成同步代码,jsp引擎需要知道此脚本变量的如下信息: ;P%1j|7  
_C[q4?  
· 脚本变量名称 F%D.zvKN  
XXn67sF/  
· 脚本变量所属的类 ]a*d#  
0*D$R`$  
· 此脚本变量是否引用了一个新的或已存在的对象 %.-4!vj  
GM f `A,>  
· 此脚本变量的有效性 T&u5ki4NE  
z !rL s76  
有两种办法可以向jsp引擎提供关于脚本变量的信息:在TLD中定义variable子元素,或用tei-class子元素定义一个额外tag信息类。用variable最简单,但可能降低了一些灵活性。 *kDCliL  
DKJmTH]rUg  
Variable元素 fN^8{w/O  
iE^84l68  
Variable元素有如下子元素: >rKIG~P_  
c?[I?ytl  
· name-given ?D?D 给出的名字,是一个常量 MH9q ;?.J  
;LSANr&  
· name-from-attribute?D?D 属性名,在编译时给出的属性名 MPg)=LI  
c>:wd@w  
name-given或name-from-attribute两者必须选一,但以下子元素是可选的: ywm8N%]v  
tm RXgTS  
· variable-class?D?D变量的类型,缺省为java.lang.String。 k],Q9  
rgtT~$S  
· declare?D?D此脚本变量是否引用了一个新对象,缺省为True。 =BAW[%1b  
0 e ~JMUb  
· scope?D?D脚本变量的范围,缺省为NESTED。下表描述了scope的几种类型: ,,Q O^j]4~  
3/e.38m|  
脚本变量的有效范围 7XLtN "$$  
-Xm'dwm  
RF4vtQC=  
有效性 T9_RBy;%  
方法 >T3-  
V>-e y9Q\  
NESTED q"sed]  
在tag标签的开始和结束之间 ]e>w }L(gV  
如果tag处理类实现BodyTag接口,则在doInitBody和doAfterBody中调用,否则在doStartTag中调用 `l){!rg8IC  
KD7dye  
AT_BEGIN ]uJ"?k=  
从tag标签的开始一直到页面结束 {|_M # w~&  
如果tag处理类实现BodyTag接口,则在doInitBody、doAfterBody和doEndTag中调用,否则在doStartTag和doEndTag中调用 *>'V1b4}  
Yz"#^j}Kg  
AT_END })8N5C+KU  
从tag标签的结束一直到页面结束 vB|hZTW  
在doEndTag中调用 aPfO$b:  
suiS&$-E  
以struts为例,它的bean:define标签的实现遵循JSP1.1规范,此规范要求使用额外tag信息类来定义脚本变量。Variable元素是JSP1.2规范中加入的。以bean:define标签为例,你可以定义如下variable元素: A,hJIe  
cyv`B3}  
<tag> j0S# >t  
Gm.T;fc:  
<variable> u jq=F  
6/Xk7B  
<name-from-attribute>id</name-from-attribute> Fk*7;OuZl  
a /l)qB#  
<variable-class>database.BookDetails</variable-class> {9;CNsd  
>#~& -3  
<declare>true</declare> _w(7u(Z  
BsqP?/  
<scope>AT_BEGIN</scope> ,nLy4T&"  
5Y'qaIFR  
</variable> n:\~'+$  
lVR~Bh  
</tag> _j/<{vSy  
E=CsIK   
额外tag信息类 E+R1 !.  
z.9U}F  
如果要定义一个额外tag信息类,你要继承javax.servlet.jsp.TagExtraInfo类。一个TagExtraInfo类必须实现getVariableInfo方法,此方法返回一个叫VariableInfo的数组类,它包括如下信息: mD0f<gJ1  
m=A(NKZ   
· 变量名 >G*eNn  
foF({4q7b^  
· 变量所属类名 %.Fi4}+O  
Agg<tM{yB  
· 此变量是否引用了一个新对象 H*&f:mfq  
}{qZ[/JwqN  
· 此变量的有效范围 k,E{C{^M  
EZy)A$|  
jsp引擎将一个名为data的参数传给getVariableInfo方法,data中包括tag标签中的所有“属性名?D?D属性值”对。它可以用来向VariableInfo对象提供脚本变量的名字和类名。 QP^Cx=  
l7259Ro~  
以struts为例,它在bean:define标签中定义了一个名为DefineTei的额外tag信息类,用来向脚本变量提供信息。由于脚本变量的名称(book)和类名(database.BookDetails)是通过tag标签的属性来传递的,它们一般定义在VariableInfo的构建代码中,并且可用data.getAttributeString方法来得到这些信息。如果要允许book脚本变量能在从tag开始直到整个JSP页面结束的范围内都可用的话,那它的范围应设为AT_BEGIN。如下所示: zH4D8@[7O  
UkT=W!cq  
T/Gz94c  
public class DefineTei extends TagExtraInfo B^Nf #XN(  
p7VTa~\zA  
{ ~u!|qM  
J^nBdofP  
public VariableInfo[] getVariableInfo(TagData data) 8# >op6^  
F2dHH^  
{ ogtEAv~e7N  
rEnQYz  
String type = data.getAttributeString(“type”); m!4ndO;0vh  
fc%xS7&  
If( type == null) )}]g] g  
'(VJ&UlS2  
type = “java.lang.Object”; I<4Pur>"  
gsv uE  
return new VariableInfo[] { oMD>Yw c-  
D},>mfzF  
new VariableInfo(data.getAttributeString(“id”), 5k3n\sqZA  
<fjX[l<Uz  
type, {3p4:*}  
tl4V7!U@^z  
true, =J]]EoX/  
,p@y] cr  
VariableInfo.AT_BEGIN) -p&" y3<p  
FLCexlv^  
}; ,j}6? Q  
5C*Pd Wpl  
} !t %j?\f  
)uIe&B  
} ?)?Ng}  
;| 5F[  
zh`<WN&H  
注意:关于额外tag信息类的类名必须要在TLD中的tag标签下的tei-class子元素中定义。因此,DefineTei的tei-class中的定义看起来如下: wj<6kG  
<tei-class> Eh;'S"{/?j  
org.apache.struts.taglib.bean.DefineTagTei # E^1|:  
</tei-class> 9ni1f{k  
C'@i/+  
Ae^~Cz1qz  
具有协作关系的tag #$+*;  
} FlT%>Gw  
[0[i5'K:  
tag通过共享对象来进行协作,JSP技术支持2种方式的对象共享。 @* jz o  
Uq,^Wy  
第一种方法是使用pageContext对象进行对象的共享(可支持JSP页面和tag处理类之间的共享),如果在一个tag处理类中要调用由另一个tag处理类创建的对象,可调用pageContext.getAttribute(name, scope)方法。 +I:Unp  
cAqLE\h  
第二各方式的共享是对于tag之间有嵌套关系而言的,外层的tag所创建的对象对于内层的tag来说是可以共用的。这种形式的共享的好处是减少了可能存在的重名冲突。 TnOggpQ6X  
"f2$w  
要访问一个嵌套tag创建的对象,tag处理类必须先找到此嵌套tag对象,可用TagSupport的静态方法 TagSupport.findAncestorWithClass(from, class)或TagSupport.getParent方法。前者在当不确定此tag是否为嵌套tag对象时使用。一旦它的父类被找到,它就能访问其所有动态或静态创建的对象。静态创建的对象是父类的成员,而动态创建的对象可能是父类的私有对象。诸如此类的对象可以用tag处理类的setValue方法来保存,用getValue方法来获得。 |'8Nh  
Nk 8B_{  
下例阐述了以上两种共享对象的方法。在这个例子当中,一个查询tag检查一个名为connection的属性名是否在doStartTag中被设置。如果connection属性被设置,tag处理类从pageContext中得到这个connection对象。否则,此tag处理类先找到它的父tag处理类,然后从它的父tag处理类中找到connection对象。 7Lc]HSZo,  
mh{d8<Q2  
/P3 <"?#k  
public class QueryTag extends BodyTagSupport omu|yCK  
ufZDF=$7  
{ 7P5)Z-K[  
Rz:]\jcIT/  
private String connectionId; gHEu/8E  
Ugt/rf5n  
public int doStartTag() throws JspException gNrjo=  
UiP"Ixg6  
{ 6|%?tex  
\?ZB]*Fu  
String cid = getConnection(); { Fb*&|-n  
n)e 6>R ;  
if(cid != null) vHc%z$-d  
@#>rYAb8,  
{ SC!RbW@3  
 #ut  
//存在一个connection id,使用它。 AW'0,b`v  
7~% ?#  
connection = (Connection) pageContext.getAttribute(cid); J T7nG.9  
G1tY)_-8[  
} rjAn@!|:+  
r:'.nhe  
else o5O#vW2Il&  
c?*=|}N  
{ ww3-^v  
z`}qkbvi  
ConnectionTag ancestorTag = (ConnectionTag)findAncestorWithClass(this, 1;8UC;,  
S-b/S5  
ConnectionTag.class); EIAc@$4  
^4hO  
if(ancestorTag == null) 1~`fVg  
`pS9_ NYZ}  
{ EhvX)s  
9c'xHO`  
throw new JspTagException(“一个没有connection属性的查询标签必须被一个connection标记嵌套。”); DGF5CK.O  
CL;}IBd a  
} ~.nmI&3  
~2N"#b&J  
connection = ancestorTag.getConnection(); J#(LlCs?@c  
j#x6  
} RFcv^Xf  
9uO 2Mm  
} IGQFtO/x  
RnE4<Cy  
} w<3#1/g!2B  
>J?fl8  
o4,6.1}  
6]N;r5n  
此查询标签在JSP页面中的调用形式可以从以下2种定义中任选一种: /NFj(+&g+  
QXFo1m  
1{. |+S Z!  
<tt:connection id=”con01” ...> ... </tt:connection> 70nqD>M4  
GPudaF{  
<tt:query id=”balances” connection=”con01” > ]Sz:|%JP1  
e}7lBLK]*  
SELECT account, balance FROM acct_table n\'4  
1#2 I  
where customer_num = <%= request.getCustno() %> B{#I:Rs9  
(gU!=F?#m  
</tt:query> [5b--O  
a0E)2vt4  
j0aXyLNX  
y9GoPC`z  
]^7@}Ce_  
<tt:connection ...> ^|(LAjet  
wv1iSfW  
<x:query id=”balances”> 5m 4P\y^a  
=R|HV;9 h  
SELECT account, balance FROM acct_table ]|a g  
,PW'#U:  
where customer_num = <%= request.getCustno() %> i)#dWFDTv  
P>D)7 V9Hh  
</x:query> O+]ZyHnB  
R| , g<  
</tt:connection> KYI/  
U_Ptqqt%  
"m8^zg hL  
与此同时,在TLD中必须指定connection属性为可选的,定义如下:  %OCb:s  
j2[+z tG  
<tag> tw/dD +  
9:|{6_Y  
... #q$HQ&k  
ZJJY8k `  
<attribute> O _ gGf  
v{N`.~,^  
<name>connection</name> !i}w~U<  
_< V)-Y  
<required>false</required> AeM^73t  
BwpqNQN  
</attribute> B dfwa  
An0|[uWH  
</tag>
描述
快速回复

您目前还是游客,请 登录注册
如果您在写长篇帖子又不马上发表,建议存为草稿
认证码:
验证问题:
10+5=?,请输入中文答案:十五