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

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

级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
标准的JSP 标记可以调用JavaBeans组件或者执行客户的请求,这大大降低了JSP开发的复杂度和维护量。JSP技术也允许你自定义taglib,其实换句话说,taglib可以看成是对JSP标记的一种扩展,正如xml是对html的一种扩展一样。taglib通常定义在tag标签库中,这种标签库存放着你自己定义的tag标签。简而言之,如果使用taglib,那么你可以设计自己的JSP标记! L2 ^-t7  
@ZTsl ?  
一般来说,自定义tag标签主要用于操作隐藏对象、处理html提交表单、访问数据库或其它企业级的服务,诸如邮件和目录操作等等。自定义tag标签的使用者一般都是那些对java编程语言非常精通,而且对数据访问和企业级服务访问都非常熟悉的程序员,对于HTML设计者来说,使得他可以不去关注那些较复杂的商业逻辑,而将精力放在网页设计上。同时,它也将库开发者和库使用者进行合理分工,自定义tag标签将那些重复工作进行封装,从而大大提高了生产力,而且可以使得tag库可用于不同的项目中,完美地体现了软件复用的思想。 W&Pp5KR  
DU=rsePWE  
在这篇文章中,我们主要讨论: <Zn -P  
Qkq9oZ  
· 什么是自定义tag标签? .uwD;j +#  
2c4x=%  
· 怎么使用tag标签? Q{"QpVY8  
sm>5n_Vw  
o 声明要使用的tag库 Vi o ~2  
[mJmT->  
o 找到与之对应的tag处理类 `am]&0g^+(  
sfw lv^  
o tag标签的类型 #CYDh8X<i  
d]<S/D'i  
· 自定义tag标签 LCf)b>C*  
/swNhDQ"o  
o tag处理类 di5>aAJ)D  
N6wCCXd  
o tag库描述 =vc8u&L2  
`R+I(Cb  
o tag标签示例 \C eP.,<  
>Qg 9KGk'  
o 带属性的tag W]U}, g8Z  
_)6N&u8  
o 带body的tag { i2QLS  
L}x,>hbT  
o 定义了脚本变量的tag Fy8$'oc  
klwNeGF]N  
o 具有协作关系的tag _0: }"!Gq  
S#wy+*  
· 自定义tag标签 kvo V?<!  
;LjTsF'  
o 一个迭代tag的例子 do>,ELS+m  
Yl#|+xYA5[  
o 一个模板tag库 jJOs`'~Q\  
xJSK"  
o tag处理类到底是怎样被调用的? +'f+0T\)  
~qP_1() ?  
SV}C]<  
什么是自定义的tag? %zCV>D  
eG05}  
一个自定义的tag标签是用户定义的一种JSP标记。当一个含有自定义的tag标签的JSP页面被jsp引擎编译成servlet时,tag标签被转化成了对一个称为tag处理类的对象进行的操作。于是当JSP页面被jsp引擎转化为servlet后,实际上tag标签被转化成为了对tag处理类的操作。 isiehKkD  
q+}KAk|]V  
自定义tag标签有很多特色,诸如: ^w(~gQ6|mP  
yv2N5IQ>{V  
· 可以在JSP页面中自定义tag标签的属性 4' MmT'  
-xk.wWpV  
· 访问JSP页面中的所有对象 |1[3RnG S  
2\/,X CQV  
· 可以动态地修改页面输出  o<Z  
G!L(K  
· 彼此这间可以相互通信。你可以先创建一个JavaBeans组件,然后在一个tag中调用此JavaBeans组件,同时可以在另一个tag中调用它。 Tb@r@j:V  
^+'[:rE  
· tag允许相互嵌套,可以在一个JSP页面中完成一些复杂的交互。 qVDf98  
THl={,Rw`  
1q7Y,whp  
使用tag标签 jqeR{yo&0b  
! O~:  
Zl4X,9Wt  
本节主要描述怎样在JSP页面中使用tag标签,以及tag标签的不同类型。  <RaM@E  
ZJ Ke}F`l  
要使用tag标签,JSP程序员必须做2件事: ?n0Z4 8%  
l1?$quM^V  
· 声明此tag标签的tag库 b2<((H  
P56B~M_  
· 实现此tag标签 Uzzt+Iwm  
<QcQ.b  
声明tag标签所在的tag库 .nG14i7C  
a(Fx1`}  
如果要使用tag标签,则应用JSP的taglib指示符来指定其tag库(注意:taglib要在在使用此tag标签之前声明) v%2@M  
rUL_=>3  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> lH#C:n  
NZW)$c'  
uri属性定义了唯一的标签库描述(以下简称TLD),它可以是直接是tld文件名或一个独一无二的名字。prefix是用来区别其它TLD中和本TLD中有重名的tag的一种手段。 qjrl$[`X:  
^ b`wf"A  
TLD必须以.tld作为扩展名,并且存放在当前应用的WEB-INF目录或其子目录下。你可以通过它的文件名直接引用它,也可以通过别的方式间接地引用它。 2f8\Osn>m  
}\$CU N  
以下taglib指示符直接引用一个TLD: BD.>aAi!  
b$W~w*O   
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> %&[=%zc  
_< LJQ  
以下的taglib指示符通过一个逻辑名称间接地引用一个TLD: tP0\;W  
c`E0sgp  
<%@ taglib uri=”/tutorial-template” prefix=”tt” %> %p t^?  
P1u(0t  
如果是间接引用TLD的话,那你必须还要在web.xml中定义此逻辑名称与tld文件之间的映射,具体做法是在web.xml中加入一个名为taglib的元素: : FN-.1C  
;.'\8!j  
<taglib> `:>N.9'o  
yRyUOTK  
<taglib-uri>/tutorial-template</taglib-uri> S8Ec.]T   
9(AY7]6  
<taglib-location> `Hp=1a  
p`I[3/$3  
/WEB-INF/tutorial-template.tld m*f"Y"B.1I  
=euMOs  
</taglib-location> o0}kRL  
6a!b20IZh  
</taglib> V<&^zIJUR  
ARd*c?Om  
\M U-D,@  
实现此tag标签 WM8])}<L  
dMlJ2\ ]u  
&)ED||r,  
为了实现tag标签,你有2种方法来存放tag处理类。一、让tag处理类以.class的方式存放于当前应用的WEB-INF/class子目录下,二、如果tag处理类是以JAR包的形式存在的话,那可以放在当前应用的WEB-INF/lib目录下,如果tag处理类要在多个应用中共享,那么它就应放在jsp服务器上的common/lib目录下,对于tomcat来说,就是tomcat/common/lib目录下。 E gD$A!6N8  
F>lM[Lu#  
:6[G;F7s  
tag标签类型 9pMXjsE   
pAtt=R,Ht  
a9N$I@bi]  
自定义的tag标签遵循XML语法。它有一个开始标记和一个结束标记,有的还有body(即文本节点): zc.r&(d  
8quH#IhB  
<tt:tag> ZTg[}+0e  
?[!_f$50]P  
body y)K!l :X  
-SlAt$IJ  
</tt:tag> o#\c:D*k  
3'z L,WW  
nIEIb.-  
一个不带body的tag标签如下: 4L_AhX7  
n3" @E<rW  
<tt:tag /> K0'= O  
> Hwf/Gf[  
' TO/i:{\  
简单的tag标签 nJ2910"<  
cES8%UC^i  
一个没有body和属性的tag标签如下: -2qI2Z  
B".3NQ  
<tt:simple /> 9 K~X+N\  
E0*62OI~O  
cof+iI~9O%  
带属性的tag标签 ^OrO&w|  
q${+I(b,  
n3_| # 1Qu  
自定义标签可以有自己的属性。属性一般在开始标记中定义,语法为 attr=”value”。属性的作用相当于自定义标签的一个参数,它影响着tag处理类的行为。你可以在TLD中详细定义它。 %{B4M#~  
>uP1k.z'I  
你可以用一个String常量给一个属性赋值,也可以通过表达式给它赋值,如<%= ...%>。以struts为例,它的logic:present标签就是用的String常量来给属性赋值: 7TB&Q*Zf  
:qvA'.L/;z  
<loglic:present parameter = “Clear”> '>:%n  
k[a5D/b  
而另一个标签logic:iterate是用表达式来给属性赋值: _T(77KLn;  
b>@fHmpwD  
<logci:iterate collection=”<%= bookDB.getBooks() %>” ZfU &X{  
_Rk>yJD7s  
id=”book” type=”database.BookDetails”> vs2xx`Y<Lq  
]vjMfT%]W  
4&<zkAMR  
带body的tag标签 *],= !  
z0 J:"M  
一个自定义标签可以包含其它自定义标签、脚本变量、HTML标记或其它内容。 "\O{!Hj8  
[H=l# W@  
在下述例子中,此JSP页面使用了struts的logic:present标签,如果些标签定义了parameter=”Clear”的属性,则将清除购物车的内容,然后打印出一条信息: j)mi~i*U  
?OBB)hj  
<logic:present parameter=”Clear”> ,veo/k<"r8  
1[]V @P^  
<% cart.clear(); %> ]T>|Y0|  
iUq{c+h  
<font color=”#ff0000” size=”+2”><strong> { 4B7a6  
')Qb,#/,%  
你选择了清除购物车! 7,3 g{8  
e/Y& d9` I  
</strong></font> F$HL \y  
GXwQ )P5]  
</logic:present> yPk s,7U  
1>)uI@?Rb  
]htx9ds=  
到底是用属性还是用body来传递信息? \79aG3MyK  
&`}ACTY'P  
如上所述,我们既可以通过属性,也可以通过body来传递信息。但一般来说,比较简单的类型,如字符串或简单表达式最好采用属性来传递信息。 /rnP/X)T  
Q5c13g2(c  
X=[`+=  
定义脚本变量的tag标签 k8w:8*y'.  
_Kv;hR>  
所谓脚本变量,是指JSP中可以调用的变量或对象。它可由tag标签产生。以下示例阐述了一个tag标签定义了一个名为tx的由JNDI所定义的事务处理对象。脚本变量可以是ejb对象、事务、数据库连接等等: IF kU8EK&B  
I@uin|X  
<tt:lookup id=”tx” type=”UserTransaction” name=”java:comp/UserTransaction” /> ,A9{x\1!  
l<p6zD$l  
<% tx.begin(); %> &t@|/~%[  
t<yOTVah  
... 6Z!OD(/e  
rp!>rM] s  
X({R+  
具有协作关系的tag标签 /H$/s=YU\U  
4~e6z(  
自定义tag标签之间可以通过共享对象来实现协作。在下述例子中,标签tag1创建了一个名为obj1的对象,在标签tag2仍可以重复使用obj。 gx=2]~O1(  
NBO&VYs|  
<tt:tag1 attr1=”obj1” value1=”value” /> eXCH*vZY  
p}lFV,V  
<tt:tag2 attr1=”obj1” /> \SA$:^zO  
T;pe7"  
在以下这个例子当中,如果外层的tag标签创建了一个对象,那么其内层的所有tag标签都可以使用这个对象。由于这样产生的对象没有一个指定的名字,那么就可以将少重名的冲突。这个例子阐述了一系列协作的嵌套对象。 Zrp9`~_g<!  
E|ZLz~  
<tt:outerTag> %5/h;4   
p2j=73$  
<tt:innerTag /> Wa'm]J  
r~sQdf  
</tt:outerTag> !;B^\ 8{  
KTjf2/  
_;u@xl=  
Tag处理类 e2Df@8>  
O^4K o}  
)5l9!1j  
Tag处理类必须实现Tag接口或BodyTag接口,不过现在一般都流行从TagSupport或BodyTagSupport类中继承,这些类或接口都可以在javax.servlet.jsp.tagext包中找到。 QO3QR/Ww  
g({dD;  
当JSP引擎看到自己的JSP页面中包含有tag标签时,它会调用doStartTag方法来处理tag标签的开头,调用doEndTag方法来处理tag标签的结束。 K2ry@haN  
(\ Gs7  
下表说明不同类型的tag所需要不同的处理过程: 0BQ<a  
?Q/9aqHe;  
Tag处理类的方法 "%)^:('Ki  
v DVE#Nm_  
Tag标签类型 Ks.kn7<l  
所调用的方法 LE@`TPg$R  
QiQO>r  
基本标签 'fIirGOl  
doStartTag, doEndTag, release WHv xBd  
e]u3[ao  
带属性的标签 r^!P=BS{  
doStartTag, doEndTag, set/getAttribute1...N, release ZH=oQV)6  
28d=-s=[  
带内容的标签 aDE)Nf}  
doStartTag, doEndTag, release dS"%( ?o  
ntEf-x<  
带内容的标签,且内容重复循环 UU 2 =W  
doStartTag, doAfterBody, doEndTag, release 5E}~iC&  
a*nx2d  
带内容的标签,且内容与JSP交互 (ZHEPN  
doStartTag, doEndTag, release, doInitBody, doAfterBody, release ?o.Q  
&#qy:  
一个tag处理类可以通过javax.servlet.jsp.PageContext来与JSP交互,通过javax.servlet.jsp.PageContext类,tag处理类可以访问JSP中的request、session和application对像。 ~U_,z)<`)c  
Qh@A7N/L  
如果tag标签是互相嵌套的,那内层的tag处理类可以通过它的parent属性来访问上层的tag处理类。 e X q}0-*f  
kV3Zt@+  
一般情况都将所有的tag处理类打成了JAR的包,以便于发布。 ?#_]Lzn'  
 B!+`km5  
3bPF+(`J  
Tag库描述(简称TLD) $_NP4V8|z/  
.+Fh,bNYK  
[";<YR7iRN  
Tag库是用xml语言描述的,TLD包括了tag库中所有tag标签的描述,它一般用来被jsp服务器用来校验tag的语法正确性,或者被jsp开发者用来开发新的标签。 J;cTEB  
V-%Am  
TLD的文件扩展名必须为.tld,而且必须放在当前WEB应用的WEB-INF目录或其子目录中。 gTwxmp.,  
{h *Pkn1  
一个TLD的内容的开头必须遵守标准的XML开头,用于描述DTD和xml的版本,例如: m@^!?/as  
Jp]eFaqp  
<?xml version="1.0" encoding="ISO-8859-1" ?> 7cMSJM(]G  
PK|"+I0  
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd"> Ae 3:"  
TLD必须以<taglib>来作为它的根元素,<taglib>的子元素如下表: xk$U+8K  
\t 04-  
H}B%OFI\+  
<taglib>的子元素 Ye) F{WqZ#  
B&RgUIrFoY  
Element uQlQ%n%  
Description tN:PWj5  
q(I`g;MF  
tlib-version %{ToWLb{I  
Tag库的版本 C"!k`i=Lj  
dS m; e_s  
jsp-version ULIpb  
Tag库所需要的jsp的版本 Wa+q[E  
V_Oj?MMp n  
short-name >gFEA0-  
助记符,tag的一个别名(可选) =g+Rk+jn  
]EZiPW-uy  
uri MUfhk)"  
用于确定一个唯一的tag库 @>sZ'M2mq  
1O,<JrE+-  
display-name V,qc[*_3  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) CDTM<0`%  
]~1Xx:X-  
small-icon KWH l+p L  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) W6 U**ir.  
[:(^n0%  
large-icon w `0m[*  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) o0'!u  
hbg:}R=B<  
description $D)Ajd;  
对tag库的描述(可选) MF["-GvP/  
oyeJ"E2  
listener p 3*y8g-  
参见下面listener元素 EFNi# D8s  
I?_YL*  
tag 3.?kxac  
参见下面tag 元素 7; e$ sr  
cq,0?2R`t  
Listener元素 c;dMXv   
e=m=IVY #W  
一个tag库可能定义一些类做为它的事件侦听类,这些类在TLD中被称为listener 元素,jsp服务器将会实例化这些侦听类,并且注册它们。Listener元素中有一个叫listener-class的子元素,这个元素的值必须是该侦听类的完整类名。 1$#{om9  
fyE#8h_>4  
Tag元素 +__PT4ps  
^<VJ8jk<  
每个tag元素在tag库中都要指出它的名字、类名、脚本变量、tag的属性。其中脚本变量的值可以直接在TLD中定义或通过tag附加信息的类来取得。每个属性描述了这个属性是否可以省略,它的值是否可以通过<%= …%>这样的JSP语法来获得,以及属性的类型。 [|!A3o  
K7CrRT3>6  
每一个tag在TLD中对应一个tag元素,下表是tag元素的子元素: IDIok~B=e  
M'D l_dx-  
Tag元素的子元素 z[`O YwsW  
-]K9sy)I  
元素名称 FELDz7DYya  
描述 3</gK$f2  
H${5pY_M  
name gL:Vj%c  
独一无二的元素名 Z>si%Npm\  
O<o>/HH$  
tag-class %2jRJ  
Tag标签对应的tag处理类 *lT:P-  
}; ;Thfd  
tei-class A3 |hFk  
javax.servlet.jsp.tagext.TagExtraInfo的子类,用于表达脚本变量(可选) :_f5(N*{5o  
Y3QrD&V  
body-content 2aR<xcSg  
Tag标签body的类型 c?0.>^,B Q  
o'SZ sG  
display-name AYP*J  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) t.`&Q|a  
Q`kJ3b   
small-icon v?=y9lEH@%  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) #oX8EMqs<  
i=^!? i  
large-icon J )DFH~p  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) 74p=uQ  
5SNa~ kC&  
description bk}'wcX<+]  
此tag标签的描述 p9`!.~[  
-E(0}\  
variable Glw_<ag[  
提供脚本变量的信息(同tei-class)(可选) qTuQ]*[-  
p?v.42R:z  
attribute _P{f+HxU  
Tag标签的属性名 'fIoN%  
f~0CpB*X  
以下章节介绍对于不同类型的tag,如何具体地实现它们。 # zbAA<f  
Ap<kK0#h  
O8Dav^\y?  
简单的tag : [r/ Y  
'=X)0GG  
Sr#\5UDS  
tag处理类 [Ep%9(SgA'  
D02(6|  
简单的tag处理类必须实现Tag接口的doStartTag和doEndTag方法。当jsp引擎碰到tag标签的开头时,doStartTag被调用,因为简单的tag没有body,所以此方法将返回 SKIP_BODY。当jsp引擎碰到tag标签的结尾时,doEndTag被调用,如果余下的页面还要被计算,那它将返回EVAL_PAGE,否则将会返回SKIP_PAGE。 G8t9Lx  
!w;oVPNg  
以下是例子:对于标签 <tt:simple /> ,它的tag处理类实现如下: R0A|} Ee*  
psFY=^69o  
}83a^E9L  
public SimpleTag extends TagSupport "-T[D9(A  
G=ly .  
{ (E{}iq@2  
k:QeZn(  
public int doStartTag() throws JspException <9bfX 91  
pRys 5/&v  
{ u$38"&cmA  
{TL.2  
try{ [(rT,31cW  
`]7==c #Y  
pageContext.getOut().print(“Hello.”); 2Pm[ kD4E=  
)4MM>Q  
}catch(Exception e){ u _mtdB'  
bpx ^  
throw new JspTagException(“SimpleTag: “ + e.getMessage()); Db`SNk=  
8=  kwc   
} ?l9j]  
-Is;cbfLj/  
return SKIP_BODY; j"F?^0aR,Q  
R0g^0K.  
} #=g1V?D  
1p5n}|  
public int doEndTag() 1)o6jGQ  
>'1 h  
{ }] p9  
Fc6o6GyL|o  
return EVAL_PAGE; S6CI+W  
-^aJ}[uaI  
} [o"<DP6w  
?:$\ t?e^  
} , UsY0YC  
i$5<>\g  
2z9s$tp  
注意:如果tag标签没有内容的话,那必须定义body-content元素为空,例如 "P9(k>  
PS}'LhZ  
<body-content>empty</body-content> KcvstC`  
l+A)MJd oj  
xfa-   
带属性的tag标签
评价一下你浏览此帖子的感受

