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

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

级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
标准的JSP 标记可以调用JavaBeans组件或者执行客户的请求,这大大降低了JSP开发的复杂度和维护量。JSP技术也允许你自定义taglib,其实换句话说,taglib可以看成是对JSP标记的一种扩展,正如xml是对html的一种扩展一样。taglib通常定义在tag标签库中,这种标签库存放着你自己定义的tag标签。简而言之,如果使用taglib,那么你可以设计自己的JSP标记! 1(IZ,*i  
A`Y^qXFb`  
一般来说,自定义tag标签主要用于操作隐藏对象、处理html提交表单、访问数据库或其它企业级的服务,诸如邮件和目录操作等等。自定义tag标签的使用者一般都是那些对java编程语言非常精通,而且对数据访问和企业级服务访问都非常熟悉的程序员,对于HTML设计者来说,使得他可以不去关注那些较复杂的商业逻辑,而将精力放在网页设计上。同时,它也将库开发者和库使用者进行合理分工,自定义tag标签将那些重复工作进行封装,从而大大提高了生产力,而且可以使得tag库可用于不同的项目中,完美地体现了软件复用的思想。 /3~L#jS  
.7g h2K  
在这篇文章中,我们主要讨论: WK(X/!1/k  
!W@mW 5J|  
· 什么是自定义tag标签? -8Mb~Hfl0  
TaBya0-  
· 怎么使用tag标签? DR}I+<*%aD  
_Tor9Tj  
o 声明要使用的tag库 4Zwbu  
?<C(ga  
o 找到与之对应的tag处理类 (b<0=U   
<%S)6cw(3  
o tag标签的类型 3J &R os  
dVEs^ZtI  
· 自定义tag标签 VYkh@j  
Z,E$4Z  
o tag处理类 C:5- h(#  
1Ng.Ukb  
o tag库描述 . c+m(Pk  
)-Hs]D:  
o tag标签示例 }" vxYB!h3  
Qa )+Tv  
o 带属性的tag ge GhM>G  
[=q/f2_1.  
o 带body的tag eQu(3sYb  
j0; ~2W#G*  
o 定义了脚本变量的tag {Fw"y %a^  
Si?s69  
o 具有协作关系的tag /#M1J:SV  
Lxv4w  
· 自定义tag标签 U\?D;ABQ%  
~. vridH  
o 一个迭代tag的例子 S1U0sP@o  
;98b SR/  
o 一个模板tag库 o&E8<e  
0HoHu*+FX  
o tag处理类到底是怎样被调用的? aM;SE9/U  
Y_:jc{?  
|di(hY|  
什么是自定义的tag? S=!WFKcJR  
<7\j\`  
一个自定义的tag标签是用户定义的一种JSP标记。当一个含有自定义的tag标签的JSP页面被jsp引擎编译成servlet时,tag标签被转化成了对一个称为tag处理类的对象进行的操作。于是当JSP页面被jsp引擎转化为servlet后,实际上tag标签被转化成为了对tag处理类的操作。 ?I[8rzBWU  
lTMY|{9  
自定义tag标签有很多特色,诸如: m.m6.  
P|$n   
· 可以在JSP页面中自定义tag标签的属性 W4^zKnH  
uv/\1N;V3  
· 访问JSP页面中的所有对象 jj2iF/  
Intuda7e1  
· 可以动态地修改页面输出 b},2A'X  
JfN '11,$  
· 彼此这间可以相互通信。你可以先创建一个JavaBeans组件,然后在一个tag中调用此JavaBeans组件,同时可以在另一个tag中调用它。 y%i9 b&gDd  
Qq`S=:}~x  
· tag允许相互嵌套,可以在一个JSP页面中完成一些复杂的交互。 F~ 5,-atDM  
3LLG#l )8  
qS/}aDk&  
使用tag标签 7 mCf*|  
5 :IDl1f5  
I0 ~'z f  
本节主要描述怎样在JSP页面中使用tag标签,以及tag标签的不同类型。 .h=n [`RB  
1Z< ^8L<  
要使用tag标签,JSP程序员必须做2件事: {S{%KkAV  
rzAf  {2  
· 声明此tag标签的tag库 m1pA]}Y/5o  
@-dGZ 5  
· 实现此tag标签 9m)$^U>oz  
,^?g\&f(  
声明tag标签所在的tag库 qhxMO[f  
@^UgdD,BS,  
如果要使用tag标签,则应用JSP的taglib指示符来指定其tag库(注意:taglib要在在使用此tag标签之前声明) mcd{:/^?  
}S u j=oFp  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> eavn.I8J  
Ra|P5  
uri属性定义了唯一的标签库描述(以下简称TLD),它可以是直接是tld文件名或一个独一无二的名字。prefix是用来区别其它TLD中和本TLD中有重名的tag的一种手段。 qhGz2<}_j  
_HHvL=  
TLD必须以.tld作为扩展名,并且存放在当前应用的WEB-INF目录或其子目录下。你可以通过它的文件名直接引用它,也可以通过别的方式间接地引用它。 #kM|!U=  
MRt"#CO  
以下taglib指示符直接引用一个TLD: , yltt+ e  
AyO%,6p[  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> f-|?He4O]  
KBB)xez8  
以下的taglib指示符通过一个逻辑名称间接地引用一个TLD: e^O:I  
Z|n|gxe  
<%@ taglib uri=”/tutorial-template” prefix=”tt” %> r&4Xf# QD6  
=;0-t\w!  
如果是间接引用TLD的话,那你必须还要在web.xml中定义此逻辑名称与tld文件之间的映射,具体做法是在web.xml中加入一个名为taglib的元素: q!:dZES  
[n[dr@J7v  
<taglib>  U=~?ca  
*0>`XK$mWo  
<taglib-uri>/tutorial-template</taglib-uri> MT~^wI0a  
!YAX.e  
<taglib-location> k5Cy/gR  
-4Hb]#*2  
/WEB-INF/tutorial-template.tld Q0R05*  
=l43RawAmu  
</taglib-location> a -Pz<*  
-13}]Gls7Q  
</taglib> ev;&n@k_I  
)\Q(=:  
Pb'(Y  
实现此tag标签 'z8FU~oU  
t,f ec>.  
6AJk6 W^Z  
为了实现tag标签,你有2种方法来存放tag处理类。一、让tag处理类以.class的方式存放于当前应用的WEB-INF/class子目录下,二、如果tag处理类是以JAR包的形式存在的话,那可以放在当前应用的WEB-INF/lib目录下,如果tag处理类要在多个应用中共享,那么它就应放在jsp服务器上的common/lib目录下,对于tomcat来说,就是tomcat/common/lib目录下。 dBd7#V:}yV  
)ovAGO  
RlL ]p`g  
tag标签类型 l'(FM^8jv  
>;MJm  
Q<V(#)*  
自定义的tag标签遵循XML语法。它有一个开始标记和一个结束标记,有的还有body(即文本节点): 61H_o7XXk  
l%EvXdZuOy  
<tt:tag> AaYH(2m-  
!ddyJJ^a  
body AE7 7i,Xa  
N4ZV+ |  
</tt:tag> `Jc/ o=]  
?2&= +QaT  
dHIk3j-!  
一个不带body的tag标签如下: S3Y.+. 0U  
GmR3 a  
<tt:tag /> e El)wZ,A  
H7tv iSTd  
jvB[bS`<H  
简单的tag标签 -SM_JR3<  
$$m0mK  
一个没有body和属性的tag标签如下: P5?VrZy  
> mO*.'Gm  
<tt:simple /> pRun5 )7  
Qa_V  
Vr},+Rj  
带属性的tag标签 $!*>5".A  
/3aW 0/^o  
T9V=#+8#"  
自定义标签可以有自己的属性。属性一般在开始标记中定义,语法为 attr=”value”。属性的作用相当于自定义标签的一个参数,它影响着tag处理类的行为。你可以在TLD中详细定义它。 ! eZls  
$b|LZE\bU.  
你可以用一个String常量给一个属性赋值,也可以通过表达式给它赋值,如<%= ...%>。以struts为例,它的logic:present标签就是用的String常量来给属性赋值: \~*<[.8~  
 "M5  
<loglic:present parameter = “Clear”> D:Q#%wJ  
8Ij<t{Lps  
而另一个标签logic:iterate是用表达式来给属性赋值: ~Tt@ v`}  
*,Bm:F<m  
<logci:iterate collection=”<%= bookDB.getBooks() %>” T$lV+[7  
 .+1I>L  
id=”book” type=”database.BookDetails”> F NPu  
f/J/tt  
c7r( &h  
带body的tag标签 (O+d6oT=Z2  
l }/_(*  
一个自定义标签可以包含其它自定义标签、脚本变量、HTML标记或其它内容。 X\Bl? F   
.h meP MK  
在下述例子中,此JSP页面使用了struts的logic:present标签,如果些标签定义了parameter=”Clear”的属性,则将清除购物车的内容,然后打印出一条信息: Ts !g=F  
aPelt`  
<logic:present parameter=”Clear”> gw"cXny  
Cy?]o?_?  
<% cart.clear(); %> !s-A`} s+  
tG$O[f@U6  
<font color=”#ff0000” size=”+2”><strong>  ,RR{Y-  
b y>%}#M  
你选择了清除购物车! Z2M(euzfi3  
`6VnL)  
</strong></font> O z0-cM8t  
3tf_\E+mIi  
</logic:present> ^!S4?<v  
B9NUafK=  
0FcDO5ia  
到底是用属性还是用body来传递信息? F&6#j  
"v:k5a(  
如上所述,我们既可以通过属性,也可以通过body来传递信息。但一般来说,比较简单的类型,如字符串或简单表达式最好采用属性来传递信息。 } 9\_s*  
O6Py  
5&s6(?,Eu  
定义脚本变量的tag标签 ura&9~   
p"hO6b%V  
所谓脚本变量,是指JSP中可以调用的变量或对象。它可由tag标签产生。以下示例阐述了一个tag标签定义了一个名为tx的由JNDI所定义的事务处理对象。脚本变量可以是ejb对象、事务、数据库连接等等: 0;TiNrzg  
c]E pg)E  
<tt:lookup id=”tx” type=”UserTransaction” name=”java:comp/UserTransaction” /> f DXK<v)  
#` 3Q4  
<% tx.begin(); %> Hy3J2p9.  
i$] :Y`3h  
... &pzL}/u  
)L9eLxI  
<}WSYK,zUY  
具有协作关系的tag标签 IaeO0\ 4E  
.F7?}8>Z  
自定义tag标签之间可以通过共享对象来实现协作。在下述例子中,标签tag1创建了一个名为obj1的对象,在标签tag2仍可以重复使用obj。 w0g@ <( 3  
v>LK+|U  
<tt:tag1 attr1=”obj1” value1=”value” /> _\d|`3RM  
@FIL4sb  
<tt:tag2 attr1=”obj1” /> =Oy&f:s  
?Vg~7Eu0  
在以下这个例子当中,如果外层的tag标签创建了一个对象,那么其内层的所有tag标签都可以使用这个对象。由于这样产生的对象没有一个指定的名字,那么就可以将少重名的冲突。这个例子阐述了一系列协作的嵌套对象。 _5 SvZ;4  
=7+%31  
<tt:outerTag> K uwhA-IL  
;t+p2i  
<tt:innerTag /> *}C%z(  
01@ WU1IN  
</tt:outerTag> p?$N[-W6-  
:0y-n.-{  
>!1] G"U  
Tag处理类 =Lkn   
fC'u-m?!Q'  
sX6\AYF1M  
Tag处理类必须实现Tag接口或BodyTag接口,不过现在一般都流行从TagSupport或BodyTagSupport类中继承,这些类或接口都可以在javax.servlet.jsp.tagext包中找到。 N-2#-poDe  
'df@4}9  
当JSP引擎看到自己的JSP页面中包含有tag标签时,它会调用doStartTag方法来处理tag标签的开头,调用doEndTag方法来处理tag标签的结束。 >Y4^<!\v  
YA@?L!F  
下表说明不同类型的tag所需要不同的处理过程: PJZ;wqTD_  
l\ dPfJ  
Tag处理类的方法 7kV$O(4  
oA5Qk3b:  
Tag标签类型 }'Ap@4  
所调用的方法 B`QF;,3S  
aiX&`   
基本标签 9c]$d  
doStartTag, doEndTag, release vx?KenO}  
CfW#Wk:8J  
带属性的标签 _XZK2Q[  
doStartTag, doEndTag, set/getAttribute1...N, release a.<XJ\  
{BlTLAKm  
带内容的标签 #6c,_!  
doStartTag, doEndTag, release )>h3IR  
@VP/kut  
带内容的标签,且内容重复循环 e- `9-U%6  
doStartTag, doAfterBody, doEndTag, release 8*8Y\"  
e/Z{{FP%6  
带内容的标签,且内容与JSP交互 6?}|@y^fb  
doStartTag, doEndTag, release, doInitBody, doAfterBody, release WrwbLlE  
mIf)=RW  
一个tag处理类可以通过javax.servlet.jsp.PageContext来与JSP交互,通过javax.servlet.jsp.PageContext类,tag处理类可以访问JSP中的request、session和application对像。 BsXF'x<U*  
P4"BX*x  
如果tag标签是互相嵌套的,那内层的tag处理类可以通过它的parent属性来访问上层的tag处理类。 c),UO^EqV  
pRjEuOc  
一般情况都将所有的tag处理类打成了JAR的包,以便于发布。 ;s,1/ kA  
by9UwM=gp  
J37vA zK%  
Tag库描述(简称TLD) G0: <#?<5  
w@2NXcmw  
w +UB XW  
Tag库是用xml语言描述的,TLD包括了tag库中所有tag标签的描述,它一般用来被jsp服务器用来校验tag的语法正确性,或者被jsp开发者用来开发新的标签。 4;~xRg;u&*  
ww %c+O/  
TLD的文件扩展名必须为.tld,而且必须放在当前WEB应用的WEB-INF目录或其子目录中。 DOtz  
:@ &e~QP(  
一个TLD的内容的开头必须遵守标准的XML开头,用于描述DTD和xml的版本,例如: 2A  
@8J*vY =e  
<?xml version="1.0" encoding="ISO-8859-1" ?> G?F!Z"S  
Ke^/aGi}O  
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd"> '2l[~T$*  
TLD必须以<taglib>来作为它的根元素,<taglib>的子元素如下表: @}UOm- M  
y+BiaD!U  
9*j"@Rm  
<taglib>的子元素 tPiC?=4R  
o&q:b9T  
Element H)TKk%`7  
Description M GC=L .  
9Q(Lnu  
tlib-version zz3{+1w]  
Tag库的版本 vB7]L9=@"  
}c8et'HYf  
jsp-version Y_$!XIJ4  
Tag库所需要的jsp的版本 lz0dt<8eP  
8B6(SQp%  
short-name _Iy)p{y  
助记符,tag的一个别名(可选) oSYJXs  
]p(es,[  
uri Zu#^a|PE*  
用于确定一个唯一的tag库 vKoQ!7g  
}6u}?>S  
display-name 'GW~~UhdW  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) T: '<:*pD  
q\P{h ij  
small-icon &Kc45  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) S5m.oHJI*  
%[*_-%  
large-icon _JpTHpqu  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选)  w D  
%j0c|u  
description agoMsxI9  
对tag库的描述(可选) F$v^S+Ch  
N["M "s(N  
listener J|V*g]#kP  
参见下面listener元素 p&XuNk  
,UVd+rY}  
tag fCb&$oRr!  
参见下面tag 元素 ]$)};8;7W  
T;kh+ i  
Listener元素 Ktuv a3=>N  
+;@R&Y  
一个tag库可能定义一些类做为它的事件侦听类,这些类在TLD中被称为listener 元素,jsp服务器将会实例化这些侦听类,并且注册它们。Listener元素中有一个叫listener-class的子元素,这个元素的值必须是该侦听类的完整类名。 ak}k e  
F+zHgE  
Tag元素 qCk`398W  
IL&R&8'  
每个tag元素在tag库中都要指出它的名字、类名、脚本变量、tag的属性。其中脚本变量的值可以直接在TLD中定义或通过tag附加信息的类来取得。每个属性描述了这个属性是否可以省略,它的值是否可以通过<%= …%>这样的JSP语法来获得,以及属性的类型。 =AK6^v&on  
}e"2Nc_UG  
每一个tag在TLD中对应一个tag元素,下表是tag元素的子元素: OpOR!  
5=<fJXf5y  
Tag元素的子元素 Jk<b#SZ[b  
R=NK3iGTf  
元素名称 hNcEBSQ  
描述 l0!`>Xx[b  
kU)E-h  
name v~^*L iP+  
独一无二的元素名 Ov:U3P?%  
7'{%djL  
tag-class <ihJp^kgQ  
Tag标签对应的tag处理类 coXm*X>z  
k~Y_%#_  
tei-class /ubGa6N  
javax.servlet.jsp.tagext.TagExtraInfo的子类,用于表达脚本变量(可选) 0Z AtBq.s  
\ o?  
body-content )Zyw^KN^  
Tag标签body的类型 &~)1mnv.  
k V'0rb  
display-name z\J#d 1e  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) &C/,~pJ1S  
Ip,0C8T`Q  
small-icon K]U8y$^  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) fxD|_  
vf<Tq  
large-icon AIQ]lQ(  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) TY#pj  
qy!pD R;  
description fJ-8$w\uL  
此tag标签的描述 t2-bw6U  
Ga"<qmLMc  
variable y5V]uQSD  
提供脚本变量的信息(同tei-class)(可选) oH [-fF  
8{.:$T  
attribute lgCOp%>  
Tag标签的属性名 OB+I.qlHP  
X2('@Yh  
以下章节介绍对于不同类型的tag,如何具体地实现它们。 rI]n4>k{  
D7N` %A8   
BjUz"69  
简单的tag y-7$HWn  
ps]s Tw  
J}&xS<  
tag处理类 t7 $2/C  
0K^G>)l  
简单的tag处理类必须实现Tag接口的doStartTag和doEndTag方法。当jsp引擎碰到tag标签的开头时,doStartTag被调用,因为简单的tag没有body,所以此方法将返回 SKIP_BODY。当jsp引擎碰到tag标签的结尾时,doEndTag被调用,如果余下的页面还要被计算,那它将返回EVAL_PAGE,否则将会返回SKIP_PAGE。 m}-~VYDj  
7[7Sm^Tw  
以下是例子:对于标签 <tt:simple /> ,它的tag处理类实现如下: WkY>--^  
0V#eC  
0>?78QL9<  
public SimpleTag extends TagSupport ld23 ^r  
;Q8rAsf 9  
{ +(2mHS0_a  
<7~+ehu  
public int doStartTag() throws JspException 2fJ2o[v  
S|v-lJ/I  
{ P^ bcc  
ki_Py5  
try{ }~o>H a;  
[hXU$Y>"0  
pageContext.getOut().print(“Hello.”); /&'rQ`nd  
cd*F;h  
}catch(Exception e){ L sMS`o6  
\ 5^GUT  
throw new JspTagException(“SimpleTag: “ + e.getMessage()); g~=#8nJ  
I'RhA\`  
} R<-(  
K5q9u-7  
return SKIP_BODY; k*xgF[T 8  
]2B=@V t,  
} E2{SKIUm  
yn5yQ;  
public int doEndTag() M&O .7B1}  
w6l8RNRe  
{ -J*jW N!  
VFwp .1oa!  
return EVAL_PAGE; owc#RW9 7  
> jvi7  
} 3YPoObY  
CVBy&o"6A  
} R`|GBVbv  
[2cG 7A  
sHulaX{  
注意:如果tag标签没有内容的话,那必须定义body-content元素为空,例如 b]U%|bp  
w873: =  
<body-content>empty</body-content> q6v%HF-q4  
+3n07d  
"8Y4;lbN.q  
带属性的tag标签
评价一下你浏览此帖子的感受

精彩

感动

搞笑

开心

愤怒

无聊

灌水
级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
只看该作者 1 发表于: 2007-01-01
tag处理类 bR!*z  
p M:lg  
对于tag标签的每个属性,你必须依照JavaBeans规范来定义其属性,以及get和set方法。以struts的logic:present 标签为例, xW\iME  
u%vq<|~-  
<logic:present parameter=”Clear”> (r?41?5K  
LHb(T` .=  
与此相应,此tag处理类应有如下方法和定义: 8D U|j-I8  
ga~C?H,K  
^?H3:CS  
protected String parameter = null; Em8C +EM  
ZVj/lOP X  
public String getParameter() 0XBv8fg  
+ AyrKs?h  
{ 257pO9]  
fE;<)tU  
return this.parameter; |A#pG^  
"-+5`!Y  
} hYMo5?  
!giL~}j(R  
public void setParameter(String parameter) O!(M:.  
Ph'P<h:V  
{ kw>W5tNpf:  
~4\J }Kn  
this.parameter = parameter; |T}Q ~  
Oozt&* F  
} ,=tPh4>  
`)5E_E3  
0m^(|=N-  
注意:如果你的属性名为id,而且你的tag处理类是从TagSupport类继承的,那你就不需要定义它的属性和set和get方法,因为他们早已在TagSupport被定义过了。 ) )q4Rh  
8(e uWS  
Attribute元素 1>1&NQ#}  
Ap{p_~~iJ  
对于tag标签的每个属性,你必须定义它是否必须的,它的值是否可以用诸如<%= …%>的表达式来获得,以及它的类型(可选),如果不指定它的类型,那就默认为是java.lang.String类型。如果rtexprvalue元素被定义为true或yes,那么在type元素中就定义了attribute的返回类型。 a'zf8id  
/[iqga=  
<attribute> Quy&CV{@  
lU0'5!3R,  
<name>attr1</name> +wU9d8W  
mjDaus59  
<required>true|false|yes|no</required> |?=K'[ 5  
0wCJNXm  
<rtexprvalue>true|false|yes|no</rtexprvalue> -rSp gk0wL  
r(W=1e'  
<type>attribute的返回类型(只用当rtexprvalue为真是才有效)</type> h|tdK;)  
F(J6 XnQ  
</attribute> 0L_ JP9e  
O9#8%p% )  
如果tag的某个属性不是必须的,那tag处理类会自动提供一个缺省值。 $ \j/s:Y  
G'oMZb ({=  
例如,在logic:present这个tag标签中定义了一个属性叫parameter,但它不是必须的,而且它可以被诸如<%= …%>的表达式来赋值。 |UN0jR  
XrY\ot`,D  
<tag> ?CgqHmf\\(  
'`#sOH  
<name>present</name> IvFxI#.ju  
]uN}n;`12  
<tag-class>org.apache.struts.taglib.logic.PresentTag</tag-class> r%*,pN7O  
uz6S7I  
<body-content>JSP</body-content> Tji G!W8  
qU(,q/l  
3xSt -MA  
|N%?7PZ(  
<attribute> fz[o;GTc  
kQ5mIJ9(  
<name>parameter</name> LD]a!eY  
slC 38  
<required>false</required> tONX<rA|]  
p.1@4kgK&r  
<rtexprvalue>true</rtexprvalue> a\60QlAk~  
\&K{v#g ~  
</attribute> B|9)4f&\=R  
KTr7z^  
}w{ 6Ua  
[&e|:1  
</tag> >?/Pl"{b  
cn62:p]5  
z']TRjDbT  
属性元素的校验 3mI(5~4A]?  
tI42]:z  
-? _#Yttu  
有关于tag标签的有效值可以从tag库的说明文档中获得,当JSP页面被编译时,jsp引擎会强制性地参照TLD中定义的规则进行检查。 >/@wht4- j  
Ah5`Cnv  
还有一个方法也可以进行属性元素的校验,就是先继承类TagExtraInfo,然后调用它的isValid方法。这个类同时也起到提供tag中定义的脚本变量信息的作用。 -][~_Hd{  
SvZ~xTit  
IsValid方法通过TagData对象来传递属性信息,它包括着tag的所有的属性名-值的信息。由于校验发生在运行时刻,因此这个属性的值将被赋值为TagData.REQUEST_TIME_VALUE。 ^O#>LbM"x  
y:t@X~  
例如tag标签<tt:twa attr1=”value1” />在TLD中定义如下: N~rA/B]T  
0!<qfT a  
<attribute> TR;"&'#k  
w$Zi'+&*  
<name>attr1</name> 5f;6BP  
-MEp0  
<required>true</required> ,E8:!r)6  
[Dr'  
<rtexprvalue>true</rtexprvalue> )ry7a .39b  
d}@b 3   
</attribute> ;gS)o#v0  
99<]~,t=5  
Gw!VPFV>W  
这个定义说明了attr1能在运行期间被赋值。 sIUhk7Cd8  
=35g:fL  
以下的isValid方法检查attr1属性的值是否属于Boolean类型。注意由于attr1能在运行刻被赋值,那么isValid方法必须检查tag用户是否对此tag进行了运行时刻赋值。 Iw)}YZmn  
=geopktpf  
H( L.k;B  
Public class TwaTEI extends TagExtraInfo ?4k/V6n@y  
.|\}] O`  
{ ~quof>  
6pJFrWe{  
public boolean isValid(Tagdata data) JXFPN|  
>A5*=@7bY?  
{ /g/]Q^  
|/^ KFY"  
Object o = data.getAttribute(“attr1”); S2y_5XJ<D  
tx` Z?K[  
If(o != null && o != TagData.REQUEST_TIME_VALUE) w)C/EHF  
@c;XwU]2t  
{ R[#Np`z  
{5 V@O_*{  
if( ( (String)o).toLowerCase().equals(“true”) || |7Dc7p"D  
QZwUv<*  
((String)o).toLowerCase().equals(“false”) ) rra|}l4Y  
EM2=g9y  
return true; #VM+.75o1  
%mqep5n(  
else ]>v C.iYp  
`!,"">5  
return false; .rPg  
_HMQx_e0YM  
} k)j6rU  
={'3j  
else cn ~/P|B[  
p!oO}gE  
return true; 0P_=Oy"l-  
/penB[ 1i  
} NL^;C3u  
\wZ 4enm  
} ~,^pya  
#%9t-  
9%#u,I  
带body的tag SEKR`2Zz,  
LZ=E  
NqlU?  
tag处理类 _xWX/1DY  
Ez1-Nx  
ylGT9G19  
如果tag标签含有内容,那处理方式会略微有些不同,而且还要视tag处理类是否要与body交互的情况而定。如果要与body交互,那我们认为tag处理类要可能要对body进行操作。 ?^3Y+)}  
KPi_<LuK  
Tag处理类不与body交互 ?4`f@=}'K  
$)YalZ  
如果tag处理类不与body交互,tag处理类应该实现Tag接口或从TagSupport中派生,如果body要被计算,那么doStartTag方法应返回 EVAL_BODY_INCLUDE,否则应返回SKIP_BODY。 "xI70c{  
QLm#7ms*y  
如果tag处理类要对body反复运算,则它应该实现IterationTag或从TagSupport中派生。如果tag处理类认为body还未计算完的话,那它的doStartTag方法和doAfterBody方法必须返回EVAL_BODY_AGAIN。 ,+P2B%2c  
'G1~ A +  
Tag处理类与body交互 yac4\%ze  
@vc9L  
如果tag处理类与body交互,那tag处理类应实现BodyTag接口或从BodyTagSupport中派生。这种tag处理类一般要实现doInitBody和doAfterBody方法。 <lkt'iT=Sz  
A!$;pwn0  
Body允许一些方法来读写它的内容。Tag处理类可以调用body内容的getString或getReader方法来从body中提取信息,也可用 writeOut(out) 方法来将body的内容写入到out对象中。其中out对象通过tag处理类的getPreviousOut方法来获得。 "cZ){w  
$x~U&a  
如果body的内容需要被计算,那么doStartTag方法必须返回EVAL_BODY_BUFFERED,否则,它将返回 SKIP_BODY。 gB_gjn\  
w,T-vf  
doInitBody 方法 g+j\wvx0  
7_9^nDU  
此方法在body内容已经设好,但未被计算之前被调用。你可以根据不同的body内容来制定初始化策略。 r@t \a+  
>rhqhmh;W"  
doAfterBody方法 ' Ig:-  
o[aP+O Md  
此方法在body内容已被计算后进行调用。 9oj#5Hq  
9GX'+$R]  
和doStartTag方法一样,doAfterBody方法返回一个指示符指示是否要继续计算body,如果要继续计算,则doAfterBody应返回EVAL_BODY_BUFFERED,否则,它应返回SKIP_BODY。 FfRvi8  
Od("tLIO}I  
release 方法 u?4d<%5R!  
@?n~v^  
tag处理类调用此方法将它的状态重置为初始状态,并释放所有的私有资源。 r1&eA%eh  
{i<L<Y(3  
|4C5;"Pc  
以下的例子读取body的内容(其中含有一条sql语句),然后将它传递给一个对象,让它进行查询。由于此处body不须重新计算,所以doAfterBody会返回SKIP_BODY。 <YM!K8hu$  
swz)gh-*  
5E#8F  
Public class QueryTag extends BodyTagSupport fKbg?  
j6d{r\!$4  
{ *snY|hF  
%$<v:eMAs  
public int doAfterBody() throws JspTagException XI '.L ~  
Wh)>E!~ 9  
{ %oOSmt  
v t_lM  
BodyContent bc = getBodyContent(); {,=U]^A  
2Rqpok4  
//将body的内容以字符串的格式提取出来 Ofc u4pi  
$ba*=/{[q  
String query = bc.getString(); 782 oXyD  
|;(>q  
//清除body gXj3=N(l  
j.yh>"de  
bc.clearBody(); /s~BE ,su  
6/.kL;AI  
try{ Z817f]l  
sis1Dh9:  
Statement stmt = connection.createStatement(); c;,-I  
b{CS1P  
Result result = stmt.executeQuery(query); %0zp`'3Y  
q%/\  
}catch(SQLException e){ pK"iTc#\X  
@x^/X8c(p  
throw new JspTagException(“queryTag: “ + e.getMessage() ); ro+8d  
uO((Mg  
return SKIP_BODY; D/ tCB-+  
G|I}x/X"Q7  
} BZa`:ah~x  
pwv mb\  
} ,z01 *Yx  
cK,&huk  
t>2EZ{N +y  
body-content元素 mT>RQ.  
;v!Ef"E|cV  
gDjAnz#  
由于tag可能会有body,你必须用body-content元素来指定body内容的类型: $Ji;zR4,  
,*sKr)9)  
<body-content>JSP|tagdependent</body-content> b"2_EnE}1  
IC6'>2'=T  
;*{Ls#  
如果body的内容是定制的或内部的tag、脚本元素、或HTML广本,则归类为JSP类型。其他的类型,比如上面代码所述的?D?D将sql statement类传给 query tag的这种类型应该标为tagdependent。 SAU` u]E  
`[&%fTW+  
注意:实际上body-content的值并不影响tag处理类对body内容的处理,它仅仅是被tag编辑工具用来描述此body的内容。 ZkBWVZb  
5 0dx[v8  
pQ xv_4  
用tags定义脚本变量 $T_>WUiK  
+Mb}70^  
jItVAmC=i  
tag处理类 ;D<;pW  
VFK]{!C_  
Q yhu=_&  
tag处理类负责创建或设置页面中定义的脚本变量,用pageContext.setAttribute(name,value,scope)或pageContext.setAttribute(name,value)方法来实现。一般来说,tag处理类通过脚本变量的名称来获取它,脚本变量的名称一般可用get方法来获得。 T5-Yqz  
pI1g<pe  
如果脚本变量的值依赖于tag处理类中的上下文中某一对象,那它可用pageContext.getAttribute(name,scope)方法来找到那个对象。一般的处理过程是tag处理类先找到脚本变量,再对其进行处理,然后用pageContext.setAttribute(name,object)的方法来设置它的新值。 `NQ;|!  
y~z&8XrH  
对象的生存周期(scope)如下表: mMT\"bb'  
ba)hWtenH  
对象的生存周期表 tqpSir  
u p]>UX8  
名字 /A-VT  
可访问范围 P\h1%a/D  
生存周期 oz%{D@CF  
7e[&hea  
page RJ-J/NhWyI  
当前页面 jw)c|%r>  
一直有效,除非页面向客户提交响应或重定向到一个新页面 `*xSn+wL`_  
<Wd_m?z  
request &{bNa:@  
当前页面或当前页面重定向到的页面 (/S6b  
一直有效,除非页面向客户提交响应 TCK#bJ  
k&:~l@?O  
session Y=/;7T  
当前页面或在同一浏览器窗口中的页面 I5]58Ohx  
一直有效,除非关闭当前浏览器、超时、网络故障 Qnx?5R-}ZU  
xiVbVr#[  
application ;<=z^1X9  
整个web应用程序的所有请求 1I%niQv5t  
一直有效,除非发生网络故障、服务器故障 L+lX$k  
%r@:7/  
提供关于脚本变量的信息 O4!!*0(+91  
_y:a Pn  
以下示例定义了一个名为“book”的脚本变量,用来访问程序中关于书的信息: PB #EU 9  
H|3CZ=U?  
<bean:define id=”book” name=”bookDB” property=”bookDetails” type=”database.BookDetails” /> 9Qq%Fw_  
zpy&\#Vc  
<font color=”red” size=”+2” > }vZTiuzC  
wS [k}  
<%= messages.getString(“CartRemoved”) %> k;<F33v;Mh  
miV8jaV  
<strong><jsp:getProperty name=”book” property=”title” /></strong> ! QKec  
L> rW S-  
</font> +D?Re%HI  
uFG ;AY|  
当包含此tag的JSP页面被编译时,jsp引擎会自动生成关于此book的同步的代码(同步可以避免几个客户同时访问此book时造成的冲突),要生成同步代码,jsp引擎需要知道此脚本变量的如下信息: 0xV[C4E[6  
?SX0e(+}}  
· 脚本变量名称 1]aya(  
,w,)n^  
· 脚本变量所属的类 +$R%Vbd  
6-\C?w A  
· 此脚本变量是否引用了一个新的或已存在的对象 N::.o+1  
'EB5#  
· 此脚本变量的有效性 ~Q)Dcit-  
0{u#{_  
有两种办法可以向jsp引擎提供关于脚本变量的信息:在TLD中定义variable子元素,或用tei-class子元素定义一个额外tag信息类。用variable最简单,但可能降低了一些灵活性。 BQ {'r^u  
R4XcWx*pQ  
Variable元素 f|,2u5 ;z  
&>Z p}.V  
Variable元素有如下子元素: mFyYn,Mu|  
N8Un42  
· name-given ?D?D 给出的名字,是一个常量 ! H4uc  
S/6I9zOP  
· name-from-attribute?D?D 属性名,在编译时给出的属性名 XRn+6fn|  
a61?G!]  
name-given或name-from-attribute两者必须选一,但以下子元素是可选的: Q[bIkvr|  
}S9uh-j6l  
· variable-class?D?D变量的类型,缺省为java.lang.String。 h=_h,?_  
_2eL3xXha.  
· declare?D?D此脚本变量是否引用了一个新对象,缺省为True。 Ifj%"RI  
h}%yG{'/M=  
· scope?D?D脚本变量的范围,缺省为NESTED。下表描述了scope的几种类型: ; zfBe%Uf  
aIE\B4w  
脚本变量的有效范围 ScC!?rTW~7  
{\kDu#18Ld  
xKoNo^FF  
有效性 {6*{P!H  
方法 u"zQh|  
w&}UgtEm  
NESTED kN* \yH|  
在tag标签的开始和结束之间 mh~n#bah  
如果tag处理类实现BodyTag接口,则在doInitBody和doAfterBody中调用,否则在doStartTag中调用 cx4'rK.  
1F?ylZ|~  
AT_BEGIN 5O"wPsl  
从tag标签的开始一直到页面结束 uzLIllVX*  
如果tag处理类实现BodyTag接口,则在doInitBody、doAfterBody和doEndTag中调用,否则在doStartTag和doEndTag中调用 W97 &[([  
r<.*:]L  
AT_END =_d-MJy~6  
从tag标签的结束一直到页面结束 mWU*}-M  
在doEndTag中调用 0Y\7A  
=Y5*J#  
以struts为例,它的bean:define标签的实现遵循JSP1.1规范,此规范要求使用额外tag信息类来定义脚本变量。Variable元素是JSP1.2规范中加入的。以bean:define标签为例,你可以定义如下variable元素: .w)T2(  
Jm}zit:o  
<tag> @_Ly^' "  
Ox f,2r  
<variable> h_h6@/1l  
0"M0tA#  
<name-from-attribute>id</name-from-attribute> e7gWz~  
DYCXzFAa  
<variable-class>database.BookDetails</variable-class> 1H,hw  
P C  
<declare>true</declare> 9rQpKq:# E  
_:l<4u !  
<scope>AT_BEGIN</scope> HltURTbI  
,_yf5 a  
</variable> As*59jkB  
Q_n9}LanP  
</tag> R P6R1iN3  
V~qlg1h  
额外tag信息类 \JEI+A PY*  
Gex%~';+q  
如果要定义一个额外tag信息类,你要继承javax.servlet.jsp.TagExtraInfo类。一个TagExtraInfo类必须实现getVariableInfo方法,此方法返回一个叫VariableInfo的数组类,它包括如下信息: -\=kd {*B  
pn2_ {8.  
· 变量名 ek4?|!kQD  
@T+pQ)0{{  
· 变量所属类名 +Pm }_"GU  
Z=P=oldH  
· 此变量是否引用了一个新对象 lr@H4EJ{  
dNcP_l/A  
· 此变量的有效范围 Oo 95\Yf$N  
Nh|QYxOP  
jsp引擎将一个名为data的参数传给getVariableInfo方法,data中包括tag标签中的所有“属性名?D?D属性值”对。它可以用来向VariableInfo对象提供脚本变量的名字和类名。 x kebel`%  
Gu136XiX  
以struts为例,它在bean:define标签中定义了一个名为DefineTei的额外tag信息类,用来向脚本变量提供信息。由于脚本变量的名称(book)和类名(database.BookDetails)是通过tag标签的属性来传递的,它们一般定义在VariableInfo的构建代码中,并且可用data.getAttributeString方法来得到这些信息。如果要允许book脚本变量能在从tag开始直到整个JSP页面结束的范围内都可用的话,那它的范围应设为AT_BEGIN。如下所示: Qws#v}xF  
&\o !-EIK8  
awa$o  
public class DefineTei extends TagExtraInfo >P\/\xL=  
ZN?UkFnE  
{ ,b8q$ R~\  
tvG/oe .1'  
public VariableInfo[] getVariableInfo(TagData data) FqK2[]8  
ZX!u\O|w  
{ L`{EXn[  
&O.S ;b*+  
String type = data.getAttributeString(“type”); v><uHjP  
U0W- X9>y  
If( type == null) *QpKeI  
I|?Z.!I|  
type = “java.lang.Object”; 675x/0}GO  
Fu cLcq2Z  
return new VariableInfo[] { p#dpDjh  
 ,M&[c|  
new VariableInfo(data.getAttributeString(“id”), tJ9i{TS  
W:16qbK  
type, j/xL+Y(=  
 !(<Yc5  
true, URD<KIN>  
-3T6ck  
VariableInfo.AT_BEGIN) sx0:g?F3j  
eqze7EY  
}; \WVrn>%xu  
3 # ua  
} (_ElM>  
]OOL4=b  
} 0oi =}lV  
G&Sp }  
RT)*H>|  
注意:关于额外tag信息类的类名必须要在TLD中的tag标签下的tei-class子元素中定义。因此,DefineTei的tei-class中的定义看起来如下: ' cl&S:  
<tei-class> 5? s$(Lt~  
org.apache.struts.taglib.bean.DefineTagTei V/G'{ q  
</tei-class> ZrFC#wJb  
8?r ,ylUj  
a|im DY_-j  
具有协作关系的tag @E$PjdB5M  
$Y4;Xe=  
)5j%."  
tag通过共享对象来进行协作,JSP技术支持2种方式的对象共享。 mSzBNvc i  
f9g#pyH4  
第一种方法是使用pageContext对象进行对象的共享(可支持JSP页面和tag处理类之间的共享),如果在一个tag处理类中要调用由另一个tag处理类创建的对象,可调用pageContext.getAttribute(name, scope)方法。 $Q|t^(  
?q <"!U|e  
第二各方式的共享是对于tag之间有嵌套关系而言的,外层的tag所创建的对象对于内层的tag来说是可以共用的。这种形式的共享的好处是减少了可能存在的重名冲突。 A8R}W=  
dSb|hA}@  
要访问一个嵌套tag创建的对象,tag处理类必须先找到此嵌套tag对象,可用TagSupport的静态方法 TagSupport.findAncestorWithClass(from, class)或TagSupport.getParent方法。前者在当不确定此tag是否为嵌套tag对象时使用。一旦它的父类被找到,它就能访问其所有动态或静态创建的对象。静态创建的对象是父类的成员,而动态创建的对象可能是父类的私有对象。诸如此类的对象可以用tag处理类的setValue方法来保存,用getValue方法来获得。 [$Ld>`3  
}I'g@Pw9[  
下例阐述了以上两种共享对象的方法。在这个例子当中,一个查询tag检查一个名为connection的属性名是否在doStartTag中被设置。如果connection属性被设置,tag处理类从pageContext中得到这个connection对象。否则,此tag处理类先找到它的父tag处理类,然后从它的父tag处理类中找到connection对象。 (SLAq$gvd  
1v4(  
e/m ,PE  
public class QueryTag extends BodyTagSupport h+x"?^   
x.+}-(`W#~  
{ '%`W y@  
D/Y.'P:j  
private String connectionId; .sA?}H#wb  
#<bt}Tht  
public int doStartTag() throws JspException @hiwq 7[j  
r c7"sIkV  
{ qlSc[nEk  
DH_Mll>  
String cid = getConnection(); Vet7a_  
u5 EHzoq  
if(cid != null) u4=j!Zb8}  
oO|zRK1;/  
{ #"a?3!wr  
Z2WAVSw  
//存在一个connection id,使用它。 Poacd;*  
rs3Uk.Z^ '  
connection = (Connection) pageContext.getAttribute(cid); M? oK@i  
EW{z?/  
} +xwz.:::  
p IXBJk  
else 5yO6szg  
j3rBEQ,R  
{ o)7gKWjujP  
-tSWYp{  
ConnectionTag ancestorTag = (ConnectionTag)findAncestorWithClass(this, (KHTgZ6  
9/MUzt  
ConnectionTag.class); `av8|;  
$L.0$-je4  
if(ancestorTag == null) ZN|DR|c UY  
2i4FIS|z0  
{ Xz0jjO,  
0CxQ@~ttl  
throw new JspTagException(“一个没有connection属性的查询标签必须被一个connection标记嵌套。”); A?3hNvfx  
lkV% k1w  
} y5.Z<Y  
9/RbfV[)  
connection = ancestorTag.getConnection(); H>e?FDs0*R  
F9ry?g=h  
} x{C=rdp__  
?MuM _6  
} qu8i Jq  
REhXW_x  
} 2"NRnCx *  
SHPaSq'&N  
Rs:<'A  
G.O0*E2V  
此查询标签在JSP页面中的调用形式可以从以下2种定义中任选一种: 0,(U_+ n  
-@G |i$!  
]6</{b  
<tt:connection id=”con01” ...> ... </tt:connection> y>u+.z a|  
gy _86y@  
<tt:query id=”balances” connection=”con01” > 8<k0j&~J  
J1Mm,LTO  
SELECT account, balance FROM acct_table jcN84AaRFI  
MwL' H<  
where customer_num = <%= request.getCustno() %> `pN"T?Pk  
d5]9FIj  
</tt:query> Y*O7lZuF%  
S)z jfJR  
=A<kDxqH  
&TSt/b/+W  
-[v:1\Vv  
<tt:connection ...> O1coay  
q~r )B}  
<x:query id=”balances”> Nc[>CgX"@  
~o%|#-S  
SELECT account, balance FROM acct_table 6!/e_a  
h/`OG>./  
where customer_num = <%= request.getCustno() %> Oe^3YOR#j{  
Vy{=Y(cpF2  
</x:query> `ItMn&P  
U}6'_ PRQ  
</tt:connection> /9|1eSUa  
X\hD 4r"  
'+Dn~8Y+9  
与此同时,在TLD中必须指定connection属性为可选的,定义如下: FJv=5L  
&7T0nB/)  
<tag> $.cNY+  k  
[Ym?"YwVX  
... 42:\1B#[  
? 8S0  
<attribute> B>t$Z5Q^X  
O:RPH{D  
<name>connection</name> G[r_|-^S  
OAR1u}  
<required>false</required> ]~87v  
Us M|OH5k  
</attribute> tk<dp7y7  
-Duy: C6W  
</tag>
描述
快速回复

您目前还是游客,请 登录注册
如果您提交过一次失败了,可以用”恢复数据”来恢复帖子内容
认证码:
验证问题:
3+5=?,请输入中文答案:八 正确答案:八