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

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

级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
标准的JSP 标记可以调用JavaBeans组件或者执行客户的请求,这大大降低了JSP开发的复杂度和维护量。JSP技术也允许你自定义taglib,其实换句话说,taglib可以看成是对JSP标记的一种扩展,正如xml是对html的一种扩展一样。taglib通常定义在tag标签库中,这种标签库存放着你自己定义的tag标签。简而言之,如果使用taglib,那么你可以设计自己的JSP标记! A&Usddcp  
.2Elr(&*h  
一般来说,自定义tag标签主要用于操作隐藏对象、处理html提交表单、访问数据库或其它企业级的服务,诸如邮件和目录操作等等。自定义tag标签的使用者一般都是那些对java编程语言非常精通,而且对数据访问和企业级服务访问都非常熟悉的程序员,对于HTML设计者来说,使得他可以不去关注那些较复杂的商业逻辑,而将精力放在网页设计上。同时,它也将库开发者和库使用者进行合理分工,自定义tag标签将那些重复工作进行封装,从而大大提高了生产力,而且可以使得tag库可用于不同的项目中,完美地体现了软件复用的思想。 yEoF4bt  
Ww+IWW@  
在这篇文章中,我们主要讨论: 2*l/3VW  
x,pjpx  
· 什么是自定义tag标签? l'E*=Rn  
paE[rS\  
· 怎么使用tag标签? 3J|F?M"N7  
nRZ]z( b  
o 声明要使用的tag库 \aUC(K~o\;  
V1 `o%;j  
o 找到与之对应的tag处理类 w(3G&11N?  
K+K#+RBK  
o tag标签的类型 (Y?gn)*t  
&>W$6>@  
· 自定义tag标签 j[G  
t: ;Pj9  
o tag处理类 Y0dEH^I  
x,@B(9No  
o tag库描述 Zbt.t] N  
V]e8a"/[{  
o tag标签示例 Eib5  
/cQueUME`  
o 带属性的tag _P 3G  
ND#Yen ye  
o 带body的tag i0kak`x0  
}t=!(GOb}  
o 定义了脚本变量的tag }9#r0Vja  
pis`$_kmwV  
o 具有协作关系的tag 1N#| }ad  
}Gm>`cw-  
· 自定义tag标签 S8wLmd>  
DIfaVo/"  
o 一个迭代tag的例子 ^]0Pfna+N  
:tB1D@Cb6  
o 一个模板tag库 iDz++VNV  
Sc1 8dC0  
o tag处理类到底是怎样被调用的? p\tm:QWD;  
kY|utoAP  
r Iu$pZO  
什么是自定义的tag? S\YTX%Xm}  
N06OvU2>xU  
一个自定义的tag标签是用户定义的一种JSP标记。当一个含有自定义的tag标签的JSP页面被jsp引擎编译成servlet时,tag标签被转化成了对一个称为tag处理类的对象进行的操作。于是当JSP页面被jsp引擎转化为servlet后,实际上tag标签被转化成为了对tag处理类的操作。 %G/ hD  
^?7-r6  
自定义tag标签有很多特色,诸如: (pCrmyB  
FQ7T'G![  
· 可以在JSP页面中自定义tag标签的属性 u=?.}Pj  
Q4!_>YZ  
· 访问JSP页面中的所有对象 =9boya,>  
z2_*%S@  
· 可以动态地修改页面输出 .B]MpmpK  
Ky!Y"   
· 彼此这间可以相互通信。你可以先创建一个JavaBeans组件,然后在一个tag中调用此JavaBeans组件,同时可以在另一个tag中调用它。 c%2QZC  
~Z?TFg  
· tag允许相互嵌套,可以在一个JSP页面中完成一些复杂的交互。 j@U]'5EVB  
^Y>F|;M#  
[P=Jw:E  
使用tag标签 2~1SQ.Q<RY  
ll<Xz((o  
^w@%cVh  
本节主要描述怎样在JSP页面中使用tag标签,以及tag标签的不同类型。 oWim}Er=  
FxtQXu-g  
要使用tag标签,JSP程序员必须做2件事: F|o:W75  
iohop(LZ  
· 声明此tag标签的tag库 T@:Wp4>69  
Yz/md1T$  
· 实现此tag标签 jrlVvzZ  
U9:zVy  
声明tag标签所在的tag库 ^& tZ  
9N%We|L,c  
如果要使用tag标签,则应用JSP的taglib指示符来指定其tag库(注意:taglib要在在使用此tag标签之前声明) n.`($yR_  
5T_n %vz  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> 7$vYo _  
\FbvHr,  
uri属性定义了唯一的标签库描述(以下简称TLD),它可以是直接是tld文件名或一个独一无二的名字。prefix是用来区别其它TLD中和本TLD中有重名的tag的一种手段。 ?qLFaFt/  
Yq0| J  
TLD必须以.tld作为扩展名,并且存放在当前应用的WEB-INF目录或其子目录下。你可以通过它的文件名直接引用它,也可以通过别的方式间接地引用它。 * 8yAG]z  
jk; clwyz/  
以下taglib指示符直接引用一个TLD: +,T RfP Fb  
85|OGtt  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> 8>2.UrC  
j9x<Y]  
以下的taglib指示符通过一个逻辑名称间接地引用一个TLD: G_3O]BMKd)  
+j`5F3@  
<%@ taglib uri=”/tutorial-template” prefix=”tt” %> 3nIU1e  
uy[At+%zg  
如果是间接引用TLD的话,那你必须还要在web.xml中定义此逻辑名称与tld文件之间的映射,具体做法是在web.xml中加入一个名为taglib的元素: +eWQa`g  
\ =?a/  
<taglib> J{p1|+h%  
+qtJaYf/0  
<taglib-uri>/tutorial-template</taglib-uri> (lBCO?`fx  
(>UZ<2GPL  
<taglib-location> 2\A$6N ;_  
UUYSFa %  
/WEB-INF/tutorial-template.tld dh`K`b4I  
=w_Ype`  
</taglib-location> xaq-.IQAM$  
t9kzw*U9  
</taglib> ';w#w<yaI  
b,l$1{  
Z58 X5"  
实现此tag标签 (Ft+uuG  
jiV<+T?  
~drS} V  
为了实现tag标签,你有2种方法来存放tag处理类。一、让tag处理类以.class的方式存放于当前应用的WEB-INF/class子目录下,二、如果tag处理类是以JAR包的形式存在的话,那可以放在当前应用的WEB-INF/lib目录下,如果tag处理类要在多个应用中共享,那么它就应放在jsp服务器上的common/lib目录下,对于tomcat来说,就是tomcat/common/lib目录下。 zH?!  
u<7/0;D#+  
}l(&}#dY  
tag标签类型 Gv!2f  
~NrG` D}  
EnKR%Ctw  
自定义的tag标签遵循XML语法。它有一个开始标记和一个结束标记,有的还有body(即文本节点): 'NXN& {  
j\[dx^\=  
<tt:tag> )0.kv2o.  
[64:4/<}  
body Sxt"B  
7{e  4c  
</tt:tag> r_)' Ps  
P%V'4p c  
k_L7 kvpt  
一个不带body的tag标签如下: fa jGZyd0:  
|B?m,U$A!  
<tt:tag /> X:f UI4  
fy>{QC\  
aD<A.Lhy  
简单的tag标签 Q Uwd [  
j78i #}e  
一个没有body和属性的tag标签如下: %~O,zs.2p  
,8S/t+H  
<tt:simple /> .KB^3pOpx  
tVYF{3BhA  
:;RMo2Tl  
带属性的tag标签 YFLZ%(  
s [RAHU  
:T ^a&)aL%  
自定义标签可以有自己的属性。属性一般在开始标记中定义,语法为 attr=”value”。属性的作用相当于自定义标签的一个参数,它影响着tag处理类的行为。你可以在TLD中详细定义它。 4M=]wR;  
rT=rrvV3g  
你可以用一个String常量给一个属性赋值,也可以通过表达式给它赋值,如<%= ...%>。以struts为例,它的logic:present标签就是用的String常量来给属性赋值: {g'(~ qv  
<,3a3  
<loglic:present parameter = “Clear”> BA@lk+aW  
FZ{h?#2?  
而另一个标签logic:iterate是用表达式来给属性赋值: [SjqOTon{  
%+aCJu[k(z  
<logci:iterate collection=”<%= bookDB.getBooks() %>” (+w*[qHe  
G)AqbY  
id=”book” type=”database.BookDetails”> MD}w Y><C  
f&N gS+<K$  
px A?  
带body的tag标签 A9KET$i@v  
.Yamc#A-  
一个自定义标签可以包含其它自定义标签、脚本变量、HTML标记或其它内容。 >2y':fO  
%8RrRW  
在下述例子中,此JSP页面使用了struts的logic:present标签,如果些标签定义了parameter=”Clear”的属性,则将清除购物车的内容,然后打印出一条信息: A]_7}<<N  
NlA,'`,  
<logic:present parameter=”Clear”> oM X  
5c@,bIl *  
<% cart.clear(); %> >2Y=*K,:  
]{;gw<T  
<font color=”#ff0000” size=”+2”><strong> $g^@AdE%  
aj-Km`5r}  
你选择了清除购物车! k%]3vRo<  
YU'k#\gi*  
</strong></font> aG-vtld  
3<e=g)F  
</logic:present> Yj<a" Gr4[  
7m47rJyW4  
bt@< ut\  
到底是用属性还是用body来传递信息? vO H4#  
XnH05LQ  
如上所述,我们既可以通过属性,也可以通过body来传递信息。但一般来说,比较简单的类型,如字符串或简单表达式最好采用属性来传递信息。 3p$?,0ELH  
i7CX65&b  
0.Q Ujw  
定义脚本变量的tag标签 2,y|EpG#  
O0*p0J  
所谓脚本变量,是指JSP中可以调用的变量或对象。它可由tag标签产生。以下示例阐述了一个tag标签定义了一个名为tx的由JNDI所定义的事务处理对象。脚本变量可以是ejb对象、事务、数据库连接等等: F;Spi  
`_6C {<O  
<tt:lookup id=”tx” type=”UserTransaction” name=”java:comp/UserTransaction” /> K6)Gc%:`  
vRTkgH#4l  
<% tx.begin(); %> v1#otrf  
(fhb0i-  
... h,(26 y/s  
CmWeY$Jb  
j}#w )M  
具有协作关系的tag标签 [DYQ"A= )d  
]E{NNHK%2N  
自定义tag标签之间可以通过共享对象来实现协作。在下述例子中,标签tag1创建了一个名为obj1的对象,在标签tag2仍可以重复使用obj。 _kC-dEGf!y  
SjK  
<tt:tag1 attr1=”obj1” value1=”value” /> !K#qeY}  
a)!o @  
<tt:tag2 attr1=”obj1” /> oe ~'o'  
:ffY6L+  
在以下这个例子当中,如果外层的tag标签创建了一个对象,那么其内层的所有tag标签都可以使用这个对象。由于这样产生的对象没有一个指定的名字,那么就可以将少重名的冲突。这个例子阐述了一系列协作的嵌套对象。 HRpte=`q  
$o!zUH~'v  
<tt:outerTag> tb 5`cube  
k x8G  
<tt:innerTag /> `](e:be}  
NYhB'C2  
</tt:outerTag> RV1coC.g4x  
44J]I\+  
Mg+2. 8%  
Tag处理类 M.JA.I@XC  
`T1  
8u"U1  
Tag处理类必须实现Tag接口或BodyTag接口,不过现在一般都流行从TagSupport或BodyTagSupport类中继承,这些类或接口都可以在javax.servlet.jsp.tagext包中找到。 6u?>M9  
E[OJ+ ;c  
当JSP引擎看到自己的JSP页面中包含有tag标签时,它会调用doStartTag方法来处理tag标签的开头,调用doEndTag方法来处理tag标签的结束。 1Te %F+7  
!OZy7  
下表说明不同类型的tag所需要不同的处理过程: GWGSd\z  
2V]UJ<  
Tag处理类的方法 #j;^\rSv-  
&Hrj3E  
Tag标签类型 eB2a-,  
所调用的方法 )J=!L\  
D2 #ZpFp"h  
基本标签 V(}:=eK  
doStartTag, doEndTag, release 6]i-E>p3R  
S*pGMuui  
带属性的标签 Xa[.3=bV?  
doStartTag, doEndTag, set/getAttribute1...N, release )Dm s  
@ 8(q$  
带内容的标签 ,.S~ Y  
doStartTag, doEndTag, release 'z8pzMmT  
)w em|:H  
带内容的标签,且内容重复循环 zE*li`@  
doStartTag, doAfterBody, doEndTag, release vo?9(+:|e  
cF*TotU_m  
带内容的标签,且内容与JSP交互 `Uq#W+r,  
doStartTag, doEndTag, release, doInitBody, doAfterBody, release vN}#Kc\  
b\f O8{k  
一个tag处理类可以通过javax.servlet.jsp.PageContext来与JSP交互,通过javax.servlet.jsp.PageContext类,tag处理类可以访问JSP中的request、session和application对像。 #x@$ lc=k3  
eNh39er  
如果tag标签是互相嵌套的,那内层的tag处理类可以通过它的parent属性来访问上层的tag处理类。 ^+ml5m  
WH%g(6w1j  
一般情况都将所有的tag处理类打成了JAR的包,以便于发布。 cs48*+m  
_r#Z}HK  
ZT*ydln  
Tag库描述(简称TLD) '(6z. toQ  
yHYsZ,GE  
`K"L /I9  
Tag库是用xml语言描述的,TLD包括了tag库中所有tag标签的描述,它一般用来被jsp服务器用来校验tag的语法正确性,或者被jsp开发者用来开发新的标签。 v4<nI;Ux  
\Dm";Ay>  
TLD的文件扩展名必须为.tld,而且必须放在当前WEB应用的WEB-INF目录或其子目录中。 @ 6\I~s(  
'B$yo]  
一个TLD的内容的开头必须遵守标准的XML开头,用于描述DTD和xml的版本,例如: SZ7:u895E  
?9vuuIE  
<?xml version="1.0" encoding="ISO-8859-1" ?> 5"VTK  
7jrt7[{  
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd"> ';k5?^T  
TLD必须以<taglib>来作为它的根元素,<taglib>的子元素如下表: j{ ]I]\=?  
alJ)^OSIe  
2F;y;l%  
<taglib>的子元素 E#34Wh2z  
_ >?\DgjH  
Element k:i4=5^*GX  
Description O ;Rqv  
/A\8 mL8  
tlib-version !"e5h`/ADM  
Tag库的版本 B^=-Z8  
t3WiomNCc  
jsp-version .N;=\C*  
Tag库所需要的jsp的版本 ;._ l 0Jw  
DDQx g  
short-name E, Z$pKL?  
助记符,tag的一个别名(可选) 5PCqYN(:B  
L<c4kw  
uri t|?ez4/{z  
用于确定一个唯一的tag库 @/~omg}R  
r wL`Czs  
display-name 1dY}\Sp  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) PN%zIkbo  
%fZJRu 1b  
small-icon ';Ea?ID  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) YpHg&|Fr  
@)+AaC#-  
large-icon gk4;>}  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) 7O2/z:$f  
8LJ8 }%*  
description ,]C;sN%~}  
对tag库的描述(可选) ,oe <  
J-:.FKf\5l  
listener @&!ZZ 1V8  
参见下面listener元素 ;<Sd~M4f  
hR n<em  
tag ?PxP% $hS  
参见下面tag 元素 ~hH REI&  
;1W6G=m  
Listener元素 <V'@ks%  
t?X877z  
一个tag库可能定义一些类做为它的事件侦听类,这些类在TLD中被称为listener 元素,jsp服务器将会实例化这些侦听类,并且注册它们。Listener元素中有一个叫listener-class的子元素,这个元素的值必须是该侦听类的完整类名。 qx(xvU9  
%QH$ipM  
Tag元素 h f)?1z4  
3Aip}<1  
每个tag元素在tag库中都要指出它的名字、类名、脚本变量、tag的属性。其中脚本变量的值可以直接在TLD中定义或通过tag附加信息的类来取得。每个属性描述了这个属性是否可以省略,它的值是否可以通过<%= …%>这样的JSP语法来获得,以及属性的类型。 *"2+B&Y  
iozt&~o  
每一个tag在TLD中对应一个tag元素,下表是tag元素的子元素: X #dmo/L8  
phkwN}6  
Tag元素的子元素 h^45,E C  
@u+]aI!`-  
元素名称 `RT>}_j  
描述 iXkF1r]i  
qbr$>xH  
name ^6x%*/l|  
独一无二的元素名 Hvauyx5T  
^0 )g/`H^>  
tag-class G't$Qx,IC  
Tag标签对应的tag处理类 f)rq%N &  
o|^3J{3G  
tei-class S72+d%$  
javax.servlet.jsp.tagext.TagExtraInfo的子类,用于表达脚本变量(可选) YaqR[F  
k}CVQ@nd  
body-content @IKYh{j4  
Tag标签body的类型 V-P#1Kkh  
;;Y! ^^g  
display-name pX<`+t[  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) atH*5X6d  
7"D", 1h  
small-icon 2|y"!JqE1  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) +/7?HGf  
SR hiQ  
large-icon yzn%<H~  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) G Vr1`l  
TqQB@-!  
description /HEw-M9z  
此tag标签的描述 s[*rzoA  
.sW|Id )  
variable ODN /G%l  
提供脚本变量的信息(同tei-class)(可选) Wb_J(!da  
~_)^X  
attribute @;4zrzQi7  
Tag标签的属性名 G>=*yqo  
octL"t8w  
以下章节介绍对于不同类型的tag,如何具体地实现它们。 C& f= ywi0  
l30EKoul)  
Wi<m{.%\E  
简单的tag @{e}4s?7od  
]q[D>6_  
l'1pw  
tag处理类 K3m/(jdO  
-ad{tJV|  
简单的tag处理类必须实现Tag接口的doStartTag和doEndTag方法。当jsp引擎碰到tag标签的开头时,doStartTag被调用,因为简单的tag没有body,所以此方法将返回 SKIP_BODY。当jsp引擎碰到tag标签的结尾时,doEndTag被调用,如果余下的页面还要被计算,那它将返回EVAL_PAGE,否则将会返回SKIP_PAGE。 :kV#y  
}#+^{P3;  
以下是例子:对于标签 <tt:simple /> ,它的tag处理类实现如下: }&D WaO]J7  
{WS;dX4  
klYX7?  
public SimpleTag extends TagSupport Dpac^ST  
<dNOd0e  
{ 3`?7 <YJ  
T<>,lQs(a  
public int doStartTag() throws JspException E=Bf1/c\  
Oszj$C(jF  
{ \l0[rcEf  
=%O6:YM   
try{ RBd7YWo\|j  
8W7J3{d  
pageContext.getOut().print(“Hello.”); I][*j  
Lb-OsKU  
}catch(Exception e){ ]5cT cX;Z#  
H41?/U,{  
throw new JspTagException(“SimpleTag: “ + e.getMessage()); ty!`T+3  
Qel9G($=  
} hZ,_ 6mNg  
I 34>X`[o  
return SKIP_BODY; a-tmq]]E  
|-ALklXr  
} Rv>-4@fMJ  
t}4, ]m s  
public int doEndTag() Yh7t"=o  
R29~~IOqO  
{ C): 1?@  
Nx;~@  
return EVAL_PAGE; ~8+ Zs  
1GRCV8 "Z^  
} >R_&Ouh:  
G_JA-@i%  
} 372rbY  
u#~RkY7s  
; 2#y7!  
注意:如果tag标签没有内容的话,那必须定义body-content元素为空,例如 'Is kWgc  
y^ *~B(T{  
<body-content>empty</body-content> %;' s4ly  
.{^5X)  
^\% (,KNo  
带属性的tag标签
评价一下你浏览此帖子的感受

精彩

感动

搞笑

开心

愤怒

无聊

灌水
级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
只看该作者 1 发表于: 2007-01-01
tag处理类 #{6/ (X  
eByz-,{P  
对于tag标签的每个属性,你必须依照JavaBeans规范来定义其属性,以及get和set方法。以struts的logic:present 标签为例, e *C(q~PQ  
_VN?#J)o  
<logic:present parameter=”Clear”> B3I`40#  
]6` %  
与此相应,此tag处理类应有如下方法和定义: ObS3 M  
L*+@>3mu)  
ITBE|b  
protected String parameter = null; p l0\2e)  
3$R1ipb  
public String getParameter() e !Y~Qy  
!pW0qX\1n  
{ T^KKy0ZGM  
59A}}.@?m  
return this.parameter; )akoa,#%6c  
LL!Dx%JZ  
} 8<.Oq4ku  
Il 'fL'3  
public void setParameter(String parameter) t*u:hex  
+6\Zj)  
{ <'*LRd$1  
]ieeP4*  
this.parameter = parameter; ;^*W+,4WB  
*)Zdz9E'1(  
} f6Ah6tb  
CTa57R  
oc`H}Wvn  
注意:如果你的属性名为id,而且你的tag处理类是从TagSupport类继承的,那你就不需要定义它的属性和set和get方法,因为他们早已在TagSupport被定义过了。 F41=b4/  
3 0H?KAV  
Attribute元素 ,"ZMRq  
?a5!H*,  
对于tag标签的每个属性,你必须定义它是否必须的,它的值是否可以用诸如<%= …%>的表达式来获得,以及它的类型(可选),如果不指定它的类型,那就默认为是java.lang.String类型。如果rtexprvalue元素被定义为true或yes,那么在type元素中就定义了attribute的返回类型。 T5h H  
4[e X e$  
<attribute> cwg"c4V  
z:*|a+cy  
<name>attr1</name> Z9|P'R(l  
_DtV  
<required>true|false|yes|no</required> bG#>uE J-  
:I#V.  
<rtexprvalue>true|false|yes|no</rtexprvalue> &QgR*,5eo  
R m( "=(  
<type>attribute的返回类型(只用当rtexprvalue为真是才有效)</type> }7Q%6&IR  
5b*C1HS@X  
</attribute> 8ib:FF(= u  
GTd,n=  
如果tag的某个属性不是必须的,那tag处理类会自动提供一个缺省值。 .k !{*  
{wKB;?fUvk  
例如,在logic:present这个tag标签中定义了一个属性叫parameter,但它不是必须的,而且它可以被诸如<%= …%>的表达式来赋值。 {<KVx9  
4hj|cCrO  
<tag> =^?/+p8 k  
4pvMd  
<name>present</name> hgq;`_;1,  
g 7H(PF?  
<tag-class>org.apache.struts.taglib.logic.PresentTag</tag-class> Z T%5T}i  
/N{*"s2)  
<body-content>JSP</body-content> 2+XA X:YD  
})%{AfDRF  
h_'*XWd@  
AwR =]W;j  
<attribute> 5H^ (2w  
@yYkti;4-  
<name>parameter</name> F^:3?JA _  
t6c4+D'{].  
<required>false</required> gbA_DZ  
B+`g> h  
<rtexprvalue>true</rtexprvalue> CU0YIL  
 ob]w;"  
</attribute> XCQs2CHt  
h*\%vr  
Le^ n +5x  
;xTpE2 -~  
</tag> SXh-A1t  
wCBplaojJ  
:ws<-Qy  
属性元素的校验 (bS&D/N.  
}SZd  
3v-~K)hl?  
有关于tag标签的有效值可以从tag库的说明文档中获得,当JSP页面被编译时,jsp引擎会强制性地参照TLD中定义的规则进行检查。 Vurq t_nb  
%cn<ych G  
还有一个方法也可以进行属性元素的校验,就是先继承类TagExtraInfo,然后调用它的isValid方法。这个类同时也起到提供tag中定义的脚本变量信息的作用。 SpBy3wd  
DEgXQ[  
IsValid方法通过TagData对象来传递属性信息,它包括着tag的所有的属性名-值的信息。由于校验发生在运行时刻,因此这个属性的值将被赋值为TagData.REQUEST_TIME_VALUE。 LghfM"g  
u ga_T  
例如tag标签<tt:twa attr1=”value1” />在TLD中定义如下: 6u6x  
A#,ZUOPGH  
<attribute> ;'1d1\wiDQ  
%]i15;{X  
<name>attr1</name> xE}>,O|'q  
8ao_i=&x  
<required>true</required> UiNP3TJ'L  
* T1_;4i  
<rtexprvalue>true</rtexprvalue> {!`6zBsP  
uxz^/Gk  
</attribute> Y]a@j !  
%C]>9."  
Fr-SvsNFB  
这个定义说明了attr1能在运行期间被赋值。 7tp36TE  
p#tI;"\y  
以下的isValid方法检查attr1属性的值是否属于Boolean类型。注意由于attr1能在运行刻被赋值,那么isValid方法必须检查tag用户是否对此tag进行了运行时刻赋值。 4,ag(^}=  
zt%Mx>V@  
WIGi51yC.x  
Public class TwaTEI extends TagExtraInfo r JB}qYD  
ALHIGJW:6$  
{ 8P`"M#fI  
eMzk3eOJ  
public boolean isValid(Tagdata data) ar,7S&s H  
\U_@S.  
{ 5h*p\cl!Y  
{;oPLr+Z  
Object o = data.getAttribute(“attr1”); J}t%p(mb  
-?a 26o%e  
If(o != null && o != TagData.REQUEST_TIME_VALUE) ]M3yLYK/P  
k?}Zg*  
{ dh\P4  
=(^3}x  
if( ( (String)o).toLowerCase().equals(“true”) || mE[y SrV  
V]^$S"Tv  
((String)o).toLowerCase().equals(“false”) ) X8\GzNE~R  
An@t?#4gxi  
return true; ssL\g`xe  
xSu >  
else ,r}6iFu  
,,r>,Xq 6  
return false; 7:@'B|  
AXB7oV,xt  
} Ys7]B9/1O  
'GScszz  
else ;{6~Bq9  
< %Y}R\s?  
return true; ,x$,l  
^zr`;cJ+c  
} i30!}}N8  
pCG}Z Ka  
} fqd^9wl>P6  
'%;m?t% q  
jiGTA:v  
带body的tag EM_d8o)`B  
gM]:Ma  
Y-9I3?ar  
tag处理类 MK*r+xfSae  
Q{/Ef[(a@  
TqQ[_RKg2  
如果tag标签含有内容,那处理方式会略微有些不同,而且还要视tag处理类是否要与body交互的情况而定。如果要与body交互,那我们认为tag处理类要可能要对body进行操作。 Ort(AfW  
p<%d2@lp  
Tag处理类不与body交互 _0I@xQj-  
\U0'P;em  
如果tag处理类不与body交互,tag处理类应该实现Tag接口或从TagSupport中派生,如果body要被计算,那么doStartTag方法应返回 EVAL_BODY_INCLUDE,否则应返回SKIP_BODY。 rM SZ"  
K NOIZj   
如果tag处理类要对body反复运算,则它应该实现IterationTag或从TagSupport中派生。如果tag处理类认为body还未计算完的话,那它的doStartTag方法和doAfterBody方法必须返回EVAL_BODY_AGAIN。 -g<oS9   
IGgL7^MF  
Tag处理类与body交互 s#MPX3itK  
G/W>S,(  
如果tag处理类与body交互,那tag处理类应实现BodyTag接口或从BodyTagSupport中派生。这种tag处理类一般要实现doInitBody和doAfterBody方法。 g2]Qv@nxw  
iRBfx  
Body允许一些方法来读写它的内容。Tag处理类可以调用body内容的getString或getReader方法来从body中提取信息,也可用 writeOut(out) 方法来将body的内容写入到out对象中。其中out对象通过tag处理类的getPreviousOut方法来获得。 u@^LW<eD  
m[2gdJK  
如果body的内容需要被计算,那么doStartTag方法必须返回EVAL_BODY_BUFFERED,否则,它将返回 SKIP_BODY。 8,|kao:  
d_ CT $  
doInitBody 方法 MfkZ  
#;S*V"  
此方法在body内容已经设好,但未被计算之前被调用。你可以根据不同的body内容来制定初始化策略。 w(F%^o\  
a.Vuu)+Quw  
doAfterBody方法 zeRyL3fnmb  
U!]dEW|G  
此方法在body内容已被计算后进行调用。 /@5YW"1  
DNi+"[~&P  
和doStartTag方法一样,doAfterBody方法返回一个指示符指示是否要继续计算body,如果要继续计算,则doAfterBody应返回EVAL_BODY_BUFFERED,否则,它应返回SKIP_BODY。 &Qm@9Is  
Hp?/a?\Xm  
release 方法 :KO2| v\  
P2Y^d#jO  
tag处理类调用此方法将它的状态重置为初始状态,并释放所有的私有资源。 n@w%Zl  
9 $X-  
-qoH,4w  
以下的例子读取body的内容(其中含有一条sql语句),然后将它传递给一个对象,让它进行查询。由于此处body不须重新计算,所以doAfterBody会返回SKIP_BODY。 8Y?;x}  
X?Au/  
'q.!|G2U  
Public class QueryTag extends BodyTagSupport B<-Wea  
(.,G=\!  
{ Ca\6vR  
,?3G;-  
public int doAfterBody() throws JspTagException z{>Rc"%\  
GthYzd:'hJ  
{ 8>V5d Ebx'  
Ts9uL5i  
BodyContent bc = getBodyContent(); I:.s_8mH}  
%znc##j)q  
//将body的内容以字符串的格式提取出来 v,t:+ !8  
] R*A  
String query = bc.getString(); @PU [:;  
PW4q~rc=:  
//清除body ntY]SK%Z  
SX*RP;vHy  
bc.clearBody(); gZ5 |UR<  
W9)&!&<o  
try{ 9FX-1,Jx  
~s{$WL&  
Statement stmt = connection.createStatement(); D,6:EV"sa  
snJ129}A  
Result result = stmt.executeQuery(query); 7o4\oRGV  
'<M{)?  
}catch(SQLException e){ uq{ beC  
?4B`9<j8%  
throw new JspTagException(“queryTag: “ + e.getMessage() ); cNH7C"@GVu  
##{taR8  
return SKIP_BODY; y)*RV;^  
|g~ZfnP_%  
} `x|?&Ytmf9  
 @8 6f  
} A=4OWV?  
3sk9`=[{$  
$J2Gf(RU  
body-content元素 n*$ g]G$  
Je{ykL?N  
v2?ZQeHr_(  
由于tag可能会有body,你必须用body-content元素来指定body内容的类型: 5)E @F9N  
ry!!9Z>9n  
<body-content>JSP|tagdependent</body-content> W4N{S.#!  
F5Va+z,jg  
+qoRP2  
如果body的内容是定制的或内部的tag、脚本元素、或HTML广本,则归类为JSP类型。其他的类型,比如上面代码所述的?D?D将sql statement类传给 query tag的这种类型应该标为tagdependent。 b]y2+A.n  
_g. {MTQ  
注意:实际上body-content的值并不影响tag处理类对body内容的处理,它仅仅是被tag编辑工具用来描述此body的内容。 f5r0\7y0  
@.C2LIb  
% `3jL7|  
用tags定义脚本变量 xfQ1T)F3g  
[vgtc.V  
wj+*E6o-n  
tag处理类 $^ P0F9~0  
ZW}_DT0  
l ,8##7  
tag处理类负责创建或设置页面中定义的脚本变量,用pageContext.setAttribute(name,value,scope)或pageContext.setAttribute(name,value)方法来实现。一般来说,tag处理类通过脚本变量的名称来获取它,脚本变量的名称一般可用get方法来获得。 MPV5P^@X  
nR~(0G,H  
如果脚本变量的值依赖于tag处理类中的上下文中某一对象,那它可用pageContext.getAttribute(name,scope)方法来找到那个对象。一般的处理过程是tag处理类先找到脚本变量,再对其进行处理,然后用pageContext.setAttribute(name,object)的方法来设置它的新值。 nK,w]{<wG!  
hQ i2U  
对象的生存周期(scope)如下表: KSvE~h[#+  
PeT'^?>  
对象的生存周期表 *or(1DXP8  
]oxZ77ciL  
名字 "fI6Cpc  
可访问范围 0mnw{fE8_  
生存周期 ]! dTG  
/ +\9S  
page 6pzSp  
当前页面 s CRdtP  
一直有效,除非页面向客户提交响应或重定向到一个新页面 OH88n69  
Z7#+pPt!  
request N0lC0 N?_J  
当前页面或当前页面重定向到的页面 eJSxn1GW  
一直有效,除非页面向客户提交响应 j F>[?L  
. ^u,.  
session ;I*o@x_  
当前页面或在同一浏览器窗口中的页面 T |p"0b A  
一直有效,除非关闭当前浏览器、超时、网络故障 .h[:xYm  
ZEQEx]Y  
application s>en  
整个web应用程序的所有请求 H.c7Nle  
一直有效,除非发生网络故障、服务器故障 /mMV{[  
:svq E+2  
提供关于脚本变量的信息 g{Rd=1SK]  
;r8X.>P*  
以下示例定义了一个名为“book”的脚本变量,用来访问程序中关于书的信息: ,>M[@4`,U  
U17d>]ka  
<bean:define id=”book” name=”bookDB” property=”bookDetails” type=”database.BookDetails” /> ~zgGa:uU  
7"##]m.  
<font color=”red” size=”+2” > ?CZd Ol  
H[gWGbPq7  
<%= messages.getString(“CartRemoved”) %> ?(PKeq6  
nu^436MSOa  
<strong><jsp:getProperty name=”book” property=”title” /></strong> ]yu:i-SfP  
a}d@ T  
</font> d1*<Ll9K  
ebq4g387X  
当包含此tag的JSP页面被编译时,jsp引擎会自动生成关于此book的同步的代码(同步可以避免几个客户同时访问此book时造成的冲突),要生成同步代码,jsp引擎需要知道此脚本变量的如下信息: ;*N5Y}?j'  
),)lzN%!  
· 脚本变量名称 <GJbmRc|  
m[$_7a5  
· 脚本变量所属的类 Bwrx*J  
/{[o ~:'p  
· 此脚本变量是否引用了一个新的或已存在的对象 mR~&)QBP.  
[Zrr)8A  
· 此脚本变量的有效性 XG?8s &  
Fs{*XKv&lH  
有两种办法可以向jsp引擎提供关于脚本变量的信息:在TLD中定义variable子元素,或用tei-class子元素定义一个额外tag信息类。用variable最简单,但可能降低了一些灵活性。 omFz@  
@7u0v  
Variable元素 [m -bV$-d  
\GBuWY3B  
Variable元素有如下子元素: [RL9>n8f  
>sF)Bo Lc  
· name-given ?D?D 给出的名字,是一个常量 cS$_\65  
0a7Ppntb@  
· name-from-attribute?D?D 属性名,在编译时给出的属性名  9!GM{  
9^x> 3Bo  
name-given或name-from-attribute两者必须选一,但以下子元素是可选的: UBs4K*h|  
E{\2='3\  
· variable-class?D?D变量的类型,缺省为java.lang.String。 YQ} o?Q$z  
. me;.,$#  
· declare?D?D此脚本变量是否引用了一个新对象,缺省为True。 .X&9Q9T=#  
^pS~Z~[d/  
· scope?D?D脚本变量的范围,缺省为NESTED。下表描述了scope的几种类型: jo7\`#(Q  
t:S+%u U  
脚本变量的有效范围 LP-o8c  
=AT."$r>  
So6x"1B  
有效性 IgzQr >  
方法 3R/bz0 V>  
Zfw,7am/  
NESTED *Ly6`HZ9  
在tag标签的开始和结束之间  \*da6Am  
如果tag处理类实现BodyTag接口,则在doInitBody和doAfterBody中调用,否则在doStartTag中调用 0_/[k*Re  
V+\Wb[zDJ  
AT_BEGIN l}h!B_P'  
从tag标签的开始一直到页面结束 N mG#   
如果tag处理类实现BodyTag接口,则在doInitBody、doAfterBody和doEndTag中调用,否则在doStartTag和doEndTag中调用 QP x^_jA  
t-AmX) $  
AT_END m~|40)   
从tag标签的结束一直到页面结束 0J|3kY-n>  
在doEndTag中调用 "4Nt\WQ  
+_!QSU,@  
以struts为例,它的bean:define标签的实现遵循JSP1.1规范,此规范要求使用额外tag信息类来定义脚本变量。Variable元素是JSP1.2规范中加入的。以bean:define标签为例,你可以定义如下variable元素: ~Ei<Z`3}7"  
h;Kx!5)y  
<tag> TpaInXR  
CITc2v3a  
<variable> <aw[XFg  
!Cs_F&l"j  
<name-from-attribute>id</name-from-attribute> qK+5NF|  
Sdo-nt  
<variable-class>database.BookDetails</variable-class> UG^q9 :t  
mDWG7Asp  
<declare>true</declare> i%/+5gq  
x;S @bY  
<scope>AT_BEGIN</scope> S/ *E,))m  
[^)g%|W  
</variable> zA 3_Lx!  
do_[&  
</tag> 3$tdwe$S  
|)&%A%m  
额外tag信息类 GyIV Hby  
Xvv6~  
如果要定义一个额外tag信息类,你要继承javax.servlet.jsp.TagExtraInfo类。一个TagExtraInfo类必须实现getVariableInfo方法,此方法返回一个叫VariableInfo的数组类,它包括如下信息: =l6mL+C  
#E?4E1bnB  
· 变量名 %>yL1BeA4  
mw!F{pw  
· 变量所属类名 `uFdwO'DD  
{ax:RUQxy  
· 此变量是否引用了一个新对象 wJ]d&::@h  
oDR%\VY6T  
· 此变量的有效范围 \bF{-"7.  
H|*m$| $,  
jsp引擎将一个名为data的参数传给getVariableInfo方法,data中包括tag标签中的所有“属性名?D?D属性值”对。它可以用来向VariableInfo对象提供脚本变量的名字和类名。 [ 3Gf2_  
8}[).d160  
以struts为例,它在bean:define标签中定义了一个名为DefineTei的额外tag信息类,用来向脚本变量提供信息。由于脚本变量的名称(book)和类名(database.BookDetails)是通过tag标签的属性来传递的,它们一般定义在VariableInfo的构建代码中,并且可用data.getAttributeString方法来得到这些信息。如果要允许book脚本变量能在从tag开始直到整个JSP页面结束的范围内都可用的话,那它的范围应设为AT_BEGIN。如下所示: XX@ZQcN  
Hz~zu{;{J  
CAJ'zA|o  
public class DefineTei extends TagExtraInfo r$1Qf}J3=  
|>Vb9:q9Po  
{ ok[i<zl; '  
97]E1j]  
public VariableInfo[] getVariableInfo(TagData data) yfSmDPh  
hM{bavd  
{ NUZl`fu1Z4  
6<]lW  
String type = data.getAttributeString(“type”); b-DvW4B  
M+>u/fldV  
If( type == null) 3Ul*QN{6  
S!UaH>Rh  
type = “java.lang.Object”; n]9$:aLZ  
Ey2^?  
return new VariableInfo[] { 'V{W-W<  
I0 -MRU~[K  
new VariableInfo(data.getAttributeString(“id”), %{|pj +  
\<' ?8ri#  
type, L#J1b!D&<6  
fl(wV.Je|  
true, t!XwW$@  
vt8By@]:  
VariableInfo.AT_BEGIN) n[z+<VGwC  
Z~CjA%l  
}; 6'/ #+,d'  
_U(  
} Nc`L;CP  
L_T5nD^D  
}  )2.Si#  
M-71 1|eGI  
# ] QZ  
注意:关于额外tag信息类的类名必须要在TLD中的tag标签下的tei-class子元素中定义。因此,DefineTei的tei-class中的定义看起来如下: wj,=$RX  
<tei-class> +whDU2 "  
org.apache.struts.taglib.bean.DefineTagTei q 1,~  
</tei-class> Xhm c6?  
KPF1cJ2N  
SU0 hma8  
具有协作关系的tag ! mHO$bQ"  
fVlB=8DNk&  
5+'<R8{:,  
tag通过共享对象来进行协作,JSP技术支持2种方式的对象共享。 GJrG~T  
C_Dn{  
第一种方法是使用pageContext对象进行对象的共享(可支持JSP页面和tag处理类之间的共享),如果在一个tag处理类中要调用由另一个tag处理类创建的对象,可调用pageContext.getAttribute(name, scope)方法。 ;+%rw2Z,B  
r&CiSMS*  
第二各方式的共享是对于tag之间有嵌套关系而言的,外层的tag所创建的对象对于内层的tag来说是可以共用的。这种形式的共享的好处是减少了可能存在的重名冲突。 t0S 1QC+  
Cy e.gsCT  
要访问一个嵌套tag创建的对象,tag处理类必须先找到此嵌套tag对象,可用TagSupport的静态方法 TagSupport.findAncestorWithClass(from, class)或TagSupport.getParent方法。前者在当不确定此tag是否为嵌套tag对象时使用。一旦它的父类被找到,它就能访问其所有动态或静态创建的对象。静态创建的对象是父类的成员,而动态创建的对象可能是父类的私有对象。诸如此类的对象可以用tag处理类的setValue方法来保存,用getValue方法来获得。 z_HdISy0  
/x hKd]Q  
下例阐述了以上两种共享对象的方法。在这个例子当中,一个查询tag检查一个名为connection的属性名是否在doStartTag中被设置。如果connection属性被设置,tag处理类从pageContext中得到这个connection对象。否则,此tag处理类先找到它的父tag处理类,然后从它的父tag处理类中找到connection对象。 1#x0q:6  
5+vaE 2v  
_/|\aqF.  
public class QueryTag extends BodyTagSupport aUp g u"  
80I#TA6C  
{ w:0E(z  
p{_ " bB  
private String connectionId; @C$]//;  
s<Ziegmw|g  
public int doStartTag() throws JspException +>,I1{u%&  
m`XHKRp  
{ 3BI1fXT4=j  
s!J9|]o  
String cid = getConnection(); R_C)  
_f83-':W6  
if(cid != null) ^('wy};  
%EH)&k  
{ XSR 4iu  
V0@=^Bls  
//存在一个connection id,使用它。 e+WNk 2  
Vr}'.\$  
connection = (Connection) pageContext.getAttribute(cid); l#o ~W`  
aN?zmkPpov  
} /: "1Z]@  
=bOW~0Z1  
else )`:UP~)H  
]Ze1s02(  
{ )7F/O3Tq  
0kh6@y3  
ConnectionTag ancestorTag = (ConnectionTag)findAncestorWithClass(this, M%HU4pTW#o  
q~3>R=t  
ConnectionTag.class); ye&;(30Oq  
G{}VPcrbC  
if(ancestorTag == null) jA1 +x:Wq  
-n 1 v3  
{ P:c w|Q  
M3\AY30L  
throw new JspTagException(“一个没有connection属性的查询标签必须被一个connection标记嵌套。”); 54 T`OE =  
/m1\iM\  
} zX[U~.  
';CNGv -  
connection = ancestorTag.getConnection(); 0mE 0 j  
Ud?Q%) X  
} ^qs $v06  
%b$>qW\*&  
} _6Sp QW  
B\~}3!j  
} )9g2D`a4  
|Cv!,]9:r  
( .:e,l{U%  
y[;>#j$  
此查询标签在JSP页面中的调用形式可以从以下2种定义中任选一种: l?e.9o2-  
N~Jda o  
r!v\"6:OM  
<tt:connection id=”con01” ...> ... </tt:connection> D.:Zx  
4hB]vY\T  
<tt:query id=”balances” connection=”con01” > j2k"cmsKh  
wk^B"+Uhy  
SELECT account, balance FROM acct_table IGl9 g_18  
M`_0C38  
where customer_num = <%= request.getCustno() %> HMXE$d=[  
BmT!aue  
</tt:query> i!Ba]n   
Gc?a+T  
3";q[&F9y  
MgZ/(X E  
"oyo#-5z  
<tt:connection ...> w;M#c Y  
81F9uM0  
<x:query id=”balances”> vM={V$D&  
vx =&QavL  
SELECT account, balance FROM acct_table #!=tDc &  
VbYdZCC  
where customer_num = <%= request.getCustno() %> )%TmAaj9d  
z{q`GwW  
</x:query> U{mYTN*:j$  
$ nb[GV  
</tt:connection> *. t^MP  
W?& %x(6M  
tQVVhXQ7  
与此同时,在TLD中必须指定connection属性为可选的,定义如下: ^iA9%zp  
7V>M]  
<tag> UKGPtKE<  
*~`(RV  
... h[ ZN+M  
i8p6Xht  
<attribute> Wwo0%<2y  
e-;}366}  
<name>connection</name> JF]JOI6.e  
sO Y:e/_F  
<required>false</required> A/(a`"mK|'  
;uW FHc5@B  
</attribute> i b m4fa  
(7Qo  
</tag>
描述
快速回复

您目前还是游客,请 登录注册
如果您提交过一次失败了,可以用”恢复数据”来恢复帖子内容
认证码:
验证问题:
3+5=?,请输入中文答案:八 正确答案:八