精彩

感动

搞笑

开心

愤怒

无聊

灌水
级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
只看该作者 1 发表于: 2007-01-01
tag处理类 oo\7\b#Jx  
V,h}l"  
对于tag标签的每个属性,你必须依照JavaBeans规范来定义其属性,以及get和set方法。以struts的logic:present 标签为例, (^NYC$ZxM=  
\$4 [qG=  
<logic:present parameter=”Clear”> )_YB8jUR-X  
z"97AXu  
与此相应,此tag处理类应有如下方法和定义: n_4 r'w  
7 x'2  
uOO\!Hqq  
protected String parameter = null; DL*vF>v  
#CV]S4/^  
public String getParameter() r~z'QG6v/  
U`aB&[=$  
{ k2@]nW"S  
'u:-~nSX)  
return this.parameter; |A/H*J,  
N; '] &f  
} #;yxn.</  
`*l aUn  
public void setParameter(String parameter) H$+@O-  
<D[0mi0  
{ ]OtnekkK$  
]"&](e6*  
this.parameter = parameter; Mg~4) DW]  
yQ)&u+r  
} rz0)S py6  
B[I9<4}  
[j}JCmWY   
注意:如果你的属性名为id,而且你的tag处理类是从TagSupport类继承的,那你就不需要定义它的属性和set和get方法,因为他们早已在TagSupport被定义过了。 _i_P@I<M|~  
" Lh&s<[  
Attribute元素 Cz)&R^  
<5? pa3  
对于tag标签的每个属性,你必须定义它是否必须的,它的值是否可以用诸如<%= …%>的表达式来获得,以及它的类型(可选),如果不指定它的类型,那就默认为是java.lang.String类型。如果rtexprvalue元素被定义为true或yes,那么在type元素中就定义了attribute的返回类型。 Cyos *  
kO5lLqE  
<attribute> cNbUr  
a%A!Dz S  
<name>attr1</name> GsmXcBzDw2  
&+n9T?+b  
<required>true|false|yes|no</required> P)kJ[Zv>f  
! ,bQ;p3g|  
<rtexprvalue>true|false|yes|no</rtexprvalue> j^7A }fz  
=?c""~7  
<type>attribute的返回类型(只用当rtexprvalue为真是才有效)</type> hrm<!uKn  
a'-u(Bw  
</attribute> d:k n%L6k_  
Wqkzj^;"G  
如果tag的某个属性不是必须的,那tag处理类会自动提供一个缺省值。 Wqkb1~]#Y  
o{6q>Jm  
例如,在logic:present这个tag标签中定义了一个属性叫parameter,但它不是必须的,而且它可以被诸如<%= …%>的表达式来赋值。 |his8\C+x  
B>W8pZu-J  
<tag> 0-uw3U<  
?G5,}%  
<name>present</name> ?!K6")SE  
9b&|'BBW  
<tag-class>org.apache.struts.taglib.logic.PresentTag</tag-class> P}]o$nWT  
9vz\R-un  
<body-content>JSP</body-content> 4-t^?T: qF  
5f{P% x(  
:\vs kk),  
|{&M#qXe  
<attribute> )S 7+y6f&*  
r\d(*q3B  
<name>parameter</name> S3:AitGJ  
zs~Tu  
<required>false</required> lH;V9D^  
A#6zI NK#B  
<rtexprvalue>true</rtexprvalue> LQHL4jRXU  
{O9(<g  
</attribute> 8Z0x*Ssk  
Z2gWa~dBC  
{nbT$3=Zt  
<)p.GAZ  
</tag> Lo~ ;pvv  
1_<x%>zG  
59O-"Sc[  
属性元素的校验 o//h|fU@  
%uN<^`JZ  
]q.%_  
有关于tag标签的有效值可以从tag库的说明文档中获得,当JSP页面被编译时,jsp引擎会强制性地参照TLD中定义的规则进行检查。 d)e mTXB(  
h7 E~I J  
还有一个方法也可以进行属性元素的校验,就是先继承类TagExtraInfo,然后调用它的isValid方法。这个类同时也起到提供tag中定义的脚本变量信息的作用。 g"Y _!)X  
<(q(5jG  
IsValid方法通过TagData对象来传递属性信息,它包括着tag的所有的属性名-值的信息。由于校验发生在运行时刻,因此这个属性的值将被赋值为TagData.REQUEST_TIME_VALUE。  ]'`E  
m/1FVC@*  
例如tag标签<tt:twa attr1=”value1” />在TLD中定义如下: `XhH{*Q"X  
qx'0(q2Ii(  
<attribute> c7jmzo  
>;^/B R=  
<name>attr1</name> (Kwqa"Hk4{  
~g\~x  
<required>true</required> aknIrblS\  
&yvvea]  
<rtexprvalue>true</rtexprvalue> F)(^c  
H; NV?CD  
</attribute> iCPm7AU  
bDM},(  
R>* z8n  
这个定义说明了attr1能在运行期间被赋值。 *^uK=CH1?(  
%(1O jfZc  
以下的isValid方法检查attr1属性的值是否属于Boolean类型。注意由于attr1能在运行刻被赋值,那么isValid方法必须检查tag用户是否对此tag进行了运行时刻赋值。 W48RZghmx  
RkE)2q[5  
*3H=t$1G}  
Public class TwaTEI extends TagExtraInfo _Xt/U>N  
g#=<;X2  
{ >I|8yqbfm  
st;iGg  
public boolean isValid(Tagdata data) b2OwLt9  
b)<WC$"  
{ SHX`/  
~=*o  
Object o = data.getAttribute(“attr1”); 3uocAmY  
z.Ic?Wz7  
If(o != null && o != TagData.REQUEST_TIME_VALUE) bGCC?}\  
==OUd6e}  
{ /)6T>/  
&t[[4+Qt  
if( ( (String)o).toLowerCase().equals(“true”) || `9co7[Z  
WM'!|lg  
((String)o).toLowerCase().equals(“false”) ) d ItfR'$  
orFwy!  
return true; &KjMw:l  
#NW+t|E  
else Jt=- >  
`qc"JB  
return false; ~t)cbF(UO  
]>1Mq,!  
} +6#$6hG  
)&@YRT\c?8  
else rx2)uUbR  
 y:RW:D&  
return true; F qH))2  
ENuL!H>;*  
} C2}y#AI  
2y - QH  
} &VGV0K3 Dp  
uu.X>agg  
'4 *0Pw  
带body的tag <= o<lRU  
dd  
V: D;?$Jl  
tag处理类 "V' r}>  
&DWSf`:Hx  
+]eG=. u  
如果tag标签含有内容,那处理方式会略微有些不同,而且还要视tag处理类是否要与body交互的情况而定。如果要与body交互,那我们认为tag处理类要可能要对body进行操作。 M-nRhso  
i1cd9  
Tag处理类不与body交互 0vqVE]C  
J\y^T3Z  
如果tag处理类不与body交互,tag处理类应该实现Tag接口或从TagSupport中派生,如果body要被计算,那么doStartTag方法应返回 EVAL_BODY_INCLUDE,否则应返回SKIP_BODY。 @Chl>s  
p AOKy  
如果tag处理类要对body反复运算,则它应该实现IterationTag或从TagSupport中派生。如果tag处理类认为body还未计算完的话,那它的doStartTag方法和doAfterBody方法必须返回EVAL_BODY_AGAIN。 YB"gLv?  
TcaW'&(K  
Tag处理类与body交互 V vrsf6l]  
.dU91> ~Ov  
如果tag处理类与body交互,那tag处理类应实现BodyTag接口或从BodyTagSupport中派生。这种tag处理类一般要实现doInitBody和doAfterBody方法。 UjI./"]O  
b*n3Fej  
Body允许一些方法来读写它的内容。Tag处理类可以调用body内容的getString或getReader方法来从body中提取信息,也可用 writeOut(out) 方法来将body的内容写入到out对象中。其中out对象通过tag处理类的getPreviousOut方法来获得。 p< 7rF_?W0  
4Hz3 KKu  
如果body的内容需要被计算,那么doStartTag方法必须返回EVAL_BODY_BUFFERED,否则,它将返回 SKIP_BODY。 4 neZw'm  
C}h(WOcr`X  
doInitBody 方法 ` IVQ  
z}[ u~P,  
此方法在body内容已经设好,但未被计算之前被调用。你可以根据不同的body内容来制定初始化策略。 <  o?ua}  
juR>4SH  
doAfterBody方法 uppa`addK  
HPt3WBRzS;  
此方法在body内容已被计算后进行调用。 z\m$>C|  
U4"^NLAq  
和doStartTag方法一样,doAfterBody方法返回一个指示符指示是否要继续计算body,如果要继续计算,则doAfterBody应返回EVAL_BODY_BUFFERED,否则,它应返回SKIP_BODY。 |8'}mjs.Q  
L<!h3n  
release 方法 b-_l&;NWg  
*:CTIV5N0  
tag处理类调用此方法将它的状态重置为初始状态,并释放所有的私有资源。 @@D/&}#F  
ww{k_'RRJ  
z:-{Y2F  
以下的例子读取body的内容(其中含有一条sql语句),然后将它传递给一个对象,让它进行查询。由于此处body不须重新计算,所以doAfterBody会返回SKIP_BODY。 GJB+] b-  
u&l;\w  
`,V&@}&"n  
Public class QueryTag extends BodyTagSupport }ppApJT  
! v![K  
{ b$'%)\('g  
5;XC!Gz  
public int doAfterBody() throws JspTagException %$&eC  
?ES{t4"  
{ >V^8<^?G  
R|RGoGE6g  
BodyContent bc = getBodyContent(); MGF !ZZ\  
JPDxzp  
//将body的内容以字符串的格式提取出来 lf( +]k30  
wrkw,H  
String query = bc.getString(); P'Y(f!%  
u0wu\  
//清除body j EbmW*   
1|p\rHGd  
bc.clearBody(); <sC(a7i1  
JY c:@\   
try{ < dE7+w  
 c k;:84  
Statement stmt = connection.createStatement(); 1O Ft}>1  
lz`\Q6rZ  
Result result = stmt.executeQuery(query); RhJ3>DL  
,O:4[M!$w  
}catch(SQLException e){ ()|e xWW  
aUMiRm-   
throw new JspTagException(“queryTag: “ + e.getMessage() ); 1Lf -  
y;ey(  
return SKIP_BODY; c\. )vH  
F7}yt  
} 7oE:]  
j/Kul}Ml\*  
} #sU>L=  
w?D=  
A@3'I  ;  
body-content元素 'cCM[P+  
ar@,SKU'K  
~[!Tpq5  
由于tag可能会有body,你必须用body-content元素来指定body内容的类型: MTwzL<@$  
b|87=1^m[  
<body-content>JSP|tagdependent</body-content> 9+(b7L   
%{ U (y#  
@^0}wk  
如果body的内容是定制的或内部的tag、脚本元素、或HTML广本,则归类为JSP类型。其他的类型,比如上面代码所述的?D?D将sql statement类传给 query tag的这种类型应该标为tagdependent。 !v3d:n\W8  
&v]xYb)+<  
注意:实际上body-content的值并不影响tag处理类对body内容的处理,它仅仅是被tag编辑工具用来描述此body的内容。 6<z#*`U1  
p_xJ KQS  
/\fR6|tJ  
用tags定义脚本变量 sB0]lj-[Un  
fbI5!i#lz  
iw.F8[})  
tag处理类 "U9e)a0v  
~e|E5[-i  
<YCjo[(~  
tag处理类负责创建或设置页面中定义的脚本变量,用pageContext.setAttribute(name,value,scope)或pageContext.setAttribute(name,value)方法来实现。一般来说,tag处理类通过脚本变量的名称来获取它,脚本变量的名称一般可用get方法来获得。 GB+$ed5@<  
7IUJHc?  
如果脚本变量的值依赖于tag处理类中的上下文中某一对象,那它可用pageContext.getAttribute(name,scope)方法来找到那个对象。一般的处理过程是tag处理类先找到脚本变量,再对其进行处理,然后用pageContext.setAttribute(name,object)的方法来设置它的新值。 g1XpERsSEV  
JSFNn]z2P  
对象的生存周期(scope)如下表: Zq{gp1WC  
~&,S xQT  
对象的生存周期表 m!INbIh  
h9d*N9!;M  
名字 Urw =a$  
可访问范围 #+i5'p(4  
生存周期 MNh:NFCRA  
{%2p(5FB  
page 5bZ0}^FYF  
当前页面 7yG%E  
一直有效,除非页面向客户提交响应或重定向到一个新页面 rXSw@pqZ&  
hB 'rkjt  
request k'v+/6 Y  
当前页面或当前页面重定向到的页面 mb'{@  
一直有效,除非页面向客户提交响应 ^!m%:r7Dr  
l(MjLXw5  
session pl}W|kW}  
当前页面或在同一浏览器窗口中的页面 Cf 202pF3y  
一直有效,除非关闭当前浏览器、超时、网络故障 0}Kyj"-3  
Nt tu)wr  
application shLMj)7!  
整个web应用程序的所有请求 1< b~="  
一直有效,除非发生网络故障、服务器故障 mJ8EiRSE  
HII@Ed f?  
提供关于脚本变量的信息 uEsF 8  
6Po {tKU  
以下示例定义了一个名为“book”的脚本变量,用来访问程序中关于书的信息: g6gwNC:aF  
KfK5e{yT  
<bean:define id=”book” name=”bookDB” property=”bookDetails” type=”database.BookDetails” /> 0{!-h  
/`qQWB5b  
<font color=”red” size=”+2” > ;Gu(Yoa}y  
"MPS&OK  
<%= messages.getString(“CartRemoved”) %> n1x3q/~  
_Kli~$c& M  
<strong><jsp:getProperty name=”book” property=”title” /></strong> >TGc0 z+  
)eX{a/Be  
</font> xxgdp. (  
y`z?lmV)xM  
当包含此tag的JSP页面被编译时,jsp引擎会自动生成关于此book的同步的代码(同步可以避免几个客户同时访问此book时造成的冲突),要生成同步代码,jsp引擎需要知道此脚本变量的如下信息: X~*/ ~f  
iDCQqj`  
· 脚本变量名称 zGL.+@  
m8l!+8  
· 脚本变量所属的类 Tv,ZS   
3#uc+$[  
· 此脚本变量是否引用了一个新的或已存在的对象 J6 A3Hrg  
y2B'0l  
· 此脚本变量的有效性 s=R^2;^  
OSJL,F,  
有两种办法可以向jsp引擎提供关于脚本变量的信息:在TLD中定义variable子元素,或用tei-class子元素定义一个额外tag信息类。用variable最简单,但可能降低了一些灵活性。 Cpn!}!Gnf  
oB<!U%BN  
Variable元素 qus%?B{b}  
ubKp P%Z  
Variable元素有如下子元素: 'v(b^x<ZS  
wgQx.8 h>  
· name-given ?D?D 给出的名字,是一个常量 :VR% I;g;  
f]Zj"Tt-  
· name-from-attribute?D?D 属性名,在编译时给出的属性名 Yru,YA   
*aYuuRx  
name-given或name-from-attribute两者必须选一,但以下子元素是可选的: ey:%Zy [~  
##" Hui  
· variable-class?D?D变量的类型,缺省为java.lang.String。 h5n@SE>G  
8NWuhRRrw  
· declare?D?D此脚本变量是否引用了一个新对象,缺省为True。 I,/E.cRV<  
y :QnK0  
· scope?D?D脚本变量的范围,缺省为NESTED。下表描述了scope的几种类型: b$/7rVH!  
y?iW^>|?L=  
脚本变量的有效范围 !@h)3f]`1G  
MbQ%'z6D  
WQ{^+C9g'1  
有效性 {(d 6of`C_  
方法 #A~7rH%hi  
5sB~.z@  
NESTED nx!+: P ,  
在tag标签的开始和结束之间 T#}"?A|  
如果tag处理类实现BodyTag接口,则在doInitBody和doAfterBody中调用,否则在doStartTag中调用 H@|m^1  
Kciz^)'Z  
AT_BEGIN IR8qFWDZ  
从tag标签的开始一直到页面结束 $GD Q1&Z  
如果tag处理类实现BodyTag接口,则在doInitBody、doAfterBody和doEndTag中调用,否则在doStartTag和doEndTag中调用 us U6,  
S""F58 H n  
AT_END bhKe"#m|S  
从tag标签的结束一直到页面结束 wEl/s P  
在doEndTag中调用 B?d+^sz]  
( _MY;S  
以struts为例,它的bean:define标签的实现遵循JSP1.1规范,此规范要求使用额外tag信息类来定义脚本变量。Variable元素是JSP1.2规范中加入的。以bean:define标签为例,你可以定义如下variable元素: ]0")iY_  
EO/TuKt  
<tag> ,H/BW`rL]#  
N.V5>2  
<variable> $%1oZ{&M  
F~GIfJU  
<name-from-attribute>id</name-from-attribute> Xk:_aJ  
a!&<jM  
<variable-class>database.BookDetails</variable-class> 0|mC k  
BtF7P}:MGf  
<declare>true</declare> `nd$6i^#W  
s+0S,?{$  
<scope>AT_BEGIN</scope> "Qk)EY  
j 9f QV  
</variable> WXa<(\S\V  
;YrmT9Jx6  
</tag> !3ji]q;uF  
c`UizZ  
额外tag信息类 =_$Hn>vO  
4@jX{{^6%  
如果要定义一个额外tag信息类,你要继承javax.servlet.jsp.TagExtraInfo类。一个TagExtraInfo类必须实现getVariableInfo方法,此方法返回一个叫VariableInfo的数组类,它包括如下信息: 5"L.C32  
cZ ,}1?!  
· 变量名 rL/H{.@$`  
`Js"*[z  
· 变量所属类名 1Uc/ r>u9  
C)&BtiUN/  
· 此变量是否引用了一个新对象 =]LAL w  
eB<R"Yvi  
· 此变量的有效范围 EuKkIr/(  
=BO>Bi&&  
jsp引擎将一个名为data的参数传给getVariableInfo方法,data中包括tag标签中的所有“属性名?D?D属性值”对。它可以用来向VariableInfo对象提供脚本变量的名字和类名。 C:vVFU|4  
|cl*wFm|3  
以struts为例,它在bean:define标签中定义了一个名为DefineTei的额外tag信息类,用来向脚本变量提供信息。由于脚本变量的名称(book)和类名(database.BookDetails)是通过tag标签的属性来传递的,它们一般定义在VariableInfo的构建代码中,并且可用data.getAttributeString方法来得到这些信息。如果要允许book脚本变量能在从tag开始直到整个JSP页面结束的范围内都可用的话,那它的范围应设为AT_BEGIN。如下所示: /b."d\  
U ?6.UtNf  
'On%p|s)H  
public class DefineTei extends TagExtraInfo K#x|/b'5d  
WS\Ir-B  
{ S3y(' PeF  
o}Q3mCB  
public VariableInfo[] getVariableInfo(TagData data) *dx E (dP  
6&"GTK  
{ {Ok]$0L  
-=2V4WU~  
String type = data.getAttributeString(“type”); -T>i5'2)  
+DYsBCVbag  
If( type == null) 8)YDUE%VH  
E g_ram`\R  
type = “java.lang.Object”; iE^=Vf;  
O0sLcuT$  
return new VariableInfo[] { vSwRj<|CF  
(~?p`g+I.P  
new VariableInfo(data.getAttributeString(“id”), "6i3'jc`  
OgCz[QXr_  
type, (J.k\d   
x-~=@oiv  
true, Am"&ApK  
8-x)8B  
VariableInfo.AT_BEGIN) B|r'  
-7VQ {nC  
}; 2CV?cm  
yg82a7D  
} 4i+H(d n  
jaQH1^~l/-  
} 1;~| [C  
9D7i>e%,;-  
!9_'_8  
注意:关于额外tag信息类的类名必须要在TLD中的tag标签下的tei-class子元素中定义。因此,DefineTei的tei-class中的定义看起来如下: ,k}(]{ -  
<tei-class> R#W=*cN  
org.apache.struts.taglib.bean.DefineTagTei G|z%T`!U1;  
</tei-class> #@P0i^pFTB  
f8)fm2^09  
BR:Mcc  
具有协作关系的tag eaDG7+iS  
D=}\]Krmay  
#j)"#1IE2W  
tag通过共享对象来进行协作,JSP技术支持2种方式的对象共享。 BCh|^Pk  
">vi=Tr  
第一种方法是使用pageContext对象进行对象的共享(可支持JSP页面和tag处理类之间的共享),如果在一个tag处理类中要调用由另一个tag处理类创建的对象,可调用pageContext.getAttribute(name, scope)方法。 # GzowI'  
OU<v9`<  
第二各方式的共享是对于tag之间有嵌套关系而言的,外层的tag所创建的对象对于内层的tag来说是可以共用的。这种形式的共享的好处是减少了可能存在的重名冲突。 H`rd bE  
(btm g<WT"  
要访问一个嵌套tag创建的对象,tag处理类必须先找到此嵌套tag对象,可用TagSupport的静态方法 TagSupport.findAncestorWithClass(from, class)或TagSupport.getParent方法。前者在当不确定此tag是否为嵌套tag对象时使用。一旦它的父类被找到,它就能访问其所有动态或静态创建的对象。静态创建的对象是父类的成员,而动态创建的对象可能是父类的私有对象。诸如此类的对象可以用tag处理类的setValue方法来保存,用getValue方法来获得。 EKEJ9Y+47H  
wv ^n#  
下例阐述了以上两种共享对象的方法。在这个例子当中,一个查询tag检查一个名为connection的属性名是否在doStartTag中被设置。如果connection属性被设置,tag处理类从pageContext中得到这个connection对象。否则,此tag处理类先找到它的父tag处理类,然后从它的父tag处理类中找到connection对象。 wJh/tb=$o  
tN z(s)  
P[tYu:  
public class QueryTag extends BodyTagSupport TrBW0Bn>p  
U|x#'jGo'  
{ E[<*Al +N  
l_Zx'm  
private String connectionId; ^ U~QQ  
XJ7pX1nf  
public int doStartTag() throws JspException "6Z(0 iu:{  
/ |isRh|  
{ \J(kM,ZJ  
9T0g%&  
String cid = getConnection(); -\2hSIXj  
$dG:29w  
if(cid != null) J|`.d46  
ygQe'S{!S\  
{ pj7v{H+  
1:J+`mzpl  
//存在一个connection id,使用它。 IL`=r6\  
t8`wO+4@  
connection = (Connection) pageContext.getAttribute(cid); A# Y:VavQ?  
ilAhw4A  
} ',/2J0_  
U>DCra;  
else uF<?y0t  
~0@fK<C)O  
{ A WJA?  
QQv%>=_`  
ConnectionTag ancestorTag = (ConnectionTag)findAncestorWithClass(this, <T&v\DN  
'.&Y)A6!  
ConnectionTag.class); D}Sww5ZmP  
/Q_ Dd  
if(ancestorTag == null) <. *bJ  
l>KkAA  
{ lc3Gu78 A/  
M=3gV?N  
throw new JspTagException(“一个没有connection属性的查询标签必须被一个connection标记嵌套。”); m=SI *V  
"lSh 4X  
} bc3`x1)\^  
Ej1 <T,w_  
connection = ancestorTag.getConnection(); dFy GI?  
[bRE=Zr$Ry  
} Sa kew  
CP0'pL=;  
} u1=K#5^  
7*"Jx}eM  
} 5JHEBw5W%  
y G3aF(  
B{*{9!(l9  
Gr#3GvL  
此查询标签在JSP页面中的调用形式可以从以下2种定义中任选一种: u@CQ+pnf:(  
W/AF  
eW;3koE  
<tt:connection id=”con01” ...> ... </tt:connection> 2_y]MXG+%  
"c|Rpzs[  
<tt:query id=”balances” connection=”con01” > [c;#>UQMf  
is~2{:  
SELECT account, balance FROM acct_table w ?*eBLJ(G  
YV!hlYOBi  
where customer_num = <%= request.getCustno() %> 2;0eW&e   
N$x&k$w R  
</tt:query> kw E2V+2  
Ih>s2nL  
)Yv=:+f  
|0Xf":  
AI`k }sA~  
<tt:connection ...> &{UqGD#1&  
r$8'1s37`  
<x:query id=”balances”> P=_fYA3  
/KNDo^P  
SELECT account, balance FROM acct_table ;S '?l0  
}}i'8  
where customer_num = <%= request.getCustno() %> {M5t)-  
 *} ?  
</x:query> n,2   
=^i K^)  
</tt:connection> mEsb_3?#+  
D:f=Z?L)>  
Od)y4nr3~  
与此同时,在TLD中必须指定connection属性为可选的,定义如下: gdA2u;q  
=/`]lY&  
<tag> oeB'{bG  
Fxc_s/^=t  
... O^j*"#f  
&K{8- t  
<attribute> ');vc~C  
rQyjNh  
<name>connection</name> N9-7YQ`D  
m|F1_Ggz  
<required>false</required> ^6z"@+;*  
=$fz</S=J  
</attribute> KmTFJ,iM  
w"wW0uE^  
</tag>
描述
快速回复

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