社区应用 最新帖子 精华区 社区服务 会员列表 统计排行 社区论坛任务 迷你宠物
  • 3287阅读
  • 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'!2  
_Kl_61k  
一般来说,自定义tag标签主要用于操作隐藏对象、处理html提交表单、访问数据库或其它企业级的服务,诸如邮件和目录操作等等。自定义tag标签的使用者一般都是那些对java编程语言非常精通,而且对数据访问和企业级服务访问都非常熟悉的程序员,对于HTML设计者来说,使得他可以不去关注那些较复杂的商业逻辑,而将精力放在网页设计上。同时,它也将库开发者和库使用者进行合理分工,自定义tag标签将那些重复工作进行封装,从而大大提高了生产力,而且可以使得tag库可用于不同的项目中,完美地体现了软件复用的思想。 gG<~-8uQ  
VVac:  
在这篇文章中,我们主要讨论: 49GkPy#]L=  
D$ dfNiCH  
· 什么是自定义tag标签? 6jE |  
B +\3-q  
· 怎么使用tag标签? s4A43i'g!h  
;oW6 NJ  
o 声明要使用的tag库  M+||rct  
I*{4rDt  
o 找到与之对应的tag处理类 \2N!:%k  
*|%@6I(  
o tag标签的类型 x@P y>f2  
?Y-%'J(  
· 自定义tag标签 Cl; oi}L  
-JMdE_h  
o tag处理类 LClNxm2X  
y"bByd|6  
o tag库描述 .7e2YI,S  
'\Giv!>  
o tag标签示例 F U_jGwD  
*6sl   
o 带属性的tag s.bc>E0  
'&x#rjo#  
o 带body的tag 1"zDin!A  
&]"  
o 定义了脚本变量的tag 2|3)S`WZl  
Sg&UagBj  
o 具有协作关系的tag 2D75:@JL}|  
qkt0**\  
· 自定义tag标签 K&POyOvT  
6IBgt!=,  
o 一个迭代tag的例子 jF ^~p9z  
LPZF)@|`  
o 一个模板tag库 e<3K;Q  
Aw}"gpL  
o tag处理类到底是怎样被调用的? >zw.GwN|  
S>h;K`  
3LAIl913  
什么是自定义的tag? >.Chl$)<  
ve MH  
一个自定义的tag标签是用户定义的一种JSP标记。当一个含有自定义的tag标签的JSP页面被jsp引擎编译成servlet时,tag标签被转化成了对一个称为tag处理类的对象进行的操作。于是当JSP页面被jsp引擎转化为servlet后,实际上tag标签被转化成为了对tag处理类的操作。 rSZd!OQ  
7E!IF>`  
自定义tag标签有很多特色,诸如: 13=A  
F<n3  
· 可以在JSP页面中自定义tag标签的属性 p`b"-[93  
gp5_Z-me  
· 访问JSP页面中的所有对象 uD\?(LM  
<Wfx+F  
· 可以动态地修改页面输出 XRcqhv  
%SX|o-B~.o  
· 彼此这间可以相互通信。你可以先创建一个JavaBeans组件,然后在一个tag中调用此JavaBeans组件,同时可以在另一个tag中调用它。 \]</w5 Pi,  
0 t Fkd  
· tag允许相互嵌套,可以在一个JSP页面中完成一些复杂的交互。 !k 6K?xt  
r"C  
#yI mKEYX  
使用tag标签 hlV=qfc  
K~AR*1??[  
Kf>A\l^X7  
本节主要描述怎样在JSP页面中使用tag标签,以及tag标签的不同类型。 -wp|RD,}(  
k_sg ?(-!o  
要使用tag标签,JSP程序员必须做2件事: @JtM5qB  
w1hPc!I  
· 声明此tag标签的tag库 XlV0*}S  
tmv&U;0Z  
· 实现此tag标签 rm5bkJcg~  
O #F   
声明tag标签所在的tag库 =T -&j60  
JG" R\2  
如果要使用tag标签,则应用JSP的taglib指示符来指定其tag库(注意:taglib要在在使用此tag标签之前声明) ukIQr/k  
>OL3H$F  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> isQ[ Gc!8  
aNScF  
uri属性定义了唯一的标签库描述(以下简称TLD),它可以是直接是tld文件名或一个独一无二的名字。prefix是用来区别其它TLD中和本TLD中有重名的tag的一种手段。 tasIDoo+!J  
ur3(HL  
TLD必须以.tld作为扩展名,并且存放在当前应用的WEB-INF目录或其子目录下。你可以通过它的文件名直接引用它,也可以通过别的方式间接地引用它。 )Hpa}FGT  
]ro*G"-_1#  
以下taglib指示符直接引用一个TLD: uEktQ_u[  
_oHNkKQ  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> 6{"$nF]  
o<[#0T^K   
以下的taglib指示符通过一个逻辑名称间接地引用一个TLD: R$ q; !  
{l>yi  
<%@ taglib uri=”/tutorial-template” prefix=”tt” %> { vKLAxc  
T?x[C4wf+  
如果是间接引用TLD的话,那你必须还要在web.xml中定义此逻辑名称与tld文件之间的映射,具体做法是在web.xml中加入一个名为taglib的元素: mzeY%A<0^  
I,0q4  
<taglib> ^5H >pat  
"Q!(52_@J  
<taglib-uri>/tutorial-template</taglib-uri> $"FQj4%d  
AfX}y+Ah  
<taglib-location> S<VSn}vn  
{4G%:09~J  
/WEB-INF/tutorial-template.tld eM$sv9?  
fDT%!  
</taglib-location> v*r7Zz6l  
x c/}#>ED  
</taglib> $}) g?Q  
vr6MU<  
>33=<~#n  
实现此tag标签 (#Wu# F1;  
KVT-P};jy*  
$6mX  
为了实现tag标签,你有2种方法来存放tag处理类。一、让tag处理类以.class的方式存放于当前应用的WEB-INF/class子目录下,二、如果tag处理类是以JAR包的形式存在的话,那可以放在当前应用的WEB-INF/lib目录下,如果tag处理类要在多个应用中共享,那么它就应放在jsp服务器上的common/lib目录下,对于tomcat来说,就是tomcat/common/lib目录下。 Hkwl>R$  
)TVFtI=,NN  
Y8m1M-#w  
tag标签类型 iPd[l {85Z  
~\Hc,5G  
;$smH=I  
自定义的tag标签遵循XML语法。它有一个开始标记和一个结束标记,有的还有body(即文本节点): M}yDXJx  
)(ImLbM)  
<tt:tag> w8MG(Lq1"  
y~q8pH1  
body x4E7X_  
D|e uX7b  
</tt:tag> /J=v]<87a  
f"%{%M$K  
Dp)=0<$y  
一个不带body的tag标签如下: :cF[(i/k4  
9{ >Ui  
<tt:tag /> gP0LCK>  
%= fHu+  
gk"$,\DI  
简单的tag标签 G+X Sfr  
m 8aITd8  
一个没有body和属性的tag标签如下: `< xn8h9p  
mt,OniU=Q  
<tt:simple /> _V7r1fY:  
]sE?ezu  
>`A9[`$n  
带属性的tag标签 ;#vKi0V7  
Y8-86 *zC  
TU:7Df  
自定义标签可以有自己的属性。属性一般在开始标记中定义,语法为 attr=”value”。属性的作用相当于自定义标签的一个参数,它影响着tag处理类的行为。你可以在TLD中详细定义它。 ,*7 (%k^`  
^/\Of{OZ-  
你可以用一个String常量给一个属性赋值,也可以通过表达式给它赋值,如<%= ...%>。以struts为例,它的logic:present标签就是用的String常量来给属性赋值: p<,*3huj  
#a'Ex=%rM  
<loglic:present parameter = “Clear”> r76J N  
q|!-0B @  
而另一个标签logic:iterate是用表达式来给属性赋值: ZWc]$H?  
eHn7iuS8  
<logci:iterate collection=”<%= bookDB.getBooks() %>” $}>+kHoT{  
G(p`1~xm  
id=”book” type=”database.BookDetails”> ms*(9l.hOK  
&#!4XOyB  
Mxyb5h  
带body的tag标签 G9xmmc  
W4pL ,(S  
一个自定义标签可以包含其它自定义标签、脚本变量、HTML标记或其它内容。 NQ(1   
^c^#dpn  
在下述例子中,此JSP页面使用了struts的logic:present标签,如果些标签定义了parameter=”Clear”的属性,则将清除购物车的内容,然后打印出一条信息: }o(zj=7  
6{n!Cb[e  
<logic:present parameter=”Clear”> i rU 6D  
vms|x wb  
<% cart.clear(); %> {^CY..3 A  
mH%yGBp_  
<font color=”#ff0000” size=”+2”><strong> M>~Drul  
5nT"rA  
你选择了清除购物车! pWK(z[D  
*h!28Ya(~  
</strong></font> r'^Hg/Jzt  
\;qW 3~  
</logic:present> eJxw) zd7  
$c]fPt"i  
fGUE<l  
到底是用属性还是用body来传递信息? VH9dleZ  
H*ow\ Ct  
如上所述,我们既可以通过属性,也可以通过body来传递信息。但一般来说,比较简单的类型,如字符串或简单表达式最好采用属性来传递信息。 fVF2-Rh=  
/67 h&j  
NdMb)l)m  
定义脚本变量的tag标签 `Aw^H!  
-I8=T]_D  
所谓脚本变量,是指JSP中可以调用的变量或对象。它可由tag标签产生。以下示例阐述了一个tag标签定义了一个名为tx的由JNDI所定义的事务处理对象。脚本变量可以是ejb对象、事务、数据库连接等等: QEz? w}b*  
C-Q28lD}f  
<tt:lookup id=”tx” type=”UserTransaction” name=”java:comp/UserTransaction” /> AK'[c+2[  
oB}BU`-l  
<% tx.begin(); %> N5Q[nd  
kW;+|qs^  
... ii T"5`KY  
,}3 'I [  
'[AlhBX  
具有协作关系的tag标签 R3x3]]D  
w65K[l;2  
自定义tag标签之间可以通过共享对象来实现协作。在下述例子中,标签tag1创建了一个名为obj1的对象,在标签tag2仍可以重复使用obj。 >AVVEv18  
?}wk.gt>  
<tt:tag1 attr1=”obj1” value1=”value” /> 0 ?s|i :  
[<n2Uz7MP  
<tt:tag2 attr1=”obj1” /> 1eS&&J5  
b*a#<K$T_  
在以下这个例子当中,如果外层的tag标签创建了一个对象,那么其内层的所有tag标签都可以使用这个对象。由于这样产生的对象没有一个指定的名字,那么就可以将少重名的冲突。这个例子阐述了一系列协作的嵌套对象。 A)bWcB}U  
Q# ~Q=T'<  
<tt:outerTag> q!.byrod  
zr-*$1eu  
<tt:innerTag /> -`'I{g&A  
VCV"S>aVf  
</tt:outerTag> J\+0[~~  
ns9U/ :L  
g%sluT[#  
Tag处理类 I(i}c~ R  
.B7,j%1r  
n6wV.?8  
Tag处理类必须实现Tag接口或BodyTag接口,不过现在一般都流行从TagSupport或BodyTagSupport类中继承,这些类或接口都可以在javax.servlet.jsp.tagext包中找到。 ;rF\kX&Jh  
B,?T%  
当JSP引擎看到自己的JSP页面中包含有tag标签时,它会调用doStartTag方法来处理tag标签的开头,调用doEndTag方法来处理tag标签的结束。 vx>b^tJKC  
) pzy  
下表说明不同类型的tag所需要不同的处理过程: [4YTDEv%  
,)0H3t  
Tag处理类的方法 Px4) >/ z,  
gZN8!#h}B  
Tag标签类型 ]OM"ZG/^  
所调用的方法 `#rL*;\uV  
8[a=OP  
基本标签 ] ] !VK  
doStartTag, doEndTag, release |?!~{-o  
nr95YSH  
带属性的标签 n`#tKwWHYx  
doStartTag, doEndTag, set/getAttribute1...N, release 3k\#CiB{  
_dqzB$JV  
带内容的标签 Xnt~]k\"  
doStartTag, doEndTag, release IbT=8l,Li  
vmU@^2JSJ  
带内容的标签,且内容重复循环 DVG(V w  
doStartTag, doAfterBody, doEndTag, release ?qP7Y nl  
y^;#&k!  
带内容的标签,且内容与JSP交互 }u\])I3  
doStartTag, doEndTag, release, doInitBody, doAfterBody, release SON-Z"v  
y`VyQWW  
一个tag处理类可以通过javax.servlet.jsp.PageContext来与JSP交互,通过javax.servlet.jsp.PageContext类,tag处理类可以访问JSP中的request、session和application对像。 p)jk>j B  
T5R-B=YWu  
如果tag标签是互相嵌套的,那内层的tag处理类可以通过它的parent属性来访问上层的tag处理类。 ?Y$JWEPJ  
eX?OYDDC0j  
一般情况都将所有的tag处理类打成了JAR的包,以便于发布。 )Lk639r  
:G [|CPm-  
Vp#JS3Y  
Tag库描述(简称TLD) lsJSYJG&  
dz:E?  
-?H#LUk  
Tag库是用xml语言描述的,TLD包括了tag库中所有tag标签的描述,它一般用来被jsp服务器用来校验tag的语法正确性,或者被jsp开发者用来开发新的标签。 s(5Y  
_Us#\+]_:  
TLD的文件扩展名必须为.tld,而且必须放在当前WEB应用的WEB-INF目录或其子目录中。 .~)q};Z  
8LyD7P 1\  
一个TLD的内容的开头必须遵守标准的XML开头,用于描述DTD和xml的版本,例如: }{,^@xdyW  
u#Pa7_zBj]  
<?xml version="1.0" encoding="ISO-8859-1" ?> F5LuSy+v  
1Lc#m`Jln  
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd"> (iBNZ7sJ  
TLD必须以<taglib>来作为它的根元素,<taglib>的子元素如下表: `n.5f[wC  
~d o9;8v  
o@r7 n>G  
<taglib>的子元素 1A?W:'N  
dV*]f$wQ  
Element /1Qr#OJ(]  
Description O%Scjm-^X  
v6[!o<@"a  
tlib-version zbXI%  
Tag库的版本 zE336  
nii A7Ux  
jsp-version 0m7Y>0wC6T  
Tag库所需要的jsp的版本 >] qc-{>&  
%G3h?3  
short-name q VjdOY:z  
助记符,tag的一个别名(可选) fsmN)_T  
dl.N.P7}4  
uri $CxKuB(  
用于确定一个唯一的tag库 %OtFHhb  
,oORW/0iS  
display-name CHdX;'`*  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) 00<cYy  
&qLf@1AD  
small-icon f"B3,6m  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) >lmi@UN|k  
#&cI3i  
large-icon n?oW< &  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) D_?K"E=fw  
"C?#SO B  
description x"eRJii?  
对tag库的描述(可选) cO-7ke  
zuP B6W^  
listener *zNYZ#  
参见下面listener元素 d]`CxI]  
Y4%:7mw~=  
tag v.\*./-i  
参见下面tag 元素 Dw|}9;5:A  
`+`Z7  
Listener元素 9*$t!r{B@  
TH)"wNa  
一个tag库可能定义一些类做为它的事件侦听类,这些类在TLD中被称为listener 元素,jsp服务器将会实例化这些侦听类,并且注册它们。Listener元素中有一个叫listener-class的子元素,这个元素的值必须是该侦听类的完整类名。 909?_ v  
J%8(kWQ|  
Tag元素 bf0+DvIB  
YW-usvl&  
每个tag元素在tag库中都要指出它的名字、类名、脚本变量、tag的属性。其中脚本变量的值可以直接在TLD中定义或通过tag附加信息的类来取得。每个属性描述了这个属性是否可以省略,它的值是否可以通过<%= …%>这样的JSP语法来获得,以及属性的类型。 JgG$?n\  
=6xrfDbN8  
每一个tag在TLD中对应一个tag元素,下表是tag元素的子元素: R|JC1f8P5  
&9/O!3p)  
Tag元素的子元素 S(QpM.9*  
vVj  
元素名称 :s=NUw_^  
描述 832v"k CD  
85lCj-cs  
name $GYm6x\4  
独一无二的元素名 Rn#KfI:{  
+nUy,S?43  
tag-class ckV`OaRw4  
Tag标签对应的tag处理类 @HT% n  
hZ[E7=NTQ^  
tei-class Z,`iO %W  
javax.servlet.jsp.tagext.TagExtraInfo的子类,用于表达脚本变量(可选) ,_|]Ufr!a  
uB |Ss  
body-content s~X+*@.  
Tag标签body的类型 Tfh 2.  
jQk*8   
display-name )64@2 ~4y  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) #u2J;9P  
;V^ 112|C  
small-icon A01AlK_B  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) I[b}4M6E  
'[J<=2&  
large-icon Pa(^}n|  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) lW<PoT  
r~+\ Y"rM  
description . 7zK@6i  
此tag标签的描述 kR]!Vr*yh  
&P.4(1sC  
variable j lp:lX  
提供脚本变量的信息(同tei-class)(可选) np%\&CVhN  
(&&4J{`W9  
attribute p7);uF^O%  
Tag标签的属性名 BQBeo&n6  
)Y]{HQd  
以下章节介绍对于不同类型的tag,如何具体地实现它们。 u583_k%  
iP@ZM =&wz  
h tx;8:  
简单的tag qud\K+  
[v$0[IuY,  
hOFOO_byzO  
tag处理类 Op"M.]#  
FW) x:2BG  
简单的tag处理类必须实现Tag接口的doStartTag和doEndTag方法。当jsp引擎碰到tag标签的开头时,doStartTag被调用,因为简单的tag没有body,所以此方法将返回 SKIP_BODY。当jsp引擎碰到tag标签的结尾时,doEndTag被调用,如果余下的页面还要被计算,那它将返回EVAL_PAGE,否则将会返回SKIP_PAGE。 ,QC{3i~  
<WjF*x p  
以下是例子:对于标签 <tt:simple /> ,它的tag处理类实现如下: :gerQz4R8  
k4,BNJt'Z  
?I/qE='*  
public SimpleTag extends TagSupport )foq),2  
'7D,m H  
{ 4&xZ]QC)O5  
z^_*&  
public int doStartTag() throws JspException 4 SHU  
Y7#-Fra0W  
{ _ ):d`O e  
F.-R r  
try{ lrWV#`6!+  
S{FROC~1R  
pageContext.getOut().print(“Hello.”); #Y0-BYa^  
uHH/rMV  
}catch(Exception e){ F^N82  
TT50(_8  
throw new JspTagException(“SimpleTag: “ + e.getMessage()); &LF` W  
TpmwD{c[\  
} 1BAgtd$3  
U7!.,kR-  
return SKIP_BODY; _<=S_ <$2  
j<2m,~k`V  
} c1$ngH0  
1z&Ly3  
public int doEndTag() Ubh{!Y  
0dA7pY9  
{ : p{+G  
mNb ?*3\  
return EVAL_PAGE; /n5F(5<  
{K4+6p  
} :8 jhiB)  
hq:&wN 7Q  
} VtzI9CD  
t~E<j+<2B  
7_.11$E=H  
注意:如果tag标签没有内容的话,那必须定义body-content元素为空,例如 Aub]IO~  
UOGuqV-  
<body-content>empty</body-content> 6`0mta Q  
/,MJq#@K  
DUL4noq{  
带属性的tag标签
评价一下你浏览此帖子的感受

精彩

感动

搞笑

开心

愤怒

无聊

灌水
级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
只看该作者 1 发表于: 2007-01-01
tag处理类 CW)Z[<d8  
s-Aw<Q)d  
对于tag标签的每个属性,你必须依照JavaBeans规范来定义其属性,以及get和set方法。以struts的logic:present 标签为例, RP 2_l$  
R g?1-|Tj  
<logic:present parameter=”Clear”> 8>7RxSF  
Fhv2V,nZ<  
与此相应,此tag处理类应有如下方法和定义: '=E3[0W  
^pS+/ZSi^  
2>]a)  
protected String parameter = null; |+:h|UIUQ  
c{>uqPTY  
public String getParameter() "c(Sysl.L  
0l=+$& D  
{ X53mzs  
4"@GNk~e  
return this.parameter; x lsqj`=  
6AvHavA^Y  
} R#n%cXc|  
K7e4_ZGI  
public void setParameter(String parameter) Y7GF$}%UL  
tp:\j@dB  
{ >tG+?Y'{  
? b[n|^wS  
this.parameter = parameter; ,;<RW]r-P  
sBK <zR  
} ]WUC:6x  
T *I?9d{k  
*9 Q^5;y  
注意:如果你的属性名为id,而且你的tag处理类是从TagSupport类继承的,那你就不需要定义它的属性和set和get方法,因为他们早已在TagSupport被定义过了。 [EY`am8[  
nRb^<cZf  
Attribute元素 <e)o1+[w  
a`E*\O'd  
对于tag标签的每个属性,你必须定义它是否必须的,它的值是否可以用诸如<%= …%>的表达式来获得,以及它的类型(可选),如果不指定它的类型,那就默认为是java.lang.String类型。如果rtexprvalue元素被定义为true或yes,那么在type元素中就定义了attribute的返回类型。 _Cy:]2o  
#5&jt@NS  
<attribute> .fzu"XAPu  
kvGCbRC  
<name>attr1</name> 'r} zY-FM`  
3L _I[T$s  
<required>true|false|yes|no</required> ?Pwx~[<1""  
LF?P> 1%-  
<rtexprvalue>true|false|yes|no</rtexprvalue> ~:lKS;PRuK  
o5Y2vmz?9  
<type>attribute的返回类型(只用当rtexprvalue为真是才有效)</type> T#!lPH :&h  
T;\^#1  
</attribute> pi5GxDA]  
0IT@V5Gdj  
如果tag的某个属性不是必须的,那tag处理类会自动提供一个缺省值。 r]P,9  
$ P: O/O=>  
例如,在logic:present这个tag标签中定义了一个属性叫parameter,但它不是必须的,而且它可以被诸如<%= …%>的表达式来赋值。 ukuo:P<a  
Jqr)V2Y  
<tag> bm}6{28R  
~%ozgzr^  
<name>present</name> U>S`k6  
%8)W0WMe  
<tag-class>org.apache.struts.taglib.logic.PresentTag</tag-class> Qn:kz*:  
PzZZ>7_6S  
<body-content>JSP</body-content> XM|%^ry  
i3mAfDF  
2UP,Tgn..  
7S$&S;  
<attribute> PT9v*3Bq~  
R4e&^tI@*  
<name>parameter</name> 8[bkHfI  
DF1<JdO+  
<required>false</required> LS.r%:$mb  
K(T\9J.  
<rtexprvalue>true</rtexprvalue> 'GJVWpvUU  
0{^H]Y  
</attribute> 9l+{OA  
uXQ >WI@eF  
"DSPPE&[c  
WxGSv#u  
</tag> 8 Op.eYe  
59rY[&|  
o%y;(|4t >  
属性元素的校验 V+Xl9v4O  
I<h=Cj[[  
>O]s&34  
有关于tag标签的有效值可以从tag库的说明文档中获得,当JSP页面被编译时,jsp引擎会强制性地参照TLD中定义的规则进行检查。 :a3LS|W  
)%Y IGV;&  
还有一个方法也可以进行属性元素的校验,就是先继承类TagExtraInfo,然后调用它的isValid方法。这个类同时也起到提供tag中定义的脚本变量信息的作用。 Di=9mHC  
beZ(o?uK  
IsValid方法通过TagData对象来传递属性信息,它包括着tag的所有的属性名-值的信息。由于校验发生在运行时刻,因此这个属性的值将被赋值为TagData.REQUEST_TIME_VALUE。 UQd6/mD`e  
O.k \]'  
例如tag标签<tt:twa attr1=”value1” />在TLD中定义如下: zuL7%qyv  
, fb( WY  
<attribute> N dR ]  
r$nkU4N'  
<name>attr1</name> h3Fo-]0  
)QY![&k}1z  
<required>true</required> tSv0" L  
+=c am/A  
<rtexprvalue>true</rtexprvalue> We`'>'W0  
^[-> )  
</attribute> gbOCR1PBg  
\gccQig1CJ  
}fIqH4bp  
这个定义说明了attr1能在运行期间被赋值。 ;vO@m!h}U  
6~5$s1Yc  
以下的isValid方法检查attr1属性的值是否属于Boolean类型。注意由于attr1能在运行刻被赋值,那么isValid方法必须检查tag用户是否对此tag进行了运行时刻赋值。 ARL  
}uX|5&=~f  
kI*UkM-  
Public class TwaTEI extends TagExtraInfo $V8vrT#:  
-!*p*3|03|  
{ Q e1oT)  
#Ws 53mT  
public boolean isValid(Tagdata data) 6E9N(kFYs  
5M?mYNQR/H  
{ A['uD<4b  
y7zkAXhJ  
Object o = data.getAttribute(“attr1”); IG.f=+<0  
6 ,N6jaW  
If(o != null && o != TagData.REQUEST_TIME_VALUE) M%=P)cC  
]TK=>;&  
{ 3n(*E_n  
t]m!ee8*X<  
if( ( (String)o).toLowerCase().equals(“true”) || ]b[,LwB\`~  
TGWdyIk  
((String)o).toLowerCase().equals(“false”) ) (:$9%,x  
EI`vVI  
return true; 3-Y=EH_0  
Sa]Ek*  
else V 4qtaHf  
5RA<Z.  
return false; o+)A'S  
/)1v9<vM"  
} ]XrE  
(zah890//  
else Uu2N9.5  
ha'qIT 3&  
return true; 2uu[52H8d%  
kfpm=dKL  
} bf98B4<  
I]sqi#h$2W  
} 1*R_"#  
1=TSJ2{ 9  
MTB@CP!u  
带body的tag ATO 5  
nGZ \<-  
Ff/Ig]Lb  
tag处理类 r%!FmS<  
D=w9cKa  
9H$g?';  
如果tag标签含有内容,那处理方式会略微有些不同,而且还要视tag处理类是否要与body交互的情况而定。如果要与body交互,那我们认为tag处理类要可能要对body进行操作。 $y6rvQ 2>S  
3bH5C3(u  
Tag处理类不与body交互 7jezw'\=~  
'jbMTI  
如果tag处理类不与body交互,tag处理类应该实现Tag接口或从TagSupport中派生,如果body要被计算,那么doStartTag方法应返回 EVAL_BODY_INCLUDE,否则应返回SKIP_BODY。 G^" H*a  
BD1K H;  
如果tag处理类要对body反复运算,则它应该实现IterationTag或从TagSupport中派生。如果tag处理类认为body还未计算完的话,那它的doStartTag方法和doAfterBody方法必须返回EVAL_BODY_AGAIN。 eJf>"IF-  
, ,{6m d  
Tag处理类与body交互 3LfTGO  
B007x{-L  
如果tag处理类与body交互,那tag处理类应实现BodyTag接口或从BodyTagSupport中派生。这种tag处理类一般要实现doInitBody和doAfterBody方法。 B/u*<k4  
T+W3_xISX  
Body允许一些方法来读写它的内容。Tag处理类可以调用body内容的getString或getReader方法来从body中提取信息,也可用 writeOut(out) 方法来将body的内容写入到out对象中。其中out对象通过tag处理类的getPreviousOut方法来获得。 8on[%Vk  
JFJIls  
如果body的内容需要被计算,那么doStartTag方法必须返回EVAL_BODY_BUFFERED,否则,它将返回 SKIP_BODY。 oQBiPN+v.3  
^fZGX<fH   
doInitBody 方法 D5[VK `4Z  
n `#+L~X  
此方法在body内容已经设好,但未被计算之前被调用。你可以根据不同的body内容来制定初始化策略。 z\h, SX<U  
W8uVd zQ   
doAfterBody方法 %QE5<2k  
8 DL hk  
此方法在body内容已被计算后进行调用。 4^MSX+zt  
^^Bm$9  
和doStartTag方法一样,doAfterBody方法返回一个指示符指示是否要继续计算body,如果要继续计算,则doAfterBody应返回EVAL_BODY_BUFFERED,否则,它应返回SKIP_BODY。 Uf[T_  
F(G<* lA  
release 方法 $:]tcY-L9  
$nc, ?)i!  
tag处理类调用此方法将它的状态重置为初始状态,并释放所有的私有资源。 oYg/*k7EDX  
^(m0M$Wk*  
{*nEKPq(_*  
以下的例子读取body的内容(其中含有一条sql语句),然后将它传递给一个对象,让它进行查询。由于此处body不须重新计算,所以doAfterBody会返回SKIP_BODY。 ~"5C${~{  
 qV?sg  
67ZYtA|t  
Public class QueryTag extends BodyTagSupport v+7*R)/  
hqWPf  
{ P[1m0!,B  
8+L7E-  
public int doAfterBody() throws JspTagException J2Y 3er  
xK=J.>h3  
{ IPkA7VhFF  
X#Ak'%J  
BodyContent bc = getBodyContent(); ~ \-r  
'@S,V/jy0z  
//将body的内容以字符串的格式提取出来 HD~jU>}}  
J,`_,T  
String query = bc.getString(); e7hO;=?b'  
F42TKPN^uu  
//清除body v?%0~!  
Flne=ij6g  
bc.clearBody(); uJm#{[  
1uY3[Z9S  
try{ ,?;sT`Mh)  
5@CpP-W#  
Statement stmt = connection.createStatement(); bA0uGLc  
xan/ay>  
Result result = stmt.executeQuery(query); Yo@m50s$  
]zy~@,\  
}catch(SQLException e){ U"/yB8!W  
,?t}NZY&  
throw new JspTagException(“queryTag: “ + e.getMessage() ); 1riBvBT  
;4R =eI  
return SKIP_BODY; HUD7{6}4  
mC% %)F'Zf  
} ;*"!:GR%h  
''%;EW>  
} *u<rU,C8  
%h3L  
k>$FT `  
body-content元素 EI%M Azj}  
%e(9-M4*  
k62$:9`5  
由于tag可能会有body,你必须用body-content元素来指定body内容的类型: QR|XV%$  
A4}JZi6@  
<body-content>JSP|tagdependent</body-content> IsWcz+1n  
^#}dPGm  
`X3Xz!  
如果body的内容是定制的或内部的tag、脚本元素、或HTML广本,则归类为JSP类型。其他的类型,比如上面代码所述的?D?D将sql statement类传给 query tag的这种类型应该标为tagdependent。 mQmBf|Rl  
ntDRlX  
注意:实际上body-content的值并不影响tag处理类对body内容的处理,它仅仅是被tag编辑工具用来描述此body的内容。 Z={D0`  
[..,(  
xcAF  
用tags定义脚本变量 ?,D>+::  
.A )\F",X  
0,;E.Py?.  
tag处理类 d*]Dv,#X  
NW }>pb9  
#>MO]  
tag处理类负责创建或设置页面中定义的脚本变量,用pageContext.setAttribute(name,value,scope)或pageContext.setAttribute(name,value)方法来实现。一般来说,tag处理类通过脚本变量的名称来获取它,脚本变量的名称一般可用get方法来获得。 h85 (N  
FLi(#9  
如果脚本变量的值依赖于tag处理类中的上下文中某一对象,那它可用pageContext.getAttribute(name,scope)方法来找到那个对象。一般的处理过程是tag处理类先找到脚本变量,再对其进行处理,然后用pageContext.setAttribute(name,object)的方法来设置它的新值。 o(?VX`2"  
782[yLyv  
对象的生存周期(scope)如下表: s$js5 ou  
HKq2Js  
对象的生存周期表 97['VOh0  
J(3gT }z-  
名字 T_(qN;_  
可访问范围 Fl8w7LcF7  
生存周期 i#CaKS  
jc${.?m  
page ._8xY$l$  
当前页面 dM$N1DB{U+  
一直有效,除非页面向客户提交响应或重定向到一个新页面 bbfDt^  
N |OMj%Uk  
request CpUI|Rs  
当前页面或当前页面重定向到的页面 g5lmUKlQ$0  
一直有效,除非页面向客户提交响应 % JgRcx  
iSSc5ek4  
session '*o7_Ez-{  
当前页面或在同一浏览器窗口中的页面 .Z(S4wV  
一直有效,除非关闭当前浏览器、超时、网络故障 stf,<W  
+a7EsR  
application U:s} /to  
整个web应用程序的所有请求 D[?k ,*  
一直有效,除非发生网络故障、服务器故障 Vy?R/ Uu  
ccHLL6F{  
提供关于脚本变量的信息 H1aV}KD  
m1~qaD<DZ$  
以下示例定义了一个名为“book”的脚本变量,用来访问程序中关于书的信息: fW_}!`:  
d~togTs1  
<bean:define id=”book” name=”bookDB” property=”bookDetails” type=”database.BookDetails” /> yYxeNE"  
5`1(}  
<font color=”red” size=”+2” > */0vJz%<.M  
Verbmeg&n  
<%= messages.getString(“CartRemoved”) %> GnSgO-$"  
zhVa.r A  
<strong><jsp:getProperty name=”book” property=”title” /></strong> Ov0O#`  
: ;E7+m  
</font> 3i@ "D  
KdBq@  
当包含此tag的JSP页面被编译时,jsp引擎会自动生成关于此book的同步的代码(同步可以避免几个客户同时访问此book时造成的冲突),要生成同步代码,jsp引擎需要知道此脚本变量的如下信息: !=~s/{$PE  
.}L-c>o"o  
· 脚本变量名称 &cv@Kihq(  
0U>t>&,"  
· 脚本变量所属的类 )OW(T^>_'I  
C8bGae(  
· 此脚本变量是否引用了一个新的或已存在的对象 0%GqCg  
CjC'"+[w  
· 此脚本变量的有效性 *G2)@0 {  
(>!]A6^L~  
有两种办法可以向jsp引擎提供关于脚本变量的信息:在TLD中定义variable子元素,或用tei-class子元素定义一个额外tag信息类。用variable最简单,但可能降低了一些灵活性。 BR&Qw'O%  
jc%{a*n"vr  
Variable元素 NB!'u) lFD  
|.Y@^z;P3  
Variable元素有如下子元素: I,CAFq  
AF9[2AH=Y  
· name-given ?D?D 给出的名字,是一个常量 Mp^OL7p^^  
VuX >  
· name-from-attribute?D?D 属性名,在编译时给出的属性名 pJ 2:` f<;  
Z1)jRE2dl  
name-given或name-from-attribute两者必须选一,但以下子元素是可选的: cuV8#: i  
.-O@UQx.I  
· variable-class?D?D变量的类型,缺省为java.lang.String。 8%vh6$s6/  
i-:8TfI,  
· declare?D?D此脚本变量是否引用了一个新对象,缺省为True。 ? $)x$nS`  
rm5T=fNJ  
· scope?D?D脚本变量的范围,缺省为NESTED。下表描述了scope的几种类型: T!^?d5uW#  
RpmBP[  
脚本变量的有效范围 y(bt56 | z  
hX>VVeIZ  
${E[pT  
有效性 0gwm gc/#  
方法 %h/#^esi  
^\7 x5gO  
NESTED 2$SofG6D}  
在tag标签的开始和结束之间 ]RJb;  
如果tag处理类实现BodyTag接口,则在doInitBody和doAfterBody中调用,否则在doStartTag中调用 Oet#wp/I  
:XPC0^4s  
AT_BEGIN QKUBh-QFK  
从tag标签的开始一直到页面结束 6 h0U  
如果tag处理类实现BodyTag接口,则在doInitBody、doAfterBody和doEndTag中调用,否则在doStartTag和doEndTag中调用 ABq{<2iYN  
T/Wm S?  
AT_END 7 BnenHD  
从tag标签的结束一直到页面结束 0]h8)EW  
在doEndTag中调用 &z xBi"  
&0th1-OP_  
以struts为例,它的bean:define标签的实现遵循JSP1.1规范,此规范要求使用额外tag信息类来定义脚本变量。Variable元素是JSP1.2规范中加入的。以bean:define标签为例,你可以定义如下variable元素: 4mM2C`I  
YvxMA#  
<tag> 1a=9z'8V  
3gV&`>@  
<variable> ATMogxh  
 23(E3:.  
<name-from-attribute>id</name-from-attribute> mD^qx0o<  
%0~wtZH_!  
<variable-class>database.BookDetails</variable-class> Q~b M  
XRz%KVysp  
<declare>true</declare> fbzKO^Ub  
UpszCY4  
<scope>AT_BEGIN</scope> R+kZLOE  
j J`Zz  
</variable> .5KC'?  
xM'S ;Sg  
</tag> N?2 #YTjR  
evg 7d  
额外tag信息类 eF8 aB?&"  
z|DA _dG  
如果要定义一个额外tag信息类,你要继承javax.servlet.jsp.TagExtraInfo类。一个TagExtraInfo类必须实现getVariableInfo方法,此方法返回一个叫VariableInfo的数组类,它包括如下信息: cyHak u+  
+/~\b/  
· 变量名 ].<sAmL^  
#<tWYE  
· 变量所属类名 jL7MmR#y5"  
$!l2=^\3  
· 此变量是否引用了一个新对象 eUKl Co  
rjpafGCp  
· 此变量的有效范围 OFQi&/  
0r$hPmvv8  
jsp引擎将一个名为data的参数传给getVariableInfo方法,data中包括tag标签中的所有“属性名?D?D属性值”对。它可以用来向VariableInfo对象提供脚本变量的名字和类名。 4xAlaOw5M  
_/sf@R  
以struts为例,它在bean:define标签中定义了一个名为DefineTei的额外tag信息类,用来向脚本变量提供信息。由于脚本变量的名称(book)和类名(database.BookDetails)是通过tag标签的属性来传递的,它们一般定义在VariableInfo的构建代码中,并且可用data.getAttributeString方法来得到这些信息。如果要允许book脚本变量能在从tag开始直到整个JSP页面结束的范围内都可用的话,那它的范围应设为AT_BEGIN。如下所示: F~Z 0  
\9|]  
{Hp}F!X$  
public class DefineTei extends TagExtraInfo NBg>i7KQ  
-t~B@%  
{ ![P(B0Ct/  
~0^,L3M  
public VariableInfo[] getVariableInfo(TagData data) LA=>g/+i.X  
U@v8H!p^i  
{ Y?vm%t`K  
Fzld0p9=  
String type = data.getAttributeString(“type”); ]tdo&  
uVuToMCp  
If( type == null) -o!,,XYj .  
]}l+ !NV<  
type = “java.lang.Object”; B[0,\>  
0Yzb=QMD  
return new VariableInfo[] { I>8@=V~  
ndCS<ojcBP  
new VariableInfo(data.getAttributeString(“id”), = C'e1=]  
n0_Az2   
type, z$BnEd.y=:  
NKUI! [  
true, /o1)ZC$  
Ni@e/| 2b  
VariableInfo.AT_BEGIN) :UhFou_D4l  
6kF uMtjc  
}; d Xo'#.  
\2<yZCn  
} $m: a-.I  
n8OdRv  
} w)m0Z4*  
k>0cTBY&  
55\X\> 0C7  
注意:关于额外tag信息类的类名必须要在TLD中的tag标签下的tei-class子元素中定义。因此,DefineTei的tei-class中的定义看起来如下: _6-/S!7Y\  
<tei-class> *UL|{_)c  
org.apache.struts.taglib.bean.DefineTagTei ^qus `6  
</tei-class> CMG`'gT  
r4NT`&`g?  
2E ; %=e  
具有协作关系的tag ,^IZ[D>u)  
HlL@{<  
4Ig{#}<  
tag通过共享对象来进行协作,JSP技术支持2种方式的对象共享。 @x F8' [<  
dYqDL<se/I  
第一种方法是使用pageContext对象进行对象的共享(可支持JSP页面和tag处理类之间的共享),如果在一个tag处理类中要调用由另一个tag处理类创建的对象,可调用pageContext.getAttribute(name, scope)方法。  hL{B9?  
vK.4JOlRF  
第二各方式的共享是对于tag之间有嵌套关系而言的,外层的tag所创建的对象对于内层的tag来说是可以共用的。这种形式的共享的好处是减少了可能存在的重名冲突。   [aS)<^  
vS t=Ax3]  
要访问一个嵌套tag创建的对象,tag处理类必须先找到此嵌套tag对象,可用TagSupport的静态方法 TagSupport.findAncestorWithClass(from, class)或TagSupport.getParent方法。前者在当不确定此tag是否为嵌套tag对象时使用。一旦它的父类被找到,它就能访问其所有动态或静态创建的对象。静态创建的对象是父类的成员,而动态创建的对象可能是父类的私有对象。诸如此类的对象可以用tag处理类的setValue方法来保存,用getValue方法来获得。 iBiA0 W  
5B.??;xtaV  
下例阐述了以上两种共享对象的方法。在这个例子当中,一个查询tag检查一个名为connection的属性名是否在doStartTag中被设置。如果connection属性被设置,tag处理类从pageContext中得到这个connection对象。否则,此tag处理类先找到它的父tag处理类,然后从它的父tag处理类中找到connection对象。 W7[ S7kd  
$9_.Q/9>  
$}UJs <-F  
public class QueryTag extends BodyTagSupport ihBl",l&Hq  
<:{[Zvl'k  
{ ?a0}^:6  
+e]b,9.sR  
private String connectionId; +$= Wms-z  
ylxfh(  
public int doStartTag() throws JspException }.$ B1%2  
Lr\ B  
{ E)_!Hi0<s  
=+-.5M  
String cid = getConnection(); KZ}4<{3  
>)A  
if(cid != null) !6/IKh`J  
t02"v4_i  
{ g+/U^JIc4l  
3N%Ev o  
//存在一个connection id,使用它。 6dy4{i  
)B&<Bk+  
connection = (Connection) pageContext.getAttribute(cid); ~\}EROb <  
rH:X/i;D  
} p;t!"I:`?  
'sQO0611S  
else pH:|G  
e(\S,@VN2  
{ qf=[*ZY  
pVa|o&,  
ConnectionTag ancestorTag = (ConnectionTag)findAncestorWithClass(this, +\Mm (Nd  
UO!6&k>c  
ConnectionTag.class); H$z+gbjJ  
g5|\G%dOt  
if(ancestorTag == null) rLVc<595  
!>@V#I  
{ Iy4M MU  
WblV`"~e  
throw new JspTagException(“一个没有connection属性的查询标签必须被一个connection标记嵌套。”); FC(cXPX}  
I64:-P[\  
} #:zPpMAl  
D&m"~wI  
connection = ancestorTag.getConnection(); >(ww6vk2  
+}0*_VW  
} eC`f8=V  
Jc?ssm\%  
} nW%=k!''  
+2 o|#`)i  
} h>%JG'DV  
# %y{mn  
l<: E+lU  
~S>ba']  
此查询标签在JSP页面中的调用形式可以从以下2种定义中任选一种: ![!b^:f  
#R PB;#{  
L0VR(  
<tt:connection id=”con01” ...> ... </tt:connection> ?HyioLO  
e CUcE(  
<tt:query id=”balances” connection=”con01” > "#k(V=y  
&8i{'k,l  
SELECT account, balance FROM acct_table 9qy 9  
}o:sx/=u_  
where customer_num = <%= request.getCustno() %> `oWjq6  
y]Tn#4 ,/  
</tt:query> c@B%`6kF  
RcM0VbR"EU  
<\~#\A=;  
B@vH1T  
,:4w$!;  
<tt:connection ...> }UdqX1jz  
knzED~ v@(  
<x:query id=”balances”> )-"L4TC)  
*dTf(J  
SELECT account, balance FROM acct_table lFV|GJ  
g uWqHVSs  
where customer_num = <%= request.getCustno() %> s(.-bjR  
ZxPAu%Y  
</x:query> ~ A|*]0,  
/=(FM   
</tt:connection> 3D dG$@  
(3r,PS@Qq@  
G ]By_  
与此同时,在TLD中必须指定connection属性为可选的,定义如下: G&3<rT3Ib  
<sB45sNbU`  
<tag> 3'e 4{  
&.4_4"l(  
... km^+ mK  
O~ 0 1)%  
<attribute> QaBXzf   
r8 >?-P  
<name>connection</name> -y*+G&  
@}!$NI8  
<required>false</required> w>Sz^_ h  
( +hI   
</attribute> 8N_rJ)f  
!`=?<Fl  
</tag>
描述
快速回复

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