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

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

级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
标准的JSP 标记可以调用JavaBeans组件或者执行客户的请求,这大大降低了JSP开发的复杂度和维护量。JSP技术也允许你自定义taglib,其实换句话说,taglib可以看成是对JSP标记的一种扩展,正如xml是对html的一种扩展一样。taglib通常定义在tag标签库中,这种标签库存放着你自己定义的tag标签。简而言之,如果使用taglib,那么你可以设计自己的JSP标记! `mTxtuid{  
RWcQT`  
一般来说,自定义tag标签主要用于操作隐藏对象、处理html提交表单、访问数据库或其它企业级的服务,诸如邮件和目录操作等等。自定义tag标签的使用者一般都是那些对java编程语言非常精通,而且对数据访问和企业级服务访问都非常熟悉的程序员,对于HTML设计者来说,使得他可以不去关注那些较复杂的商业逻辑,而将精力放在网页设计上。同时,它也将库开发者和库使用者进行合理分工,自定义tag标签将那些重复工作进行封装,从而大大提高了生产力,而且可以使得tag库可用于不同的项目中,完美地体现了软件复用的思想。 R*#Q=_  
;//q jo  
在这篇文章中,我们主要讨论: )L("t  
HCy}'}d  
· 什么是自定义tag标签? )cBV; E<  
0|vWwZq  
· 怎么使用tag标签? 3YF]o9  
~?+m=\  
o 声明要使用的tag库 ~i#xjD5  
l:/V%{sx  
o 找到与之对应的tag处理类 )%c)-c  
=qQQ^`^F'~  
o tag标签的类型 `g1~ya(MC  
>~InO^R`5  
· 自定义tag标签 f TtMmz  
p{PYUW"?^  
o tag处理类 4 V*)0?oYE  
Vs(Zs[  
o tag库描述 na; ^/_U@  
:m)?+  
o tag标签示例 /Loe y   
NistW+{<  
o 带属性的tag OyZ>R~c'B  
dAt[i \S  
o 带body的tag _( Cp   
oIgj)AY<  
o 定义了脚本变量的tag j"=jK^  
jd'R2e  
o 具有协作关系的tag bv];Gk*Z-  
>p:fWQ6  
· 自定义tag标签 h"S/D[  
.H.v c_/  
o 一个迭代tag的例子 ^: j:;\;  
<p .[E]a2_  
o 一个模板tag库 g5\B-3{  
\H12~=p`B  
o tag处理类到底是怎样被调用的?  e n":  
Lj,%pzJ  
@SB+u+mOS  
什么是自定义的tag? r\`m[Q  
s``L?9  
一个自定义的tag标签是用户定义的一种JSP标记。当一个含有自定义的tag标签的JSP页面被jsp引擎编译成servlet时,tag标签被转化成了对一个称为tag处理类的对象进行的操作。于是当JSP页面被jsp引擎转化为servlet后,实际上tag标签被转化成为了对tag处理类的操作。 oI/ThM`=q  
i*>yUav"  
自定义tag标签有很多特色,诸如: cv1L!Ce,  
go5!zSs  
· 可以在JSP页面中自定义tag标签的属性 J z b".A  
>f/g:[  
· 访问JSP页面中的所有对象 t$|6} BX  
w!M ^p&T7  
· 可以动态地修改页面输出 4(IP  
C"WZsF^3  
· 彼此这间可以相互通信。你可以先创建一个JavaBeans组件,然后在一个tag中调用此JavaBeans组件,同时可以在另一个tag中调用它。 (#`o >G(  
YT8`Vz$+  
· tag允许相互嵌套,可以在一个JSP页面中完成一些复杂的交互。 8A_(]Q  
n\Nl2u& m  
/Qy0vAvJ  
使用tag标签 np(<Ap r  
$ 7!GA9Bn  
5}ah%  
本节主要描述怎样在JSP页面中使用tag标签,以及tag标签的不同类型。 Dh<e9s:  
T]`" Xl8  
要使用tag标签,JSP程序员必须做2件事: SO"P3X  
1)ne-e  
· 声明此tag标签的tag库 #Xly5J  
iDJ2dM}v  
· 实现此tag标签 u> Hx#R<*%  
X=~QE}x  
声明tag标签所在的tag库 #n r1- sf|  
M$9h)3(B  
如果要使用tag标签,则应用JSP的taglib指示符来指定其tag库(注意:taglib要在在使用此tag标签之前声明) y0]O 6.{  
sqRuqUj+  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> G= e[TR)i  
:8 :>CHa  
uri属性定义了唯一的标签库描述(以下简称TLD),它可以是直接是tld文件名或一个独一无二的名字。prefix是用来区别其它TLD中和本TLD中有重名的tag的一种手段。 Nx'j+>bz>y  
K6oLSr+EAK  
TLD必须以.tld作为扩展名,并且存放在当前应用的WEB-INF目录或其子目录下。你可以通过它的文件名直接引用它,也可以通过别的方式间接地引用它。 Hy'&x?F6  
]ghPbS@  
以下taglib指示符直接引用一个TLD: ^lj>v}4fkW  
~ .-'pdz%  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> 0jH2. d=  
gw:BKR'o  
以下的taglib指示符通过一个逻辑名称间接地引用一个TLD: ?=&*6H_v  
=j-{Mxb3  
<%@ taglib uri=”/tutorial-template” prefix=”tt” %> C/G[B?:h  
"H8N,eb2  
如果是间接引用TLD的话,那你必须还要在web.xml中定义此逻辑名称与tld文件之间的映射,具体做法是在web.xml中加入一个名为taglib的元素: J .d<5`7   
{rQ`#?J}^?  
<taglib> ML-g"wv  
TuL( /  
<taglib-uri>/tutorial-template</taglib-uri> W#7c`nm  
,@xZuq+K<  
<taglib-location> ;C'*Ui  
+,,~ <Vm  
/WEB-INF/tutorial-template.tld bql6Z1l  
"^`AS"z'  
</taglib-location> 62) F  
v80 e]M!  
</taglib> he@swE&  
3V]a "C   
|>)mYLN!y  
实现此tag标签 gC.T5,tn  
qI9 BAs1~}  
lKcnM3n  
为了实现tag标签,你有2种方法来存放tag处理类。一、让tag处理类以.class的方式存放于当前应用的WEB-INF/class子目录下,二、如果tag处理类是以JAR包的形式存在的话,那可以放在当前应用的WEB-INF/lib目录下,如果tag处理类要在多个应用中共享,那么它就应放在jsp服务器上的common/lib目录下,对于tomcat来说,就是tomcat/common/lib目录下。 6*tGf`Pfdw  
*RhdoD|a  
.E(Ucnz/  
tag标签类型 q=U=Y n  
hE${eJQ| U  
fqxMTTg@  
自定义的tag标签遵循XML语法。它有一个开始标记和一个结束标记,有的还有body(即文本节点): ryP z q}#  
p{Uro!J,K  
<tt:tag> XQ>m8K?\d  
utv.uwfat  
body %?ad.F+7  
-VL3em|0  
</tt:tag> Jh1fM`kB5K  
#\qES7We 6  
MeC@+@C  
一个不带body的tag标签如下: ~7|z2L  
^<c?Ire  
<tt:tag /> K2JS2Y]  
H|]Q;,C  
>K3Lww)Ln  
简单的tag标签 ?]S*=6  
"Z <1Msz  
一个没有body和属性的tag标签如下: V0>,Kxk  
> ewcD{bt  
<tt:simple /> ? T9-FGW  
p)`JVq,H/B  
@xo9'M<l  
带属性的tag标签 7y!{lr=n  
Ad(j&P  
idHBz*3~ps  
自定义标签可以有自己的属性。属性一般在开始标记中定义,语法为 attr=”value”。属性的作用相当于自定义标签的一个参数,它影响着tag处理类的行为。你可以在TLD中详细定义它。 YRFM1?*  
Dcq^C LPY  
你可以用一个String常量给一个属性赋值,也可以通过表达式给它赋值,如<%= ...%>。以struts为例,它的logic:present标签就是用的String常量来给属性赋值: 9#+X?|p+0  
pnWDsC~)  
<loglic:present parameter = “Clear”> ~O!v?2it8q  
0[^f9NZ>-  
而另一个标签logic:iterate是用表达式来给属性赋值: YC{od5a  
] '..G-  
<logci:iterate collection=”<%= bookDB.getBooks() %>” umY4tNe]$  
o}BaZ|iZ2  
id=”book” type=”database.BookDetails”> OvkYzI`  
yfj<P/aA+  
u7K0m! jW  
带body的tag标签 1:?Wv DN=  
ebf0;1!  
一个自定义标签可以包含其它自定义标签、脚本变量、HTML标记或其它内容。 qbjRw!2?w  
o4xZaF4+  
在下述例子中,此JSP页面使用了struts的logic:present标签,如果些标签定义了parameter=”Clear”的属性,则将清除购物车的内容,然后打印出一条信息: ral0@\T  
>Gkkr{s9  
<logic:present parameter=”Clear”> =Z2sQQVS  
tq{ aa  
<% cart.clear(); %> rc"yEI-``"  
qSON3Iid  
<font color=”#ff0000” size=”+2”><strong> ^vUdf.n9  
9!tRM-  
你选择了清除购物车! ."${.BPn~  
>354O6  
</strong></font> ZDlMkHJ  
g94NU X  
</logic:present> Y`%:hvy~  
L49`=p<  
}JS?42CTaV  
到底是用属性还是用body来传递信息? xRb-m$B}L  
E=7~\7TE  
如上所述,我们既可以通过属性,也可以通过body来传递信息。但一般来说,比较简单的类型,如字符串或简单表达式最好采用属性来传递信息。 J^U#dYd  
US-P>yF  
pl5!Ih6  
定义脚本变量的tag标签 M*nfWQ a  
dI3U*:$X  
所谓脚本变量,是指JSP中可以调用的变量或对象。它可由tag标签产生。以下示例阐述了一个tag标签定义了一个名为tx的由JNDI所定义的事务处理对象。脚本变量可以是ejb对象、事务、数据库连接等等: dLLF#N  
)!'SSVaRs  
<tt:lookup id=”tx” type=”UserTransaction” name=”java:comp/UserTransaction” /> @X:P`?("^  
IL\#!|>  
<% tx.begin(); %> {JMFCc[  
zUeS7\(l  
... Rh iiQ  
wT;D<rqe`  
!RV}dhI  
具有协作关系的tag标签 P7Kp*He)  
Eg>MG87  
自定义tag标签之间可以通过共享对象来实现协作。在下述例子中,标签tag1创建了一个名为obj1的对象,在标签tag2仍可以重复使用obj。 _jp8;M~Z  
F9N)UW:w  
<tt:tag1 attr1=”obj1” value1=”value” /> M%Ov6u<I8  
tT'+3  
<tt:tag2 attr1=”obj1” /> aB.`'d)V  
7cH[}v`pn  
在以下这个例子当中,如果外层的tag标签创建了一个对象,那么其内层的所有tag标签都可以使用这个对象。由于这样产生的对象没有一个指定的名字,那么就可以将少重名的冲突。这个例子阐述了一系列协作的嵌套对象。 %c):^;6p  
]*?qaIdqu  
<tt:outerTag> |:C=j/f   
!ce:S!P  
<tt:innerTag /> 1qtu,yIf  
in$Pk$ c  
</tt:outerTag> X2~>Z^, U  
*:wu{3g}M`  
0Db#W6*^  
Tag处理类 zgV{S Qo  
Drz#D1-2  
Z':}ZXy]  
Tag处理类必须实现Tag接口或BodyTag接口,不过现在一般都流行从TagSupport或BodyTagSupport类中继承,这些类或接口都可以在javax.servlet.jsp.tagext包中找到。 !ce5pA  
a8''t_Dp  
当JSP引擎看到自己的JSP页面中包含有tag标签时,它会调用doStartTag方法来处理tag标签的开头,调用doEndTag方法来处理tag标签的结束。 vk&C'&uV9@  
IZ "d s=w  
下表说明不同类型的tag所需要不同的处理过程: Z8Qmj5'[  
Ry8@U9B6,t  
Tag处理类的方法 l:%4@t`  
4$C:r&K  
Tag标签类型 __OD^?qa  
所调用的方法 WOiw 0  
1jpcoJ@s  
基本标签 lUbQ@7a<'  
doStartTag, doEndTag, release a~=$9+?w  
4 @ )|N'  
带属性的标签 4gzrxV  
doStartTag, doEndTag, set/getAttribute1...N, release j'g':U  
> -OQk"o  
带内容的标签 YLk/16r  
doStartTag, doEndTag, release $ba3dqbCW  
1jO}{U  
带内容的标签,且内容重复循环 pbt/i+!  
doStartTag, doAfterBody, doEndTag, release L'M'I0"/  
$5Jo %K%  
带内容的标签,且内容与JSP交互 L> > %  
doStartTag, doEndTag, release, doInitBody, doAfterBody, release >8\EdN59{  
uDbz`VpK  
一个tag处理类可以通过javax.servlet.jsp.PageContext来与JSP交互,通过javax.servlet.jsp.PageContext类,tag处理类可以访问JSP中的request、session和application对像。 9v=5x[fE  
hKj"Lb9 ]  
如果tag标签是互相嵌套的,那内层的tag处理类可以通过它的parent属性来访问上层的tag处理类。 Tapj7/0`  
%3!DRz  
一般情况都将所有的tag处理类打成了JAR的包,以便于发布。 g4^=Q'j-  
4*&_h g)h  
'#L.w6<B  
Tag库描述(简称TLD) \L Gj]mb1  
V*U{q%p(  
Ey4%N`H-^  
Tag库是用xml语言描述的,TLD包括了tag库中所有tag标签的描述,它一般用来被jsp服务器用来校验tag的语法正确性,或者被jsp开发者用来开发新的标签。 bVaydJ*  
x8|sdZFxo  
TLD的文件扩展名必须为.tld,而且必须放在当前WEB应用的WEB-INF目录或其子目录中。 `KgIr,Q)  
HG{r\jh  
一个TLD的内容的开头必须遵守标准的XML开头,用于描述DTD和xml的版本,例如: W{B)c?G]  
~ (I'm[  
<?xml version="1.0" encoding="ISO-8859-1" ?> 2|8e7q:+*  
Hx5t![g2K!  
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd"> ckG`^<  
TLD必须以<taglib>来作为它的根元素,<taglib>的子元素如下表: }}y~\TB~}  
vau0Jn%=ck  
z)*7LI  
<taglib>的子元素 >VIb|YA  
XR3=Y0YDf  
Element kqdF)Wa am  
Description kwF4I )6  
1 w*DU9f  
tlib-version U51C /A  
Tag库的版本 Q4i@y6z  
;w--fqxVl  
jsp-version ancs  
Tag库所需要的jsp的版本 m_ >+$uL  
HY|=Z\l"  
short-name ?Zu2=<DU  
助记符,tag的一个别名(可选) :!Ea.v  
5'*v-l,[  
uri 4'9yMXR  
用于确定一个唯一的tag库 K)=<hL  
M*6}#ST  
display-name ;iEr+  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) U (*k:Fw  
kB:6e7D|[  
small-icon 6d4)7PL  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) !} ~K'1"  
[ed6n@/O@  
large-icon %+0 7>/  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) 9 8O0M#|d  
vG;)(.:  
description *>"k/XUn$  
对tag库的描述(可选) a8$gXX-2  
R{N9'2l:  
listener w=Cq v~  
参见下面listener元素 `q":i>FP2  
C5k\RS9  
tag 1VRe xp  
参见下面tag 元素 />FgDIO  
Bg3`w__l;  
Listener元素 ,j^z];  
<B"M} Y>_P  
一个tag库可能定义一些类做为它的事件侦听类,这些类在TLD中被称为listener 元素,jsp服务器将会实例化这些侦听类,并且注册它们。Listener元素中有一个叫listener-class的子元素,这个元素的值必须是该侦听类的完整类名。 N3O~_=/v?  
UM[<v9NWE  
Tag元素 0{0BL@H  
^6c=[N$aW  
每个tag元素在tag库中都要指出它的名字、类名、脚本变量、tag的属性。其中脚本变量的值可以直接在TLD中定义或通过tag附加信息的类来取得。每个属性描述了这个属性是否可以省略,它的值是否可以通过<%= …%>这样的JSP语法来获得,以及属性的类型。 Pi7IBz  
bvpP/LeY  
每一个tag在TLD中对应一个tag元素,下表是tag元素的子元素: c:>&iB-Yu  
ZoFQJJK56B  
Tag元素的子元素 xweV8k/  
N i\*<:_  
元素名称 3"9'MDKH  
描述 B}Lz#'5_  
p:g`K# [F  
name $;@L PE  
独一无二的元素名 +T\c<lJ9  
B{`4"uEb$G  
tag-class %#g9d  
Tag标签对应的tag处理类 t>]wWYy  
~_|OGp_a  
tei-class ;ndsq[k>  
javax.servlet.jsp.tagext.TagExtraInfo的子类,用于表达脚本变量(可选) <Vu/6"DP  
{Ftz4y)6  
body-content  +=Xgi$  
Tag标签body的类型 02|f@bP.  
fYv= yP~  
display-name F?>rWP   
被可视化工具(诸如Jbuilder)用来显示的名称(可选) _DlkTi5(w  
4|PNsHXt  
small-icon \*24NB  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) 1lAx"VL  
/<J&ZoeJB  
large-icon qhNY<  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) r@j$$Pk`  
d`M]>EDXp  
description zzq7?]D  
此tag标签的描述 RfM uWo:  
-&3WN!egq  
variable H ?ZlJ|/c  
提供脚本变量的信息(同tei-class)(可选) 7F=Xn@ _  
EKwA1,Xz  
attribute x^s2bb  
Tag标签的属性名 X}!r4<;(  
!sbKJ+V7  
以下章节介绍对于不同类型的tag,如何具体地实现它们。 4d\"gk  
HkgmZw,  
X^pxu6nm-  
简单的tag ,VtrQb)Yf  
~Z ,bd$  
Uwd^%x*  
tag处理类 =v (MdjwFl  
G|WO  
简单的tag处理类必须实现Tag接口的doStartTag和doEndTag方法。当jsp引擎碰到tag标签的开头时,doStartTag被调用,因为简单的tag没有body,所以此方法将返回 SKIP_BODY。当jsp引擎碰到tag标签的结尾时,doEndTag被调用,如果余下的页面还要被计算,那它将返回EVAL_PAGE,否则将会返回SKIP_PAGE。 v\LcZt`}  
gc%aaYf>  
以下是例子:对于标签 <tt:simple /> ,它的tag处理类实现如下: +W=  
q '6gj  
$M `%A  
public SimpleTag extends TagSupport w>RBth^p  
a-P 'h1hbH  
{ ( Lp~:p  
-85]x)JE  
public int doStartTag() throws JspException ~hJ/&,vH!  
YJioR4+q  
{ *""JE'wG  
\M@9#bd  
try{ CTqAhL 4}  
pH#*:v!)  
pageContext.getOut().print(“Hello.”); yS*s[vT  
st8=1}:&\  
}catch(Exception e){ ^\Bm5QkS  
|sa{!tKJ  
throw new JspTagException(“SimpleTag: “ + e.getMessage()); N S^(5g  
caK<;bmu-  
} @O~  
;H%&Jht  
return SKIP_BODY; T2;%@Ghc  
hWzjn5w3  
} j\,HquTR  
37 #|X*L  
public int doEndTag() KK}?x6wV0,  
7N@4c   
{ ~j1.;WId[  
$]&0`F  
return EVAL_PAGE; }Pu|%\  
1pT v6  
} 6CKWKc  
H|E{n/g  
} |2!!>1k  
t#kPEiD  
i\4Qv"%  
注意:如果tag标签没有内容的话,那必须定义body-content元素为空,例如 ||{V*"+\  
5kX#qT=  
<body-content>empty</body-content> ;g-L2(T05;  
m\3r<*q6  
Bl)znJ^  
带属性的tag标签
评价一下你浏览此帖子的感受

精彩

感动

搞笑

开心

愤怒

无聊

灌水
级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
只看该作者 1 发表于: 2007-01-01
tag处理类 ]6W;~w%  
P)7_RE*gY  
对于tag标签的每个属性,你必须依照JavaBeans规范来定义其属性,以及get和set方法。以struts的logic:present 标签为例, /F>\-    
x~7_`=}rO  
<logic:present parameter=”Clear”> Je|D]w  
IEi E6z]L(  
与此相应,此tag处理类应有如下方法和定义: `(SWE+m1g  
LGxQ>f[V  
.JR"|;M}  
protected String parameter = null; P'4oI0Bw  
jU4*fzsZI  
public String getParameter() SvlS 4C  
kR C0iTV'I  
{ n+5X*~D  
Ol;}+?[Q  
return this.parameter; k\:f2%!!  
1|4'3^3  
} |2yTt*!-r  
1[QH68  
public void setParameter(String parameter) $VX<UK$|s  
TEgmE9^`)7  
{ B3p[A k  
j Hd <*  
this.parameter = parameter; %h "+J  
6bL"ZOEu  
} [+=h[DC  
}v0IzGKs  
0baq696<F  
注意:如果你的属性名为id,而且你的tag处理类是从TagSupport类继承的,那你就不需要定义它的属性和set和get方法,因为他们早已在TagSupport被定义过了。 aLwd#/!  
Ek!$Ary  
Attribute元素 4r@dV%:%<  
\O]1QM94Y  
对于tag标签的每个属性,你必须定义它是否必须的,它的值是否可以用诸如<%= …%>的表达式来获得,以及它的类型(可选),如果不指定它的类型,那就默认为是java.lang.String类型。如果rtexprvalue元素被定义为true或yes,那么在type元素中就定义了attribute的返回类型。 <K8$00lm  
` ,B&oV>  
<attribute> e/;1<5tfj  
4o:  
<name>attr1</name> 8&AHu  
8}Pd- .se  
<required>true|false|yes|no</required> fk(l.A$  
OG# 7Va  
<rtexprvalue>true|false|yes|no</rtexprvalue> #8 N9@  
3@k;"pFa<  
<type>attribute的返回类型(只用当rtexprvalue为真是才有效)</type> *fBI),bZa  
91oIxW  
</attribute> =4RBHe8`  
F",S}cK*MH  
如果tag的某个属性不是必须的,那tag处理类会自动提供一个缺省值。 \wmNeGC2  
vXUrS+~x  
例如,在logic:present这个tag标签中定义了一个属性叫parameter,但它不是必须的,而且它可以被诸如<%= …%>的表达式来赋值。 XxW~4<r  
(t.pM P4  
<tag> yFt'<{z[nL  
+vxU~WIV&  
<name>present</name> 0:(`t~  
_8Si8+j  
<tag-class>org.apache.struts.taglib.logic.PresentTag</tag-class> dXKv"*7l  
Dh*>361y-  
<body-content>JSP</body-content> NN<kO#c+2  
sje}E+{[  
N=) E$h  
LK8K=AA3P  
<attribute> 3r=IO#  
cmQLkT"#K  
<name>parameter</name> 9R XT  
/rd6p{F  
<required>false</required> ~rBeJZ  
%eoO3"//  
<rtexprvalue>true</rtexprvalue> 4m%RD&ZN  
_ ?f~UvK  
</attribute> U!@3['  
]Y|Y?  
&`7tX.iMlh  
(h0i2>K  
</tag> 8aw'Q?  
<De29'},y  
xACAtJ'gc  
属性元素的校验 f1Ruaz-  
oB27Y&nO  
H<dOh5MFh  
有关于tag标签的有效值可以从tag库的说明文档中获得,当JSP页面被编译时,jsp引擎会强制性地参照TLD中定义的规则进行检查。 YaTJKgi"0  
B\2<r5|QG  
还有一个方法也可以进行属性元素的校验,就是先继承类TagExtraInfo,然后调用它的isValid方法。这个类同时也起到提供tag中定义的脚本变量信息的作用。 $'}:nwq6x  
M9MfO*  
IsValid方法通过TagData对象来传递属性信息,它包括着tag的所有的属性名-值的信息。由于校验发生在运行时刻,因此这个属性的值将被赋值为TagData.REQUEST_TIME_VALUE。 u</21fz'  
~ifo7,  
例如tag标签<tt:twa attr1=”value1” />在TLD中定义如下: UzVnC:  
P,Fs7  
<attribute> Aa* UV6(v  
M*)}F  
<name>attr1</name> B7qm;(?X&  
+{ QyB  
<required>true</required> umXa   
48]1"h%*qB  
<rtexprvalue>true</rtexprvalue> #!\g5 ')mC  
wK@k}d  
</attribute> Mn(:qQo^&`  
brN:Ypf-e  
clQN@1] M  
这个定义说明了attr1能在运行期间被赋值。 7O{c>@\  
1F'j .1  
以下的isValid方法检查attr1属性的值是否属于Boolean类型。注意由于attr1能在运行刻被赋值,那么isValid方法必须检查tag用户是否对此tag进行了运行时刻赋值。 9)p VDS  
8W?/Sg`  
y\Z7]LHCqw  
Public class TwaTEI extends TagExtraInfo #RK?3?wcr  
g7k|Ho-W  
{ (3C6'Wt  
3O<:eS~  
public boolean isValid(Tagdata data) `[V]xP%V  
=!_e(J  
{ lz X0B&:  
%s~MfK.k  
Object o = data.getAttribute(“attr1”); ZbJzf]y:6  
yG'5up  
If(o != null && o != TagData.REQUEST_TIME_VALUE) Ip]-OVg  
8>G3KZ3  
{ bH+p5Fd;  
AW@ I,  
if( ( (String)o).toLowerCase().equals(“true”) || W?8 |h  
0_Tr>hz  
((String)o).toLowerCase().equals(“false”) ) f.0~HnNg1  
mM"!=' z  
return true; `,ZsKxI  
M xUj7ae  
else %-?HC jT  
FbQ"ZTN\;Y  
return false; <#w0=W?  
O3#4B!J$E  
} [ aj F  
I&|%Fn  
else K2<Q9 ,vt  
aG QC  
return true;  :0ZFbIy  
uArs[e|f  
} {:c*-+?  
w\KO1 Ob  
} g*Nc+W](P>  
fkWuSGi  
G 8OLx+!0e  
带body的tag HjKj.fV  
g@YJ#S(}  
AQ 3n=Lr   
tag处理类 zghUwW|K  
tG(?PmQ  
z c N1i^   
如果tag标签含有内容,那处理方式会略微有些不同,而且还要视tag处理类是否要与body交互的情况而定。如果要与body交互,那我们认为tag处理类要可能要对body进行操作。 EY;C5P4  
yWsV !Ub  
Tag处理类不与body交互 |Vc8W0~0  
L%9DaK  
如果tag处理类不与body交互,tag处理类应该实现Tag接口或从TagSupport中派生,如果body要被计算,那么doStartTag方法应返回 EVAL_BODY_INCLUDE,否则应返回SKIP_BODY。 DLe?@R5  
jx a?  
如果tag处理类要对body反复运算,则它应该实现IterationTag或从TagSupport中派生。如果tag处理类认为body还未计算完的话,那它的doStartTag方法和doAfterBody方法必须返回EVAL_BODY_AGAIN。 'E+Ty(ED5  
TYW$=p|  
Tag处理类与body交互 ext`%$ U7  
l'T3RC,\  
如果tag处理类与body交互,那tag处理类应实现BodyTag接口或从BodyTagSupport中派生。这种tag处理类一般要实现doInitBody和doAfterBody方法。 oEvXZ;F@.  
Q PgM<ns  
Body允许一些方法来读写它的内容。Tag处理类可以调用body内容的getString或getReader方法来从body中提取信息,也可用 writeOut(out) 方法来将body的内容写入到out对象中。其中out对象通过tag处理类的getPreviousOut方法来获得。 :P<} bGN  
m&jh7)V  
如果body的内容需要被计算,那么doStartTag方法必须返回EVAL_BODY_BUFFERED,否则,它将返回 SKIP_BODY。 Y~(#_K  
.T?9-`I9  
doInitBody 方法 XHcT7}]  
%qL0=ad  
此方法在body内容已经设好,但未被计算之前被调用。你可以根据不同的body内容来制定初始化策略。 .]g>.  
^il'Q_-{  
doAfterBody方法 ]&w>p#_C  
si,fs%D&  
此方法在body内容已被计算后进行调用。 3{ i'8  
,TaaXI  
和doStartTag方法一样,doAfterBody方法返回一个指示符指示是否要继续计算body,如果要继续计算,则doAfterBody应返回EVAL_BODY_BUFFERED,否则,它应返回SKIP_BODY。 -qz;  
-m)N~>{qS  
release 方法 AB40WCu]*  
{\ vj":  
tag处理类调用此方法将它的状态重置为初始状态,并释放所有的私有资源。 ^yg`U(  
i>i@r ;:|  
L,V\g^4$K  
以下的例子读取body的内容(其中含有一条sql语句),然后将它传递给一个对象,让它进行查询。由于此处body不须重新计算,所以doAfterBody会返回SKIP_BODY。 <Hl.MS  
v.H00}[.  
Wfgs[  
Public class QueryTag extends BodyTagSupport 4ihv|%@  
LL@VR#n"V  
{ XZhuV<  
iZ2|/hnw  
public int doAfterBody() throws JspTagException &S9Sl  
9cud CF  
{ zz3Rld!b[  
_3-nw  
BodyContent bc = getBodyContent(); V6Ie\+@.\  
U`sybtuBP'  
//将body的内容以字符串的格式提取出来 VU`aH9g3(  
ykc$B5*  
String query = bc.getString(); tK{2'e6x  
!7t,(Id8  
//清除body FI{9k(  
,5Jq ZD  
bc.clearBody(); &P Wz4hZ  
?khwupdi  
try{ A$.woE@  
[xq"[*Evv  
Statement stmt = connection.createStatement(); H/'tSb  
>7. $=y8b  
Result result = stmt.executeQuery(query); ;*ebq'D([  
U,S&"`a  
}catch(SQLException e){ :{?8rA5  
cN_e0;*Ua  
throw new JspTagException(“queryTag: “ + e.getMessage() ); \xJTsdd  
/Ps}IW  
return SKIP_BODY; ujsJ;\c  
'|Dm\cy  
} VXlTA>a }  
cLR02  
} ;i?Ao:]  
HV ab14}E  
=FUORj\O  
body-content元素 'aMT^w4if)  
I@~hz%'  
s,> 1n0a  
由于tag可能会有body,你必须用body-content元素来指定body内容的类型: Z'p7I}-qr  
} <; y,4f  
<body-content>JSP|tagdependent</body-content> *kE2d{h^=C  
S*~v9+  
]^:l?F\h  
如果body的内容是定制的或内部的tag、脚本元素、或HTML广本,则归类为JSP类型。其他的类型,比如上面代码所述的?D?D将sql statement类传给 query tag的这种类型应该标为tagdependent。 uCuXY#R+  
L9[? qFp  
注意:实际上body-content的值并不影响tag处理类对body内容的处理,它仅仅是被tag编辑工具用来描述此body的内容。 z 3)pvX5  
?zp@HS a9  
:c%vl$  
用tags定义脚本变量 //*>p  
_D7MJT  
~jMdM~}  
tag处理类 wZN<Og+;  
!/O c)Yk  
'zV/4iE=  
tag处理类负责创建或设置页面中定义的脚本变量,用pageContext.setAttribute(name,value,scope)或pageContext.setAttribute(name,value)方法来实现。一般来说,tag处理类通过脚本变量的名称来获取它,脚本变量的名称一般可用get方法来获得。 K~8;wDN`b  
]Ija,C!#  
如果脚本变量的值依赖于tag处理类中的上下文中某一对象,那它可用pageContext.getAttribute(name,scope)方法来找到那个对象。一般的处理过程是tag处理类先找到脚本变量,再对其进行处理,然后用pageContext.setAttribute(name,object)的方法来设置它的新值。 r#LoBfM;^A  
. fq[>zG'&  
对象的生存周期(scope)如下表: #"% ]1={b  
\Ku6 gEy  
对象的生存周期表 x"0*U9f  
wQiRj.  
名字 Z[:fqvXQ  
可访问范围 s8iJl+Jm  
生存周期  L>Bf}^  
r2H_)Oi  
page ~$ } `R=  
当前页面 :{<( )gfk  
一直有效,除非页面向客户提交响应或重定向到一个新页面 )? WiO}"  
OLpE0gZ.|`  
request v`8dRVN  
当前页面或当前页面重定向到的页面 y)_T!&ze  
一直有效,除非页面向客户提交响应 Pda(O;aNU  
&A>Hq/Y  
session I;kKY  
当前页面或在同一浏览器窗口中的页面 is_`UDaB  
一直有效,除非关闭当前浏览器、超时、网络故障 f;M7y:A8q,  
m5Gt8Z 6a  
application #UGm/4C  
整个web应用程序的所有请求 b?`8-g  
一直有效,除非发生网络故障、服务器故障 ,W"Q)cL  
Y%OE1F$6NN  
提供关于脚本变量的信息 _KVge)j  
D(6d#c  
以下示例定义了一个名为“book”的脚本变量,用来访问程序中关于书的信息: ]l.y/pRP5[  
GGHe{l  
<bean:define id=”book” name=”bookDB” property=”bookDetails” type=”database.BookDetails” /> n)$T zND  
) 9h5a+Z  
<font color=”red” size=”+2” > OpeK-K  
`iuo([E d  
<%= messages.getString(“CartRemoved”) %> }ybveZxv5A  
@+1-_Q`s/R  
<strong><jsp:getProperty name=”book” property=”title” /></strong> m'H%O-h\  
v7"' ^sZ?  
</font> Wi]Mp7b  
]0<T,m Z  
当包含此tag的JSP页面被编译时,jsp引擎会自动生成关于此book的同步的代码(同步可以避免几个客户同时访问此book时造成的冲突),要生成同步代码,jsp引擎需要知道此脚本变量的如下信息: sLh9= Kh`  
BhC.#u/   
· 脚本变量名称 gd3~R+Kd  
`ro~l_U;A  
· 脚本变量所属的类 rxtp?|v9  
r<4FF=  
· 此脚本变量是否引用了一个新的或已存在的对象 {2?o:  
qv|geBW  
· 此脚本变量的有效性 7N0V`&}T  
3uA%1 E  
有两种办法可以向jsp引擎提供关于脚本变量的信息:在TLD中定义variable子元素,或用tei-class子元素定义一个额外tag信息类。用variable最简单,但可能降低了一些灵活性。 .zf#S0y%(  
aV3:wp]Gn  
Variable元素 !IlsKMZ  
a!YpSFr  
Variable元素有如下子元素: }Jkz0JY~  
$rFLhp}  
· name-given ?D?D 给出的名字,是一个常量 +:@HJXwK  
H SEfpbh  
· name-from-attribute?D?D 属性名,在编译时给出的属性名 a& b75.-  
z$OKn#%T  
name-given或name-from-attribute两者必须选一,但以下子元素是可选的: hhQLld4  
6FuZMasr*  
· variable-class?D?D变量的类型,缺省为java.lang.String。 N3 qtq9{  
  )z#  
· declare?D?D此脚本变量是否引用了一个新对象,缺省为True。 qTFktJZw  
3>%oGbo  
· scope?D?D脚本变量的范围,缺省为NESTED。下表描述了scope的几种类型: ??Zh$^No:  
Z>1\|j  
脚本变量的有效范围 u'}SaX]0  
CC,_I>t  
9C[i#+_3M  
有效性 *|S.[i_7  
方法 ^6Y4=  
K~Lh'6  
NESTED #hPa:I$Oc  
在tag标签的开始和结束之间 (bnyT?p%  
如果tag处理类实现BodyTag接口,则在doInitBody和doAfterBody中调用,否则在doStartTag中调用 ,YzrqVY  
)`5k fj  
AT_BEGIN YSi[s*.G  
从tag标签的开始一直到页面结束 _(=[d  
如果tag处理类实现BodyTag接口,则在doInitBody、doAfterBody和doEndTag中调用,否则在doStartTag和doEndTag中调用 w_o|k&~,  
?g*#l d()  
AT_END 3B|?{U~  
从tag标签的结束一直到页面结束 .|x\6 jf  
在doEndTag中调用 )i@j``P  
F&? &8.  
以struts为例,它的bean:define标签的实现遵循JSP1.1规范,此规范要求使用额外tag信息类来定义脚本变量。Variable元素是JSP1.2规范中加入的。以bean:define标签为例,你可以定义如下variable元素: =8BMCedH|  
8nn%wps  
<tag> .*+?]  
9Qja|;  
<variable> CD|)TXy  
PMPB}-d  
<name-from-attribute>id</name-from-attribute> $|~YXH~O  
f?)BAah  
<variable-class>database.BookDetails</variable-class> y>}dKbCN  
S !Dq8  
<declare>true</declare> ,n&@O,XGy  
D{1k{/cF  
<scope>AT_BEGIN</scope> Z6@W)QX  
&K Ti[  
</variable> *h59Vaoc  
{=n-S2%  
</tag> ;OjxEXaq  
x>MrB  
额外tag信息类 4t3Y/X  
bs{i@1$  
如果要定义一个额外tag信息类,你要继承javax.servlet.jsp.TagExtraInfo类。一个TagExtraInfo类必须实现getVariableInfo方法,此方法返回一个叫VariableInfo的数组类,它包括如下信息: !ER,o_T<  
nl v8HC  
· 变量名 Ubtu?wRBW  
n^Co  
· 变量所属类名 uA#uq^3  
:ryyo$  
· 此变量是否引用了一个新对象 #gjhs"$~  
EXt?xiha?  
· 此变量的有效范围 sp%EA=: E  
Jv*[@ -.k  
jsp引擎将一个名为data的参数传给getVariableInfo方法,data中包括tag标签中的所有“属性名?D?D属性值”对。它可以用来向VariableInfo对象提供脚本变量的名字和类名。 rGjP|v@3^  
iDp'M`(6h  
以struts为例,它在bean:define标签中定义了一个名为DefineTei的额外tag信息类,用来向脚本变量提供信息。由于脚本变量的名称(book)和类名(database.BookDetails)是通过tag标签的属性来传递的,它们一般定义在VariableInfo的构建代码中,并且可用data.getAttributeString方法来得到这些信息。如果要允许book脚本变量能在从tag开始直到整个JSP页面结束的范围内都可用的话,那它的范围应设为AT_BEGIN。如下所示: uLok0"}  
}"k+e^0^  
o/ Z  
public class DefineTei extends TagExtraInfo ?"oW1a\  
;2lKo="  
{ 'F3cvpc`  
D vG9(Eh  
public VariableInfo[] getVariableInfo(TagData data) C:Tjue{G2  
)*!"6d)^  
{ P,.<3W"4i  
?[~"$  
String type = data.getAttributeString(“type”); j*2Q{ik>J  
pO^goo V\  
If( type == null) b|7c]l  
~loJYq'y  
type = “java.lang.Object”; 5\hJ&  
JIeKp7;^  
return new VariableInfo[] { >,JLYz|</  
xqV>m  
new VariableInfo(data.getAttributeString(“id”), 7S"W7O1>  
{J_1.uN=  
type, D|zlC,J,  
X}XTEk3[  
true, 6 <&jY  
t^N 92$|  
VariableInfo.AT_BEGIN) a>w@9   
VKzY6  
}; z D&5R/I  
>e F4YZ"  
} \1k(4MWd  
v]`}T/n  
} VU~ R  
@y3u'Y,B  
AawK/tfs  
注意:关于额外tag信息类的类名必须要在TLD中的tag标签下的tei-class子元素中定义。因此,DefineTei的tei-class中的定义看起来如下:  U~%V;*|4  
<tei-class> BK,h$z7#6  
org.apache.struts.taglib.bean.DefineTagTei T)QZ9a  
</tei-class> 0UV5}/2rP  
p72:oX\Q I  
/{|<3CEe  
具有协作关系的tag EvA{@g4>  
\SA"DT  
,{4G@:Fm  
tag通过共享对象来进行协作,JSP技术支持2种方式的对象共享。 be ^09'  
4}mp~AXy;z  
第一种方法是使用pageContext对象进行对象的共享(可支持JSP页面和tag处理类之间的共享),如果在一个tag处理类中要调用由另一个tag处理类创建的对象,可调用pageContext.getAttribute(name, scope)方法。 CHeU`!:  
/$]#L%   
第二各方式的共享是对于tag之间有嵌套关系而言的,外层的tag所创建的对象对于内层的tag来说是可以共用的。这种形式的共享的好处是减少了可能存在的重名冲突。 a(|YLN  
^Kvbpi,  
要访问一个嵌套tag创建的对象,tag处理类必须先找到此嵌套tag对象,可用TagSupport的静态方法 TagSupport.findAncestorWithClass(from, class)或TagSupport.getParent方法。前者在当不确定此tag是否为嵌套tag对象时使用。一旦它的父类被找到,它就能访问其所有动态或静态创建的对象。静态创建的对象是父类的成员,而动态创建的对象可能是父类的私有对象。诸如此类的对象可以用tag处理类的setValue方法来保存,用getValue方法来获得。 :`FL95  
iF.eBL%  
下例阐述了以上两种共享对象的方法。在这个例子当中,一个查询tag检查一个名为connection的属性名是否在doStartTag中被设置。如果connection属性被设置,tag处理类从pageContext中得到这个connection对象。否则,此tag处理类先找到它的父tag处理类,然后从它的父tag处理类中找到connection对象。 /]0-|Kg+R  
)HLe8:PG~  
?`& l Y  
public class QueryTag extends BodyTagSupport M]\p9p(_  
.uu[f2.N+  
{ +f#o ij  
,mpvGvAI  
private String connectionId; =P* YwLb  
\FVm_)  
public int doStartTag() throws JspException o;.6Y `-fJ  
x6=Yt{  
{ z5~{WAAI  
<:v2 N/i  
String cid = getConnection(); [A@K)A$f  
8|:bis~wm  
if(cid != null) )(&Z&2~A  
/qf2LO'+  
{ f>g< :.k*  
f-Yp`lnn.d  
//存在一个connection id,使用它。 Oy U[(  
BU\P5uB!V  
connection = (Connection) pageContext.getAttribute(cid); QfLDyJv`e  
&4g]#A>@  
} !8cS1(a  
H l'za  
else eRI'pi[#.  
i5oV,fiZo  
{ :?!kZD!  
.f+ul@o  
ConnectionTag ancestorTag = (ConnectionTag)findAncestorWithClass(this, tS$^k)ZXip  
O\=U'6 @  
ConnectionTag.class); B,`B!rU  
]{tnNr>mv  
if(ancestorTag == null) /FzO9'kj  
*rs@6BSj  
{ y.KFz9Qv  
nEtG(^N  
throw new JspTagException(“一个没有connection属性的查询标签必须被一个connection标记嵌套。”); "rV-D1Dki  
fn6;  
} 7/p&]0w  
wHGiN9A+  
connection = ancestorTag.getConnection(); (:JX;<-  
Pfy2PpA  
} -ahSFBZlg  
l4 @  
} :/F=j;o  
}sbh|#  
} V$D+Joj  
mM6g-)cV  
=Gka;,n  
-pWnO9q  
此查询标签在JSP页面中的调用形式可以从以下2种定义中任选一种: (e:@7W)L  
7=$@bHEF#*  
* $  
<tt:connection id=”con01” ...> ... </tt:connection> 9qhX\, h  
^lF'KW$  
<tt:query id=”balances” connection=”con01” > s7x&x;-  
'X()|{  
SELECT account, balance FROM acct_table f-w-K)y$ht  
XkG:1H;Q%  
where customer_num = <%= request.getCustno() %> =qQH,{]c6  
ck=x_HB1  
</tt:query> Dd1\$RBo  
i|- 6  
^A4bsoW  
Ro&s\T+d  
4$j7DJ8dj  
<tt:connection ...> v[3QI7E3  
zz4TJ('  
<x:query id=”balances”> Z *9Qeu-N:  
H9@24NFb  
SELECT account, balance FROM acct_table C'6 yt  
J(k\Pz*  
where customer_num = <%= request.getCustno() %> ?`m#Y&Oi  
PP2>v|  
</x:query> ;oe j~  
+[ +4h}?  
</tt:connection> QD<GXPu?N  
hKZ<PwBi  
Bh'_@PHP  
与此同时,在TLD中必须指定connection属性为可选的,定义如下: qDMVZb-(#  
L7~9u|7a#  
<tag> utH,pGs C.  
Y[(U~l,a+  
... hJkP_( +J\  
SN${cs%  
<attribute> C}i1)   
W@X/Z8.(  
<name>connection</name> v;S_7#  
q%G"P*g$(  
<required>false</required> t`b!3U>I  
.ZV-]jgr  
</attribute> AW;ncx;  
'U9l  
</tag>
描述
快速回复

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