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

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

级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
标准的JSP 标记可以调用JavaBeans组件或者执行客户的请求,这大大降低了JSP开发的复杂度和维护量。JSP技术也允许你自定义taglib,其实换句话说,taglib可以看成是对JSP标记的一种扩展,正如xml是对html的一种扩展一样。taglib通常定义在tag标签库中,这种标签库存放着你自己定义的tag标签。简而言之,如果使用taglib,那么你可以设计自己的JSP标记! *Qkc[XHqy  
x<ax9{  
一般来说,自定义tag标签主要用于操作隐藏对象、处理html提交表单、访问数据库或其它企业级的服务,诸如邮件和目录操作等等。自定义tag标签的使用者一般都是那些对java编程语言非常精通,而且对数据访问和企业级服务访问都非常熟悉的程序员,对于HTML设计者来说,使得他可以不去关注那些较复杂的商业逻辑,而将精力放在网页设计上。同时,它也将库开发者和库使用者进行合理分工,自定义tag标签将那些重复工作进行封装,从而大大提高了生产力,而且可以使得tag库可用于不同的项目中,完美地体现了软件复用的思想。 -(#-I $z  
 s;Y<BD  
在这篇文章中,我们主要讨论: l-.(Ez*  
XErUS80  
· 什么是自定义tag标签? *1^$.Q&  
#BY`h~&T  
· 怎么使用tag标签? #@qN8J}R  
OeElMRU"  
o 声明要使用的tag库 !aNh!  
ONX8}Ob~  
o 找到与之对应的tag处理类 +e P.s_t  
s0C:m  
o tag标签的类型 cozXb$bBY  
gU1#`r>[)  
· 自定义tag标签 U)D[]BVg  
/ty?<24ko  
o tag处理类 4(cJ^]wb^  
n~g LPHY  
o tag库描述 _A+w#kiv>  
&@v<nO-  
o tag标签示例 #E$X ,[ZFo  
}Hcx=}j  
o 带属性的tag ^6;V}2>v}  
3l4NC03I&  
o 带body的tag Tum_aI  
g|%L"-%gJ  
o 定义了脚本变量的tag C#Bz >2;#  
|< qs  
o 具有协作关系的tag +dW|^I{H}  
"y;bsZBd"  
· 自定义tag标签 F{m{d?:OA  
1|| +6bRP  
o 一个迭代tag的例子 z[nS$]u  
0g=`DSC<(  
o 一个模板tag库 E167=BD9<  
e3[:D5  
o tag处理类到底是怎样被调用的? T~xwo  
3 hKBc0  
}< 5F  
什么是自定义的tag? C~4PE>YtTv  
%.HJK  
一个自定义的tag标签是用户定义的一种JSP标记。当一个含有自定义的tag标签的JSP页面被jsp引擎编译成servlet时,tag标签被转化成了对一个称为tag处理类的对象进行的操作。于是当JSP页面被jsp引擎转化为servlet后,实际上tag标签被转化成为了对tag处理类的操作。 D g>^ A  
=!b6FjsiG  
自定义tag标签有很多特色,诸如: Pbu{'y3J  
c EnkU]  
· 可以在JSP页面中自定义tag标签的属性 3l1cyPv  
3Q By\1h.  
· 访问JSP页面中的所有对象 GK*v{`  
w:i:~f .  
· 可以动态地修改页面输出 DcD{*t?x  
<skajQQ  
· 彼此这间可以相互通信。你可以先创建一个JavaBeans组件,然后在一个tag中调用此JavaBeans组件,同时可以在另一个tag中调用它。 &1|?BZv  
ExBUpDQc  
· tag允许相互嵌套,可以在一个JSP页面中完成一些复杂的交互。 D=r))  
ZWUP^V  
/+]s.V.  
使用tag标签 vH[47CvG5  
0(TTw(;  
)c2_b  
本节主要描述怎样在JSP页面中使用tag标签,以及tag标签的不同类型。 |N/G'>TS  
YDJ4c;37  
要使用tag标签,JSP程序员必须做2件事: S$q =;"  
AyKMhac  
· 声明此tag标签的tag库 NAC_pM&B  
p=Q0!!_r  
· 实现此tag标签 d3Mva,bw<  
G3i !PwW  
声明tag标签所在的tag库 =+:{P?*}  
:mppv8bh  
如果要使用tag标签,则应用JSP的taglib指示符来指定其tag库(注意:taglib要在在使用此tag标签之前声明) -Z-f1.Dm5  
)u%je~Vw  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> ~&dyRt W4  
feM6K!fL`  
uri属性定义了唯一的标签库描述(以下简称TLD),它可以是直接是tld文件名或一个独一无二的名字。prefix是用来区别其它TLD中和本TLD中有重名的tag的一种手段。 ZP\M9Ja  
bm~W EX  
TLD必须以.tld作为扩展名,并且存放在当前应用的WEB-INF目录或其子目录下。你可以通过它的文件名直接引用它,也可以通过别的方式间接地引用它。 C4$:mJ>y  
Sl2iz?   
以下taglib指示符直接引用一个TLD: -fI`3#  
7cDU2l  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> &)d$t'7p  
BaI $S>/Q  
以下的taglib指示符通过一个逻辑名称间接地引用一个TLD: o G*5f  
M9\#Aq&\i  
<%@ taglib uri=”/tutorial-template” prefix=”tt” %> `4?~nbz  
nQX+pkJ  
如果是间接引用TLD的话,那你必须还要在web.xml中定义此逻辑名称与tld文件之间的映射,具体做法是在web.xml中加入一个名为taglib的元素: (& "su3z  
t_z>Cl^u  
<taglib> %M F;`;1  
_9 .(a  
<taglib-uri>/tutorial-template</taglib-uri> r|Z3$J{^"  
`:8J46or  
<taglib-location> pIV-kI:w  
olB)p$aH#  
/WEB-INF/tutorial-template.tld & F:IIo7  
"Mw[P [w*  
</taglib-location> 7"F*u :  
#AkV/1Y  
</taglib> h0--B]f@  
5@IB39  
-&x2&WE'  
实现此tag标签 qU2~fNY  
vy2Q g  
u-D dq~;|  
为了实现tag标签,你有2种方法来存放tag处理类。一、让tag处理类以.class的方式存放于当前应用的WEB-INF/class子目录下,二、如果tag处理类是以JAR包的形式存在的话,那可以放在当前应用的WEB-INF/lib目录下,如果tag处理类要在多个应用中共享,那么它就应放在jsp服务器上的common/lib目录下,对于tomcat来说,就是tomcat/common/lib目录下。 )~4II.`%^  
K%<j=c  
K5ZC:Ks  
tag标签类型 _ nA p6i  
k(>h^  
{e[%;W%c&  
自定义的tag标签遵循XML语法。它有一个开始标记和一个结束标记,有的还有body(即文本节点): =!O*/6rz  
/tV/85r  
<tt:tag> 'FlJpA}  
6=4wp?  
body El_wdbbT  
H&1[n U{?>  
</tt:tag> 4 %PfrJ  
cMyiW$;  
4a0:2 kIKa  
一个不带body的tag标签如下: Wt)Drv{@ {  
rk+#GO{  
<tt:tag /> O ,rwP  
H1<>NWm!v7  
Tus}\0/i>  
简单的tag标签 =9oP owq  
N8qDdr9p?c  
一个没有body和属性的tag标签如下: [U}+sTQ  
:tIC~GG]_)  
<tt:simple /> F(4?tX T  
s2?T5oWU  
Fc~'TBf,,`  
带属性的tag标签 QK0 h6CX  
.Ha'p.  
1(|D'y#  
自定义标签可以有自己的属性。属性一般在开始标记中定义,语法为 attr=”value”。属性的作用相当于自定义标签的一个参数,它影响着tag处理类的行为。你可以在TLD中详细定义它。 mRB   
]k9)G*  
你可以用一个String常量给一个属性赋值,也可以通过表达式给它赋值,如<%= ...%>。以struts为例,它的logic:present标签就是用的String常量来给属性赋值: 4}_O`Uxh  
2*(Z==XC7  
<loglic:present parameter = “Clear”> 6KD `oUx  
vN 2u34  
而另一个标签logic:iterate是用表达式来给属性赋值: wi9DhVvc 0  
1;Pv0&[q/  
<logci:iterate collection=”<%= bookDB.getBooks() %>” [V4{c@  
: ^ 8  
id=”book” type=”database.BookDetails”> "ZTTg>r  
| 8qBm  
bSVlk`  
带body的tag标签 :2njp%  
e]jH+IR:>  
一个自定义标签可以包含其它自定义标签、脚本变量、HTML标记或其它内容。 t){"Tf c:  
IbcZ@'RSw  
在下述例子中,此JSP页面使用了struts的logic:present标签,如果些标签定义了parameter=”Clear”的属性,则将清除购物车的内容,然后打印出一条信息: SQeRSz8bK4  
|_omr&[_  
<logic:present parameter=”Clear”> .{;Y'Zc14S  
gM [w1^lj  
<% cart.clear(); %> :>p8zG  
Ou{v/'9z,  
<font color=”#ff0000” size=”+2”><strong> l>Ub!^;  
0afei4i~N  
你选择了清除购物车! ,39aF*r1Q  
?$e9<lsQq)  
</strong></font> b T 2a40ul  
4t)%<4  
</logic:present> DJP2IP  
<>m }}^  
$T :un.TM  
到底是用属性还是用body来传递信息? $lhC{&tBV  
4%1D}9hO6  
如上所述,我们既可以通过属性,也可以通过body来传递信息。但一般来说,比较简单的类型,如字符串或简单表达式最好采用属性来传递信息。 }du XC[6  
*>VVt8*Et  
0flg=U9  
定义脚本变量的tag标签 RT>{*E<I  
%lg=YGLQB  
所谓脚本变量,是指JSP中可以调用的变量或对象。它可由tag标签产生。以下示例阐述了一个tag标签定义了一个名为tx的由JNDI所定义的事务处理对象。脚本变量可以是ejb对象、事务、数据库连接等等: O5H9Y}i]  
= waA`Id  
<tt:lookup id=”tx” type=”UserTransaction” name=”java:comp/UserTransaction” /> RxMH!^  
Jvun?J m  
<% tx.begin(); %> |Yq$s U  
S$2b>#@UJ  
... lY*[tmz)  
s}pIk.4ot!  
KFa_  
具有协作关系的tag标签 kh%{C] ".1  
e[Abp~@M1  
自定义tag标签之间可以通过共享对象来实现协作。在下述例子中,标签tag1创建了一个名为obj1的对象,在标签tag2仍可以重复使用obj。 3_q3Bk  
<L&m4O#|  
<tt:tag1 attr1=”obj1” value1=”value” /> pH`44KAuM  
[b:e:P 2  
<tt:tag2 attr1=”obj1” /> (|wz7 AY2  
L.]$6Q0  
在以下这个例子当中,如果外层的tag标签创建了一个对象,那么其内层的所有tag标签都可以使用这个对象。由于这样产生的对象没有一个指定的名字,那么就可以将少重名的冲突。这个例子阐述了一系列协作的嵌套对象。 Z@Ae$ '9H  
h[Gg}N!  
<tt:outerTag> 1".v6caW  
*'"^NSJ  
<tt:innerTag /> u !!X6<  
m[k_>e\ u  
</tt:outerTag> Py{ <bd  
v`1,4,;,qs  
.k[o$z\EkF  
Tag处理类 5s?Hxn  
T)\"Xj  
K!,<7[MBg  
Tag处理类必须实现Tag接口或BodyTag接口,不过现在一般都流行从TagSupport或BodyTagSupport类中继承,这些类或接口都可以在javax.servlet.jsp.tagext包中找到。 l|5fE1K9U  
H~ u[3LQz  
当JSP引擎看到自己的JSP页面中包含有tag标签时,它会调用doStartTag方法来处理tag标签的开头,调用doEndTag方法来处理tag标签的结束。 :6q]F<oK  
n<B<93f/  
下表说明不同类型的tag所需要不同的处理过程: d,$d~alY  
TY(bPq  
Tag处理类的方法 gl&5l1&  
{)AMwq  
Tag标签类型 V(Yxh+KU  
所调用的方法 ^}f -!nf[  
fh^lO ^  
基本标签 @xc',I  
doStartTag, doEndTag, release +/D>|loRC  
>3u ]OSb  
带属性的标签 Dz./w  
doStartTag, doEndTag, set/getAttribute1...N, release TE )gVE]  
`mT$s,:h  
带内容的标签 s}j1"@  
doStartTag, doEndTag, release 7OW bAu;  
=+w*gDr  
带内容的标签,且内容重复循环 ;L&TxO>#J  
doStartTag, doAfterBody, doEndTag, release E\m5%bK\B  
]59i>  
带内容的标签,且内容与JSP交互 c]B$i*t  
doStartTag, doEndTag, release, doInitBody, doAfterBody, release -YD+(c`l  
lO:. OZu  
一个tag处理类可以通过javax.servlet.jsp.PageContext来与JSP交互,通过javax.servlet.jsp.PageContext类,tag处理类可以访问JSP中的request、session和application对像。 jp' K%P  
 lWm'  
如果tag标签是互相嵌套的,那内层的tag处理类可以通过它的parent属性来访问上层的tag处理类。 Nm):9YQ/  
g,:j/vR  
一般情况都将所有的tag处理类打成了JAR的包,以便于发布。 M/Pme&%  
"n:{ !1VGw  
)etmE  
Tag库描述(简称TLD) s( <uo{  
D#S\!>m  
6!^[];%xN  
Tag库是用xml语言描述的,TLD包括了tag库中所有tag标签的描述,它一般用来被jsp服务器用来校验tag的语法正确性,或者被jsp开发者用来开发新的标签。 #0 6-:  
Q%aU42?_1  
TLD的文件扩展名必须为.tld,而且必须放在当前WEB应用的WEB-INF目录或其子目录中。 !.1%}4@Q]  
NA,C Z  
一个TLD的内容的开头必须遵守标准的XML开头,用于描述DTD和xml的版本,例如: c#N<"cy>  
_lW+>xQ  
<?xml version="1.0" encoding="ISO-8859-1" ?> ;6 +}z~  
Q!,<@b)  
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd"> 0b91y3R+  
TLD必须以<taglib>来作为它的根元素,<taglib>的子元素如下表: Vx_rc%'  
PM":Vd/  
)6~1 ^tD  
<taglib>的子元素 d3^OEwe  
rw)kAe31  
Element 0ult7s}  
Description /J)l/oI  
Jw~( G9G  
tlib-version ``ekR6[8c  
Tag库的版本 *Ywpz^2?:  
v}^5Rp&m  
jsp-version Nx#4W1B[`H  
Tag库所需要的jsp的版本 t?nX=i*~]  
D\ /xu-&  
short-name ;d$qc<2uA  
助记符,tag的一个别名(可选) Da$r`  
(J"T]-[  
uri fQ+VT|jzx  
用于确定一个唯一的tag库 ~](fFa{  
7t9c7HLuj/  
display-name &4dz}zz90  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) G= ^X1+_  
d +iR/Ssc  
small-icon TgU**JN)  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) 8&"(WuZ@  
mYB`)M*Y  
large-icon @&1Wy p  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) B@Nt`ky0*  
c':ezEaC  
description ?j7vZ}iRi  
对tag库的描述(可选) 04!(okubyp  
6)\dBOz  
listener }2)DPP:ic  
参见下面listener元素 iV.p5FD  
bt+,0\Vg5  
tag ~fz[x9\  
参见下面tag 元素 PU9`<3z5  
 0JRD  
