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

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

级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
标准的JSP 标记可以调用JavaBeans组件或者执行客户的请求,这大大降低了JSP开发的复杂度和维护量。JSP技术也允许你自定义taglib,其实换句话说,taglib可以看成是对JSP标记的一种扩展,正如xml是对html的一种扩展一样。taglib通常定义在tag标签库中,这种标签库存放着你自己定义的tag标签。简而言之,如果使用taglib,那么你可以设计自己的JSP标记!  p#[.{  
!-Y3V"  
一般来说,自定义tag标签主要用于操作隐藏对象、处理html提交表单、访问数据库或其它企业级的服务,诸如邮件和目录操作等等。自定义tag标签的使用者一般都是那些对java编程语言非常精通,而且对数据访问和企业级服务访问都非常熟悉的程序员,对于HTML设计者来说,使得他可以不去关注那些较复杂的商业逻辑,而将精力放在网页设计上。同时,它也将库开发者和库使用者进行合理分工,自定义tag标签将那些重复工作进行封装,从而大大提高了生产力,而且可以使得tag库可用于不同的项目中,完美地体现了软件复用的思想。 &/b~k3{M_  
%bfZn9_m  
在这篇文章中,我们主要讨论: 'n|5ZhXPB  
6^Sa;  
· 什么是自定义tag标签? kN>!2UfNS  
`"~%bS  
· 怎么使用tag标签? Sc   
ZC}QId  
o 声明要使用的tag库 FC*[*  
wAd9  
o 找到与之对应的tag处理类 B ZxvJQ  
fT{Yg /j  
o tag标签的类型 j.kG};f  
9/;P->wy  
· 自定义tag标签 z ]Ue|%K  
EE'!|N3  
o tag处理类 E"@wek.-  
9/7u*>:  
o tag库描述 cAc@n6[`3  
;>YzEo  
o tag标签示例 BB'OCN  
!a<ng&H^U  
o 带属性的tag +MLVbK  
gNhQD*+>{  
o 带body的tag KdlQ!5(?X  
Wm3X[?V  
o 定义了脚本变量的tag 9,tej  
 *,m;  
o 具有协作关系的tag XrPfotj1  
F>cv<l =6l  
· 自定义tag标签 @K]|K]cby  
]fD} ^s3G  
o 一个迭代tag的例子 8*fv'  
:eg4z )  
o 一个模板tag库 )WoxMmz  
.6V}3q$-@  
o tag处理类到底是怎样被调用的? ^I)N. 5  
e$pV%5=  
<9%R\_@$H  
什么是自定义的tag? g[t [/TV   
BSMwdr  
一个自定义的tag标签是用户定义的一种JSP标记。当一个含有自定义的tag标签的JSP页面被jsp引擎编译成servlet时,tag标签被转化成了对一个称为tag处理类的对象进行的操作。于是当JSP页面被jsp引擎转化为servlet后,实际上tag标签被转化成为了对tag处理类的操作。 V_:&S2j  
c=+!>Z&i$G  
自定义tag标签有很多特色,诸如: )0R'(#  
)Beiu*  
· 可以在JSP页面中自定义tag标签的属性 X|8c>_}  
m9A!D  
· 访问JSP页面中的所有对象 Ow077v ?  
ukY"+&  
· 可以动态地修改页面输出 pD74+/DD  
Bnd [X  
· 彼此这间可以相互通信。你可以先创建一个JavaBeans组件,然后在一个tag中调用此JavaBeans组件,同时可以在另一个tag中调用它。 9I/N4sou  
w\brVnt  
· tag允许相互嵌套,可以在一个JSP页面中完成一些复杂的交互。 B+0hzkPY  
hG:|9Sol,  
+H Usz ?  
使用tag标签 "}JZU!?  
!L8#@BjU  
$pudoAO  
本节主要描述怎样在JSP页面中使用tag标签,以及tag标签的不同类型。 +KEWP\r  
)tpL#J  
要使用tag标签,JSP程序员必须做2件事: i@ BtM9:  
QVE6We  
· 声明此tag标签的tag库 +H2-ZXr  
3Le{\}-$.  
· 实现此tag标签 w'3iY,_ufC  
-S+zmo8  
声明tag标签所在的tag库 Y5d\d\e/  
f4Rf?w*  
如果要使用tag标签,则应用JSP的taglib指示符来指定其tag库(注意:taglib要在在使用此tag标签之前声明) 0C*7K?/  
EU/8=JA1  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> `V3Fx{  
4NIRmDEd  
uri属性定义了唯一的标签库描述(以下简称TLD),它可以是直接是tld文件名或一个独一无二的名字。prefix是用来区别其它TLD中和本TLD中有重名的tag的一种手段。 S@ f9c  
_]*>*XfF(  
TLD必须以.tld作为扩展名,并且存放在当前应用的WEB-INF目录或其子目录下。你可以通过它的文件名直接引用它,也可以通过别的方式间接地引用它。 vA.MRu#  
&yol_%C  
以下taglib指示符直接引用一个TLD: vI)LB)Q  
27< Enq]  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> ,'iE;o{Tu  
Jdp3nzM^^@  
以下的taglib指示符通过一个逻辑名称间接地引用一个TLD: :Xd<74Nu  
* +wW(#[  
<%@ taglib uri=”/tutorial-template” prefix=”tt” %> \_6/vZ%-B  
-7(@1@1  
如果是间接引用TLD的话,那你必须还要在web.xml中定义此逻辑名称与tld文件之间的映射,具体做法是在web.xml中加入一个名为taglib的元素: [ps*uva  
jMDY(mwt  
<taglib> BI}Cg{^km  
3 SGDy]  
<taglib-uri>/tutorial-template</taglib-uri> E=w1=,/y  
14'45  
<taglib-location> 5Zva:  
.eP.&  
/WEB-INF/tutorial-template.tld z%LIX^q9  
HgkC~'  
</taglib-location> E`k@{*Hn&  
4X(H ;  
</taglib> C C^'@~)?  
}Ys >(w  
AZ}Xj>=  
实现此tag标签 '!a'ZjYyi  
d$AWu{y  
)D82N`c2\i  
为了实现tag标签,你有2种方法来存放tag处理类。一、让tag处理类以.class的方式存放于当前应用的WEB-INF/class子目录下,二、如果tag处理类是以JAR包的形式存在的话,那可以放在当前应用的WEB-INF/lib目录下,如果tag处理类要在多个应用中共享,那么它就应放在jsp服务器上的common/lib目录下,对于tomcat来说,就是tomcat/common/lib目录下。 .%C|+#&d  
#`X?=/q  
ApXy=?fc  
tag标签类型 :Qf '2.h)  
f.`*Qg L  
QW~1%`  
自定义的tag标签遵循XML语法。它有一个开始标记和一个结束标记,有的还有body(即文本节点): V}NbuvDB@  
'anG:=  
<tt:tag> lR6x3C H@  
kd$D 3S ^{  
body az|N-?u  
3gj+%%!G\  
</tt:tag> ;?g6QIN9  
0tB0@Wj  
 y%b F&  
一个不带body的tag标签如下: h.s+)fl\  
Vr1<^Ib  
<tt:tag /> bB;5s`-  
r!a3\ep  
^_5r<{7/ :  
简单的tag标签 gH3vk $WS  
{LQ#y/H?  
一个没有body和属性的tag标签如下: @<]Ekkg  
h@WhNk7"xa  
<tt:simple /> ">j j  
{Wu$YWE*sx  
SrK<fAkx  
带属性的tag标签 y e? 'Ze  
 XJ5 .  
rkY[E(SY  
自定义标签可以有自己的属性。属性一般在开始标记中定义,语法为 attr=”value”。属性的作用相当于自定义标签的一个参数,它影响着tag处理类的行为。你可以在TLD中详细定义它。 m&?r%x  
A1?2*W  
你可以用一个String常量给一个属性赋值,也可以通过表达式给它赋值,如<%= ...%>。以struts为例,它的logic:present标签就是用的String常量来给属性赋值: %lGfAYEM=  
p >t#@Eu|  
<loglic:present parameter = “Clear”> cX OK)g#  
=-lb)Z"d  
而另一个标签logic:iterate是用表达式来给属性赋值: u21EP[[,  
"djw>|,N<  
<logci:iterate collection=”<%= bookDB.getBooks() %>” tlp@?(u  
(%W&4a1di  
id=”book” type=”database.BookDetails”> 2WVka  
(<oy N7NT  
cFnDmt I:  
带body的tag标签 l.bYE/F0&  
'B0{_RaTb  
一个自定义标签可以包含其它自定义标签、脚本变量、HTML标记或其它内容。 Gvqxi|  
#!KE\OI;@5  
在下述例子中,此JSP页面使用了struts的logic:present标签,如果些标签定义了parameter=”Clear”的属性,则将清除购物车的内容,然后打印出一条信息: YgV817OV  
1.9}_4!  
<logic:present parameter=”Clear”> 4l45N6"  
t#pS{.I  
<% cart.clear(); %> z}ddqZ27G$  
zY!j:FT1HY  
<font color=”#ff0000” size=”+2”><strong> sC b=5uI  
=k0_eX0  
你选择了清除购物车! %vhnl'  
Z//+Gw<'  
</strong></font> z(^]J`+\  
)i^<r;_z  
</logic:present> aL&7 1^R,  
H_X [t*2  
!XCm>]R  
到底是用属性还是用body来传递信息? xZwLlY  
I\[_9  
如上所述,我们既可以通过属性,也可以通过body来传递信息。但一般来说,比较简单的类型,如字符串或简单表达式最好采用属性来传递信息。 |! E)GahM  
}YNR"X9*)/  
NI [ pp`  
定义脚本变量的tag标签 C-MjJ6D<  
zvH8^1yzG  
所谓脚本变量,是指JSP中可以调用的变量或对象。它可由tag标签产生。以下示例阐述了一个tag标签定义了一个名为tx的由JNDI所定义的事务处理对象。脚本变量可以是ejb对象、事务、数据库连接等等: | Aw%zw1@  
 Qq;Foa  
<tt:lookup id=”tx” type=”UserTransaction” name=”java:comp/UserTransaction” /> CZI66pDy  
%H&@^Tt a  
<% tx.begin(); %> m~d]a$KQ5-  
1@1U/ss1  
... =i*;VFc  
0dh aAq`k  
usCt#eZK  
具有协作关系的tag标签 4k_vdz  
.QJ5sgmh  
自定义tag标签之间可以通过共享对象来实现协作。在下述例子中,标签tag1创建了一个名为obj1的对象,在标签tag2仍可以重复使用obj。 c~uKsU  
4 f'V8|QM{  
<tt:tag1 attr1=”obj1” value1=”value” /> ,+xB$e  
c>RFdc:U  
<tt:tag2 attr1=”obj1” /> '*w00  
CtAwBQO  
在以下这个例子当中,如果外层的tag标签创建了一个对象,那么其内层的所有tag标签都可以使用这个对象。由于这样产生的对象没有一个指定的名字,那么就可以将少重名的冲突。这个例子阐述了一系列协作的嵌套对象。 u5 : q$P  
r^paD2&}  
<tt:outerTag> ~%=MpQ3  
5r8< 7g:>C  
<tt:innerTag /> pd;br8yE$@  
i?g5_HI  
</tt:outerTag> K&70{r  
LNpup`>`  
#32"=MfQn  
Tag处理类 %<*g!y `  
HbA kZP  
d>fkA0G/9!  
Tag处理类必须实现Tag接口或BodyTag接口,不过现在一般都流行从TagSupport或BodyTagSupport类中继承,这些类或接口都可以在javax.servlet.jsp.tagext包中找到。 P} SCF  
72y0/FJ  
当JSP引擎看到自己的JSP页面中包含有tag标签时,它会调用doStartTag方法来处理tag标签的开头,调用doEndTag方法来处理tag标签的结束。 oxkoA  
1Y@Aixx  
下表说明不同类型的tag所需要不同的处理过程: OFv%B/O  
TQ*1L:X7M&  
Tag处理类的方法 f@DYN!Z_m  
48qV >Gwf  
Tag标签类型 &c:Ad% z  
所调用的方法 M .JoHH  
sy"^?th}b  
基本标签 xt%7@/hiE  
doStartTag, doEndTag, release L3--r  
C=It* j55  
带属性的标签 7/f3Z 1g  
doStartTag, doEndTag, set/getAttribute1...N, release G) 7;;  
TbGn46!:  
带内容的标签 ,J>5:ht(6  
doStartTag, doEndTag, release WDPb!-VT  
3#&7-o  
带内容的标签,且内容重复循环 | >htvDL  
doStartTag, doAfterBody, doEndTag, release 6%Pdy$ P  
Vz~nT  
带内容的标签,且内容与JSP交互 |J} Mgb-4  
doStartTag, doEndTag, release, doInitBody, doAfterBody, release  L0@SCt  
uv(Sdiir8  
一个tag处理类可以通过javax.servlet.jsp.PageContext来与JSP交互,通过javax.servlet.jsp.PageContext类,tag处理类可以访问JSP中的request、session和application对像。 -Sx\Xi"<o=  
a]/>ra5{  
如果tag标签是互相嵌套的,那内层的tag处理类可以通过它的parent属性来访问上层的tag处理类。 L>%o[tS  
e5B Qr$j  
一般情况都将所有的tag处理类打成了JAR的包,以便于发布。 ~ga`\% J  
4V==7p x(  
#+5pgD2C  
Tag库描述(简称TLD) MLWM&cFG  
;\Y& ce  
9Hu/u=vB<  
Tag库是用xml语言描述的,TLD包括了tag库中所有tag标签的描述,它一般用来被jsp服务器用来校验tag的语法正确性,或者被jsp开发者用来开发新的标签。 !Kj,9NX{U  
X+}1  
TLD的文件扩展名必须为.tld,而且必须放在当前WEB应用的WEB-INF目录或其子目录中。 "4H +!r}  
^Z# W_R\l  
一个TLD的内容的开头必须遵守标准的XML开头,用于描述DTD和xml的版本,例如: V<@ o<R  
k"]dK,,  
<?xml version="1.0" encoding="ISO-8859-1" ?> _/!y)&4"  
;z:UN}  
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd"> \":m!K;Z  
TLD必须以<taglib>来作为它的根元素,<taglib>的子元素如下表:  &8_gRP  
<U >>ZSi  
1ilBz9x*!  
<taglib>的子元素 ;Q[mL(1:  
Upd3-2kr&J  
Element #KXa&C  
Description ;b(p=\i  
,%Up0Rr,  
tlib-version &PK\|\\2  
Tag库的版本 7`8Ik`lY  
BT"42#7_  
jsp-version aKuSd3E@#  
Tag库所需要的jsp的版本 h{p=WWK  
>ByXB!Wi+  
short-name 4^Q :  
助记符,tag的一个别名(可选)  {=QiZWu  
UE ,t8j  
uri x{c/$+Z[  
用于确定一个唯一的tag库 4NG?_D5&  
WRDjh7~Efn  
display-name wG< (F}VX  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) :!b'Vk  
5<j%EQN|D  
small-icon LLXVNO@e+  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) yH*6@P4:0=  
Zrr5csE  
large-icon ,|plWIl~  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) .?e\I`Kk^'  
x,S P'fcP  
description k]HEhY  
对tag库的描述(可选) )Ocl=H|=  
Gz[fG  
listener _b.qkTWUB  
参见下面listener元素 Adgc% .#  
)R  2.  
tag HcV"X,7S  
参见下面tag 元素 ]U7KLUY>:  
q)vplV1A  
Listener元素 /2Bi@syxK  
?6jkI2w  
一个tag库可能定义一些类做为它的事件侦听类,这些类在TLD中被称为listener 元素,jsp服务器将会实例化这些侦听类,并且注册它们。Listener元素中有一个叫listener-class的子元素,这个元素的值必须是该侦听类的完整类名。 'hv k  
qt^T6+faaQ  
Tag元素 ^=SD9V  
5-0{+R5v  
每个tag元素在tag库中都要指出它的名字、类名、脚本变量、tag的属性。其中脚本变量的值可以直接在TLD中定义或通过tag附加信息的类来取得。每个属性描述了这个属性是否可以省略,它的值是否可以通过<%= …%>这样的JSP语法来获得,以及属性的类型。 9*=W-v  
e|D ;OM  
每一个tag在TLD中对应一个tag元素,下表是tag元素的子元素: mL`5u f  
w{90`  
Tag元素的子元素 z7Eg5rm|QZ  
g HbxgeL  
元素名称 6 ]pX>Xho  
描述 -7&Gi +]  
D<X.\})Md  
name R% ,<\d7  
独一无二的元素名 ZwerDkd  
BQ2wnGc  
tag-class BC;:  
Tag标签对应的tag处理类 (N=5 .7"T  
{ e5/+W  
tei-class B8%{}[q  
javax.servlet.jsp.tagext.TagExtraInfo的子类,用于表达脚本变量(可选) GMZv RAu i  
{$^DMANDx  
body-content gzD@cx?V  
Tag标签body的类型 0 Ir<y  
CZt \JW+"  
display-name 2'<[7!  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) ld7v3:M  
R &4Z*?S  
small-icon -"[<ek  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) A4?+T+#d  
lP!;3iJ B  
large-icon WJ9 cZL  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) ^3FE\V/=  
{; >Q.OX@  
description P7f,OY<@%o  
此tag标签的描述 y&=ALx@  
(V%`k'N7f  
variable d k<XzO~g  
提供脚本变量的信息(同tei-class)(可选) NwR}yb6  
)Cw`"n  
attribute ;kJA'|GX  
Tag标签的属性名 g@Qgxsyk>  
b (I2m  
以下章节介绍对于不同类型的tag,如何具体地实现它们。 D^;*U[F?  
.*JA!B  
zb Z4|_  
简单的tag 'vaLUy9]  
.pvV1JA'  
RTu4@7XP  
tag处理类 wgRs Z  
T}=>C+3r  
简单的tag处理类必须实现Tag接口的doStartTag和doEndTag方法。当jsp引擎碰到tag标签的开头时,doStartTag被调用,因为简单的tag没有body,所以此方法将返回 SKIP_BODY。当jsp引擎碰到tag标签的结尾时,doEndTag被调用,如果余下的页面还要被计算,那它将返回EVAL_PAGE,否则将会返回SKIP_PAGE。 awUx=%ERtA  
=}:)y0L  
以下是例子:对于标签 <tt:simple /> ,它的tag处理类实现如下: BMIyskl=i  
@IP)S[^' t  
I;?X f  
public SimpleTag extends TagSupport y{a$y}7#X  
/Y2/!mU</  
{ F[!ckes<bB  
3u\;j; Td!  
public int doStartTag() throws JspException R1W}dRE}  
c$QX )V  
{ M}wXJ8aF?  
5 VA(tzmCt  
try{ FHPXu59u  
AisN@  
pageContext.getOut().print(“Hello.”); *VkgQ`c  
')$NfarQ.  
}catch(Exception e){ U70]!EaT  
PSmfiaThwo  
throw new JspTagException(“SimpleTag: “ + e.getMessage()); 0G2g4DSKD  
Zf>^4_x3P  
} KYxBVgJ  
@i3bgx>_o  
return SKIP_BODY; N=)z  
i o3yLIy,  
} a%Jx `hx  
5Y3i|cj  
public int doEndTag() -sMytHH.  
tB' V  
{ f0LP?]  
y9|K|xO[  
return EVAL_PAGE; <d7V<&@o=  
7.+#zyF  
} 9=/N|m8.  
[;b=A  
} kV Rn`n0  
/+3a n9h  
.M4IGOvOS  
注意:如果tag标签没有内容的话,那必须定义body-content元素为空,例如 5b6s4ZyV  
,s^<X85gp\  
<body-content>empty</body-content> 6dEyv99  
PZD>U)M  
ib0g3p-Lc  
带属性的tag标签
评价一下你浏览此帖子的感受

