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

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

级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
标准的JSP 标记可以调用JavaBeans组件或者执行客户的请求,这大大降低了JSP开发的复杂度和维护量。JSP技术也允许你自定义taglib,其实换句话说,taglib可以看成是对JSP标记的一种扩展,正如xml是对html的一种扩展一样。taglib通常定义在tag标签库中,这种标签库存放着你自己定义的tag标签。简而言之,如果使用taglib,那么你可以设计自己的JSP标记! Z\xR+3  
KMznl=LF  
一般来说,自定义tag标签主要用于操作隐藏对象、处理html提交表单、访问数据库或其它企业级的服务,诸如邮件和目录操作等等。自定义tag标签的使用者一般都是那些对java编程语言非常精通,而且对数据访问和企业级服务访问都非常熟悉的程序员,对于HTML设计者来说,使得他可以不去关注那些较复杂的商业逻辑,而将精力放在网页设计上。同时,它也将库开发者和库使用者进行合理分工,自定义tag标签将那些重复工作进行封装,从而大大提高了生产力,而且可以使得tag库可用于不同的项目中,完美地体现了软件复用的思想。 uj&^W[s  
l_u1 ~K  
在这篇文章中,我们主要讨论: q+t*3;X.  
fk P@e3  
· 什么是自定义tag标签? `6!l!8 v  
ReP7c3D>p  
· 怎么使用tag标签? 6@!<' l%z  
DJrE[wI  
o 声明要使用的tag库 <!&nyuSz  
PBr-< J  
o 找到与之对应的tag处理类 kAf:_0?6  
4NwGP^ n  
o tag标签的类型 Y{@ez  
&^1DNpUZ  
· 自定义tag标签 _C"W;n'  
IZ3w.:A  
o tag处理类 uKh),@JV  
]BCH9%zLj  
o tag库描述 gOO\` #  
Hbx=vLQ6  
o tag标签示例 b}o^ ?NtA  
Yv9(8  
o 带属性的tag 1d|+7  
1I KDp]SN  
o 带body的tag iO3@2J  
Tm[IOuhM'?  
o 定义了脚本变量的tag j$zw(EkN  
,jbj-b(  
o 具有协作关系的tag vhZpYW8  
d/- f]   
· 自定义tag标签 O} QTg  
+=Crfvt  
o 一个迭代tag的例子 z)q9O_g9  
Q9X_aB0  
o 一个模板tag库 GKtG#jZ&  
sBq @W4  
o tag处理类到底是怎样被调用的? qJVW :$1q  
<"AP&J'H  
J^ryUO o}b  
什么是自定义的tag? ,S:LhgSP  
Fc7mAV=  
一个自定义的tag标签是用户定义的一种JSP标记。当一个含有自定义的tag标签的JSP页面被jsp引擎编译成servlet时,tag标签被转化成了对一个称为tag处理类的对象进行的操作。于是当JSP页面被jsp引擎转化为servlet后,实际上tag标签被转化成为了对tag处理类的操作。 @xB"9s  
e!ar:>T  
自定义tag标签有很多特色,诸如: vz,l{0 v  
Yc/rjEn7O  
· 可以在JSP页面中自定义tag标签的属性 #G|iEC0C  
<y\>[7Y  
· 访问JSP页面中的所有对象 (5;w^E9*n;  
1Xt% O86  
· 可以动态地修改页面输出 p-y,OG  
nod?v2%   
· 彼此这间可以相互通信。你可以先创建一个JavaBeans组件,然后在一个tag中调用此JavaBeans组件,同时可以在另一个tag中调用它。 jUZ84Gm{  
 _*9eAeJ  
· tag允许相互嵌套,可以在一个JSP页面中完成一些复杂的交互。 RXb+"/   
%IW=[D6Tg  
&voyEvX/S  
使用tag标签 {*`qL0u]^  
3uz@JY"mK  
$=TFTSO  
本节主要描述怎样在JSP页面中使用tag标签,以及tag标签的不同类型。 3rTYe6q$U  
|JSj<~1ki  
要使用tag标签,JSP程序员必须做2件事: L/"XIMI*Xg  
;a XcGa  
· 声明此tag标签的tag库 >"{3lDyq-  
Qy*`s  
· 实现此tag标签 %w=*4!NWb  
/^ i7^  
声明tag标签所在的tag库 ON~SZa  
 4EJ  
如果要使用tag标签,则应用JSP的taglib指示符来指定其tag库(注意:taglib要在在使用此tag标签之前声明) nxKV7d@R  
O2q`2L~  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> ]P<u^ `{*  
cc*A/lD  
uri属性定义了唯一的标签库描述(以下简称TLD),它可以是直接是tld文件名或一个独一无二的名字。prefix是用来区别其它TLD中和本TLD中有重名的tag的一种手段。 %/CCh;N#  
't{~#0d=  
TLD必须以.tld作为扩展名,并且存放在当前应用的WEB-INF目录或其子目录下。你可以通过它的文件名直接引用它,也可以通过别的方式间接地引用它。 g a? .7F  
>jME == U0  
以下taglib指示符直接引用一个TLD: BEx? bf@|]  
dG'aJQw  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> H.hF`n  
>>Z.]  
以下的taglib指示符通过一个逻辑名称间接地引用一个TLD: PR|F-/o  
"b8<C>wY  
<%@ taglib uri=”/tutorial-template” prefix=”tt” %> z^T/kK3I  
.v9#|d d+  
如果是间接引用TLD的话,那你必须还要在web.xml中定义此逻辑名称与tld文件之间的映射,具体做法是在web.xml中加入一个名为taglib的元素: >93vMk~hU  
MVs@~=  
<taglib> [, 3o  
0g,;Yzm  
<taglib-uri>/tutorial-template</taglib-uri> cclx$)X1X  
'mXf8   
<taglib-location> A/|To!R  
yJ c#y   
/WEB-INF/tutorial-template.tld 5(^&0c>P  
|yx]TD{~P  
</taglib-location> Q.>@w<[!L  
<[@AMdS  
</taglib> )/1AF^ E  
|`1lCyV\tE  
D kl4 ^}  
实现此tag标签 9i*t3W71]  
a"EX<6"  
P B_ +:S^8  
为了实现tag标签,你有2种方法来存放tag处理类。一、让tag处理类以.class的方式存放于当前应用的WEB-INF/class子目录下,二、如果tag处理类是以JAR包的形式存在的话,那可以放在当前应用的WEB-INF/lib目录下,如果tag处理类要在多个应用中共享,那么它就应放在jsp服务器上的common/lib目录下,对于tomcat来说,就是tomcat/common/lib目录下。 fr#Y<=Jo  
*8M 0h9S$  
<kN4@bd;  
tag标签类型 l<>syHCH;L  
[`BMi-WQ  
+)h*)  
自定义的tag标签遵循XML语法。它有一个开始标记和一个结束标记,有的还有body(即文本节点): s3>,%8O6  
] +<[D2f  
<tt:tag> 7IB<0  
WUm8 3"  
body D>|m8-@]  
/bv1R5  
</tt:tag> Q0K2md_%x  
7xTgG!>v  
\  $;E,  
一个不带body的tag标签如下: RZ-=UIf  
zc01\M  
<tt:tag /> J]yUjnQ[h  
?& qMC  
9fj3q>Un,  
简单的tag标签 7g8}]\i+  
r: ]t9y>$<  
一个没有body和属性的tag标签如下: HT0VdvLw  
thy)J.<J  
<tt:simple /> *pK bMG#  
`U?" {;j {  
+!h~T5Ck  
带属性的tag标签 {+%|n OWV  
Z0uo. H@.N  
}^U7NZn<"  
自定义标签可以有自己的属性。属性一般在开始标记中定义,语法为 attr=”value”。属性的作用相当于自定义标签的一个参数,它影响着tag处理类的行为。你可以在TLD中详细定义它。 @iwVU]j  
D!Pv`wm  
你可以用一个String常量给一个属性赋值,也可以通过表达式给它赋值,如<%= ...%>。以struts为例,它的logic:present标签就是用的String常量来给属性赋值: v W=$C  
y.(Yh1  
<loglic:present parameter = “Clear”> iZ}Afj  
cH%qoHgx  
而另一个标签logic:iterate是用表达式来给属性赋值: Ezsb'cUa(  
'APtY;x^{  
<logci:iterate collection=”<%= bookDB.getBooks() %>” 6<X.]"u+E~  
_<s[HGA`z  
id=”book” type=”database.BookDetails”> un([3r  
44C"Pl E u  
}N[|2n R'  
带body的tag标签 }%Mj`Bh  
W^#HR  
一个自定义标签可以包含其它自定义标签、脚本变量、HTML标记或其它内容。 {9:[nqX  
FcVQ_6  
在下述例子中,此JSP页面使用了struts的logic:present标签,如果些标签定义了parameter=”Clear”的属性,则将清除购物车的内容,然后打印出一条信息: P'%#B&LZo  
E[q:65xl  
<logic:present parameter=”Clear”> E-gI'qG\(  
.' foS>W=t  
<% cart.clear(); %> tljZE)  
XrP'FLY o  
<font color=”#ff0000” size=”+2”><strong> HYU-F_|N=  
vP6NIcWC3  
你选择了清除购物车! UdO(9Jc5^  
e.-+zkQ8EI  
</strong></font> cj K\(b3  
[PG#5.jwQ  
</logic:present> " kp+1sG8  
} DQ<YF+  
@uA=v/>+  
到底是用属性还是用body来传递信息? O?\UPNb:K  
#J=^CE  
如上所述,我们既可以通过属性,也可以通过body来传递信息。但一般来说,比较简单的类型,如字符串或简单表达式最好采用属性来传递信息。 v~E\u  
)S?.YCv?  
?.Iau/  
定义脚本变量的tag标签 QA|87alh  
Qp>'V<%m-  
所谓脚本变量,是指JSP中可以调用的变量或对象。它可由tag标签产生。以下示例阐述了一个tag标签定义了一个名为tx的由JNDI所定义的事务处理对象。脚本变量可以是ejb对象、事务、数据库连接等等: 1i=lJmr  
4`E[ WE:Q  
<tt:lookup id=”tx” type=”UserTransaction” name=”java:comp/UserTransaction” /> t&|M@Ouet  
>-8r|};+  
<% tx.begin(); %> QIl=Ho"c  
 -c%#Hd  
... ,~8&0p  
P:D@ 5  
qZQB"Q.*  
具有协作关系的tag标签 *^[m?3"W  
@yV.Yx"p_  
自定义tag标签之间可以通过共享对象来实现协作。在下述例子中,标签tag1创建了一个名为obj1的对象,在标签tag2仍可以重复使用obj。 Yr!@pHy  
)R %>g-dw  
<tt:tag1 attr1=”obj1” value1=”value” /> B ]*v{?<W  
T{ WJf-pI  
<tt:tag2 attr1=”obj1” /> ZkWX4?&OMt  
JG^fu*K  
在以下这个例子当中,如果外层的tag标签创建了一个对象,那么其内层的所有tag标签都可以使用这个对象。由于这样产生的对象没有一个指定的名字,那么就可以将少重名的冲突。这个例子阐述了一系列协作的嵌套对象。 wFbw3>'a9  
LV}Z[\?   
<tt:outerTag> ohEIr2  
;]gj:6M  
<tt:innerTag /> +az=EF  
9 +1}8"~  
</tt:outerTag> #*;G8yV  
uwI$t[  
s!73To}>  
Tag处理类 I{nrOb1G(  
q,;8Ka )  
! 2=m |,  
Tag处理类必须实现Tag接口或BodyTag接口,不过现在一般都流行从TagSupport或BodyTagSupport类中继承,这些类或接口都可以在javax.servlet.jsp.tagext包中找到。 ]?p 9)d=%<  
MS5X#B  
当JSP引擎看到自己的JSP页面中包含有tag标签时,它会调用doStartTag方法来处理tag标签的开头,调用doEndTag方法来处理tag标签的结束。 &VPfI  
(#e,tu  
下表说明不同类型的tag所需要不同的处理过程: ]mzghH:E  
Mo'6<"x  
Tag处理类的方法 M{GT$Q  
r..&6-%:N  
Tag标签类型 m!Y4+KTwD`  
所调用的方法 mETGYkPUa  
C[ma!he  
基本标签 <@.!\  
doStartTag, doEndTag, release \u4`6EYF?  
yC&u^{~BC  
带属性的标签 zrDcO~w  
doStartTag, doEndTag, set/getAttribute1...N, release =Ju%3ptH0  
q%S^3C&  
带内容的标签 JnE\z*NB  
doStartTag, doEndTag, release y.>1r7  
Z\[6 'R4.#  
带内容的标签,且内容重复循环 P>}OwW  
doStartTag, doAfterBody, doEndTag, release bU4l|i;j  
%ztv.K(8  
带内容的标签,且内容与JSP交互 '_q&~M{  
doStartTag, doEndTag, release, doInitBody, doAfterBody, release t~v_k\` {  
PAD&sTjE*  
一个tag处理类可以通过javax.servlet.jsp.PageContext来与JSP交互,通过javax.servlet.jsp.PageContext类,tag处理类可以访问JSP中的request、session和application对像。 Q]1s*P  
yDapl(  
如果tag标签是互相嵌套的,那内层的tag处理类可以通过它的parent属性来访问上层的tag处理类。 5M v<8P~  
QZwZ4$jkiO  
一般情况都将所有的tag处理类打成了JAR的包,以便于发布。 tkIpeL[d  
+b sc3  
S1I# qb  
Tag库描述(简称TLD) GI5#{-)  
^\ku}X_ [?  
Hb&C;lk  
Tag库是用xml语言描述的,TLD包括了tag库中所有tag标签的描述,它一般用来被jsp服务器用来校验tag的语法正确性,或者被jsp开发者用来开发新的标签。 %\f<N1~*  
`RlMfd  
TLD的文件扩展名必须为.tld,而且必须放在当前WEB应用的WEB-INF目录或其子目录中。 Mni@@W  
Zjkg"  
一个TLD的内容的开头必须遵守标准的XML开头,用于描述DTD和xml的版本,例如: mXwDB)O{)  
r=gF&Og,?  
<?xml version="1.0" encoding="ISO-8859-1" ?> zI7iZ"2a  
Um~DA  
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd"> BMdcW MYU\  
TLD必须以<taglib>来作为它的根元素,<taglib>的子元素如下表: he! Uq%e  
P=<>H9p:o  
@ JfQ}`  
<taglib>的子元素 ThiM6Hb  
.Lm0$o*`  
Element ){<qp  
Description  9dCf@5]  
eWGaGRem  
tlib-version ET0^_yk  
Tag库的版本 AfT;IG%Gt  
=/m$ayG  
jsp-version 'wA4yJ<  
Tag库所需要的jsp的版本 { Ba_.]x  
]G}:cCpd+a  
short-name " ?=$(7uc  
助记符,tag的一个别名(可选) fR&x5Ika0  
X1XmaO% A  
uri (zml704dI)  
用于确定一个唯一的tag库 AA XQ+!  
WRqpQEY  
display-name ' OXL'_Xl  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) sl_f+h0  
TcpaZ 'x  
small-icon Ake$M^Bz  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) Yln[ZmK9g  
!NO)|N>  
large-icon jaL#  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) /k.?x]Ab  
^&7gUH*v  
description '/F%  ff  
对tag库的描述(可选) 2-dEie/{'  
q uL+UFuM  
listener 7r{159&=  
参见下面listener元素 |wM<n  
!B/5@P  
tag MLvd6tIv,  
参见下面tag 元素 24I\smO  
+>QD4z#  
Listener元素 O`f[9^fN  
5 \iX%w@  
一个tag库可能定义一些类做为它的事件侦听类,这些类在TLD中被称为listener 元素,jsp服务器将会实例化这些侦听类,并且注册它们。Listener元素中有一个叫listener-class的子元素,这个元素的值必须是该侦听类的完整类名。 PTH'-G  
-\&b&;_  
Tag元素 lho0Xy gn  
FT6~\9m(  
每个tag元素在tag库中都要指出它的名字、类名、脚本变量、tag的属性。其中脚本变量的值可以直接在TLD中定义或通过tag附加信息的类来取得。每个属性描述了这个属性是否可以省略,它的值是否可以通过<%= …%>这样的JSP语法来获得,以及属性的类型。 }u+cS[#-  
5H2Ugk3  
每一个tag在TLD中对应一个tag元素,下表是tag元素的子元素: ],F@.pg  
}u.I%{4  
Tag元素的子元素 y_M,p?]^,  
l.uW>AoLh  
元素名称 5ajd$t  
描述 rm%MQmF  
534DAhpD=.  
name ZC97Z sE  
独一无二的元素名 7|DPevrk  
[5-3PuT&9  
tag-class !bBx'  
Tag标签对应的tag处理类 mvu$  
yq6:7<  
tei-class %\B@!4]  
javax.servlet.jsp.tagext.TagExtraInfo的子类,用于表达脚本变量(可选) vAqVs5 j  
\ZtF,`Z  
body-content ?t [C?{'  
Tag标签body的类型 i:2e J.  
@ r/f  
display-name Q#PkfjXS  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) lnnT_[ni.  
IoCi(N;  
small-icon | $D`*  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) ;<H\{w@D  
ki ?ETC  
large-icon 9+!"[  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) lpnPd{kE  
BM[jF=0  
description o)+Uyl   
此tag标签的描述 j/, I)Za  
y eWB.M~X  
variable  zt2#6v  
提供脚本变量的信息(同tei-class)(可选) H{g&yo  
qa,i:T(w  
attribute #@:GLmD%  
Tag标签的属性名 j4+kL4M@H  
xeW}`i5_w  
以下章节介绍对于不同类型的tag,如何具体地实现它们。 evlz R/  
uF\ ;m.  
c^7QiTt_  
简单的tag ]5+<Rqdbg  
R] " jr  
 h@+(VQ  
tag处理类 &d=ZCaP  
O~c\+~5M*  
简单的tag处理类必须实现Tag接口的doStartTag和doEndTag方法。当jsp引擎碰到tag标签的开头时,doStartTag被调用,因为简单的tag没有body,所以此方法将返回 SKIP_BODY。当jsp引擎碰到tag标签的结尾时,doEndTag被调用,如果余下的页面还要被计算,那它将返回EVAL_PAGE,否则将会返回SKIP_PAGE。 o{OY1 ;=6  
Eb89B%L62G  
以下是例子:对于标签 <tt:simple /> ,它的tag处理类实现如下: HME`7dw?  
)KKmV6>b  
B`?5G\7L  
public SimpleTag extends TagSupport Fjw+D1q.  
.-}F~FES  
{ lj 2OOU{  
 K2D, *w  
public int doStartTag() throws JspException =6xxZy[  
~#|Pe1Y  
{ f5,!,]XO  
sh;>6xB  
try{ dPmNX-'7  
%<h+_(\h  
pageContext.getOut().print(“Hello.”); wqAj=1M\  
7i88iT  
}catch(Exception e){ Q6hWHfS  
dReJ;x4  
throw new JspTagException(“SimpleTag: “ + e.getMessage()); ?y2v?h"  
1{?5/F \ +  
} +J7xAyv_Oz  
%ql2 XAY  
return SKIP_BODY; Pvz\zRq  
Y(C-o[-N  
} v|wO qS  
.NT9dX  
public int doEndTag() -$o4WSd~  
oNp(GQ@0  
{ Z?)=4|  
CYZ0F5+t  
return EVAL_PAGE; n0opb [?  
0l2@3}e  
} fu{.Ir  
~c${?uf   
} {J]x81}*;  
!c;BOCqa  
M1J77LfS8  
注意:如果tag标签没有内容的话,那必须定义body-content元素为空,例如 a$]i8AeG  
jn+BH3e  
<body-content>empty</body-content> Bb*P);#.K  
-}9>#<v  
~ }?*v}  
带属性的tag标签
评价一下你浏览此帖子的感受

精彩

感动

搞笑

开心

愤怒

无聊

灌水
级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
只看该作者 1 发表于: 2007-01-01
tag处理类 X% X &<  
E @7);i5K  
对于tag标签的每个属性,你必须依照JavaBeans规范来定义其属性,以及get和set方法。以struts的logic:present 标签为例, x#}{z1op9  
HB, k}Q  
<logic:present parameter=”Clear”> G$-[(eu -  
;CLOZ{  
与此相应,此tag处理类应有如下方法和定义: O^KIB%}fu  
?k+>~k{}a  
s}bv o  
protected String parameter = null; ,O`~ D~$  
c&I"&oZ@&  
public String getParameter() rA[wC%%  
LW*v/`@  
{ #T$yQ;eQ  
W \XLf,_+  
return this.parameter;  I6rB_~]h  
R>R8LIZZc  
} 3h`_Qv%g  
Jo4iWJpK  
public void setParameter(String parameter) YK)e  
]B3f$;W  
{ ;P9cjfSn  
@w73U; 9\  
this.parameter = parameter; G1G*TSf  
Lb}$)AcC  
} GDY=^r  
 $M|  
uc]`^,`2/  
注意:如果你的属性名为id,而且你的tag处理类是从TagSupport类继承的,那你就不需要定义它的属性和set和get方法,因为他们早已在TagSupport被定义过了。 B;c2gu  
 C^*3nd3  
Attribute元素 k%%0"+y#a  
l#fwNM/F  
对于tag标签的每个属性,你必须定义它是否必须的,它的值是否可以用诸如<%= …%>的表达式来获得,以及它的类型(可选),如果不指定它的类型,那就默认为是java.lang.String类型。如果rtexprvalue元素被定义为true或yes,那么在type元素中就定义了attribute的返回类型。 @ ('/NjTZ  
CJe~>4BT  
<attribute> 4^_'LiX3[  
9qI#vHA  
<name>attr1</name> "g:1br?X,9  
jP}Ix8vc=  
<required>true|false|yes|no</required> #}S<O_  
R?iC"s!  
<rtexprvalue>true|false|yes|no</rtexprvalue> T.pc3+B8N  
[(*?  
<type>attribute的返回类型(只用当rtexprvalue为真是才有效)</type> Y>Fh<"A|$  
2k M;7:  
</attribute> Eal*){"<,?  
\^x`GsVy  
如果tag的某个属性不是必须的,那tag处理类会自动提供一个缺省值。 E-Y4TBZ*  
kV:T2}]|H  
例如,在logic:present这个tag标签中定义了一个属性叫parameter,但它不是必须的,而且它可以被诸如<%= …%>的表达式来赋值。 UZx8ozv'  
,f}u|D 3@  
<tag> !yD$fY  
tA{h x -  
<name>present</name> x*! %o(G  
\EW<;xq  
<tag-class>org.apache.struts.taglib.logic.PresentTag</tag-class> qu%}b>  
)Y:C'*.r  
<body-content>JSP</body-content> ,vB~9^~  
x};sti R  
qyL!>kZr@  
SGP)A(,k9  
<attribute> 8:fq!m  
|syvtS{  
<name>parameter</name> x Tf|u  
1<;G oC"  
<required>false</required> mOfTq] @B  
k\Z7Dg$\D  
<rtexprvalue>true</rtexprvalue> :%>TM/E N  
d8.A8<wUr  
</attribute> ~PyZh5x  
A5go)~x\  
'+v[z=.8]  
_B7+n"t\r  
</tag> "=,IbC  
)`K!XX$%  
dO4J f9)  
属性元素的校验 p(. z#o#  
I R~szUY6  
QC6:ZxP  
有关于tag标签的有效值可以从tag库的说明文档中获得,当JSP页面被编译时,jsp引擎会强制性地参照TLD中定义的规则进行检查。 -lS(W^r4  
w5;d/r<q  
还有一个方法也可以进行属性元素的校验,就是先继承类TagExtraInfo,然后调用它的isValid方法。这个类同时也起到提供tag中定义的脚本变量信息的作用。 p|Qn?^C:  
*K;s*-|U  
IsValid方法通过TagData对象来传递属性信息,它包括着tag的所有的属性名-值的信息。由于校验发生在运行时刻,因此这个属性的值将被赋值为TagData.REQUEST_TIME_VALUE。 e[Jh7r>'  
..Bf-)w  
例如tag标签<tt:twa attr1=”value1” />在TLD中定义如下: rw.DKM'  
rIeOli:<  
<attribute> LC})aV|  
|p`}vRv Uh  
<name>attr1</name> nQ#NW8*Fs  
ZoR6f\2M  
<required>true</required> { t@7r  
6[Wv g  
<rtexprvalue>true</rtexprvalue> Axw+zO  
h^'+y1  
</attribute> _b9>ZF~  
rA /T>ZM  
&]O^d4/  
这个定义说明了attr1能在运行期间被赋值。 X#Hl<d2  
`\yQn7 Oq  
以下的isValid方法检查attr1属性的值是否属于Boolean类型。注意由于attr1能在运行刻被赋值,那么isValid方法必须检查tag用户是否对此tag进行了运行时刻赋值。 Qv]>L4PO  
_2X6c,  
*_@$ "9  
Public class TwaTEI extends TagExtraInfo X3m)  
M\9+?  
{ ,:8 oVq>?  
$0*D7P^8  
public boolean isValid(Tagdata data) /_r`A  
AI]lG]q8  
{ B/I1<%Yk  
`t>:i!s/  
Object o = data.getAttribute(“attr1”); RG:_:%@%}  
#6@4c5{2=4  
If(o != null && o != TagData.REQUEST_TIME_VALUE) \G2PK&)F  
K"8!  
{ #N'bhs  
t'[`"pp=  
if( ( (String)o).toLowerCase().equals(“true”) || ~z'Y(qG  
H` h]y  
((String)o).toLowerCase().equals(“false”) ) h/]));p  
dg#w!etB  
return true; R%"'k<`#  
A`*Sx"~jdx  
else HjY! ]!4p  
[I,s:mn  
return false; y>0Gmr  
Jk57| )/  
} T@d4NF#  
O@a7MzJ  
else O+t'E9Fa  
{Rq5=/b  
return true; G%>M@nYUE  
i93^E~q]  
} |eqp3@Y1E  
|y4j:`@.  
} /L=Y8tDt  
as"@E>a  
@b{$s  
带body的tag wZt2%+$6m  
\hP.Q;"MtO  
2FQTu*p&B  
tag处理类 >aT~ G!y  
7GRPPh<4  
a}[rk*QmZ  
如果tag标签含有内容,那处理方式会略微有些不同,而且还要视tag处理类是否要与body交互的情况而定。如果要与body交互,那我们认为tag处理类要可能要对body进行操作。 M/kBAxNIC|  
iUlSRfrC$#  
Tag处理类不与body交互 q^6l`JJ  
8|tnhA]~  
如果tag处理类不与body交互,tag处理类应该实现Tag接口或从TagSupport中派生,如果body要被计算,那么doStartTag方法应返回 EVAL_BODY_INCLUDE,否则应返回SKIP_BODY。 uP.dCs9-  
bycnh  
如果tag处理类要对body反复运算,则它应该实现IterationTag或从TagSupport中派生。如果tag处理类认为body还未计算完的话,那它的doStartTag方法和doAfterBody方法必须返回EVAL_BODY_AGAIN。 Zou;o9Ww  
a~Yq0d?`D  
Tag处理类与body交互 %v[KLMo'(  
D&1(qi=x&  
如果tag处理类与body交互,那tag处理类应实现BodyTag接口或从BodyTagSupport中派生。这种tag处理类一般要实现doInitBody和doAfterBody方法。 bT`et*]  
^G NL:D%6d  
Body允许一些方法来读写它的内容。Tag处理类可以调用body内容的getString或getReader方法来从body中提取信息,也可用 writeOut(out) 方法来将body的内容写入到out对象中。其中out对象通过tag处理类的getPreviousOut方法来获得。 36}&{A  
V0xO:7G^  
如果body的内容需要被计算,那么doStartTag方法必须返回EVAL_BODY_BUFFERED,否则,它将返回 SKIP_BODY。 EAoq2_(`a  
j:U6q,f]  
doInitBody 方法 =nv/ r  
\pXo~;E\  
此方法在body内容已经设好,但未被计算之前被调用。你可以根据不同的body内容来制定初始化策略。 *mn"G K6  
7=a e^GKo  
doAfterBody方法 _% i!LyG  
E+J+fi  
此方法在body内容已被计算后进行调用。 Ehq [4}  
|OIU)53A-  
和doStartTag方法一样,doAfterBody方法返回一个指示符指示是否要继续计算body,如果要继续计算,则doAfterBody应返回EVAL_BODY_BUFFERED,否则,它应返回SKIP_BODY。 Se>v|6  
h]&o)%{4  
release 方法 _7 ^:1i~:.  
<(l`zLf4p  
tag处理类调用此方法将它的状态重置为初始状态,并释放所有的私有资源。 YwZ ]J  
}brBhe8a  
0B"_St}3D  
以下的例子读取body的内容(其中含有一条sql语句),然后将它传递给一个对象,让它进行查询。由于此处body不须重新计算,所以doAfterBody会返回SKIP_BODY。 w!OYH1ds]_  
uCc5)  
IEY\l{s  
Public class QueryTag extends BodyTagSupport YcW) D  
Z61L;E  
{ Px&)kEQ  
`Dp4Z>| K  
public int doAfterBody() throws JspTagException f& Vx`oj  
&U\//   
{ qUk-BG8^  
}O2P>Z?V  
BodyContent bc = getBodyContent(); luJNdA:t&  
De<i 8/^=  
//将body的内容以字符串的格式提取出来 GjbOc   
Kf`/ Gc!  
String query = bc.getString(); [Xww`OUsh  
L$ZsNs+  
//清除body PoD/i@  
&;U F,  
bc.clearBody(); p,14'HS%@  
I7W?}bR*6  
try{ v.c.5@%%o  
*S'?u_Y7  
Statement stmt = connection.createStatement(); h$p}/A  
oz7=1;r  
Result result = stmt.executeQuery(query); Qjmo{'d  
.x1.`Y   
}catch(SQLException e){ tg7QX/KX  
_o==  
throw new JspTagException(“queryTag: “ + e.getMessage() ); TWdhl9Ot  
Tn?D~?a*O  
return SKIP_BODY; u/%Z0`X  
a\KM^jrCD  
} cCcJOhk|d  
j9.%(*  
} izLB4pk$  
[XkWPx`  
B?ipo,2~{  
body-content元素 ps*iE=D  
n(_wt##wE~  
Z8Tb43?  
由于tag可能会有body,你必须用body-content元素来指定body内容的类型: Ss:'H H4  
gi+FL_8CzU  
<body-content>JSP|tagdependent</body-content> !ZY1AhGZ  
y:k7eE"  
S";}gw?r6  
如果body的内容是定制的或内部的tag、脚本元素、或HTML广本,则归类为JSP类型。其他的类型,比如上面代码所述的?D?D将sql statement类传给 query tag的这种类型应该标为tagdependent。 Eo@rrM:  
t-Ble  
注意:实际上body-content的值并不影响tag处理类对body内容的处理,它仅仅是被tag编辑工具用来描述此body的内容。 t-SZBNb  
AvB21~t&]  
.e\PCf9v  
用tags定义脚本变量 Nx!7sE*b$1  
,My'_"S?  
 p4P"U  
tag处理类 MR zY<MD  
yO@@-)$[y  
&UAYYH  
tag处理类负责创建或设置页面中定义的脚本变量,用pageContext.setAttribute(name,value,scope)或pageContext.setAttribute(name,value)方法来实现。一般来说,tag处理类通过脚本变量的名称来获取它,脚本变量的名称一般可用get方法来获得。 HcpAp]L)  
$5@[l5cJU;  
如果脚本变量的值依赖于tag处理类中的上下文中某一对象,那它可用pageContext.getAttribute(name,scope)方法来找到那个对象。一般的处理过程是tag处理类先找到脚本变量,再对其进行处理,然后用pageContext.setAttribute(name,object)的方法来设置它的新值。 ]ClqX;'weJ  
y2nT)nL  
对象的生存周期(scope)如下表: ]'Gz~Z%>F  
K{XE|g  
对象的生存周期表 Mtn{63cK  
uJa.]J~L=  
名字 <&HHo>rl  
可访问范围 ;8cTy8  
生存周期 ek d[|g  
xu@xP5GB^  
page WA5.qw  
当前页面 #-l+c u{  
一直有效,除非页面向客户提交响应或重定向到一个新页面 =[0| qGzg  
q-S#[I+g  
request ]2_=(N\Kt  
当前页面或当前页面重定向到的页面 /xd|mo)D  
一直有效,除非页面向客户提交响应 cDz^jC   
C1OiMb(:  
session c=re(  
当前页面或在同一浏览器窗口中的页面 3pyE'9"f6  
一直有效,除非关闭当前浏览器、超时、网络故障 4W=fQx]  
fIn^a 3TV  
application O 2/_$i[F  
整个web应用程序的所有请求 | NyANsI  
一直有效,除非发生网络故障、服务器故障 <slrzc_>&  
'@1C$0tx  
提供关于脚本变量的信息 sVe<l mL  
.>2]m[53  
以下示例定义了一个名为“book”的脚本变量,用来访问程序中关于书的信息:  xF*i+'2  
xrkR)~ E  
<bean:define id=”book” name=”bookDB” property=”bookDetails” type=”database.BookDetails” /> +5GPU 9k  
~DS.b-E  
<font color=”red” size=”+2” > v3wq-  
| g"K7XfM4  
<%= messages.getString(“CartRemoved”) %> ED>P>Gg  
'Jd*r(2d  
<strong><jsp:getProperty name=”book” property=”title” /></strong> W9S6 SO^\  
.u]d5z BR  
</font> v=DC3oh-  
u R]8ZT")  
当包含此tag的JSP页面被编译时,jsp引擎会自动生成关于此book的同步的代码(同步可以避免几个客户同时访问此book时造成的冲突),要生成同步代码,jsp引擎需要知道此脚本变量的如下信息: Dn`  
z~ua#(z1S  
· 脚本变量名称 V14+?L  
GQ sE5Vb  
· 脚本变量所属的类 SQ<{X/5  
k&npC8oA  
· 此脚本变量是否引用了一个新的或已存在的对象 3;AJp_;  
I~nz~U:ak  
· 此脚本变量的有效性 Lzx2An@R  
T&j:gg  
有两种办法可以向jsp引擎提供关于脚本变量的信息:在TLD中定义variable子元素,或用tei-class子元素定义一个额外tag信息类。用variable最简单,但可能降低了一些灵活性。 pk6<wAs*?#  
A>)Ced!  
Variable元素 RQ4+EW 1G  
|gU)6}V@  
Variable元素有如下子元素: BN6cu9a  
EtQ:x$S_  
· name-given ?D?D 给出的名字,是一个常量 24\^{3nOK  
cI-@nV  
· name-from-attribute?D?D 属性名,在编译时给出的属性名 *DvQnj  
i/ PL!'oq  
name-given或name-from-attribute两者必须选一,但以下子元素是可选的: 1/%5pb2\  
onm" 7JsO'  
· variable-class?D?D变量的类型,缺省为java.lang.String。 Ql"~ z^L  
*a-KQw  
· declare?D?D此脚本变量是否引用了一个新对象,缺省为True。 \5j#ad  
#$l:%  
· scope?D?D脚本变量的范围,缺省为NESTED。下表描述了scope的几种类型: >` u8(  
0 qW"b`9R  
脚本变量的有效范围 ,o}CBB! k  
AuY*x;~  
U[z2{\  
有效性 a3,A_M}M'  
方法 6#ktw)e  
MjK<n[.  
NESTED 4~2 9,  
在tag标签的开始和结束之间 t_+owiF)M  
如果tag处理类实现BodyTag接口,则在doInitBody和doAfterBody中调用,否则在doStartTag中调用 B_RF)meux  
3mL(xpT.8z  
AT_BEGIN lHE \Z`  
从tag标签的开始一直到页面结束 R0K{wY58  
如果tag处理类实现BodyTag接口,则在doInitBody、doAfterBody和doEndTag中调用,否则在doStartTag和doEndTag中调用 AEUR` .  
O^_CqT%  
AT_END  j}w  
从tag标签的结束一直到页面结束 ^FZ9q  
在doEndTag中调用 +^%)QH>9   
w*X(bua@  
以struts为例,它的bean:define标签的实现遵循JSP1.1规范,此规范要求使用额外tag信息类来定义脚本变量。Variable元素是JSP1.2规范中加入的。以bean:define标签为例,你可以定义如下variable元素: *nEG<Y)  
Y Azj>c&  
<tag> 'Z)#SzY  
AYDAt5K_  
<variable> }|)T<|Y;  
*\*]:BIe&v  
<name-from-attribute>id</name-from-attribute> `/<f([w  
hsJGly5H  
<variable-class>database.BookDetails</variable-class> PGuPw'2;[  
X_)x Fg'k  
<declare>true</declare> >)k[085t  
""IPaNHQ  
<scope>AT_BEGIN</scope> w=^~M[%w  
)( pgJLW  
</variable> L]l?_#*x  
s.a@uR^  
</tag> HcrlcxwM\i  
4\j1+&W   
额外tag信息类 1B$8<NCQ=?  
mRN[l j  
如果要定义一个额外tag信息类,你要继承javax.servlet.jsp.TagExtraInfo类。一个TagExtraInfo类必须实现getVariableInfo方法,此方法返回一个叫VariableInfo的数组类,它包括如下信息: tg<bVA)E'J  
\\C!{}+  
· 变量名 l-5O5|C  
($ gmN 4  
· 变量所属类名 AdbTI#eY  
SJE!14|e  
· 此变量是否引用了一个新对象 iH>b"H >  
UJjtDV3@_g  
· 此变量的有效范围 JURg=r]LI  
iF_u/#  
jsp引擎将一个名为data的参数传给getVariableInfo方法,data中包括tag标签中的所有“属性名?D?D属性值”对。它可以用来向VariableInfo对象提供脚本变量的名字和类名。 Y oZd,} i  
ygd*zy9  
以struts为例,它在bean:define标签中定义了一个名为DefineTei的额外tag信息类,用来向脚本变量提供信息。由于脚本变量的名称(book)和类名(database.BookDetails)是通过tag标签的属性来传递的,它们一般定义在VariableInfo的构建代码中,并且可用data.getAttributeString方法来得到这些信息。如果要允许book脚本变量能在从tag开始直到整个JSP页面结束的范围内都可用的话,那它的范围应设为AT_BEGIN。如下所示: O9RnS\  
fw|t`mUGu  
IDdu2HNu  
public class DefineTei extends TagExtraInfo pP%+@;  
CY"i|s  
{ JB!*{{  
BF"eVKA  
public VariableInfo[] getVariableInfo(TagData data) %Rf{v5  
4-9cp=\PE  
{ #IeG/t(  
\*pS 4vy5x  
String type = data.getAttributeString(“type”); ClufP6'  
^c"\%!w"O  
If( type == null) Psm9hP :m  
|T-Y tuy8  
type = “java.lang.Object”; wkp$/IZKMj  
Np;tpq~  
return new VariableInfo[] { (e9hp2m  
Y 2^y73&k  
new VariableInfo(data.getAttributeString(“id”), 7w\!3pv  
(~(FQ:L %U  
type, swMR+F#u*  
S<5.}cR  
true, >n1UK5QD  
|=W>4>  
VariableInfo.AT_BEGIN) [P]M)vJ**  
Q[lkhx|.B  
}; yKmHTjX=  
3Q,p,  
} McN'J. Sxp  
Rli`]~!w  
} 9gZS )MZ  
/q!_f!<q4x  
EPM(hxCIQ  
注意:关于额外tag信息类的类名必须要在TLD中的tag标签下的tei-class子元素中定义。因此,DefineTei的tei-class中的定义看起来如下: S-brV\v7  
<tei-class> nVGOhYn  
org.apache.struts.taglib.bean.DefineTagTei \_+Af`  
</tei-class> 7j"B-k#  
FH;)5GGnv  
u@zT~\ h*  
具有协作关系的tag "T}HH  
M[e{(iQ:  
GF0Utp:Zf;  
tag通过共享对象来进行协作,JSP技术支持2种方式的对象共享。 rNgAzH  
YLV$#a3  
第一种方法是使用pageContext对象进行对象的共享(可支持JSP页面和tag处理类之间的共享),如果在一个tag处理类中要调用由另一个tag处理类创建的对象,可调用pageContext.getAttribute(name, scope)方法。 7/\SN04l  
t2qWB[r  
第二各方式的共享是对于tag之间有嵌套关系而言的,外层的tag所创建的对象对于内层的tag来说是可以共用的。这种形式的共享的好处是减少了可能存在的重名冲突。 0IsnG?"  
54 f?YR  
要访问一个嵌套tag创建的对象,tag处理类必须先找到此嵌套tag对象,可用TagSupport的静态方法 TagSupport.findAncestorWithClass(from, class)或TagSupport.getParent方法。前者在当不确定此tag是否为嵌套tag对象时使用。一旦它的父类被找到,它就能访问其所有动态或静态创建的对象。静态创建的对象是父类的成员,而动态创建的对象可能是父类的私有对象。诸如此类的对象可以用tag处理类的setValue方法来保存,用getValue方法来获得。 /FcwsD\=$  
r?`7i'  
下例阐述了以上两种共享对象的方法。在这个例子当中,一个查询tag检查一个名为connection的属性名是否在doStartTag中被设置。如果connection属性被设置,tag处理类从pageContext中得到这个connection对象。否则,此tag处理类先找到它的父tag处理类,然后从它的父tag处理类中找到connection对象。 u;8bbv4  
3>z+3!I z  
uW,rmd  
public class QueryTag extends BodyTagSupport @!(V0-  
L.a~vk 1  
{ ],wzZhA  
O^R ^Aw  
private String connectionId; 8)J,jh9q  
"||G`%aO+t  
public int doStartTag() throws JspException Z3iX^  
;;LiZlf  
{ aQ)g7C  
^Ux*"\/Es  
String cid = getConnection(); A^F0}MYT  
+jp^  
if(cid != null) o7g6*hJz  
?\a';@h  
{ ,Ne v7X[0  
{1GIiP-U  
//存在一个connection id,使用它。 "~IGE3{  
nm<S#i*  
connection = (Connection) pageContext.getAttribute(cid); ~ o5h}OU"  
`]<~lf  
} );^{;fLy%  
VF9-&HuC  
else ||4++84{  
AFNE1q;{\  
{ `ln= D$  
pB,@<\l %  
ConnectionTag ancestorTag = (ConnectionTag)findAncestorWithClass(this, iS28p  
}5ONDg(I~  
ConnectionTag.class); \Eyy^pb  
!q*]_1  
if(ancestorTag == null) =/HTe&  
;p)fW/<  
{ [kZe6gYP&  
}-M% $ ~`  
throw new JspTagException(“一个没有connection属性的查询标签必须被一个connection标记嵌套。”); lb#`f,r>  
,An*w_  
} v>mr  
|Oe$)(`|h  
connection = ancestorTag.getConnection(); L|w}#|-  
I*8_5?)g<  
} <' b%  
ekuRGG  
} ` _]tN  
wmgKh)`@_{  
} 0CUUgwA /  
lD)QB!*v  
Q,xKi|$r  
ehls:)F  
此查询标签在JSP页面中的调用形式可以从以下2种定义中任选一种: )Y,>cg:z~  
^2um.`8  
`LCxxpHi|  
<tt:connection id=”con01” ...> ... </tt:connection> 3`m n#RM  
9Vv&\m!0  
<tt:query id=”balances” connection=”con01” > q oVp@=\:"  
.e%B'  
SELECT account, balance FROM acct_table (g]J hG  
uEkUK|  
where customer_num = <%= request.getCustno() %> gkNvvuQXc  
$+ ?A[{JG  
</tt:query> }\!38{&  
C$$lJ=>  
[z`m`9Aq  
}c*6|B@f  
*HN0em  
<tt:connection ...> |(a< b  
pUaGrdGxzQ  
<x:query id=”balances”> p)=Fi}#D\  
Yv jRJ  
SELECT account, balance FROM acct_table bi[gyl#  
lTpmoDa%  
where customer_num = <%= request.getCustno() %>  $mG&4Y  
/S+gh;2OC  
</x:query> l %{$CmG\  
G@igxnm}  
</tt:connection> n~k9Z^ $  
gb_k^wg~1'  
j:{d'OV  
与此同时,在TLD中必须指定connection属性为可选的,定义如下: 3?GEXO&,E  
-kd_gbnr3  
<tag> p<3^= 8Y$  
j5;eSL@ /  
... K"r'w8  P  
}x1*4+Y1  
<attribute> rz%=qY  
]`x\Oj &  
<name>connection</name> za20Y?)[  
we&g9j'  
<required>false</required> 9L'R;H?L  
Y8 a![  
</attribute> =<,AzuV  
k;pTOj  
</tag>
描述
快速回复

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