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

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

级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
标准的JSP 标记可以调用JavaBeans组件或者执行客户的请求,这大大降低了JSP开发的复杂度和维护量。JSP技术也允许你自定义taglib,其实换句话说,taglib可以看成是对JSP标记的一种扩展,正如xml是对html的一种扩展一样。taglib通常定义在tag标签库中,这种标签库存放着你自己定义的tag标签。简而言之,如果使用taglib,那么你可以设计自己的JSP标记! 4C }#lW9  
U E-1p  
一般来说,自定义tag标签主要用于操作隐藏对象、处理html提交表单、访问数据库或其它企业级的服务,诸如邮件和目录操作等等。自定义tag标签的使用者一般都是那些对java编程语言非常精通,而且对数据访问和企业级服务访问都非常熟悉的程序员,对于HTML设计者来说,使得他可以不去关注那些较复杂的商业逻辑,而将精力放在网页设计上。同时,它也将库开发者和库使用者进行合理分工,自定义tag标签将那些重复工作进行封装,从而大大提高了生产力,而且可以使得tag库可用于不同的项目中,完美地体现了软件复用的思想。 E/hO0Ox6  
Y^QG\6q  
在这篇文章中,我们主要讨论: 3~\,VO''  
H}cq|hodn  
· 什么是自定义tag标签? 'd]t@[#  
@5h(bLEP  
· 怎么使用tag标签? ;TL>{"z`x  
ZU;nXqjc  
o 声明要使用的tag库 K?Jo"oy7  
G%>{Z?!B  
o 找到与之对应的tag处理类 t;}`~B  
#kgLdd"  
o tag标签的类型 \s6 VOR/  
T%yGSk  
· 自定义tag标签 < =!FB8 .  
"%w E>E  
o tag处理类 U^kk0OT^  
w&*oWI$i  
o tag库描述 eMtQa;Lc9o  
#i=m%>zjN  
o tag标签示例 i)(-Ad_  
47)\\n_\z  
o 带属性的tag +o]J0Gu  
(gUVZeVFP  
o 带body的tag _QneaPm%  
q}C;~nMD  
o 定义了脚本变量的tag 23X-h#w  
NbK67p:  
o 具有协作关系的tag I:M15  
^sF(IV[>  
· 自定义tag标签 p: u@? k  
l4 YTR4D  
o 一个迭代tag的例子 }" STc&1  
Qx8O&C?Ti  
o 一个模板tag库 H-3*},9  
/}k?Tg/  
o tag处理类到底是怎样被调用的? )BZ6QO`5n  
sY* qf=  
~&D5RfK5f  
什么是自定义的tag? B.}j1 Bb  
zd=N.  
一个自定义的tag标签是用户定义的一种JSP标记。当一个含有自定义的tag标签的JSP页面被jsp引擎编译成servlet时,tag标签被转化成了对一个称为tag处理类的对象进行的操作。于是当JSP页面被jsp引擎转化为servlet后,实际上tag标签被转化成为了对tag处理类的操作。 esd9N'.Q*  
e 3TKg  
自定义tag标签有很多特色,诸如: \"9ysePI  
#Eqx E o;  
· 可以在JSP页面中自定义tag标签的属性 6M[OEI5  
Bqw/\Lxwlf  
· 访问JSP页面中的所有对象 s14 ot80)  
P&Wf.qr{:  
· 可以动态地修改页面输出 J I E0O`  
u17 9!  
· 彼此这间可以相互通信。你可以先创建一个JavaBeans组件,然后在一个tag中调用此JavaBeans组件,同时可以在另一个tag中调用它。 2tS,q_-=  
>+@EU)  
· tag允许相互嵌套,可以在一个JSP页面中完成一些复杂的交互。 HE-ErEtGB  
jpZ 7p ;  
|<#yXSi  
使用tag标签 l4y>uZ>a  
(Ft#6oK"  
U%)*I~9  
本节主要描述怎样在JSP页面中使用tag标签,以及tag标签的不同类型。 [j?<&^SW  
lt%9Zgr[u  
要使用tag标签,JSP程序员必须做2件事: ctR ^"'u  
7)BK&kpVr  
· 声明此tag标签的tag库 fr&K^je\  
Sc:)H2k`$  
· 实现此tag标签 1cV0TUrz  
WL;2&S/{@  
声明tag标签所在的tag库 L(}/W~En  
4 ;^  
如果要使用tag标签,则应用JSP的taglib指示符来指定其tag库(注意:taglib要在在使用此tag标签之前声明) 7b(r'b@N  
o`nJJ:Cxq-  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> ,D'bIk  
D 1(9/;9  
uri属性定义了唯一的标签库描述(以下简称TLD),它可以是直接是tld文件名或一个独一无二的名字。prefix是用来区别其它TLD中和本TLD中有重名的tag的一种手段。 0QBK(_O`  
kQ|phtbI  
TLD必须以.tld作为扩展名,并且存放在当前应用的WEB-INF目录或其子目录下。你可以通过它的文件名直接引用它,也可以通过别的方式间接地引用它。 "sed{?  
X\5EF7:S  
以下taglib指示符直接引用一个TLD: gH0Rd WX  
_8wT4|z5  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> EE*FvI`  
X3l6b+p  
以下的taglib指示符通过一个逻辑名称间接地引用一个TLD: ;pG5zRe  
<<&SyP  
<%@ taglib uri=”/tutorial-template” prefix=”tt” %> cUwR6I9  
`m\ ?gsw7  
如果是间接引用TLD的话,那你必须还要在web.xml中定义此逻辑名称与tld文件之间的映射,具体做法是在web.xml中加入一个名为taglib的元素: R.rE+gxO1  
x) R4_ 3  
<taglib> )jMk ~;'r  
IeB^BD+j  
<taglib-uri>/tutorial-template</taglib-uri> V5+|H1=  
33NzQb  
<taglib-location> LG=_>:~t>  
uk3PoB^>  
/WEB-INF/tutorial-template.tld |%j7Es  
^geY Ay  
</taglib-location> F ZN}T{<  
$S U<KNMZ  
</taglib> 64SRW8AH  
zS `>65}e  
>(W\Eh{J  
实现此tag标签 *7C l1o  
bK|nxL  
;JX2ebx  
为了实现tag标签,你有2种方法来存放tag处理类。一、让tag处理类以.class的方式存放于当前应用的WEB-INF/class子目录下,二、如果tag处理类是以JAR包的形式存在的话,那可以放在当前应用的WEB-INF/lib目录下,如果tag处理类要在多个应用中共享,那么它就应放在jsp服务器上的common/lib目录下,对于tomcat来说,就是tomcat/common/lib目录下。 P?zL`czWd  
hYVy65Ea  
>| hqt8lY  
tag标签类型 2lxA/.f  
Rc}#4pM8  
L7N>p4h]Xj  
自定义的tag标签遵循XML语法。它有一个开始标记和一个结束标记,有的还有body(即文本节点): Bb7Vf7>  
Ca3 {e1  
<tt:tag> ;e Mb$px  
WDh*8!)  
body DK<}q1xi  
rR(\fX!dg  
</tt:tag> ! ;R}=  
XW*d\vDun  
1(/rg  
一个不带body的tag标签如下: }LX.gm  
) Hqn  
<tt:tag /> 1+Bj` ACP  
YGZa##i  
*-s':('R  
简单的tag标签 +`TwBN,kp-  
o6 8;-b'n  
一个没有body和属性的tag标签如下: \ZC0bHsA  
(~^KXJ{->  
<tt:simple /> 7+m.:~H3}  
n0w0]dJ&lc  
xfA@GYCfT  
带属性的tag标签 sfC/Q"Zs  
kj`h{Wc[)  
T>m|C}yy  
自定义标签可以有自己的属性。属性一般在开始标记中定义,语法为 attr=”value”。属性的作用相当于自定义标签的一个参数,它影响着tag处理类的行为。你可以在TLD中详细定义它。 1fV\84m^  
-\g@s@5  
你可以用一个String常量给一个属性赋值,也可以通过表达式给它赋值,如<%= ...%>。以struts为例,它的logic:present标签就是用的String常量来给属性赋值: xgWVxX^)  
D}?JX5.  
<loglic:present parameter = “Clear”> t=n@<1d  
f4^\iZ{`G  
而另一个标签logic:iterate是用表达式来给属性赋值: {QT:1U \.  
s+a#x(7{  
<logci:iterate collection=”<%= bookDB.getBooks() %>” tS[@?qP  
%D[6;PT  
id=”book” type=”database.BookDetails”> w=ZK=@  
5- "aK~@+  
j`-9.  
带body的tag标签 0fx.n  
kQ.3J.Q5  
一个自定义标签可以包含其它自定义标签、脚本变量、HTML标记或其它内容。 1P/4,D@  
+P=I4-?eX  
在下述例子中,此JSP页面使用了struts的logic:present标签,如果些标签定义了parameter=”Clear”的属性,则将清除购物车的内容,然后打印出一条信息: qhNYQ/uS  
/z4n?&tM  
<logic:present parameter=”Clear”> 3EyVoS6D  
m"vWu0/#  
<% cart.clear(); %> BSg 3  
}1YQ?:@  
<font color=”#ff0000” size=”+2”><strong> 0V'XE1h  
9<"l!noy  
你选择了清除购物车! |]OI)w*  
<2fvEW/#v  
</strong></font> 7@ mP;K0  
e;&fO[ 2  
</logic:present> K[9{]$(Z  
Ml+O - 3T  
-nk0Q_7N  
到底是用属性还是用body来传递信息? 0vcFX)]yW  
2%@<A  
如上所述,我们既可以通过属性,也可以通过body来传递信息。但一般来说,比较简单的类型,如字符串或简单表达式最好采用属性来传递信息。 U_5\ FM  
CK1gzIg>  
9TV1[+JWe  
定义脚本变量的tag标签 ^-K ~y  
&(A'uX.>pr  
所谓脚本变量,是指JSP中可以调用的变量或对象。它可由tag标签产生。以下示例阐述了一个tag标签定义了一个名为tx的由JNDI所定义的事务处理对象。脚本变量可以是ejb对象、事务、数据库连接等等: incUa;  
01o,9_|FL  
<tt:lookup id=”tx” type=”UserTransaction” name=”java:comp/UserTransaction” /> "ax"k0  
3!u:*ibt  
<% tx.begin(); %> Q5tx\GE  
t+n+_X  
... @%[ VegT  
T :X A  
41\V;yib  
具有协作关系的tag标签 3 ~\S]  
jUy$aGX  
自定义tag标签之间可以通过共享对象来实现协作。在下述例子中,标签tag1创建了一个名为obj1的对象,在标签tag2仍可以重复使用obj。 {iVmae  
X8(WsN  
<tt:tag1 attr1=”obj1” value1=”value” /> 1'9YY")#  
i UW.$1l  
<tt:tag2 attr1=”obj1” /> G1/  
BY??X=  
在以下这个例子当中,如果外层的tag标签创建了一个对象,那么其内层的所有tag标签都可以使用这个对象。由于这样产生的对象没有一个指定的名字,那么就可以将少重名的冲突。这个例子阐述了一系列协作的嵌套对象。 9d&}CZr  
j'|`:^ Sy  
<tt:outerTag> `Qo}4nuRs  
4AuJ1Z  
<tt:innerTag /> <k-hRs2d  
Ozs&YZ  
</tt:outerTag> >A1;!kGE#  
@8V~&yqq  
H?j!f$sw  
Tag处理类 K_LwYO3  
C07U.nzh  
ftbOvG/ I  
Tag处理类必须实现Tag接口或BodyTag接口,不过现在一般都流行从TagSupport或BodyTagSupport类中继承,这些类或接口都可以在javax.servlet.jsp.tagext包中找到。 zNJ-JIo%  
K"9V8x3Wg  
当JSP引擎看到自己的JSP页面中包含有tag标签时,它会调用doStartTag方法来处理tag标签的开头,调用doEndTag方法来处理tag标签的结束。 y`-5/4  
CFiO+p&  
下表说明不同类型的tag所需要不同的处理过程: F[==vte|  
RTvzS]  
Tag处理类的方法 oHkjMqju  
1<3!   
Tag标签类型 = j S  
所调用的方法 !gFUC<4bu  
?K^~(D8(  
基本标签 2^=.jML[  
doStartTag, doEndTag, release $nW^Gqwj]1  
pN7 v7rs  
带属性的标签 1U~yu&  
doStartTag, doEndTag, set/getAttribute1...N, release F9 C3i  
;n=A245W\  
带内容的标签 ob"yz}  
doStartTag, doEndTag, release SDICN0X*  
Y!lc/[8  
带内容的标签,且内容重复循环 {Aq:Kh`&  
doStartTag, doAfterBody, doEndTag, release dE|luN~  
,5thD  
带内容的标签,且内容与JSP交互 E>O1dPZcM  
doStartTag, doEndTag, release, doInitBody, doAfterBody, release PU^@BZ_m  
wv_<be[?*  
一个tag处理类可以通过javax.servlet.jsp.PageContext来与JSP交互,通过javax.servlet.jsp.PageContext类,tag处理类可以访问JSP中的request、session和application对像。 $+@xwuY'+  
qn|~z@"  
如果tag标签是互相嵌套的,那内层的tag处理类可以通过它的parent属性来访问上层的tag处理类。 nV&v@g4Tt  
9U~sRj=D  
一般情况都将所有的tag处理类打成了JAR的包,以便于发布。 -[.A6W  
]*JH~.p  
HVK./y qy  
Tag库描述(简称TLD) :_"%o=  
yaKw/vV  
bcC+af0L  
Tag库是用xml语言描述的,TLD包括了tag库中所有tag标签的描述,它一般用来被jsp服务器用来校验tag的语法正确性,或者被jsp开发者用来开发新的标签。 Ve^rzGU  
j\.\ePmk]  
TLD的文件扩展名必须为.tld,而且必须放在当前WEB应用的WEB-INF目录或其子目录中。 sn?YD'>k  
eFdN"8EW  
一个TLD的内容的开头必须遵守标准的XML开头,用于描述DTD和xml的版本,例如: WHvU|rJ  
##clReS  
<?xml version="1.0" encoding="ISO-8859-1" ?> Gmp`3  
PV,AN   
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd"> *q |3QHZ  
TLD必须以<taglib>来作为它的根元素,<taglib>的子元素如下表: 'ai!6[|SD  
DX%D8atrr  
SHT^Etri  
<taglib>的子元素 <P4*7:jX  
f!aE/e\  
Element Qv>rww]  
Description IYk^eG:;  
I`8jJpGA  
tlib-version 5D%gDw+"  
Tag库的版本 A%c)=(,  
J{bNx8.&  
jsp-version #Bgq]6G2  
Tag库所需要的jsp的版本 KK4"H]!.  
.WT^L2l%  
short-name f:|O);nM  
助记符,tag的一个别名(可选) hXx.  
?\$\YX%/p  
uri KL\]1YX  
用于确定一个唯一的tag库 Jh)K0>R  
cPm-)/E)i  
display-name S|?Ht61k  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) N"wp2w  
%1jApCJ  
small-icon fK{[=xMr@  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) Y94/tjt  
&33.mdBH  
large-icon .a *^6TC.  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) j}$Up7pW  
@"E{gM@B  
description KGoHn6jM  
对tag库的描述(可选) l`A4)8Y@  
Lb} cjI:  
listener 81<0B @E  
参见下面listener元素 Z 2x%  
hpVu   
tag Qo;#}%}^^  
参见下面tag 元素 )Mj $/  
eX@7f!uz  
Listener元素 J \V.J/  
GxR, 3  
一个tag库可能定义一些类做为它的事件侦听类,这些类在TLD中被称为listener 元素,jsp服务器将会实例化这些侦听类,并且注册它们。Listener元素中有一个叫listener-class的子元素,这个元素的值必须是该侦听类的完整类名。 {BlKVsQ  
0{ ;[k  
Tag元素 +\O[)\  
Udh!%QP%[w  
每个tag元素在tag库中都要指出它的名字、类名、脚本变量、tag的属性。其中脚本变量的值可以直接在TLD中定义或通过tag附加信息的类来取得。每个属性描述了这个属性是否可以省略,它的值是否可以通过<%= …%>这样的JSP语法来获得,以及属性的类型。 bhb*,iWA  
!(wH}ti  
每一个tag在TLD中对应一个tag元素,下表是tag元素的子元素: 11Hf)]M   
tSvklI  
Tag元素的子元素 =!cI@TI  
t|Ipxk.)  
元素名称 w>W`8P_b@  
描述 ^sjL@.'m$N  
Y[yw8a  
name 3]9twfF 'J  
独一无二的元素名 r\-25F<e5  
 j{;RuNt  
tag-class l6S6Y  
Tag标签对应的tag处理类 yU@~UCmja  
_\tGmME37  
tei-class X0.-q%5  
javax.servlet.jsp.tagext.TagExtraInfo的子类,用于表达脚本变量(可选) Fc"&lk4e  
l< y9ue=  
body-content f @cs<x  
Tag标签body的类型 P;dp>jL  
Q&9%XF uM  
display-name ,OQ!lI_`R  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) :~2An-V  
!j3V'XU#Zn  
small-icon yT>t[t60/S  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) ;^,2 QsM  
Y)@PGxjz  
large-icon ]/+qM)F  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) VhAZncw  
P~+?:buqc  
description {xC CUU  
此tag标签的描述 'ZHu=UT7_  
WR*|kh  
variable Hh bf9)  
提供脚本变量的信息(同tei-class)(可选) ikGH:{  
$DfaW3bJ  
attribute J\%<.S>  
Tag标签的属性名 .=>T yq  
P'Fy,fNg  
以下章节介绍对于不同类型的tag,如何具体地实现它们。 y%H;o?<WX  
|-zwl8E  
r]{fjw(~  
简单的tag p.2>- L  
:`Kr|3bQ  
8dw]i1t<  
tag处理类 :8_`T$8i4  
{tE/Jv $  
简单的tag处理类必须实现Tag接口的doStartTag和doEndTag方法。当jsp引擎碰到tag标签的开头时,doStartTag被调用,因为简单的tag没有body,所以此方法将返回 SKIP_BODY。当jsp引擎碰到tag标签的结尾时,doEndTag被调用,如果余下的页面还要被计算,那它将返回EVAL_PAGE,否则将会返回SKIP_PAGE。 %(-YOTDr  
lK^Q#td:`  
以下是例子:对于标签 <tt:simple /> ,它的tag处理类实现如下: : {9|/a  
a.5s5g)8  
T2wn!N?r  
public SimpleTag extends TagSupport 8j,_  
f/b }X3K  
{  :*M\z3`k  
;UgRm#  
public int doStartTag() throws JspException 6bg+U`&g  
n;"4`6L~  
{ z#!xqIg0  
7[-jr;v  
try{ 0<L@f=i  
lO9{S=N  
pageContext.getOut().print(“Hello.”); g[;iVX^1&  
f*~ 4Kv  
}catch(Exception e){ %uGA+ \b  
Yi[dS`,d  
throw new JspTagException(“SimpleTag: “ + e.getMessage()); t.pg;#  
33kI#45s  
} Yf:utCvv  
O#7ldF(  
return SKIP_BODY; 2t { Cpw  
s8|#sHT  
} UBRMV s  
e>t9\vN#bx  
public int doEndTag() N,ik&NIWy  
 FZ>*<&  
{ vc2xAAQ  
yT&bS\  
return EVAL_PAGE; ?E2k]y6<  
^BM/K&7^  
} %:o@IRTRU  
; _i0@@J  
} 2al~`  
>V(2Ke Y  
ke>\.|HT}  
注意:如果tag标签没有内容的话,那必须定义body-content元素为空,例如 1TQ $(bI  
Kc udWW]  
<body-content>empty</body-content> 8{+~3@T  
@sKAsn  
16N8h]l  
带属性的tag标签
评价一下你浏览此帖子的感受

精彩

感动

搞笑

开心

愤怒

无聊

灌水
级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
只看该作者 1 发表于: 2007-01-01
tag处理类 P'9aZd  
J#V `W&\,6  
对于tag标签的每个属性,你必须依照JavaBeans规范来定义其属性,以及get和set方法。以struts的logic:present 标签为例, w78Ius,  
lIjHd#q-C  
<logic:present parameter=”Clear”> Aq'%a)Y2  
=cC]8Pz?  
与此相应,此tag处理类应有如下方法和定义: cn\& ;55v  
f!$J_dz  
>qF KXzI  
protected String parameter = null; ^YIOS]d>8#  
8v^i%Gg  
public String getParameter() bOz\-=au  
LVEVCpp@  
{ <$yer)_J!k  
,IJNuu\  
return this.parameter; Ee|+uQ981>  
@&ZTEznbyt  
} ^LU[{HZV  
f[}SS]d:E  
public void setParameter(String parameter) @$+[IiP  
?ha}&##  
{ : m5u=:t  
:s'%IGy>:  
this.parameter = parameter; 93WYZNpX  
ygf qP  
} &HXSO,@  
FY|x<-f  
hE6tu'  
注意:如果你的属性名为id,而且你的tag处理类是从TagSupport类继承的,那你就不需要定义它的属性和set和get方法,因为他们早已在TagSupport被定义过了。 ewY[vbF  
CQ( @7  
Attribute元素 \7j)^  
kxn;;  
对于tag标签的每个属性,你必须定义它是否必须的,它的值是否可以用诸如<%= …%>的表达式来获得,以及它的类型(可选),如果不指定它的类型,那就默认为是java.lang.String类型。如果rtexprvalue元素被定义为true或yes,那么在type元素中就定义了attribute的返回类型。 *i?qOv /=>  
?*s!&-KI  
<attribute> _@OYC<  
yX~[yH+Pn  
<name>attr1</name> m~U{ V9;*  
F>b6fUtR  
<required>true|false|yes|no</required> Uqpvj90sw  
0&nF Vsz  
<rtexprvalue>true|false|yes|no</rtexprvalue> 654%X(:q  
R$@.{d&:w  
<type>attribute的返回类型(只用当rtexprvalue为真是才有效)</type> |Gf{}  
{f&ga  
</attribute> _uu:)%  
wwAT@=X*}  
如果tag的某个属性不是必须的,那tag处理类会自动提供一个缺省值。 Y>#c2@^i<  
j d8 1E  
例如,在logic:present这个tag标签中定义了一个属性叫parameter,但它不是必须的,而且它可以被诸如<%= …%>的表达式来赋值。 W_ 6Jl5]  
7}x-({bqy  
<tag> )ED[cYGx  
PjP%,-@1  
<name>present</name> =0)^![y]v  
xqtjtH9X  
<tag-class>org.apache.struts.taglib.logic.PresentTag</tag-class>  XGoy#h  
"/'= gE  
<body-content>JSP</body-content> L,D>E  
/r%+hS  
$F-XXBp  
PW`Tuj  
<attribute> jFXU xf  
&rd(q'Vi  
<name>parameter</name> I>5@s;  
\Cs<'(=  
<required>false</required> S }n;..{  
J9 =gv0  
<rtexprvalue>true</rtexprvalue> bvx:R ~E$  
<di_2hN  
</attribute> i`SF<)M(  
31* 6 ;(  
%KA/  
3-R3Qlr  
</tag> 0hkuBQb\  
3PA'Uk"5Z  
>" .qFn g  
属性元素的校验 m%V[&"5%e  
0c5_L6_z  
#~x5}8  
有关于tag标签的有效值可以从tag库的说明文档中获得,当JSP页面被编译时,jsp引擎会强制性地参照TLD中定义的规则进行检查。  * [5  
tAA7  
还有一个方法也可以进行属性元素的校验,就是先继承类TagExtraInfo,然后调用它的isValid方法。这个类同时也起到提供tag中定义的脚本变量信息的作用。  5q ,  
W =zG  
IsValid方法通过TagData对象来传递属性信息,它包括着tag的所有的属性名-值的信息。由于校验发生在运行时刻,因此这个属性的值将被赋值为TagData.REQUEST_TIME_VALUE。 @(cS8%wK  
-"zu"H~t4  
例如tag标签<tt:twa attr1=”value1” />在TLD中定义如下: 8[C6LG  
,2TqzU;  
<attribute> Y2X1!Em>B  
S>,I&`yi  
<name>attr1</name> &FrB6 y  
9^ r  
<required>true</required> C' ._}\nX  
1955(:I  
<rtexprvalue>true</rtexprvalue> JLu0;XVK  
Ln_l>X6j51  
</attribute> j1 F+,   
%-l:_A  
PBL^xlg  
这个定义说明了attr1能在运行期间被赋值。 +_eb*Z`5o  
pNlisS  
以下的isValid方法检查attr1属性的值是否属于Boolean类型。注意由于attr1能在运行刻被赋值,那么isValid方法必须检查tag用户是否对此tag进行了运行时刻赋值。 ^JtHTLHL=  
zcKC5vqb  
ElXe=5L\#  
Public class TwaTEI extends TagExtraInfo 6 b}feEh$!  
' D&G~$  
{ Qm#i"jvV  
v)yimIHzo  
public boolean isValid(Tagdata data) .dCP8|  
u =kSs  
{ 6Qb)Uq3}]  
u mlZ(??.  
Object o = data.getAttribute(“attr1”); ge?-^s4M  
<~M9 nz(<  
If(o != null && o != TagData.REQUEST_TIME_VALUE) 5uo(z,WLR  
l~YNmmv_  
{ 3}21bL  
n:'BN([]o  
if( ( (String)o).toLowerCase().equals(“true”) || HiG/(<bs9O  
f hG2  
((String)o).toLowerCase().equals(“false”) ) }qv-lO  
XyphQ}\u  
return true; E ZKz-}  
r$FM8$cJ  
else z[%v _S  
 vkpV,}H  
return false; rO$>zdmYHs  
va(9{AXI  
} [\9(@Bx  
LDEt.,6i  
else k6L373e#Q  
K=x1m M+RK  
return true; IKDjatn  
F[=lA"F^  
} yl<$yd0Zdu  
}AW)R&m  
} }pnFJ  
xqWrW)  
,?<h] !aQ  
带body的tag m]d6@"Z.  
^Cn]+0G#C8  
ff1B)e  
tag处理类 HoE.//b  
R9/xC7l@  
K}`p_)(  
如果tag标签含有内容,那处理方式会略微有些不同,而且还要视tag处理类是否要与body交互的情况而定。如果要与body交互,那我们认为tag处理类要可能要对body进行操作。 K4/P(*r`  
|D`b7h  
Tag处理类不与body交互 Y"kS!!C>[  
u7zB9iQ&  
如果tag处理类不与body交互,tag处理类应该实现Tag接口或从TagSupport中派生,如果body要被计算,那么doStartTag方法应返回 EVAL_BODY_INCLUDE,否则应返回SKIP_BODY。 SE )j}go  
tc <M]4-  
如果tag处理类要对body反复运算,则它应该实现IterationTag或从TagSupport中派生。如果tag处理类认为body还未计算完的话,那它的doStartTag方法和doAfterBody方法必须返回EVAL_BODY_AGAIN。 \G=R hx f  
%4|}&,%%r  
Tag处理类与body交互 ^P g YP  
,XG|oo -  
如果tag处理类与body交互,那tag处理类应实现BodyTag接口或从BodyTagSupport中派生。这种tag处理类一般要实现doInitBody和doAfterBody方法。 M(zY[O  
qb> r\bc  
Body允许一些方法来读写它的内容。Tag处理类可以调用body内容的getString或getReader方法来从body中提取信息,也可用 writeOut(out) 方法来将body的内容写入到out对象中。其中out对象通过tag处理类的getPreviousOut方法来获得。 T 0v@mXBQ  
sq(Ar(L<  
如果body的内容需要被计算,那么doStartTag方法必须返回EVAL_BODY_BUFFERED,否则,它将返回 SKIP_BODY。 E'S;4B5?  
dU>R<jl!$  
doInitBody 方法 liw 9:@+V  
wu!_BCIy  
此方法在body内容已经设好,但未被计算之前被调用。你可以根据不同的body内容来制定初始化策略。 *<1x:PR  
`V):V4!j),  
doAfterBody方法 uxMy 1oy  
<Mn7`i  
此方法在body内容已被计算后进行调用。 &iiK ZZ`_o  
uM)9b*Vbo  
和doStartTag方法一样,doAfterBody方法返回一个指示符指示是否要继续计算body,如果要继续计算,则doAfterBody应返回EVAL_BODY_BUFFERED,否则,它应返回SKIP_BODY。 n+\Cw`'<H  
1X"H6j[w  
release 方法 ^ $+f3Z'  
|@L &yg,x  
tag处理类调用此方法将它的状态重置为初始状态,并释放所有的私有资源。 H"GE\  
7cmr *y  
]7S7CVDk4  
以下的例子读取body的内容(其中含有一条sql语句),然后将它传递给一个对象,让它进行查询。由于此处body不须重新计算,所以doAfterBody会返回SKIP_BODY。 sJI -  
'"]>`=R  
lDPRn~[#\  
Public class QueryTag extends BodyTagSupport hW !@$Ph  
#D LT-G0  
{ h[je_^5  
B,vHn2W  
public int doAfterBody() throws JspTagException zNr_W[  
<aSLm=  
{ _h=< _Z  
AV[PQI  
BodyContent bc = getBodyContent(); JIbzh?$aD  
XJlDiBs9=Q  
//将body的内容以字符串的格式提取出来 YNgR1 :l  
$:u7Dv}\  
String query = bc.getString(); 3@TG.)N4  
C*y6~AYN#  
//清除body r< ?o}Qq  
O{ %A&Ui  
bc.clearBody(); 0]eh>ab>  
!OoaE* s  
try{ me[J\MJ;w^  
?V5Pt s  
Statement stmt = connection.createStatement(); vi!r8k  
(ln  
Result result = stmt.executeQuery(query); (m3I#L  
:S99}pgY  
}catch(SQLException e){ 9u7n/o&8v6  
8A8xY446)  
throw new JspTagException(“queryTag: “ + e.getMessage() ); V:G}=~+=  
x#F1@r8R  
return SKIP_BODY; RSPRfYU/  
xU13fl  
} ttbQergS  
M~z (a3@[V  
} }lC64;yo  
g"Q}h  
3h[:0W!C]  
body-content元素 'x45E.wYw  
{GX &)c4  
ndKvJH4  
由于tag可能会有body,你必须用body-content元素来指定body内容的类型: @u"kX2>Eq  
C?/r}ly<\  
<body-content>JSP|tagdependent</body-content> SD|4ybK>d  
m.HX2(&\3  
VO @ 4A6  
如果body的内容是定制的或内部的tag、脚本元素、或HTML广本,则归类为JSP类型。其他的类型,比如上面代码所述的?D?D将sql statement类传给 query tag的这种类型应该标为tagdependent。 K.#,O+-Kg`  
/ UaNYv/  
注意:实际上body-content的值并不影响tag处理类对body内容的处理,它仅仅是被tag编辑工具用来描述此body的内容。 C6D=>%uY  
liCCc;&B;  
RQ*|+ ~H  
用tags定义脚本变量 !4 4mT'Y  
#.MIW*==  
L.T gJv43  
tag处理类 HoIKx_  
s;-78ejj7  
+YQ~t,/  
tag处理类负责创建或设置页面中定义的脚本变量,用pageContext.setAttribute(name,value,scope)或pageContext.setAttribute(name,value)方法来实现。一般来说,tag处理类通过脚本变量的名称来获取它,脚本变量的名称一般可用get方法来获得。 FU]8.)`G  
hk7(2j7B  
如果脚本变量的值依赖于tag处理类中的上下文中某一对象,那它可用pageContext.getAttribute(name,scope)方法来找到那个对象。一般的处理过程是tag处理类先找到脚本变量,再对其进行处理,然后用pageContext.setAttribute(name,object)的方法来设置它的新值。 liugaRO8J  
gc,J2B]61  
对象的生存周期(scope)如下表: y,y/PyN)  
5Aa31"43n  
对象的生存周期表 `uNvFlP  
L.IoGUxD  
名字 B~V<n&<  
可访问范围 Jv 6nlK`  
生存周期 ~ F?G5cN5  
t-eKruj+  
page _#J_$CE#  
当前页面 cYq']$]  
一直有效,除非页面向客户提交响应或重定向到一个新页面 vR%j#v|s  
]5o0  
request _A;vSp.`  
当前页面或当前页面重定向到的页面 eN<>#: `  
一直有效,除非页面向客户提交响应 7,W]zKH  
;<bj{#mMv  
session [Hv*\rb  
当前页面或在同一浏览器窗口中的页面 [D<RV3x9  
一直有效,除非关闭当前浏览器、超时、网络故障 'B:Z=0{>N  
$ ,; ;u:-  
application ~{1/*&P  
整个web应用程序的所有请求 NK  
一直有效,除非发生网络故障、服务器故障 Rm,[D)D^0N  
v2M"b?Q  
提供关于脚本变量的信息 XI@6a9Uk  
` x%U  
以下示例定义了一个名为“book”的脚本变量,用来访问程序中关于书的信息: 5T$9'5V7  
0\\ueMj  
<bean:define id=”book” name=”bookDB” property=”bookDetails” type=”database.BookDetails” /> )){PBT}t]  
&jXca|wAR  
<font color=”red” size=”+2” > 629~Uc6]  
9atjK4+o  
<%= messages.getString(“CartRemoved”) %>  Z;j/K  
r3+<r<gs  
<strong><jsp:getProperty name=”book” property=”title” /></strong> aW`:)y&f  
zmy4tsmX  
</font> c W81  
* 1 |YLy  
当包含此tag的JSP页面被编译时,jsp引擎会自动生成关于此book的同步的代码(同步可以避免几个客户同时访问此book时造成的冲突),要生成同步代码,jsp引擎需要知道此脚本变量的如下信息: #;\L,a|>*  
p|&ZJ@3  
· 脚本变量名称 vHs>ba$"  
0%;N9\  
· 脚本变量所属的类 Cbgj@4H  
F:[7^GQZ{  
· 此脚本变量是否引用了一个新的或已存在的对象 ou<S)_|Iu  
3o+KP[A  
· 此脚本变量的有效性 L?=#*4t  
{f`lSu  
有两种办法可以向jsp引擎提供关于脚本变量的信息:在TLD中定义variable子元素,或用tei-class子元素定义一个额外tag信息类。用variable最简单,但可能降低了一些灵活性。 _L&n&y1+%  
IZ4W_NN  
Variable元素 ONjC(7  
rmY,v  
Variable元素有如下子元素: ]Y_{P~ZX  
\GijNn9ah  
· name-given ?D?D 给出的名字,是一个常量 -:)DX++  
Nk lz_ ]  
· name-from-attribute?D?D 属性名,在编译时给出的属性名 =&di4'`  
b34zhZ  
name-given或name-from-attribute两者必须选一,但以下子元素是可选的: 2x7(}+eD  
c&E*KfOG  
· variable-class?D?D变量的类型,缺省为java.lang.String。 bn0"M+7)f  
a za o`z  
· declare?D?D此脚本变量是否引用了一个新对象,缺省为True。 i&A{L}eCr:  
3+CSQb8  
· scope?D?D脚本变量的范围,缺省为NESTED。下表描述了scope的几种类型: 8fJR{jD(s  
/~H[= Pf  
脚本变量的有效范围 /[\6oa  
<u6c2!I{  
MZCL:#  
有效性 .@y{)/  
方法 bWGyLo,  
6@"Vqm|HD  
NESTED Si#"Wn?|  
在tag标签的开始和结束之间 o\_ Td  
如果tag处理类实现BodyTag接口,则在doInitBody和doAfterBody中调用,否则在doStartTag中调用 X4d Xm>*?=  
gbYLA a  
AT_BEGIN W0VA'W  
从tag标签的开始一直到页面结束 D3<IuWeM  
如果tag处理类实现BodyTag接口,则在doInitBody、doAfterBody和doEndTag中调用,否则在doStartTag和doEndTag中调用 >}ro[x`K  
9 b?i G  
AT_END [Xxw]C6\>(  
从tag标签的结束一直到页面结束 I["F+kt^^  
在doEndTag中调用 e(?:g@]-r  
6?53q e  
以struts为例,它的bean:define标签的实现遵循JSP1.1规范,此规范要求使用额外tag信息类来定义脚本变量。Variable元素是JSP1.2规范中加入的。以bean:define标签为例,你可以定义如下variable元素: GLo\q:5A  
0L!er%GM  
<tag> sFbfFUd  
$a`J(I  
<variable> z[WC7hvU  
fm3(70F\  
<name-from-attribute>id</name-from-attribute> J)-T:.i|0  
?F!EB4E\y}  
<variable-class>database.BookDetails</variable-class> .i MnWW  
5,F;j<F  
<declare>true</declare> Bj;\mUsk  
}*?yHJ3  
<scope>AT_BEGIN</scope> Lf5%M|o.)  
nVz5V%a!\q  
</variable> \9046An  
m,\i  
</tag> x^zdTMNhw  
I)[`ZVAXR  
额外tag信息类 W\HLal  
;l$9gD>R  
如果要定义一个额外tag信息类,你要继承javax.servlet.jsp.TagExtraInfo类。一个TagExtraInfo类必须实现getVariableInfo方法,此方法返回一个叫VariableInfo的数组类,它包括如下信息: n"(7dl?  
BmJkt3j."  
· 变量名 ZrFr`L5F;  
Bx+d3  
· 变量所属类名 *y)4D[ z-  
A ?#]s  
· 此变量是否引用了一个新对象 # .~ga7Q  
6_W<hevI  
· 此变量的有效范围 \|v`l{  
\s,Iz[0Vfz  
jsp引擎将一个名为data的参数传给getVariableInfo方法,data中包括tag标签中的所有“属性名?D?D属性值”对。它可以用来向VariableInfo对象提供脚本变量的名字和类名。 7@FDBjq  
Kp8fh-4_  
以struts为例,它在bean:define标签中定义了一个名为DefineTei的额外tag信息类,用来向脚本变量提供信息。由于脚本变量的名称(book)和类名(database.BookDetails)是通过tag标签的属性来传递的,它们一般定义在VariableInfo的构建代码中,并且可用data.getAttributeString方法来得到这些信息。如果要允许book脚本变量能在从tag开始直到整个JSP页面结束的范围内都可用的话,那它的范围应设为AT_BEGIN。如下所示: )V=0IZi  
:_>\DJ'>  
L_E^}^1!  
public class DefineTei extends TagExtraInfo xcHen/4X  
@XeEpDn]  
{ ,o BlJvm  
#]@9qPyn  
public VariableInfo[] getVariableInfo(TagData data) VK9Q?nu  
^SEc./$  
{ Tj Mb>w9  
DG3[^B  
String type = data.getAttributeString(“type”); D`en%Lf!m  
_8al  
If( type == null) +-U@0&Y3M  
pQqbZ3]  
type = “java.lang.Object”; xtOx|FkYcl  
n;%y  
return new VariableInfo[] { 6*sw,sU[y  
3QIdN  
new VariableInfo(data.getAttributeString(“id”), -RGPt D@  
FQ U\0<5  
type, g`kY]lu  
ZOp^`c9~  
true, mU50pM~/i  
]+mjOks~  
VariableInfo.AT_BEGIN) 3u*82s\8T  
j H(&oV  
}; JwjI{,jY  
A1Ka(3"  
} "t=UX -3  
&D]&UQf  
} 5qC:yI  
JfbKf~g  
L1rwIOgq^  
注意:关于额外tag信息类的类名必须要在TLD中的tag标签下的tei-class子元素中定义。因此,DefineTei的tei-class中的定义看起来如下: yji>*XG  
<tei-class> ?<! nm&~  
org.apache.struts.taglib.bean.DefineTagTei =9^Q"t4  
</tei-class> p+RAtRf  
>'N!dM.+9  
Z{} n8 b*  
具有协作关系的tag R0vww_fz  
C>4UbU  
k5wi'  
tag通过共享对象来进行协作,JSP技术支持2种方式的对象共享。 4\\.n  
WK*S4c  
第一种方法是使用pageContext对象进行对象的共享(可支持JSP页面和tag处理类之间的共享),如果在一个tag处理类中要调用由另一个tag处理类创建的对象,可调用pageContext.getAttribute(name, scope)方法。 o!=WFAi[pX  
3B;}j/h2  
第二各方式的共享是对于tag之间有嵌套关系而言的,外层的tag所创建的对象对于内层的tag来说是可以共用的。这种形式的共享的好处是减少了可能存在的重名冲突。 3I]Fdp)'  
'[Xl>Z[  
要访问一个嵌套tag创建的对象,tag处理类必须先找到此嵌套tag对象,可用TagSupport的静态方法 TagSupport.findAncestorWithClass(from, class)或TagSupport.getParent方法。前者在当不确定此tag是否为嵌套tag对象时使用。一旦它的父类被找到,它就能访问其所有动态或静态创建的对象。静态创建的对象是父类的成员,而动态创建的对象可能是父类的私有对象。诸如此类的对象可以用tag处理类的setValue方法来保存,用getValue方法来获得。 0potz]}  
V`[P4k+b   
下例阐述了以上两种共享对象的方法。在这个例子当中,一个查询tag检查一个名为connection的属性名是否在doStartTag中被设置。如果connection属性被设置,tag处理类从pageContext中得到这个connection对象。否则,此tag处理类先找到它的父tag处理类,然后从它的父tag处理类中找到connection对象。 `os8;`G  
(|dPeix|  
<~N%W#z/  
public class QueryTag extends BodyTagSupport Vg{Zv4+t  
p!}ZdX[u  
{ mW~P!7]  
U_l7CCK +  
private String connectionId; G,=F<TnI'  
D;jK/2  
public int doStartTag() throws JspException #MglHQO+  
 #I;D  
{ y+A{Y  
JD ]OIh  
String cid = getConnection(); %J _ymJ'pd  
i|S: s  
if(cid != null) p0Gk j-  
b~*i91)\  
{ F?cq'd  
5/ * >v  
//存在一个connection id,使用它。 VRF6g|0;  
L%XXf3;c  
connection = (Connection) pageContext.getAttribute(cid); ` 5#h jLe  
~p\n&{P0  
} {OCJ(^8i  
qU-!7=}7  
else nVXg,Jl  
:Jk33 N4y0  
{ 7TpRCq#  
iX%n0i  
ConnectionTag ancestorTag = (ConnectionTag)findAncestorWithClass(this, DT\ym9  
AWT"Y4Ie  
ConnectionTag.class); U<[jT=L  
Oc~aW3*A(  
if(ancestorTag == null) B6MkF"J<  
M&f#wQ  
{ w12}Rn8  
=!CU $g  
throw new JspTagException(“一个没有connection属性的查询标签必须被一个connection标记嵌套。”); W$'0Dc  
8+>\3j  
} 5ITq?%{M  
^)0 9OV+hF  
connection = ancestorTag.getConnection(); 5kn+ >{jh`  
|1Hc&  
} _B[WY  
:6D0j  
} !y. $J<  
Jq)U</  
} /H)Br~ l  
{cR=N~_EO  
Rh<N);Sl7  
DsGI/c  
此查询标签在JSP页面中的调用形式可以从以下2种定义中任选一种: %i"}x/CD[  
EnJ!mr  
g<a<*)&  
<tt:connection id=”con01” ...> ... </tt:connection> _mk5^u/u  
1TZPef^y  
<tt:query id=”balances” connection=”con01” > +s~.A_7)  
xA #H0?a]  
SELECT account, balance FROM acct_table :gf;}  
k.GA8=]>  
where customer_num = <%= request.getCustno() %> oH X$k{6  
uR_F,Mp?%u  
</tt:query> uPLErO9Es[  
m$:&P|!'p  
kjE*9bUc  
5)M 2r!\  
Fw"$A0  
<tt:connection ...> ~5 >[`)  
6Dst;:  
<x:query id=”balances”> r~>,$[|n})  
'N6 S}w7  
SELECT account, balance FROM acct_table $r79n-  
/oL8;:m  
where customer_num = <%= request.getCustno() %> y@;%Uv&  
O('Nn]wo~9  
</x:query> 9M'DC^x*T  
9/kXc4  
</tt:connection> ;^3$kF  
; )llt G  
Q9slfQ  
与此同时,在TLD中必须指定connection属性为可选的,定义如下:  g_q<ze  
cp%ii'  
<tag> ;GOz>pg  
|=5/Rax^  
... 0+`Pg  
hO( RZ '{  
<attribute> *||d\peQ  
g_z/{1$  
<name>connection</name> t&}6;z 3  
A,#2^dR  
<required>false</required> SaO3 zz@L  
{rXs:N@  
</attribute> 61@EDIYPc  
o8ppMM8_R[  
</tag>
描述
快速回复

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