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

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

级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
标准的JSP 标记可以调用JavaBeans组件或者执行客户的请求,这大大降低了JSP开发的复杂度和维护量。JSP技术也允许你自定义taglib,其实换句话说,taglib可以看成是对JSP标记的一种扩展,正如xml是对html的一种扩展一样。taglib通常定义在tag标签库中,这种标签库存放着你自己定义的tag标签。简而言之,如果使用taglib,那么你可以设计自己的JSP标记! otVdx&%]  
*wyLX9{:  
一般来说,自定义tag标签主要用于操作隐藏对象、处理html提交表单、访问数据库或其它企业级的服务,诸如邮件和目录操作等等。自定义tag标签的使用者一般都是那些对java编程语言非常精通,而且对数据访问和企业级服务访问都非常熟悉的程序员,对于HTML设计者来说,使得他可以不去关注那些较复杂的商业逻辑,而将精力放在网页设计上。同时,它也将库开发者和库使用者进行合理分工,自定义tag标签将那些重复工作进行封装,从而大大提高了生产力,而且可以使得tag库可用于不同的项目中,完美地体现了软件复用的思想。 MM$" 6Jor  
:@'0)7  
在这篇文章中,我们主要讨论: tF1%=&ss  
_( /lBf{|  
· 什么是自定义tag标签? gxtbu$  
tdK^X1  
· 怎么使用tag标签? +W[#;)ea(  
:u+#:8u  
o 声明要使用的tag库 JT_B@TO\  
9uoj3Rh<  
o 找到与之对应的tag处理类 B>2 1A9&  
`r$WInsDu  
o tag标签的类型 UoT}m^ G  
ITPp T  
· 自定义tag标签 SytDo (_=W  
&Y2P!\\2  
o tag处理类 VQ}3r)ch  
l:}4 6%  
o tag库描述 euC,]n.  
ee[NZz  
o tag标签示例 }r<^]Q*&p  
[,X,2  
o 带属性的tag !9OgA  
()JDjzQT  
o 带body的tag 6MQ:C'8T&=  
QP0X8%+p  
o 定义了脚本变量的tag ZO$T/GE6%  
5ml}TSMu'  
o 具有协作关系的tag n:] 1^wX#  
|H@p^.;  
· 自定义tag标签 glIIJ5d|,  
4u7>NQUDu  
o 一个迭代tag的例子 nL~ b   
?saVk7Z[|5  
o 一个模板tag库 Ka2tr]+s  
<cjTn:w  
o tag处理类到底是怎样被调用的? aBLb i  
K7Tell\`  
JPKZU<:+V  
什么是自定义的tag? qE=OQs9  
Vtk|WV?>P+  
一个自定义的tag标签是用户定义的一种JSP标记。当一个含有自定义的tag标签的JSP页面被jsp引擎编译成servlet时,tag标签被转化成了对一个称为tag处理类的对象进行的操作。于是当JSP页面被jsp引擎转化为servlet后,实际上tag标签被转化成为了对tag处理类的操作。 bUL9*{>G  
ogbdt1  
自定义tag标签有很多特色,诸如: be@uHikp;v  
^<+heX  
· 可以在JSP页面中自定义tag标签的属性 ^Z+D7Q  
>xgd<  
· 访问JSP页面中的所有对象 zt}p-U2I  
8iA(:Tb  
· 可以动态地修改页面输出 g+*[CKO{  
>*CK@"o  
· 彼此这间可以相互通信。你可以先创建一个JavaBeans组件,然后在一个tag中调用此JavaBeans组件,同时可以在另一个tag中调用它。 (Ad! hyE(  
l))IO`s=_  
· tag允许相互嵌套,可以在一个JSP页面中完成一些复杂的交互。 T0jJp7O  
~cwwB{  
G"w Q(6J@  
使用tag标签 mr.DP~O:9p  
_"`h~jB  
f d5~'2  
本节主要描述怎样在JSP页面中使用tag标签,以及tag标签的不同类型。 X|G+N(`|(  
Ry3 f'gx  
要使用tag标签,JSP程序员必须做2件事: 3/05ee;|  
Bk <P~-I  
· 声明此tag标签的tag库 *h9vMks o  
GrC")Z|3u  
· 实现此tag标签 7C^ nk z  
UlytxWkUX  
声明tag标签所在的tag库 >^N :A  
`;@4f |N9  
如果要使用tag标签,则应用JSP的taglib指示符来指定其tag库(注意:taglib要在在使用此tag标签之前声明) PD4E& k  
JnJz{(c  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> KYN{iaj  
}FVX5/.'  
uri属性定义了唯一的标签库描述(以下简称TLD),它可以是直接是tld文件名或一个独一无二的名字。prefix是用来区别其它TLD中和本TLD中有重名的tag的一种手段。 g7i6Yj1  
l0)uu4|  
TLD必须以.tld作为扩展名,并且存放在当前应用的WEB-INF目录或其子目录下。你可以通过它的文件名直接引用它,也可以通过别的方式间接地引用它。 #m>mYp8E.5  
q5PYc.E([  
以下taglib指示符直接引用一个TLD: 3}Qh`+Yj]  
K4~O x  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> 5Bo)j_Qo  
Fwqf4&/  
以下的taglib指示符通过一个逻辑名称间接地引用一个TLD: 9f`Pi:*+/  
q#Vf2U55m  
<%@ taglib uri=”/tutorial-template” prefix=”tt” %> O!tD1^O!1}  
:_ox8xS4  
如果是间接引用TLD的话,那你必须还要在web.xml中定义此逻辑名称与tld文件之间的映射,具体做法是在web.xml中加入一个名为taglib的元素: ls Ch K  
gZv <_0N  
<taglib> Hc9pWr "N  
EVsZ:Ra^k  
<taglib-uri>/tutorial-template</taglib-uri> 9_{!nQC.g  
[DwB7l)O(  
<taglib-location> g(k|"g`*  
RUKSGj_NJ  
/WEB-INF/tutorial-template.tld FO$Tn+\6  
UepBXt3)  
</taglib-location> +_Z/VQv  
_!zY(9%  
</taglib> 3FN? CN] O  
pkx>6(Y  
vKf=t&gqr  
实现此tag标签 g=Di2j{A  
-f=hL7NW  
/jD'o>  
为了实现tag标签,你有2种方法来存放tag处理类。一、让tag处理类以.class的方式存放于当前应用的WEB-INF/class子目录下,二、如果tag处理类是以JAR包的形式存在的话,那可以放在当前应用的WEB-INF/lib目录下,如果tag处理类要在多个应用中共享,那么它就应放在jsp服务器上的common/lib目录下,对于tomcat来说,就是tomcat/common/lib目录下。 KG$2u:n  
ig{5 ]wZ(  
|{T2|iJI  
tag标签类型 }__+[-  
A$cbH.  
h;->i]  
自定义的tag标签遵循XML语法。它有一个开始标记和一个结束标记,有的还有body(即文本节点): -yeT$P&|  
"Cb<~Dy  
<tt:tag> 6tguy  
c^y 1s*  
body _rd{cvdR  
-}@9lhS,  
</tt:tag> xTT>3Fj  
xFZq6si?  
s?Kn,6Y  
一个不带body的tag标签如下: }T,uw8?f!  
>YLm]7v}  
<tt:tag /> v &n &i?  
g%trGW3{-  
3QpT O,  
简单的tag标签 tS$Ne7yk e  
/Ny&;Y  
一个没有body和属性的tag标签如下: +Sfv.6~v  
e=2D^ G#qE  
<tt:simple /> Cmj)CJ-  
q@:&^CS  
LxT] -  
带属性的tag标签 YVT^}7#  
n>WS@b/o  
XJ;/ kR  
自定义标签可以有自己的属性。属性一般在开始标记中定义,语法为 attr=”value”。属性的作用相当于自定义标签的一个参数,它影响着tag处理类的行为。你可以在TLD中详细定义它。 00i9yC8@6  
N2>JG]G  
你可以用一个String常量给一个属性赋值,也可以通过表达式给它赋值,如<%= ...%>。以struts为例,它的logic:present标签就是用的String常量来给属性赋值: bb{+  
8{C3ijR  
<loglic:present parameter = “Clear”> Tx*m p+q  
fvD wg  
而另一个标签logic:iterate是用表达式来给属性赋值: *M:Bhw  
!T*izMX}  
<logci:iterate collection=”<%= bookDB.getBooks() %>” 9=|5-? ^  
=>G A_  
id=”book” type=”database.BookDetails”> |{ k B`  
q`P:PRgM  
V~;YV]1Y  
带body的tag标签 S4w/ kml3  
\ (,2^T'$J  
一个自定义标签可以包含其它自定义标签、脚本变量、HTML标记或其它内容。 H< j+-u4b  
@lwqk J  
在下述例子中,此JSP页面使用了struts的logic:present标签,如果些标签定义了parameter=”Clear”的属性,则将清除购物车的内容,然后打印出一条信息: &+v&Dd&  
tz,FK;8  
<logic:present parameter=”Clear”> ?D_zAh?pW  
DjIs"5Iei  
<% cart.clear(); %> k{~5pxd-t  
Y*Pr  
<font color=”#ff0000” size=”+2”><strong> D)5wGp  
VI?[8@*Z  
你选择了清除购物车! -Q; w4@  
{-xnBx  
</strong></font> zF PSk ]  
$IHa]9 {  
</logic:present> pfT7  
(I$hw"%&  
:O7J9K|  
到底是用属性还是用body来传递信息? |fUSq1//  
y{&,YV&_h  
如上所述,我们既可以通过属性,也可以通过body来传递信息。但一般来说,比较简单的类型,如字符串或简单表达式最好采用属性来传递信息。 hXCDlCO  
D)Zv  
DCj!m<Y&  
定义脚本变量的tag标签 b|NEU-oy  
Y3[@(  
所谓脚本变量,是指JSP中可以调用的变量或对象。它可由tag标签产生。以下示例阐述了一个tag标签定义了一个名为tx的由JNDI所定义的事务处理对象。脚本变量可以是ejb对象、事务、数据库连接等等: `JR dOe  
CVm*Q[5s"  
<tt:lookup id=”tx” type=”UserTransaction” name=”java:comp/UserTransaction” /> R`c5-0A  
4T:ZEvdzf  
<% tx.begin(); %> Sz =z TPnO  
<*[(t;i  
... %X3T<3<  
MYjCxy-;A  
O%Mh g\#B  
具有协作关系的tag标签 6[cMPp x  
&\LbajP:+  
自定义tag标签之间可以通过共享对象来实现协作。在下述例子中,标签tag1创建了一个名为obj1的对象,在标签tag2仍可以重复使用obj。 CV k8MA  
B4hR3%  
<tt:tag1 attr1=”obj1” value1=”value” /> 0^+W"O  
 ZM"t.  
<tt:tag2 attr1=”obj1” /> :z[SI{Y  
>a<;)K^1  
在以下这个例子当中,如果外层的tag标签创建了一个对象,那么其内层的所有tag标签都可以使用这个对象。由于这样产生的对象没有一个指定的名字,那么就可以将少重名的冲突。这个例子阐述了一系列协作的嵌套对象。 \?j(U8mB>  
*d=pK*g  
<tt:outerTag> u>BR WN  
u% FA.  
<tt:innerTag /> PYZ8@G  
{0?76|  
</tt:outerTag> % :NI@59  
V{][{5SR  
1peN@Yk2W  
Tag处理类 ^dro*a,  
/#tOi[0[  
b{A#P?  
Tag处理类必须实现Tag接口或BodyTag接口,不过现在一般都流行从TagSupport或BodyTagSupport类中继承,这些类或接口都可以在javax.servlet.jsp.tagext包中找到。 t4h* re+  
v"j7},P@  
当JSP引擎看到自己的JSP页面中包含有tag标签时,它会调用doStartTag方法来处理tag标签的开头,调用doEndTag方法来处理tag标签的结束。 L(.5:&Y=`  
rB4]TQ`c  
下表说明不同类型的tag所需要不同的处理过程: G]{)yZ'}  
y0 xte&  
Tag处理类的方法 RW'QU`N[Y  
zR%#Q_  
Tag标签类型 , vWcWT  
所调用的方法 r;-\z(h  
@ Fu|et  
基本标签 #(%6urd  
doStartTag, doEndTag, release QgP UP[  
='(:fHhhX  
带属性的标签 w0pH|$"/P  
doStartTag, doEndTag, set/getAttribute1...N, release B{44|aq1|  
d4lEd>Ni  
带内容的标签 N)QW$iw9  
doStartTag, doEndTag, release @sP?@< C  
WkT4&|POJ  
带内容的标签,且内容重复循环 ;e+ErN`a.~  
doStartTag, doAfterBody, doEndTag, release 4XRVluD%W.  
a$ Z06j  
带内容的标签,且内容与JSP交互 p &A3l  
doStartTag, doEndTag, release, doInitBody, doAfterBody, release [L:,A{rve  
,+ WDa%R  
一个tag处理类可以通过javax.servlet.jsp.PageContext来与JSP交互,通过javax.servlet.jsp.PageContext类,tag处理类可以访问JSP中的request、session和application对像。 oYW:p tJ  
HJDM\j*5  
如果tag标签是互相嵌套的,那内层的tag处理类可以通过它的parent属性来访问上层的tag处理类。 )gZ yW  
WHL@]^E@m  
一般情况都将所有的tag处理类打成了JAR的包,以便于发布。 env]*gx+=  
jVr:O `  
J=  T!  
Tag库描述(简称TLD) kEi!q  
2QdqVwm  
8< R#}  
Tag库是用xml语言描述的,TLD包括了tag库中所有tag标签的描述,它一般用来被jsp服务器用来校验tag的语法正确性,或者被jsp开发者用来开发新的标签。 W_%Dg]l   
6:H@= fEv  
TLD的文件扩展名必须为.tld,而且必须放在当前WEB应用的WEB-INF目录或其子目录中。 %5'6^bT  
HN\9 d  
一个TLD的内容的开头必须遵守标准的XML开头,用于描述DTD和xml的版本,例如: 0y*8;7-|r)  
{$Qw]?Yv  
<?xml version="1.0" encoding="ISO-8859-1" ?> v81<K*w`P  
$%ps:ui~X  
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd"> yN9/'c~  
TLD必须以<taglib>来作为它的根元素,<taglib>的子元素如下表: Mp}U>+8  
up1kg>i%"  
t\ ym4`"  
<taglib>的子元素 :M3Fq@w=  
*&XOzaVU  
Element C-&\qAo?<:  
Description i!(u4wTFF  
*4]}_ .rG#  
tlib-version I=0`xF|4K-  
Tag库的版本 d-y8c  
V!u W\i/  
jsp-version nwf(`=TC  
Tag库所需要的jsp的版本 (V&$KDOA  
xtyOG  
short-name v#TU7v?~  
助记符,tag的一个别名(可选) N^v"n*M0|  
|Y4c+6@_  
uri ^DD]jx  
用于确定一个唯一的tag库 9J*.'Y  
=XVw{\#9 b  
display-name  (cx Q<5  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) tw,uV)xm  
FG/1!8F  
small-icon Ko: <@h  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) y2KR^/LN|Y  
7*.nd  
large-icon h:xvnyaI  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) /@ m]@  
-V7dSi  
description z#m ~}  
对tag库的描述(可选) wt]onve}%  
Z ):q1:y  
listener ~ 6DaM!  
参见下面listener元素 &sJ-&7YZ  
mb,\wZ  
tag vhvFBx0  
参见下面tag 元素 %py3fzg  
T,r?% G{XE  
Listener元素 6/6M.p  
g%TOYZr!X  
一个tag库可能定义一些类做为它的事件侦听类,这些类在TLD中被称为listener 元素,jsp服务器将会实例化这些侦听类,并且注册它们。Listener元素中有一个叫listener-class的子元素,这个元素的值必须是该侦听类的完整类名。 BlnR{Y  
{u~JR(C:  
Tag元素 }]<0!q &xB  
DHQS7%)f`  
每个tag元素在tag库中都要指出它的名字、类名、脚本变量、tag的属性。其中脚本变量的值可以直接在TLD中定义或通过tag附加信息的类来取得。每个属性描述了这个属性是否可以省略,它的值是否可以通过<%= …%>这样的JSP语法来获得,以及属性的类型。 xa8;"Y~"bg  
}p5_JXBV  
每一个tag在TLD中对应一个tag元素,下表是tag元素的子元素: Kl_(4kQE_  
3$G &~A{  
Tag元素的子元素 $t0o*i{  
c^3,e/H  
元素名称 iSbPOC7  
描述 ||D PIn]  
!y+uQ_IS@  
name x n?$@  
独一无二的元素名 >jz9o9?8  
*+(rQ";x  
tag-class w$iQ,--  
Tag标签对应的tag处理类 R#HVrzOO|T  
xIA]5@;a  
tei-class OY Sq)!:  
javax.servlet.jsp.tagext.TagExtraInfo的子类,用于表达脚本变量(可选) KrdEB0qh  
5\V""fH  
body-content [4w*<({*  
Tag标签body的类型 agt/;>q\~  
zG{P5@:.R  
display-name z^vfha  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) rtNYX=P  
iYD5~pK8  
small-icon e.\dqt~%y  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) MX? *jYl  
?8N^jjG  
large-icon SSxp!E'  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) ,.Lwtp,n  
;.'?(iEB  
description 9TX2h0U?  
此tag标签的描述 )pSA|Qt N  
$GP66Ev  
variable 60;_^v  
提供脚本变量的信息(同tei-class)(可选) C#-HWoSi  
}{y)a<`  
attribute |sdG<+  
Tag标签的属性名 NOg/rDs'{  
i\<S ;  
以下章节介绍对于不同类型的tag,如何具体地实现它们。 auga`*  
Unvl~lm6  
! c`&L_ "!  
简单的tag ; [G:  
? X6M8`  
r0!')?#Z  
tag处理类 f0vO(@I  
#9gx4U  
简单的tag处理类必须实现Tag接口的doStartTag和doEndTag方法。当jsp引擎碰到tag标签的开头时,doStartTag被调用,因为简单的tag没有body,所以此方法将返回 SKIP_BODY。当jsp引擎碰到tag标签的结尾时,doEndTag被调用,如果余下的页面还要被计算,那它将返回EVAL_PAGE,否则将会返回SKIP_PAGE。 ^s6}[LDW>@  
}4N'as/ZO  
以下是例子:对于标签 <tt:simple /> ,它的tag处理类实现如下: 8OKG@hc  
"4\k1H"_  
^D<CoxG  
public SimpleTag extends TagSupport 6R,Y.srR  
! ui   
{ E*O($tS  
`6)(Fk--"  
public int doStartTag() throws JspException )X-'Q-  
+j{(NwsX  
{ TG[u3 Y4  
-'Ay(h   
try{ rRg,{:;A  
D'<L6w`  
pageContext.getOut().print(“Hello.”); R\|,GZ!`+  
1~t.2eUG  
}catch(Exception e){ ]XU4nNi  
HdN5zl,q  
throw new JspTagException(“SimpleTag: “ + e.getMessage()); |Fe[RGi+8  
y_X jY  
} aX`uF<c9  
V:w%5'^3  
return SKIP_BODY; ?TeozhUY  
b3EGtC}^  
} 'y\Je7  
?HJh;96B  
public int doEndTag() j*@@H6G  
jB8Q% {%  
{ ele@xl  
TKM^  
return EVAL_PAGE; 4^uSW&`;/  
E{EO9EI  
} KJRAW]?{  
& ?xR  
} Wk\(jaL%  
GA[Ebzi  
ydyTDn  
注意:如果tag标签没有内容的话,那必须定义body-content元素为空,例如 g]lEG>y1R  
p;>A:i  
<body-content>empty</body-content> u [._RA  
&nP0T-T5y  
g E _+r  
带属性的tag标签
评价一下你浏览此帖子的感受

精彩

感动

搞笑

开心

愤怒

无聊

灌水
级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
只看该作者 1 发表于: 2007-01-01
tag处理类 W}f)VC;D  
=..Bh8P71!  
对于tag标签的每个属性,你必须依照JavaBeans规范来定义其属性,以及get和set方法。以struts的logic:present 标签为例, R3~,&ab  
B:T s_9*  
<logic:present parameter=”Clear”> J-hJqR*;K  
Jqj!k*=/  
与此相应,此tag处理类应有如下方法和定义: H:@hCO[a  
zbmC? 2$  
Z+&V  >  
protected String parameter = null; +P^ ;7"H  
|tGUx*NN  
public String getParameter() SI=$s>1  
`Gqe]ZE#"  
{ <Z]#vr q  
"E(i<  
return this.parameter; o/w3b 8  
6;Z -Y>\c  
} +4s]#{mP  
$Z:O&sD{  
public void setParameter(String parameter) 2)n`Bd  
o]4]fLQ  
{ Kcm+%p^  
6nZ]y&$G-k  
this.parameter = parameter; Ipk;Nq  
S MWXP  
} KLyRb0V  
5MVa;m  
CIx(SeEF  
注意:如果你的属性名为id,而且你的tag处理类是从TagSupport类继承的,那你就不需要定义它的属性和set和get方法,因为他们早已在TagSupport被定义过了。 {Rkd;`Q`!  
lS4rpbU_  
Attribute元素 ?H=q!i  
L}`/v]E"eU  
对于tag标签的每个属性,你必须定义它是否必须的,它的值是否可以用诸如<%= …%>的表达式来获得,以及它的类型(可选),如果不指定它的类型,那就默认为是java.lang.String类型。如果rtexprvalue元素被定义为true或yes,那么在type元素中就定义了attribute的返回类型。 5dePpFD5  
~w? 02FU  
<attribute> e$J>z {  
C^L+R7  
<name>attr1</name> M]s\F(*ib  
pR61bl)  
<required>true|false|yes|no</required> wtw=RA  
w"v!+~/9  
<rtexprvalue>true|false|yes|no</rtexprvalue>  r{;NGQYs  
yp#!$+a}  
<type>attribute的返回类型(只用当rtexprvalue为真是才有效)</type> PMfW;%I.  
4yyw:"  
</attribute> JT?u[p Q^  
d=D-s  
如果tag的某个属性不是必须的,那tag处理类会自动提供一个缺省值。  k,:W]KD  
=Kd'(ct  
例如,在logic:present这个tag标签中定义了一个属性叫parameter,但它不是必须的,而且它可以被诸如<%= …%>的表达式来赋值。 +<a\0FsD  
'z ?Hv  
<tag> x4WCAqi/2  
cUY-  
<name>present</name> iFd !ED  
eFG/!b<17  
<tag-class>org.apache.struts.taglib.logic.PresentTag</tag-class> 'z$$ZEz!C  
F\m^slsu7=  
<body-content>JSP</body-content> z`wIb  
Zw]"p63eMa  
l7|z]v-  
qX ,q*hr-  
<attribute> 3vY-;&  
ek][^^4o  
<name>parameter</name> ~*HQPp?v  
w"j>^#8  
<required>false</required> |V a:*3u  
S(gr>eC5  
<rtexprvalue>true</rtexprvalue> =I# pXL  
YnEyL2SuU  
</attribute> 'H5 30Y\  
|0n )U(  
2:38CdkYp  
'(.5!7?Qc  
</tag> h.edb6  
~/L:$  
(!* l+}  
属性元素的校验 *ERV\/  
"t0^4=c+7  
" `qk}n-  
有关于tag标签的有效值可以从tag库的说明文档中获得,当JSP页面被编译时,jsp引擎会强制性地参照TLD中定义的规则进行检查。 l77 -I:  
=A'>1N  
还有一个方法也可以进行属性元素的校验,就是先继承类TagExtraInfo,然后调用它的isValid方法。这个类同时也起到提供tag中定义的脚本变量信息的作用。 b j&!$')  
sY;h~a0n  
IsValid方法通过TagData对象来传递属性信息,它包括着tag的所有的属性名-值的信息。由于校验发生在运行时刻,因此这个属性的值将被赋值为TagData.REQUEST_TIME_VALUE。 Uu_qy(4  
vNSUrf,r  
例如tag标签<tt:twa attr1=”value1” />在TLD中定义如下: c,a8#Og  
o(hUC$vW  
<attribute> I~&*^q6 |  
2P"643tz  
<name>attr1</name> LKM018H>  
%g9y m@s  
<required>true</required> 0z>IYw|UB  
`=(<!nXJx  
<rtexprvalue>true</rtexprvalue> tx09B)0  
ji/`OS-iq  
</attribute> }F>RI jj  
 ``/L18  
jr` swyg  
这个定义说明了attr1能在运行期间被赋值。 f Fi=/}  
^T&{ORWz  
以下的isValid方法检查attr1属性的值是否属于Boolean类型。注意由于attr1能在运行刻被赋值,那么isValid方法必须检查tag用户是否对此tag进行了运行时刻赋值。 WsHD Ip  
fEBi'Ad  
%r^tZ;; l  
Public class TwaTEI extends TagExtraInfo .#&)%}GC  
Ic'D# m  
{ G#%Sokkb'  
& DP"RWT/  
public boolean isValid(Tagdata data) Oe Q[-e  
-HF?1c  
{ k6#$Nb606  
v?He]e'  
Object o = data.getAttribute(“attr1”); jkk%zu  
zZMKgFR@  
If(o != null && o != TagData.REQUEST_TIME_VALUE) (dg,w*t'  
<WUgH6"  
{ b$@I(.X:  
"09v6Tx  
if( ( (String)o).toLowerCase().equals(“true”) || |b\a)1Po:  
z};|.N}  
((String)o).toLowerCase().equals(“false”) ) rZgu`5 <a  
- |p eD L  
return true; v.RA{a 9  
-|V#U`mwF  
else H,D5)1Uu  
JZ}zXv   
return false; Q&I #  
Uh0g !zzp  
} fq>{5ODO  
wqG#jC!5  
else &k'<xW?x  
,u}wW*?,sT  
return true; + E{[j  
ozY$}|sjDT  
} H^'%$F?Ss  
G ]h  
} Ry +?#P+  
@x1cV_s[  
;L$ -_Z  
带body的tag OG{*:1EP  
=Htt'""DN  
p-j6H  
tag处理类 +&\. ]Pp  
N_92,xI#  
{`):X_$T  
如果tag标签含有内容,那处理方式会略微有些不同,而且还要视tag处理类是否要与body交互的情况而定。如果要与body交互,那我们认为tag处理类要可能要对body进行操作。 yV`Tw"p  
GJdL1ptc  
Tag处理类不与body交互 u.A}&'H  
6?x F!VIL  
如果tag处理类不与body交互,tag处理类应该实现Tag接口或从TagSupport中派生,如果body要被计算,那么doStartTag方法应返回 EVAL_BODY_INCLUDE,否则应返回SKIP_BODY。  L]l/w  
|dxWO  
如果tag处理类要对body反复运算,则它应该实现IterationTag或从TagSupport中派生。如果tag处理类认为body还未计算完的话,那它的doStartTag方法和doAfterBody方法必须返回EVAL_BODY_AGAIN。 k9eyl)  
?$`kT..j,u  
Tag处理类与body交互 4Q!%16 P  
3^P;mQ$p1  
如果tag处理类与body交互,那tag处理类应实现BodyTag接口或从BodyTagSupport中派生。这种tag处理类一般要实现doInitBody和doAfterBody方法。 @:im/SE  
53hX%{3  
Body允许一些方法来读写它的内容。Tag处理类可以调用body内容的getString或getReader方法来从body中提取信息,也可用 writeOut(out) 方法来将body的内容写入到out对象中。其中out对象通过tag处理类的getPreviousOut方法来获得。 &B5&:ib1D  
Z,p@toj'  
如果body的内容需要被计算,那么doStartTag方法必须返回EVAL_BODY_BUFFERED,否则,它将返回 SKIP_BODY。 d%I7OBBx@  
o~'p&f  
doInitBody 方法 ^Zvb3RJg  
a=W%x{  
此方法在body内容已经设好,但未被计算之前被调用。你可以根据不同的body内容来制定初始化策略。 )&E]   
 3*Q=)}  
doAfterBody方法 yMdu Zmkc  
dA~_[x:Z  
此方法在body内容已被计算后进行调用。 u"zR_CzYc  
%KVmpWku  
和doStartTag方法一样,doAfterBody方法返回一个指示符指示是否要继续计算body,如果要继续计算,则doAfterBody应返回EVAL_BODY_BUFFERED,否则,它应返回SKIP_BODY。 ]-t>F  
b~UWFX#U  
release 方法 sPc}hG+N  
vw>(JCR  
tag处理类调用此方法将它的状态重置为初始状态,并释放所有的私有资源。 ktPM66`b  
z4 =OR@ h  
}J?,?>Z  
以下的例子读取body的内容(其中含有一条sql语句),然后将它传递给一个对象,让它进行查询。由于此处body不须重新计算,所以doAfterBody会返回SKIP_BODY。 >-V632(/{o  
z 8M\(<  
n><ad*|MX  
Public class QueryTag extends BodyTagSupport k5>UAea_  
Ytc[ kp  
{ 48z%dBmTT*  
o6^ETQ  
public int doAfterBody() throws JspTagException TfJ*G6\7e#  
uhj]le!  
{ t;Z9p7rk  
)^8[({r~  
BodyContent bc = getBodyContent(); G(?1 Urxi  
&~;M16XM,e  
//将body的内容以字符串的格式提取出来 -J=6)  
Q\zaa9P  
String query = bc.getString(); %7 -(c  
hlre eXv  
//清除body 9BP'[SM%),  
tJ_Y6oFm=  
bc.clearBody(); f?ycZ  
@H$8;CRM  
try{ u[KxI9Q  
>VZxDJ$R  
Statement stmt = connection.createStatement(); ]@21KO  
W{J e)N  
Result result = stmt.executeQuery(query); Vo^J2[U  
#|8%h  
}catch(SQLException e){ vCej( ))  
59$PWfi-\  
throw new JspTagException(“queryTag: “ + e.getMessage() ); ?7pn%_S  
s)E8}-v  
return SKIP_BODY; tq,^!RSbZ  
#/Ob_~-?j  
} =\u,4  
|Isn<|_  
} >`3F`@1L0  
PSv 5tQhm  
8&HBR #  
body-content元素 ;F- mt(Y  
IR]5,K^l  
dh%O {t  
由于tag可能会有body,你必须用body-content元素来指定body内容的类型: >Q<XyAH~  
BPkL3Ev1V  
<body-content>JSP|tagdependent</body-content> b&@]f2 /  
U/PNEGuQ  
}|/A &c  
如果body的内容是定制的或内部的tag、脚本元素、或HTML广本,则归类为JSP类型。其他的类型,比如上面代码所述的?D?D将sql statement类传给 query tag的这种类型应该标为tagdependent。 Z  #  
(Z @dz  
注意:实际上body-content的值并不影响tag处理类对body内容的处理,它仅仅是被tag编辑工具用来描述此body的内容。 )H]L/n  
i._RMl5zg  
Fs~*-R$  
用tags定义脚本变量 x>mI$K(6M  
wQhuU  
\15'~ ]d  
tag处理类 g]JJ!$*1  
Z" H;t\P  
*tT}N@<%  
tag处理类负责创建或设置页面中定义的脚本变量,用pageContext.setAttribute(name,value,scope)或pageContext.setAttribute(name,value)方法来实现。一般来说,tag处理类通过脚本变量的名称来获取它,脚本变量的名称一般可用get方法来获得。 PA803R74  
.7 )oWd!  
如果脚本变量的值依赖于tag处理类中的上下文中某一对象,那它可用pageContext.getAttribute(name,scope)方法来找到那个对象。一般的处理过程是tag处理类先找到脚本变量,再对其进行处理,然后用pageContext.setAttribute(name,object)的方法来设置它的新值。 SIm1fC  
qZ E3T:S  
对象的生存周期(scope)如下表: A@_>9;   
~9APc{"A  
对象的生存周期表 R}w}G6"\  
z &P1C,n)  
名字 5m'AT]5Tn_  
可访问范围 d3\?:}o,  
生存周期 %^E 7Iqc  
_(?`eWo  
page K_ymA,&()  
当前页面 :sK4mRF  
一直有效,除非页面向客户提交响应或重定向到一个新页面 s* u1n+Zq  
t90M]EAV  
request {hOS0).(w7  
当前页面或当前页面重定向到的页面 _:NQF7X#ug  
一直有效,除非页面向客户提交响应 OO?N)IB@  
:4)x  
session ks phO-  
当前页面或在同一浏览器窗口中的页面 :qqG%RB  
一直有效,除非关闭当前浏览器、超时、网络故障 6q'Q ?Uw^  
,6MJW#~]  
application Hmm0H6&u  
整个web应用程序的所有请求 Vb#a ,t  
一直有效,除非发生网络故障、服务器故障 At<MY`ka  
'OTZ&;7{  
提供关于脚本变量的信息 ^Os }sJ*5S  
]!!?gnPd5  
以下示例定义了一个名为“book”的脚本变量,用来访问程序中关于书的信息: 4Zu1G#(zP  
@i(9k  
<bean:define id=”book” name=”bookDB” property=”bookDetails” type=”database.BookDetails” /> un!v1g9O  
3O4lG e#u  
<font color=”red” size=”+2” > V;RgO}  
2V% z=  
<%= messages.getString(“CartRemoved”) %> 3f^jy(  
9 4H')(  
<strong><jsp:getProperty name=”book” property=”title” /></strong> t\QLj&h}E  
$X-PjQb1Bb  
</font> &R.5t/x_  
ORP<?SG55u  
当包含此tag的JSP页面被编译时,jsp引擎会自动生成关于此book的同步的代码(同步可以避免几个客户同时访问此book时造成的冲突),要生成同步代码,jsp引擎需要知道此脚本变量的如下信息: G na%|tUz|  
W;R6+@I[  
· 脚本变量名称 XNx$^I=  
EUI*:JU-  
· 脚本变量所属的类 :+>7m  
'?m2|9~  
· 此脚本变量是否引用了一个新的或已存在的对象 ipMSMk7gx  
- |DWPU!"  
· 此脚本变量的有效性 5tkKd4VfL  
h]~FYY  
有两种办法可以向jsp引擎提供关于脚本变量的信息:在TLD中定义variable子元素,或用tei-class子元素定义一个额外tag信息类。用variable最简单,但可能降低了一些灵活性。 aqqo>O3 s  
%X\A|V&  
Variable元素 R0#scr   
@$5~`?  
Variable元素有如下子元素: k kD#Bb  
C[%&;\3S@  
· name-given ?D?D 给出的名字,是一个常量 Sn'!Nq>  
6y Muj<L  
· name-from-attribute?D?D 属性名,在编译时给出的属性名 '3^qW  
RAhDSDf  
name-given或name-from-attribute两者必须选一,但以下子元素是可选的: WzR)R9x]  
\hI?XnL#  
· variable-class?D?D变量的类型,缺省为java.lang.String。 cs\=8_5  
t 3N}):  
· declare?D?D此脚本变量是否引用了一个新对象,缺省为True。 t@#5 G* _Q  
(i(E~^O  
· scope?D?D脚本变量的范围,缺省为NESTED。下表描述了scope的几种类型: n7~3~i` D;  
t>%b[(a  
脚本变量的有效范围 IFr"IOr'l  
mT@Gf>}/A  
9&zR i  
有效性 HH6H4K3Zj  
方法 \fC;b"j  
bG"FN/vg  
NESTED r|ZB3L|7  
在tag标签的开始和结束之间 $$0 < &  
如果tag处理类实现BodyTag接口,则在doInitBody和doAfterBody中调用,否则在doStartTag中调用 DC> R  
RJ0,7 E<B  
AT_BEGIN Yz[Rl ^  
从tag标签的开始一直到页面结束 }oG6XI9  
如果tag处理类实现BodyTag接口,则在doInitBody、doAfterBody和doEndTag中调用,否则在doStartTag和doEndTag中调用 iNi1+sm  
LzLJ6A>;R  
AT_END Bx}"X?%S  
从tag标签的结束一直到页面结束 _nzq(m1@  
在doEndTag中调用 ,MJddbcg  
[cEGkz  
以struts为例,它的bean:define标签的实现遵循JSP1.1规范,此规范要求使用额外tag信息类来定义脚本变量。Variable元素是JSP1.2规范中加入的。以bean:define标签为例,你可以定义如下variable元素: 9'~qA(=.?  
8/)q$zs  
<tag> !F~1+V>zP  
bxxLAWQ(  
<variable> Hr}"g@ <  
B[YyA  
<name-from-attribute>id</name-from-attribute> 5"3 `ss<m  
[bo"!Qk%  
<variable-class>database.BookDetails</variable-class> 3l`"(5  
cy mC?8<  
<declare>true</declare> .Xf_U.h$*@  
"8z Me L  
<scope>AT_BEGIN</scope> Si~wig2  
ljrJC  
</variable> 6=JJ!`"<2  
Cpd>xXZz&S  
</tag> u:(=gj,~x  
0^J%&1aIc  
额外tag信息类 .i_ gE5  
./7-[d  
如果要定义一个额外tag信息类,你要继承javax.servlet.jsp.TagExtraInfo类。一个TagExtraInfo类必须实现getVariableInfo方法,此方法返回一个叫VariableInfo的数组类,它包括如下信息: nSSJl  
jZidT9[g  
· 变量名 U)-aecB!  
avG#0AY  
· 变量所属类名 \,p?pL<'  
)q4nyT>M  
· 此变量是否引用了一个新对象 >a2[P"   
]P7gEBi  
· 此变量的有效范围 F:<+}{Av  
>#mKM%T2MJ  
jsp引擎将一个名为data的参数传给getVariableInfo方法,data中包括tag标签中的所有“属性名?D?D属性值”对。它可以用来向VariableInfo对象提供脚本变量的名字和类名。 $$4flfx  
BIx*(  
以struts为例,它在bean:define标签中定义了一个名为DefineTei的额外tag信息类,用来向脚本变量提供信息。由于脚本变量的名称(book)和类名(database.BookDetails)是通过tag标签的属性来传递的,它们一般定义在VariableInfo的构建代码中,并且可用data.getAttributeString方法来得到这些信息。如果要允许book脚本变量能在从tag开始直到整个JSP页面结束的范围内都可用的话,那它的范围应设为AT_BEGIN。如下所示: 8,+T[S  
d@*dbECG  
RB""(<  
public class DefineTei extends TagExtraInfo r/ATZAgHP  
" @ ""  
{ ^qC.bv]&  
75R4[C6T  
public VariableInfo[] getVariableInfo(TagData data) .*YOyK3H  
h \`(  
{ O\yYCi(  
6z~ [Ay  
String type = data.getAttributeString(“type”); 3 Z SU^v  
}*-fh$QJ  
If( type == null) p*cyW l  
Mx93D   
type = “java.lang.Object”; dXY}B=C  
P*?2+.  
return new VariableInfo[] { r SoT]6/   
x?0(K=h,  
new VariableInfo(data.getAttributeString(“id”), Lnn^j#n  
PeEaF@#k  
type, 1 +M !EW  
-Tuk.>i)  
true, BgCEv"G5  
9 s2z=^  
VariableInfo.AT_BEGIN) FRPdfo37  
TDP Q+Kg_  
}; G6Wa0Z  
g;o5m}  
} TK> ~)hc}  
l!j=em@  
} 7X$pgNRx/a  
DBvozTsF~  
M6]:^;p'  
注意:关于额外tag信息类的类名必须要在TLD中的tag标签下的tei-class子元素中定义。因此,DefineTei的tei-class中的定义看起来如下: yMgS0  
<tei-class> \!>qtFT  
org.apache.struts.taglib.bean.DefineTagTei ZL!5dT&@W  
</tei-class> ~^ '+ .  
5V0#_!QAN  
@WKJ7pt`'N  
具有协作关系的tag !,7)ZW?*8  
r:U<cL T[9  
%3HF_DNOY=  
tag通过共享对象来进行协作,JSP技术支持2种方式的对象共享。 1Sns$t%b  
J<cY'?D  
第一种方法是使用pageContext对象进行对象的共享(可支持JSP页面和tag处理类之间的共享),如果在一个tag处理类中要调用由另一个tag处理类创建的对象,可调用pageContext.getAttribute(name, scope)方法。 .k!2{A  
G [yI[7=d  
第二各方式的共享是对于tag之间有嵌套关系而言的,外层的tag所创建的对象对于内层的tag来说是可以共用的。这种形式的共享的好处是减少了可能存在的重名冲突。 /W}"/W9  
K7qR  
要访问一个嵌套tag创建的对象,tag处理类必须先找到此嵌套tag对象,可用TagSupport的静态方法 TagSupport.findAncestorWithClass(from, class)或TagSupport.getParent方法。前者在当不确定此tag是否为嵌套tag对象时使用。一旦它的父类被找到,它就能访问其所有动态或静态创建的对象。静态创建的对象是父类的成员,而动态创建的对象可能是父类的私有对象。诸如此类的对象可以用tag处理类的setValue方法来保存,用getValue方法来获得。 6k37RpgH  
Y|-&=  
下例阐述了以上两种共享对象的方法。在这个例子当中,一个查询tag检查一个名为connection的属性名是否在doStartTag中被设置。如果connection属性被设置,tag处理类从pageContext中得到这个connection对象。否则,此tag处理类先找到它的父tag处理类,然后从它的父tag处理类中找到connection对象。 mG *Yv  
!*"#*)S.  
O+Db#FW  
public class QueryTag extends BodyTagSupport a(`"qS  
?FZ) LZM  
{ mI^S% HT  
e]:(.Wb- 9  
private String connectionId; RM25]hx  
9I1i(0q  
public int doStartTag() throws JspException <{eJbNp  
%wJ>V-\e  
{ N_0B[!B]  
shY8h   
String cid = getConnection(); 1)-VlQK p  
sk t9mU  
if(cid != null) q{q;X{  
h)r=+Q\'(S  
{ QT"o"B  
.36]>8  
//存在一个connection id,使用它。 Ob|tA  
xCu\jc)2  
connection = (Connection) pageContext.getAttribute(cid); ~!Rf5QA85  
b|.<rV'BTt  
} 8feLhWg'P  
/)Weg1b  
else _#<7s`i  
ZZeF1y[q  
{ f_.0 uM  
#Y'ub 5s  
ConnectionTag ancestorTag = (ConnectionTag)findAncestorWithClass(this, d&DQ8Gm ^  
Hv =7+O$  
ConnectionTag.class); /XuOv(j  
j  W -K  
if(ancestorTag == null) ~.S/<:`U  
$|19]3T@Z  
{ 3HndE~_C&  
lp1GK/!s  
throw new JspTagException(“一个没有connection属性的查询标签必须被一个connection标记嵌套。”); wr6(C:  
WsmP]i^Q  
} 8/|1FI  
7z+Ngt' !  
connection = ancestorTag.getConnection(); 4_ZHY?VRd  
T'14OU2N{Y  
} 5%fR9?)  
"(;t`,F  
} ;Z&w"oSJ  
j|r$ ! gV  
} *.-qbwOg  
OV7SLf  
n*eqM2L  
pG$l   
此查询标签在JSP页面中的调用形式可以从以下2种定义中任选一种: xHn "D@  
g`H;~ w  
uX&Tn1Kg  
<tt:connection id=”con01” ...> ... </tt:connection> 6#2E {uy;R  
/8>we`4  
<tt:query id=”balances” connection=”con01” > P#2#i]-  
Rap_1o9#\  
SELECT account, balance FROM acct_table <'P+2(Oi  
T FK#ign  
where customer_num = <%= request.getCustno() %> HhUk9 >7  
^F+7@*u  
</tt:query> Qy'-3GB  
0&6(y* #Z  
3hR3)(+1  
04!akPP<  
+tv"j;z  
<tt:connection ...> SiT5QJe  
J~5+=V7OV  
<x:query id=”balances”> q{Gf@  
IOH6h=  
SELECT account, balance FROM acct_table /| [%~`?BM  
tfd!;`B  
where customer_num = <%= request.getCustno() %> %T~LK=m  
+?C7(-U>  
</x:query> 8wzQr2:  
5S%#3YHY2  
</tt:connection> $"{I| UFC  
^cI RP  
@9h6D<?  
与此同时,在TLD中必须指定connection属性为可选的,定义如下: [F^j(qTR  
lUM-~  
<tag> I oC}0C7  
/h K/t;  
... iaQ3mk#  
2NWQiSz  
<attribute> R-BN}ZS  
m)xz_Plc  
<name>connection</name> !;&{Q^}  
MZ <BCRB  
<required>false</required> (L7%V !  
M}!E :bv'  
</attribute> S>EO6z#   
sKL"JA T  
</tag>
描述
快速回复

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