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

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

级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
标准的JSP 标记可以调用JavaBeans组件或者执行客户的请求,这大大降低了JSP开发的复杂度和维护量。JSP技术也允许你自定义taglib,其实换句话说,taglib可以看成是对JSP标记的一种扩展,正如xml是对html的一种扩展一样。taglib通常定义在tag标签库中,这种标签库存放着你自己定义的tag标签。简而言之,如果使用taglib,那么你可以设计自己的JSP标记! j>A=Wa7  
@me ( pnD  
一般来说,自定义tag标签主要用于操作隐藏对象、处理html提交表单、访问数据库或其它企业级的服务,诸如邮件和目录操作等等。自定义tag标签的使用者一般都是那些对java编程语言非常精通,而且对数据访问和企业级服务访问都非常熟悉的程序员,对于HTML设计者来说,使得他可以不去关注那些较复杂的商业逻辑,而将精力放在网页设计上。同时,它也将库开发者和库使用者进行合理分工,自定义tag标签将那些重复工作进行封装,从而大大提高了生产力,而且可以使得tag库可用于不同的项目中,完美地体现了软件复用的思想。 +6s6QeNS8  
]23+ d/  
在这篇文章中,我们主要讨论: 9`cj9zz7  
u-R;rf5%k  
· 什么是自定义tag标签? ONMR2J(  
"10.,QK  
· 怎么使用tag标签? 'o|=_0-7W  
(p(-E  
o 声明要使用的tag库 :czUOZ_  
"c*#ZP  
o 找到与之对应的tag处理类 0}9  
#Yx /ubg6  
o tag标签的类型 c/}-pZn<  
nU/x,W[}  
· 自定义tag标签 rw%OA4>  
LCMn9I  
o tag处理类 p4@0Dz`Q  
\L"0Pmt[  
o tag库描述 LfMN 'Cb  
`=E4J2"  
o tag标签示例 Erm]uI9`  
{ {+:Vy  
o 带属性的tag <G#Q f|&  
G \|P3j  
o 带body的tag &H/3@A3  
Q+p9^_r  
o 定义了脚本变量的tag tS[%C)  
E&0]s  
o 具有协作关系的tag naM=oSB(  
D<lVWP  
· 自定义tag标签 :oytJhxU  
=xr2-K)e  
o 一个迭代tag的例子 m6o o-muAr  
;-VXp80J  
o 一个模板tag库 H(DI /"N  
gH/(4h  
o tag处理类到底是怎样被调用的? <*z9:jz Q  
e7n` fEpO  
bdj')%@n  
什么是自定义的tag? * & : J  
W.> }5uVl6  
一个自定义的tag标签是用户定义的一种JSP标记。当一个含有自定义的tag标签的JSP页面被jsp引擎编译成servlet时,tag标签被转化成了对一个称为tag处理类的对象进行的操作。于是当JSP页面被jsp引擎转化为servlet后,实际上tag标签被转化成为了对tag处理类的操作。 Vo9Fl Yj  
8*EqG5OP  
自定义tag标签有很多特色,诸如: K<p)-q  
9^@#Ua  
· 可以在JSP页面中自定义tag标签的属性 u(~(+1W  
R]NCD*~  
· 访问JSP页面中的所有对象 &"=<w  
&?^"m\K4J*  
· 可以动态地修改页面输出 M<ba+Qn$  
?GGBDql  
· 彼此这间可以相互通信。你可以先创建一个JavaBeans组件,然后在一个tag中调用此JavaBeans组件,同时可以在另一个tag中调用它。 .=@CF8ArG  
&Y-jK<  
· tag允许相互嵌套,可以在一个JSP页面中完成一些复杂的交互。 *a'I  
G!U `8R  
M<xF4L3]  
使用tag标签 L DdgI  
?zK\!r{  
}VqCyJu&{  
本节主要描述怎样在JSP页面中使用tag标签,以及tag标签的不同类型。 +GT"n$)+  
 ?S'Wd=  
要使用tag标签,JSP程序员必须做2件事: .x_F4#Ka  
?-=<7 ~$  
· 声明此tag标签的tag库 %)=c#H1  
>(F y6m  
· 实现此tag标签 V-lp';bD  
Mc 6v  
声明tag标签所在的tag库 h! w d/jR  
WB\chb%ej#  
如果要使用tag标签,则应用JSP的taglib指示符来指定其tag库(注意:taglib要在在使用此tag标签之前声明) ^"+Vx9H"{  
gt!t Du  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> 7w?N-Q$y  
 \1?:  
uri属性定义了唯一的标签库描述(以下简称TLD),它可以是直接是tld文件名或一个独一无二的名字。prefix是用来区别其它TLD中和本TLD中有重名的tag的一种手段。 ?{r-z3@ N  
Q\aC:68  
TLD必须以.tld作为扩展名,并且存放在当前应用的WEB-INF目录或其子目录下。你可以通过它的文件名直接引用它,也可以通过别的方式间接地引用它。 ),Igu  
q }hHoSG]=  
以下taglib指示符直接引用一个TLD: ADB,gap  
v|:TYpku3  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> nw=:+?  
ZX0!BS  
以下的taglib指示符通过一个逻辑名称间接地引用一个TLD: du&9mOrr  
( \7Yo^  
<%@ taglib uri=”/tutorial-template” prefix=”tt” %> B dxV [SF  
DS=Dg@y  
如果是间接引用TLD的话,那你必须还要在web.xml中定义此逻辑名称与tld文件之间的映射,具体做法是在web.xml中加入一个名为taglib的元素: BoofJm  
gNSsT])  
<taglib> R RnT.MU  
yAu .=Eo7  
<taglib-uri>/tutorial-template</taglib-uri> +z+u=)I  
F<(?N!C?@  
<taglib-location> *u!l"0'\  
-Hg,:re2  
/WEB-INF/tutorial-template.tld gCM(h[7A  
YRU#/TP  
</taglib-location> _s+_M+@et  
x n}HB  
</taglib> 3H`ES_JL  
.|GnTC q  
uk)D2.eS,  
实现此tag标签 a t%qowt  
}kMKA.O"  
0f"la=6  
为了实现tag标签,你有2种方法来存放tag处理类。一、让tag处理类以.class的方式存放于当前应用的WEB-INF/class子目录下,二、如果tag处理类是以JAR包的形式存在的话,那可以放在当前应用的WEB-INF/lib目录下,如果tag处理类要在多个应用中共享,那么它就应放在jsp服务器上的common/lib目录下,对于tomcat来说,就是tomcat/common/lib目录下。 >(a[b@[K  
1Wz5Iv#Ez  
**F-#",  
tag标签类型 I1W~;2cK  
<Gz*2i  
+{cCKRm  
自定义的tag标签遵循XML语法。它有一个开始标记和一个结束标记,有的还有body(即文本节点): V(OD^GU  
s;xErH@RA  
<tt:tag> G9h Bp  
hc]5f3Z  
body $#FA/+<&$  
/\5u-o)  
</tt:tag> 92Rm{n   
aV G4D f  
teJY*)d  
一个不带body的tag标签如下: PB!*&T'!  
.gA4gI1kH  
<tt:tag /> 7 '{wl,u  
cTL W}4m%g  
La\|Bwx  
简单的tag标签 DpQ:U5j  
[wcp2g3Px  
一个没有body和属性的tag标签如下: w s7LDY&(  
w>&g'  
<tt:simple /> RNb"O{3  
PRN%4G  
e# KP3Lp  
带属性的tag标签 :jGgX>GG  
TTz_w-68  
[+b&)jN*2  
自定义标签可以有自己的属性。属性一般在开始标记中定义,语法为 attr=”value”。属性的作用相当于自定义标签的一个参数,它影响着tag处理类的行为。你可以在TLD中详细定义它。 %^bN^Sq -  
$%"~.L4  
你可以用一个String常量给一个属性赋值,也可以通过表达式给它赋值,如<%= ...%>。以struts为例,它的logic:present标签就是用的String常量来给属性赋值: JvM:xy9  
E 7"`D\*  
<loglic:present parameter = “Clear”> MzIn~[\  
EN)0b,ax  
而另一个标签logic:iterate是用表达式来给属性赋值: {\ J%i|u  
JmbWEX|  
<logci:iterate collection=”<%= bookDB.getBooks() %>” =7 -@&S=?s  
d.p%jVO)"  
id=”book” type=”database.BookDetails”> E~1"Nh  
cB}6{c$_sW  
H`NT`BE  
带body的tag标签 Vn6]h|vm  
#)( D_*  
一个自定义标签可以包含其它自定义标签、脚本变量、HTML标记或其它内容。 pxHJX2  
iTJE:[W"y  
在下述例子中,此JSP页面使用了struts的logic:present标签,如果些标签定义了parameter=”Clear”的属性,则将清除购物车的内容,然后打印出一条信息: vS G vv43G  
S0tPnwco[~  
<logic:present parameter=”Clear”>  B q7Qbj  
g UA_&_  
<% cart.clear(); %> [u7i)fn5?  
W.TdhJW9  
<font color=”#ff0000” size=”+2”><strong> Kl w9  
-PskUl'  
你选择了清除购物车! Cm#[$T@C  
rIJd(=  
</strong></font> }N W01nee  
LRv[,]b  
</logic:present> P#qQde/y  
'~[JV>5  
%Su,  
到底是用属性还是用body来传递信息? >npFg@A  
$@<cZ4  
如上所述,我们既可以通过属性,也可以通过body来传递信息。但一般来说,比较简单的类型,如字符串或简单表达式最好采用属性来传递信息。 zN,2 (v"  
z460a[Wl  
Mtq^6`JJ'  
定义脚本变量的tag标签 4_h?E:sBb  
GqD_6cdh  
所谓脚本变量,是指JSP中可以调用的变量或对象。它可由tag标签产生。以下示例阐述了一个tag标签定义了一个名为tx的由JNDI所定义的事务处理对象。脚本变量可以是ejb对象、事务、数据库连接等等: >+2gAO!  
OLyl.#J  
<tt:lookup id=”tx” type=”UserTransaction” name=”java:comp/UserTransaction” /> 3ULn ]jA  
F'^?s= QX  
<% tx.begin(); %> YUQKy2  
_:VIlg U  
... }vt>}%%  
i" >kF@]c8  
dR >hb*k J  
具有协作关系的tag标签 L'<.#(|  
d`4F  
自定义tag标签之间可以通过共享对象来实现协作。在下述例子中,标签tag1创建了一个名为obj1的对象,在标签tag2仍可以重复使用obj。 I'%ASZ  
9M1UkS$`@  
<tt:tag1 attr1=”obj1” value1=”value” /> Mt%=z9OLq9  
b1-'q^M  
<tt:tag2 attr1=”obj1” /> )H- y  
wZKEUJpQ  
在以下这个例子当中,如果外层的tag标签创建了一个对象,那么其内层的所有tag标签都可以使用这个对象。由于这样产生的对象没有一个指定的名字,那么就可以将少重名的冲突。这个例子阐述了一系列协作的嵌套对象。 8U7X/L  
aX|LEZ;D>  
<tt:outerTag> o/mGd~  
')1p  
<tt:innerTag /> 3Jw}MFFV  
mI-9=6T_  
</tt:outerTag> n@y*~sG]  
x4;ndck%U  
?7R&=B1g  
Tag处理类 |TCg`ZS`cZ  
jT1^oXn@  
jQ9i<-zc  
Tag处理类必须实现Tag接口或BodyTag接口,不过现在一般都流行从TagSupport或BodyTagSupport类中继承,这些类或接口都可以在javax.servlet.jsp.tagext包中找到。 l]z=0  
nsyeid*  
当JSP引擎看到自己的JSP页面中包含有tag标签时,它会调用doStartTag方法来处理tag标签的开头,调用doEndTag方法来处理tag标签的结束。 >2dF^cDE-3  
vlh$NK+F  
下表说明不同类型的tag所需要不同的处理过程: m-XS_5x\  
0M|Jvw'n|  
Tag处理类的方法 NLF6O9  
 g\=e86  
Tag标签类型 _/cL"Wf  
所调用的方法 {}N=pL8MS  
T/ TMi&:?.  
基本标签 _A,mY6 *  
doStartTag, doEndTag, release }g_\?z3gt  
i=X B0-  
带属性的标签 |J^$3RX  
doStartTag, doEndTag, set/getAttribute1...N, release s!WI:E7  
y\c-I!6>26  
带内容的标签 <F-W fR  
doStartTag, doEndTag, release C,nU.0  
W,ik ;P\  
带内容的标签,且内容重复循环 .|<+-Rsj  
doStartTag, doAfterBody, doEndTag, release _X]S`e1F  
|ZJ<N\\h-  
带内容的标签,且内容与JSP交互 (v1~p3H  
doStartTag, doEndTag, release, doInitBody, doAfterBody, release oO][X  
4 -Cca  
一个tag处理类可以通过javax.servlet.jsp.PageContext来与JSP交互,通过javax.servlet.jsp.PageContext类,tag处理类可以访问JSP中的request、session和application对像。 x`VA3nE9  
IHvrx:7  
如果tag标签是互相嵌套的,那内层的tag处理类可以通过它的parent属性来访问上层的tag处理类。 "D?:8!\!  
X!!3>`|  
一般情况都将所有的tag处理类打成了JAR的包,以便于发布。 fm&pxQjg  
-VkPy<)  
v `7`'  
Tag库描述(简称TLD) N_| '`]D  
Z^r? MX/  
rxQ&N[r2  
Tag库是用xml语言描述的,TLD包括了tag库中所有tag标签的描述,它一般用来被jsp服务器用来校验tag的语法正确性,或者被jsp开发者用来开发新的标签。 <}bF49z  
##|]el%Y  
TLD的文件扩展名必须为.tld,而且必须放在当前WEB应用的WEB-INF目录或其子目录中。 &~#y-o"  
f'%Pkk  
一个TLD的内容的开头必须遵守标准的XML开头,用于描述DTD和xml的版本,例如: iBaz1pDc  
dI) 9@UL  
<?xml version="1.0" encoding="ISO-8859-1" ?> X^9eCj;c  
&M*f4PeXb  
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd"> \2VYDBi?|  
TLD必须以<taglib>来作为它的根元素,<taglib>的子元素如下表: ysFp`  
[WW ~SOJe  
.lyK ,p  
<taglib>的子元素 ZOY zCc(d  
GLr7sack  
Element (V9 ;  
Description vw[i.af  
D=:O ^<  
tlib-version m+9~f_}  
Tag库的版本 s|d"2w6t  
Qs7*_=+h  
jsp-version x5%x""VEK  
Tag库所需要的jsp的版本 G'f5MP 1  
,@0D_&JAl  
short-name ^@OdY& 5^  
助记符,tag的一个别名(可选) C] >?YR4  
%#iu  
uri a/dq+  
用于确定一个唯一的tag库 se&Q\!&M  
OO*2>Qy~z  
display-name p~f=0K  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) ^s_7-p])(  
W+u-M>Cj6  
small-icon IHcR/\mz  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) 0UOjk.~b  
oJe`]_XZ  
large-icon eH^~r{{R  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) *m*sg64Zw  
MeW?z|x`'  
description =gQ^,x0R9  
对tag库的描述(可选) #8@o%%F d  
.T\_4C  
listener @23~)uiZa  
参见下面listener元素 R/Z zmb{  
?z0N- A2C2  
tag 8ib%CYR  
参见下面tag 元素 ?3a:ntX h  
F P>.@ Y  
Listener元素 SkyX\&  
hD9b2KZv  
一个tag库可能定义一些类做为它的事件侦听类,这些类在TLD中被称为listener 元素,jsp服务器将会实例化这些侦听类,并且注册它们。Listener元素中有一个叫listener-class的子元素,这个元素的值必须是该侦听类的完整类名。 ]'5 G/H5?;  
'ZAl7k .  
Tag元素 ,v_NrX=f?  
-T{G8@V0I  
每个tag元素在tag库中都要指出它的名字、类名、脚本变量、tag的属性。其中脚本变量的值可以直接在TLD中定义或通过tag附加信息的类来取得。每个属性描述了这个属性是否可以省略,它的值是否可以通过<%= …%>这样的JSP语法来获得,以及属性的类型。 "WZ|   
][`%vj9r  
每一个tag在TLD中对应一个tag元素,下表是tag元素的子元素: E_T!|Q.  
@^Yr=d ba  
Tag元素的子元素 p,7, tx  
\@m^w"Ij  
元素名称 _(F8}s  
描述 ubUVxYD?  
5&TH\2u  
name {fa3"k_ke  
独一无二的元素名 LsO}a;t5  
qB5.of[N!  
tag-class JasA w7  
Tag标签对应的tag处理类 .X34[AXd  
DIF-%X5  
tei-class !!d?o  
javax.servlet.jsp.tagext.TagExtraInfo的子类,用于表达脚本变量(可选) tR(nD UHV5  
~Xz?H=}U+  
body-content p((a(Q/  
Tag标签body的类型 -_ <z_IL\%  
qylI/,y{  
display-name OxqkpK&  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) SVBo0wvz-  
}56WAP}Z 4  
small-icon >)+N$EN  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) 58P[EMhL  
il% u)NN  
large-icon XeX` h_  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) d r$E:kr  
nYE%@Up  
description OXI>`$we  
此tag标签的描述 n50W HlMtt  
:B:6ezDF6  
variable SM\qd4  
提供脚本变量的信息(同tei-class)(可选) nM|F MK^  
Vh N6 oI  
attribute c3.;o  
Tag标签的属性名 ?OS0.  
tmi)LRF H  
以下章节介绍对于不同类型的tag,如何具体地实现它们。 u=t.1eS5  
S?#6{rx  
ZlP+t>  
简单的tag MI)v@_1d  
LB`{35b-  
^@^K <SVc  
tag处理类 `T{'ufI4B  
hlmeT9v{  
简单的tag处理类必须实现Tag接口的doStartTag和doEndTag方法。当jsp引擎碰到tag标签的开头时,doStartTag被调用,因为简单的tag没有body,所以此方法将返回 SKIP_BODY。当jsp引擎碰到tag标签的结尾时,doEndTag被调用,如果余下的页面还要被计算,那它将返回EVAL_PAGE,否则将会返回SKIP_PAGE。 @MO/LvD  
><I{R|bC  
以下是例子:对于标签 <tt:simple /> ,它的tag处理类实现如下: lBGYZ--  
)6(|A$~C+  
P1ak>T *#2  
public SimpleTag extends TagSupport 5bBCI\&sam  
wSi$.C2  
{ |Wr$5r  
)+|Y;zC9  
public int doStartTag() throws JspException ?AK`M #M  
J4u>77I  
{ [0vqm:P  
IKV!0-={!z  
try{ " =6kH,  
nJ h)iQu  
pageContext.getOut().print(“Hello.”); 3S" /l  
9g]%}+D  
}catch(Exception e){ c(aykIVOo  
 QJ!2Vw4K  
throw new JspTagException(“SimpleTag: “ + e.getMessage()); yK-DzAv  
:kFPPx?  
} OrwVRqW-z  
sou~m,#  
return SKIP_BODY; Q-z `rW  
:W;eW%Y  
} ;Y0M]pC  
W4UK?#S+  
public int doEndTag() iBI->xU[U  
sNM ]bei  
{ ~d\^ynQ  
t YxN^VqU  
return EVAL_PAGE; O_]hbXV0  
Ec@cW6g(%  
} zK&1ti@wln  
,3N>`]Km'  
} X9ZHYlr+Q  
> l]Ble  
KWojMPs  
注意:如果tag标签没有内容的话,那必须定义body-content元素为空,例如 RLZfXXMn  
|<'6rJ[i>  
<body-content>empty</body-content> [>t;P ,  
U.X` z3q  
`][vaLd`Q  
带属性的tag标签
评价一下你浏览此帖子的感受

精彩

感动

搞笑

开心

愤怒

无聊

灌水
级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
只看该作者 1 发表于: 2007-01-01
tag处理类 XRO(p`OE-  
>]8(3&zd  
对于tag标签的每个属性,你必须依照JavaBeans规范来定义其属性,以及get和set方法。以struts的logic:present 标签为例, s1h|/7gG  
RMiDV^.u`  
<logic:present parameter=”Clear”> UI"UBZZ$  
`S0`3q}L3%  
与此相应,此tag处理类应有如下方法和定义: _QEw=*.<  
yjsj+K pL  
un4fnoc  
protected String parameter = null; FSm.o?>  
7'"qW"<  
public String getParameter() ptrwZ8'  
4wkv#vi7!-  
{ k1oJ<$ Q  
DP0@x+`k  
return this.parameter; _GFh+eS}  
~M8|r!_  
} Cf9{lhE8  
`a83bF35  
public void setParameter(String parameter) E*`PD<:)H  
;i\N!T{>  
{ /(*Ucv2i}T  
GcDA0%i  
this.parameter = parameter; L9N }lH  
9cHo~F|ur  
} Rk7F;2  
K1^7v}P  
w^Yo)"6  
注意:如果你的属性名为id,而且你的tag处理类是从TagSupport类继承的,那你就不需要定义它的属性和set和get方法,因为他们早已在TagSupport被定义过了。 }X?#"JFX?  
{kw% 7}!  
Attribute元素 ~ \<$H'  
}I-nT!D'y  
对于tag标签的每个属性,你必须定义它是否必须的,它的值是否可以用诸如<%= …%>的表达式来获得,以及它的类型(可选),如果不指定它的类型,那就默认为是java.lang.String类型。如果rtexprvalue元素被定义为true或yes,那么在type元素中就定义了attribute的返回类型。 3}!u8,P  
"w%:5~u 9  
<attribute> pS |K[:5  
;N?(R\* 8  
<name>attr1</name> |9=A"092{  
&+&@;2  
<required>true|false|yes|no</required> LRts W(A/  
!^&VZh  
<rtexprvalue>true|false|yes|no</rtexprvalue> 9 :Oz-b  
yvj/u c  
<type>attribute的返回类型(只用当rtexprvalue为真是才有效)</type> <g%A2 lI  
T[)!7@4r  
</attribute> 5!fOc]]Ow  
r5N TTc  
如果tag的某个属性不是必须的,那tag处理类会自动提供一个缺省值。 :\JCxS=EW  
\ a,}1FS  
例如,在logic:present这个tag标签中定义了一个属性叫parameter,但它不是必须的,而且它可以被诸如<%= …%>的表达式来赋值。 zWhj >Za  
YLi6G Y  
<tag> /AAD Fa  
p]EugLEmG  
<name>present</name> ]"b:IWPeI  
9?MzIt  
<tag-class>org.apache.struts.taglib.logic.PresentTag</tag-class> J@2wPKh?Yp  
|Z94@uB  
<body-content>JSP</body-content> ||>4XDV#  
[K$5 Rm5  
… Yj1|]i5b  
IycZ\^5*-  
<attribute> [#mk TY  
v}N\z2A  
<name>parameter</name> |(Mxbprz  
{'tfU  
<required>false</required> $BMXjXd}  
:MY=Q]l  
<rtexprvalue>true</rtexprvalue> Y|Q(JX  
E`I(x&_  
</attribute> n)"JMzjQ<  
-f&vH_eK  
… !5(DU~S*@S  
l[c '%M|N  
</tag> 0t%]z!  
e}1Q+h\  
w(&EZDe  
属性元素的校验 Jh0Grq  
" Q?~LB  
wR@>U.XT@  
有关于tag标签的有效值可以从tag库的说明文档中获得,当JSP页面被编译时,jsp引擎会强制性地参照TLD中定义的规则进行检查。 >fzyD(>  
%L*EB;nK  
还有一个方法也可以进行属性元素的校验,就是先继承类TagExtraInfo,然后调用它的isValid方法。这个类同时也起到提供tag中定义的脚本变量信息的作用。 ~Ym _ {  
Q;8z&4s@  
IsValid方法通过TagData对象来传递属性信息,它包括着tag的所有的属性名-值的信息。由于校验发生在运行时刻,因此这个属性的值将被赋值为TagData.REQUEST_TIME_VALUE。 MGsQF#6]  
05R"/r*  
例如tag标签<tt:twa attr1=”value1” />在TLD中定义如下: myR{ }G  
Lm~<BBp.  
<attribute> ;7qIm83  
38p"lT  
<name>attr1</name> G9^`cTvv'8  
Z! O4hA4  
<required>true</required> ~q}L13^k  
j=irx5:  
<rtexprvalue>true</rtexprvalue> i,r:R g~  
17Cb{Q  
</attribute> uAeo&|&  
e O\72? K  
fV|uKs(W  
这个定义说明了attr1能在运行期间被赋值。 6!"wiM"]  
,{HQKHg  
以下的isValid方法检查attr1属性的值是否属于Boolean类型。注意由于attr1能在运行刻被赋值,那么isValid方法必须检查tag用户是否对此tag进行了运行时刻赋值。 k3qQU)  
vvv'!\'#  
yiQ?p:DM  
Public class TwaTEI extends TagExtraInfo N'VTdf?  
?-<lIF Fh  
{ m%`YAD@2z  
jeWv~JA%L|  
public boolean isValid(Tagdata data) &|{1Ws  
cl4z%qv*  
{ {73V?#P4  
F1stRZ1ZI  
Object o = data.getAttribute(“attr1”); "ktuq\a@  
KJ'ID  
If(o != null && o != TagData.REQUEST_TIME_VALUE) qx5`lm~L  
i`2SebDj'w  
{ c%/b*nQ(=  
\L(cFjLIl  
if( ( (String)o).toLowerCase().equals(“true”) || |qn 2b=  
W:]2T p  
((String)o).toLowerCase().equals(“false”) ) e9{0hw7  
t<Yi!6  
return true; "jum*<QZz  
PiKP.  
else o@zxzZWg  
:TU|:2+  
return false; aNEah  
z qq  
} VQHB}Y@^  
vd[7Pxe  
else '_G\_h}5  
RH;ulAD6(~  
return true; \s&Mz;:  
nUP, Yd  
} d=xjLbsZ  
^7spXfSAd  
} a{T.U-0   
7x6 M]1F  
adP  :{j  
带body的tag T06(Q[)  
Q 84t=  
D8wf`RUt  
tag处理类 W]oD(eZ  
ae sk.  
a ~v$ bNu  
如果tag标签含有内容,那处理方式会略微有些不同,而且还要视tag处理类是否要与body交互的情况而定。如果要与body交互,那我们认为tag处理类要可能要对body进行操作。 xc#t8`  
89LD:+p/  
Tag处理类不与body交互 }CBQdH&g;  
Y.Zd_,qy  
如果tag处理类不与body交互,tag处理类应该实现Tag接口或从TagSupport中派生,如果body要被计算,那么doStartTag方法应返回 EVAL_BODY_INCLUDE,否则应返回SKIP_BODY。 =Pl@+RgK+  
|MZ1j(_  
如果tag处理类要对body反复运算,则它应该实现IterationTag或从TagSupport中派生。如果tag处理类认为body还未计算完的话,那它的doStartTag方法和doAfterBody方法必须返回EVAL_BODY_AGAIN。 T ?[28|  
QgqJ #  
Tag处理类与body交互 8D )nM|  
NbU`_^oC  
如果tag处理类与body交互,那tag处理类应实现BodyTag接口或从BodyTagSupport中派生。这种tag处理类一般要实现doInitBody和doAfterBody方法。 =o##z5j K  
2L](4Q[M  
Body允许一些方法来读写它的内容。Tag处理类可以调用body内容的getString或getReader方法来从body中提取信息,也可用 writeOut(out) 方法来将body的内容写入到out对象中。其中out对象通过tag处理类的getPreviousOut方法来获得。 GM%OO)dO}  
y8~OkdlN#  
如果body的内容需要被计算,那么doStartTag方法必须返回EVAL_BODY_BUFFERED,否则,它将返回 SKIP_BODY。 SCcvU4`o  
\ZLi Y  
doInitBody 方法 :0l+x 0l}  
#h[>RtP:  
此方法在body内容已经设好,但未被计算之前被调用。你可以根据不同的body内容来制定初始化策略。 (I}owr5:  
eK:?~BI!  
doAfterBody方法 wN!\$i@E:  
P?h1nxm`'  
此方法在body内容已被计算后进行调用。 DU%E883  
z,TH}s6  
和doStartTag方法一样,doAfterBody方法返回一个指示符指示是否要继续计算body,如果要继续计算,则doAfterBody应返回EVAL_BODY_BUFFERED,否则,它应返回SKIP_BODY。 src9EeiV  
oFU:]+.+D  
release 方法 WVa%<  
g3$'G hf  
tag处理类调用此方法将它的状态重置为初始状态,并释放所有的私有资源。 !{jw!bB  
x 7by|G(  
MV"n{1B  
以下的例子读取body的内容(其中含有一条sql语句),然后将它传递给一个对象,让它进行查询。由于此处body不须重新计算,所以doAfterBody会返回SKIP_BODY。 d%8n   
%b^4XTz  
wSjDa.?'  
Public class QueryTag extends BodyTagSupport 44ty,M3  
_X4Y1zh  
{ S $p>sItO  
1jg* DQ7L  
public int doAfterBody() throws JspTagException 4,sE{%vb  
cz9J&Le>  
{ 0~ho/_  
zzf@U&x<  
BodyContent bc = getBodyContent(); E#KZZ lbx  
I8gNg Z  
//将body的内容以字符串的格式提取出来 '. "_TEIF  
nEsD+ }E?  
String query = bc.getString(); hU$o^ICH  
|0i{z(B  
//清除body g5nJ0=9  
|c/=9Bb  
bc.clearBody(); z{W C w  
u4Nh_x8\Nr  
try{ J 8%gC  
r/sSkF F  
Statement stmt = connection.createStatement(); 2#.s{Bv  
%P0  
Result result = stmt.executeQuery(query); 0&,D&y%  
hQ@k|3=Re  
}catch(SQLException e){ t.9s49P  
(.:*GUg  
throw new JspTagException(“queryTag: “ + e.getMessage() ); unFRfec{  
ircF3P>a?  
return SKIP_BODY; a}%f +`z  
Z<.&fZ^jS  
} \\dUp>1=  
`7=$I~`  
} w#b@6d  
zQyI4RHG[  
QR&e~rks  
body-content元素 Q6HJ+H-Ub  
^K<3_D>1>  
"/zgh  
由于tag可能会有body,你必须用body-content元素来指定body内容的类型: b{<?E };%  
YCDH0M  
<body-content>JSP|tagdependent</body-content> SI!A?34  
!.6n=r8 d  
F{ %*(U  
如果body的内容是定制的或内部的tag、脚本元素、或HTML广本,则归类为JSP类型。其他的类型,比如上面代码所述的?D?D将sql statement类传给 query tag的这种类型应该标为tagdependent。 @U_ CnhPQq  
sE[`x^1'8  
注意:实际上body-content的值并不影响tag处理类对body内容的处理,它仅仅是被tag编辑工具用来描述此body的内容。 n2K1X!E$  
d=vuy   
G<7M;vRvP  
用tags定义脚本变量 2f[;U"  
r84^/+"T  
~lo43$)^  
tag处理类 C+TB>~Gv`  
wtYgHC}X  
Cy[G7A%  
tag处理类负责创建或设置页面中定义的脚本变量,用pageContext.setAttribute(name,value,scope)或pageContext.setAttribute(name,value)方法来实现。一般来说,tag处理类通过脚本变量的名称来获取它,脚本变量的名称一般可用get方法来获得。 p*b_ "aF1  
9G/!18 X?f  
如果脚本变量的值依赖于tag处理类中的上下文中某一对象,那它可用pageContext.getAttribute(name,scope)方法来找到那个对象。一般的处理过程是tag处理类先找到脚本变量,再对其进行处理,然后用pageContext.setAttribute(name,object)的方法来设置它的新值。 VM%g QOo<  
8ao-]QoMZ  
对象的生存周期(scope)如下表: XkA] 9,@  
r? /Uu &  
对象的生存周期表 {U;yW)  
x-[ItJ% l  
名字 to?!qxn  
可访问范围 1 sHjM %  
生存周期 mXz*Gi  
M.Yp'Av  
page C 7C4 eW8  
当前页面 ooVs8T2  
一直有效,除非页面向客户提交响应或重定向到一个新页面 I> ;{BYPV  
yJI~{VmU7  
request 3=d%WPgQ  
当前页面或当前页面重定向到的页面 +4:eb)e  
一直有效,除非页面向客户提交响应 e#*3X4<\K  
(xb2H~WrN  
session _f^6F<!  
当前页面或在同一浏览器窗口中的页面 lEHx/#qt9  
一直有效,除非关闭当前浏览器、超时、网络故障 iAz0 A  
fmixWL7.Zg  
application jfMkN  
整个web应用程序的所有请求 v.|#^A?Qx  
一直有效,除非发生网络故障、服务器故障 8%K{lg"  
$U_(e:m}f  
提供关于脚本变量的信息 (I$%6JO:  
m#'eDO:  
以下示例定义了一个名为“book”的脚本变量,用来访问程序中关于书的信息: qSNCBn '  
UQDAql  
<bean:define id=”book” name=”bookDB” property=”bookDetails” type=”database.BookDetails” /> MKfK9>a  
pT|s#-}  
<font color=”red” size=”+2” > G=zNZ  
OInl?_,,T#  
<%= messages.getString(“CartRemoved”) %> (p5q MP]L  
b&P)J|Fe  
<strong><jsp:getProperty name=”book” property=”title” /></strong>  JQQ[jl;  
, '0#q  
</font> I;w!  
B $g\;$G  
当包含此tag的JSP页面被编译时,jsp引擎会自动生成关于此book的同步的代码(同步可以避免几个客户同时访问此book时造成的冲突),要生成同步代码,jsp引擎需要知道此脚本变量的如下信息: -FJ3;fP&  
8m{e,o2.  
· 脚本变量名称 GURiW42  
~]-n%J $q  
· 脚本变量所属的类 M G$+Blw>  
U 3< 3T  
· 此脚本变量是否引用了一个新的或已存在的对象 )NZH{G  
v Z9OJrF  
· 此脚本变量的有效性 WK6,K92  
-zFJ)!/?  
有两种办法可以向jsp引擎提供关于脚本变量的信息:在TLD中定义variable子元素,或用tei-class子元素定义一个额外tag信息类。用variable最简单,但可能降低了一些灵活性。 6Hnez@d  
?z.?(xZ 6  
Variable元素 !`e`4y*N  
5!?5S$>  
Variable元素有如下子元素: e6taQz@}  
w x]?D%l  
· name-given ?D?D 给出的名字,是一个常量 Onq^|r's&  
`PbY(6CF  
· name-from-attribute?D?D 属性名,在编译时给出的属性名 [\W&  
4H6Fq*W{k  
name-given或name-from-attribute两者必须选一,但以下子元素是可选的: q KD  
vL@<l^`$0  
· variable-class?D?D变量的类型,缺省为java.lang.String。 `0qjaC  
A1prYD  
· declare?D?D此脚本变量是否引用了一个新对象,缺省为True。 `$/a-K}  
$bG*f*w  
· scope?D?D脚本变量的范围,缺省为NESTED。下表描述了scope的几种类型: Br!;Ac&N  
d}Pfj=W  
脚本变量的有效范围 ><}nZ7  
7Vy_Cec1  
值 u1 Q;M`+>  
有效性 x[58C+  
方法 nz3*s#k\-  
~s+vJvWz  
NESTED )7& -DI1  
在tag标签的开始和结束之间 &#e;`(*  
如果tag处理类实现BodyTag接口,则在doInitBody和doAfterBody中调用,否则在doStartTag中调用 zu1"`K3b  
i9L]h69r  
AT_BEGIN 4z(~)#'^  
从tag标签的开始一直到页面结束 b1?^9c#0d  
如果tag处理类实现BodyTag接口,则在doInitBody、doAfterBody和doEndTag中调用,否则在doStartTag和doEndTag中调用 ?(gha  
T#qf&Q Z  
AT_END dM;\)jm  
从tag标签的结束一直到页面结束  oE+P=  
在doEndTag中调用 AAQ!8!  
U,W MP<5&  
以struts为例,它的bean:define标签的实现遵循JSP1.1规范,此规范要求使用额外tag信息类来定义脚本变量。Variable元素是JSP1.2规范中加入的。以bean:define标签为例,你可以定义如下variable元素: ^UKAD'_#%O  
684& H8  
<tag> zd[k|lj  
,cNe-KJk  
<variable> s;I @En  
"<=4]Z  
<name-from-attribute>id</name-from-attribute> 59zWB,y(P  
a=}1`Q  
<variable-class>database.BookDetails</variable-class> uLzE'Z mV  
JP Zp*5c6A  
<declare>true</declare> iHhdoY[]  
nook/7]  
<scope>AT_BEGIN</scope> OdFF)-K >~  
i(|u g_^  
</variable> a(vt"MQ_  
IVPN=jg?  
</tag> #r#[&b  
]jD\4\M}  
额外tag信息类 /O:4u_  
@ ;!IPiU  
如果要定义一个额外tag信息类,你要继承javax.servlet.jsp.TagExtraInfo类。一个TagExtraInfo类必须实现getVariableInfo方法,此方法返回一个叫VariableInfo的数组类,它包括如下信息: \OVFZ D  
Z5'^81m$o  
· 变量名 ~ L4NK#  
:2KHiT5  
· 变量所属类名 v's1 &%sM  
d'96$e o~  
· 此变量是否引用了一个新对象 /''=V.-N  
f!kZyD7  
· 此变量的有效范围 )l`Ks  
+A?P4}  
jsp引擎将一个名为data的参数传给getVariableInfo方法,data中包括tag标签中的所有“属性名?D?D属性值”对。它可以用来向VariableInfo对象提供脚本变量的名字和类名。 Bug.>ln1  
G{[w+ObX  
以struts为例,它在bean:define标签中定义了一个名为DefineTei的额外tag信息类,用来向脚本变量提供信息。由于脚本变量的名称(book)和类名(database.BookDetails)是通过tag标签的属性来传递的,它们一般定义在VariableInfo的构建代码中,并且可用data.getAttributeString方法来得到这些信息。如果要允许book脚本变量能在从tag开始直到整个JSP页面结束的范围内都可用的话,那它的范围应设为AT_BEGIN。如下所示: k( Sda>-  
~Y`ys[Z m  
9HJYrzf{%  
public class DefineTei extends TagExtraInfo oH w!~ c7  
y>=YMD  
{ 7nT|yL?  
`+n0a@BVB  
public VariableInfo[] getVariableInfo(TagData data) &j:e<{@  
:O413#8  
{ Pp } Z"  
9;LjM ~Ct  
String type = data.getAttributeString(“type”); 2FuV%\p  
=W7-;&  
If( type == null) gfK_g)'2U  
+\Vw:~e  
type = “java.lang.Object”; ~+1mH  
KfjWZ4{v  
return new VariableInfo[] { _+48(Q F<  
?+EAp"{j  
new VariableInfo(data.getAttributeString(“id”), UWO3sZpU  
/V*SI!C<f  
type, F% n}vA`  
{LjzkXs  
true, ^>E>\uz0v  
v'?Smd1v /  
VariableInfo.AT_BEGIN) PR"x&JG@  
fof}I:vO  
}; Y#c439&  
MtL<)?HQ  
} %j^QK>%  
@K!JE w\  
} @ovaOX  
 7V5c`:"  
eHvUgDt  
注意:关于额外tag信息类的类名必须要在TLD中的tag标签下的tei-class子元素中定义。因此,DefineTei的tei-class中的定义看起来如下: l8?C[, K%  
<tei-class> :jv(-RTI  
org.apache.struts.taglib.bean.DefineTagTei C"kfxpCi  
</tei-class> 6qDt 6uB  
%!t9)pNc  
#~'d Y\&  
具有协作关系的tag #qVTB@d  
9@CRL=  
h rSH)LbJ  
tag通过共享对象来进行协作,JSP技术支持2种方式的对象共享。 J\@g3oGw  
/x@aAJ|  
第一种方法是使用pageContext对象进行对象的共享(可支持JSP页面和tag处理类之间的共享),如果在一个tag处理类中要调用由另一个tag处理类创建的对象,可调用pageContext.getAttribute(name, scope)方法。 [[c0g6  
J.JD8o9sa  
第二各方式的共享是对于tag之间有嵌套关系而言的,外层的tag所创建的对象对于内层的tag来说是可以共用的。这种形式的共享的好处是减少了可能存在的重名冲突。 'a0M.*f}G  
,iYhD-"'  
要访问一个嵌套tag创建的对象,tag处理类必须先找到此嵌套tag对象,可用TagSupport的静态方法 TagSupport.findAncestorWithClass(from, class)或TagSupport.getParent方法。前者在当不确定此tag是否为嵌套tag对象时使用。一旦它的父类被找到,它就能访问其所有动态或静态创建的对象。静态创建的对象是父类的成员,而动态创建的对象可能是父类的私有对象。诸如此类的对象可以用tag处理类的setValue方法来保存,用getValue方法来获得。 >rlUV"8jY;  
ynw(wSH=  
下例阐述了以上两种共享对象的方法。在这个例子当中,一个查询tag检查一个名为connection的属性名是否在doStartTag中被设置。如果connection属性被设置,tag处理类从pageContext中得到这个connection对象。否则,此tag处理类先找到它的父tag处理类,然后从它的父tag处理类中找到connection对象。 =)Hu(;Yv  
nam]eW  
w>*Jgc@A*  
public class QueryTag extends BodyTagSupport YT?Lt!cl=  
WD\Yx~o  
{ m4~ |z  
-6J <{1V  
private String connectionId; HTQTDbhV^  
LT$t%V0?.e  
public int doStartTag() throws JspException E] g Lwg9K  
tRI<K  
{ "y~*1kBu  
q`mxN!1[  
String cid = getConnection(); sDBSc:5+e  
eV!(a8  
if(cid != null) MH)V=xU|)  
.'o=J`|  
{ q`PA~C];  
1|8Bv0-b  
//存在一个connection id,使用它。 b;D  
7yu-xnt3s  
connection = (Connection) pageContext.getAttribute(cid); B?&0NpVD  
\%r0'1f  
} d:iJUVpr  
w/ ~\NI  
else ;+ C$EJw-  
d1_kw A2y  
{ (b~l.@xh  
\},H\kK+^  
ConnectionTag ancestorTag = (ConnectionTag)findAncestorWithClass(this, -3yK>\y=|  
BPv+gx(>k  
ConnectionTag.class); Q&PWW#D  
@+t|Aa^g  
if(ancestorTag == null) >{ {ds--  
t0fgG/f'  
{ @D-I@Cyl  
7WH'GoBh  
throw new JspTagException(“一个没有connection属性的查询标签必须被一个connection标记嵌套。”); 'qEw]l  
w_>\Yd[  
} r'nPP6`  
pf'DbY!  
connection = ancestorTag.getConnection(); -zYa@PW  
3.Mpd  
} cvy 5|;-u  
LhKbZ oPp  
} hzk!H]>E  
4A"nm6  
} ;bG?R0a  
jMBM qQNU  
?J + jv  
#Pk{emYW  
此查询标签在JSP页面中的调用形式可以从以下2种定义中任选一种: ;{0alhMZ  
1o/(fy  
OcMB)1uh\  
<tt:connection id=”con01” ...> ... </tt:connection> >"1EN5W  
T^] ]z}k  
<tt:query id=”balances” connection=”con01” > xGr{ad.N  
(KN",u6F  
SELECT account, balance FROM acct_table jNx{*2._r  
$k )K}U  
where customer_num = <%= request.getCustno() %> VF11eZ"  
:0(^^6Q\  
</tt:query> 7L/LlO/  
3pML+Y|ij  
|LJv*  
或 @TW:6v`  
v&G9HiH  
<tt:connection ...> clyp0`,7  
,7cw%mQA  
<x:query id=”balances”> Zs t)S(  
msCz\8Xd  
SELECT account, balance FROM acct_table * G*VY#L  
>QJDO ]~V  
where customer_num = <%= request.getCustno() %> H0tu3Pqk  
i[LnU#+  
</x:query> (rJ-S"^u  
yuC$S&Y >!  
</tt:connection> 6d8)]  
L"vk ^>E6  
6 Q7MAP M  
与此同时,在TLD中必须指定connection属性为可选的,定义如下: }@6yROy.  
j<)$ [v6  
<tag> !nL94:8U  
?uc]Wgw"s  
... 5l@} 1n  
[u*7( 4e  
<attribute> {?^ES*5  
; Yc\O:Qq  
<name>connection</name> 6'mZM=d  
~t2" L|i  
<required>false</required> q1YNp`]0i8  
+%[, m&  
</attribute>  *`qI<]!  
w(_:+-rqQ<  
</tag>
描述
快速回复

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