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

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

级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
标准的JSP 标记可以调用JavaBeans组件或者执行客户的请求,这大大降低了JSP开发的复杂度和维护量。JSP技术也允许你自定义taglib,其实换句话说,taglib可以看成是对JSP标记的一种扩展,正如xml是对html的一种扩展一样。taglib通常定义在tag标签库中,这种标签库存放着你自己定义的tag标签。简而言之,如果使用taglib,那么你可以设计自己的JSP标记! Aq}]{gfQ1  
,Utp6X  
一般来说,自定义tag标签主要用于操作隐藏对象、处理html提交表单、访问数据库或其它企业级的服务,诸如邮件和目录操作等等。自定义tag标签的使用者一般都是那些对java编程语言非常精通,而且对数据访问和企业级服务访问都非常熟悉的程序员,对于HTML设计者来说,使得他可以不去关注那些较复杂的商业逻辑,而将精力放在网页设计上。同时,它也将库开发者和库使用者进行合理分工,自定义tag标签将那些重复工作进行封装,从而大大提高了生产力,而且可以使得tag库可用于不同的项目中,完美地体现了软件复用的思想。 67Z|=B !7  
. Yg)|/  
在这篇文章中,我们主要讨论: >z1RCQWju  
RZ9vQ\X U)  
· 什么是自定义tag标签? 7E4=\vM  
eZ y)>.6Z  
· 怎么使用tag标签? T@uY6))>F  
<SUjz}_Oa:  
o 声明要使用的tag库 l njaHol0  
tB4- of3+  
o 找到与之对应的tag处理类 a5:Q%F<!  
%lAJ]$m  
o tag标签的类型 Zg%U4m:  
l~wx8 ,?G  
· 自定义tag标签 ~oh=QakW  
-@-cG\{  
o tag处理类 2P~zYdjS  
M;={]w@n  
o tag库描述 b2. xJ4  
]L%qfy4  
o tag标签示例 &C<B=T"I  
|_8- 3  
o 带属性的tag ,2/qQD n/  
6$w)"Rq  
o 带body的tag d {a^  
I2(5]85&]s  
o 定义了脚本变量的tag -kxNJ Gc?  
qdrk.~_  
o 具有协作关系的tag 1Dg\\aUk  
mF [w-<:.d  
· 自定义tag标签 ScYw3i  
f@+[-yF  
o 一个迭代tag的例子 G*ZHLLO4S\  
J{Ei+@^/9  
o 一个模板tag库 :bFmw dX  
R4u=.  
o tag处理类到底是怎样被调用的? 0#KDvCBJ  
meT~b  
mdR:XuRD"t  
什么是自定义的tag? |S|0'C*  
~T9%%W[  
一个自定义的tag标签是用户定义的一种JSP标记。当一个含有自定义的tag标签的JSP页面被jsp引擎编译成servlet时,tag标签被转化成了对一个称为tag处理类的对象进行的操作。于是当JSP页面被jsp引擎转化为servlet后,实际上tag标签被转化成为了对tag处理类的操作。 hV])\t=yf  
G0Smss=K  
自定义tag标签有很多特色,诸如: ngj=w;7~+  
I4ZL +a  
· 可以在JSP页面中自定义tag标签的属性 N\1!)b  
n;)!N  
· 访问JSP页面中的所有对象 | Uf6k`  
v-J*PB.0p  
· 可以动态地修改页面输出 ;(fDR8  
Q5b?- P  
· 彼此这间可以相互通信。你可以先创建一个JavaBeans组件,然后在一个tag中调用此JavaBeans组件,同时可以在另一个tag中调用它。 h.ojj$f,  
2@@OjeANsX  
· tag允许相互嵌套,可以在一个JSP页面中完成一些复杂的交互。 LX'.up11X5  
b"t95qlL  
: I28Zi*  
使用tag标签 ao#{N=mn  
>xws  
gEbe6!; q3  
本节主要描述怎样在JSP页面中使用tag标签,以及tag标签的不同类型。 ByoSwQ  
}(z[ rZ  
要使用tag标签,JSP程序员必须做2件事: 6 uW?xB9  
N%%2!Z#  
· 声明此tag标签的tag库 ;ajCnSmR  
N_lQz(nG/2  
· 实现此tag标签 la>:%SD  
*P_(hG&c  
声明tag标签所在的tag库 }20 Q`?  
s3kHNDdC  
如果要使用tag标签,则应用JSP的taglib指示符来指定其tag库(注意:taglib要在在使用此tag标签之前声明) H%> E6rVB  
YwyP+S r\  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> ~UX@%0%)N  
0m $f9b|Q?  
uri属性定义了唯一的标签库描述(以下简称TLD),它可以是直接是tld文件名或一个独一无二的名字。prefix是用来区别其它TLD中和本TLD中有重名的tag的一种手段。 ^A dHP!I  
O%;H#3kn&s  
TLD必须以.tld作为扩展名,并且存放在当前应用的WEB-INF目录或其子目录下。你可以通过它的文件名直接引用它,也可以通过别的方式间接地引用它。 4eK!1|1  
F0W4B  
以下taglib指示符直接引用一个TLD: #\[h.4i  
a,tzt ]>  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> lfp[(Ph)9  
MWl?pG!Y  
以下的taglib指示符通过一个逻辑名称间接地引用一个TLD: q  9lz  
KSnU;B6w>  
<%@ taglib uri=”/tutorial-template” prefix=”tt” %> kg?[   
<|[G=GA\S!  
如果是间接引用TLD的话,那你必须还要在web.xml中定义此逻辑名称与tld文件之间的映射,具体做法是在web.xml中加入一个名为taglib的元素: b}< T<  
DW&%"$2  
<taglib> CRf!tsj@  
F]DRT6)  
<taglib-uri>/tutorial-template</taglib-uri> W~(@*H  
"{1`~pDj?  
<taglib-location> 8TGO6oY+=  
AVf'"~?  
/WEB-INF/tutorial-template.tld UjxEbk5>^  
YyEW}2  
</taglib-location> 8+K=3=05#U  
v7&oHOk!  
</taglib> u :AKp<'  
xDU>y  
;[TC`DuNj0  
实现此tag标签 'QW/TJ=7r  
6x|"1 G{  
'8\7(0$c  
为了实现tag标签,你有2种方法来存放tag处理类。一、让tag处理类以.class的方式存放于当前应用的WEB-INF/class子目录下,二、如果tag处理类是以JAR包的形式存在的话,那可以放在当前应用的WEB-INF/lib目录下,如果tag处理类要在多个应用中共享,那么它就应放在jsp服务器上的common/lib目录下,对于tomcat来说,就是tomcat/common/lib目录下。 V/5.37FSb  
6t/nM  
P1KXvc}JGe  
tag标签类型 m}&cXY  
vaN}M)W/  
C4wJSQl_I  
自定义的tag标签遵循XML语法。它有一个开始标记和一个结束标记,有的还有body(即文本节点): S`g:z b_  
1.*VliY  
<tt:tag> &<hDl<E  
TP7'tb  
body q-kMqnQ  
IX@g].)C  
</tt:tag> "~-H]9  
QP/%+[E.  
jej|B#?`  
一个不带body的tag标签如下: `2N&{(  
u"eO&Vc  
<tt:tag /> 8w1TX [b  
pa4,W!t  
zY_xJ"/9  
简单的tag标签 "c5C0 pK0  
bW03m_<M<1  
一个没有body和属性的tag标签如下: ,{DZvif   
f}{ lRk  
<tt:simple /> *FhD%><  
!_EL{/ko  
W,<L/ZKJ  
带属性的tag标签 J |4q9$  
xS.Rpx/8  
'](4g/%  
自定义标签可以有自己的属性。属性一般在开始标记中定义,语法为 attr=”value”。属性的作用相当于自定义标签的一个参数,它影响着tag处理类的行为。你可以在TLD中详细定义它。 HQPb  
fXfBDB  
你可以用一个String常量给一个属性赋值,也可以通过表达式给它赋值,如<%= ...%>。以struts为例,它的logic:present标签就是用的String常量来给属性赋值: 4CAV)  
74f3a|vx/  
<loglic:present parameter = “Clear”> 0-Z sV3I&  
)Dn~e#  
而另一个标签logic:iterate是用表达式来给属性赋值: s&(,_34  
&%J+d"n(  
<logci:iterate collection=”<%= bookDB.getBooks() %>” +LBDn"5  
$p_FrN{  
id=”book” type=”database.BookDetails”> [4qCW{x._  
j{}-zQ]n  
A8Z2o\+  
带body的tag标签 4cZig\mE;  
w1Ar[ P  
一个自定义标签可以包含其它自定义标签、脚本变量、HTML标记或其它内容。 fDe4 [QQ8  
55lL aus  
在下述例子中,此JSP页面使用了struts的logic:present标签,如果些标签定义了parameter=”Clear”的属性,则将清除购物车的内容,然后打印出一条信息: CbPCj.MH  
0LI:R'P+P[  
<logic:present parameter=”Clear”> 5gP<+S#>T  
X( Q*(_  
<% cart.clear(); %> zx)^!dEMM  
[t)omPy<c  
<font color=”#ff0000” size=”+2”><strong> m ,B,dqT  
iV+'p->/  
你选择了清除购物车! IX/FKSuq  
$BIQ# T>qK  
</strong></font> D2hEI2S  
OPm ?kr  
</logic:present> $xx5+A%,  
38Rod]\E  
|GmV1hN  
到底是用属性还是用body来传递信息? ~vf&JH'!  
z9> yg_Q  
如上所述,我们既可以通过属性,也可以通过body来传递信息。但一般来说,比较简单的类型,如字符串或简单表达式最好采用属性来传递信息。 *Nfn6lVB  
\Xy]z  
z^(6>U ?  
定义脚本变量的tag标签 O[nl#$w  
.-kqt^Gc  
所谓脚本变量,是指JSP中可以调用的变量或对象。它可由tag标签产生。以下示例阐述了一个tag标签定义了一个名为tx的由JNDI所定义的事务处理对象。脚本变量可以是ejb对象、事务、数据库连接等等: PqOy"HO  
5<0d2bK$  
<tt:lookup id=”tx” type=”UserTransaction” name=”java:comp/UserTransaction” /> \)?mIwo7~  
m3|KIUP  
<% tx.begin(); %> %y@iA91K  
@\~qXz{6J  
... 44s K2  
 ]J= S\  
k:?+75?$  
具有协作关系的tag标签 eFO+@  
$`nKq4Y   
自定义tag标签之间可以通过共享对象来实现协作。在下述例子中,标签tag1创建了一个名为obj1的对象,在标签tag2仍可以重复使用obj。 T9 @^@l$  
>)Ih[0~M  
<tt:tag1 attr1=”obj1” value1=”value” /> ONx|c'0g  
XTIRY4{ d  
<tt:tag2 attr1=”obj1” /> lHYu-}TNP  
R'E8>ee; ^  
在以下这个例子当中,如果外层的tag标签创建了一个对象,那么其内层的所有tag标签都可以使用这个对象。由于这样产生的对象没有一个指定的名字,那么就可以将少重名的冲突。这个例子阐述了一系列协作的嵌套对象。 Y~RZf /`  
7V/yU5  
<tt:outerTag> $D,m o2I  
doR'E=Z4h  
<tt:innerTag /> tykA69X\W  
pB @l+ n^  
</tt:outerTag> ,gU%%>-_~w  
| ?6wlf  
Q:iW k6  
Tag处理类 4SG22$7W  
C:tA|<b|  
;bt@wgY  
Tag处理类必须实现Tag接口或BodyTag接口,不过现在一般都流行从TagSupport或BodyTagSupport类中继承,这些类或接口都可以在javax.servlet.jsp.tagext包中找到。 Y`FGD25`  
,v"/3Ff{,  
当JSP引擎看到自己的JSP页面中包含有tag标签时,它会调用doStartTag方法来处理tag标签的开头,调用doEndTag方法来处理tag标签的结束。 ++KY+j.^  
+mBJvrI  
下表说明不同类型的tag所需要不同的处理过程: JOj\#!\>k0  
Q37VhScs  
Tag处理类的方法 d6lhA7  
!g? ~<`   
Tag标签类型 -Q@jL{Ue  
所调用的方法 ] =Js5  
//--r5Q  
基本标签 {$iJYS\  
doStartTag, doEndTag, release l+'1>T.I  
k&nhF9Y4  
带属性的标签 o3H+.u$  
doStartTag, doEndTag, set/getAttribute1...N, release Xco$ yF%  
Tb-`0^y&X1  
带内容的标签 'e6 W$?z  
doStartTag, doEndTag, release y)3(  
MDkIaz\U  
带内容的标签,且内容重复循环 ArkFC  
doStartTag, doAfterBody, doEndTag, release c%.f|/.k  
9X&Xs/B  
带内容的标签,且内容与JSP交互 inBd.%Yr  
doStartTag, doEndTag, release, doInitBody, doAfterBody, release H*QN/{|RU  
mRCgKW<  
一个tag处理类可以通过javax.servlet.jsp.PageContext来与JSP交互,通过javax.servlet.jsp.PageContext类,tag处理类可以访问JSP中的request、session和application对像。 R|Ft@]  
=#XsY,r  
如果tag标签是互相嵌套的,那内层的tag处理类可以通过它的parent属性来访问上层的tag处理类。 A!v-[AI[  
TJtW?c7  
一般情况都将所有的tag处理类打成了JAR的包,以便于发布。 {d$S~  
X.0/F6U  
dE5DH~ldV  
Tag库描述(简称TLD) !DnG)4#  
KmV>tn BQ  
- Pz )O@ ;  
Tag库是用xml语言描述的,TLD包括了tag库中所有tag标签的描述,它一般用来被jsp服务器用来校验tag的语法正确性,或者被jsp开发者用来开发新的标签。 ^_<>o[qE  
IidZ -Il  
TLD的文件扩展名必须为.tld,而且必须放在当前WEB应用的WEB-INF目录或其子目录中。 u)P$xkf  
3&*0n^g  
一个TLD的内容的开头必须遵守标准的XML开头,用于描述DTD和xml的版本,例如: rL URP2~  
^F*)Jq  
<?xml version="1.0" encoding="ISO-8859-1" ?> F~d !Ub$>  
sF;1)7]Pq  
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd"> +N[dYm  
TLD必须以<taglib>来作为它的根元素,<taglib>的子元素如下表: bcpH|}[F)  
Fga9  
yZ&By?.0  
<taglib>的子元素 yZ:|wxVY  
w8%yX$<  
Element F *; +-e  
Description +ZXGT  
mxHNK4/  
tlib-version _}]o~  
Tag库的版本 6,G^iv6H  
5q]u:  
jsp-version ,Ucb)8a  
Tag库所需要的jsp的版本 HZQI|  
}jd[>zk  
short-name pmCBe6n \l  
助记符,tag的一个别名(可选) i/xPO  
&3{:h  
uri SU# S'  
用于确定一个唯一的tag库 |~H'V4)zXu  
5*buRYck0  
display-name oW]&]*>J  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) wri[#D {  
zJ9ZqC]  
small-icon z!Kadqns  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选)  1 ,PFz  
f Jv 0 B*  
large-icon %8o(x 0  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) {yyg=AMz  
C>68$wd>  
description ! # tRl  
对tag库的描述(可选) ,h/0:?R KW  
U7crbj;c)d  
listener any\}   
参见下面listener元素 B_cn[?M  
2|}p&~G(  
tag 8Z3+S)6  
参见下面tag 元素 &s/aJgJhp  
?5mVC]W?]  
Listener元素 ^Hq}9OyS9  
V2/+SvB2  
一个tag库可能定义一些类做为它的事件侦听类,这些类在TLD中被称为listener 元素,jsp服务器将会实例化这些侦听类,并且注册它们。Listener元素中有一个叫listener-class的子元素,这个元素的值必须是该侦听类的完整类名。 6lT'%ho}B  
N83RsL "}_  
Tag元素 :o}7C%Q8  
`ss]\46>  
每个tag元素在tag库中都要指出它的名字、类名、脚本变量、tag的属性。其中脚本变量的值可以直接在TLD中定义或通过tag附加信息的类来取得。每个属性描述了这个属性是否可以省略,它的值是否可以通过<%= …%>这样的JSP语法来获得,以及属性的类型。  NkO$ M  
(f#W:]o/  
每一个tag在TLD中对应一个tag元素,下表是tag元素的子元素: <i`EP/x  
c<&+[{|  
Tag元素的子元素 !.t'3~dUf$  
/HzhgMV3  
元素名称 nBiSc*  
描述 kj0A%q#'}  
Y_/Kd7,\~  
name `MTOe 1  
独一无二的元素名 9:~,TH  
$E7yJ|p{  
tag-class F$ h/k^  
Tag标签对应的tag处理类 McsqMI6  
95 ]%j\  
tei-class X<9DE!/)  
javax.servlet.jsp.tagext.TagExtraInfo的子类,用于表达脚本变量(可选) Jy|Mfl%d  
.j&jf^a5  
body-content %oor7 -l  
Tag标签body的类型 g"Ii'JZ?  
wFqz.HoB  
display-name =D[h0U  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) 6  09=o+  
c7rYG]  
small-icon t1Jz?Ix6%  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) M3z7P.\G  
|9\Lv $VJ  
large-icon D[tGbk  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) d'3'{C|kk  
Ne9 .wd  
description SbI,9<  
此tag标签的描述 S?3{G@!  
W' 2)$e  
variable S'@"a%EV  
提供脚本变量的信息(同tei-class)(可选) |u}sX5/q  
Cn`% *w  
attribute uk'<9g^  
Tag标签的属性名 .`h+fqa  
O3BU.X1'%  
以下章节介绍对于不同类型的tag,如何具体地实现它们。 t o?"{  
hXr vb[6  
pP/o2  
简单的tag }bnkTC  
X r)d;@yi  
pH~JPNng  
tag处理类 gRqz8UI  
{W4t]Ff  
简单的tag处理类必须实现Tag接口的doStartTag和doEndTag方法。当jsp引擎碰到tag标签的开头时,doStartTag被调用,因为简单的tag没有body,所以此方法将返回 SKIP_BODY。当jsp引擎碰到tag标签的结尾时,doEndTag被调用,如果余下的页面还要被计算,那它将返回EVAL_PAGE,否则将会返回SKIP_PAGE。 {(MG: B  
kXjpCtCu  
以下是例子:对于标签 <tt:simple /> ,它的tag处理类实现如下: WI~%n  
VmT5? i  
^X;>?_Bk  
public SimpleTag extends TagSupport a0LX<}   
"Q J-IRt &  
{ '+QgZ>q"  
9E#(iP  
public int doStartTag() throws JspException (@#Lk"B  
+es6c')  
{ %4-pw|':  
hBqu,A  
try{ U&/S  
>S3 >b  
pageContext.getOut().print(“Hello.”); <A&R%5Vs  
*oWzH_  
}catch(Exception e){ =N0cz%  
=~S   
throw new JspTagException(“SimpleTag: “ + e.getMessage()); o{Ep/O`  
PJ.jgN(r  
} pxC5a i  
f 0#V^[%Q  
return SKIP_BODY; Arv8P P^'  
!'MD8  
} nc{ <v  
1e+?O7/  
public int doEndTag() 1&As:kv5I  
3//v{ce1]  
{ N}h%8\  
7U7 i2 4  
return EVAL_PAGE; t8+93,*B  
+]zP $5_e  
} CKur$$B  
O^$Zz<  
} m{yON&y  
syfR5wc  
qs b4@jt+  
注意:如果tag标签没有内容的话,那必须定义body-content元素为空,例如 4%7*tVG  
4>HGwk@+8  
<body-content>empty</body-content> sP |i '  
CUG<v3\  
*Wau7  
带属性的tag标签
评价一下你浏览此帖子的感受

精彩

感动

搞笑

开心

愤怒

无聊

灌水
级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
只看该作者 1 发表于: 2007-01-01
tag处理类 jY.%~Y1y  
7q=0]Hrg(D  
对于tag标签的每个属性,你必须依照JavaBeans规范来定义其属性,以及get和set方法。以struts的logic:present 标签为例, 19t*THgq  
c%!wKoD  
<logic:present parameter=”Clear”> Uf<vw3  
8(;i~f:bCW  
与此相应,此tag处理类应有如下方法和定义: 9 JtG&^*  
OXB-.<  
"lZ<bG  
protected String parameter = null; jFv<]D%A[  
Uy:.m  
public String getParameter() ?0a 0 R  
g < o;\\  
{ VLN3x.BY  
g-}sVvM  
return this.parameter; : \OvVS/  
~dLZ[6Z  
} nSiNSLv  
ZM?r1Z4  
public void setParameter(String parameter) xTZ5q*Hqx  
uSJP"Lw  
{ pAuwSn#i  
mK-:laIL"  
this.parameter = parameter; 1 %`:8  
'7R'fhiO/3  
} <k6xScy$}  
]IV; >94[  
O :^[4$~  
注意:如果你的属性名为id,而且你的tag处理类是从TagSupport类继承的,那你就不需要定义它的属性和set和get方法,因为他们早已在TagSupport被定义过了。 &/F[kAy  
R2`g?5v  
Attribute元素 (^9M9+L[i  
A~V\r<N j  
对于tag标签的每个属性,你必须定义它是否必须的,它的值是否可以用诸如<%= …%>的表达式来获得,以及它的类型(可选),如果不指定它的类型,那就默认为是java.lang.String类型。如果rtexprvalue元素被定义为true或yes,那么在type元素中就定义了attribute的返回类型。 '[^2uQc  
Q ^rW^d  
<attribute> }C1wfZ~F~  
K;y\ &'E  
<name>attr1</name> ?g4|EV-56  
)M 0O=Cl1  
<required>true|false|yes|no</required> Z(M)2  
={ '($t%|T  
<rtexprvalue>true|false|yes|no</rtexprvalue> UGt7iT<`8  
!?/bK[ P,  
<type>attribute的返回类型(只用当rtexprvalue为真是才有效)</type> :nUsC+oBS  
bicL %I2h  
</attribute> JUFO.m^w  
Q8oo5vqQ#C  
如果tag的某个属性不是必须的,那tag处理类会自动提供一个缺省值。 |plo65  
 &7&*As  
例如,在logic:present这个tag标签中定义了一个属性叫parameter,但它不是必须的,而且它可以被诸如<%= …%>的表达式来赋值。 6DW|O<k^j  
R <\Yg3m8  
<tag> ""^BW Re D  
{;DZ@2|  
<name>present</name> Dys"|,F  
E|  
<tag-class>org.apache.struts.taglib.logic.PresentTag</tag-class> qEr[fC@x  
[i1D~rCcn  
<body-content>JSP</body-content> j//wh1  
)d u{ZWr  
p9WskYpm  
vh8Kd' y  
<attribute> h_yR$H&tX  
S(h*\we  
<name>parameter</name> J)|K/W9  
Gx_e\fe-/  
<required>false</required> b.*4RL  
pw yl,A  
<rtexprvalue>true</rtexprvalue> wR4u}gb#q  
j]O[I^5  
</attribute> 6CRPdLTDf  
<h51KPo^P  
9[E$>o"%  
c[lob{,  
</tag> Ki6.'#%7  
NV4W2thYo  
/,Id_TTCO  
属性元素的校验 'a?.X _t  
$ow`)?sh  
F)kLlsp  
有关于tag标签的有效值可以从tag库的说明文档中获得,当JSP页面被编译时,jsp引擎会强制性地参照TLD中定义的规则进行检查。 <9tG_  
vXQmEIm  
还有一个方法也可以进行属性元素的校验,就是先继承类TagExtraInfo,然后调用它的isValid方法。这个类同时也起到提供tag中定义的脚本变量信息的作用。 <# r.}T.l  
7h/Q;P5  
IsValid方法通过TagData对象来传递属性信息,它包括着tag的所有的属性名-值的信息。由于校验发生在运行时刻,因此这个属性的值将被赋值为TagData.REQUEST_TIME_VALUE。 0]W]#X4A  
+STzG /9#  
例如tag标签<tt:twa attr1=”value1” />在TLD中定义如下: 72vGfT2HtZ  
=e-aZ0P  
<attribute> x>" JWD  
-L?% o_  
<name>attr1</name> 8z8SwWS?  
 .OS?^\  
<required>true</required> )}\@BtcjA]  
)ZyuF(C&  
<rtexprvalue>true</rtexprvalue> !>Y\&zA  
]mo<qWRc>p  
</attribute>  Rha3  
!&jgcw/E  
jI<WzvhYG  
这个定义说明了attr1能在运行期间被赋值。 |0R%!v(,  
oe|<xWu  
以下的isValid方法检查attr1属性的值是否属于Boolean类型。注意由于attr1能在运行刻被赋值,那么isValid方法必须检查tag用户是否对此tag进行了运行时刻赋值。 qgsE7 ]  
"d>g)rvOc  
]m#MwN$  
Public class TwaTEI extends TagExtraInfo A""*vqA  
<L ( =  
{ y"L`bl A9}  
O[p^lr(B7  
public boolean isValid(Tagdata data) gJ8 c]2c  
D)7$M]d%  
{ 0QH3,Ps1C  
MXJ9,U{<C'  
Object o = data.getAttribute(“attr1”); P^m 6di  
)r,R!8  
If(o != null && o != TagData.REQUEST_TIME_VALUE) &~A*(+S  
maEpT43f  
{ +Z~!n  
jTUf4&b-  
if( ( (String)o).toLowerCase().equals(“true”) || $RNUr \9A  
a{Hb7&  
((String)o).toLowerCase().equals(“false”) ) IetGg{h.  
(My$@l973  
return true; )u)$ `a  
a:^ Gr%  
else G$|;~'E  
UQ?OD~7  
return false; [67E5rk-  
6 %k+0\d  
} :`^3MMLO  
Cm<j*Cnl  
else S}Y|s]6  
{r2|fgi  
return true; zpr@!76  
o"}&qA;  
} OPt;G,$ta  
P ^<0d'(  
} zM r!WoW  
akCo+ @  
hd ;S>K/C  
带body的tag ck_fEF  
b hr E  
?(ls<&s{w  
tag处理类 8u5 'g1M  
,\9mAt1O  
S O:V|Tfj  
如果tag标签含有内容,那处理方式会略微有些不同,而且还要视tag处理类是否要与body交互的情况而定。如果要与body交互,那我们认为tag处理类要可能要对body进行操作。 QT= ,En  
.0fh>kQ  
Tag处理类不与body交互 9}jq`xSL  
!+DJhw&c,  
如果tag处理类不与body交互,tag处理类应该实现Tag接口或从TagSupport中派生,如果body要被计算,那么doStartTag方法应返回 EVAL_BODY_INCLUDE,否则应返回SKIP_BODY。 i|]Va44  
=Pb5b6Y@6  
如果tag处理类要对body反复运算,则它应该实现IterationTag或从TagSupport中派生。如果tag处理类认为body还未计算完的话,那它的doStartTag方法和doAfterBody方法必须返回EVAL_BODY_AGAIN。 5 -WRv;  
[aM'  
Tag处理类与body交互 Li-(p"  
C| L^Ds0  
如果tag处理类与body交互,那tag处理类应实现BodyTag接口或从BodyTagSupport中派生。这种tag处理类一般要实现doInitBody和doAfterBody方法。 $7DcQ b9  
$n#Bi.A j  
Body允许一些方法来读写它的内容。Tag处理类可以调用body内容的getString或getReader方法来从body中提取信息,也可用 writeOut(out) 方法来将body的内容写入到out对象中。其中out对象通过tag处理类的getPreviousOut方法来获得。 %::deV7  
dbuJ~?D,  
如果body的内容需要被计算,那么doStartTag方法必须返回EVAL_BODY_BUFFERED,否则,它将返回 SKIP_BODY。 6+B{4OY  
" $IXZ  
doInitBody 方法 =i^<a7M~  
4,F3@m:<  
此方法在body内容已经设好,但未被计算之前被调用。你可以根据不同的body内容来制定初始化策略。 Cq*}b4^;  
9kX=99kf[  
doAfterBody方法 =e!l=d|/  
<k\H`P  
此方法在body内容已被计算后进行调用。 c6Aut`dK  
"ryk\}*<  
和doStartTag方法一样,doAfterBody方法返回一个指示符指示是否要继续计算body,如果要继续计算,则doAfterBody应返回EVAL_BODY_BUFFERED,否则,它应返回SKIP_BODY。 ^L-w(r62<  
v]{uxlh  
release 方法 o%WjJ~!zL  
6(J4IzZ  
tag处理类调用此方法将它的状态重置为初始状态,并释放所有的私有资源。 euj8p:+X  
T<f\*1~^  
Z 5)_B,E:X  
以下的例子读取body的内容(其中含有一条sql语句),然后将它传递给一个对象,让它进行查询。由于此处body不须重新计算,所以doAfterBody会返回SKIP_BODY。 7.e7Fi{  
Vl 19Md  
95^i/6Gl!P  
Public class QueryTag extends BodyTagSupport Gkv~e?Kc~^  
\SiHrr5  
{ S2 "=B&,}  
Y%0d\{@a  
public int doAfterBody() throws JspTagException o`\.I&Ij  
wLOQhviI^-  
{ (\T0n[  
x* =sRf  
BodyContent bc = getBodyContent(); y3cf[Q  
JpxbB)/  
//将body的内容以字符串的格式提取出来 z{@R.'BD  
*|k;a]HT  
String query = bc.getString(); >^yc=mM(g3  
/j' B\,  
//清除body <wt$Gglk  
'cAc{\)  
bc.clearBody(); *j /S4qG  
Cl6m$YUt  
try{ ) Ab6!"'  
q1f=&kGX~  
Statement stmt = connection.createStatement(); .B'UQ|NR  
7Y32p'  
Result result = stmt.executeQuery(query); Y8%0;!T  
|/;U)M  
}catch(SQLException e){ Q'|0?nBOY  
OpK. Lsd0y  
throw new JspTagException(“queryTag: “ + e.getMessage() ); 8wII{FHX  
+:>JZ$  
return SKIP_BODY; kYxl1n v  
rps(Jos_~  
} yOWOU`y?  
)_77>f%  
} WgA`kT  
|As2"1_f  
bR`rT4.F  
body-content元素 JAlU%n?R  
U~*c#U"bh  
iUIy,Y  
由于tag可能会有body,你必须用body-content元素来指定body内容的类型: pd4cg?K  
g@@&sB-A"  
<body-content>JSP|tagdependent</body-content> l]_b;iux  
<Zp^lDxa  
Mny'9hsl  
如果body的内容是定制的或内部的tag、脚本元素、或HTML广本,则归类为JSP类型。其他的类型,比如上面代码所述的?D?D将sql statement类传给 query tag的这种类型应该标为tagdependent。 Z&FkLww  
i s L{9^  
注意:实际上body-content的值并不影响tag处理类对body内容的处理,它仅仅是被tag编辑工具用来描述此body的内容。 {[2tG U9  
}pMP!%|  
" F-Y^  
用tags定义脚本变量 E &7@#'l  
c[VrC+e m  
?&znUoB  
tag处理类 ,Z>wbMJig  
e=t<H"&  
P_p6GT:5  
tag处理类负责创建或设置页面中定义的脚本变量,用pageContext.setAttribute(name,value,scope)或pageContext.setAttribute(name,value)方法来实现。一般来说,tag处理类通过脚本变量的名称来获取它,脚本变量的名称一般可用get方法来获得。 Ys-Keyg  
>1x7UXs~:  
如果脚本变量的值依赖于tag处理类中的上下文中某一对象,那它可用pageContext.getAttribute(name,scope)方法来找到那个对象。一般的处理过程是tag处理类先找到脚本变量,再对其进行处理,然后用pageContext.setAttribute(name,object)的方法来设置它的新值。 )Fqy%uR8  
{~"7vkc+  
对象的生存周期(scope)如下表: {r={#mO;p  
E@w[&#  
对象的生存周期表 'h-3V8m^e  
J=UZ){c>:.  
名字 Bx(yu'g|a  
可访问范围 ! FNf>z+  
生存周期 5x8'K7/4.  
Tu]&^[B('  
page Y4mC_4EU  
当前页面 `gBD_0<T7  
一直有效,除非页面向客户提交响应或重定向到一个新页面 _QR g7  
8> UKIdp  
request Fr-[UZ~V  
当前页面或当前页面重定向到的页面 :GQ UM6  
一直有效,除非页面向客户提交响应 I4)Nb WQ  
k$C"xg2  
session Dp*:Q){>E  
当前页面或在同一浏览器窗口中的页面 8q?;2w\l  
一直有效,除非关闭当前浏览器、超时、网络故障 >']+OrQH  
C"w,('~@kW  
application GDF{Lf)/v  
整个web应用程序的所有请求 NB E pM  
一直有效,除非发生网络故障、服务器故障 $ye^uu;Z  
xXF2"+  
提供关于脚本变量的信息 (NX)o P  
ajW[eyX  
以下示例定义了一个名为“book”的脚本变量,用来访问程序中关于书的信息: nV'3sUvR#  
[#p&D~Du&  
<bean:define id=”book” name=”bookDB” property=”bookDetails” type=”database.BookDetails” /> >DL/ ..  
3&es]1b  
<font color=”red” size=”+2” > }wG,BB%N  
wGPotPdE2  
<%= messages.getString(“CartRemoved”) %> EMLx?JnP  
osl=[pm  
<strong><jsp:getProperty name=”book” property=”title” /></strong> MDk*j,5V  
+%P t_  
</font> Vo%Yf9C  
*|mz_cKu  
当包含此tag的JSP页面被编译时,jsp引擎会自动生成关于此book的同步的代码(同步可以避免几个客户同时访问此book时造成的冲突),要生成同步代码,jsp引擎需要知道此脚本变量的如下信息: |U#DUqw  
9Uk(0A  
· 脚本变量名称 /I`3dWL  
;Xqn-R  
· 脚本变量所属的类 d7* CwY9"  
Yi 6Nw+$  
· 此脚本变量是否引用了一个新的或已存在的对象 Rho5s@N7  
@0$}? 2  
· 此脚本变量的有效性 HOfF"QAR$  
qNpu}\L  
有两种办法可以向jsp引擎提供关于脚本变量的信息:在TLD中定义variable子元素,或用tei-class子元素定义一个额外tag信息类。用variable最简单,但可能降低了一些灵活性。 N[pZIH5ho=  
jZRhKT  
Variable元素 KxY$PgcC  
e#.\^   
Variable元素有如下子元素: E#8_hT]5  
~;[&K%n  
· name-given ?D?D 给出的名字,是一个常量 R2l[Q){!  
rJ DnuR  
· name-from-attribute?D?D 属性名,在编译时给出的属性名 [[w2p  
)R~aA#<>  
name-given或name-from-attribute两者必须选一,但以下子元素是可选的: (^LS']ybc  
0Q'v HZ"  
· variable-class?D?D变量的类型,缺省为java.lang.String。 & 1[y"S  
tw=K&/@^O  
· declare?D?D此脚本变量是否引用了一个新对象,缺省为True。 x=.tiM{#  
y0<U u  
· scope?D?D脚本变量的范围,缺省为NESTED。下表描述了scope的几种类型: I:i<>kG  
tRteyNA  
脚本变量的有效范围 e&0NK8&#+  
`m%:rE,  
bp#fyG"  
有效性 j&WL*XP&5  
方法 z>G;(F2  
&'s^nn]  
NESTED 8V-,Xig;`  
在tag标签的开始和结束之间 ACb/ITu  
如果tag处理类实现BodyTag接口,则在doInitBody和doAfterBody中调用,否则在doStartTag中调用 s"i~6})K<$  
,t1vb3  
AT_BEGIN A[`G^ $  
从tag标签的开始一直到页面结束 4}i*cB `  
如果tag处理类实现BodyTag接口,则在doInitBody、doAfterBody和doEndTag中调用,否则在doStartTag和doEndTag中调用 H-(q#?:  
)Vg2Jix,]  
AT_END gz;&u)  
从tag标签的结束一直到页面结束 MLV:U  
在doEndTag中调用 x` 2| }AP(  
`}gdN};  
以struts为例,它的bean:define标签的实现遵循JSP1.1规范,此规范要求使用额外tag信息类来定义脚本变量。Variable元素是JSP1.2规范中加入的。以bean:define标签为例,你可以定义如下variable元素: 4=xq:Tf  
"b]#MO}P  
<tag> FQROK4x%"  
e0 u,zg+m  
<variable> ]9*;;4M g  
`XW*kxpm  
<name-from-attribute>id</name-from-attribute> %H& ].47  
V@%  
<variable-class>database.BookDetails</variable-class> \gItZ}+c4}  
E"#Xc@  
<declare>true</declare> .%'Z~|K4  
4PWAGuN^  
<scope>AT_BEGIN</scope> @A{m5h  
K'aWCscM  
</variable> gRAC d&)  
` H XEZ|  
</tag> e3 v5,.  
vc8?I."?  
额外tag信息类  W8]V  
PK 4`5uT  
如果要定义一个额外tag信息类,你要继承javax.servlet.jsp.TagExtraInfo类。一个TagExtraInfo类必须实现getVariableInfo方法,此方法返回一个叫VariableInfo的数组类,它包括如下信息: 'eyJS`  
xx }GOY.J  
· 变量名 G 4qy*.  
&Jy)U  
· 变量所属类名 [ ]^X`R  
FRZs[\I|iT  
· 此变量是否引用了一个新对象 O4L#jBa+  
{U"^UuU]  
· 此变量的有效范围 Qf xH9_  
d"ZU y!a  
jsp引擎将一个名为data的参数传给getVariableInfo方法,data中包括tag标签中的所有“属性名?D?D属性值”对。它可以用来向VariableInfo对象提供脚本变量的名字和类名。 3F+Jdr'  
BAV>o|-K  
以struts为例,它在bean:define标签中定义了一个名为DefineTei的额外tag信息类,用来向脚本变量提供信息。由于脚本变量的名称(book)和类名(database.BookDetails)是通过tag标签的属性来传递的,它们一般定义在VariableInfo的构建代码中,并且可用data.getAttributeString方法来得到这些信息。如果要允许book脚本变量能在从tag开始直到整个JSP页面结束的范围内都可用的话,那它的范围应设为AT_BEGIN。如下所示: C!&y   
qaVy.  
mI7~c;~  
public class DefineTei extends TagExtraInfo 9JshMo  
# ??%B  
{ PB9/m-\H  
uP@\#/4u  
public VariableInfo[] getVariableInfo(TagData data) 2r&R"B1`(  
_w(ln9   
{ xx)-d,S  
pBp #a  
String type = data.getAttributeString(“type”); ?WpenUWk  
)R?;M  
If( type == null) ]]BOk  
C4\,z\Q  
type = “java.lang.Object”; 9o0!m Cq  
j U[ O  
return new VariableInfo[] { 347eis'  
E4i0i!<z  
new VariableInfo(data.getAttributeString(“id”), lA^+Flh  
W3rl^M=r  
type, e ZLMP  
+ G;LX'B  
true, >&S0#>wmyG  
aWy]9F&C:  
VariableInfo.AT_BEGIN) z ;Q<F  
2i7e#  
}; 8)yI<`q6  
5$rSEVg9  
} kKiA  
L]d-33.c!H  
} EQ<RDhC@b  
nSx]QREL!  
+4qU>  
注意:关于额外tag信息类的类名必须要在TLD中的tag标签下的tei-class子元素中定义。因此,DefineTei的tei-class中的定义看起来如下: ZA(T  
<tei-class> :I1_X  
org.apache.struts.taglib.bean.DefineTagTei \or G63T:  
</tei-class> .*YD&(  
?okx<'"[  
jS<_ )  
具有协作关系的tag )ev<7g9*q  
)]43R   
7~1IO|4t  
tag通过共享对象来进行协作,JSP技术支持2种方式的对象共享。 Vj?DA5W`'  
+&|S'7&{  
第一种方法是使用pageContext对象进行对象的共享(可支持JSP页面和tag处理类之间的共享),如果在一个tag处理类中要调用由另一个tag处理类创建的对象,可调用pageContext.getAttribute(name, scope)方法。 xV\5<7qk5g  
$uDqqG(^  
第二各方式的共享是对于tag之间有嵌套关系而言的,外层的tag所创建的对象对于内层的tag来说是可以共用的。这种形式的共享的好处是减少了可能存在的重名冲突。 TDtAmk  
]N{0:Va@D  
要访问一个嵌套tag创建的对象,tag处理类必须先找到此嵌套tag对象,可用TagSupport的静态方法 TagSupport.findAncestorWithClass(from, class)或TagSupport.getParent方法。前者在当不确定此tag是否为嵌套tag对象时使用。一旦它的父类被找到,它就能访问其所有动态或静态创建的对象。静态创建的对象是父类的成员,而动态创建的对象可能是父类的私有对象。诸如此类的对象可以用tag处理类的setValue方法来保存,用getValue方法来获得。 Anm=*;*M`  
%|"g/2sF[G  
下例阐述了以上两种共享对象的方法。在这个例子当中,一个查询tag检查一个名为connection的属性名是否在doStartTag中被设置。如果connection属性被设置,tag处理类从pageContext中得到这个connection对象。否则,此tag处理类先找到它的父tag处理类,然后从它的父tag处理类中找到connection对象。 k\`S lb1  
NbRn*nb/T  
*G5c|Y  
public class QueryTag extends BodyTagSupport 1.U`D\7mb  
Ts$@s^S]  
{ E=]4ctK  
ut2~rRiK  
private String connectionId; M@Q3M(z  
YDC&u8  
public int doStartTag() throws JspException ZD>a>]  
TX [%(ft  
{ ^|MjJsn  
Q{g;J`Z)p  
String cid = getConnection(); Tr&M~Lgb)  
{aYY85j  
if(cid != null) SHVWwoieT  
BX+.0M  
{ _-TA{21)  
BB$oq'  
//存在一个connection id,使用它。 ?sz)J 3  
dt}_D={Be  
connection = (Connection) pageContext.getAttribute(cid); gB'fFkd  
M]]pTU((  
} #/2$+x  
t2HJsMX  
else XFVV},V  
_~u2: yl (  
{ ZraT3  
rjx6Djo>  
ConnectionTag ancestorTag = (ConnectionTag)findAncestorWithClass(this, a>O9pX  
4LH[4Yj?`  
ConnectionTag.class); e4>"92hX  
*hLQ  
if(ancestorTag == null) {LHR!~d}5f  
(~~w7L s  
{ RDqFL.-S  
. #lsic8]  
throw new JspTagException(“一个没有connection属性的查询标签必须被一个connection标记嵌套。”); :Y,BdU  
/Ci*Az P  
} Kf tgOG f  
8T)&`dM6P~  
connection = ancestorTag.getConnection(); }~K`/kvs  
u+H ; @  
} !TM*o+;  
=3ioQZ^Vz  
} _5 ^I.5Z3  
%V9ZyQg%*  
} <_Z:'~Zp  
7Z ;?b0W  
^O(=Vry  
{--0 z3n>  
此查询标签在JSP页面中的调用形式可以从以下2种定义中任选一种: U6E\AvbRn  
0|&\'{  
ZK;zm  
<tt:connection id=”con01” ...> ... </tt:connection> jHXwOJq %  
'y]\-T  
<tt:query id=”balances” connection=”con01” > FTc.]laO  
mrIh0B:`  
SELECT account, balance FROM acct_table 2%RNq<{Z_  
zmj"fN{\  
where customer_num = <%= request.getCustno() %> t\P<X^d%  
*Xo]-cKL0  
</tt:query> (+uj1z^  
P 3MhU;  
~lNsa".c  
b45|vX+j  
=@,Q Dm]L  
<tt:connection ...> tE6!+c<7  
i) E|bW;  
<x:query id=”balances”> WQ yLf;!Lz  
wNFz*|n  
SELECT account, balance FROM acct_table H{J'# 9H  
g~V+4+  
where customer_num = <%= request.getCustno() %> GdV1^`M6  
~Tbj=f  
</x:query> 4P^6oh0"  
7dsefNPb  
</tt:connection> 8 C[/dH  
3(TsgP >`  
vAY,E=&XvM  
与此同时,在TLD中必须指定connection属性为可选的,定义如下: Y!iZW  
z#BR5jF  
<tag> Hbv6_H  
kKC9{^%)  
... T91moRv  
K\"R&{+=  
<attribute> u:0aM}9A  
lL1k.& |5m  
<name>connection</name> pym!U@$t  
F}Vr:~  
<required>false</required> `Al;vVMRO  
ctE\ q  
</attribute> uqz]J$  
}D+}DPL{^  
</tag>
描述
快速回复

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