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

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

级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
标准的JSP 标记可以调用JavaBeans组件或者执行客户的请求,这大大降低了JSP开发的复杂度和维护量。JSP技术也允许你自定义taglib,其实换句话说,taglib可以看成是对JSP标记的一种扩展,正如xml是对html的一种扩展一样。taglib通常定义在tag标签库中,这种标签库存放着你自己定义的tag标签。简而言之,如果使用taglib,那么你可以设计自己的JSP标记! 8^ezqd`  
=}7[ypQM`]  
一般来说,自定义tag标签主要用于操作隐藏对象、处理html提交表单、访问数据库或其它企业级的服务,诸如邮件和目录操作等等。自定义tag标签的使用者一般都是那些对java编程语言非常精通,而且对数据访问和企业级服务访问都非常熟悉的程序员,对于HTML设计者来说,使得他可以不去关注那些较复杂的商业逻辑,而将精力放在网页设计上。同时,它也将库开发者和库使用者进行合理分工,自定义tag标签将那些重复工作进行封装,从而大大提高了生产力,而且可以使得tag库可用于不同的项目中,完美地体现了软件复用的思想。 #JIh-h@  
Fi_JF;  
在这篇文章中,我们主要讨论: ?5MOp  
mq*Efb)!  
· 什么是自定义tag标签? +-+%6O<C  
+ 4*jO5EZ  
· 怎么使用tag标签? +YK/^;Th  
";$rcg"%X  
o 声明要使用的tag库 f*& 4d  
@ob4y  
o 找到与之对应的tag处理类 MH=;[| N  
Zcg@]Sx(I  
o tag标签的类型 "~^ #{q  
yPhTCr5pK  
· 自定义tag标签 %`1 p8>n  
tsvh/)V  
o tag处理类 \C.s%m  
)mF;^3  
o tag库描述 vS_Ji<W~E  
sGs_w:Hn  
o tag标签示例 Y}Gf%Xi,  
YdNmnB %J  
o 带属性的tag lay)I11- >  
cas5  
o 带body的tag T0=%RID%=  
\>@QJ  
o 定义了脚本变量的tag zxffjz,Fe:  
c-gpO|4>  
o 具有协作关系的tag POtwT">z  
(c=.?{U  
· 自定义tag标签 E+xC1U 3  
HbXYinG%  
o 一个迭代tag的例子 smTPca)7s  
QKt[Kte  
o 一个模板tag库  YD|;xuh  
Nn]|#lLP  
o tag处理类到底是怎样被调用的? WfF~\DlrD  
B%Vz -t  
Tz{f 5c&  
什么是自定义的tag? cgevP`*]  
8) 1+j>OQ  
一个自定义的tag标签是用户定义的一种JSP标记。当一个含有自定义的tag标签的JSP页面被jsp引擎编译成servlet时,tag标签被转化成了对一个称为tag处理类的对象进行的操作。于是当JSP页面被jsp引擎转化为servlet后,实际上tag标签被转化成为了对tag处理类的操作。 _Nmc1azS  
aHdXlmL  
自定义tag标签有很多特色,诸如: D?:AHj%gW  
lZ![?t}2`  
· 可以在JSP页面中自定义tag标签的属性 c.;}e:)s  
zEYT,l  
· 访问JSP页面中的所有对象 u~y0H  
M8HHyV[AmC  
· 可以动态地修改页面输出 "fTW2D74  
DcL;7IT  
· 彼此这间可以相互通信。你可以先创建一个JavaBeans组件,然后在一个tag中调用此JavaBeans组件,同时可以在另一个tag中调用它。 >azTAX6L3  
8Z:T.Gc  
· tag允许相互嵌套,可以在一个JSP页面中完成一些复杂的交互。 />,KWHR|:  
9yt)9f  
K~DQUmU@  
使用tag标签 7g&"clRGO  
ZN `D!e6  
9C_Vb39::$  
本节主要描述怎样在JSP页面中使用tag标签,以及tag标签的不同类型。 +M^+qt;]V  
mOQN$d[  
要使用tag标签,JSP程序员必须做2件事: e[)oT  
"q,.O5q}Y  
· 声明此tag标签的tag库 y (w&6:  
;:5Ahfo \  
· 实现此tag标签 O h{ >xg  
U&}v1wdZ3  
声明tag标签所在的tag库 VQ,;~^Td  
)J<VDO:_YA  
如果要使用tag标签,则应用JSP的taglib指示符来指定其tag库(注意:taglib要在在使用此tag标签之前声明) V+'C71-P  
DN%b!K:  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> (o5^@aDr  
V0ig#?]  
uri属性定义了唯一的标签库描述(以下简称TLD),它可以是直接是tld文件名或一个独一无二的名字。prefix是用来区别其它TLD中和本TLD中有重名的tag的一种手段。 / 8 0Q  
2Sg^SZFH+o  
TLD必须以.tld作为扩展名,并且存放在当前应用的WEB-INF目录或其子目录下。你可以通过它的文件名直接引用它,也可以通过别的方式间接地引用它。 q{:]D(   
nhZ^`mP  
以下taglib指示符直接引用一个TLD: ,6iXlch  
Je1'0h9d  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> Q?uHdmY*X  
C@#KZ`c)  
以下的taglib指示符通过一个逻辑名称间接地引用一个TLD: N!#0O.6  
R$Or&:E ^  
<%@ taglib uri=”/tutorial-template” prefix=”tt” %> K#>@T<  
Y_SB3 $])  
如果是间接引用TLD的话,那你必须还要在web.xml中定义此逻辑名称与tld文件之间的映射,具体做法是在web.xml中加入一个名为taglib的元素: E[8R )xC@  
2#hfBJg@  
<taglib> LI`H,2Km  
[')C]YQb=  
<taglib-uri>/tutorial-template</taglib-uri> M8p6f)l3  
Y;dQLZ CC  
<taglib-location> Z| f~   
'1r<g\ l  
/WEB-INF/tutorial-template.tld +IkL=/';#  
A<$w }Fy;  
</taglib-location> de<T5/  
]b6gZ<  
</taglib> 3 J!J#  
KdTDBC  
t<DZW#  
实现此tag标签 nA)KRCi  
[d^ [Y:I'\  
a58]#L~  
为了实现tag标签,你有2种方法来存放tag处理类。一、让tag处理类以.class的方式存放于当前应用的WEB-INF/class子目录下,二、如果tag处理类是以JAR包的形式存在的话,那可以放在当前应用的WEB-INF/lib目录下,如果tag处理类要在多个应用中共享,那么它就应放在jsp服务器上的common/lib目录下,对于tomcat来说,就是tomcat/common/lib目录下。 5H!6 #pqM  
r-aCa/4y!  
$(=0J*ND"  
tag标签类型 lc8zF5  
8EBy5X}US  
dtDT^~  
自定义的tag标签遵循XML语法。它有一个开始标记和一个结束标记,有的还有body(即文本节点): zHu w[  
\zMx~-2oN  
<tt:tag> 5dXDL~/2p  
j : $Ruy  
body |K,[[D<R  
.s8u?1b  
</tt:tag> u#^~([ I  
aSVR +of  
A]_5O8<buW  
一个不带body的tag标签如下: G%#M17   
8`GN8 F  
<tt:tag /> ;T,`m^@zf  
A/A; '9  
:5, k64'D  
简单的tag标签 E$1P H)  
*MM8\p_PuT  
一个没有body和属性的tag标签如下: o_@6R"|  
W#sCvI@   
<tt:simple /> )~LqBh  
*Al`QEW  
Q@aDa8Z  
带属性的tag标签 :|TQi9L$rj  
\{K~x@`  
^9`S`Bhp  
自定义标签可以有自己的属性。属性一般在开始标记中定义,语法为 attr=”value”。属性的作用相当于自定义标签的一个参数,它影响着tag处理类的行为。你可以在TLD中详细定义它。 9tBE=L=  
(D~NW*,9  
你可以用一个String常量给一个属性赋值,也可以通过表达式给它赋值,如<%= ...%>。以struts为例,它的logic:present标签就是用的String常量来给属性赋值: <Dq7^,}#  
{wwkbc*  
<loglic:present parameter = “Clear”> e.l3xwt>$  
[MI?  
而另一个标签logic:iterate是用表达式来给属性赋值: mVVL[z2+  
e4<[|B!O  
<logci:iterate collection=”<%= bookDB.getBooks() %>” o)r%4YOL  
S>nf]J`  
id=”book” type=”database.BookDetails”> #y>q)Ph  
$dkkgsw 7  
jk9/EmV*r  
带body的tag标签 cOrFe;8-.  
GX,)~Syw*  
一个自定义标签可以包含其它自定义标签、脚本变量、HTML标记或其它内容。 =?oYEO7  
3`U^sr:[%  
在下述例子中,此JSP页面使用了struts的logic:present标签,如果些标签定义了parameter=”Clear”的属性,则将清除购物车的内容,然后打印出一条信息: }]!?t~5*  
:vo#(  
<logic:present parameter=”Clear”> *DS>#x@3*i  
8Luw< Q  
<% cart.clear(); %> ee\xj$,  
M'>8P6O  
<font color=”#ff0000” size=”+2”><strong> ? e<D +  
#.W^7}H  
你选择了清除购物车! ?f&O4H  
Q)L6+gW^  
</strong></font> W~Ae&gcn#  
v FWg0 $,  
</logic:present> gBd@4{y6C.  
W0;MGBfb  
O;H|nW}  
到底是用属性还是用body来传递信息? m>&:)K}m  
rfH Az  
如上所述,我们既可以通过属性,也可以通过body来传递信息。但一般来说,比较简单的类型,如字符串或简单表达式最好采用属性来传递信息。 1|/-Ff"1@  
-]!zj#&  
2Mw^EjR  
定义脚本变量的tag标签 CEEAyip-c  
IEeh9:Km  
所谓脚本变量,是指JSP中可以调用的变量或对象。它可由tag标签产生。以下示例阐述了一个tag标签定义了一个名为tx的由JNDI所定义的事务处理对象。脚本变量可以是ejb对象、事务、数据库连接等等: u1) #^?  
y@2$sK3K  
<tt:lookup id=”tx” type=”UserTransaction” name=”java:comp/UserTransaction” /> J[{?Y'RUM  
/?_5!3KJ  
<% tx.begin(); %> >NMq^J'/  
-W'T3_  
... cZ l/8?dj}  
AoFxho  
<BX'Owbs!O  
具有协作关系的tag标签 ukwO%JAr  
vHM,_I{  
自定义tag标签之间可以通过共享对象来实现协作。在下述例子中,标签tag1创建了一个名为obj1的对象,在标签tag2仍可以重复使用obj。 r"bV{v  
4ztU) 1  
<tt:tag1 attr1=”obj1” value1=”value” /> kH">(f  
e763 yd  
<tt:tag2 attr1=”obj1” /> #CTeZ/g  
i&Xjbcbp  
在以下这个例子当中,如果外层的tag标签创建了一个对象,那么其内层的所有tag标签都可以使用这个对象。由于这样产生的对象没有一个指定的名字,那么就可以将少重名的冲突。这个例子阐述了一系列协作的嵌套对象。 n1PV/ Z  
AEE&{ _[S  
<tt:outerTag> @*^%^ P  
`FHKQS5  
<tt:innerTag /> ?my2dd,|  
aM!%EaT  
</tt:outerTag> "U o~fJ  
2!Sl!x+i\'  
Y"UB\_=  
Tag处理类 (K`@OwD  
R}T\<6Y  
X6G2$|  
Tag处理类必须实现Tag接口或BodyTag接口,不过现在一般都流行从TagSupport或BodyTagSupport类中继承,这些类或接口都可以在javax.servlet.jsp.tagext包中找到。 s~g0VNu Y  
R@A"U[*  
当JSP引擎看到自己的JSP页面中包含有tag标签时,它会调用doStartTag方法来处理tag标签的开头,调用doEndTag方法来处理tag标签的结束。 DM=`hyf(v  
ihBIE  
下表说明不同类型的tag所需要不同的处理过程: Cd'`rs}3  
*RJiHcII  
Tag处理类的方法 #iVr @|,  
ePscSMx&  
Tag标签类型  kAnK1W>  
所调用的方法 9 `T2  
qLa6c2o,  
基本标签 Bh5z4  
doStartTag, doEndTag, release 0}qnq"  
fp?cb2'7  
带属性的标签 {vox x&UX  
doStartTag, doEndTag, set/getAttribute1...N, release mJ JF  
 Vl`!6.F3  
带内容的标签 \kEC|O)8  
doStartTag, doEndTag, release a_U[!`/ w  
q:<vl^<j  
带内容的标签,且内容重复循环 |"i"8~/@<  
doStartTag, doAfterBody, doEndTag, release {pz7ADK<  
J?_-Dg(=  
带内容的标签,且内容与JSP交互 `L7Cf&W\l8  
doStartTag, doEndTag, release, doInitBody, doAfterBody, release /33m6+  
}II)<g'  
一个tag处理类可以通过javax.servlet.jsp.PageContext来与JSP交互,通过javax.servlet.jsp.PageContext类,tag处理类可以访问JSP中的request、session和application对像。 SmCtwcB1  
aK?PK }@  
如果tag标签是互相嵌套的,那内层的tag处理类可以通过它的parent属性来访问上层的tag处理类。 $*c!9Etl4  
@BoZZ  
一般情况都将所有的tag处理类打成了JAR的包,以便于发布。 $VnPs!a  
.kp3<.  
wuKr 9W9Xa  
Tag库描述(简称TLD) \ fSo9$  
Rg%Xy`gS  
3S{3AmKj?  
Tag库是用xml语言描述的,TLD包括了tag库中所有tag标签的描述,它一般用来被jsp服务器用来校验tag的语法正确性,或者被jsp开发者用来开发新的标签。 Hh`HMa'q  
>TG#  
TLD的文件扩展名必须为.tld,而且必须放在当前WEB应用的WEB-INF目录或其子目录中。 C8AR ^F W  
T07 AH  
一个TLD的内容的开头必须遵守标准的XML开头,用于描述DTD和xml的版本,例如: *^i"q\n5(  
u]MQ(@HHF  
<?xml version="1.0" encoding="ISO-8859-1" ?> Z}yd` 7  
St;@ZV  
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd"> 8 Az|SJ<  
TLD必须以<taglib>来作为它的根元素,<taglib>的子元素如下表: {Y1&GO;  
9"cyZO  
35n'sVn  
<taglib>的子元素 9O|k|FD  
]/{iIS_  
Element wj 15Og?  
Description nQ08(8  
N4$ K {  
tlib-version }S 6h1X  
Tag库的版本 PasVfC@  
{-1N@*K  
jsp-version y,Z2`Zmu  
Tag库所需要的jsp的版本 EqF>=5*  
:uB(PeAv*  
short-name Nn-EtM0w  
助记符,tag的一个别名(可选) DA^!aJ6iF  
yM# %UeZ\  
uri N ,nvAM  
用于确定一个唯一的tag库 6[\1Nzy>  
\:9<d@?  
display-name 'c#AGi9  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) W<T Ui51Y  
(kL(:P/  
small-icon NS){D7T  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) !112u#V  
 I|. <  
large-icon Yd]  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) a^7QHYJ6  
B_S))3   
description [ i8Ju  
对tag库的描述(可选) " 1%\Fil  
}%`f%/  
listener ]e(\<R6Gf  
参见下面listener元素 0y3C />a  
DqA$%b yyE  
tag 2)9XTY 6$  
参见下面tag 元素 =4 NKXP~C  
$J=`fx  
Listener元素 <z8z\4Hz  
: $N43_Wb  
一个tag库可能定义一些类做为它的事件侦听类,这些类在TLD中被称为listener 元素,jsp服务器将会实例化这些侦听类,并且注册它们。Listener元素中有一个叫listener-class的子元素,这个元素的值必须是该侦听类的完整类名。 mNKcaM?h  
@`XbM7D 5  
Tag元素 58t~? 2E  
gdkHaLL"  
每个tag元素在tag库中都要指出它的名字、类名、脚本变量、tag的属性。其中脚本变量的值可以直接在TLD中定义或通过tag附加信息的类来取得。每个属性描述了这个属性是否可以省略,它的值是否可以通过<%= …%>这样的JSP语法来获得,以及属性的类型。 A@jBn6  
p<c1$O*  
每一个tag在TLD中对应一个tag元素,下表是tag元素的子元素: &"d :+!4h  
&Xh=bM'/%m  
Tag元素的子元素 uTNy{RBD+  
aj]pN,g@N  
元素名称 z?WkHQ9  
描述 X3HJ3F;==  
%J+k.UrM  
name uvJmEBL:  
独一无二的元素名 `$XgfMBf |  
#6mr'e1  
tag-class ce7 $# #f  
Tag标签对应的tag处理类 XwDt8TxL  
8 @r>`c  
tei-class >%A~ :  
javax.servlet.jsp.tagext.TagExtraInfo的子类,用于表达脚本变量(可选) OmZK~$K_  
S^{tRPF%d  
body-content `a5,5}7v%`  
Tag标签body的类型 zQoJ8i>  
8=u88?Bh  
display-name \ESNfL5  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) |y&vMx~t  
"qoJIwl#q  
small-icon IwR=@Ne8  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) O)c3Lm-w  
o.wXaS8  
large-icon WF-^pfRq~  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) Kh{_BdN  
pV*d"~T  
description @ 1FWBH~  
此tag标签的描述 S e|h]+G  
FpZ5@  
variable DTl&V|h$  
提供脚本变量的信息(同tei-class)(可选) BirnCfj/2  
ik5"9b-\<  
attribute Awe'MGp%  
Tag标签的属性名 zC`ediyu  
e#@u&+K/f  
以下章节介绍对于不同类型的tag,如何具体地实现它们。 f{U,kCv  
|nY+Nen7  
G0(A~Q"  
简单的tag (zw.?ADPCT  
tR(L>ZG{  
|WSm puf  
tag处理类 c 6/lfgN  
Up*6K=Tny  
简单的tag处理类必须实现Tag接口的doStartTag和doEndTag方法。当jsp引擎碰到tag标签的开头时,doStartTag被调用,因为简单的tag没有body,所以此方法将返回 SKIP_BODY。当jsp引擎碰到tag标签的结尾时,doEndTag被调用,如果余下的页面还要被计算,那它将返回EVAL_PAGE,否则将会返回SKIP_PAGE。 99~ZZG  
QB*n [(?  
以下是例子:对于标签 <tt:simple /> ,它的tag处理类实现如下: 4KY@y?H g  
e?WI=Og  
+/r h8?  
public SimpleTag extends TagSupport {6iHUK   
n1)].`  
{ |;R-q8  
=z'533C  
public int doStartTag() throws JspException m Gx{Vpt  
$x2G/5?  
{ tD])&0"(  
- XB[2h  
try{ 0G3T.4I  
a> S -50  
pageContext.getOut().print(“Hello.”); $YK~7!!  
r@ba1*y0  
}catch(Exception e){ Qm4cuV-0{  
^+Njz{rpG  
throw new JspTagException(“SimpleTag: “ + e.getMessage()); z5W;-sCz  
n +dRAIqB  
} 5"w%  
xLw[ aYy4  
return SKIP_BODY; vqo ~?9z[e  
rLcXo %w  
} KJ_L>$ ]*  
@}{Fw;,(7n  
public int doEndTag() ._<gc;G  
9mEhZ"  
{ qG0gc\C}  
i8.OM*[f  
return EVAL_PAGE; RY*yj&?w [  
e r"gPW  
} cBU@853  
d4o_/[  
} L>!MEMqm  
1wW4bg 5  
X:W}S/  
注意:如果tag标签没有内容的话,那必须定义body-content元素为空,例如 r]&&*:  
EC?U#!kv  
<body-content>empty</body-content> BXr._y, cr  
!={QL:  
]% UAN_T  
带属性的tag标签
评价一下你浏览此帖子的感受

精彩

感动

搞笑

开心

愤怒

无聊

灌水
级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
只看该作者 1 发表于: 2007-01-01
tag处理类 Ms A)Y  
6H:EBj54?  
对于tag标签的每个属性,你必须依照JavaBeans规范来定义其属性,以及get和set方法。以struts的logic:present 标签为例, {=_xze)  
YrTjHIn~w  
<logic:present parameter=”Clear”> 2hT H  
osTin*T.  
与此相应,此tag处理类应有如下方法和定义: PAu/iqCH  
#b{;)C fL  
g")pvK[e  
protected String parameter = null; q,(hs]\@  
E5$uvxCI  
public String getParameter() ;MjOs&1f0K  
<@=w4\5j9  
{ w4Ku1G#jC  
_2WIi/6K  
return this.parameter; +ID% (:  
RueL~$*6.~  
} m\ /V0V\  
rE\.[mFI  
public void setParameter(String parameter)  34~[dY  
Dz+R Q`Vn  
{ <(Ktf0'__  
"`5BAv;u  
this.parameter = parameter; ]j< & :_  
j,#R?Ig  
} dH0wVI<z  
G)\6W#de4  
KT8]/T`U  
注意:如果你的属性名为id,而且你的tag处理类是从TagSupport类继承的,那你就不需要定义它的属性和set和get方法,因为他们早已在TagSupport被定义过了。 &qZ:"k  
|*zvaI(}  
Attribute元素 YQ5d!a.  
[R Hji47  
对于tag标签的每个属性,你必须定义它是否必须的,它的值是否可以用诸如<%= …%>的表达式来获得,以及它的类型(可选),如果不指定它的类型,那就默认为是java.lang.String类型。如果rtexprvalue元素被定义为true或yes,那么在type元素中就定义了attribute的返回类型。 #NWc<Dd  
,y/N^^\  
<attribute> H/Ov8|  
+K[H! fD  
<name>attr1</name> j(\jYH>   
N9cUlrDO  
<required>true|false|yes|no</required> mKBPIQ+ZS  
xsXf_gGu  
<rtexprvalue>true|false|yes|no</rtexprvalue> )"<:Md$7  
p\M\mK  
<type>attribute的返回类型(只用当rtexprvalue为真是才有效)</type> g [+_T{  
*5;#+%A  
</attribute> "_e /O&-cH  
GZ/vUe  
如果tag的某个属性不是必须的,那tag处理类会自动提供一个缺省值。 ,?s: s&4  
>"+bL6#  
例如,在logic:present这个tag标签中定义了一个属性叫parameter,但它不是必须的,而且它可以被诸如<%= …%>的表达式来赋值。 44cy_  
]}dAm S/  
<tag> NeY,Of|  
Q GDfX_  
<name>present</name> 8BwJWxBQ  
\+sP<'~M  
<tag-class>org.apache.struts.taglib.logic.PresentTag</tag-class> :KJZo,\  
/<oBgFMoJ  
<body-content>JSP</body-content> G7H'OB &  
t~FOaSt  
Hf$LWPL)lM  
> v ]-B"Y  
<attribute> JZB@K6 ~dO  
XRR`GBI  
<name>parameter</name> X7& ^"|:  
Y/< ],1U  
<required>false</required> V .VV:`S  
Fs)m;C  
<rtexprvalue>true</rtexprvalue> .=4k'99,  
a,*~wmg  
</attribute> 1]Gp \P}  
`1"Xj ^ YM  
w B[H &  
?BnjtefIe  
</tag> pwO U6A!  
}z8HS< #Q  
`=cOTn52  
属性元素的校验 m;KD@E!  
zAdZXa[MRY  
;?0r,0l2$  
有关于tag标签的有效值可以从tag库的说明文档中获得,当JSP页面被编译时,jsp引擎会强制性地参照TLD中定义的规则进行检查。 En/EQ\T@F  
"+:IA|1wD  
还有一个方法也可以进行属性元素的校验,就是先继承类TagExtraInfo,然后调用它的isValid方法。这个类同时也起到提供tag中定义的脚本变量信息的作用。 Se-n#  
"#a,R ^J  
IsValid方法通过TagData对象来传递属性信息,它包括着tag的所有的属性名-值的信息。由于校验发生在运行时刻,因此这个属性的值将被赋值为TagData.REQUEST_TIME_VALUE。 >0qe*4n|M  
iu 6NIy7D  
例如tag标签<tt:twa attr1=”value1” />在TLD中定义如下: . 'rC'FT  
SV96eYT<  
<attribute> O<?z\yBtS^  
-|~tZuf  
<name>attr1</name> A&6qt  
C| Vz `FY  
<required>true</required> |cUBS)[)X  
iZ-"l3) D  
<rtexprvalue>true</rtexprvalue> |VD}:  
> H(o=39s  
</attribute> vL"[7'  
fbK`A?5K  
ON<X1eU  
这个定义说明了attr1能在运行期间被赋值。 OAXF=V F#  
vtVc^j4  
以下的isValid方法检查attr1属性的值是否属于Boolean类型。注意由于attr1能在运行刻被赋值,那么isValid方法必须检查tag用户是否对此tag进行了运行时刻赋值。 #y&O5    
L@HWm;aN  
Sx3R 2-!Z  
Public class TwaTEI extends TagExtraInfo Z>zW83a  
)j>BvO  
{ 11 >K\"K}  
* >XmJ6w  
public boolean isValid(Tagdata data) COf>H0^%Q  
.IJgkP)!]  
{ B`SHr"k!V[  
VDP \E<3"  
Object o = data.getAttribute(“attr1”); #$[}JiuL/  
jVtRn.qh  
If(o != null && o != TagData.REQUEST_TIME_VALUE) "~&d= f0m  
{)d{:&*K.  
{ mlD 1 o  
d=_Wgz,d  
if( ( (String)o).toLowerCase().equals(“true”) || +sc--e?  
d2e4=/ A%  
((String)o).toLowerCase().equals(“false”) ) Zr.6J*&!  
)2jBhT  
return true; 9c_h+XN?y  
*N #{~  
else k)l^ ;x-  
VU[4 W8f  
return false; UI>?"b6 L  
uY6|LTK&x  
} `vFYe N;  
gP?uLnzvi  
else )W& $FU4JK  
`Mp-4)mn  
return true; %IbG@ }54  
&_N$S2  
} b\O%gg\p%!  
i>`!W|=_  
} CUR70[pB)  
3'zm)SXJ  
9AsK=/Buf  
带body的tag r g$2)z1  
+/E yX =  
UoiXIf_Q  
tag处理类 8#MiM . f  
3M[b)At V.  
a!US:^}lu  
如果tag标签含有内容,那处理方式会略微有些不同,而且还要视tag处理类是否要与body交互的情况而定。如果要与body交互,那我们认为tag处理类要可能要对body进行操作。 h^}r$k_n  
_#8OHG.x  
Tag处理类不与body交互 ZCbnDj  
Y@Zv52,  
如果tag处理类不与body交互,tag处理类应该实现Tag接口或从TagSupport中派生,如果body要被计算,那么doStartTag方法应返回 EVAL_BODY_INCLUDE,否则应返回SKIP_BODY。 &gL &@';,  
8T#tB,<fFW  
如果tag处理类要对body反复运算,则它应该实现IterationTag或从TagSupport中派生。如果tag处理类认为body还未计算完的话,那它的doStartTag方法和doAfterBody方法必须返回EVAL_BODY_AGAIN。 \%FEQa0u  
,{br6*E  
Tag处理类与body交互 -}Iw!p#O3  
, 9C~%c0Pw  
如果tag处理类与body交互,那tag处理类应实现BodyTag接口或从BodyTagSupport中派生。这种tag处理类一般要实现doInitBody和doAfterBody方法。 C<.Ny,U  
"/zIsn7  
Body允许一些方法来读写它的内容。Tag处理类可以调用body内容的getString或getReader方法来从body中提取信息,也可用 writeOut(out) 方法来将body的内容写入到out对象中。其中out对象通过tag处理类的getPreviousOut方法来获得。 =#"ZO  
pGO)9?j_N  
如果body的内容需要被计算,那么doStartTag方法必须返回EVAL_BODY_BUFFERED,否则,它将返回 SKIP_BODY。 Dr!g$,9  
LT3ViCZ-n  
doInitBody 方法 dlx "L%  
UpU2H4  
此方法在body内容已经设好,但未被计算之前被调用。你可以根据不同的body内容来制定初始化策略。 Iw<: k  
dk^Uf84.Gr  
doAfterBody方法 kCu"G  
}RvP*i  
此方法在body内容已被计算后进行调用。 @l:o0(!W  
L/VlmN_v>s  
和doStartTag方法一样,doAfterBody方法返回一个指示符指示是否要继续计算body,如果要继续计算,则doAfterBody应返回EVAL_BODY_BUFFERED,否则,它应返回SKIP_BODY。 $C;)Tlh  
u,R;=DNl  
release 方法 z[I3k  
`;9Z?]}`  
tag处理类调用此方法将它的状态重置为初始状态,并释放所有的私有资源。 mXH\z  
;L gxL Qy;  
sr&hQ  
以下的例子读取body的内容(其中含有一条sql语句),然后将它传递给一个对象,让它进行查询。由于此处body不须重新计算,所以doAfterBody会返回SKIP_BODY。 J}9 I5O  
DhAQ|SdCf  
A80r@)i  
Public class QueryTag extends BodyTagSupport tX$ v)O|  
|Ts|>"F'  
{ Jmp%%^  
/*+P}__k  
public int doAfterBody() throws JspTagException _U"9#<  
Whd2mKwiO  
{ H7 xyK  
uq>\pO&P  
BodyContent bc = getBodyContent(); /8(\AuDT  
[a<u cJ  
//将body的内容以字符串的格式提取出来 &C.{7ZNt  
8~=<!(M)m/  
String query = bc.getString(); /2!Wy6 p  
5VU 5kiCt  
//清除body 8 pQx6QE  
\C )S3!h  
bc.clearBody(); ?4kM5NtP  
t@`w}o[#  
try{ _i=431Z40  
DaV:Slp9  
Statement stmt = connection.createStatement(); W]]@pbG"H\  
NEpomE(>x  
Result result = stmt.executeQuery(query); .@  3  
tf VK  
}catch(SQLException e){ +ti_?gfx  
}W:Rg}v  
throw new JspTagException(“queryTag: “ + e.getMessage() ); @MS}tZ5  
SpM|b5c5  
return SKIP_BODY; xb2xl.2x!  
UkE  fuH  
} TJHab;7F  
(^:0g.~c  
} ,[ UqUEO  
w&vZ$n-|  
[f^:V:) {  
body-content元素 g9A8b(>F&@  
o1m+4.-  
5cv&`h8uo_  
由于tag可能会有body,你必须用body-content元素来指定body内容的类型: 6%hr]>L  
"G^Z>Z-`  
<body-content>JSP|tagdependent</body-content> E^)>9f7  
m zh8<w?ns  
{<~oa+"  
如果body的内容是定制的或内部的tag、脚本元素、或HTML广本,则归类为JSP类型。其他的类型,比如上面代码所述的?D?D将sql statement类传给 query tag的这种类型应该标为tagdependent。 ps DY}y\"  
\; 9log<Z  
注意:实际上body-content的值并不影响tag处理类对body内容的处理,它仅仅是被tag编辑工具用来描述此body的内容。 ,eI2#6w|C  
m44"qp  
S~~G0GiW  
用tags定义脚本变量 "~1{|lj|)  
Y ,Iv<Hg  
A &d67,&B  
tag处理类 4O TuX!  
4=G)j+RCH  
78=a^gRB  
tag处理类负责创建或设置页面中定义的脚本变量,用pageContext.setAttribute(name,value,scope)或pageContext.setAttribute(name,value)方法来实现。一般来说,tag处理类通过脚本变量的名称来获取它,脚本变量的名称一般可用get方法来获得。 y@#JzfY?Hr  
%j.B/U$  
如果脚本变量的值依赖于tag处理类中的上下文中某一对象,那它可用pageContext.getAttribute(name,scope)方法来找到那个对象。一般的处理过程是tag处理类先找到脚本变量,再对其进行处理,然后用pageContext.setAttribute(name,object)的方法来设置它的新值。 #%~PNki  
\iBEyr]  
对象的生存周期(scope)如下表: K@JGGgrE`!  
B_gzpS]  
对象的生存周期表 kqebU!0-  
lUL6L 4m  
名字 ?5N7,|K)  
可访问范围 Hwz.5hV"  
生存周期 [tKH'}/s=  
q X"Pg  
page :>:F6Db"U  
当前页面 FZt a  
一直有效,除非页面向客户提交响应或重定向到一个新页面 v%ldg833l  
N;YAG#'9~_  
request p;y\%i_  
当前页面或当前页面重定向到的页面 Y#VtZTcT  
一直有效,除非页面向客户提交响应 CAbeb+O  
9J*M~gKbz  
session .T2P%Jn.  
当前页面或在同一浏览器窗口中的页面 pR3@loFQ`o  
一直有效,除非关闭当前浏览器、超时、网络故障 yDuMn<=3  
XF6ed  
application 'n>v}__&|  
整个web应用程序的所有请求 sjZ@}Vk3b  
一直有效,除非发生网络故障、服务器故障 c:J;Q){Xz  
ii3{HJ*C  
提供关于脚本变量的信息 T J!d 7  
.T>^bLuFy  
以下示例定义了一个名为“book”的脚本变量,用来访问程序中关于书的信息: 8h.Dc&V  
^$N}[1   
<bean:define id=”book” name=”bookDB” property=”bookDetails” type=”database.BookDetails” /> R{3?`x!fY  
bAUruTn  
<font color=”red” size=”+2” > n$*e(  
8\N`2mPt  
<%= messages.getString(“CartRemoved”) %> T 5AoBUw  
A-&'/IHR"B  
<strong><jsp:getProperty name=”book” property=”title” /></strong> )YtdU(^J$  
\y7kb  
</font> ;kX:k~,]}>  
fn~Jc~[G|  
当包含此tag的JSP页面被编译时,jsp引擎会自动生成关于此book的同步的代码(同步可以避免几个客户同时访问此book时造成的冲突),要生成同步代码,jsp引擎需要知道此脚本变量的如下信息: Rk8oshS+2  
QY^v*+lr\  
· 脚本变量名称 S [$Os7  
3pk=c-x  
· 脚本变量所属的类 2C@ui728  
!.EDQ1k  
· 此脚本变量是否引用了一个新的或已存在的对象 [z2jR(+`U  
# :)yh]MP  
· 此脚本变量的有效性 pX/42W  
RBA{!  
有两种办法可以向jsp引擎提供关于脚本变量的信息:在TLD中定义variable子元素,或用tei-class子元素定义一个额外tag信息类。用variable最简单,但可能降低了一些灵活性。  CJ~gE"  
URo#0fV4C  
Variable元素 f4 [Bj{F  
ndXUR4  
Variable元素有如下子元素: RT~6#Caf  
ZLS\K/F>>=  
· name-given ?D?D 给出的名字,是一个常量 =o+js;3  
z'!sc"]W6  
· name-from-attribute?D?D 属性名,在编译时给出的属性名 Ec/-f `8  
mu>L9Z~(L_  
name-given或name-from-attribute两者必须选一,但以下子元素是可选的: oIJ.Tv@N(  
< %t$0'  
· variable-class?D?D变量的类型,缺省为java.lang.String。 O0~Qh0~l  
wn&5Ul9Elb  
· declare?D?D此脚本变量是否引用了一个新对象,缺省为True。 UNC%<=  
ju8DmC5  
· scope?D?D脚本变量的范围,缺省为NESTED。下表描述了scope的几种类型: hmG^l4B.T  
7rZE7+%]  
脚本变量的有效范围 uto E}U7]  
FQgc\-8tm  
 {ch+G~oS  
有效性 z~f;5xtI  
方法 w vQ.9  
~stG2^"[  
NESTED ?O|CY  
在tag标签的开始和结束之间 u&Lp  
如果tag处理类实现BodyTag接口,则在doInitBody和doAfterBody中调用,否则在doStartTag中调用 1UwpLd  
S#|dmg;p  
AT_BEGIN )Bb:?!EuEH  
从tag标签的开始一直到页面结束 rQ:+LVfXjA  
如果tag处理类实现BodyTag接口,则在doInitBody、doAfterBody和doEndTag中调用,否则在doStartTag和doEndTag中调用 Z{ AF8r  
"Xz[|Xl  
AT_END A4mnm6Tf  
从tag标签的结束一直到页面结束 Ltrw)H}  
在doEndTag中调用 F5(DA  
AB0>|.  
以struts为例,它的bean:define标签的实现遵循JSP1.1规范,此规范要求使用额外tag信息类来定义脚本变量。Variable元素是JSP1.2规范中加入的。以bean:define标签为例,你可以定义如下variable元素: <0M 2qt8  
I&s!}$cD  
<tag> T:G8xI1 P  
3yXSv1  
<variable> i uGly~  
C"[d bh!  
<name-from-attribute>id</name-from-attribute> ]T<\d-!CZN  
OV+|j  
<variable-class>database.BookDetails</variable-class> g4U`Qf3  
ol#4AU`  
<declare>true</declare> so]p1@K  
RX cfd-us  
<scope>AT_BEGIN</scope> W02t6DW  
+DR,&;  
</variable> [Q:C\f]  
jFwu&e[9;  
</tag> w dpd`  
F=9-po  
额外tag信息类 f8 vWN  
j}F;Bfq!  
如果要定义一个额外tag信息类,你要继承javax.servlet.jsp.TagExtraInfo类。一个TagExtraInfo类必须实现getVariableInfo方法,此方法返回一个叫VariableInfo的数组类,它包括如下信息: '0tNo.8K  
pLtAusx  
· 变量名 hVLV Mqd  
E8Y(C_:s  
· 变量所属类名 bH1MDBb2  
v9K=\ j  
· 此变量是否引用了一个新对象 FC&841F  
}u&,;]  
· 此变量的有效范围 8oxYgj&~X  
<3WaFi u  
jsp引擎将一个名为data的参数传给getVariableInfo方法,data中包括tag标签中的所有“属性名?D?D属性值”对。它可以用来向VariableInfo对象提供脚本变量的名字和类名。 rT/4w#_3  
8HxtmFqG  
以struts为例,它在bean:define标签中定义了一个名为DefineTei的额外tag信息类,用来向脚本变量提供信息。由于脚本变量的名称(book)和类名(database.BookDetails)是通过tag标签的属性来传递的,它们一般定义在VariableInfo的构建代码中,并且可用data.getAttributeString方法来得到这些信息。如果要允许book脚本变量能在从tag开始直到整个JSP页面结束的范围内都可用的话,那它的范围应设为AT_BEGIN。如下所示: RGC DC*\  
D@iE2-n&V  
.cCB,re  
public class DefineTei extends TagExtraInfo tFrNnbmlQ  
\O G`+"|L  
{ *{1]b_<  
Cu-z`.#}R  
public VariableInfo[] getVariableInfo(TagData data) 0m>?-/uDx  
o7^u@*"F  
{ Hr}pO"%  
zLS=>iLD{  
String type = data.getAttributeString(“type”); t}m"rMbt  
@S#Ls="G  
If( type == null) i0py5Q  
: kw14?]_  
type = “java.lang.Object”; 9|5>?'CqP  
(+w.?l  
return new VariableInfo[] { {Ip)%uR  
g(-}M`  
new VariableInfo(data.getAttributeString(“id”), ;: 4PT~\*  
88~ lP7J  
type, 3^2P7$W=   
M?G4k]  
true, -xMM}r y  
nX\Q{R2  
VariableInfo.AT_BEGIN) biy[h3b  
0?/vcsO  
}; dePI&z:  
2& ZoG%)  
} ?I}0[+)V  
NWt5)xl  
} AiOz1Er  
68YJ@(iS  
ZB5u\NpcW  
注意:关于额外tag信息类的类名必须要在TLD中的tag标签下的tei-class子元素中定义。因此,DefineTei的tei-class中的定义看起来如下: v3Xt<I=4y  
<tei-class> C#@>osC  
org.apache.struts.taglib.bean.DefineTagTei 5nh:S0M6V  
</tei-class> -gR }^D   
e,I{+ ^P  
z3|)WS^  
具有协作关系的tag j`LvS  
{q^?Rw  
\rPT7\ZA  
tag通过共享对象来进行协作,JSP技术支持2种方式的对象共享。 !dZpV~g0  
a/s6|ri`0  
第一种方法是使用pageContext对象进行对象的共享(可支持JSP页面和tag处理类之间的共享),如果在一个tag处理类中要调用由另一个tag处理类创建的对象,可调用pageContext.getAttribute(name, scope)方法。 ; +%|!~  
5l,Q=V^@l  
第二各方式的共享是对于tag之间有嵌套关系而言的,外层的tag所创建的对象对于内层的tag来说是可以共用的。这种形式的共享的好处是减少了可能存在的重名冲突。 yE>f.|(  
6fcn(&Qk  
要访问一个嵌套tag创建的对象,tag处理类必须先找到此嵌套tag对象,可用TagSupport的静态方法 TagSupport.findAncestorWithClass(from, class)或TagSupport.getParent方法。前者在当不确定此tag是否为嵌套tag对象时使用。一旦它的父类被找到,它就能访问其所有动态或静态创建的对象。静态创建的对象是父类的成员,而动态创建的对象可能是父类的私有对象。诸如此类的对象可以用tag处理类的setValue方法来保存,用getValue方法来获得。 [&H?--I  
+E8}5pDt  
下例阐述了以上两种共享对象的方法。在这个例子当中,一个查询tag检查一个名为connection的属性名是否在doStartTag中被设置。如果connection属性被设置,tag处理类从pageContext中得到这个connection对象。否则,此tag处理类先找到它的父tag处理类,然后从它的父tag处理类中找到connection对象。  OYwH$5  
ns;nle|m  
IP-}J$$1  
public class QueryTag extends BodyTagSupport 0\a;} S'g#  
&Rxy]kBA  
{ lgei<\6~n5  
g4CdzN~  
private String connectionId; xjO((JC  
s\dhQZw3  
public int doStartTag() throws JspException $bo 5:c  
/Q*cyLv  
{ mvrg!/0w  
Yh 9fIRR  
String cid = getConnection(); D`fi\A  
ZW>?y$C+  
if(cid != null) {H$m1=S  
BBUXoz  
{ "F8A:tR  
8"2X 8C8  
//存在一个connection id,使用它。 aVbv.>  
9_5tA'Q  
connection = (Connection) pageContext.getAttribute(cid); Wzx Dnd<B  
=h/0k y  
} u>I;Cir4  
N,Ys}qP  
else "H!2{l{  
=`y.L5  
{ *3r{s'm  
G>H',iOI  
ConnectionTag ancestorTag = (ConnectionTag)findAncestorWithClass(this, Kl)PF),  
gt= _;KZ  
ConnectionTag.class); T.R(  
j@b18wZ  
if(ancestorTag == null) wU= @,K  
Y/aNrIK7  
{ H;nq4;^yK  
}iF"&b0n"  
throw new JspTagException(“一个没有connection属性的查询标签必须被一个connection标记嵌套。”); vJE>H4qPmD  
Gkq<?q({t  
} d}e/f)(  
|e#ea~/b  
connection = ancestorTag.getConnection(); a}]zwV&  
$Y Cy,Ew   
} I_/kJ#7vj  
3[E)/~-  
} {2,OK=XM|  
a|\ZC\(xI  
} p"XQJUuD  
.Lc<1s  
7 *#pv}Y  
?a]u yw,  
此查询标签在JSP页面中的调用形式可以从以下2种定义中任选一种: k2S6 SB  
MX.=k>  
=5yI>A0  
<tt:connection id=”con01” ...> ... </tt:connection> E*_lT`Hzf  
gbJz5EEq  
<tt:query id=”balances” connection=”con01” > }\oy?_8~  
{V)Z!D  
SELECT account, balance FROM acct_table !ENb \'>J>  
wZV/]jmlEt  
where customer_num = <%= request.getCustno() %> |Skxa\MI  
1*!`G5c,}  
</tt:query> {Noa4i  
Im\{b=vT  
MxXu&.| _  
,:!dqonn  
]c \gUU  
<tt:connection ...> utz!ElzA  
i1#\S0jN  
<x:query id=”balances”> L*VO2YI  
B3V=;zn3  
SELECT account, balance FROM acct_table tE: m& ;I  
k^IC"p Uc  
where customer_num = <%= request.getCustno() %> Jm+hDZrW  
,&\uuD&.@  
</x:query> Yy"05V.  
^|(w)Sy  
</tt:connection> liUrw7,  
?r,lgaw  
u}7#3JfLn  
与此同时,在TLD中必须指定connection属性为可选的,定义如下: ttwfWfX  
IaU  
<tag> M)U 32gI:  
HZ1e~IIw  
... @ qfVt  
)&j4F)  
<attribute> 7O)U(<70  
L##lXUl  
<name>connection</name> ~ZSP K;D[  
GCUzKf&  
<required>false</required> _:,:U[@Vz  
JWa9[Dj  
</attribute> x"Hi!h)v  
tfr*/+F  
</tag>
描述
快速回复

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