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

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

级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
标准的JSP 标记可以调用JavaBeans组件或者执行客户的请求,这大大降低了JSP开发的复杂度和维护量。JSP技术也允许你自定义taglib,其实换句话说,taglib可以看成是对JSP标记的一种扩展,正如xml是对html的一种扩展一样。taglib通常定义在tag标签库中,这种标签库存放着你自己定义的tag标签。简而言之,如果使用taglib,那么你可以设计自己的JSP标记! &u=FLp5  
Z,i klB-  
一般来说,自定义tag标签主要用于操作隐藏对象、处理html提交表单、访问数据库或其它企业级的服务,诸如邮件和目录操作等等。自定义tag标签的使用者一般都是那些对java编程语言非常精通,而且对数据访问和企业级服务访问都非常熟悉的程序员,对于HTML设计者来说,使得他可以不去关注那些较复杂的商业逻辑,而将精力放在网页设计上。同时,它也将库开发者和库使用者进行合理分工,自定义tag标签将那些重复工作进行封装,从而大大提高了生产力,而且可以使得tag库可用于不同的项目中,完美地体现了软件复用的思想。  iI ^{OD  
!uO|T'u0a  
在这篇文章中,我们主要讨论: J.?p?-"  
?N|PgNu X  
· 什么是自定义tag标签? ["L?t ^*G  
n<hwstk  
· 怎么使用tag标签?  &R^mpV5  
^E:;8h4$9  
o 声明要使用的tag库 |g;XC^!%=o  
uwQ4RYz  
o 找到与之对应的tag处理类 5<a<!]|C  
JK_$A;Q  
o tag标签的类型 t]&n_]`{.  
=)I{KT:y  
· 自定义tag标签 q?0goL  
fV5#k@,")  
o tag处理类 qob!!A14p  
A|a\pL`@  
o tag库描述 Hd2_Cg FB  
]g)%yuox9F  
o tag标签示例 x)Th2es\  
Xs?>6i@$$  
o 带属性的tag _|Dt6  
d*AV(g#B  
o 带body的tag &WRoNc  
vcSS+  
o 定义了脚本变量的tag qzmZ/z96  
d8r+UP@#  
o 具有协作关系的tag x p$0J<2  
02+^rqIx5  
· 自定义tag标签 T(}da**X  
pucHB<R@bL  
o 一个迭代tag的例子 ~G$OY9UC  
#,9|Hr%  
o 一个模板tag库 e,4G:V'NX  
i@;a%$5  
o tag处理类到底是怎样被调用的? r\1*N.O3|O  
W>Kwl*Cis"  
j>:T)zhyY  
什么是自定义的tag? l00D|W_ 9  
=0-qBodbl  
一个自定义的tag标签是用户定义的一种JSP标记。当一个含有自定义的tag标签的JSP页面被jsp引擎编译成servlet时,tag标签被转化成了对一个称为tag处理类的对象进行的操作。于是当JSP页面被jsp引擎转化为servlet后,实际上tag标签被转化成为了对tag处理类的操作。 EtcamI*`  
Q6>vF)( -  
自定义tag标签有很多特色,诸如: hPH7(f|c{g  
Jzj~uz  
· 可以在JSP页面中自定义tag标签的属性 lt]U?VZ   
lu}[XN  
· 访问JSP页面中的所有对象 Qp54(`  
>fdN`W }M  
· 可以动态地修改页面输出 M#p,Z F  
-,tYfQ;:  
· 彼此这间可以相互通信。你可以先创建一个JavaBeans组件,然后在一个tag中调用此JavaBeans组件,同时可以在另一个tag中调用它。 t5qAH++axN  
C G7 LF  
· tag允许相互嵌套,可以在一个JSP页面中完成一些复杂的交互。 7lpVK]  
n" ~*9'  
~_&.A*Jh  
使用tag标签 u0e#iX  
D^~g q`/)  
4ca-!pI0  
本节主要描述怎样在JSP页面中使用tag标签,以及tag标签的不同类型。 nX S%>1o,  
P:TpB6.=q  
要使用tag标签,JSP程序员必须做2件事: vB{b/xmah  
K6U>Qums  
· 声明此tag标签的tag库 m0,9yY::wj  
,W-0qN&%/  
· 实现此tag标签 (D{}1sZBQ  
?Sqm`)\>4  
声明tag标签所在的tag库 !O-+ h0Z  
a3 x~B=E  
如果要使用tag标签,则应用JSP的taglib指示符来指定其tag库(注意:taglib要在在使用此tag标签之前声明) EHHxCq?  
yDC97#%3u  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> /z5lxS@#  
h"ylpv+  
uri属性定义了唯一的标签库描述(以下简称TLD),它可以是直接是tld文件名或一个独一无二的名字。prefix是用来区别其它TLD中和本TLD中有重名的tag的一种手段。 Wd AGZUp  
g@k9w{_  
TLD必须以.tld作为扩展名,并且存放在当前应用的WEB-INF目录或其子目录下。你可以通过它的文件名直接引用它,也可以通过别的方式间接地引用它。 bAiw]xi  
S+G)&<a^  
以下taglib指示符直接引用一个TLD: 4QNR_w  
3c3Z"JV  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> mW-W7-JhO7  
AF$o >f  
以下的taglib指示符通过一个逻辑名称间接地引用一个TLD: *F*X_O  
HH?*"cKF~  
<%@ taglib uri=”/tutorial-template” prefix=”tt” %> 6~ `bAe`}  
!&lPdEc@T  
如果是间接引用TLD的话,那你必须还要在web.xml中定义此逻辑名称与tld文件之间的映射,具体做法是在web.xml中加入一个名为taglib的元素: >G2-kL_  
~PnpYd<2  
<taglib> oDUMoX%4s  
JZzf,G:  
<taglib-uri>/tutorial-template</taglib-uri> sV[Z|$&Z  
C4tl4df9  
<taglib-location> b]BA,D 4  
sjgR \`AU  
/WEB-INF/tutorial-template.tld (N|xDl &;  
)`mF.87b&h  
</taglib-location> %n25Uq  
HDyZzjgG  
</taglib> v:MS0]  
!h>$bm  
uk  f\*  
实现此tag标签 2bnIT>(  
lMez!qx,=  
KHz838C]  
为了实现tag标签,你有2种方法来存放tag处理类。一、让tag处理类以.class的方式存放于当前应用的WEB-INF/class子目录下,二、如果tag处理类是以JAR包的形式存在的话,那可以放在当前应用的WEB-INF/lib目录下,如果tag处理类要在多个应用中共享,那么它就应放在jsp服务器上的common/lib目录下,对于tomcat来说,就是tomcat/common/lib目录下。 y%bqeo L~  
$L8s/1up  
Z'dI!8(Nf  
tag标签类型 NoZ4['NI\  
?{,)XFck  
|~LjH|*M  
自定义的tag标签遵循XML语法。它有一个开始标记和一个结束标记,有的还有body(即文本节点): */dh_P<Yj  
HcVs(]tIW  
<tt:tag> irb.F>(x  
Z?c=t-yqp  
body 8sF0]J[g{  
`Mn{bd  
</tt:tag> ((>3,%B`  
*2 $m>N  
e=)* O  
一个不带body的tag标签如下: rI66frbj  
O\F^@;] F6  
<tt:tag /> +Y9D!=_lj  
sFM>gG  
Doc'7P  
简单的tag标签 zHc4e   
< Gy!i/  
一个没有body和属性的tag标签如下: PSqtZN  
+6)kX4  
<tt:simple /> ySK Yqt z  
%3#I:>si  
P}WhE  
带属性的tag标签 t2%@py*bU  
X.AWs=:-  
V<NsmC=g  
自定义标签可以有自己的属性。属性一般在开始标记中定义,语法为 attr=”value”。属性的作用相当于自定义标签的一个参数,它影响着tag处理类的行为。你可以在TLD中详细定义它。 ^@LhUs>3  
Ta\8 >\6  
你可以用一个String常量给一个属性赋值,也可以通过表达式给它赋值,如<%= ...%>。以struts为例,它的logic:present标签就是用的String常量来给属性赋值: {S"  
9q)nNX<$)  
<loglic:present parameter = “Clear”> tTh;.88Z{  
9k+&fyy  
而另一个标签logic:iterate是用表达式来给属性赋值: qTa]th;  
m57tO X  
<logci:iterate collection=”<%= bookDB.getBooks() %>” nK%/tdq  
K-Dk2(x  
id=”book” type=”database.BookDetails”> i_'R"ob{S  
MV;Y?%>  
)av'u.]%c  
带body的tag标签 >&Ui*  
"G-0iKW;  
一个自定义标签可以包含其它自定义标签、脚本变量、HTML标记或其它内容。 pGbFg&  
0O['-x  
在下述例子中,此JSP页面使用了struts的logic:present标签,如果些标签定义了parameter=”Clear”的属性,则将清除购物车的内容,然后打印出一条信息: {cyo0-9nv  
E ^SM`  
<logic:present parameter=”Clear”> ^I0GZG  
rb}wv16?  
<% cart.clear(); %> kSDa\l!W]  
&(uF&-PwO4  
<font color=”#ff0000” size=”+2”><strong> K.iH  
=y-!k)t  
你选择了清除购物车! 9p\wTzA  
Ubw!/|mi  
</strong></font> Q!2iOvK  
w(e+o.:  
</logic:present> .t^UK#@#4  
leb^,1/D6  
*/5<L99v  
到底是用属性还是用body来传递信息? XC/]u%n8](  
y5AXL5  
如上所述,我们既可以通过属性,也可以通过body来传递信息。但一般来说,比较简单的类型,如字符串或简单表达式最好采用属性来传递信息。 ]dGr1 ncu  
rMXOwkE  
)(?UA$"  
定义脚本变量的tag标签 |<$<L`xoe  
2NA rE@  
所谓脚本变量,是指JSP中可以调用的变量或对象。它可由tag标签产生。以下示例阐述了一个tag标签定义了一个名为tx的由JNDI所定义的事务处理对象。脚本变量可以是ejb对象、事务、数据库连接等等: L%o65  
%+7T9>+  
<tt:lookup id=”tx” type=”UserTransaction” name=”java:comp/UserTransaction” /> sx-Hw4.a"  
=~W0~lxX  
<% tx.begin(); %> 5}d/8tS  
z7@(uIl=X  
... |B1; l<|`  
6Bq~\b^  
}4\!7]FVYX  
具有协作关系的tag标签 S`W'G&bCj  
$xUzFLh=`  
自定义tag标签之间可以通过共享对象来实现协作。在下述例子中,标签tag1创建了一个名为obj1的对象,在标签tag2仍可以重复使用obj。 N)vk0IM!  
M8#*zCp{5  
<tt:tag1 attr1=”obj1” value1=”value” /> k binf  
q2S!m6!  
<tt:tag2 attr1=”obj1” /> \&\_>X.,  
Ha=_u+@  
在以下这个例子当中,如果外层的tag标签创建了一个对象,那么其内层的所有tag标签都可以使用这个对象。由于这样产生的对象没有一个指定的名字,那么就可以将少重名的冲突。这个例子阐述了一系列协作的嵌套对象。 )O2Nlk~l&  
nI`f_sp  
<tt:outerTag> ElEv(>G*  
fd5ZaE#f  
<tt:innerTag /> )y%jLiQv  
QX/X {h6  
</tt:outerTag> AK@`'$  
w PG1P'w;  
#K :-Bys5v  
Tag处理类 bVa+kYE  
96"yNqBf  
n*vTVt)dJ  
Tag处理类必须实现Tag接口或BodyTag接口,不过现在一般都流行从TagSupport或BodyTagSupport类中继承,这些类或接口都可以在javax.servlet.jsp.tagext包中找到。 (xZr ]v ]U  
@pF fpHq?>  
当JSP引擎看到自己的JSP页面中包含有tag标签时,它会调用doStartTag方法来处理tag标签的开头,调用doEndTag方法来处理tag标签的结束。 lC'{QUC  
%1-K);S J  
下表说明不同类型的tag所需要不同的处理过程: sJ))<,e5I  
3d*&':  
Tag处理类的方法 .N~PHyXZR  
D00G1:Ft(T  
Tag标签类型 :]CzN^k(1c  
所调用的方法 ,:#,}w_HyO  
d5@X#3Hd  
基本标签 (O)\#%,@R  
doStartTag, doEndTag, release K3vseor  
C5O5S:|'  
带属性的标签 n S_Ta  
doStartTag, doEndTag, set/getAttribute1...N, release }xAie(  
kz ZDtI)  
带内容的标签 doP$N3Zm  
doStartTag, doEndTag, release H~A"C'P3#  
A}t%;V2  
带内容的标签,且内容重复循环 r4O|()  
doStartTag, doAfterBody, doEndTag, release s kN9O"^A  
-PNi^ K_  
带内容的标签,且内容与JSP交互 +hE',i.  
doStartTag, doEndTag, release, doInitBody, doAfterBody, release 2v0!` &?M{  
aWyUu/g<A`  
一个tag处理类可以通过javax.servlet.jsp.PageContext来与JSP交互,通过javax.servlet.jsp.PageContext类,tag处理类可以访问JSP中的request、session和application对像。 Vy-28icZ`  
K)\(wxv  
如果tag标签是互相嵌套的,那内层的tag处理类可以通过它的parent属性来访问上层的tag处理类。 WtEI] WO  
"-w ^D!C  
一般情况都将所有的tag处理类打成了JAR的包,以便于发布。 D`6iDi t  
t#C,VwMe[  
<d5@CA+M  
Tag库描述(简称TLD) t)YUPDQ@J  
= 96G8hlT  
JnfqXbE  
Tag库是用xml语言描述的,TLD包括了tag库中所有tag标签的描述,它一般用来被jsp服务器用来校验tag的语法正确性,或者被jsp开发者用来开发新的标签。 KQ&Y2l1*>>  
MkwU<ae AB  
TLD的文件扩展名必须为.tld,而且必须放在当前WEB应用的WEB-INF目录或其子目录中。 n.*3,4.]  
U^MuZ  
一个TLD的内容的开头必须遵守标准的XML开头,用于描述DTD和xml的版本,例如: cv}aS_`f  
P0^c?s"I  
<?xml version="1.0" encoding="ISO-8859-1" ?> a6%@d_A  
ebqg"tPN{  
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd"> 2 P=[  
TLD必须以<taglib>来作为它的根元素,<taglib>的子元素如下表: |^R*4;Phe  
]*qU+&  
74+A+SK[  
<taglib>的子元素 `ncNEHh7K  
NUCiY\td  
Element i}v9ut]B  
Description %}P4kEY  
MaO"#{i  
tlib-version +Mk#9 r  
Tag库的版本 mzWP8Hlw  
#)o7"PW:  
jsp-version H3 , ut  
Tag库所需要的jsp的版本 t2- ^-g6  
xACdZB(  
short-name C-m*?))go  
助记符,tag的一个别名(可选) =.*98  
fiVHRSX60  
uri {CtR+4KD  
用于确定一个唯一的tag库 Bq@zaMv  
` J]xP$)  
display-name 54{q.I@n  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) 03k?:D+5  
qj!eLA-aD  
small-icon }u%"$[I}  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) ](#&.q%5!  
\=;uu_v$  
large-icon Iy';x  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) }XR : 2  
9@K.cdRjQ  
description N>|XS ,  
对tag库的描述(可选) JN4fPGbV  
x({H{'9?  
listener ('C7=u&F  
参见下面listener元素 wJeG(h  
['q&@_d7  
tag S QY"OBo<e  
参见下面tag 元素 #aar9  
\, &9  
Listener元素 x[(?#  
D)Q)NI  
一个tag库可能定义一些类做为它的事件侦听类,这些类在TLD中被称为listener 元素,jsp服务器将会实例化这些侦听类,并且注册它们。Listener元素中有一个叫listener-class的子元素,这个元素的值必须是该侦听类的完整类名。 -r<#rITH"  
2-'Opu  
Tag元素 jZpa0grA  
;`dh fcU  
每个tag元素在tag库中都要指出它的名字、类名、脚本变量、tag的属性。其中脚本变量的值可以直接在TLD中定义或通过tag附加信息的类来取得。每个属性描述了这个属性是否可以省略,它的值是否可以通过<%= …%>这样的JSP语法来获得,以及属性的类型。 QAPu<rdJP  
~rD={&0  
每一个tag在TLD中对应一个tag元素,下表是tag元素的子元素: rJJ[X4$  
9Q;c ,]  
Tag元素的子元素 \.uc06  
G8Z4J7^  
元素名称 ytz SAbj  
描述 \4d.sy0&>-  
,=QM#l]  
name ::5E8919  
独一无二的元素名  Q=uRKh  
TUIk$U?/I  
tag-class B,WTHU[AV  
Tag标签对应的tag处理类 ] )DX%$f  
(X[CsaXt  
tei-class o|BP$P8V  
javax.servlet.jsp.tagext.TagExtraInfo的子类,用于表达脚本变量(可选) w|[RDaAb  
Pmg)v!"  
body-content BYrZEVM9  
Tag标签body的类型 .|qK +Hnc  
8eBOr9l+j  
display-name !4"^`ors$  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) oR1^/e  
/u%h8!"R  
small-icon lbdTQ6R  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选)  +=q)  
G!N{NCq  
large-icon B+d<F[ |  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) 7dG 79H  
z4#(Ze@u~_  
description dy__e^qi  
此tag标签的描述 m([(:.X/IX  
}9HmTr|  
variable 57a2^  
提供脚本变量的信息(同tei-class)(可选) kd`0E-QU  
u]-_<YZ'B  
attribute 9^"b*&>P  
Tag标签的属性名 }?F`t[+  
%3q0(Xl  
以下章节介绍对于不同类型的tag,如何具体地实现它们。 im} ?rY  
U[L9*=P;  
%J:SO_6  
简单的tag {rfF'@[  
*L6PLe  
*-W#G}O0  
tag处理类 h&.wo !  
Jj~EiA  
简单的tag处理类必须实现Tag接口的doStartTag和doEndTag方法。当jsp引擎碰到tag标签的开头时,doStartTag被调用,因为简单的tag没有body,所以此方法将返回 SKIP_BODY。当jsp引擎碰到tag标签的结尾时,doEndTag被调用,如果余下的页面还要被计算,那它将返回EVAL_PAGE,否则将会返回SKIP_PAGE。 Oa;X +  
R[z`:1lo  
以下是例子:对于标签 <tt:simple /> ,它的tag处理类实现如下: fDE%R={!n5  
]5~s "fnG  
e^4 p%  
public SimpleTag extends TagSupport !Fo*e  
G22NQ~w8  
{ Spo?i.#  
2%*MW"Q  
public int doStartTag() throws JspException }i {sg#  
Q9}dHIe1E  
{ 5D M"0  
Uv YF[@  
try{ />'V!iWyz  
1O].v&{  
pageContext.getOut().print(“Hello.”); }X GEX:1K  
o"wXIHUmV  
}catch(Exception e){ H&r,FmI@  
m)V/L]4  
throw new JspTagException(“SimpleTag: “ + e.getMessage()); PH"hn]  
*Av"JAX  
} m9U"[Huv1E  
4Mk-2 Dx  
return SKIP_BODY; {G <kA(Lm  
dz~co Z9  
} ^[%%r3"$C  
m<L;  
public int doEndTag() +<,gB $j  
Ii7QJ:^  
{ 1c JF/"v  
VG/3xR&y  
return EVAL_PAGE; n wI!O  
n|GaV  
} >]o}}KF?  
~Lc066bLeq  
} 6} FO[  
pP(XIC  
r`c_e)STO  
注意:如果tag标签没有内容的话,那必须定义body-content元素为空,例如 uEc<}pV  
P0 `Mdk371  
<body-content>empty</body-content> 0]HYP;E"U  
52upoU>}2  
~=R SKyzt  
带属性的tag标签
评价一下你浏览此帖子的感受

精彩

感动

搞笑

开心

愤怒

无聊

灌水
级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
只看该作者 1 发表于: 2007-01-01
tag处理类  |W<+U  
Gycm,Cy  
对于tag标签的每个属性,你必须依照JavaBeans规范来定义其属性,以及get和set方法。以struts的logic:present 标签为例, (knp#   
> x IJE2  
<logic:present parameter=”Clear”> vM_:&j_?``  
A)ipFB 6K  
与此相应,此tag处理类应有如下方法和定义: o:V|:*1Q  
]({~,8s  
# p[',$cC  
protected String parameter = null; " vtCTl~t  
M:5b4$Qh<  
public String getParameter() V ]90  
IKie1!ZU{"  
{ H4]Ul eU  
<V>dM4Mkr  
return this.parameter; [ Bl c^C{f  
(rg;IXAq%  
} G\T fL^A  
?)e37  
public void setParameter(String parameter) @?"h !fyu  
8b0d]*q  
{ -\#0]F:-  
{&Q9"C  
this.parameter = parameter; n("0%@ov  
s=[h?kB  
} >ooZj9:'  
VE8;sGaJ  
Zdn~`Q{  
注意:如果你的属性名为id,而且你的tag处理类是从TagSupport类继承的,那你就不需要定义它的属性和set和get方法,因为他们早已在TagSupport被定义过了。 CW<N: F.9  
=Fdg/X1  
Attribute元素 M`S0u~#tI  
\rPbK+G.  
对于tag标签的每个属性,你必须定义它是否必须的,它的值是否可以用诸如<%= …%>的表达式来获得,以及它的类型(可选),如果不指定它的类型,那就默认为是java.lang.String类型。如果rtexprvalue元素被定义为true或yes,那么在type元素中就定义了attribute的返回类型。 In[Cr/&/Y  
)XWP\ h  
<attribute> &?h,7 D;A  
36am-G  
<name>attr1</name> VWO9=A*Y|  
t:fFU1x  
<required>true|false|yes|no</required> dXnl'pFS  
NssELMtF!g  
<rtexprvalue>true|false|yes|no</rtexprvalue>  }K3x  
O eL}EVs8=  
<type>attribute的返回类型(只用当rtexprvalue为真是才有效)</type> 1T[et-  
@'GGm#<   
</attribute> L QjsOo  
!A%<#Gjt  
如果tag的某个属性不是必须的,那tag处理类会自动提供一个缺省值。 \_B[{e7z  
E4hLtc^ +  
例如,在logic:present这个tag标签中定义了一个属性叫parameter,但它不是必须的,而且它可以被诸如<%= …%>的表达式来赋值。 cH>%r^G\  
i'\T R|qd  
<tag> HbW0wuI  
w}=5ElB  
<name>present</name> QVtQx>K`  
50={%R  
<tag-class>org.apache.struts.taglib.logic.PresentTag</tag-class> ,{c?ymw?  
Q1+dCCY#F  
<body-content>JSP</body-content> [Jv@J\  
s-v  
#f+$Ddg*  
 f& CBU  
<attribute> Jkek-m  
#_u~/jhX  
<name>parameter</name> )6aAB|  
k5T,990  
<required>false</required> [1u-Q%?#  
YD7Oao4:o  
<rtexprvalue>true</rtexprvalue> &#iTQD  
}+sT4'Ah>  
</attribute> y`=]T>X&x  
[W7CXZDd  
?F3h)(}  
pfI"36]F  
</tag> ~Rr~1I&mR,  
a0#J9O_  
R~6$oeWAw  
属性元素的校验 {yExQbN  
_FWBUZ;N  
RVQh2'w  
有关于tag标签的有效值可以从tag库的说明文档中获得,当JSP页面被编译时,jsp引擎会强制性地参照TLD中定义的规则进行检查。 j{Q9{}<e  
8#g1P4  
还有一个方法也可以进行属性元素的校验,就是先继承类TagExtraInfo,然后调用它的isValid方法。这个类同时也起到提供tag中定义的脚本变量信息的作用。 |/)${*a4n  
a5 TioQ  
IsValid方法通过TagData对象来传递属性信息,它包括着tag的所有的属性名-值的信息。由于校验发生在运行时刻,因此这个属性的值将被赋值为TagData.REQUEST_TIME_VALUE。 MpR2]k#n<  
&:`U&06q  
例如tag标签<tt:twa attr1=”value1” />在TLD中定义如下: uwy:t!(j  
rQ qW_t%  
<attribute> , JQp'e  
m*kl  
<name>attr1</name> W@I|Q -  
D-._z:_  
<required>true</required> e-EUf  
u@cYw:-C  
<rtexprvalue>true</rtexprvalue> ,]d /Q<  
CTZ8Da^  
</attribute> _y} T/I9  
#$8% w  
z\%67C  
这个定义说明了attr1能在运行期间被赋值。 G\+L~t  
.0`m\~L  
以下的isValid方法检查attr1属性的值是否属于Boolean类型。注意由于attr1能在运行刻被赋值,那么isValid方法必须检查tag用户是否对此tag进行了运行时刻赋值。 x5-}h*  
`M^= D&Bf  
o9dY9o+Z  
Public class TwaTEI extends TagExtraInfo Tq[kl'_  
2so!  
{ _ =VqrK7T  
Zm_UR*"  
public boolean isValid(Tagdata data) ^Xq 6:  
hRD=Y<>A  
{ [R^i F  
(Hb:?(  
Object o = data.getAttribute(“attr1”); IS&ZqE(`e  
sl`s_$J  
If(o != null && o != TagData.REQUEST_TIME_VALUE) ?FpWvyz|  
)9"_J9G  
{ ]rH\`0  
TU,s*D&e  
if( ( (String)o).toLowerCase().equals(“true”) || n%o5kVx0  
B][U4WJ)  
((String)o).toLowerCase().equals(“false”) ) eoG$.M"  
zkuU5O  
return true; jN;@=COi  
f=r<nb'H  
else pS'FI@.'{  
sHt].gZ  
return false; IID-k  
bB1UZ O  
} /-_h1.!   
R6kD=JY/!  
else rrBsb -  
:~tAUy":_*  
return true; 0zlb0[  
$j5K8Ad  
} T?tgd J  
!Sh&3uy_qN  
} `(ue63AZ  
lm-dW'7&  
M3c$=>  
带body的tag 1{ ~#H<K  
P2BWuh F  
}@'$b<!B  
tag处理类 .f%fHj  
:8=ikwQ  
"U>JM@0DNm  
如果tag标签含有内容,那处理方式会略微有些不同,而且还要视tag处理类是否要与body交互的情况而定。如果要与body交互,那我们认为tag处理类要可能要对body进行操作。 !;Yg/'vD-  
A+ZK4]xb  
Tag处理类不与body交互 hV8[@&Sx3  
}Jy8.<Gd^  
如果tag处理类不与body交互,tag处理类应该实现Tag接口或从TagSupport中派生,如果body要被计算,那么doStartTag方法应返回 EVAL_BODY_INCLUDE,否则应返回SKIP_BODY。 V@e?#iz  
;qafT@ }C  
如果tag处理类要对body反复运算,则它应该实现IterationTag或从TagSupport中派生。如果tag处理类认为body还未计算完的话,那它的doStartTag方法和doAfterBody方法必须返回EVAL_BODY_AGAIN。 %Gz0^[+  
y&q*maa[  
Tag处理类与body交互 ?I_s0k I  
z;{iM/Xe  
如果tag处理类与body交互,那tag处理类应实现BodyTag接口或从BodyTagSupport中派生。这种tag处理类一般要实现doInitBody和doAfterBody方法。 3G,Oba[$<  
8uc1iB  
Body允许一些方法来读写它的内容。Tag处理类可以调用body内容的getString或getReader方法来从body中提取信息,也可用 writeOut(out) 方法来将body的内容写入到out对象中。其中out对象通过tag处理类的getPreviousOut方法来获得。 l&OKBUG  
+7D|4  
如果body的内容需要被计算,那么doStartTag方法必须返回EVAL_BODY_BUFFERED,否则,它将返回 SKIP_BODY。 :mh_G  
@=bLDTx;c)  
doInitBody 方法 "CSsCA$/  
!"HO]3-o  
此方法在body内容已经设好,但未被计算之前被调用。你可以根据不同的body内容来制定初始化策略。 qON|4+~u%  
s @&`f{  
doAfterBody方法 twL3\ }N/B  
V+* P2|  
此方法在body内容已被计算后进行调用。 lGPUIoUo  
GY6`JWk  
和doStartTag方法一样,doAfterBody方法返回一个指示符指示是否要继续计算body,如果要继续计算,则doAfterBody应返回EVAL_BODY_BUFFERED,否则,它应返回SKIP_BODY。 ][gq#Vx@  
~P*6ozSYpY  
release 方法 >:AARx%  
6]V4muz#c  
tag处理类调用此方法将它的状态重置为初始状态,并释放所有的私有资源。 ,X[kt z  
*W4m3Lq  
lGV0 *Cji  
以下的例子读取body的内容(其中含有一条sql语句),然后将它传递给一个对象,让它进行查询。由于此处body不须重新计算,所以doAfterBody会返回SKIP_BODY。 ^=BTz9QM  
M>wYD\oeg  
k$R~R-'  
Public class QueryTag extends BodyTagSupport 0LPig[  
7L`A{L  
{ prC;L*~8  
_Zp}?b5Q  
public int doAfterBody() throws JspTagException 1t:Q_j0Ym  
'-r).Xk  
{ ' KWyx  
iqC|G/  
BodyContent bc = getBodyContent(); hEA<o67  
j#X.KM   
//将body的内容以字符串的格式提取出来 dT`D:)*:  
@)UZ@ ~R  
String query = bc.getString(); _D+}q_  
sd,J3  
//清除body Ee)T1~;W  
~xA-V4.  
bc.clearBody(); <>dT64R|  
-|J"s$yO4  
try{ bV(Y`g  
G<At_YS  
Statement stmt = connection.createStatement(); @E;=*9ek{u  
Y#!UPhg<  
Result result = stmt.executeQuery(query); Hc!  mB  
gwOa$f%O  
}catch(SQLException e){ cGtO +DE  
"oTHq]Ku  
throw new JspTagException(“queryTag: “ + e.getMessage() ); 33o9Yg|J~  
t|H^`Cv6  
return SKIP_BODY; ~T ]m>A!  
9*2[B"5  
} aDq5C-MzG  
&qMPq->  
} T?:Rdo!:u  
ql<i]Y  
~?D4[D|sB  
body-content元素 {\S+#W\  
bHPYp5UwN  
;'?l$ ._  
由于tag可能会有body,你必须用body-content元素来指定body内容的类型: p!rG PyGC  
;1(qGy4  
<body-content>JSP|tagdependent</body-content> MOH,'@&6^  
do :RPZ!  
XH_qA[=c]  
如果body的内容是定制的或内部的tag、脚本元素、或HTML广本,则归类为JSP类型。其他的类型,比如上面代码所述的?D?D将sql statement类传给 query tag的这种类型应该标为tagdependent。 CM@"lV_  
U 8 .0L  
注意:实际上body-content的值并不影响tag处理类对body内容的处理,它仅仅是被tag编辑工具用来描述此body的内容。 4^jZv$l5  
@N:3`[oB  
:u|UVp5  
用tags定义脚本变量 pqNoL* H  
Di5Op(S((  
B=nx8s  
tag处理类 % 'L=  
KlSY^(kHR  
swe8  
tag处理类负责创建或设置页面中定义的脚本变量,用pageContext.setAttribute(name,value,scope)或pageContext.setAttribute(name,value)方法来实现。一般来说,tag处理类通过脚本变量的名称来获取它,脚本变量的名称一般可用get方法来获得。 '&o> %V  
6`{)p&9  
如果脚本变量的值依赖于tag处理类中的上下文中某一对象,那它可用pageContext.getAttribute(name,scope)方法来找到那个对象。一般的处理过程是tag处理类先找到脚本变量,再对其进行处理,然后用pageContext.setAttribute(name,object)的方法来设置它的新值。 r0XGGLFuZl  
E rRMiT  
对象的生存周期(scope)如下表: ;tIIEc  
0$dY;,Q.  
对象的生存周期表 E '6 z7m.  
&<; nl^  
名字 %@,:RA\pm  
可访问范围 H6+st`{  
生存周期 BRQ5  
Yh!\:9@(  
page ;-P:$zw9c  
当前页面 &b#NF1Q.  
一直有效,除非页面向客户提交响应或重定向到一个新页面 i~M.F=I5  
{UjIxV(J  
request N'1[t  
当前页面或当前页面重定向到的页面 Q0oDl8~  
一直有效,除非页面向客户提交响应 ZB h@%A  
s9)8{z  
session D/!G]hx  
当前页面或在同一浏览器窗口中的页面 :O2v0Kx  
一直有效,除非关闭当前浏览器、超时、网络故障 ]`+"o[  
Ub-k<]yZ  
application 9R<J$e  
整个web应用程序的所有请求 ,HjHt\!~<  
一直有效,除非发生网络故障、服务器故障 Z{>Y':\?<  
z8MpE  
提供关于脚本变量的信息 -ZMl[;OM  
m~\m"zJ4  
以下示例定义了一个名为“book”的脚本变量,用来访问程序中关于书的信息: Uu<sntyv  
-1Ki7|0,  
<bean:define id=”book” name=”bookDB” property=”bookDetails” type=”database.BookDetails” /> z@40 g)R2A  
 6-E4)0\  
<font color=”red” size=”+2” > sRI=TE]s  
'J<zVD}0  
<%= messages.getString(“CartRemoved”) %> vzQmijr-  
Lw78v@dY  
<strong><jsp:getProperty name=”book” property=”title” /></strong> dYttse'  
< oG\)!O  
</font> n ;fTx  
.M#>@~XR  
当包含此tag的JSP页面被编译时,jsp引擎会自动生成关于此book的同步的代码(同步可以避免几个客户同时访问此book时造成的冲突),要生成同步代码,jsp引擎需要知道此脚本变量的如下信息: Ymh2qGcj]8  
UHm+5%ZC  
· 脚本变量名称 2LK*Cv[  
jZgnt{  
· 脚本变量所属的类 `[R:L.H1  
UM;bVf?  
· 此脚本变量是否引用了一个新的或已存在的对象 B=qRZA!DQ?  
AF nl t  
· 此脚本变量的有效性 LHGK!zI  
Xwqf Wd_  
有两种办法可以向jsp引擎提供关于脚本变量的信息:在TLD中定义variable子元素,或用tei-class子元素定义一个额外tag信息类。用variable最简单,但可能降低了一些灵活性。 +vY`?k`  
<Ucfd G&Lp  
Variable元素 U8@*I>vA  
tw^.(m5d  
Variable元素有如下子元素: 5nlyb,"^g  
"Kf~`0P  
· name-given ?D?D 给出的名字,是一个常量 +=F);;!  
+/ d8d  
· name-from-attribute?D?D 属性名,在编译时给出的属性名 E~U|v'GCd  
yvnrZ&x :  
name-given或name-from-attribute两者必须选一,但以下子元素是可选的: oHGf |  
*v-xC5L1\  
· variable-class?D?D变量的类型,缺省为java.lang.String。 E;*TRr><  
4zvU"np  
· declare?D?D此脚本变量是否引用了一个新对象,缺省为True。 F;l<>|vG  
z[I/ AORl  
· scope?D?D脚本变量的范围,缺省为NESTED。下表描述了scope的几种类型: ,}$x'8v  
5Ddyb%  
脚本变量的有效范围 Q14;G<l-  
I.0Usa"z  
;C@^wI  
有效性 .ceU @^  
方法 jT_Tx\k  
&Fr68HNmj  
NESTED fXR_)d  
在tag标签的开始和结束之间 )=y6s^}  
如果tag处理类实现BodyTag接口,则在doInitBody和doAfterBody中调用,否则在doStartTag中调用 U\plt%2m>  
s.Ic3ITd,  
AT_BEGIN 15yV4wHr  
从tag标签的开始一直到页面结束 m,"tdVo.  
如果tag处理类实现BodyTag接口,则在doInitBody、doAfterBody和doEndTag中调用,否则在doStartTag和doEndTag中调用 G@6,O-Sj  
;-wPXXR  
AT_END I>\?t4t  
从tag标签的结束一直到页面结束 ))-M+CA  
在doEndTag中调用 :re(khZq#  
(B4 A$t  
以struts为例,它的bean:define标签的实现遵循JSP1.1规范,此规范要求使用额外tag信息类来定义脚本变量。Variable元素是JSP1.2规范中加入的。以bean:define标签为例,你可以定义如下variable元素: /-9+(  
"PP0PL^5F  
<tag> @Pg@ltUd  
#8HXR3L5=!  
<variable> 2:0Y'\nn  
x" =q+sA  
<name-from-attribute>id</name-from-attribute> :9< r(22  
Q/SC7R&"t  
<variable-class>database.BookDetails</variable-class> 6R,b 8  
YuuG:Kk  
<declare>true</declare> mqxy(zS]  
W- B[_  
<scope>AT_BEGIN</scope> ?a_q!,8:  
DFH6.0UW  
</variable> (9lx5  
f*@:{2I.v  
</tag> Z1}zf( JU  
QiL  
额外tag信息类 tXuxTVhoT  
Q(Y,p`>  
如果要定义一个额外tag信息类,你要继承javax.servlet.jsp.TagExtraInfo类。一个TagExtraInfo类必须实现getVariableInfo方法,此方法返回一个叫VariableInfo的数组类,它包括如下信息: M?CMN.Dw  
ph+tk5k  
· 变量名 tOVm~C,R  
ZX}"  
· 变量所属类名 )4C6+63OD&  
- C]a2  
· 此变量是否引用了一个新对象 Q";eyYdOL  
b,sc  
· 此变量的有效范围 1F8EL)9  
-w0>4JDs  
jsp引擎将一个名为data的参数传给getVariableInfo方法,data中包括tag标签中的所有“属性名?D?D属性值”对。它可以用来向VariableInfo对象提供脚本变量的名字和类名。 }J lW\#  
I=-;*3g6  
以struts为例,它在bean:define标签中定义了一个名为DefineTei的额外tag信息类,用来向脚本变量提供信息。由于脚本变量的名称(book)和类名(database.BookDetails)是通过tag标签的属性来传递的,它们一般定义在VariableInfo的构建代码中,并且可用data.getAttributeString方法来得到这些信息。如果要允许book脚本变量能在从tag开始直到整个JSP页面结束的范围内都可用的话,那它的范围应设为AT_BEGIN。如下所示: F'Vl\qPt  
''YjeX  
WHT%m|yn  
public class DefineTei extends TagExtraInfo \C.@ @4{  
\5_^P{p7<  
{ (LPc\\Vv  
4(gf!U  
public VariableInfo[] getVariableInfo(TagData data) (ytkq(  
I(S6DkU  
{ N#ObxOE6T"  
U /Fomu  
String type = data.getAttributeString(“type”); VG7#6)sQoK  
EF~PM  
If( type == null) pdu  
' qVa/GJ  
type = “java.lang.Object”; Xqw7lj;K  
tYa*%|!v  
return new VariableInfo[] { SW, Po>Y  
hdb4E|'A  
new VariableInfo(data.getAttributeString(“id”), c^k. <EA  
R:p,Hav<q  
type, _ RYZyw   
WGK::?  
true, *RM'0[1F4  
iHB)wC`u  
VariableInfo.AT_BEGIN) DVH><3FF  
v,B\+q/  
}; 7F~+z7(h  
ARo5 Ss{  
} q"oNB-bz  
]^<~[QK_C  
} W@=ilW3RD  
l"8YIsir  
7L"/4w  
注意:关于额外tag信息类的类名必须要在TLD中的tag标签下的tei-class子元素中定义。因此,DefineTei的tei-class中的定义看起来如下: jyr#e  
<tei-class> G.T1rUh=  
org.apache.struts.taglib.bean.DefineTagTei !HYqM(|{.  
</tei-class> xcA:Q`c.{  
D$;/ l}s?  
89bKnsV  
具有协作关系的tag }fZBP]<I(  
AJ u.  
!C?z$5g  
tag通过共享对象来进行协作,JSP技术支持2种方式的对象共享。 \9^@,kfP  
Po3W+; @  
第一种方法是使用pageContext对象进行对象的共享(可支持JSP页面和tag处理类之间的共享),如果在一个tag处理类中要调用由另一个tag处理类创建的对象,可调用pageContext.getAttribute(name, scope)方法。 <ZEA&:p  
AtI,& S#{  
第二各方式的共享是对于tag之间有嵌套关系而言的,外层的tag所创建的对象对于内层的tag来说是可以共用的。这种形式的共享的好处是减少了可能存在的重名冲突。 {VG6m Hw  
W{d/m;<@N  
要访问一个嵌套tag创建的对象,tag处理类必须先找到此嵌套tag对象,可用TagSupport的静态方法 TagSupport.findAncestorWithClass(from, class)或TagSupport.getParent方法。前者在当不确定此tag是否为嵌套tag对象时使用。一旦它的父类被找到,它就能访问其所有动态或静态创建的对象。静态创建的对象是父类的成员,而动态创建的对象可能是父类的私有对象。诸如此类的对象可以用tag处理类的setValue方法来保存,用getValue方法来获得。 1\uS~RR  
<Vb{QOgc;  
下例阐述了以上两种共享对象的方法。在这个例子当中,一个查询tag检查一个名为connection的属性名是否在doStartTag中被设置。如果connection属性被设置,tag处理类从pageContext中得到这个connection对象。否则,此tag处理类先找到它的父tag处理类,然后从它的父tag处理类中找到connection对象。 Viw3 /K  
=KLYR UW  
QZol( 2~Y  
public class QueryTag extends BodyTagSupport dGe  
CS49M  
{ yk/XfwQ5  
\\JXY*DA:+  
private String connectionId; u.6%n. g  
F ReK  
public int doStartTag() throws JspException T*m_rDDt  
9`AQsZ2  
{ U^D7T|P$V  
b8&9pLl  
String cid = getConnection(); ;nE}%lT  
; ]!  
if(cid != null) _NFJm(X.  
Pif1sL6'  
{ +8M{y D9#  
~4 ab\hq  
//存在一个connection id,使用它。 m`~ Qr~  
&0ra a  
connection = (Connection) pageContext.getAttribute(cid); FmPF7  
H'2 =yhtVh  
} ^E^:=Q?'_  
$ }53f'QjW  
else [Wc 73-  
Alz#zBGb  
{ ff0,K#-  
\=)h6AG  
ConnectionTag ancestorTag = (ConnectionTag)findAncestorWithClass(this, r+Y1m\  
x{E[qH_1Fm  
ConnectionTag.class); ln5On_Wm  
& BkNkb0  
if(ancestorTag == null) gK /K Z8  
4)_ [)MZ\j  
{ H@zpw1fH+  
U!4 ^;  
throw new JspTagException(“一个没有connection属性的查询标签必须被一个connection标记嵌套。”); -SQYr  
A:f+x|[  
} eR CGr?e4  
P\JpE  
connection = ancestorTag.getConnection(); .JE7vPv%!  
M%/D:0  
} Ts\7)6|F  
6C:Lq%}  
}  (c"!0v  
IF=rD-x  
} 4.8,&{w<m  
; OsN^   
Hi Yx(hY  
%}/)_RzQ  
此查询标签在JSP页面中的调用形式可以从以下2种定义中任选一种: u8*0r{kOH  
m N{$z<r  
LBg#KQ @  
<tt:connection id=”con01” ...> ... </tt:connection> )lbF'.i  
pmC@ fB  
<tt:query id=”balances” connection=”con01” > vd~O:=)4  
&m`  
SELECT account, balance FROM acct_table =GF+hM/~  
deNU[  
where customer_num = <%= request.getCustno() %> [kCn6\_<V  
2rxdRg'YLQ  
</tt:query> z,)Fvs4U.  
tc[PJH&P  
k(MQ:9'|  
&>-Cz%IV  
q~qig,$Y  
<tt:connection ...> $jHL8r\e7  
7Ny>W(8  
<x:query id=”balances”> Xe5J  
HN:{rAIfc  
SELECT account, balance FROM acct_table *G9;d0  
(/%}a`2#o  
where customer_num = <%= request.getCustno() %> QwhPN'U  
z# y<QH  
</x:query> -I -wdyDr  
-$7Jc=:>  
</tt:connection> thh, V   
?F-,4Ox{/  
1xw},y6T2  
与此同时,在TLD中必须指定connection属性为可选的,定义如下: Z1Ms ~tch  
:!%oQQO  
<tag> G 5)?!  
_?{2{^v  
... &rn,[w_F[  
_2|,j\f;L  
<attribute> L8V'mUyD  
CTwP{[%Pk  
<name>connection</name> KT3[{lr  
`]%{0 Rx  
<required>false</required> ^3e l-dZ  
"PX~Yc  
</attribute> |PWLFiT(>  
Qwb@3{  
</tag>
描述
快速回复

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