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

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

级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
标准的JSP 标记可以调用JavaBeans组件或者执行客户的请求,这大大降低了JSP开发的复杂度和维护量。JSP技术也允许你自定义taglib,其实换句话说,taglib可以看成是对JSP标记的一种扩展,正如xml是对html的一种扩展一样。taglib通常定义在tag标签库中,这种标签库存放着你自己定义的tag标签。简而言之,如果使用taglib,那么你可以设计自己的JSP标记! ,L$, d  
_qsg2e}n  
一般来说,自定义tag标签主要用于操作隐藏对象、处理html提交表单、访问数据库或其它企业级的服务,诸如邮件和目录操作等等。自定义tag标签的使用者一般都是那些对java编程语言非常精通,而且对数据访问和企业级服务访问都非常熟悉的程序员,对于HTML设计者来说,使得他可以不去关注那些较复杂的商业逻辑,而将精力放在网页设计上。同时,它也将库开发者和库使用者进行合理分工,自定义tag标签将那些重复工作进行封装,从而大大提高了生产力,而且可以使得tag库可用于不同的项目中,完美地体现了软件复用的思想。 ok(dCAKP  
L[O.]2  
在这篇文章中,我们主要讨论: 9;tY'32/  
|6!L\/}M%  
· 什么是自定义tag标签? *#7]PA Qw  
?(>fB2^  
· 怎么使用tag标签? Qb?e A  
ev9ltl{  
o 声明要使用的tag库 y28 e=i  
#?fKi$fS;L  
o 找到与之对应的tag处理类 E @7);i5K  
#SqU>R  
o tag标签的类型 rixt_}aE  
Jq_AR!} %  
· 自定义tag标签 Q=#N4[W'  
E{xcu9  
o tag处理类 L<Q>:U.@\  
;ji[ "b  
o tag库描述 zaG1  
LW*v/`@  
o tag标签示例 Wph@LRB]  
4Bk9d\z  
o 带属性的tag $n* wS,  
=jkiM_<h  
o 带body的tag dQJ)0!B  
vY2^*3\<D  
o 定义了脚本变量的tag Z Z9D6+R  
P; 9{;  
o 具有协作关系的tag 89\DS!\x9  
V~fPp"F  
· 自定义tag标签 }N0v_Nas;v  
XxLauJP K  
o 一个迭代tag的例子 PAS0 D #  
+AYB0`X)  
o 一个模板tag库 9}jezLI/3  
$HP<C>^Z8  
o tag处理类到底是怎样被调用的? o e,yCdPs  
0{qe1pb w  
6D/K=-   
什么是自定义的tag? 9qI#vHA  
Eh&-b6:  
一个自定义的tag标签是用户定义的一种JSP标记。当一个含有自定义的tag标签的JSP页面被jsp引擎编译成servlet时,tag标签被转化成了对一个称为tag处理类的对象进行的操作。于是当JSP页面被jsp引擎转化为servlet后,实际上tag标签被转化成为了对tag处理类的操作。 Ft 6{g JBG  
rObg:(z&\  
自定义tag标签有很多特色,诸如: {3eg4j.Z  
R?iC"s!  
· 可以在JSP页面中自定义tag标签的属性 XU|>SOR@z  
q}cm"lO$  
· 访问JSP页面中的所有对象 T&+y~c[au  
Mq52B_  
· 可以动态地修改页面输出 4KB>O)YNg'  
D|D) 782  
· 彼此这间可以相互通信。你可以先创建一个JavaBeans组件,然后在一个tag中调用此JavaBeans组件,同时可以在另一个tag中调用它。 S,vh  
odh cU5  
· tag允许相互嵌套,可以在一个JSP页面中完成一些复杂的交互。 !yD$fY  
R3hyz~\x&  
.> 5[;  
使用tag标签 0bl8J5Ar5  
uYCWsw/  
,vB~9^~  
本节主要描述怎样在JSP页面中使用tag标签,以及tag标签的不同类型。 85qD~o?O  
rmJ`^6V  
要使用tag标签,JSP程序员必须做2件事: W]I+Rlv)U  
v@Qfx V2  
· 声明此tag标签的tag库 `l0"4 [?  
qh#?a'  
· 实现此tag标签 Td 5yRN! ?  
vbEO pYCS  
声明tag标签所在的tag库 fVz0H1\J&  
z -uW,  
如果要使用tag标签,则应用JSP的taglib指示符来指定其tag库(注意:taglib要在在使用此tag标签之前声明) (O"-6`w[  
`Ha<t.v(  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> M`p[ Zq  
98XlcI#  
uri属性定义了唯一的标签库描述(以下简称TLD),它可以是直接是tld文件名或一个独一无二的名字。prefix是用来区别其它TLD中和本TLD中有重名的tag的一种手段。 T&^b~T(y  
X.eocy  
TLD必须以.tld作为扩展名,并且存放在当前应用的WEB-INF目录或其子目录下。你可以通过它的文件名直接引用它,也可以通过别的方式间接地引用它。 /~3kkM(Ty  
T\w{&3ONm  
以下taglib指示符直接引用一个TLD: 65U&P5W  
4(&sw<k  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> ZKt`>KZ  
J*4T| #0  
以下的taglib指示符通过一个逻辑名称间接地引用一个TLD: YK>?;U+|  
@1s 2# )l(  
<%@ taglib uri=”/tutorial-template” prefix=”tt” %> Xxr"Gc[  
GTke<R  
如果是间接引用TLD的话,那你必须还要在web.xml中定义此逻辑名称与tld文件之间的映射,具体做法是在web.xml中加入一个名为taglib的元素: [oOV@GE  
6cX Z3;a  
<taglib> #vzt6x@*  
/kAbGjp0  
<taglib-uri>/tutorial-template</taglib-uri> B7( bNr  
KJ cuZ."wX  
<taglib-location> }#2I/dn  
w^MiyX  
/WEB-INF/tutorial-template.tld ?*&5`Xh  
yOO@v6jO)  
</taglib-location> y wmC>`0p  
I ;F\'P)e  
</taglib> #|K5ma  
DFp">1@`PR  
Y'yGhpT~  
实现此tag标签 (BGflb  
B-h@\y  
4 {+47=n  
为了实现tag标签,你有2种方法来存放tag处理类。一、让tag处理类以.class的方式存放于当前应用的WEB-INF/class子目录下,二、如果tag处理类是以JAR包的形式存在的话,那可以放在当前应用的WEB-INF/lib目录下,如果tag处理类要在多个应用中共享,那么它就应放在jsp服务器上的common/lib目录下,对于tomcat来说,就是tomcat/common/lib目录下。 B/I1<%Yk  
rPK1#  
gWfMUl  
tag标签类型 WHcw5_3#  
G UK %R C8  
#N'bhs  
自定义的tag标签遵循XML语法。它有一个开始标记和一个结束标记,有的还有body(即文本节点): vngn^2  
F#a'N c9  
<tt:tag> gwDVWhq  
!M}ZK(  
body |LirjC4  
7A^L$TY  
</tt:tag> %7 $X *  
>,x``-  
|%@pjJ`3  
一个不带body的tag标签如下: yM*_"z!L  
"EnxVV  
<tt:tag /> A().1h1_k  
>cH}sNHy  
%*OQH?pyx}  
简单的tag标签 {Rq5=/b  
C?g<P0h  
一个没有body和属性的tag标签如下: %[on.Q'1]2  
x#fv<Cj4  
<tt:simple /> D!mx&O9  
as"@E>a  
"] ]aF1  
带属性的tag标签 0+NGFX \p  
 CP Ju=  
" f.9u  
自定义标签可以有自己的属性。属性一般在开始标记中定义,语法为 attr=”value”。属性的作用相当于自定义标签的一个参数,它影响着tag处理类的行为。你可以在TLD中详细定义它。 7GRPPh<4  
p21li}Iu  
你可以用一个String常量给一个属性赋值,也可以通过表达式给它赋值,如<%= ...%>。以struts为例,它的logic:present标签就是用的String常量来给属性赋值: e6Kyu*  
+|qw>1J(  
<loglic:present parameter = “Clear”> P?J\p J1|7  
q-qz-cR  
而另一个标签logic:iterate是用表达式来给属性赋值: bycnh  
!:a^f2^=  
<logci:iterate collection=”<%= bookDB.getBooks() %>” i4m P*RwC  
xn anca  
id=”book” type=”database.BookDetails”> @_ Tq>tOr&  
^G NL:D%6d  
4jW <*jM  
带body的tag标签 's$/-AV  
])?[9c  
一个自定义标签可以包含其它自定义标签、脚本变量、HTML标记或其它内容。 r-,u)zf"  
8Yf=)  
在下述例子中,此JSP页面使用了struts的logic:present标签,如果些标签定义了parameter=”Clear”的属性,则将清除购物车的内容,然后打印出一条信息: 8zQN[[#n  
P?+ VR=t  
<logic:present parameter=”Clear”> 8Fv4\dr  
:(;ho.zz  
<% cart.clear(); %> yeA]j[ #  
Se>v|6  
<font color=”#ff0000” size=”+2”><strong> mp8Zb&Ggb  
Q}#xfrprF  
你选择了清除购物车! o_&Qb^W  
G4uA&"OE  
</strong></font> 0B"_St}3D  
w`[`:H_z  
</logic:present> :VE0eJ]J6  
j |LOg  
@ X5#?  
到底是用属性还是用body来传递信息? Px&)kEQ  
I2z6iT4nB  
如上所述,我们既可以通过属性,也可以通过body来传递信息。但一般来说,比较简单的类型,如字符串或简单表达式最好采用属性来传递信息。 Nb)Mh  
goc; .~?  
p tlag&Z  
定义脚本变量的tag标签 luJNdA:t&  
R,8T t!n  
所谓脚本变量,是指JSP中可以调用的变量或对象。它可由tag标签产生。以下示例阐述了一个tag标签定义了一个名为tx的由JNDI所定义的事务处理对象。脚本变量可以是ejb对象、事务、数据库连接等等: o0TB>DX$`  
k=9k4l  
<tt:lookup id=”tx” type=”UserTransaction” name=”java:comp/UserTransaction” /> TjOK8 t  
[^gb6W9Y  
<% tx.begin(); %> ;f /2u  
9&{HD  
... DuIgFp  
iB+ _+A  
h$p}/A  
具有协作关系的tag标签 ysFp$!9Ux  
fJ+4H4K  
自定义tag标签之间可以通过共享对象来实现协作。在下述例子中,标签tag1创建了一个名为obj1的对象,在标签tag2仍可以重复使用obj。 ps33&  
zICrp  
<tt:tag1 attr1=”obj1” value1=”value” /> 9/{ 8Y&  
zm#%]p80f  
<tt:tag2 attr1=”obj1” /> |Rz}bsrZ  
2\CZ"a#[  
在以下这个例子当中,如果外层的tag标签创建了一个对象,那么其内层的所有tag标签都可以使用这个对象。由于这样产生的对象没有一个指定的名字,那么就可以将少重名的冲突。这个例子阐述了一系列协作的嵌套对象。 7Ac.^rv5  
[XkWPx`  
<tt:outerTag> o)8VJ\ &  
XpPcQIM*  
<tt:innerTag /> (O/W`qo  
=69sWcC8  
</tt:outerTag> 0Z{u;FI  
?O0,)hro  
y:k7eE"  
Tag处理类 O6ltGtF  
sn+ kFvk}S  
E,QD6<?[  
Tag处理类必须实现Tag接口或BodyTag接口,不过现在一般都流行从TagSupport或BodyTagSupport类中继承,这些类或接口都可以在javax.servlet.jsp.tagext包中找到。 ;rl61d}NH#  
H %ScrJ#V  
当JSP引擎看到自己的JSP页面中包含有tag标签时,它会调用doStartTag方法来处理tag标签的开头,调用doEndTag方法来处理tag标签的结束。 u$qazj  
&:~9'-O  
下表说明不同类型的tag所需要不同的处理过程: ? 8)k6:  
+NoVe#  
Tag处理类的方法 &UAYYH  
5kCXy$"%  
Tag标签类型 )"%J~:`h}  
所调用的方法 (]-RL A>  
qR kPl!5  
基本标签 zuF]E+  
doStartTag, doEndTag, release  WfQZ7e  
uEkGo5  
带属性的标签 I p|[  
doStartTag, doEndTag, set/getAttribute1...N, release f]2;s#cu  
%K0Wm#)  
带内容的标签 ?y,KN}s_  
doStartTag, doEndTag, release u ^M'[<{  
dwb^z+   
带内容的标签,且内容重复循环 [Bj\h7 G  
doStartTag, doAfterBody, doEndTag, release /xd|mo)D  
&Y3ZGRT  
带内容的标签,且内容与JSP交互 eTI?Mu>C  
doStartTag, doEndTag, release, doInitBody, doAfterBody, release E9]*!^=/  
)U{\c2b  
一个tag处理类可以通过javax.servlet.jsp.PageContext来与JSP交互,通过javax.servlet.jsp.PageContext类,tag处理类可以访问JSP中的request、session和application对像。 WUb] 8$n  
JO~62='J  
如果tag标签是互相嵌套的,那内层的tag处理类可以通过它的parent属性来访问上层的tag处理类。 ~6{U^3  
*P?Rucg  
一般情况都将所有的tag处理类打成了JAR的包,以便于发布。 gI/(hp3ob  
]Mvpec_B  
>|mZu)HIY;  
Tag库描述(简称TLD) ak{XLzn  
xEufbFAN?  
ViU5l*n;  
Tag库是用xml语言描述的,TLD包括了tag库中所有tag标签的描述,它一般用来被jsp服务器用来校验tag的语法正确性,或者被jsp开发者用来开发新的标签。 :g{ybTSEe  
k{bC3)'$#R  
TLD的文件扩展名必须为.tld,而且必须放在当前WEB应用的WEB-INF目录或其子目录中。 'Jd*r(2d  
AmrVxn4  
一个TLD的内容的开头必须遵守标准的XML开头,用于描述DTD和xml的版本,例如: bQdu=s[  
zX6Q7Bc  
<?xml version="1.0" encoding="ISO-8859-1" ?> k h6n(B\  
V/RV,K1/  
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd"> SQ<{X/5  
TLD必须以<taglib>来作为它的根元素,<taglib>的子元素如下表: Nl^u A  
Xm<|m#  
'_ys4hz}  
<taglib>的子元素 4j zjrG  
pk6<wAs*?#  
Element 4h T!DS  
Description z}Um$'. =  
c7nbHJi  
tlib-version [MF&x9Ss?%  
Tag库的版本 L0Ajj=  
ER;\Aes*?  
jsp-version R`,|08E  
Tag库所需要的jsp的版本 -8v:eyc  
z6|kEc"{  
short-name B &3sV+  
助记符,tag的一个别名(可选) *a-KQw  
)!;20Po  
uri Hx n#vAc  
用于确定一个唯一的tag库 Bve',.xH  
tRNMiU  
display-name U[z2{\  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) 2SlI5+u  
y[GqV_~?Y  
small-icon fh` }~ aQ  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) x+v&3YF  
t_+owiF)M  
large-icon QQD7NN>  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) 7/iN`3Bz  
FytGg[#]  
description 0n\AUgVPF  
对tag库的描述(可选) O^_CqT%  
d+"F(R9  
listener +}eK8>2  
参见下面listener元素 $"va8,  
iDdR-T|  
tag bmh@SB  
参见下面tag 元素 ^2i$AM1t  
H|/"'t OZ  
Listener元素 +o35${  
V;gC[7H  
一个tag库可能定义一些类做为它的事件侦听类,这些类在TLD中被称为listener 元素,jsp服务器将会实例化这些侦听类,并且注册它们。Listener元素中有一个叫listener-class的子元素,这个元素的值必须是该侦听类的完整类名。 %g69kizoWi  
)~IOsTjI  
Tag元素 |hX\ep   
o\fPZ`p-m~  
每个tag元素在tag库中都要指出它的名字、类名、脚本变量、tag的属性。其中脚本变量的值可以直接在TLD中定义或通过tag附加信息的类来取得。每个属性描述了这个属性是否可以省略,它的值是否可以通过<%= …%>这样的JSP语法来获得,以及属性的类型。 g"`jWSt7Q  
qHPinxewx  
每一个tag在TLD中对应一个tag元素,下表是tag元素的子元素: L]l?_#*x  
S'`RP2P  
Tag元素的子元素 ->Fsmb+R  
l~[ K.p&  
元素名称 %v UUx+  
描述 # wyjb:Ql  
Z A}!Rzo  
name F2Gg_u@7M  
独一无二的元素名 r4fd@<=g  
r]Lj@0F>8  
tag-class L @J$kqWY  
Tag标签对应的tag处理类 "]q0|ZdOwH  
"![KQ  
tei-class vzF6e eaD  
javax.servlet.jsp.tagext.TagExtraInfo的子类,用于表达脚本变量(可选) bAUYJPRpy  
O9RnS\  
body-content Z% ]LZ/O8  
Tag标签body的类型 NOf{Xx<#k  
+~7[T/v+n  
display-name <3Rq!w/  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) pp2 Jy{\d  
,+x\NY2d  
small-icon @6-3D/=  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) W #kLM\2L  
TN/&^/  
large-icon hMgk+4*  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) pV1 ;gqXNS  
"#pN  
description ^ '_Fd  
此tag标签的描述 lq?N>~PG  
xXJzE|)1h!  
variable %Rf{v5  
提供脚本变量的信息(同tei-class)(可选) {;o54zuKf  
dvglh?7d  
attribute ebLt:gGo  
Tag标签的属性名 Kr`.q:0GK  
mS.!lkV  
以下章节介绍对于不同类型的tag,如何具体地实现它们。 rLbFaLeQ  
wkp$/IZKMj  
$?9u;+jIR  
简单的tag )=5*iWe  
`:2np{  
1y eD-M"w  
tag处理类 J3'0^JP*  
S<5.}cR  
简单的tag处理类必须实现Tag接口的doStartTag和doEndTag方法。当jsp引擎碰到tag标签的开头时,doStartTag被调用,因为简单的tag没有body,所以此方法将返回 SKIP_BODY。当jsp引擎碰到tag标签的结尾时,doEndTag被调用,如果余下的页面还要被计算,那它将返回EVAL_PAGE,否则将会返回SKIP_PAGE。 mn(MgJKQ\  
QRF:6bAxsL  
以下是例子:对于标签 <tt:simple /> ,它的tag处理类实现如下: @?</8;%3W  
C*Q x  
GT3}'`f B  
public SimpleTag extends TagSupport [7[$P.MS{  
>f;oY9 {m  
{ UM'JK#P"  
[mF=<G"  
public int doStartTag() throws JspException }( WUZ^L  
buHUBn[3)  
{ YP{mzGdE&  
aZmbt,.V  
try{ ]agdVr^  
T<RWz  
pageContext.getOut().print(“Hello.”); _HAr0R8BY  
luz,z( v  
}catch(Exception e){ rNgAzH  
Z eWst w7  
throw new JspTagException(“SimpleTag: “ + e.getMessage()); /#}%c'  
t'C9;  
} l_fERp#y  
:k~ p=ko  
return SKIP_BODY; P[e#j  
XLm@, A[  
} |~=4Z rcCP  
X4"[,:Tw  
public int doEndTag() /!y3ZzL  
, - _ReL  
{ 1i Q(q\%  
k7z{q/]M  
return EVAL_PAGE; ^ .Q/iXgh  
^{g+HFTA@  
} Z3iX^  
CS"p3$7,  
} 1 EHNg<J(  
<"S/M]9  
B_%O6  
注意:如果tag标签没有内容的话,那必须定义body-content元素为空,例如 o7g6*hJz  
9(BB>o54r  
<body-content>empty</body-content> mPi{:  
QSOJHRl=C  
2f 9%HX(5  
带属性的tag标签
评价一下你浏览此帖子的感受

精彩

感动

搞笑

开心

愤怒

无聊

灌水
级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
只看该作者 1 发表于: 2007-01-01
tag处理类 }@g#S@o  
iS28p  
对于tag标签的每个属性,你必须依照JavaBeans规范来定义其属性,以及get和set方法。以struts的logic:present 标签为例, N)$yBzN  
m*TJ@gI*t  
<logic:present parameter=”Clear”> 7me1 :}4  
i(<do "Am<  
与此相应,此tag处理类应有如下方法和定义: [kZe6gYP&  
4buzx&  
" gi 1{  
protected String parameter = null; I4 4bm?[S  
<1E* wPm8  
public String getParameter() vlZ?qIDe  
YCB=RT]&`  
{ c::Vh  
$RV'DQO  
return this.parameter; 'I)E.DoF  
m2Q#ATLW  
} aAkO>X%[  
7o64|@'j  
public void setParameter(String parameter) Yy8%vDdJO  
-o0~xspF  
{ `LCxxpHi|  
NU|T`gP  
this.parameter = parameter; [a1}r=6~  
las|ougLy  
} V9kL\Ys  
Y<-dd"\  
zLLe3?8:  
注意:如果你的属性名为id,而且你的tag处理类是从TagSupport类继承的,那你就不需要定义它的属性和set和get方法,因为他们早已在TagSupport被定义过了。 gj Ue{cb5  
Mo+HLN  
Attribute元素 To19=,:  
!/MHD  
对于tag标签的每个属性,你必须定义它是否必须的,它的值是否可以用诸如<%= …%>的表达式来获得,以及它的类型(可选),如果不指定它的类型,那就默认为是java.lang.String类型。如果rtexprvalue元素被定义为true或yes,那么在type元素中就定义了attribute的返回类型。 K3^N_^H  
u-E*_% y  
<attribute> b 7bbrR8  
p)=Fi}#D\  
<name>attr1</name> t6O/Q0_  
*a4nd_!  
<required>true|false|yes|no</required> {sL(PS.z  
QK%6Ncv  
<rtexprvalue>true|false|yes|no</rtexprvalue> p,+$7f1S  
G@igxnm}  
<type>attribute的返回类型(只用当rtexprvalue为真是才有效)</type> z,B'I.)M  
.pQ4#AJ  
</attribute> *.9.BD9  
)fz<n$3|$#  
如果tag的某个属性不是必须的,那tag处理类会自动提供一个缺省值。 |>P`Gl]E  
G>0S( M)  
例如,在logic:present这个tag标签中定义了一个属性叫parameter,但它不是必须的,而且它可以被诸如<%= …%>的表达式来赋值。 E6d0YgfD  
}$|uIS  
<tag> B? r[|  
f ^f{tOX  
<name>present</name> zy9# *gGq  
_S;L| 1>S  
<tag-class>org.apache.struts.taglib.logic.PresentTag</tag-class> wA<#E6^vG  
{'#^  
<body-content>JSP</body-content> sX,oJIt  
(s`yMUC+  
PO[ AP%;  
D=nuK25  
<attribute> ;F;`y),  
:jq   
<name>parameter</name> tA2I_W Cl  
qwU,D6  
<required>false</required> z`D;8x2b  
^w XXx=Xf  
<rtexprvalue>true</rtexprvalue> fhAK^@h  
j6KGri  
</attribute> p}NIZ)]$  
K?q1I<94  
}*4K]3et$  
T)ra>r<#  
</tag> nx >PZb  
` AA[k  
9ci=]C5o3K  
属性元素的校验 )MZQ\8,)]  
e8@@Pi<sB  
Zv*Z^; X9  
有关于tag标签的有效值可以从tag库的说明文档中获得,当JSP页面被编译时,jsp引擎会强制性地参照TLD中定义的规则进行检查。 $b/oiy!=|3  
"1H?1"w~  
还有一个方法也可以进行属性元素的校验,就是先继承类TagExtraInfo,然后调用它的isValid方法。这个类同时也起到提供tag中定义的脚本变量信息的作用。 C{ {DZ*  
r~uWr'}a}  
IsValid方法通过TagData对象来传递属性信息,它包括着tag的所有的属性名-值的信息。由于校验发生在运行时刻,因此这个属性的值将被赋值为TagData.REQUEST_TIME_VALUE。 <5Jp2x#  
7)NQK9~  
例如tag标签<tt:twa attr1=”value1” />在TLD中定义如下: L s=2!  
HUtuUX  
<attribute> }F1|& A  
zUqt^_  
<name>attr1</name> zM^ux!T=  
{<a(1#{  
<required>true</required> b<B|p|  
~bCn%r2  
<rtexprvalue>true</rtexprvalue> R)"Y 40nW  
[}|-% 4s  
</attribute> z&o"K\y\  
Pgs^#(^>  
+1 H.5|  
这个定义说明了attr1能在运行期间被赋值。 QUp()B1  
WKFmU0RK  
以下的isValid方法检查attr1属性的值是否属于Boolean类型。注意由于attr1能在运行刻被赋值,那么isValid方法必须检查tag用户是否对此tag进行了运行时刻赋值。 fo$iV;x`  
ki#O ^vl  
gd6We)&  
Public class TwaTEI extends TagExtraInfo y_$=Pu6H  
xr) Rx{)3h  
{ ee]PFW28  
=~% B}T  
public boolean isValid(Tagdata data) uuzDu]Gwu  
kEtYuf^  
{ 4Wq{ch  
Cyxt EzPp  
Object o = data.getAttribute(“attr1”); sT9P  
t+k"$zR  
If(o != null && o != TagData.REQUEST_TIME_VALUE) zm}4=Kz}  
q79)nhC F  
{ C26PQGo#$  
Dcq\1V.e`W  
if( ( (String)o).toLowerCase().equals(“true”) || twqjaFA>  
t i)foam  
((String)o).toLowerCase().equals(“false”) ) ^{["]!f#  
Pq~"`-h7:  
return true; &E$jAqc  
}'dnL  
else rp.S4;=Q9  
#F.;N<a  
return false; dZm>LVjG  
W$@q ~/E  
} e@s+]a8D-k  
W?!(/`J]  
else VY$hg  
KUVsCmiT  
return true; Re('7m h~  
S=^yJ6 xJ  
} -c!{';Zn  
~wIVw}  
} =*qu:f\y  
}`4o+  
%-|Po:6  
带body的tag 0 ]U ;5  
oYnA 3  
;Br8\2=$  
tag处理类 FGBPhH% (8  
u#?K/sU  
; )O)\__"-  
如果tag标签含有内容,那处理方式会略微有些不同,而且还要视tag处理类是否要与body交互的情况而定。如果要与body交互,那我们认为tag处理类要可能要对body进行操作。 {IJV(%E   
7rc^-!k  
Tag处理类不与body交互 I@a7AuOw  
9ulJZ\cQ  
如果tag处理类不与body交互,tag处理类应该实现Tag接口或从TagSupport中派生,如果body要被计算,那么doStartTag方法应返回 EVAL_BODY_INCLUDE,否则应返回SKIP_BODY。 =L9sb!  
f .rz2)o  
如果tag处理类要对body反复运算,则它应该实现IterationTag或从TagSupport中派生。如果tag处理类认为body还未计算完的话,那它的doStartTag方法和doAfterBody方法必须返回EVAL_BODY_AGAIN。 X^#48*"a  
 mQBq-;  
Tag处理类与body交互 <O&L2E @~f  
w`,[w,t  
如果tag处理类与body交互,那tag处理类应实现BodyTag接口或从BodyTagSupport中派生。这种tag处理类一般要实现doInitBody和doAfterBody方法。 }8p;w T!  
~;,]/'O  
Body允许一些方法来读写它的内容。Tag处理类可以调用body内容的getString或getReader方法来从body中提取信息,也可用 writeOut(out) 方法来将body的内容写入到out对象中。其中out对象通过tag处理类的getPreviousOut方法来获得。 iCao;Zb  
#O z<<G<  
如果body的内容需要被计算,那么doStartTag方法必须返回EVAL_BODY_BUFFERED,否则,它将返回 SKIP_BODY。 /sH3Rk.>  
9zEO$<e o  
doInitBody 方法 DIH.c7o  
Gk*Mx6|N  
此方法在body内容已经设好,但未被计算之前被调用。你可以根据不同的body内容来制定初始化策略。 |]HU$Gt S  
CN\SxK`,  
doAfterBody方法 fzRzkn:=  
b~  
此方法在body内容已被计算后进行调用。 /K:M ,q  
]<A|GY0q1  
和doStartTag方法一样,doAfterBody方法返回一个指示符指示是否要继续计算body,如果要继续计算,则doAfterBody应返回EVAL_BODY_BUFFERED,否则,它应返回SKIP_BODY。 @$gvV]dA  
*Eu ca~%=  
release 方法 rv1kIc5Za<  
Byyus[b'A  
tag处理类调用此方法将它的状态重置为初始状态,并释放所有的私有资源。 ej47'#EY  
$[}31=0  
BbA>1#i5]  
以下的例子读取body的内容(其中含有一条sql语句),然后将它传递给一个对象,让它进行查询。由于此处body不须重新计算,所以doAfterBody会返回SKIP_BODY。 s<H0ka@  
,(}7 ST  
<w(UDZ  
Public class QueryTag extends BodyTagSupport CtV$lXxup  
mfQQ<Q@  
{ %YM4x!6  
R{\vOw:*  
public int doAfterBody() throws JspTagException dY68wW>d|  
;FQAL@"Yj  
{ bdk"7N  
~4'e)g.hG  
BodyContent bc = getBodyContent(); 9 }iEEI  
N?U;G*G  
//将body的内容以字符串的格式提取出来 WmP"u7I4  
LpeQx\  
String query = bc.getString(); 1Z6<W~,1OM  
E< "aUnI  
//清除body YTpSR~!Rj  
\$T  
bc.clearBody(); 2PE|4zG  
YwQxN"  
try{ *oL?R2#7  
N\l\ M  
Statement stmt = connection.createStatement(); 2B3H -`  
~dC)EG  
Result result = stmt.executeQuery(query); (Ybc~M)z  
D3$PvX[f  
}catch(SQLException e){ ++-HdSHY  
$IA(QC_]AO  
throw new JspTagException(“queryTag: “ + e.getMessage() ); 2aX|E4F  
Q}d6+C  
return SKIP_BODY; LoSblV  
eZIqyw  
} ?<]BLkx  
=LDzZ:' X  
} 'U.)f@L#w  
3ox%1x NA  
H ifKa/}P8  
body-content元素 ;"-(QE?Mv  
b4ZZyw  
w&hgJ  
由于tag可能会有body,你必须用body-content元素来指定body内容的类型: E'j>[C:U  
X#'DS&{  
<body-content>JSP|tagdependent</body-content> 'Xoif"  
6x)7=_:0  
No>XRG+  
如果body的内容是定制的或内部的tag、脚本元素、或HTML广本,则归类为JSP类型。其他的类型,比如上面代码所述的?D?D将sql statement类传给 query tag的这种类型应该标为tagdependent。 #wK {G)J  
vm"LPwSk>  
注意:实际上body-content的值并不影响tag处理类对body内容的处理,它仅仅是被tag编辑工具用来描述此body的内容。 %%)"W n#`  
Hdw;=]-  
6O bB/*h  
用tags定义脚本变量 u\ro9l  
.LhIB?  
z85%2Apd  
tag处理类 BaZ$pO^  
Yrs7F.Y"  
ExeD3Zj  
tag处理类负责创建或设置页面中定义的脚本变量,用pageContext.setAttribute(name,value,scope)或pageContext.setAttribute(name,value)方法来实现。一般来说,tag处理类通过脚本变量的名称来获取它,脚本变量的名称一般可用get方法来获得。 F&%@p&  
t'|A0r$  
如果脚本变量的值依赖于tag处理类中的上下文中某一对象,那它可用pageContext.getAttribute(name,scope)方法来找到那个对象。一般的处理过程是tag处理类先找到脚本变量,再对其进行处理,然后用pageContext.setAttribute(name,object)的方法来设置它的新值。 Bha#=>4FU  
d00#;R  
对象的生存周期(scope)如下表: Oq@+/UWX  
p:Ry F4{b2  
对象的生存周期表 ?;zu>4f|  
O;z:?  
名字 n^B9Mh @  
可访问范围 aUa.!,_dh  
生存周期 )' +" y~  
5. 5<.")  
page `ltc)$  
当前页面 k\BJs@-  
一直有效,除非页面向客户提交响应或重定向到一个新页面 3u#bx1  
h/5|3  
request (hNTr(z  
当前页面或当前页面重定向到的页面 rR]U Ff  
一直有效,除非页面向客户提交响应 7aRtw:PQn  
nF>41 K  
session ?!^ow5"8  
当前页面或在同一浏览器窗口中的页面 5xC4lT/U  
一直有效,除非关闭当前浏览器、超时、网络故障 |a4cER.'2^  
J9eOBom8e<  
application i)y8MlC{  
整个web应用程序的所有请求 :dq.@:+<R  
一直有效,除非发生网络故障、服务器故障 ~k\Dde  
3.+TM]RYN  
提供关于脚本变量的信息 86Hg?!<i.  
s|F}Abx,^  
以下示例定义了一个名为“book”的脚本变量,用来访问程序中关于书的信息: ?C)a0>L  
M2H +1ic  
<bean:define id=”book” name=”bookDB” property=”bookDetails” type=”database.BookDetails” /> 2 j.6  
?+av9;Kg  
<font color=”red” size=”+2” > `ppyCUX  
fh_+M"Y0`  
<%= messages.getString(“CartRemoved”) %> |y9(qcKn$  
WoM;)Q  
<strong><jsp:getProperty name=”book” property=”title” /></strong> 0DtewN{Z  
kvcDa+#  
</font> ~MWI-oK  
\4Uhc3  
当包含此tag的JSP页面被编译时,jsp引擎会自动生成关于此book的同步的代码(同步可以避免几个客户同时访问此book时造成的冲突),要生成同步代码,jsp引擎需要知道此脚本变量的如下信息: $inlI_  
"Vh3hnS~  
· 脚本变量名称 JguPXHa0  
9gq+,g>E_  
· 脚本变量所属的类 ' ` _TFTO  
hr$Wt ?B  
· 此脚本变量是否引用了一个新的或已存在的对象 yq.<,b=87  
 _U.|$pU  
· 此脚本变量的有效性 VyX5MVh  
Ov8^6O  
有两种办法可以向jsp引擎提供关于脚本变量的信息:在TLD中定义variable子元素,或用tei-class子元素定义一个额外tag信息类。用variable最简单,但可能降低了一些灵活性。 =LXjq~p  
/pY-how%!  
Variable元素 fi%)520  
i>z_6Gax*[  
Variable元素有如下子元素: $7h]A$$Fv  
n*A?>NV  
· name-given ?D?D 给出的名字,是一个常量 (4o<U%3kGq  
&~mJ ).*  
· name-from-attribute?D?D 属性名,在编译时给出的属性名 LMKhtOZ?  
$UNC0 (4  
name-given或name-from-attribute两者必须选一,但以下子元素是可选的: b@QCdi,u  
{p\ll  
· variable-class?D?D变量的类型,缺省为java.lang.String。 }NjZfBQW`  
o|:c{pwq  
· declare?D?D此脚本变量是否引用了一个新对象,缺省为True。 c wNJ{S+  
>{6U1ft):  
· scope?D?D脚本变量的范围,缺省为NESTED。下表描述了scope的几种类型: Tp46K\}Uf  
R [ZY;g:p  
脚本变量的有效范围 e5RF6roxO  
[ Y+Ta,  
QPX&P{!g  
有效性 "; 1@f"kw  
方法 6am g*=]  
6ChFsteGFr  
NESTED IG+g7kDCY  
在tag标签的开始和结束之间 Qy ghNImp  
如果tag处理类实现BodyTag接口,则在doInitBody和doAfterBody中调用,否则在doStartTag中调用 vA3wn><  
Ez8k.]qu  
AT_BEGIN SzP`(}AU  
从tag标签的开始一直到页面结束 M*!WXQlud  
如果tag处理类实现BodyTag接口,则在doInitBody、doAfterBody和doEndTag中调用,否则在doStartTag和doEndTag中调用 {N3&JL5\"E  
azz=,^U#  
AT_END 8)lrQvZ  
从tag标签的结束一直到页面结束 rJZR8bo  
在doEndTag中调用 &(7=NAQsE  
]d67 HOyK  
以struts为例,它的bean:define标签的实现遵循JSP1.1规范,此规范要求使用额外tag信息类来定义脚本变量。Variable元素是JSP1.2规范中加入的。以bean:define标签为例,你可以定义如下variable元素: LZ34x: ,C  
zmU@ k  
<tag> t4iD<{4  
},n?  
<variable> SJB^dI**/d  
Nq9\2p  
<name-from-attribute>id</name-from-attribute> Vwu dNjL  
_tUh*"e&  
<variable-class>database.BookDetails</variable-class> Rk,'ujc  
ZDG~tCh=@  
<declare>true</declare> W#)X@TlE  
#M%K82"  
<scope>AT_BEGIN</scope> ;FQNO:NP  
?7>"ZGDe>  
</variable> H;R~d%!b  
FnKC|X  
</tag> 2E8G 5?qe)  
;j.-6#n  
额外tag信息类 ph}%Ay$  
^@3,/dH1 t  
如果要定义一个额外tag信息类,你要继承javax.servlet.jsp.TagExtraInfo类。一个TagExtraInfo类必须实现getVariableInfo方法,此方法返回一个叫VariableInfo的数组类,它包括如下信息: -Bl]RpHCe  
7Db}bDU1 |  
· 变量名 $xT9e  
HfZ^ED"}  
· 变量所属类名 c]h@<wnv  
%s497'  
· 此变量是否引用了一个新对象 /GVjesN  
PB *v45  
· 此变量的有效范围 d~AL4~}  
8>@JW]  
jsp引擎将一个名为data的参数传给getVariableInfo方法,data中包括tag标签中的所有“属性名?D?D属性值”对。它可以用来向VariableInfo对象提供脚本变量的名字和类名。 lb$_$+@Vr  
h%U}Y5Ps~  
以struts为例,它在bean:define标签中定义了一个名为DefineTei的额外tag信息类,用来向脚本变量提供信息。由于脚本变量的名称(book)和类名(database.BookDetails)是通过tag标签的属性来传递的,它们一般定义在VariableInfo的构建代码中,并且可用data.getAttributeString方法来得到这些信息。如果要允许book脚本变量能在从tag开始直到整个JSP页面结束的范围内都可用的话,那它的范围应设为AT_BEGIN。如下所示: [GPCd@  
J5(0J7C  
76bMy4re  
public class DefineTei extends TagExtraInfo dB6['z)2  
*|<T@BXn  
{ GeDI\-  
C{,^4Eh3r  
public VariableInfo[] getVariableInfo(TagData data) ufCpX>lNF  
c<,LE@ V  
{ d<+hQ\BF,  
~4pP( JP  
String type = data.getAttributeString(“type”); S)g:+P  
6I: 6+n  
If( type == null) @R}3f6@67  
}toe'6  
type = “java.lang.Object”; =\_gT=tZ  
Q-<Qm?  
return new VariableInfo[] { PW|=IPS  
S2DG=hi`GK  
new VariableInfo(data.getAttributeString(“id”), ?m5E Xe  
lP*n%Pn)  
type, 1 _Oc1RM   
MT"&|Og  
true, 'da 'WZG  
V*ao@;sD  
VariableInfo.AT_BEGIN) }% f7O  
-uWV( ,|  
}; /!2`pv  
SkMFJ?J/  
} [al$sCD]+  
x&*f5Y9hCi  
} 8q%y(e  
Pw| h`[h  
L-}J=n\  
注意:关于额外tag信息类的类名必须要在TLD中的tag标签下的tei-class子元素中定义。因此,DefineTei的tei-class中的定义看起来如下: 9Q^cE\j  
<tei-class> O >pv/Ns  
org.apache.struts.taglib.bean.DefineTagTei Yb-{+H8{J  
</tei-class> e*qGrg(E  
X3a9-  
:^PksR  
具有协作关系的tag hrtz>qN  
SF&2a(~s  
(T0MWp0  
tag通过共享对象来进行协作,JSP技术支持2种方式的对象共享。 );':aX j  
u1L^INo/  
第一种方法是使用pageContext对象进行对象的共享(可支持JSP页面和tag处理类之间的共享),如果在一个tag处理类中要调用由另一个tag处理类创建的对象,可调用pageContext.getAttribute(name, scope)方法。 3ZI7;Gw  
0W}qp?  
第二各方式的共享是对于tag之间有嵌套关系而言的,外层的tag所创建的对象对于内层的tag来说是可以共用的。这种形式的共享的好处是减少了可能存在的重名冲突。 *Q^ z4UY  
=V]0G,,\  
要访问一个嵌套tag创建的对象,tag处理类必须先找到此嵌套tag对象,可用TagSupport的静态方法 TagSupport.findAncestorWithClass(from, class)或TagSupport.getParent方法。前者在当不确定此tag是否为嵌套tag对象时使用。一旦它的父类被找到,它就能访问其所有动态或静态创建的对象。静态创建的对象是父类的成员,而动态创建的对象可能是父类的私有对象。诸如此类的对象可以用tag处理类的setValue方法来保存,用getValue方法来获得。 >xabn*Kq  
i?Pnyi  
下例阐述了以上两种共享对象的方法。在这个例子当中,一个查询tag检查一个名为connection的属性名是否在doStartTag中被设置。如果connection属性被设置,tag处理类从pageContext中得到这个connection对象。否则,此tag处理类先找到它的父tag处理类,然后从它的父tag处理类中找到connection对象。 ?9a%g\`?:  
6_4 B!  
i ? ~-%  
public class QueryTag extends BodyTagSupport w^ut,`yW R  
z,4mg6gt  
{ VO8rd>b4  
>P:X\5Oj  
private String connectionId; ~<f[7dBv  
E Izy  
public int doStartTag() throws JspException Z.Yq)\it  
v8*)^-Fx  
{ kFwFPK%B  
KF00=HE|]  
String cid = getConnection(); X0u,QSt' O  
{?eUAB<  
if(cid != null) 1*9.K'  
<- !1`@l>  
{ ,JE_aje7  
/W$i8g  
//存在一个connection id,使用它。 H #_Zv]  
>< $LV&  
connection = (Connection) pageContext.getAttribute(cid); u*G<?  
A}SGw.3  
} OQ&N]P2p  
)Q'E^[Ua  
else (tX3?[ii  
s:}? rSI  
{ nf/?7~3?[  
-3R:~z^L  
ConnectionTag ancestorTag = (ConnectionTag)findAncestorWithClass(this, h9)fXW  
W~'xJ  
ConnectionTag.class); qK a}O*  
&7f8\TG|  
if(ancestorTag == null) ]alc%(=  
n?.;*:  
{ 3$nK   
JP5e=Z<  
throw new JspTagException(“一个没有connection属性的查询标签必须被一个connection标记嵌套。”); t\K (zE  
hc3hU   
} kun/KY  
:J`@@H  
connection = ancestorTag.getConnection(); ::oFL#+  
93HVx#  
} 'd+fGx7i  
g0tnt)]  
} 0I)$!1~O)  
#m.e9MU  
} =EP`,zqn$9  
e{5?+6KH  
cjEqN8  
$+'H000x  
此查询标签在JSP页面中的调用形式可以从以下2种定义中任选一种: Cy]=Y  
iPTQqx-m$7  
xmv %O&0^}  
<tt:connection id=”con01” ...> ... </tt:connection> AU$~Ap*rsa  
ZwS:Te9-  
<tt:query id=”balances” connection=”con01” > 3F2IL)Hn  
X ."z+-eh  
SELECT account, balance FROM acct_table U=.PL\  
'dwT&v]@  
where customer_num = <%= request.getCustno() %> Af;Pl|Zh[  
R@\}iyM  
</tt:query> D*%am|QL  
XP@dg4Z=z  
jmID@37t  
g#J aw|N  
X&pYLm72;  
<tt:connection ...> ,-#MEr  
&:&89<C'  
<x:query id=”balances”> ST*h{:u&A  
!4vb{AH  
SELECT account, balance FROM acct_table Tn}`VW~  
zeHF-_{  
where customer_num = <%= request.getCustno() %> R |c=I }@F  
7Jf~Bn  
</x:query> 2tq2   
MxsLrWxm  
</tt:connection> 5naFnm7%  
N)X Tmh2v|  
OUv<a `0  
与此同时,在TLD中必须指定connection属性为可选的,定义如下: AHb_BgOU*  
<b:%o^  
<tag> Ga7E}y%  
E=s,-  
... Ay16/7h@hi  
}`"}eN @,  
<attribute> ,n/]ALz>~  
rwF$aR>9  
<name>connection</name> QH/py  
0\dmp'j]  
<required>false</required> F^yW3|Sb  
ra$:ibLN  
</attribute> ,X?/FAcb  
<~ smBd  
</tag>
描述
快速回复

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