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

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

级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
标准的JSP 标记可以调用JavaBeans组件或者执行客户的请求,这大大降低了JSP开发的复杂度和维护量。JSP技术也允许你自定义taglib,其实换句话说,taglib可以看成是对JSP标记的一种扩展,正如xml是对html的一种扩展一样。taglib通常定义在tag标签库中,这种标签库存放着你自己定义的tag标签。简而言之,如果使用taglib,那么你可以设计自己的JSP标记! <%% )C>l  
Sw"h!\c`  
一般来说,自定义tag标签主要用于操作隐藏对象、处理html提交表单、访问数据库或其它企业级的服务,诸如邮件和目录操作等等。自定义tag标签的使用者一般都是那些对java编程语言非常精通,而且对数据访问和企业级服务访问都非常熟悉的程序员,对于HTML设计者来说,使得他可以不去关注那些较复杂的商业逻辑,而将精力放在网页设计上。同时,它也将库开发者和库使用者进行合理分工,自定义tag标签将那些重复工作进行封装,从而大大提高了生产力,而且可以使得tag库可用于不同的项目中,完美地体现了软件复用的思想。 rO.[/#p\  
AkW>*x  
在这篇文章中,我们主要讨论: yp^k;G?_d  
IQtQf_"e1  
· 什么是自定义tag标签? 9kF0H a}J  
Ee7+ob  
· 怎么使用tag标签? irq{ 21  
! }e75=x  
o 声明要使用的tag库 7%? bl  
];6955I!  
o 找到与之对应的tag处理类 s !2Iui @  
:Z2997@Y  
o tag标签的类型 ru9@|FgAE  
(BxmV1  
· 自定义tag标签 ?<W|Ya  
>K4Nn(~ys  
o tag处理类 +y'2 h%>h[  
oOvQA W8`  
o tag库描述 {5X,xdzR  
,lvG5B\0  
o tag标签示例 r"{jrBK$  
.uS`RS8JM  
o 带属性的tag o/V T"cT  
.AO-S)wHR  
o 带body的tag Lp(`m=;O  
C"**>OGe  
o 定义了脚本变量的tag u<fZ.1  
Z#N w[>NN*  
o 具有协作关系的tag c?_7e9}2  
~M H ^R1=]  
· 自定义tag标签 p o)lN[v  
V?G%-+^  
o 一个迭代tag的例子 ~D|,$E tX4  
$6*Yh-"g  
o 一个模板tag库 "h[)5V{  
u=v-,Tw  
o tag处理类到底是怎样被调用的? F$ G)vskd  
a$Ud"  
inO;Uwlv  
什么是自定义的tag? 7* Y*_cH5  
?G',Qtz<K  
一个自定义的tag标签是用户定义的一种JSP标记。当一个含有自定义的tag标签的JSP页面被jsp引擎编译成servlet时,tag标签被转化成了对一个称为tag处理类的对象进行的操作。于是当JSP页面被jsp引擎转化为servlet后,实际上tag标签被转化成为了对tag处理类的操作。 ?uL-qsU  
~!5Qb{^  
自定义tag标签有很多特色,诸如: z{w %pUn}  
O9By5j 4  
· 可以在JSP页面中自定义tag标签的属性 e_|<tYx><  
D>W&#A8&y  
· 访问JSP页面中的所有对象 f9>pMfi:@  
=Jw*T[E  
· 可以动态地修改页面输出 G[ #R1'  
uk$MQ v*D  
· 彼此这间可以相互通信。你可以先创建一个JavaBeans组件,然后在一个tag中调用此JavaBeans组件,同时可以在另一个tag中调用它。 :ZB.I(v  
ibQ xL3  
· tag允许相互嵌套,可以在一个JSP页面中完成一些复杂的交互。 0vSPeZ  
2%R.~9HtA  
L(Twclrb  
使用tag标签 L7(FD v,?  
;DnUeE8  
+3zQ"lLD^  
本节主要描述怎样在JSP页面中使用tag标签,以及tag标签的不同类型。 1DAU *^-  
fm^`   
要使用tag标签,JSP程序员必须做2件事: +l)t5Mg\  
q#c+%,Z=C  
· 声明此tag标签的tag库 e4Ibj/  
OZf@cOTWK  
· 实现此tag标签 r`Fs"n#^-4  
b~tu;:  
声明tag标签所在的tag库 6U8esPs,  
0Mn |Yb4p  
如果要使用tag标签,则应用JSP的taglib指示符来指定其tag库(注意:taglib要在在使用此tag标签之前声明) Gchs$^1`t  
V 1d#7rP  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> "DvZCf[}  
s=jH1^  
uri属性定义了唯一的标签库描述(以下简称TLD),它可以是直接是tld文件名或一个独一无二的名字。prefix是用来区别其它TLD中和本TLD中有重名的tag的一种手段。 P~!,"rY  
o@360#njF  
TLD必须以.tld作为扩展名,并且存放在当前应用的WEB-INF目录或其子目录下。你可以通过它的文件名直接引用它,也可以通过别的方式间接地引用它。 ;g#nGs>  
|+HJ>xA4I  
以下taglib指示符直接引用一个TLD: PD S( /x&  
"dt}k$Gr  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> ZEDvY=@a   
<Bn0wr8)\  
以下的taglib指示符通过一个逻辑名称间接地引用一个TLD: 2Uf/'  
-U$;\1--  
<%@ taglib uri=”/tutorial-template” prefix=”tt” %> I`IW^eZM  
"eTALRL'o  
如果是间接引用TLD的话,那你必须还要在web.xml中定义此逻辑名称与tld文件之间的映射,具体做法是在web.xml中加入一个名为taglib的元素: (m! kg  
fHZ9wK>  
<taglib> (r?hD*2r  
nJv=kk1|o  
<taglib-uri>/tutorial-template</taglib-uri> Y$,~"$su|  
Sw>>]UjU  
<taglib-location>  ^ b5+A6?  
b1'849i'y=  
/WEB-INF/tutorial-template.tld g^|R;s{  
v]Pyz<+  
</taglib-location> K0vS  
Z6Mjc/  
</taglib> J{a9pr6  
b5%<},ySq  
*wJz0ex7R/  
实现此tag标签 I<<1mEk  
"R)n1,0  
2x|F Vp  
为了实现tag标签,你有2种方法来存放tag处理类。一、让tag处理类以.class的方式存放于当前应用的WEB-INF/class子目录下,二、如果tag处理类是以JAR包的形式存在的话,那可以放在当前应用的WEB-INF/lib目录下,如果tag处理类要在多个应用中共享,那么它就应放在jsp服务器上的common/lib目录下,对于tomcat来说,就是tomcat/common/lib目录下。 ~$^ >Vo  
0'A"]6  
jbZTlG  
tag标签类型 [+A]E,pv]1  
$E;Tj|W  
}zkFl{/u  
自定义的tag标签遵循XML语法。它有一个开始标记和一个结束标记,有的还有body(即文本节点): ^%Y-~yB-  
J_yXL7d  
<tt:tag> /L(}VJg-  
K9}Brhe  
body znWB.H  
o>+mw|{  
</tt:tag> ]3 GO_tL  
B9 ?58v&  
T)q Uf H  
一个不带body的tag标签如下: /|&4&$  
4|Y1W}!0/  
<tt:tag /> t(6i4c>  
_~umE/tz  
yXEI%2~)  
简单的tag标签 sieC7raO  
}C[ "'tLX  
一个没有body和属性的tag标签如下: E^{!B]/oP  
)'7Qd(4WT  
<tt:simple /> >y#qn9rV1  
Dz2Z (EXI~  
:?ZrD,D  
带属性的tag标签 _e8v12s  
p NQ7uy  
PMbq5  
自定义标签可以有自己的属性。属性一般在开始标记中定义,语法为 attr=”value”。属性的作用相当于自定义标签的一个参数,它影响着tag处理类的行为。你可以在TLD中详细定义它。 [%6)  
6'uCwAQU  
你可以用一个String常量给一个属性赋值,也可以通过表达式给它赋值,如<%= ...%>。以struts为例,它的logic:present标签就是用的String常量来给属性赋值: x)$0Nr62D  
726UO#*  
<loglic:present parameter = “Clear”> jVoD9H F/  
8a8D0}'  
而另一个标签logic:iterate是用表达式来给属性赋值: k}}'f A  
1.8"N&s  
<logci:iterate collection=”<%= bookDB.getBooks() %>” 1!U:M8T|  
.ej+?QYwC  
id=”book” type=”database.BookDetails”> Y+$]N:\F\  
x11riK  
BOA7@Zaa$p  
带body的tag标签 >mMfZvxl%  
 H4YA  
一个自定义标签可以包含其它自定义标签、脚本变量、HTML标记或其它内容。 # &5.   
K]yWpW  
在下述例子中,此JSP页面使用了struts的logic:present标签,如果些标签定义了parameter=”Clear”的属性,则将清除购物车的内容,然后打印出一条信息: C+`V?rp=s  
/$\8?<Pc".  
<logic:present parameter=”Clear”> -,g.39u  
;0?OBUDO  
<% cart.clear(); %> N. nGez  
#CyqiOM\*  
<font color=”#ff0000” size=”+2”><strong> z`Nss o=  
,-(D (J;}1  
你选择了清除购物车! =^{MyR7  
DC BN89#  
</strong></font> )^6Os2  
?X\.O-=4X  
</logic:present> fsnZHL}=n  
'<ZHzDW@  
/S~ =qodS  
到底是用属性还是用body来传递信息? v*As:;D_  
RDy&i  
如上所述,我们既可以通过属性,也可以通过body来传递信息。但一般来说,比较简单的类型,如字符串或简单表达式最好采用属性来传递信息。 lt2MB#  
Tj<B;f!u  
GGhk`z  
定义脚本变量的tag标签 ` ` Yk  
QSM3qke  
所谓脚本变量,是指JSP中可以调用的变量或对象。它可由tag标签产生。以下示例阐述了一个tag标签定义了一个名为tx的由JNDI所定义的事务处理对象。脚本变量可以是ejb对象、事务、数据库连接等等: >mEfd=p  
9pS:#hg  
<tt:lookup id=”tx” type=”UserTransaction” name=”java:comp/UserTransaction” /> ouFKqRs;  
sD{Wc%5  
<% tx.begin(); %> ,D<U PtPQ  
GM)q\Hx{  
... /P]N40_@  
U:c 0s  
B J I N  
具有协作关系的tag标签 i`vy<Dvpz  
Nvh& =%{g  
自定义tag标签之间可以通过共享对象来实现协作。在下述例子中,标签tag1创建了一个名为obj1的对象,在标签tag2仍可以重复使用obj。 f:~$x  
Cp>y<C"  
<tt:tag1 attr1=”obj1” value1=”value” /> 7(^F@,,@  
=i Dd{$  
<tt:tag2 attr1=”obj1” /> #mK?:O\-1  
y; <}`  
在以下这个例子当中,如果外层的tag标签创建了一个对象,那么其内层的所有tag标签都可以使用这个对象。由于这样产生的对象没有一个指定的名字,那么就可以将少重名的冲突。这个例子阐述了一系列协作的嵌套对象。 !)W#|sys&  
E:PPb9Kd  
<tt:outerTag> R>;&4Sjr  
M_r[wYt!  
<tt:innerTag /> a{rUk%x  
v?Cakwu  
</tt:outerTag> zzW$F)X  
DvOvtd  
^L7!lzyo  
Tag处理类 d'3"A"9R7-  
<$25kb R5K  
7-u'x[=m  
Tag处理类必须实现Tag接口或BodyTag接口,不过现在一般都流行从TagSupport或BodyTagSupport类中继承,这些类或接口都可以在javax.servlet.jsp.tagext包中找到。 ! R3P@,j  
ssoE,6kS  
当JSP引擎看到自己的JSP页面中包含有tag标签时,它会调用doStartTag方法来处理tag标签的开头,调用doEndTag方法来处理tag标签的结束。 U^U hZ!  
se=^K#o  
下表说明不同类型的tag所需要不同的处理过程: UA ]fKi  
bz~aj}"`  
Tag处理类的方法 VhAJ1[k4!  
owVks-/  
Tag标签类型 *n[B Bz  
所调用的方法 } _^ vvu  
*W>, 98  
基本标签 NPM2qL9&J  
doStartTag, doEndTag, release Ze#DFe$  
?cKTeGrS  
带属性的标签 Z 5)v  
doStartTag, doEndTag, set/getAttribute1...N, release %f1IV(3Qc  
D<<q5gG  
带内容的标签 O/d]2<V  
doStartTag, doEndTag, release KtH^k&z.f  
dn Sb}J  
带内容的标签,且内容重复循环 u%I%4 gM  
doStartTag, doAfterBody, doEndTag, release E'(nJ  
8ZM#.yB B  
带内容的标签,且内容与JSP交互 .c0u##/0  
doStartTag, doEndTag, release, doInitBody, doAfterBody, release #Er"i  
Q6e7Z-8  
一个tag处理类可以通过javax.servlet.jsp.PageContext来与JSP交互,通过javax.servlet.jsp.PageContext类,tag处理类可以访问JSP中的request、session和application对像。 HJ0;BD.]  
#M+_Lk3  
如果tag标签是互相嵌套的,那内层的tag处理类可以通过它的parent属性来访问上层的tag处理类。 dG]B-(WTC  
,Oy$q~.  
一般情况都将所有的tag处理类打成了JAR的包,以便于发布。 &1&OXm$  
U,61 3G  
y;<suGl  
Tag库描述(简称TLD) #d/T7c#  
fqq4Qc)#U&  
$8AW  
Tag库是用xml语言描述的,TLD包括了tag库中所有tag标签的描述,它一般用来被jsp服务器用来校验tag的语法正确性,或者被jsp开发者用来开发新的标签。 ~/z%yg  
6-)WXJ@V  
TLD的文件扩展名必须为.tld,而且必须放在当前WEB应用的WEB-INF目录或其子目录中。 g`fMHU7  
[6_.Y*}N  
一个TLD的内容的开头必须遵守标准的XML开头,用于描述DTD和xml的版本,例如: dC-~=}HR^  
uozq^sy  
<?xml version="1.0" encoding="ISO-8859-1" ?> ZZTf/s*  
WVOj ;c  
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd"> v>Kh5H5e~  
TLD必须以<taglib>来作为它的根元素,<taglib>的子元素如下表: ~1twGG_;  
D_~;!^  
CV\y60n  
<taglib>的子元素 1TR+p? "  
V@b7$z  
Element ABkDOG2br  
Description %Q &']  
oSkQ/5hg.  
tlib-version ``$$yS~d};  
Tag库的版本 )z18:C3  
7Hgn/b[?b  
jsp-version 0j6b5<Gpc*  
Tag库所需要的jsp的版本 Jvsy 6R  
<g;,or#$  
short-name {f)aFGp  
助记符,tag的一个别名(可选) SG|AJ9  
fR'!p: ~  
uri @fp@1n  
用于确定一个唯一的tag库 [MwL=9;!H  
<2&qIvHL  
display-name :( m, 06K  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) S#B%[3@  
ort*Ux)  
small-icon -s`Wd4AP  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) 8Q<Nl=g>'  
N|2d9E  
large-icon '/9j"mIA9$  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) I]+ zG  
gT$WG$^i  
description K{/i2^4  
对tag库的描述(可选) %7aJSuQN%  
f77W{T4  
listener Z$KyK.FUU  
参见下面listener元素 7z1@XO<D  
A^X\  
tag hp(MKfhH  
参见下面tag 元素 wbKJ:eWgt  
eaDZ^Z Er  
Listener元素 [m h>N$  
Kb<c||2Nh5  
一个tag库可能定义一些类做为它的事件侦听类,这些类在TLD中被称为listener 元素,jsp服务器将会实例化这些侦听类,并且注册它们。Listener元素中有一个叫listener-class的子元素,这个元素的值必须是该侦听类的完整类名。 l9=Ka{$^*  
Ib{l$#  
Tag元素 ,e;,+w=~E  
Cy6!?Mik  
每个tag元素在tag库中都要指出它的名字、类名、脚本变量、tag的属性。其中脚本变量的值可以直接在TLD中定义或通过tag附加信息的类来取得。每个属性描述了这个属性是否可以省略,它的值是否可以通过<%= …%>这样的JSP语法来获得,以及属性的类型。 )z@ +|A  
[Ca''JqrA  
每一个tag在TLD中对应一个tag元素,下表是tag元素的子元素: DIQ30(MS  
2RNee@!JJP  
Tag元素的子元素 F{ vT^/  
dba_(I~y  
元素名称 [T7&)p  
描述 $04lL/;  
oP56f"BE(  
name _)Txg2?=  
独一无二的元素名 m)<+?Bv y  
0H +nVR  
tag-class cyWb*Wv  
Tag标签对应的tag处理类 2&:z[d}~H  
]=-=D9ZS3  
tei-class yxpv;v:)=  
javax.servlet.jsp.tagext.TagExtraInfo的子类,用于表达脚本变量(可选) {e2ZW]  
wo(O+L/w  
body-content O_2o/  
Tag标签body的类型 [W$Mn.5<s  
ke W7pN?  
display-name z0ufLxq  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) _8 K|2$X  
[Nm?qY  
small-icon 6 .?0 {2s  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) [vb#W!M&|  
Sb2_&5  
large-icon TeZu*c  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) NkGtZ.!pk  
ShV_8F z  
description M8 Bp-_  
此tag标签的描述 I'{Ctc  
0k\,z(e  
variable 'M?ptu?f  
提供脚本变量的信息(同tei-class)(可选) b9?Vpu`?  
4`oKvL9  
attribute i}>EGmv m  
Tag标签的属性名 *HV_$^)=  
X[<#B5  
以下章节介绍对于不同类型的tag,如何具体地实现它们。 e&ZTRgYdi  
RJDk7{(  
K`X'Hg#_P2  
简单的tag 4n(w{W>  
6A>bm{`c:  
0;`FS /[(f  
tag处理类 /03 Wst  
;IPk+,hpmi  
简单的tag处理类必须实现Tag接口的doStartTag和doEndTag方法。当jsp引擎碰到tag标签的开头时,doStartTag被调用,因为简单的tag没有body,所以此方法将返回 SKIP_BODY。当jsp引擎碰到tag标签的结尾时,doEndTag被调用,如果余下的页面还要被计算,那它将返回EVAL_PAGE,否则将会返回SKIP_PAGE。 RlvvO  
K9ih(fh)  
以下是例子:对于标签 <tt:simple /> ,它的tag处理类实现如下: ~qL/P 5*+  
Bmt8yR2  
NhYUSk ~u  
public SimpleTag extends TagSupport G;/> N'#  
Imzh`SI,  
{ +B+cN[d  
*&_A4)  
public int doStartTag() throws JspException @*6_Rp"@  
}>,%El/  
{ zU0JwZi  
IJPyCi)  
try{ $'!n4}$}  
cyjgi /Z  
pageContext.getOut().print(“Hello.”); (A}c22qe  
"=40%j0  
}catch(Exception e){ Ty!V)i  
6b` Jq>v  
throw new JspTagException(“SimpleTag: “ + e.getMessage()); l)DcwkIG  
X9" T(`  
} m\ qR myO  
8"ZcKxDk  
return SKIP_BODY; @LU[po1I  
 ]5ibg"{S  
} 67Tu8I/r  
I%j]pY4  
public int doEndTag() -biw{  
0,__{?!  
{ ~xPetkl@  
JiA1yt  
return EVAL_PAGE; 0U.Ld:  
DEfhR?v  
} %A&g-4(  
:}SR{}]yXs  
} b3GTsX\2|  
[a^<2V!vMn  
.Z17X_  
注意:如果tag标签没有内容的话,那必须定义body-content元素为空,例如 VWCC(YRU|$  
mII8jyg*c  
<body-content>empty</body-content> X0$?$ ta  
fv>Jn`  
%uP/v\l  
带属性的tag标签
评价一下你浏览此帖子的感受

精彩

感动

搞笑

开心

愤怒

无聊

灌水
级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
只看该作者 1 发表于: 2007-01-01
tag处理类 lg jY\?  
vZSwX@0  
对于tag标签的每个属性,你必须依照JavaBeans规范来定义其属性,以及get和set方法。以struts的logic:present 标签为例, 2 t]=-@  
I]d?F:cdX  
<logic:present parameter=”Clear”> 34vH+,!u  
baf@"P9@\A  
与此相应,此tag处理类应有如下方法和定义: XToYtdt2  
\'nE{  
f%STkL)  
protected String parameter = null; )q%DRLD'G  
*>j4tA{b@v  
public String getParameter() DJNM =v  
.-p?skm=a  
{ As#/ln$nE  
]G=^7O]`C!  
return this.parameter; Jz_`dLL^ w  
Qhn>aeW,  
} b=Q%Jxz?  
S3 /Z]?o  
public void setParameter(String parameter) N8]d0  
54&&=NVs|  
{ Uw>g^[V;  
#!M;4~Sfx  
this.parameter = parameter; ]<E\J+5K  
SL%lY  
} uacVF[9|W  
=ThacZHb8  
J,wpY$93  
注意:如果你的属性名为id,而且你的tag处理类是从TagSupport类继承的,那你就不需要定义它的属性和set和get方法,因为他们早已在TagSupport被定义过了。  *U4eL-  
,W;2A0A?X  
Attribute元素 @1 )][r-7  
}Xy<F?Mh  
对于tag标签的每个属性,你必须定义它是否必须的,它的值是否可以用诸如<%= …%>的表达式来获得,以及它的类型(可选),如果不指定它的类型,那就默认为是java.lang.String类型。如果rtexprvalue元素被定义为true或yes,那么在type元素中就定义了attribute的返回类型。 l'(7p`?  
QPwUW  
<attribute> R&s\h"=*  
;jpsH?3g  
<name>attr1</name> ?bK^IHh  
Tk0Senq,  
<required>true|false|yes|no</required> vC!}%sxVw_  
&r !*Y&  
<rtexprvalue>true|false|yes|no</rtexprvalue> e? !A]2  
0N*~"j;r#M  
<type>attribute的返回类型(只用当rtexprvalue为真是才有效)</type> D7b] ;Nf\  
_n_|skG  
</attribute> OX)[?1m8  
pWXoJ0N  
如果tag的某个属性不是必须的,那tag处理类会自动提供一个缺省值。 2=xjgK  
=P<7tsSuoK  
例如,在logic:present这个tag标签中定义了一个属性叫parameter,但它不是必须的,而且它可以被诸如<%= …%>的表达式来赋值。 N;]"_"  
Q>emyij  
<tag> &8uq5uKg  
p_2-(n@  
<name>present</name> ( RCQbI  
F2RU7o'f.  
<tag-class>org.apache.struts.taglib.logic.PresentTag</tag-class> qY$/i#  
u >o2lvy8  
<body-content>JSP</body-content> t#6@~49  
o72G oUfs  
… -*Z;EA-  
n[pW^&7x  
<attribute> !r*Ogv[  
^X/[x]UOT@  
<name>parameter</name> ;y"q uJ'O  
8n^v,s>  
<required>false</required> >|22%YVX  
yb:Xjg7   
<rtexprvalue>true</rtexprvalue> D|p`~(  
P Yp<eo\  
</attribute> K7H` Yt  
o3~ecJ?k  
… k-&fPEjG  
]ozZW:  
</tag> ]N+(SU  
{@c)!% 2$  
hI{M?LQd  
属性元素的校验 :Ojsj_Z;;  
({}JvSn1  
n$fYgZKn  
有关于tag标签的有效值可以从tag库的说明文档中获得,当JSP页面被编译时,jsp引擎会强制性地参照TLD中定义的规则进行检查。 - W5ml @  
tz&oe  
还有一个方法也可以进行属性元素的校验,就是先继承类TagExtraInfo,然后调用它的isValid方法。这个类同时也起到提供tag中定义的脚本变量信息的作用。  X)^kJ`  
w{1DwCLKq  
IsValid方法通过TagData对象来传递属性信息,它包括着tag的所有的属性名-值的信息。由于校验发生在运行时刻,因此这个属性的值将被赋值为TagData.REQUEST_TIME_VALUE。 M/X&zr  
,Mp/Y>f  
例如tag标签<tt:twa attr1=”value1” />在TLD中定义如下: "[ 091<  
JC6Bs`=s~  
<attribute> IOx9".  
_S[@d^cY  
<name>attr1</name> G/:;Qig  
"r Bb2.  
<required>true</required> i,DnXgmz@  
7r?s)ZV  
<rtexprvalue>true</rtexprvalue> 9b8ZOk'9_  
gxS*rzCG  
</attribute> -c"nx$  
Bg?f}nu7  
i1"4z tZ  
这个定义说明了attr1能在运行期间被赋值。 -Q6njt&  
t<Iy `r7 1  
以下的isValid方法检查attr1属性的值是否属于Boolean类型。注意由于attr1能在运行刻被赋值,那么isValid方法必须检查tag用户是否对此tag进行了运行时刻赋值。 QN!$41A?{  
Ov$_Phm:  
brk>oM;t  
Public class TwaTEI extends TagExtraInfo 2cy: l03  
.]_ (>^6  
{ Hp2y sU  
iB  =R  
public boolean isValid(Tagdata data) %QW1?VVP  
Bw ]Y7 1  
{ |#p`mc%f~\  
>}tm8|IHoo  
Object o = data.getAttribute(“attr1”); 7$8YBcZ6  
}0& @J'<  
If(o != null && o != TagData.REQUEST_TIME_VALUE) /1F5khN  
dWhki|c  
{ &R? \q*  
1'O++j_%y  
if( ( (String)o).toLowerCase().equals(“true”) || _sEkKh8x  
x]~{#pH@<  
((String)o).toLowerCase().equals(“false”) ) v##k,R.d  
9A@/5Z:v5W  
return true; n&? --9r  
s<f<:BC  
else O$=[m9V  
lV4|(NQ9  
return false; 8T&.8r  
v{/z`J!JR  
} `1AVw] k  
oCw>b]S  
else ]kXiT Yg  
ia'eV10  
return true; c7~+ 5  
381a(F[$e  
} l :e&w(1H  
5cr d.1@^  
} _$g2;X >  
=l7@YCj5c  
N- !>\n  
带body的tag cPFs K*w  
MLbmz\8a  
4f)B@A-  
tag处理类 k0@b"y*  
4=BIYC"Lu  
Ez\TwK  
如果tag标签含有内容,那处理方式会略微有些不同,而且还要视tag处理类是否要与body交互的情况而定。如果要与body交互,那我们认为tag处理类要可能要对body进行操作。 JDp"!x{O  
:5YL!D/&  
Tag处理类不与body交互 Bri yy  
RM\A$.5  
如果tag处理类不与body交互,tag处理类应该实现Tag接口或从TagSupport中派生,如果body要被计算,那么doStartTag方法应返回 EVAL_BODY_INCLUDE,否则应返回SKIP_BODY。 O[$,e%  
[&Yrnkgr  
如果tag处理类要对body反复运算,则它应该实现IterationTag或从TagSupport中派生。如果tag处理类认为body还未计算完的话,那它的doStartTag方法和doAfterBody方法必须返回EVAL_BODY_AGAIN。 oGtz*AP%  
8>\tD  
Tag处理类与body交互 =tkO^  
aR- ?t14  
如果tag处理类与body交互,那tag处理类应实现BodyTag接口或从BodyTagSupport中派生。这种tag处理类一般要实现doInitBody和doAfterBody方法。 O,a1?_m8  
]~YY#I":  
Body允许一些方法来读写它的内容。Tag处理类可以调用body内容的getString或getReader方法来从body中提取信息,也可用 writeOut(out) 方法来将body的内容写入到out对象中。其中out对象通过tag处理类的getPreviousOut方法来获得。 LqZsH0C  
|Ok@:Au  
如果body的内容需要被计算,那么doStartTag方法必须返回EVAL_BODY_BUFFERED,否则,它将返回 SKIP_BODY。 Gx&o3^t  
8)Z)pCN  
doInitBody 方法 4l2/eh]Hc(  
hDn?R}^l{  
此方法在body内容已经设好,但未被计算之前被调用。你可以根据不同的body内容来制定初始化策略。 )#(6J  
4p}?QR>tZ  
doAfterBody方法 >/BMA;`  
iE6?Px9]  
此方法在body内容已被计算后进行调用。 8M<\?JD~_f  
bR\Oyd~e  
和doStartTag方法一样,doAfterBody方法返回一个指示符指示是否要继续计算body,如果要继续计算,则doAfterBody应返回EVAL_BODY_BUFFERED,否则,它应返回SKIP_BODY。 G!G]*p5  
Y8%bk2  
release 方法 h4 X=d5qd  
Q\QSnMM&]  
tag处理类调用此方法将它的状态重置为初始状态,并释放所有的私有资源。 vtA%^~0  
/h(bMbZ  
A$7j B4  
以下的例子读取body的内容(其中含有一条sql语句),然后将它传递给一个对象,让它进行查询。由于此处body不须重新计算,所以doAfterBody会返回SKIP_BODY。 |E}-j;(  
s"'ns  
/WxCsQn  
Public class QueryTag extends BodyTagSupport J,W<vrKOcN  
-eQ>3x&3r  
{ * ^+]`S  
_9pcHhJux  
public int doAfterBody() throws JspTagException es6]c%o:t^  
|7$Q'3V  
{ (zmL MG(R  
+lhjz*0  
BodyContent bc = getBodyContent(); \ cr)O^&  
Jv8JCu"eky  
//将body的内容以字符串的格式提取出来 _?I6[Mz  
9OS~;9YR  
String query = bc.getString(); 59l9^<{A  
fi tsu"G  
//清除body {Qf/.[  
:'$V7LZ5  
bc.clearBody(); 8 U<$u,WS  
hWz/PK,  
try{ .gJv})Vi  
^&z3zFTp  
Statement stmt = connection.createStatement(); d(_;@%p1X  
INRP@Cp1  
Result result = stmt.executeQuery(query); c!ul9Cw  
7%sx["%@  
}catch(SQLException e){ @TraEBJGL  
)4;$;a1  
throw new JspTagException(“queryTag: “ + e.getMessage() ); 5L0w!q'W  
']:>Ww.S  
return SKIP_BODY; Maw$^Tz,  
*K'#$`2  
} $lAQcG&Q  
>h9T/J8  
} wlEmy.)H  
?~9o2[  
n.b_fkZNr  
body-content元素 p;<aZ&@O  
]^6r7nfR6|  
.)|2^ 'W  
由于tag可能会有body,你必须用body-content元素来指定body内容的类型: w\}Q.$@  
w?JM;'<AYQ  
<body-content>JSP|tagdependent</body-content> S#F%OIx  
J93@\b  
5,#aN}v#?  
如果body的内容是定制的或内部的tag、脚本元素、或HTML广本,则归类为JSP类型。其他的类型,比如上面代码所述的?D?D将sql statement类传给 query tag的这种类型应该标为tagdependent。 p1']+4r%  
8FJPw"9  
注意:实际上body-content的值并不影响tag处理类对body内容的处理,它仅仅是被tag编辑工具用来描述此body的内容。 e% #?B *  
U1=]iG<%  
}PX8#C_P  
用tags定义脚本变量 lbj_ if;  
 bE%*ZB  
