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

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

级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
标准的JSP 标记可以调用JavaBeans组件或者执行客户的请求,这大大降低了JSP开发的复杂度和维护量。JSP技术也允许你自定义taglib,其实换句话说,taglib可以看成是对JSP标记的一种扩展,正如xml是对html的一种扩展一样。taglib通常定义在tag标签库中,这种标签库存放着你自己定义的tag标签。简而言之,如果使用taglib,那么你可以设计自己的JSP标记! 2*:lFv wP  
d5$2*h{^v  
一般来说,自定义tag标签主要用于操作隐藏对象、处理html提交表单、访问数据库或其它企业级的服务,诸如邮件和目录操作等等。自定义tag标签的使用者一般都是那些对java编程语言非常精通,而且对数据访问和企业级服务访问都非常熟悉的程序员,对于HTML设计者来说,使得他可以不去关注那些较复杂的商业逻辑,而将精力放在网页设计上。同时,它也将库开发者和库使用者进行合理分工,自定义tag标签将那些重复工作进行封装,从而大大提高了生产力,而且可以使得tag库可用于不同的项目中,完美地体现了软件复用的思想。 +!9&E{pmo  
^zn j J\  
在这篇文章中,我们主要讨论: cn1CM'Ru  
_[}r2,e  
· 什么是自定义tag标签? t]1j4S"pm  
UO(B>Abp  
· 怎么使用tag标签? MJ^NRT0?b  
V {R<R2h1  
o 声明要使用的tag库 g _fvbVX  
Bs2.$~   
o 找到与之对应的tag处理类 oK1"8k|Z  
QA_SS'*  
o tag标签的类型 v#u]cmI  
$r%m<Uc;}O  
· 自定义tag标签 '~i;g.n=}-  
t/z]KdK P  
o tag处理类 MIo5Y`T  
sIQd }  
o tag库描述 hYRGIpu5  
4?YhqJ  
o tag标签示例 |eT?XT<=o  
]eA<  
o 带属性的tag ( XYYbP  
P7r?rbO"  
o 带body的tag `c@KlL*!Q  
fF !Mmm"  
o 定义了脚本变量的tag [OFg (R-  
R:S Fj!W1  
o 具有协作关系的tag "5Oi[w&F5  
}m NP[L  
· 自定义tag标签  e;8>/G  
.m_yx{FZ=  
o 一个迭代tag的例子 5Gm,lNQAv  
A[L+w9  
o 一个模板tag库 pC,MiV$c"  
Gs$<r~Tg  
o tag处理类到底是怎样被调用的? mlCw(i,  
F. X{(8  
M##h<3I  
什么是自定义的tag? fhqc[@Y[  
(9q61z A  
一个自定义的tag标签是用户定义的一种JSP标记。当一个含有自定义的tag标签的JSP页面被jsp引擎编译成servlet时,tag标签被转化成了对一个称为tag处理类的对象进行的操作。于是当JSP页面被jsp引擎转化为servlet后,实际上tag标签被转化成为了对tag处理类的操作。 "orZje9AC  
cQEK>aAd  
自定义tag标签有很多特色,诸如: `[\*1GpAo  
NyU~8?bp  
· 可以在JSP页面中自定义tag标签的属性 v{4K$o  
xXQ#?::m  
· 访问JSP页面中的所有对象 a.)Gd]}g  
lO},fM2j  
· 可以动态地修改页面输出  TA;  
J \U}U'qP  
· 彼此这间可以相互通信。你可以先创建一个JavaBeans组件,然后在一个tag中调用此JavaBeans组件,同时可以在另一个tag中调用它。 \[&`PD  
^S!^$d*  
· tag允许相互嵌套,可以在一个JSP页面中完成一些复杂的交互。 sl^i%xJ|l'  
n,sl|hv2U  
)qs>Z?7  
使用tag标签 @2Xw17[f35  
Wj2]1A  
^G'8!!ys  
本节主要描述怎样在JSP页面中使用tag标签,以及tag标签的不同类型。 qH'T~# S  
KB+,}7  
要使用tag标签,JSP程序员必须做2件事: S)Cd1`Gf  
$7~ k#_#PC  
· 声明此tag标签的tag库 ws9F~LmLbr  
*44^M{ti<  
· 实现此tag标签 l]R O'  
01Bs7@"+  
声明tag标签所在的tag库 q:N"mp<%  
u )+;(Vd  
如果要使用tag标签,则应用JSP的taglib指示符来指定其tag库(注意:taglib要在在使用此tag标签之前声明) |0YDCMq(  
[.;$6C/?  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> FEgM4m.(G<  
IT& U%hw  
uri属性定义了唯一的标签库描述(以下简称TLD),它可以是直接是tld文件名或一个独一无二的名字。prefix是用来区别其它TLD中和本TLD中有重名的tag的一种手段。 n1K"VjZk  
g(xuA^~J  
TLD必须以.tld作为扩展名,并且存放在当前应用的WEB-INF目录或其子目录下。你可以通过它的文件名直接引用它,也可以通过别的方式间接地引用它。 cl4`FU  
5]cmDk  
以下taglib指示符直接引用一个TLD: n[4F\I>  
}R5>ja0  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> *qKPZb~  
<)c/PI[j  
以下的taglib指示符通过一个逻辑名称间接地引用一个TLD: {U8Sl.  
"3CQ0  
<%@ taglib uri=”/tutorial-template” prefix=”tt” %> QXx<Hi^ /  
xC;b<~zN  
如果是间接引用TLD的话,那你必须还要在web.xml中定义此逻辑名称与tld文件之间的映射,具体做法是在web.xml中加入一个名为taglib的元素: HN,E+ dQ  
K~"uZa^s  
<taglib> TV)bX  
W6f?/{Oo8  
<taglib-uri>/tutorial-template</taglib-uri> [*zB vj}G  
K~ gt=NH  
<taglib-location> :3WrRT,'L  
'6i"pJ0%  
/WEB-INF/tutorial-template.tld i/;Ql, gm  
Y$SZqW0!/  
</taglib-location> ecIxiv\  
+e_NpC  
</taglib> =YlsJ={h  
HJ[@;F|aU  
Y6L_ _ RT  
实现此tag标签 >mRA|0$  
to~Ap=E  
KP" lz  
为了实现tag标签,你有2种方法来存放tag处理类。一、让tag处理类以.class的方式存放于当前应用的WEB-INF/class子目录下,二、如果tag处理类是以JAR包的形式存在的话,那可以放在当前应用的WEB-INF/lib目录下,如果tag处理类要在多个应用中共享,那么它就应放在jsp服务器上的common/lib目录下,对于tomcat来说,就是tomcat/common/lib目录下。 a$!|)+  
ju#/ {V;D  
em`z=JGG  
tag标签类型 9:zW$Gt&  
|x*~PXb  
c6gRXp'ID  
自定义的tag标签遵循XML语法。它有一个开始标记和一个结束标记,有的还有body(即文本节点): 1HYrJb,d  
fsqK(io28  
<tt:tag> b|| c^f  
& Ji!*~sE  
body 9`kxyh</  
8'J"+TsOW  
</tt:tag> g[<K FVlG  
_r+2o-ZR  
$(pzh:|  
一个不带body的tag标签如下: EGWm0 F_  
nDx}6}5)  
<tt:tag /> ihjs%5Jo%  
B|E4(,]^  
v-u53Fy  
简单的tag标签 $%9.qy\8  
EJ7}h?a]U_  
一个没有body和属性的tag标签如下: C5mq@$6  
SQ7Ws u>T@  
<tt:simple /> #DjSS.iW  
dLl/V3C6t  
-Z )j"J  
带属性的tag标签 e]-bB#-A  
\fG?j@Qx  
Htd-E^/  
自定义标签可以有自己的属性。属性一般在开始标记中定义,语法为 attr=”value”。属性的作用相当于自定义标签的一个参数,它影响着tag处理类的行为。你可以在TLD中详细定义它。 KhK:%1po  
`l+{jrRb<  
你可以用一个String常量给一个属性赋值,也可以通过表达式给它赋值,如<%= ...%>。以struts为例,它的logic:present标签就是用的String常量来给属性赋值: @-y.Y}k#$~  
k2{*WF  
<loglic:present parameter = “Clear”> 5tUp[/]pl  
?pq#|PI)  
而另一个标签logic:iterate是用表达式来给属性赋值: ^PDz"L<*  
RGd@3OjN  
<logci:iterate collection=”<%= bookDB.getBooks() %>” \IB@*_G  
 ,r\  
id=”book” type=”database.BookDetails”> O ;,BzA-n  
@ *W)r~ "~  
* S4IMfp  
带body的tag标签 -0[?6.(s"  
297X).  
一个自定义标签可以包含其它自定义标签、脚本变量、HTML标记或其它内容。 Ax &Z=  
H4DM,.04  
在下述例子中,此JSP页面使用了struts的logic:present标签,如果些标签定义了parameter=”Clear”的属性,则将清除购物车的内容,然后打印出一条信息: Q?df5{6  
i?" ~g!A  
<logic:present parameter=”Clear”> ,e\'Y!'  
;{mKt%#  
<% cart.clear(); %> ! h7?Ap  
,z A9*  
<font color=”#ff0000” size=”+2”><strong> h!l&S2)D`  
;"/[gFD5u  
你选择了清除购物车! Q/'jw yj_  
K,f*}1$qM  
</strong></font> ;tK%Q~To  
tQz=_;jy  
</logic:present> R5PXX&Q  
t[$C r;  
t5 :4'%|  
到底是用属性还是用body来传递信息? GG0l\! 2)  
0X6|pC~  
如上所述,我们既可以通过属性,也可以通过body来传递信息。但一般来说,比较简单的类型,如字符串或简单表达式最好采用属性来传递信息。 z0=(l?)#  
9K~0:c  
-1'O  
定义脚本变量的tag标签 xZ'-G6O "~  
kY d'6+m  
所谓脚本变量,是指JSP中可以调用的变量或对象。它可由tag标签产生。以下示例阐述了一个tag标签定义了一个名为tx的由JNDI所定义的事务处理对象。脚本变量可以是ejb对象、事务、数据库连接等等: :iW+CD)j  
~*aPeJ  
<tt:lookup id=”tx” type=”UserTransaction” name=”java:comp/UserTransaction” /> F91uuSSL  
f|U;4{ k  
<% tx.begin(); %> ^e*Tg&  
Cu*+E%P9`  
... SM%N ]/@U  
BPgY_f  
45g:q  
具有协作关系的tag标签 !h\.w9o[  
2>%|PQ  
自定义tag标签之间可以通过共享对象来实现协作。在下述例子中,标签tag1创建了一个名为obj1的对象,在标签tag2仍可以重复使用obj。 ?\|QDJXY  
-J7BEx  
<tt:tag1 attr1=”obj1” value1=”value” /> ?#N: a  
kn2s,%\`<p  
<tt:tag2 attr1=”obj1” /> [ 6+iR  
+XL^dzN[|$  
在以下这个例子当中,如果外层的tag标签创建了一个对象,那么其内层的所有tag标签都可以使用这个对象。由于这样产生的对象没有一个指定的名字,那么就可以将少重名的冲突。这个例子阐述了一系列协作的嵌套对象。 Ht >5R  
KO*# ^+g  
<tt:outerTag> U$zd3a_(  
lG[@s 'j  
<tt:innerTag /> =j,2  
S$O+p&!X  
</tt:outerTag> l|WdJn o  
H&$L1CrdL  
qUNK Dt  
Tag处理类 %H)^k${  
`6bIxb{  
eBUexxBY  
Tag处理类必须实现Tag接口或BodyTag接口,不过现在一般都流行从TagSupport或BodyTagSupport类中继承,这些类或接口都可以在javax.servlet.jsp.tagext包中找到。 )\nKr;4MH  
DxuT23. (  
当JSP引擎看到自己的JSP页面中包含有tag标签时,它会调用doStartTag方法来处理tag标签的开头,调用doEndTag方法来处理tag标签的结束。 HW|5'opF  
9]u=b\fzZ  
下表说明不同类型的tag所需要不同的处理过程: %x}iEqkU  
Kkfza  
Tag处理类的方法 *u J0ZO9  
{owXyQ2mK  
Tag标签类型 rlUo#  
所调用的方法 "AN*2)e4  
o2AfMSt.  
基本标签 6}z-X*  
doStartTag, doEndTag, release ZLP)i;Az  
+pcGxje\  
带属性的标签 FM{^ND9x  
doStartTag, doEndTag, set/getAttribute1...N, release Ez()W,6]g  
]iI2  
带内容的标签 %5g(|Y]  
doStartTag, doEndTag, release S10"yhn(-t  
=&%}p[ 3g  
带内容的标签,且内容重复循环 Nuc;Y  
doStartTag, doAfterBody, doEndTag, release \mK;BWg)  
+Tf4SJ  
带内容的标签,且内容与JSP交互 *'?aXS -'r  
doStartTag, doEndTag, release, doInitBody, doAfterBody, release "Zh3,  
P8& BtA  
一个tag处理类可以通过javax.servlet.jsp.PageContext来与JSP交互,通过javax.servlet.jsp.PageContext类,tag处理类可以访问JSP中的request、session和application对像。 RA];hQI?  
DxM$4  
如果tag标签是互相嵌套的,那内层的tag处理类可以通过它的parent属性来访问上层的tag处理类。 KM-d8^\:  
N.~zQVO#R  
一般情况都将所有的tag处理类打成了JAR的包,以便于发布。 -hd@<+;E  
 _'Jz+f.  
