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

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

级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
标准的JSP 标记可以调用JavaBeans组件或者执行客户的请求,这大大降低了JSP开发的复杂度和维护量。JSP技术也允许你自定义taglib,其实换句话说,taglib可以看成是对JSP标记的一种扩展,正如xml是对html的一种扩展一样。taglib通常定义在tag标签库中,这种标签库存放着你自己定义的tag标签。简而言之,如果使用taglib,那么你可以设计自己的JSP标记! Zj-U^6^L  
Y#Q!mbp  
一般来说,自定义tag标签主要用于操作隐藏对象、处理html提交表单、访问数据库或其它企业级的服务,诸如邮件和目录操作等等。自定义tag标签的使用者一般都是那些对java编程语言非常精通,而且对数据访问和企业级服务访问都非常熟悉的程序员,对于HTML设计者来说,使得他可以不去关注那些较复杂的商业逻辑,而将精力放在网页设计上。同时,它也将库开发者和库使用者进行合理分工,自定义tag标签将那些重复工作进行封装,从而大大提高了生产力,而且可以使得tag库可用于不同的项目中,完美地体现了软件复用的思想。 RD"-(T  
}:{9!RMO  
在这篇文章中,我们主要讨论: $'>JG9M  
|U;O HS  
· 什么是自定义tag标签? [U",yN]d  
343d`FRa}  
· 怎么使用tag标签? DO *  
+v 3: \#  
o 声明要使用的tag库 {J izCUo_'  
~##FW|N)  
o 找到与之对应的tag处理类 h@NC#Iod  
vpf.0!zh  
o tag标签的类型 f,E7eL@  
PuREqa\_[  
· 自定义tag标签 [520!JhZY  
\eNB L[  
o tag处理类 ~  z3J4s  
>W8"Ar  
o tag库描述 7 s{vou  
UO&$1rV  
o tag标签示例 >V?0#f45@  
* 30K}&T  
o 带属性的tag (E)hEQ@8  
RqGX(Iuv  
o 带body的tag x55W"q7  
?RS:I%bL  
o 定义了脚本变量的tag BCe'J!  
^Z#G_%\Y:  
o 具有协作关系的tag wEM=Tr/h  
YPI,u7-  
· 自定义tag标签 " (O3B  
)dX(0E4Td/  
o 一个迭代tag的例子 #+l`tj4b/  
Sx QA*}N  
o 一个模板tag库 RG'76?z  
2[Lv_<i|  
o tag处理类到底是怎样被调用的? *l{epum;  
Nj3iZD|  
n<j+KD#a  
什么是自定义的tag? Pb>/b\&JS  
po*8WSl9c[  
一个自定义的tag标签是用户定义的一种JSP标记。当一个含有自定义的tag标签的JSP页面被jsp引擎编译成servlet时,tag标签被转化成了对一个称为tag处理类的对象进行的操作。于是当JSP页面被jsp引擎转化为servlet后,实际上tag标签被转化成为了对tag处理类的操作。 6];3h>c]N  
KS93v9|  
自定义tag标签有很多特色,诸如: .!KsF h,pK  
 {Ba&  
· 可以在JSP页面中自定义tag标签的属性 YwET.(oo  
H}5WglV.  
· 访问JSP页面中的所有对象 s$>n U  
<^Vj1s  
· 可以动态地修改页面输出 :=;{w~D  
'7el`Ff  
· 彼此这间可以相互通信。你可以先创建一个JavaBeans组件,然后在一个tag中调用此JavaBeans组件,同时可以在另一个tag中调用它。 jw=PeT|  
GW;%~qH[,  
· tag允许相互嵌套,可以在一个JSP页面中完成一些复杂的交互。 "}qs +  
DbH;DcV7  
eIalcBY  
使用tag标签 [Cv./hEQi  
RYEZ'<  
I:iMRvp  
本节主要描述怎样在JSP页面中使用tag标签,以及tag标签的不同类型。 }' AY#g  
; $80}TY '  
要使用tag标签,JSP程序员必须做2件事: EZ .3Z`  
)S%t) }  
· 声明此tag标签的tag库 wxo  
z``wqK  
· 实现此tag标签 ;\2Z?Kq  
aim\ 3y~  
声明tag标签所在的tag库 QcQ%A%VIV  
A_oZSUrR  
如果要使用tag标签,则应用JSP的taglib指示符来指定其tag库(注意:taglib要在在使用此tag标签之前声明) jW`JThoq  
Cn3 _D  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %>  SW#/;|m  
&;d N:F;  
uri属性定义了唯一的标签库描述(以下简称TLD),它可以是直接是tld文件名或一个独一无二的名字。prefix是用来区别其它TLD中和本TLD中有重名的tag的一种手段。 (^ EuF]  
`T[@-   
TLD必须以.tld作为扩展名,并且存放在当前应用的WEB-INF目录或其子目录下。你可以通过它的文件名直接引用它,也可以通过别的方式间接地引用它。 IB[$~sGe  
e9KD mX_  
以下taglib指示符直接引用一个TLD: )ciP6WzzbI  
vlbZ5  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> j %gd:-tA  
N~O3KG q  
以下的taglib指示符通过一个逻辑名称间接地引用一个TLD: L/tn;0  
BM,hcT r?  
<%@ taglib uri=”/tutorial-template” prefix=”tt” %> ~/`/r%1/J  
0wv#AT  
如果是间接引用TLD的话,那你必须还要在web.xml中定义此逻辑名称与tld文件之间的映射,具体做法是在web.xml中加入一个名为taglib的元素: 1}DA| !~  
m g'q-G`\<  
<taglib> c("|xe  
oM~y8O  
<taglib-uri>/tutorial-template</taglib-uri> jn V=giBu  
|g3:+&  
<taglib-location> b/z-W`gw  
ja_8n["z  
/WEB-INF/tutorial-template.tld ]WDmx$"&e  
^b+>r  
</taglib-location> RtMI[  
v<!S_7h  
</taglib> kKSGC?d  
{g%N(2  
BUBx}dbCM  
实现此tag标签 eTS}-  
$5&%X'jk  
{\l  
为了实现tag标签,你有2种方法来存放tag处理类。一、让tag处理类以.class的方式存放于当前应用的WEB-INF/class子目录下,二、如果tag处理类是以JAR包的形式存在的话,那可以放在当前应用的WEB-INF/lib目录下,如果tag处理类要在多个应用中共享,那么它就应放在jsp服务器上的common/lib目录下,对于tomcat来说,就是tomcat/common/lib目录下。 \tI%[g1M  
sg $db62>  
yv[j Pbe  
tag标签类型 }UW7py!TN  
luf5-XT  
g^]Iw~T6$  
自定义的tag标签遵循XML语法。它有一个开始标记和一个结束标记,有的还有body(即文本节点): XX~vg>3_  
)Fv.eIBY  
<tt:tag>  l!|c_  
J2W-l{`r<  
body ~:z.Xu5m  
/e'3\,2_  
</tt:tag> LW]fme<V?  
=*,SD  
K?^;|m-  
一个不带body的tag标签如下: `-L?x2)U  
dM-cQo:  
<tt:tag /> 1(?4*v@B  
.zO2g8(VR  
c1'@_Is  
简单的tag标签 (gBKC]zvz3  
8 c8`"i  
一个没有body和属性的tag标签如下: N6y9'LGG`  
|RiJ>/ MK\  
<tt:simple /> !2LX+*;  
K|7"YNohfG  
15g! Q *v  
带属性的tag标签 ,&t+D-s<f  
!!1?2ine  
dE7x  SI  
自定义标签可以有自己的属性。属性一般在开始标记中定义,语法为 attr=”value”。属性的作用相当于自定义标签的一个参数,它影响着tag处理类的行为。你可以在TLD中详细定义它。 "<ZV'z  
Y P2VSK2Q  
你可以用一个String常量给一个属性赋值,也可以通过表达式给它赋值,如<%= ...%>。以struts为例,它的logic:present标签就是用的String常量来给属性赋值: C Bkoky 9&  
C& +MRP  
<loglic:present parameter = “Clear”> r[L%ap\{  
")|/\ w,  
而另一个标签logic:iterate是用表达式来给属性赋值: \HeJc:^  
+94)BxrY  
<logci:iterate collection=”<%= bookDB.getBooks() %>” &bsq;)wzs  
+lym8n~-O  
id=”book” type=”database.BookDetails”> +vh|m5"7I7  
NfgXOLthM  
;>J!$B?,  
带body的tag标签 T+0=Ou"N  
ob.<j  
一个自定义标签可以包含其它自定义标签、脚本变量、HTML标记或其它内容。 Bs~~C8+  
n1f8jS+'}  
在下述例子中,此JSP页面使用了struts的logic:present标签,如果些标签定义了parameter=”Clear”的属性,则将清除购物车的内容,然后打印出一条信息: } !m43x/&  
o^"+X7)  
<logic:present parameter=”Clear”>  q#K{~:  
-N45ni87  
<% cart.clear(); %> w+br)  
DB'0  
<font color=”#ff0000” size=”+2”><strong> E`IXBI  
Vm[Rp, "  
你选择了清除购物车! .a*?Pal@@  
N"S`9B1eD(  
</strong></font> pi"H?EHk  
,-pE/3|(  
</logic:present> uBm"Xkxe|w  
|#TU"$;  
o7) y~ ke  
到底是用属性还是用body来传递信息? )(}[S:`  
-H-U8/WC  
如上所述,我们既可以通过属性,也可以通过body来传递信息。但一般来说,比较简单的类型,如字符串或简单表达式最好采用属性来传递信息。 hg)Xr5>  
Th)  
5 D|#l*V  
定义脚本变量的tag标签 I\@r ~]+y  
*QC6zJ  
所谓脚本变量,是指JSP中可以调用的变量或对象。它可由tag标签产生。以下示例阐述了一个tag标签定义了一个名为tx的由JNDI所定义的事务处理对象。脚本变量可以是ejb对象、事务、数据库连接等等: 7~h3B<  
O =Z}DGa+  
<tt:lookup id=”tx” type=”UserTransaction” name=”java:comp/UserTransaction” /> .a%6A#<X  
%F*9D3^h  
<% tx.begin(); %> dAI^P/y%  
}je<^]a  
... [?]N GTr#  
h,{m{Xh  
t 7Q$  
具有协作关系的tag标签 7>Scf  
W{6QvQD8  
自定义tag标签之间可以通过共享对象来实现协作。在下述例子中,标签tag1创建了一个名为obj1的对象,在标签tag2仍可以重复使用obj。 z74JyY  
Kr}RFJ"d  
<tt:tag1 attr1=”obj1” value1=”value” /> BIx*t9wA  
EmNVQ1w  
<tt:tag2 attr1=”obj1” /> Za|7gt];l  
m eF7[>!U  
在以下这个例子当中,如果外层的tag标签创建了一个对象,那么其内层的所有tag标签都可以使用这个对象。由于这样产生的对象没有一个指定的名字,那么就可以将少重名的冲突。这个例子阐述了一系列协作的嵌套对象。 */aY $aWv  
+b|F_  
<tt:outerTag> k6tCfq;  
$S6(V}yh  
<tt:innerTag /> Rh'z;Gyr  
km %r{  
</tt:outerTag> >F$9&s&  
pzF_g- B  
T\6Qr$t  
Tag处理类 2I.FSR_G?  
y1V}c ,  
!sT>]e  
Tag处理类必须实现Tag接口或BodyTag接口,不过现在一般都流行从TagSupport或BodyTagSupport类中继承,这些类或接口都可以在javax.servlet.jsp.tagext包中找到。 NFT:$>83`  
a5a ;Fp  
当JSP引擎看到自己的JSP页面中包含有tag标签时,它会调用doStartTag方法来处理tag标签的开头,调用doEndTag方法来处理tag标签的结束。 r:QLU]   
GBz? $]6  
下表说明不同类型的tag所需要不同的处理过程: _J,**AZ~z  
i$Y#7^l%k  
Tag处理类的方法 V.~kG ,Ht  
1[egCC\Mo_  
Tag标签类型 dwA"QVp{  
所调用的方法 )."ob=m  
1$*8F  
基本标签 uYC^&siS<s  
doStartTag, doEndTag, release 9ihg[k  
gwj?.7N*k  
带属性的标签 8lF9LZ8  
doStartTag, doEndTag, set/getAttribute1...N, release {cdICWy(F3  
bmT%?it  
带内容的标签 }<Ydj .85  
doStartTag, doEndTag, release # qd!_oN  
)]>t(  
带内容的标签,且内容重复循环 0|GYtnd  
doStartTag, doAfterBody, doEndTag, release L$ T2 bul  
"aGmv9\  
带内容的标签,且内容与JSP交互 rZUTBLZ`j  
doStartTag, doEndTag, release, doInitBody, doAfterBody, release &9e  
4 ]oe`yx  
一个tag处理类可以通过javax.servlet.jsp.PageContext来与JSP交互,通过javax.servlet.jsp.PageContext类,tag处理类可以访问JSP中的request、session和application对像。 x?i wtZ@  
jFQy[k-B  
如果tag标签是互相嵌套的,那内层的tag处理类可以通过它的parent属性来访问上层的tag处理类。 !'$*Z(  
)<x9t@$  
一般情况都将所有的tag处理类打成了JAR的包,以便于发布。 M"z=114  
0:{W t  
Bc=(1ty)  
Tag库描述(简称TLD) @]Q4K%1^"  
xU;SRB   
0akJv^^D  
Tag库是用xml语言描述的,TLD包括了tag库中所有tag标签的描述,它一般用来被jsp服务器用来校验tag的语法正确性,或者被jsp开发者用来开发新的标签。 g`y9UYeh  
<@J$hs9s  
TLD的文件扩展名必须为.tld,而且必须放在当前WEB应用的WEB-INF目录或其子目录中。 V9[_aP;  
jOhAXe;~X{  
一个TLD的内容的开头必须遵守标准的XML开头,用于描述DTD和xml的版本,例如: ` nX, x-UM  
)!(gS,  
<?xml version="1.0" encoding="ISO-8859-1" ?> ruaZ(R[  
b:(+d"S  
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd"> H{cOkuy  
TLD必须以<taglib>来作为它的根元素,<taglib>的子元素如下表: FK BRJ5O  
p\zqZ=s  
9/"&6,  
<taglib>的子元素 A1zRzg4I  
c!@|y E,  
Element x8lBpr  
Description ~&:-c v  
?y|&Mz'XJ(  
tlib-version shw?_#?1dy  
Tag库的版本 or-k~1D  
091m$~r*  
jsp-version 5bb#{?2i  
Tag库所需要的jsp的版本 oyVT  
*twGIX  
short-name <MEm+8e/s6  
助记符,tag的一个别名(可选) P$'PB*5d|  
GW {tZaB  
uri bWL!=  
用于确定一个唯一的tag库 T4x%3-4 ;  
.XgY&5Qk  
display-name Y6wr}U  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) >s%Db<(P=  
fBX@ MedC  
small-icon }w)}=WmD  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) LR&MhG7  
i, ^-9  
large-icon X au %v5r  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) o?]Q&,tO  
Q`i@['?p  
description A^lm0[3q  
对tag库的描述(可选) U*nB= =  
wQW` Er3w  
listener "1|g eO|  
参见下面listener元素 j&ti "|2\  
&._"rhz  
tag Ee5YW/9]  
参见下面tag 元素 39^+;Mev  
)EMlGM'2q  
Listener元素 $`OyGeq"T  
d/GSG%zB  
一个tag库可能定义一些类做为它的事件侦听类,这些类在TLD中被称为listener 元素,jsp服务器将会实例化这些侦听类,并且注册它们。Listener元素中有一个叫listener-class的子元素,这个元素的值必须是该侦听类的完整类名。 @o[ZJ4>*  
m 70r'b]  
Tag元素 Q'U!  
gZHgL7@  
每个tag元素在tag库中都要指出它的名字、类名、脚本变量、tag的属性。其中脚本变量的值可以直接在TLD中定义或通过tag附加信息的类来取得。每个属性描述了这个属性是否可以省略,它的值是否可以通过<%= …%>这样的JSP语法来获得,以及属性的类型。 N5 sR  
AXcmN  
每一个tag在TLD中对应一个tag元素,下表是tag元素的子元素: pI f6RwH}%  
P^o@x,V!&  
Tag元素的子元素 U/FysN_N!  
t tr`  
元素名称 !ak760*A  
描述 e!Z}aOeE  
M_0f{  
name [Zdrm:=]L  
独一无二的元素名 8XVRRk  
:V$\y up  
tag-class L%[>z'Zp  
Tag标签对应的tag处理类 ="G2I\  
[<r.M<3  
tei-class b4:{PD~Mh  
javax.servlet.jsp.tagext.TagExtraInfo的子类,用于表达脚本变量(可选) 1.%|Er 4  
]U@~vA#''  
body-content q1 HJ_y  
Tag标签body的类型 KrP?*yk  
'Rnzu0<lF  
display-name #^9bBF/  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) o5/BE`VD5c  
I_#5gq  
small-icon xd `MEOY  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) 0fj C>AS  
o w(9dB&E  
large-icon @|h9jx|  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) RKrNmD*rk*  
1N65 M=)  
description ~%lUzabMa  
此tag标签的描述 {$t*XTY6R  
%1 RWF6  
variable _{):w~zi  
提供脚本变量的信息(同tei-class)(可选) |WUM=g7PC  
,e|"p[z ~T  
attribute B0 A`@9  
Tag标签的属性名 7"Nda3  
4'3;{k$z  
以下章节介绍对于不同类型的tag,如何具体地实现它们。 0"j:-1  
%4` U' j  
O\uIIuy  
简单的tag tvn o3"  
3AENY@*  
P cbhylKd  
tag处理类 +*W lj8  
jD<xpD  
简单的tag处理类必须实现Tag接口的doStartTag和doEndTag方法。当jsp引擎碰到tag标签的开头时,doStartTag被调用,因为简单的tag没有body,所以此方法将返回 SKIP_BODY。当jsp引擎碰到tag标签的结尾时,doEndTag被调用,如果余下的页面还要被计算,那它将返回EVAL_PAGE,否则将会返回SKIP_PAGE。 6 o   
W.s8!KH:  
以下是例子:对于标签 <tt:simple /> ,它的tag处理类实现如下: erv94acq  
G8'{nPA~  
Dl~(NLM  
public SimpleTag extends TagSupport NsS;d^%I  
h}nS&.  
{ {tOf0W|  
Px-VRANZt  
public int doStartTag() throws JspException 34CcZEQQ  
P )oNNY6}  
{ Y(aUB$"  
#Rfc p!  
try{ #|+4`Gf^  
I lO,Ql  
pageContext.getOut().print(“Hello.”); 6jm?d"9  
Q%~BD@Io  
}catch(Exception e){ 67/\0mV:~  
3 ;"[WOv  
throw new JspTagException(“SimpleTag: “ + e.getMessage()); / j "}e_Q  
A *:| d~  
} feS$)H9-  
;`xCfOY(  
return SKIP_BODY; 2Y9u9;ah  
NKEmY-f;  
} wWx{#!W  
iEI#J!~  
public int doEndTag() G*_]Lz(N  
FS)# v  
{ > jiez,  
r"K!]Vw  
return EVAL_PAGE; DC_uh  
^AI02`c.  
} 2::YR?  
+qpG$#J0  
} J9;fqQCt  
du'`&{_/  
 /s^42  
