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

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

级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
标准的JSP 标记可以调用JavaBeans组件或者执行客户的请求,这大大降低了JSP开发的复杂度和维护量。JSP技术也允许你自定义taglib,其实换句话说,taglib可以看成是对JSP标记的一种扩展,正如xml是对html的一种扩展一样。taglib通常定义在tag标签库中,这种标签库存放着你自己定义的tag标签。简而言之,如果使用taglib,那么你可以设计自己的JSP标记! %jY /jp=R  
hb"t8_--c  
一般来说,自定义tag标签主要用于操作隐藏对象、处理html提交表单、访问数据库或其它企业级的服务,诸如邮件和目录操作等等。自定义tag标签的使用者一般都是那些对java编程语言非常精通,而且对数据访问和企业级服务访问都非常熟悉的程序员,对于HTML设计者来说,使得他可以不去关注那些较复杂的商业逻辑,而将精力放在网页设计上。同时,它也将库开发者和库使用者进行合理分工,自定义tag标签将那些重复工作进行封装,从而大大提高了生产力,而且可以使得tag库可用于不同的项目中,完美地体现了软件复用的思想。 sgo({zA`i  
'Z+~G  
在这篇文章中,我们主要讨论: z2&SZ.mk  
+?~'K&@  
· 什么是自定义tag标签? u4=j!Zb8}  
|wZ8O}O{E  
· 怎么使用tag标签? F}A@H<?  
Yo c N@s  
o 声明要使用的tag库 #s1O(rLRl  
vvLm9Tw  
o 找到与之对应的tag处理类 Poacd;*  
rs3Uk.Z^ '  
o tag标签的类型 M? oK@i  
tqE LF  
· 自定义tag标签 .Mw'P\GtM  
b$nXljV4?  
o tag处理类 i=-zaboo  
4XDR?KUM  
o tag库描述 k|,pj^  
F+_4Q  
o tag标签示例 PqIGc  
QH6Lb%]/  
o 带属性的tag 85l 1  
Pt?]JJxl-  
o 带body的tag ]S[zD|U%  
Zg|z\VR  
o 定义了脚本变量的tag !=#E/il,  
3C8'0DB  
o 具有协作关系的tag /b20!3  
glh2CRUj  
· 自定义tag标签 "';'*x  
zqqpBwk#  
o 一个迭代tag的例子 5,'?NEyw  
1<^"OjQ  
o 一个模板tag库 /J8AnA1  
86~HkHliv  
o tag处理类到底是怎样被调用的? jN V2o  
'z2}qJJ)  
W?G4\ubM3<  
什么是自定义的tag? abUn{X+f~  
l'VgS:NT  
一个自定义的tag标签是用户定义的一种JSP标记。当一个含有自定义的tag标签的JSP页面被jsp引擎编译成servlet时,tag标签被转化成了对一个称为tag处理类的对象进行的操作。于是当JSP页面被jsp引擎转化为servlet后,实际上tag标签被转化成为了对tag处理类的操作。 wYhWRgP  
y>u+.z a|  
自定义tag标签有很多特色,诸如: BUv;BzyV  
~ -Rr[O=E  
· 可以在JSP页面中自定义tag标签的属性 >/EmC3?b!  
_h7+.U=  
· 访问JSP页面中的所有对象 *"0Yr`)S  
,qpn4`zE~  
· 可以动态地修改页面输出 m~#S76!w  
'!Vn  
· 彼此这间可以相互通信。你可以先创建一个JavaBeans组件,然后在一个tag中调用此JavaBeans组件,同时可以在另一个tag中调用它。 BG"~yyKA  
Tn/T :7C  
· tag允许相互嵌套,可以在一个JSP页面中完成一些复杂的交互。 t-lWvxXe  
%$I\\q q>{  
Vf*!m~]Vqi  
使用tag标签 y%=\E  
+M (\R?@gr  
Fm{Ri=X<:  
本节主要描述怎样在JSP页面中使用tag标签,以及tag标签的不同类型。 <dDGV>n4;  
R 3 Eh47  
要使用tag标签,JSP程序员必须做2件事: =V_} z3b  
?};}#%971  
· 声明此tag标签的tag库 }+QgRGQ  
U n2xZ[4  
· 实现此tag标签 JTpKF_Za<  
=lS~2C  
声明tag标签所在的tag库 '+Dn~8Y+9  
FJv=5L  
如果要使用tag标签,则应用JSP的taglib指示符来指定其tag库(注意:taglib要在在使用此tag标签之前声明) &7T0nB/)  
n<kcK  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> t</rvAH E  
`Qv7aY  
uri属性定义了唯一的标签库描述(以下简称TLD),它可以是直接是tld文件名或一个独一无二的名字。prefix是用来区别其它TLD中和本TLD中有重名的tag的一种手段。 ? 8S0  
B>t$Z5Q^X  
TLD必须以.tld作为扩展名,并且存放在当前应用的WEB-INF目录或其子目录下。你可以通过它的文件名直接引用它,也可以通过别的方式间接地引用它。 <[?oP[ j  
9C$b^wHd  
以下taglib指示符直接引用一个TLD: d37l/I  
T%KZV/  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> ,|"tLN *m  
?y'KX]/  
以下的taglib指示符通过一个逻辑名称间接地引用一个TLD: ]}8<h5h)  
._-^ 58[  
<%@ taglib uri=”/tutorial-template” prefix=”tt” %> 2<yi8O\  
_C&2-tnp  
如果是间接引用TLD的话,那你必须还要在web.xml中定义此逻辑名称与tld文件之间的映射,具体做法是在web.xml中加入一个名为taglib的元素: Gk8"fs  
f$iv+7<B^  
<taglib> FsY}mql  
vX)JJ|g  
<taglib-uri>/tutorial-template</taglib-uri> 4/S 4bk*8  
q>%KIBh(  
<taglib-location> Yp./3b VO  
n%3rv?m7  
/WEB-INF/tutorial-template.tld /P5w}n  
a =*(>=  
</taglib-location> %z J)mOu  
AR]y p{NS  
</taglib> K&9|0xt  
*ZKI02M  
WHqp7NPl  
实现此tag标签 s,"<+80%  
Bra>C  
ly}6zOC\  
为了实现tag标签,你有2种方法来存放tag处理类。一、让tag处理类以.class的方式存放于当前应用的WEB-INF/class子目录下,二、如果tag处理类是以JAR包的形式存在的话,那可以放在当前应用的WEB-INF/lib目录下,如果tag处理类要在多个应用中共享,那么它就应放在jsp服务器上的common/lib目录下,对于tomcat来说,就是tomcat/common/lib目录下。 ?2%d;tW  
h5U@Ys  
fr;>`u[;  
tag标签类型 mgL~ $  
R?(0:f  
V? w;YTg  
自定义的tag标签遵循XML语法。它有一个开始标记和一个结束标记,有的还有body(即文本节点): 0V"r$7(}  
f`.8.1Rd  
<tt:tag> g6IG>)  
 VD;Ot<%  
