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

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

级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
标准的JSP 标记可以调用JavaBeans组件或者执行客户的请求,这大大降低了JSP开发的复杂度和维护量。JSP技术也允许你自定义taglib,其实换句话说,taglib可以看成是对JSP标记的一种扩展,正如xml是对html的一种扩展一样。taglib通常定义在tag标签库中,这种标签库存放着你自己定义的tag标签。简而言之,如果使用taglib,那么你可以设计自己的JSP标记! r1]^#&V;MC  
|0-L08DW  
一般来说,自定义tag标签主要用于操作隐藏对象、处理html提交表单、访问数据库或其它企业级的服务,诸如邮件和目录操作等等。自定义tag标签的使用者一般都是那些对java编程语言非常精通,而且对数据访问和企业级服务访问都非常熟悉的程序员,对于HTML设计者来说,使得他可以不去关注那些较复杂的商业逻辑,而将精力放在网页设计上。同时,它也将库开发者和库使用者进行合理分工,自定义tag标签将那些重复工作进行封装,从而大大提高了生产力,而且可以使得tag库可用于不同的项目中,完美地体现了软件复用的思想。 H l@rS  
b}*hodzF  
在这篇文章中,我们主要讨论: qcF{Kex"  
r_m&Jl@4  
· 什么是自定义tag标签? [:qX3"B  
jo~vOu  
· 怎么使用tag标签? U"]i.J1  
[-ecKPx  
o 声明要使用的tag库 ]\lw^.%  
E?uv&evPK7  
o 找到与之对应的tag处理类 CjGI}t  
A )cb  
o tag标签的类型 HZ3<}`P_W  
i1C'  
· 自定义tag标签 <0m;|Ai'W  
R?Qou!*]  
o tag处理类 J:a^''  
QR)eJ5<  
o tag库描述 -(EqBr@_  
:JYOC+#q7  
o tag标签示例 ] W_T(C*  
OH w6#N$\  
o 带属性的tag 8J0tya"z  
I j /J  
o 带body的tag =g:\R$lQ  
jg(A_V  
o 定义了脚本变量的tag X1"nq]chGy  
zqkmsFH{  
o 具有协作关系的tag 1Rh&04O>VL  
t JP(eaqZ  
· 自定义tag标签 \!3='~2:=o  
j3>< J  
o 一个迭代tag的例子 %O${EN  
mVLGQlvVK  
o 一个模板tag库 BJ5#!I%h  
g d-fJ._1  
o tag处理类到底是怎样被调用的? mN`a]L'  
MgekLP )&  
T$e_ao|  
什么是自定义的tag? xjpW<-)MLf  
53QP~[F8R]  
一个自定义的tag标签是用户定义的一种JSP标记。当一个含有自定义的tag标签的JSP页面被jsp引擎编译成servlet时,tag标签被转化成了对一个称为tag处理类的对象进行的操作。于是当JSP页面被jsp引擎转化为servlet后,实际上tag标签被转化成为了对tag处理类的操作。 :`K;0`C +  
DH%X+r  
自定义tag标签有很多特色,诸如: J98K:SAR  
?0x;L/d])  
· 可以在JSP页面中自定义tag标签的属性 OZ6%AUot  
92i# It}-/  
· 访问JSP页面中的所有对象 ~ocr^V{"<~  
wHmEt ORo  
· 可以动态地修改页面输出 R)=<q]Ms  
?:E;C<Ar  
· 彼此这间可以相互通信。你可以先创建一个JavaBeans组件,然后在一个tag中调用此JavaBeans组件,同时可以在另一个tag中调用它。 vuf|2!kh/  
^&}Y>O,  
· tag允许相互嵌套,可以在一个JSP页面中完成一些复杂的交互。 P_gQ-pF.  
VWi-)  
|8B[yr.b  
使用tag标签 3]i1M%'i  
C6`8dn   
>7 |37a  
本节主要描述怎样在JSP页面中使用tag标签,以及tag标签的不同类型。 kL-+V)Kl  
-Da_#_F  
要使用tag标签,JSP程序员必须做2件事: Sv ,_G'  
e#wn;wo?  
· 声明此tag标签的tag库 $f+9svq  
bpzA ' g>  
· 实现此tag标签 gS%J`X$  
@;0Ep 0[  
声明tag标签所在的tag库 -3fvO~  
P1kd6]s  
如果要使用tag标签,则应用JSP的taglib指示符来指定其tag库(注意:taglib要在在使用此tag标签之前声明) seq$]  
FD<~?-  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> a'Z"Yz^Eo  
ktCh*R[`  
uri属性定义了唯一的标签库描述(以下简称TLD),它可以是直接是tld文件名或一个独一无二的名字。prefix是用来区别其它TLD中和本TLD中有重名的tag的一种手段。 ~VOmMw4HV  
G4i&:0  
TLD必须以.tld作为扩展名,并且存放在当前应用的WEB-INF目录或其子目录下。你可以通过它的文件名直接引用它,也可以通过别的方式间接地引用它。 4{Iz\:G:{/  
n;U|7it7  
以下taglib指示符直接引用一个TLD: :X^B1z3X4  
 tua+R_"  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> Ii)TCSt9U?  
wv<"W@& 9  
以下的taglib指示符通过一个逻辑名称间接地引用一个TLD: XxIUB(.QI  
\h-[u%  
<%@ taglib uri=”/tutorial-template” prefix=”tt” %> ~LVa#  
,Y*f]  
如果是间接引用TLD的话,那你必须还要在web.xml中定义此逻辑名称与tld文件之间的映射,具体做法是在web.xml中加入一个名为taglib的元素: &^EkM  
X7G6y|4;w  
<taglib> {XVSHUtw  
eg3{sDv,  
<taglib-uri>/tutorial-template</taglib-uri> /mb| %U]~  
*M="k 1P1  
<taglib-location> g%Z;rDfi  
W`Soa&9  
/WEB-INF/tutorial-template.tld loZfzN&6A  
T<OLfuV  
</taglib-location> ukw'$Yt2  
dL"v*3Fy  
</taglib> ()7=(<x{  
NM4 n  
lBCM; #P  
实现此tag标签 &(K*TB|Om  
f /jN$p  
h41v}5!-  
为了实现tag标签,你有2种方法来存放tag处理类。一、让tag处理类以.class的方式存放于当前应用的WEB-INF/class子目录下,二、如果tag处理类是以JAR包的形式存在的话,那可以放在当前应用的WEB-INF/lib目录下,如果tag处理类要在多个应用中共享,那么它就应放在jsp服务器上的common/lib目录下,对于tomcat来说,就是tomcat/common/lib目录下。 hi37p1t   
cIgF]My*D@  
1G\ugLm  
tag标签类型 yY1&h op  
=Ru i  
''Hq-Ng  
自定义的tag标签遵循XML语法。它有一个开始标记和一个结束标记,有的还有body(即文本节点): (i`DUF'#y  
Eb.{M  
<tt:tag> MG~^>  
 I{E10;  
body y]Y)?])  
W?$ ImW  
</tt:tag> y]/{W}D  
]`MRH[{  
{ "/@,!9rJ  
一个不带body的tag标签如下: ;{>z\6N  
gAE}3//  
<tt:tag /> P"- ,^?6  
X \h]N  
p5*i d5  
简单的tag标签 ?znSA >  
Bp}<H<@  
一个没有body和属性的tag标签如下: "8-]6p3u  
a9"Gg}h\  
<tt:simple /> ]Z~H9!%t  
`0sa94H1[  
IlwY5iL  
带属性的tag标签 E_xpq  
mFvw s  
`T-(g1:9  
自定义标签可以有自己的属性。属性一般在开始标记中定义,语法为 attr=”value”。属性的作用相当于自定义标签的一个参数,它影响着tag处理类的行为。你可以在TLD中详细定义它。 @A)gsDt9A  
[p]Ayo$~  
你可以用一个String常量给一个属性赋值,也可以通过表达式给它赋值,如<%= ...%>。以struts为例,它的logic:present标签就是用的String常量来给属性赋值: 7c+u+Yet  
%3q@\:s  
<loglic:present parameter = “Clear”> 5SDHZ?h  
j"c"sF\q  
而另一个标签logic:iterate是用表达式来给属性赋值: r`" ?K]rI  
b2Ct^`|M5  
<logci:iterate collection=”<%= bookDB.getBooks() %>” kcQ |Zg  
 Jl}$) '  
id=”book” type=”database.BookDetails”> 'j}%ec1  
zRB1V99k  
Q<"zpwHR  
带body的tag标签 f$P pFSY4  
g6N{Z e Wg  
一个自定义标签可以包含其它自定义标签、脚本变量、HTML标记或其它内容。 w7O(I"  
D[U5SS!)  
在下述例子中,此JSP页面使用了struts的logic:present标签,如果些标签定义了parameter=”Clear”的属性,则将清除购物车的内容,然后打印出一条信息: /P,J);Y  
?bbguwo~F  
<logic:present parameter=”Clear”> IH{g-#U  
dLv\H&  
<% cart.clear(); %> ecr pv+  
qgu.c`GmW  
<font color=”#ff0000” size=”+2”><strong> 75{QBlf<  
W$,c]/u|  
你选择了清除购物车! [/#;u*n  
z7J#1q~:yY  
</strong></font> [*,`a]z-Q  
)'nGuL-w!i  
</logic:present> b-ZvEDCR  
/ VJ[1o^  
\5J/ ?  
到底是用属性还是用body来传递信息? aG,N>0k8  
TVKuvKH8U  
如上所述,我们既可以通过属性,也可以通过body来传递信息。但一般来说,比较简单的类型,如字符串或简单表达式最好采用属性来传递信息。 5 J 0  
[ h%ci3  
*!Xhy87%Z)  
定义脚本变量的tag标签 @v|_APy#  
YT#" HYO  
所谓脚本变量,是指JSP中可以调用的变量或对象。它可由tag标签产生。以下示例阐述了一个tag标签定义了一个名为tx的由JNDI所定义的事务处理对象。脚本变量可以是ejb对象、事务、数据库连接等等: [_${N,1  
r] 2}S=[  
<tt:lookup id=”tx” type=”UserTransaction” name=”java:comp/UserTransaction” /> T#T!a0  
TC ^EyjD  
<% tx.begin(); %> qdOaibH_  
P E.^!j  
... 1C:lXx$|  
#VD[\#  
DUa`8cE}  
具有协作关系的tag标签 2TY|)ltsF  
K47W7zR  
自定义tag标签之间可以通过共享对象来实现协作。在下述例子中,标签tag1创建了一个名为obj1的对象,在标签tag2仍可以重复使用obj。 j5tA!o  
Uw4KdC  
<tt:tag1 attr1=”obj1” value1=”value” /> MLaH("aen  
q S2#=  
<tt:tag2 attr1=”obj1” /> N-;e" g  
l9#vr  
在以下这个例子当中,如果外层的tag标签创建了一个对象,那么其内层的所有tag标签都可以使用这个对象。由于这样产生的对象没有一个指定的名字,那么就可以将少重名的冲突。这个例子阐述了一系列协作的嵌套对象。 ~^G k7  
@TsOc0?-  
<tt:outerTag> }F**!%4d  
_aq3G9C_  
<tt:innerTag /> _v<EFal  
+K]kGF  
</tt:outerTag> -cEjB%Neo  
)mJl-u[0+  
4mUQVzV  
Tag处理类 YG<?|AS/  
l[.RnM[v  
6wfCC,2  
Tag处理类必须实现Tag接口或BodyTag接口,不过现在一般都流行从TagSupport或BodyTagSupport类中继承,这些类或接口都可以在javax.servlet.jsp.tagext包中找到。 i9uJ%nd:  
T[L  
当JSP引擎看到自己的JSP页面中包含有tag标签时,它会调用doStartTag方法来处理tag标签的开头,调用doEndTag方法来处理tag标签的结束。 HBeOK  
f0}+8JW5h  
下表说明不同类型的tag所需要不同的处理过程: zR">'bM:  
9 *Q/3|   
Tag处理类的方法 b4i=eI8  
^#p S u  
Tag标签类型 &`GQS|  
所调用的方法 _=8x?fC:rl  
wF[^?K '  
基本标签 jbGP`b1_  
doStartTag, doEndTag, release KE6[u*\  
H/Y ZwDx,i  
带属性的标签 Il>!C\hU  
doStartTag, doEndTag, set/getAttribute1...N, release } 5FdX3YR  
cl30"WK!  
带内容的标签 9psD"=/"  
doStartTag, doEndTag, release 6 O!&!  
8E ^yHd4Y  
带内容的标签,且内容重复循环 p'uk V(B  
doStartTag, doAfterBody, doEndTag, release gVl%:Ra%  
D?;$:D"  
带内容的标签,且内容与JSP交互 Jah~h44&  
doStartTag, doEndTag, release, doInitBody, doAfterBody, release +hqsIx  
-BgzAxa  
一个tag处理类可以通过javax.servlet.jsp.PageContext来与JSP交互,通过javax.servlet.jsp.PageContext类,tag处理类可以访问JSP中的request、session和application对像。 -(ABQgSO]  
Gr}Lp  
如果tag标签是互相嵌套的,那内层的tag处理类可以通过它的parent属性来访问上层的tag处理类。 s=#3f3  
CUaI66  
一般情况都将所有的tag处理类打成了JAR的包,以便于发布。 7xz|u\?_2  
?(n|ykXwc  
la[xbv   
Tag库描述(简称TLD) [0w @0?[  
0sLR5A  
c4k3|=f  
Tag库是用xml语言描述的,TLD包括了tag库中所有tag标签的描述,它一般用来被jsp服务器用来校验tag的语法正确性,或者被jsp开发者用来开发新的标签。 b<~\IPY  
f^Lw3|rq4  
TLD的文件扩展名必须为.tld,而且必须放在当前WEB应用的WEB-INF目录或其子目录中。 =i4Ds  
_ ^r KOd  
一个TLD的内容的开头必须遵守标准的XML开头,用于描述DTD和xml的版本,例如: {YT!vD9.  
Yu>VW\Fb  
<?xml version="1.0" encoding="ISO-8859-1" ?> 8S"vRR  
MyXgp>?~T  
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd"> AbC /  
TLD必须以<taglib>来作为它的根元素,<taglib>的子元素如下表: @or&GcQ*  
wWQv]c%  
SoI"a^fY  
<taglib>的子元素 Kzfa4C  
)#N)w5DU  
Element " +'E  
Description c~K^ooS-  
PTXy:>]M  
tlib-version TL U^ad#9E  
Tag库的版本 _p"nR  
hS/oOeG<Y  
jsp-version 6Xu8~%i  
Tag库所需要的jsp的版本 uhz:G~x!  
Y.$ '<1  
short-name FY|.eY_7 {  
助记符,tag的一个别名(可选) y'(l]F1]  
PF+v[h;,  
uri " qY Pi  
用于确定一个唯一的tag库 G'{$$+U^K  
Py3Xvudv  
display-name A]id*RtY  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) *tC]Z&5  
&.,ZU\`zT  
small-icon >jD,%yG  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) _@3@_GE  
nlQ<Aa-%  
large-icon C0|<+3uND=  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) -{dsl|Dl  
`9}\kn-</8  
description - &Aw] +  
对tag库的描述(可选) wws)**]J8  
l*T> 9yC  
listener ;I1}g]  
参见下面listener元素 hqd}L~o:  
4mq+{c0  
tag 2"*7H S  
参见下面tag 元素 K+5S7wFDZ  
po~V{>fUm  
Listener元素 S-&[Tp+N  
q-P$ \":  
一个tag库可能定义一些类做为它的事件侦听类,这些类在TLD中被称为listener 元素,jsp服务器将会实例化这些侦听类,并且注册它们。Listener元素中有一个叫listener-class的子元素,这个元素的值必须是该侦听类的完整类名。 uDJi2,|n  
~3< Li}W  
Tag元素 {p&L wTnf  
 ^AS*X2y  
每个tag元素在tag库中都要指出它的名字、类名、脚本变量、tag的属性。其中脚本变量的值可以直接在TLD中定义或通过tag附加信息的类来取得。每个属性描述了这个属性是否可以省略,它的值是否可以通过<%= …%>这样的JSP语法来获得,以及属性的类型。 UT|FV twO  
#05#@v8.f  
每一个tag在TLD中对应一个tag元素,下表是tag元素的子元素: 5-3`@ (/  
]PJb 9$f2  
Tag元素的子元素 UE^_SZ  
tkx1iBW=  
元素名称 ;3wj(o0  
描述 5RCZv\Wd&  
qPY OO  
name f<bc8Lp  
独一无二的元素名 &rj3UF@hb  
}YH@T]O}  
tag-class !$P +hX`  
Tag标签对应的tag处理类 P#H|at  
Nn5z   
tei-class q] eSDRW  
javax.servlet.jsp.tagext.TagExtraInfo的子类,用于表达脚本变量(可选) ]y= ff6Q  
Ch8w_Jf1yx  
body-content zY6{ OP!#  
Tag标签body的类型 o-"/1zLg4  
O*^=  
display-name WlVp|s{TYP  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) P[6@1  
6UOV,`:m+  
small-icon (ds-p[`[m  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) *)+1BYMo  
iLiEh2%P  
large-icon ICwhqH&  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) 1sKKmtgH  
b<o Uy  
description ,&[2z!  
此tag标签的描述 d:jD  
 yG -1g0  
variable eq +t%  
提供脚本变量的信息(同tei-class)(可选) $ K1 /^  
vcTWe$;Q  
attribute q y"VrR  
Tag标签的属性名 Sp8Xka~5*#  
d1$3~Xl]  
以下章节介绍对于不同类型的tag,如何具体地实现它们。 fZ!fwg$  
VU6nu4   
^c",!Lp}{  
简单的tag Mr'P0^^  
[!9 dA.tF  
+NL^/y<;  
tag处理类 {Wp+Y9c[  
HPJ\]HV(  
简单的tag处理类必须实现Tag接口的doStartTag和doEndTag方法。当jsp引擎碰到tag标签的开头时,doStartTag被调用,因为简单的tag没有body,所以此方法将返回 SKIP_BODY。当jsp引擎碰到tag标签的结尾时,doEndTag被调用,如果余下的页面还要被计算,那它将返回EVAL_PAGE,否则将会返回SKIP_PAGE。 )vVt{g  
Ln/6]CMl  
以下是例子:对于标签 <tt:simple /> ,它的tag处理类实现如下: >Hb>wlYR  
<8#Q5   
IH|PdVNtg  
public SimpleTag extends TagSupport )QS4Z{)U  
uJ ;7]  
{ 1d)wE4c=Z  
wO:!B\e  
public int doStartTag() throws JspException f@U\2r  
5A(zQ'6  
{ ]l\'1-/  
# LRN@?P  
try{ ~xI1@^ r  
M =Pn8<h~  
pageContext.getOut().print(“Hello.”); \z"0lAv"  
8`Wj 1 ,q  
}catch(Exception e){ V?"X0>]0  
v"'Co6fw  
throw new JspTagException(“SimpleTag: “ + e.getMessage()); m>dZ n  
Sj?u^L8es}  
} `tZu~ n  
bH+x `]{A  
return SKIP_BODY; +76{S_CZ  
ds@X%L;_  
} g=w,*68vuy  
g$C-G5/bjD  
public int doEndTag() .KiJq:$H  
WmU5YZ(mAq  
{  !]]QbB  
S |SN3)  
return EVAL_PAGE; IHqY/j  
Kjbt1n  
} eZDqW)x  
%jaB>4.A:  
} p<>x qU  
,nn5LQ|l.j  
`m2e *  
注意:如果tag标签没有内容的话,那必须定义body-content元素为空,例如 9[qEJ$--  
::13$g=T9s  
<body-content>empty</body-content> HU[a b  
,#=ykg*~/  
kO3{2$S6  
带属性的tag标签
评价一下你浏览此帖子的感受

精彩

感动

搞笑

开心

愤怒

无聊

灌水
级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
只看该作者 1 发表于: 2007-01-01
tag处理类 t;BvKH77  
q^{Z"ifL  
对于tag标签的每个属性,你必须依照JavaBeans规范来定义其属性,以及get和set方法。以struts的logic:present 标签为例, k2>gnk0  
z;Pr] *F  
<logic:present parameter=”Clear”> ]RYk Y7>`  
nya-Io.  
与此相应,此tag处理类应有如下方法和定义: X4<!E#  
U?/UW;k[  
+rEqE/QF  
protected String parameter = null; D&1*,`  
*"rgK|CM$  
public String getParameter() piIr .]  
3Cq/ o'  
{ Izrf42 >k  
/Mq]WXq[V  
return this.parameter; D>& ;K{!  
Vp3 9`m-W  
} eF8!}|*N  
npcB+6  
public void setParameter(String parameter) u Qy5t:!  
%9.] bd|%F  
{ KX*Hev'K  
$`q8-+{  
this.parameter = parameter; a }6Fj&hj  
KM$5ZbCF:  
} ?VM#Nf\  
Dd+ f,$  
%(4G[R[  
注意:如果你的属性名为id,而且你的tag处理类是从TagSupport类继承的,那你就不需要定义它的属性和set和get方法,因为他们早已在TagSupport被定义过了。 ~$g$31/  
tPO\e]  
Attribute元素 1$,t:/'-4  
gI^);J rTE  
对于tag标签的每个属性,你必须定义它是否必须的,它的值是否可以用诸如<%= …%>的表达式来获得,以及它的类型(可选),如果不指定它的类型,那就默认为是java.lang.String类型。如果rtexprvalue元素被定义为true或yes,那么在type元素中就定义了attribute的返回类型。 M1._{Jw5  
rCcNu  
<attribute> Qxds]5WB/  
)tQG5.to  
<name>attr1</name> '& L;y  
x' Z<  
<required>true|false|yes|no</required> b XcDsP$.  
bS 'a)  
<rtexprvalue>true|false|yes|no</rtexprvalue> D;bQ"P-m47  
jRz2l`~7#  
<type>attribute的返回类型(只用当rtexprvalue为真是才有效)</type> c"ukV_6~J  
75Xi%mlE7  
</attribute> XQEGMaZ  
LS:3Dtq  
如果tag的某个属性不是必须的,那tag处理类会自动提供一个缺省值。 t3 AZS0  
bH7[6#y$  
例如,在logic:present这个tag标签中定义了一个属性叫parameter,但它不是必须的,而且它可以被诸如<%= …%>的表达式来赋值。 33d86H% ;  
mT57NP  
<tag> iQ= %iou  
%N)o*H&  
<name>present</name> oOk.Fq  
'8~cf  
<tag-class>org.apache.struts.taglib.logic.PresentTag</tag-class> 4XL*e+UfJ  
G9\Bi-'ul  
<body-content>JSP</body-content> Y""-U3;T~  
yI9~LTlA3  
7Dy\-9:v  
5qco4@8  
<attribute> b6D}GuW  
]d"4G7mu`l  
<name>parameter</name> H[o'j@0  
&]~z-0`$!  
<required>false</required> }G&#pw2  
G'XlsyaWrb  
<rtexprvalue>true</rtexprvalue> bw#zMU^E  
4QWDuLu  
</attribute>  9H*$3  
&fYx0JT  
b5YjhRimS  
S~vbISl  
</tag> ZTG*|  
?uUK9*N  
8?']W\)  
属性元素的校验 HMNjQ 1y  
* [*#cMZ   
6G"AP~|0  
有关于tag标签的有效值可以从tag库的说明文档中获得,当JSP页面被编译时,jsp引擎会强制性地参照TLD中定义的规则进行检查。 *BVkviqxz  
).eT~e Gj  
还有一个方法也可以进行属性元素的校验,就是先继承类TagExtraInfo,然后调用它的isValid方法。这个类同时也起到提供tag中定义的脚本变量信息的作用。 *IzcW6 [9  
^SCZ  
IsValid方法通过TagData对象来传递属性信息,它包括着tag的所有的属性名-值的信息。由于校验发生在运行时刻,因此这个属性的值将被赋值为TagData.REQUEST_TIME_VALUE。 _<5o1  
;VS;),h/  
例如tag标签<tt:twa attr1=”value1” />在TLD中定义如下: <FH3 ePz  
bG +p  
<attribute> '#<?QE!d2  
lj.z>  
<name>attr1</name> BQf}S +  
87EI<\mP  
<required>true</required> );$Uf!v4  
'{kNXCnZ  
<rtexprvalue>true</rtexprvalue> ]+[ NX)=  
@Z!leyam  
</attribute> tklU zv  
D8_m_M| P  
+S M $#  
这个定义说明了attr1能在运行期间被赋值。 P*/px4;6  
/s6':~4  
以下的isValid方法检查attr1属性的值是否属于Boolean类型。注意由于attr1能在运行刻被赋值,那么isValid方法必须检查tag用户是否对此tag进行了运行时刻赋值。 </<_e0  
v%> ?~`Y  
?[Q;275  
Public class TwaTEI extends TagExtraInfo Z~g~,q  
=HP_IG_  
{ BZ1@?3  
r6]r+!63"  
public boolean isValid(Tagdata data) '#t"^E2$  
cl2@p@av  
{ 6+IOJtj  
6KhHS@Z  
Object o = data.getAttribute(“attr1”); 8E/$nRfO d  
AEK* w4  
If(o != null && o != TagData.REQUEST_TIME_VALUE) [8Ub#<]]  
uf`o\wqU  
{ ~/[cZY @  
po"M$4`9  
if( ( (String)o).toLowerCase().equals(“true”) ||  >0+m  
133lIX+(k  
((String)o).toLowerCase().equals(“false”) ) 2Iz@lrO6  
T~Jl{(s9)  
return true; =b,$jCv<,5  
[?W3XUJ,Y  
else L3nHvKA]  
Opmb   
return false; Pf)<6?T  
VYf$0oo\4  
} U_!"&O5lr  
?TE#4}p|  
else H1|X0 a(j  
*we3i  
return true; =0,")aa!  
)QaJYC^+  
} m*P~X*St  
9R>A,x(  
} /j -LW1:N  
i1vBg}WHN  
n5UcivyX  
带body的tag (W3R3>;  
abD55YJY  
;eG%#=>  
tag处理类  2b1LC!'U  
&Z=}H0y q  
w[PW-m^`  
如果tag标签含有内容,那处理方式会略微有些不同,而且还要视tag处理类是否要与body交互的情况而定。如果要与body交互,那我们认为tag处理类要可能要对body进行操作。 :@_CQc*yB  
n5S$Dl  
Tag处理类不与body交互 |Y/iq9l  
ErB6fl  
如果tag处理类不与body交互,tag处理类应该实现Tag接口或从TagSupport中派生,如果body要被计算,那么doStartTag方法应返回 EVAL_BODY_INCLUDE,否则应返回SKIP_BODY。 {>QrI4*A  
+ls *04  
如果tag处理类要对body反复运算,则它应该实现IterationTag或从TagSupport中派生。如果tag处理类认为body还未计算完的话,那它的doStartTag方法和doAfterBody方法必须返回EVAL_BODY_AGAIN。 ZH_ J+  
]lQhIf6)k  
Tag处理类与body交互 zfi{SO l  
M0c"wi@S_  
如果tag处理类与body交互,那tag处理类应实现BodyTag接口或从BodyTagSupport中派生。这种tag处理类一般要实现doInitBody和doAfterBody方法。 5/:Zj,41{  
ICq;jfML  
Body允许一些方法来读写它的内容。Tag处理类可以调用body内容的getString或getReader方法来从body中提取信息,也可用 writeOut(out) 方法来将body的内容写入到out对象中。其中out对象通过tag处理类的getPreviousOut方法来获得。 PKdM-R'Z  
"5XD+qi  
如果body的内容需要被计算,那么doStartTag方法必须返回EVAL_BODY_BUFFERED,否则,它将返回 SKIP_BODY。 ,n &|+&  
4x8mJ4[H^  
doInitBody 方法 e[915Q_  
JEY%(UR8  
此方法在body内容已经设好,但未被计算之前被调用。你可以根据不同的body内容来制定初始化策略。 sF_.9G)S0  
"TtK!>!.  
doAfterBody方法 a+\ Gz  
~<v`&Gm?"  
此方法在body内容已被计算后进行调用。 M%&`&{  
4,H}'@Db}  
和doStartTag方法一样,doAfterBody方法返回一个指示符指示是否要继续计算body,如果要继续计算,则doAfterBody应返回EVAL_BODY_BUFFERED,否则,它应返回SKIP_BODY。 FjiLc=RXXz  
}}t"^ms  
release 方法 BT d$n!'$n  
xZ`t~4qR  
tag处理类调用此方法将它的状态重置为初始状态,并释放所有的私有资源。 zd#qBj]g  
3p!R4f)GN  
_3A$z A  
以下的例子读取body的内容(其中含有一条sql语句),然后将它传递给一个对象,让它进行查询。由于此处body不须重新计算,所以doAfterBody会返回SKIP_BODY。 $C#~c1w  
^_5$+  
-Rjn<bTIy  
Public class QueryTag extends BodyTagSupport %<1fj#X8  
qcQ`WU{  
{ X:8=jHkz  
J_rCo4}  
public int doAfterBody() throws JspTagException EF)kYz!@  
c~R ElL  
{ \FVR'A1  
=\X<UA}  
BodyContent bc = getBodyContent(); oH6(Lq'q  
n6Q 3X  
//将body的内容以字符串的格式提取出来 )}G HG#D{  
!3yR?Xem}  
String query = bc.getString(); &e,xN;  
qf24l&}  
//清除body WHE*NWz>q  
zKfb  
bc.clearBody(); rQisk8 %  
'|Q=J)  
try{ -fUz$Df/R  
T'Jw\u>"R  
Statement stmt = connection.createStatement(); >@ H:+0h-  
3: mF!  
Result result = stmt.executeQuery(query); qV iky=/-  
Y 3KCIL9  
}catch(SQLException e){ y0(k7D|\  
d9Rj-e1x  
throw new JspTagException(“queryTag: “ + e.getMessage() ); vNE91  
N SHlo*)}  
return SKIP_BODY; iy$]9Wf6=@  
) 3Y E$,  
} P.;B V",  
[&FMVM`  
} mhlJzGr*q  
+hXph  
B>?. Nr  
body-content元素 $ P#k|A  
o6vm(I%  
Ypv"u0  
由于tag可能会有body,你必须用body-content元素来指定body内容的类型: /-BplU*"9  
|_O; U=2  
<body-content>JSP|tagdependent</body-content> i"w$D{N  
a |z{B b  
$: Qi9N   
如果body的内容是定制的或内部的tag、脚本元素、或HTML广本,则归类为JSP类型。其他的类型,比如上面代码所述的?D?D将sql statement类传给 query tag的这种类型应该标为tagdependent。 d54>nycU~N  
.P,\69g~A  
注意:实际上body-content的值并不影响tag处理类对body内容的处理,它仅仅是被tag编辑工具用来描述此body的内容。 W4>8  
3$HFHUMQsk  
A|y&\~<A  
用tags定义脚本变量 TC R(  
H.i_,ZF  
hrcR"OZ~X  
tag处理类 I9>1WT<Yy  
5[/ *UtB  
~=0zZTG  
tag处理类负责创建或设置页面中定义的脚本变量,用pageContext.setAttribute(name,value,scope)或pageContext.setAttribute(name,value)方法来实现。一般来说,tag处理类通过脚本变量的名称来获取它,脚本变量的名称一般可用get方法来获得。 4|++0=#D$  
/5yW vra  
如果脚本变量的值依赖于tag处理类中的上下文中某一对象,那它可用pageContext.getAttribute(name,scope)方法来找到那个对象。一般的处理过程是tag处理类先找到脚本变量,再对其进行处理,然后用pageContext.setAttribute(name,object)的方法来设置它的新值。 N{Is2Ia  
5,?9#n\E,  
对象的生存周期(scope)如下表: kv (N/G  
7sLs+ |<"  
对象的生存周期表 !*pK#  
o"UqI  
名字 PkG+`N  
可访问范围 S4?ss I  
生存周期 ND21;  
'{OZ[$E  
page {mkYW-4Se  
当前页面 kTC6fNj[  
一直有效,除非页面向客户提交响应或重定向到一个新页面 dAAE2}e  
oz[E>%  
request \W1?Qc1]  
当前页面或当前页面重定向到的页面 $,h*xb.  
一直有效,除非页面向客户提交响应 VnIJ$5Y  
q~l&EH0  
session .}CP Z3y  
当前页面或在同一浏览器窗口中的页面 IS'=%qhC`  
一直有效,除非关闭当前浏览器、超时、网络故障 #;^.&2Lt  
8Cm^#S,+  
application {W0]0_mI(  
整个web应用程序的所有请求 % ;6e@U}  
一直有效,除非发生网络故障、服务器故障 urog.Q  
}"xC1<]  
提供关于脚本变量的信息 *;o=hM)Tp  
p=7kFv  
以下示例定义了一个名为“book”的脚本变量,用来访问程序中关于书的信息: >#0yd7BST  
/"/$1F%{  
<bean:define id=”book” name=”bookDB” property=”bookDetails” type=”database.BookDetails” /> .6.oqb  
DUW;G9LP$-  
<font color=”red” size=”+2” > u4.-AY {  
%C)U F  
<%= messages.getString(“CartRemoved”) %> U<#i\4W  
DQ'+,bxk=9  
<strong><jsp:getProperty name=”book” property=”title” /></strong> vx-u+/\  
P5aHLNit  
</font> gQ/zk3?k  
L:B&`,E  
当包含此tag的JSP页面被编译时,jsp引擎会自动生成关于此book的同步的代码(同步可以避免几个客户同时访问此book时造成的冲突),要生成同步代码,jsp引擎需要知道此脚本变量的如下信息: fNB*o={r|  
~yO.R)4v  
· 脚本变量名称 V?5_J%  
//6m2a  
· 脚本变量所属的类 y4envjl 0  
r}vI#;&  
· 此脚本变量是否引用了一个新的或已存在的对象 .g4bV5ma3  
f#^%\K:YYR  
· 此脚本变量的有效性 M{z+=c&w  
*M KVm)Iv  
有两种办法可以向jsp引擎提供关于脚本变量的信息:在TLD中定义variable子元素,或用tei-class子元素定义一个额外tag信息类。用variable最简单,但可能降低了一些灵活性。 y< 146   
Vw)\#6FL  
Variable元素 nGyY`wt&Rg  
44_n5vp,T  
Variable元素有如下子元素: M)3h 4yQ  
D;:lw]  
· name-given ?D?D 给出的名字,是一个常量 ?rHc%H  
pGsVO5M?  
· name-from-attribute?D?D 属性名,在编译时给出的属性名 O`Z>Oon?  
X\YeO> C  
name-given或name-from-attribute两者必须选一,但以下子元素是可选的: ]`UJwq  
x{ZcF=4  
· variable-class?D?D变量的类型,缺省为java.lang.String。 |t.WPp5,  
J.O;c5wL  
· declare?D?D此脚本变量是否引用了一个新对象,缺省为True。 7dU X(D,?  
B`KpaE]  
· scope?D?D脚本变量的范围,缺省为NESTED。下表描述了scope的几种类型: 8qBw;A)  
_;0:wXib =  
脚本变量的有效范围 >GZF \ER  
?mF-zA'4]  
mXa1SZnE   
有效性 du47la 3  
方法 tpCEWdn5  
u,'c:RMV  
NESTED flmcY7ZV  
在tag标签的开始和结束之间 TYLf..i<  
如果tag处理类实现BodyTag接口,则在doInitBody和doAfterBody中调用,否则在doStartTag中调用 uswz@ [pa  
lkl#AH  
AT_BEGIN ,cbP yg  
从tag标签的开始一直到页面结束 2poU \|H  
如果tag处理类实现BodyTag接口,则在doInitBody、doAfterBody和doEndTag中调用,否则在doStartTag和doEndTag中调用 +  ^~n09  
iAXx`>}m  
AT_END DpTQPu9  
从tag标签的结束一直到页面结束 (T`x-wTl  
在doEndTag中调用 & f!!UZMt)  
~[,E i k  
以struts为例,它的bean:define标签的实现遵循JSP1.1规范,此规范要求使用额外tag信息类来定义脚本变量。Variable元素是JSP1.2规范中加入的。以bean:define标签为例,你可以定义如下variable元素: Ie+z"&0  
{~d4;ht1Y  
<tag> $v>- @  
T`vj6F  
<variable> Xv'64Nc!;  
tc# rL   
<name-from-attribute>id</name-from-attribute> guf+AVPno  
@o>2:D1G  
<variable-class>database.BookDetails</variable-class> $Y ]*v)}X  
qnT:x{o  
<declare>true</declare> NP|U |zn  
4#=^YuKaF1  
<scope>AT_BEGIN</scope> c{&sf y  
9$Hgh7'hvs  
</variable> ql_aDo j  
`Y+p7*Qr2  
</tag> eJ?SLMLY  
9]kWM]B)o  
额外tag信息类 )DoY*'Cl  
t,RR\S  
如果要定义一个额外tag信息类,你要继承javax.servlet.jsp.TagExtraInfo类。一个TagExtraInfo类必须实现getVariableInfo方法,此方法返回一个叫VariableInfo的数组类,它包括如下信息: &Cdd  
67f#Z&r2k  
· 变量名 Ho\z ^w+T`  
v'Lckw@G4  
· 变量所属类名 f5`exfdHE  
s<^UAdLnl  
· 此变量是否引用了一个新对象 lYq R6^  
"_5av!;A g  
· 此变量的有效范围 BeplS  
1L^\TC  
jsp引擎将一个名为data的参数传给getVariableInfo方法,data中包括tag标签中的所有“属性名?D?D属性值”对。它可以用来向VariableInfo对象提供脚本变量的名字和类名。 +n%WmRf6!  
qt3 \*U7x  
以struts为例,它在bean:define标签中定义了一个名为DefineTei的额外tag信息类,用来向脚本变量提供信息。由于脚本变量的名称(book)和类名(database.BookDetails)是通过tag标签的属性来传递的,它们一般定义在VariableInfo的构建代码中,并且可用data.getAttributeString方法来得到这些信息。如果要允许book脚本变量能在从tag开始直到整个JSP页面结束的范围内都可用的话,那它的范围应设为AT_BEGIN。如下所示: 3 vE;s"/  
\N;s@j W  
`)SkA?yKI  
public class DefineTei extends TagExtraInfo m2\ZnC  
(+T|B E3*#  
{ b%pLjvU  
EP{y?+E2  
public VariableInfo[] getVariableInfo(TagData data) m T\]  
=(@J+Ou  
{ GKm)wOb(*S  
< v0 d8  
String type = data.getAttributeString(“type”); YMm Fpy  
~Uga=&  
If( type == null) oBIKt S*L  
T#h`BtET[  
type = “java.lang.Object”; "9R3S[  
tohYwXN  
return new VariableInfo[] { |%TH|?kB  
-KO E2f  
new VariableInfo(data.getAttributeString(“id”), VIynlvy  
!_zmm$bR  
type, L+d_+:w  
Y$% Ze]~  
true, 4xg%OH  
XB^z' P{-Y  
VariableInfo.AT_BEGIN) -S9$C*t  
xNl_Q8Z?R^  
}; UJlKw `4  
C+2*m=r  
} O(wt[AEA  
E[ e ''  
} `) K1[&  
LVO`+:  
-w^E~J0*L  
注意:关于额外tag信息类的类名必须要在TLD中的tag标签下的tei-class子元素中定义。因此,DefineTei的tei-class中的定义看起来如下: wYNh0QlBH  
<tei-class> ].` i`.T  
org.apache.struts.taglib.bean.DefineTagTei .}]5y4UQ.  
</tei-class> iv3NmkP1  
p6I@o7f  
[ tm J6^s  
具有协作关系的tag Jfo#IRC  
*`mwm:4  
R%54!f0 %  
tag通过共享对象来进行协作,JSP技术支持2种方式的对象共享。 Hz+edM UL  
u9}=g%TV  
第一种方法是使用pageContext对象进行对象的共享(可支持JSP页面和tag处理类之间的共享),如果在一个tag处理类中要调用由另一个tag处理类创建的对象,可调用pageContext.getAttribute(name, scope)方法。 +d Ig&}Tr  
lts{<AU~  
第二各方式的共享是对于tag之间有嵌套关系而言的,外层的tag所创建的对象对于内层的tag来说是可以共用的。这种形式的共享的好处是减少了可能存在的重名冲突。 J Wof<D,  
|P~TZ  
要访问一个嵌套tag创建的对象,tag处理类必须先找到此嵌套tag对象,可用TagSupport的静态方法 TagSupport.findAncestorWithClass(from, class)或TagSupport.getParent方法。前者在当不确定此tag是否为嵌套tag对象时使用。一旦它的父类被找到,它就能访问其所有动态或静态创建的对象。静态创建的对象是父类的成员,而动态创建的对象可能是父类的私有对象。诸如此类的对象可以用tag处理类的setValue方法来保存,用getValue方法来获得。 Z>M0[DJ_  
<C]s\ "o-`  
下例阐述了以上两种共享对象的方法。在这个例子当中,一个查询tag检查一个名为connection的属性名是否在doStartTag中被设置。如果connection属性被设置,tag处理类从pageContext中得到这个connection对象。否则,此tag处理类先找到它的父tag处理类,然后从它的父tag处理类中找到connection对象。 42X[Huy]  
N(&,+KJ)  
M%yT?R+  
public class QueryTag extends BodyTagSupport )1&[uE#L  
/ey}#SHm,  
{ |Y2u=B  
+>37 'PD  
private String connectionId; $Jx] FZDQ  
YV 2T$#7u  
public int doStartTag() throws JspException JtvAi\52$  
dsrzXmE0  
{ BTGPP@p4  
</Q<*@p?  
String cid = getConnection(); ,in`JM<o  
l}K {=%U>7  
if(cid != null) 'tp+g3V  
s#-`,jqD  
{ 57D /"  
%A:<rO85o  
//存在一个connection id,使用它。 exZa:9 sp  
7n}J}8Y*U2  
connection = (Connection) pageContext.getAttribute(cid); 2NqlE  
kf.w:X"i  
} - =QA{n  
oB#KR1 >%7  
else ^Jsx^?  
jt=mK ,%  
{ r1JKTuuo  
?neXs-'-p  
ConnectionTag ancestorTag = (ConnectionTag)findAncestorWithClass(this, *)H?d  
x>Q\j>^  
ConnectionTag.class); -05#/-Z=  
dI{)^  
if(ancestorTag == null) K'Bq@6@C g  
h@@2vs2  
{ D3|y|Dr  
@e3O=_m-  
throw new JspTagException(“一个没有connection属性的查询标签必须被一个connection标记嵌套。”); 8v5cQ5Lc  
##EMJi  
} [f&ja[m q  
~UEft  
connection = ancestorTag.getConnection(); ^4h/6^b0c  
<jY"+@rF  
} 0a ZplE,  
ggXg4~WL  
} z3[ J>  
|ILj}4ZA7  
} $wub)^  
Nu<M~/  
nV@k}IJg:?  
@y2{LUJe  
此查询标签在JSP页面中的调用形式可以从以下2种定义中任选一种: >5'C<jc C  
o{37}if  
G?#f@N0.5p  
<tt:connection id=”con01” ...> ... </tt:connection> hL+)XJu^J  
)Gh"(]-<  
<tt:query id=”balances” connection=”con01” > v&(PM{3o  
71Q-_Hi  
SELECT account, balance FROM acct_table DUFfk6#X}  
{OXKXRCa  
where customer_num = <%= request.getCustno() %> M]vc W  
.m9s+D]fI  
</tt:query> L$=6R3GI  
+.! F]0ju  
xi %u)p  
~C\R!DN,  
,Hlbl}.ls  
<tt:connection ...> iqRk\yq<  
Y1h8O%?  
<x:query id=”balances”> [:&4Tp*C  
WA \ P`'lg  
SELECT account, balance FROM acct_table `07xW*K(\Y  
h;u8{t"  
where customer_num = <%= request.getCustno() %> |$f.Qs~?  
9o@5:.b<j  
</x:query> /xUTm=w7u  
{U= Mfo?AH  
</tt:connection> )! Jo7SR  
yM`J+tq  
Y(h86>z*w  
与此同时,在TLD中必须指定connection属性为可选的,定义如下: p~J|l$%0rQ  
Po~{Mpe  
<tag> ,9SBGxK5`  
w@ALl#z;}  
... IlJ!jq  
nYhI0q  
<attribute> H$bu*o-Z  
+*Y/+.4WE$  
<name>connection</name> F=?0:2P0bD  
b= amd*  
<required>false</required> x|g>Zd/n  
V+G.TI P  
</attribute> nd_+g2x'  
\qj4v^\  
</tag>
描述
快速回复

您目前还是游客,请 登录注册
如果您提交过一次失败了,可以用”恢复数据”来恢复帖子内容
认证码:
验证问题:
10+5=?,请输入中文答案:十五