精彩

感动

搞笑

开心

愤怒

无聊

灌水
级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
只看该作者 1 发表于: 2007-01-01
tag处理类 KIVH!2q;  
,`8Y8  
对于tag标签的每个属性,你必须依照JavaBeans规范来定义其属性,以及get和set方法。以struts的logic:present 标签为例, '7im  
dy>|c j  
<logic:present parameter=”Clear”> - n6jG}01b  
RX2{g^V7  
与此相应,此tag处理类应有如下方法和定义: pD@zmCU  
fH8!YQG8$  
&VWlt2-R0h  
protected String parameter = null; Cv=GZGn-  
~L+]n0*  
public String getParameter() ^Dx#7bsDZR  
4rU! 4l  
{ G7* h{nE  
em]xtya  
return this.parameter; &4$oudn  
WO,xMfK  
} r5/R5Ga^  
u>Ki$xP1  
public void setParameter(String parameter) tO.$+4a  
swpnuuC-  
{ "L2m-e6  
:a< hQ|p  
this.parameter = parameter; } IlP:  
]5v:5:H  
} ? 4)v`*  
r[Zq3  
q?~Rnv  
注意:如果你的属性名为id,而且你的tag处理类是从TagSupport类继承的,那你就不需要定义它的属性和set和get方法,因为他们早已在TagSupport被定义过了。 3#<* k>1G?  
/ axTh  
Attribute元素 QlW=_Ymv{  
Z]-WFU_ N  
对于tag标签的每个属性,你必须定义它是否必须的,它的值是否可以用诸如<%= …%>的表达式来获得,以及它的类型(可选),如果不指定它的类型,那就默认为是java.lang.String类型。如果rtexprvalue元素被定义为true或yes,那么在type元素中就定义了attribute的返回类型。 s!6=|SS7  
p#_[  
<attribute> `!w^0kZ  
04 y!\  
<name>attr1</name> CM~MoV[k7e  
LI:T c7t  
<required>true|false|yes|no</required> ur2!#bU9  
e4qj .b  
<rtexprvalue>true|false|yes|no</rtexprvalue> ibF#$&!  
]X" / yAn  
<type>attribute的返回类型(只用当rtexprvalue为真是才有效)</type> LBX%HGH  
Wtv#h~jy9  
</attribute> <uF [,  
_qTpy)+  
如果tag的某个属性不是必须的,那tag处理类会自动提供一个缺省值。 pX<a2F P  
S>ugRasZ$  
例如,在logic:present这个tag标签中定义了一个属性叫parameter,但它不是必须的,而且它可以被诸如<%= …%>的表达式来赋值。 B[xR-6phW  
Xi~9&ed#$i  
<tag> '.p? 6k!K  
BQjam+u6  
<name>present</name> t^@T`2jL  
c#q"\"  
<tag-class>org.apache.struts.taglib.logic.PresentTag</tag-class> 6d{j0?mM  
?TuI:dC  
<body-content>JSP</body-content> "]]q} O?  
Dc FCKji  
R^Bk]  
} 21j  
<attribute> .u< U:*  
'>^Xqn  
<name>parameter</name> ( D}" &2  
|@`"F5@,  
<required>false</required> *:arva5  
Sa}D.SBg  
<rtexprvalue>true</rtexprvalue> bc}dYK3$q  
\X@IkL$r  
</attribute> 56s*A*z$ ;  
-fux2?8M  
dokuyiN\  
cjg=nTsBA  
</tag> dp^N_9$cdO  
v"k 4ATWP  
&]3:D  
属性元素的校验 yzc pG6 ,  
1!s28C5u  
*:QXz<_x+  
有关于tag标签的有效值可以从tag库的说明文档中获得,当JSP页面被编译时,jsp引擎会强制性地参照TLD中定义的规则进行检查。 piu0^vEEH  
8!j=vCv  
还有一个方法也可以进行属性元素的校验,就是先继承类TagExtraInfo,然后调用它的isValid方法。这个类同时也起到提供tag中定义的脚本变量信息的作用。 uJPH~mdW   
YZ[%uArm  
IsValid方法通过TagData对象来传递属性信息,它包括着tag的所有的属性名-值的信息。由于校验发生在运行时刻,因此这个属性的值将被赋值为TagData.REQUEST_TIME_VALUE。 &"j@79Ym1~  
!P"?  
例如tag标签<tt:twa attr1=”value1” />在TLD中定义如下: Ve14rn  
%vc'{`P  
<attribute> ^W['A]l  
MxN]7  
<name>attr1</name> .S|-4}G(6  
&PWf:y{R`  
<required>true</required> ^I./L)0= }  
{Tx 3$eU  
<rtexprvalue>true</rtexprvalue> K.h]JD]o  
Fd"WlBYy0  
</attribute> f%1wMOzx  
$SF3odpt  
Th+|*=Il  
这个定义说明了attr1能在运行期间被赋值。 hgj0tIi/  
k6g|7^es2  
以下的isValid方法检查attr1属性的值是否属于Boolean类型。注意由于attr1能在运行刻被赋值,那么isValid方法必须检查tag用户是否对此tag进行了运行时刻赋值。 <`mOU} 0 )  
S&|VkZR)  
td/5Bmj  
Public class TwaTEI extends TagExtraInfo nCB[4  
2))t*9;h  
{ KW:r;BFx  
y<uE-4  
public boolean isValid(Tagdata data) x9\J1\  
J=L`]XE  
{ GG>Y/;^  
A[RN-R,  
Object o = data.getAttribute(“attr1”); J/gQQ. s  
1Q_ ``.M  
If(o != null && o != TagData.REQUEST_TIME_VALUE) 7 NUenCdc  
WFpl1O73  
{ 6)+9G_  
q @*UUj@   
if( ( (String)o).toLowerCase().equals(“true”) || eHROBxH&  
WnO DDr  
((String)o).toLowerCase().equals(“false”) ) +cw{aI`a8  
U;>B7X;`E4  
return true; 9T]va]w?#  
C[W5d~@;E  
else YRu%j4Tx  
^~*8 @v""  
return false; H>Sf[8w)%  
UR\ZN@O  
} }9 FD/  
o5V`'[c  
else g` kZ T} h  
K5+!(5V~  
return true; %)dI2 J^Xf  
:3 PGf  
} 7ozYq_ $  
TwwIt5_fN  
} _jk|}IB;X  
]t7ClT)n!  
w=gQ3j#s  
带body的tag U!_sh<  
7~lB}$L  
6e&g$ R v  
tag处理类 kEx8+2s=M  
0vcET(  
#VQ36pCd  
如果tag标签含有内容,那处理方式会略微有些不同,而且还要视tag处理类是否要与body交互的情况而定。如果要与body交互,那我们认为tag处理类要可能要对body进行操作。 ! 7Nn ]Lx  
/;b.-v&  
Tag处理类不与body交互 x1:vUHwC  
lW&[mnR  
如果tag处理类不与body交互,tag处理类应该实现Tag接口或从TagSupport中派生,如果body要被计算,那么doStartTag方法应返回 EVAL_BODY_INCLUDE,否则应返回SKIP_BODY。 _4~k3%w\`l  
NywB 3  
如果tag处理类要对body反复运算,则它应该实现IterationTag或从TagSupport中派生。如果tag处理类认为body还未计算完的话,那它的doStartTag方法和doAfterBody方法必须返回EVAL_BODY_AGAIN。 j5'.P~  
2;O  c^  
Tag处理类与body交互 T?Z OHH8  
%pd5w~VP  
如果tag处理类与body交互,那tag处理类应实现BodyTag接口或从BodyTagSupport中派生。这种tag处理类一般要实现doInitBody和doAfterBody方法。 ?#U0eb5u  
`$f\ %  
Body允许一些方法来读写它的内容。Tag处理类可以调用body内容的getString或getReader方法来从body中提取信息,也可用 writeOut(out) 方法来将body的内容写入到out对象中。其中out对象通过tag处理类的getPreviousOut方法来获得。 %d ZM9I0  
JPHUmv6  
如果body的内容需要被计算,那么doStartTag方法必须返回EVAL_BODY_BUFFERED,否则,它将返回 SKIP_BODY。 a{5H33JA  
kzW\z4f  
doInitBody 方法  \8 g.  
1k0^6gE|  
此方法在body内容已经设好,但未被计算之前被调用。你可以根据不同的body内容来制定初始化策略。 xqU^I5Z  
-fhAtxkg  
doAfterBody方法 h#vL5At  
j}i,G!-u  
此方法在body内容已被计算后进行调用。 d|R HG  
D1"1MUSod  
和doStartTag方法一样,doAfterBody方法返回一个指示符指示是否要继续计算body,如果要继续计算,则doAfterBody应返回EVAL_BODY_BUFFERED,否则,它应返回SKIP_BODY。 9#s,K! !3{  
(=6P]~,  
release 方法 VvzPQk  
sn2r >m3  
tag处理类调用此方法将它的状态重置为初始状态,并释放所有的私有资源。 fYv ;TV>73  
5 1v r^  
DIL)7K4  
以下的例子读取body的内容(其中含有一条sql语句),然后将它传递给一个对象,让它进行查询。由于此处body不须重新计算,所以doAfterBody会返回SKIP_BODY。 D[+|^,^>  
=lYvj  
UU*0dSWr  
Public class QueryTag extends BodyTagSupport tbL1g{Dz,  
ks)fQFSbu  
{ LqMe'z  
7 _X&5ni  
public int doAfterBody() throws JspTagException #tCIuQ,  
e OO!jrT:  
{ C+}CU}  
zUvB0\{q  
BodyContent bc = getBodyContent(); i%#th'C!P  
5R$=^gE  
//将body的内容以字符串的格式提取出来 :Fw *r|  
?S+/QyjcfJ  
String query = bc.getString(); p{+tFQy  
i.B$?cr~  
//清除body {\ A_%  
^[k6]1h  
bc.clearBody(); K'>P!R:El  
l!xgtP K  
try{ IEKMa   
bEBZ!ghU  
Statement stmt = connection.createStatement(); h[vAU 9f)  
ke{DFq h  
Result result = stmt.executeQuery(query); $Vd?K@W[h  
qb#V)  
}catch(SQLException e){ _SU,f>  
d@_'P`%-  
throw new JspTagException(“queryTag: “ + e.getMessage() ); h#$ _<U  
M80}3mgP~  
return SKIP_BODY; _Y}^%eFw  
?z*W8b]'  
} j 8~Gv=(h  
}])G Q@  
} O~7p^i}  
>$d d 9|[  
J@=!w[v+  
body-content元素 eh8<?(eK  
@B}&62T  
Yb,G^+;  
由于tag可能会有body,你必须用body-content元素来指定body内容的类型: S(q4OQ B{  
e7)>U!9c9  
<body-content>JSP|tagdependent</body-content> j@kRv@  
0j-F6a*p'1  
VQZT.^  
如果body的内容是定制的或内部的tag、脚本元素、或HTML广本,则归类为JSP类型。其他的类型,比如上面代码所述的?D?D将sql statement类传给 query tag的这种类型应该标为tagdependent。 bQ${8ZO  
Udb0&Y1^  
注意:实际上body-content的值并不影响tag处理类对body内容的处理,它仅仅是被tag编辑工具用来描述此body的内容。 7lnM|nD  
gDUoc*+h  
s (l+{b &  
用tags定义脚本变量 tSw~_s_V  
> 2!^ dT^D  
Dg?Ho2ih  
tag处理类 ?STI8AdO  
#t5JUi%in*  
_dH[STT  
tag处理类负责创建或设置页面中定义的脚本变量,用pageContext.setAttribute(name,value,scope)或pageContext.setAttribute(name,value)方法来实现。一般来说,tag处理类通过脚本变量的名称来获取它,脚本变量的名称一般可用get方法来获得。 |\yDgs%EGy  
7z0;FW3>9  
如果脚本变量的值依赖于tag处理类中的上下文中某一对象,那它可用pageContext.getAttribute(name,scope)方法来找到那个对象。一般的处理过程是tag处理类先找到脚本变量,再对其进行处理,然后用pageContext.setAttribute(name,object)的方法来设置它的新值。 \`p|,j  
X"]mR7k  
对象的生存周期(scope)如下表: '6Rs0__  
URj% J/jD  
对象的生存周期表 hfP(N_""S  
VH$\ a~|  
名字 `UzCq06rJ1  
可访问范围 M[&.kH  
生存周期 TLR Lng  
ul]m>W  
page $)WH^Ir~  
当前页面 'PxL^  
一直有效,除非页面向客户提交响应或重定向到一个新页面 d@`-!"  
qrORP3D@  
request }VJ hw*s  
当前页面或当前页面重定向到的页面 Ezo" f  
一直有效,除非页面向客户提交响应 kG~ivB}x  
"X!_37kQ  
session -&HoR!af  
当前页面或在同一浏览器窗口中的页面 "1pZzad  
一直有效,除非关闭当前浏览器、超时、网络故障 b W`)CWd  
`rRg(fCN!M  
application _YD<Q@  
整个web应用程序的所有请求 +eH=;8  
一直有效,除非发生网络故障、服务器故障 (\AszLW  
iIC9rso"Q1  
提供关于脚本变量的信息 9h)P8B.>M  
).@)t:uNa  
以下示例定义了一个名为“book”的脚本变量,用来访问程序中关于书的信息: !*$'fn'bAA  
|x}&wFV  
<bean:define id=”book” name=”bookDB” property=”bookDetails” type=”database.BookDetails” /> )gm\e?^   
\t 7zMp  
<font color=”red” size=”+2” > +q>C}9s3  
&  t @  
<%= messages.getString(“CartRemoved”) %> rUJSzLy  
! a8h  
<strong><jsp:getProperty name=”book” property=”title” /></strong> Av[|.~g  
LO Yyj?^7  
</font> !'UsC6Y4  
Iclan\q#y  
当包含此tag的JSP页面被编译时,jsp引擎会自动生成关于此book的同步的代码(同步可以避免几个客户同时访问此book时造成的冲突),要生成同步代码,jsp引擎需要知道此脚本变量的如下信息: 'TEwU0<%  
NJz*N%VWD  
· 脚本变量名称 WA)lk>(+  
2{Lc^6i(t  
· 脚本变量所属的类 LVz%$Cq,0  
q@=#`746e  
· 此脚本变量是否引用了一个新的或已存在的对象 !15@M|,OL  
!IrKou)/_  
· 此脚本变量的有效性 5juCeG+Z  
Kk"B501  
有两种办法可以向jsp引擎提供关于脚本变量的信息:在TLD中定义variable子元素,或用tei-class子元素定义一个额外tag信息类。用variable最简单,但可能降低了一些灵活性。 TQyFF/K  
+k"8e?/e.  
Variable元素 {Rh+]=7  
_{@}Fd?o  
Variable元素有如下子元素: 1OJD\wc  
ok W)s*7  
· name-given ?D?D 给出的名字,是一个常量 6CzvRvA*P  
bB[*\  
· name-from-attribute?D?D 属性名,在编译时给出的属性名 vU=k8  
7dL=E"WL  
name-given或name-from-attribute两者必须选一,但以下子元素是可选的: p>hCh5  
rea}Uq+po  
· variable-class?D?D变量的类型,缺省为java.lang.String。 ?R~Ye  
yW7S }I  
· declare?D?D此脚本变量是否引用了一个新对象,缺省为True。 Y)-)NLLG;n  
P+ h<{%:*  
· scope?D?D脚本变量的范围,缺省为NESTED。下表描述了scope的几种类型: l2_E6U"  
5&7?0h+I  
脚本变量的有效范围 RM=+ZmA  
xsypIbN  
A_$Mt~qKi^  
有效性 W,eKQV<j  
方法 "{1}  
fCo2".Tk  
NESTED r  E *u  
在tag标签的开始和结束之间 X<bj2 w  
如果tag处理类实现BodyTag接口,则在doInitBody和doAfterBody中调用,否则在doStartTag中调用 ;Z<*.f'^fc  
{b8Y-  
AT_BEGIN Kps GQM  
从tag标签的开始一直到页面结束 w6%CB E2  
如果tag处理类实现BodyTag接口,则在doInitBody、doAfterBody和doEndTag中调用,否则在doStartTag和doEndTag中调用 Ab|NjY:  
bTYP{x~ y  
AT_END 0 GLB3I >  
从tag标签的结束一直到页面结束 b`%e{99\  
在doEndTag中调用 Xf/<.5A  
x#xO {  
以struts为例,它的bean:define标签的实现遵循JSP1.1规范,此规范要求使用额外tag信息类来定义脚本变量。Variable元素是JSP1.2规范中加入的。以bean:define标签为例,你可以定义如下variable元素: ?p\II7   
7m)ykq:?  
<tag> 7=[O6<+o  
J!gWRw5  
<variable> %)@(T ye -  
7]+'%Uwu)  
<name-from-attribute>id</name-from-attribute> t~=@r9`S  
IF21T  
<variable-class>database.BookDetails</variable-class> G6g=F+X2  
"I 1M$^8n  
<declare>true</declare> d}G."wnG9,  
At_Y$N:  
<scope>AT_BEGIN</scope> s)ajy^6'M  
1$!K2=%OXj  
</variable> @9Pn(fd]  
aLo>Yi  
</tag> YedipYG9;  
Wn</",Gf  
额外tag信息类 1OGv+b)  
g KY ,G  
如果要定义一个额外tag信息类,你要继承javax.servlet.jsp.TagExtraInfo类。一个TagExtraInfo类必须实现getVariableInfo方法,此方法返回一个叫VariableInfo的数组类,它包括如下信息: wEn&zZjx  
ktJLp Z<0O  
· 变量名 79fyn!Iz<  
BY2txLLB  
· 变量所属类名 %3B>1h9N  
.0/Z'.c 8  
· 此变量是否引用了一个新对象 E;e2{@SX2K  
7)X&fV6<8  
· 此变量的有效范围 Q`fA)6U  
aD`e]K ^L  
jsp引擎将一个名为data的参数传给getVariableInfo方法,data中包括tag标签中的所有“属性名?D?D属性值”对。它可以用来向VariableInfo对象提供脚本变量的名字和类名。 zU=[Kc=$  
p%qL0   
以struts为例,它在bean:define标签中定义了一个名为DefineTei的额外tag信息类,用来向脚本变量提供信息。由于脚本变量的名称(book)和类名(database.BookDetails)是通过tag标签的属性来传递的,它们一般定义在VariableInfo的构建代码中,并且可用data.getAttributeString方法来得到这些信息。如果要允许book脚本变量能在从tag开始直到整个JSP页面结束的范围内都可用的话,那它的范围应设为AT_BEGIN。如下所示: B=xZkc  
Cjb p-  
!ef)Ra-W  
public class DefineTei extends TagExtraInfo V0&QEul  
X-^Oz@.>  
{ ZQ8Aak  
Y2$`o4*3  
public VariableInfo[] getVariableInfo(TagData data) 5rSth.&  
aWK7 -n  
{ \crmNH)3  
X-WvKH(=w  
String type = data.getAttributeString(“type”); fmyS# 6"  
dfd%A" I  
If( type == null) B{u.Yc:  
r_CN/a  
type = “java.lang.Object”; v~=ol8J B  
eEFT(e5.>3  
return new VariableInfo[] { eWs^[^c.<  
jWCC`0 T  
new VariableInfo(data.getAttributeString(“id”), <qiap2  
enepAu-="p  
type, I!#^F 1p1  
6E&&0'm  
true, Wm/k(R`O<  
akoKx)(<  
VariableInfo.AT_BEGIN) ZdzGJ[$  
4v JIO{m  
}; ?5M2DLh~  
YZJP7nN  
} $e\R5L u  
0]W/88ut*u  
} OH~qJ <  
'0?E|B]Cp%  
bHG>SW\]`?  
注意:关于额外tag信息类的类名必须要在TLD中的tag标签下的tei-class子元素中定义。因此,DefineTei的tei-class中的定义看起来如下: ?':'zT  
<tei-class> ~hX'FV  
org.apache.struts.taglib.bean.DefineTagTei ~Q]M_,`M  
</tei-class> cK/odOi  
>QPS0Vx[  
$~\qoW<  
具有协作关系的tag D(GHkS*0q  
>FhBl\oIi  
 X;g|-<  
tag通过共享对象来进行协作,JSP技术支持2种方式的对象共享。 >,1LBM|0u  
Y5 pNKL  
第一种方法是使用pageContext对象进行对象的共享(可支持JSP页面和tag处理类之间的共享),如果在一个tag处理类中要调用由另一个tag处理类创建的对象,可调用pageContext.getAttribute(name, scope)方法。 {1c eF  
(9%%^s]uPT  
第二各方式的共享是对于tag之间有嵌套关系而言的,外层的tag所创建的对象对于内层的tag来说是可以共用的。这种形式的共享的好处是减少了可能存在的重名冲突。 <H#K`|Ag  
j3F=P  
要访问一个嵌套tag创建的对象,tag处理类必须先找到此嵌套tag对象,可用TagSupport的静态方法 TagSupport.findAncestorWithClass(from, class)或TagSupport.getParent方法。前者在当不确定此tag是否为嵌套tag对象时使用。一旦它的父类被找到,它就能访问其所有动态或静态创建的对象。静态创建的对象是父类的成员,而动态创建的对象可能是父类的私有对象。诸如此类的对象可以用tag处理类的setValue方法来保存,用getValue方法来获得。 *mt v[  
r4zS,J;,  
下例阐述了以上两种共享对象的方法。在这个例子当中,一个查询tag检查一个名为connection的属性名是否在doStartTag中被设置。如果connection属性被设置,tag处理类从pageContext中得到这个connection对象。否则,此tag处理类先找到它的父tag处理类,然后从它的父tag处理类中找到connection对象。 $*ZHk0 7x  
YiMecu  
J'v|^`bE  
public class QueryTag extends BodyTagSupport zW.sXV,  
CAO{$<M5m  
{ MQu6Tm H  
vnpX-c  
private String connectionId; W5{e.eI}|  
n&JP/P3Y  
public int doStartTag() throws JspException dy'?@Lj;  
b@Cvs4  
{ 8tk`1E8!j  
HDxw2nz*R  
String cid = getConnection(); &*SnDuc  
}(6k7{,Gw,  
if(cid != null) .? / J  
zvj\n9H  
{ ~VKXL,.  
$T0[  
//存在一个connection id,使用它。 sP7(1)\  
n!nv.-n  
connection = (Connection) pageContext.getAttribute(cid); L1BpY-=  
'z:p8"h}  
}  X'<xw  
;C%EF  
else b*i+uV?  
&kBs'P8>  
{ !8].Z"5J  
^(3k uF  
ConnectionTag ancestorTag = (ConnectionTag)findAncestorWithClass(this, `Ea3z~<7M  
yuB BO:\.  
ConnectionTag.class); C~*m&,@TT^  
B*7o\~5  
if(ancestorTag == null) h'+ swPh  
}rZp(FG@*  
{ g<Xwk2_=g  
2} -W@R  
throw new JspTagException(“一个没有connection属性的查询标签必须被一个connection标记嵌套。”); Tc :`TE=2  
AJ mzg  
} 5[k35 c{  
\;<Y/sg  
connection = ancestorTag.getConnection(); 5**xU+&  
xl$ Qw'  
} 0Og =H79<  
I6_+3}Hm{  
} oxZ(qfjS  
~c"c9s+o  
} y-mmc}B>N  
xC(PH?_  
^8)d8?}  
*k -UQLJ  
此查询标签在JSP页面中的调用形式可以从以下2种定义中任选一种: Z"u/8  
$9/r*@bu8d  
$}@l l^  
<tt:connection id=”con01” ...> ... </tt:connection> Yc}b&  
\T?O.  
<tt:query id=”balances” connection=”con01” > ;Xns9  
tti.-  
SELECT account, balance FROM acct_table $6N. ykJ  
+]X^bB[  
where customer_num = <%= request.getCustno() %> yI)2:Ca*  
v*pVcBY>  
</tt:query> 9viC3bj.o  
"rtmDNpL  
5h&8!!$[  
;A_QI>>  
z; +x`i.  
<tt:connection ...> smggr{-  
tP9}:gu  
<x:query id=”balances”> ?a% u=G  
?(z3/ "g]  
SELECT account, balance FROM acct_table _kS us  
}PVB+i M  
where customer_num = <%= request.getCustno() %> P<1zXs.H  
%Vq@WF  
</x:query> :BS`Q/<w  
7@\iBmr6  
</tt:connection> ,aeFEsi  
q!n|Ju<  
4{V=X3,x  
与此同时,在TLD中必须指定connection属性为可选的,定义如下: <Ip}uy[Y  
O;~1M3Ii  
<tag> *7ox_ R@  
P&K~wP]  
... Rs dACP   
b3ZPlLx6  
<attribute> ?^5x d1>E  
J GdVSjNC  
<name>connection</name> d 9|u~3  
PF~&!~S>W  
<required>false</required> 4D8q Gti  
f`Nu]#i  
</attribute> {,m!%FDL  
L_(|5#IDw  
</tag>
描述
快速回复

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