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

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

级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
标准的JSP 标记可以调用JavaBeans组件或者执行客户的请求,这大大降低了JSP开发的复杂度和维护量。JSP技术也允许你自定义taglib,其实换句话说,taglib可以看成是对JSP标记的一种扩展,正如xml是对html的一种扩展一样。taglib通常定义在tag标签库中,这种标签库存放着你自己定义的tag标签。简而言之,如果使用taglib,那么你可以设计自己的JSP标记! x~O_v  
R_DZJV O  
一般来说,自定义tag标签主要用于操作隐藏对象、处理html提交表单、访问数据库或其它企业级的服务,诸如邮件和目录操作等等。自定义tag标签的使用者一般都是那些对java编程语言非常精通,而且对数据访问和企业级服务访问都非常熟悉的程序员,对于HTML设计者来说,使得他可以不去关注那些较复杂的商业逻辑,而将精力放在网页设计上。同时,它也将库开发者和库使用者进行合理分工,自定义tag标签将那些重复工作进行封装,从而大大提高了生产力,而且可以使得tag库可用于不同的项目中,完美地体现了软件复用的思想。 Y{#m=-h  
bPdbKi{j@  
在这篇文章中,我们主要讨论: qg@Wzs7c~  
%g&i.2v  
· 什么是自定义tag标签? 80ms7 B  
vV9q5Bj:  
· 怎么使用tag标签? SA$1rqU=  
cS1BB#N0  
o 声明要使用的tag库 NCysYmt  
AU +2'  
o 找到与之对应的tag处理类 \=/^H  
s*j0uAq)up  
o tag标签的类型 m)9qO7P  
(Sg52zv  
· 自定义tag标签 ]LhNP}c  
I806I@ix  
o tag处理类 Q:B:  
q[SUYb;,  
o tag库描述  Dy@f21+  
V<!E9/4rS  
o tag标签示例 ~FV Z0%+,  
bP 2IX  
o 带属性的tag az]S&\i7T  
f[/E $r99J  
o 带body的tag COK7 i^  
UujFZg[-P9  
o 定义了脚本变量的tag pJ#R :#P  
,2%>e"%  
o 具有协作关系的tag b1;80P/:D  
Y<S,Xr;J:  
· 自定义tag标签 v(t?d  
ATU 2\Y  
o 一个迭代tag的例子 |EaEdA@T  
rX#} 2  
o 一个模板tag库 cwxO| .m  
`?VB)  
o tag处理类到底是怎样被调用的? * 5#Y [c  
bg)yl iX  
#9Z*.  
什么是自定义的tag? ?8X+)nU@  
t$Z#zx X  
一个自定义的tag标签是用户定义的一种JSP标记。当一个含有自定义的tag标签的JSP页面被jsp引擎编译成servlet时,tag标签被转化成了对一个称为tag处理类的对象进行的操作。于是当JSP页面被jsp引擎转化为servlet后,实际上tag标签被转化成为了对tag处理类的操作。 M+ gYKPP  
d\V\,% &.  
自定义tag标签有很多特色,诸如: `1KZ14K  
\~zTc_  
· 可以在JSP页面中自定义tag标签的属性 U:E:"  
!R WX1Z  
· 访问JSP页面中的所有对象 kN>AY'1  
SL/ FMYdd  
· 可以动态地修改页面输出 Ss&R!w9p  
J~:/,'Ea  
· 彼此这间可以相互通信。你可以先创建一个JavaBeans组件,然后在一个tag中调用此JavaBeans组件,同时可以在另一个tag中调用它。 3L4lk8Dd  
$N=A,S  
· tag允许相互嵌套,可以在一个JSP页面中完成一些复杂的交互。 6;GL>))'  
!_cT_ WHty  
C``%<)WC  
使用tag标签 :(Feg2c  
CBTa9|57  
xU^Flw,4  
本节主要描述怎样在JSP页面中使用tag标签,以及tag标签的不同类型。 Kl$!_$  
v>$GVCY  
要使用tag标签,JSP程序员必须做2件事: Au" [2cG  
g0^%X9s  
· 声明此tag标签的tag库 quU%9m \S`  
Ajhrsa\~a  
· 实现此tag标签 W]n%$a  
;{ Y|n_  
声明tag标签所在的tag库 ue$\ i=jw  
c`y[V6q9  
如果要使用tag标签,则应用JSP的taglib指示符来指定其tag库(注意:taglib要在在使用此tag标签之前声明) pWB)N7x&  
Sg0 _l(  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> ){")RrD(  
VWmZ|9Ri  
uri属性定义了唯一的标签库描述(以下简称TLD),它可以是直接是tld文件名或一个独一无二的名字。prefix是用来区别其它TLD中和本TLD中有重名的tag的一种手段。 (6?pBdZ  
h.g11xa  
TLD必须以.tld作为扩展名,并且存放在当前应用的WEB-INF目录或其子目录下。你可以通过它的文件名直接引用它,也可以通过别的方式间接地引用它。 .)B_~tct  
Kig.hHj@  
以下taglib指示符直接引用一个TLD: A[!Fg0X0  
V D.p"F(]  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> ~y^#?;  
Sz"J-3b^  
以下的taglib指示符通过一个逻辑名称间接地引用一个TLD: r 06}@7  
w=3@IW  
<%@ taglib uri=”/tutorial-template” prefix=”tt” %> M>0=A  
^C@uP9g  
如果是间接引用TLD的话,那你必须还要在web.xml中定义此逻辑名称与tld文件之间的映射,具体做法是在web.xml中加入一个名为taglib的元素: ^gh/$my;  
VD +8j29  
<taglib> +8Zt<snG  
7##nY3",^  
<taglib-uri>/tutorial-template</taglib-uri> "a6 wd  
GOa](oD}  
<taglib-location> f 7et  
pH?VM&x  
/WEB-INF/tutorial-template.tld bUp%87<*X  
9 YU7R)  
</taglib-location> Sy'/%[+goJ  
PT|^RF%fT  
</taglib> B.K"1o  
*6q8kQsz^1  
fh )QX  
实现此tag标签 {`KgyC W:  
T2} I,{U  
hX 9.%-@sR  
为了实现tag标签,你有2种方法来存放tag处理类。一、让tag处理类以.class的方式存放于当前应用的WEB-INF/class子目录下,二、如果tag处理类是以JAR包的形式存在的话,那可以放在当前应用的WEB-INF/lib目录下,如果tag处理类要在多个应用中共享,那么它就应放在jsp服务器上的common/lib目录下,对于tomcat来说,就是tomcat/common/lib目录下。 }` Q'!_`  
9.lSF  
<{YP=WYW  
tag标签类型 @|%t<{y^I  
djPr 4Nog  
:4<+)r26  
自定义的tag标签遵循XML语法。它有一个开始标记和一个结束标记,有的还有body(即文本节点): Rmn|"ZK  
4G@vO {$  
<tt:tag> <=cj)  
LlRvm/  
body ,^,Vq]$3  
L1Fn;nR  
</tt:tag> 2ADUJ  
dj?.Hc7od  
/!JpmI  
一个不带body的tag标签如下: 5cxA,T  
u$&7fmZ  
<tt:tag /> xh @H@Q\  
>('L2]4\v  
I\Y/*u  
简单的tag标签 ~0|~Fg  
ZGzrh`j{-  
一个没有body和属性的tag标签如下: gUL`)t\}*  
=a?l@dI]  
<tt:simple /> M$%aX,nk'  
68Wm=j.m  
. ~G>vVb  
带属性的tag标签 _myam3[W  
Trbgg  
6VQ*z8wLw  
自定义标签可以有自己的属性。属性一般在开始标记中定义,语法为 attr=”value”。属性的作用相当于自定义标签的一个参数,它影响着tag处理类的行为。你可以在TLD中详细定义它。 d~S.PRg=  
QCa$<~c  
你可以用一个String常量给一个属性赋值,也可以通过表达式给它赋值,如<%= ...%>。以struts为例,它的logic:present标签就是用的String常量来给属性赋值: 6O$OM  
}N2T/U  
<loglic:present parameter = “Clear”> Kdx?s;i  
KTBsH;6  
而另一个标签logic:iterate是用表达式来给属性赋值: 4'Vuhqk  
zL3~,z/o  
<logci:iterate collection=”<%= bookDB.getBooks() %>” x nWapG  
6rt.ec(  
id=”book” type=”database.BookDetails”> ;r^8In@6  
Bu>srX9f  
0D|^S<z6  
带body的tag标签 Qgo0uu M  
"] kaaF$U%  
一个自定义标签可以包含其它自定义标签、脚本变量、HTML标记或其它内容。 26 o68U8&y  
( y2%G=.j  
在下述例子中,此JSP页面使用了struts的logic:present标签,如果些标签定义了parameter=”Clear”的属性,则将清除购物车的内容,然后打印出一条信息: L;fhJ~ r  
6;I&{9  
<logic:present parameter=”Clear”> 9!_`HE+(XJ  
1reJ7b0  
<% cart.clear(); %> YmB z$  
N: d`L+tcc  
<font color=”#ff0000” size=”+2”><strong> !ygh`]6V  
-7'>Rw  
你选择了清除购物车! ztgSd8GGE  
9i yNR!  
</strong></font> PM7*@~.  
`Kpn@Xg  
</logic:present> ud'r ?QDM  
=6ZZ/+6b  
7$Bq.Lc#z  
到底是用属性还是用body来传递信息? k U*\Fa*E  
3PpycJ}  
如上所述,我们既可以通过属性,也可以通过body来传递信息。但一般来说,比较简单的类型,如字符串或简单表达式最好采用属性来传递信息。 P9G c)$6{p  
#&1mc_`/  
V. =!^0'A  
定义脚本变量的tag标签 6n  
$w)yQ %  
所谓脚本变量,是指JSP中可以调用的变量或对象。它可由tag标签产生。以下示例阐述了一个tag标签定义了一个名为tx的由JNDI所定义的事务处理对象。脚本变量可以是ejb对象、事务、数据库连接等等: eMPi ho  
rVt6tx  
<tt:lookup id=”tx” type=”UserTransaction” name=”java:comp/UserTransaction” /> 'F5&f9 A  
B3c rms['  
<% tx.begin(); %> c:>&Bg&,6T  
8"N<g'Yl,  
... ,kpk XK  
vbmi_[,U  
\gDf&I  
具有协作关系的tag标签 flVQG@  
XcR2]\  
自定义tag标签之间可以通过共享对象来实现协作。在下述例子中,标签tag1创建了一个名为obj1的对象,在标签tag2仍可以重复使用obj。 !-U5d9!  
xl5mI~n_~  
<tt:tag1 attr1=”obj1” value1=”value” /> ;} Ty b  
h-<('w:A  
<tt:tag2 attr1=”obj1” /> ",w@_}z:  
+Z/ *=;  
在以下这个例子当中,如果外层的tag标签创建了一个对象,那么其内层的所有tag标签都可以使用这个对象。由于这样产生的对象没有一个指定的名字,那么就可以将少重名的冲突。这个例子阐述了一系列协作的嵌套对象。 ^0pd- n@pn  
(}V.xi  
<tt:outerTag> ,=Xr'7w,  
rt_%_f>qd  
<tt:innerTag /> ht (RX  
8l~] }2LAs  
</tt:outerTag> _o'ii VDuD  
|b QKymS  
.Quu_S_ vH  
Tag处理类 ]- ")r  
X#Y0g`muW  
/[q6"R!uMz  
Tag处理类必须实现Tag接口或BodyTag接口,不过现在一般都流行从TagSupport或BodyTagSupport类中继承,这些类或接口都可以在javax.servlet.jsp.tagext包中找到。 mHM38T9C%  
&;&i#ZO  
当JSP引擎看到自己的JSP页面中包含有tag标签时,它会调用doStartTag方法来处理tag标签的开头,调用doEndTag方法来处理tag标签的结束。 lr=? &>MXj  
,5mK_iUw3  
下表说明不同类型的tag所需要不同的处理过程: Qo4]_,kR  
WJ<nc+/v:  
Tag处理类的方法 blpX_N  
P%8 Gaa=  
Tag标签类型 )iNM jg  
所调用的方法 ONH!ms(kb  
yS[:C 2v  
基本标签 B: \\aOEj  
doStartTag, doEndTag, release g j8rrd |  
)D{L<.i_  
带属性的标签 9E'fM  
doStartTag, doEndTag, set/getAttribute1...N, release 1p[C5j3  
ai)S:2  
带内容的标签 6}6;%{p"Gu  
doStartTag, doEndTag, release 0M7Or)qN  
Iojyku\W.  
带内容的标签,且内容重复循环 |L}zB,  
doStartTag, doAfterBody, doEndTag, release v8Vw.Ce`f  
x_pS(O(C  
带内容的标签,且内容与JSP交互 !8lG"l|,l  
doStartTag, doEndTag, release, doInitBody, doAfterBody, release z#ab V1 Xi  
^I4'7]n-  
一个tag处理类可以通过javax.servlet.jsp.PageContext来与JSP交互,通过javax.servlet.jsp.PageContext类,tag处理类可以访问JSP中的request、session和application对像。 ;R|i@[(J  
4nK\gXz19  
如果tag标签是互相嵌套的,那内层的tag处理类可以通过它的parent属性来访问上层的tag处理类。 ,m;S-Im_Xr  
cKJf0S:cx-  
一般情况都将所有的tag处理类打成了JAR的包,以便于发布。 jfP2n5X83  
O-J;iX}  
HY0q!.qog  
Tag库描述(简称TLD) K+ZJSfO6  
9>yLSM,!rS  
$M{MOehZ  
Tag库是用xml语言描述的,TLD包括了tag库中所有tag标签的描述,它一般用来被jsp服务器用来校验tag的语法正确性,或者被jsp开发者用来开发新的标签。 jd8`D6|Z  
7?!A~Seo|  
TLD的文件扩展名必须为.tld,而且必须放在当前WEB应用的WEB-INF目录或其子目录中。 a8ya5EO  
_1Iy/T@1  
一个TLD的内容的开头必须遵守标准的XML开头,用于描述DTD和xml的版本,例如: K&Ner(/X`6  
}(k#,&Fv`  
<?xml version="1.0" encoding="ISO-8859-1" ?> "O{j}QwY  
^0)Mc"&{  
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd"> pRWEBd1U  
TLD必须以<taglib>来作为它的根元素,<taglib>的子元素如下表: XtY!fo *  
8,B?!%FP  
jBZlN Ew  
<taglib>的子元素 -AnQZy  
%J(y2 }  
Element 8=QOp[w   
Description 5&?[ Vt  
1P4cB w%  
tlib-version .c__<I<G<  
Tag库的版本 !"1}zeve  
I@Cq<:+(3  
jsp-version ~tK4C|  
Tag库所需要的jsp的版本 _gU:!:}  
qE B3Y54+  
short-name \WS2g"(  
助记符,tag的一个别名(可选) 4/KGrY! ck  
wcr3ugvT  
uri tfB}U.  
用于确定一个唯一的tag库 < z':_,  
Y-2IAJHS8  
display-name {1?94rz  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) kN7 J Z12  
UWU(6J|Fk  
small-icon KLb"_1z  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) }9:( l  
p7{2/m j  
large-icon yS#)F.  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) 6/-]  
A]0A,A0  
description 9NF2a)&~  
对tag库的描述(可选) L`'#}#O l  
,+w9_Gy2H  
listener /q| r!+  
参见下面listener元素 1Vf?Rw  
/80H.|8O  
tag YnR8mVo5Q  
参见下面tag 元素 $4>(}  
pbCj ^  
Listener元素 CdBpz/  
jY;T:C-T  
一个tag库可能定义一些类做为它的事件侦听类,这些类在TLD中被称为listener 元素,jsp服务器将会实例化这些侦听类,并且注册它们。Listener元素中有一个叫listener-class的子元素,这个元素的值必须是该侦听类的完整类名。 ;X_bDiG$  
1`hmD1d  
Tag元素 } 6 ,m2u  
IRhi1{K$"  
每个tag元素在tag库中都要指出它的名字、类名、脚本变量、tag的属性。其中脚本变量的值可以直接在TLD中定义或通过tag附加信息的类来取得。每个属性描述了这个属性是否可以省略,它的值是否可以通过<%= …%>这样的JSP语法来获得,以及属性的类型。 (Q5rOrA"  
5!QT }Um  
每一个tag在TLD中对应一个tag元素,下表是tag元素的子元素: 5)5$h]Nz>  
WCNycH+1  
Tag元素的子元素 'FNnFm  
D\:dn  
元素名称 R$XHjb)  
描述 V0)bPcS/  
7xF)\um  
name q t(+X  
独一无二的元素名 O]4v\~@-j  
}_/]f!]  
tag-class sX@}4[)<&  
Tag标签对应的tag处理类 RWg'W,v=!  
=K)[3mX X  
tei-class ( ]E0fjk  
javax.servlet.jsp.tagext.TagExtraInfo的子类,用于表达脚本变量(可选) 8Y]% S9.  
i:a*6b.U@N  
body-content a8WWFAC[  
Tag标签body的类型 a}e GB +  
dhX$b!DA  
display-name f+ cN'jH E  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) !>:SPt l  
c;?J  
small-icon >D jJ*vM  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) h;+{0a  
I4|LD/b  
large-icon ["O_ Phb|  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) C66 9:%  
lfAiW;giJ  
description /[=Yv!  
此tag标签的描述 E^iShe  
wBWqibY|  
variable o;9 G{Xj3@  
提供脚本变量的信息(同tei-class)(可选) %G|Rb MP  
?8w5tfN6t  
attribute <{+U- ^rzR  
Tag标签的属性名 qfkd Q/fP  
XU`ly3!  
以下章节介绍对于不同类型的tag,如何具体地实现它们。 {wDq*va  
*@{  
0HO'%'Ga*  
简单的tag y6dQ4Whv&  
vM@8&,;  
85f:!p  
tag处理类 %aI,K0\  
ddS3;Rk2  
简单的tag处理类必须实现Tag接口的doStartTag和doEndTag方法。当jsp引擎碰到tag标签的开头时,doStartTag被调用,因为简单的tag没有body,所以此方法将返回 SKIP_BODY。当jsp引擎碰到tag标签的结尾时,doEndTag被调用,如果余下的页面还要被计算,那它将返回EVAL_PAGE,否则将会返回SKIP_PAGE。 y| 0!sNg  
O14\_eAu6  
以下是例子:对于标签 <tt:simple /> ,它的tag处理类实现如下: cL<,]%SkE  
MQQQaD:v  
nC%<BatQ  
public SimpleTag extends TagSupport AdpJ4}|0  
!4a#);`G  
{ f}~=C2R1<!  
~ _hA{$  
public int doStartTag() throws JspException l^XOW- ;u  
`W>Sss  
{ %)72glB  
+1a3^A\  
try{ cij8'( "+!  
PqIskv+  
pageContext.getOut().print(“Hello.”);  &1f3e  
}= wor~  
}catch(Exception e){ 9[`c"Pd  
2z.~K&+x  
throw new JspTagException(“SimpleTag: “ + e.getMessage()); mrq,kwM  
HOx+umjxW  
} Qqi?DW1)-  
}$'XV.  
return SKIP_BODY; P:_bF>r ?  
M}j[{wW3  
} ,J '_Vi  
M KX+'p\w  
public int doEndTag() blWtC/!Aq;  
ySB0"bl  
{ ie11syhV"  
>S-JAPuO  
return EVAL_PAGE; Y]=k"]:%  
d&+0JI<  
} $bD`B'5  
C(9"59>{]y  
} Yo1]HG(kXB  
j /_&]6!  
W"*2,R[}%  
注意:如果tag标签没有内容的话,那必须定义body-content元素为空,例如 6O/c%1VHA3  
,a?oGi  
<body-content>empty</body-content> &]Uo>Gb3!q  
#?k</~s6M`  
m[(_fOd  
带属性的tag标签
评价一下你浏览此帖子的感受

精彩

感动

搞笑

开心

愤怒

无聊

灌水
级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
只看该作者 1 发表于: 2007-01-01
tag处理类 r{t6Vv2J  
3z, Ci$[  
对于tag标签的每个属性,你必须依照JavaBeans规范来定义其属性,以及get和set方法。以struts的logic:present 标签为例, ZjMnGRP  
zfE8=d8U  
<logic:present parameter=”Clear”> <5mv8'{L  
 BdiV  
与此相应,此tag处理类应有如下方法和定义: K9.Gjw  
:s&dn%5N"  
]j>`BK>FE  
protected String parameter = null; |`Noj+T47I  
fN&uat7  
public String getParameter() AD^I1 ]2f  
c|`$ h  
{ Zhv%mUj~  
kxd*B P  
return this.parameter; tk*-Cx?_  
i\l}M]Z#  
} $Hj;i/zD  
A6 .wXv,  
public void setParameter(String parameter) ,Pcg+^A  
.4U*.Rf  
{ [>r0 (x&.  
`Fo/RZOW  
this.parameter = parameter; 4bp})>}jB  
\lm]G7h  
} H8[A*uYL  
'Etq;^H  
7n.Oem  
注意:如果你的属性名为id,而且你的tag处理类是从TagSupport类继承的,那你就不需要定义它的属性和set和get方法,因为他们早已在TagSupport被定义过了。 KK #E qJ  
DpvHIE:W  
Attribute元素 &Jb\}c}  
7(X z%v   
对于tag标签的每个属性,你必须定义它是否必须的,它的值是否可以用诸如<%= …%>的表达式来获得,以及它的类型(可选),如果不指定它的类型,那就默认为是java.lang.String类型。如果rtexprvalue元素被定义为true或yes,那么在type元素中就定义了attribute的返回类型。 NU?<bIQ  
;*t#:U*  
<attribute> aA52Li  
6 iMJ0  
<name>attr1</name> mB"I(>q*M  
Jy% ?"wn  
<required>true|false|yes|no</required> E/a2b(,Tg  
e2N K7  
<rtexprvalue>true|false|yes|no</rtexprvalue> HnKgD:  
Wh| T3&  
<type>attribute的返回类型(只用当rtexprvalue为真是才有效)</type> #"rK1Z  
ZK'46lh  
</attribute> 72"H#dy%U  
Q2- lHn^L:  
如果tag的某个属性不是必须的,那tag处理类会自动提供一个缺省值。 Tn1V+)  
Gj-nT N  
例如,在logic:present这个tag标签中定义了一个属性叫parameter,但它不是必须的,而且它可以被诸如<%= …%>的表达式来赋值。 dH;2OWM  
M @-:iP  
<tag> WEe7\bWF  
+Tu?PuT7k  
<name>present</name> n`&D_AbQ  
]#^v754X^T  
<tag-class>org.apache.struts.taglib.logic.PresentTag</tag-class> 8$A0q%n  
_Iav2= 0Wi  
<body-content>JSP</body-content> ]q{_i   
1J/'R37lP  
&xN+a{&  
&`v?oN9$  
<attribute> l;@+=uVDHm  
~Ay)kv;  
<name>parameter</name> bV&9>fC  
@QVg5  
<required>false</required> 0jlM~H  
X1`3KqK<9  
<rtexprvalue>true</rtexprvalue> 4k@n5JNa  
\8QOZjy  
</attribute> J'|=J   
0Q&(j7`^@  
<n]PD;.4  
pN5kcvQ  
</tag> O8$~dzf,2  
Ge-Bk)6  
|*NZ^6`@  
属性元素的校验 "d$~}=a[  
zT78FliY6  
77O$^fG2  
有关于tag标签的有效值可以从tag库的说明文档中获得,当JSP页面被编译时,jsp引擎会强制性地参照TLD中定义的规则进行检查。 * &:_Vgu  
)8W! |  
还有一个方法也可以进行属性元素的校验,就是先继承类TagExtraInfo,然后调用它的isValid方法。这个类同时也起到提供tag中定义的脚本变量信息的作用。 8(\}\4G_  
GT<oYrjU  
IsValid方法通过TagData对象来传递属性信息,它包括着tag的所有的属性名-值的信息。由于校验发生在运行时刻,因此这个属性的值将被赋值为TagData.REQUEST_TIME_VALUE。 pvyEs|f=%  
e6j1Fa9  
例如tag标签<tt:twa attr1=”value1” />在TLD中定义如下: Mg`!tFe3  
M@.S Q@E  
<attribute> =eQB-Xe8Y  
T3z ovnR  
<name>attr1</name> Mi8)r_l%O  
R#4l"  
<required>true</required> ?yef?JI$p  
)xV37]  
<rtexprvalue>true</rtexprvalue> <N=k&\  
Fk/I (Q  
</attribute> w!20  
BjvQ6M{Y"+  
1 6zxPSTr}  
这个定义说明了attr1能在运行期间被赋值。 M<w.q|P  
JK =A=  
以下的isValid方法检查attr1属性的值是否属于Boolean类型。注意由于attr1能在运行刻被赋值,那么isValid方法必须检查tag用户是否对此tag进行了运行时刻赋值。 xyGwYv>*KO  
e`qrafa  
W|>jj$/o  
Public class TwaTEI extends TagExtraInfo XY'8oU`]{  
bzNnEH`^]  
{ Z2$_9.  
<x^$Fu  
public boolean isValid(Tagdata data) fI)XV7,X  
3s!6rT_=)d  
{ 1PwtzH .w  
dw<i)P^   
Object o = data.getAttribute(“attr1”); ^}-l["u`  
rS BI'op  
If(o != null && o != TagData.REQUEST_TIME_VALUE) 4@-tT;$  
-pYmM d,  
{ ~{Iw[,MJ  
7y|U!r"Y  
if( ( (String)o).toLowerCase().equals(“true”) || L K #A  
'\#q7YjaL  
((String)o).toLowerCase().equals(“false”) ) =IMmtOvJ  
2O=$[b3  
return true; DA "V)  
`Ow]@flLI  
else vTK%8qoZ  
6m;>R%S_  
return false; VxN#\D i&  
hH1Q:}a  
} / 3N2?zS{  
k _V+;&:%  
else vMp=\U-~^  
caQ1SV^{9  
return true; ^@V*:n^  
C|&tdh :g  
} #EzhtuHxn  
s1 >8uW  
} s5@BVD'}E  
MF"*xr v  
1yE',9?  
带body的tag gtuSJ+up  
3%)cUkD  
nnPT08$  
tag处理类 K:U=Y$x  
_;PQt" ]  
; pBLmm*F  
如果tag标签含有内容,那处理方式会略微有些不同,而且还要视tag处理类是否要与body交互的情况而定。如果要与body交互,那我们认为tag处理类要可能要对body进行操作。 kc2B_+Y1  
H>/,Re  
Tag处理类不与body交互 0BC @wV  
UmVn:a  
如果tag处理类不与body交互,tag处理类应该实现Tag接口或从TagSupport中派生,如果body要被计算,那么doStartTag方法应返回 EVAL_BODY_INCLUDE,否则应返回SKIP_BODY。 j_rO_m<8  
0OHXg=  
如果tag处理类要对body反复运算,则它应该实现IterationTag或从TagSupport中派生。如果tag处理类认为body还未计算完的话,那它的doStartTag方法和doAfterBody方法必须返回EVAL_BODY_AGAIN。 K`N$nOw  
P}Ig6^[m\  
Tag处理类与body交互 g&g:H H :  
QgU]3`z"  
如果tag处理类与body交互,那tag处理类应实现BodyTag接口或从BodyTagSupport中派生。这种tag处理类一般要实现doInitBody和doAfterBody方法。 nr]=O`Mvh  
2@a'n@-  
Body允许一些方法来读写它的内容。Tag处理类可以调用body内容的getString或getReader方法来从body中提取信息,也可用 writeOut(out) 方法来将body的内容写入到out对象中。其中out对象通过tag处理类的getPreviousOut方法来获得。 )isS^O$qH  
_K#7#qp2  
如果body的内容需要被计算,那么doStartTag方法必须返回EVAL_BODY_BUFFERED,否则,它将返回 SKIP_BODY。 _ooHB>sH  
Ja3#W K  
doInitBody 方法 l5w^rj  
Lmjd,t  
此方法在body内容已经设好,但未被计算之前被调用。你可以根据不同的body内容来制定初始化策略。 $R #_c}  
j4i$2ZT'  
doAfterBody方法 F4\:9ws  
aZ~e;}w.Zq  
此方法在body内容已被计算后进行调用。 p_Xfj2E4c  
LkJq Bg  
和doStartTag方法一样,doAfterBody方法返回一个指示符指示是否要继续计算body,如果要继续计算,则doAfterBody应返回EVAL_BODY_BUFFERED,否则,它应返回SKIP_BODY。 ZiR}S  
h:pgN,W}  
release 方法 z\tY A  
IA0 vSF:  
tag处理类调用此方法将它的状态重置为初始状态,并释放所有的私有资源。 ByjfPb#  
A/=cGE  
(Yj6 |`  
以下的例子读取body的内容(其中含有一条sql语句),然后将它传递给一个对象,让它进行查询。由于此处body不须重新计算,所以doAfterBody会返回SKIP_BODY。 *m "@*O'  
qE2<vjRg  
zk$h71<{.  
Public class QueryTag extends BodyTagSupport yam'LF  
 $Z &6  
{ <IR@/b!,  
LeN }Q  
public int doAfterBody() throws JspTagException 8i "CU:(  
4mY^pQ1=L  
{ 9ls1y=M8J  
e[x,@P`  
BodyContent bc = getBodyContent(); > U3>I^Y  
Lb$Uba-_  
//将body的内容以字符串的格式提取出来 *}:P  
]kNxytH\o  
String query = bc.getString(); .n IGs'P  
i/!{k2  
//清除body rIPg,4y*S!  
h(q4 B~  
bc.clearBody(); ;,Vdj[W$>  
("A45\5  
try{ L`M{bRl+1  
im<!JMI  
Statement stmt = connection.createStatement(); suQ`a_ zJ  
tx;2C|S$oU  
Result result = stmt.executeQuery(query); \Yp"D7:Qi  
r|Uz?  
}catch(SQLException e){ o$bQ-_B`  
2pHR$GZ2  
throw new JspTagException(“queryTag: “ + e.getMessage() ); 5Qg*j/z?  
Q +hOW-  
return SKIP_BODY; 9i#,V@  
XH0{|#hwN  
} fC^d@4ha  
T:Q+ Z }v+  
} Fc=F2Mo?  
iU0jv7}n  
B7A.~' =  
body-content元素 $m>( kd1  
7 HL Uk3  
3 |e~YmZx  
由于tag可能会有body,你必须用body-content元素来指定body内容的类型: !U5Cwq  
s!09cS  
<body-content>JSP|tagdependent</body-content> 78T;b7!-C  
aG"  
MAqETjB  
如果body的内容是定制的或内部的tag、脚本元素、或HTML广本,则归类为JSP类型。其他的类型,比如上面代码所述的?D?D将sql statement类传给 query tag的这种类型应该标为tagdependent。 mMZ=9 ?m  
t re`iCH~  
注意:实际上body-content的值并不影响tag处理类对body内容的处理,它仅仅是被tag编辑工具用来描述此body的内容。 Y edF%  
\8Ewl|"N:u  
lh0G/8+C  
用tags定义脚本变量 ?~^p:T  
k?pNmKVJM  
BR6HD7G  
tag处理类 P'5Lu  
4wS!g10}  
|Qpo[E }a  
tag处理类负责创建或设置页面中定义的脚本变量,用pageContext.setAttribute(name,value,scope)或pageContext.setAttribute(name,value)方法来实现。一般来说,tag处理类通过脚本变量的名称来获取它,脚本变量的名称一般可用get方法来获得。 UQ e1rf  
I`{=[.c  
如果脚本变量的值依赖于tag处理类中的上下文中某一对象,那它可用pageContext.getAttribute(name,scope)方法来找到那个对象。一般的处理过程是tag处理类先找到脚本变量,再对其进行处理,然后用pageContext.setAttribute(name,object)的方法来设置它的新值。  M+=q"#&  
i+-=I+L3  
对象的生存周期(scope)如下表: ^s8JW"H  
%AgCE"!  
对象的生存周期表 ojWf]$^y}  
}/xdHt  
名字 00W_XhJ  
可访问范围 <p_2&& ?  
生存周期 ~8Ef`zL  
}q/[\3  
page sQzr+]+#9  
当前页面 $iy(+}  
一直有效,除非页面向客户提交响应或重定向到一个新页面 D1fUEHB}A8  
78mJ3/?rC  
request S@L%X<Vm  
当前页面或当前页面重定向到的页面 DqH]FS?]  
一直有效,除非页面向客户提交响应 \Zk<|T61$  
Mm^6*L]  
session ,(yaWd6  
当前页面或在同一浏览器窗口中的页面 e $5s],,n  
一直有效,除非关闭当前浏览器、超时、网络故障 xUs1-O1i  
'xOH~RlE  
application ,+_gx.H2j  
整个web应用程序的所有请求 |R Qa.^.  
一直有效,除非发生网络故障、服务器故障 {2&MyxV  
Zvz}Z8jW  
提供关于脚本变量的信息 }Oy/F  
F.R0c@&W  
以下示例定义了一个名为“book”的脚本变量,用来访问程序中关于书的信息: na/,1iI<  
X`}4=>  
<bean:define id=”book” name=”bookDB” property=”bookDetails” type=”database.BookDetails” /> (5^SL Y  
x A ZRl  
<font color=”red” size=”+2” > SQ`ec95',  
MB5X$5it  
<%= messages.getString(“CartRemoved”) %> HtI>rj/\ x  
 YP}r15P  
<strong><jsp:getProperty name=”book” property=”title” /></strong> |VX0o2  
Fo| rRI2  
</font> /%^^hr  
LTio^uH  
当包含此tag的JSP页面被编译时,jsp引擎会自动生成关于此book的同步的代码(同步可以避免几个客户同时访问此book时造成的冲突),要生成同步代码,jsp引擎需要知道此脚本变量的如下信息: 8x6{[Tx   
gG6BEsGa,  
· 脚本变量名称 3n TpL#  
^t)alNGos  
· 脚本变量所属的类 A `=.F  
cA B^]j  
· 此脚本变量是否引用了一个新的或已存在的对象 ^$\#aTyFK  
1\Vp[^#Vx  
· 此脚本变量的有效性 0bMbM^xV6  
yCye3z.  
有两种办法可以向jsp引擎提供关于脚本变量的信息:在TLD中定义variable子元素,或用tei-class子元素定义一个额外tag信息类。用variable最简单,但可能降低了一些灵活性。 [IuF0$w=dj  
|Q~5TL>b  
Variable元素 8J#TP7;  
2k""/xMF'  
Variable元素有如下子元素: PxZMH=  
 AQz&u  
· name-given ?D?D 给出的名字,是一个常量 A&;Pt/#'  
<3aW3i/jTc  
· name-from-attribute?D?D 属性名,在编译时给出的属性名 gNo}\ lm4V  
Xc@%_6  
name-given或name-from-attribute两者必须选一,但以下子元素是可选的: x\XOtjJr  
'4d+!%2t  
· variable-class?D?D变量的类型,缺省为java.lang.String。 &l1CE1 9<  
sr,8Qd 0M  
· declare?D?D此脚本变量是否引用了一个新对象,缺省为True。 r*s)T`T}}  
8:(e~? f6  
· scope?D?D脚本变量的范围,缺省为NESTED。下表描述了scope的几种类型: cY\"{o"C  
wrt^0n'r)c  
脚本变量的有效范围 79(Px2H2  
be{tyV  
;F'/[l{+  
有效性 5U&?P   
方法 5l(Q#pSX  
o.H(&ex|  
NESTED '@+a]kCMev  
在tag标签的开始和结束之间 8a4&}^|  
如果tag处理类实现BodyTag接口,则在doInitBody和doAfterBody中调用,否则在doStartTag中调用 o5eFLJ6  
e!~x-P5M`  
AT_BEGIN (|<.7K N  
从tag标签的开始一直到页面结束 u~a@:D/F{G  
如果tag处理类实现BodyTag接口,则在doInitBody、doAfterBody和doEndTag中调用,否则在doStartTag和doEndTag中调用 UKxeN[fv  
'xY@ I`x  
AT_END \a\ApD  
从tag标签的结束一直到页面结束 .FXn=4l'vV  
在doEndTag中调用 m`lsUN,  
14v,z;HXj  
以struts为例,它的bean:define标签的实现遵循JSP1.1规范,此规范要求使用额外tag信息类来定义脚本变量。Variable元素是JSP1.2规范中加入的。以bean:define标签为例,你可以定义如下variable元素: uEKa  FRm  
@z)_m!yV1  
<tag> *z A1NH5  
7 V+rQ  
<variable> }PDNW  
^d2bl,1  
<name-from-attribute>id</name-from-attribute> ^yB>0/{)z  
w oSI 2i  
<variable-class>database.BookDetails</variable-class>  $VCWc#  
x GHS  
<declare>true</declare> f#9\&-h e0  
#I.Wmfz  
<scope>AT_BEGIN</scope> %A<|@OSdOa  
0vRug|}k#%  
</variable> hVcV_  
\WeGO.i-  
</tag> l1qWl   
M(2c{TT  
额外tag信息类 i`1QR@11  
j.@TPf*  
如果要定义一个额外tag信息类,你要继承javax.servlet.jsp.TagExtraInfo类。一个TagExtraInfo类必须实现getVariableInfo方法,此方法返回一个叫VariableInfo的数组类,它包括如下信息: to  
_ADK8a6%)  
· 变量名 `n!<h,S'2  
Dab1^H!KT  
· 变量所属类名 A,T3%TE  
YbrsXp"  
· 此变量是否引用了一个新对象 zF[>K4  
#'-L`])7uw  
· 此变量的有效范围  ? h$>7|  
vO)nqtw  
jsp引擎将一个名为data的参数传给getVariableInfo方法,data中包括tag标签中的所有“属性名?D?D属性值”对。它可以用来向VariableInfo对象提供脚本变量的名字和类名。 ^r<bi%@C$  
H[{ch t h  
以struts为例,它在bean:define标签中定义了一个名为DefineTei的额外tag信息类,用来向脚本变量提供信息。由于脚本变量的名称(book)和类名(database.BookDetails)是通过tag标签的属性来传递的,它们一般定义在VariableInfo的构建代码中,并且可用data.getAttributeString方法来得到这些信息。如果要允许book脚本变量能在从tag开始直到整个JSP页面结束的范围内都可用的话,那它的范围应设为AT_BEGIN。如下所示: J 8"Cw<=O  
hD>O LoO  
*zy0,{bl  
public class DefineTei extends TagExtraInfo @Ooh}V#J  
Z=Oo%lM6B  
{ 46dh@&U  
Z;_WU  
public VariableInfo[] getVariableInfo(TagData data) /EOtK|E  
By 8C-jD  
{ uL!{xuN  
:LL>C)(f  
String type = data.getAttributeString(“type”); he/UvMu  
S) [`Bm  
If( type == null) SZCF db  
sY t8NsQ  
type = “java.lang.Object”; @^vVou_  
JeJc(e  
return new VariableInfo[] { uE>2 *u\  
RkN a;j)t  
new VariableInfo(data.getAttributeString(“id”), <8Qa"<4f;  
$b#"Rv  
type, ".qh]RVjV  
=S-'*F  
true, 1X/ q7lR  
IiACr@[?e  
VariableInfo.AT_BEGIN) "~4ULl< i'  
bf `4GD(  
}; HzM^Zn57%  
w*ig[{ I  
} 5w`v 3o  
PCs+` WP!M  
} v!ULErs  
!9i,V{$c`"  
c8gdY`  
注意:关于额外tag信息类的类名必须要在TLD中的tag标签下的tei-class子元素中定义。因此,DefineTei的tei-class中的定义看起来如下: cT8jG ,+"}  
<tei-class> ] w FFGy  
org.apache.struts.taglib.bean.DefineTagTei ;h3uMUCml  
</tei-class> 6tM CpSJ  
#5T+P8  
)L`0VTw'M  
具有协作关系的tag 9q;\;-  
;KmSz 1A  
QhK]>d.  
tag通过共享对象来进行协作,JSP技术支持2种方式的对象共享。 Bya!pzbpr  
Hq^sU%  
第一种方法是使用pageContext对象进行对象的共享(可支持JSP页面和tag处理类之间的共享),如果在一个tag处理类中要调用由另一个tag处理类创建的对象,可调用pageContext.getAttribute(name, scope)方法。 U]fE(mpI9  
rZZueYuXO  
第二各方式的共享是对于tag之间有嵌套关系而言的,外层的tag所创建的对象对于内层的tag来说是可以共用的。这种形式的共享的好处是减少了可能存在的重名冲突。 g!<@6\RB  
j3~:\H  
要访问一个嵌套tag创建的对象,tag处理类必须先找到此嵌套tag对象,可用TagSupport的静态方法 TagSupport.findAncestorWithClass(from, class)或TagSupport.getParent方法。前者在当不确定此tag是否为嵌套tag对象时使用。一旦它的父类被找到,它就能访问其所有动态或静态创建的对象。静态创建的对象是父类的成员,而动态创建的对象可能是父类的私有对象。诸如此类的对象可以用tag处理类的setValue方法来保存,用getValue方法来获得。 B5!$5 Qc  
@Q3aJ98)2  
下例阐述了以上两种共享对象的方法。在这个例子当中,一个查询tag检查一个名为connection的属性名是否在doStartTag中被设置。如果connection属性被设置,tag处理类从pageContext中得到这个connection对象。否则,此tag处理类先找到它的父tag处理类,然后从它的父tag处理类中找到connection对象。 X#(?V[F]  
k oC2bX  
k:<yy^g$X  
public class QueryTag extends BodyTagSupport p SASMc@  
?G1-X~Z8  
{ OGrVy=rd  
:h N*  
private String connectionId; Tm@mk  
OUe@U;l{Z  
public int doStartTag() throws JspException G6Z2[Ej1  
iU{F\>  
{ T<DQi  
y-{^L`%Mk  
String cid = getConnection(); <O>r e3s  
@Wy>4B^  
if(cid != null) on+ c*#  
}V?SedsY  
{ ;&P%A<[`  
$ W(m  
//存在一个connection id,使用它。 S[{#AX=0  
%K /=7  
connection = (Connection) pageContext.getAttribute(cid); J(h=@cw  
:sFP{rFx~  
} RT8xU;   
sn/^#Aa=N  
else -d6| D?}S  
*8fnxWR   
{ Z= dEk`  
.ev'd&l.  
ConnectionTag ancestorTag = (ConnectionTag)findAncestorWithClass(this, gc7S_D~;  
"kz``6C  
ConnectionTag.class); I' ej?~  
4\Y2{Z>P?  
if(ancestorTag == null) rcPP-+XW  
S-npJh 6  
{ .#6Dad=S*  
&n6mXFF#>P  
throw new JspTagException(“一个没有connection属性的查询标签必须被一个connection标记嵌套。”); 'AE)&56  
1fm\5/}'`1  
}  Jt.dR6,  
Lcf =)GL  
connection = ancestorTag.getConnection(); ^{_`jE  
7:I` ~ @m  
} B[!wo  
v}IkY  
} $[6:KV  
h2zuPgz,  
} +T+f``RcK  
$xyG0Q.  
hUcG3IOBf  
N' t*eCi  
此查询标签在JSP页面中的调用形式可以从以下2种定义中任选一种: )$I;)` q  
O$E3ry+?  
9l@VxX68M  
<tt:connection id=”con01” ...> ... </tt:connection> <K%qaf  
cn XIE{9M  
<tt:query id=”balances” connection=”con01” > mZDrvTI'  
> F&Wuf  
SELECT account, balance FROM acct_table bg*4Z?[dd  
:kfHILi  
where customer_num = <%= request.getCustno() %> !1]72%k[  
4$+1jjC]>~  
</tt:query> [iwn"e  
cj`g)cX|  
#{1w#Iz;  
VJS|H!CH  
j#"?Oe{_1  
<tt:connection ...> t;T MD\BU  
&7!&]kA+  
<x:query id=”balances”>   _p\  
Aj#CB.y  
SELECT account, balance FROM acct_table $U<so{xn%  
<- Q=h?D  
where customer_num = <%= request.getCustno() %> "D'A7DA  
4*g`!~)  
</x:query> fmXA;^%  
1D&Q{?RM  
</tt:connection> 9w^1/t&=04  
AqZ{x9g!  
;"hED:z6%  
与此同时,在TLD中必须指定connection属性为可选的,定义如下: -tAdA2?G  
qYBoo]}a  
<tag> +N: K V}K  
BK]bSj  
... !s06uh  
G4vXPx%a8  
<attribute> Wp`wIe6  
INOw0E[  
<name>connection</name> X(U CN0#  
oJ\UF S  
<required>false</required> w,cfSF;=tC  
V.vA~a  
</attribute> w7cciD|  
MU4/arXy  
</tag>
描述
快速回复

您目前还是游客,请 登录注册
欢迎提供真实交流,考虑发帖者的感受
认证码:
验证问题:
3+5=?,请输入中文答案:八 正确答案:八