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

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

级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
标准的JSP 标记可以调用JavaBeans组件或者执行客户的请求,这大大降低了JSP开发的复杂度和维护量。JSP技术也允许你自定义taglib,其实换句话说,taglib可以看成是对JSP标记的一种扩展,正如xml是对html的一种扩展一样。taglib通常定义在tag标签库中,这种标签库存放着你自己定义的tag标签。简而言之,如果使用taglib,那么你可以设计自己的JSP标记! ?_!} lg  
(}E ] g  
一般来说,自定义tag标签主要用于操作隐藏对象、处理html提交表单、访问数据库或其它企业级的服务,诸如邮件和目录操作等等。自定义tag标签的使用者一般都是那些对java编程语言非常精通,而且对数据访问和企业级服务访问都非常熟悉的程序员,对于HTML设计者来说,使得他可以不去关注那些较复杂的商业逻辑,而将精力放在网页设计上。同时,它也将库开发者和库使用者进行合理分工,自定义tag标签将那些重复工作进行封装,从而大大提高了生产力,而且可以使得tag库可用于不同的项目中,完美地体现了软件复用的思想。 4t%g:9]vr  
g^V4+3v|a'  
在这篇文章中,我们主要讨论: rr@S|k:|  
~ .FZF  
· 什么是自定义tag标签? zB8 @Wl  
" ^t3VjN  
· 怎么使用tag标签? u+&t"B  
-UHa;W H  
o 声明要使用的tag库 @F+zME   
7u9]BhcFv?  
o 找到与之对应的tag处理类 h=fzX .dt  
efK|)_i :  
o tag标签的类型 u; c)T t  
,:Q+>h  
· 自定义tag标签 *kliI]B F]  
 2]$ 7  