L0lqm0h  
Tag库描述(简称TLD) 6&J7=g%G  
t,bQ@x{zVC  
-uk}Fou  
Tag库是用xml语言描述的,TLD包括了tag库中所有tag标签的描述,它一般用来被jsp服务器用来校验tag的语法正确性,或者被jsp开发者用来开发新的标签。 u; ]4 ydp  
2}\/_Y6  
TLD的文件扩展名必须为.tld,而且必须放在当前WEB应用的WEB-INF目录或其子目录中。 1eP`  
1hTE^\W  
一个TLD的内容的开头必须遵守标准的XML开头,用于描述DTD和xml的版本,例如: 1]&FB{l  
+,g3Xqs}X  
<?xml version="1.0" encoding="ISO-8859-1" ?> }Qu kn  
-- >q=hlA  
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd"> U ;%cp  
TLD必须以<taglib>来作为它的根元素,<taglib>的子元素如下表: F<V.OFt  
R$|"eb5  
5&C:&=Y  
<taglib>的子元素 o=zr]vv  
}srmG|@:  
Element {sOWDM5  
Description E|,RM;7  
o=]\Jy  
tlib-version MlKSjKl" !  
Tag库的版本 mb\"qD5  
Svicw`uX0  
jsp-version  `1`Qu!  
Tag库所需要的jsp的版本 V|3^H^\5P  
,=IGqw  
short-name TCWt3\  
助记符,tag的一个别名(可选) >%\&tS'  
$-i(xnU/nl  
uri drwD3jx0xv  
用于确定一个唯一的tag库 <jAn~=Uq[,  
4 (c{%%  
display-name mu*RXLai  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) ljP<WD  
0$g;O5y"i  
small-icon ;Yve m  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) C~-.zQ$  
c5em*qCw$  
large-icon i5 0c N<o  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) Di"Tv<RlQ  
koa-sy)#L  
description yZV Y3<]  
对tag库的描述(可选) r"|UgCc  
O))YJh"'_  
listener #&}j'oD|N  
参见下面listener元素 XW.k%H4@  
vR7S !  
tag ^M)+2@6  
参见下面tag 元素 Ya `$.D  
m:D0O]2  
Listener元素 nv <t$r  
.% 79(r^  
一个tag库可能定义一些类做为它的事件侦听类,这些类在TLD中被称为listener 元素,jsp服务器将会实例化这些侦听类,并且注册它们。Listener元素中有一个叫listener-class的子元素,这个元素的值必须是该侦听类的完整类名。 TE9Iyl|=  
b_vKP  
Tag元素 xj[v$HP  
M?_7*o]!  
每个tag元素在tag库中都要指出它的名字、类名、脚本变量、tag的属性。其中脚本变量的值可以直接在TLD中定义或通过tag附加信息的类来取得。每个属性描述了这个属性是否可以省略,它的值是否可以通过<%= …%>这样的JSP语法来获得,以及属性的类型。 7n)ob![\d  
%-KgR  
每一个tag在TLD中对应一个tag元素,下表是tag元素的子元素: w `nm}4M  
T'ei>]y]  
Tag元素的子元素 &n'@L9v81  
IhHKRb[  
元素名称 wq7h8Z}l  
描述 VkkC;/BBW  
Jsa]RA  
name #p<(2wN  
独一无二的元素名 jmG)p|6  
R; ui 4wg6  
tag-class t$3B#=  
Tag标签对应的tag处理类 ]$BC f4:  
\fsNI T/  
tei-class *P/DDRq(2  
javax.servlet.jsp.tagext.TagExtraInfo的子类,用于表达脚本变量(可选) +G6 Ge;  
+NJIi@  
body-content e'sS",o*  
Tag标签body的类型 I7\T :Q[  
#w@FBFr@  
display-name h[;DRD!Z  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) {"2Hv;x  
Mh2Zj  
small-icon {oS/Xa  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) r~G  amjS  
>`l^ C  
large-icon 1En:QQ4/  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) UIkO_/}  
&;bey4_J  
description <iBn-EG l>  
此tag标签的描述 9^&B.6!6  
::_bEmk  
variable J/QqwoR  
提供脚本变量的信息(同tei-class)(可选) 2tg07  
<J>k%,:B  
attribute d)3jkHYEjj  
Tag标签的属性名 WL|<xNL  
,vo]WIQ\:  
以下章节介绍对于不同类型的tag,如何具体地实现它们。 e=s({V  
},{sJ0To  
iL!4r]~H  
简单的tag lvRTy|%[  
j]U~ZAn,K  
H|$ *HQm  
tag处理类 GO.7IL{ {  
KG4zjQf  
简单的tag处理类必须实现Tag接口的doStartTag和doEndTag方法。当jsp引擎碰到tag标签的开头时,doStartTag被调用,因为简单的tag没有body,所以此方法将返回 SKIP_BODY。当jsp引擎碰到tag标签的结尾时,doEndTag被调用,如果余下的页面还要被计算,那它将返回EVAL_PAGE,否则将会返回SKIP_PAGE。 vw$b]MO!  
A)gSOC{3F)  
以下是例子:对于标签 <tt:simple /> ,它的tag处理类实现如下: .mNw^>:cq  
"sIww  
wwet90_g  
public SimpleTag extends TagSupport gi>W&6  
xLb=^Xjec  
{ (5A8#7a  
M?=I{}!@Q  
public int doStartTag() throws JspException Fn0 |v66  
 7|yEf  
{ BnfuI  
%O!TS_~9  
try{ g<ov` bF  
"[rz*[o8I  
pageContext.getOut().print(“Hello.”); &grvlK  
;W|GUmADf  
}catch(Exception e){ R! n7g8I%  
89j:YfA=v  
throw new JspTagException(“SimpleTag: “ + e.getMessage()); #k1IrqUp  
L]H' ]wpn=  
} N`{ 6<Z0  
*&I _fAh]  
return SKIP_BODY; >K&chg@Hv  
.'.bokl/  
} ?p/}eRgi  
EM@EB< pRX  
public int doEndTag() H!6+x*P0  
ll[&O4.F  
{ cq5^7.  
yJ `{\7Uqg  
return EVAL_PAGE; y>:U&P^  
^O =G%de  
} x3( ->?)D  
p5py3k  
} )*R';/zaI  
M IyT9",Pl  
,6#%+u}f  
注意:如果tag标签没有内容的话,那必须定义body-content元素为空,例如 WJ)4rQ$o  
]NtBP  
<body-content>empty</body-content> 'r(g5H1}gi  
..k8HFz>"  
Kv:Rvo  
带属性的tag标签
评价一下你浏览此帖子的感受

