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

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

级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
标准的JSP 标记可以调用JavaBeans组件或者执行客户的请求,这大大降低了JSP开发的复杂度和维护量。JSP技术也允许你自定义taglib,其实换句话说,taglib可以看成是对JSP标记的一种扩展,正如xml是对html的一种扩展一样。taglib通常定义在tag标签库中,这种标签库存放着你自己定义的tag标签。简而言之,如果使用taglib,那么你可以设计自己的JSP标记! !h23cj+V  
J\:R|KaP<p  
一般来说,自定义tag标签主要用于操作隐藏对象、处理html提交表单、访问数据库或其它企业级的服务,诸如邮件和目录操作等等。自定义tag标签的使用者一般都是那些对java编程语言非常精通,而且对数据访问和企业级服务访问都非常熟悉的程序员,对于HTML设计者来说,使得他可以不去关注那些较复杂的商业逻辑,而将精力放在网页设计上。同时,它也将库开发者和库使用者进行合理分工,自定义tag标签将那些重复工作进行封装,从而大大提高了生产力,而且可以使得tag库可用于不同的项目中,完美地体现了软件复用的思想。 mpU$ +  
,*&:2o_r  
在这篇文章中,我们主要讨论: _u5#v0Y  
$0>60<J  
· 什么是自定义tag标签? %7IugHH9y  
p93r'&Q  
· 怎么使用tag标签? t\k$};qJ  
@hiCI.?X  
o 声明要使用的tag库 /'l{E  
`(ue63AZ  
o 找到与之对应的tag处理类 _/-jX  
4U+xb>  
o tag标签的类型 7vrl'^1  
|Mu p8(gCk  
· 自定义tag标签 [B#R94  
'MUv5 Th  
o tag处理类 m.# VYN`+A  
bYpnt V  
o tag库描述 t^R][Ay&  
bnq; )>&  
o tag标签示例 ' g=  
cdl&9-}  
o 带属性的tag pN:Kdi  
bpJ(XN}E  
o 带body的tag ;g5m0l5  
-:Da&V  
o 定义了脚本变量的tag 0WZ_7C?  
-Ta9 pxZk  
o 具有协作关系的tag 8dZSi  
Lsq A**=  
· 自定义tag标签 iNtaDX| %/  
JQ8fdP A  
o 一个迭代tag的例子 r@h5w_9  
q<[P6}.  
o 一个模板tag库 zZPuha8  
e6R}0w~G  
o tag处理类到底是怎样被调用的? .h@rLorm>  
"7'J &^|  
Vd,jlt.t  
什么是自定义的tag? QdH\LL^8R4  
NO "xL,  
一个自定义的tag标签是用户定义的一种JSP标记。当一个含有自定义的tag标签的JSP页面被jsp引擎编译成servlet时,tag标签被转化成了对一个称为tag处理类的对象进行的操作。于是当JSP页面被jsp引擎转化为servlet后,实际上tag标签被转化成为了对tag处理类的操作。 0%&1\rm+j  
[R(`W#W  
自定义tag标签有很多特色,诸如: p Dx1z|@z  
WejY y|  
· 可以在JSP页面中自定义tag标签的属性 S!jTyY7e  
-LK B$   
· 访问JSP页面中的所有对象 ddJQC|xR}  
h58`XH  
· 可以动态地修改页面输出 q>_/u"  
:q$.,EZ4#n  
· 彼此这间可以相互通信。你可以先创建一个JavaBeans组件,然后在一个tag中调用此JavaBeans组件,同时可以在另一个tag中调用它。 dpAjR  
b#uL?f  
· tag允许相互嵌套,可以在一个JSP页面中完成一些复杂的交互。 2iY3Lsna  
.b3Qfxc>  
[-65PC4aN  
使用tag标签 rn/ /%  
>:AARx%  
lP[w?O  
本节主要描述怎样在JSP页面中使用tag标签,以及tag标签的不同类型。 jqWu  
iEVb"w0 59  
要使用tag标签,JSP程序员必须做2件事: 9oRy)_5Z(=  
[pC$+NX  
· 声明此tag标签的tag库 ^=BTz9QM  
ypbe!Y<i]  
· 实现此tag标签 3EV;LH L  
_GXk0Ia3`  
声明tag标签所在的tag库 K SbKEA  
j`JMeCG=Ee  
如果要使用tag标签,则应用JSP的taglib指示符来指定其tag库(注意:taglib要在在使用此tag标签之前声明) IpINH3odT  
,~aQL  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> _(_a*ml  
$*^kY;  
uri属性定义了唯一的标签库描述(以下简称TLD),它可以是直接是tld文件名或一个独一无二的名字。prefix是用来区别其它TLD中和本TLD中有重名的tag的一种手段。 mC4zactv  
@oNH@a j%  
TLD必须以.tld作为扩展名,并且存放在当前应用的WEB-INF目录或其子目录下。你可以通过它的文件名直接引用它,也可以通过别的方式间接地引用它。 Hbj,[$Jb  
#o=y?(  
以下taglib指示符直接引用一个TLD: iQ tN Aj  
Vi>,kF.f V  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> nGpXI\K  
8ZM?)# `@{  
以下的taglib指示符通过一个逻辑名称间接地引用一个TLD: gQo]  
In:9\7~jC  
<%@ taglib uri=”/tutorial-template” prefix=”tt” %> 8>trS=;n  
]9YJ,d@J  
如果是间接引用TLD的话,那你必须还要在web.xml中定义此逻辑名称与tld文件之间的映射,具体做法是在web.xml中加入一个名为taglib的元素: o9|nJ;  
Y'c>:;JEe  
<taglib> %zA;+s$l  
R}G4rO-J  
<taglib-uri>/tutorial-template</taglib-uri> yWg@v +  
Q}1 R5@7  
<taglib-location> 4H,`]B8(D  
-d~4A  
/WEB-INF/tutorial-template.tld 6DM$g=/ '  
xAqb\|$^  
</taglib-location> vL|SY_:4  
9 8j>1 "8  
</taglib> kY&k-K\  
hU(umL<  
.Obw|V-  
实现此tag标签 oo,uO;0G  
yyoqX"v[  
`s"'r !  
为了实现tag标签,你有2种方法来存放tag处理类。一、让tag处理类以.class的方式存放于当前应用的WEB-INF/class子目录下,二、如果tag处理类是以JAR包的形式存在的话,那可以放在当前应用的WEB-INF/lib目录下,如果tag处理类要在多个应用中共享,那么它就应放在jsp服务器上的common/lib目录下,对于tomcat来说,就是tomcat/common/lib目录下。 VYu~26Zr  
 W,4QzcQR  
KX!T8+Y  
tag标签类型 NhfJ30~  
;Yx)tWQI  
o]+z)5zC  
自定义的tag标签遵循XML语法。它有一个开始标记和一个结束标记,有的还有body(即文本节点): | h`0u'#  
*'OxAfa#x  
<tt:tag> vGc,vjC3x  
l,R/Gl  
body qHsUP;7  
m`IC6*  
</tt:tag> ~Fe${2   
~res V  
@x9a?L.48  
一个不带body的tag标签如下: c;%_EN%  
K\>tA)IPSV  
<tt:tag /> {s)+R[?m<o  
sSOOXdnGG  
&K[_J  
简单的tag标签 &J55P]7w  
* "R|4"uy  
一个没有body和属性的tag标签如下: K)-U1JE7  
&Flglj~7l  
<tt:simple /> e`@ # *}A  
w<C#Bka  
*7*lE"$p  
带属性的tag标签 *n; !G8\  
Q Btnx[  
rW0kA1=E  
自定义标签可以有自己的属性。属性一般在开始标记中定义,语法为 attr=”value”。属性的作用相当于自定义标签的一个参数,它影响着tag处理类的行为。你可以在TLD中详细定义它。 x N=i]~  
zw+B9PYqX  
你可以用一个String常量给一个属性赋值,也可以通过表达式给它赋值,如<%= ...%>。以struts为例,它的logic:present标签就是用的String常量来给属性赋值: flk=>h|  
H]Cy=Zi"  
<loglic:present parameter = “Clear”> 8 ![|F:  
09dK0H3(  
而另一个标签logic:iterate是用表达式来给属性赋值: B,M(@5wz  
HqI t74+  
<logci:iterate collection=”<%= bookDB.getBooks() %>” 0rh]]kj  
SLO%7%>p  
id=”book” type=”database.BookDetails”> >QA uEM  
-0?~  
'=[?~0(B  
带body的tag标签 w<zIAQN  
>G);j@Q  
一个自定义标签可以包含其它自定义标签、脚本变量、HTML标记或其它内容。 .nG#co"r}3  
|\QgX%  
在下述例子中,此JSP页面使用了struts的logic:present标签,如果些标签定义了parameter=”Clear”的属性,则将清除购物车的内容,然后打印出一条信息: >fe- d#!{  
`n$I]_}/%  
<logic:present parameter=”Clear”> {88)~  
k9)jjR*XxG  
<% cart.clear(); %> Fkvl%n  
Uh7v@YMC  
<font color=”#ff0000” size=”+2”><strong> @b"t]#V(E  
OTMJ6)n7  
你选择了清除购物车! &Ts-a$Z7?S  
8dV=[+  
</strong></font> cU0s p  
:{qv~&+C  
</logic:present> :80Z6F.k`  
f&}k^>N#3  
[`p=(/I&L  
到底是用属性还是用body来传递信息? r;>*_Oc7g  
"5;;)\o ~  
如上所述,我们既可以通过属性,也可以通过body来传递信息。但一般来说,比较简单的类型,如字符串或简单表达式最好采用属性来传递信息。 cU ? 0(z7  
eAX )^q  
Wi[~fI8^!  
定义脚本变量的tag标签 hfnN@Kg?B}  
!lEY=1nHOJ  
所谓脚本变量,是指JSP中可以调用的变量或对象。它可由tag标签产生。以下示例阐述了一个tag标签定义了一个名为tx的由JNDI所定义的事务处理对象。脚本变量可以是ejb对象、事务、数据库连接等等: qP{/[uj[K  
n3}!p'-CC  
<tt:lookup id=”tx” type=”UserTransaction” name=”java:comp/UserTransaction” /> MxSM@3v(  
ZX5xF<os8  
<% tx.begin(); %> (rkyWz  
(Q%'N3gk  
... =:DaS`~V  
M%1}/!J3  
 Mu2  
具有协作关系的tag标签 I?"q/Ub~h  
Gqcq,_?gt  
自定义tag标签之间可以通过共享对象来实现协作。在下述例子中,标签tag1创建了一个名为obj1的对象,在标签tag2仍可以重复使用obj。 bA\<.d  
(7XCA,KTGI  
<tt:tag1 attr1=”obj1” value1=”value” /> <,3^|$c%  
dY@WI[yog  
<tt:tag2 attr1=”obj1” /> fQL"O}Z  
N` aF{3[  
在以下这个例子当中,如果外层的tag标签创建了一个对象,那么其内层的所有tag标签都可以使用这个对象。由于这样产生的对象没有一个指定的名字,那么就可以将少重名的冲突。这个例子阐述了一系列协作的嵌套对象。 S|apw7C  
G2t;DN(  
<tt:outerTag> >tO`r.5u9  
g)s{ IAVx  
<tt:innerTag /> *.\  
hF@Gn/  
</tt:outerTag>  Np'2}6P  
_@ *+~9%8p  
8wVY0oRnU  
Tag处理类 >Y_*%QGH_  
]xX$<@HR  
COTp  
Tag处理类必须实现Tag接口或BodyTag接口,不过现在一般都流行从TagSupport或BodyTagSupport类中继承,这些类或接口都可以在javax.servlet.jsp.tagext包中找到。 ~=8uN<  
0{dz5gUde  
当JSP引擎看到自己的JSP页面中包含有tag标签时,它会调用doStartTag方法来处理tag标签的开头,调用doEndTag方法来处理tag标签的结束。 qw@puw@D  
L:_bg8eD#  
下表说明不同类型的tag所需要不同的处理过程: YyTSyP4  
ua5OGx  
Tag处理类的方法 k]5Bykf`Ky  
A|L8P  
Tag标签类型 fO0(Z  
所调用的方法 "I=\[l8t  
([-|}  
基本标签 @y82L8G/  
doStartTag, doEndTag, release ?[)}l9  
OiE;B  
带属性的标签 YnxRg  
doStartTag, doEndTag, set/getAttribute1...N, release 'XzXZJ[uq  
:JfE QIN  
带内容的标签 %^1cyk  
doStartTag, doEndTag, release b&=5m  
p/U+0f  
带内容的标签,且内容重复循环 mp9{m`Jb*  
doStartTag, doAfterBody, doEndTag, release &Y 4F!Rb  
'@jXbN  
带内容的标签,且内容与JSP交互 DyQM>xw)t  
doStartTag, doEndTag, release, doInitBody, doAfterBody, release =JKv:</.G  
RRGWC$>?  
一个tag处理类可以通过javax.servlet.jsp.PageContext来与JSP交互,通过javax.servlet.jsp.PageContext类,tag处理类可以访问JSP中的request、session和application对像。 br0++}vwL  
z]2]XTmWs  
如果tag标签是互相嵌套的,那内层的tag处理类可以通过它的parent属性来访问上层的tag处理类。 MXzVgy  
2Fz|fW_  
一般情况都将所有的tag处理类打成了JAR的包,以便于发布。 [@Q_(LQ-U  
HcedE3Rg  
H|ER  
Tag库描述(简称TLD) =egW  
yv\#8I:qh  
 ~BDu$  
Tag库是用xml语言描述的,TLD包括了tag库中所有tag标签的描述,它一般用来被jsp服务器用来校验tag的语法正确性,或者被jsp开发者用来开发新的标签。 `ORECg)  
$Bj;D=d@V  
TLD的文件扩展名必须为.tld,而且必须放在当前WEB应用的WEB-INF目录或其子目录中。 4#5:~M }  
2*N_5&9mE  
一个TLD的内容的开头必须遵守标准的XML开头,用于描述DTD和xml的版本,例如: - !>}_AH  
>~`r:0',  
<?xml version="1.0" encoding="ISO-8859-1" ?> -0_d/'d  
>[ Ye  
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd"> j:,NE(DF  
TLD必须以<taglib>来作为它的根元素,<taglib>的子元素如下表: B9T!j]'  
rQEyD  
e]T`ot#/  
<taglib>的子元素 OKi\zS  
fm(e3]  
Element k51Eyy50(  
Description &q`q4g&7  
2-"0 ^n{  
tlib-version 8ZCoc5  
Tag库的版本 iSFuT7; %  
w|CZ7|6  
jsp-version M @3"<[g  
Tag库所需要的jsp的版本 !q-f9E4`  
+uBLk0/)>  
short-name ?d4m!HgR   
助记符,tag的一个别名(可选) 70lfb`  
iA0q_( \X  
uri 2P]L9'N{Y  
用于确定一个唯一的tag库 Wm H~m k"  
_{Sm k [  
display-name MwfOy@|N  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) <5G{"U+ \  
%0 #XPc("  
small-icon u7xDau(c  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) 0W3i()  
'S[++w?Qq  
large-icon l^d[EL+  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) _:+ KMR  
`+t.!tv!  
description  49d@!  
对tag库的描述(可选) sz @p_Z/  
GZ{]0$9I'  
listener DfV~!bY  
参见下面listener元素 x Au/  
pA;-v MpMj  
tag fK&e7j`qO  
参见下面tag 元素 BC,.^"fA6  
AW#<i_Ybf  
Listener元素 [xh*"wT#g  
zE)~0v4  
一个tag库可能定义一些类做为它的事件侦听类,这些类在TLD中被称为listener 元素,jsp服务器将会实例化这些侦听类,并且注册它们。Listener元素中有一个叫listener-class的子元素,这个元素的值必须是该侦听类的完整类名。 RNPbH.  
BS q)RV/3  
Tag元素 Z_gC&7+  
zZiJ 9 e  
每个tag元素在tag库中都要指出它的名字、类名、脚本变量、tag的属性。其中脚本变量的值可以直接在TLD中定义或通过tag附加信息的类来取得。每个属性描述了这个属性是否可以省略,它的值是否可以通过<%= …%>这样的JSP语法来获得,以及属性的类型。 c8Q]!p+Yp  
aF|d^  
每一个tag在TLD中对应一个tag元素,下表是tag元素的子元素: @$"L:1_  
5/gDK+%4D(  
Tag元素的子元素 w'X]M#Q><  
_5MNMV LwW  
元素名称 W5/0`[4  
描述 bS >0DU   
<`!PCuR  
name 7O`o ovW$  
独一无二的元素名 |0{u->+ )  
u*7Z~R  
tag-class h;V,n  
Tag标签对应的tag处理类 8F)G7 H ,  
mp~{W  
tei-class dr{y0`CCN  
javax.servlet.jsp.tagext.TagExtraInfo的子类,用于表达脚本变量(可选) #k<":O  
aS|wpm)K>8  
body-content 8h<ehNX ^I  
Tag标签body的类型 $|KaBx1  
{F N;'Uc  
display-name >)_ojDO  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) x90jw$\%7  
0W`LVue  
small-icon ;nmM7TZ;  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) \Hqc 9&0  
Q,Z*8FH=  
large-icon )'Wb&A'  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) e75UMWaeC  
"Lh  
description vRA',(](  
此tag标签的描述 aFY_:.o2k`  
[oc~iDx%W  
variable /,5Z-Z*wq  
提供脚本变量的信息(同tei-class)(可选) "0jJh^vk  
rOD1_X-  
attribute i.iio-  
Tag标签的属性名 E?PGu!&u  
+VEU:1Gt  
以下章节介绍对于不同类型的tag,如何具体地实现它们。 W[NEe,.>  
I~'*$l  
Y{f7 f'_  
简单的tag  17hTr  
DhI>p0* T  
=He. fEy  
tag处理类 %Hi~aRz  
+TN9ujL6@  
简单的tag处理类必须实现Tag接口的doStartTag和doEndTag方法。当jsp引擎碰到tag标签的开头时,doStartTag被调用,因为简单的tag没有body,所以此方法将返回 SKIP_BODY。当jsp引擎碰到tag标签的结尾时,doEndTag被调用,如果余下的页面还要被计算,那它将返回EVAL_PAGE,否则将会返回SKIP_PAGE。 =QV ::/  
V'Qn sI  
以下是例子:对于标签 <tt:simple /> ,它的tag处理类实现如下: |'HLz=5\  
tn/T6C^)  
m:`@?n~..  
public SimpleTag extends TagSupport tUE'K.-  
}bB` (B,m  
{ lm'Zy"~::  
!- ~ X?s~L  
public int doStartTag() throws JspException w#G2-?aj  
Z& !!]"I  
{ <o:@dS  
4ax|Vb)D  
try{ s[3fqdLP&  
}dSFAKI2dM  
pageContext.getOut().print(“Hello.”); d<o.o?Vc  
i 6no;}j  
}catch(Exception e){ x.DzViP/  
v:ER 4  
throw new JspTagException(“SimpleTag: “ + e.getMessage()); Ar, 9U9  
>`V}U*}*H  
} p{;i& HNdp  
]j.k?P$U}  
return SKIP_BODY; LhJa)jFQ  
'Am-vhpm  
} ysXx%k  
^nDal':*  
public int doEndTag() )c tr"&-  
XYbyOM VI  
{ M^SuV  
KS>$`ax,  
return EVAL_PAGE; O+ .*lo  
k&s; {|!  
} o$_93<zc  
h_ ! >yK  
} (6xDu.u?A  
CJ w$j`k  
,-#GX{!  
注意:如果tag标签没有内容的话,那必须定义body-content元素为空,例如 -Wjh**  
T |"`8mG  
<body-content>empty</body-content> rFd@mO  
.gD km^  
e6P[c=m #  
带属性的tag标签
评价一下你浏览此帖子的感受

精彩

感动

搞笑

开心

愤怒

无聊

灌水
级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
只看该作者 1 发表于: 2007-01-01
tag处理类 k,_i#9 X  
^5)_wUf  
对于tag标签的每个属性,你必须依照JavaBeans规范来定义其属性,以及get和set方法。以struts的logic:present 标签为例, XS/n>C  
k^*$^;z  
<logic:present parameter=”Clear”> fv==Gu%{  
d.\PS9l  
与此相应,此tag处理类应有如下方法和定义: =R9*;6?N  
#]zhZW4  
R+Lk~X^*l'  
protected String parameter = null; bF6gBM@*  
oyQ0V94j  
public String getParameter() <IH*\q:7  
YN^jm  
{ 6Q$BUL}2?  
QNJ\!+,HV  
return this.parameter; okDJ(AIV+  
ay[ZsQC  
} ysth{[<5F3  
9HKf^+';n  
public void setParameter(String parameter) u\5g3BH  
nP u`;no  
{ Z:^3Fm->+  
QK7e|M  
this.parameter = parameter; @LC~*_y   
s!`H  
} 8r^j P.V  
>;}]pI0T  
Lupy:4AD  
注意:如果你的属性名为id,而且你的tag处理类是从TagSupport类继承的,那你就不需要定义它的属性和set和get方法,因为他们早已在TagSupport被定义过了。 _#(s2.h~J  
cuMc*i$w!  
Attribute元素 oT!/J  
bqNLkw#  
对于tag标签的每个属性,你必须定义它是否必须的,它的值是否可以用诸如<%= …%>的表达式来获得,以及它的类型(可选),如果不指定它的类型,那就默认为是java.lang.String类型。如果rtexprvalue元素被定义为true或yes,那么在type元素中就定义了attribute的返回类型。 eaxfn]gV  
F,.Q|.nN  
<attribute> < 4$YO-:E  
ex0oAt^  
<name>attr1</name> #nbn K  
c.-cpFk^L&  
<required>true|false|yes|no</required> 4L11P  
We\Y \*!v  
<rtexprvalue>true|false|yes|no</rtexprvalue> d/4ubf+$k  
o oDdV >  
<type>attribute的返回类型(只用当rtexprvalue为真是才有效)</type> w Oj88J)  
h,.fM}=H  
</attribute> 1^tSn#j  
QSv^l-<  
如果tag的某个属性不是必须的,那tag处理类会自动提供一个缺省值。 e SK((T  
_y"a2M  
例如,在logic:present这个tag标签中定义了一个属性叫parameter,但它不是必须的,而且它可以被诸如<%= …%>的表达式来赋值。 <H-tZDh5  
 kMqD iJ  
<tag> Vp\80D&  
EqoASu  
<name>present</name> Tfr`?:yF  
$)l2G;&  
<tag-class>org.apache.struts.taglib.logic.PresentTag</tag-class> =!YP$hfY  
pqOA/^ar  
<body-content>JSP</body-content> MN\i-vAL8  
Z$1.^H.Db  
[~!.a\[RW  
K:uQ#W.&  
<attribute> / Z1Wy-Z  
i<J^:7  
<name>parameter</name> u*U_7Uw$  
4p?+LdL  
<required>false</required> VZt;P%1;h  
T^d#hl.U  
<rtexprvalue>true</rtexprvalue> #gF2(iK6  
[6G=yp  
</attribute> :ao^/&HZ  
I7A7X*  
6W]OpM  
F9F" F  
</tag> dZ.}j&ZH'  
Tm%WWbc  
?U}sQ;c$  
属性元素的校验 %Fs*#S  
.zQ4/  
>).@Nb;e  
有关于tag标签的有效值可以从tag库的说明文档中获得,当JSP页面被编译时,jsp引擎会强制性地参照TLD中定义的规则进行检查。 Av@& hD\  
Th.3j's  
还有一个方法也可以进行属性元素的校验,就是先继承类TagExtraInfo,然后调用它的isValid方法。这个类同时也起到提供tag中定义的脚本变量信息的作用。 qwL 0~I  
<zfO1~^  
IsValid方法通过TagData对象来传递属性信息,它包括着tag的所有的属性名-值的信息。由于校验发生在运行时刻,因此这个属性的值将被赋值为TagData.REQUEST_TIME_VALUE。 ~K4k'   
,:c :6Y^  
例如tag标签<tt:twa attr1=”value1” />在TLD中定义如下: r(PJ~8)(=  
2;dM:FHLhO  
<attribute> an-\k*w  
6{cybD`Ef&  
<name>attr1</name> MP6 \r  
 =|^X$H  
<required>true</required> &uv>'S#%  
=%Q\*xaR.W  
<rtexprvalue>true</rtexprvalue> ;Gjv9:hUn  
9"m, p  
</attribute> s4!|v`+$M  
m]bL)]Z  
E6,`Ld;c[  
这个定义说明了attr1能在运行期间被赋值。 ]R97n|s_  
VC/R)%@%  
以下的isValid方法检查attr1属性的值是否属于Boolean类型。注意由于attr1能在运行刻被赋值,那么isValid方法必须检查tag用户是否对此tag进行了运行时刻赋值。 sZ0g99eX  
Wpiv1GZ%c8  
jXc5fXO N  
Public class TwaTEI extends TagExtraInfo {KF7j63  
;m-6.AV  
{ !O 0ZD4/{4  
I@8+k&nXS  
public boolean isValid(Tagdata data) }`+O$0A  
U'JP1\  
{ s4\SX,  
0S)"Q^6n y  
Object o = data.getAttribute(“attr1”); sV9{4T~#|  
zv$=*  
If(o != null && o != TagData.REQUEST_TIME_VALUE)  9OrA9r  
},?-$eyX  
{ ?7rmwy\  
^N*pIVLC  
if( ( (String)o).toLowerCase().equals(“true”) || `D&#U'wB   
KUl Zk^a  
((String)o).toLowerCase().equals(“false”) ) mafAC73  
>=Rd3dgDG  
return true; VZ9e~){xA  
;XD>$t@  
else 6/p]jN  
<8F->k1"3  
return false; {,nd_3"Vq  
"6|'& 6&  
} 2c*VHIl;  
7LyV`6{70  
else +oxqS&$L  
$G^H7|PzdC  
return true; K-g=td/@  
\kua9bK  
} ;iwD/=Y  
g/n"N>L  
} VC_3ll]vr  
m%BMd  
+#i,87  
带body的tag ( S C7m /  
Z(Ls#hp  
g:@Cg.q8  
tag处理类 9I^H)~S  
(<5'ceF )X  
.q|xMS}4  
如果tag标签含有内容,那处理方式会略微有些不同,而且还要视tag处理类是否要与body交互的情况而定。如果要与body交互,那我们认为tag处理类要可能要对body进行操作。 5jj5 7j"  
@eG#%6">  
Tag处理类不与body交互 6i?kkULBS  
YA/H;707l  
如果tag处理类不与body交互,tag处理类应该实现Tag接口或从TagSupport中派生,如果body要被计算,那么doStartTag方法应返回 EVAL_BODY_INCLUDE,否则应返回SKIP_BODY。 [8om9 Z3  
/M{)k_V  
如果tag处理类要对body反复运算,则它应该实现IterationTag或从TagSupport中派生。如果tag处理类认为body还未计算完的话,那它的doStartTag方法和doAfterBody方法必须返回EVAL_BODY_AGAIN。 *I;Mp  
N|^!"/  
Tag处理类与body交互 <iY 9cV|}3  
XQJV.SVS  
如果tag处理类与body交互,那tag处理类应实现BodyTag接口或从BodyTagSupport中派生。这种tag处理类一般要实现doInitBody和doAfterBody方法。 QVA!z##  
G1n>@Y'j''  
Body允许一些方法来读写它的内容。Tag处理类可以调用body内容的getString或getReader方法来从body中提取信息,也可用 writeOut(out) 方法来将body的内容写入到out对象中。其中out对象通过tag处理类的getPreviousOut方法来获得。 6=[ PJM  
CsQ}P)  
如果body的内容需要被计算,那么doStartTag方法必须返回EVAL_BODY_BUFFERED,否则,它将返回 SKIP_BODY。 ) Sh;UW  
3`C3+  
doInitBody 方法 0^-b}  
rnt$BB[g  
此方法在body内容已经设好,但未被计算之前被调用。你可以根据不同的body内容来制定初始化策略。  :L+zUlsf  
:;gwdZ  
doAfterBody方法 s$=B~l  
>=RHE@  
此方法在body内容已被计算后进行调用。 jak|LOp  
<P Z\qE*+y  
和doStartTag方法一样,doAfterBody方法返回一个指示符指示是否要继续计算body,如果要继续计算,则doAfterBody应返回EVAL_BODY_BUFFERED,否则,它应返回SKIP_BODY。 :fMM-?s]  
W1M/Z[h6)5  
release 方法 %%-Tjw o  
;-P:$zw9c  
tag处理类调用此方法将它的状态重置为初始状态,并释放所有的私有资源。 A5 J#x6@  
L:];[xa%  
rH9|JEz  
以下的例子读取body的内容(其中含有一条sql语句),然后将它传递给一个对象,让它进行查询。由于此处body不须重新计算,所以doAfterBody会返回SKIP_BODY。 _ d"Y6 0  
J1wGK|F~  
;kcFQed\w  
Public class QueryTag extends BodyTagSupport { N8rZ[Oo  
c9TkIe  
{ Z{>Y':\?<  
s?gXp{O?X  
public int doAfterBody() throws JspTagException )Z`viT  
b9!J}hto,  
{ W71#NjM2Z  
sRI=TE]s  
BodyContent bc = getBodyContent(); JZ*?1S>  
Ffqn|} gb  
//将body的内容以字符串的格式提取出来 :y)&kJpleP  
P<w>1 =  
String query = bc.getString(); enO=-#  
E!]rh,mYK  
//清除body @;-Un/'C;7  
r4qV}-E  
bc.clearBody(); ;jfXU_K  
[ZpG+VAJ8  
try{ xo@/k   
;{#M  
Statement stmt = connection.createStatement(); QrRCsy70  
qv >(  
Result result = stmt.executeQuery(query); A-NC,3  
G7#~=W 2M  
}catch(SQLException e){ oA^ ]x>  
aIyY%QT  
throw new JspTagException(“queryTag: “ + e.getMessage() ); Le+8s LE`Y  
m_W.r+s~C4  
return SKIP_BODY; rAi!'vIE  
9n2%7dLQ*  
} 8Y kH  
YRX2^v ^[  
} 5s2}nIe  
X| 0`$f  
jT_Tx\k  
body-content元素  E8V\J  
GeR -k9  
`e:RZ  
由于tag可能会有body,你必须用body-content元素来指定body内容的类型: t ,Rn  
G\+MT(&5  
<body-content>JSP|tagdependent</body-content> 8&iI+\lCy  
;&:Et  
(B4 A$t  
如果body的内容是定制的或内部的tag、脚本元素、或HTML广本,则归类为JSP类型。其他的类型,比如上面代码所述的?D?D将sql statement类传给 query tag的这种类型应该标为tagdependent。 JaN_[ou  
1T^L) %&p_  
注意:实际上body-content的值并不影响tag处理类对body内容的处理,它仅仅是被tag编辑工具用来描述此body的内容。 S~`AnX3!  
V)?g4M3}  
nqW:P$  
用tags定义脚本变量 Tm,L?Jh  
$6+P&"8  
8-#2?=  
tag处理类 |I<-x)joIK  
!!pi\J?sk  
{N`<e>A]{  
tag处理类负责创建或设置页面中定义的脚本变量,用pageContext.setAttribute(name,value,scope)或pageContext.setAttribute(name,value)方法来实现。一般来说,tag处理类通过脚本变量的名称来获取它,脚本变量的名称一般可用get方法来获得。 y.NArN|%  
+ opN\`  
如果脚本变量的值依赖于tag处理类中的上下文中某一对象,那它可用pageContext.getAttribute(name,scope)方法来找到那个对象。一般的处理过程是tag处理类先找到脚本变量,再对其进行处理,然后用pageContext.setAttribute(name,object)的方法来设置它的新值。 L*Cf&c`8r  
m eWq9:z  
对象的生存周期(scope)如下表: c.> (/  
*g}&&$b0  
对象的生存周期表 r\D8_S_  
PA[Rhoit,  
名字 M- A}(r +J  
可访问范围 JQ4>S<ttJ  
生存周期 g0$k_  
U Bg_b?k  
page 6XU5T5+P^  
当前页面 |ZzBCL8q  
一直有效,除非页面向客户提交响应或重定向到一个新页面 pZn%g]nRD  
!Z)^c&  
request {NDe9V5  
当前页面或当前页面重定向到的页面 .k(_ j.v  
一直有效,除非页面向客户提交响应 QQcj"s  
%05a>Rf&  
session AXI:h"so  
当前页面或在同一浏览器窗口中的页面 I'YotV7  
一直有效,除非关闭当前浏览器、超时、网络故障 '1nU[,Wj  
e8v=n@0  
application 5Yr$dNe  
整个web应用程序的所有请求 hglt D8,  
一直有效,除非发生网络故障、服务器故障 <ZdNPcT<s  
g{(nt5|^l  
提供关于脚本变量的信息 oPBjsQ  
>c eU!=>  
以下示例定义了一个名为“book”的脚本变量,用来访问程序中关于书的信息: iHB)wC`u  
/L^dHI]Q  
<bean:define id=”book” name=”bookDB” property=”bookDetails” type=”database.BookDetails” /> R MXj)~4.  
h#nQd=H<g#  
<font color=”red” size=”+2” > tTt~W5lo  
}IL@j A  
<%= messages.getString(“CartRemoved”) %> +3CMfYsr8  
h='=uj8o5  
<strong><jsp:getProperty name=”book” property=”title” /></strong> !HYqM(|{.  
D$;/ l}s?  
</font> GAKJc\o  
nt6"}vO  
当包含此tag的JSP页面被编译时,jsp引擎会自动生成关于此book的同步的代码(同步可以避免几个客户同时访问此book时造成的冲突),要生成同步代码,jsp引擎需要知道此脚本变量的如下信息: !C?z$5g  
x ,W+:l9~s  
· 脚本变量名称 tAUMSr|?  
ZxQP,Ys_Y  
· 脚本变量所属的类 5$X{{j2  
1\uS~RR  
· 此脚本变量是否引用了一个新的或已存在的对象 htaLOTO;A  
aT#|mk=\  
· 此脚本变量的有效性 XLT<,B}e  
&@+; ]t  
有两种办法可以向jsp引擎提供关于脚本变量的信息:在TLD中定义variable子元素,或用tei-class子元素定义一个额外tag信息类。用variable最简单,但可能降低了一些灵活性。 \\JXY*DA:+  
0sa EcJ-  
Variable元素 %<t/xAge  
^(R gSMuT`  
Variable元素有如下子元素: M;R>]wP"V  
}{J8U2])k  
· name-given ?D?D 给出的名字,是一个常量 &3V4~L1aEg  
5]E5V@C   
· name-from-attribute?D?D 属性名,在编译时给出的属性名 :|Cf$2k7  
`Ec+i  
name-given或name-from-attribute两者必须选一,但以下子元素是可选的: R#>E{[9  
Y i`.zm  
· variable-class?D?D变量的类型,缺省为java.lang.String。 {;U:0BPI3  
Wj&s5;2a  
· declare?D?D此脚本变量是否引用了一个新对象,缺省为True。 S5JnJkNn  
jk@]d5  
· scope?D?D脚本变量的范围,缺省为NESTED。下表描述了scope的几种类型: "'Ik{wGc  
CfU )+20  
脚本变量的有效范围 _PF><ODX2  
Ad`IgZ  
l}x{.q7U l  
有效性 F+GQl  
方法 rk|6!kry  
9YKEME+:  
NESTED !wgj$5Rw.  
在tag标签的开始和结束之间 ~X/T6(n$  
如果tag处理类实现BodyTag接口,则在doInitBody和doAfterBody中调用,否则在doStartTag中调用 N@g+51ye  
_[ x(p6Xp  
AT_BEGIN \MU4"sXw  
从tag标签的开始一直到页面结束 L@wnzt  
如果tag处理类实现BodyTag接口,则在doInitBody、doAfterBody和doEndTag中调用,否则在doStartTag和doEndTag中调用 kcle|B  
DQSv'!KFO  
AT_END @azS)4L  
从tag标签的结束一直到页面结束 Nn$$yUkMX  
在doEndTag中调用 ep5aBrN]"  
0*q:p`OLw*  
以struts为例,它的bean:define标签的实现遵循JSP1.1规范,此规范要求使用额外tag信息类来定义脚本变量。Variable元素是JSP1.2规范中加入的。以bean:define标签为例,你可以定义如下variable元素: x;+,lP  
f5N~K>  
<tag> m5S/T\,X  
3]'3{@{} H  
<variable> ^JTfRZ :a  
HN:{rAIfc  
<name-from-attribute>id</name-from-attribute> ]n{2cPx5d  
;BqX=X+#  
<variable-class>database.BookDetails</variable-class> L@/+u+j0  
HV}NT~  
<declare>true</declare> [-l^,,E  
Ac|`5'/Tx  
<scope>AT_BEGIN</scope> A#T;Gi  
T/H*Bo *=5  
</variable> * 08LW|:,  
CTwP{[%Pk  
</tag> /fX]Yu  
rJAY7/u  
额外tag信息类 uuq?0t2Z  
2]@U$E='s  
如果要定义一个额外tag信息类,你要继承javax.servlet.jsp.TagExtraInfo类。一个TagExtraInfo类必须实现getVariableInfo方法,此方法返回一个叫VariableInfo的数组类,它包括如下信息: k2xjcrg  
(vQShe\  
· 变量名 0Vg8o @  
'8dqJ`Gj  
· 变量所属类名 w'UP#vT5&  
"MyYu}AD  
· 此变量是否引用了一个新对象 pD){K  
!XK p_v  
· 此变量的有效范围 &=f%(,+  
mk[n3oE1  
jsp引擎将一个名为data的参数传给getVariableInfo方法,data中包括tag标签中的所有“属性名?D?D属性值”对。它可以用来向VariableInfo对象提供脚本变量的名字和类名。 ztu N0}'  
*QrTZ$\C  
以struts为例,它在bean:define标签中定义了一个名为DefineTei的额外tag信息类,用来向脚本变量提供信息。由于脚本变量的名称(book)和类名(database.BookDetails)是通过tag标签的属性来传递的,它们一般定义在VariableInfo的构建代码中,并且可用data.getAttributeString方法来得到这些信息。如果要允许book脚本变量能在从tag开始直到整个JSP页面结束的范围内都可用的话,那它的范围应设为AT_BEGIN。如下所示: il:+O08_  
g >X!Q  
_N<8!(|w  
public class DefineTei extends TagExtraInfo /ZAEvdO*P  
?A]:`l_"  
{ aa$+(  
hGPjH=^EM  
public VariableInfo[] getVariableInfo(TagData data) P*\.dAi  
FQ);el'_V  
{ A6-JV8^  
6Z7{|B5}Y  
String type = data.getAttributeString(“type”); 3x eW!~  
m,-:(82  
If( type == null) ."9v1kW  
X.g1 312~  
type = “java.lang.Object”; 1 ,Y-_e)  
*ozeoX'5D  
return new VariableInfo[] { '#^ONnSTn  
tM~R?9OaJ  
new VariableInfo(data.getAttributeString(“id”), 1XwbsKQ}  
)bqO}_B  
type, B1 'Ds  
mlX^5h'  
true, {G_ZEo#x8,  
gR%fv  
VariableInfo.AT_BEGIN) ]5B5J  
l,L#y 4#  
}; 7n {uxE#U)  
5_{C \S`T  
} OSxr@  
`5Q0U%`W  
} ;ZB[g78%R%  
_r&`[@m  
=fEn h'KE  
注意:关于额外tag信息类的类名必须要在TLD中的tag标签下的tei-class子元素中定义。因此,DefineTei的tei-class中的定义看起来如下: B_nim[72  
<tei-class> Ee d2`~  
org.apache.struts.taglib.bean.DefineTagTei "\Z.YZUa\  
</tei-class> y?;&(Tcbt8  
,{=#  
F:1w%#6av  
具有协作关系的tag Fep#Pw1  
pvD\E  
>`SIB; &>j  
tag通过共享对象来进行协作,JSP技术支持2种方式的对象共享。 V!(Ty%7  
+.:- :  
第一种方法是使用pageContext对象进行对象的共享(可支持JSP页面和tag处理类之间的共享),如果在一个tag处理类中要调用由另一个tag处理类创建的对象,可调用pageContext.getAttribute(name, scope)方法。 |-%[Z  
V`m'r+ Y  
第二各方式的共享是对于tag之间有嵌套关系而言的,外层的tag所创建的对象对于内层的tag来说是可以共用的。这种形式的共享的好处是减少了可能存在的重名冲突。 iO~3rWQ  
L W 8LD|@  
要访问一个嵌套tag创建的对象,tag处理类必须先找到此嵌套tag对象,可用TagSupport的静态方法 TagSupport.findAncestorWithClass(from, class)或TagSupport.getParent方法。前者在当不确定此tag是否为嵌套tag对象时使用。一旦它的父类被找到,它就能访问其所有动态或静态创建的对象。静态创建的对象是父类的成员,而动态创建的对象可能是父类的私有对象。诸如此类的对象可以用tag处理类的setValue方法来保存,用getValue方法来获得。 Q!iM7C!8  
TDq(%IW  
下例阐述了以上两种共享对象的方法。在这个例子当中,一个查询tag检查一个名为connection的属性名是否在doStartTag中被设置。如果connection属性被设置,tag处理类从pageContext中得到这个connection对象。否则,此tag处理类先找到它的父tag处理类,然后从它的父tag处理类中找到connection对象。 = a$7OV.  
\x5b=~/   
U@ Y0 z.Y  
public class QueryTag extends BodyTagSupport ~*@ UQ9*p#  
by (xv0v;  
{ Z.ky=vCt  
pqmtN*zV  
private String connectionId; 0[/>> !ws  
<k+dJ=f  
public int doStartTag() throws JspException [W;iR_7T5  
uS`XWn<CSD  
{ FCgr  
p"\Z@c  
String cid = getConnection(); XvETys@d  
9`4M o+  
if(cid != null) \R\?`8O rz  
F !g>fIg  
{ )O*\}6:S  
uxLT*,  
//存在一个connection id,使用它。 nLicog)!I  
=bgzl=A`  
connection = (Connection) pageContext.getAttribute(cid); 4+I@   
P'MfuTtT&  
} ova4  
iq*]CF  
else jMr[ UZ  
/enlkZx=8  
{ ?gD^K,A Hd  
tqbYrF)  
ConnectionTag ancestorTag = (ConnectionTag)findAncestorWithClass(this, XT+V> H I  
pDqX% $^  
ConnectionTag.class); |iSd<  
F#NuZ'U  
if(ancestorTag == null) y``[CBj  
&GYnGrw?@  
{ 0+S ;0  
cH>@ZFTF  
throw new JspTagException(“一个没有connection属性的查询标签必须被一个connection标记嵌套。”); ,^wjtA 3j8  
O?,Grn%'.  
} gOb"-;Zw  
Ck1{\=t  
connection = ancestorTag.getConnection(); gi {rqM  
28 Q\{Z.  
} oD<aWZ"Z  
6sjd:~J:  
} U/ds(*g@  
L;RHs hTy  
} 2nra@  
xu%_Zt2/?j  
l(A)Gd5>  
rF?gKk  
此查询标签在JSP页面中的调用形式可以从以下2种定义中任选一种: okm }%#|  
Q l#y7HW  
G]v BI=  
<tt:connection id=”con01” ...> ... </tt:connection> b I"+b\K  
M:M"7>:  
<tt:query id=”balances” connection=”con01” > CKE):kHu  
gUr #3#  
SELECT account, balance FROM acct_table NI  r"i2  
"%(SLQOyy  
where customer_num = <%= request.getCustno() %> 8&Md=ZvK`  
F:7 d}Jx  
</tt:query> "%I<yUP]U  
O,PTY^  
P+L#p(K  
mV'-1  
sEymwpm9  
<tt:connection ...> A Xpg_JC  
fK|P144   
<x:query id=”balances”> CSwPL>tUV  
mWUkkR(/  
SELECT account, balance FROM acct_table =f?vpKq40  
&j}:8Tst  
where customer_num = <%= request.getCustno() %> w2H^q3*  
:u]QEZ@@  
</x:query> Hk f<.U  
CzDV^Iv;Q{  
</tt:connection> _]v@Dq VP  
QXu[<V  
M3G ecjR  
与此同时,在TLD中必须指定connection属性为可选的,定义如下: Skg}/Ek  
%At.nlss  
<tag> Xhs*nt%l  
[*J?TNk  
... fHODS9HQ  
F'-,Ksn  
<attribute> EQtYb"_  
F%f)oq`B  
<name>connection</name> _WR/]1R  
r=HL!XFk  
<required>false</required> x1h&`QUP  
G0A\"2U  
</attribute> &+0?Xip{Z  
Cg(&WJw(ep  
</tag>
描述
快速回复

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