注意:如果tag标签没有内容的话,那必须定义body-content元素为空,例如 &:ZR% f  
YH+(N  
<body-content>empty</body-content> Uu*iL< `  
&Qv HjjQ?u  
(#6Fg|f4Y  
带属性的tag标签
评价一下你浏览此帖子的感受

精彩

感动

搞笑

开心

愤怒

无聊

灌水
级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
只看该作者 1 发表于: 2007-01-01
tag处理类 DC/Czkv9  
a-S tOO5s  
对于tag标签的每个属性,你必须依照JavaBeans规范来定义其属性,以及get和set方法。以struts的logic:present 标签为例, IIT[^_g  
R|$b\3  
<logic:present parameter=”Clear”> iO Z#}"  
i?b9zn  
与此相应,此tag处理类应有如下方法和定义: iF +@aA  
}=\?]9`  
CV=qcD  
protected String parameter = null; 21Dc.t{  
"l-#v| 54  
public String getParameter() )HI\T];  
m3o -p   
{ 2<!IYEyT  
DOGGQ$0  
return this.parameter; |qj"p  
co\Il]`R/  
} - 7T`/6  
32HF&P+0%  
public void setParameter(String parameter) .`_iWfK  
.vy@uT,  
{ 8!.V`|@lt  
!x ~s`z  
this.parameter = parameter; "P|n'Mx  
WvArppANo  
} 2 z#S| $  
cNwH Y Z'  
)qMbk7:v\  
注意:如果你的属性名为id,而且你的tag处理类是从TagSupport类继承的,那你就不需要定义它的属性和set和get方法,因为他们早已在TagSupport被定义过了。 opm_|0  
?aWVfX!+G5  
Attribute元素 EFx>Hu/ [G  
'nM4t  
对于tag标签的每个属性,你必须定义它是否必须的,它的值是否可以用诸如<%= …%>的表达式来获得,以及它的类型(可选),如果不指定它的类型,那就默认为是java.lang.String类型。如果rtexprvalue元素被定义为true或yes,那么在type元素中就定义了attribute的返回类型。 )=iv3nF?6N  
<b *sn] l  
<attribute> 9M($_2,44  
VoUo!t:(+  
<name>attr1</name> QD3tM5(Yr  
P%Vq#5  
<required>true|false|yes|no</required> } )L z%Z  
45wtl/^9  
<rtexprvalue>true|false|yes|no</rtexprvalue> ;ltk}hJ]  
XKws_  
<type>attribute的返回类型(只用当rtexprvalue为真是才有效)</type> vOz1& |;D  
-8FUR~WJ  
</attribute> ,m]5j_< }  
Bf #cBI  
如果tag的某个属性不是必须的,那tag处理类会自动提供一个缺省值。 }Md;=_TP  
-@_v@]:  
例如,在logic:present这个tag标签中定义了一个属性叫parameter,但它不是必须的,而且它可以被诸如<%= …%>的表达式来赋值。 Q 318a0  
-L]-u6kC[  
<tag> 1|"BpX~D  
OqciZ@#5n  
<name>present</name> x>##qYT  
j-R*!i  
<tag-class>org.apache.struts.taglib.logic.PresentTag</tag-class> y2jw3R  
 3TCRCz  
<body-content>JSP</body-content> ,>b>I#{  
*IWW,@0  
8 I_  
"|1iz2L  
<attribute> 7M7Ir\d0lp  
IKP GqoM  
<name>parameter</name> {]}94T~/k  
mgVYKZWL-i  
<required>false</required> $57b.+2n  
p$|7T31 *  
<rtexprvalue>true</rtexprvalue> eZU9L/w:  
-j]k^  
</attribute> m#8 PX$_  
]7K2S{/o{  
7`A]X,:  
R Qo a  
</tag> O8bxd6xb  
Kf BT'6t  
J=$\-  
属性元素的校验 Q*%}w_D6f  
kUS]g r~i  
`q<W %'Tb$  
有关于tag标签的有效值可以从tag库的说明文档中获得,当JSP页面被编译时,jsp引擎会强制性地参照TLD中定义的规则进行检查。 U7 D!w$4  
&5R|{',(Y  
还有一个方法也可以进行属性元素的校验,就是先继承类TagExtraInfo,然后调用它的isValid方法。这个类同时也起到提供tag中定义的脚本变量信息的作用。 'n,V*9  
bz#]>RD  
IsValid方法通过TagData对象来传递属性信息,它包括着tag的所有的属性名-值的信息。由于校验发生在运行时刻,因此这个属性的值将被赋值为TagData.REQUEST_TIME_VALUE。 =iKl<CqI$E  
cXqYO|3/M  
例如tag标签<tt:twa attr1=”value1” />在TLD中定义如下: C[ mTVxd  
KsOWTq"uj  
<attribute> JL1A3G  
JJtx `@Bc  
<name>attr1</name> yTd8)zWq  
J,CwC)  
<required>true</required> \|{/.R  
S$Zi{bU`G  
<rtexprvalue>true</rtexprvalue> \*e\MOp6  
BXYH&2]Q  
</attribute> Wj(#!\ 7F  
m!%aB{e  
thJ~* 0^  
这个定义说明了attr1能在运行期间被赋值。 6u+aP  
I6f/+;E  
以下的isValid方法检查attr1属性的值是否属于Boolean类型。注意由于attr1能在运行刻被赋值,那么isValid方法必须检查tag用户是否对此tag进行了运行时刻赋值。 b),fz  
3*=0`}jMJ  
OQKeU0v  
Public class TwaTEI extends TagExtraInfo rT/r"vr  
"hf |7E_  
{ ]9y\W}j  
q iOJ:'@  
public boolean isValid(Tagdata data) [MFnS",7c  
s||" } l  
{ :NF4[c  
P Y^#hC5:  
Object o = data.getAttribute(“attr1”); ^HJ?k:u  
WrGnLE kiV  
If(o != null && o != TagData.REQUEST_TIME_VALUE) Mq Ai}z%  
vW=L{8zu  
{ .N qXdari  
jhm??Af  
if( ( (String)o).toLowerCase().equals(“true”) || m<-ShRr*b  
I} jgz  
((String)o).toLowerCase().equals(“false”) ) 3@gsKtA&H4  
Ck Nl;g l  
return true; }<0N)dpT  
Xv-p7$?f  
else m|qktLx  
;Nj9,Va(t  
return false; aE`d[d SG  
+ GI906K  
} Q< :RLKVT  
R{H[< s+n  
else e(? w h   
y'K2#Y~1e  
return true; !,m  
gQ>kDl^$Ls  
} HYfGu1j?X  
 m[B#k$  
} sF{aG6u   
X@\W* nq  
DpT9"?g7  
带body的tag g |>LT_  
sCFxn  
H&)}Z6C"  
tag处理类 +P2oQ_Fk`9  
!5o j~H  
e|\xF V=4  
如果tag标签含有内容,那处理方式会略微有些不同,而且还要视tag处理类是否要与body交互的情况而定。如果要与body交互,那我们认为tag处理类要可能要对body进行操作。 IW0S*mO$  
i7Up AHd/  
Tag处理类不与body交互 }uZs)UQ|$  
y QW7ng7D0  
如果tag处理类不与body交互,tag处理类应该实现Tag接口或从TagSupport中派生,如果body要被计算,那么doStartTag方法应返回 EVAL_BODY_INCLUDE,否则应返回SKIP_BODY。 \l~^dn}  
RRIh;HhX  
如果tag处理类要对body反复运算,则它应该实现IterationTag或从TagSupport中派生。如果tag处理类认为body还未计算完的话,那它的doStartTag方法和doAfterBody方法必须返回EVAL_BODY_AGAIN。 |vI`u[P  
SeD}H=,@  
Tag处理类与body交互 -&5YRfr!  
aTuu",f  
如果tag处理类与body交互,那tag处理类应实现BodyTag接口或从BodyTagSupport中派生。这种tag处理类一般要实现doInitBody和doAfterBody方法。 -fq  
K($l>PB,y@  
Body允许一些方法来读写它的内容。Tag处理类可以调用body内容的getString或getReader方法来从body中提取信息,也可用 writeOut(out) 方法来将body的内容写入到out对象中。其中out对象通过tag处理类的getPreviousOut方法来获得。 l_^SU8i57  
W,<q!<z\t  
如果body的内容需要被计算,那么doStartTag方法必须返回EVAL_BODY_BUFFERED,否则,它将返回 SKIP_BODY。 zw>L0gC  
t}YcB`q)  
doInitBody 方法 ?*fY$93O  
vk92j?  
此方法在body内容已经设好,但未被计算之前被调用。你可以根据不同的body内容来制定初始化策略。 b6N[t _,  
p{g4`o  
doAfterBody方法 ;Bs~E  
C`[<6>&y  
此方法在body内容已被计算后进行调用。 8:,($a/KF  
kFn/dQ4|  
和doStartTag方法一样,doAfterBody方法返回一个指示符指示是否要继续计算body,如果要继续计算,则doAfterBody应返回EVAL_BODY_BUFFERED,否则,它应返回SKIP_BODY。 V*giF`gq  
Q/+`9z+c  
release 方法 Muo E~K2  
<\^0!v  
tag处理类调用此方法将它的状态重置为初始状态,并释放所有的私有资源。 QqA=QTZ}  
v'W{+>.  
bhqSqU}6~  
以下的例子读取body的内容(其中含有一条sql语句),然后将它传递给一个对象,让它进行查询。由于此处body不须重新计算,所以doAfterBody会返回SKIP_BODY。 h_%q`y,  
.^Sgl o  
heVk CM :  
Public class QueryTag extends BodyTagSupport "v8p<JfB`  
V?uT5.B2  
{ @+gr/Pul^  
J}#gTG( '  
public int doAfterBody() throws JspTagException ?=? _32O  
>'*%wf[{  
{ 6 c_#"4  
-s3`mc}*  
BodyContent bc = getBodyContent(); qoO`)<  
4&}%GH>}  
//将body的内容以字符串的格式提取出来 u 272)@R  
kxMvOB$  
String query = bc.getString(); paqGW]  
*N">93:  
//清除body =;rLv7(a  
SqM>xm  
bc.clearBody(); 0q}i5%m7  
h?mDtMCw2  
try{ S,m(  
5\+*ml  
Statement stmt = connection.createStatement(); 5Gz!Bf@!!  
2S?7j[@%i`  
Result result = stmt.executeQuery(query); >,e^}K}C  
}[AaI #  
}catch(SQLException e){ Vrt$/ d  
F9fLJol  
throw new JspTagException(“queryTag: “ + e.getMessage() ); 5,"c1[`-  
2 XP }:e  
return SKIP_BODY; fiGTI}=P  
UA>=# $  
} u]yy%@U1  
"q=Cye  
} (dy(.4W\  
>y3FU1w5d  
>q"dLZ  
body-content元素 `i.BB jx`  
,mHME~  
Y^fw37b  
由于tag可能会有body,你必须用body-content元素来指定body内容的类型: -DI >O/  
GX>8B:]o|  
<body-content>JSP|tagdependent</body-content> m5K?oV@n  
9&lemz  
r48|C{je-  
如果body的内容是定制的或内部的tag、脚本元素、或HTML广本,则归类为JSP类型。其他的类型,比如上面代码所述的?D?D将sql statement类传给 query tag的这种类型应该标为tagdependent。 &<A,\ M  
Qg4D*r\|@  
注意:实际上body-content的值并不影响tag处理类对body内容的处理,它仅仅是被tag编辑工具用来描述此body的内容。 y )QLR<wf  
`YNzcn0x  
Sdu\4;(  
用tags定义脚本变量 {wqT$( (<  
bb6x} jR  
(GJtTp~2C4  
tag处理类 _Mw3>GNl  
D2$ 9$xeR  
eZ'8JU]  
tag处理类负责创建或设置页面中定义的脚本变量,用pageContext.setAttribute(name,value,scope)或pageContext.setAttribute(name,value)方法来实现。一般来说,tag处理类通过脚本变量的名称来获取它,脚本变量的名称一般可用get方法来获得。 L'+bVP{L  
] ZV[}7I.  
如果脚本变量的值依赖于tag处理类中的上下文中某一对象,那它可用pageContext.getAttribute(name,scope)方法来找到那个对象。一般的处理过程是tag处理类先找到脚本变量,再对其进行处理,然后用pageContext.setAttribute(name,object)的方法来设置它的新值。 [`n_> p!  
=U]9>  
对象的生存周期(scope)如下表: 8 v/H;65  
%U\,IO`g  
对象的生存周期表 6,>$Jzs)5E  
K*~{M+lU7  
名字 3=O [Q:8  
可访问范围 ;_<~9;  
生存周期 ~KK} $iM  
sxNf"C=-.  
page [D"6&  
当前页面 )+_Vx}O:}  
一直有效,除非页面向客户提交响应或重定向到一个新页面 qG9a!sj   
KF%BX ~80C  
request k2}DBVu1  
当前页面或当前页面重定向到的页面 G6G Bqp6|  
一直有效,除非页面向客户提交响应 %e iV^>  
@ {/)k%U  
session "Z.6@ c7  
当前页面或在同一浏览器窗口中的页面 p{Lrv%-j  
一直有效,除非关闭当前浏览器、超时、网络故障 ynI e4b  
]A5F}wV4  
application ha :l-<a  
整个web应用程序的所有请求 =pL$*`]?  
一直有效,除非发生网络故障、服务器故障 jSI1tW8  
wHLQfrl0  
提供关于脚本变量的信息 E7X6RB b  
odhcD;^X1  
以下示例定义了一个名为“book”的脚本变量,用来访问程序中关于书的信息: q/s-".%P  
K=gg<E<  
<bean:define id=”book” name=”bookDB” property=”bookDetails” type=”database.BookDetails” /> #C9f?fnM  
f_~T  
<font color=”red” size=”+2” > dxeiN#(XT  
,/f\  
<%= messages.getString(“CartRemoved”) %> C[7!pd  
JwG(WLb:  
<strong><jsp:getProperty name=”book” property=”title” /></strong> 0D5Z#iW>1  
_Ewh:IM-  
</font> %' DO FiU  
R"cQyG4  
当包含此tag的JSP页面被编译时,jsp引擎会自动生成关于此book的同步的代码(同步可以避免几个客户同时访问此book时造成的冲突),要生成同步代码,jsp引擎需要知道此脚本变量的如下信息: iOiF kka  
*AH `ob}  
· 脚本变量名称 4|x _C-@  
SU0SsgFB  
· 脚本变量所属的类 g[} L ?  
^/n1h g  
· 此脚本变量是否引用了一个新的或已存在的对象 #}7T$Va  
HPtMp#`T  
· 此脚本变量的有效性 W@R7CQE@  
Rw+r1vW:A  
有两种办法可以向jsp引擎提供关于脚本变量的信息:在TLD中定义variable子元素,或用tei-class子元素定义一个额外tag信息类。用variable最简单,但可能降低了一些灵活性。 )tlj{ 7p  
iv*RE9?^  
Variable元素 |8 ` }8vo)  
ex>7f%\  
Variable元素有如下子元素: 9\8ektq}Z  
V(ELrjB0  
· name-given ?D?D 给出的名字,是一个常量 xlv(PVdn  
Gu$/rb?  
· name-from-attribute?D?D 属性名,在编译时给出的属性名 cH_qHXi[G  
+`d92Tz  
name-given或name-from-attribute两者必须选一,但以下子元素是可选的: ,^9+G"H:I  
P zJ(Q  
· variable-class?D?D变量的类型,缺省为java.lang.String。 qiz(k:\o  
[4"(\r\f  
· declare?D?D此脚本变量是否引用了一个新对象,缺省为True。 \uZpAV)5  
$0V+<  
· scope?D?D脚本变量的范围,缺省为NESTED。下表描述了scope的几种类型: Uu7]`Ul  
] (e ,J  
脚本变量的有效范围 utck{]P  
tA1?8`bQ  
bB<S4@jF8z  
有效性 6,q0F*q  
方法  q0ktABB  
gS FZ>v*6  
NESTED 8F[ ];LF>  
在tag标签的开始和结束之间 Y-it3q'Z  
如果tag处理类实现BodyTag接口,则在doInitBody和doAfterBody中调用,否则在doStartTag中调用 -6)nQNj|  
rWr'+v?  
AT_BEGIN xP\s^]e  
从tag标签的开始一直到页面结束 #$UwJB]_D  
如果tag处理类实现BodyTag接口,则在doInitBody、doAfterBody和doEndTag中调用,否则在doStartTag和doEndTag中调用 :Wbp|:N0  
kqB# 9  
AT_END kn:hxdZ  
从tag标签的结束一直到页面结束 vHvz-3  
在doEndTag中调用 L } R"1O  
GvtK=A$b  
以struts为例,它的bean:define标签的实现遵循JSP1.1规范,此规范要求使用额外tag信息类来定义脚本变量。Variable元素是JSP1.2规范中加入的。以bean:define标签为例,你可以定义如下variable元素: tav@a)  
3I 0pHP5  
<tag> YeCnk:_ kg  
.]E(P   
<variable> X3sAy(q  
(Z<@dkO?)  
<name-from-attribute>id</name-from-attribute> |&K;*g|a  
y A5h^I  
<variable-class>database.BookDetails</variable-class> lITd{E,+r  
8Yc-3ozH  
<declare>true</declare> h[dJNawL  
QPm[4Fd{G  
<scope>AT_BEGIN</scope> (rFkXK4^J  
faOiNR7;h  
</variable> 4A+g-{d  
4D&L]eJ  
</tag> H!Gw@u]E  
$7YZ;=~B  
额外tag信息类 gw)z*3]~s  
6wpW!SWD  
如果要定义一个额外tag信息类,你要继承javax.servlet.jsp.TagExtraInfo类。一个TagExtraInfo类必须实现getVariableInfo方法,此方法返回一个叫VariableInfo的数组类,它包括如下信息: #~p;s>  
cn}15JHdR  
· 变量名 XoD:gf  
^?{&v19m  
· 变量所属类名 B-g-T>8  
4- QlIIf  
· 此变量是否引用了一个新对象 }`CF(Do  
<,$*(dX)(  
· 此变量的有效范围 !,ODczWvh  
<Y6Vfee,&  
jsp引擎将一个名为data的参数传给getVariableInfo方法,data中包括tag标签中的所有“属性名?D?D属性值”对。它可以用来向VariableInfo对象提供脚本变量的名字和类名。 by1q"\-,  
NK|U:p2H  
以struts为例,它在bean:define标签中定义了一个名为DefineTei的额外tag信息类,用来向脚本变量提供信息。由于脚本变量的名称(book)和类名(database.BookDetails)是通过tag标签的属性来传递的,它们一般定义在VariableInfo的构建代码中,并且可用data.getAttributeString方法来得到这些信息。如果要允许book脚本变量能在从tag开始直到整个JSP页面结束的范围内都可用的话,那它的范围应设为AT_BEGIN。如下所示: u>;aQtK~  
q25p3  
2|7:`e~h  
public class DefineTei extends TagExtraInfo ="]lN  
|8E~C~d  
{ r.)n>  
yLf9cS6=  
public VariableInfo[] getVariableInfo(TagData data) !RJ@;S  
v 8F{qT50  
{ 62nmm/c  
Kz b-a$  
String type = data.getAttributeString(“type”); ,m*HRUY  
9+ Mj$  
If( type == null) Q=! lbW  
> 3x^jh  
type = “java.lang.Object”; $cn8]*Z =  
d7BpmM  
return new VariableInfo[] { O-[YU%K3?  
Ak3^en  
new VariableInfo(data.getAttributeString(“id”), F4~ OsgZ'N  
cAN8'S(s1  
type, n',7=~  
.WSn Y71  
true, 41/civX>V  
@F8NN\  
VariableInfo.AT_BEGIN) Q1Qw45$  
(,sz.  
}; V}TPt6C2  
Ur 1k3  
} ^jL44? W}l  
,Gy,bcv{  
} bv <^zuV  
?1g`'q@T%  
o#"yFP1  
注意:关于额外tag信息类的类名必须要在TLD中的tag标签下的tei-class子元素中定义。因此,DefineTei的tei-class中的定义看起来如下: +s_a{iMVP  
<tei-class> Zbl*U(KU?  
org.apache.struts.taglib.bean.DefineTagTei *0oa2fz%  
</tei-class> *DcIC]ao[  
XR8`,qH>  
hgYFR6VH  
具有协作关系的tag `6-flc0r  
X*#\JF4$i  
zEQQ4)mA  
tag通过共享对象来进行协作,JSP技术支持2种方式的对象共享。 7h(  
)+v5 H  
第一种方法是使用pageContext对象进行对象的共享(可支持JSP页面和tag处理类之间的共享),如果在一个tag处理类中要调用由另一个tag处理类创建的对象,可调用pageContext.getAttribute(name, scope)方法。 %@(+`CCA  
_!|$i  
第二各方式的共享是对于tag之间有嵌套关系而言的,外层的tag所创建的对象对于内层的tag来说是可以共用的。这种形式的共享的好处是减少了可能存在的重名冲突。 KUPQ6v }  
|H=5Am  
要访问一个嵌套tag创建的对象,tag处理类必须先找到此嵌套tag对象,可用TagSupport的静态方法 TagSupport.findAncestorWithClass(from, class)或TagSupport.getParent方法。前者在当不确定此tag是否为嵌套tag对象时使用。一旦它的父类被找到,它就能访问其所有动态或静态创建的对象。静态创建的对象是父类的成员,而动态创建的对象可能是父类的私有对象。诸如此类的对象可以用tag处理类的setValue方法来保存,用getValue方法来获得。 n[y=DdiKGS  
?lqqu#;8  
下例阐述了以上两种共享对象的方法。在这个例子当中,一个查询tag检查一个名为connection的属性名是否在doStartTag中被设置。如果connection属性被设置,tag处理类从pageContext中得到这个connection对象。否则,此tag处理类先找到它的父tag处理类,然后从它的父tag处理类中找到connection对象。 uFmpc7  
b i-Am/9  
k~;~i)Eg  
public class QueryTag extends BodyTagSupport Tq* <J~-  
JoB-&r}\V*  
{ | #a{1Z)  
3v$n}.  
private String connectionId; !M}-N  
?!F<xi:  
public int doStartTag() throws JspException +?t& 7={~  
zxs)o}8icO  
{ *fd:(dN|  
?r]0%W^  
String cid = getConnection(); )w}'kih  
S&=@Hj-  
if(cid != null) qDg`4yX.}  
T+0z.E!~I  
{ I_Z?'M  
i`6utOq  
//存在一个connection id,使用它。  S\ZCZ0  
RKMF?:  
connection = (Connection) pageContext.getAttribute(cid); ve a$G~[%6  
,]qc#KDq-1  
} ?l[#d7IB  
)jwovS?V  
else f7 ew<c\  
'M?pg$ta_V  
{ U4a8z<l$  
}j6|+  
ConnectionTag ancestorTag = (ConnectionTag)findAncestorWithClass(this, L#D)[v"  
=.J>'9Q  
ConnectionTag.class); -q)|I|y*7  
|VE.khq#  
if(ancestorTag == null) \p\p~FVS  
1 h162  
{ e?XGv0^qu  
&9Z@P[f  
throw new JspTagException(“一个没有connection属性的查询标签必须被一个connection标记嵌套。”); +yr~UP_ }  
D}{]5R  
} i5WO)9Us  
dqU)(T=C  
connection = ancestorTag.getConnection(); a{;+_J3S  
-'oxenu  
} Ss{5'SF)$c  
]9<H[5>$R  
} !#5y%Bf  
\'w.<)(GI  
} w4^ $@GtN  
^eV  K.  
}f{5-iwD}  
4*n1Xu 7^x  
此查询标签在JSP页面中的调用形式可以从以下2种定义中任选一种: 0jXDjk5'<  
3<Z@!ft8  
0aGauG[  
<tt:connection id=”con01” ...> ... </tt:connection> ;$*tn"- ?~  
KB\ri&bF  
<tt:query id=”balances” connection=”con01” > _=[pW2p  
E^w0X,0XlE  
SELECT account, balance FROM acct_table 0ikA@SAq  
: @gW3'  
where customer_num = <%= request.getCustno() %> e'v_eD T^  
/lHs]) ,  
</tt:query> <g&GIFE,  
8SiWAOQAL  
5M>SrZH  
oY\;KPz  
-G1R><8[  
<tt:connection ...> Uu`}| &@i  
! }eq~3  
<x:query id=”balances”> M.$=tuUL  
925T#%y  
SELECT account, balance FROM acct_table 5}]gL  
`]&'yt  
where customer_num = <%= request.getCustno() %> "|WKK}  
d.>O`.Mu)}  
</x:query> )C$Ij9<A  
Py9:(fdS  
</tt:connection> vXSpn71Jb  
Y}\3PaUa  
527u d^:  
与此同时,在TLD中必须指定connection属性为可选的,定义如下: % 5!Y#$:{o  
2{hG",JL  
<tag> d)%l-jj9,  
Me+)2S 9  
... /PBK:B  
a5]]AkvA  
<attribute> !$-QWKD4  
 poZ&S  
<name>connection</name> pL.~z  
v`jFWq8I,  
<required>false</required> WK SWOSJ  
mL@7,GD  
</attribute> JS >"j d#  
@nj`T{*.  
</tag>
描述
快速回复

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