A,;[9J2\&  
tag处理类 D9r4oRkP*  
o<L=l Q  
l}XnCOIT,  
tag处理类负责创建或设置页面中定义的脚本变量,用pageContext.setAttribute(name,value,scope)或pageContext.setAttribute(name,value)方法来实现。一般来说,tag处理类通过脚本变量的名称来获取它,脚本变量的名称一般可用get方法来获得。 jMP;$w  
.|/VD'xV"  
如果脚本变量的值依赖于tag处理类中的上下文中某一对象,那它可用pageContext.getAttribute(name,scope)方法来找到那个对象。一般的处理过程是tag处理类先找到脚本变量,再对其进行处理,然后用pageContext.setAttribute(name,object)的方法来设置它的新值。 <.U(%`|  
~kOXMLRg  
对象的生存周期(scope)如下表: ?#|in}  
4p&YhV7j)o  
对象的生存周期表 M!O &\2Q  
a/gr1  
名字 | W<jN  
可访问范围 _53N uEM1  
生存周期 h9cx~/7,_)  
"q7pkxEuJ  
page ?Vc/mO2X  
当前页面 0GcOI}  
一直有效,除非页面向客户提交响应或重定向到一个新页面 v4W<_ 7L_  
R[!%d6jDE  
request g]PC6xr38  
当前页面或当前页面重定向到的页面 POb2U1Sj  
一直有效,除非页面向客户提交响应 xX\A& 9m  
,H5o/qNU`{  
session g*$yUt  
当前页面或在同一浏览器窗口中的页面 V ee;&  
一直有效,除非关闭当前浏览器、超时、网络故障 : G0^t  
BF(Kaf;<t.  
application vve[.Lud'  
整个web应用程序的所有请求 @ iaz_;  
一直有效,除非发生网络故障、服务器故障 xj. )iegQ  
T#=&oy7  
提供关于脚本变量的信息 vU!<-T#  
5`f\[oA  
以下示例定义了一个名为“book”的脚本变量,用来访问程序中关于书的信息: Kc {~Q  
QUi=ZD1  
<bean:define id=”book” name=”bookDB” property=”bookDetails” type=”database.BookDetails” /> 7=@Mn F`  
W4rh7e4  
<font color=”red” size=”+2” > m.>y(TI  
XO"BEj<x  
<%= messages.getString(“CartRemoved”) %> cB2jf</  
Y[`%j\=  
<strong><jsp:getProperty name=”book” property=”title” /></strong> @^K_>s9B  
y3NMt6  
</font> T`r\yl}  
ZO!)G   
当包含此tag的JSP页面被编译时,jsp引擎会自动生成关于此book的同步的代码(同步可以避免几个客户同时访问此book时造成的冲突),要生成同步代码,jsp引擎需要知道此脚本变量的如下信息: e(EXQP2P>  
?ubIh.d  
· 脚本变量名称 U?yKwH^{  
& <Jvaf_=  
· 脚本变量所属的类 =y1/V'2E  
?G$X 4KY6`  
· 此脚本变量是否引用了一个新的或已存在的对象 qh~S)^zFJ  
f*GdHUZ*  
· 此脚本变量的有效性 7Hp~:i30  
.[hbiv#  
有两种办法可以向jsp引擎提供关于脚本变量的信息:在TLD中定义variable子元素,或用tei-class子元素定义一个额外tag信息类。用variable最简单,但可能降低了一些灵活性。 ]5hGSl2  
q NE( @at  
Variable元素 uY*|bD`6&  
PU{7s  
Variable元素有如下子元素: ^g*2jH+  
'X1fb:8m8  
· name-given ?D?D 给出的名字,是一个常量 eXsFPM  
% .n 7+  
· name-from-attribute?D?D 属性名,在编译时给出的属性名 :Y>M/ /0  
$XO#qOW  
name-given或name-from-attribute两者必须选一,但以下子元素是可选的: *WX,bN6Ot  
4e5 5  
· variable-class?D?D变量的类型,缺省为java.lang.String。 tx01*2]pX  
~pj/_@S@x  
· declare?D?D此脚本变量是否引用了一个新对象,缺省为True。 C`>|D [  
%b(non*  
· scope?D?D脚本变量的范围,缺省为NESTED。下表描述了scope的几种类型: =#ls<Zo:  
Dt p\ T|)  
脚本变量的有效范围 vTF_`X  
PgF7ug%,@C  
值 6Y(Vs>  
有效性 ^qD@qJ  
方法 C!r9+z)<  
K=mW`XXup  
NESTED {=GWQn6cc  
在tag标签的开始和结束之间 m?=9j~F *  
如果tag处理类实现BodyTag接口,则在doInitBody和doAfterBody中调用,否则在doStartTag中调用 60u}iiC@  
0/Wo":R:  
AT_BEGIN :6Oh?y@  
从tag标签的开始一直到页面结束 . |g67PH=  
如果tag处理类实现BodyTag接口,则在doInitBody、doAfterBody和doEndTag中调用,否则在doStartTag和doEndTag中调用 y 2v69nu~q  
rM?ox  
AT_END q[w.[]  
从tag标签的结束一直到页面结束 sTALOL<  
在doEndTag中调用 \.7O0Q{  
|2eF~tJqc  
以struts为例,它的bean:define标签的实现遵循JSP1.1规范,此规范要求使用额外tag信息类来定义脚本变量。Variable元素是JSP1.2规范中加入的。以bean:define标签为例,你可以定义如下variable元素: ZHku3)V=o  
D3+UV+&R/  
<tag> jS,zdJs=  
u LXV,  
<variable> x>yeF,q1  
 Py)'%e  
<name-from-attribute>id</name-from-attribute> 5wws8w  
"T_OLegdK  
<variable-class>database.BookDetails</variable-class> /:j9 #kj  
C/!c?$J  
<declare>true</declare> `RG_FS"v  
E'g2<k  
<scope>AT_BEGIN</scope> q3s +?&  
S2jO  
</variable> EFg s}BV_9  
jJmg9&^R  
</tag> ;i2N`t2  
%7$oig\wE  
额外tag信息类 G 39  
?OU+)kgzh  
如果要定义一个额外tag信息类,你要继承javax.servlet.jsp.TagExtraInfo类。一个TagExtraInfo类必须实现getVariableInfo方法,此方法返回一个叫VariableInfo的数组类,它包括如下信息: lilKYrUmG  
9x~qcH%  
· 变量名 DfCo=  
UJ'}p&E  
· 变量所属类名 8\~IwtSk  
wb>>bV+U  
· 此变量是否引用了一个新对象 m_7)r  
U 6y ;V  
· 此变量的有效范围 90pk  
Zh WtY  
jsp引擎将一个名为data的参数传给getVariableInfo方法,data中包括tag标签中的所有“属性名?D?D属性值”对。它可以用来向VariableInfo对象提供脚本变量的名字和类名。 c !ybz{L  
Z81{v<c;  
以struts为例,它在bean:define标签中定义了一个名为DefineTei的额外tag信息类,用来向脚本变量提供信息。由于脚本变量的名称(book)和类名(database.BookDetails)是通过tag标签的属性来传递的,它们一般定义在VariableInfo的构建代码中,并且可用data.getAttributeString方法来得到这些信息。如果要允许book脚本变量能在从tag开始直到整个JSP页面结束的范围内都可用的话,那它的范围应设为AT_BEGIN。如下所示: Hset(-=X  
jF'azlT  
L}&U%eD  
public class DefineTei extends TagExtraInfo ZU&I`q|Y6  
aQ ~  
{ VvwQz#S  
r"a4 ;&mf  
public VariableInfo[] getVariableInfo(TagData data) SR#%gR_SC  
MK]S205{  
{ ]3iu-~  
~%4#R4&  
String type = data.getAttributeString(“type”); sa~.qmqu  
0VV1!g  
If( type == null) ba?]eK   
2'"$Y'  
type = “java.lang.Object”; ;X u&['  
saH +C@_,  
return new VariableInfo[] { 8VLr*83~8  
n_@YKz;8  
new VariableInfo(data.getAttributeString(“id”), '|e5cW6z  
@|&P#wd.u  
type, 3<x_[0v`K1  
]?L?q2>&  
true, g]C+uj^  
5Mb1==/R  
VariableInfo.AT_BEGIN) %D z|p]49!  
S:] w@$  
}; @:i>q$aF  
a%f5dj+  
} apUV6h-v  
}k}5\%#li5  
} t=~5 I >  
3Gt'<E|"  
Dj>.)n  
注意:关于额外tag信息类的类名必须要在TLD中的tag标签下的tei-class子元素中定义。因此,DefineTei的tei-class中的定义看起来如下: p/WEQ2   
<tei-class> uJG^>B?`b  
org.apache.struts.taglib.bean.DefineTagTei Gq;0j:?CC  
</tei-class> K/Axojo  
8 k+Ctk  
rQK2&37-,@  
具有协作关系的tag mxjY-Kq  
A0S6 4(  
0;OpT0  
tag通过共享对象来进行协作,JSP技术支持2种方式的对象共享。 Yc#oGCt  
NS=puo  
第一种方法是使用pageContext对象进行对象的共享(可支持JSP页面和tag处理类之间的共享),如果在一个tag处理类中要调用由另一个tag处理类创建的对象,可调用pageContext.getAttribute(name, scope)方法。 R\yw9!ESd  
FFH-Kw,  
第二各方式的共享是对于tag之间有嵌套关系而言的,外层的tag所创建的对象对于内层的tag来说是可以共用的。这种形式的共享的好处是减少了可能存在的重名冲突。 1O9V Ej5  
<"CG%RGP  
要访问一个嵌套tag创建的对象,tag处理类必须先找到此嵌套tag对象,可用TagSupport的静态方法 TagSupport.findAncestorWithClass(from, class)或TagSupport.getParent方法。前者在当不确定此tag是否为嵌套tag对象时使用。一旦它的父类被找到,它就能访问其所有动态或静态创建的对象。静态创建的对象是父类的成员,而动态创建的对象可能是父类的私有对象。诸如此类的对象可以用tag处理类的setValue方法来保存,用getValue方法来获得。 \C*?a0!:Z}  
&nj@t>5Bs$  
下例阐述了以上两种共享对象的方法。在这个例子当中,一个查询tag检查一个名为connection的属性名是否在doStartTag中被设置。如果connection属性被设置,tag处理类从pageContext中得到这个connection对象。否则,此tag处理类先找到它的父tag处理类,然后从它的父tag处理类中找到connection对象。 av wU)6L  
*8"5mC ;"  
vK#xA+W  
public class QueryTag extends BodyTagSupport 2NsI3M4$8  
V )1SZt@x  
{ fYx$3a.  
GS$OrUA  
private String connectionId; W3 2mAz;  
(q*T.   
public int doStartTag() throws JspException ~oT0h[<  
4jis\W}%L3  
{ :?jOts>uP  
S! ,.#e(Y  
String cid = getConnection(); 0?SdAF[:z  
w{K_+}fAC  
if(cid != null) )e9(&y*o  
.knRH^  
{ YG?W8)T  
#)=P/N1  
//存在一个connection id,使用它。 rq}ew0&/  
X,x{!  
connection = (Connection) pageContext.getAttribute(cid); =wU08}  
#12PO q  
} v2JC{XqrI  
n`0}g_\q  
else v?!x,H$Qd  
F7#   
{ bPOehvK/  
gjvKrg  
ConnectionTag ancestorTag = (ConnectionTag)findAncestorWithClass(this, 2@:Go`mg  
QF'N8Kla  
ConnectionTag.class); %{&yXi:mS  
M<~z=B#  
if(ancestorTag == null) MBXumc_g  
WJ=eV8Uk  
{ ~e ]83?  
#s)6u?N  
throw new JspTagException(“一个没有connection属性的查询标签必须被一个connection标记嵌套。”); !95ZK.UT  
E]6;nY?  
} vkASp&a  
C{-e(G`Yd  
connection = ancestorTag.getConnection(); . sgV  
29 Yg>R!/  
} k[gO>UGB;  
dilRL,  
} oh:g  
yWsN G;>  
} GO+cCNMa"  
UOy`N~\gh+  
: JD% =w_  
xWU0Ev)4U  
此查询标签在JSP页面中的调用形式可以从以下2种定义中任选一种: lBgf' b3$  
& LwR9\sh  
b Zn:q[7  
<tt:connection id=”con01” ...> ... </tt:connection> *y='0)[BD  
/3L1Un*  
<tt:query id=”balances” connection=”con01” > # ~} 26  
506B =  
SELECT account, balance FROM acct_table C*,-lk0b@  
OgY4J|<  
where customer_num = <%= request.getCustno() %> Zq}w}v  
bT|a]b:  
</tt:query> 0;#%KC,  
+=)< Su.  
M-e!F+d{od  
或 3qXOsa7  
Yo/U/dB  
<tt:connection ...> (vB aem9  
26G2. /**<  
<x:query id=”balances”> lQ<2Vw#Yl  
J{ P<^<m_  
SELECT account, balance FROM acct_table t>)iC)^u  
xdd7OSc0{  
where customer_num = <%= request.getCustno() %> #5wOgOv  
X*KQWs.  
</x:query> c*-8h{}  
6iV jAxR  
</tt:connection> Kyt.[" p  
ug'I:#@2  
Z3g6 ?2w6  
与此同时,在TLD中必须指定connection属性为可选的,定义如下: 5x(`z   
J;W(}"cFq  
<tag> DJ_,1F  
! @{rk p  
... ZR.1SA0x?O  
:9Zu&t  
<attribute> o@>{kzCx  
w<3}(1  
<name>connection</name> b'Pq [ )  
]( V+ qj  
<required>false</required> 8c(}*,O/  
G~1#kg  
</attribute> hb9e6Cc  
u/Fa+S  
</tag>
描述
快速回复

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