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

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

级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
标准的JSP 标记可以调用JavaBeans组件或者执行客户的请求,这大大降低了JSP开发的复杂度和维护量。JSP技术也允许你自定义taglib,其实换句话说,taglib可以看成是对JSP标记的一种扩展,正如xml是对html的一种扩展一样。taglib通常定义在tag标签库中,这种标签库存放着你自己定义的tag标签。简而言之,如果使用taglib,那么你可以设计自己的JSP标记! W.'#pd  
$BXZFC_1S  
一般来说,自定义tag标签主要用于操作隐藏对象、处理html提交表单、访问数据库或其它企业级的服务,诸如邮件和目录操作等等。自定义tag标签的使用者一般都是那些对java编程语言非常精通,而且对数据访问和企业级服务访问都非常熟悉的程序员,对于HTML设计者来说,使得他可以不去关注那些较复杂的商业逻辑,而将精力放在网页设计上。同时,它也将库开发者和库使用者进行合理分工,自定义tag标签将那些重复工作进行封装,从而大大提高了生产力,而且可以使得tag库可用于不同的项目中,完美地体现了软件复用的思想。 !D!~4h)  
{P&{+`sov  
在这篇文章中,我们主要讨论: ^ Vso`(Ss  
M ~z A  
· 什么是自定义tag标签? ;:4&nJ*qG  
|-a5|3  
· 怎么使用tag标签? 7l/.f SW  
:PE{2*  
o 声明要使用的tag库 ikX"f?Q;S2  
WXV(R,*Tc  
o 找到与之对应的tag处理类 BKvX,[R2  
@a$_F3W  
o tag标签的类型 AJ}QS?p8s  
`<2k.aW4e8  
· 自定义tag标签 [% \>FT[  
VHyH't_&s  
o tag处理类 ,h,OUo]LIY  
l25_J.e  
o tag库描述 <:/Lap#D^  
Q6)Wh6Cm  
o tag标签示例 n_QSuh/Wn  
nWb*u  
o 带属性的tag 7^)8DwAl  
DcYL8u  
o 带body的tag i^T@jg+K  
{*mf Is  
o 定义了脚本变量的tag Pt5"q3ec{T  
W>TG!R 5  
o 具有协作关系的tag jV{?.0/h|  
IUf&*'_  
· 自定义tag标签 6<1 2j7  
#O 2g]YH  
o 一个迭代tag的例子 2iM]t&^<+  
-&q@|h'  
o 一个模板tag库 q8A;%.ZLG  
wnUuoX(  
o tag处理类到底是怎样被调用的? {=K);z  
BOt1J_;(rO  
+pUG6.j%  
什么是自定义的tag? >AK9F. _z  
?vt#M^Q   
一个自定义的tag标签是用户定义的一种JSP标记。当一个含有自定义的tag标签的JSP页面被jsp引擎编译成servlet时,tag标签被转化成了对一个称为tag处理类的对象进行的操作。于是当JSP页面被jsp引擎转化为servlet后,实际上tag标签被转化成为了对tag处理类的操作。 !0-KB#  
t 57MKDn  
自定义tag标签有很多特色,诸如: FEY_(70  
=hRo#]{(K  
· 可以在JSP页面中自定义tag标签的属性 HuT4OGBFpC  
90wGS_P04  
· 访问JSP页面中的所有对象 (aC~0 #4  
{ 9:vq|  
· 可以动态地修改页面输出 Xwp6]lx  
!$u:_8  
· 彼此这间可以相互通信。你可以先创建一个JavaBeans组件,然后在一个tag中调用此JavaBeans组件,同时可以在另一个tag中调用它。 8k{KnH  
e5AZU7%.  
· tag允许相互嵌套,可以在一个JSP页面中完成一些复杂的交互。 rEHlo[7^  
jOUM+QO  
MO^Q 8v  
使用tag标签  p!> 5}f6  
7 D(Eo{ue  
'VpzB s#  
本节主要描述怎样在JSP页面中使用tag标签,以及tag标签的不同类型。 E3hXs6P  
^'%Q>FVb  
要使用tag标签,JSP程序员必须做2件事: aT4I sPA?_  
9dVHh?E  
· 声明此tag标签的tag库 ~xLo0EV "  
a B$x(8pP@  
· 实现此tag标签 _Z>n y&   
Tw,|ZA4XH  
声明tag标签所在的tag库 bMq)[8,N  
/IQ$[WR cx  
如果要使用tag标签,则应用JSP的taglib指示符来指定其tag库(注意:taglib要在在使用此tag标签之前声明) lY&Sx{-  
|.z4VJi4  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> !J&UO/q.  
9!_JV;2  
uri属性定义了唯一的标签库描述(以下简称TLD),它可以是直接是tld文件名或一个独一无二的名字。prefix是用来区别其它TLD中和本TLD中有重名的tag的一种手段。 z"nMR_TTu  
::p%R@?  
TLD必须以.tld作为扩展名,并且存放在当前应用的WEB-INF目录或其子目录下。你可以通过它的文件名直接引用它,也可以通过别的方式间接地引用它。 Or#KF6+ut  
W(}2R>$  
以下taglib指示符直接引用一个TLD: uZM%F)  
KV8Ok  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %>  :yw8_D3  
llN/  
以下的taglib指示符通过一个逻辑名称间接地引用一个TLD: e ?7y$H-  
uZTbJ3$$  
<%@ taglib uri=”/tutorial-template” prefix=”tt” %> V%(T#_E/6  
0.S7uH%"  
如果是间接引用TLD的话,那你必须还要在web.xml中定义此逻辑名称与tld文件之间的映射,具体做法是在web.xml中加入一个名为taglib的元素: rf^ u&f  
i#NtiZ.t=  
<taglib> f?r{Q  
Sd F+b+P]  
<taglib-uri>/tutorial-template</taglib-uri> ]u^ybW"  
]SAGh|+xl  
<taglib-location> 4p7j "d5  
27i-B\r  
/WEB-INF/tutorial-template.tld NFyV02.  
#eF,* d  
</taglib-location> 4B9D  
G6}!PEwM  
</taglib> i=R%MH+  
Es- =0gpK  
k]A =Q  
实现此tag标签 ]XcWGQv~  
*0vRVlYf  
._]*Y`5)d  
为了实现tag标签,你有2种方法来存放tag处理类。一、让tag处理类以.class的方式存放于当前应用的WEB-INF/class子目录下,二、如果tag处理类是以JAR包的形式存在的话,那可以放在当前应用的WEB-INF/lib目录下,如果tag处理类要在多个应用中共享,那么它就应放在jsp服务器上的common/lib目录下,对于tomcat来说,就是tomcat/common/lib目录下。 Sz:PeUr9h  
\T[OF8yhW  
fRxn,HyV  
tag标签类型 ^;K"Y'f$  
R_9M-RP6*  
WZn"I& Z  
自定义的tag标签遵循XML语法。它有一个开始标记和一个结束标记,有的还有body(即文本节点): ]heVR&bQ  
qfdL *D  
<tt:tag> A#{I- *D[  
z}iz~WZ  
body 03A QB;.  
([|^3tM  
</tt:tag> uP$i2Cy  
P8#_E{f  
Xg l %2'  
一个不带body的tag标签如下: elR1NhB|p  
>Hmho'  
<tt:tag /> P9R-41!  
'SXLnoeTa  
~.6% %1?  
简单的tag标签 9=FH2|Z  
?9 W2ax-4  
一个没有body和属性的tag标签如下: cd~QGP_C  
(#x&Y#5  
<tt:simple /> e\O625  
rLY I\  
,$aqF<+;  
带属性的tag标签 \II^&xSF  
<IBUl}|\  
{u0sbb(  
自定义标签可以有自己的属性。属性一般在开始标记中定义,语法为 attr=”value”。属性的作用相当于自定义标签的一个参数,它影响着tag处理类的行为。你可以在TLD中详细定义它。 Z"KrirZ  
0C3Y =F  
你可以用一个String常量给一个属性赋值,也可以通过表达式给它赋值,如<%= ...%>。以struts为例,它的logic:present标签就是用的String常量来给属性赋值: [,;O$j}  
U6o]7j&6  
<loglic:present parameter = “Clear”> f =A#:d  
bdvpH DA  
而另一个标签logic:iterate是用表达式来给属性赋值: R&:Qy7"  
N/b$S@  
<logci:iterate collection=”<%= bookDB.getBooks() %>” 82V;J 8T?  
.Iz JJp  
id=”book” type=”database.BookDetails”> dj4a)p|YN  
$VP\Ac,!  
&LG|YvMY6  
带body的tag标签 KxBvL[/  
c/=\YeR  
一个自定义标签可以包含其它自定义标签、脚本变量、HTML标记或其它内容。 B/mfm 7  
({$rb-  
在下述例子中,此JSP页面使用了struts的logic:present标签,如果些标签定义了parameter=”Clear”的属性,则将清除购物车的内容,然后打印出一条信息: b\kA  
fN21[Jv3  
<logic:present parameter=”Clear”> 7VdxQ T  
[\%a7ji#  
<% cart.clear(); %> % .ss  
|oePB<N  
<font color=”#ff0000” size=”+2”><strong> ^; }Y ZBy  
Q~n%c7  
你选择了清除购物车! )nq(XM7  
?5^DQ|Hg ^  
</strong></font> dB QCr{7  
)T&r770  
</logic:present> ;#8xRLW  
T.B7QAI. H  
|Ho} D~  
到底是用属性还是用body来传递信息? @Jb-[W$*  
f]C^{Uk#  
如上所述,我们既可以通过属性,也可以通过body来传递信息。但一般来说,比较简单的类型,如字符串或简单表达式最好采用属性来传递信息。 \.GA" _y  
aZ|S$-}  
Fiw^twz5  
定义脚本变量的tag标签 ytV[x  
W'Y(@  
所谓脚本变量,是指JSP中可以调用的变量或对象。它可由tag标签产生。以下示例阐述了一个tag标签定义了一个名为tx的由JNDI所定义的事务处理对象。脚本变量可以是ejb对象、事务、数据库连接等等: <K>qK]|C  
,% .)mf  
<tt:lookup id=”tx” type=”UserTransaction” name=”java:comp/UserTransaction” /> j0n.+CO-{  
8%a ^j\L  
<% tx.begin(); %> EN,}[^Z  
+CXq41g"c  
... \J;]g\&I"  
YM.  
{h.j6  
具有协作关系的tag标签 ?+%bEZ`  
7&w[h4Lw  
自定义tag标签之间可以通过共享对象来实现协作。在下述例子中,标签tag1创建了一个名为obj1的对象,在标签tag2仍可以重复使用obj。 w6-<HPW<S  
~at:\h4:  
<tt:tag1 attr1=”obj1” value1=”value” /> WY5HmNX3E  
0xaK"\Q   
<tt:tag2 attr1=”obj1” /> :KGPQ@:O  
,Vof<,x0  
在以下这个例子当中,如果外层的tag标签创建了一个对象,那么其内层的所有tag标签都可以使用这个对象。由于这样产生的对象没有一个指定的名字,那么就可以将少重名的冲突。这个例子阐述了一系列协作的嵌套对象。 TZ}y%iU:mB  
o!c~"  
<tt:outerTag> g; 7u-nP  
5dbj{r)s6i  
<tt:innerTag /> x0%@u^BF  
.&8a ;Q?c  
</tt:outerTag> L!`PM.:9  
_NpxV'E  
C<w&mFozL  
Tag处理类 X/m~^  
O.8k [Ht  
lvLz){  
Tag处理类必须实现Tag接口或BodyTag接口,不过现在一般都流行从TagSupport或BodyTagSupport类中继承,这些类或接口都可以在javax.servlet.jsp.tagext包中找到。 aB`jFp-  
,pVe@d'  
当JSP引擎看到自己的JSP页面中包含有tag标签时,它会调用doStartTag方法来处理tag标签的开头,调用doEndTag方法来处理tag标签的结束。 !!cN4X  
#3A|Z=,5  
下表说明不同类型的tag所需要不同的处理过程: d'b9.ki\  
FC]n?1?<(  
Tag处理类的方法 o*oFCR]j  
.Sv/0&O  
Tag标签类型 Y.#fpG'  
所调用的方法 tX,x%(  
y'non0P.  
基本标签 *55unc  
doStartTag, doEndTag, release Ry?f; s  
d"Zyc(Jk  
带属性的标签 I8YCXh  
doStartTag, doEndTag, set/getAttribute1...N, release s%RG_"l  
Dt iM}=:  
带内容的标签 6)>otB8)J  
doStartTag, doEndTag, release >5D;uTy u  
Hxleh><c-  
带内容的标签,且内容重复循环 W! J@30  
doStartTag, doAfterBody, doEndTag, release /w2-Pgm-[\  
I~;H'7|e  
带内容的标签,且内容与JSP交互 yD@eT:lyi  
doStartTag, doEndTag, release, doInitBody, doAfterBody, release 8Dn~U :F/?  
0sB[]E|7[s  
一个tag处理类可以通过javax.servlet.jsp.PageContext来与JSP交互,通过javax.servlet.jsp.PageContext类,tag处理类可以访问JSP中的request、session和application对像。 @ rF|WT  
b/ h#{'  
如果tag标签是互相嵌套的,那内层的tag处理类可以通过它的parent属性来访问上层的tag处理类。 Lu5X~6j"$  
Y%>u.HzL  
一般情况都将所有的tag处理类打成了JAR的包,以便于发布。 kv;P2:"|  
tf[)| /M  
*d PbV.HCl  
Tag库描述(简称TLD) }]JHY P\  
!%.=35NS@E  
> `0mn|+  
Tag库是用xml语言描述的,TLD包括了tag库中所有tag标签的描述,它一般用来被jsp服务器用来校验tag的语法正确性,或者被jsp开发者用来开发新的标签。 %E"Z &_3{  
8DM! ]L  
TLD的文件扩展名必须为.tld,而且必须放在当前WEB应用的WEB-INF目录或其子目录中。 II Amx[ b  
%.onO0})  
一个TLD的内容的开头必须遵守标准的XML开头,用于描述DTD和xml的版本,例如: 'g3T'2"`5  
g!9|1z  
<?xml version="1.0" encoding="ISO-8859-1" ?> fPPmUM^C9  
?GW}:'z  
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd"> LWhP d\  
TLD必须以<taglib>来作为它的根元素,<taglib>的子元素如下表: n|KYcU#  
n7yp6 Db  
d[XMQX  
<taglib>的子元素 1l Cr?  
w4M;e;8m[U  
Element vu#ZLq  
Description )4m`Ya,E3  
V Ew| N)  
tlib-version ]hoq!:>M1  
Tag库的版本 ncUS8z  
OHrzN ']  
jsp-version jL'`M%8O  
Tag库所需要的jsp的版本 _uXb>V*8  
euVj,m  
short-name +.OdrvN4)  
助记符,tag的一个别名(可选) =%7s0l3z  
._Ww  
uri '4Fwh]Ee  
用于确定一个唯一的tag库 y%spI/(  
4 Tw~4b  
display-name h9#)Eo   
被可视化工具(诸如Jbuilder)用来显示的名称(可选) VxuV`Plf  
.{} 8mFi1  
small-icon P;mp)1C  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) j<k6z   
+jyGRSo  
large-icon M.r7^9P  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) 4e#$ -V   
HD/!J9&  
description ,v,rY'  
对tag库的描述(可选) z|X6\8f  
o. ;Vrc  
listener  o?m/  
参见下面listener元素 @un+y9m[C  
"WUS?Q  
tag [ ~2imS  
参见下面tag 元素 n|LpM.  
$(Mz@#%  
Listener元素 ~x#TfeU]  
-Ou.C7ol  
一个tag库可能定义一些类做为它的事件侦听类,这些类在TLD中被称为listener 元素,jsp服务器将会实例化这些侦听类,并且注册它们。Listener元素中有一个叫listener-class的子元素,这个元素的值必须是该侦听类的完整类名。 ?Rx(@  
#/f~LTE  
Tag元素 fe,6YXUf  
j7k}!j_O{  
每个tag元素在tag库中都要指出它的名字、类名、脚本变量、tag的属性。其中脚本变量的值可以直接在TLD中定义或通过tag附加信息的类来取得。每个属性描述了这个属性是否可以省略,它的值是否可以通过<%= …%>这样的JSP语法来获得,以及属性的类型。 y& 1@d+Lf  
#mA(x@:*  
每一个tag在TLD中对应一个tag元素,下表是tag元素的子元素: /:' >-253  
6/Xs}[iJ  
Tag元素的子元素 -p.\fvip  
F!wz{i6\h  
元素名称 9S*"={}%  
描述 T?t/[iuHrj  
$R1I(sJ  
name uMS+,dXy  
独一无二的元素名 wz*iwd-  
$t(v `,  
tag-class |#kY_d)10  
Tag标签对应的tag处理类 J5I@*f)l  
q`b6if"  
tei-class g}xL7bTlI>  
javax.servlet.jsp.tagext.TagExtraInfo的子类,用于表达脚本变量(可选)  pUb1#=  
IrqM_OjC  
body-content .Dr!\.hL  
Tag标签body的类型 0)332}Oh  
y]m: {  
display-name 49$<:{~  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) {;c'@U  
.qO4ceW2-~  
small-icon KBmOi  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) Wye* ~t  
|'nQvn:{  
large-icon L(VFzPkY%  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) f +{=##'0  
<m]0!ii  
description =cS&>MT  
此tag标签的描述 -AdDPWn  
iZ-R%-}B  
variable j|k/&q[St  
提供脚本变量的信息(同tei-class)(可选) w={q@. g%  
@MES.g  
attribute c$Kc,`2m7  
Tag标签的属性名 tQ|c.`)W  
mH&7{2r  
以下章节介绍对于不同类型的tag,如何具体地实现它们。 <+oh\y16  
i6'=]f'{  
CUu Owx6%  
简单的tag !C#oZU]P  
q!y.cyL  
@:C)^f"  
tag处理类 #'_#t/u  
mqZH<.mn  
简单的tag处理类必须实现Tag接口的doStartTag和doEndTag方法。当jsp引擎碰到tag标签的开头时,doStartTag被调用,因为简单的tag没有body,所以此方法将返回 SKIP_BODY。当jsp引擎碰到tag标签的结尾时,doEndTag被调用,如果余下的页面还要被计算,那它将返回EVAL_PAGE,否则将会返回SKIP_PAGE。 nK1eh@a9Qv  
.SD-6GVD  
以下是例子:对于标签 <tt:simple /> ,它的tag处理类实现如下: HAxLYun(3w  
$0_K&_5w~  
>^s2$@J?p  
public SimpleTag extends TagSupport 2/&=:,"t,B  
,|A^ <R`  
{ 1=R$ RI  
)D+BvJ Y"  
public int doStartTag() throws JspException }?s-$@$R  
E(~7NRRm  
{ 3W?7hh  
FS1\`#Bm)  
try{ 72dRp!J U  
/ox7$|Jyr  
pageContext.getOut().print(“Hello.”); u#76w74  
Lh[0B.g<  
}catch(Exception e){ jJ#D`iog5  
D S U`(`  
throw new JspTagException(“SimpleTag: “ + e.getMessage()); QLY;@-jF$  
4/ _jrZO  
} !mlfG "FE  
9O;Sn+  
return SKIP_BODY; u7< +)6-  
d{S'6*`D  
} /vSGmW-*  
\CjJa(vV  
public int doEndTag() Cqr{Nssu  
oco,sxT  
{ t2d sYU/  
}4C_r'd6  
return EVAL_PAGE; <=.6Z*x+  
Y#F.{ i  
} cY5&1Shb~  
RTmp$lV  
} Q!l(2nva  
 =yod  
o/{`\4  
注意:如果tag标签没有内容的话,那必须定义body-content元素为空,例如 +f/ I>9G  
rI$NNk'A  
<body-content>empty</body-content> *u+DAg'&  
: @|Rj_S;  
8jz>^.-o  
带属性的tag标签
评价一下你浏览此帖子的感受

精彩

感动

搞笑

开心

愤怒

无聊

灌水
级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
只看该作者 1 发表于: 2007-01-01
tag处理类 j@4MV^F2c  
%IO*(5f  
对于tag标签的每个属性,你必须依照JavaBeans规范来定义其属性,以及get和set方法。以struts的logic:present 标签为例, fqI67E$59  
N:lE{IvRJ  
<logic:present parameter=”Clear”> GQ1/pys  
f"7MYw\  
与此相应,此tag处理类应有如下方法和定义: 'w ,gYW  
vEI{AmogRx  
,7wYa&  
protected String parameter = null; gXI-{R7Me  
Mxl;Im]!`.  
public String getParameter() qt L]x -O  
y`oj\  
{ 4M&$wi  
uGZGI;9f4  
return this.parameter; ]$2 yV&V&  
k^cZePqE6d  
} $I9&cNPv  
3(oMASf  
public void setParameter(String parameter) 4$iS@o|  
M0$MK>  
{ *6yY>LW  
:6Z2@9.}w  
this.parameter = parameter; MFROAVPZ5  
'xta/@Sq  
} {dxFd-K3  
OB.rETg  
<eXGtD  
注意:如果你的属性名为id,而且你的tag处理类是从TagSupport类继承的,那你就不需要定义它的属性和set和get方法,因为他们早已在TagSupport被定义过了。 vb[0H{TT2  
dU9;sx  
Attribute元素 :!_l@=l  
2-@)'6"n  
对于tag标签的每个属性,你必须定义它是否必须的,它的值是否可以用诸如<%= …%>的表达式来获得,以及它的类型(可选),如果不指定它的类型,那就默认为是java.lang.String类型。如果rtexprvalue元素被定义为true或yes,那么在type元素中就定义了attribute的返回类型。 }Nr6oUn  
deAV:c  
<attribute> *OA(v^@tx7  
I/w;4!+)  
<name>attr1</name> 7G+!9^  
fNLO%\G~2  
<required>true|false|yes|no</required> Fj`k3~tUw  
HN7tIz@Frc  
<rtexprvalue>true|false|yes|no</rtexprvalue> x1Gx9z9  
d0B`5#4  
<type>attribute的返回类型(只用当rtexprvalue为真是才有效)</type> =Xvm#/  
* sldv  
</attribute> Lk|`\I T  
q;#AlquY@  
如果tag的某个属性不是必须的,那tag处理类会自动提供一个缺省值。 se.HA  
oh-EEo4,  
例如,在logic:present这个tag标签中定义了一个属性叫parameter,但它不是必须的,而且它可以被诸如<%= …%>的表达式来赋值。 &?y@`',a0{  
J.R]) &CB  
<tag> bVz<8b6h'-  
Sj I,v+  
<name>present</name> I=dn]}b#P  
pfZ[YC-  
<tag-class>org.apache.struts.taglib.logic.PresentTag</tag-class> S(CkA\[rz  
kBqgz| jE%  
<body-content>JSP</body-content> >TglX t+  
x%s1)\^A  
F5X9)9S  
qv(3qY  
<attribute> 8o+:|V~X  
l@&-be  
<name>parameter</name> &Z>??|f  
adu6`2 *$  
<required>false</required> 'Z#_"s#L  
a& 0g0n6  
<rtexprvalue>true</rtexprvalue> tm/ >H  
3|!3R'g/ >  
</attribute> c$,1j%[)  
4`"}0:t.  
TgjjwcO Y  
E} ]=<8V  
</tag> V'#R1x"3  
EUs9BJFP  
va_u4  
属性元素的校验 0^tY|(b3/M  
;6 W[%{  
3 1c*^ZE.  
有关于tag标签的有效值可以从tag库的说明文档中获得,当JSP页面被编译时,jsp引擎会强制性地参照TLD中定义的规则进行检查。 q#AIN`H  
OqS!y( (  
还有一个方法也可以进行属性元素的校验,就是先继承类TagExtraInfo,然后调用它的isValid方法。这个类同时也起到提供tag中定义的脚本变量信息的作用。 iS)-25M'  
Dqo#+_v  
IsValid方法通过TagData对象来传递属性信息,它包括着tag的所有的属性名-值的信息。由于校验发生在运行时刻,因此这个属性的值将被赋值为TagData.REQUEST_TIME_VALUE。 . s>@@m-  
%y9sC1T  
例如tag标签<tt:twa attr1=”value1” />在TLD中定义如下: J*b Je"8  
),vDn}>  
<attribute> #8M?y*<I  
T8Mqu`$r  
<name>attr1</name> y+k^CT/u  
f6K.F  
<required>true</required> _f";zd  
xi{ r-D8Z  
<rtexprvalue>true</rtexprvalue> L,.~VNy-  
I;"pPJ3G  
</attribute> al}J^MJ  
sM MtU@<x  
?e6>dNw  
这个定义说明了attr1能在运行期间被赋值。 \~A qA!)6  
VQqBo~  
以下的isValid方法检查attr1属性的值是否属于Boolean类型。注意由于attr1能在运行刻被赋值,那么isValid方法必须检查tag用户是否对此tag进行了运行时刻赋值。 "P#1=  
z]rr Q=dAA  
Lfi6b%/z  
Public class TwaTEI extends TagExtraInfo NjZ~b/  
hsY?og_H  
{ Z6${nUX  
v.<mrI#?  
public boolean isValid(Tagdata data) xE@/8h  
DFWO5Y_  
{ WN=0s  
8>[g/%W  
Object o = data.getAttribute(“attr1”); :p}8#rb  
.\_RavW23  
If(o != null && o != TagData.REQUEST_TIME_VALUE) 'o}[9ZBjn  
:!g|pd[{ag  
{ =[]6NjKS,  
{rR(K"M  
if( ( (String)o).toLowerCase().equals(“true”) || 2lsUCQI;  
hm73Zy  
((String)o).toLowerCase().equals(“false”) ) vb]kh _  
:sg}e  
return true; !Nx1I  
<7Pp98si,u  
else O_1[KiZ  
V2}\]x'1  
return false; I)'bf/6?  
1V1I[CxlX  
} ;9OhK71}  
gEj#>=s  
else |~BnE  
&$/ #"lW,V  
return true; cp(qaa  
;B=aK"\  
} T3P9  
q_.fVn:!  
} RN(I}]]a  
EWD^=VITL  
;Z{D@g+  
带body的tag uem-fTG  
nU_O|l9  
GVXdyi  
tag处理类 ^MvuFA ,C  
2; ^ME\  
e7U\gtZ.  
如果tag标签含有内容,那处理方式会略微有些不同,而且还要视tag处理类是否要与body交互的情况而定。如果要与body交互,那我们认为tag处理类要可能要对body进行操作。 PoF3fy%.  
[HQ)4xG  
Tag处理类不与body交互 @[3c1B6K  
o]oiJvOr  
如果tag处理类不与body交互,tag处理类应该实现Tag接口或从TagSupport中派生,如果body要被计算,那么doStartTag方法应返回 EVAL_BODY_INCLUDE,否则应返回SKIP_BODY。 0MHiW=  
"O jAhKfG  
如果tag处理类要对body反复运算,则它应该实现IterationTag或从TagSupport中派生。如果tag处理类认为body还未计算完的话,那它的doStartTag方法和doAfterBody方法必须返回EVAL_BODY_AGAIN。 0ae8Xm3J@R  
^OY]Y+S`Ox  
Tag处理类与body交互 [7v|bd  
Tzex\]fw  
如果tag处理类与body交互,那tag处理类应实现BodyTag接口或从BodyTagSupport中派生。这种tag处理类一般要实现doInitBody和doAfterBody方法。 >Wr%usNxc  
sApix=Lr  
Body允许一些方法来读写它的内容。Tag处理类可以调用body内容的getString或getReader方法来从body中提取信息,也可用 writeOut(out) 方法来将body的内容写入到out对象中。其中out对象通过tag处理类的getPreviousOut方法来获得。 o&q>[c  
@yuiNj .T  
如果body的内容需要被计算,那么doStartTag方法必须返回EVAL_BODY_BUFFERED,否则,它将返回 SKIP_BODY。 dDPQDIx  
-@#w)  
doInitBody 方法 [%.v;+L  
3%Y:+%VE  
此方法在body内容已经设好,但未被计算之前被调用。你可以根据不同的body内容来制定初始化策略。 >c,s}HJ  
xR1G  
doAfterBody方法 >aVgI<  
Ha@; Sz<R  
此方法在body内容已被计算后进行调用。 _>- D*l  
PE%$g\#?  
和doStartTag方法一样,doAfterBody方法返回一个指示符指示是否要继续计算body,如果要继续计算,则doAfterBody应返回EVAL_BODY_BUFFERED,否则,它应返回SKIP_BODY。 }g}Eh>U  
_M^.4H2  
release 方法 #V!a<w4_  
?"d$SK"6Z  
tag处理类调用此方法将它的状态重置为初始状态,并释放所有的私有资源。 TLdlPBnr8  
EA& 3rI>U)  
I^ ?tF'E  
以下的例子读取body的内容(其中含有一条sql语句),然后将它传递给一个对象,让它进行查询。由于此处body不须重新计算,所以doAfterBody会返回SKIP_BODY。 75^6?#GS  
1-_r\sb  
V_+&Y$msi~  
Public class QueryTag extends BodyTagSupport >d/H4;8  
0xB2  
{ @5%&wC  
^|Q]WHNFB  
public int doAfterBody() throws JspTagException x;/LOa{LR  
Y?0/f[Ax,y  
{ L:G#>  
-JMn?]  
BodyContent bc = getBodyContent(); K;?D^n.  
Gt`7i(  
//将body的内容以字符串的格式提取出来 m@4Dz|  
jJ ,_-ui  
String query = bc.getString(); DP ? d C`  
pO` KtagL  
//清除body gYKz,$  
:L[>!~YG_n  
bc.clearBody(); 3nxG>D7  
2xI|G 3U  
try{ >Fel) a  
#z `W ,^C  
Statement stmt = connection.createStatement(); .JhQxXj  
@YJI'Hf67  
Result result = stmt.executeQuery(query); yYG<tUG;  
P?54"$b  
}catch(SQLException e){ d1 j9{  
fr@F7s5}  
throw new JspTagException(“queryTag: “ + e.getMessage() ); ;a:H-iC  
hx;f/E Px  
return SKIP_BODY; +a1x;  
*ukyQZ9  
} wKV4-uyr  
rO1!h%&o"  
} rwm^{Qa  
%`Re {%1;  
hp\&g2_S0W  
body-content元素 ._mep\#.:  
Rj8%% G-pt  
c'2d+*[  
由于tag可能会有body,你必须用body-content元素来指定body内容的类型: A4K.,bZ   
mgs(n5V5  
<body-content>JSP|tagdependent</body-content> vvoxK0  
t}EM X9SQ  
xmW~R*^  
如果body的内容是定制的或内部的tag、脚本元素、或HTML广本,则归类为JSP类型。其他的类型,比如上面代码所述的?D?D将sql statement类传给 query tag的这种类型应该标为tagdependent。 z6>@9+V-&  
sDY~jP[Oa  
注意:实际上body-content的值并不影响tag处理类对body内容的处理,它仅仅是被tag编辑工具用来描述此body的内容。 sp9gz~Kq  
i!wU8 @  
eI #Gx_mg  
用tags定义脚本变量 %u -x9  
gv#\}/->4  
ny={OhP-  
tag处理类 o5<<vvdA  
cTqkM@S  
jN=<d q ~  
tag处理类负责创建或设置页面中定义的脚本变量,用pageContext.setAttribute(name,value,scope)或pageContext.setAttribute(name,value)方法来实现。一般来说,tag处理类通过脚本变量的名称来获取它,脚本变量的名称一般可用get方法来获得。 .R9Z$Kbq  
6% D9;-N)  
如果脚本变量的值依赖于tag处理类中的上下文中某一对象,那它可用pageContext.getAttribute(name,scope)方法来找到那个对象。一般的处理过程是tag处理类先找到脚本变量,再对其进行处理,然后用pageContext.setAttribute(name,object)的方法来设置它的新值。 d_RgKdR )k  
s}D>.9  
对象的生存周期(scope)如下表: }[*'  
x-^6U  
对象的生存周期表 *6uccx7{  
7ubz7*  
名字 1v o)]ff  
可访问范围 iyskADS  
生存周期 f0<zK !  
jvT'N@  
page 4#U}bN  
当前页面 {4"V)9o-1>  
一直有效,除非页面向客户提交响应或重定向到一个新页面 K %^n.  
xQy,1f3s+  
request !-gU~0  
当前页面或当前页面重定向到的页面 U=>S|>daR  
一直有效,除非页面向客户提交响应 R>Ra~ b  
c :R?da  
session @=J|%NO  
当前页面或在同一浏览器窗口中的页面 'U@o!\=a  
一直有效,除非关闭当前浏览器、超时、网络故障 [ oWkd_dK  
{]vD@)k  
application i`,FXF)  
整个web应用程序的所有请求 MB plhVK8  
一直有效,除非发生网络故障、服务器故障 ``o]i{x  
gN&i &%*!  
提供关于脚本变量的信息 w~'xZ?  
{.Tx70kn  
以下示例定义了一个名为“book”的脚本变量,用来访问程序中关于书的信息: Hl*vS  
AerU`^  
<bean:define id=”book” name=”bookDB” property=”bookDetails” type=”database.BookDetails” /> sFU< PgV  
Iq$| ?MH  
<font color=”red” size=”+2” > !^J;S%MB:K  
3? {AGJ1  
<%= messages.getString(“CartRemoved”) %> [B0 BHJ~  
_vQ52H,  
<strong><jsp:getProperty name=”book” property=”title” /></strong> nhI+xqfn  
yzK;  
</font> +z >)'#  
lFBdiIw  
当包含此tag的JSP页面被编译时,jsp引擎会自动生成关于此book的同步的代码(同步可以避免几个客户同时访问此book时造成的冲突),要生成同步代码,jsp引擎需要知道此脚本变量的如下信息: (Wzp sDte  
'uPAG;)m  
· 脚本变量名称 dBWny&  
)m%uSSx#  
· 脚本变量所属的类 _0H oJ  
4WT[(  
· 此脚本变量是否引用了一个新的或已存在的对象 O&%'j  
?HEqv$n  
· 此脚本变量的有效性  T:}Q3  
F!z0N&#  
有两种办法可以向jsp引擎提供关于脚本变量的信息:在TLD中定义variable子元素,或用tei-class子元素定义一个额外tag信息类。用variable最简单,但可能降低了一些灵活性。 f@*69a8  
nep#L>LP$x  
Variable元素 >CB-a :  
1ni+)p>]  
Variable元素有如下子元素: c-Gp|.C  
U ?[ (  
· name-given ?D?D 给出的名字,是一个常量 W"{Ggk `  
rxCzPF  
· name-from-attribute?D?D 属性名,在编译时给出的属性名 )>a~%~:  
{QG.> lB  
name-given或name-from-attribute两者必须选一,但以下子元素是可选的: Y&2FH/(M  
GT{4L]C  
· variable-class?D?D变量的类型,缺省为java.lang.String。 '|}A /`  
;QI9OcE@/  
· declare?D?D此脚本变量是否引用了一个新对象,缺省为True。 ( eV,f  
n,I3\l9  
· scope?D?D脚本变量的范围,缺省为NESTED。下表描述了scope的几种类型: dPUe5k)G_  
#UGSn:D<i  
脚本变量的有效范围 T"wg/mT  
U}92%W?  
IZVP-  
有效性 i_qY=*a?y  
方法 [ATJ! O  
WjD885Xo  
NESTED bWSN]]e1#  
在tag标签的开始和结束之间 !'f7;%7s  
如果tag处理类实现BodyTag接口,则在doInitBody和doAfterBody中调用,否则在doStartTag中调用 f*k7 @[rSv  
g`fG84  
AT_BEGIN @yp0WB  
从tag标签的开始一直到页面结束 4o>y9  
如果tag处理类实现BodyTag接口,则在doInitBody、doAfterBody和doEndTag中调用,否则在doStartTag和doEndTag中调用 4uF.kz-cg  
wAh]C;+{  
AT_END -^&=I3bp  
从tag标签的结束一直到页面结束 2|pTw5z~  
在doEndTag中调用 k 9i W1  
s-p)^B  
以struts为例,它的bean:define标签的实现遵循JSP1.1规范,此规范要求使用额外tag信息类来定义脚本变量。Variable元素是JSP1.2规范中加入的。以bean:define标签为例,你可以定义如下variable元素: ^*.[b  
Ft5A(P >  
<tag> v l"8Oi*r^  
x0j5D  
<variable> sXVl4!=l6  
]r`;89:s>  
<name-from-attribute>id</name-from-attribute> /x3*oO1  
T zL|{9  
<variable-class>database.BookDetails</variable-class> 7F<{ Qn  
'LgRdtO6  
<declare>true</declare> qbyYNlXqm  
z'l$;9(y  
<scope>AT_BEGIN</scope> Q,?_;,I}  
6_mi9_w  
</variable> St5;X&Q  
w=KfkdAJ*/  
</tag> Es>' N3A z  
[,;Y5#Y[5  
额外tag信息类 ElO|6kOBYG  
=.`\V]  
如果要定义一个额外tag信息类,你要继承javax.servlet.jsp.TagExtraInfo类。一个TagExtraInfo类必须实现getVariableInfo方法,此方法返回一个叫VariableInfo的数组类,它包括如下信息: gIo\^ktW  
a1pp=3Pd?~  
· 变量名 Sk{skvd;  
dD,}i$  
· 变量所属类名 aRTy=~  
=g+}4P  
· 此变量是否引用了一个新对象 eT b!xb  
Fz#@[1,  
· 此变量的有效范围 r<!hEWO>v  
] SJ#:7  
jsp引擎将一个名为data的参数传给getVariableInfo方法,data中包括tag标签中的所有“属性名?D?D属性值”对。它可以用来向VariableInfo对象提供脚本变量的名字和类名。 W.3b]zcV  
xPZ>vCg  
以struts为例,它在bean:define标签中定义了一个名为DefineTei的额外tag信息类,用来向脚本变量提供信息。由于脚本变量的名称(book)和类名(database.BookDetails)是通过tag标签的属性来传递的,它们一般定义在VariableInfo的构建代码中,并且可用data.getAttributeString方法来得到这些信息。如果要允许book脚本变量能在从tag开始直到整个JSP页面结束的范围内都可用的话,那它的范围应设为AT_BEGIN。如下所示: `r$7Cc$C  
sVx}(J  
puPI ^6y%  
public class DefineTei extends TagExtraInfo mZ71_4X#  
8-#kY}d.  
{ ^E^`"  
q|*^{(tWs  
public VariableInfo[] getVariableInfo(TagData data) !Cgj >=  
A}ZZQ  
{ 2E }vuw=c  
eN])qw{  
String type = data.getAttributeString(“type”); <0d2{RQ;  
0+SDFh  
If( type == null) PC9,;T&7_  
s4bV0k  
type = “java.lang.Object”; I )mB]j  
y#'hOSR2  
return new VariableInfo[] { vRe{B7}p;  
|aDBp  
new VariableInfo(data.getAttributeString(“id”), ko9}?qs  
m!7%5=Fc  
type, '3S~QN  
>!Yuef <P  
true, `XxnQng  
=TD`Pet  
VariableInfo.AT_BEGIN) 8m") )i-  
oPi>]#X  
}; coAXYn  
c'2/C5  
} .D W>c}1  
@jn&Wf?  
} ! AwMD  
Na91K4r#  
dJR[9T_OF  
注意:关于额外tag信息类的类名必须要在TLD中的tag标签下的tei-class子元素中定义。因此,DefineTei的tei-class中的定义看起来如下: k|-\[Yl.  
<tei-class> DMUirA;  
org.apache.struts.taglib.bean.DefineTagTei (H_dZL  
</tei-class> 4<Vi`X7[F  
(~DW_+?]'  
yz68g?"  
具有协作关系的tag x^K4&'</  
&3SS.&g4W  
-m@c{&r  
tag通过共享对象来进行协作,JSP技术支持2种方式的对象共享。 ko@ej^  
J];Sj  
第一种方法是使用pageContext对象进行对象的共享(可支持JSP页面和tag处理类之间的共享),如果在一个tag处理类中要调用由另一个tag处理类创建的对象,可调用pageContext.getAttribute(name, scope)方法。 m]jA(  
h,{Q%sqO  
第二各方式的共享是对于tag之间有嵌套关系而言的,外层的tag所创建的对象对于内层的tag来说是可以共用的。这种形式的共享的好处是减少了可能存在的重名冲突。 7i($/mNl  
9d"*Z%!j  
要访问一个嵌套tag创建的对象,tag处理类必须先找到此嵌套tag对象,可用TagSupport的静态方法 TagSupport.findAncestorWithClass(from, class)或TagSupport.getParent方法。前者在当不确定此tag是否为嵌套tag对象时使用。一旦它的父类被找到,它就能访问其所有动态或静态创建的对象。静态创建的对象是父类的成员,而动态创建的对象可能是父类的私有对象。诸如此类的对象可以用tag处理类的setValue方法来保存,用getValue方法来获得。 dWd%>9 }  
?TA7i b_  
下例阐述了以上两种共享对象的方法。在这个例子当中,一个查询tag检查一个名为connection的属性名是否在doStartTag中被设置。如果connection属性被设置,tag处理类从pageContext中得到这个connection对象。否则,此tag处理类先找到它的父tag处理类,然后从它的父tag处理类中找到connection对象。 ^BF}wQb :j  
MT/jpx  
+JErc)%  
public class QueryTag extends BodyTagSupport ZO/e!yju  
CE3l_[c  
{ b/_Zw^DPC  
}<WJR Y6j  
private String connectionId; eu5te0{G  
)|*Qs${tF  
public int doStartTag() throws JspException =n,;S W  
CFFb>d  
{ z)T-<zWO;  
EA~xxKq  
String cid = getConnection(); Zbnxs.i!  
Bj 7* 2}  
if(cid != null) ~IZ-:?+S^  
4r$#-  
{ wm@j(h4  
"-f]d~P>  
//存在一个connection id,使用它。 |!(8c>]Bo  
Fu.aV876\f  
connection = (Connection) pageContext.getAttribute(cid); A"S"La%"  
kZF]BPh.  
} GXZ="3W |  
437Wy+Q|e  
else {v*4mT  
F/2cQ .u2  
{ QjLU@?&  
q.J6'v lj/  
ConnectionTag ancestorTag = (ConnectionTag)findAncestorWithClass(this, ~ n<|f  
j#f/M3  
ConnectionTag.class); !5dn7Wuj  
u [qy1M0  
if(ancestorTag == null) lH3.q4D 5  
mH,s!6j?Vp  
{ TzC(YWt  
k$v 7@|Aw  
throw new JspTagException(“一个没有connection属性的查询标签必须被一个connection标记嵌套。”); W_XFTqp^  
#N`'hPD}  
} lSR\wz*Fk  
n`= S&oKH  
connection = ancestorTag.getConnection(); HVvm3qu4  
t'F$/mx.  
} 9]3l'  
_A]jiPq  
}  5V<6_o  
L\ysy2E0  
} @16y%]Q-E#  
w'}s'gGE  
[%>*P~6nK  
fyUW;dj  
此查询标签在JSP页面中的调用形式可以从以下2种定义中任选一种: PE7V1U#$o,  
pjO  
0(&uH0x  
<tt:connection id=”con01” ...> ... </tt:connection> Yaq0mef0  
RCqL~7C+ k  
<tt:query id=”balances” connection=”con01” > (a!E3y5,  
Q \X_JZ  
SELECT account, balance FROM acct_table W=2.0QmW  
=SJ[)|  
where customer_num = <%= request.getCustno() %> fx 08>r   
sUF5Y q:9  
</tt:query> [9?]|4  
*RkvM?o@jC  
~i^,Z&X:  
J'cE@(US  
ed,+Slg  
<tt:connection ...> ;$a|4_U$m  
\^F6)COy  
<x:query id=”balances”> ]Gl_L7u`  
Zo-Au  
SELECT account, balance FROM acct_table oQyMs>g  
?Wt_Obl  
where customer_num = <%= request.getCustno() %> UL7%6v{'*  
]H:K$nmX  
</x:query> @Ng q+uXm  
!/&~Feb  
</tt:connection> x2i`$iNhmP  
!x:w2  
:?%_JM5U  
与此同时,在TLD中必须指定connection属性为可选的,定义如下: zJ0'KHF}o  
"2"*3R<Y  
<tag> p|Fhh\,*`X  
ZG)C#I1;O  
... /=OSGIJzm  
U|h@Pw z  
<attribute> qj|B #dU  
a-TsD}'X  
<name>connection</name> #iGz&S3iN$  
xcIZ'V  
<required>false</required> Q^V`%+  
J2#=`|t"  
</attribute> H+2J.&Ch  
T{K+1SPy4  
</tag>
描述
快速回复

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