o tag处理类 e~NEyS~3  
/!V) 2j,  
o tag库描述 x9,X0JO  
x8#bd{  
o tag标签示例 wNHvYu lI  
epcBr_}  
o 带属性的tag wVSk.OOB  
KfSI6 Y _  
o 带body的tag ,-C%+SC  
y@5{.jsr_  
o 定义了脚本变量的tag .d^XM  
!,}F2z?4c  
o 具有协作关系的tag GE2^v_  
ypCarvQT  
· 自定义tag标签 P)>`^wc$  
IfK%i/J  
o 一个迭代tag的例子 ({GN.pC(  
qqmhh_[T  
o 一个模板tag库 G,VTFM6  
J FYV@%1~  
o tag处理类到底是怎样被调用的? 6 J&_H(^  
^""Ss  
r+4<Lon~  
什么是自定义的tag? 3kTOWIX  
HF2w?:  
一个自定义的tag标签是用户定义的一种JSP标记。当一个含有自定义的tag标签的JSP页面被jsp引擎编译成servlet时,tag标签被转化成了对一个称为tag处理类的对象进行的操作。于是当JSP页面被jsp引擎转化为servlet后,实际上tag标签被转化成为了对tag处理类的操作。 vZDM}u  
0/1Ay{ns  
自定义tag标签有很多特色,诸如: W[+=_B  
|>/T*zk<  
· 可以在JSP页面中自定义tag标签的属性 *Zj2*e{Z9U  
:sf(=Y.qA  
· 访问JSP页面中的所有对象 p~n62(  
J=%(f1X<W  
· 可以动态地修改页面输出 20Umjw.D  
[VD)DO5  
· 彼此这间可以相互通信。你可以先创建一个JavaBeans组件,然后在一个tag中调用此JavaBeans组件,同时可以在另一个tag中调用它。 {Qe 7/ln!  
VZ#@7t  
· tag允许相互嵌套,可以在一个JSP页面中完成一些复杂的交互。 j9V*f HK  
kw%vO6"q(  
aBBTcN%'  
使用tag标签 }mZ sK>  
F5hOKUjv  
NrHh(:  
本节主要描述怎样在JSP页面中使用tag标签,以及tag标签的不同类型。 bJ~@ k,'  
gc ce]QS  
要使用tag标签,JSP程序员必须做2件事: _iJ8*v 8A  
jD`p;#~8  
· 声明此tag标签的tag库 9S .J%*F7  
;tBc&LJ?  
· 实现此tag标签 Lrr1) h  
$Ur-Q d  
声明tag标签所在的tag库 wM]j#  
O&]P u5  
如果要使用tag标签,则应用JSP的taglib指示符来指定其tag库(注意:taglib要在在使用此tag标签之前声明) ,?'":T1[  
cZ<@1I5QK  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> D2060ze  
9r5<A!1#L  
uri属性定义了唯一的标签库描述(以下简称TLD),它可以是直接是tld文件名或一个独一无二的名字。prefix是用来区别其它TLD中和本TLD中有重名的tag的一种手段。 ]*M VVzF  
f  _ O  
TLD必须以.tld作为扩展名,并且存放在当前应用的WEB-INF目录或其子目录下。你可以通过它的文件名直接引用它,也可以通过别的方式间接地引用它。 *0*1.>Vg  
zqDG#}3f^  
以下taglib指示符直接引用一个TLD: STr&"9c  
zKnHo:SV  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> %, U@ D4w  
55mDLiA  
以下的taglib指示符通过一个逻辑名称间接地引用一个TLD: l"C)Ia&/  
1ymq7F(2  
<%@ taglib uri=”/tutorial-template” prefix=”tt” %> F$|Ec9  
eJ=K*t|  
如果是间接引用TLD的话,那你必须还要在web.xml中定义此逻辑名称与tld文件之间的映射,具体做法是在web.xml中加入一个名为taglib的元素: /^m3?q[a  
_o'3v=5T  
<taglib> [K*>W[n  
`4@_Y<  
<taglib-uri>/tutorial-template</taglib-uri> i*T>, z  
`8.Oc;*zu  
<taglib-location> 2[O\"a%  
&s+F+8"P+  
/WEB-INF/tutorial-template.tld +2ZBj6 e9  
7QOQG:-  
</taglib-location> fsA-}Qc  
f|U J%}$v;  
</taglib> @CxXkR  
e5 "?ol0  
^Hdru]A$2  
实现此tag标签 &fIx2ZM[  
zFR=inI  
-C>q,mDJZ  
为了实现tag标签,你有2种方法来存放tag处理类。一、让tag处理类以.class的方式存放于当前应用的WEB-INF/class子目录下,二、如果tag处理类是以JAR包的形式存在的话,那可以放在当前应用的WEB-INF/lib目录下,如果tag处理类要在多个应用中共享,那么它就应放在jsp服务器上的common/lib目录下,对于tomcat来说,就是tomcat/common/lib目录下。 )\!-n]+A  
na%DF@Rt#  
!6yyX}%o  
tag标签类型 'ot,6@~x>  
~ sC<V  
viLK\>>  
自定义的tag标签遵循XML语法。它有一个开始标记和一个结束标记,有的还有body(即文本节点): Ot^<:\< `G  
NV[_XXTv7  
<tt:tag> l6AG!8H  
^2|G0d@.:  
body 0c pI2  
ranlbxp2l  
</tt:tag> GC<zL }  
FtEmSKD  
`:4\RcTb/  
一个不带body的tag标签如下: [i  ]  
Q9\6Pn ]T  
<tt:tag /> ,.g9HO/R1  
ssWSY(j]  
#VLO6  
简单的tag标签 RfZZqe U  
G;'=#c ^  
一个没有body和属性的tag标签如下: _(TYR*  
&ND8^lR=Y;  
<tt:simple /> p5`d@y\hj  
g4`)n`  
1z#0CX}Y/H  
带属性的tag标签 dV:vM9+x  
f<Co&^A  
Uc?4!{$X  
自定义标签可以有自己的属性。属性一般在开始标记中定义,语法为 attr=”value”。属性的作用相当于自定义标签的一个参数,它影响着tag处理类的行为。你可以在TLD中详细定义它。 JyfWy  
Xyf7sHQ  
你可以用一个String常量给一个属性赋值,也可以通过表达式给它赋值,如<%= ...%>。以struts为例,它的logic:present标签就是用的String常量来给属性赋值: RH"&B`  
.;:jGe(  
<loglic:present parameter = “Clear”> OE"r=is  
FTA[O.tiG  
而另一个标签logic:iterate是用表达式来给属性赋值: s--\<v  
:kaHvf  
<logci:iterate collection=”<%= bookDB.getBooks() %>” #Is/j =  
0VA$ Ige  
id=”book” type=”database.BookDetails”> uPp9 UW  
+ pq/:h  
-%h0`hOG{  
带body的tag标签 %"1*,g{  
nj@l5[  
一个自定义标签可以包含其它自定义标签、脚本变量、HTML标记或其它内容。 M<s Y_<z  
C8J3^ ?7E  
在下述例子中,此JSP页面使用了struts的logic:present标签,如果些标签定义了parameter=”Clear”的属性,则将清除购物车的内容,然后打印出一条信息: $;ssW"7~Qn  
I|{A&G}|q  
<logic:present parameter=”Clear”> H=f'nm]dQ  
5z$>M3  
<% cart.clear(); %> %U4w@jp  
Ga%x(1U[&  
<font color=”#ff0000” size=”+2”><strong> ,z*-93H1  
Gz>M`M`[4  
你选择了清除购物车! ]Q%|69H}B  
syseYt]  
</strong></font> Yy_o*Ozq  
z@_ 9.n]  
</logic:present> 6*cY[R|q!  
@ eQo  
|.s#m^"  
到底是用属性还是用body来传递信息? RCS91[  
f a9n6uT  
如上所述,我们既可以通过属性,也可以通过body来传递信息。但一般来说,比较简单的类型,如字符串或简单表达式最好采用属性来传递信息。 cITF=Ez  
H,? )6pZ  
1VH$l(7IQ  
定义脚本变量的tag标签 mJ>@Dh3>G  
bhI yq4N  
所谓脚本变量,是指JSP中可以调用的变量或对象。它可由tag标签产生。以下示例阐述了一个tag标签定义了一个名为tx的由JNDI所定义的事务处理对象。脚本变量可以是ejb对象、事务、数据库连接等等: vbZGs7%  
#kuk3}&  
<tt:lookup id=”tx” type=”UserTransaction” name=”java:comp/UserTransaction” /> <MPoDf?h  
lF=l|.c  
<% tx.begin(); %> <Bmqox0  
jMT];%$[  
... ~HR/FGe?N  
LPOZA`  
|H,g}XWMU  
具有协作关系的tag标签 nt"8kv  
{O"?_6',  
自定义tag标签之间可以通过共享对象来实现协作。在下述例子中,标签tag1创建了一个名为obj1的对象,在标签tag2仍可以重复使用obj。 `wyX)6A|bt  
49BLJ|:P?  
<tt:tag1 attr1=”obj1” value1=”value” /> /pa8>_,~  
^w+jPT-n  
<tt:tag2 attr1=”obj1” /> {U`B|  
.Fz5K&E=  
在以下这个例子当中,如果外层的tag标签创建了一个对象,那么其内层的所有tag标签都可以使用这个对象。由于这样产生的对象没有一个指定的名字,那么就可以将少重名的冲突。这个例子阐述了一系列协作的嵌套对象。 f +#  
K}]0<\N  
<tt:outerTag> zW@OSKq4  
|?t6h 5Mt"  
<tt:innerTag /> )"&$.bWn  
ic"n*SZa  
</tt:outerTag> Ul<'@A8  
0'DlsC/`*  
S[J=d%(  
Tag处理类 ;T|y^D  
Rv ]?qJL  
Lnk!zj  
Tag处理类必须实现Tag接口或BodyTag接口,不过现在一般都流行从TagSupport或BodyTagSupport类中继承,这些类或接口都可以在javax.servlet.jsp.tagext包中找到。 +Rtz`V1d  
+18)e;   
当JSP引擎看到自己的JSP页面中包含有tag标签时,它会调用doStartTag方法来处理tag标签的开头,调用doEndTag方法来处理tag标签的结束。 Y'.WO[dgf  
K{ s=k/h  
下表说明不同类型的tag所需要不同的处理过程: bi fi02  
G]Jchg <  
Tag处理类的方法 8\M%\]_  
$jd>=TU|  
Tag标签类型 ^GXy:S$  
所调用的方法 .>(?c92  
$ljgFmR_  
基本标签 ?|i6]y=D  
doStartTag, doEndTag, release /f_c?|  
J.`z;0]op  
带属性的标签 KAR XC,z  
doStartTag, doEndTag, set/getAttribute1...N, release ~dIb>[7wy  
(okCZ-_Jn  
带内容的标签 fs]9HK/@\  
doStartTag, doEndTag, release ,tEvz  
8Ee bWs*1  
带内容的标签,且内容重复循环 6zQ {Y"0  
doStartTag, doAfterBody, doEndTag, release cI)XXb4  
A2` QlhZ  
带内容的标签,且内容与JSP交互 bb6 ~H  
doStartTag, doEndTag, release, doInitBody, doAfterBody, release ;|2h&8yX(/  
sP0pw]!  
一个tag处理类可以通过javax.servlet.jsp.PageContext来与JSP交互,通过javax.servlet.jsp.PageContext类,tag处理类可以访问JSP中的request、session和application对像。 dBV^Khf J  
u@`)u#  
如果tag标签是互相嵌套的,那内层的tag处理类可以通过它的parent属性来访问上层的tag处理类。 oCLs"L-r{  
Tl#Jf3XY}  
一般情况都将所有的tag处理类打成了JAR的包,以便于发布。 XFeeNcqF  
2p(M`@  
'~-Lxvf'  
Tag库描述(简称TLD) -DO*,Eecv  
w"CcWng1  
~3 {C &c  
Tag库是用xml语言描述的,TLD包括了tag库中所有tag标签的描述,它一般用来被jsp服务器用来校验tag的语法正确性,或者被jsp开发者用来开发新的标签。 \ B~9Ue!  
zS Yh ?NB5  
TLD的文件扩展名必须为.tld,而且必须放在当前WEB应用的WEB-INF目录或其子目录中。 &FWPb#  
_v=@MOI/J  
一个TLD的内容的开头必须遵守标准的XML开头,用于描述DTD和xml的版本,例如: ]Q\Ogfjp  
D_6GzgZ  
<?xml version="1.0" encoding="ISO-8859-1" ?> :x*8*@kC  
Co2* -[R  
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd"> Yx_[vLm  
TLD必须以<taglib>来作为它的根元素,<taglib>的子元素如下表: AgsMk  
)Oq N\  
{cF7h)j  
<taglib>的子元素 \?,'i/c-  
\C3ir&  
Element ?VMj;+'tr  
Description @<]xbWhuw  
XpzdvR1  
tlib-version w;.'>ORC  
Tag库的版本 ZQvpkO7}M  
mMqT-jT  
jsp-version -aiQp@^/J  
Tag库所需要的jsp的版本 G"jKYW  
q+{-p?;;  
short-name U[zY0B  
助记符,tag的一个别名(可选) \lKiUy/  
?Z@FxW  
uri YJw9 d]  
用于确定一个唯一的tag库 oZ1#.o{  
;lST@>  
display-name d7A08l{  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) pRtxyL"y  
}>JFO:v&  
small-icon @GGzah#  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) LxkToO{  
ce{GpmW  
large-icon /&=E=S6  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) h<.G^c)  
6Q,-ZM=Z_p  
description ND\&#  
对tag库的描述(可选) P>=~\v nN#  
=R#K` H66j  
listener MN2#  
参见下面listener元素 BRP9j y  
omM*h{z$$  
tag ?;.j)  
参见下面tag 元素 .~V0>r~my  
:X[(ymWNE  
Listener元素 8uoFV=bj\  
b r)oSw  
一个tag库可能定义一些类做为它的事件侦听类,这些类在TLD中被称为listener 元素,jsp服务器将会实例化这些侦听类,并且注册它们。Listener元素中有一个叫listener-class的子元素,这个元素的值必须是该侦听类的完整类名。 @v9 PI/c  
C #ng`7 q  
Tag元素 S .rT5A[  
U">D_ 8  
每个tag元素在tag库中都要指出它的名字、类名、脚本变量、tag的属性。其中脚本变量的值可以直接在TLD中定义或通过tag附加信息的类来取得。每个属性描述了这个属性是否可以省略,它的值是否可以通过<%= …%>这样的JSP语法来获得,以及属性的类型。 TX]4Y953D  
8WU UE=p  
每一个tag在TLD中对应一个tag元素,下表是tag元素的子元素: [~ bfM6Jw  
vy#n7hdCc  
Tag元素的子元素 wKhuUZj{  
-zg,pK$+  
元素名称 2q J}5  
描述 m~~_iz_*  
`rC9i5:  
name 1oaiA/bq  
独一无二的元素名 FG7}MUu  
|,bsMJh0  
tag-class ]]$s"F<  
Tag标签对应的tag处理类 *L8Pj`zR  
Q44Pg$jp  
tei-class ks7g*; 3{@  
javax.servlet.jsp.tagext.TagExtraInfo的子类,用于表达脚本变量(可选) 38! $9)  
k,M%/AXd  
body-content 693J?Yah[  
Tag标签body的类型 I#Ay)+D  
$rDeI-)S  
display-name @D8c-`LC"*  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) :(?joLA  
S#qd#Zk|Y  
small-icon c&2ZjM  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) qIK"@i[ uq  
@(PYeXdV6&  
large-icon ^jb55X}  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) J_R54Y~vu  
m8H|cQ@Uu  
description xBd#  
此tag标签的描述 oD_je~b)  
F"j0;}+N  
variable bp2l%A;  
提供脚本变量的信息(同tei-class)(可选) aQwcPy|1R  
bC?uy o"  
attribute F ^Rt 6Io  
Tag标签的属性名 >/1N#S#9  
 ~%_$e/T  
以下章节介绍对于不同类型的tag,如何具体地实现它们。 h@FDP#H  
xh[Mmq/R  
CJk$o K{Q  
简单的tag O>xGH0H  
9H ?er_6Yf  
?hvPPEJf  
tag处理类 CQ2{5  
EtJyI&7VK  
简单的tag处理类必须实现Tag接口的doStartTag和doEndTag方法。当jsp引擎碰到tag标签的开头时,doStartTag被调用,因为简单的tag没有body,所以此方法将返回 SKIP_BODY。当jsp引擎碰到tag标签的结尾时,doEndTag被调用,如果余下的页面还要被计算,那它将返回EVAL_PAGE,否则将会返回SKIP_PAGE。 * 7.!"rb8A  
`?{QCBVj  
以下是例子:对于标签 <tt:simple /> ,它的tag处理类实现如下: (E59)z -  
y%k\=:m  
= ^:TW%O  
public SimpleTag extends TagSupport [=9-AG~}  
M *BDrM  
{ 7+JQaYO`"  
kVw5z3]Xg  
public int doStartTag() throws JspException KgX~PP>  
[wP;g'F  
{ O^|dc=  
R6] /g  
try{ ,xB&{ J  
Bv \ihUg/  
pageContext.getOut().print(“Hello.”); ,K .P,z~*  
p!>FPS  
}catch(Exception e){ =2pGbD;*  
U 9TEC)  
throw new JspTagException(“SimpleTag: “ + e.getMessage()); Lv+lLK  
*W,"UL6U8y  
} E~_2Jf\U  
)6iY9[@tN  
return SKIP_BODY; gxpR#/(E~  
K>6#MI  
} {&8-OoH ~  
esx<feP)\  
public int doEndTag() }9t$Cs%  
IBb3A  
{ Q.#@xaX'{`  
Q+)fI  
return EVAL_PAGE; rA&|!1q"B  
mf6?8!O}>  
}  y$7Fq'  
/8@JWK^I{  
} MBRRzq%F  
a \B<(R.  
e~=fo#*2?@  
注意:如果tag标签没有内容的话,那必须定义body-content元素为空,例如 id@!kSR  
&Eg>[gAIlp  
<body-content>empty</body-content> n|IdEgD$  
~"!F&  
ChF:N0w? p  
带属性的tag标签
评价一下你浏览此帖子的感受

精彩

感动

搞笑

开心

愤怒

无聊

灌水
级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
只看该作者 1 发表于: 2007-01-01
tag处理类 qCOv4b`  
:q S=_!1  
对于tag标签的每个属性,你必须依照JavaBeans规范来定义其属性,以及get和set方法。以struts的logic:present 标签为例, bVSa}&*kM  
x0@J~ _0  
<logic:present parameter=”Clear”> (p26TN;*$5  
%h 6?/  
与此相应,此tag处理类应有如下方法和定义: )Xg,;^  
zI8Q "b  
A>(m}P  
protected String parameter = null; *,{. oO9#  
sh[Yu  
public String getParameter() +u' ?VBv  
q0{KYWOvk  
{ J!O5`k*.C  
/vS!9f${  
return this.parameter; YW9 [^  
Q\&FuU  
} .9+"rK}u  
^-c j=on=Q  
public void setParameter(String parameter) hNmC(saMGm  
#P=rP=  
{ &}@U#w]l  
R<{bb'  
this.parameter = parameter; G$ XvxJ  
?Z {4iF  
} B-ReBtN  
)+RTA y[k  
[?iA`#^d  
注意:如果你的属性名为id,而且你的tag处理类是从TagSupport类继承的,那你就不需要定义它的属性和set和get方法,因为他们早已在TagSupport被定义过了。 $wH{snX  
b>=MG8  
Attribute元素 q]YPDdR#  
"8%B (a 5A  
对于tag标签的每个属性,你必须定义它是否必须的,它的值是否可以用诸如<%= …%>的表达式来获得,以及它的类型(可选),如果不指定它的类型,那就默认为是java.lang.String类型。如果rtexprvalue元素被定义为true或yes,那么在type元素中就定义了attribute的返回类型。 hH[UIe  
gN1b?_g  
<attribute> 5s_7 P"&H  
7)!(0.&  
<name>attr1</name> \.2?951}  
F7gipCc1We  
<required>true|false|yes|no</required> 7S LJLn3d  
Ac'[(  
<rtexprvalue>true|false|yes|no</rtexprvalue> I8@NQ=UV0  
&1YqPk  
<type>attribute的返回类型(只用当rtexprvalue为真是才有效)</type> PN[ `p1F  
<:0649ZB  
</attribute> U:m[* }+<  
fs+l  
如果tag的某个属性不是必须的,那tag处理类会自动提供一个缺省值。 wV-1B\m  
>(S4h}^I  
例如,在logic:present这个tag标签中定义了一个属性叫parameter,但它不是必须的,而且它可以被诸如<%= …%>的表达式来赋值。 <#<4A0:  
QCQku\GLV  
<tag> 2s>dlz  
f9u^/QVS&  
<name>present</name> /:d03N\9k  
_}R?&yO  
<tag-class>org.apache.struts.taglib.logic.PresentTag</tag-class> U*`7   
ewg&DBbN"  
<body-content>JSP</body-content> Gf\Dc   
L22GOa0  
H|k!5W^  
9%WUh-|'p  
<attribute> S.rlF1`  
MKLntX  
<name>parameter</name> =fG c?PQ  
=k6zUw;5 U  
<required>false</required> }Iz'#I Xx  
+gqtW8 6  
<rtexprvalue>true</rtexprvalue> \?7)oFNz  
0H,1"~,w]  
</attribute> {%5k1,/(  
U1bhd}MoR  
F%@( $f  
RX8$&z  
</tag> 4V9DPBh  
WL$Ee=  
dOh'9kk3  
属性元素的校验 8rwkux >  
=G3O7\KmH  
S453oG"  
有关于tag标签的有效值可以从tag库的说明文档中获得,当JSP页面被编译时,jsp引擎会强制性地参照TLD中定义的规则进行检查。 ,o7aIg&_H  
tgK$}#.*  
还有一个方法也可以进行属性元素的校验,就是先继承类TagExtraInfo,然后调用它的isValid方法。这个类同时也起到提供tag中定义的脚本变量信息的作用。 ,}2yxo;i  
QEK,mc3  
IsValid方法通过TagData对象来传递属性信息,它包括着tag的所有的属性名-值的信息。由于校验发生在运行时刻,因此这个属性的值将被赋值为TagData.REQUEST_TIME_VALUE。 OY7\*wc:  
q+f]E&':  
例如tag标签<tt:twa attr1=”value1” />在TLD中定义如下: lMz5))Rr  
La9v97H:  
<attribute> 8aZuI|z  
i <0H W  
<name>attr1</name> |@? B%sY  
a3e<< <Z>R  
<required>true</required> |6w.m<p  
c9imfA+e  
<rtexprvalue>true</rtexprvalue> ~L(=-B`Ow  
0yr=$F(]s  
</attribute> RFd.L@-]  
,g2|8>sJP  
Z3?,r[   
这个定义说明了attr1能在运行期间被赋值。 V{@ xhW0  
(e sTb,  
以下的isValid方法检查attr1属性的值是否属于Boolean类型。注意由于attr1能在运行刻被赋值,那么isValid方法必须检查tag用户是否对此tag进行了运行时刻赋值。 9 X}F{!p~1  
qYv/" 1  
*5Upb,* *  
Public class TwaTEI extends TagExtraInfo x'kwk  
N p9N#m?  
{ wr{03mQHxp  
f>\OT   
public boolean isValid(Tagdata data) w='1uV<6  
ktLXL;~X  
{ \~!9T5/*  
Z*S 9pkWcF  
Object o = data.getAttribute(“attr1”); e@'rY#:u  
}YJ(|z""  
If(o != null && o != TagData.REQUEST_TIME_VALUE) ?Q1(L$-=  
g.OBh_j-v  
{ &EKP93  
cnr&%-  
if( ( (String)o).toLowerCase().equals(“true”) || YfL|FsCh  
OE)n4X  
((String)o).toLowerCase().equals(“false”) ) ^]c/hb|X  
Fgq"d7`9@  
return true; tn\Y:  
Su`LBz"  
else U">J$M@  
a7'.*H]  
return false; ` W$  
$O"S*)9  
} ModwJ w  
c#sPM!!  
else z3+y|nx!  
y;A<R[|Ve  
return true; WmU4~.  
pFi.?|6"  
} & V :q}Q  
Y: &?xR  
} [^xLK  
xcdy/J&  
{[WEA^C~Q  
带body的tag hZ|*=/3k  
q !\Ht2$b  
d%_v eVIe  
tag处理类 ].53t"*  
pOP`n3m0  
UMR0S5`}  
如果tag标签含有内容,那处理方式会略微有些不同,而且还要视tag处理类是否要与body交互的情况而定。如果要与body交互,那我们认为tag处理类要可能要对body进行操作。 >m='#x0>Y  
|_L\^T|6  
Tag处理类不与body交互 ?8[,0l:|  
+7n;Bsk _  
如果tag处理类不与body交互,tag处理类应该实现Tag接口或从TagSupport中派生,如果body要被计算,那么doStartTag方法应返回 EVAL_BODY_INCLUDE,否则应返回SKIP_BODY。 `<&RZB2  
cPA-EH  
如果tag处理类要对body反复运算,则它应该实现IterationTag或从TagSupport中派生。如果tag处理类认为body还未计算完的话,那它的doStartTag方法和doAfterBody方法必须返回EVAL_BODY_AGAIN。 Pk/{~!+ $  
NIufL }6\  
Tag处理类与body交互 s\ft:a@  
$z,lq#zzl  
如果tag处理类与body交互,那tag处理类应实现BodyTag接口或从BodyTagSupport中派生。这种tag处理类一般要实现doInitBody和doAfterBody方法。 j<H`<S  
lx*"Pj9hho  
Body允许一些方法来读写它的内容。Tag处理类可以调用body内容的getString或getReader方法来从body中提取信息,也可用 writeOut(out) 方法来将body的内容写入到out对象中。其中out对象通过tag处理类的getPreviousOut方法来获得。 ~_ss[\N  
USfpCRj9  
如果body的内容需要被计算,那么doStartTag方法必须返回EVAL_BODY_BUFFERED,否则,它将返回 SKIP_BODY。 @igGfYy  
YT\x'`>Q  
doInitBody 方法 \Z9+U:n  
hZ NS$  
此方法在body内容已经设好,但未被计算之前被调用。你可以根据不同的body内容来制定初始化策略。 7=C$*)x  
B:S/ ?v  
doAfterBody方法 [1Pw2MC<  
OAPR wOQ^=  
此方法在body内容已被计算后进行调用。 (sLFJ a6e  
V`xZ4 i%L  
和doStartTag方法一样,doAfterBody方法返回一个指示符指示是否要继续计算body,如果要继续计算,则doAfterBody应返回EVAL_BODY_BUFFERED,否则,它应返回SKIP_BODY。 WLGk  
rX*4$d0  
release 方法 $"&0  
am,UUJ+h>  
tag处理类调用此方法将它的状态重置为初始状态,并释放所有的私有资源。 'o=`1I  
;u`zZb=,[  
S^nshQI  
以下的例子读取body的内容(其中含有一条sql语句),然后将它传递给一个对象,让它进行查询。由于此处body不须重新计算,所以doAfterBody会返回SKIP_BODY。 8 CKN^8E  
gi!{y   
2mUq$kws  
Public class QueryTag extends BodyTagSupport SK f9 yS#  
ut z.  
{ zf-)c1$*r  
l>K z5re^  
public int doAfterBody() throws JspTagException fw aq  
!f5I.r~  
{ d`]| i:*q  
R2{y1b$l  
BodyContent bc = getBodyContent(); *Pj[r  
F<SMU4]YdG  
//将body的内容以字符串的格式提取出来 d|5V"U]W;  
j8WMGSrrF  
String query = bc.getString(); 9sYN7x  
`s HrC  
//清除body oE:9}]N_  
4oW6&1  
bc.clearBody(); df@IC@`pB  
P.^%8L  
try{ H9'Y` -r  
;xF5P'T?|  
Statement stmt = connection.createStatement(); o.Ld.I)  
7"}<J7"})  
Result result = stmt.executeQuery(query); +~~FfIzf#  
xb/L AlJ  
}catch(SQLException e){ E__^>=  
UeNa  
throw new JspTagException(“queryTag: “ + e.getMessage() ); SF$'$6x}  
#wz1uw[pI!  
return SKIP_BODY; YC!Tgb~H  
qK}4r5U  
} l)y$c}U  
Br w-"tmx  
} lq0@)'D  
Y rq-(  
a1V+doC  
body-content元素 ap|7./yg  
vbT"}+^Sh  
p.{9OrH(4  
由于tag可能会有body,你必须用body-content元素来指定body内容的类型: r&F(VF0 6  
W 2/`O?  
<body-content>JSP|tagdependent</body-content> y bWb'+x  
Vgy}0pCl  
Fkgnc{NI  
如果body的内容是定制的或内部的tag、脚本元素、或HTML广本,则归类为JSP类型。其他的类型,比如上面代码所述的?D?D将sql statement类传给 query tag的这种类型应该标为tagdependent。 xWkCP2$?P  
>E*j4gg  
注意:实际上body-content的值并不影响tag处理类对body内容的处理,它仅仅是被tag编辑工具用来描述此body的内容。 JkT , i_  
VQSwRL3B=  
9 Yv;Dom  
用tags定义脚本变量 uJ:'<dJ  
@C[]o.r  
OcR6\t'  
tag处理类 r!Ujy .R  
{2u#Q 7]|  
aLr\Uq,83  
tag处理类负责创建或设置页面中定义的脚本变量,用pageContext.setAttribute(name,value,scope)或pageContext.setAttribute(name,value)方法来实现。一般来说,tag处理类通过脚本变量的名称来获取它,脚本变量的名称一般可用get方法来获得。 m1,?rqeb  
1J$sIY,Ou  
如果脚本变量的值依赖于tag处理类中的上下文中某一对象,那它可用pageContext.getAttribute(name,scope)方法来找到那个对象。一般的处理过程是tag处理类先找到脚本变量,再对其进行处理,然后用pageContext.setAttribute(name,object)的方法来设置它的新值。 aXi5~,Ks_  
OVr, {[r  
对象的生存周期(scope)如下表: s^5KFK1  
r\6 "mU  
对象的生存周期表 IIC1T{D}v  
/8V#6d_  
名字 &Xr@nt0H  
可访问范围 :e9}k5kdk  
生存周期 fq^D<c{3  
nXjf,J-T  
page &?~OV:r9  
当前页面 3SbtN3  
一直有效,除非页面向客户提交响应或重定向到一个新页面 O{b.-<  
?xTM mm  
request QwaCaYoh  
当前页面或当前页面重定向到的页面 o`B,Pt5vu  
一直有效,除非页面向客户提交响应 x!6&)T?!n  
gFk~SJd  
session =4RXNWkud  
当前页面或在同一浏览器窗口中的页面 x13t@b  
一直有效,除非关闭当前浏览器、超时、网络故障 8r7}6  
u=a5Z4N'  
application =`VA_xVu  
整个web应用程序的所有请求 ?6h65GO{  
一直有效,除非发生网络故障、服务器故障 W zM9{c  
C$MaJHkiF  
提供关于脚本变量的信息 .j*muDVQn  
}9n{E-bj*  
以下示例定义了一个名为“book”的脚本变量,用来访问程序中关于书的信息: R"Ol'y{  
wNsAVUjLe  
<bean:define id=”book” name=”bookDB” property=”bookDetails” type=”database.BookDetails” /> /I[?TsXp  
g\sW2qXEw  
<font color=”red” size=”+2” > |&JCf =  
88fH !6b  
<%= messages.getString(“CartRemoved”) %> Az +}[t  
INca  
<strong><jsp:getProperty name=”book” property=”title” /></strong> p-]vf$u  
&\(p<TF  
</font> W/*2I3a  
,TrrqCw>  
当包含此tag的JSP页面被编译时,jsp引擎会自动生成关于此book的同步的代码(同步可以避免几个客户同时访问此book时造成的冲突),要生成同步代码,jsp引擎需要知道此脚本变量的如下信息: u,<#z0R|;$  
)vH6N_  
· 脚本变量名称 }6#lE,\lM  
>T*/[{L8;  
· 脚本变量所属的类 U68o"iE  
Uj!3H]d  
· 此脚本变量是否引用了一个新的或已存在的对象 /jJi`'{U  
tb;!2$  
· 此脚本变量的有效性 Rv9oK-S  
Uloa]X=Im8  
有两种办法可以向jsp引擎提供关于脚本变量的信息:在TLD中定义variable子元素,或用tei-class子元素定义一个额外tag信息类。用variable最简单,但可能降低了一些灵活性。 [kf$8 2  
!Pnvqgp/  
Variable元素 $[zy|Y(  
bzFwQi}>  
Variable元素有如下子元素: !acm@"Ea  
BR1oE3in  
· name-given ?D?D 给出的名字,是一个常量 l{U-$}  
O 0Fw!IQk  
· name-from-attribute?D?D 属性名,在编译时给出的属性名 W5a)`%H  
xf1@mi[a  
name-given或name-from-attribute两者必须选一,但以下子元素是可选的: rUC@Bf  
FI @!7@  
· variable-class?D?D变量的类型,缺省为java.lang.String。 YGy.39@31  
7P}&<;5zD  
· declare?D?D此脚本变量是否引用了一个新对象,缺省为True。 B+:'Ld](  
i7h!,vaK  
· scope?D?D脚本变量的范围,缺省为NESTED。下表描述了scope的几种类型: 6FMW}*6<  
x!CCSM;q  
脚本变量的有效范围 ?yKW^,q+  
?)=A[  
g~FA:R  
有效性 ya7/&Z )0  
方法 g70B22!y  
r+8%oWj  
NESTED r5ONAa3.  
在tag标签的开始和结束之间 WLr\ l29  
如果tag处理类实现BodyTag接口,则在doInitBody和doAfterBody中调用,否则在doStartTag中调用 5a moK7  
X}?`G?'  
AT_BEGIN #h'F6  
从tag标签的开始一直到页面结束 #7S[Ch}O  
如果tag处理类实现BodyTag接口,则在doInitBody、doAfterBody和doEndTag中调用,否则在doStartTag和doEndTag中调用 5&5 x[S8  
l4c9.'6  
AT_END ur\v[k=  
从tag标签的结束一直到页面结束 Sp+ zP-3  
在doEndTag中调用 ;q:.&dak1  
c`]_Q1'30w  
以struts为例,它的bean:define标签的实现遵循JSP1.1规范,此规范要求使用额外tag信息类来定义脚本变量。Variable元素是JSP1.2规范中加入的。以bean:define标签为例,你可以定义如下variable元素: {Lj]++`fB]  
NUVFG;  
<tag> 0eQwi l@  
_F|oL|  
<variable> a4gJ-FE  
%%["&  
<name-from-attribute>id</name-from-attribute> KCR6@{@  
<dxc"A  
<variable-class>database.BookDetails</variable-class> Ps3wg=ni[  
<ptZY.8N  
<declare>true</declare> 7TCY$RcF,I  
T_}9b  
<scope>AT_BEGIN</scope> t!MGSB~  
H+&c=~D\_  
</variable> {(r`&[  
w i,}sEoM  
</tag> yyZV/ x~  
-3 .Sr|t  
额外tag信息类 -eH5s3:A  
\W5fcxf  
如果要定义一个额外tag信息类,你要继承javax.servlet.jsp.TagExtraInfo类。一个TagExtraInfo类必须实现getVariableInfo方法,此方法返回一个叫VariableInfo的数组类,它包括如下信息: .Y}~2n  
(UW V#AR  
· 变量名 !Yx9=>R  
$q`650&S*  
· 变量所属类名 tHez S~t_  
M*|,05>  
· 此变量是否引用了一个新对象 )H&rr(  
d(u"^NH;  
· 此变量的有效范围 P !:LAb(  
xij`Mr  
jsp引擎将一个名为data的参数传给getVariableInfo方法,data中包括tag标签中的所有“属性名?D?D属性值”对。它可以用来向VariableInfo对象提供脚本变量的名字和类名。 =FXO1UZ!  
=b{wzx}e  
以struts为例,它在bean:define标签中定义了一个名为DefineTei的额外tag信息类,用来向脚本变量提供信息。由于脚本变量的名称(book)和类名(database.BookDetails)是通过tag标签的属性来传递的,它们一般定义在VariableInfo的构建代码中,并且可用data.getAttributeString方法来得到这些信息。如果要允许book脚本变量能在从tag开始直到整个JSP页面结束的范围内都可用的话,那它的范围应设为AT_BEGIN。如下所示: P@ Oq'y[  
m22FOjk\  
sJ{S(wpi"  
public class DefineTei extends TagExtraInfo <d".v  
3ZO\P u  
{ nCF1i2*6|"  
LadE4:oy  
public VariableInfo[] getVariableInfo(TagData data) df}DJB  
nH*JR  
{ R"NR-iU  
p^u;]~J O  
String type = data.getAttributeString(“type”); 1"pvrX}  
3 o=R_%r  
If( type == null) *3;H6   
hV,)u3  
type = “java.lang.Object”; ~(Wq 5<v  
/"w%?Ea  
return new VariableInfo[] { CmyCne   
R-Y07A  
new VariableInfo(data.getAttributeString(“id”), oWg"f*  
k+ Shhe1  
type, kXw&*B-/  
"`l8*]z  
true, 6\jhDP@`9  
neN #Mo'A  
VariableInfo.AT_BEGIN) V\U,PNkZQ  
7noxUGmFw  
}; wxy. &a]  
X?PcEAi;w  
} +6dq+8msF  
y8j wfO3  
} >K<n~;ON|  
a o"\L0;{  
UVND1XV^f  
注意:关于额外tag信息类的类名必须要在TLD中的tag标签下的tei-class子元素中定义。因此,DefineTei的tei-class中的定义看起来如下: Yyl(<,Yi  
<tei-class> x+niY;Z E  
org.apache.struts.taglib.bean.DefineTagTei `;?`XC"m  
</tei-class> WvV!F?uqZ  
%Z T@&  
8_yhV{  
具有协作关系的tag W dM?{; #  
H{ Fww4pn  
0$8iWL  
tag通过共享对象来进行协作,JSP技术支持2种方式的对象共享。 ma__LWKM,  
QtM9G@%  
第一种方法是使用pageContext对象进行对象的共享(可支持JSP页面和tag处理类之间的共享),如果在一个tag处理类中要调用由另一个tag处理类创建的对象,可调用pageContext.getAttribute(name, scope)方法。 ;- ~}g7$  
Fp3NWvu  
第二各方式的共享是对于tag之间有嵌套关系而言的,外层的tag所创建的对象对于内层的tag来说是可以共用的。这种形式的共享的好处是减少了可能存在的重名冲突。 OAGI|`E$/-  
C !a#M{:  
要访问一个嵌套tag创建的对象,tag处理类必须先找到此嵌套tag对象,可用TagSupport的静态方法 TagSupport.findAncestorWithClass(from, class)或TagSupport.getParent方法。前者在当不确定此tag是否为嵌套tag对象时使用。一旦它的父类被找到,它就能访问其所有动态或静态创建的对象。静态创建的对象是父类的成员,而动态创建的对象可能是父类的私有对象。诸如此类的对象可以用tag处理类的setValue方法来保存,用getValue方法来获得。 -+9,RtHR7  
tWD5Yh>.?$  
下例阐述了以上两种共享对象的方法。在这个例子当中,一个查询tag检查一个名为connection的属性名是否在doStartTag中被设置。如果connection属性被设置,tag处理类从pageContext中得到这个connection对象。否则,此tag处理类先找到它的父tag处理类,然后从它的父tag处理类中找到connection对象。 9fLxp$`(T  
{<f |h)r  
Yz6+ x]  
public class QueryTag extends BodyTagSupport *qM)[XO  
m-%.LDqM  
{ u">KE6um  
fa~4+jx>S  
private String connectionId; U]!~C 1cmw  
s/' ]* n  
public int doStartTag() throws JspException v[P $c$Xi  
Pra,r9h,  
{ 3<c_`BWu  
)#|I(Gz ^  
String cid = getConnection(); NR </Jm*  
Ft} h&aYP  
if(cid != null) ?4G/f<ou  
>fX_zowX  
{ IYZ$a/{P  
3m2hB%SNb  
//存在一个connection id,使用它。 $F^p5EXkc6  
ExJch\  
connection = (Connection) pageContext.getAttribute(cid); 'fIBJ3s[o  
|2ttdc.  
} aJAQ G  
> St]MS  
else \piHdVD  
,\2w+L5TD  
{ J 'qhY'te  
o3=2`BvJ  
ConnectionTag ancestorTag = (ConnectionTag)findAncestorWithClass(this, 1MVzu7  
^p@ #  
ConnectionTag.class); 8ux?K5_  
d :(&q  
if(ancestorTag == null) 5;:P^[cH9  
eyUhM jd  
{ P&3Z,f0  
^seb8o7  
throw new JspTagException(“一个没有connection属性的查询标签必须被一个connection标记嵌套。”); g`NJ `  
Ms * `w5n  
} !:zWhu,  
i'6>_,\(  
connection = ancestorTag.getConnection(); GxFmw:  
BAy]&q|.  
} wO>P< KBU  
d z-  
} RxeyMNd  
-c_}^j  
} xzI?'?duC  
klUW_d-  
:h(r2?=7  
pb`!_GmB  
此查询标签在JSP页面中的调用形式可以从以下2种定义中任选一种: mrc% 6Ri  
cq?&edjP  
p  K=  
<tt:connection id=”con01” ...> ... </tt:connection> zJxO\  
&@&0n)VTd  
<tt:query id=”balances” connection=”con01” > T^b62j'b5_  
PF6w'T 5  
SELECT account, balance FROM acct_table 7BNu.5*y  
MPS{MGVjbJ  
where customer_num = <%= request.getCustno() %> 3 $~6+i  
n"Gow/-;  
</tt:query> q8Z,XfF^S  
= nIl$9  
krt8yAkG  
=W*Js%4  
}\-"L/D?+  
<tt:connection ...> w%Bo7 'o)V  
8dBG ZwyET  
<x:query id=”balances”>  + f+#W  
<"}Gvi  
SELECT account, balance FROM acct_table Iz^lED  
ko Tb{UL  
where customer_num = <%= request.getCustno() %>  ~[wh  
#0F6{&; M  
</x:query> O)Wc\-  
df'xx)kW  
</tt:connection> >}?4;:.=  
X~#jx(0_  
EId_1F;V^  
与此同时,在TLD中必须指定connection属性为可选的,定义如下: OS.oknzZZ  
q%rfKHMA50  
<tag> XH"-sZt  
M8,_E\*  
... 0r|mg::'  
Da@H^  
<attribute> "&Y5Nh  
:t'*fHi~  
<name>connection</name> Wwf],Ya  
$@ R[$/  
<required>false</required> ,'FdUq)i  
Z2.S:y.  
</attribute> @y+Hb@ >.  
qh]ILE87(  
</tag>
描述
快速回复

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