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

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

级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
标准的JSP 标记可以调用JavaBeans组件或者执行客户的请求,这大大降低了JSP开发的复杂度和维护量。JSP技术也允许你自定义taglib,其实换句话说,taglib可以看成是对JSP标记的一种扩展,正如xml是对html的一种扩展一样。taglib通常定义在tag标签库中,这种标签库存放着你自己定义的tag标签。简而言之,如果使用taglib,那么你可以设计自己的JSP标记! ~u*4k:2H  
}Q`+hJ0  
一般来说,自定义tag标签主要用于操作隐藏对象、处理html提交表单、访问数据库或其它企业级的服务,诸如邮件和目录操作等等。自定义tag标签的使用者一般都是那些对java编程语言非常精通,而且对数据访问和企业级服务访问都非常熟悉的程序员,对于HTML设计者来说,使得他可以不去关注那些较复杂的商业逻辑,而将精力放在网页设计上。同时,它也将库开发者和库使用者进行合理分工,自定义tag标签将那些重复工作进行封装,从而大大提高了生产力,而且可以使得tag库可用于不同的项目中,完美地体现了软件复用的思想。 [x)T2sA  
x_7$g<n  
在这篇文章中,我们主要讨论: gxO~44"  
0o8`Y  
· 什么是自定义tag标签? 7X( 2SI3m  
7u"Q1n(h/  
· 怎么使用tag标签? %i\rw*f  
CNRSc 4Le  
o 声明要使用的tag库 3rRIrrYO  
m@ <,bZkl  
o 找到与之对应的tag处理类 uRy}HLZ"  
G+=G c(J  
o tag标签的类型 bg|$1ue  
j*QdD\)  
· 自定义tag标签 S5JM t;O  
)L&y@dy)  
o tag处理类 w yxPvI`   
q&:7R .Ci  
o tag库描述 fExFpR,`  
76T7<.S  
o tag标签示例 [lIX&!T"  
)y] Dmm  
o 带属性的tag _!2lnJ4+5  
o+x%q<e;c  
o 带body的tag pS8\B  
E#P#{_BR^  
o 定义了脚本变量的tag w#1BHx  
4 6v C/  
o 具有协作关系的tag {eU>E /SQ  
p@78Xmu?q  
· 自定义tag标签 ,xU#uyB  
vs8[352  
o 一个迭代tag的例子 jW&*?6<  
3sV$#l P  
o 一个模板tag库 =RUy4+0>F  
6`2i'flv  
o tag处理类到底是怎样被调用的? HxK'u4I  
;8#6da,  
3z0Bg  
什么是自定义的tag? \2u7>fU!  
9z4F/tUq  
一个自定义的tag标签是用户定义的一种JSP标记。当一个含有自定义的tag标签的JSP页面被jsp引擎编译成servlet时,tag标签被转化成了对一个称为tag处理类的对象进行的操作。于是当JSP页面被jsp引擎转化为servlet后,实际上tag标签被转化成为了对tag处理类的操作。 9(fh+  
\r aP  
自定义tag标签有很多特色,诸如: -)%\$z  
>yc),]1~  
· 可以在JSP页面中自定义tag标签的属性 (w-"1(  
0VvY(j:hp  
· 访问JSP页面中的所有对象 "#Z e3Uy\  
&DGqY5=  
· 可以动态地修改页面输出 G!`%.tH  
zji9\  
· 彼此这间可以相互通信。你可以先创建一个JavaBeans组件,然后在一个tag中调用此JavaBeans组件,同时可以在另一个tag中调用它。 'sAkrl8kt  
ty!DMg#  
· tag允许相互嵌套,可以在一个JSP页面中完成一些复杂的交互。 6\l F  
Q:) 4  
nGGw(6c%>  
使用tag标签 VP< zOk7  
6MOwn*%5k  
2L^/\!V#  
本节主要描述怎样在JSP页面中使用tag标签,以及tag标签的不同类型。 >W+,(kAS  
&LM@xt4"^[  
要使用tag标签,JSP程序员必须做2件事: VXCB.C"  
#HL$`&m  
· 声明此tag标签的tag库 0qR#o/~I  
W+u@UJi  
· 实现此tag标签 @j\;9>I/  
;|T|*0vY[  
声明tag标签所在的tag库 tY#&_%W  
u9:sj  
如果要使用tag标签,则应用JSP的taglib指示符来指定其tag库(注意:taglib要在在使用此tag标签之前声明) oG22;  
euY+jc%  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> K:XXtG  
fBTNI`#  
uri属性定义了唯一的标签库描述(以下简称TLD),它可以是直接是tld文件名或一个独一无二的名字。prefix是用来区别其它TLD中和本TLD中有重名的tag的一种手段。 &T-:`(  
"viZ"/ ~6  
TLD必须以.tld作为扩展名,并且存放在当前应用的WEB-INF目录或其子目录下。你可以通过它的文件名直接引用它,也可以通过别的方式间接地引用它。 xe OfofC(l  
@/aJi6d"^E  
以下taglib指示符直接引用一个TLD: MuO(%.H  
j^/<:e c.  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> >WO;q  
Lm$KR!z  
以下的taglib指示符通过一个逻辑名称间接地引用一个TLD: ^Zpz@T>m  
$lB!Q8a$  
<%@ taglib uri=”/tutorial-template” prefix=”tt” %> Mb_"M7  
q: F6MW  
如果是间接引用TLD的话,那你必须还要在web.xml中定义此逻辑名称与tld文件之间的映射,具体做法是在web.xml中加入一个名为taglib的元素: 1$))@K-I  
Q~^v=ye  
<taglib> &hVf=We  
,P`:`XQ>_B  
<taglib-uri>/tutorial-template</taglib-uri> [)}`w;#  
UptKN|S&V  
<taglib-location> Fu?_<G%Ynp  
eOVln1a  
/WEB-INF/tutorial-template.tld c&#Q`m  
s'/_0  
</taglib-location> /hg^hF  
11S{XbU  
</taglib> `$4wm0G|  
%b pQ=  
Hv"qRuQ?[  
实现此tag标签 z+fy&NPl  
b7'A5]X  
cooicKS7  
为了实现tag标签,你有2种方法来存放tag处理类。一、让tag处理类以.class的方式存放于当前应用的WEB-INF/class子目录下,二、如果tag处理类是以JAR包的形式存在的话,那可以放在当前应用的WEB-INF/lib目录下,如果tag处理类要在多个应用中共享,那么它就应放在jsp服务器上的common/lib目录下,对于tomcat来说,就是tomcat/common/lib目录下。 *W=1yPP  
{'P?wv  
\Ogs]4   
tag标签类型 E08!a  
-iy17$  
}K.)yv n  
自定义的tag标签遵循XML语法。它有一个开始标记和一个结束标记,有的还有body(即文本节点): V 7 p{'C   
rk+s[Qi~  
<tt:tag> 9~ V(wG  
ty;a!yjC  
body }q_Iep  
@B)5Ho  
</tt:tag> v*y,PY1*  
6X2w)cO  
9;gy38.3  
一个不带body的tag标签如下: 5[6{o$I  
4M$"0}O;[h  
<tt:tag /> Hm 0;[i  
A;xH{vo{  
\V j7%ph  
简单的tag标签 c ]ll89`||  
}!kvoV)]1  
一个没有body和属性的tag标签如下: 7Or?$  
3cqc<  
<tt:simple /> M%13b$i~f  
pcQzvLk  
0CeBU(U+|R  
带属性的tag标签  fsKZ  
 ^AwDZX  
@ uL4'@Ej  
自定义标签可以有自己的属性。属性一般在开始标记中定义,语法为 attr=”value”。属性的作用相当于自定义标签的一个参数,它影响着tag处理类的行为。你可以在TLD中详细定义它。 h^zcM_  
)x,-O#"A  
你可以用一个String常量给一个属性赋值,也可以通过表达式给它赋值,如<%= ...%>。以struts为例,它的logic:present标签就是用的String常量来给属性赋值: ,=u!hg  
sEb*GF*.V  
<loglic:present parameter = “Clear”> V#&S&dn  
Y,KSr|vG  
而另一个标签logic:iterate是用表达式来给属性赋值: uq!d8{IMu  
27JZwlzZ  
<logci:iterate collection=”<%= bookDB.getBooks() %>” (^|vN ;  
0;5qo~1  
id=”book” type=”database.BookDetails”> =b3<}]  
-!j5j:RR  
,PWMl [X  
带body的tag标签 > W^"*B  
)P W Zc?M  
一个自定义标签可以包含其它自定义标签、脚本变量、HTML标记或其它内容。 zM%2h:*+{  
E zU=q E  
在下述例子中,此JSP页面使用了struts的logic:present标签,如果些标签定义了parameter=”Clear”的属性,则将清除购物车的内容,然后打印出一条信息: ]D>\Z(b  
pr \OjpvD  
<logic:present parameter=”Clear”> 78'3&,+si  
@oRo6Y<-  
<% cart.clear(); %> f2P2wt.$  
DRu#vC  
<font color=”#ff0000” size=”+2”><strong> Gd2t^tc  
b9 l%5a  
你选择了清除购物车! 8(@(G_skp  
=6, w~|W  
</strong></font> %&$s0=+  
p^QppM94  
</logic:present> l\bgp3.+  
CDFX>>N  
h],l`lT1\  
到底是用属性还是用body来传递信息? $=!_ !tr  
#"JtH"pF  
如上所述,我们既可以通过属性,也可以通过body来传递信息。但一般来说,比较简单的类型,如字符串或简单表达式最好采用属性来传递信息。 !y;xt?  
/:w.Zf>B9  
O=}jg0k  
定义脚本变量的tag标签 y(6*)~Dh  
h"$], =  
所谓脚本变量,是指JSP中可以调用的变量或对象。它可由tag标签产生。以下示例阐述了一个tag标签定义了一个名为tx的由JNDI所定义的事务处理对象。脚本变量可以是ejb对象、事务、数据库连接等等: 8Vm)jnM  
enQev?8%  
<tt:lookup id=”tx” type=”UserTransaction” name=”java:comp/UserTransaction” /> $gcC}tX  
YLNJ4nE  
<% tx.begin(); %> U'xmn$ O  
Z=144n 1  
... G8 CM  
JN<u4\e{-&  
D7,{p2<2T  
具有协作关系的tag标签 WD'[|s\  
m@c\<-P  
自定义tag标签之间可以通过共享对象来实现协作。在下述例子中,标签tag1创建了一个名为obj1的对象,在标签tag2仍可以重复使用obj。 lDtl6r/  
)WF*fcx{  
<tt:tag1 attr1=”obj1” value1=”value” /> S4>1d-  
Ei\tn`I&  
<tt:tag2 attr1=”obj1” /> }C{wGK+o[  
-]Q6Ril  
在以下这个例子当中,如果外层的tag标签创建了一个对象,那么其内层的所有tag标签都可以使用这个对象。由于这样产生的对象没有一个指定的名字,那么就可以将少重名的冲突。这个例子阐述了一系列协作的嵌套对象。 :8Ql (I  
^14a[ta/'  
<tt:outerTag> Z'\{hL S  
m^YYdyn]M  
<tt:innerTag /> $mDlS  
OO?BN!  
</tt:outerTag> |D[4 G6&  
@O&;%IZMY  
G+W0X  
Tag处理类 ;fKFmY41  
/: }"Zb  
~`CWpc:  
Tag处理类必须实现Tag接口或BodyTag接口,不过现在一般都流行从TagSupport或BodyTagSupport类中继承,这些类或接口都可以在javax.servlet.jsp.tagext包中找到。 wb (quu  
k9o LJ<.k  
当JSP引擎看到自己的JSP页面中包含有tag标签时,它会调用doStartTag方法来处理tag标签的开头,调用doEndTag方法来处理tag标签的结束。 aL0,=g%  
<.c#l':  
下表说明不同类型的tag所需要不同的处理过程: i{nFk',xX  
QR{pph*zn-  
Tag处理类的方法 `Ct fe8  
ood,k{  
Tag标签类型 rTYMN  
所调用的方法 ^yVKW5x  
6n Hyd<o  
基本标签 *gL-v]V  
doStartTag, doEndTag, release `RL n)a  
Ab)X/g-I @  
带属性的标签 Hyz:i)2  
doStartTag, doEndTag, set/getAttribute1...N, release 5(&'/U^  
U=\!`_f':  
带内容的标签 ~_hn{Ou s  
doStartTag, doEndTag, release /UPe@  
YhFd0A?]  
带内容的标签,且内容重复循环 }SBpc{ch  
doStartTag, doAfterBody, doEndTag, release ;=E!xfp5U  
LHgEb9\Q  
带内容的标签,且内容与JSP交互 g/e2t=qP  
doStartTag, doEndTag, release, doInitBody, doAfterBody, release ]='zY3  
tFYo d#  
一个tag处理类可以通过javax.servlet.jsp.PageContext来与JSP交互,通过javax.servlet.jsp.PageContext类,tag处理类可以访问JSP中的request、session和application对像。 T!Eyq,]  
)i*-j =  
如果tag标签是互相嵌套的,那内层的tag处理类可以通过它的parent属性来访问上层的tag处理类。 4lpkq  
s&~i S[  
一般情况都将所有的tag处理类打成了JAR的包,以便于发布。 ! p|d[  
md`"zV  
`_5{: 9N$  
Tag库描述(简称TLD) :PF6xL&  
0l>4Umxr{J  
3=xN)j#B  
Tag库是用xml语言描述的,TLD包括了tag库中所有tag标签的描述,它一般用来被jsp服务器用来校验tag的语法正确性,或者被jsp开发者用来开发新的标签。 X) xeq  
4n, >EA85  
TLD的文件扩展名必须为.tld,而且必须放在当前WEB应用的WEB-INF目录或其子目录中。 :7jDgqn^|i  
DE_ <LN  
一个TLD的内容的开头必须遵守标准的XML开头,用于描述DTD和xml的版本,例如: h}c R >  
7C@%1kL  
<?xml version="1.0" encoding="ISO-8859-1" ?> 0GP\*Y8  
zY&/^^y  
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd"> qA5PIEvdq  
TLD必须以<taglib>来作为它的根元素,<taglib>的子元素如下表: Ij9ezNZT=  
Tg|/UUn  
SK G!DKQ  
<taglib>的子元素  ]pP:  
<WRrB `nO  
Element 5Cjh%rj(jl  
Description U *']7-  
k86j& .m_  
tlib-version = & =#G3f  
Tag库的版本 s\A4y "  
[|"{a  
jsp-version ;{hE]jReH  
Tag库所需要的jsp的版本 x|`o7.  
)$7-CNWr~  
short-name $`Hb -  
助记符,tag的一个别名(可选) Fl0 :Z  
:o+&>z  
uri b?{\t;  
用于确定一个唯一的tag库 < k?jt  
f15f)P  
display-name |w w@V<'/#  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) 1a>TJdoa  
(,!G$~Sy  
small-icon vv5 uU8  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) y=spD^tM8  
1^_V8dm)  
large-icon "-a CF  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) pGdo:L?  
( !=^(Nd  
description mx;1'!'fr  
对tag库的描述(可选) 7\nR'MOZ  
Tq*K =^  
listener P{gy/'PH,  
参见下面listener元素 t2 0Es  
40)Ti  
tag  4fa2_  
参见下面tag 元素 Qy_! +q  
b!3Y<D*  
Listener元素 +JrbC/&  
mcqLN5  
一个tag库可能定义一些类做为它的事件侦听类,这些类在TLD中被称为listener 元素,jsp服务器将会实例化这些侦听类,并且注册它们。Listener元素中有一个叫listener-class的子元素,这个元素的值必须是该侦听类的完整类名。 #<EMG|&(  
X4{O/G  
Tag元素 |VxO ,[~  
7t~12m8x  
每个tag元素在tag库中都要指出它的名字、类名、脚本变量、tag的属性。其中脚本变量的值可以直接在TLD中定义或通过tag附加信息的类来取得。每个属性描述了这个属性是否可以省略,它的值是否可以通过<%= …%>这样的JSP语法来获得,以及属性的类型。 ~rICPR  
t0-)\kXcA  
每一个tag在TLD中对应一个tag元素,下表是tag元素的子元素: (Y>|P  
[) S&PK  
Tag元素的子元素 C6ry]R@  
"Q <  
元素名称 D +Ui1h-  
描述 ~![J~CkPS  
yON";|*\m  
name M:QM*?+)  
独一无二的元素名 LZF %bJv  
I("lGY  
tag-class ,wPvv(b]a  
Tag标签对应的tag处理类 ^DH*\ee  
%=EN 3>,  
tei-class ll8Zo+-[  
javax.servlet.jsp.tagext.TagExtraInfo的子类,用于表达脚本变量(可选) uXkc07 r'  
-}$mv  
body-content O\&-3#e  
Tag标签body的类型 i}E&mv'  
 A4  
display-name JNk6:j&Pf  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) z8-dntkf  
Ka+N5 T.f  
small-icon <2,NWn.  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) &&$,BFY4  
)Lb?ZXT3  
large-icon R?L? 6~/q  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) +pG[ [}/  
-lqsFaW  
description R+b~m!5 8  
此tag标签的描述 kX)QHNzP  
lGZf_X)gA^  
variable w8iXuRv  
提供脚本变量的信息(同tei-class)(可选) S\"#E:A  
1];OGJuJ2  
attribute 0Q4i<4 XW  
Tag标签的属性名 f@7HVv&  
KbTd`AIL  
以下章节介绍对于不同类型的tag,如何具体地实现它们。 \h48]ZjC`  
h#JX$9  
YHQvx_0yP  
简单的tag 3)0z(30  
|9Pi*)E  
-|g9__|@  
tag处理类 +Z=%4  
a>8&B  
简单的tag处理类必须实现Tag接口的doStartTag和doEndTag方法。当jsp引擎碰到tag标签的开头时,doStartTag被调用,因为简单的tag没有body,所以此方法将返回 SKIP_BODY。当jsp引擎碰到tag标签的结尾时,doEndTag被调用,如果余下的页面还要被计算,那它将返回EVAL_PAGE,否则将会返回SKIP_PAGE。 [M/0Qx[,  
!))!! {  
以下是例子:对于标签 <tt:simple /> ,它的tag处理类实现如下: [x8_ax} w  
)\RG NJMC  
.Q5zmaA]  
public SimpleTag extends TagSupport )j\9IdkU;y  
T-a [  
{ 4H*M^?h\#  
h-+vN hH  
public int doStartTag() throws JspException ?d' vIpzO!  
z0T9tN!(  
{ E]dc4US  
>1  %|T  
try{ twP%+/g]<  
}Yargj_Gn  
pageContext.getOut().print(“Hello.”); \]|(w*C  
<i~=-Z(  
}catch(Exception e){ !D|c2  
6]NaP_\0  
throw new JspTagException(“SimpleTag: “ + e.getMessage()); rd1EA|T  
3-v&ktD&N'  
} L}=t"y  
'_B;e=v`  
return SKIP_BODY; ?*L{xNC#  
Z>PS>6  
} 4QBPN@~t  
6Wk9"?+1  
public int doEndTag() noZ!j>f{@l  
SQT]'  
{ MGLcM&oR  
J b?x-%Za  
return EVAL_PAGE; o3cE.YUF  
fLg :+Ue<B  
} i6P'_  
$[0\Th  
} Go)}%[@w  
K1CgM1v  
w0PAtu  
注意:如果tag标签没有内容的话,那必须定义body-content元素为空,例如 R5N~%Dg)3  
^Eif~v  
<body-content>empty</body-content> te;VGpv.  
:_[pZ;-@  
B|ctauJ  
带属性的tag标签
评价一下你浏览此帖子的感受

精彩

感动

搞笑

开心

愤怒

无聊

灌水
级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
只看该作者 1 发表于: 2007-01-01
tag处理类 <9]J/w+  
zNM*xPgS  
对于tag标签的每个属性,你必须依照JavaBeans规范来定义其属性,以及get和set方法。以struts的logic:present 标签为例, L, 2;-b|  
H"c2kno9  
<logic:present parameter=”Clear”> nT9Hw~f<j  
L KLLBrm:  
与此相应,此tag处理类应有如下方法和定义: A "/|h].  
/h 4rW>8D2  
)Lg~2]'?j  
protected String parameter = null; C9 j{:&  
9L>73P{_  
public String getParameter() 0IyT(1hS  
3QCCX$,  
{ Ym?VF{e,  
0[p"8+x  
return this.parameter; N<XMSt  
X7txAp.  
} V;"Rp-`^  
!b?cY{  
public void setParameter(String parameter) K!(hj '0.  
U#`2~Qv/1  
{ ^qLesP#   
"~q~)T1Z  
this.parameter = parameter; iL|5}x5\  
tA^CuJR  
} l[^0Ik-G  
Q_`EKz;N{  
O~|Y#T  
注意:如果你的属性名为id,而且你的tag处理类是从TagSupport类继承的,那你就不需要定义它的属性和set和get方法,因为他们早已在TagSupport被定义过了。 xy]oj  
z.;!Pj  
Attribute元素 piFZu/~Gq\  
8WpZ "  
对于tag标签的每个属性,你必须定义它是否必须的,它的值是否可以用诸如<%= …%>的表达式来获得,以及它的类型(可选),如果不指定它的类型,那就默认为是java.lang.String类型。如果rtexprvalue元素被定义为true或yes,那么在type元素中就定义了attribute的返回类型。 @w(X}q1  
=7F?'&LC  
<attribute> C(vQR~_  
|3g'~E?$  
<name>attr1</name> %$N,6}n  
?3gf)g=  
<required>true|false|yes|no</required> DDj:(I?,w  
cNMDI  
<rtexprvalue>true|false|yes|no</rtexprvalue> HMhdK  
,z#S=I  
<type>attribute的返回类型(只用当rtexprvalue为真是才有效)</type> OVGB7CB]S  
.:O($9^Ho  
</attribute> :r7!HG _  
!Y 9V1oVf"  
如果tag的某个属性不是必须的,那tag处理类会自动提供一个缺省值。 7bQST0 ?  
Ymf@r?F<  
例如,在logic:present这个tag标签中定义了一个属性叫parameter,但它不是必须的,而且它可以被诸如<%= …%>的表达式来赋值。 K5F;/ KR"  
OHt^e7\  
<tag> 'n}]  
zm3$)*p1  
<name>present</name> .yHi"ss3  
=t %;mi,M  
<tag-class>org.apache.struts.taglib.logic.PresentTag</tag-class> Ii!{\p!  
bX 6uGu 7  
<body-content>JSP</body-content> a% /D~5Z  
~=9S AJr]  
Qe_C^ (P  
rONz*ly|i  
<attribute> WLiFD.  
$,0EV9+af  
<name>parameter</name> .)<l69ZD Z  
$4Dr +Z H  
<required>false</required> 3R)|DGql=1  
)4N1EuD6  
<rtexprvalue>true</rtexprvalue> ,y@WFRsx  
X^rFRk  
</attribute> mY]o_\`  
cPkP/3I]h  
S VypR LVB  
5}a.<  
</tag> K+ ~1z>&  
RK p9[^/?  
ihekON":  
属性元素的校验 +U4';[LG1C  
\-sW>LIA  
s>%.bAxc  
有关于tag标签的有效值可以从tag库的说明文档中获得,当JSP页面被编译时,jsp引擎会强制性地参照TLD中定义的规则进行检查。 d[Zx [=h  
;.^! 7j  
还有一个方法也可以进行属性元素的校验,就是先继承类TagExtraInfo,然后调用它的isValid方法。这个类同时也起到提供tag中定义的脚本变量信息的作用。 (}s& 84!  
@$nh6l>i  
IsValid方法通过TagData对象来传递属性信息,它包括着tag的所有的属性名-值的信息。由于校验发生在运行时刻,因此这个属性的值将被赋值为TagData.REQUEST_TIME_VALUE。 5Pf)&iG  
{$ > .I  
例如tag标签<tt:twa attr1=”value1” />在TLD中定义如下: dKhS;!K9p  
4q.yp0E  
<attribute> 5F!i%{XQvm  
I@IE0+ [n  
<name>attr1</name> gX*j|( r  
0|g@; Pc  
<required>true</required> Yj'"Wg  
(EjlnG}5l  
<rtexprvalue>true</rtexprvalue> Z?'?|vM  
,/kZt!  
</attribute> g~U<0+&yw%  
KpDb%j  
*3s-=.U~  
这个定义说明了attr1能在运行期间被赋值。 VVcli*  
JJ'f\f9  
以下的isValid方法检查attr1属性的值是否属于Boolean类型。注意由于attr1能在运行刻被赋值,那么isValid方法必须检查tag用户是否对此tag进行了运行时刻赋值。 Y!+H9R  
;j qF:Wl@  
nM *}VI  
Public class TwaTEI extends TagExtraInfo M+%qVwp  
x U"g~hT  
{ Pz\ByD  
4iZg2"[D  
public boolean isValid(Tagdata data) CugZ!>;^  
)&Z`SaoP|J  
{ I8c:U2D  
`\'V]9wS  
Object o = data.getAttribute(“attr1”); PHJHW#sv  
C6Cr+TScH  
If(o != null && o != TagData.REQUEST_TIME_VALUE) Ikw.L  
d[  _@l  
{ 0g HV(L?  
lr?SL\D  
if( ( (String)o).toLowerCase().equals(“true”) || 2R,8q0qR:  
X|D-[|P  
((String)o).toLowerCase().equals(“false”) ) 7SNdC8GZ~  
lBm`W]3T  
return true; h<bhH=6~  
~gHn>]S0  
else P00%EB  
Z9|A"[b  
return false; s0:M'wA  
9JX@c k  
} {:3:GdM6  
%3AE2"  
else pvb&vtp  
l<+PA$+}}  
return true; %nG>3.%  
^Wn+G8n  
} FnI}N;"  
#)@#Qd  
} e\^}PU  
G!wb|-4<$  
6b$C/  
带body的tag `)4v Q+A>  
wmIe x  
nkTdn  
tag处理类 gsUF\4A(J  
!YI<A\P  
o!U(=:*b  
如果tag标签含有内容,那处理方式会略微有些不同,而且还要视tag处理类是否要与body交互的情况而定。如果要与body交互,那我们认为tag处理类要可能要对body进行操作。 UFu0{rY_  
r=SC bv  
Tag处理类不与body交互 q2'}S A/  
0pG + yec  
如果tag处理类不与body交互,tag处理类应该实现Tag接口或从TagSupport中派生,如果body要被计算,那么doStartTag方法应返回 EVAL_BODY_INCLUDE,否则应返回SKIP_BODY。 @vXXf/  
ew~?&=  
如果tag处理类要对body反复运算,则它应该实现IterationTag或从TagSupport中派生。如果tag处理类认为body还未计算完的话,那它的doStartTag方法和doAfterBody方法必须返回EVAL_BODY_AGAIN。 <&2<>*/.y  
"6U@e0ht  
Tag处理类与body交互 >`/s+V  
~j(vGO3JB  
如果tag处理类与body交互,那tag处理类应实现BodyTag接口或从BodyTagSupport中派生。这种tag处理类一般要实现doInitBody和doAfterBody方法。 u;!h   
bsr]Z&9rrk  
Body允许一些方法来读写它的内容。Tag处理类可以调用body内容的getString或getReader方法来从body中提取信息,也可用 writeOut(out) 方法来将body的内容写入到out对象中。其中out对象通过tag处理类的getPreviousOut方法来获得。 :I7mM y*  
`& h-+  
如果body的内容需要被计算,那么doStartTag方法必须返回EVAL_BODY_BUFFERED,否则,它将返回 SKIP_BODY。 e+F $fQt>  
[\Nmm4  
doInitBody 方法 4]$OO'  
K=E+QvSG  
此方法在body内容已经设好,但未被计算之前被调用。你可以根据不同的body内容来制定初始化策略。 gat;Er  
VH<d[Mj  
doAfterBody方法 r!O[|h  
!M`.(sO]  
此方法在body内容已被计算后进行调用。 kPiY|EH  
mEu2@3^E }  
和doStartTag方法一样,doAfterBody方法返回一个指示符指示是否要继续计算body,如果要继续计算,则doAfterBody应返回EVAL_BODY_BUFFERED,否则,它应返回SKIP_BODY。 N ~fE&@-  
ULBEe@ s  
release 方法 jT< I`K*  
?1c7wEk  
tag处理类调用此方法将它的状态重置为初始状态,并释放所有的私有资源。 </@5>hx/  
'/t9#I@G\  
j@^zK!mO  
以下的例子读取body的内容(其中含有一条sql语句),然后将它传递给一个对象,让它进行查询。由于此处body不须重新计算,所以doAfterBody会返回SKIP_BODY。 c q[nqjC=  
-Eig#]Se3  
=:xX~,qmv  
Public class QueryTag extends BodyTagSupport UNwjx7usD  
BDzAmrO<  
{ =S\^j"  
8F[ ;ma>Z8  
public int doAfterBody() throws JspTagException 4nP4F +  
;|Hpg_~%>  
{ 6R^32VeK($  
C.":2F;-e  
BodyContent bc = getBodyContent(); jDTG15_=  
R4R\B  
//将body的内容以字符串的格式提取出来 :T?WN+3  
C22h*QM*  
String query = bc.getString(); &4sz:y4T>  
e`H>}O/ai  
//清除body O[eU{ ;P  
X }i2qv  
bc.clearBody(); KdYR?rY  
9I2&Vx=DSt  
try{ 0#Pa;(  
.VNz( s  
Statement stmt = connection.createStatement(); , V,Q(!$F  
TBQ68o  
Result result = stmt.executeQuery(query); D`!BjhlW  
q_`j-!  
}catch(SQLException e){ !bCL/[  
=nc;~u|]  
throw new JspTagException(“queryTag: “ + e.getMessage() ); M!mw6';k  
K(lSR  
return SKIP_BODY; O cPgw/ I  
 H!hd0.  
} Bq HqS  
{r$Ewc$Yb7  
} 1aV32oK  
iGz*4^ %  
hmOGteAf-  
body-content元素 J Eo;Fx]  
vnVT0)Lel  
Mzg P@tB  
由于tag可能会有body,你必须用body-content元素来指定body内容的类型: "S6";G^I  
V|B4lGS&  
<body-content>JSP|tagdependent</body-content> 64mD%URT  
G4P*U3&p  
K1A<m=If  
如果body的内容是定制的或内部的tag、脚本元素、或HTML广本,则归类为JSP类型。其他的类型,比如上面代码所述的?D?D将sql statement类传给 query tag的这种类型应该标为tagdependent。 tP*GYWI48  
<2%9O;bV[  
注意:实际上body-content的值并不影响tag处理类对body内容的处理,它仅仅是被tag编辑工具用来描述此body的内容。 F[%k ;aJ  
\P9ms?((A  
`''y,{Fs  
用tags定义脚本变量 }uC]o@/  
3.hFYA w  
^BRqsVw9  
tag处理类 mD ZA\P_  
qm_m8   
)*XWe|H_  
tag处理类负责创建或设置页面中定义的脚本变量,用pageContext.setAttribute(name,value,scope)或pageContext.setAttribute(name,value)方法来实现。一般来说,tag处理类通过脚本变量的名称来获取它,脚本变量的名称一般可用get方法来获得。 ?PTXgIC  
ILl~f\xG)  
如果脚本变量的值依赖于tag处理类中的上下文中某一对象,那它可用pageContext.getAttribute(name,scope)方法来找到那个对象。一般的处理过程是tag处理类先找到脚本变量,再对其进行处理,然后用pageContext.setAttribute(name,object)的方法来设置它的新值。 ! l0"nPM=  
.{ljhE:  
对象的生存周期(scope)如下表: cF=WhP*f  
cN?/YkW?]  
对象的生存周期表 %+,*$wk#*  
PN 8#T:E  
名字 7NWkN7:B  
可访问范围 Xx[,n-rA  
生存周期 E@xrn+L>-  
DCZG'eb  
page %xG<hNw/  
当前页面 BY[7`@  
一直有效,除非页面向客户提交响应或重定向到一个新页面 Iy4%,8C]g  
D_JGbNigA  
request 7)[Ve1;/N  
当前页面或当前页面重定向到的页面 vk X+{n  
一直有效,除非页面向客户提交响应 chUYLX}45  
4@Db $PHs  
session U*\K<fw   
当前页面或在同一浏览器窗口中的页面 l4r >#n\yj  
一直有效,除非关闭当前浏览器、超时、网络故障 ];6955I!  
0asP,)i  
application {D..(f1*u  
整个web应用程序的所有请求 Ri_2@U-  
一直有效,除非发生网络故障、服务器故障 ~CV.Ci.dG  
ru9@|FgAE  
提供关于脚本变量的信息 ( >ze{T|  
F <6(Hw#>  
以下示例定义了一个名为“book”的脚本变量,用来访问程序中关于书的信息: kqj)&0|X  
+_pfBJ_$%  
<bean:define id=”book” name=”bookDB” property=”bookDetails” type=”database.BookDetails” /> Fp@>(M#3  
F7*)u-4Yn  
<font color=”red” size=”+2” > ^M q@} 0  
[pm IQ228  
<%= messages.getString(“CartRemoved”) %> ~+t@7A=  
u*I'c2m  
<strong><jsp:getProperty name=”book” property=”title” /></strong> Q8h0.(#-  
=. \hCgq  
</font> &k_*Y- l7]  
umq6X8K  
当包含此tag的JSP页面被编译时,jsp引擎会自动生成关于此book的同步的代码(同步可以避免几个客户同时访问此book时造成的冲突),要生成同步代码,jsp引擎需要知道此脚本变量的如下信息: T* 0;3&sA  
Keo<#Cc?  
· 脚本变量名称 hF@%k ;I  
zng.(]U/?H  
· 脚本变量所属的类 ovM;6o  
n YUFRV$  
· 此脚本变量是否引用了一个新的或已存在的对象 (.@peHu)#  
=M*pym]QSY  
· 此脚本变量的有效性 nr -< mQ  
!DSm[Z1  
有两种办法可以向jsp引擎提供关于脚本变量的信息:在TLD中定义variable子元素,或用tei-class子元素定义一个额外tag信息类。用variable最简单,但可能降低了一些灵活性。 82EvlmD  
Z#N w[>NN*  
Variable元素 WrDFbcH  
%!nN<%  
Variable元素有如下子元素: d|Wqx7t]P  
zz(|V  
· name-given ?D?D 给出的名字,是一个常量 p o)lN[v  
EKF4 ]  
· name-from-attribute?D?D 属性名,在编译时给出的属性名 K/N{F\  
=:w,wI.  
name-given或name-from-attribute两者必须选一,但以下子元素是可选的: F_R\  
&@CUxK  
· variable-class?D?D变量的类型,缺省为java.lang.String。 j|Vl\Z&o)  
Xy K,  
· declare?D?D此脚本变量是否引用了一个新对象,缺省为True。 kw2yb   
M$@~|pQ<  
· scope?D?D脚本变量的范围,缺省为NESTED。下表描述了scope的几种类型: )LKJfoo PY  
cf"&22TQ+Z  
脚本变量的有效范围 E%D.a=UX,  
|k*bWuXgLs  
<W8 %eRfU  
有效性 -`\^_nVC  
方法 {'M/wT)FeC  
p2rT0gu!  
NESTED GeY!f/yQ<  
在tag标签的开始和结束之间 P%l?C?L  
如果tag处理类实现BodyTag接口,则在doInitBody和doAfterBody中调用,否则在doStartTag中调用 PcT]  
DMch88W  
AT_BEGIN  \SQ4yc  
从tag标签的开始一直到页面结束 ^(C4Q?[2m  
如果tag处理类实现BodyTag接口,则在doInitBody、doAfterBody和doEndTag中调用,否则在doStartTag和doEndTag中调用 3'0vLi  
>]ux3F3\  
AT_END F>#F@j^c  
从tag标签的结束一直到页面结束 ^VMCs/g6  
在doEndTag中调用 j][&o-Ev  
XPMUhozV  
以struts为例,它的bean:define标签的实现遵循JSP1.1规范,此规范要求使用额外tag信息类来定义脚本变量。Variable元素是JSP1.2规范中加入的。以bean:define标签为例,你可以定义如下variable元素: \C>IVz<O  
;K8}Yq9p9  
<tag> rm3/R<  
J Hm Pa  
<variable> $},XRo&R  
+ <E zv  
<name-from-attribute>id</name-from-attribute> -['& aey}a  
."BXA8c;A  
<variable-class>database.BookDetails</variable-class> juF=ZW%i  
5&EBU l}  
<declare>true</declare> 3$YbEl@#  
0<@['W}G  
<scope>AT_BEGIN</scope> \rUKP""m  
I|&DXF  
</variable> T|BlFJ0"  
-A<@Pg  
</tag> 7"aN7Q+EbI  
&gS-.{w "  
额外tag信息类 N.z2eo  
l"dXL"h  
如果要定义一个额外tag信息类,你要继承javax.servlet.jsp.TagExtraInfo类。一个TagExtraInfo类必须实现getVariableInfo方法,此方法返回一个叫VariableInfo的数组类,它包括如下信息: c\rP -"C  
}UGSE2^1  
· 变量名 )Z/w|5<  
P nE7}  
· 变量所属类名 &53,8r  
$#5 'c+0  
· 此变量是否引用了一个新对象 aL&egM*  
psIo[.$rTk  
· 此变量的有效范围 Y0lLO0'  
4V,p\$;  
jsp引擎将一个名为data的参数传给getVariableInfo方法,data中包括tag标签中的所有“属性名?D?D属性值”对。它可以用来向VariableInfo对象提供脚本变量的名字和类名。 }qp)VF  
H6K8.  
以struts为例,它在bean:define标签中定义了一个名为DefineTei的额外tag信息类,用来向脚本变量提供信息。由于脚本变量的名称(book)和类名(database.BookDetails)是通过tag标签的属性来传递的,它们一般定义在VariableInfo的构建代码中,并且可用data.getAttributeString方法来得到这些信息。如果要允许book脚本变量能在从tag开始直到整个JSP页面结束的范围内都可用的话,那它的范围应设为AT_BEGIN。如下所示: mUP!jTF  
&W<9#RPK'  
x!s=Nola  
public class DefineTei extends TagExtraInfo QbHX.:C  
9QHj$)?k,  
{ yZp/P%y  
|gxPuAXa)  
public VariableInfo[] getVariableInfo(TagData data) tF/Ni*\^rV  
;g#nGs>  
{ 7w9'x Y  
tx<^PV2  
String type = data.getAttributeString(“type”); hVB(*WA^D  
,Il) tH  
If( type == null) ^}vf  
@UdF6 :T  
type = “java.lang.Object”; tpA-IL?KQw  
AHuIA{AdUR  
return new VariableInfo[] { [+b8 !'|&  
#0h}{y E  
new VariableInfo(data.getAttributeString(“id”), a)r["*bTx  
A*+gWn,4Y_  
type, (c}!gjm  
yLCMu | +  
true, X0j>g^b8  
W(ryL_#;  
VariableInfo.AT_BEGIN) ,jz~Np_2  
=?y0fLTc  
}; l}(HE+?  
;(}~m&p  
} ;! ?l8R  
85dC6wI4K  
} W-r^ME  
x 4LPrF1  
V+lS\E.  
注意:关于额外tag信息类的类名必须要在TLD中的tag标签下的tei-class子元素中定义。因此,DefineTei的tei-class中的定义看起来如下: Io IhQ  
<tei-class> G^h:#T  
org.apache.struts.taglib.bean.DefineTagTei g^|R;s{  
</tei-class> v8C($<3%  
g&w~eWpk  
G~&8/ s  
具有协作关系的tag 58HAl_8W  
[ t8]'RI%  
J{a9pr6  
tag通过共享对象来进行协作,JSP技术支持2种方式的对象共享。 =c,7uB  
D{7^y>8_Y-  
第一种方法是使用pageContext对象进行对象的共享(可支持JSP页面和tag处理类之间的共享),如果在一个tag处理类中要调用由另一个tag处理类创建的对象,可调用pageContext.getAttribute(name, scope)方法。 <a_ (qh@B  
"v0bdaQH3  
第二各方式的共享是对于tag之间有嵌套关系而言的,外层的tag所创建的对象对于内层的tag来说是可以共用的。这种形式的共享的好处是减少了可能存在的重名冲突。 ,m0 M:!hK  
mc2uI-W  
要访问一个嵌套tag创建的对象,tag处理类必须先找到此嵌套tag对象,可用TagSupport的静态方法 TagSupport.findAncestorWithClass(from, class)或TagSupport.getParent方法。前者在当不确定此tag是否为嵌套tag对象时使用。一旦它的父类被找到,它就能访问其所有动态或静态创建的对象。静态创建的对象是父类的成员,而动态创建的对象可能是父类的私有对象。诸如此类的对象可以用tag处理类的setValue方法来保存,用getValue方法来获得。 wS,fj gX  
7>r[.g  
下例阐述了以上两种共享对象的方法。在这个例子当中,一个查询tag检查一个名为connection的属性名是否在doStartTag中被设置。如果connection属性被设置,tag处理类从pageContext中得到这个connection对象。否则,此tag处理类先找到它的父tag处理类,然后从它的父tag处理类中找到connection对象。 |"Zf0G  
^K J#dT  
+C7W2!I[G2  
public class QueryTag extends BodyTagSupport l+y;>21sTu  
sb_/FE5e  
{ cg]Gt1SU  
Qp:m=f6@  
private String connectionId; / s Apj  
\@h$|nb  
public int doStartTag() throws JspException fXnewPr=#  
*a|575e< z  
{ se>\5k  
Au)~"N~p?  
String cid = getConnection(); FaWc:GsfB  
"B +F6  
if(cid != null) Pz D30VA  
QAo/d4  
{ u~ FVI  
Oop6o $k  
//存在一个connection id,使用它。 wmR~e  
%{V7 |Azt  
connection = (Connection) pageContext.getAttribute(cid); Fo ;J3<U)  
 yoe@]c=  
} =5^1Bl  
2-UD^;0  
else wXnVQ-6H  
=tA;JB  
{ H ~fF; I  
qG~6YCqii  
ConnectionTag ancestorTag = (ConnectionTag)findAncestorWithClass(this, `?l /HUw  
8n2;47 a  
ConnectionTag.class); <f.Eog  
.dxELSV  
if(ancestorTag == null) {gu3KV  
|}YxxeAk  
{ ;{R;lF,  
jHHCJOHB8  
throw new JspTagException(“一个没有connection属性的查询标签必须被一个connection标记嵌套。”); O+< +yQl  
"8?Fl&=Q  
} Dz2Z (EXI~  
}Cfl|t<5f  
connection = ancestorTag.getConnection(); |-*50j l  
S{MB$JA  
} U %BtBPL  
E|RC|Sz=u  
} "+&pd!\  
up8d3  
} >e.KD) qA  
X6t9*|C  
Tu}EAr  
bJ6C7-w:wa  
此查询标签在JSP页面中的调用形式可以从以下2种定义中任选一种: e~'z;% O~  
"dOQ)<;  
d2U?rw_  
<tt:connection id=”con01” ...> ... </tt:connection> /ET+`=n  
LH_ U#P`E  
<tt:query id=”balances” connection=”con01” > 1.8"N&s  
|) &d9|]  
SELECT account, balance FROM acct_table 5{DwD{Q  
-U_,RMw~  
where customer_num = <%= request.getCustno() %> ~g#/q~UE  
- 3PLP$P  
</tt:query> ([rSYKpi  
<:nyRy}  
HFyQ$pbBU  
!OPHS^L  
_tje xS'  
<tt:connection ...> .qYQ3G'V  
!:esdJH  
<x:query id=”balances”> L0=`1q  
LLzxCMc9*  
SELECT account, balance FROM acct_table l:/x &=w  
Ijz*wq\s;  
where customer_num = <%= request.getCustno() %> *M#L)c;6  
6;!)^b  
</x:query> #s>'IPc0  
jRDvVV/-wr  
</tt:connection> 4!96k~d}  
[,ulz4"  
;+o6"ky5  
与此同时,在TLD中必须指定connection属性为可选的,定义如下: #CyqiOM\*  
}F9#3W&`c  
<tag> lMg#zT!?  
$txF|Fj]^A  
... uz$p'Q  
^k^?>h  
<attribute> EDnZ/)6Gg  
fF#Fc&B  
<name>connection</name> ;GOu'34j  
[C;Neslo  
<required>false</required> IBu\Sh-  
Pn@DHYP  
</attribute> cmCD}Skk  
SG0PQ  
</tag>
描述
快速回复

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