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

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

级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
标准的JSP 标记可以调用JavaBeans组件或者执行客户的请求,这大大降低了JSP开发的复杂度和维护量。JSP技术也允许你自定义taglib,其实换句话说,taglib可以看成是对JSP标记的一种扩展,正如xml是对html的一种扩展一样。taglib通常定义在tag标签库中,这种标签库存放着你自己定义的tag标签。简而言之,如果使用taglib,那么你可以设计自己的JSP标记! ae&i]K;  
3!&PI  
一般来说,自定义tag标签主要用于操作隐藏对象、处理html提交表单、访问数据库或其它企业级的服务,诸如邮件和目录操作等等。自定义tag标签的使用者一般都是那些对java编程语言非常精通,而且对数据访问和企业级服务访问都非常熟悉的程序员,对于HTML设计者来说,使得他可以不去关注那些较复杂的商业逻辑,而将精力放在网页设计上。同时,它也将库开发者和库使用者进行合理分工,自定义tag标签将那些重复工作进行封装,从而大大提高了生产力,而且可以使得tag库可用于不同的项目中,完美地体现了软件复用的思想。 pBd_Ba N  
rzR=% >  
在这篇文章中,我们主要讨论: l@h|os  
J$]-)`[G&  
· 什么是自定义tag标签? @scy v@5)F  
zQ&k$l9  
· 怎么使用tag标签? 4;rt|X77  
k^JV37;bl  
o 声明要使用的tag库 \1[=t+/  
S\,~6]^T  
o 找到与之对应的tag处理类 ^AI5SjOUx  
4(h19-V  
o tag标签的类型 #|ppW fZQ  
t#fbagTON  
· 自定义tag标签 \$g,Hgp/<  
w$D&LA}(M  
o tag处理类 8)NQt$lWp  
RS8tE(  
o tag库描述 \V1geSoE  
EAdr}io  
o tag标签示例 ZFJ qI  
L"_l(<g  
o 带属性的tag Epl\(  
A;06Zrf1  
o 带body的tag LNA5!E  
!xIK<H{*  
o 定义了脚本变量的tag  MeP,8,n'  
l{2Y[&%  
o 具有协作关系的tag (=T%eJ61  
P 2j"L#%  
· 自定义tag标签 S4salpz  
w;p: 4`  
o 一个迭代tag的例子 $4*wK@xu  
^#V7\;v$G  
o 一个模板tag库 aw3 oG?3I  
eB]R<a60  
o tag处理类到底是怎样被调用的? 9On0om>  
60iMfc T  
f4b`*KGf  
什么是自定义的tag? vmY 88Kx&S  
HW@r1[Y  
一个自定义的tag标签是用户定义的一种JSP标记。当一个含有自定义的tag标签的JSP页面被jsp引擎编译成servlet时,tag标签被转化成了对一个称为tag处理类的对象进行的操作。于是当JSP页面被jsp引擎转化为servlet后,实际上tag标签被转化成为了对tag处理类的操作。 ;RElG>#$  
^z _m<&r  
自定义tag标签有很多特色,诸如: f3p)Q<H>`(  
1 luRTI8^  
· 可以在JSP页面中自定义tag标签的属性 jNC@b>E?~  
;PA^.RB  
· 访问JSP页面中的所有对象 'a^'f]"  
R9!GDKts%  
· 可以动态地修改页面输出 HRG2sv T4t  
k*U(ln  
· 彼此这间可以相互通信。你可以先创建一个JavaBeans组件,然后在一个tag中调用此JavaBeans组件,同时可以在另一个tag中调用它。 HQ7  
KysJ3G.k\  
· tag允许相互嵌套,可以在一个JSP页面中完成一些复杂的交互。 k>'c4ay290  
=Qf.  
2JMMNpya  
使用tag标签 vhEXtjL  
HgY>M`U  
Mq#sSBE<K  
本节主要描述怎样在JSP页面中使用tag标签,以及tag标签的不同类型。 ZDhl$m [m  
x =7qC#+)  
要使用tag标签,JSP程序员必须做2件事: *%(BE*C}  
zG|#__=T  
· 声明此tag标签的tag库 M?nYplC  
X`+8r O[  
· 实现此tag标签 `El)uTnuZ[  
k7R}]hq]""  
声明tag标签所在的tag库 1p DL()t  
x3QQ`w-  
如果要使用tag标签,则应用JSP的taglib指示符来指定其tag库(注意:taglib要在在使用此tag标签之前声明) U7(t >/  
%"C%pA  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> #K4lnC2qz  
kzb%=EI  
uri属性定义了唯一的标签库描述(以下简称TLD),它可以是直接是tld文件名或一个独一无二的名字。prefix是用来区别其它TLD中和本TLD中有重名的tag的一种手段。 5TB==Fj ?  
#% 1|$V*:  
TLD必须以.tld作为扩展名,并且存放在当前应用的WEB-INF目录或其子目录下。你可以通过它的文件名直接引用它,也可以通过别的方式间接地引用它。 4kr! Af  
 yf/c  
以下taglib指示符直接引用一个TLD: ]rY3bG'&  
!ot$Q  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> h=7eOK]  
8euh]+  
以下的taglib指示符通过一个逻辑名称间接地引用一个TLD: 'y? HF@NJ  
WNa#X]*E)  
<%@ taglib uri=”/tutorial-template” prefix=”tt” %> /BaXWrd+  
$&@etsW0/  
如果是间接引用TLD的话,那你必须还要在web.xml中定义此逻辑名称与tld文件之间的映射,具体做法是在web.xml中加入一个名为taglib的元素: "+BNas^rF  
`SN?4;N0  
<taglib> f:K3 P[|  
hj*Fn  
<taglib-uri>/tutorial-template</taglib-uri> h{BO\^6x  
UomO^P  
<taglib-location> mKh <M)Bz  
nWzGb2Y  
/WEB-INF/tutorial-template.tld M,WC+")Z=  
|Ox !tvyr  
</taglib-location> 4or8fG  
=I6u*$9<  
</taglib> G#(+p|n  
>.}ewz&9o  
.o_?n.H'&  
实现此tag标签 zB@@Gs>  
6j{O/  
V!3.MQM  
为了实现tag标签,你有2种方法来存放tag处理类。一、让tag处理类以.class的方式存放于当前应用的WEB-INF/class子目录下,二、如果tag处理类是以JAR包的形式存在的话,那可以放在当前应用的WEB-INF/lib目录下,如果tag处理类要在多个应用中共享,那么它就应放在jsp服务器上的common/lib目录下,对于tomcat来说,就是tomcat/common/lib目录下。 (+=TKI<=  
C\d5t4s  
!P"=57d}"l  
tag标签类型 S^/:O.X)c,  
mm@)uV<\  
UZ qQ|3  
自定义的tag标签遵循XML语法。它有一个开始标记和一个结束标记,有的还有body(即文本节点): P-*=e8z{  
.:(N1n'>1  
<tt:tag> `tjH#W`  
uJX(s6["=  
body wsg u# as|  
|:{H4  
</tt:tag> UN"U#Si)  
=nTNL.SX  
 @U;U0  
一个不带body的tag标签如下: &8^1:CcE  
iI.d8}A  
<tt:tag /> {k#RWDespy  
5uJ{#Zd  
G'\x9%  
简单的tag标签 B<A=U r  
kpU-//lk+  
一个没有body和属性的tag标签如下: TM1D|H  
hG3p"_L  
<tt:simple /> 4qc 0QA%  
oD=6D9c?  
;&9A Yh.  
带属性的tag标签 ji~P?5(:  
)ZP-t!).G#  
6IQkP9P(  
自定义标签可以有自己的属性。属性一般在开始标记中定义,语法为 attr=”value”。属性的作用相当于自定义标签的一个参数,它影响着tag处理类的行为。你可以在TLD中详细定义它。 @jp}WwC/  
)U':NV2  
你可以用一个String常量给一个属性赋值,也可以通过表达式给它赋值,如<%= ...%>。以struts为例,它的logic:present标签就是用的String常量来给属性赋值: df$VC  
01-n_ $b  
<loglic:present parameter = “Clear”> FKN!*}3  
:.k)!  
而另一个标签logic:iterate是用表达式来给属性赋值: -UhGacw  
L9FijF7  
<logci:iterate collection=”<%= bookDB.getBooks() %>” =rrbS8To=  
?R ;K`f9<  
id=”book” type=”database.BookDetails”> ny,a5zEnF  
T P5?%SlJ  
mAFVjSa2  
带body的tag标签 !83N. gN  
^z^ UFW  
一个自定义标签可以包含其它自定义标签、脚本变量、HTML标记或其它内容。 c_33.i"I}  
WRWcB  
在下述例子中,此JSP页面使用了struts的logic:present标签,如果些标签定义了parameter=”Clear”的属性,则将清除购物车的内容,然后打印出一条信息: @fVCGV?'  
b[MdA|C%j  
<logic:present parameter=”Clear”> w?+v+k\  
-5Km 9X8  
<% cart.clear(); %> Yom,{;Bv  
nOd'$q  
<font color=”#ff0000” size=”+2”><strong> O+o4E?}  
Yp_R+a^  
你选择了清除购物车! &Vtgh3I  
$)5-}NJf'  
</strong></font> ?xTh}Sky  
A|D]e)/6+B  
</logic:present> V@(7K0  
~<%/)d0  
"?lm`3W"  
到底是用属性还是用body来传递信息? Px>Gc:!>  
\ :*<En0  
如上所述,我们既可以通过属性,也可以通过body来传递信息。但一般来说,比较简单的类型,如字符串或简单表达式最好采用属性来传递信息。 Y\qiYra  
wK7wu.  
v GF<  
定义脚本变量的tag标签 SQZUkKfb  
BE;J/  
所谓脚本变量,是指JSP中可以调用的变量或对象。它可由tag标签产生。以下示例阐述了一个tag标签定义了一个名为tx的由JNDI所定义的事务处理对象。脚本变量可以是ejb对象、事务、数据库连接等等: iE|qU_2Y  
nVTCbV  
<tt:lookup id=”tx” type=”UserTransaction” name=”java:comp/UserTransaction” /> ww]^H$In  
WG{mg/\2(C  
<% tx.begin(); %> b 83__i  
yvgn}F{}  
... xz+Y1fYT  
"\'g2|A  
NdS6j'%B@7  
具有协作关系的tag标签 1D0_k  
*hHy> (*  
自定义tag标签之间可以通过共享对象来实现协作。在下述例子中,标签tag1创建了一个名为obj1的对象,在标签tag2仍可以重复使用obj。 K$H>/*&'~  
s{-`y`JP  
<tt:tag1 attr1=”obj1” value1=”value” /> G n_AXN  
L29,Y=n@  
<tt:tag2 attr1=”obj1” /> ,6zH;fi  
y1JxAj  
在以下这个例子当中,如果外层的tag标签创建了一个对象,那么其内层的所有tag标签都可以使用这个对象。由于这样产生的对象没有一个指定的名字,那么就可以将少重名的冲突。这个例子阐述了一系列协作的嵌套对象。 R?Dbv'lp>  
z|Hc=AU8y  
<tt:outerTag> x*~a{M,h  
%0PdN@I  
<tt:innerTag /> (;V=A4F-D  
brkR,(#L3  
</tt:outerTag> >+[uV ^2[  
D&{ 7Av  
XIu3n9g^#  
Tag处理类 3gW4\2|T  
jhWNMu  
|\ 1?CYx  
Tag处理类必须实现Tag接口或BodyTag接口,不过现在一般都流行从TagSupport或BodyTagSupport类中继承,这些类或接口都可以在javax.servlet.jsp.tagext包中找到。 oRM,_  
h^P>,dy0  
当JSP引擎看到自己的JSP页面中包含有tag标签时,它会调用doStartTag方法来处理tag标签的开头,调用doEndTag方法来处理tag标签的结束。 \8uPHf_  
Lc|5&<8ZG1  
下表说明不同类型的tag所需要不同的处理过程: 62B` Z5j#  
E6SGK,f0D  
Tag处理类的方法 p_$03q>oQ  
gY], (*v  
Tag标签类型 <}RU37,W  
所调用的方法 7@MGs2  
J?XEF@?'G  
基本标签 T/ CI?sn  
doStartTag, doEndTag, release zaX!f ~;"  
|H.(?!nTb  
带属性的标签 ^;3z9}9  
doStartTag, doEndTag, set/getAttribute1...N, release M%wj6!5  
EO'[AU%~  
带内容的标签 td@F%*  
doStartTag, doEndTag, release bA-=au?o5  
E'=~<&  
带内容的标签,且内容重复循环 P5ii3a?R  
doStartTag, doAfterBody, doEndTag, release fW Vd[zuD4  
G?)vqmJ%  
带内容的标签,且内容与JSP交互 ?aInn:FE  
doStartTag, doEndTag, release, doInitBody, doAfterBody, release Urhh)i  
m:<cLc :.  
一个tag处理类可以通过javax.servlet.jsp.PageContext来与JSP交互,通过javax.servlet.jsp.PageContext类,tag处理类可以访问JSP中的request、session和application对像。 "Hmo`EB0  
im^G{3z  
如果tag标签是互相嵌套的,那内层的tag处理类可以通过它的parent属性来访问上层的tag处理类。 %-+lud  
D"F5-s7  
一般情况都将所有的tag处理类打成了JAR的包,以便于发布。 0X\,!FL  
rUkiwqr~E  
dOq*W<%  
Tag库描述(简称TLD) 6uQfe? aD  
rMqWXGl`(  
{A4"KX(U  
Tag库是用xml语言描述的,TLD包括了tag库中所有tag标签的描述,它一般用来被jsp服务器用来校验tag的语法正确性,或者被jsp开发者用来开发新的标签。 @b2{'#9]}  
M'D;2qo  
TLD的文件扩展名必须为.tld,而且必须放在当前WEB应用的WEB-INF目录或其子目录中。 v709#/ cR  
w .l2  
一个TLD的内容的开头必须遵守标准的XML开头,用于描述DTD和xml的版本,例如: ]*pALT6  
0fnd9`N!0  
<?xml version="1.0" encoding="ISO-8859-1" ?> E.?|L-fy  
"])X0z yM  
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd"> $%VFk53I  
TLD必须以<taglib>来作为它的根元素,<taglib>的子元素如下表: h2+vl@X  
8^;[c  
>`8r52  
<taglib>的子元素 *J@2A)ZDv0  
ecA[  
Element !z X`M1J  
Description `9eE139V='  
I ms?^`N  
tlib-version aYe,5dK>  
Tag库的版本 RX:\@c&  
J%EbJ5p<QF  
jsp-version x=yBB;&  
Tag库所需要的jsp的版本 ["GC   
JP9eNc[  
short-name 'OSZ'F3PV  
助记符,tag的一个别名(可选) b mZRCvW>A  
[#n ~ L6  
uri i NzoDmE*  
用于确定一个唯一的tag库 :h?"0,  
2t\a/QE)E  
display-name :*#AJV)  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) |~k=:sSz{  
"$PbpY  
small-icon (7`&5m d  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) E=GCq=Uw  
4(2}O-~  
large-icon gIep6nq1`|  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) Bm"jf]  
e{.2*>pH  
description X1!m ]s(I  
对tag库的描述(可选) Nqp%Z7G  
j/wG0~<kz  
listener c*K-?n9YMz  
参见下面listener元素 cC1nC76[  
pq+Gsu1^  
tag e2UbeP  
参见下面tag 元素 i 4lR$]@  
ItHKpTe r  
Listener元素 `4}zB#3  
vLJ<_&6  
一个tag库可能定义一些类做为它的事件侦听类,这些类在TLD中被称为listener 元素,jsp服务器将会实例化这些侦听类,并且注册它们。Listener元素中有一个叫listener-class的子元素,这个元素的值必须是该侦听类的完整类名。 d4/snvq  
Fe%Q8RIh_  
Tag元素 . [+ObF9=  
i0Qg[%{9#  
每个tag元素在tag库中都要指出它的名字、类名、脚本变量、tag的属性。其中脚本变量的值可以直接在TLD中定义或通过tag附加信息的类来取得。每个属性描述了这个属性是否可以省略,它的值是否可以通过<%= …%>这样的JSP语法来获得,以及属性的类型。 u2y?WcMv  
V' "p a  
每一个tag在TLD中对应一个tag元素,下表是tag元素的子元素: 6cVaO@/(  
PDvqA{  
Tag元素的子元素 yAG4W[  
D$;mur'  
元素名称 yp wVzCUG  
描述 oat*ORL  
g&O%qX-  
name BQ,]]}e43z  
独一无二的元素名 tx}{E<\>$  
f8+($Ys  
tag-class Xl;u  
Tag标签对应的tag处理类 + B%fp*  
U%"c@%B0  
tei-class 0^*4LM|z  
javax.servlet.jsp.tagext.TagExtraInfo的子类,用于表达脚本变量(可选) ?Q="w5OOD  
M/:kh,3  
body-content 0Q_AF`"  
Tag标签body的类型 F'*y2FC  
Cd#[b)d ?^  
display-name sKB])mf]  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) &48wa^d  
bk}.^m!  
small-icon ^, q\S  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) D@!`b6  
]MfT5#(6h  
large-icon ?lnX."eAdB  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) jAfUz7@  
h35x'`g7+r  
description l131^48U  
此tag标签的描述 M,8a$Mdqh  
fMlxtj+5   
variable 9(QY~F  
提供脚本变量的信息(同tei-class)(可选) QB'-`GwL  
8TD:~ee  
attribute 4M*UVdJ;  
Tag标签的属性名 $L)9'X   
ea3AcT6  
以下章节介绍对于不同类型的tag,如何具体地实现它们。 aDm$^yP  
.<gA a"  
s7tNAj bgD  
简单的tag <oS2a/Nd  
qtnLQl"M  
$^INl0Pg  
tag处理类 '=G4R{  
s+2\uMwf*  
简单的tag处理类必须实现Tag接口的doStartTag和doEndTag方法。当jsp引擎碰到tag标签的开头时,doStartTag被调用,因为简单的tag没有body,所以此方法将返回 SKIP_BODY。当jsp引擎碰到tag标签的结尾时,doEndTag被调用,如果余下的页面还要被计算,那它将返回EVAL_PAGE,否则将会返回SKIP_PAGE。 3cBuqQ  
\vT0\1:|i  
以下是例子:对于标签 <tt:simple /> ,它的tag处理类实现如下: l"*qj#FD  
T12?'JL^r  
&q#$SU,$(  
public SimpleTag extends TagSupport f7)}A/$4+  
D06'"  
{ 8|.( Y  
'C]zB'H=  
public int doStartTag() throws JspException aAh")B2  
<8|vj 2d2  
{ 57Y(_h:  
f$Q#xlQM  
try{ 8wp)aGTcU  
9IIQon  
pageContext.getOut().print(“Hello.”); KRd.Ubs -  
sOa`Tk  
}catch(Exception e){ {# ;e{v  
HTao)`.  
throw new JspTagException(“SimpleTag: “ + e.getMessage()); C8}ujC  
,}2M'DSWa  
} G5|xWeNgA  
tQ< ou,   
return SKIP_BODY; oL1m<cQo9  
pFX Do4eH  
} U;Se'*5xv  
[h""AJ~t  
public int doEndTag() H[U$4 %t  
n7i;^=9 mM  
{ uhSRl~tn  
/ *Z( ;-  
return EVAL_PAGE; =>-:o:Cu{  
Lfx&DK !  
} v*7}ux8  
M&Sjo' ( .  
} {'l^{"GO"  
3kx/Q#  
%k_R;/fjW  
注意:如果tag标签没有内容的话,那必须定义body-content元素为空,例如 wQgW9546  
mk~&>\  
<body-content>empty</body-content> }BlVLf%C  
}i!hzkK#  
v~[=|_{  
带属性的tag标签
评价一下你浏览此帖子的感受

精彩

感动

搞笑

开心

愤怒

无聊

灌水
级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
只看该作者 1 发表于: 2007-01-01
tag处理类 W(Z_ac^e[  
|&eZ[Sy(=l  
对于tag标签的每个属性,你必须依照JavaBeans规范来定义其属性,以及get和set方法。以struts的logic:present 标签为例, bq/ m?;  
/.9j$iK#  
<logic:present parameter=”Clear”> B!0o6)u'  
.0kltnB  
与此相应,此tag处理类应有如下方法和定义: X1?7}VO  
GGo)k1T|)  
[g`9C!P-G  
protected String parameter = null;  }&BE*U8_  
JV(qTb W  
public String getParameter() \W=~@k  
:0|]cHm  
{ fDt#<f 4;  
U??P  
return this.parameter; !#j y=A  
3B!lE(r%J  
} vh5`R/<3  
$"1Unu&P  
public void setParameter(String parameter) fgIzT!fyz  
1wP#?p)c  
{ Nd'+s>d0  
Z 6KM%R  
this.parameter = parameter; |TL&#U  
A]L;LkEM  
} @{ *z1{  
H^z6.!$m  
,e$]jC<sv2  
注意:如果你的属性名为id,而且你的tag处理类是从TagSupport类继承的,那你就不需要定义它的属性和set和get方法,因为他们早已在TagSupport被定义过了。  >Eg/ir0  
c]LE9<G  
Attribute元素 > 2_xRn<P  
nt. A X  
对于tag标签的每个属性,你必须定义它是否必须的,它的值是否可以用诸如<%= …%>的表达式来获得,以及它的类型(可选),如果不指定它的类型,那就默认为是java.lang.String类型。如果rtexprvalue元素被定义为true或yes,那么在type元素中就定义了attribute的返回类型。 s ;EwAd(  
Xu\FcQ{  
<attribute> 2z+Vt_%  
is}6cR  
<name>attr1</name> 1><@$kVMm~  
Z-X(. Q  
<required>true|false|yes|no</required> (3a]#`Q  
nAIV]9RAZ%  
<rtexprvalue>true|false|yes|no</rtexprvalue> .<&o,D  
K"4m)B~@Y  
<type>attribute的返回类型(只用当rtexprvalue为真是才有效)</type> iR} 3 [  
*+|D8xp  
</attribute> Ilt!O^  
6[3oOO:uo  
如果tag的某个属性不是必须的,那tag处理类会自动提供一个缺省值。 >K:| +XbH  
Mbbgsy3W  
例如,在logic:present这个tag标签中定义了一个属性叫parameter,但它不是必须的,而且它可以被诸如<%= …%>的表达式来赋值。 PNy)TqdRS  
@ 3n;>oi  
<tag> ,36AR|IO)  
.Ukejx  
<name>present</name> 3"v k$  
Cka&b  
<tag-class>org.apache.struts.taglib.logic.PresentTag</tag-class> Fu0"Asxce  
\l)Jb*t  
<body-content>JSP</body-content> wxC&KrRF  
Y)~Y;;/G  
bEO\oS  
f@JMDJ  
<attribute> b!(ew`Y;  
bUv}({  
<name>parameter</name> d_t>  
%63zQFk  
<required>false</required> 9, A(|g  
#kGgz O  
<rtexprvalue>true</rtexprvalue> R'Gka1v  
`.oWmBey\  
</attribute> =7^rKrD  
0`WjM2So  
K)ZW1d;  
]81t~t9LQ  
</tag> uUhqj.::<Y  
0iKSUw ps  
CBkI! In2  
属性元素的校验 3VI[*b  
R #f*QXv  
E =*82Y=B  
有关于tag标签的有效值可以从tag库的说明文档中获得,当JSP页面被编译时,jsp引擎会强制性地参照TLD中定义的规则进行检查。 95XQ?%  
{th=MldJ?  
还有一个方法也可以进行属性元素的校验,就是先继承类TagExtraInfo,然后调用它的isValid方法。这个类同时也起到提供tag中定义的脚本变量信息的作用。 wo#,c(  
hSN{jl{L`  
IsValid方法通过TagData对象来传递属性信息,它包括着tag的所有的属性名-值的信息。由于校验发生在运行时刻,因此这个属性的值将被赋值为TagData.REQUEST_TIME_VALUE。 ,H)v+lI  
mRurGaR  
例如tag标签<tt:twa attr1=”value1” />在TLD中定义如下: ]2_b_ok  
dCb7sqJ%  
<attribute> ~M c'~:{O  
3BZa}Q_  
<name>attr1</name>  =8o$  
yjF;%A/0  
<required>true</required> .S_7R/2(?  
}O + a  
<rtexprvalue>true</rtexprvalue> cko^_V&x  
ron-v"!  
</attribute> |&oTxx$S  
,<CFjtelO  
sBq-"YcjR  
这个定义说明了attr1能在运行期间被赋值。 2FVO@D  
BNw};.lO  
以下的isValid方法检查attr1属性的值是否属于Boolean类型。注意由于attr1能在运行刻被赋值,那么isValid方法必须检查tag用户是否对此tag进行了运行时刻赋值。 R9&3QRW|  
uGc0Lv4i/  
K\trT!I  
Public class TwaTEI extends TagExtraInfo @zC p/fo3  
C>:,\=y%  
{ 3a\De(;  
Pf:;iXH?  
public boolean isValid(Tagdata data) T Ob(  
mB5Sm|{  
{ j[RY  
}> ]`#s  
Object o = data.getAttribute(“attr1”); %TeH#%[g>\  
2CF5qn}T  
If(o != null && o != TagData.REQUEST_TIME_VALUE) 9 _b_O T  
u9*7Buou^  
{ 5-RA<d#  
b[2 #t  
if( ( (String)o).toLowerCase().equals(“true”) || cakwGs_{  
}Pm; xHnf&  
((String)o).toLowerCase().equals(“false”) ) \v _R]0m\  
pV(qan,  
return true; m ##_U9O  
3^,p$D<T:,  
else tc|PN+v;  
=&"a:l  
return false; ^4~?]5Y\  
RgD%pNhI  
} s}<i[hY>  
;r BbLM`  
else M#.dF{ %%  
W) ?s''WE;  
return true; %%T?LRv  
:I2spBx  
} w y&yK*w  
1l s8h  
} j 6dlAe  
GQ0(lS  
+TC##}Zmb  
带body的tag 8K9RA<  
E^B3MyS^^  
8I7JsCj  
tag处理类 Fu>;hx]s  
X2mZ~RB(p  
(7C$'T-ZK  
如果tag标签含有内容,那处理方式会略微有些不同,而且还要视tag处理类是否要与body交互的情况而定。如果要与body交互,那我们认为tag处理类要可能要对body进行操作。 AHzm9U @  
5Y>fVq{U?;  
Tag处理类不与body交互 G6bvV*TRi  
Zm vtUma  
如果tag处理类不与body交互,tag处理类应该实现Tag接口或从TagSupport中派生,如果body要被计算,那么doStartTag方法应返回 EVAL_BODY_INCLUDE,否则应返回SKIP_BODY。 tN;^{O-(V  
}vd72P B  
如果tag处理类要对body反复运算,则它应该实现IterationTag或从TagSupport中派生。如果tag处理类认为body还未计算完的话,那它的doStartTag方法和doAfterBody方法必须返回EVAL_BODY_AGAIN。 ^[VEr"X  
E <N%  
Tag处理类与body交互 Z~K} @  
R(s[JH(&  
如果tag处理类与body交互,那tag处理类应实现BodyTag接口或从BodyTagSupport中派生。这种tag处理类一般要实现doInitBody和doAfterBody方法。 sWKv> bx  
J4Ca0Ag  
Body允许一些方法来读写它的内容。Tag处理类可以调用body内容的getString或getReader方法来从body中提取信息,也可用 writeOut(out) 方法来将body的内容写入到out对象中。其中out对象通过tag处理类的getPreviousOut方法来获得。 jfYM*%  
8:U0M'}u>  
如果body的内容需要被计算,那么doStartTag方法必须返回EVAL_BODY_BUFFERED,否则,它将返回 SKIP_BODY。 LX}|%- iv  
t!59upbN}3  
doInitBody 方法 Ckhw d  
xLP8*lvy  
此方法在body内容已经设好,但未被计算之前被调用。你可以根据不同的body内容来制定初始化策略。 MhjIE<OI=  
{<zE}7/2-  
doAfterBody方法 S[CWrPaDQ  
PHMp, z8  
此方法在body内容已被计算后进行调用。 jGYl*EBx  
CoV @{Pi  
和doStartTag方法一样,doAfterBody方法返回一个指示符指示是否要继续计算body,如果要继续计算,则doAfterBody应返回EVAL_BODY_BUFFERED,否则,它应返回SKIP_BODY。 Lr Kx  
 CVZ 4:p  
release 方法 E O"  
<9x|)2P  
tag处理类调用此方法将它的状态重置为初始状态,并释放所有的私有资源。 P0rdGf 5T  
ppu<k N  
bd3>IWihp  
以下的例子读取body的内容(其中含有一条sql语句),然后将它传递给一个对象,让它进行查询。由于此处body不须重新计算,所以doAfterBody会返回SKIP_BODY。 g` ,(O  
X^C $|:  
'.e 5Ku  
Public class QueryTag extends BodyTagSupport I.o3Old  
)O\l3h"  
{ xOZvQ\%  
&VxK AQMxN  
public int doAfterBody() throws JspTagException xEB 4oQ5  
@^`5;JiUk  
{ G }M!  
mG%cE(j*D  
BodyContent bc = getBodyContent(); =|d5V%mK  
{XW>3 "  
//将body的内容以字符串的格式提取出来 &# @"^(} 6  
vIFx'S~D  
String query = bc.getString(); R!WeSgKCs  
ktv{-WG2_  
//清除body ">s0B5F7  
<4;f?e u  
bc.clearBody(); G+iJS!=  
^1ks`1  
try{ V.[b${  
C |rl",&  
Statement stmt = connection.createStatement(); }Ub "Vb  
!Tu.A@  
Result result = stmt.executeQuery(query); tdC kvVE  
[ HjGdC  
}catch(SQLException e){ gKb5W094@  
t;[Q&Jl  
throw new JspTagException(“queryTag: “ + e.getMessage() ); s'@@q  
@T-}\AU  
return SKIP_BODY; <pUc( tPoz  
*OZ O} i  
} B^1Io9  
r3.v^  
} tQ4{:WPG  
I3?:KVa  
i4 tW8 Il  
body-content元素 "2@Ys* e  
$w<~W1\:  
LZu_-I  
由于tag可能会有body,你必须用body-content元素来指定body内容的类型: J15$P8J  
M~!LjJg;  
<body-content>JSP|tagdependent</body-content> L G9#D  
Xgm9>/y  
Y'%_--  
如果body的内容是定制的或内部的tag、脚本元素、或HTML广本,则归类为JSP类型。其他的类型,比如上面代码所述的?D?D将sql statement类传给 query tag的这种类型应该标为tagdependent。 \'N|1!EO|t  
Va'K~$d_  
注意:实际上body-content的值并不影响tag处理类对body内容的处理,它仅仅是被tag编辑工具用来描述此body的内容。 [h2V9>4:  
m;I;{+"u  
YuDNm}r[  
用tags定义脚本变量 ~LzTqMHM  
]0:R^dHE  
^A$~8?f  
tag处理类 =;xlmndT,  
E0S[TEDa]  
x]U (EX`t$  
tag处理类负责创建或设置页面中定义的脚本变量,用pageContext.setAttribute(name,value,scope)或pageContext.setAttribute(name,value)方法来实现。一般来说,tag处理类通过脚本变量的名称来获取它,脚本变量的名称一般可用get方法来获得。 #$%gs]  
cjO,#W0&f  
如果脚本变量的值依赖于tag处理类中的上下文中某一对象,那它可用pageContext.getAttribute(name,scope)方法来找到那个对象。一般的处理过程是tag处理类先找到脚本变量,再对其进行处理,然后用pageContext.setAttribute(name,object)的方法来设置它的新值。 k07) g:_  
4B}w;d@R  
对象的生存周期(scope)如下表: mwTn}h3N  
9P)<CD0  
对象的生存周期表 ^q$vyY   
M>k7 '@G  
名字 ,K6]Q|U@r  
可访问范围 ^ihXM]1{G  
生存周期 @w:sNXz-  
?-'Q-\j  
page :<IW'  
当前页面 I_ .;nU1xA  
一直有效,除非页面向客户提交响应或重定向到一个新页面 o6K BJx  
(A &@ <  
request [%nG_np  
当前页面或当前页面重定向到的页面 |/lIasI  
一直有效,除非页面向客户提交响应 NI s4v(!  
+;[`fSi  
session L{fP_DIa  
当前页面或在同一浏览器窗口中的页面 L}a3!33)C  
一直有效,除非关闭当前浏览器、超时、网络故障 <p0$Q!^dK=  
pr0V)C6  
application 6eK^T=  
整个web应用程序的所有请求 Yhw* `"X  
一直有效,除非发生网络故障、服务器故障 L kq>>?T=  
BK d(  
提供关于脚本变量的信息 Dfhs@ z  
Z ''P5B;  
以下示例定义了一个名为“book”的脚本变量,用来访问程序中关于书的信息: 1v\-jM"  
/?XfVhA:A  
<bean:define id=”book” name=”bookDB” property=”bookDetails” type=”database.BookDetails” /> Z%OSW  
}Rux<=cd|  
<font color=”red” size=”+2” > hy)RV=X  
usTCn3u  
<%= messages.getString(“CartRemoved”) %> !d0@^JbM"  
B=c^ma  
<strong><jsp:getProperty name=”book” property=”title” /></strong> VD3[ko  
;W*$<~_  
</font> !3&vgvr  
Rt:PW}rFf  
当包含此tag的JSP页面被编译时,jsp引擎会自动生成关于此book的同步的代码(同步可以避免几个客户同时访问此book时造成的冲突),要生成同步代码,jsp引擎需要知道此脚本变量的如下信息: d<3"$%C  
KnFbRhu[  
· 脚本变量名称 BVNh>^W5B  
#dfW1@m  
· 脚本变量所属的类 3z#;0n}  
Go67VqJr  
· 此脚本变量是否引用了一个新的或已存在的对象 r#}Sy \  
 Fszk?0T  
· 此脚本变量的有效性 q%vUEQLBp  
2$ rq  
有两种办法可以向jsp引擎提供关于脚本变量的信息:在TLD中定义variable子元素,或用tei-class子元素定义一个额外tag信息类。用variable最简单,但可能降低了一些灵活性。 t3XMQ']  
&4[iC/}  
Variable元素 n{yjH*\Z  
-?'CUm*Od  
Variable元素有如下子元素: KE3v3g<  
WE7l[<b  
· name-given ?D?D 给出的名字,是一个常量 %% >?<4t  
z} \9/`  
· name-from-attribute?D?D 属性名,在编译时给出的属性名 *j* WE\  
QaO`:wJj  
name-given或name-from-attribute两者必须选一,但以下子元素是可选的: D/Wuan?yPN  
)-{Qa\6(%  
· variable-class?D?D变量的类型,缺省为java.lang.String。 2yZ6:U~  
eBV{B70k  
· declare?D?D此脚本变量是否引用了一个新对象,缺省为True。 HlSuhbi'@  
)pLq^j  
· scope?D?D脚本变量的范围,缺省为NESTED。下表描述了scope的几种类型: ^hgAgP{{  
N [u Xo  
脚本变量的有效范围 g3XAs@  
.'1j5Y-l`N  
GXRjR\Ch  
有效性 K?je(t^  
方法 [s2V-'2  
@^%_ir(  
NESTED YeLOd  
在tag标签的开始和结束之间 ^-!HbbVv  
如果tag处理类实现BodyTag接口,则在doInitBody和doAfterBody中调用,否则在doStartTag中调用 v1=X=H  
S\ZAcz4  
AT_BEGIN n:D*r$ C|p  
从tag标签的开始一直到页面结束 iL, XBoE  
如果tag处理类实现BodyTag接口,则在doInitBody、doAfterBody和doEndTag中调用,否则在doStartTag和doEndTag中调用 3>" h*U#  
5uer [1A  
AT_END &^_(xgJL  
从tag标签的结束一直到页面结束 }6> J   
在doEndTag中调用 N0[I2'^.  
7]j-zv  
以struts为例,它的bean:define标签的实现遵循JSP1.1规范,此规范要求使用额外tag信息类来定义脚本变量。Variable元素是JSP1.2规范中加入的。以bean:define标签为例,你可以定义如下variable元素: ([-=NT}Aq  
)1}g7:  
<tag> 61/zrMPn  
zYdtQjv  
<variable> Ekme62Q>u  
)<F\IM  
<name-from-attribute>id</name-from-attribute> /AW>5r]  
Xh"iP%  
<variable-class>database.BookDetails</variable-class> }GDG$QI]K&  
<WJ0St  
<declare>true</declare> f](uc(8Z  
0s""%MhFI  
<scope>AT_BEGIN</scope> &2=KQ\HO  
Q;O)>K  
</variable> J*!:ar  
c/Yi0Rl)  
</tag> FraW6T}_  
)K>@$6H +2  
额外tag信息类 _-J@$d%  
t=rAc yNM  
如果要定义一个额外tag信息类,你要继承javax.servlet.jsp.TagExtraInfo类。一个TagExtraInfo类必须实现getVariableInfo方法,此方法返回一个叫VariableInfo的数组类,它包括如下信息: V55J[s*6!  
(iOCzZ6S  
· 变量名 ~hslLUE  
u7&'3ef  
· 变量所属类名 LIC~Kehi  
qd~98FS  
· 此变量是否引用了一个新对象 )?&kQ^@v  
n qLAby_  
· 此变量的有效范围 1`]IU_)1B  
kj!7|1i2  
jsp引擎将一个名为data的参数传给getVariableInfo方法,data中包括tag标签中的所有“属性名?D?D属性值”对。它可以用来向VariableInfo对象提供脚本变量的名字和类名。 rHgdvDc  
4t Nvq  
以struts为例,它在bean:define标签中定义了一个名为DefineTei的额外tag信息类,用来向脚本变量提供信息。由于脚本变量的名称(book)和类名(database.BookDetails)是通过tag标签的属性来传递的,它们一般定义在VariableInfo的构建代码中,并且可用data.getAttributeString方法来得到这些信息。如果要允许book脚本变量能在从tag开始直到整个JSP页面结束的范围内都可用的话,那它的范围应设为AT_BEGIN。如下所示: L1kM~M  
nQ17E{^pR  
ioNa~F&  
public class DefineTei extends TagExtraInfo T#G<?oF  
-^4bA<dCCE  
{ )YMlF zYr  
^I<T+X+<  
public VariableInfo[] getVariableInfo(TagData data) Dbdzb m7  
U+PCvl=x  
{ @" 0tW:  
V.Ba''E7  
String type = data.getAttributeString(“type”); +lgF/y6  
).}k6v[4)  
If( type == null) 4m~7 ~-h  
[TK? P0  
type = “java.lang.Object”; PIEW\i  
2PR7M.V 7  
return new VariableInfo[] { n!ZP?]FR  
{ w8 !K  
new VariableInfo(data.getAttributeString(“id”), 4Wla&yy  
gJPDNZ*6pk  
type, 5+bFy.UW  
}kCn@  
true, }or2 $\>m  
JC&6q >$  
VariableInfo.AT_BEGIN) jemx ky  
974eY  
}; P 0Efh?oZ  
&7($kj  
} mC:X4l]5  
1]>$5 1Q  
} eMN+qkvH  
9eGCBVW:*  
3|~(?4aE  
注意:关于额外tag信息类的类名必须要在TLD中的tag标签下的tei-class子元素中定义。因此,DefineTei的tei-class中的定义看起来如下: Q)G!Y (g\  
<tei-class> R5K-KSvW  
org.apache.struts.taglib.bean.DefineTagTei E5*-;>2c  
</tei-class> i0'Xy>l  
f^!11/Wv  
|I}A> XG  
具有协作关系的tag N a. nA  
9 V=<| 2  
n9kd2[s|  
tag通过共享对象来进行协作,JSP技术支持2种方式的对象共享。 P?q G  
gH i~nEH  
第一种方法是使用pageContext对象进行对象的共享(可支持JSP页面和tag处理类之间的共享),如果在一个tag处理类中要调用由另一个tag处理类创建的对象,可调用pageContext.getAttribute(name, scope)方法。 gb=80s0  
^V<J69ny|9  
第二各方式的共享是对于tag之间有嵌套关系而言的,外层的tag所创建的对象对于内层的tag来说是可以共用的。这种形式的共享的好处是减少了可能存在的重名冲突。 Ql~#((K  
PyC;f8n'(  
要访问一个嵌套tag创建的对象,tag处理类必须先找到此嵌套tag对象,可用TagSupport的静态方法 TagSupport.findAncestorWithClass(from, class)或TagSupport.getParent方法。前者在当不确定此tag是否为嵌套tag对象时使用。一旦它的父类被找到,它就能访问其所有动态或静态创建的对象。静态创建的对象是父类的成员,而动态创建的对象可能是父类的私有对象。诸如此类的对象可以用tag处理类的setValue方法来保存,用getValue方法来获得。 *MYt:ms  
M8^.19q;  
下例阐述了以上两种共享对象的方法。在这个例子当中,一个查询tag检查一个名为connection的属性名是否在doStartTag中被设置。如果connection属性被设置,tag处理类从pageContext中得到这个connection对象。否则,此tag处理类先找到它的父tag处理类,然后从它的父tag处理类中找到connection对象。 n2n00%Wu[  
$R%+*  
;Ze"<U  
public class QueryTag extends BodyTagSupport S9G8aea/  
j`2B}@2  
{ @A [)hk&(R  
d[Rb:Y w  
private String connectionId; c8#T:HM|`  
M8 iEVJ  
public int doStartTag() throws JspException bbd0ocva  
>"cr-LB  
{ A$7Eo`Of  
\R86;9ov  
String cid = getConnection(); x1N me%%&  
>vQ6V'F  
if(cid != null) j6n2dMRvSE  
$Q8P@L)[  
{ MxY50 ^}(  
C!!mOAhJ  
//存在一个connection id,使用它。 D3%l4.h  
RRx`}E9,  
connection = (Connection) pageContext.getAttribute(cid); PqT"jOF]n  
0SJ{@*  
} 4JGE2ArR  
`Uz s+k-]  
else HR[Q ?rg  
^pJ0nY# c  
{ &bB6}H(  
n<{aPLQ  
ConnectionTag ancestorTag = (ConnectionTag)findAncestorWithClass(this, )*!1bgXQ  
+->\79<#V(  
ConnectionTag.class); 3QCMK^#Z:  
_kh>Z  
if(ancestorTag == null) d2ohW|  
XK1fHfCEa  
{ =f o4x|{O  
PdR >;$1  
throw new JspTagException(“一个没有connection属性的查询标签必须被一个connection标记嵌套。”); ^[en3aQ  
rwoF}}  
} R @"`~#$$  
!loO%3_)  
connection = ancestorTag.getConnection(); D2Y&[zgv  
u-lrTa""z  
} ?LM:RADCm  
5QR}IxQ  
} ?4:rP@  
l#Yx TY  
} !2(.$}E  
O8gfiQqF&  
NzAQ@E 2d:  
{&uT3*V1  
此查询标签在JSP页面中的调用形式可以从以下2种定义中任选一种: s}jlS  
?F1wh2o q  
Pow|:Lau!  
<tt:connection id=”con01” ...> ... </tt:connection> >Z}@7$(7!~  
n9DbiL1{  
<tt:query id=”balances” connection=”con01” > T 4eWbNSs  
<p09oZ{6  
SELECT account, balance FROM acct_table l7ZB3'  
&%6NQWW  
where customer_num = <%= request.getCustno() %> }0Y`|H\v  
Z^<Sj5}6  
</tt:query> &T7cH>E'K^  
2@fa rx:  
B9}E {)T?  
bCzdszvg3  
=9(tsB gTX  
<tt:connection ...> vuZf#\zh}  
A9t8`|1"%H  
<x:query id=”balances”> ~*,Wj?~+7  
(oF-O{  
SELECT account, balance FROM acct_table yu=piP  
`T=1<Twc  
where customer_num = <%= request.getCustno() %> J=@xAVBc  
?;_H{/)m  
</x:query> |<1M&\oaQ'  
of=ql  
</tt:connection> X>}@EHT  
l/M[am  
kB V/rw  
与此同时,在TLD中必须指定connection属性为可选的,定义如下: 9Yn)t#G'`F  
IYLZ +>  
<tag> e]+7DE  
l:)S 3  
... zXjw nep  
/w0w* n H  
<attribute> BR3wX4i\  
z<i,D08|d  
<name>connection</name> J B(<.E 2  
'aZAS Pn[  
<required>false</required> $,@JYLC2  
9ZhDZ~)p,  
</attribute> i+I0k~wY  
u3ST;  
</tag>
描述
快速回复

您目前还是游客,请 登录注册
温馨提示:欢迎交流讨论,请勿纯表情、纯引用!
认证码:
验证问题:
3+5=?,请输入中文答案:八 正确答案:八