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

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

级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
标准的JSP 标记可以调用JavaBeans组件或者执行客户的请求,这大大降低了JSP开发的复杂度和维护量。JSP技术也允许你自定义taglib,其实换句话说,taglib可以看成是对JSP标记的一种扩展,正如xml是对html的一种扩展一样。taglib通常定义在tag标签库中,这种标签库存放着你自己定义的tag标签。简而言之,如果使用taglib,那么你可以设计自己的JSP标记! =/0=$\Ws  
#FxPj-3(ix  
一般来说,自定义tag标签主要用于操作隐藏对象、处理html提交表单、访问数据库或其它企业级的服务,诸如邮件和目录操作等等。自定义tag标签的使用者一般都是那些对java编程语言非常精通,而且对数据访问和企业级服务访问都非常熟悉的程序员,对于HTML设计者来说,使得他可以不去关注那些较复杂的商业逻辑,而将精力放在网页设计上。同时,它也将库开发者和库使用者进行合理分工,自定义tag标签将那些重复工作进行封装,从而大大提高了生产力,而且可以使得tag库可用于不同的项目中,完美地体现了软件复用的思想。 r(A.<`\   
` uCIXb  
在这篇文章中,我们主要讨论: GX{XdJD  
*# {z3{+  
· 什么是自定义tag标签? &HZmQ>!R D  
XzIx:J6  
· 怎么使用tag标签? )?! [}t  
5VW|fI  
o 声明要使用的tag库 <.K4JlbT  
\*t~==WB  
o 找到与之对应的tag处理类 !D^c3d  
E0n6$5Uc?  
o tag标签的类型 8jlLUG:g  
~nLN`H d  
· 自定义tag标签 )FN;+"IJ  
B=f,QU  
o tag处理类 &EGqgNl  
~ Heb1tl ;  
o tag库描述 k44Q):ncY7  
K>:]Bx#F7  
o tag标签示例 HeGY u?&  
_*M42<wcO  
o 带属性的tag |KI UgI  
8 )*2@-Rp  
o 带body的tag {V19Zv"j  
w'4AJ Q|;  
o 定义了脚本变量的tag . 5y"38e  
=<@2#E)  
o 具有协作关系的tag 9LnN$e  
E_z;s3AXQ  
· 自定义tag标签 {PU!=IkTS  
B<?[Mrdxw  
o 一个迭代tag的例子 q<W=#Sx  
{~GYj%-^  
o 一个模板tag库 ~5 N)f UI\  
k,F"-K+M  
o tag处理类到底是怎样被调用的? /'2O.d0}.  
] Wy)   
R:-JkV>e:  
什么是自定义的tag? +yob)%  
1F'1>Bu~  
一个自定义的tag标签是用户定义的一种JSP标记。当一个含有自定义的tag标签的JSP页面被jsp引擎编译成servlet时,tag标签被转化成了对一个称为tag处理类的对象进行的操作。于是当JSP页面被jsp引擎转化为servlet后,实际上tag标签被转化成为了对tag处理类的操作。 eK_*2=;XRW  
EI>6Nh  
自定义tag标签有很多特色,诸如: %_-zWVJ  
7tM9u5FF  
· 可以在JSP页面中自定义tag标签的属性 n]_[NR) i  
[S]S^ej*8  
· 访问JSP页面中的所有对象 /I5X"x  
b+-f.!j  
· 可以动态地修改页面输出  MTER(L  
G0 J4O!3  
· 彼此这间可以相互通信。你可以先创建一个JavaBeans组件,然后在一个tag中调用此JavaBeans组件,同时可以在另一个tag中调用它。 V3;.{0k  
`O?TUQGR  
· tag允许相互嵌套,可以在一个JSP页面中完成一些复杂的交互。 qW:)!z3\  
=o}"jVE  
sbkQ71T:  
使用tag标签 z{"2S="  
mffn//QS  
Ab%;Z5$fr  
本节主要描述怎样在JSP页面中使用tag标签,以及tag标签的不同类型。 7'-Lp@an  
mME 4 l  
要使用tag标签,JSP程序员必须做2件事: X:a`B(@S  
v8gdU7Ll,  
· 声明此tag标签的tag库 +x? #DH-  
s5.AW8X=?*  
· 实现此tag标签 SVlua@]ChU  
P7ph}mB  
声明tag标签所在的tag库 :WI.LKlo~  
$&s=68  
如果要使用tag标签,则应用JSP的taglib指示符来指定其tag库(注意:taglib要在在使用此tag标签之前声明) %<?0apO  
b `2|I {  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> `-`qdda  
tt?58dm|  
uri属性定义了唯一的标签库描述(以下简称TLD),它可以是直接是tld文件名或一个独一无二的名字。prefix是用来区别其它TLD中和本TLD中有重名的tag的一种手段。 KIA 2"KbjG  
Nw&!}#m  
TLD必须以.tld作为扩展名,并且存放在当前应用的WEB-INF目录或其子目录下。你可以通过它的文件名直接引用它,也可以通过别的方式间接地引用它。 ^=n+T7"J  
\T]EZ'+O  
以下taglib指示符直接引用一个TLD: S-31-Zjw  
#j#_cImE  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> QIN."&qC^  
di)*-+  
以下的taglib指示符通过一个逻辑名称间接地引用一个TLD: HkV1sT  
/( .6bv  
<%@ taglib uri=”/tutorial-template” prefix=”tt” %> 6C>_a*w  
e__@GBG  
如果是间接引用TLD的话,那你必须还要在web.xml中定义此逻辑名称与tld文件之间的映射,具体做法是在web.xml中加入一个名为taglib的元素: RT93Mt%P  
,\ 2a=Fp  
<taglib> 2oa#0`{  
%N;!+ ;F_g  
<taglib-uri>/tutorial-template</taglib-uri> 1:NrP'W^  
[s9O0i" Y  
<taglib-location> c`lJu_  
dC=)^(  
/WEB-INF/tutorial-template.tld OA:%lC!  
VIP7OHJh  
</taglib-location> |/g W_;(  
$F.([?)k?  
</taglib> 1Z[/KJ  
pE{yv1Yg  
7'wS\/e4a  
实现此tag标签 r1ws1 rr=  
j8|g!>Nv  
V`adWXu  
为了实现tag标签,你有2种方法来存放tag处理类。一、让tag处理类以.class的方式存放于当前应用的WEB-INF/class子目录下,二、如果tag处理类是以JAR包的形式存在的话,那可以放在当前应用的WEB-INF/lib目录下,如果tag处理类要在多个应用中共享,那么它就应放在jsp服务器上的common/lib目录下,对于tomcat来说,就是tomcat/common/lib目录下。 *A}cL  
Qn ^bVhG+  
Oz|K8p  
tag标签类型 ]zO/A4  
|Iu npZV  
Te2zK7:  
自定义的tag标签遵循XML语法。它有一个开始标记和一个结束标记,有的还有body(即文本节点): KXV[OF&J  
H Te<x  
<tt:tag> 5XuT={o  
^Qu iH'  
body X7,PEA  
9}B`uJ  
</tt:tag> iK?b~Q  
[2ax>Yk$  
&V|>dLT>A  
一个不带body的tag标签如下: 2+Px'U\  
jjJ2>3avY  
<tt:tag /> 3E f1bhi  
Qb8KPpd  
SuZ&vqS  
简单的tag标签 ~&\ f|%  
R<i38/ ~G  
一个没有body和属性的tag标签如下: m/NdJMoN=  
0Z|FZGRP  
<tt:simple /> ExHKw~y9  
A:<;M@q !  
bCZ g cN  
带属性的tag标签 @aQ1khEd  
do uc('@  
c9R 5w.t:  
自定义标签可以有自己的属性。属性一般在开始标记中定义,语法为 attr=”value”。属性的作用相当于自定义标签的一个参数,它影响着tag处理类的行为。你可以在TLD中详细定义它。 @"T"7c?Cv  
Ll MpS<2NO  
你可以用一个String常量给一个属性赋值,也可以通过表达式给它赋值,如<%= ...%>。以struts为例,它的logic:present标签就是用的String常量来给属性赋值: aA-  
65ly2gl  
<loglic:present parameter = “Clear”> qS&%!  
,G#.BLH cX  
而另一个标签logic:iterate是用表达式来给属性赋值: fQLt=Lrp  
[FUjnI  
<logci:iterate collection=”<%= bookDB.getBooks() %>” s:00yQ  
,ZblI O Wb  
id=”book” type=”database.BookDetails”> [sW.CK= 3  
IlX$YOf4  
yfU<UQ!1  
带body的tag标签 Bx[rC  
"U. ^lkN  
一个自定义标签可以包含其它自定义标签、脚本变量、HTML标记或其它内容。 vpPl$ga5bY  
-T6(hT\  
在下述例子中,此JSP页面使用了struts的logic:present标签,如果些标签定义了parameter=”Clear”的属性,则将清除购物车的内容,然后打印出一条信息: $8l({:*q0  
\:> Wpqw  
<logic:present parameter=”Clear”> Ifk#/d  
::n;VY2&  
<% cart.clear(); %> .oEmU+  
Y2o6kS{x  
<font color=”#ff0000” size=”+2”><strong> :V)lbn\  
+!f=jg06  
你选择了清除购物车! Iqs+r?  
q_ =b<.;  
</strong></font> ;M]C1!D9#  
+l^LlqA  
</logic:present> @`FCiHM  
|}){}or  
A?G IBjs  
到底是用属性还是用body来传递信息? -st7_3  
)m3q2W  
如上所述,我们既可以通过属性,也可以通过body来传递信息。但一般来说,比较简单的类型,如字符串或简单表达式最好采用属性来传递信息。 K.gEj*@  
?Z\Yu'  
Cw5%\K$=  
定义脚本变量的tag标签 b'zR 9V  
a:~@CUD >I  
所谓脚本变量,是指JSP中可以调用的变量或对象。它可由tag标签产生。以下示例阐述了一个tag标签定义了一个名为tx的由JNDI所定义的事务处理对象。脚本变量可以是ejb对象、事务、数据库连接等等: "i:T+#i({O  
3cj3u4y  
<tt:lookup id=”tx” type=”UserTransaction” name=”java:comp/UserTransaction” /> X &2oPo  
JcJmds  
<% tx.begin(); %> \b}~2oX  
]0D}T'wM  
... {F&-7u0  
@1zQce>  
R`F,aIJ]  
具有协作关系的tag标签 ,? E&V_5  
i` A  
自定义tag标签之间可以通过共享对象来实现协作。在下述例子中,标签tag1创建了一个名为obj1的对象,在标签tag2仍可以重复使用obj。 \3Oij^l 0  
BiE08,nj  
<tt:tag1 attr1=”obj1” value1=”value” /> WS& kx~oQ  
g%[n4  
<tt:tag2 attr1=”obj1” /> !gwjN_ZJ^  
EoX_KG{  
在以下这个例子当中,如果外层的tag标签创建了一个对象,那么其内层的所有tag标签都可以使用这个对象。由于这样产生的对象没有一个指定的名字,那么就可以将少重名的冲突。这个例子阐述了一系列协作的嵌套对象。 \EbbkN:D  
+@X5!S6  
<tt:outerTag> Z?MoJ{.!?R  
{Hr$wa~  
<tt:innerTag /> P`U<7xF~  
59(U`X  
</tt:outerTag> 4([.xT  
9^P2I)aD  
a )*6gf<5  
Tag处理类 nW\(IkX\  
cIXwiC8t  
t?;T3k[RM  
Tag处理类必须实现Tag接口或BodyTag接口,不过现在一般都流行从TagSupport或BodyTagSupport类中继承,这些类或接口都可以在javax.servlet.jsp.tagext包中找到。 \(I6_a_{  
Np)3+!^1"  
当JSP引擎看到自己的JSP页面中包含有tag标签时,它会调用doStartTag方法来处理tag标签的开头,调用doEndTag方法来处理tag标签的结束。 ~;-9X|  
j-]&'-h}#  
下表说明不同类型的tag所需要不同的处理过程: ]O:M$ $  
kfC0zd+  
Tag处理类的方法 ,xJrXPW  
>5~7u\#9  
Tag标签类型 T+"f]v  
所调用的方法 NTs;FX~g[  
K0+ ;b u  
基本标签 lD;'tqaC  
doStartTag, doEndTag, release x )5V.q  
BpAB5=M0  
带属性的标签 =4C}{IL  
doStartTag, doEndTag, set/getAttribute1...N, release qZ2&Xw.{1  
tP ~zKU  
带内容的标签 -237Lx$/  
doStartTag, doEndTag, release _X5_ez^/=  
PW}OU9is  
带内容的标签,且内容重复循环 U` R;P-  
doStartTag, doAfterBody, doEndTag, release pL oy  
g+q@i{Yn  
带内容的标签,且内容与JSP交互 vTr34n  
doStartTag, doEndTag, release, doInitBody, doAfterBody, release ^Uw[x\%#gD  
<FFJzNc+  
一个tag处理类可以通过javax.servlet.jsp.PageContext来与JSP交互,通过javax.servlet.jsp.PageContext类,tag处理类可以访问JSP中的request、session和application对像。 l_FGZ!7  
5$l9@0D.\  
如果tag标签是互相嵌套的,那内层的tag处理类可以通过它的parent属性来访问上层的tag处理类。 6=|&tE  
$,1dQeE  
一般情况都将所有的tag处理类打成了JAR的包,以便于发布。 K6\` __mLf  
kv|,b  
Iur9I>8h  
Tag库描述(简称TLD) g%J./F=@3  
[p;*r)f2}  
tR`S#rk  
Tag库是用xml语言描述的,TLD包括了tag库中所有tag标签的描述,它一般用来被jsp服务器用来校验tag的语法正确性,或者被jsp开发者用来开发新的标签。 RpQ*!a~O  
-R+zeu(e'  
TLD的文件扩展名必须为.tld,而且必须放在当前WEB应用的WEB-INF目录或其子目录中。 I/u9RmbU  
OS7R Qw1  
一个TLD的内容的开头必须遵守标准的XML开头,用于描述DTD和xml的版本,例如: P9#)~Zm}]  
nW;kcS*A  
<?xml version="1.0" encoding="ISO-8859-1" ?> Zy$Lrr!  
ki\uTD`mf  
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd"> p,#6 @*  
TLD必须以<taglib>来作为它的根元素,<taglib>的子元素如下表: 2YQ#-M  
3l:XhLOj  
~^o=a?L`<  
<taglib>的子元素 mX_)b>iW  
bAhZ7;T~  
Element #a}N"*P  
Description e9@(/+  
X\2_; zwf  
tlib-version u*R7zY  
Tag库的版本 $+VgDe5{S  
T&}Ye\%  
jsp-version ;<6"JP>0  
Tag库所需要的jsp的版本 N=fz/CD)I  
Zw=G@4xoU  
short-name Y}1 P~  
助记符,tag的一个别名(可选) -{x(`9H;  
lSCY5[?  
uri #tz8{o?ebN  
用于确定一个唯一的tag库 o<\6Rm  
gRvJ.Q{h  
display-name v5Y@O|i#  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) y_%&]/%  
`!Ln|_,d  
small-icon QWhp:] }  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) p$OD*f_b  
wXCyj+XB*  
large-icon u8uW9 <  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) 9".Uc8^p/F  
D0M!"c>\  
description wiV&xl  
对tag库的描述(可选) -Op@y2+c  
m.1 46  
listener iPFL"v<#J  
参见下面listener元素 pGk"3.ce  
'Kd7l}e!  
tag |>JmS  
参见下面tag 元素 [f(uqLdeM  
S~&\o\"5  
Listener元素 7K !GK  
R<j<. h  
一个tag库可能定义一些类做为它的事件侦听类,这些类在TLD中被称为listener 元素,jsp服务器将会实例化这些侦听类,并且注册它们。Listener元素中有一个叫listener-class的子元素,这个元素的值必须是该侦听类的完整类名。 R#fy60  
o}!&y?mp  
Tag元素 cUM_ncYOP  
:~r#LRgc  
每个tag元素在tag库中都要指出它的名字、类名、脚本变量、tag的属性。其中脚本变量的值可以直接在TLD中定义或通过tag附加信息的类来取得。每个属性描述了这个属性是否可以省略,它的值是否可以通过<%= …%>这样的JSP语法来获得,以及属性的类型。 =#'+"+lQ }  
vK'9{q|g  
每一个tag在TLD中对应一个tag元素,下表是tag元素的子元素: `vH&K{   
uXP- J]>  
Tag元素的子元素 -&7=uRQk  
~FNPD'`t  
元素名称 _DrnL}9I7  
描述 /MqP[*L  
JOgmF_(>Z  
name v['AB4  
独一无二的元素名 p}r yKW\cJ  
nO:HB.&@  
tag-class 59/Q*7ZJ  
Tag标签对应的tag处理类 / (.'*biQ  
@|]iSD&T #  
tei-class lk~dgky@  
javax.servlet.jsp.tagext.TagExtraInfo的子类,用于表达脚本变量(可选) ~q5-9{ma  
{'&8`d  
body-content l]/> `62  
Tag标签body的类型 jiOf')d5  
8|Q4-VK<!  
display-name d)9PEtI  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) B ;;cbY  
Do(P dF6A  
small-icon +:b(%|  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) I(y`)$}  
>Ziy1Dp  
large-icon =^ gvZ| ]  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) i"KL;t[1  
(kdC1,E  
description vN' VDvVM  
此tag标签的描述 i{4'cdr?  
./2Z?,  
variable /S/tE  
提供脚本变量的信息(同tei-class)(可选) N.k+AQb  
EOofa6f&l  
attribute EF0Pt  
Tag标签的属性名 SG1&a:c+.  
<b3x(/  
以下章节介绍对于不同类型的tag,如何具体地实现它们。 |:\$n}K  
G)4 ZK#wz  
t.gq5Y.[  
简单的tag .$n$%|"H-  
4;",@}  
k q/t]%(  
tag处理类 q.U*X5  
nmTm(?yE  
简单的tag处理类必须实现Tag接口的doStartTag和doEndTag方法。当jsp引擎碰到tag标签的开头时,doStartTag被调用,因为简单的tag没有body,所以此方法将返回 SKIP_BODY。当jsp引擎碰到tag标签的结尾时,doEndTag被调用,如果余下的页面还要被计算,那它将返回EVAL_PAGE,否则将会返回SKIP_PAGE。 t@l(xnsV  
z0=Rp0_W  
以下是例子:对于标签 <tt:simple /> ,它的tag处理类实现如下: 6sO  
z%++\.g_  
m j'"Z75  
public SimpleTag extends TagSupport "m wl-=  
^cfkP(Y3kx  
{ (R9QBZP5  
UZ[/aq  
public int doStartTag() throws JspException <W=~UUsn  
/>2A<{6\=P  
{ ocb%&m ;i  
:|*Gnu  
try{ l{M;PaJ`}  
Aqx3!  
pageContext.getOut().print(“Hello.”); /5L'9e  
} IIK~d,  
}catch(Exception e){ -lJx%9>  
Ec7{BhH)  
throw new JspTagException(“SimpleTag: “ + e.getMessage()); wrZ7Sr!/V  
H9oXZSm  
} U-wq- GT  
OpWC2t)  
return SKIP_BODY; *u:;:W&5y  
(=S"Kvb~#  
} ^&f{beU9  
12%z3/i  
public int doEndTag() l044c,AW(  
=;'ope(?S  
{ 7/5NaUmPTt  
2)HxW}o  
return EVAL_PAGE; Uxj<x`<1x  
yDu yMt#  
} ^g}gT-l%  
-D&.)N9ctQ  
} 97:t29N  
'$2oSd  
KZp,=[t  
注意:如果tag标签没有内容的话,那必须定义body-content元素为空,例如 Cg]3(3   
5WtQwN~  
<body-content>empty</body-content> "/ a*[_sV  
Lic{'w&  
?9wFV/  
带属性的tag标签
评价一下你浏览此帖子的感受

精彩

感动

搞笑

开心

愤怒

无聊

灌水
级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
只看该作者 1 发表于: 2007-01-01
tag处理类 Y7b,td1  
m"?' hR2  
对于tag标签的每个属性,你必须依照JavaBeans规范来定义其属性,以及get和set方法。以struts的logic:present 标签为例, ^Q43)H0  
t`Y1.]@U  
<logic:present parameter=”Clear”> NXWIE4T>*^  
~q#[5l(r8  
与此相应,此tag处理类应有如下方法和定义: )=,9`+Zta  
1S)0 23N  
3 4A&LBwC  
protected String parameter = null; Rrs`h `'-  
+*:x#$phx  
public String getParameter() !7,K9/"  
L[QI 5N  
{ 2'O!~8U  
9rf|r 3  
return this.parameter; UtGd/\:  
8^~ZNU-~v  
} qu#@F\gX  
=aCIaL&9Y  
public void setParameter(String parameter) eqUn8<<s  
?:;hTY  
{ T0np<l]A  
$.3CiM }~  
this.parameter = parameter;  \3y=0  
&:cTo(C'  
} ;hfG$ {l;  
fB @pwmu  
[}xIg8  
注意:如果你的属性名为id,而且你的tag处理类是从TagSupport类继承的,那你就不需要定义它的属性和set和get方法,因为他们早已在TagSupport被定义过了。 "|l oSf@  
w4< u@L  
Attribute元素 %.atWX`b  
zm)CfEF 8  
对于tag标签的每个属性,你必须定义它是否必须的,它的值是否可以用诸如<%= …%>的表达式来获得,以及它的类型(可选),如果不指定它的类型,那就默认为是java.lang.String类型。如果rtexprvalue元素被定义为true或yes,那么在type元素中就定义了attribute的返回类型。 UNZVu~WnF  
]K0,nj*\c  
<attribute> dPdHY&#`  
m(7_ZiL=  
<name>attr1</name> Q&U= jX  
>* Qk~kv<%  
<required>true|false|yes|no</required> in;+d~?  
Dk{nOvZu<  
<rtexprvalue>true|false|yes|no</rtexprvalue> [9W&1zY  
.n|3A3:  
<type>attribute的返回类型(只用当rtexprvalue为真是才有效)</type> ;xkf ?|  
$Ln2O#  
</attribute>  V\7u  
$gD(MKR)~  
如果tag的某个属性不是必须的,那tag处理类会自动提供一个缺省值。 /RULPd PH  
=ILo`Q~  
例如,在logic:present这个tag标签中定义了一个属性叫parameter,但它不是必须的,而且它可以被诸如<%= …%>的表达式来赋值。 5A=xFj{  
=L; n8~{@y  
<tag> v'Py[[R  
V:" \(Y  
<name>present</name> CYic_rF$  
xyJgHbml  
<tag-class>org.apache.struts.taglib.logic.PresentTag</tag-class> G?/8&%8  
f.xSr!  
<body-content>JSP</body-content> zZ"')+7q&%  
&WWO13\qd  
wYxFjXm  
t-ReT_D|;  
<attribute> c$Nl-?W  
'~6CGqU*  
<name>parameter</name> AxqTPx7`|  
x:wq"X  
<required>false</required> [~r $US  
K]azUK7  
<rtexprvalue>true</rtexprvalue> "kuBjj2  
b:d.Lf{y7  
</attribute> g='2~c  
vH:+  
I3=Sc^zz&V  
ha'm`LiX  
</tag> 5suSR;8  
# 2t\>7]  
:QY9pT  
属性元素的校验 Rn ^N+3o'M  
rlh6\Fa  
HOI`F3#XI  
有关于tag标签的有效值可以从tag库的说明文档中获得,当JSP页面被编译时,jsp引擎会强制性地参照TLD中定义的规则进行检查。 w0>)y -  
j3'/jk]\  
还有一个方法也可以进行属性元素的校验,就是先继承类TagExtraInfo,然后调用它的isValid方法。这个类同时也起到提供tag中定义的脚本变量信息的作用。 $R}iL  
j{+I~|ZB,  
IsValid方法通过TagData对象来传递属性信息,它包括着tag的所有的属性名-值的信息。由于校验发生在运行时刻,因此这个属性的值将被赋值为TagData.REQUEST_TIME_VALUE。 4 6JP1  
ll^O+>1dO  
例如tag标签<tt:twa attr1=”value1” />在TLD中定义如下: F,$$N>  
`-e}:9~q  
<attribute> R_&V.\e_  
.:Xe*Q  
<name>attr1</name> jtCob'n8  
jS)-COk  
<required>true</required> 2MrR|hLx  
-BH'.9uqGQ  
<rtexprvalue>true</rtexprvalue> ?4dd|n  
~$9"|  
</attribute> H zK=UcD  
q:eAL'OkM  
"[Lp-4A\  
这个定义说明了attr1能在运行期间被赋值。 iFT3fP'> 5  
Eu_0n6J  
以下的isValid方法检查attr1属性的值是否属于Boolean类型。注意由于attr1能在运行刻被赋值,那么isValid方法必须检查tag用户是否对此tag进行了运行时刻赋值。 *J- jr8&  
q"vT]=Y}:  
#.K&]OV/88  
Public class TwaTEI extends TagExtraInfo _e^V\O>  
Cf 8 - %  
{ V#FLxITk  
0a;zT O/"v  
public boolean isValid(Tagdata data) m=y)i]=1  
:zZM&r>  
{ _dY}86{  
"A$Y)j<#G  
Object o = data.getAttribute(“attr1”); +4RaN`I  
D7oV&vXg  
If(o != null && o != TagData.REQUEST_TIME_VALUE) @ uWD>(D  
8XE0 p7  
{ p#I1l2nE  
eS+LFS7*k  
if( ( (String)o).toLowerCase().equals(“true”) || ucO]&'hu:  
$t?e=#G  
((String)o).toLowerCase().equals(“false”) ) qd;f]ndo  
4WnxJ]5`  
return true; |1x,_uyQ%  
"R]K!GUU  
else  iSax-Mc  
^u<+tV   
return false; Mqy`j9FbL  
smNr%}_g  
} r +fzmb  
{hR23eE)#  
else )FCqYCfk  
]].21  
return true; y2>] gX5  
%dQX d ]  
} yLX\pkAt4  
C$; ~=  
} e4P.G4  
gr7_oJ:R  
2y,wN"qH*  
带body的tag i vk|-C'\  
 glUP  
vUA,`  
tag处理类 ]vrs?  
_Fjv.VQ,  
_XtY/7n  
如果tag标签含有内容,那处理方式会略微有些不同,而且还要视tag处理类是否要与body交互的情况而定。如果要与body交互,那我们认为tag处理类要可能要对body进行操作。 P&VI2k  
 0]HI c  
Tag处理类不与body交互 jTIn@Q  
SfR_#"Uu  
如果tag处理类不与body交互,tag处理类应该实现Tag接口或从TagSupport中派生,如果body要被计算,那么doStartTag方法应返回 EVAL_BODY_INCLUDE,否则应返回SKIP_BODY。 [8n4lE[)"  
.BvV[`P  
如果tag处理类要对body反复运算,则它应该实现IterationTag或从TagSupport中派生。如果tag处理类认为body还未计算完的话,那它的doStartTag方法和doAfterBody方法必须返回EVAL_BODY_AGAIN。 3@J wL{C  
+aap/sYp  
Tag处理类与body交互 bx> D  
Os;\\~e5  
如果tag处理类与body交互,那tag处理类应实现BodyTag接口或从BodyTagSupport中派生。这种tag处理类一般要实现doInitBody和doAfterBody方法。 im"v75 tc  
AnQRSB (  
Body允许一些方法来读写它的内容。Tag处理类可以调用body内容的getString或getReader方法来从body中提取信息,也可用 writeOut(out) 方法来将body的内容写入到out对象中。其中out对象通过tag处理类的getPreviousOut方法来获得。 4a~_hkY]  
4{=Em5`HbO  
如果body的内容需要被计算,那么doStartTag方法必须返回EVAL_BODY_BUFFERED,否则,它将返回 SKIP_BODY。 b7/4~_s  
jLg4_N1SD  
doInitBody 方法 5q[@N  J  
R<U <Y'Y  
此方法在body内容已经设好,但未被计算之前被调用。你可以根据不同的body内容来制定初始化策略。 (H7q[UG|  
XR(kR{yo  
doAfterBody方法 h";sQ'us  
lDzVc`c  
此方法在body内容已被计算后进行调用。 |{(ynZ]R  
W=/B[@3'  
和doStartTag方法一样,doAfterBody方法返回一个指示符指示是否要继续计算body,如果要继续计算,则doAfterBody应返回EVAL_BODY_BUFFERED,否则,它应返回SKIP_BODY。 :1Ay_ b_J  
z!tHn#  
release 方法 (msJ:SG  
P=.W.oS  
tag处理类调用此方法将它的状态重置为初始状态,并释放所有的私有资源。 uWSG+  
a,.9eHf  
Bs*s8}6  
以下的例子读取body的内容(其中含有一条sql语句),然后将它传递给一个对象,让它进行查询。由于此处body不须重新计算,所以doAfterBody会返回SKIP_BODY。 B(hNBq7  
/}wGmX! -!  
i*3'O:Gq  
Public class QueryTag extends BodyTagSupport !#QD;,SE+  
PeOgXg)L`z  
{ G|V ^C_:  
3JwmLGj}  
public int doAfterBody() throws JspTagException G7u85cie  
y9 "!ys  
{ Xv9C D  
&Ef'5  
BodyContent bc = getBodyContent(); V'8 (}(s/  
2ma.zI@^u9  
//将body的内容以字符串的格式提取出来  )57OZ  
`#~@f!';  
String query = bc.getString(); HRk+2'wjAz  
C]}0h!_V  
//清除body  (1ebE  
*<KY^;  
bc.clearBody(); vg<_U&N=-r  
x\lua  
try{ |b|p0Z%7{  
r*$KF!-dg  
Statement stmt = connection.createStatement(); K-K+%U  
Z# 1Qj9  
Result result = stmt.executeQuery(query); QJxcH$  
>[[< 5$,T  
}catch(SQLException e){ tUzuel*  
*}FoeDe  
throw new JspTagException(“queryTag: “ + e.getMessage() ); ]:F]VRPT  
_uDtRoI8  
return SKIP_BODY; p!=/a)4X  
cdk;HK_Ve.  
} v6]lH9c{,  
V XC_Y  
} (UpSi6?\  
j5AW}   
6x_8m^+m  
body-content元素 }V 09tK/M  
a &j H9  
)U5AnL  
由于tag可能会有body,你必须用body-content元素来指定body内容的类型: k9a-\UIMet  
(ue;O~  
<body-content>JSP|tagdependent</body-content> jQc$>M<"o  
7z`)1^ M  
By%aTuV$  
如果body的内容是定制的或内部的tag、脚本元素、或HTML广本,则归类为JSP类型。其他的类型,比如上面代码所述的?D?D将sql statement类传给 query tag的这种类型应该标为tagdependent。 6ZX{K1_q  
~Xa >;  
注意:实际上body-content的值并不影响tag处理类对body内容的处理,它仅仅是被tag编辑工具用来描述此body的内容。 *PD7H9m  
i9$ -lk  
(.Sj"6+  
用tags定义脚本变量 I~EJctOG  
hCM+=]z"  
L_O m<LO2  
tag处理类 Y'58.8hl  
g+U6E6}1  
nD|Bo 9  
tag处理类负责创建或设置页面中定义的脚本变量,用pageContext.setAttribute(name,value,scope)或pageContext.setAttribute(name,value)方法来实现。一般来说,tag处理类通过脚本变量的名称来获取它,脚本变量的名称一般可用get方法来获得。 pLNv\M+  
Ak&eGd$d  
如果脚本变量的值依赖于tag处理类中的上下文中某一对象,那它可用pageContext.getAttribute(name,scope)方法来找到那个对象。一般的处理过程是tag处理类先找到脚本变量,再对其进行处理,然后用pageContext.setAttribute(name,object)的方法来设置它的新值。 !M\8k$#"n  
.- uH ax0  
对象的生存周期(scope)如下表: kowBB0  
g\GuH?|   
对象的生存周期表 4; y*y tY*  
W A-\2  
名字 R FWJ ZN"  
可访问范围 :(E.sT "R  
生存周期 0"LJ{:plz  
Dy mf  
page WQK ~;GV-  
当前页面 [s"xOP9R  
一直有效,除非页面向客户提交响应或重定向到一个新页面 ;X*I,g.+H  
AKu]c-  
request l*^c?lp)  
当前页面或当前页面重定向到的页面 /c6:B5G  
一直有效,除非页面向客户提交响应 w`x4i fZ0q  
M*$#j|  
session J4"?D9T3G  
当前页面或在同一浏览器窗口中的页面 v*U OD'tk  
一直有效,除非关闭当前浏览器、超时、网络故障  ]?M3X_Mq  
[2ez"4e  
application c>mTd{Abi  
整个web应用程序的所有请求 C/_Z9LL?F  
一直有效,除非发生网络故障、服务器故障 i_Ol vuy~  
"V'<dn  
提供关于脚本变量的信息 gw O]U=Y  
Wa.y7S0(@  
以下示例定义了一个名为“book”的脚本变量,用来访问程序中关于书的信息: %=e^MN1  
h6`v%7H?  
<bean:define id=”book” name=”bookDB” property=”bookDetails” type=”database.BookDetails” /> T uG%oV}   
Y#7sDd!N|  
<font color=”red” size=”+2” > 'ioX,KD  
[&eG>zF"  
<%= messages.getString(“CartRemoved”) %> RA^6c![  
YMXhzqj  
<strong><jsp:getProperty name=”book” property=”title” /></strong> F}MjZZj(U=  
r^zra|]  
</font> dT?mMTKn+  
t.X8c/,;g  
当包含此tag的JSP页面被编译时,jsp引擎会自动生成关于此book的同步的代码(同步可以避免几个客户同时访问此book时造成的冲突),要生成同步代码,jsp引擎需要知道此脚本变量的如下信息: DXyRNE<G[C  
&1 t84p:^=  
· 脚本变量名称 mH6\8I  
"d"6.ND  
· 脚本变量所属的类 0Sx$6:-~  
%^pm~ck!  
· 此脚本变量是否引用了一个新的或已存在的对象 Dqu?mg;L  
Yc^;?n`x  
· 此脚本变量的有效性 wDp5HZ>  
\&BT#8ELG  
有两种办法可以向jsp引擎提供关于脚本变量的信息:在TLD中定义variable子元素,或用tei-class子元素定义一个额外tag信息类。用variable最简单,但可能降低了一些灵活性。 :yxP3e%rp  
"vvv@sYxi  
Variable元素 N.'-9hv  
*{x8@|K8  
Variable元素有如下子元素: 9KCeKT>v  
'"C& dia  
· name-given ?D?D 给出的名字,是一个常量 XmJ?oPr7  
FeL!%z  
· name-from-attribute?D?D 属性名,在编译时给出的属性名 s+0n0C  
%_ (Xn  
name-given或name-from-attribute两者必须选一,但以下子元素是可选的: 2=,O)g  
t9~Y ?  
· variable-class?D?D变量的类型,缺省为java.lang.String。 <I 0EjV  
thLx!t  
· declare?D?D此脚本变量是否引用了一个新对象,缺省为True。 yRy^'E~  
#sm@|'Q%  
· scope?D?D脚本变量的范围,缺省为NESTED。下表描述了scope的几种类型: j6GR-WQ]t  
*JArR1J  
脚本变量的有效范围 eNDc220b  
]?sw<D{  
Yij_'0vZ  
有效性 Esdv+f}4;  
方法 v8U&{pD,  
Owz>g4l r  
NESTED |U`A So  
在tag标签的开始和结束之间 B-p ].  
如果tag处理类实现BodyTag接口,则在doInitBody和doAfterBody中调用,否则在doStartTag中调用 &SMM<^P.  
}hA)p:  
AT_BEGIN jO.c>C[?  
从tag标签的开始一直到页面结束 Pd+Wb3  
如果tag处理类实现BodyTag接口,则在doInitBody、doAfterBody和doEndTag中调用,否则在doStartTag和doEndTag中调用 RDxvN:v  
KBI36=UV  
AT_END t vp kc;  
从tag标签的结束一直到页面结束 @NYlVk2  
在doEndTag中调用 R-6km Tex>  
x-T7 tr&(  
以struts为例,它的bean:define标签的实现遵循JSP1.1规范,此规范要求使用额外tag信息类来定义脚本变量。Variable元素是JSP1.2规范中加入的。以bean:define标签为例,你可以定义如下variable元素: J\?d+}hynX  
a;f A0_  
<tag> $Yj4&Two<  
9w<k1j  
<variable> ^S:I38gR#q  
H<Zs2DP`  
<name-from-attribute>id</name-from-attribute> v*&WqVg  
#]2,1dJ  
<variable-class>database.BookDetails</variable-class> 0Wb3M"#9<  
wKE}BO >  
<declare>true</declare> >mMmc!u>G  
r)gtx!bx  
<scope>AT_BEGIN</scope> XZ 4H(Cj  
rsD? ;XzH  
</variable> B/K{sI  
T^@P.zX  
</tag> ^.>XDUO F  
|?LUt@r;  
额外tag信息类 5N[H@%>QO  
:?$<:  
如果要定义一个额外tag信息类,你要继承javax.servlet.jsp.TagExtraInfo类。一个TagExtraInfo类必须实现getVariableInfo方法,此方法返回一个叫VariableInfo的数组类,它包括如下信息: 9u1Fk'cxG,  
2 W Wr./q  
· 变量名 #{~3bgY  
72sBx3 ;  
· 变量所属类名 Lu[xoQ~I  
J5zu}U?  
· 此变量是否引用了一个新对象 M5{vYk>,1Q  
xL|4'8  
· 此变量的有效范围 71G00@&w9D  
(RLJ_M|;/b  
jsp引擎将一个名为data的参数传给getVariableInfo方法,data中包括tag标签中的所有“属性名?D?D属性值”对。它可以用来向VariableInfo对象提供脚本变量的名字和类名。 ++CL0S$e  
^ oh%Ns  
以struts为例,它在bean:define标签中定义了一个名为DefineTei的额外tag信息类,用来向脚本变量提供信息。由于脚本变量的名称(book)和类名(database.BookDetails)是通过tag标签的属性来传递的,它们一般定义在VariableInfo的构建代码中,并且可用data.getAttributeString方法来得到这些信息。如果要允许book脚本变量能在从tag开始直到整个JSP页面结束的范围内都可用的话,那它的范围应设为AT_BEGIN。如下所示: IWnyqt(k  
+\66; 7]s  
CW@G(R  
public class DefineTei extends TagExtraInfo eQsoZQA1  
0hX@ta[Up  
{  p/?TU  
9 F|e .  
public VariableInfo[] getVariableInfo(TagData data) 6'JP%~QlS  
y5:al7*P  
{ Cz#3W8jV  
-P$E)5?^  
String type = data.getAttributeString(“type”); \\,z[C  
nXxSv~r  
If( type == null) LJBDB6  
UdX aC= Q  
type = “java.lang.Object”; f2FGod<CzN  
E']Gh  
return new VariableInfo[] { Wg5i#6y8w  
ATf{;S}  
new VariableInfo(data.getAttributeString(“id”), g<PdiVp+  
KDy:A>_ G"  
type, :]-? l4(%  
U4,hEnJBT  
true, z,/y2H2  
Y^CbpG&-vC  
VariableInfo.AT_BEGIN) My\  
( ?pn2- Ip  
}; o!M*cyq  
von~-51;  
} s*W)BK|+?  
|h65[9DMP  
} IXmO1*o@  
d 3 }'J  
*oz=k  
注意:关于额外tag信息类的类名必须要在TLD中的tag标签下的tei-class子元素中定义。因此,DefineTei的tei-class中的定义看起来如下: 7<c&)No;  
<tei-class> R7!^ M  
org.apache.struts.taglib.bean.DefineTagTei }V % b  
</tei-class> o'nrLI(t  
44kb  
A[m4do  
具有协作关系的tag 8yc?9&/ |  
Rd.[8#7VE  
~+Da`Wp  
tag通过共享对象来进行协作,JSP技术支持2种方式的对象共享。 s% ~p?_P   
))>)qav  
第一种方法是使用pageContext对象进行对象的共享(可支持JSP页面和tag处理类之间的共享),如果在一个tag处理类中要调用由另一个tag处理类创建的对象,可调用pageContext.getAttribute(name, scope)方法。 5-pz/%,  
|d1%N'Ll  
第二各方式的共享是对于tag之间有嵌套关系而言的,外层的tag所创建的对象对于内层的tag来说是可以共用的。这种形式的共享的好处是减少了可能存在的重名冲突。 :}18G}B  
_;+N=/l0  
要访问一个嵌套tag创建的对象,tag处理类必须先找到此嵌套tag对象,可用TagSupport的静态方法 TagSupport.findAncestorWithClass(from, class)或TagSupport.getParent方法。前者在当不确定此tag是否为嵌套tag对象时使用。一旦它的父类被找到,它就能访问其所有动态或静态创建的对象。静态创建的对象是父类的成员,而动态创建的对象可能是父类的私有对象。诸如此类的对象可以用tag处理类的setValue方法来保存,用getValue方法来获得。 4c=oAL  
3fJwj}wL  
下例阐述了以上两种共享对象的方法。在这个例子当中,一个查询tag检查一个名为connection的属性名是否在doStartTag中被设置。如果connection属性被设置,tag处理类从pageContext中得到这个connection对象。否则,此tag处理类先找到它的父tag处理类,然后从它的父tag处理类中找到connection对象。 @Q atgYu  
N:@C% UW}  
 Cz_chK4  
public class QueryTag extends BodyTagSupport md/Z[du:'  
`'`T'+0  
{ cnOk  
V F'! OPN  
private String connectionId; M('cG  
B1A5b=6G<  
public int doStartTag() throws JspException -W+67@(\8H  
^50/.Z >  
{ p=(;WnsK  
_k@{> ?(a  
String cid = getConnection(); ft[g1  
>9g`9hB  
if(cid != null) -$4%@Z  
0ZV)Y<DJ  
{ yX(6C]D  
u-h3xj  
//存在一个connection id,使用它。 v=|BqG`  
gH0B[w ]  
connection = (Connection) pageContext.getAttribute(cid); s%z'1KPS  
^F~e?^s  
} zY|]bP[NEH  
LxVd7r VY6  
else +2w54X%?M  
zHB{I(q  
{ ,\DB8v6l\A  
W &4`eB/4}  
ConnectionTag ancestorTag = (ConnectionTag)findAncestorWithClass(this,  #~.i\|VL  
*ma/_rjK  
ConnectionTag.class); *ftJ(  
Ik1,?A  
if(ancestorTag == null) @U:T}5)wc  
WytCc>oL  
{ ooIMN =  
Z=!*7@QY  
throw new JspTagException(“一个没有connection属性的查询标签必须被一个connection标记嵌套。”); `z)!!y  
ojVpw4y.  
} [`fq4Ky  
6DJ,/J2F  
connection = ancestorTag.getConnection(); s80_e  
Mn~A;=%qF  
} pLzsL>6h  
vo`wYJ3W  
} U&3*c+B4  
yK?~X V:  
} h;4g#|,  
G>mgoN  
M:`hb$k:  
sD{b0mZT  
此查询标签在JSP页面中的调用形式可以从以下2种定义中任选一种: .4!N #'  
d<7J)zUm3  
? 3}UO:B  
<tt:connection id=”con01” ...> ... </tt:connection> I9F[b#'Pn  
rY!uc!  
<tt:query id=”balances” connection=”con01” > N@MeaO  
-;P<Q`{I  
SELECT account, balance FROM acct_table \;7DS:d@  
d BlOU.B  
where customer_num = <%= request.getCustno() %> RaU.yCYyu  
YRp\#pVnZ  
</tt:query> 7-o=E=  
Jl]]nO BQ/  
: l>Ue&  
i9!Urq-  
b(Z%#*e  
<tt:connection ...> @i{JqHU"  
|O4A+S  
<x:query id=”balances”> ax^${s|{-  
<go~WpA|r  
SELECT account, balance FROM acct_table q5vs;,_ |  
Oq[E\8Wn  
where customer_num = <%= request.getCustno() %> ?Nh%!2n  
4{vd6T}V!  
</x:query> phc1AN=[E  
<Y orQ>  
</tt:connection> r0 X2cc  
\4j+pU  
@zJI0_Bp  
与此同时,在TLD中必须指定connection属性为可选的,定义如下: :>X7(&j8  
-ufmpq.  
<tag> &16bZw  
R&4E7wrdP  
... `5 6QX'?  
1!f'nS  
<attribute> 6fV)8,F3  
'.K,EM!-~h  
<name>connection</name> %7d"()L  
k_a'a)`$6  
<required>false</required> DO\EB6xH>%  
ya_'Oz!C  
</attribute> x>J3tp$2  
Hxl,U>za#  
</tag>
描述
快速回复

您目前还是游客,请 登录注册
如果您在写长篇帖子又不马上发表,建议存为草稿
认证码:
验证问题:
3+5=?,请输入中文答案:八 正确答案:八