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

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

级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
标准的JSP 标记可以调用JavaBeans组件或者执行客户的请求,这大大降低了JSP开发的复杂度和维护量。JSP技术也允许你自定义taglib,其实换句话说,taglib可以看成是对JSP标记的一种扩展,正如xml是对html的一种扩展一样。taglib通常定义在tag标签库中,这种标签库存放着你自己定义的tag标签。简而言之,如果使用taglib,那么你可以设计自己的JSP标记! `"-`D!U?$  
H"kc^G+(R"  
一般来说,自定义tag标签主要用于操作隐藏对象、处理html提交表单、访问数据库或其它企业级的服务,诸如邮件和目录操作等等。自定义tag标签的使用者一般都是那些对java编程语言非常精通,而且对数据访问和企业级服务访问都非常熟悉的程序员,对于HTML设计者来说,使得他可以不去关注那些较复杂的商业逻辑,而将精力放在网页设计上。同时,它也将库开发者和库使用者进行合理分工,自定义tag标签将那些重复工作进行封装,从而大大提高了生产力,而且可以使得tag库可用于不同的项目中,完美地体现了软件复用的思想。 !M#?kKj  
d7n4zx1Hh  
在这篇文章中,我们主要讨论: Rq~ >h99M  
n:{-Vvt  
· 什么是自定义tag标签? 6ba2^3GH  
W,L>'$#pM  
· 怎么使用tag标签? U/ v"?pg[  
Lk$Je O  
o 声明要使用的tag库 |>m# m*{S  
}-k_?2"A  
o 找到与之对应的tag处理类 98<bF{#0WM  
h[M6.  
o tag标签的类型 AOq9v~)z-  
3:z4M9f  
· 自定义tag标签 U[H+87zg  
N69eI dl  
o tag处理类 "m<eHz]D  
FN8=YUYK%  
o tag库描述 o>QFd x  
DT1i2!  
o tag标签示例 H@OrX  
8=u+BDG  
o 带属性的tag Oa3=+_C~$1  
I*`=[nR  
o 带body的tag a`GN@ 8  
5r2ctde)Y  
o 定义了脚本变量的tag _tWfb}6;Zb  
)SlUQ7f>  
o 具有协作关系的tag 8/kx3  
HT1dvC$COo  
· 自定义tag标签 519:yt   
l%Fse&4\  
o 一个迭代tag的例子 D+@/x{wX2  
7o 83|s.Bm  
o 一个模板tag库 W6!4Qyn  
U- UV<}  
o tag处理类到底是怎样被调用的? 2rE~V.)%  
H8Z Z@@ qm  
!EyGJa[ i  
什么是自定义的tag? yScov)dp(  
.,BD DPFB  
一个自定义的tag标签是用户定义的一种JSP标记。当一个含有自定义的tag标签的JSP页面被jsp引擎编译成servlet时,tag标签被转化成了对一个称为tag处理类的对象进行的操作。于是当JSP页面被jsp引擎转化为servlet后,实际上tag标签被转化成为了对tag处理类的操作。 $ M[}(m  
A(!ZZ9 Wc  
自定义tag标签有很多特色,诸如: nP3;<*T P0  
/d]V{I~6  
· 可以在JSP页面中自定义tag标签的属性 0ga1Yr]  
GhfUCW%  
· 访问JSP页面中的所有对象 u3v6$CD?  
`mHOgS>|  
· 可以动态地修改页面输出 Z ^9{Qq  
AcfkY m~  
· 彼此这间可以相互通信。你可以先创建一个JavaBeans组件,然后在一个tag中调用此JavaBeans组件,同时可以在另一个tag中调用它。 X?k V1  
4q 2=:"z4  
· tag允许相互嵌套,可以在一个JSP页面中完成一些复杂的交互。 O'yjB$j  
")[Q4H;V  
8bKWIN g_n  
使用tag标签 Bafz&#;Q'  
<PuB3PEvV  
=-s20mdj  
本节主要描述怎样在JSP页面中使用tag标签,以及tag标签的不同类型。 f 7QUZb\  
TG%hy"k  
要使用tag标签,JSP程序员必须做2件事: $'mB8 S  
Ubos#hP  
· 声明此tag标签的tag库 Xxsnpb>  
#Ot*jb1  
· 实现此tag标签 R*TGn_J`  
[C~)&2wh>  
声明tag标签所在的tag库 ^Hhw(@`qf  
%JA&O  
如果要使用tag标签,则应用JSP的taglib指示符来指定其tag库(注意:taglib要在在使用此tag标签之前声明) >[P7Zlwv4  
?U9d3] W  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> p9] 7g%  
2ZzD^:V[}  
uri属性定义了唯一的标签库描述(以下简称TLD),它可以是直接是tld文件名或一个独一无二的名字。prefix是用来区别其它TLD中和本TLD中有重名的tag的一种手段。 +hvIJv ?  
"!_ 4%z-  
TLD必须以.tld作为扩展名,并且存放在当前应用的WEB-INF目录或其子目录下。你可以通过它的文件名直接引用它,也可以通过别的方式间接地引用它。 94k)a8-!  
'|A5a+[  
以下taglib指示符直接引用一个TLD: xvz5\s|b  
; K 6Fe)  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> Z!=Pc$?  
D A)0Y_  
以下的taglib指示符通过一个逻辑名称间接地引用一个TLD: yU8Y{o;:  
+]~w ?^h  
<%@ taglib uri=”/tutorial-template” prefix=”tt” %> UC LjR<}  
H* L2gw  
如果是间接引用TLD的话,那你必须还要在web.xml中定义此逻辑名称与tld文件之间的映射,具体做法是在web.xml中加入一个名为taglib的元素: +K?N:w  
H6 f; BS  
<taglib> _2Xu1q.6~5  
"6o}qeB l  
<taglib-uri>/tutorial-template</taglib-uri> U"Ob@$ROFy  
LkZo/K~  
<taglib-location> He_(JXTP  
$?JLCa  
/WEB-INF/tutorial-template.tld 'V9aB5O&  
E<G@LT  
</taglib-location> a]=vq(N'r  
?`*-QG}  
</taglib> s2v#evI`+  
Z6/~2S@  
m ?"%&|  
实现此tag标签 Zow^bzy4  
f;XsShxr  
a:%5.!Vd  
为了实现tag标签,你有2种方法来存放tag处理类。一、让tag处理类以.class的方式存放于当前应用的WEB-INF/class子目录下,二、如果tag处理类是以JAR包的形式存在的话,那可以放在当前应用的WEB-INF/lib目录下,如果tag处理类要在多个应用中共享,那么它就应放在jsp服务器上的common/lib目录下,对于tomcat来说,就是tomcat/common/lib目录下。 ]! J3?G  
0N[DV]  
A =[f>8  
tag标签类型 l|tp0[  
wj5s5dH  
I%b:Z  
自定义的tag标签遵循XML语法。它有一个开始标记和一个结束标记,有的还有body(即文本节点): _M4v1Hr48  
V7'x? pt  
<tt:tag> |iJZC  
|b@A:8ss  
body :a!a  
e4H0<h }{  
</tt:tag> >W]"a3E  
vc{]c }  
AdS_-Cm  
一个不带body的tag标签如下: h \cK  
]B'  
<tt:tag /> )n[Mh!mn  
./*,Thc  
lGBdQc]IL  
简单的tag标签 G`lhvpifG  
<21^{ yt1  
一个没有body和属性的tag标签如下: `ip69 IF2*  
%c2i.E/G  
<tt:simple /> G6F['g);  
J0mCWtx&  
m]}"FMH$  
带属性的tag标签 /2V',0  
k)' z<EL6c  
;9 n8on\  
自定义标签可以有自己的属性。属性一般在开始标记中定义,语法为 attr=”value”。属性的作用相当于自定义标签的一个参数,它影响着tag处理类的行为。你可以在TLD中详细定义它。 e[&3K<  
#UeU:RJ1  
你可以用一个String常量给一个属性赋值,也可以通过表达式给它赋值,如<%= ...%>。以struts为例,它的logic:present标签就是用的String常量来给属性赋值: lc(iy:z@  
eV+wnE?SB5  
<loglic:present parameter = “Clear”> gm$MEeC  
$ rnr;V  
而另一个标签logic:iterate是用表达式来给属性赋值: \ iSBLU  
,lYU#Hx*  
<logci:iterate collection=”<%= bookDB.getBooks() %>” qc"/T16M]  
w7V W   
id=”book” type=”database.BookDetails”> ?+tZP3'  
7+r5?h|  
JN-8\ L  
带body的tag标签 1Nu`@)D0  
cU[pneY  
一个自定义标签可以包含其它自定义标签、脚本变量、HTML标记或其它内容。 gy`qEY~B&  
n:)Y'52}  
在下述例子中,此JSP页面使用了struts的logic:present标签,如果些标签定义了parameter=”Clear”的属性,则将清除购物车的内容,然后打印出一条信息: F>R)~;Ja  
'E8Qi'g  
<logic:present parameter=”Clear”> r_RTtS#  
h;[Nc j]  
<% cart.clear(); %> [M>_(u6  
)`7h,w J[1  
<font color=”#ff0000” size=”+2”><strong> Fa^]\:  
ZWEzL$VWi  
你选择了清除购物车! ub&29Qte  
[6N39G$  
</strong></font> Md{f,,E'^@  
;KN@v5`p  
</logic:present> +c_CYkHJ/  
8}@a?QS(&  
7^X_tQf  
到底是用属性还是用body来传递信息? ZA@"uqa6b  
sg\ jC#  
如上所述,我们既可以通过属性,也可以通过body来传递信息。但一般来说,比较简单的类型,如字符串或简单表达式最好采用属性来传递信息。 z H4#\d  
r{&"]'/X  
aX:$Q }S  
定义脚本变量的tag标签 `q*ABsj  
nzDY!Y  
所谓脚本变量,是指JSP中可以调用的变量或对象。它可由tag标签产生。以下示例阐述了一个tag标签定义了一个名为tx的由JNDI所定义的事务处理对象。脚本变量可以是ejb对象、事务、数据库连接等等: IW*.B6Hw8  
NebZGD2K  
<tt:lookup id=”tx” type=”UserTransaction” name=”java:comp/UserTransaction” /> {4*%\?c,n  
=Ybu_>  
<% tx.begin(); %> 3|3lUU\I  
e0 EJ[bG  
... +N:%`9}2V  
Mq$=zsj  
;Yj&7k1  
具有协作关系的tag标签 Pw{+7b$  
,_O[; L  
自定义tag标签之间可以通过共享对象来实现协作。在下述例子中,标签tag1创建了一个名为obj1的对象,在标签tag2仍可以重复使用obj。 w+H=Xh4t  
[%:NR  
<tt:tag1 attr1=”obj1” value1=”value” /> <'33!8 G  
-XB>&dNl)T  
<tt:tag2 attr1=”obj1” /> H\vO0 <X  
K2Zy6lGOZ  
在以下这个例子当中,如果外层的tag标签创建了一个对象,那么其内层的所有tag标签都可以使用这个对象。由于这样产生的对象没有一个指定的名字,那么就可以将少重名的冲突。这个例子阐述了一系列协作的嵌套对象。 } q(0uzaG  
_Qas+8NW  
<tt:outerTag> ,55`s#;  
s#3{c@^3  
<tt:innerTag /> o 8U2vMH  
&5<lQ1  
</tt:outerTag> $4pW#4/4  
3WS % H17  
Ja1*a,],L  
Tag处理类 B%/Pn 2  
!$HWUxM;p  
MiRB*eA  
Tag处理类必须实现Tag接口或BodyTag接口,不过现在一般都流行从TagSupport或BodyTagSupport类中继承,这些类或接口都可以在javax.servlet.jsp.tagext包中找到。 D![Twlll  
P@#6.Bb#V  
当JSP引擎看到自己的JSP页面中包含有tag标签时,它会调用doStartTag方法来处理tag标签的开头,调用doEndTag方法来处理tag标签的结束。 wwz<c5  
\ZB;K~BV&  
下表说明不同类型的tag所需要不同的处理过程: I(4k{=\ph]  
P.0-(  
Tag处理类的方法 Mtr~d  
rYJvI  
Tag标签类型 NR5A"_'  
所调用的方法 ^ 9i^Ci9  
[nrP; _  
基本标签 I$&/?ns@O  
doStartTag, doEndTag, release N>_7Ltw/  
Z:Wix|,ONS  
带属性的标签 ~A)$="  
doStartTag, doEndTag, set/getAttribute1...N, release kH'Cx^=c6h  
NKRXY~zHh  
带内容的标签 -#r_9HQ,w  
doStartTag, doEndTag, release G+}LLm.wX  
F-6* BUqJ  
带内容的标签,且内容重复循环 zV]0S o  
doStartTag, doAfterBody, doEndTag, release k)J7) L  
 O>3'ylBQ  
带内容的标签,且内容与JSP交互 >cp9{+#f  
doStartTag, doEndTag, release, doInitBody, doAfterBody, release 1Sy#*  
_rM%N+$&d_  
一个tag处理类可以通过javax.servlet.jsp.PageContext来与JSP交互,通过javax.servlet.jsp.PageContext类,tag处理类可以访问JSP中的request、session和application对像。 DuWP)#kg  
P|?z1JUd  
如果tag标签是互相嵌套的,那内层的tag处理类可以通过它的parent属性来访问上层的tag处理类。 e0TnA N  
{2nXItso  
一般情况都将所有的tag处理类打成了JAR的包,以便于发布。 g 0L 4  
]k Pco4  
z(ajR*\#  
Tag库描述(简称TLD) (R, eWWF8~  
"~ /3  
hug12Cu  
Tag库是用xml语言描述的,TLD包括了tag库中所有tag标签的描述,它一般用来被jsp服务器用来校验tag的语法正确性,或者被jsp开发者用来开发新的标签。 gOkO8P6P8  
VYwaU^  
TLD的文件扩展名必须为.tld,而且必须放在当前WEB应用的WEB-INF目录或其子目录中。 YW5E |z  
+%yh@X6  
一个TLD的内容的开头必须遵守标准的XML开头,用于描述DTD和xml的版本,例如: Z`W.(gua  
5IepVS(>?v  
<?xml version="1.0" encoding="ISO-8859-1" ?> .q=X58tHu  
}yw\+fc  
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd"> } 8svd#S+  
TLD必须以<taglib>来作为它的根元素,<taglib>的子元素如下表: 'D4NPG`z  
,uw &)A  
G`n-WP  
<taglib>的子元素 L=$P  
Z_;' r|c  
Element |!|`Je3 K  
Description I9MI}0}7  
@EQ{lGpU3  
tlib-version 9we=aX5  
Tag库的版本 MLDuo|?  
wK3}K  
jsp-version h3:,Gbyap  
Tag库所需要的jsp的版本 #Ky0` n  
VKlD"UTk  
short-name ^\!^#rO  
助记符,tag的一个别名(可选) )*uI/E  
Mk?9`?g.  
uri 4e:hKv,+4  
用于确定一个唯一的tag库 6B 8!2  
A;g[G>J  
display-name >[p+L='  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) 8dpVB#]pp,  
>A)he!I  
small-icon emHi= [!i  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) HG^8&uh]  
V6!oe^a7'  
large-icon bUBuJ  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) +,%x&L&I  
D Lu]d$G  
description V}(%2W5X+  
对tag库的描述(可选) YONg1.^!(  
u66w('2  
listener J:>TV.TP  
参见下面listener元素 G0^PnE0-  
?gkK*\x2  
tag rUyT5Vf  
参见下面tag 元素 X0lIeGwrQ  
w"D"9 G  
Listener元素 FrVD~;  
[)a,rrhj  
一个tag库可能定义一些类做为它的事件侦听类,这些类在TLD中被称为listener 元素,jsp服务器将会实例化这些侦听类,并且注册它们。Listener元素中有一个叫listener-class的子元素,这个元素的值必须是该侦听类的完整类名。 zJ\I%7h*  
A_g'9  
Tag元素 )TWf/L cp  
BG|Kw)z*KM  
每个tag元素在tag库中都要指出它的名字、类名、脚本变量、tag的属性。其中脚本变量的值可以直接在TLD中定义或通过tag附加信息的类来取得。每个属性描述了这个属性是否可以省略,它的值是否可以通过<%= …%>这样的JSP语法来获得,以及属性的类型。 t512]eqhb(  
w90y-^p%  
每一个tag在TLD中对应一个tag元素,下表是tag元素的子元素: ^!}lA9\gY  
> 1r>cZn  
Tag元素的子元素 Fb_~{q  
<sPB|5Ak  
元素名称 I5e!vCG)  
描述 Mn=_lhW K  
fN&O `T>  
name 9|go`^*.  
独一无二的元素名 -wO`o<  
TKmC/c  
tag-class fpzTv3D=I  
Tag标签对应的tag处理类 _Q7)FK  
{ u;ntDr  
tei-class R% ddB D\?  
javax.servlet.jsp.tagext.TagExtraInfo的子类,用于表达脚本变量(可选) f5O*Njl  
"z qt'b0bW  
body-content `aC#s3[  
Tag标签body的类型 VA]%i P,O-  
kt@+UK."  
display-name #)\KV7f! ;  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) ";GLX%C!{@  
Y!SD^Ie7!  
small-icon aC:rrS  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) 5Po.&eS  
\h"s[G zq  
large-icon s*S@} l  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) F'Wef11Yz  
h[ t OY  
description Z,!Rj7wZ  
此tag标签的描述 d+/d)cu  
v7g-M  
variable Sd{>(YWx~  
提供脚本变量的信息(同tei-class)(可选) Y#Hf\8r,d  
ov|s5yH8e  
attribute D7=gUm >  
Tag标签的属性名 :@pm gp  
~#g Vs*K  
以下章节介绍对于不同类型的tag,如何具体地实现它们。 te:@F]A  
ArF+9upGY  
]A_)&`"Cb  
简单的tag XX/cJp  
[jafPi(#g  
YWm:#{n.  
tag处理类 LEk W^Mv  
Qx {/izc  
简单的tag处理类必须实现Tag接口的doStartTag和doEndTag方法。当jsp引擎碰到tag标签的开头时,doStartTag被调用,因为简单的tag没有body,所以此方法将返回 SKIP_BODY。当jsp引擎碰到tag标签的结尾时,doEndTag被调用,如果余下的页面还要被计算,那它将返回EVAL_PAGE,否则将会返回SKIP_PAGE。 D F0~A  
b7=]"|c$@  
以下是例子:对于标签 <tt:simple /> ,它的tag处理类实现如下: K}Aaflq  
'a4xi0**I  
m+1MoeR  
public SimpleTag extends TagSupport >bmL;)mc&  
SA}]ZK P  
{ z<)?8tAgq  
==c\* o  
public int doStartTag() throws JspException 2p@S-Lp  
|JrG?:n  
{ @!K)(B;A0b  
u YJ6 "j  
try{ QHA<7Wg  
i1  
pageContext.getOut().print(“Hello.”); YsDn?pD@  
]2tX'=X  
}catch(Exception e){ {GZHD^Ce  
U+nwLxe'  
throw new JspTagException(“SimpleTag: “ + e.getMessage()); b PiJCX0d  
(3 B; V  
} fNQ.FAK":  
?e yo2:-$  
return SKIP_BODY; -<qci3Ba}  
M]eH JZ~v  
} $UKV2c  
ba|~B8rII[  
public int doEndTag() ;Q-(tGd  
R$NH [Tz  
{ O+c@B}[!  
HlLF<k~}  
return EVAL_PAGE; K+PzTGWq^  
F@&q4whaVD  
} ~M+|g4W%  
T|r@:t[  
} R )ejIKtY  
HuCH`|v-  
G+=&\+{#4  
注意:如果tag标签没有内容的话,那必须定义body-content元素为空,例如 7*uG9iX  
&QLCij5:  
<body-content>empty</body-content> 7G!SlC X}W  
IZniRd;  
_q M'm^z5  
带属性的tag标签
评价一下你浏览此帖子的感受

精彩

感动

搞笑

开心

愤怒

无聊

灌水
级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
只看该作者 1 发表于: 2007-01-01
tag处理类 n-}.Yc  
'P39^rb  
对于tag标签的每个属性,你必须依照JavaBeans规范来定义其属性,以及get和set方法。以struts的logic:present 标签为例, ~`u?|+*BO  
e*:[#LJ]C  
<logic:present parameter=”Clear”> :$j!e#?=  
0q>f x  
与此相应,此tag处理类应有如下方法和定义: "-90:"W  
v5RS<?o  
7f~DD8R  
protected String parameter = null; ;M>0,  
UdT ~ h  
public String getParameter() &7XB $  
cg}46)^<QH  
{ `LVXK|m+$  
:~{XL>:S  
return this.parameter; *Iyv${  
#sq-V,8  
} f @Hp,-  
M%1-fd  
public void setParameter(String parameter) !D7 [R'RgY  
/Vg R[  
{ 4ehajK  
x{&0:|bCs6  
this.parameter = parameter; -P!vCf^{ t  
Bz }Kdyur  
} JU1U=Lu."  
jgVra*   
Xa Yx avq  
注意:如果你的属性名为id,而且你的tag处理类是从TagSupport类继承的,那你就不需要定义它的属性和set和get方法,因为他们早已在TagSupport被定义过了。 \V+$2 :A  
Z"mpE+U*  
Attribute元素 U^snb6\5  
VQ$=F8ivG  
对于tag标签的每个属性,你必须定义它是否必须的,它的值是否可以用诸如<%= …%>的表达式来获得,以及它的类型(可选),如果不指定它的类型,那就默认为是java.lang.String类型。如果rtexprvalue元素被定义为true或yes,那么在type元素中就定义了attribute的返回类型。 @$F(({?  
OHR9u  
<attribute> _C)u#]t  
ZL+{?1&-  
<name>attr1</name> gOx4qxy/m|  
LrsP4G  
<required>true|false|yes|no</required> Z=L' [6  
:2 n5;fp  
<rtexprvalue>true|false|yes|no</rtexprvalue> .1t$(]CyC  
BT2[@qH|qF  
<type>attribute的返回类型(只用当rtexprvalue为真是才有效)</type> EJNj.c-#  
T=ox;r  
</attribute> OV;Ho  
CDO _A\  
如果tag的某个属性不是必须的,那tag处理类会自动提供一个缺省值。 k(3 s^B  
v7\~OOoH]  
例如,在logic:present这个tag标签中定义了一个属性叫parameter,但它不是必须的,而且它可以被诸如<%= …%>的表达式来赋值。 QtW5; A-h  
K}1>n2P  
<tag> ~g;(` g  
S2*-UluG  
<name>present</name> s<sqO,!  
TEE$1RxV(  
<tag-class>org.apache.struts.taglib.logic.PresentTag</tag-class> |/]bpG'z  
RIC'JLWQ  
<body-content>JSP</body-content> +G7A.d`V}  
V}'|a<8kVv  
/:z}WAW  
+7sdQCO(Co  
<attribute> [A yq%MA  
b0rC\^x  
<name>parameter</name> }zlvs a+  
cJ&l86/l1  
<required>false</required> $kZ,uvKN  
R 7xV{o  
<rtexprvalue>true</rtexprvalue> SdnqM`uFo  
deda=%w0  
</attribute> Y xGIv8O]  
*xkbKkm  
v)%EG  
=uKK{\+|Y  
</tag> E-E+/.A  
FnvN 4h{S  
S]K^wj[  
属性元素的校验 FOquQr1cF  
Mf%/t HK  
yJ/m21f  
有关于tag标签的有效值可以从tag库的说明文档中获得,当JSP页面被编译时,jsp引擎会强制性地参照TLD中定义的规则进行检查。 (x&#>5  
A}t.`FLP,j  
还有一个方法也可以进行属性元素的校验,就是先继承类TagExtraInfo,然后调用它的isValid方法。这个类同时也起到提供tag中定义的脚本变量信息的作用。 <*8nv.PX*  
0 m";=:(w  
IsValid方法通过TagData对象来传递属性信息,它包括着tag的所有的属性名-值的信息。由于校验发生在运行时刻,因此这个属性的值将被赋值为TagData.REQUEST_TIME_VALUE。 Nr:%oD_G*  
v~L} :  
例如tag标签<tt:twa attr1=”value1” />在TLD中定义如下: O<L /m[]  
"h2;65@  
<attribute> |>j=#2  
[0m'a\YE9  
<name>attr1</name> tN3Xn]   
dm8veKW'l  
<required>true</required> jMW|B  
#y-OkGS ^  
<rtexprvalue>true</rtexprvalue> unSF;S<  
0b?9LFd  
</attribute> ;=_<\2  
KD-0NO=oL  
sFC1PdSk4T  
这个定义说明了attr1能在运行期间被赋值。 &7E0H{  
K*7*`6iU  
以下的isValid方法检查attr1属性的值是否属于Boolean类型。注意由于attr1能在运行刻被赋值,那么isValid方法必须检查tag用户是否对此tag进行了运行时刻赋值。 rya4sxCh  
T_5 E  
Wj8\~B=('  
Public class TwaTEI extends TagExtraInfo 4w2V["?X1  
x03GJy5  
{ >+#TsX{  
P)(Ly5$*  
public boolean isValid(Tagdata data) F] M3/M  
C UlANd"  
{ V [[B~Rs  
:3Ty%W&&  
Object o = data.getAttribute(“attr1”); hYb!RRGn  
cMC1|3  
If(o != null && o != TagData.REQUEST_TIME_VALUE) %+o]1R  
r>$jMo.S"  
{ n)$ q*IN"  
:L*CL 8m  
if( ( (String)o).toLowerCase().equals(“true”) || e] **Z,Z  
zh*NRN  
((String)o).toLowerCase().equals(“false”) ) BIw9@.99B-  
2=["jP!B  
return true; M?)>, !Z)  
;2#7"a^  
else BCsW03sQ  
bL swq  
return false; EBK\.[  
FIC 2)  
} Zt[ P kBi  
+SUQRDF@i  
else u'Mq^8  
D' uzH|z8  
return true; M ;\K+,  
f{* G%  
} n+Fl|4  
#G)ZhgB^  
} %S$P+B?  
MJ}VNv|S  
NBUM* Z  
带body的tag OM}:1He  
0DS<(  
MttVgNV  
tag处理类 =]Qu"nRB  
ro^Y$;G  
q SCt= eQ  
如果tag标签含有内容,那处理方式会略微有些不同,而且还要视tag处理类是否要与body交互的情况而定。如果要与body交互,那我们认为tag处理类要可能要对body进行操作。 "z@q G]#5  
olK%TM[Y  
Tag处理类不与body交互 N9,n/t  
KY2xKco  
如果tag处理类不与body交互,tag处理类应该实现Tag接口或从TagSupport中派生,如果body要被计算,那么doStartTag方法应返回 EVAL_BODY_INCLUDE,否则应返回SKIP_BODY。 ug UV`5w   
 <&$!;d8  
如果tag处理类要对body反复运算,则它应该实现IterationTag或从TagSupport中派生。如果tag处理类认为body还未计算完的话,那它的doStartTag方法和doAfterBody方法必须返回EVAL_BODY_AGAIN。 7th&C,c&  
O3Ks|%1  
Tag处理类与body交互 15Yy&9D  
")x9A&p  
如果tag处理类与body交互,那tag处理类应实现BodyTag接口或从BodyTagSupport中派生。这种tag处理类一般要实现doInitBody和doAfterBody方法。 ]%shs  
}tc,3> /  
Body允许一些方法来读写它的内容。Tag处理类可以调用body内容的getString或getReader方法来从body中提取信息,也可用 writeOut(out) 方法来将body的内容写入到out对象中。其中out对象通过tag处理类的getPreviousOut方法来获得。 [S3X  
Bv3?WW  
如果body的内容需要被计算,那么doStartTag方法必须返回EVAL_BODY_BUFFERED,否则,它将返回 SKIP_BODY。 gt}/C4|  
*$(9,y\  
doInitBody 方法 G} }oeS  
IE'OK  
此方法在body内容已经设好,但未被计算之前被调用。你可以根据不同的body内容来制定初始化策略。 ^t9"!K  
F4">go  
doAfterBody方法 #t3j u^ |?  
8.]dThaq  
此方法在body内容已被计算后进行调用。 7&m*: J  
}IEYH&4!  
和doStartTag方法一样,doAfterBody方法返回一个指示符指示是否要继续计算body,如果要继续计算,则doAfterBody应返回EVAL_BODY_BUFFERED,否则,它应返回SKIP_BODY。 aViJ?*  
w7w$z _P  
release 方法 <J?i+b  
uop_bJ  
tag处理类调用此方法将它的状态重置为初始状态,并释放所有的私有资源。 Ha4?I$'$  
0+cRUH9Ew  
7m@pdq5Ub  
以下的例子读取body的内容(其中含有一条sql语句),然后将它传递给一个对象,让它进行查询。由于此处body不须重新计算,所以doAfterBody会返回SKIP_BODY。 |Q.?<T:wt=  
 :jB(!XH  
 ,ulTZV  
Public class QueryTag extends BodyTagSupport `^ F'af  
t-_N|iW' 5  
{ bF?EuL  
bpKMQrwd  
public int doAfterBody() throws JspTagException J"FKd3~:E  
^>[DG]g  
{ !=q {1\#  
KJcdX9x  
BodyContent bc = getBodyContent(); HHa7Kh|-H  
^ /:]HG  
//将body的内容以字符串的格式提取出来 <~X=6  
^vsOlA(4  
String query = bc.getString(); o.}^6.h"  
U{eC^yjt"o  
//清除body klJDYFX=HK  
LF*3Iw|v  
bc.clearBody(); >\(Ma3S   
z9;vE7n!  
try{ +`.%aJIi9  
sOU_j4M{  
Statement stmt = connection.createStatement(); 4ol=YGCI_  
@RbAC*Y]g  
Result result = stmt.executeQuery(query); 2tn%/gf'm  
XD%?'uUQ_  
}catch(SQLException e){ e0>@Yp[Kd  
gEU)UIJ  
throw new JspTagException(“queryTag: “ + e.getMessage() ); ;@v7AF6Hq  
C'7W50b  
return SKIP_BODY; ?vf\_R'M  
,FS iE\  
} '>'h7F=tY  
d'Gv\i&e  
} U|U/B  
$_)YrqSo~  
xH3SVn(I  
body-content元素 X]  Tb4  
V! "^6)  
B;W=61d  
由于tag可能会有body,你必须用body-content元素来指定body内容的类型: kFD-  
!jYV,:'  
<body-content>JSP|tagdependent</body-content> fp12-Hk ~  
-b)p6>G-C  
y~ ^>my7G  
如果body的内容是定制的或内部的tag、脚本元素、或HTML广本,则归类为JSP类型。其他的类型,比如上面代码所述的?D?D将sql statement类传给 query tag的这种类型应该标为tagdependent。 p c-'+7Dh>  
zS?i@e $  
注意:实际上body-content的值并不影响tag处理类对body内容的处理,它仅仅是被tag编辑工具用来描述此body的内容。 -cq ~\m^6  
)S8q.h  
iP' }eQn]c  
用tags定义脚本变量 NSb< 7_L  
*xL#1  
EY2s${26%  
tag处理类 >]C;sP  
5\QNGRu"  
 tEP^w  
tag处理类负责创建或设置页面中定义的脚本变量,用pageContext.setAttribute(name,value,scope)或pageContext.setAttribute(name,value)方法来实现。一般来说,tag处理类通过脚本变量的名称来获取它,脚本变量的名称一般可用get方法来获得。 ?7a< V+V:  
"lN<v=  
如果脚本变量的值依赖于tag处理类中的上下文中某一对象,那它可用pageContext.getAttribute(name,scope)方法来找到那个对象。一般的处理过程是tag处理类先找到脚本变量,再对其进行处理,然后用pageContext.setAttribute(name,object)的方法来设置它的新值。 .fD k5uo  
?]h+En5z8  
对象的生存周期(scope)如下表: i1aS2gFi_  
:nZ*x=aq  
对象的生存周期表 pR\etXeLd  
s/ZOA[Yux  
名字 Y>%A*|U%  
可访问范围 rR C3^X`u  
生存周期 =WDf [?ED  
@X\nY</E#M  
page 6{+~B2Ef  
当前页面 JZP2NB_xt  
一直有效,除非页面向客户提交响应或重定向到一个新页面 y)(SS8JR  
kN>d5q9b%X  
request rt~X (S  
当前页面或当前页面重定向到的页面 3_Oq4/  
一直有效,除非页面向客户提交响应 xYwbbFGrG  
Aoa0czC~  
session Eda sGCo  
当前页面或在同一浏览器窗口中的页面 T<!`~#kM  
一直有效,除非关闭当前浏览器、超时、网络故障 gVq{g,yi  
70KXBu<6  
application t.knYO)  
整个web应用程序的所有请求 ?hDEFW9&^x  
一直有效,除非发生网络故障、服务器故障 aty K^*aX  
dc lJ  
提供关于脚本变量的信息 NPS=?5p>  
%FyB\IQ  
以下示例定义了一个名为“book”的脚本变量,用来访问程序中关于书的信息: z': >nw  
]7xAL7x  
<bean:define id=”book” name=”bookDB” property=”bookDetails” type=”database.BookDetails” /> _B W$?:)9  
AvV.faa  
<font color=”red” size=”+2” > OpH9sBnA  
C<n.C*o  
<%= messages.getString(“CartRemoved”) %> Wg}#{[4  
7Uj[0Awn  
<strong><jsp:getProperty name=”book” property=”title” /></strong> 3:=XU9p)x  
_=}Y lR  
</font> 9sT?"(=  
Nw|Lrn*h!  
当包含此tag的JSP页面被编译时,jsp引擎会自动生成关于此book的同步的代码(同步可以避免几个客户同时访问此book时造成的冲突),要生成同步代码,jsp引擎需要知道此脚本变量的如下信息: +9h6{&yr1  
%FF  S&vd  
· 脚本变量名称 pr;L~$JW  
eY&UFe  
· 脚本变量所属的类 K7_)!=DcX  
/H3,v8J@  
· 此脚本变量是否引用了一个新的或已存在的对象 ff:&MsA|,  
4|:{apH  
· 此脚本变量的有效性 >StvP=our  
;'<K}h  
有两种办法可以向jsp引擎提供关于脚本变量的信息:在TLD中定义variable子元素,或用tei-class子元素定义一个额外tag信息类。用variable最简单,但可能降低了一些灵活性。 ,#"AWQ  
/pyKTZ|  
Variable元素 VVe>}  
I1}{7-_t  
Variable元素有如下子元素: {1SxM /  
 &`@Jy|N\  
· name-given ?D?D 给出的名字,是一个常量 LRbevpZ,  
a .] !  
· name-from-attribute?D?D 属性名,在编译时给出的属性名 gE$dz#t.  
iK.MC%8?  
name-given或name-from-attribute两者必须选一,但以下子元素是可选的: IGB>8$7  
@nZFw.  
· variable-class?D?D变量的类型,缺省为java.lang.String。 a7d782~  
W)9KYI9u  
· declare?D?D此脚本变量是否引用了一个新对象,缺省为True。 :'rXu6c-  
n%?g+@y,^  
· scope?D?D脚本变量的范围,缺省为NESTED。下表描述了scope的几种类型: U}qW9X;o  
L50`,,WF  
脚本变量的有效范围 Hh qx)u  
%9zcc)cP  
Ak9W8Z}  
有效性 -}N{'S,Bp  
方法 h1Q7(8=Eg  
^qk$W? pX  
NESTED [M;P:@  
在tag标签的开始和结束之间 Ar):D#D  
如果tag处理类实现BodyTag接口,则在doInitBody和doAfterBody中调用,否则在doStartTag中调用 >?tcL *  
Vy5Q+gw  
AT_BEGIN mS );bs  
从tag标签的开始一直到页面结束 0` S!+d  
如果tag处理类实现BodyTag接口,则在doInitBody、doAfterBody和doEndTag中调用,否则在doStartTag和doEndTag中调用 p@Qzg /X  
<4! w2vxG  
AT_END \?C(fp R  
从tag标签的结束一直到页面结束 m|-O/6~  
在doEndTag中调用 {Qhv HV  
@*c+`5)_  
以struts为例,它的bean:define标签的实现遵循JSP1.1规范,此规范要求使用额外tag信息类来定义脚本变量。Variable元素是JSP1.2规范中加入的。以bean:define标签为例,你可以定义如下variable元素: O&O1O> [p1  
5-C6;7%:  
<tag> klx4Mvq+/@  
F\]rxl4(L  
<variable> Ia(A&Za  
WUHx0I  
<name-from-attribute>id</name-from-attribute> %WO;WxG8^  
kKjYMYT6  
<variable-class>database.BookDetails</variable-class> 1fC|_V(0  
FF/MTd}6qG  
<declare>true</declare> f?{Y<M~]  
@lmke>  
<scope>AT_BEGIN</scope> rSZWmns  
]-AT(L >  
</variable> 9:kb0oBa?l  
=W4cWG?+  
</tag> $ &^ ,(z9  
dyx 4_!fO  
额外tag信息类 >Ek `PVPD  
^|x{E20  
如果要定义一个额外tag信息类,你要继承javax.servlet.jsp.TagExtraInfo类。一个TagExtraInfo类必须实现getVariableInfo方法,此方法返回一个叫VariableInfo的数组类,它包括如下信息: <<A@69"4n  
ZPMEN,Dw  
· 变量名 IBuuZ.=j2h  
*3k~%RM%?  
· 变量所属类名 Al` ;SWN  
A] F K\  
· 此变量是否引用了一个新对象 W5x]bl#  
jAJkCCG  
· 此变量的有效范围 fe Q%L  
=_UPZ]  
jsp引擎将一个名为data的参数传给getVariableInfo方法,data中包括tag标签中的所有“属性名?D?D属性值”对。它可以用来向VariableInfo对象提供脚本变量的名字和类名。 ;0BCM(>Wo  
|FNP~5v  
以struts为例,它在bean:define标签中定义了一个名为DefineTei的额外tag信息类,用来向脚本变量提供信息。由于脚本变量的名称(book)和类名(database.BookDetails)是通过tag标签的属性来传递的,它们一般定义在VariableInfo的构建代码中,并且可用data.getAttributeString方法来得到这些信息。如果要允许book脚本变量能在从tag开始直到整个JSP页面结束的范围内都可用的话,那它的范围应设为AT_BEGIN。如下所示: `#(4K4]1.  
$rlIJwqn  
kPxEGuL'  
public class DefineTei extends TagExtraInfo !BY=HFT  
J[B8sa  
{ My[L3KTTp  
59ivL6=3  
public VariableInfo[] getVariableInfo(TagData data) F0|T%!FB>%  
xp39TiXJ*  
{ V]<dh|x  
w5[POo' 5  
String type = data.getAttributeString(“type”); j[z\p~^  
%_ z]iz4  
If( type == null) te:VYP  
@&~BGh  
type = “java.lang.Object”; \l[5U3{  
U "}Kth  
return new VariableInfo[] { S\f^y8*<  
: i(h[0  
new VariableInfo(data.getAttributeString(“id”), BHU[Rz7x  
{:rU5 !n  
type, E+01"G<Q  
$b8>SSz  
true, ypsCyDQK`  
Gm|QOuw  
VariableInfo.AT_BEGIN) i|=XW6J%  
F{}z[0  
}; &zm5s*yNt  
0? l  
} >!oN+8[~  
nyDqR#t  
} 9~4Kbmr>q  
zxj!ihs<  
=B/^c>w2  
注意:关于额外tag信息类的类名必须要在TLD中的tag标签下的tei-class子元素中定义。因此,DefineTei的tei-class中的定义看起来如下: [oYe/<3  
<tei-class> %%f=aPw  
org.apache.struts.taglib.bean.DefineTagTei bc 0|tJc  
</tei-class> #{]=>n)j  
O ,DX%wk,  
M 35}5+  
具有协作关系的tag 8C YJR/  
- -]\z*x  
n =v %}@f2  
tag通过共享对象来进行协作,JSP技术支持2种方式的对象共享。 e;gf??8}  
Onk~1ks:  
第一种方法是使用pageContext对象进行对象的共享(可支持JSP页面和tag处理类之间的共享),如果在一个tag处理类中要调用由另一个tag处理类创建的对象,可调用pageContext.getAttribute(name, scope)方法。 !"1bV [^  
kQ:2@SOm  
第二各方式的共享是对于tag之间有嵌套关系而言的,外层的tag所创建的对象对于内层的tag来说是可以共用的。这种形式的共享的好处是减少了可能存在的重名冲突。 !Q?4sAB  
cJty4m-  
要访问一个嵌套tag创建的对象,tag处理类必须先找到此嵌套tag对象,可用TagSupport的静态方法 TagSupport.findAncestorWithClass(from, class)或TagSupport.getParent方法。前者在当不确定此tag是否为嵌套tag对象时使用。一旦它的父类被找到,它就能访问其所有动态或静态创建的对象。静态创建的对象是父类的成员,而动态创建的对象可能是父类的私有对象。诸如此类的对象可以用tag处理类的setValue方法来保存,用getValue方法来获得。 7'<4'BGzl]  
`&+ L/  
下例阐述了以上两种共享对象的方法。在这个例子当中,一个查询tag检查一个名为connection的属性名是否在doStartTag中被设置。如果connection属性被设置,tag处理类从pageContext中得到这个connection对象。否则,此tag处理类先找到它的父tag处理类,然后从它的父tag处理类中找到connection对象。 :q= XE$%H  
'fgDe  
} K Ou  
public class QueryTag extends BodyTagSupport E O}(MXS  
RJ-CWt [LG  
{ G{s ,Y^  
)WzCUYE1/  
private String connectionId; 8G@FX $$Q  
Tq?W @DM*  
public int doStartTag() throws JspException +6>Pp[%  
)45,~+XX  
{ T xN5K`q  
O35f5Kz  
String cid = getConnection(); ]>:>":<:  
\myc n/e  
if(cid != null) B 51LZP  
bb<Vh2b>R  
{ )-sEm`(`I9  
U%#=d@?  
//存在一个connection id,使用它。 Pgo5&SQb  
!7w-?1?D  
connection = (Connection) pageContext.getAttribute(cid); oL~Yrb%R  
(g;Ff`P Pc  
} >B9rr0d0  
vuK 5DG4  
else <.AIV p  
]A\n>Z!;  
{ !P;qc  
y3xP~]n  
ConnectionTag ancestorTag = (ConnectionTag)findAncestorWithClass(this, FJD*A`a  
71 2i |  
ConnectionTag.class); $~2A o[  
4gZN~_AI<  
if(ancestorTag == null) $X{& KLM[  
f]hW>-B(q  
{ J d`NS3;*p  
6$z UFIk  
throw new JspTagException(“一个没有connection属性的查询标签必须被一个connection标记嵌套。”); D?E5p.!A  
MRa>@Jn??A  
} ="4jk=on  
hIw*dob  
connection = ancestorTag.getConnection(); F%Xq}LMd  
VP"L _Um  
} \GkcK$Y  
9DT}sCLz:B  
} c]O4l2nCL  
kn<[v;+  
} .h6h&[TEU  
M\GS&K$lq  
ePF9Vzq  
HS2)vd@)  
此查询标签在JSP页面中的调用形式可以从以下2种定义中任选一种: /RMep8 &  
`aUA_"f  
#(A>yW702  
<tt:connection id=”con01” ...> ... </tt:connection> 2{qoWys8[  
Gh< r_O~L3  
<tt:query id=”balances” connection=”con01” > Q'rG' |  
h?SUDk:2^  
SELECT account, balance FROM acct_table UR\*KR;yM  
`zvYuKQ.}  
where customer_num = <%= request.getCustno() %> 5H5< ft,  
aR3W9  
</tt:query> 's9)\LS>p  
F!Uk`[L  
6Y=$7%z  
|5W u0T  
+yYz;, \  
<tt:connection ...> -W oZwqh  
)S5Q5"j&=f  
<x:query id=”balances”> Kg%_e9nj#  
YS/DIH{9e  
SELECT account, balance FROM acct_table phNv^R+  
^,rbA>/L  
where customer_num = <%= request.getCustno() %> U"ZDt  
y)=Xo7j  
</x:query> hxv/285B  
0>AA-~=-  
</tt:connection> '91Ak,cWB  
5ecqJ  
uYs+x X_  
与此同时,在TLD中必须指定connection属性为可选的,定义如下: X2EC+<  
jbG #__#_  
<tag> Xf.SJ8G  
.<tb*6rX>  
... z,^baU  
;Neld #%J  
<attribute> P>)qN,a  
J0{0B=d;  
<name>connection</name> yYW>)  
tW 9vo-{+  
<required>false</required> K)&AR*Tc  
O* 7" Q&  
</attribute> +.zriiF]i  
p! Hpq W  
</tag>
描述
快速回复

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