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

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

级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
标准的JSP 标记可以调用JavaBeans组件或者执行客户的请求,这大大降低了JSP开发的复杂度和维护量。JSP技术也允许你自定义taglib,其实换句话说,taglib可以看成是对JSP标记的一种扩展,正如xml是对html的一种扩展一样。taglib通常定义在tag标签库中,这种标签库存放着你自己定义的tag标签。简而言之,如果使用taglib,那么你可以设计自己的JSP标记! Wp,R ^d  
v@pky0  
一般来说,自定义tag标签主要用于操作隐藏对象、处理html提交表单、访问数据库或其它企业级的服务,诸如邮件和目录操作等等。自定义tag标签的使用者一般都是那些对java编程语言非常精通,而且对数据访问和企业级服务访问都非常熟悉的程序员,对于HTML设计者来说,使得他可以不去关注那些较复杂的商业逻辑,而将精力放在网页设计上。同时,它也将库开发者和库使用者进行合理分工,自定义tag标签将那些重复工作进行封装,从而大大提高了生产力,而且可以使得tag库可用于不同的项目中,完美地体现了软件复用的思想。 )/P}?` I  
}m8q}~>tL  
在这篇文章中,我们主要讨论: uAk.@nfiEv  
?7A>+EY  
· 什么是自定义tag标签? $cg cX  
Hr C+Yjp  
· 怎么使用tag标签? t JmTBsn  
2 E= L8<  
o 声明要使用的tag库 ;VK.2^jW!  
~J]qP#C  
o 找到与之对应的tag处理类 qP ,EBE  
'"Nr,vQo  
o tag标签的类型 ~ri5zb20  
naNghGQ  
· 自定义tag标签  !@sUj  
p7 ~!z.)o  
o tag处理类 1;iUWU1@  
ry]l.@o;  
o tag库描述 {8etv:y  
HZOMlOZ  
o tag标签示例 ?]5qr?W%  
3g B7g'U  
o 带属性的tag 4Tc~b3\!Y  
)%]J>&/0J  
o 带body的tag 3' 'me  
IGgL7^MF  
o 定义了脚本变量的tag ,: ^u-b|  
{{1G`;|v 9  
o 具有协作关系的tag =MWHJ'3-/  
3c%caK  
· 自定义tag标签 g2]Qv@nxw  
u@444Vzg  
o 一个迭代tag的例子 `@%LzeGz  
X-/]IH DN  
o 一个模板tag库 3U}%2ARo_  
^f@=:eWI  
o tag处理类到底是怎样被调用的? [><Tm \(:  
Lj7AZ|k  
^^Vg~){4  
什么是自定义的tag? d_ CT $  
MOC/KNb  
一个自定义的tag标签是用户定义的一种JSP标记。当一个含有自定义的tag标签的JSP页面被jsp引擎编译成servlet时,tag标签被转化成了对一个称为tag处理类的对象进行的操作。于是当JSP页面被jsp引擎转化为servlet后,实际上tag标签被转化成为了对tag处理类的操作。 YZ7.1`8  
=lSNs   
自定义tag标签有很多特色,诸如: 7Yy ;  
/V By^L:  
· 可以在JSP页面中自定义tag标签的属性 ABkl%m6xf  
"jCu6Rjd  
· 访问JSP页面中的所有对象 < Z$J<]I  
3gzXbP,  
· 可以动态地修改页面输出 yQrD9*t&g  
7:~_D7n  
· 彼此这间可以相互通信。你可以先创建一个JavaBeans组件,然后在一个tag中调用此JavaBeans组件,同时可以在另一个tag中调用它。 q\)-BXw:  
T{'RV0%   
· tag允许相互嵌套,可以在一个JSP页面中完成一些复杂的交互。 Ca-j?bb!  
/Kbl%u  
{+Jv+J9  
使用tag标签 Hp?/a?\Xm  
#E]59_  
4K74=r),i  
本节主要描述怎样在JSP页面中使用tag标签,以及tag标签的不同类型。 *ui</+  
x^CS"v7  
要使用tag标签,JSP程序员必须做2件事: W l4%GB  
?ubro0F:  
· 声明此tag标签的tag库 5-M-X#(  
AwN!;t_0+N  
· 实现此tag标签 !'Kj x  
LQ% `c  
声明tag标签所在的tag库 \NC3'G:Ii  
nFn5v'g  
如果要使用tag标签,则应用JSP的taglib指示符来指定其tag库(注意:taglib要在在使用此tag标签之前声明) N g,j#  
}7X%'Bg=M  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> 5 dg(e3T  
p[cX O=  
uri属性定义了唯一的标签库描述(以下简称TLD),它可以是直接是tld文件名或一个独一无二的名字。prefix是用来区别其它TLD中和本TLD中有重名的tag的一种手段。 adw2x pj  
.(vwIb8\_  
TLD必须以.tld作为扩展名,并且存放在当前应用的WEB-INF目录或其子目录下。你可以通过它的文件名直接引用它,也可以通过别的方式间接地引用它。 %)wjR/o  
Hv, LS ;W  
以下taglib指示符直接引用一个TLD: 45oR=At n  
^}r1;W?n  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> 0IpmRH/  
r*Xuj=  
以下的taglib指示符通过一个逻辑名称间接地引用一个TLD: ;d?R:Uw8  
F[0]/  
<%@ taglib uri=”/tutorial-template” prefix=”tt” %> ~ K=b\xc^  
Mp]rUPK  
如果是间接引用TLD的话,那你必须还要在web.xml中定义此逻辑名称与tld文件之间的映射,具体做法是在web.xml中加入一个名为taglib的元素: pJ{Y lS{  
<vP=zk  
<taglib> ?# fQ~ s  
.^g p?  
<taglib-uri>/tutorial-template</taglib-uri> 'PHl$f*k  
+h$ 9\  
<taglib-location> cnLro  
 3CJwj  
/WEB-INF/tutorial-template.tld KTv$  
;Xw~D_uv  
</taglib-location> ;Qq\DFe.w  
=Sv/IXX\di  
</taglib> <uJ@:oWG7  
qWw=8Bq  
o(HbGHIP  
实现此tag标签 j<x_&1  
P*o9a  
;\]@K6m/Ap  
为了实现tag标签,你有2种方法来存放tag处理类。一、让tag处理类以.class的方式存放于当前应用的WEB-INF/class子目录下,二、如果tag处理类是以JAR包的形式存在的话,那可以放在当前应用的WEB-INF/lib目录下,如果tag处理类要在多个应用中共享,那么它就应放在jsp服务器上的common/lib目录下,对于tomcat来说,就是tomcat/common/lib目录下。 *`U~?q}  
0aAoV0fMDz  
He)%S]RLk  
tag标签类型 q:(%*sY>  
h$*!8=M  
Ls%MGs9PI  
自定义的tag标签遵循XML语法。它有一个开始标记和一个结束标记,有的还有body(即文本节点): [!z,lY>  
u4j5w  
<tt:tag>  XilS!,  
ix$bRdl  
body _j3fAr(V  
|{8Pb3#U  
</tt:tag> 626r^c=  
rGO8!X 3d  
:-'qC8C  
一个不带body的tag标签如下: ]{iQ21`a-  
36NpfTW  
<tt:tag /> v:U-6W_)|  
4Up/p&1@  
}'.m*#Y  
简单的tag标签 c|%6e(g"L  
^s=8!=A(  
一个没有body和属性的tag标签如下: L$-T,Kze  
9gFUaDLo  
<tt:simple /> $?Wb}DU7_L  
ys~x $  
7Wno':w8  
带属性的tag标签 pUTr!fR  
OCUr{Nh  
&vJH$R  
自定义标签可以有自己的属性。属性一般在开始标记中定义,语法为 attr=”value”。属性的作用相当于自定义标签的一个参数,它影响着tag处理类的行为。你可以在TLD中详细定义它。 G?ZXWu.  
;fJ.8C  
你可以用一个String常量给一个属性赋值,也可以通过表达式给它赋值,如<%= ...%>。以struts为例,它的logic:present标签就是用的String常量来给属性赋值: TN.rrop`#g  
uc=B,3  
<loglic:present parameter = “Clear”> Fp:'M X  
@VBcJ{e,  
而另一个标签logic:iterate是用表达式来给属性赋值: ~V-XEQA  
,'+kBZOv  
<logci:iterate collection=”<%= bookDB.getBooks() %>” +H.`MZ=  
<N)oS-m>  
id=”book” type=”database.BookDetails”> M{\I8oOg  
WM{=CD  
R@0R`Zs  
带body的tag标签 p[-O( 3Y  
G"6 !{4g  
一个自定义标签可以包含其它自定义标签、脚本变量、HTML标记或其它内容。 rZF*q2?  
:t[_:3@  
在下述例子中,此JSP页面使用了struts的logic:present标签,如果些标签定义了parameter=”Clear”的属性,则将清除购物车的内容,然后打印出一条信息: KP"+e:a%  
Rv=YFo[B  
<logic:present parameter=”Clear”> Vj-h;rB0z  
74u&%Rj  
<% cart.clear(); %> <[phnU^ 8  
sS Mh`4'  
<font color=”#ff0000” size=”+2”><strong> (ZGbh MK  
%RVZD#zr  
你选择了清除购物车! y(&Ac[foS}  
)7d&NE_  
</strong></font> j [a(#V{  
4JEpl'5^Q  
</logic:present> TV:9bn?r)  
} #J/fa9 !  
J05e#-)<K  
到底是用属性还是用body来传递信息? !W\+#ez  
7 &\yj9  
如上所述,我们既可以通过属性,也可以通过body来传递信息。但一般来说,比较简单的类型,如字符串或简单表达式最好采用属性来传递信息。 cR{#V1Z  
/{[o ~:'p  
mR~&)QBP.  
定义脚本变量的tag标签 : +u]S2u{  
XG?8s &  
所谓脚本变量,是指JSP中可以调用的变量或对象。它可由tag标签产生。以下示例阐述了一个tag标签定义了一个名为tx的由JNDI所定义的事务处理对象。脚本变量可以是ejb对象、事务、数据库连接等等: Fs{*XKv&lH  
omFz@  
<tt:lookup id=”tx” type=”UserTransaction” name=”java:comp/UserTransaction” /> @7u0v  
[m -bV$-d  
<% tx.begin(); %> pw#-_  
@L`jk+Y0vF  
... K'xV;r7Nt  
S @Y39  
7nSxi+6e  
具有协作关系的tag标签 fOHxtHM  
5N]"~w*  
自定义tag标签之间可以通过共享对象来实现协作。在下述例子中,标签tag1创建了一个名为obj1的对象,在标签tag2仍可以重复使用obj。 pdMc}=K  
@d_M@\r=j  
<tt:tag1 attr1=”obj1” value1=”value” /> KXrjqqXs  
Z,=1buSz_  
<tt:tag2 attr1=”obj1” /> Y@v>FlqI{  
*hrvYil2b  
在以下这个例子当中,如果外层的tag标签创建了一个对象,那么其内层的所有tag标签都可以使用这个对象。由于这样产生的对象没有一个指定的名字,那么就可以将少重名的冲突。这个例子阐述了一系列协作的嵌套对象。 Kq!3wb;  
yVfC-Z   
<tt:outerTag> vX>)je5#  
ta0|^KAA  
<tt:innerTag /> _GPe<H  
<%^&2UMg  
</tt:outerTag> Ni>[D"|  
Smh,zCc>s  
vI?, 47Hj+  
Tag处理类 [7-?7mp!B  
"7 yD0T)2  
yu|>t4#GT  
Tag处理类必须实现Tag接口或BodyTag接口,不过现在一般都流行从TagSupport或BodyTagSupport类中继承,这些类或接口都可以在javax.servlet.jsp.tagext包中找到。 TvM~y\s  
2eogY#  
当JSP引擎看到自己的JSP页面中包含有tag标签时,它会调用doStartTag方法来处理tag标签的开头,调用doEndTag方法来处理tag标签的结束。 q)GdD==  
maZ)cW?  
下表说明不同类型的tag所需要不同的处理过程: K}y f>'O  
xo)P?-  
Tag处理类的方法 RFGffA&  
:m;p:l|W  
Tag标签类型 54,er$$V  
所调用的方法 pCDmXB  
?0.NIu,,o  
基本标签 +3gp%`c4  
doStartTag, doEndTag, release =wJX 0A|  
<aw[XFg  
带属性的标签 !Cs_F&l"j  
doStartTag, doEndTag, set/getAttribute1...N, release qK+5NF|  
Sdo-nt  
带内容的标签 A,]h),b  
doStartTag, doEndTag, release l{9Y  
Wqnc{oq |$  
带内容的标签,且内容重复循环 x;S @bY  
doStartTag, doAfterBody, doEndTag, release S/ *E,))m  
gUlo]!$  
带内容的标签,且内容与JSP交互 [^)g%|W  
doStartTag, doEndTag, release, doInitBody, doAfterBody, release OI*H,Z "  
wkq 66?  
一个tag处理类可以通过javax.servlet.jsp.PageContext来与JSP交互,通过javax.servlet.jsp.PageContext类,tag处理类可以访问JSP中的request、session和application对像。 .}t e>]A*  
9$t( &z=  
如果tag标签是互相嵌套的,那内层的tag处理类可以通过它的parent属性来访问上层的tag处理类。 Gdw VtqbX  
@~e5<:|5#  
一般情况都将所有的tag处理类打成了JAR的包,以便于发布。 -=="<0c  
+vH4MwG$.&  
J,hCvm  
Tag库描述(简称TLD) mw!F{pw  
M:8R -c#![  
`uFdwO'DD  
Tag库是用xml语言描述的,TLD包括了tag库中所有tag标签的描述,它一般用来被jsp服务器用来校验tag的语法正确性,或者被jsp开发者用来开发新的标签。 {ax:RUQxy  
wJ]d&::@h  
TLD的文件扩展名必须为.tld,而且必须放在当前WEB应用的WEB-INF目录或其子目录中。 | Iib|HQ)  
^~dWU>  
一个TLD的内容的开头必须遵守标准的XML开头,用于描述DTD和xml的版本,例如: ]d]]'Hk  
dM5-;  
<?xml version="1.0" encoding="ISO-8859-1" ?> Q8NX)R  
e(sk[guvX  
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd"> 4Ig;3 ^%71  
TLD必须以<taglib>来作为它的根元素,<taglib>的子元素如下表: 7/H)Az@i45  
0f/<7R  
s1rCpzK0  
<taglib>的子元素 97]E1j]  
<} .$l  
Element hM{bavd  
Description NUZl`fu1Z4  
6<]lW  
tlib-version 8y L Y  
Tag库的版本 zda 3 ,U2o  
UZMd~|  
jsp-version hrn+UL:d  
Tag库所需要的jsp的版本 P?\6@_ Z  
@- xjfC\d  
short-name ^ y::jK  
助记符,tag的一个别名(可选) XUYtEf  
pkzaNY/q  
uri DrR@n~  
用于确定一个唯一的tag库 WY/}1X9.%  
?}0,o.  
display-name |N2#ItBbW  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) Za9qjBH   
tYS06P^<  
small-icon vt8By@]:  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) l;Wj]  
'NmRR]Q9  
large-icon ~a:  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) Oz95  
Pal=F0-Q\  
description /7kC<  
对tag库的描述(可选) +rd+0 `}C  
V&5wRz+`W  
listener =  [E  
参见下面listener元素 oxs#866x  
? k/`  
tag  @5FQX  
参见下面tag 元素 bw7@5=?;  
Ytkv!]"  
Listener元素 k:;r2f  
,F|f. 7;  
一个tag库可能定义一些类做为它的事件侦听类,这些类在TLD中被称为listener 元素,jsp服务器将会实例化这些侦听类,并且注册它们。Listener元素中有一个叫listener-class的子元素,这个元素的值必须是该侦听类的完整类名。 p2eGm-Erq  
}tz7b#  
Tag元素 [WmM6UEVS  
iMlWM-wz>O  
每个tag元素在tag库中都要指出它的名字、类名、脚本变量、tag的属性。其中脚本变量的值可以直接在TLD中定义或通过tag附加信息的类来取得。每个属性描述了这个属性是否可以省略,它的值是否可以通过<%= …%>这样的JSP语法来获得,以及属性的类型。 h0$iOE  
icgfB-1|i  
每一个tag在TLD中对应一个tag元素,下表是tag元素的子元素: l **X^+=$  
dH!*!r>  
Tag元素的子元素 U6K|fY N`  
UNYqft4  
元素名称 CTb%(<r  
描述 "sTRS*  
)8AXm  
name @]j1:PN-  
独一无二的元素名 A"]YM'.  
f#;>g  
tag-class iTwm3V P  
Tag标签对应的tag处理类 ;pAK_>  
GOPfXtkC  
tei-class ;p//QJB9  
javax.servlet.jsp.tagext.TagExtraInfo的子类,用于表达脚本变量(可选) LoV<:|GTI  
jp,4h4C^)  
body-content ]Um/FAW  
Tag标签body的类型 jd: 6:Fm  
 R&&4y 7  
display-name A^g(k5M*  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) Nb\4 /;#  
F5<H m_\:  
small-icon V0@=^Bls  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) Vr}'.\$  
l#o ~W`  
large-icon aN?zmkPpov  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) /: "1Z]@  
)`:UP~)H  
description ]Ze1s02(  
此tag标签的描述 \e*]Ls#jS  
4x34u}l  
variable %J(:ADu]  
提供脚本变量的信息(同tei-class)(可选) Y<OFsWYY  
G{}VPcrbC  
attribute @JMiO^  
Tag标签的属性名 C+$#y2"z#n  
$4LzcwG  
以下章节介绍对于不同类型的tag,如何具体地实现它们。 M3\AY30L  
79gT+~z   
N8jIMb'<  
简单的tag <~)P7~$d?p  
';CNGv -  
0mE 0 j  
tag处理类 Ud?Q%) X  
^qs $v06  
简单的tag处理类必须实现Tag接口的doStartTag和doEndTag方法。当jsp引擎碰到tag标签的开头时,doStartTag被调用,因为简单的tag没有body,所以此方法将返回 SKIP_BODY。当jsp引擎碰到tag标签的结尾时,doEndTag被调用,如果余下的页面还要被计算,那它将返回EVAL_PAGE,否则将会返回SKIP_PAGE。 tQ)qCk07  
_6Sp QW  
以下是例子:对于标签 <tt:simple /> ,它的tag处理类实现如下: B\~}3!j  
/uflpV|  
Z.,MVcd  
public SimpleTag extends TagSupport oA 1yIp  
y[;>#j$  
{ l?e.9o2-  
N~Jda o  
public int doStartTag() throws JspException r!v\"6:OM  
ch]IzdD  
{ #a#F,ZT  
KlEpzJ98  
try{ 7CysfBF0g  
:WEDAFq0  
pageContext.getOut().print(“Hello.”); C|bET  
>4TO=i  
}catch(Exception e){ i-1op> Y  
&C}*w2]0S  
throw new JspTagException(“SimpleTag: “ + e.getMessage()); =_CzH(=f#  
rq{$,/6.  
} }BEB1Q}L  
w;M#c Y  
return SKIP_BODY; OUnA;_  
vx =&QavL  
} #!=tDc &  
j 7B!h|  
public int doEndTag() )%TmAaj9d  
F,kZU$  
{ F59 TZI  
W9&=xs6  
return EVAL_PAGE; *. t^MP  
NEs:},)o  
} xT8?&Bx  
iZmcI;?u  
} 7V>M]  
X w1*(ffk  
*~`(RV  
注意:如果tag标签没有内容的话,那必须定义body-content元素为空,例如 h[ ZN+M  
kJU2C=m@e2  
<body-content>empty</body-content>  " bG2:  
u8^lB7!e/  
`[A];]  
带属性的tag标签
评价一下你浏览此帖子的感受

精彩

感动

搞笑

开心

愤怒

无聊

灌水
级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
只看该作者 1 发表于: 2007-01-01
tag处理类 DG/Pb)%Y  
f$( e\+ +  
对于tag标签的每个属性,你必须依照JavaBeans规范来定义其属性,以及get和set方法。以struts的logic:present 标签为例, ]:;&1h3'7  
iU-j"&L5  
<logic:present parameter=”Clear”> %O<BfIZ  
Cx"sw }  
与此相应,此tag处理类应有如下方法和定义: xno\s.H%]  
=1! 'QUc  
 _F{C\}  
protected String parameter = null; ~&O%N  
=N@t'fOr  
public String getParameter() }]Tx lSp!;  
I fir ,8  
{ INf&4!&h  
CLSK'+l  
return this.parameter; Xj*Wu_  
hZ3bVi)L\  
} E`q_bn  
#$vEGY}1  
public void setParameter(String parameter) 8L XHk l  
:gT4K-O j  
{ 13PS2  
k9R9Nz|J  
this.parameter = parameter; a.'*G6~Qgw  
^.tg7%dJ  
} GILfbNcd  
}G=M2V<L  
9L9sqZUB  
注意:如果你的属性名为id,而且你的tag处理类是从TagSupport类继承的,那你就不需要定义它的属性和set和get方法,因为他们早已在TagSupport被定义过了。 TC. ,V_  
(hsl~Jf  
Attribute元素 )"LJ hLg  
m|# y >4  
对于tag标签的每个属性,你必须定义它是否必须的,它的值是否可以用诸如<%= …%>的表达式来获得,以及它的类型(可选),如果不指定它的类型,那就默认为是java.lang.String类型。如果rtexprvalue元素被定义为true或yes,那么在type元素中就定义了attribute的返回类型。 NI5``BwpO  
fM}#ON>Z  
<attribute> E]6 6]+;0_  
Bx!-"e  
<name>attr1</name> _@g;8CA  
tkhCw/  
<required>true|false|yes|no</required> !wNO8;(  
l2d{ 73h  
<rtexprvalue>true|false|yes|no</rtexprvalue> l0] EX>"E  
4 :=]<sc,  
<type>attribute的返回类型(只用当rtexprvalue为真是才有效)</type> a?.=V  
@;kSx":b  
</attribute> |}1dFp  
hph4`{T  
如果tag的某个属性不是必须的,那tag处理类会自动提供一个缺省值。 h![#;>(  
Jwp7gYZ  
例如,在logic:present这个tag标签中定义了一个属性叫parameter,但它不是必须的,而且它可以被诸如<%= …%>的表达式来赋值。 M2|is ~  
CARzO7 b\w  
<tag> *=n:-  
l~.-e^p?  
<name>present</name> JRFtsio*  
+V+a4lU14  
<tag-class>org.apache.struts.taglib.logic.PresentTag</tag-class> /=h` L ,  
p'fYULYE  
<body-content>JSP</body-content> HDKbF/  
n(Uyz`qE  
h~26WLf.  
:EH=_"  
<attribute> /bEAK-  
"j-CZ\]U|  
<name>parameter</name> r/sNrB1U"y  
U&xUfBDt  
<required>false</required> J;%Xfx]  
_|]x2xb)  
<rtexprvalue>true</rtexprvalue> m,S{p<-h  
.B yuN  
</attribute> 7|D+Ihy;  
{[(h[MW#  
OTp]Xe/  
fV:83|eQ  
</tag> .o8t+X'G  
&R siVBA  
q =Il|Nb>  
属性元素的校验 H[UlY?&+  
w*!aZ,P  
ExM,g'7  
有关于tag标签的有效值可以从tag库的说明文档中获得,当JSP页面被编译时,jsp引擎会强制性地参照TLD中定义的规则进行检查。 !+njS  
DJ%PWlK5  
还有一个方法也可以进行属性元素的校验,就是先继承类TagExtraInfo,然后调用它的isValid方法。这个类同时也起到提供tag中定义的脚本变量信息的作用。 e%6QTg5#  
&?vgP!d&M  
IsValid方法通过TagData对象来传递属性信息,它包括着tag的所有的属性名-值的信息。由于校验发生在运行时刻,因此这个属性的值将被赋值为TagData.REQUEST_TIME_VALUE。 i&k7-<  
6Iw\c  
例如tag标签<tt:twa attr1=”value1” />在TLD中定义如下: TKjFp%  
 9a kH  
<attribute> x:7IIvP  
{|\.i  
<name>attr1</name> _w Ot39e&  
KF/-wZ"1s  
<required>true</required> '!$%> ||S  
H:G1BZjq  
<rtexprvalue>true</rtexprvalue> 66 Tpi![  
7 ?t6UPf  
</attribute> rH>)oThA#  
875od  
V$~9]*Wn  
这个定义说明了attr1能在运行期间被赋值。 3~ \[7I/  
d\Zng!Z'  
以下的isValid方法检查attr1属性的值是否属于Boolean类型。注意由于attr1能在运行刻被赋值,那么isValid方法必须检查tag用户是否对此tag进行了运行时刻赋值。 %UM *79  
8X0z~ &  
(ik\|y% A  
Public class TwaTEI extends TagExtraInfo >j`qh:^  
s <Fl p  
{ Wl Sm  
4fzZ;2sl}  
public boolean isValid(Tagdata data) FC*[*  
wAd9  
{ !by\9  ?n  
fT{Yg /j  
Object o = data.getAttribute(“attr1”); m4g$N)  
L-\GHu~)  
If(o != null && o != TagData.REQUEST_TIME_VALUE) go"Hf_  
Ru~j,|0r4  
{ d[35d J7F  
_2nx^E(pd  
if( ( (String)o).toLowerCase().equals(“true”) || ;$tSb ~K+  
Z8oK2Dw  
((String)o).toLowerCase().equals(“false”) ) ,(4K4pN  
ASfaX:ke  
return true; ]~nKK@Rw  
:aQt;C6Z>  
else m6djeOl  
Wm3X[?V  
return false; 9,tej  
 *,m;  
} ? qA]w9x  
r9lR|\Ax2U  
else @K]|K]cby  
*:NQ&y*uj  
return true; :lzrgsW  
_?OG1t!  
} JG,%qFlk  
MWL% Bz  
} 9mFE?J  
63A.@mL  
Yuc> fFA  
带body的tag m_l[MG\  
A4ygW:  
X|8c>_}  
tag处理类 m9A!D  
${)b[22":  
#=v~8  
如果tag标签含有内容,那处理方式会略微有些不同,而且还要视tag处理类是否要与body交互的情况而定。如果要与body交互,那我们认为tag处理类要可能要对body进行操作。 +U.I( 83F  
7!$^r$t   
Tag处理类不与body交互 -tNUMi'  
!YJs]_Wr  
如果tag处理类不与body交互,tag处理类应该实现Tag接口或从TagSupport中派生,如果body要被计算,那么doStartTag方法应返回 EVAL_BODY_INCLUDE,否则应返回SKIP_BODY。 T n}s*<=V  
_,d~}_$`i  
如果tag处理类要对body反复运算,则它应该实现IterationTag或从TagSupport中派生。如果tag处理类认为body还未计算完的话,那它的doStartTag方法和doAfterBody方法必须返回EVAL_BODY_AGAIN。 @fV9 S"TcM  
69 o 7EA  
Tag处理类与body交互 (b6NX~G-:  
+KEWP\r  
如果tag处理类与body交互,那tag处理类应实现BodyTag接口或从BodyTagSupport中派生。这种tag处理类一般要实现doInitBody和doAfterBody方法。 )tpL#J  
PY0j 9$i?  
Body允许一些方法来读写它的内容。Tag处理类可以调用body内容的getString或getReader方法来从body中提取信息,也可用 writeOut(out) 方法来将body的内容写入到out对象中。其中out对象通过tag处理类的getPreviousOut方法来获得。 o+9j?|M  
xRsWI!d+|  
如果body的内容需要被计算,那么doStartTag方法必须返回EVAL_BODY_BUFFERED,否则,它将返回 SKIP_BODY。 D)'bH5  
TW>WHCAm  
doInitBody 方法 *|E[L^  
XS BA$y  
此方法在body内容已经设好,但未被计算之前被调用。你可以根据不同的body内容来制定初始化策略。 uOGw9O-d9  
=kqt   
doAfterBody方法 :Lug7bUVD  
 JSg$wi8  
此方法在body内容已被计算后进行调用。 Y)a^(!<H<  
evJ.<{M  
和doStartTag方法一样,doAfterBody方法返回一个指示符指示是否要继续计算body,如果要继续计算,则doAfterBody应返回EVAL_BODY_BUFFERED,否则,它应返回SKIP_BODY。 vA.MRu#  
Zr,VR-kW+  
release 方法 +&"zU GTIc  
}-3mPy(*%  
tag处理类调用此方法将它的状态重置为初始状态,并释放所有的私有资源。 Uv~QUL3>  
n\.Vqe  
LYg- .~<I  
以下的例子读取body的内容(其中含有一条sql语句),然后将它传递给一个对象,让它进行查询。由于此处body不须重新计算,所以doAfterBody会返回SKIP_BODY。 HX{`Vah E  
&(mR> mT  
-FCe:iY! A  
Public class QueryTag extends BodyTagSupport \_6/vZ%-B  
-7(@1@1  
{ I,'k>@w{s  
@oad,=R&  
public int doAfterBody() throws JspTagException 7fX<511(  
- FlzEZ  
{ j9OG\m  
d&s9t;@=  
BodyContent bc = getBodyContent(); B !=F2  
gOOPe5+ J  
//将body的内容以字符串的格式提取出来 P_#bow  
l?^4!&Nm  
String query = bc.getString(); @k/NY *+  
g SAt@2*U2  
//清除body U~l$\ c  
Bn g@-#`/  
bc.clearBody(); y Ej^=pw  
`I5wV/%ib  
try{ [,KXze_m  
xpx\=iAe  
Statement stmt = connection.createStatement(); A6iq[b]  
Nl(3Xqov  
Result result = stmt.executeQuery(query); fe#\TNeQJ[  
D+7Rz_=  
}catch(SQLException e){ QS]1daMIK<  
}<y7bqA  
throw new JspTagException(“queryTag: “ + e.getMessage() ); @[i4^  
om-omo&,X=  
return SKIP_BODY; 3gj+%%!G\  
;?g6QIN9  
} ^Zy% fv,  
y {<9]'  
} M_w<m  
`P;s 8~  
|WdPE@P  
body-content元素 3J438M.ka  
yD6[\'%  
gy9U2Wgf|  
由于tag可能会有body,你必须用body-content元素来指定body内容的类型: _1L![-ac  
}:*]aL<7_  
<body-content>JSP|tagdependent</body-content> ~PahoRS  
 \qK&q  
?vHU #  
如果body的内容是定制的或内部的tag、脚本元素、或HTML广本,则归类为JSP类型。其他的类型,比如上面代码所述的?D?D将sql statement类传给 query tag的这种类型应该标为tagdependent。 :+|Z@KB  
[o5Hl^  
注意:实际上body-content的值并不影响tag处理类对body内容的处理,它仅仅是被tag编辑工具用来描述此body的内容。 rkY[E(SY  
A;|D:;x3G  
%zw1}|s#z  
用tags定义脚本变量 >q1L2',pK  
v(D;PS3r 7  
u4%Pca9(=  
tag处理类 Y6L ~K?  
W$ 2C47i  
 3 +fp2  
tag处理类负责创建或设置页面中定义的脚本变量,用pageContext.setAttribute(name,value,scope)或pageContext.setAttribute(name,value)方法来实现。一般来说,tag处理类通过脚本变量的名称来获取它,脚本变量的名称一般可用get方法来获得。 I[##2  
\1 &,|\E#  
如果脚本变量的值依赖于tag处理类中的上下文中某一对象,那它可用pageContext.getAttribute(name,scope)方法来找到那个对象。一般的处理过程是tag处理类先找到脚本变量,再对其进行处理,然后用pageContext.setAttribute(name,object)的方法来设置它的新值。 l9u!aD  
FA3~|Zg  
对象的生存周期(scope)如下表: EJ:%}HhA  
nl,uuc*;  
对象的生存周期表 s)Cjc.Qs  
e?=^;v%r  
名字 2eol gXp  
可访问范围 1.9}_4!  
生存周期 9dUravC7  
t#pS{.I  
page z}ddqZ27G$  
当前页面 qF-@V25P  
一直有效,除非页面向客户提交响应或重定向到一个新页面 W= qVc  
j578)!aJ  
request {_Rr 6  
当前页面或当前页面重定向到的页面 s^uS1  
一直有效,除非页面向客户提交响应 M |`U"vO  
`LE6jp3,  
session //<nr\oP  
当前页面或在同一浏览器窗口中的页面 28J^DMOW  
一直有效,除非关闭当前浏览器、超时、网络故障 hP)LY=- 2  
u'W8;G*~  
application |3[Wa^U5  
整个web应用程序的所有请求 ndz]cx  
一直有效,除非发生网络故障、服务器故障 vucxt }Ti  
Om@C X<(9C  
提供关于脚本变量的信息 2!J&+r  
 K;z7/[%  
以下示例定义了一个名为“book”的脚本变量,用来访问程序中关于书的信息: Uu(SR/R}  
V<uR>TD(  
<bean:define id=”book” name=”bookDB” property=”bookDetails” type=”database.BookDetails” /> z]?N+NHOA  
M`i\VG  
<font color=”red” size=”+2” > {I#]@,  
a^zibPG  
<%= messages.getString(“CartRemoved”) %> c%G{#}^2  
/M4{Wc  
<strong><jsp:getProperty name=”book” property=”title” /></strong> T iiWp!mX  
H>B&|BO_[  
</font> {U m)15K  
!F1N~6f  
当包含此tag的JSP页面被编译时,jsp引擎会自动生成关于此book的同步的代码(同步可以避免几个客户同时访问此book时造成的冲突),要生成同步代码,jsp引擎需要知道此脚本变量的如下信息: (HE9V]  
5Qn '  
· 脚本变量名称 ssRbhlD/*1  
E:}r5S) 4  
· 脚本变量所属的类 k$J zH$  
nV:LqF=  
· 此脚本变量是否引用了一个新的或已存在的对象 4$S;(  
/%TI??PGu  
· 此脚本变量的有效性 'JfdV%M  
lP@Ki5  
有两种办法可以向jsp引擎提供关于脚本变量的信息:在TLD中定义variable子元素,或用tei-class子元素定义一个额外tag信息类。用variable最简单,但可能降低了一些灵活性。 pd;br8yE$@  
(ECnM ti+  
Variable元素 ^ xh;  
LNpup`>`  
Variable元素有如下子元素: #32"=MfQn  
-pGE]nwDL  
· name-given ?D?D 给出的名字,是一个常量 Y>G@0r BG  
,TN 2  
· name-from-attribute?D?D 属性名,在编译时给出的属性名 kZZh"#W: L  
cm[&?  
name-given或name-from-attribute两者必须选一,但以下子元素是可选的: Dq5j1m.  
FrYqaP  
· variable-class?D?D变量的类型,缺省为java.lang.String。 p@5`& Em,  
vchm"p?9)  
· declare?D?D此脚本变量是否引用了一个新对象,缺省为True。 uPG4V2  
2fR02={-  
· scope?D?D脚本变量的范围,缺省为NESTED。下表描述了scope的几种类型: 2Mmz%S'd  
khrb-IY@  
脚本变量的有效范围 s,=i_gyPQ  
orfO^;qTY  
/! $c/QZ  
有效性 fM63+9I)\  
方法 ZUR6n>r  
4?7W+/~<&  
NESTED ytoo~n  
在tag标签的开始和结束之间 ps%q9}J  
如果tag处理类实现BodyTag接口,则在doInitBody和doAfterBody中调用,否则在doStartTag中调用 `t9?=h!  
dEA6   
AT_BEGIN O6/f5  
从tag标签的开始一直到页面结束 pd7NF-KD  
如果tag处理类实现BodyTag接口,则在doInitBody、doAfterBody和doEndTag中调用,否则在doStartTag和doEndTag中调用 ]0)|7TV*  
7=WT69,&  
AT_END (>GK \=:<  
从tag标签的结束一直到页面结束 zN@} #Hk  
在doEndTag中调用 b6F4>@gjg  
^1aAjYFn  
以struts为例,它的bean:define标签的实现遵循JSP1.1规范,此规范要求使用额外tag信息类来定义脚本变量。Variable元素是JSP1.2规范中加入的。以bean:define标签为例,你可以定义如下variable元素: ReI/]#Us  
Hp|_6hO 2  
<tag> 4 G-wd  
"a"]o  
<variable> -VTkG]{`Ir  
'BPp ]R#{  
<name-from-attribute>id</name-from-attribute> 7MHKeLq  
&LVn6zAba  
<variable-class>database.BookDetails</variable-class> jeX^}]x|%  
k_q0Q;6w!l  
<declare>true</declare> RUT,Y4 b  
FPI;Jx6W'  
<scope>AT_BEGIN</scope> ^[XYFQTL  
#Av.iAs  
</variable> ;@Z#b8aM}  
(B_\TdQ  
</tag> "xHgqgFyO  
OJ zs Q  
额外tag信息类 .!,z:l$Kh  
3G~@H>j  
如果要定义一个额外tag信息类,你要继承javax.servlet.jsp.TagExtraInfo类。一个TagExtraInfo类必须实现getVariableInfo方法,此方法返回一个叫VariableInfo的数组类,它包括如下信息: Z1Z1@2 T  
( %xwl  
· 变量名 Mo @C9Y0  
K7W6ZH9;  
· 变量所属类名 `~;rblo;  
@reeO=  
· 此变量是否引用了一个新对象 C@W"yYt  
,o,I5>`  
· 此变量的有效范围 h{p=WWK  
>ByXB!Wi+  
jsp引擎将一个名为data的参数传给getVariableInfo方法,data中包括tag标签中的所有“属性名?D?D属性值”对。它可以用来向VariableInfo对象提供脚本变量的名字和类名。 lh D,\3/O  
fKeT~z{~  
以struts为例,它在bean:define标签中定义了一个名为DefineTei的额外tag信息类,用来向脚本变量提供信息。由于脚本变量的名称(book)和类名(database.BookDetails)是通过tag标签的属性来传递的,它们一般定义在VariableInfo的构建代码中,并且可用data.getAttributeString方法来得到这些信息。如果要允许book脚本变量能在从tag开始直到整个JSP页面结束的范围内都可用的话,那它的范围应设为AT_BEGIN。如下所示: 5qoSEI-m  
K7Wk6Aw  
G\r?f&  
public class DefineTei extends TagExtraInfo FE! lok  
5~WGZc  
{ #ap9Yoyk\  
WT`4s  
public VariableInfo[] getVariableInfo(TagData data) @kU@N?5e  
eI:C{0p=  
{ xz{IH,?IG  
)Ocl=H|=  
String type = data.getAttributeString(“type”); Gz[fG  
G\Ro}5TO  
If( type == null) Adgc% .#  
H0SQ"?  
type = “java.lang.Object”; sx51X^d  
wqW 0v\  
return new VariableInfo[] { ~\3kx]^10  
Z(_ZAB%+D  
new VariableInfo(data.getAttributeString(“id”), *`Yv.=cd  
'ao"9-c  
type, s)2fG\1  
{aC!~qR  
true, &F5@6nJ`  
Bk\Gj`"7  
VariableInfo.AT_BEGIN) z,:a8LB#[  
njnDW~Snb  
}; Y.U[wL>  
T%n2$  
} {Gw.l."  
@%lBrM  
} zyg  }F  
e^Ky<*Y  
e$uiJNS2  
注意:关于额外tag信息类的类名必须要在TLD中的tag标签下的tei-class子元素中定义。因此,DefineTei的tei-class中的定义看起来如下: UNi`P9D]3  
<tei-class> "0k8IVwp  
org.apache.struts.taglib.bean.DefineTagTei P#/HTu5q7  
</tei-class> h=_0+\%  
v\"S Gc  
?9=9C"&s  
具有协作关系的tag Css l{B  
fH ?ha  
n?urE-_  
tag通过共享对象来进行协作,JSP技术支持2种方式的对象共享。 *(>}Y  
?8mlZ X9C  
第一种方法是使用pageContext对象进行对象的共享(可支持JSP页面和tag处理类之间的共享),如果在一个tag处理类中要调用由另一个tag处理类创建的对象,可调用pageContext.getAttribute(name, scope)方法。 U}l14  
zf>5,k'x'A  
第二各方式的共享是对于tag之间有嵌套关系而言的,外层的tag所创建的对象对于内层的tag来说是可以共用的。这种形式的共享的好处是减少了可能存在的重名冲突。 FwZ>{~?3  
U(;&(W"M  
要访问一个嵌套tag创建的对象,tag处理类必须先找到此嵌套tag对象,可用TagSupport的静态方法 TagSupport.findAncestorWithClass(from, class)或TagSupport.getParent方法。前者在当不确定此tag是否为嵌套tag对象时使用。一旦它的父类被找到,它就能访问其所有动态或静态创建的对象。静态创建的对象是父类的成员,而动态创建的对象可能是父类的私有对象。诸如此类的对象可以用tag处理类的setValue方法来保存,用getValue方法来获得。 aCxE5$~$  
LtKI3ou  
下例阐述了以上两种共享对象的方法。在这个例子当中,一个查询tag检查一个名为connection的属性名是否在doStartTag中被设置。如果connection属性被设置,tag处理类从pageContext中得到这个connection对象。否则,此tag处理类先找到它的父tag处理类,然后从它的父tag处理类中找到connection对象。 FSb Hn{@  
rf%7b8[v  
k8uvNLA)a  
public class QueryTag extends BodyTagSupport g@Qgxsyk>  
b (I2m  
{ PeE/iZ.  
2kUxD8BcN  
private String connectionId; iTg;7~1pY  
@b3#X@e}  
public int doStartTag() throws JspException }Lw>I94e  
u}|%@=xn  
{ >xn}N6Rj2~  
ulJX1I=|p  
String cid = getConnection(); n%\ /J  
2{.QjYw^  
if(cid != null) \S)2  
EmT`YNuc  
{ z5X~3s\dP  
n7YEG-J  
//存在一个connection id,使用它。 VCcr3Dx()F  
*I0-O*Xr  
connection = (Connection) pageContext.getAttribute(cid); rUjdq/I:Z  
oejfU;+$  
} M}wXJ8aF?  
5 VA(tzmCt  
else q0bHB_|wL  
?`Y\)'}   
{ %D`,k*X  
\rV B5|D?  
ConnectionTag ancestorTag = (ConnectionTag)findAncestorWithClass(this, D*Q.G8(  
5I@w~z  
ConnectionTag.class); 6k/U3&R  
DK&h eVIoZ  
if(ancestorTag == null) %&\jOq~  
Lh-`OmO0>F  
{ 45H!;Q sk  
ec|/ /  
throw new JspTagException(“一个没有connection属性的查询标签必须被一个connection标记嵌套。”); >u(>aV|A  
vkRi5!bR  
} a%Jx `hx  
<p?&udqD  
connection = ancestorTag.getConnection();  X}6#II  
*$M'`vj:  
} oiX"Lz{  
HOp-P8z  
} *X38{r j  
2spg?]  
} =4 X]gW  
^R$'eG 4L?  
fXQiNm[P  
;*[9Q'lI*  
此查询标签在JSP页面中的调用形式可以从以下2种定义中任选一种: 1SV^){5I  
NS,5/t  
Z2bcCIq4  
<tt:connection id=”con01” ...> ... </tt:connection> i$KpDXP\  
J%]D%2vnk`  
<tt:query id=”balances” connection=”con01” > ^5t  
Ut)r&?  
SELECT account, balance FROM acct_table 2_t=P|Uo  
9(!]NNf!  
where customer_num = <%= request.getCustno() %> cDXsi#Raj  
Sb:T*N0gS  
</tt:query> Us~ X9n_F  
!z zW2>  
qYp$fmj  
mEuHl>  
s2v(=  
<tt:connection ...> yO>V/5`  
WnAd5#G  
<x:query id=”balances”> 7e&\{*  
m$$?icA  
SELECT account, balance FROM acct_table h.whjiCFa  
*xM/ ;)  
where customer_num = <%= request.getCustno() %>  [&P`ak  
Cv=GZGn-  
</x:query> b]]N{: I  
t^tCA -  
</tt:connection> |@o6NZ<9N  
4o9$bv  
I 2HT2c$  
与此同时,在TLD中必须指定connection属性为可选的,定义如下: Cj;/Uhs  
G(1 K9{i$  
<tag> c~dM`2J,  
tO.$+4a  
... swpnuuC-  
"L2m-e6  
<attribute> ;' e@t8i6  
5`E))?*"Pe  
<name>connection</name> \T-~JQVj  
`HX3|w6W;  
<required>false</required> 1ZKzumF  
H"+c)FGi  
</attribute> chAan~r[*  
(=T$_-Dj`}  
</tag>
描述
快速回复

您目前还是游客,请 登录注册
欢迎提供真实交流,考虑发帖者的感受
认证码:
验证问题:
10+5=?,请输入中文答案:十五