精彩

感动

搞笑

开心

愤怒

无聊

灌水
级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
只看该作者 1 发表于: 2007-01-01
tag处理类 8^D1u`  
m`n~-_  
对于tag标签的每个属性,你必须依照JavaBeans规范来定义其属性,以及get和set方法。以struts的logic:present 标签为例, r&Qa;-4Pl  
#d<|_  
<logic:present parameter=”Clear”> |H]0pbC)w  
h@'CmIZc  
与此相应,此tag处理类应有如下方法和定义: 34[TM3L].  
*-(o. !#1  
>]%$lSCW\D  
protected String parameter = null; WbBd<^Q  
+V9xKhR;x  
public String getParameter() kwqY~@W  
ADVS}d!;]  
{ 6|{&7=1t  
yGSZ;BDW:K  
return this.parameter; VXlAK(   
%rgW}Z5  
} =F Y2O`%a  
fBh/$    
public void setParameter(String parameter) Hq,@j{($  
#D%6b  
{ Qca3{|r`  
BjsTHS&  
this.parameter = parameter; fL d2{jI,  
&cJ?mSI  
} LXsZk|IhM  
2_6ON   
h:U#F )  
注意:如果你的属性名为id,而且你的tag处理类是从TagSupport类继承的,那你就不需要定义它的属性和set和get方法,因为他们早已在TagSupport被定义过了。 aG]^8`~>'  
\x\N?$`ANc  
Attribute元素 >T\@j\X4  
IbJl/N%o  
对于tag标签的每个属性,你必须定义它是否必须的,它的值是否可以用诸如<%= …%>的表达式来获得,以及它的类型(可选),如果不指定它的类型,那就默认为是java.lang.String类型。如果rtexprvalue元素被定义为true或yes,那么在type元素中就定义了attribute的返回类型。 s$(%?,yf2  
>dJ~  
<attribute> $+ N~Fa  
,nCvA%B!  
<name>attr1</name> ~b!la  
W}2!~ep!  
<required>true|false|yes|no</required> 6O.kKhk  
[~RO9=;L  
<rtexprvalue>true|false|yes|no</rtexprvalue> _uL[ Z  
5~T+d1md  
<type>attribute的返回类型(只用当rtexprvalue为真是才有效)</type> XJKns  
NI.ROk1{+4  
</attribute> R".$x{{  
dLF*'JjY  
如果tag的某个属性不是必须的,那tag处理类会自动提供一个缺省值。 cDzb}W*UM  
}<@-=  
例如,在logic:present这个tag标签中定义了一个属性叫parameter,但它不是必须的,而且它可以被诸如<%= …%>的表达式来赋值。 1-N+qNSD`  
z*q+5p@~  
<tag> C2\WvE%!  
sKsMF:|OT  
<name>present</name> @iXBy:@  
} XhL`%  
<tag-class>org.apache.struts.taglib.logic.PresentTag</tag-class> ?*yB&(a:8  
aI ;$N|]u  
<body-content>JSP</body-content> ^,t@HN;gA  
GUqG1u z9  
Rg\4#9S JF  
W,[QK~  
<attribute> *)`PY4zF  
q# Q%p+  
<name>parameter</name> 5G gH6   
]4V1]  
<required>false</required> ,b IJW]h0  
`?WN*__["  
<rtexprvalue>true</rtexprvalue> }{=}^c"t'  
oWLP|c~ Ap  
</attribute> #gT"G18/!  
NWPT89@l  
/{jt]8/;7  
yzT1Zg_ER  
</tag> =Ry8E2NuM  
+kEM%z  
Yb_HvP  
属性元素的校验 D)DD6  
 ;Ss!OFK  