body xpx=t71Hq  
pB&3JmgR$)  
</tt:tag> d `>M-:dF  
s-}|_g.Pt  
tlV>  
一个不带body的tag标签如下: 1%]| O  
A9Q!V01_  
<tt:tag /> Y _m4:9p  
xM8}Xo  
l{>fma]7  
简单的tag标签 $/Gvz)M  
Yew n  
一个没有body和属性的tag标签如下: [!]a' T#x  
A`T VV  
<tt:simple /> @HxEp;*NH"  
%2f``48#  
OKNA36cU'  
带属性的tag标签 {^i73}@O  
KiT>W~  
);_g2=:#  
自定义标签可以有自己的属性。属性一般在开始标记中定义,语法为 attr=”value”。属性的作用相当于自定义标签的一个参数,它影响着tag处理类的行为。你可以在TLD中详细定义它。 dFS>uIT7X  
gV$j ]  
你可以用一个String常量给一个属性赋值,也可以通过表达式给它赋值,如<%= ...%>。以struts为例,它的logic:present标签就是用的String常量来给属性赋值: L@HPU;<  
@*]l.F   
<loglic:present parameter = “Clear”>  U":hJ*F)  
8i!AJF9IQ}  
而另一个标签logic:iterate是用表达式来给属性赋值: :'91qA%Wr  
J0*hJ-/u  
<logci:iterate collection=”<%= bookDB.getBooks() %>” 9h> nP8  
Rq )&v*=  
id=”book” type=”database.BookDetails”> "+/%s#&  
n1m[7s.[&  
hEi]-N\X  
带body的tag标签 eqU2>bI f  
|iKk'Rta4  
一个自定义标签可以包含其它自定义标签、脚本变量、HTML标记或其它内容。 oG M Ls  
M$~3`n*^  
在下述例子中,此JSP页面使用了struts的logic:present标签,如果些标签定义了parameter=”Clear”的属性,则将清除购物车的内容,然后打印出一条信息: ^q5~;_z|  
!O6e,l  
<logic:present parameter=”Clear”> id<i|  
u~[HC)4(0  
<% cart.clear(); %> MGze IrV  
C,~wmS )@  
<font color=”#ff0000” size=”+2”><strong> $}V<U m  
fOJ 0#^Z  
你选择了清除购物车! {a^A-Xh[u  
k"D6Vyy`  
</strong></font> 0<_|K>5dS|  
lffp\v{w  
</logic:present> 2+zE|I.  
sd9$4k"  
[zv>Wlf,%  
到底是用属性还是用body来传递信息? vQ/}E@?u  
PLU8:H@X  
如上所述,我们既可以通过属性,也可以通过body来传递信息。但一般来说,比较简单的类型,如字符串或简单表达式最好采用属性来传递信息。 nlmc/1C  
1+6:K._C(m  
s7.2EkGl=  
定义脚本变量的tag标签 #<0Yx9Jh.  
,Tc3koi  
所谓脚本变量,是指JSP中可以调用的变量或对象。它可由tag标签产生。以下示例阐述了一个tag标签定义了一个名为tx的由JNDI所定义的事务处理对象。脚本变量可以是ejb对象、事务、数据库连接等等: 5OeTOI()&5  
)]WWx-Uf'  
<tt:lookup id=”tx” type=”UserTransaction” name=”java:comp/UserTransaction” /> `Fa49B|`D  
gwhd) .*  
<% tx.begin(); %> 28FC@&'H  
' QGacV   
... B?A c  
1{+x >Pv:  
g?N~mca$  
具有协作关系的tag标签 gw~ %jD-2  
bHVAa#  
自定义tag标签之间可以通过共享对象来实现协作。在下述例子中,标签tag1创建了一个名为obj1的对象,在标签tag2仍可以重复使用obj。 (uW/t1  
)*#Pp )Q  
<tt:tag1 attr1=”obj1” value1=”value” /> H,,-;tN?  
u$ [R>l9  
<tt:tag2 attr1=”obj1” /> +13h *  
MJNY#v3  
在以下这个例子当中,如果外层的tag标签创建了一个对象,那么其内层的所有tag标签都可以使用这个对象。由于这样产生的对象没有一个指定的名字,那么就可以将少重名的冲突。这个例子阐述了一系列协作的嵌套对象。 d]1%/$v^  
:K.%^ag=j  
<tt:outerTag>  R}Pw#*B  
[M>Md-pj  
<tt:innerTag /> QK _1!t3  
0q'd }DW  
</tt:outerTag> L[l ?}\  
uo0g51%9  
'f&o%5]  
Tag处理类 RrrW0<Ed  
y_O[r1MF  
5tPBTS<<"L  
Tag处理类必须实现Tag接口或BodyTag接口,不过现在一般都流行从TagSupport或BodyTagSupport类中继承,这些类或接口都可以在javax.servlet.jsp.tagext包中找到。 "hwg";Z$n  
f!6oW(r-L  
当JSP引擎看到自己的JSP页面中包含有tag标签时,它会调用doStartTag方法来处理tag标签的开头,调用doEndTag方法来处理tag标签的结束。 =|>CB  
Y<|!)JLB2  
下表说明不同类型的tag所需要不同的处理过程: S\fEV"  
)006\W|t9  
Tag处理类的方法 1Vq]4_09g1  
! |SPOk  
Tag标签类型 qu]ch&"?U  
所调用的方法 b`"E(S/  
I)#=#eI* :  
基本标签 iEx.BQ+  
doStartTag, doEndTag, release &:}e`u@5|  
v{{Cj83S+  
带属性的标签 L%](C  
doStartTag, doEndTag, set/getAttribute1...N, release u8ofgcFYE  
^0"^Xk*  
带内容的标签 Ow7NOhw  
doStartTag, doEndTag, release RC 7|@a  
+|}R^x`z  
带内容的标签,且内容重复循环 :g)0-gN   
doStartTag, doAfterBody, doEndTag, release g8^\|  
W>C!V  
带内容的标签,且内容与JSP交互 h(}$-'g  
doStartTag, doEndTag, release, doInitBody, doAfterBody, release dWHl<BUm  
)|;*[S4  
一个tag处理类可以通过javax.servlet.jsp.PageContext来与JSP交互,通过javax.servlet.jsp.PageContext类,tag处理类可以访问JSP中的request、session和application对像。 ` nBCCz'Y!  
`$og]Dn;  
如果tag标签是互相嵌套的,那内层的tag处理类可以通过它的parent属性来访问上层的tag处理类。 zNSix!F  
W: Rs 0O  
一般情况都将所有的tag处理类打成了JAR的包,以便于发布。 @L^Fz$Sx  
D|8vS8p  
m-f"EFmP  
Tag库描述(简称TLD) fR_ jYP 1  
GwiG..Y]&  
UeWEncN(  
Tag库是用xml语言描述的,TLD包括了tag库中所有tag标签的描述,它一般用来被jsp服务器用来校验tag的语法正确性,或者被jsp开发者用来开发新的标签。  V|=PaO  
_XT],"  
TLD的文件扩展名必须为.tld,而且必须放在当前WEB应用的WEB-INF目录或其子目录中。 '[#a-8-JY_  
~3}Gu^@  
一个TLD的内容的开头必须遵守标准的XML开头,用于描述DTD和xml的版本,例如: 4d&#NP  
{FzL@!||  
<?xml version="1.0" encoding="ISO-8859-1" ?> #_yQv?J  
OJd!g/V  
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd"> (;utiupW  
TLD必须以<taglib>来作为它的根元素,<taglib>的子元素如下表: qW]gp7jK4  
;\`~M  
Enee\!@v  
<taglib>的子元素 gfQ&U@N  
"zW3d KVc  
Element =4GJYhj  
Description (]wi^dE  
b?Wg|D  
tlib-version 3L/qU^`  
Tag库的版本 H5t 9Mg|  
Gd0-}4S?  
jsp-version 8r[ZGUV  
Tag库所需要的jsp的版本 wu?ahNb.`Y  
H <CsB  
short-name i^P@?  
助记符,tag的一个别名(可选) N;,?k.vU  
97:1L4w.(  
uri .0]4@'  
用于确定一个唯一的tag库 wUzQ`h2  
Hj ]$  
display-name PoMkFG6  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) /x.TF'Z*  
Q,Tet&in )  
small-icon #!p=P<4M  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) gr %8 O-n  
I( BG%CO9  
large-icon yu"Ii-9z  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) 2}j2Bhc  
`mPmEV<  
description ^_4TDC~h  
对tag库的描述(可选) '^'4C'J  
C("PCD   
listener uY0V!W  
参见下面listener元素 CG'NC\x5  
R`=3lY;  
tag &SS"A*xg  
参见下面tag 元素 Lm+!/e  
8?] :>  
Listener元素 '$Jt}O  
~^/zCPy[w  
一个tag库可能定义一些类做为它的事件侦听类,这些类在TLD中被称为listener 元素,jsp服务器将会实例化这些侦听类,并且注册它们。Listener元素中有一个叫listener-class的子元素,这个元素的值必须是该侦听类的完整类名。 J5LP#o(V  
ja$>>5<q  
Tag元素 WujIaJt-  
}_XW?^/8  
每个tag元素在tag库中都要指出它的名字、类名、脚本变量、tag的属性。其中脚本变量的值可以直接在TLD中定义或通过tag附加信息的类来取得。每个属性描述了这个属性是否可以省略,它的值是否可以通过<%= …%>这样的JSP语法来获得,以及属性的类型。 sh.xp8^)^>  
Myss$gt}  
每一个tag在TLD中对应一个tag元素,下表是tag元素的子元素: <B 5^  
8>x.zO_.c>  
Tag元素的子元素 &_FNDJ>MCk  
/H.QGPr  
元素名称 \3K6NA!L  
描述 U`q[5U"  
^B@4 w\t  
name  k*|dX.C:  
独一无二的元素名 2rHw5Wn]~  
EQPZV K/  
tag-class y8: 0VZox  
Tag标签对应的tag处理类 Okk[}G)  
4W8rb'B!Ay  
tei-class |Hn[XRsf  
javax.servlet.jsp.tagext.TagExtraInfo的子类,用于表达脚本变量(可选) IV^LYu  
dsDoPo0!  
body-content 5_Yv>tx  
Tag标签body的类型 BOJ h-(>I  
oTtmn, T  
display-name mOwgk7s[ J  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) > 7!aZO  
s# w+^Mw$  
small-icon Qo  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) rh2pVDS  
FW7+!A&F  
large-icon Ff>Y<7CQ v  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) Y0BvN`E  
hM E|=\  
description O;[PEV ~  
此tag标签的描述 BEvSX|M>x  
)DMu`cD  
variable )ufHk  
提供脚本变量的信息(同tei-class)(可选) q?z6|]M|u  
$n `Zvl2  
attribute Qpd-uC_Ni  
Tag标签的属性名 yp5*8g5  
rP ;~<IxEr  
以下章节介绍对于不同类型的tag,如何具体地实现它们。 (Wr;:3i  
'R_U,9y`  
D,xWc|V  
简单的tag 9CJUOB>]  
q" wi.&|  
2a.NWJS  
tag处理类 <0P`ct0,i  
WA Y<X:|We  
简单的tag处理类必须实现Tag接口的doStartTag和doEndTag方法。当jsp引擎碰到tag标签的开头时,doStartTag被调用,因为简单的tag没有body,所以此方法将返回 SKIP_BODY。当jsp引擎碰到tag标签的结尾时,doEndTag被调用,如果余下的页面还要被计算,那它将返回EVAL_PAGE,否则将会返回SKIP_PAGE。 &ukNzV}VW  
GQqw(2Ub}  
以下是例子:对于标签 <tt:simple /> ,它的tag处理类实现如下: !N$4.slr<p  
q`1t*<sk  
7qE V5!  
public SimpleTag extends TagSupport 2`5(XpYe  
7tAWPSwf  
{ *" <tFQ  
{N5g52MN  
public int doStartTag() throws JspException N=D Ynz_~  
4:r^6m%%  
{ T.ub! ,Y  
:&yRvu  
try{ !Go(8`>  
|L;'In  
pageContext.getOut().print(“Hello.”); :EgdV  
N(vbo  
}catch(Exception e){ OpxVy _5,  
yD1*^~loJ  
throw new JspTagException(“SimpleTag: “ + e.getMessage()); {\|? {8f  
u-UUF  
} mk\U wv  
i?=3RdP/R1  
return SKIP_BODY; {DN c7G  
SNvK8,"g  
} *(?YgV  
O#O~A |  
public int doEndTag() #a#~YSnG  
"EEE09~l\  
{ b]RCe^E1  
C,2IET  
return EVAL_PAGE; h83ho  
D\({]oj]  
} >[|:cz  
-D:J$d 6R<  
} W}L =JJo},  
eE7 R d>  
jLr8?Hyf  
注意:如果tag标签没有内容的话,那必须定义body-content元素为空,例如 4L!{U@ '  
IUd>jHp`6  
<body-content>empty</body-content> ItM?nyA  
c09] Cp<  
KXw \N!  
带属性的tag标签
评价一下你浏览此帖子的感受

精彩

感动

搞笑

开心

愤怒

无聊

灌水
级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
只看该作者 1 发表于: 2007-01-01
tag处理类 [Hd^49<P2  
I$f:K]|.m!  
对于tag标签的每个属性,你必须依照JavaBeans规范来定义其属性,以及get和set方法。以struts的logic:present 标签为例, Fi5,y;]R  
Ce5 }+A}  
<logic:present parameter=”Clear”> gFDP:I/`  
FC]? T  
与此相应,此tag处理类应有如下方法和定义: *3"C"4S  
!@VmaAT  
Kjz,p^Y\  
protected String parameter = null; 44%::Oh  
>5^Z'!Z"  
public String getParameter() [*}[W6 3v  
U7PA%  
{ )%^oR5W  
-D!F|&$  
return this.parameter; I*lq0&  
boN)C?"^h  
} uaU!V4-  
7ZZSAI  
public void setParameter(String parameter) Y!POUMA }A  
1M 3U)U  
{ yvH:U5%  
d=>5%$:v  
this.parameter = parameter; <S\S @3  
).tZMLM/-  
} TP^.]I O-  
W:5m8aE\  
vO0ql  
注意:如果你的属性名为id,而且你的tag处理类是从TagSupport类继承的,那你就不需要定义它的属性和set和get方法,因为他们早已在TagSupport被定义过了。 R1P,0Yf  
/o|@]SAe.  
Attribute元素 e'\I^'`!M  
p~3CXmUc~  
对于tag标签的每个属性,你必须定义它是否必须的,它的值是否可以用诸如<%= …%>的表达式来获得,以及它的类型(可选),如果不指定它的类型,那就默认为是java.lang.String类型。如果rtexprvalue元素被定义为true或yes,那么在type元素中就定义了attribute的返回类型。 hJd#Gc~*M  
xY!]eLZ)&  
<attribute> 3I"&Qp%2  
K] Eq"3  
<name>attr1</name> k.lnG5e  
MH !CzV&  
<required>true|false|yes|no</required> Pi8U}lG;  
gpw(j0/Fs  
<rtexprvalue>true|false|yes|no</rtexprvalue> /u #9M {  
tY[y?DJ  
<type>attribute的返回类型(只用当rtexprvalue为真是才有效)</type> *\joaw  
l,v:[N  
</attribute> x7NxHTL  
RIJBHOa  
如果tag的某个属性不是必须的,那tag处理类会自动提供一个缺省值。 m7RWuI,  
iz*aBXVA[  
例如,在logic:present这个tag标签中定义了一个属性叫parameter,但它不是必须的,而且它可以被诸如<%= …%>的表达式来赋值。 ?<nz2 piP,  
|_w*:NCV5  
<tag> @'}X&TN<a  
-TD6s:'  
<name>present</name> D J<c  
"\>3mVOb  
<tag-class>org.apache.struts.taglib.logic.PresentTag</tag-class> nmSpNkJ5  
+i)1 jX<  
<body-content>JSP</body-content> c89RuI `B~  
5mFi)0={y  
@EZXPU  
g` h>:5]  
<attribute> MI@ RdXkY  
zM@iG]?kc  
<name>parameter</name> 2<988F  
*50Ykf  
<required>false</required> Aga7X@fV(  
R#T6I i  
<rtexprvalue>true</rtexprvalue> RuXK` y Sv  
CLYcg$V  
</attribute> nEGku]pCH{  
lZ.,"F@  
Q`//HOM,  
G)e 20Mst  
</tag> k~q[qKb8y:  
[j![R  
94a _ W9  
属性元素的校验 3aDma/  
|2oB3 \)/  
[ 0~qs|27  
有关于tag标签的有效值可以从tag库的说明文档中获得,当JSP页面被编译时,jsp引擎会强制性地参照TLD中定义的规则进行检查。 >K &b,o,[  
{ j/w3  
还有一个方法也可以进行属性元素的校验,就是先继承类TagExtraInfo,然后调用它的isValid方法。这个类同时也起到提供tag中定义的脚本变量信息的作用。 #Kh`ATme  
ar^`r!ABEh  
IsValid方法通过TagData对象来传递属性信息,它包括着tag的所有的属性名-值的信息。由于校验发生在运行时刻,因此这个属性的值将被赋值为TagData.REQUEST_TIME_VALUE。 $K,aLcu  
f a\cLC  
例如tag标签<tt:twa attr1=”value1” />在TLD中定义如下: fe0 Y^vW  
&c\8` # 6  
<attribute> {==Q6BG*  
de`6%%|  
<name>attr1</name> ZO;]Zt]  
v$mA7|(t!  
<required>true</required> ~cZ1=,P  
19=Dd#Nf  
<rtexprvalue>true</rtexprvalue> sV*Q8b*  
3; M!]9ms  
</attribute> 3$kZu  
=k8A7P  
+L49 pv5  
这个定义说明了attr1能在运行期间被赋值。 1/fvk  
-~-2 g  
以下的isValid方法检查attr1属性的值是否属于Boolean类型。注意由于attr1能在运行刻被赋值,那么isValid方法必须检查tag用户是否对此tag进行了运行时刻赋值。 '{+hti,Lh  
_rR.Y3N  
*Z0}0< D@Z  
Public class TwaTEI extends TagExtraInfo 2xnOWW   
h T Xc0  
{ P`oR-D  
D=OU61AA  
public boolean isValid(Tagdata data) >N3{*W  
MD On; Af>  
{ {Ise (>V  
\ agC Q&  
Object o = data.getAttribute(“attr1”); '+eP%Y[W%  
h]=chz  
If(o != null && o != TagData.REQUEST_TIME_VALUE) <B fwR$  
rcbixOT  
{ C4G)anT  
~Ep&:c4:D  
if( ( (String)o).toLowerCase().equals(“true”) || asJYGqdF  
}.hBmhnZmI  
((String)o).toLowerCase().equals(“false”) ) @%TQ/L^|  
ECSC,oJ  
return true; K:Ap|F  
[Ytia#Vv  
else H}$#aXEAn  
TcIUo!:z  
return false;  h43k   
Y9%yjh  
} 8jZYy!  
NMDNls&)k  
else O]Hg4">f  
?y '.sQ  
return true; vbFAS:Y:+  
~ 52  
} i3GvTg-X  
;'Y?wH[  
} -@73"w/  
cn#a/Hx  
ZHBwoC#5}  
带body的tag 54OYAkPCk  
V|D;7  
nJ?C4\#3  
tag处理类 >YW>=5_  
-`;8~wMN  
Q,4F=b  
如果tag标签含有内容,那处理方式会略微有些不同,而且还要视tag处理类是否要与body交互的情况而定。如果要与body交互,那我们认为tag处理类要可能要对body进行操作。 QZfPd\Q5  
mA."*)8VNg  
Tag处理类不与body交互 @Yg7F>s  
f^]AyU;F:  
如果tag处理类不与body交互,tag处理类应该实现Tag接口或从TagSupport中派生,如果body要被计算,那么doStartTag方法应返回 EVAL_BODY_INCLUDE,否则应返回SKIP_BODY。 55I>v3 w  
lt*k(JD  
如果tag处理类要对body反复运算,则它应该实现IterationTag或从TagSupport中派生。如果tag处理类认为body还未计算完的话,那它的doStartTag方法和doAfterBody方法必须返回EVAL_BODY_AGAIN。 gPf aiVY  
:Hd<S   
Tag处理类与body交互 m<yA] ';s  
J8%|Gd0#4  
如果tag处理类与body交互,那tag处理类应实现BodyTag接口或从BodyTagSupport中派生。这种tag处理类一般要实现doInitBody和doAfterBody方法。 yO6i "3  
UtutdkaS  
Body允许一些方法来读写它的内容。Tag处理类可以调用body内容的getString或getReader方法来从body中提取信息,也可用 writeOut(out) 方法来将body的内容写入到out对象中。其中out对象通过tag处理类的getPreviousOut方法来获得。 dnx}c4P  
}/LYI  
如果body的内容需要被计算,那么doStartTag方法必须返回EVAL_BODY_BUFFERED,否则,它将返回 SKIP_BODY。 I*ej_cFQ^  
}n.h)Oz  
doInitBody 方法 pta%%8":  
|B n=$T]  
此方法在body内容已经设好,但未被计算之前被调用。你可以根据不同的body内容来制定初始化策略。 .$yw;go3  
4/jY;YN,2  
doAfterBody方法 5A)w.i&V  
GBQb({  
此方法在body内容已被计算后进行调用。 `%=Jsi0.Nq  
r:q#l~;^  
和doStartTag方法一样,doAfterBody方法返回一个指示符指示是否要继续计算body,如果要继续计算,则doAfterBody应返回EVAL_BODY_BUFFERED,否则,它应返回SKIP_BODY。 8iCI s=06  
sH]AB =_  
release 方法 *HC8kD a%$  
Y1~SGg7(@  
tag处理类调用此方法将它的状态重置为初始状态,并释放所有的私有资源。 =j{jylC  
H>r-|*n  
X=hgLK^3<,  
以下的例子读取body的内容(其中含有一条sql语句),然后将它传递给一个对象,让它进行查询。由于此处body不须重新计算,所以doAfterBody会返回SKIP_BODY。 lVFX@I=pI  
^"Y'zI L  
1Q%.-vs  
Public class QueryTag extends BodyTagSupport gB"Tc[l1  
(H F,p,h_  
{ epL[PL}  
xo%iL  
public int doAfterBody() throws JspTagException PHXP1)^}S  
t2:c@)  
{ <d^7B9O?&w  
yjO7/< 2  
BodyContent bc = getBodyContent(); 9JtvHUkO  
N|j. @K  
//将body的内容以字符串的格式提取出来 RmQt%a7\{  
%8tN$8P  
String query = bc.getString();  )L!R~F C  
'2tEKVb  
//清除body cg.e(@(  
$SXxAS1  
bc.clearBody(); q+z\Y?  
;!}SgzSH}  
try{ v;Dcq  
Z:hrrq9  
Statement stmt = connection.createStatement(); NQJqS?^W&M  
:6/OU9f/R  
Result result = stmt.executeQuery(query); #R8l"]fxr?  
L1xD$wl  
}catch(SQLException e){ iK]g3ew|  
^zJ. W  
throw new JspTagException(“queryTag: “ + e.getMessage() ); OW}A48X[+  
##@#:B  
return SKIP_BODY; 5%`Ul  
~ t H s+  
} tb{{oxa,k  
QT$1D[>  
} c #!6  
$ ddYH  
O)|4>J*B  
body-content元素 \.a .'l  
G7;}309s  
K)+l6Q  
由于tag可能会有body,你必须用body-content元素来指定body内容的类型: ?GarD3#A  
D.o|($S0  
<body-content>JSP|tagdependent</body-content> 3R*@m  
X-,y[ )  
LwPM7S~ *  
如果body的内容是定制的或内部的tag、脚本元素、或HTML广本,则归类为JSP类型。其他的类型,比如上面代码所述的?D?D将sql statement类传给 query tag的这种类型应该标为tagdependent。 cv4M[]U~  
2S6EDXc  
注意:实际上body-content的值并不影响tag处理类对body内容的处理,它仅仅是被tag编辑工具用来描述此body的内容。 =.oWguzu  
uq%3;#[0  
4Jr[8P0/A9  
用tags定义脚本变量 X@&uu0JJ  
wKlCx  
sri#L+I  
tag处理类 #6jwCEo=V  
&] 6T^.  
--YUiNhh  
tag处理类负责创建或设置页面中定义的脚本变量,用pageContext.setAttribute(name,value,scope)或pageContext.setAttribute(name,value)方法来实现。一般来说,tag处理类通过脚本变量的名称来获取它,脚本变量的名称一般可用get方法来获得。 mJ>99:W+  
(VAL.v*  
如果脚本变量的值依赖于tag处理类中的上下文中某一对象,那它可用pageContext.getAttribute(name,scope)方法来找到那个对象。一般的处理过程是tag处理类先找到脚本变量,再对其进行处理,然后用pageContext.setAttribute(name,object)的方法来设置它的新值。 .K1E1Z_  
BDRVT Y(s  
对象的生存周期(scope)如下表: Vk_&W.~  
t)Q @sKT6  
对象的生存周期表 ('-}"3  
?1:/ 6  
名字 SQU%N  
可访问范围 ]~Vu-@ /}  
生存周期 #ljg2:I+  
9:i,WJO  
page *.c9$`s  
当前页面 (I ds<n"  
一直有效,除非页面向客户提交响应或重定向到一个新页面 K=?F3tX^  
]C6[`WF  
request Q3%# o+R>  
当前页面或当前页面重定向到的页面 h;p%EZ  
一直有效,除非页面向客户提交响应 |K;Txe_  
%OW9cqL>l  
session Yb3f]4EH  
当前页面或在同一浏览器窗口中的页面 .0E4c8R\X  
一直有效,除非关闭当前浏览器、超时、网络故障 by]|O  
<1+6O[>{  
application ~: <@`  
整个web应用程序的所有请求 niEEm`"  
一直有效,除非发生网络故障、服务器故障 7 eQoc2X2  
j4xr1y3^  
提供关于脚本变量的信息 ^s~n[  
6q[!X0u  
以下示例定义了一个名为“book”的脚本变量,用来访问程序中关于书的信息: , ."(Gp  
nl9Cdi]o  
<bean:define id=”book” name=”bookDB” property=”bookDetails” type=”database.BookDetails” /> : KP'xf.  
-f2`qltjb  
<font color=”red” size=”+2” > 0#fG4D_  
UX'NJ1f  
<%= messages.getString(“CartRemoved”) %> -0o6*?[Z  
0 ;_wAk  
<strong><jsp:getProperty name=”book” property=”title” /></strong> JX/4=..  
BH0#Q5  
</font> LL[#b2CKa  
EY&C [=  
当包含此tag的JSP页面被编译时,jsp引擎会自动生成关于此book的同步的代码(同步可以避免几个客户同时访问此book时造成的冲突),要生成同步代码,jsp引擎需要知道此脚本变量的如下信息: tP Efz+1N  
hJo^Wo  
· 脚本变量名称 VUC <0WV  
^GrkIh0nL  
· 脚本变量所属的类 ,Q=)$ `%  
Eh@T W%9*  
· 此脚本变量是否引用了一个新的或已存在的对象 + lB+|yJ+  
+#uNQ`1v  
· 此脚本变量的有效性 )*K<;WI WH  
NC.P 2^%  
有两种办法可以向jsp引擎提供关于脚本变量的信息:在TLD中定义variable子元素,或用tei-class子元素定义一个额外tag信息类。用variable最简单,但可能降低了一些灵活性。 '<&EPUO  
X ' #$e{  
Variable元素 }\939Y  
]]=-AuV.  
Variable元素有如下子元素: U 'CfP9=  
myWmU0z/  
· name-given ?D?D 给出的名字,是一个常量 TG63  
!jnqA Z  
· name-from-attribute?D?D 属性名,在编译时给出的属性名 ('* *nP  
!P~ PF:W~|  
name-given或name-from-attribute两者必须选一,但以下子元素是可选的: *pTO|x{  
KM5DYy2 A6  
· variable-class?D?D变量的类型,缺省为java.lang.String。 +dgo-)kP(_  
/LI~o~m1)  
· declare?D?D此脚本变量是否引用了一个新对象,缺省为True。 N+s?ZE*  
|J<pLz  
· scope?D?D脚本变量的范围,缺省为NESTED。下表描述了scope的几种类型: [+ 'B Q  
wyrI8UY  
脚本变量的有效范围 hD$p;LF  
S#h'\/S  
(~7m"?  
有效性 Z<N&UFw7QJ  
方法 P~\a)Szy  
].-J.  
NESTED up &NCX  
在tag标签的开始和结束之间 d{2 y/  
如果tag处理类实现BodyTag接口,则在doInitBody和doAfterBody中调用,否则在doStartTag中调用 Im?= e  
tt7PEEf  
AT_BEGIN  !u53 3  
从tag标签的开始一直到页面结束 f3zfRhkIk  
如果tag处理类实现BodyTag接口,则在doInitBody、doAfterBody和doEndTag中调用,否则在doStartTag和doEndTag中调用 c}IX"  
Tr+h$M1_Ja  
AT_END S!jF:Uc  
从tag标签的结束一直到页面结束 &Mhv XHI  
在doEndTag中调用 [+%d3+27  
{1Ju} =69  
以struts为例,它的bean:define标签的实现遵循JSP1.1规范,此规范要求使用额外tag信息类来定义脚本变量。Variable元素是JSP1.2规范中加入的。以bean:define标签为例,你可以定义如下variable元素: 1 ;\]D9i  
bB;~,W&E1  
<tag> Q7 uAf3  
*>aZc::  
<variable> U0h )pdo  
T2 :oWjC3$  
<name-from-attribute>id</name-from-attribute> :dY.D|j*  
f@! fW&  
<variable-class>database.BookDetails</variable-class> i'W_;Y}  
<78$]Z2we  
<declare>true</declare> Ha)3i{OM  
3?.1~"-J  
<scope>AT_BEGIN</scope> I&pr_~.  
R=vbUA  
</variable> .DDg%z  
lL(p]!K'  
</tag> &G-#*OG  
;|>q zx  
额外tag信息类 0i8[=  
!,Xyl} #  
如果要定义一个额外tag信息类,你要继承javax.servlet.jsp.TagExtraInfo类。一个TagExtraInfo类必须实现getVariableInfo方法,此方法返回一个叫VariableInfo的数组类,它包括如下信息: | V.S.'  
sf |oNOz  
· 变量名 YN,y0t/cQ  
vzY'+9q1.  
· 变量所属类名 ]aC ':55(  
%[]"QbF?  
· 此变量是否引用了一个新对象 L$Hx?^3  
z(g%ue\  
· 此变量的有效范围 ? G$Om  
SY%A"bC  
jsp引擎将一个名为data的参数传给getVariableInfo方法,data中包括tag标签中的所有“属性名?D?D属性值”对。它可以用来向VariableInfo对象提供脚本变量的名字和类名。 cBz!U 8(  
ZnvEv;P  
以struts为例,它在bean:define标签中定义了一个名为DefineTei的额外tag信息类,用来向脚本变量提供信息。由于脚本变量的名称(book)和类名(database.BookDetails)是通过tag标签的属性来传递的,它们一般定义在VariableInfo的构建代码中,并且可用data.getAttributeString方法来得到这些信息。如果要允许book脚本变量能在从tag开始直到整个JSP页面结束的范围内都可用的话,那它的范围应设为AT_BEGIN。如下所示: V!T^wh;  
eJU;*] xfH  
.'t (-eT,  
public class DefineTei extends TagExtraInfo 2BoFyL*  
bz, Da  
{ O.@g/05C  
,|T*|2Gm  
public VariableInfo[] getVariableInfo(TagData data) M82.khm~jM  
8hTR*e! +  
{ <|{L[  
pN\)(:"8v  
String type = data.getAttributeString(“type”); %`xV'2H  
K&=1Ap  
If( type == null) RLdl z  
)KSisEL  
type = “java.lang.Object”; :/o C:z\h  
{ 1+Cw?1d  
return new VariableInfo[] { K0tV'Ml#"  
i\t753<Ys  
new VariableInfo(data.getAttributeString(“id”), xS= _yO9-  
<8u>_o6  
type, o3Mf:;2cC  
BZovtm3 E  
true, b8rp8'M)  
W|)GV0YM  
VariableInfo.AT_BEGIN) 99<4t$KH  
E% <w5d.lq  
}; v<L=!-b^  
nd.57@*M  
} 'e}uvbK  
=yl4zQmg$  
} EkN_8(w  
qBT_! )h   
;tJWOm  
注意:关于额外tag信息类的类名必须要在TLD中的tag标签下的tei-class子元素中定义。因此,DefineTei的tei-class中的定义看起来如下: 60xa?8<cg  
<tei-class> nN>J*02(  
org.apache.struts.taglib.bean.DefineTagTei 5\okU"{d7  
</tei-class> 6ayy[5tW  
U z"sdi  
?n)Xw)]  
具有协作关系的tag 3^{8_^I  
}1 $hxfb  
+ c`AE  
tag通过共享对象来进行协作,JSP技术支持2种方式的对象共享。 AT"!{Y "H  
Vwjk[ DOL  
第一种方法是使用pageContext对象进行对象的共享(可支持JSP页面和tag处理类之间的共享),如果在一个tag处理类中要调用由另一个tag处理类创建的对象,可调用pageContext.getAttribute(name, scope)方法。 ov8 ByJc  
7; p4Wg7k}  
第二各方式的共享是对于tag之间有嵌套关系而言的,外层的tag所创建的对象对于内层的tag来说是可以共用的。这种形式的共享的好处是减少了可能存在的重名冲突。 `YPe^!` $  
YPu9Q  
要访问一个嵌套tag创建的对象,tag处理类必须先找到此嵌套tag对象,可用TagSupport的静态方法 TagSupport.findAncestorWithClass(from, class)或TagSupport.getParent方法。前者在当不确定此tag是否为嵌套tag对象时使用。一旦它的父类被找到,它就能访问其所有动态或静态创建的对象。静态创建的对象是父类的成员,而动态创建的对象可能是父类的私有对象。诸如此类的对象可以用tag处理类的setValue方法来保存,用getValue方法来获得。 ?N:B  
{S G*  
下例阐述了以上两种共享对象的方法。在这个例子当中,一个查询tag检查一个名为connection的属性名是否在doStartTag中被设置。如果connection属性被设置,tag处理类从pageContext中得到这个connection对象。否则,此tag处理类先找到它的父tag处理类,然后从它的父tag处理类中找到connection对象。 *D2Nm9sl  
t5xb"F   
Rv98\VD"  
public class QueryTag extends BodyTagSupport 85'nXYN{d  
Y=r!2u6r~  
{ *RBV'b  
)D;*DUtMVm  
private String connectionId; ~e{H#*f&1/  
Rq) 0i}F  
public int doStartTag() throws JspException JjQ8|En  
T'E ] i!$  
{ 2+z1h^)W  
F9-[%l  
String cid = getConnection(); uS~#4;R   
4CLsY n?  
if(cid != null) n=q=zn;  
uKv&7p@|_)  
{ hi!`9k  
%dc3z"u  
//存在一个connection id,使用它。 WJfES2N  
2UiR~P]%  
connection = (Connection) pageContext.getAttribute(cid); ~/2g)IS  
e9&+vsRmA  
} 62Mdm3  
</= CZy5w  
else 5y]io Jc9-  
6O pa{]  
{ r088aUO P  
n0Go p^3  
ConnectionTag ancestorTag = (ConnectionTag)findAncestorWithClass(this, z Ct\o  
D|l,08n"?  
ConnectionTag.class); /Y,r@D  
[]zua14F6  
if(ancestorTag == null) Y6A;AmM8  
{6h|6.S2  
{ &R,9+c  
3Hw[s0[$  
throw new JspTagException(“一个没有connection属性的查询标签必须被一个connection标记嵌套。”);  ;\qXbL7  
GX  }q9  
} 6W&_2a7*  
dy2rkV.z  
connection = ancestorTag.getConnection(); h./P\eDc  
OUI6 ax\[  
} :lgi>^  
a[sKE?  
} ]3ifd G k  
)o{aeV  
} hJ f2o  
?'eq",c#4N  
zT[6eZ8m  
]]2k}A[-I  
此查询标签在JSP页面中的调用形式可以从以下2种定义中任选一种:  Q=#I9-  
r8[T&z@_  
C5*xQlCq}  
<tt:connection id=”con01” ...> ... </tt:connection> | kXm}K  
};b1ahaG  
<tt:query id=”balances” connection=”con01” > iidT~l  
/7/0x ./{  
SELECT account, balance FROM acct_table FJ54S  
Mzkkc QLK  
where customer_num = <%= request.getCustno() %> bcH_V| 5}  
BMFF=  
</tt:query> dU_;2#3m  
G-u]L7t&1  
QM'X@  
`)K y0&?  
\+m$  
<tt:connection ...> *jITOR!uF`  
pK}=*y~$  
<x:query id=”balances”> <+v{GF#R  
o&SSv W  
SELECT account, balance FROM acct_table XRtD< jlA"  
-Q"hZ9  
where customer_num = <%= request.getCustno() %> !yJICjXj  
wRvb8F 0  
</x:query> 3@<zg1.9-  
gb" 4B%Hm  
</tt:connection> DHw<%Z-J  
W0I4Vvh_"  
8)j@aiF`  
与此同时,在TLD中必须指定connection属性为可选的,定义如下: eE(b4RCM  
skg|>R,kE  
<tag> n V&cC  
Bp?  
... ru9zTZZD  
vScjq5 "p  
<attribute> .0p^W9  
N|usFqCNk^  
<name>connection</name> N ( Oyi  
"_1)CDqP  
<required>false</required> vFv3'b$;G  
I&VTW8jB  
</attribute> )[Z!*am  
h6:#!Rg  
</tag>
描述
快速回复

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