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

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

级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
标准的JSP 标记可以调用JavaBeans组件或者执行客户的请求,这大大降低了JSP开发的复杂度和维护量。JSP技术也允许你自定义taglib,其实换句话说,taglib可以看成是对JSP标记的一种扩展,正如xml是对html的一种扩展一样。taglib通常定义在tag标签库中,这种标签库存放着你自己定义的tag标签。简而言之,如果使用taglib,那么你可以设计自己的JSP标记! _.K<#S  
7N I~47s|v  
一般来说,自定义tag标签主要用于操作隐藏对象、处理html提交表单、访问数据库或其它企业级的服务,诸如邮件和目录操作等等。自定义tag标签的使用者一般都是那些对java编程语言非常精通,而且对数据访问和企业级服务访问都非常熟悉的程序员,对于HTML设计者来说,使得他可以不去关注那些较复杂的商业逻辑,而将精力放在网页设计上。同时,它也将库开发者和库使用者进行合理分工,自定义tag标签将那些重复工作进行封装,从而大大提高了生产力,而且可以使得tag库可用于不同的项目中,完美地体现了软件复用的思想。 i")ucrf  
/\|Behif  
在这篇文章中,我们主要讨论: t.= 1<Ed  
-+Ab[  
· 什么是自定义tag标签? Zh 3hCxXa  
+oRwXO3W  
· 怎么使用tag标签? ad'C&^o5  
wU)vJsOq  
o 声明要使用的tag库 7&{[Y^R]"  
@/0-`Y@?  
o 找到与之对应的tag处理类 5_= HtM[v]  
Bd-@@d.H<  
o tag标签的类型 Tq`rc"&7u  
2JS&zF  
· 自定义tag标签 7S)u7  
UsBtk  
o tag处理类 R[_UbN 28  
^Yu%JCN8g  
o tag库描述 y759S)U>>p  
O'~;|-Z<  
o tag标签示例 8sGaq [  
9#ZR0t.cY  
o 带属性的tag D_)n\(3  
P *zOt]T  
o 带body的tag '}.Z' %;  
@?\[M9yK  
o 定义了脚本变量的tag l8Ks{(wh  
(_$'e%G0  
o 具有协作关系的tag Ht!]%  
+-+%6O<C  
· 自定义tag标签 [ #1<W`95  
KG8Km  
o 一个迭代tag的例子 yJG M"$  
pQf5s7  
o 一个模板tag库 BA t0YE`-,  
j`pX2S  
o tag处理类到底是怎样被调用的? tsvh/)V  
N#"(  
qKL mL2O  
什么是自定义的tag? }* s%|!{H  
"g>, X[g  
一个自定义的tag标签是用户定义的一种JSP标记。当一个含有自定义的tag标签的JSP页面被jsp引擎编译成servlet时,tag标签被转化成了对一个称为tag处理类的对象进行的操作。于是当JSP页面被jsp引擎转化为servlet后,实际上tag标签被转化成为了对tag处理类的操作。 ;u "BCW  
sAec*Q(R  
自定义tag标签有很多特色,诸如: c1L0#L/F6"  
mcFJ__3MAV  
· 可以在JSP页面中自定义tag标签的属性 z),@YJU"z  
B6gn(w3  
· 访问JSP页面中的所有对象 "hi)p9 _cR  
^B`*4  
· 可以动态地修改页面输出 d iGkwKj  
pNIu;1M5a  
· 彼此这间可以相互通信。你可以先创建一个JavaBeans组件,然后在一个tag中调用此JavaBeans组件,同时可以在另一个tag中调用它。 ROc)LCA  
[c_o.`S_\  
· tag允许相互嵌套,可以在一个JSP页面中完成一些复杂的交互。 sj& j\<(  
W|e$@u9  
q"O4}4`  
使用tag标签 yE4X6  
fce~a\y0  
EmO{lCENk  
本节主要描述怎样在JSP页面中使用tag标签,以及tag标签的不同类型。 /$NZj" #  
1?}5.*j<  
要使用tag标签,JSP程序员必须做2件事: M!j: 2dT"  
?ot7_vl  
· 声明此tag标签的tag库 oYn|>`+6:y  
1Ff Sqd  
· 实现此tag标签 [9U: :  
gJUawK  
声明tag标签所在的tag库 +P5\N,,7R  
P UJkC  
如果要使用tag标签,则应用JSP的taglib指示符来指定其tag库(注意:taglib要在在使用此tag标签之前声明) {InD/l'v6n  
y.PsC '  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> zm7IkYF  
B{ptP4As-  
uri属性定义了唯一的标签库描述(以下简称TLD),它可以是直接是tld文件名或一个独一无二的名字。prefix是用来区别其它TLD中和本TLD中有重名的tag的一种手段。 ^vA"3Ixb!  
zs<2Ozv  
TLD必须以.tld作为扩展名,并且存放在当前应用的WEB-INF目录或其子目录下。你可以通过它的文件名直接引用它,也可以通过别的方式间接地引用它。  ^D.u   
;Or]x?-  
以下taglib指示符直接引用一个TLD: gfY1:0  
j{?ogFfi  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> V^[B=|56  
aI'MVKwMk  
以下的taglib指示符通过一个逻辑名称间接地引用一个TLD: +8#hi5e  
b|'{f?  
<%@ taglib uri=”/tutorial-template” prefix=”tt” %> rOyKugHe  
(SnrY O`#  
如果是间接引用TLD的话,那你必须还要在web.xml中定义此逻辑名称与tld文件之间的映射,具体做法是在web.xml中加入一个名为taglib的元素: ]8;2Oh   
(n+FEE<  
<taglib> {dF_ =`.  
 ZFH;  
<taglib-uri>/tutorial-template</taglib-uri> @7j$$  
|Y")$pjz  
<taglib-location> %c"t`  
N" =$S|Gs  
/WEB-INF/tutorial-template.tld a58]#L~  
![l`@NH[U  
</taglib-location> $(=0J*ND"  
q0y#Y  
</taglib> 7q;wj~  
u4QBD5T"  
z3mo2e  
实现此tag标签 zS<idy F`  
|JVp(Kx  
Rxfhk,I  
为了实现tag标签,你有2种方法来存放tag处理类。一、让tag处理类以.class的方式存放于当前应用的WEB-INF/class子目录下,二、如果tag处理类是以JAR包的形式存在的话,那可以放在当前应用的WEB-INF/lib目录下,如果tag处理类要在多个应用中共享,那么它就应放在jsp服务器上的common/lib目录下,对于tomcat来说,就是tomcat/common/lib目录下。 Mr6q7  
ucwUeRw,  
"t!_b ma  
tag标签类型 )ld`2) 4  
__OH gp 1  
OS]FGD3a  
自定义的tag标签遵循XML语法。它有一个开始标记和一个结束标记,有的还有body(即文本节点): 'U/X<LCl  
Y-fDYMm  
<tt:tag> Vu1swq)l  
WTX!)H6Zv  
body }*>xSb1  
H2oD0f|  
</tt:tag> l/6$BP U`  
W6Z3UJ-  
FNy-&{P2  
一个不带body的tag标签如下: /4wPMAlb  
FesUE_L2$  
<tt:tag /> f C_H0h3  
u|EHe"V"  
l`(pV ;{W  
简单的tag标签 e4<[|B!O  
^P~NE#p5  
一个没有body和属性的tag标签如下: S>nf]J`  
%RD%AliO}K  
<tt:simple /> Dxp.b$0t  
-hpC8YS  
A=bBI>GEYP  
带属性的tag标签 W>cHZ. _  
& T&>4I!'M  
sHn-#SGm  
自定义标签可以有自己的属性。属性一般在开始标记中定义,语法为 attr=”value”。属性的作用相当于自定义标签的一个参数,它影响着tag处理类的行为。你可以在TLD中详细定义它。 |:)ARH6l#  
[\,Jy8t)\  
你可以用一个String常量给一个属性赋值,也可以通过表达式给它赋值,如<%= ...%>。以struts为例,它的logic:present标签就是用的String常量来给属性赋值: yDmx)^En  
E*G {V j  
<loglic:present parameter = “Clear”> aYrbB#  
}Jm~b9j  
而另一个标签logic:iterate是用表达式来给属性赋值: )7;E,m<:tO  
i{2ny$55h  
<logci:iterate collection=”<%= bookDB.getBooks() %>” eccJt  
kpLx?zW--q  
id=”book” type=”database.BookDetails”> ?v@pB>NZ  
6 H' W]T&  
rPXy(d1<`S  
带body的tag标签 \wM8I-f!  
!v68`l15  
一个自定义标签可以包含其它自定义标签、脚本变量、HTML标记或其它内容。 F*J@OY8i  
9D,/SZ-v  
在下述例子中,此JSP页面使用了struts的logic:present标签,如果些标签定义了parameter=”Clear”的属性,则将清除购物车的内容,然后打印出一条信息: !63]t?QXMG  
]aI   
<logic:present parameter=”Clear”> Q1^kU0M}  
wq = Ef  
<% cart.clear(); %> Xn # v!  
>&D}^TMYY  
<font color=”#ff0000” size=”+2”><strong> 5Zy%Nam'gN  
'wd&O03&  
你选择了清除购物车! Un^3%=;  
@;`d\lQ  
</strong></font> )Nnrsa  
.Hm1ispq  
</logic:present> [/GCy0jk  
s]'EIw}mo  
wHE1Jqpo  
到底是用属性还是用body来传递信息? i>{.Y};  
i(an]%'v  
如上所述,我们既可以通过属性,也可以通过body来传递信息。但一般来说,比较简单的类型,如字符串或简单表达式最好采用属性来传递信息。 ihBIE  
Mi:i1i cdn  
#iVr @|,  
定义脚本变量的tag标签 |?<^4U8  
9 `T2  
所谓脚本变量,是指JSP中可以调用的变量或对象。它可由tag标签产生。以下示例阐述了一个tag标签定义了一个名为tx的由JNDI所定义的事务处理对象。脚本变量可以是ejb对象、事务、数据库连接等等: %[WOQ.Sh  
>eucQ]  
<tt:lookup id=”tx” type=”UserTransaction” name=”java:comp/UserTransaction” /> ?~=5 x  
{vox x&UX  
<% tx.begin(); %> :)DvZxHE@  
5\.w\  
... qt`HP3J&  
=cWg 39$(I  
M+GtUE~"  
具有协作关系的tag标签 rq![a};~  
rt C:3fDy  
自定义tag标签之间可以通过共享对象来实现协作。在下述例子中,标签tag1创建了一个名为obj1的对象,在标签tag2仍可以重复使用obj。 g66x;2Q  
0T.kwZ8  
<tt:tag1 attr1=”obj1” value1=”value” /> W,bu=2K6  
Tu&W7aoX5  
<tt:tag2 attr1=”obj1” />  ?F/)<r  
Y_,Tm  
在以下这个例子当中,如果外层的tag标签创建了一个对象,那么其内层的所有tag标签都可以使用这个对象。由于这样产生的对象没有一个指定的名字,那么就可以将少重名的冲突。这个例子阐述了一系列协作的嵌套对象。 sj8lvIY5  
O~4Q:#^c  
<tt:outerTag> 3S{3AmKj?  
Mt\.?V:  
<tt:innerTag /> :@#6]W  
w" ,ab j  
</tt:outerTag> 3='Kii=LA  
K8 Hj)$E61  
(o518fmR  
Tag处理类 ]6@6g>f?  
;uN&yj<}a  
vpz l{  
Tag处理类必须实现Tag接口或BodyTag接口,不过现在一般都流行从TagSupport或BodyTagSupport类中继承,这些类或接口都可以在javax.servlet.jsp.tagext包中找到。 6!Uk c'r  
v(~EO(n.  
当JSP引擎看到自己的JSP页面中包含有tag标签时,它会调用doStartTag方法来处理tag标签的开头,调用doEndTag方法来处理tag标签的结束。 .tA=5 QY,  
d5#z\E??  
下表说明不同类型的tag所需要不同的处理过程: &}!AjA)  
0S&C[I o6  
Tag处理类的方法 9=.7[-6i9  
q_z;kCHM  
Tag标签类型 Ib2n Bg>j  
所调用的方法 #Q$e%VJ(c1  
46gDoSS  
基本标签 [ @9a  
doStartTag, doEndTag, release k|3hs('y|  
[7h/ 2La#  
带属性的标签 iiv`ji  
doStartTag, doEndTag, set/getAttribute1...N, release hr`,s!0Y  
z LZ HVvL3  
带内容的标签 Mw|lEctN0  
doStartTag, doEndTag, release FXh*!%"*  
OXS.CFZM  
带内容的标签,且内容重复循环 cS(=wC  
doStartTag, doAfterBody, doEndTag, release GC7W7B  
o]@'R<F(u  
带内容的标签,且内容与JSP交互 Qq3>Xv <  
doStartTag, doEndTag, release, doInitBody, doAfterBody, release ?^WX] SAl  
6f)7*j~  
一个tag处理类可以通过javax.servlet.jsp.PageContext来与JSP交互,通过javax.servlet.jsp.PageContext类,tag处理类可以访问JSP中的request、session和application对像。 tY%T  
~T!D:2G  
如果tag标签是互相嵌套的,那内层的tag处理类可以通过它的parent属性来访问上层的tag处理类。 qJ[wVNHh!  
uTNy{RBD+  
一般情况都将所有的tag处理类打成了JAR的包,以便于发布。 {hVc,\A  
\ 0.!al0  
k,LaFe`W  
Tag库描述(简称TLD) 1pP q)}=+  
t|C?=:_  
6\USeZh  
Tag库是用xml语言描述的,TLD包括了tag库中所有tag标签的描述,它一般用来被jsp服务器用来校验tag的语法正确性,或者被jsp开发者用来开发新的标签。 4@=[r Zb9  
L'O=;C"f  
TLD的文件扩展名必须为.tld,而且必须放在当前WEB应用的WEB-INF目录或其子目录中。 $ZlzS`XF7  
6W9lKD_i  
一个TLD的内容的开头必须遵守标准的XML开头,用于描述DTD和xml的版本,例如: =yZ6$ hK  
<K <|G  
<?xml version="1.0" encoding="ISO-8859-1" ?> .p%V]Ka  
*1h@Jb34  
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd"> WF-^pfRq~  
TLD必须以<taglib>来作为它的根元素,<taglib>的子元素如下表: y\R-=Am".  
&/?OP)N,}  
T;v^BVn  
<taglib>的子元素 [ nLd>2P  
c=aVYQ"2  
Element wlpcuz@  
Description zS '{F>w  
rh T!8dTk  
tlib-version et<@3wyd]  
Tag库的版本 u. 2^t :A  
'![VA8  
jsp-version `HILsU=|  
Tag库所需要的jsp的版本 uTrQ<|}#  
8# IEE|1  
short-name g{JH5IZ~  
助记符,tag的一个别名(可选) w:2yFC  
B-V   
uri Mo\nY5  
用于确定一个唯一的tag库 J]|S0JC`  
[ZD`t,x(  
display-name lHO.pN`2  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) zLg_0r*h1  
0OBwe6*  
small-icon lM.k *`$  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) v1$ }JX   
tDtqTB}  
large-icon &Q t1~#1  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) z5W;-sCz  
@'"7[k!y;  
description xLw[ aYy4  
对tag库的描述(可选) X [;n149o  
KJ_L>$ ]*  
listener XlJ+:st  
参见下面listener元素 CFeAKjG  
S9 @*g3  
tag wD SSgk  
参见下面tag 元素 jR{t=da  
hroRDD   
Listener元素 9HAK  
Nrc-@ ]  
一个tag库可能定义一些类做为它的事件侦听类,这些类在TLD中被称为listener 元素,jsp服务器将会实例化这些侦听类,并且注册它们。Listener元素中有一个叫listener-class的子元素,这个元素的值必须是该侦听类的完整类名。 [yVcH3GcjI  
\{1Vjo  
Tag元素 s "l ^v5  
kp*BAQ  
每个tag元素在tag库中都要指出它的名字、类名、脚本变量、tag的属性。其中脚本变量的值可以直接在TLD中定义或通过tag附加信息的类来取得。每个属性描述了这个属性是否可以省略,它的值是否可以通过<%= …%>这样的JSP语法来获得,以及属性的类型。 jyC>~}?  
)T@+"Pw8t  
每一个tag在TLD中对应一个tag元素,下表是tag元素的子元素: `7'=~BP?X  
[}y"rs`!  
Tag元素的子元素 i>;6Z s>S  
Job&qW9W`  
元素名称 =A; 79@bY  
描述 Ms A)Y  
5S4`.'  
name sJ|IW0Mr  
独一无二的元素名 7` t,   
}:+P{  
tag-class (Jk:Qz5  
Tag标签对应的tag处理类 s$VLVT*6  
EZ^M?awB4  
tei-class y |Tv;v1L  
javax.servlet.jsp.tagext.TagExtraInfo的子类,用于表达脚本变量(可选) ,tuZ_"?M  
< !]7Gt  
body-content %xt\|Lt  
Tag标签body的类型 UFUm-~x`  
e{d$OzT) V  
display-name vo2TP:  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) q|e<b  
"`5BAv;u  
small-icon [Kd"M[1[ <  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) *. ; }v@  
n:YA4t7S  
large-icon t8-LPq  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) @fSqGsSk  
9wv 7 HD|  
description #NWc<Dd  
此tag标签的描述 9_pOV%Qs  
) 2Hl\"F  
variable ow,=M%x"0  
提供脚本变量的信息(同tei-class)(可选) 8 9f{8B]z  
jVdB- y/r  
attribute xsXf_gGu  
Tag标签的属性名 oOK&+r7  
D i #Em[  
以下章节介绍对于不同类型的tag,如何具体地实现它们。 Q?W}]RW  
)9>E} SU/  
?:sQ]S/Er  
简单的tag ca8.8uHY\  
XJi^gT N  
R8R,!3 N  
tag处理类 W>`#`u  
Fv9n>%W&  
简单的tag处理类必须实现Tag接口的doStartTag和doEndTag方法。当jsp引擎碰到tag标签的开头时,doStartTag被调用,因为简单的tag没有body,所以此方法将返回 SKIP_BODY。当jsp引擎碰到tag标签的结尾时,doEndTag被调用,如果余下的页面还要被计算,那它将返回EVAL_PAGE,否则将会返回SKIP_PAGE。 }4"T# [n#  
MM4Eq>F/  
以下是例子:对于标签 <tt:simple /> ,它的tag处理类实现如下: e5fzV.'5  
fHwr6"DJ  
/h73'"SpDy  
public SimpleTag extends TagSupport 8p~G)J3U  
f}F   
{ &sJ%ur+G  
7 {#^ zr  
public int doStartTag() throws JspException ]Q0+1'yuK  
uSK<{UT~3  
{ o9uir"=  
z8hAZ?r1`  
try{ ' fP`ET5  
&c1zEgl  
pageContext.getOut().print(“Hello.”); ZtqN8$[6n  
Lj03Mx.2S  
}catch(Exception e){ ar| !iU  
6@o *"4~Q  
throw new JspTagException(“SimpleTag: “ + e.getMessage()); _m|Tr*i8  
G[5z3  
} O<?z\yBtS^  
lGtTZ cg  
return SKIP_BODY; \4|o5,+(@  
S^4T#/  
}  MUd 9R  
" tUF,G(<  
public int doEndTag() #q%V|Ajq  
*(sFr E  
{ "FT(U{^7d  
g}=opw6z  
return EVAL_PAGE; 2k$~Mv@L  
)~l`%+  
} <i!7f26r  
Cn>RUGoUsI  
} nJ-U*yz  
Y^@Nvt$<K  
6:vdo~  
注意:如果tag标签没有内容的话,那必须定义body-content元素为空,例如 dLn Md0  
i5 F9*  
<body-content>empty</body-content> V,CVMbn/%N  
kX^Y{73  
b)Px  
带属性的tag标签
评价一下你浏览此帖子的感受

精彩

感动

搞笑

开心

愤怒

无聊

灌水
级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
只看该作者 1 发表于: 2007-01-01
tag处理类 ~Z#jIG<?g  
3'zm)SXJ  
对于tag标签的每个属性,你必须依照JavaBeans规范来定义其属性,以及get和set方法。以struts的logic:present 标签为例, 4/tp-dBip  
xi =\]  
<logic:present parameter=”Clear”> oG_-a(N  
]wQ#8}zO  
与此相应,此tag处理类应有如下方法和定义: E{Ux|r~  
dwc$#cMf  
A#6\5u  
protected String parameter = null; cKKl\g@}  
?$#,h30  
public String getParameter() )Q%hd|R  
{yPiBu  
{ n(MVm-H  
(haYY]W\  
return this.parameter; =#"ZO  
_26<}&]b*  
} LT3ViCZ-n  
c= }#8d.  
public void setParameter(String parameter) Iw<: k  
XOe8(cXa9  
{ 2/c^3[ccR  
%;r0,lN|II  
this.parameter = parameter; ^U`Bj*"2  
6?3f+=e"~!  
} ,L"1Ah  
1%nE  
)lo;y~ o  
注意:如果你的属性名为id,而且你的tag处理类是从TagSupport类继承的,那你就不需要定义它的属性和set和get方法,因为他们早已在TagSupport被定义过了。 @,Iyn<v{B  
wewYlm5@  
Attribute元素 w)hH8jx{  
fgW>U*.ar  
对于tag标签的每个属性,你必须定义它是否必须的,它的值是否可以用诸如<%= …%>的表达式来获得,以及它的类型(可选),如果不指定它的类型,那就默认为是java.lang.String类型。如果rtexprvalue元素被定义为true或yes,那么在type元素中就定义了attribute的返回类型。 .qcIl)3  
o"Dk`L2  
<attribute>  jx3J$5  
:|\{mo1NB  
<name>attr1</name> V u/{Hr  
#xMl<  
<required>true|false|yes|no</required> SGd[cA Ko  
O{^ET:K@  
<rtexprvalue>true|false|yes|no</rtexprvalue> #]iSh(|8  
'V=i;2mB*  
<type>attribute的返回类型(只用当rtexprvalue为真是才有效)</type> bk-veJR  
;w/|5 ;{A;  
</attribute> MrW#~S|ED  
"lFS{7  
如果tag的某个属性不是必须的,那tag处理类会自动提供一个缺省值。 r{V=)h  
5ir[}I^z  
例如,在logic:present这个tag标签中定义了一个属性叫parameter,但它不是必须的,而且它可以被诸如<%= …%>的表达式来赋值。 f8T6(cA  
|bwz  
<tag> ^*{:;F@  
LovVJ^TD0i  
<name>present</name> V6:S<A  
Y~P1r]piB  
<tag-class>org.apache.struts.taglib.logic.PresentTag</tag-class> < ] ~FX 25  
s7A3CY]->  
<body-content>JSP</body-content> }, < dGmkx  
x.+r.cAXH  
6%hr]>L  
(9#$za>  
<attribute> m5wfQ_}}ss  
aDV~T24  
<name>parameter</name> *Vbf ;=Mb  
>tmv3_<=  
<required>false</required> 59Lv/Mfy  
k$kOp *X  
<rtexprvalue>true</rtexprvalue> ^ZxT0oaL  
e ej:  
</attribute> LFzL{rny!U  
")'9:c  
i#&iT P`  
\gBsAZE  
</tag> g[D(]t\#x  
EO&PabZWR  
X]Aobtz  
属性元素的校验 Io|3zE*<  
P}2i[m.*,  
I%^Bl:M  
有关于tag标签的有效值可以从tag库的说明文档中获得,当JSP页面被编译时,jsp引擎会强制性地参照TLD中定义的规则进行检查。 G^G= .9O  
p;y\%i_  
还有一个方法也可以进行属性元素的校验,就是先继承类TagExtraInfo,然后调用它的isValid方法。这个类同时也起到提供tag中定义的脚本变量信息的作用。 \E(Negt7  
9J*M~gKbz  
IsValid方法通过TagData对象来传递属性信息,它包括着tag的所有的属性名-值的信息。由于校验发生在运行时刻,因此这个属性的值将被赋值为TagData.REQUEST_TIME_VALUE。 $s2Y,0>I6  
>@Nn_d  
例如tag标签<tt:twa attr1=”value1” />在TLD中定义如下: ^^9O9]  
$ $=N'Q  
<attribute> DOsQVdH  
F*}.0SQ  
<name>attr1</name> TFQX}kr]  
\>DMN #  
<required>true</required> 0r=KY@D  
n$*e(  
<rtexprvalue>true</rtexprvalue> \CY_nn|&g  
fEWXC|"  
</attribute> U.$7=Zl8t  
kBRy(?Mft&  
?2q;`Nb  
这个定义说明了attr1能在运行期间被赋值。 6>X9|w  
R0WI s:k2  
以下的isValid方法检查attr1属性的值是否属于Boolean类型。注意由于attr1能在运行刻被赋值,那么isValid方法必须检查tag用户是否对此tag进行了运行时刻赋值。 ?o D]J  
1ti9FQ  
;8~tt I  
Public class TwaTEI extends TagExtraInfo Vx~N`|yY  
Fk-}2_=v i  
{ RBA{!  
l0v]+>1i:  
public boolean isValid(Tagdata data) zrazbHI  
G-DvM6T  
{ IyV%tOy  
q-3e^-S*  
Object o = data.getAttribute(“attr1”); !eC]=PoY  
"!AbH<M;@  
If(o != null && o != TagData.REQUEST_TIME_VALUE) 'QP~uK  
zm&?G  
{ (2l?~CaK  
YQ`m;<  
if( ( (String)o).toLowerCase().equals(“true”) || `{B<|W$=  
`J26Y"]P  
((String)o).toLowerCase().equals(“false”) ) *#| lhf'  
6p}dl>T_y  
return true; :~ ; 48m  
p%]ZG,  
else gz~)v\5D/  
l2S1?*  
return false; q=J8SvSRl  
Q2 S!}A  
} )/Mk\``j  
5i eF8F%  
else o6@`aU  
Yo^9Y@WDW  
return true; ? JliKFD%  
R/|2s  
} i uGly~  
@krh<T6|  
} t91z<Y|  
xfFsW^w  
U~l.%mui  
带body的tag $;Nw_S@  
X[;-SXq  
J^xIfV~ zt  
tag处理类 #sJL"GB  
l(j._j~p  
Mf_urbp]  
如果tag标签含有内容,那处理方式会略微有些不同,而且还要视tag处理类是否要与body交互的情况而定。如果要与body交互,那我们认为tag处理类要可能要对body进行操作。 62Q`&n6  
:vWixgLg  
Tag处理类不与body交互 Y2&hf6BE  
EA=EcUf'  
如果tag处理类不与body交互,tag处理类应该实现Tag接口或从TagSupport中派生,如果body要被计算,那么doStartTag方法应返回 EVAL_BODY_INCLUDE,否则应返回SKIP_BODY。 6EY W:o  
'1NZSiv+C?  
如果tag处理类要对body反复运算,则它应该实现IterationTag或从TagSupport中派生。如果tag处理类认为body还未计算完的话,那它的doStartTag方法和doAfterBody方法必须返回EVAL_BODY_AGAIN。 4Mr)~f rc  
s^lm 81;  
Tag处理类与body交互 e{k)]]J  
CeD(!1V G  
如果tag处理类与body交互,那tag处理类应实现BodyTag接口或从BodyTagSupport中派生。这种tag处理类一般要实现doInitBody和doAfterBody方法。 V =-hqo(  
#}8 x  
Body允许一些方法来读写它的内容。Tag处理类可以调用body内容的getString或getReader方法来从body中提取信息,也可用 writeOut(out) 方法来将body的内容写入到out对象中。其中out对象通过tag处理类的getPreviousOut方法来获得。 8;+dlWp  
yE=tuHv(0  
如果body的内容需要被计算,那么doStartTag方法必须返回EVAL_BODY_BUFFERED,否则,它将返回 SKIP_BODY。 0m>?-/uDx  
p/4}SU  
doInitBody 方法 FXO{i:Zo  
JM>4m)h#  
此方法在body内容已经设好,但未被计算之前被调用。你可以根据不同的body内容来制定初始化策略。 @S#Ls="G  
.J fV4!=o  
doAfterBody方法 9|5>?'CqP  
=+>^:3cCQ  
此方法在body内容已被计算后进行调用。 g(-}M`  
Fb^f`UI  
和doStartTag方法一样,doAfterBody方法返回一个指示符指示是否要继续计算body,如果要继续计算,则doAfterBody应返回EVAL_BODY_BUFFERED,否则,它应返回SKIP_BODY。 $geDB~ 2>  
m`B .3  
release 方法 je`w$ ^w  
c8}jO=/5+  
tag处理类调用此方法将它的状态重置为初始状态,并释放所有的私有资源。 ?<h|Q~JH  
0?/vcsO  
.~jn N  
以下的例子读取body的内容(其中含有一条sql语句),然后将它传递给一个对象,让它进行查询。由于此处body不须重新计算,所以doAfterBody会返回SKIP_BODY。 -5.~POO  
s3+6Z~g'B  
&8'QD~  
Public class QueryTag extends BodyTagSupport c,FhI~>R  
_ H$^m#h  
{ h$#zuqm  
YM4njkI7  
public int doAfterBody() throws JspTagException y_A7CG"^  
V(6GM+  
{ rwCjNky!  
vm4q1!!(  
BodyContent bc = getBodyContent(); 6"PwOEt  
4M3{P  
//将body的内容以字符串的格式提取出来 X0+M|8:   
kf>L  
String query = bc.getString(); C Y K W4  
&Rxy]kBA  
//清除body |C_sP,W  
= }6l.9  
bc.clearBody(); /'WVRa  
+:m'a5Dm  
try{ ;VI W/  
oNa*|CSE>  
Statement stmt = connection.createStatement(); p&<X&D   
8j%hxAV$  
Result result = stmt.executeQuery(query); `|d&ta[{  
aVbv.>  
}catch(SQLException e){ DX)T}V&mP  
=h/0k y  
throw new JspTagException(“queryTag: “ + e.getMessage() ); \5=fC9*G  
53jtwklA  
return SKIP_BODY; `Q~`Eq?@  
a eo/4  
} "i3Q)$"S  
0"O22<K3a  
} r -SQk>Y}  
' *x?8-KP  
XkJzt  
body-content元素 ~.'NG? %7P  
oN/T>&d  
jf'#2-   
由于tag可能会有body,你必须用body-content元素来指定body内容的类型: _O*"_^6  
ob3Z I  
<body-content>JSP|tagdependent</body-content> U3zwC5}BN  
K;}h u(*\]  
I%q&4L7pj  
如果body的内容是定制的或内部的tag、脚本元素、或HTML广本,则归类为JSP类型。其他的类型,比如上面代码所述的?D?D将sql statement类传给 query tag的这种类型应该标为tagdependent。 v4V|j<R  
k2S6 SB  
注意:实际上body-content的值并不影响tag处理类对body内容的处理,它仅仅是被tag编辑工具用来描述此body的内容。 oztfr<cUH  
E*_lT`Hzf  
WF{rrU:  
用tags定义脚本变量 {V)Z!D  
Tfba3+V  
jSyF]$"  
tag处理类 zXHCP.Rmg  
Uhz<B #tj  
e2 ?7>?  
tag处理类负责创建或设置页面中定义的脚本变量,用pageContext.setAttribute(name,value,scope)或pageContext.setAttribute(name,value)方法来实现。一般来说,tag处理类通过脚本变量的名称来获取它,脚本变量的名称一般可用get方法来获得。  ou[_ y  
X(;,-7Jw  
如果脚本变量的值依赖于tag处理类中的上下文中某一对象,那它可用pageContext.getAttribute(name,scope)方法来找到那个对象。一般的处理过程是tag处理类先找到脚本变量,再对其进行处理,然后用pageContext.setAttribute(name,object)的方法来设置它的新值。 +R_w- NI  
ZxRD+`  
对象的生存周期(scope)如下表: f/:XIG  
k^IC"p Uc  
对象的生存周期表 b6k'`vLA  
Yy"05V.  
名字 TCd1JF0  
可访问范围 ?r,lgaw  
生存周期 Z ?{;|Z5  
N}*|*!6hI  
page mt+IB4`  
当前页面 HZ1e~IIw  
一直有效,除非页面向客户提交响应或重定向到一个新页面 fdD?"z  
YAIDSZ&l[  
request d2x|PpmH  
当前页面或当前页面重定向到的页面 T`;>Kq:s  
一直有效,除非页面向客户提交响应 [kyF|3k~  
tfr*/+F  
session ^]$x/1I;  
当前页面或在同一浏览器窗口中的页面 I]]3=?Y  
一直有效,除非关闭当前浏览器、超时、网络故障 ^fLePsmd  
Ua^'KRSO  
application  pv=g)  
整个web应用程序的所有请求 0wLu*K5$4E  
一直有效,除非发生网络故障、服务器故障 "b!EtlT9  
E0<9NF Qr7  
提供关于脚本变量的信息 >C`b 4xQ  
-$E_L :M  
以下示例定义了一个名为“book”的脚本变量,用来访问程序中关于书的信息: Xz'pZ*Hr$v  
vMiZ:*iaj@  
<bean:define id=”book” name=”bookDB” property=”bookDetails” type=”database.BookDetails” /> 1}C|Javkn  
'*5I5'[ X,  
<font color=”red” size=”+2” > @N,EoSb :  
$/aZ/O)F  
<%= messages.getString(“CartRemoved”) %> 4ey m$UWw  
x?:[:Hf   
<strong><jsp:getProperty name=”book” property=”title” /></strong> t%e}'?#^  
 eU"!X9  
</font> z O  
Tw< N  
当包含此tag的JSP页面被编译时,jsp引擎会自动生成关于此book的同步的代码(同步可以避免几个客户同时访问此book时造成的冲突),要生成同步代码,jsp引擎需要知道此脚本变量的如下信息: 1f]04TI  
dyRKmLb  
· 脚本变量名称 M1^?_;B  
C:/O]slH  
· 脚本变量所属的类 ,~-"EQT  
Wc4F'}s  
· 此脚本变量是否引用了一个新的或已存在的对象 /R&!92I0*  
 u%<Je  
· 此脚本变量的有效性 V]cD^Fqp  
MO+g*N  
有两种办法可以向jsp引擎提供关于脚本变量的信息:在TLD中定义variable子元素,或用tei-class子元素定义一个额外tag信息类。用variable最简单,但可能降低了一些灵活性。 1D03Nbh|5  
Kv'2^B  
Variable元素 .eAN`-t;  
gnW `|-:\  
Variable元素有如下子元素: sr+* q6W  
#5xK&qA  
· name-given ?D?D 给出的名字,是一个常量 |*5Kfxq  
7t7"glP  
· name-from-attribute?D?D 属性名,在编译时给出的属性名 ^uIP   
4k5X'&Q  
name-given或name-from-attribute两者必须选一,但以下子元素是可选的: f"zXiUV  
GsG.9nd  
· variable-class?D?D变量的类型,缺省为java.lang.String。 _5(lp} s  
:c@v_J6C&  
· declare?D?D此脚本变量是否引用了一个新对象,缺省为True。 +jePp_3$O  
XBE+O7  
· scope?D?D脚本变量的范围,缺省为NESTED。下表描述了scope的几种类型: ld8E!t[  
`9BZ))Pg  
脚本变量的有效范围 7U> Xi'?  
nFU'DZ  
QFMR~6 ?  
有效性 W 86`R  
方法 j+He8w-4  
~0"(C#l 9  
NESTED S)T]>Ash  
在tag标签的开始和结束之间 P(BjXMd  
如果tag处理类实现BodyTag接口,则在doInitBody和doAfterBody中调用,否则在doStartTag中调用 Umx~!YL!  
5+*MqO>  
AT_BEGIN f8yE>qJP  
从tag标签的开始一直到页面结束 7\>P@s  
如果tag处理类实现BodyTag接口,则在doInitBody、doAfterBody和doEndTag中调用,否则在doStartTag和doEndTag中调用 r(;sX  
[IT*>;b+?  
AT_END v?e@`;- <  
从tag标签的结束一直到页面结束 84v7g`lrR  
在doEndTag中调用 p4QQ5O$;  
N `-\'h  
以struts为例,它的bean:define标签的实现遵循JSP1.1规范,此规范要求使用额外tag信息类来定义脚本变量。Variable元素是JSP1.2规范中加入的。以bean:define标签为例,你可以定义如下variable元素: 'B dZN  
bBwQ1,c$  
<tag> ~d]X@(G&  
{;uOc{~+  
<variable> Bx9R!u5D  
{~J'J$hn8  
<name-from-attribute>id</name-from-attribute> GCaiogiBg  
d:C|laZHn  
<variable-class>database.BookDetails</variable-class> iNj*G j  
~6YTm6o  
<declare>true</declare> oYOR%'0*m+  
jeb ]3i=pw  
<scope>AT_BEGIN</scope> Jbv66)0M  
X{cFq W7  
</variable> $*N^ bj  
mX8k4$z  
</tag> .nDB{@#  
r<< ]41  
额外tag信息类 =PU! hZj"L  
in}d(%3h  
如果要定义一个额外tag信息类,你要继承javax.servlet.jsp.TagExtraInfo类。一个TagExtraInfo类必须实现getVariableInfo方法,此方法返回一个叫VariableInfo的数组类,它包括如下信息: /e|vz^#+1,  
w[ )97d  
· 变量名 "[A]tklP  
90g=&O5@O  
· 变量所属类名 imb.CYS74  
Fpe>|"&  
· 此变量是否引用了一个新对象 K qK?w*Qw  
2bIP.M2Fs  
· 此变量的有效范围 >|j8j:S[  
t UOqF  
jsp引擎将一个名为data的参数传给getVariableInfo方法,data中包括tag标签中的所有“属性名?D?D属性值”对。它可以用来向VariableInfo对象提供脚本变量的名字和类名。 K=Q<G:+&V  
-/^a2_d[  
以struts为例,它在bean:define标签中定义了一个名为DefineTei的额外tag信息类,用来向脚本变量提供信息。由于脚本变量的名称(book)和类名(database.BookDetails)是通过tag标签的属性来传递的,它们一般定义在VariableInfo的构建代码中,并且可用data.getAttributeString方法来得到这些信息。如果要允许book脚本变量能在从tag开始直到整个JSP页面结束的范围内都可用的话,那它的范围应设为AT_BEGIN。如下所示: i&K-|[3{g  
%?2:1o  
eMT}"u8$A  
public class DefineTei extends TagExtraInfo YCBp ]xuE  
6KH&-ffd  
{ ;@5N  
dd?ZQ:n  
public VariableInfo[] getVariableInfo(TagData data) U5[,UrC  
"}|&eBH^<  
{ mFk6a{+YX  
[hhPkJf|f  
String type = data.getAttributeString(“type”); %"yy8~|  
`8x.Mv  
If( type == null) Nbyc,a[o  
v35!? 5{  
type = “java.lang.Object”; [B_(,/?  
E]MyP=g$  
return new VariableInfo[] { l|jb}9(J  
;NoD4*  
new VariableInfo(data.getAttributeString(“id”), KtMD?  
]r&dWF  
type, U L3++bt  
n/ m7+=]v  
true, nqv#?>Z^OT  
Z*Lv!6WS  
VariableInfo.AT_BEGIN) {Gi:W/jJ  
$`'%1;y@  
};  \LP?,<  
lm[LDtc  
} u^X,ASkQ  
 \X]  
} j0(+Kq:J  
|+h8g@;Z  
<8sy*A?0z  
注意:关于额外tag信息类的类名必须要在TLD中的tag标签下的tei-class子元素中定义。因此,DefineTei的tei-class中的定义看起来如下: wK*b2r}0/  
<tei-class> ;=i$0w9W  
org.apache.struts.taglib.bean.DefineTagTei @\)a&p]a  
</tei-class> {0J (=\u  
6$'0^Ftm'  
{!av3Pz\  
具有协作关系的tag JANP_b:t  
O8<@+xlX  
!fT3mI6u\  
tag通过共享对象来进行协作,JSP技术支持2种方式的对象共享。 4+2hj*I  
 1k39KO@  
第一种方法是使用pageContext对象进行对象的共享(可支持JSP页面和tag处理类之间的共享),如果在一个tag处理类中要调用由另一个tag处理类创建的对象,可调用pageContext.getAttribute(name, scope)方法。 LQ'VhNU  
fs3jPHZJ#  
第二各方式的共享是对于tag之间有嵌套关系而言的,外层的tag所创建的对象对于内层的tag来说是可以共用的。这种形式的共享的好处是减少了可能存在的重名冲突。 ;Y@"!\t}  
Ynx.$$`$=  
要访问一个嵌套tag创建的对象,tag处理类必须先找到此嵌套tag对象,可用TagSupport的静态方法 TagSupport.findAncestorWithClass(from, class)或TagSupport.getParent方法。前者在当不确定此tag是否为嵌套tag对象时使用。一旦它的父类被找到,它就能访问其所有动态或静态创建的对象。静态创建的对象是父类的成员,而动态创建的对象可能是父类的私有对象。诸如此类的对象可以用tag处理类的setValue方法来保存,用getValue方法来获得。 a";xG,U  
A6AIkKjzq  
下例阐述了以上两种共享对象的方法。在这个例子当中,一个查询tag检查一个名为connection的属性名是否在doStartTag中被设置。如果connection属性被设置,tag处理类从pageContext中得到这个connection对象。否则,此tag处理类先找到它的父tag处理类,然后从它的父tag处理类中找到connection对象。 bqI| wGCA"  
>XomjU[srQ  
O ]Stf7]%;  
public class QueryTag extends BodyTagSupport $@}\T  
5;yVA  
{ /sa\Ze;E  
=2tl149m/z  
private String connectionId; jb {5   
$ 8WJ$73  
public int doStartTag() throws JspException :d`8:gv?  
d\ {a&\v  
{ 99mo]1_  
otSF8[  
String cid = getConnection(); lk. ;  
c:f++||  
if(cid != null) |@lVFEl]  
d*(wU>J '  
{ eF%IX  
5^GFN*poig  
//存在一个connection id,使用它。 n?z^"vv$i  
,`nl";Zc  
connection = (Connection) pageContext.getAttribute(cid); C~([aH@-I  
wG2-,\:  
} AYLCdCoK.  
QnPgp(d <  
else @[] A&)B  
GP._C=]?c  
{ k w]m7 T  
5q>u]n9]  
ConnectionTag ancestorTag = (ConnectionTag)findAncestorWithClass(this, 2`]_c=  
i[M]d`<36  
ConnectionTag.class); y9'F D5\s  
kn1+lF@  
if(ancestorTag == null) DJ#z0)3<p  
VtJy0OGcRP  
{ JHCV7$RS  
( O>oN~  
throw new JspTagException(“一个没有connection属性的查询标签必须被一个connection标记嵌套。”); {Q@pF  
QW_QizR>|  
} 7h3JH  
bAl0z)p  
connection = ancestorTag.getConnection(); NA`EG,2  
Y><")%Q  
} /|. |y S9  
9&t!U+  
} .Iret :  
;*8nd-\  
} l .wf= /  
Gr a(DGX  
^"Nsb&  
V^^nJs tV  
此查询标签在JSP页面中的调用形式可以从以下2种定义中任选一种: LpJ_HU7@lk  
m#oZu {  
Hx]{'?   
<tt:connection id=”con01” ...> ... </tt:connection> ?-e'gC  
9u\&kQxqD  
<tt:query id=”balances” connection=”con01” > =>7\s}QZ  
yfD)|lK  
SELECT account, balance FROM acct_table [Bz'c1  
 xedbr  
where customer_num = <%= request.getCustno() %> Y=6b oT  
}Pj3O~z  
</tt:query> Cl+TjmOV\`  
]GS@ub  
X[cSmkp7  
1Jx|0YmO  
V %cU @  
<tt:connection ...> Bi +a)_K  
Odo"S;)  
<x:query id=”balances”> 3t4_{']:/  
mmVx',k  
SELECT account, balance FROM acct_table _S(]/d(c  
Q.Kr;64G  
where customer_num = <%= request.getCustno() %> s)e; c<(/  
wghz[qe  
</x:query> Q1Jkt  
"5-S:+  
</tt:connection> ve #cz2Z  
w:z@!<  
!S/hH%C  
与此同时,在TLD中必须指定connection属性为可选的,定义如下: l_!.yV{  
J]f\=;z;<a  
<tag> R; X8%'   
G~{xTpL  
... o%Lk6QA$  
bT@7&  
<attribute> dJ#. m  
eXaa'bTx  
<name>connection</name> / 4K*iq  
#lax0IYY=  
<required>false</required> >8 V;:(nt  
F*QD\sG:  
</attribute> yT42u|xZA  
#4{f2s[j6  
</tag>
描述
快速回复

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