社区应用 最新帖子 精华区 社区服务 会员列表 统计排行 社区论坛任务 迷你宠物
  • 4542阅读
  • 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%pRDytA  
S}b~_}  
一般来说,自定义tag标签主要用于操作隐藏对象、处理html提交表单、访问数据库或其它企业级的服务,诸如邮件和目录操作等等。自定义tag标签的使用者一般都是那些对java编程语言非常精通,而且对数据访问和企业级服务访问都非常熟悉的程序员,对于HTML设计者来说,使得他可以不去关注那些较复杂的商业逻辑,而将精力放在网页设计上。同时,它也将库开发者和库使用者进行合理分工,自定义tag标签将那些重复工作进行封装,从而大大提高了生产力,而且可以使得tag库可用于不同的项目中,完美地体现了软件复用的思想。  HD H  
?9Ma^C;}  
在这篇文章中,我们主要讨论: KGD'mByt"  
T0Q51Q  
· 什么是自定义tag标签? C bQ4Y  
5VZjDg?  
· 怎么使用tag标签? ]VDn'@uM  
q~M2:SN@X  
o 声明要使用的tag库 d#8e~  
x;(g  
o 找到与之对应的tag处理类 >4c`UW  
qlvwK&W<QM  
o tag标签的类型 QXY}STs  
<]'|$8&jY  
· 自定义tag标签 7"a4/e;^  
+99Bi2H}o  
o tag处理类 x0ne8NDP  
ai9  
o tag库描述 8)?_{  
]'UgZsJ  
o tag标签示例 yV2e5/i  
| k}e&Q_/G  
o 带属性的tag 32^#RlSu8  
O2lIlCL  
o 带body的tag K_&_z  
?0) @jc=  
o 定义了脚本变量的tag z7k$0&  
E-F5y  
o 具有协作关系的tag w5(yCyNp~  
`I#`:hj  
· 自定义tag标签 dN0mYlu1|  
& g$rrpTzv  
o 一个迭代tag的例子 xW0Z'==  
&?r*p0MQC  
o 一个模板tag库 4m\([EO  
{G%3*=?,j  
o tag处理类到底是怎样被调用的? K:a3+k d  
BV1u,<T"  
kC31$jMC3!  
什么是自定义的tag? ;j!UY.i  
5zVQ;;9  
一个自定义的tag标签是用户定义的一种JSP标记。当一个含有自定义的tag标签的JSP页面被jsp引擎编译成servlet时,tag标签被转化成了对一个称为tag处理类的对象进行的操作。于是当JSP页面被jsp引擎转化为servlet后,实际上tag标签被转化成为了对tag处理类的操作。 ?S9Nm~vlt  
J'Gm7h{   
自定义tag标签有很多特色,诸如: RJwb@r<v  
B/G3T u uG  
· 可以在JSP页面中自定义tag标签的属性 %l;*I?0H  
` yYvYc  
· 访问JSP页面中的所有对象 zQ<88E&&Xs  
:P,2K5]y  
· 可以动态地修改页面输出 IX.sy  
2+Zti8  
· 彼此这间可以相互通信。你可以先创建一个JavaBeans组件,然后在一个tag中调用此JavaBeans组件,同时可以在另一个tag中调用它。 -!~vA+jw1  
%",ULtZ+  
· tag允许相互嵌套,可以在一个JSP页面中完成一些复杂的交互。 ,jTPg/r  
}k| g%H J  
| @ *3^'  
使用tag标签 # \<P]<C  
O{nC^`X  
@.1Qs`pt  
本节主要描述怎样在JSP页面中使用tag标签,以及tag标签的不同类型。 9 ?(x>P  
7JS#a=D#  
要使用tag标签,JSP程序员必须做2件事: nNu[c[V  
qsTq*G  
· 声明此tag标签的tag库 yi|:}K$  
FCAJavOGH  
· 实现此tag标签 jceHK l  
5!8-)J-H  
声明tag标签所在的tag库 ,8~dz  
j C9<hLt  
如果要使用tag标签,则应用JSP的taglib指示符来指定其tag库(注意:taglib要在在使用此tag标签之前声明) xY+A]Up|w  
GBW 7Y  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> pLPd[a  
],AbcTX  
uri属性定义了唯一的标签库描述(以下简称TLD),它可以是直接是tld文件名或一个独一无二的名字。prefix是用来区别其它TLD中和本TLD中有重名的tag的一种手段。 HwM /}-t  
=O,e97  
TLD必须以.tld作为扩展名,并且存放在当前应用的WEB-INF目录或其子目录下。你可以通过它的文件名直接引用它,也可以通过别的方式间接地引用它。 eWw y28t  
=uS8>.Qj  
以下taglib指示符直接引用一个TLD: GV=V^Fl .  
%![4d;Z%x  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> kHZKj!!R  
^&HI +M  
以下的taglib指示符通过一个逻辑名称间接地引用一个TLD: S`4e@Z$  
[-QK$~[ g  
<%@ taglib uri=”/tutorial-template” prefix=”tt” %> 4">84,-N  
,d5ia4\K  
如果是间接引用TLD的话,那你必须还要在web.xml中定义此逻辑名称与tld文件之间的映射,具体做法是在web.xml中加入一个名为taglib的元素: %$^$'6\77  
N!Rt;Xm2@  
<taglib> 8XgVY9]Qm  
8`6 LMQ  
<taglib-uri>/tutorial-template</taglib-uri> ^g\h]RD}  
\#HL`R"  
<taglib-location> Kgps_tY%  
[]!tT-Gzy  
/WEB-INF/tutorial-template.tld -B",&yTV  
VB}PNg  
</taglib-location> N c9<X  
v!iWzN  
</taglib> 3huzz<n3  
4D0(Fl  
Z5 w`-#  
实现此tag标签 m21QN9(i%  
VNr!|bp5  
 j@s=ER  
为了实现tag标签,你有2种方法来存放tag处理类。一、让tag处理类以.class的方式存放于当前应用的WEB-INF/class子目录下,二、如果tag处理类是以JAR包的形式存在的话,那可以放在当前应用的WEB-INF/lib目录下,如果tag处理类要在多个应用中共享,那么它就应放在jsp服务器上的common/lib目录下,对于tomcat来说,就是tomcat/common/lib目录下。 "bL P3  
ikeJDKSG  
vr5<LNCLQ  
tag标签类型 _Jt_2o%G  
8s\8`2=  
Ov F8&*A  
自定义的tag标签遵循XML语法。它有一个开始标记和一个结束标记,有的还有body(即文本节点): "0p +SZ~D  
] `b<"  
<tt:tag> u66TrYStG  
bf&.rJ0  
body ;F" kD  
o;HdW  
</tt:tag> f]O5V$!RuE  
g wZ+GA  
(Q*2dd>  
一个不带body的tag标签如下: %`t]FV^#  
!xJLeQFJI]  
<tt:tag /> r? 6Z1  
G FSlYG  
d|D'&&&c  
简单的tag标签 U~JG1#z6  
fJ|Bu("N  
一个没有body和属性的tag标签如下: dK-  ^  
js%4;  
<tt:simple /> HZ[68T[8b  
=PeW$q+  
3\+[38 _  
带属性的tag标签 mYsuNTx!.  
d6Q :{!Sd"  
J"a2 @S&  
自定义标签可以有自己的属性。属性一般在开始标记中定义,语法为 attr=”value”。属性的作用相当于自定义标签的一个参数,它影响着tag处理类的行为。你可以在TLD中详细定义它。 ys~p(  
.lNnY8<  
你可以用一个String常量给一个属性赋值,也可以通过表达式给它赋值,如<%= ...%>。以struts为例,它的logic:present标签就是用的String常量来给属性赋值: iPtm@f,bI  
ajcPt]f  
<loglic:present parameter = “Clear”> V}Y~z)i0  
sbq44L)  
而另一个标签logic:iterate是用表达式来给属性赋值: !pF KC)  
(pRy1DH~  
<logci:iterate collection=”<%= bookDB.getBooks() %>” 4u{E D(  
%3@RZe  
id=”book” type=”database.BookDetails”> l yLK$B?/  
\e5,`  
dKN3ZCw*gF  
带body的tag标签 z? b(|f\!  
v=yI#5  
一个自定义标签可以包含其它自定义标签、脚本变量、HTML标记或其它内容。 ~n]2)>6  
m%[2x#  
在下述例子中,此JSP页面使用了struts的logic:present标签,如果些标签定义了parameter=”Clear”的属性,则将清除购物车的内容,然后打印出一条信息: Vms7 Jay  
MlcoOi!  
<logic:present parameter=”Clear”> cvLcre% >A  
}1^ tK(Am  
<% cart.clear(); %> RE*S7[ge  
L}sm R,  
<font color=”#ff0000” size=”+2”><strong> ~]t2?SqNm  
gWU(uBS  
你选择了清除购物车! 3!L<=X  
OHa{!SaL  
</strong></font> O.40^u~  
vng8{Mx90*  
</logic:present> kI1{>vYD  
J|64b  
t BXsWY{  
到底是用属性还是用body来传递信息? iRr& 'k  
Zn=JmZ  
如上所述,我们既可以通过属性,也可以通过body来传递信息。但一般来说,比较简单的类型,如字符串或简单表达式最好采用属性来传递信息。 Pt)}HF|u  
_$jJpy  
KX`nHu;  
定义脚本变量的tag标签 YI(OrR;V  
C?<XtIoB  
所谓脚本变量,是指JSP中可以调用的变量或对象。它可由tag标签产生。以下示例阐述了一个tag标签定义了一个名为tx的由JNDI所定义的事务处理对象。脚本变量可以是ejb对象、事务、数据库连接等等: @BQB NGR1  
$!3t$-TSD  
<tt:lookup id=”tx” type=”UserTransaction” name=”java:comp/UserTransaction” /> ,9j:h)ks?  
(j8,n<o  
<% tx.begin(); %> X72X:"  
Y Z2VP  
... 1Qe!  
2 n+XML  
arH\QPaka'  
具有协作关系的tag标签 Dp |FyP_w  
+Q#Qu0_   
自定义tag标签之间可以通过共享对象来实现协作。在下述例子中,标签tag1创建了一个名为obj1的对象,在标签tag2仍可以重复使用obj。 *gpD4c7A\  
50hh0!1  
<tt:tag1 attr1=”obj1” value1=”value” /> HkB<RsS$p_  
umn~hb5O  
<tt:tag2 attr1=”obj1” /> g[+Q~/yq  
(c|qX-%rC  
在以下这个例子当中,如果外层的tag标签创建了一个对象,那么其内层的所有tag标签都可以使用这个对象。由于这样产生的对象没有一个指定的名字,那么就可以将少重名的冲突。这个例子阐述了一系列协作的嵌套对象。 A-`J!xj#/  
Ewsg&CCN  
<tt:outerTag> h}<ZZ  
KIl.?_61O  
<tt:innerTag /> scEQDV  
Y_YIJ@  
</tt:outerTag> c89vx 9  
+rO<'H:umJ  
SpiC0  
Tag处理类 M@@O50~  
O!+5As  
x#VUEu]8  
Tag处理类必须实现Tag接口或BodyTag接口,不过现在一般都流行从TagSupport或BodyTagSupport类中继承,这些类或接口都可以在javax.servlet.jsp.tagext包中找到。 O;t?@!_  
O9&:(2'f  
当JSP引擎看到自己的JSP页面中包含有tag标签时,它会调用doStartTag方法来处理tag标签的开头,调用doEndTag方法来处理tag标签的结束。 Ui;s.f  
'yjH~F.  
下表说明不同类型的tag所需要不同的处理过程: 0\^2HjsJ  
",_  
Tag处理类的方法 ?t P/VL  
(,y/nc=GN  
Tag标签类型 0! %}  
所调用的方法 Hxi=\2-  
tX}S[jdq  
基本标签 l;kZS  
doStartTag, doEndTag, release ^}\R]})w"  
!jnIXvT1qy  
带属性的标签 dph6aN(49  
doStartTag, doEndTag, set/getAttribute1...N, release Mwk_S Cy  
c)fp;^  
带内容的标签 a/#,Y<kJ  
doStartTag, doEndTag, release 3mz>Y*^?0  
'PbA/MN  
带内容的标签,且内容重复循环 S6X<3L`FfH  
doStartTag, doAfterBody, doEndTag, release @ xr   
mj|9x1U)  
带内容的标签,且内容与JSP交互 =(\!,S'  
doStartTag, doEndTag, release, doInitBody, doAfterBody, release A@'W $p?5r  
ibw;BU  
一个tag处理类可以通过javax.servlet.jsp.PageContext来与JSP交互,通过javax.servlet.jsp.PageContext类,tag处理类可以访问JSP中的request、session和application对像。 @'4D9A  
7?] p\`  
如果tag标签是互相嵌套的,那内层的tag处理类可以通过它的parent属性来访问上层的tag处理类。 nJg2O@mRJ  
6<nO2GW  
一般情况都将所有的tag处理类打成了JAR的包,以便于发布。 Hp AZ{P7  
u;}B4Rx  
s'4p+eJ  
Tag库描述(简称TLD) B35f 5m7r  
6P|neb}  
k0?6.[ku  
Tag库是用xml语言描述的,TLD包括了tag库中所有tag标签的描述,它一般用来被jsp服务器用来校验tag的语法正确性,或者被jsp开发者用来开发新的标签。 r%n[PK^(  
Pc1N~?}.  
TLD的文件扩展名必须为.tld,而且必须放在当前WEB应用的WEB-INF目录或其子目录中。 DBDfB b  
[Nc  Ok,  
一个TLD的内容的开头必须遵守标准的XML开头,用于描述DTD和xml的版本,例如: .`].\Zykf  
rgY~8PY"  
<?xml version="1.0" encoding="ISO-8859-1" ?> JK`P mp>  
-AQX-[B  
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd"> $n"Llw&)  
TLD必须以<taglib>来作为它的根元素,<taglib>的子元素如下表: 1 Y& d%AA  
Ls{fCi/2F  
y"ck;OQD  
<taglib>的子元素 sTz*tSwQv  
+n dyR  
Element Jhc S  
Description ehq6.+l  
}^q#0`e(y  
tlib-version :83" t-O8[  
Tag库的版本 L?fv5 S3  
e)kf;Hkf  
jsp-version .w~USJ=X  
Tag库所需要的jsp的版本 -E7\ .K3  
|sh  U  
short-name 2OTpGl  
助记符,tag的一个别名(可选) Qp ,l>k  
iJBZnU:Mp  
uri _f`m/l  
用于确定一个唯一的tag库 )-@EUN0E>5  
G. }yNjL8  
display-name X#yl8k_  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) 1yu!:8=ee  
~a$% a  
small-icon sq_:U_tJ  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) :$j~;)2  
}W<L;yD  
large-icon SxDE3A-:  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) c.fj[U|j  
abND#t  
description :.cX3dP@  
对tag库的描述(可选) ~&x%;cnv_  
-AX3Rnv^!  
listener R|suBF3  
参见下面listener元素 "hfwj`U  
-n9e-0  
tag  VV  
参见下面tag 元素 NQAnvX;  
v!,O7XGH~  
Listener元素 wb}tN7~Y;  
_W;u Qg']  
一个tag库可能定义一些类做为它的事件侦听类,这些类在TLD中被称为listener 元素,jsp服务器将会实例化这些侦听类,并且注册它们。Listener元素中有一个叫listener-class的子元素,这个元素的值必须是该侦听类的完整类名。 <R2  
^ !9b#Ja  
Tag元素 g_=Q=y@,  
f_7p.H6\  
每个tag元素在tag库中都要指出它的名字、类名、脚本变量、tag的属性。其中脚本变量的值可以直接在TLD中定义或通过tag附加信息的类来取得。每个属性描述了这个属性是否可以省略,它的值是否可以通过<%= …%>这样的JSP语法来获得,以及属性的类型。 /a q%l]hQ@  
0pR04"`;  
每一个tag在TLD中对应一个tag元素,下表是tag元素的子元素: N(9'U0z  
^Z*_@A_v  
Tag元素的子元素 c:0$ M w=  
% ;<FfS  
元素名称 :* 'i\  
描述 ?d %_o@  
"CaVT7L  
name I$Z"o9"  
独一无二的元素名 .JiQq]  
.C #}g  
tag-class lY1m%  
Tag标签对应的tag处理类 j<!$ug9VA  
#U1soZ7  
tei-class {M$1?j"7  
javax.servlet.jsp.tagext.TagExtraInfo的子类,用于表达脚本变量(可选) &(0iSS  
(~P&$$qfD  
body-content ?eu=0|d  
Tag标签body的类型 ~7ArH9k .  
HZ|6&9we  
display-name gs!{'=4wT  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) ?832#a?FZ;  
u4S3NLG)  
small-icon &L/ C:<.  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) lj[Bd >  
PY^Yx$t9  
large-icon +@!9&5S A  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) JK1b 68n  
cZwQ{9>  
description ss[8d%V  
此tag标签的描述 _ pJU~8  
Dk4Wj"LS  
variable V{"5)Ly?fu  
提供脚本变量的信息(同tei-class)(可选) Ad"::&&Wk  
2<y -cQ?>  
attribute 6sPd")%G  
Tag标签的属性名 9oaq%Sf  
cJqPcCq(wn  
以下章节介绍对于不同类型的tag,如何具体地实现它们。 _-D(N/  
Me8d o; G|  
I($u L@$  
简单的tag N8KHNTb-M  
_gc2h@x1O  
`dj/Uk  
tag处理类 ^lQej%  
_]<]:b  
简单的tag处理类必须实现Tag接口的doStartTag和doEndTag方法。当jsp引擎碰到tag标签的开头时,doStartTag被调用,因为简单的tag没有body,所以此方法将返回 SKIP_BODY。当jsp引擎碰到tag标签的结尾时,doEndTag被调用,如果余下的页面还要被计算,那它将返回EVAL_PAGE,否则将会返回SKIP_PAGE。 \O^= Z{3y  
 UWu|w  
以下是例子:对于标签 <tt:simple /> ,它的tag处理类实现如下: M HgS5b2  
}#Vo XilX  
i G<|3I  
public SimpleTag extends TagSupport UboOIx5:  
87*R#((  
{ V-jo2+Y5=  
T *$uc,  
public int doStartTag() throws JspException x{+rx.  
oXGf#>keg  
{ 7}nOF{RH]  
EmLPq!C  
try{ 7C&`i}/t  
/R^!~J50  
pageContext.getOut().print(“Hello.”); z9VQsC'K  
`pLp+#1 `R  
}catch(Exception e){ N'^ 0:zK:  
&jj\-;=~Ho  
throw new JspTagException(“SimpleTag: “ + e.getMessage()); M>0~Ek%3  
X-t4irZ)  
} l ='lV]  
PUa~Apj '  
return SKIP_BODY; Bw{W-&$o  
Cu!4ha.e`  
} *gBaF/C  
=r GkM.^  
public int doEndTag() 8o~\L= l  
!4 6 ^}3  
{ GifD>c |z  
2y,~i;;_  
return EVAL_PAGE; U~7.aZHPx3  
-"(e*&TJ#  
} n)pBK>+  
mv + .5X  
} FmnA+fA  
{5*+  
<01MXT-  
注意:如果tag标签没有内容的话,那必须定义body-content元素为空,例如 % 3FI>\3  
9N9|hy  
<body-content>empty</body-content> fV[xv4D.  
]Q^oc  
5nEvnnx0  
带属性的tag标签
评价一下你浏览此帖子的感受

精彩

感动

搞笑

开心

愤怒

无聊

灌水
级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
只看该作者 1 发表于: 2007-01-01
tag处理类 d{DlW |_  
*mBn''a"*  
对于tag标签的每个属性,你必须依照JavaBeans规范来定义其属性,以及get和set方法。以struts的logic:present 标签为例, qE(`@G  
`SOaQ|H  
<logic:present parameter=”Clear”> hX YVi6(k  
rs\*$20  
与此相应,此tag处理类应有如下方法和定义: -7\RO%U  
#r0A<+t{T  
tjYe82  
protected String parameter = null; VRMlr.T +  
K@ W~  
public String getParameter() ?ILNp`k  
+}z T][9w  
{ <:/V`b3a  
;Q-sie(#  
return this.parameter; |nMbf  
Z;lE-`Z*(F  
} - !7QH'  
4oCn F+(  
public void setParameter(String parameter) OB5{EILej  
5tQffo8t  
{ 0wxQ,PI1'  
gl00$}C  
this.parameter = parameter; c1b@3  
vzs6YsA  
} .viA+V  
vFy /  
B>-Iv _  
注意:如果你的属性名为id,而且你的tag处理类是从TagSupport类继承的,那你就不需要定义它的属性和set和get方法,因为他们早已在TagSupport被定义过了。 W._vikR  
bm(0raugs  
Attribute元素 )FE'#\  
P0UMMn\-#  
对于tag标签的每个属性,你必须定义它是否必须的,它的值是否可以用诸如<%= …%>的表达式来获得,以及它的类型(可选),如果不指定它的类型,那就默认为是java.lang.String类型。如果rtexprvalue元素被定义为true或yes,那么在type元素中就定义了attribute的返回类型。 Bqa%L.N2SS  
c]&(h L  
<attribute> oM QH- \(}  
O^|,Cbon6  
<name>attr1</name> q0SvZw]f1  
67Ge}6*2pd  
<required>true|false|yes|no</required> ;I]TM#qGF  
W:hR8 1ci  
<rtexprvalue>true|false|yes|no</rtexprvalue> gXs@FhR0  
dYk)RX`}7!  
<type>attribute的返回类型(只用当rtexprvalue为真是才有效)</type> PDM>6U  
Mx0c # d.  
</attribute> R4p bi=  
:cIE8<\%  
如果tag的某个属性不是必须的,那tag处理类会自动提供一个缺省值。 Nf1) 5  
aD 24)?db-  
例如,在logic:present这个tag标签中定义了一个属性叫parameter,但它不是必须的,而且它可以被诸如<%= …%>的表达式来赋值。 }+I 8l'  
{ZN{$Ad3/  
<tag> ukvz#hdE  
b< Pjmb+  
<name>present</name> |M0 XLCNd_  
0Rrz   
<tag-class>org.apache.struts.taglib.logic.PresentTag</tag-class> V ;"?='vVe  
I\`:(V  
<body-content>JSP</body-content> E8#y9q  
/>.&  
… >-EoE;s  
_17c}o#`5w  
<attribute> 2|w(d  
`[57U,v  
<name>parameter</name> &!KJrQ  
5j,)}AYO  
<required>false</required> [Z~>7ayF+)  
;bkS0Vmg  
<rtexprvalue>true</rtexprvalue> K xh)'aal  
QO%>RG  
</attribute> 2zArAch  
E5-8tHV   
… HgduH::\#  
zVkHDT[  
</tag> T-f+<Cxf  
QBai;p{  
Lu1>A {et  
属性元素的校验 t~,!a?S7  
r{p?aG  
D-~HJ  
有关于tag标签的有效值可以从tag库的说明文档中获得,当JSP页面被编译时,jsp引擎会强制性地参照TLD中定义的规则进行检查。 pr@8PD2%  
gaTI:SKzc  
还有一个方法也可以进行属性元素的校验,就是先继承类TagExtraInfo,然后调用它的isValid方法。这个类同时也起到提供tag中定义的脚本变量信息的作用。 7-6_`Q2}Y  
1B,RRHXn6  
IsValid方法通过TagData对象来传递属性信息,它包括着tag的所有的属性名-值的信息。由于校验发生在运行时刻,因此这个属性的值将被赋值为TagData.REQUEST_TIME_VALUE。 dRas9g  
Gd:fWz(  
例如tag标签<tt:twa attr1=”value1” />在TLD中定义如下: f^m8 4o'  
vnXpC!1  
<attribute> <bIAq8  
RrKs!2sCT  
<name>attr1</name> sL+/Eeb` c  
?%*Zgk!l7  
<required>true</required> k NK)mE  
?6tuo:gP  
<rtexprvalue>true</rtexprvalue> ?Za1  b  
 =Lp0i9c  
</attribute> wR>\5z )^  
\>:(++g  
)v0m7L v#/  
这个定义说明了attr1能在运行期间被赋值。 j Dy  
}g>&l.2X  
以下的isValid方法检查attr1属性的值是否属于Boolean类型。注意由于attr1能在运行刻被赋值,那么isValid方法必须检查tag用户是否对此tag进行了运行时刻赋值。 :N%]<Mq  
0dXZd2oK@  
J} %&;uv  
Public class TwaTEI extends TagExtraInfo L!-T`R8'c  
YuLW]Q?v  
{ Y 1LE.{  
`4(k ?Pk2  
public boolean isValid(Tagdata data) YadyRUE  
s.Yywy  
{ ;Fp"]z!Qh+  
kAf2g  
Object o = data.getAttribute(“attr1”); OG!^:OY  
8Qek![3^  
If(o != null && o != TagData.REQUEST_TIME_VALUE) 0u -'{6  
;`s/|v  
{ sq&$   
~{RXc+  
if( ( (String)o).toLowerCase().equals(“true”) || !XzRV?Ih;  
n#bC ,  
((String)o).toLowerCase().equals(“false”) ) / u>")f  
v34XcA  
return true; RzFv``g  
V\X.AGc  
else u= !?<Q  
l9#M`x9  
return false; Xxp<qIEm  
h]vA%VuE'E  
} b!ot%uZZ  
}(20MW8rMc  
else E3;[*ve  
[p[Kpunr{l  
return true; LIirOf~e;!  
"*XR'9~7  
} OAR#* ~q  
%R-"5?eTtu  
} zD7\Gv  
jrZM  
*<"xF'C  
带body的tag _{C:aIl[2  
50uNgLs  
b P4R  
tag处理类 ^MKvZ DOP  
+8v^J8q0  
]'EtLFv)  
如果tag标签含有内容,那处理方式会略微有些不同,而且还要视tag处理类是否要与body交互的情况而定。如果要与body交互,那我们认为tag处理类要可能要对body进行操作。 qOqQt=ObU  
nO,<`}pV  
Tag处理类不与body交互 Ca0~K42~  
|Q?IV5%$  
如果tag处理类不与body交互,tag处理类应该实现Tag接口或从TagSupport中派生,如果body要被计算,那么doStartTag方法应返回 EVAL_BODY_INCLUDE,否则应返回SKIP_BODY。 I+kDx=T !  
CES^ c-. k  
如果tag处理类要对body反复运算,则它应该实现IterationTag或从TagSupport中派生。如果tag处理类认为body还未计算完的话,那它的doStartTag方法和doAfterBody方法必须返回EVAL_BODY_AGAIN。 K8ecSs}}J  
- b:&ACY  
Tag处理类与body交互 ggzg, ~V  
gp$oQh#37;  
如果tag处理类与body交互,那tag处理类应实现BodyTag接口或从BodyTagSupport中派生。这种tag处理类一般要实现doInitBody和doAfterBody方法。 wm=!tx\`k  
4S`2")V  
Body允许一些方法来读写它的内容。Tag处理类可以调用body内容的getString或getReader方法来从body中提取信息,也可用 writeOut(out) 方法来将body的内容写入到out对象中。其中out对象通过tag处理类的getPreviousOut方法来获得。 pGc_Klq  
H3H3UIIT_  
如果body的内容需要被计算,那么doStartTag方法必须返回EVAL_BODY_BUFFERED,否则,它将返回 SKIP_BODY。 Ze~^+ EE  
2bPrND\P=  
doInitBody 方法 =EA*h_"q9  
hl(M0cxEWP  
此方法在body内容已经设好,但未被计算之前被调用。你可以根据不同的body内容来制定初始化策略。 N2 wBH+3w  
1 `hj]@.]  
doAfterBody方法 U,_uy@fE=?  
7hlgm7 ^  
此方法在body内容已被计算后进行调用。 7q&Ru|T33  
%AwR4"M  
和doStartTag方法一样,doAfterBody方法返回一个指示符指示是否要继续计算body,如果要继续计算,则doAfterBody应返回EVAL_BODY_BUFFERED,否则,它应返回SKIP_BODY。 :aS8%m  
O(2)A>}  
release 方法 UA>UW!I  
q"7rd?r52  
tag处理类调用此方法将它的状态重置为初始状态,并释放所有的私有资源。 Q=}p P*  
&U^6N+l9  
b)"bX}  
以下的例子读取body的内容(其中含有一条sql语句),然后将它传递给一个对象,让它进行查询。由于此处body不须重新计算,所以doAfterBody会返回SKIP_BODY。 ]vo&NE  
/>=)=CGv;  
vq-Tq>  
Public class QueryTag extends BodyTagSupport _Q_"_*e  
JKN0:/t7 Q  
{ 3)b[C&`  
2+y<&[A8U  
public int doAfterBody() throws JspTagException UIPi<_Xa  
wl|cipy"  
{ wqEO+7)S  
fTQRn  
BodyContent bc = getBodyContent(); YC+}H3 3  
3 (Bd`=9  
//将body的内容以字符串的格式提取出来 Jn!-Wa,  
o?%1^6&HE  
String query = bc.getString(); I-<U u 2  
I<yd=#:n  
//清除body Qk2^p^ T6  
KKB&)R  
bc.clearBody(); LE#ko2#ke  
g$$i WC!S<  
try{ "O@L IR7  
6%?bl{pNn  
Statement stmt = connection.createStatement(); GF]V$5.ps  
V/xGk9L~  
Result result = stmt.executeQuery(query); 3<">1] /,  
j_YpkKh en  
}catch(SQLException e){ {BB#Bh[  
/B eA-\B  
throw new JspTagException(“queryTag: “ + e.getMessage() ); P| c[EUT  
^U1@ hq*u  
return SKIP_BODY; 6_xPk`m  
qI (<5Wxl  
} v',%   
?VUW.-  
} ~\HGV+S!g}  
nKxu8YAJe  
(|Zah1k&]  
body-content元素 0i%r+_E_  
%2)B.qTp&  
)o4B^kq  
由于tag可能会有body,你必须用body-content元素来指定body内容的类型: Rb!V{jQ  
2GRL`.1  
<body-content>JSP|tagdependent</body-content> 6yU#;|6d  
v>S[} du  
6d%V=1^F  
如果body的内容是定制的或内部的tag、脚本元素、或HTML广本,则归类为JSP类型。其他的类型,比如上面代码所述的?D?D将sql statement类传给 query tag的这种类型应该标为tagdependent。 _d<xxF^q  
OH+kN /Fd  
注意:实际上body-content的值并不影响tag处理类对body内容的处理,它仅仅是被tag编辑工具用来描述此body的内容。 qpjG_G5/  
QV&yVH=Xs  
mEh([ZnY  
用tags定义脚本变量 jEa U;  
:9c[J$R4  
^}VAH#c  
tag处理类 YoU|)6Of   
CRpMpPi@}  
?^f=7e8]  
tag处理类负责创建或设置页面中定义的脚本变量,用pageContext.setAttribute(name,value,scope)或pageContext.setAttribute(name,value)方法来实现。一般来说,tag处理类通过脚本变量的名称来获取它,脚本变量的名称一般可用get方法来获得。 4 C7z6VWg  
= ^NTHc^*  
如果脚本变量的值依赖于tag处理类中的上下文中某一对象,那它可用pageContext.getAttribute(name,scope)方法来找到那个对象。一般的处理过程是tag处理类先找到脚本变量,再对其进行处理,然后用pageContext.setAttribute(name,object)的方法来设置它的新值。 eG&3E`[  
j*7#1<T  
对象的生存周期(scope)如下表: 0 UbY0sYo  
&-e@Et`Pg  
对象的生存周期表 ?q lpi(  
\7\7i-Vo  
名字 kuX{2h*`  
可访问范围 |L}1@0i  
生存周期 JA <Hm.V#  
16cc9%   
page &N+i3l6`  
当前页面 $F#eD 0|  
一直有效,除非页面向客户提交响应或重定向到一个新页面 ^F="'/Pq[  
Kn#CIFbBN  
request Ow3t2G  
当前页面或当前页面重定向到的页面 (gQr?K  
一直有效,除非页面向客户提交响应 l>t0 H($  
C)z?-f  
session Sy0-tK4  
当前页面或在同一浏览器窗口中的页面 =^5,ua6  
一直有效,除非关闭当前浏览器、超时、网络故障 xj#anr  
Tu[I84  
application eE0'3?q(  
整个web应用程序的所有请求 r`OC5IoQ  
一直有效,除非发生网络故障、服务器故障 HB0DG<c-  
j7>a ^W  
提供关于脚本变量的信息 N~)RR {$w  
N'@E^ rYc  
以下示例定义了一个名为“book”的脚本变量,用来访问程序中关于书的信息: q L-Ni  
~:xR0dqx  
<bean:define id=”book” name=”bookDB” property=”bookDetails” type=”database.BookDetails” /> ,bRYqU?#0  
]ME2V  
<font color=”red” size=”+2” > esk~\!d  
OTmw/#ug  
<%= messages.getString(“CartRemoved”) %> 4R&e5!  
|e+r|i]  
<strong><jsp:getProperty name=”book” property=”title” /></strong> b.#0{*/G  
mJYG k_ua  
</font> =#.qe=  
VTl\'>(Cl  
当包含此tag的JSP页面被编译时,jsp引擎会自动生成关于此book的同步的代码(同步可以避免几个客户同时访问此book时造成的冲突),要生成同步代码,jsp引擎需要知道此脚本变量的如下信息: %c-T Gr,  
k+% c8w 9  
· 脚本变量名称 PZYVLUw `  
`Re{j{~s  
· 脚本变量所属的类 Lyy:G9OV  
/DGEI&}&:u  
· 此脚本变量是否引用了一个新的或已存在的对象 =>Q$S  
UPGS/Xs]1  
· 此脚本变量的有效性 n qC@dHP  
4%"Df1 U  
有两种办法可以向jsp引擎提供关于脚本变量的信息:在TLD中定义variable子元素,或用tei-class子元素定义一个额外tag信息类。用variable最简单,但可能降低了一些灵活性。 T%TfkQ__d  
OeYZLC(  
Variable元素 r=Od%  
 <6STw  
Variable元素有如下子元素: K]H [A,  
5}|bDJ$%_  
· name-given ?D?D 给出的名字,是一个常量 ?atHZLF  
n h&[e  
· name-from-attribute?D?D 属性名,在编译时给出的属性名 HvJ-P#  
myqQqVW  
name-given或name-from-attribute两者必须选一,但以下子元素是可选的: V:h3F7  
G"|c_qX  
· variable-class?D?D变量的类型,缺省为java.lang.String。 @E%f AC  
w@i;<LY.  
· declare?D?D此脚本变量是否引用了一个新对象,缺省为True。 _M)J{ {?:  
xv 9 G%  
· scope?D?D脚本变量的范围,缺省为NESTED。下表描述了scope的几种类型: WJBwo%J  
5]F4.sa  
脚本变量的有效范围 DP08$Iq  
9ohO-t$XkY  
值 %h4|$  
有效性 1pJ?YV  
方法 ~^v*f   
+O?`uV  
NESTED 4)].{Z4 q  
在tag标签的开始和结束之间 ; -,VJCPi  
如果tag处理类实现BodyTag接口,则在doInitBody和doAfterBody中调用,否则在doStartTag中调用 h{.x:pPXy  
>fx/TSql:J  
AT_BEGIN UdK+,k~m/  
从tag标签的开始一直到页面结束 9RmdQ]1n4  
如果tag处理类实现BodyTag接口,则在doInitBody、doAfterBody和doEndTag中调用,否则在doStartTag和doEndTag中调用 P%y$e0  
<I.{meDg  
AT_END y;ymyy&  
从tag标签的结束一直到页面结束 Z/+H  
在doEndTag中调用 4\iy{1{E,C  
GEZ!z5";BQ  
以struts为例,它的bean:define标签的实现遵循JSP1.1规范,此规范要求使用额外tag信息类来定义脚本变量。Variable元素是JSP1.2规范中加入的。以bean:define标签为例,你可以定义如下variable元素: :,pdR>q%(y  
[5wU0~>'  
<tag> /[=U$=uH  
KYC<*1k  
<variable> KDu~,P]  
R~N'5#.*M  
<name-from-attribute>id</name-from-attribute> qd@Fb*  
n+w$'l  
<variable-class>database.BookDetails</variable-class> VNHt ]Ewj  
Mk|*=#e;  
<declare>true</declare> ?Suv.!wfLl  
9}#9i^%}  
<scope>AT_BEGIN</scope> mL]5Tnc  
;`rz]7,*  
</variable> g7O , <  
4S*7*ak{  
</tag> f\c%G=y  
_2rxDd1#.  
额外tag信息类 v0,&wdi  
DPylc9[-  
如果要定义一个额外tag信息类,你要继承javax.servlet.jsp.TagExtraInfo类。一个TagExtraInfo类必须实现getVariableInfo方法,此方法返回一个叫VariableInfo的数组类,它包括如下信息: ],w+4;+  
L^{wxOf&6E  
· 变量名 J%lEyU  
L; 'C5#GN  
· 变量所属类名 eN-lz_..7  
Rv@( [rn+  
· 此变量是否引用了一个新对象 ~[`*)(4E  
QIu!o,B  
· 此变量的有效范围 %\?Gzc_  
pb}4{]sI  
jsp引擎将一个名为data的参数传给getVariableInfo方法,data中包括tag标签中的所有“属性名?D?D属性值”对。它可以用来向VariableInfo对象提供脚本变量的名字和类名。 ;BjJ<?^{  
A]AM|2 D  
以struts为例,它在bean:define标签中定义了一个名为DefineTei的额外tag信息类,用来向脚本变量提供信息。由于脚本变量的名称(book)和类名(database.BookDetails)是通过tag标签的属性来传递的,它们一般定义在VariableInfo的构建代码中,并且可用data.getAttributeString方法来得到这些信息。如果要允许book脚本变量能在从tag开始直到整个JSP页面结束的范围内都可用的话,那它的范围应设为AT_BEGIN。如下所示: 06fs,!Q@  
(5&l<u"K~  
O*-sSf   
public class DefineTei extends TagExtraInfo <PTi>C8;r  
.p /VRlLU  
{ {6 brVN.V  
.9KW| (uW  
public VariableInfo[] getVariableInfo(TagData data) r!HB""w  
7kH GU  
{ OvtiFN^s'  
eVB.g@%T  
String type = data.getAttributeString(“type”); -[-Ry6G  
4&'_~qU  
If( type == null) I<L<xwh1(E  
jG~UyzWH;  
type = “java.lang.Object”; <nE|Y@S  
0q:g Dc6z  
return new VariableInfo[] { IX y  $  
aIABx!83>  
new VariableInfo(data.getAttributeString(“id”), XIJ{qrDr  
/dt'iai~l  
type, o;M-M(EZQ6  
et0yS%7+?@  
true, &4-rDR,  
&yQM 8J~  
VariableInfo.AT_BEGIN) ; #^Jy#)  
ht@s!5\LK  
}; Zfn390_  
'P5|[du+  
} 7]6HXR@  
5Pu F]5  
} a?QDf5C q  
O`W&`B(*k  
"J CvsCe  
注意:关于额外tag信息类的类名必须要在TLD中的tag标签下的tei-class子元素中定义。因此,DefineTei的tei-class中的定义看起来如下: |`yzH$,F  
<tei-class> {|Pz9a- :  
org.apache.struts.taglib.bean.DefineTagTei VIjsz42C  
</tei-class> ,-[dr|.  
,0R2k `m!  
 zOnQ656  
具有协作关系的tag L?5OWVX!v  
[F< Tl =  
Kzd`|+?'`M  
tag通过共享对象来进行协作,JSP技术支持2种方式的对象共享。 (iZE}qf7 g  
Aa;s.:?  
第一种方法是使用pageContext对象进行对象的共享(可支持JSP页面和tag处理类之间的共享),如果在一个tag处理类中要调用由另一个tag处理类创建的对象,可调用pageContext.getAttribute(name, scope)方法。 %wp#vO-$  
`kP (2b  
第二各方式的共享是对于tag之间有嵌套关系而言的,外层的tag所创建的对象对于内层的tag来说是可以共用的。这种形式的共享的好处是减少了可能存在的重名冲突。 De*Z UN|<  
uoe5@j2  
要访问一个嵌套tag创建的对象,tag处理类必须先找到此嵌套tag对象,可用TagSupport的静态方法 TagSupport.findAncestorWithClass(from, class)或TagSupport.getParent方法。前者在当不确定此tag是否为嵌套tag对象时使用。一旦它的父类被找到,它就能访问其所有动态或静态创建的对象。静态创建的对象是父类的成员,而动态创建的对象可能是父类的私有对象。诸如此类的对象可以用tag处理类的setValue方法来保存,用getValue方法来获得。 = ?hx+-'  
Gv,0{DVX<  
下例阐述了以上两种共享对象的方法。在这个例子当中,一个查询tag检查一个名为connection的属性名是否在doStartTag中被设置。如果connection属性被设置,tag处理类从pageContext中得到这个connection对象。否则,此tag处理类先找到它的父tag处理类,然后从它的父tag处理类中找到connection对象。 buhn~ c  
O} !L;?  
zaVDe9B,7  
public class QueryTag extends BodyTagSupport M7(vI4V  
r4~Bn7j2  
{ ZTx~+'(  
Hop$w  
private String connectionId; t?0D*!D  
[z:bnS~yiD  
public int doStartTag() throws JspException :fr 2K  
#(53YoV_8  
{ d/GP.d  
~{[~ =~\u  
String cid = getConnection(); O\ T  
1a)NM#  
if(cid != null) *a@pZI0'  
9_rNJLj8y  
{ )T:{(v7 d`  
B(mxW8y  
//存在一个connection id,使用它。 0C}7=_?  
x,js}Mlw  
connection = (Connection) pageContext.getAttribute(cid); '!!w|k d  
'?5=j1  
} \K)"@gdW  
` BH8v  
else )@3ce'  
e:V(kzAY;  
{ B7TA:K  
6:B[8otQ  
ConnectionTag ancestorTag = (ConnectionTag)findAncestorWithClass(this, QzIK580%t  
sb_>D`>  
ConnectionTag.class); +|Q8P?YD_  
ASAz<H$  
if(ancestorTag == null) K,' ]G&K  
S,vrz!'>A  
{ A5Yfm.Jy  
'r4 j;Jn  
throw new JspTagException(“一个没有connection属性的查询标签必须被一个connection标记嵌套。”); -) $$4<L  
K(Otgp+zb  
} !5 %c`4  
:SSe0ZZ_6b  
connection = ancestorTag.getConnection(); DI9x] CR  
;,Sl+)@h  
} Ol"p^sqwj  
Hbx=vLQ6  
} J}KATpHs  
-sGfpLy<6  
} ;04doub  
zF(I#|Vo  
M'HmVg4'  
<<v,9*h  
此查询标签在JSP页面中的调用形式可以从以下2种定义中任选一种: ,/|"0$p2x  
2@1A,  
-GCGxC2u  
<tt:connection id=”con01” ...> ... </tt:connection> 'wLQ9o%=p|  
A%oHx|PD  
<tt:query id=”balances” connection=”con01” > znFa4  
D>~z{H%\  
SELECT account, balance FROM acct_table #G|iEC0C  
D^I%tn=F  
where customer_num = <%= request.getCustno() %> EG59L~nM  
5X nA.?F^  
</tt:query> lz faW-nu  
`K~300-hOb  
wvcG <sj  
或 $=TFTSO  
U=QV^I Qm  
<tt:connection ...> R.!'&<Svq  
l^%Ez?-:s  
<x:query id=”balances”> !CTchk<{(  
X&TTw/J!^  
SELECT account, balance FROM acct_table #)tt}GX  
6^s=25>p  
where customer_num = <%= request.getCustno() %> TV#pUQ3K  
cMsm[D{b  
</x:query> k!>MZ  
gb|C592R5C  
</tt:connection> /^G1wz2  
s|dcO  
u= 5&e)v3  
与此同时,在TLD中必须指定connection属性为可选的,定义如下: mMS%O]m,|  
9sFZs]uM  
<tag> vXAO#'4tm%  
PzWhB* iBR  
... ^J< I Ia4  
JZNRMxu  
<attribute> A7 qyv0F  
4`yCvPu  
<name>connection</name> 4%LGP h  
fr#Y<=Jo  
<required>false</required> o|*ao2a  
Fo=Icvo  
</attribute> P%A;EF~ v  
?'Y\5n/*$  
</tag>
描述
快速回复

您目前还是游客,请 登录 或 注册
批量上传需要先选择文件,再选择上传
认证码:
验证问题:
10+5=?,请输入中文答案:十五