/\uopa  
有关于tag标签的有效值可以从tag库的说明文档中获得,当JSP页面被编译时,jsp引擎会强制性地参照TLD中定义的规则进行检查。 'UxI-L t  
/Z!$bD  
还有一个方法也可以进行属性元素的校验,就是先继承类TagExtraInfo,然后调用它的isValid方法。这个类同时也起到提供tag中定义的脚本变量信息的作用。 5/i/. 0?n  
w0Ex}  
IsValid方法通过TagData对象来传递属性信息,它包括着tag的所有的属性名-值的信息。由于校验发生在运行时刻,因此这个属性的值将被赋值为TagData.REQUEST_TIME_VALUE。 ~Dz:n]Vk/  
}o7-3!{L!  
例如tag标签<tt:twa attr1=”value1” />在TLD中定义如下: O"EL3$9V  
gPc1oc(  
<attribute> :4Nv6X61  
L(u@%.S  
<name>attr1</name> <uJ {>~  
}!>\Ja<\  
<required>true</required> g-_=$#&{  
oYA"8ei=  
<rtexprvalue>true</rtexprvalue> g\8B;  
5}Ge  
</attribute> ^ <`SUBI  
vV$^`WY4  
OHj>ufwVq  
这个定义说明了attr1能在运行期间被赋值。 ZI qXkD  
cn/&QA"  
以下的isValid方法检查attr1属性的值是否属于Boolean类型。注意由于attr1能在运行刻被赋值,那么isValid方法必须检查tag用户是否对此tag进行了运行时刻赋值。 Q&w_kz.  
He5y;5  
L kl E,W  
Public class TwaTEI extends TagExtraInfo ]v),[]Xs  
+/eJ#Xw3u8  
{ m9MY d  
l;A'^  
public boolean isValid(Tagdata data) \v\ONp"  
);TB(PQsBT  
{ dY0W=,X$7T  
;-Os~81o?  
Object o = data.getAttribute(“attr1”); );}M"W8  
y= f.;  
If(o != null && o != TagData.REQUEST_TIME_VALUE) a73VDQr I  
@lWNSf  
{ $IX(a4'  
ub9[!}r't  
if( ( (String)o).toLowerCase().equals(“true”) || "DGap*=J  
4|I;z  
((String)o).toLowerCase().equals(“false”) ) Ja4M@z  
&v1E)/q{Z  
return true; }`H{;A h  
r(Z?Fs/  
else Gf9sexn]l  
[A {o"zY  
return false; mLkp*?sfC  
'jE/Tre^  
} (jhi<eV  
KWD{_h{R  
else "nfi :A1  
WbhYGcRy  
return true; x7^VU5w#  
517wduj  
} r#1W$~?>  
X(Mpg[,N"  
} w/*#TDR  
}a, ycFt  
cC/32SmY4  
带body的tag /F"eqMN  
I0Allw[  
fJ5mKN  
tag处理类 .57F h)Y  
"q=ss:(  
?SO!INJ  
如果tag标签含有内容,那处理方式会略微有些不同,而且还要视tag处理类是否要与body交互的情况而定。如果要与body交互,那我们认为tag处理类要可能要对body进行操作。 zh=0zJ  
}1[s,  
Tag处理类不与body交互 /U!B2%vq_  
+aM[!pW(e  
如果tag处理类不与body交互,tag处理类应该实现Tag接口或从TagSupport中派生,如果body要被计算,那么doStartTag方法应返回 EVAL_BODY_INCLUDE,否则应返回SKIP_BODY。 st)v'ce,  
a'Odw2Q_  
如果tag处理类要对body反复运算,则它应该实现IterationTag或从TagSupport中派生。如果tag处理类认为body还未计算完的话,那它的doStartTag方法和doAfterBody方法必须返回EVAL_BODY_AGAIN。 : OjmaP  
NvTK7? v  
Tag处理类与body交互 8rlf9m  
nHDKe )V  
如果tag处理类与body交互,那tag处理类应实现BodyTag接口或从BodyTagSupport中派生。这种tag处理类一般要实现doInitBody和doAfterBody方法。 4VeT]`C^h  
edcz%IOM(  
Body允许一些方法来读写它的内容。Tag处理类可以调用body内容的getString或getReader方法来从body中提取信息,也可用 writeOut(out) 方法来将body的内容写入到out对象中。其中out对象通过tag处理类的getPreviousOut方法来获得。 ?f3R+4  
B=%%3V)2  
如果body的内容需要被计算,那么doStartTag方法必须返回EVAL_BODY_BUFFERED,否则,它将返回 SKIP_BODY。 C{nk,j L  
Akc |E!V  
doInitBody 方法 LH+Bu%s  
RyukQY~<W  
此方法在body内容已经设好,但未被计算之前被调用。你可以根据不同的body内容来制定初始化策略。 _w %:PnO  
!t~tIJ>6  
doAfterBody方法 <*^|Aj|#  
;r6YIS4@  
此方法在body内容已被计算后进行调用。 ;~$Q;m 1  
"x$L 2>9  
和doStartTag方法一样,doAfterBody方法返回一个指示符指示是否要继续计算body,如果要继续计算,则doAfterBody应返回EVAL_BODY_BUFFERED,否则,它应返回SKIP_BODY。 M[O22wFs  
fJ _MuAv  
release 方法 R<Mp$K^b  
{: _*P TVk  
tag处理类调用此方法将它的状态重置为初始状态,并释放所有的私有资源。 =?+w5oI0  
T95FoA  
_7';1 D  
以下的例子读取body的内容(其中含有一条sql语句),然后将它传递给一个对象,让它进行查询。由于此处body不须重新计算,所以doAfterBody会返回SKIP_BODY。 !ii( 2U  
\}kR'l  
gpzFY"MS=  
Public class QueryTag extends BodyTagSupport .mqMzV  
NX(+%EBcA  
{ %x@bP6d[  
Eul3 {+]  
public int doAfterBody() throws JspTagException s 72yu}  
&FOq c  
{ /y4A?*w6  
"SQyy  
BodyContent bc = getBodyContent(); NJd4( P  
VyYrL]OrA  
//将body的内容以字符串的格式提取出来 $6 Hf[(/e  
t.RDS2N|  
String query = bc.getString(); dxZn| Y  
=MM+(mD  
//清除body ~Eik&5 z  
5eF tcK  
bc.clearBody(); sh`3${  
|Thm5,ao  
try{ . uGne  
,\3Cq2h  
Statement stmt = connection.createStatement(); Z[Iej:o5  
HfP<hQmN'  
Result result = stmt.executeQuery(query); [)8O\/:  
5?Q5cD2]\6  
}catch(SQLException e){ UA6 C/  
9fTl6?x  
throw new JspTagException(“queryTag: “ + e.getMessage() ); be_h uZ  
PGxv4(%  
return SKIP_BODY; y0O e)oP  
%G6x\[,  
} l& sEdEA  
wouk~>Jft  
} n!X%i+|4x  
HpUJ_pZ  
o.|36#Fa  
body-content元素 o>d0R w4h  
b%@9j;  
N.E{6_{S  
由于tag可能会有body,你必须用body-content元素来指定body内容的类型: Q;=4']hYU  
[9~EH8  
<body-content>JSP|tagdependent</body-content> UL&>]aQ  
;$$w`LyP  
ds+2z=!!e  
如果body的内容是定制的或内部的tag、脚本元素、或HTML广本,则归类为JSP类型。其他的类型,比如上面代码所述的?D?D将sql statement类传给 query tag的这种类型应该标为tagdependent。 _(io8zqe{j  
|pMP-  
注意:实际上body-content的值并不影响tag处理类对body内容的处理,它仅仅是被tag编辑工具用来描述此body的内容。 glM42s  
S ;8=+I,  
<~v4BiQ3l^  
用tags定义脚本变量 6MU;9|&  
+:70vZc:V@  
A>S7Ap4z>  
tag处理类 7oUo[  
Rw[!Jq  
8(q8}s$>  
tag处理类负责创建或设置页面中定义的脚本变量,用pageContext.setAttribute(name,value,scope)或pageContext.setAttribute(name,value)方法来实现。一般来说,tag处理类通过脚本变量的名称来获取它,脚本变量的名称一般可用get方法来获得。 4 8 J{Y3F  
Zg4wd/y?  
如果脚本变量的值依赖于tag处理类中的上下文中某一对象,那它可用pageContext.getAttribute(name,scope)方法来找到那个对象。一般的处理过程是tag处理类先找到脚本变量,再对其进行处理,然后用pageContext.setAttribute(name,object)的方法来设置它的新值。 NL-PQ%lUA  
"la0@/n  
对象的生存周期(scope)如下表: :*|So5fs  
g%m-*v*  
对象的生存周期表 XPt>klf  
g3%x"SlIU  
名字 TI"Ki$jC  
可访问范围 {LqYb:/C5U  
生存周期 tId,Q>zH  
lq`7$7-4  
page @V Tw>=94  
当前页面 Vz!{nL0Q(  
一直有效,除非页面向客户提交响应或重定向到一个新页面 " ~6&rt  
gr.G']9lNq  
request sMJa4P>O@  
当前页面或当前页面重定向到的页面 ff fWvf  
一直有效,除非页面向客户提交响应 9M|#X1r{%{  
VRY@}>W'  
session l_+q a6C*  
当前页面或在同一浏览器窗口中的页面 xZV|QVY;  
一直有效,除非关闭当前浏览器、超时、网络故障 b!"qbC1  
+[S<"}ls7  
application }PDtx:T-  
整个web应用程序的所有请求 AtAu$"ue  
一直有效,除非发生网络故障、服务器故障 6*>vie  
q %tq9%  
提供关于脚本变量的信息 i{Q,>Rt  
juM~X5b  
以下示例定义了一个名为“book”的脚本变量,用来访问程序中关于书的信息: P^lRJB<$Q  
S4(?= ,^-  
<bean:define id=”book” name=”bookDB” property=”bookDetails” type=”database.BookDetails” /> tI9p2!  
~G^+.>j  
<font color=”red” size=”+2” > D`B*+  
d=\\ik8  
<%= messages.getString(“CartRemoved”) %> ,~l4-x.,  
l}g_<  
<strong><jsp:getProperty name=”book” property=”title” /></strong> Xo.3OER  
vZ=dlu_t  
</font> u^VQwu6?G  
d] E.F64{  
当包含此tag的JSP页面被编译时,jsp引擎会自动生成关于此book的同步的代码(同步可以避免几个客户同时访问此book时造成的冲突),要生成同步代码,jsp引擎需要知道此脚本变量的如下信息: R \y qM;2  
"Nq5FcS9  
· 脚本变量名称 ?$/W3Xn0%  
w0<1=;_%  
· 脚本变量所属的类 i5*/ZA_  
;1TQr3w  
· 此脚本变量是否引用了一个新的或已存在的对象 #Wv8+&n  
uBM%E OE  
· 此脚本变量的有效性 [Mv'*.7  
j zZEP4  
有两种办法可以向jsp引擎提供关于脚本变量的信息:在TLD中定义variable子元素,或用tei-class子元素定义一个额外tag信息类。用variable最简单,但可能降低了一些灵活性。 kO/;lrwC  
AVc|(~V  
Variable元素 /" &Jf}r  
\C1`F [d_  
Variable元素有如下子元素: YB]^Y^"e  
{qSYe!`  
· name-given ?D?D 给出的名字,是一个常量 ^Ri ; vM  
A_J!VXq  
· name-from-attribute?D?D 属性名,在编译时给出的属性名 Nlm3RxSn  
}:b) =fs  
name-given或name-from-attribute两者必须选一,但以下子元素是可选的: c^,8eb7c  
%IUTi6P l  
· variable-class?D?D变量的类型,缺省为java.lang.String。 6WLq>Jo  
de"+ABR  
· declare?D?D此脚本变量是否引用了一个新对象,缺省为True。 86Xf6Ea  
T(+*y  
· scope?D?D脚本变量的范围,缺省为NESTED。下表描述了scope的几种类型: f2Tz5slE  
I[LHJ4  
脚本变量的有效范围 TP=#U^g*  
Hegj_FQ  
!T]bz+  
有效性 ~llw_ w  
方法 eI5W; Q4  
)OQih+#?W  
NESTED $*+UX   
在tag标签的开始和结束之间 6bbzgULl  
如果tag处理类实现BodyTag接口,则在doInitBody和doAfterBody中调用,否则在doStartTag中调用 [Ue"#w  
:&O6Y-/B  
AT_BEGIN @Y&(1Wl  
从tag标签的开始一直到页面结束 wF['oUwHH  
如果tag处理类实现BodyTag接口,则在doInitBody、doAfterBody和doEndTag中调用,否则在doStartTag和doEndTag中调用 $\nAGmp@  
$n<X'7@0  
AT_END z'Fu} ho  
从tag标签的结束一直到页面结束 `ItPTSOi  
在doEndTag中调用 a  ,<u  
uup>WW  
以struts为例,它的bean:define标签的实现遵循JSP1.1规范,此规范要求使用额外tag信息类来定义脚本变量。Variable元素是JSP1.2规范中加入的。以bean:define标签为例,你可以定义如下variable元素: (n@&M!a  
FWpb5jc)3  
<tag> 6 &MATMR  
W -5wjc  
<variable> 59a7%w  
Jn1(-  
<name-from-attribute>id</name-from-attribute> vnv:YQV/ir  
2&:w_KJ  
<variable-class>database.BookDetails</variable-class> E uk[ @1  
k'1i quc#u  
<declare>true</declare> SA -r61  
G:|=d0  
<scope>AT_BEGIN</scope> D{, b|4  
Z%Yq{tAt  
</variable> zCpXF< _C  
53?B.\  
</tag> OjY#xO+'  
/y5a~3  
额外tag信息类 +{ {'3=x9  
*JY2vq  
如果要定义一个额外tag信息类,你要继承javax.servlet.jsp.TagExtraInfo类。一个TagExtraInfo类必须实现getVariableInfo方法,此方法返回一个叫VariableInfo的数组类,它包括如下信息: aK'%E3!~=x  
8$6^S{M3  
· 变量名 !K_ ke h  
7|pF (sb0  
· 变量所属类名 1}I%yOi)  
?\T):o;/  
· 此变量是否引用了一个新对象 ?h|w7/9  
gn4 Sz")  
· 此变量的有效范围 N51RBA  
3 *[YM7y  
jsp引擎将一个名为data的参数传给getVariableInfo方法,data中包括tag标签中的所有“属性名?D?D属性值”对。它可以用来向VariableInfo对象提供脚本变量的名字和类名。 7D)i]68E  
mMtX:  
以struts为例,它在bean:define标签中定义了一个名为DefineTei的额外tag信息类,用来向脚本变量提供信息。由于脚本变量的名称(book)和类名(database.BookDetails)是通过tag标签的属性来传递的,它们一般定义在VariableInfo的构建代码中,并且可用data.getAttributeString方法来得到这些信息。如果要允许book脚本变量能在从tag开始直到整个JSP页面结束的范围内都可用的话,那它的范围应设为AT_BEGIN。如下所示: Bez 7  
]`O??wN  
#p|7\Y  
public class DefineTei extends TagExtraInfo 3Qoa ?*  
)R9QJSe  
{ `1U?^9Nf  
rtgu{m02  
public VariableInfo[] getVariableInfo(TagData data) ZNTOI]P&  
^ )[jBUT  
{ H{fOAv1*  
W*NK-F[  
String type = data.getAttributeString(“type”); ojy[<  
$+Vp>  
If( type == null) pe7R1{2Q_s  
DM)%=C6<  
type = “java.lang.Object”; -JB~yO?0  
Z3Y(g  
return new VariableInfo[] { M}b[;/~  
Zjkrne{  
new VariableInfo(data.getAttributeString(“id”), @G>Q(a*,  
'hH3d"a^=  
type, 9..! g:  
*Z=:?4u  
true, j= Ebk;6p  
bG[)r  
VariableInfo.AT_BEGIN) aMycvYzH  
wT+b|K  
}; n*GsM6Y&  
bpWEF b'f  
} BF(.^oh"n0  
DAtZp%  
} |dQ-l !  
vB9v8@[I&  
}O7b&G:nW  
注意:关于额外tag信息类的类名必须要在TLD中的tag标签下的tei-class子元素中定义。因此,DefineTei的tei-class中的定义看起来如下: *1cl PK  
<tei-class> mk&`dr  
org.apache.struts.taglib.bean.DefineTagTei 8 ,<F102(  
</tei-class> ;Jq 7E  
c2fbqM~  
`p)$7!  
具有协作关系的tag G^=C#9c.m  
q+/7v9  
[qGj*`@C  
tag通过共享对象来进行协作,JSP技术支持2种方式的对象共享。 lZ` CFZR0  
a jyuk@  
第一种方法是使用pageContext对象进行对象的共享(可支持JSP页面和tag处理类之间的共享),如果在一个tag处理类中要调用由另一个tag处理类创建的对象,可调用pageContext.getAttribute(name, scope)方法。 TbPTgE *  
tHV81F1J  
第二各方式的共享是对于tag之间有嵌套关系而言的,外层的tag所创建的对象对于内层的tag来说是可以共用的。这种形式的共享的好处是减少了可能存在的重名冲突。 b63tjqk  
5t&;>-A'?'  
要访问一个嵌套tag创建的对象,tag处理类必须先找到此嵌套tag对象,可用TagSupport的静态方法 TagSupport.findAncestorWithClass(from, class)或TagSupport.getParent方法。前者在当不确定此tag是否为嵌套tag对象时使用。一旦它的父类被找到,它就能访问其所有动态或静态创建的对象。静态创建的对象是父类的成员,而动态创建的对象可能是父类的私有对象。诸如此类的对象可以用tag处理类的setValue方法来保存,用getValue方法来获得。 l^*'W(%  
gx)!0n;  
下例阐述了以上两种共享对象的方法。在这个例子当中,一个查询tag检查一个名为connection的属性名是否在doStartTag中被设置。如果connection属性被设置,tag处理类从pageContext中得到这个connection对象。否则,此tag处理类先找到它的父tag处理类,然后从它的父tag处理类中找到connection对象。 r @ IyK%  
^u[n!R\  
PQFr4EY?i  
public class QueryTag extends BodyTagSupport DU>#eR0G  
y.'5*08S0  
{ +:&,Ts/  
ZdjmZx%%  
private String connectionId; b/eJEL  
 wN4N 2  
public int doStartTag() throws JspException XFU['BI  
 "0( _  
{ ggn:DE "  
a*gzVE7W#n  
String cid = getConnection(); D[ -Gzqh  
p Y[dJxB  
if(cid != null) c8cPGm#i  
xJ18M@" j  
{ i{ " g 7  
L]C|&K P  
//存在一个connection id,使用它。 |wFfVDp  
m$X0O_*A  
connection = (Connection) pageContext.getAttribute(cid); qz .{[ l  
/T_@rm  
} ?onTW2cG;  
FnFJw;:,{  
else vdLBf+Zi  
o2C{V1nB  
{ %kRQ9I".  
)Kw Gb&l&  
ConnectionTag ancestorTag = (ConnectionTag)findAncestorWithClass(this, #M5R>&?Jqz  
^t{2k[@  
ConnectionTag.class); .0b$mSV[  
 KDODUohC  
if(ancestorTag == null) d?uN6JH9  
ogrh"  
{ PfRe)JuB  
bm+ #OI  
throw new JspTagException(“一个没有connection属性的查询标签必须被一个connection标记嵌套。”); E0Y>2HOuL  
xy$agt>j>  
} `Z 3p( G  
A*r6  
connection = ancestorTag.getConnection(); L\u6EMyV  
k15B5  
} iVg3=R)[1  
Pl}>  
} n\ yDMY  
zFn-V EJ)  
} `(rnD  
CPto?=*A  
O_u2V'jy9  
_4]GP3`  
此查询标签在JSP页面中的调用形式可以从以下2种定义中任选一种: l,pI~A`w_  
).BZPyV<  
TNHkHR[&  
<tt:connection id=”con01” ...> ... </tt:connection> #:y h2y7a%  
X?'v FC  
<tt:query id=”balances” connection=”con01” > (rM-~h6g  
,a&&y0,  
SELECT account, balance FROM acct_table /kLG/ry8l:  
PSM~10l,  
where customer_num = <%= request.getCustno() %> y]5c!N %8  
j6NK 7Li  
</tt:query> 9 ^G. ]W]  
iIe\mV  
$T)EJe  
rk$$gXg9/  
z ]@ Q  
<tt:connection ...> 2th>+M~A  
M :4N'#`  
<x:query id=”balances”> dZ1/w0<M2  
rX-V0  
SELECT account, balance FROM acct_table B`Q~p 92  
z)Is:LhS  
where customer_num = <%= request.getCustno() %> QR+{Yp  
91 ]"D;NN  
</x:query> V@QWJZ"  
xTy[X"sJ  
</tt:connection> yMQZulCWE  
xzqgem`[\  
\,b@^W6e>  
与此同时,在TLD中必须指定connection属性为可选的,定义如下: @.PVUP  
*Z+8L*k97  
<tag> jI-\~  
]Ywj@-*q  
... `H_.<``>  
P2q'P&  
<attribute> OqaVp/,  
.fQ/a`AsU  
<name>connection</name> HR/"Nwr  
"o=*f/M  
<required>false</required> E7_)P>aS5  
: " ([i"  
</attribute> Vz"Ja  
K,VN?t <h  
</tag>
描述
快速回复

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