Listener元素 !}3,B28  
151tXSzLT  
一个tag库可能定义一些类做为它的事件侦听类,这些类在TLD中被称为listener 元素,jsp服务器将会实例化这些侦听类,并且注册它们。Listener元素中有一个叫listener-class的子元素,这个元素的值必须是该侦听类的完整类名。 A CNfS9M_w  
TY;U2.Ud  
Tag元素 %>Xr5<$:&  
MQ][mMM;w  
每个tag元素在tag库中都要指出它的名字、类名、脚本变量、tag的属性。其中脚本变量的值可以直接在TLD中定义或通过tag附加信息的类来取得。每个属性描述了这个属性是否可以省略,它的值是否可以通过<%= …%>这样的JSP语法来获得,以及属性的类型。 t qOi x/  
Ccfwax+  
每一个tag在TLD中对应一个tag元素,下表是tag元素的子元素: ~!%0Z9>ap  
iZ[tHw||  
Tag元素的子元素 Q"a2.9Eo  
|c-LSs'\  
元素名称 Oi:JiD=  
描述 cTZ)"^z!  
b'>8ZIY  
name ;i#LIHJ  
独一无二的元素名 \9)[ #Ld  
Mj0Cat=  
tag-class p}]q d4j  
Tag标签对应的tag处理类 >Pe:I  
{7Cx#Ewd  
tei-class >e5zrgV  
javax.servlet.jsp.tagext.TagExtraInfo的子类,用于表达脚本变量(可选) Q882B1H  
r -f  
body-content SA6hbcYk  
Tag标签body的类型 FyD.>ot7M  
@%i>XAe#0  
display-name (0*v*kYdL+  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) {K aN,td9  
l^ 4OC  
small-icon &R]pw`mTH  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) f[/.I,9U^  
>M^&F6  
large-icon vrcE]5(:s  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) fDuwgY0  
q G ;-o)h  
description \v`#|lT$  
此tag标签的描述 ^/KfH &E  
 ';lfS  
variable |n P_<9[  
提供脚本变量的信息(同tei-class)(可选) ./maY1>T  
9EgP9up{6!  
attribute {Qtq7q.  
Tag标签的属性名 :k!j"@r  
i^%-aBZ  
以下章节介绍对于不同类型的tag,如何具体地实现它们。 < tQc_  
l=Wd,$\  
\ZnN D1A  
简单的tag OCx5/ 88X  
~"mj;5Id  
NM L|"R;  
tag处理类 DA <ynBQ  
n85r^W  
简单的tag处理类必须实现Tag接口的doStartTag和doEndTag方法。当jsp引擎碰到tag标签的开头时,doStartTag被调用,因为简单的tag没有body,所以此方法将返回 SKIP_BODY。当jsp引擎碰到tag标签的结尾时,doEndTag被调用,如果余下的页面还要被计算,那它将返回EVAL_PAGE,否则将会返回SKIP_PAGE。 J9@}DB  
5g NLO\  
以下是例子:对于标签 <tt:simple /> ,它的tag处理类实现如下: `mErF%b  
huAyjo  
\y*j4 0  
public SimpleTag extends TagSupport vj3isI4lU  
*C_[jk@6  
{ 1)U} i ^  
F!CAitxd  
public int doStartTag() throws JspException Dr 'sIH^  
[,7-w  
{ S[U/qO)m  
N#Ag'i4HF  
try{ GoeIjuELR  
k}B DA|\s  
pageContext.getOut().print(“Hello.”); ]bfqcmh<  
N$'>XtO  
}catch(Exception e){ b[g.}'^yht  
kME^tpji  
throw new JspTagException(“SimpleTag: “ + e.getMessage()); P3$,ca'  
G ]lvHD  
} : ej_D}  
AP@<r  
return SKIP_BODY; 3i(Jon/p  
uu3M{*}  
} i`~~+6`J  
jaqV[*440U  
public int doEndTag()  4Iq5+Q  
4$i}Xk#3  
{ 6F ;Or  
9r8D*PvS  
return EVAL_PAGE; t&f" jPu>  
6K// 1U$  
} J 9a $AU*  
{5 Kz'FT  
} Qtnv#9%Vi  
EW;1`x  
=, TSMV  
注意:如果tag标签没有内容的话,那必须定义body-content元素为空,例如 U?EG6t  
(fd[P|G_]  
<body-content>empty</body-content>  QT_^M1%  
VKf6|ae  
BvI 0v:  
带属性的tag标签
评价一下你浏览此帖子的感受

精彩

感动

搞笑

开心

愤怒

无聊

灌水
级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
只看该作者 1 发表于: 2007-01-01
tag处理类 UhBz<>i;!  
CwB] )QV?  
对于tag标签的每个属性,你必须依照JavaBeans规范来定义其属性,以及get和set方法。以struts的logic:present 标签为例, ^@N`e1  
(l2<+R%1  
<logic:present parameter=”Clear”> gQ,4xTX  
No~ 6s.H  
与此相应,此tag处理类应有如下方法和定义: =ty2_6&>  
K]MzP|T,  
Uk|9@Auav  
protected String parameter = null; hvL6zCi  
`{WCrw6)  
public String getParameter() yW:AVqE)t  
)Kr(Y.w  
{ $WJy?_c  
iI}nW  
return this.parameter; @M9_j{A  
>!<V\ Fj1  
} 0pCDE s  
m9k2h1  
public void setParameter(String parameter) pdy+h{]3  
eoJFh  
{ G*=H;Upi  
4(;20(q]  
this.parameter = parameter; Upu%.[7  
/:^tc/5U ]  
} ~(M*6b  
hOV_Oqe4?  
1k`|[l^  
注意:如果你的属性名为id,而且你的tag处理类是从TagSupport类继承的,那你就不需要定义它的属性和set和get方法,因为他们早已在TagSupport被定义过了。  @}Pw0vC  
s?HsUD$b  
Attribute元素 r@;$V_I  
'2j~WUEmg  
对于tag标签的每个属性,你必须定义它是否必须的,它的值是否可以用诸如<%= …%>的表达式来获得,以及它的类型(可选),如果不指定它的类型,那就默认为是java.lang.String类型。如果rtexprvalue元素被定义为true或yes,那么在type元素中就定义了attribute的返回类型。 sgR 9d  
zEAx:6`c  
<attribute> 4bWfx _0W  
}el,^~  
<name>attr1</name> &4[<F"W>47  
`c>A >c|  
<required>true|false|yes|no</required> jw/ wcP  
J511AoQ{R  
<rtexprvalue>true|false|yes|no</rtexprvalue> x[Hhj'  
;Xz(B4N~o  
<type>attribute的返回类型(只用当rtexprvalue为真是才有效)</type> aTi0bQW{  
`yy%<&  
</attribute> <'VA=orD  
/^NJ)9IB  
如果tag的某个属性不是必须的,那tag处理类会自动提供一个缺省值。 x={kjym L  
 hgNY[,  
例如,在logic:present这个tag标签中定义了一个属性叫parameter,但它不是必须的,而且它可以被诸如<%= …%>的表达式来赋值。 *?s/Ho &'  
(1OW6xtfG  
<tag> ;k-g _{M  
}D(DU5r  
<name>present</name> _8Pmv$   
yFIl^Ck%  
<tag-class>org.apache.struts.taglib.logic.PresentTag</tag-class> JHHb|  
#V,LNX)  
<body-content>JSP</body-content> 9{T 8M  
E`U &Z  
tvv[$ b&  
Al)lWD}j2g  
<attribute> }7otuO(pRo  
se }pdL}  
<name>parameter</name> 8a_ UxB  
c,+iU R<  
<required>false</required> x4/T?4k  
Bi %Z2/  
<rtexprvalue>true</rtexprvalue> ?]759,Q3L  
Fa6H(L3  
</attribute> j'#)~>b  
9@JlaY)0  
"K/[[wX\b  
X^u4%O['  
</tag> 3}v0{c  
S5zpUF=  
CD*f4I#d  
属性元素的校验 f6@^ Mg  
"h^A]t;qe  
,ZsYXW  
有关于tag标签的有效值可以从tag库的说明文档中获得,当JSP页面被编译时,jsp引擎会强制性地参照TLD中定义的规则进行检查。 7g {g}  
^U R-#WaQ  
还有一个方法也可以进行属性元素的校验,就是先继承类TagExtraInfo,然后调用它的isValid方法。这个类同时也起到提供tag中定义的脚本变量信息的作用。 gNG0k$nP  
vsOdp:Yp9!  
IsValid方法通过TagData对象来传递属性信息,它包括着tag的所有的属性名-值的信息。由于校验发生在运行时刻,因此这个属性的值将被赋值为TagData.REQUEST_TIME_VALUE。 oSpi{ $x  
oFX"F0rx  
例如tag标签<tt:twa attr1=”value1” />在TLD中定义如下: m 4wPuW  
nNkyOaK*4  
<attribute> :Bdipc  
@&/s~3  
<name>attr1</name> (jD'+ "?  
 zZS>+O  
<required>true</required> J r=REa0  
r3*+8 D~a_  
<rtexprvalue>true</rtexprvalue> $w 5#2Za  
kxt\{iy4  
</attribute> ]Om'naD  
ahK?]:&QO  
m~A[V,os  
这个定义说明了attr1能在运行期间被赋值。 R (+h)#![  
=vB]*?;9  
以下的isValid方法检查attr1属性的值是否属于Boolean类型。注意由于attr1能在运行刻被赋值,那么isValid方法必须检查tag用户是否对此tag进行了运行时刻赋值。 PT 0Qzg  
F5 :2TEA  
T)$ 6H}[c  
Public class TwaTEI extends TagExtraInfo Z1XUYe62  
!Qj)tS#Az  
{ * ePDc'   
\<0G kp  
public boolean isValid(Tagdata data) }Rf}NWU)|  
,I 9][_  
{ }3 fLV  
FU [8:o62  
Object o = data.getAttribute(“attr1”); #`fi2K&]j  
0:7v/S!:  
If(o != null && o != TagData.REQUEST_TIME_VALUE) uD0(aqAZ  
)&b}^1  
{ LS R_x$G+t  
kMfc"JXF  
if( ( (String)o).toLowerCase().equals(“true”) || dXf]G6  
AQJ|^'%  
((String)o).toLowerCase().equals(“false”) ) )3D+gu  
.b!OZ  
return true; j\i;'t}8g  
"u3fs2  
else WcV\kemf  
wsdB; 6%$  
return false; 1[fkXO{  
1 Ovx$ *  
} *o:B oP=S  
E-BOIy,  
else 0XBBA0t q  
E.zYi7YUKK  
return true; 9XJ9~I?  
.P |+oYT&g  
} 7$Z)fkx.  
T2/v}  
} IL8'{<lM  
i"2J5LLv  
@M1yBN  
带body的tag t ?Njw7  
*Dd(+NI  
]*kP>  
tag处理类 pUCEYR  
nsr _\F\  
@4W\RwD  
如果tag标签含有内容,那处理方式会略微有些不同,而且还要视tag处理类是否要与body交互的情况而定。如果要与body交互,那我们认为tag处理类要可能要对body进行操作。 di)noQXkB-  
L:k@BCQM  
Tag处理类不与body交互 @SF" )j|  
^-c si   
如果tag处理类不与body交互,tag处理类应该实现Tag接口或从TagSupport中派生,如果body要被计算,那么doStartTag方法应返回 EVAL_BODY_INCLUDE,否则应返回SKIP_BODY。 /:*R -VdF  
@@&@}IQcR1  
如果tag处理类要对body反复运算,则它应该实现IterationTag或从TagSupport中派生。如果tag处理类认为body还未计算完的话,那它的doStartTag方法和doAfterBody方法必须返回EVAL_BODY_AGAIN。 j:de}!wc  
oJ4mxi@|#  
Tag处理类与body交互 ';fU.uy  
dcrJ,>i}  
如果tag处理类与body交互,那tag处理类应实现BodyTag接口或从BodyTagSupport中派生。这种tag处理类一般要实现doInitBody和doAfterBody方法。 sTYuwna~   
U:etcnb4w>  
Body允许一些方法来读写它的内容。Tag处理类可以调用body内容的getString或getReader方法来从body中提取信息,也可用 writeOut(out) 方法来将body的内容写入到out对象中。其中out对象通过tag处理类的getPreviousOut方法来获得。 dZ;~b(CA  
M rH%hRV6R  
如果body的内容需要被计算,那么doStartTag方法必须返回EVAL_BODY_BUFFERED,否则,它将返回 SKIP_BODY。 qw Kh,[]  
ATXx? b8h  
doInitBody 方法 K\Y6 cj  
rH} Dt@  
此方法在body内容已经设好,但未被计算之前被调用。你可以根据不同的body内容来制定初始化策略。 7Dx .;  
|RvpEy7 6  
doAfterBody方法 $fj"*   
Hjo:;s  
此方法在body内容已被计算后进行调用。 RJ`/qXL  
+i q+  
和doStartTag方法一样,doAfterBody方法返回一个指示符指示是否要继续计算body,如果要继续计算,则doAfterBody应返回EVAL_BODY_BUFFERED,否则,它应返回SKIP_BODY。 $J;=Ux)$  
@Z=y'yc'y.  
release 方法 -6 7f33  
{_k!!p6  
tag处理类调用此方法将它的状态重置为初始状态,并释放所有的私有资源。 ~YT>:Np  
(`uC"MLk  
o<Rxt *B  
以下的例子读取body的内容(其中含有一条sql语句),然后将它传递给一个对象,让它进行查询。由于此处body不须重新计算,所以doAfterBody会返回SKIP_BODY。 ,Rr&.  
([4{n  
fDm}J  
Public class QueryTag extends BodyTagSupport u[6`Jr~  
Is*0?9qU  
{ ;03*qOYc  
]mJAKycE%  
public int doAfterBody() throws JspTagException W&~iO   
yW6[Fpw  
{ a s<q  
Lu#@~  
BodyContent bc = getBodyContent(); ?XTg%U  
|]2eGrGj4  
//将body的内容以字符串的格式提取出来 3Oig/KZ  
Yf2+@E  
String query = bc.getString(); 7K5o" "  
,{mf+ 3&$,  
//清除body w3]0 !) t1  
u_/OTy  
bc.clearBody(); i5~ /+~  
&oK/ ]lub  
try{ RGPU~L  
e&a[k  
Statement stmt = connection.createStatement(); >aanLLO  
Spr:K,  
Result result = stmt.executeQuery(query); :0TSOT9.  
x x`8>2T#e  
}catch(SQLException e){ #*;fQ&p  
t73Z3M  
throw new JspTagException(“queryTag: “ + e.getMessage() ); {/|8g(  
nD?M;XN  
return SKIP_BODY; $0`$)(Y  
k~s>8N:&G  
} h+'eFAZ  
$xn%i\  
} (=&bo p  
oe_[h]Hgl  
|{|r? 3  
body-content元素 G]3ML)l  
:Ro" 0/d  
{]_{BcK+  
由于tag可能会有body,你必须用body-content元素来指定body内容的类型: cI4qgV  
Z=/L6Zb  
<body-content>JSP|tagdependent</body-content> Drq{)#7  
%RD7=Z-z  
BQfAen]  
如果body的内容是定制的或内部的tag、脚本元素、或HTML广本,则归类为JSP类型。其他的类型,比如上面代码所述的?D?D将sql statement类传给 query tag的这种类型应该标为tagdependent。 J/&*OC  
E,yzy[gl  
注意:实际上body-content的值并不影响tag处理类对body内容的处理,它仅仅是被tag编辑工具用来描述此body的内容。 O t4+VbB6  
R;-FZ@u/  
IM&7h! l"|  
用tags定义脚本变量 {pJ@I=q  
Y| N vBr  
Z-sN4fr a  
tag处理类 v.^ 'x  
Kd[`mkmS  
,DUQto  
tag处理类负责创建或设置页面中定义的脚本变量,用pageContext.setAttribute(name,value,scope)或pageContext.setAttribute(name,value)方法来实现。一般来说,tag处理类通过脚本变量的名称来获取它,脚本变量的名称一般可用get方法来获得。 A = Az[  
@.]K6qC  
如果脚本变量的值依赖于tag处理类中的上下文中某一对象,那它可用pageContext.getAttribute(name,scope)方法来找到那个对象。一般的处理过程是tag处理类先找到脚本变量,再对其进行处理,然后用pageContext.setAttribute(name,object)的方法来设置它的新值。 9oau _Q#  
)1yUV*6  
对象的生存周期(scope)如下表: ujHzG}2z  
ZtK%b+MBP  
对象的生存周期表 . eag84_  
eRqexqO!  
名字 ,["|wqM  
可访问范围 2,QApW_Y  
生存周期 kE(-vE9  
QO`SnN}  
page K}*p(1$u  
当前页面 nF y7gA|  
一直有效,除非页面向客户提交响应或重定向到一个新页面 O}iKPY8K  
Q\>SF  
request c68$pgG  
当前页面或当前页面重定向到的页面 d~bH!P  
一直有效,除非页面向客户提交响应 ]~x/8%e76  
8_,wOkk_B  
session \]:NOmI^'  
当前页面或在同一浏览器窗口中的页面 g:6}zHK  
一直有效,除非关闭当前浏览器、超时、网络故障 nsw8[pk  
L5|;VH  
application SE-, 1p  
整个web应用程序的所有请求 Kz2^f@5=F  
一直有效,除非发生网络故障、服务器故障 btz3f9  
+O:pZz  
提供关于脚本变量的信息 O NzdCgY  
kk./-G  
以下示例定义了一个名为“book”的脚本变量,用来访问程序中关于书的信息: 3:gO7Uv  
v@1Jh ns  
<bean:define id=”book” name=”bookDB” property=”bookDetails” type=”database.BookDetails” /> 7}7C0mV3  
BCDf9]X  
<font color=”red” size=”+2” > ]qG5 Ne _  
n~cm?"  
<%= messages.getString(“CartRemoved”) %> l8Iy 03H  
7(iRz  
<strong><jsp:getProperty name=”book” property=”title” /></strong> hQLx"R$  
E0%Y%PQ**{  
</font> jl%e O.  
&XTd[_VW!  
当包含此tag的JSP页面被编译时,jsp引擎会自动生成关于此book的同步的代码(同步可以避免几个客户同时访问此book时造成的冲突),要生成同步代码,jsp引擎需要知道此脚本变量的如下信息: 8}b[Q/h!  
~=]@], {  
· 脚本变量名称 k  5kX  
iYs?B0*JWK  
· 脚本变量所属的类 qBrZg  
y(BLin!O.  
· 此脚本变量是否引用了一个新的或已存在的对象 e$|)wOwU  
(zODV4,5k`  
· 此脚本变量的有效性 |y=F ( 6Z  
ba:^zO^  
有两种办法可以向jsp引擎提供关于脚本变量的信息:在TLD中定义variable子元素,或用tei-class子元素定义一个额外tag信息类。用variable最简单,但可能降低了一些灵活性。 (j Q6~1  
N28?JQha  
Variable元素 D_kz R  
otVdx&%]  
Variable元素有如下子元素: 8pt<)Rs}  
FQRcZpv;  
· name-given ?D?D 给出的名字,是一个常量 `%:(IGxz  
Yzx0[_'u  
· name-from-attribute?D?D 属性名,在编译时给出的属性名 >V=@[B(0  
tce8*:rNH  
name-given或name-from-attribute两者必须选一,但以下子元素是可选的: mK/P4]9g  
&jd<rs5}  
· variable-class?D?D变量的类型,缺省为java.lang.String。 e[o ;l  
,+evP=(cX  
· declare?D?D此脚本变量是否引用了一个新对象,缺省为True。 p%_ :(  
D??/=`|8  
· scope?D?D脚本变量的范围,缺省为NESTED。下表描述了scope的几种类型: dp W%LXM_  
UC$+&&rO  
脚本变量的有效范围 q)y8Bv|  
SytDo (_=W  
&Y2P!\\2  
有效性 -zkL)<7  
方法 ``CADiM:S  
vK~KeZ\,p=  
NESTED L uK m  
在tag标签的开始和结束之间 pC Is+1O/  
如果tag处理类实现BodyTag接口,则在doInitBody和doAfterBody中调用,否则在doStartTag中调用 BkqW>[\5xm  
]a~LA7VHO  
AT_BEGIN LZ dNG\-  
从tag标签的开始一直到页面结束 r}Av"  
如果tag处理类实现BodyTag接口,则在doInitBody、doAfterBody和doEndTag中调用,否则在doStartTag和doEndTag中调用 H5t`E^E  
@x ]^blq  
AT_END n:] 1^wX#  
从tag标签的结束一直到页面结束 X}^gmu<Vla  
在doEndTag中调用 xM,(|p(  
;g9:0,xT4  
以struts为例,它的bean:define标签的实现遵循JSP1.1规范,此规范要求使用额外tag信息类来定义脚本变量。Variable元素是JSP1.2规范中加入的。以bean:define标签为例,你可以定义如下variable元素: 1<e%)? G  
>7Q7H#~w  
<tag> %*}f<k{6  
ixpG[8s  
<variable> mSeN M  
'~a$f;: Dv  
<name-from-attribute>id</name-from-attribute> 2 ZXF_ o  
Lwk-  
<variable-class>database.BookDetails</variable-class> W4Q]<<6&  
ogbdt1  
<declare>true</declare> z5w|+9U  
<-aI%'?*  
<scope>AT_BEGIN</scope> TnAX;+u  
DlO;EH  
</variable> (LPD  
w+P^c|  
</tag> yBKlp08J  
`vBa.)u  
额外tag信息类 L@GD$F=<0  
^2@~AD`&h  
如果要定义一个额外tag信息类,你要继承javax.servlet.jsp.TagExtraInfo类。一个TagExtraInfo类必须实现getVariableInfo方法,此方法返回一个叫VariableInfo的数组类,它包括如下信息: (Ad! hyE(  
l))IO`s=_  
· 变量名 63$m& ]x  
essW,2,rjC  
· 变量所属类名 8 \Oiv$r  
4tWI)}+ak  
· 此变量是否引用了一个新对象 H4jqF~  
OO>2oH  
· 此变量的有效范围 P://Zi6>  
S45_-aE  
jsp引擎将一个名为data的参数传给getVariableInfo方法,data中包括tag标签中的所有“属性名?D?D属性值”对。它可以用来向VariableInfo对象提供脚本变量的名字和类名。 !~v>&bCG>9  
(P8oXb+%  
以struts为例,它在bean:define标签中定义了一个名为DefineTei的额外tag信息类,用来向脚本变量提供信息。由于脚本变量的名称(book)和类名(database.BookDetails)是通过tag标签的属性来传递的,它们一般定义在VariableInfo的构建代码中,并且可用data.getAttributeString方法来得到这些信息。如果要允许book脚本变量能在从tag开始直到整个JSP页面结束的范围内都可用的话,那它的范围应设为AT_BEGIN。如下所示: &i RX-)^u  
GrC")Z|3u  
A>yIH)b  
public class DefineTei extends TagExtraInfo T667&@  
L\DaZ(Y  
{ < Ifnf 6~  
b*fflJ  
public VariableInfo[] getVariableInfo(TagData data) 49GCj`As  
m"]ys #  
{ M+:wa@K l  
t68RWzqiG[  
String type = data.getAttributeString(“type”); U7?ez  
pXa? Q@ 6  
If( type == null) N3) v,S-  
~G:7*:[b  
type = “java.lang.Object”; cw{[B%vw  
Y1IlH8+0  
return new VariableInfo[] { O2f2Fb$B7  
c-d}E!C:  
new VariableInfo(data.getAttributeString(“id”), w.H+$=aK  
?C3cPt"  
type, <^{:K`  
=ndKG5  
true, ak [)+_k_  
@( l`_Wx  
VariableInfo.AT_BEGIN) ?f&I"\y  
(=9&"UH  
}; c2/HY8ttRD  
#J_i 5KmXJ  
} ^ EOjq  
-&}E:zoe  
} OFv} jT  
_!zY(9%  
3FN? CN] O  
注意:关于额外tag信息类的类名必须要在TLD中的tag标签下的tei-class子元素中定义。因此,DefineTei的tei-class中的定义看起来如下: 3LR Eue7Gr  
<tei-class> RSC-+c6 1  
org.apache.struts.taglib.bean.DefineTagTei _(foJRr  
</tei-class> s=4.Ovd\  
6Y^o8R  
{J$aA6t:"T  
具有协作关系的tag $!Tw`O  
@@jdF-Utj;  
`Fj(g!`  
tag通过共享对象来进行协作,JSP技术支持2种方式的对象共享。 E12k1gC`  
KJ_R@,v\  
第一种方法是使用pageContext对象进行对象的共享(可支持JSP页面和tag处理类之间的共享),如果在一个tag处理类中要调用由另一个tag处理类创建的对象,可调用pageContext.getAttribute(name, scope)方法。 l.$#IE  
T!bu}KO  
第二各方式的共享是对于tag之间有嵌套关系而言的,外层的tag所创建的对象对于内层的tag来说是可以共用的。这种形式的共享的好处是减少了可能存在的重名冲突。 \ 714Pyy  
*b EsWeP  
要访问一个嵌套tag创建的对象,tag处理类必须先找到此嵌套tag对象,可用TagSupport的静态方法 TagSupport.findAncestorWithClass(from, class)或TagSupport.getParent方法。前者在当不确定此tag是否为嵌套tag对象时使用。一旦它的父类被找到,它就能访问其所有动态或静态创建的对象。静态创建的对象是父类的成员,而动态创建的对象可能是父类的私有对象。诸如此类的对象可以用tag处理类的setValue方法来保存,用getValue方法来获得。 pyKag;ZtP  
<h({+N  
下例阐述了以上两种共享对象的方法。在这个例子当中,一个查询tag检查一个名为connection的属性名是否在doStartTag中被设置。如果connection属性被设置,tag处理类从pageContext中得到这个connection对象。否则,此tag处理类先找到它的父tag处理类,然后从它的父tag处理类中找到connection对象。 L%FL{G  
hr5)$qZW  
43XuQg4  
public class QueryTag extends BodyTagSupport wG O)!u 4  
c3##:"wr  
{ \BL9}5y  
@#apOoVW>  
private String connectionId; Sls> OIc  
/Ny&;Y  
public int doStartTag() throws JspException +Sfv.6~v  
e=2D^ G#qE  
{ F*f)Dv$p  
]_s]Q_+E  
String cid = getConnection(); )T?ryp3ev  
/7^~*  
if(cid != null) XJ;/ kR  
00i9yC8@6  
{ N2>JG]G  
P*>V6SK>b  
//存在一个connection id,使用它。 ioggD  
!_@%/I6  
connection = (Connection) pageContext.getAttribute(cid); D_Y;N3E/rS  
FWg7 e3  
} 9\F^\h{  
ry'(m M  
else Lmb<)YY  
'' 6  
{ 4rm/+Zes  
cu-WY8n  
ConnectionTag ancestorTag = (ConnectionTag)findAncestorWithClass(this, Ty=}A MMyE  
m| Z)h{&  
ConnectionTag.class); (]:G"W8f  
F}Au'D&n_  
if(ancestorTag == null) @lwqk J  
&+v&Dd&  
{ +-hmITJ v  
F r~xN!  
throw new JspTagException(“一个没有connection属性的查询标签必须被一个connection标记嵌套。”); ?@_dx=su  
rfjQx]3pB  
} O%r<I*T^r  
>KE(%9y~  
connection = ancestorTag.getConnection(); fOVRtSls  
z?PF9QL1  
} B !XT:.+  
L" o6)N  
} nV,a|V5Xm  
cQ`,:t#[  
} ?U |lZ~o  
+~-|( y  
DcOLK\  
hXCDlCO  
此查询标签在JSP页面中的调用形式可以从以下2种定义中任选一种: .NKN2  
4:.M*Dz  
/SiQw7yp%  
<tt:connection id=”con01” ...> ... </tt:connection> ^N]*Zf~N?  
oW6.c]Vo  
<tt:query id=”balances” connection=”con01” > WCH>9Z>cj  
G.Q+"+* ^  
SELECT account, balance FROM acct_table Yr+&|;DB  
n#*cVB81  
where customer_num = <%= request.getCustno() %> f =Nm2(e  
MYjCxy-;A  
</tt:query> O%Mh g\#B  
"k.<"pf  
jzQgD ed ]  
1n^xVk-G  
~L2Fo~fw  
<tt:connection ...> `6zoZM7?Y  
Jps!,Mflc  
<x:query id=”balances”> i |t$sBIh  
9:1ZL_yf  
SELECT account, balance FROM acct_table S7bSR?~L[  
8:f( PN  
where customer_num = <%= request.getCustno() %> v[m>;Ubg&  
4h|vd.t  
</x:query> C<3An_Dy  
9I,Trk@&  
</tt:connection> V{][{5SR  
1peN@Yk2W  
'>Z Ou3>  
与此同时,在TLD中必须指定connection属性为可选的,定义如下: Q]8r72uSk  
OA_ %%A;o  
<tag> 8W{R&Z7aL  
FGC[yz1g:  
... Ae"B]Cxb_X  
]]+"`t,-  
<attribute> O?@AnkOhn  
s^cHR1^  
<name>connection</name> [8ih-k  
o.,hCg)X  
<required>false</required> C`fQ` RL\  
}u :sh >2  
</attribute> m 9r X  
kp[Jl0K5  
</tag>
描述
快速回复

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