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

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

级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
标准的JSP 标记可以调用JavaBeans组件或者执行客户的请求,这大大降低了JSP开发的复杂度和维护量。JSP技术也允许你自定义taglib,其实换句话说,taglib可以看成是对JSP标记的一种扩展,正如xml是对html的一种扩展一样。taglib通常定义在tag标签库中,这种标签库存放着你自己定义的tag标签。简而言之,如果使用taglib,那么你可以设计自己的JSP标记! 9&bJ]  
d"tR ?j  
一般来说,自定义tag标签主要用于操作隐藏对象、处理html提交表单、访问数据库或其它企业级的服务,诸如邮件和目录操作等等。自定义tag标签的使用者一般都是那些对java编程语言非常精通,而且对数据访问和企业级服务访问都非常熟悉的程序员,对于HTML设计者来说,使得他可以不去关注那些较复杂的商业逻辑,而将精力放在网页设计上。同时,它也将库开发者和库使用者进行合理分工,自定义tag标签将那些重复工作进行封装,从而大大提高了生产力,而且可以使得tag库可用于不同的项目中,完美地体现了软件复用的思想。 ,u=+%6b)A  
zHKx,]9b  
在这篇文章中,我们主要讨论: UyAy?i8K  
}tO>&$ Z6f  
· 什么是自定义tag标签? )x<BeD  
`B~zB=}  
· 怎么使用tag标签? Ig<# {V  
CK#i 6!~r  
o 声明要使用的tag库 NX5$x/uz  
.^6yCs5~`  
o 找到与之对应的tag处理类 :'FCeS9  
DP-0,Gt&Xj  
o tag标签的类型 3RF`F i  
V KxuK0{  
· 自定义tag标签 )nGH$Mu  
KE6 XNG3  
o tag处理类 k;Fxr%  
*L~?.9R  
o tag库描述 nkzH}F=<  
Qff.QI,  
o tag标签示例 Yd(<;JKF[  
CQPq5/@Y4  
o 带属性的tag X}wo$t  
4y.qtiIP>$  
o 带body的tag &smZ;yb|'h  
8F&Y;  
o 定义了脚本变量的tag 4peRbm  
Q_Wg4n5  
o 具有协作关系的tag `2/V.REX$h  
yJ="dEn>i"  
· 自定义tag标签 dZox;_b  
{:|b,ep T  
o 一个迭代tag的例子 tXuf!  
"|Kag|(qB  
o 一个模板tag库 m@UrFPZ  
^#XQ2UN  
o tag处理类到底是怎样被调用的? pfs]pDjS:  
]:;dJc'  
\XO'7bNu-  
什么是自定义的tag? &;sW4jnt  
~6K.5t7  
一个自定义的tag标签是用户定义的一种JSP标记。当一个含有自定义的tag标签的JSP页面被jsp引擎编译成servlet时,tag标签被转化成了对一个称为tag处理类的对象进行的操作。于是当JSP页面被jsp引擎转化为servlet后,实际上tag标签被转化成为了对tag处理类的操作。 R9(Yi<CC  
Dr76+9'i  
自定义tag标签有很多特色,诸如: JLt%G^W >  
^X?uAX-RP|  
· 可以在JSP页面中自定义tag标签的属性 "lrQC`?  
l"7#(a  
· 访问JSP页面中的所有对象 U~d%5?q  
'Z]wh.]T  
· 可以动态地修改页面输出 NTEN  
@j"6f|d  
· 彼此这间可以相互通信。你可以先创建一个JavaBeans组件,然后在一个tag中调用此JavaBeans组件,同时可以在另一个tag中调用它。 `(ik2#B`}  
T2n3g|4  
· tag允许相互嵌套,可以在一个JSP页面中完成一些复杂的交互。 S>)[n]f  
w IP4Z^  
"%b Gw v  
使用tag标签 2m"cK^  
pSI8"GwQ  
D&@Iuo  
本节主要描述怎样在JSP页面中使用tag标签,以及tag标签的不同类型。 ?bpV dm!  
-:kIIK   
要使用tag标签,JSP程序员必须做2件事: J"Fp),  
m\XG7uo~  
· 声明此tag标签的tag库 jSSEfy>^  
'F#dv[N  
· 实现此tag标签 V/:2xT  
9 r&JsCc  
声明tag标签所在的tag库 ];jp)P2o  
O"/Sv'|H#  
如果要使用tag标签,则应用JSP的taglib指示符来指定其tag库(注意:taglib要在在使用此tag标签之前声明) IT)3Et@Y  
C#4_`4{  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> >q0%yh-  
IA{W-RRb  
uri属性定义了唯一的标签库描述(以下简称TLD),它可以是直接是tld文件名或一个独一无二的名字。prefix是用来区别其它TLD中和本TLD中有重名的tag的一种手段。 6B*#D.fd*  
Ndmw/ae  
TLD必须以.tld作为扩展名,并且存放在当前应用的WEB-INF目录或其子目录下。你可以通过它的文件名直接引用它,也可以通过别的方式间接地引用它。 T"aE]4_  
w0+X;aId  
以下taglib指示符直接引用一个TLD: a4gX@&it_k  
AW E ab  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> awI{%u_(nA  
Y%?*Lj|  
以下的taglib指示符通过一个逻辑名称间接地引用一个TLD: bdY:-8!3  
nt+OaXe5D  
<%@ taglib uri=”/tutorial-template” prefix=”tt” %> ~A1!!rJX  
aj,o<J  
如果是间接引用TLD的话,那你必须还要在web.xml中定义此逻辑名称与tld文件之间的映射,具体做法是在web.xml中加入一个名为taglib的元素: 1;DRcVyS+  
V#b=mp  
<taglib> @OGG]0 J  
fUGappb  
<taglib-uri>/tutorial-template</taglib-uri> Zxhbnl6  
N|Ag8/2A  
<taglib-location> q3#+G:nh  
(Q @'fb9z  
/WEB-INF/tutorial-template.tld x$bUd 9  
aL`wz !  
</taglib-location> "<{|ni}  
,p OGT71  
</taglib> 3Pllxq<n  
"wuO[c&%/  
jd,i=P%  
实现此tag标签 ~%C F3?e6  
[0hahR  
Lr 5{c5M  
为了实现tag标签,你有2种方法来存放tag处理类。一、让tag处理类以.class的方式存放于当前应用的WEB-INF/class子目录下,二、如果tag处理类是以JAR包的形式存在的话,那可以放在当前应用的WEB-INF/lib目录下,如果tag处理类要在多个应用中共享,那么它就应放在jsp服务器上的common/lib目录下,对于tomcat来说,就是tomcat/common/lib目录下。 <,rOsE6  
O`@- b#  
=<#G~8WYz  
tag标签类型 U4^c{KWS  
tXH;4K@  
lixM0  
自定义的tag标签遵循XML语法。它有一个开始标记和一个结束标记,有的还有body(即文本节点): la)^`STh  
AS@(]T#R  
<tt:tag> 2%L`b"9}V  
beC%Tnb7  
body ajtH 1Z#  
zTj ie  
</tt:tag> q\x.e.@  
Rw%?@X3m]  
#{{p4/:  
一个不带body的tag标签如下: u '/)l}  
Nh_\{ &r  
<tt:tag /> > *VvV/UU  
]wdE :k,D  
y`j=(|DV  
简单的tag标签 vq^';<Wh.  
G_J}^B*?%v  
一个没有body和属性的tag标签如下: F]PsS(  
DU$#tg}{  
<tt:simple /> 5h`LWA B  
)\ceanS  
7=9>yba)^  
带属性的tag标签 d1/9 A-{  
@ci..::5  
"C\yM{JZ  
自定义标签可以有自己的属性。属性一般在开始标记中定义,语法为 attr=”value”。属性的作用相当于自定义标签的一个参数,它影响着tag处理类的行为。你可以在TLD中详细定义它。 FRZ]E)9Z]b  
{_\cd.AuT  
你可以用一个String常量给一个属性赋值,也可以通过表达式给它赋值,如<%= ...%>。以struts为例,它的logic:present标签就是用的String常量来给属性赋值: ruvfp_:  
R-9o 3TPa  
<loglic:present parameter = “Clear”> m7g*zu2#  
GT)7VFrL  
而另一个标签logic:iterate是用表达式来给属性赋值: @$n $f  
;Tp9)UP)  
<logci:iterate collection=”<%= bookDB.getBooks() %>” `6J7c;:  
(lVMy\  
id=”book” type=”database.BookDetails”> Z|$DchC  
$x+7.%1m)~  
NWvIwt{  
带body的tag标签 _<FUS'"  
h=gtuaR4  
一个自定义标签可以包含其它自定义标签、脚本变量、HTML标记或其它内容。 8K-P]]  
k]5tU\;Yw  
在下述例子中,此JSP页面使用了struts的logic:present标签,如果些标签定义了parameter=”Clear”的属性,则将清除购物车的内容,然后打印出一条信息: $b1>,d'oz  
S-88m/"]s  
<logic:present parameter=”Clear”> GT6i9*tb #  
k|?[EWIi^  
<% cart.clear(); %> ;Vat\,45pg  
JJ ?'<)EF  
<font color=”#ff0000” size=”+2”><strong> e4SS'0|  
xxvt<J  
你选择了清除购物车! 4S ~kNp$  
A1-,b.Ni  
</strong></font> \ *[Ht!y  
T@U,<[,   
</logic:present> BJWlx*U]  
9!Q ZuZY  
(k #xF"yI  
到底是用属性还是用body来传递信息? t^"8M6BqC;  
v$Fz^<Na  
如上所述,我们既可以通过属性,也可以通过body来传递信息。但一般来说,比较简单的类型,如字符串或简单表达式最好采用属性来传递信息。 T`fT[BaY  
#jg-q|nd  
bUm%#a  
定义脚本变量的tag标签 jaodcT0  
IRx% L?  
所谓脚本变量,是指JSP中可以调用的变量或对象。它可由tag标签产生。以下示例阐述了一个tag标签定义了一个名为tx的由JNDI所定义的事务处理对象。脚本变量可以是ejb对象、事务、数据库连接等等: 7$Z_'GJ]1C  
5(J?C-Pk  
<tt:lookup id=”tx” type=”UserTransaction” name=”java:comp/UserTransaction” /> D^6iQW+.P  
g/!MEOVx  
<% tx.begin(); %> UIyLtoxu  
%p )"_q!ge  
... cMZy~>  
2SC-c `9)  
M.t,o\xl  
具有协作关系的tag标签 U|tacO5w`  
UHvA43  
自定义tag标签之间可以通过共享对象来实现协作。在下述例子中,标签tag1创建了一个名为obj1的对象,在标签tag2仍可以重复使用obj。 lWj*tnnn[  
7)jN:+4N  
<tt:tag1 attr1=”obj1” value1=”value” /> 6[k<&;  
TS9<uRO0  
<tt:tag2 attr1=”obj1” /> (LmU\Pe%  
cYK:Y!|`F  
在以下这个例子当中,如果外层的tag标签创建了一个对象,那么其内层的所有tag标签都可以使用这个对象。由于这样产生的对象没有一个指定的名字,那么就可以将少重名的冲突。这个例子阐述了一系列协作的嵌套对象。 F&R*njJcc  
M-i3_H)  
<tt:outerTag> y!P!Fif'  
SR?mSpq5  
<tt:innerTag /> 2e%\aP`D2  
*cXq=/s  
</tt:outerTag> ZBpcC0 z  
5H XF3  
:cWU,V  
Tag处理类 5["3[h  
5uQ+'*xN%  
c.Hw K\IU  
Tag处理类必须实现Tag接口或BodyTag接口,不过现在一般都流行从TagSupport或BodyTagSupport类中继承,这些类或接口都可以在javax.servlet.jsp.tagext包中找到。 ?# FYF\P  
`i cs2po  
当JSP引擎看到自己的JSP页面中包含有tag标签时,它会调用doStartTag方法来处理tag标签的开头,调用doEndTag方法来处理tag标签的结束。 $Bz};@  
XH~(=^/_  
下表说明不同类型的tag所需要不同的处理过程:  4bA^Gq  
7:?\1 a  
Tag处理类的方法 FqA4 O U  
%AA&n*m  
Tag标签类型 ]b%U9hmL^f  
所调用的方法 ZN $%\,<  
b`D]L/}pr  
基本标签 (Q=o 9o:b  
doStartTag, doEndTag, release SkmTW@v  
-`XS2  
带属性的标签 -_t4A *  
doStartTag, doEndTag, set/getAttribute1...N, release 8bdO-LJ9  
R&.&x'<  
带内容的标签 0}NDi|o  
doStartTag, doEndTag, release hxMRmH[f:  
.cJoNl'q  
带内容的标签,且内容重复循环 U~?VN!<x[  
doStartTag, doAfterBody, doEndTag, release LJ~#0Zu?  
E7iAN\vo  
带内容的标签,且内容与JSP交互 1Y$%| `  
doStartTag, doEndTag, release, doInitBody, doAfterBody, release ,Kj>F2{  
a)pc+w#  
一个tag处理类可以通过javax.servlet.jsp.PageContext来与JSP交互,通过javax.servlet.jsp.PageContext类,tag处理类可以访问JSP中的request、session和application对像。 mbkt7. ,P  
a($7J6]M  
如果tag标签是互相嵌套的,那内层的tag处理类可以通过它的parent属性来访问上层的tag处理类。 (@XQ]S}L  
Tph^o^  
一般情况都将所有的tag处理类打成了JAR的包,以便于发布。 fub04x)  
V 9$T=[  
|;~=^a3?q  
Tag库描述(简称TLD) qA!p7"m|  
OJa(Gds  
4RVqfD  
Tag库是用xml语言描述的,TLD包括了tag库中所有tag标签的描述,它一般用来被jsp服务器用来校验tag的语法正确性,或者被jsp开发者用来开发新的标签。 jdJTOT  
46D`h!7L  
TLD的文件扩展名必须为.tld,而且必须放在当前WEB应用的WEB-INF目录或其子目录中。 u~M$<|;  
n46!H0mJ  
一个TLD的内容的开头必须遵守标准的XML开头,用于描述DTD和xml的版本,例如: H~s8M  
lM4Z7mT /  
<?xml version="1.0" encoding="ISO-8859-1" ?> p%mHxYP  
%p  
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd"> b-VtQ%Q  
TLD必须以<taglib>来作为它的根元素,<taglib>的子元素如下表: 7 nnF!9JOv  
*:xOenI  
8]`#ax 5  
<taglib>的子元素 |D-[M_T5  
RR[zvH} E  
Element */IiL%g4u  
Description /_m )D;!y  
&^#iS<s1  
tlib-version Fdhgm{Y2s  
Tag库的版本 R`<2DC>h9  
aBReIK o  
jsp-version ?HPAX  
Tag库所需要的jsp的版本 q( ~rk  
[nig^8  
short-name ?} 8r h%  
助记符,tag的一个别名(可选) Jg=!GU/::  
"!zJQl@  
uri [yN+(^ i  
用于确定一个唯一的tag库 ./XX  
W=^.s>7G  
display-name wl]3g  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) _"Bj`5S  
M#o.O?.`  
small-icon vwu/33  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) [5L?#Y  
ow9a^|@a  
large-icon !@Qk=Xkg  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) ^wBlQmW7J  
M]6+s`?r  
description \78^ O  
对tag库的描述(可选) n?cC]k;P~  
Ed u(dZbKg  
listener { DP9^hg  
参见下面listener元素 WlQCPC  
@;OsHudd  
tag o]&q'>Rf  
参见下面tag 元素 /jJD {  
6:|;O  
Listener元素 `$JvWN,kB  
/5Qh*.(S  
一个tag库可能定义一些类做为它的事件侦听类,这些类在TLD中被称为listener 元素,jsp服务器将会实例化这些侦听类,并且注册它们。Listener元素中有一个叫listener-class的子元素,这个元素的值必须是该侦听类的完整类名。 Qb?a[[3  
!gW`xVGv  
Tag元素 \;N+PE  
o+{,>t  
每个tag元素在tag库中都要指出它的名字、类名、脚本变量、tag的属性。其中脚本变量的值可以直接在TLD中定义或通过tag附加信息的类来取得。每个属性描述了这个属性是否可以省略,它的值是否可以通过<%= …%>这样的JSP语法来获得,以及属性的类型。 AA[1[  
Jfr'OD2$ %  
每一个tag在TLD中对应一个tag元素,下表是tag元素的子元素: WT,I~'r=S  
bT 42G [x  
Tag元素的子元素 n',X,P0  
! 1I# L!9  
元素名称 7d>w]R,Z  
描述 Ygk_gBRiC  
R q@|o5O  
name L>IP!.J]?  
独一无二的元素名 w;ZT-Fti  
G(wK(P0j  
tag-class BH {z]a  
Tag标签对应的tag处理类  :'F,l:  
,zx{RDI  
tei-class c6vJ;iz  
javax.servlet.jsp.tagext.TagExtraInfo的子类,用于表达脚本变量(可选) }nPt[77U_7  
C8|Ls(4Ck  
body-content + GQ{{B  
Tag标签body的类型 $,by!w'e:l  
D%o(HS\E  
display-name x+4K,r;  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) 7<]&pSt=  
%OgK{h  
small-icon i kfJ!f  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) K_L7a>Fr  
$7AsMlq[(  
large-icon ,V 52Fj  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) THQ #zQ-  
u|}\Af  
description u~uz=Yse  
此tag标签的描述 L@T/4e./  
Kt*b) <  
variable :'wxm3f  
提供脚本变量的信息(同tei-class)(可选) H6`k%O*  
TfZM0Wz  
attribute wnd #J `  
Tag标签的属性名 @>46.V{P}B  
6w &<j&V  
以下章节介绍对于不同类型的tag,如何具体地实现它们。 K>.}>)0  
9~Sa7P  
C2rG3X^~Jm  
简单的tag l[[`-f8j  
_Kaqx"D  
BN]o!Y  
tag处理类 3HtM<su*h  
I-!7 EC2{!  
简单的tag处理类必须实现Tag接口的doStartTag和doEndTag方法。当jsp引擎碰到tag标签的开头时,doStartTag被调用,因为简单的tag没有body,所以此方法将返回 SKIP_BODY。当jsp引擎碰到tag标签的结尾时,doEndTag被调用,如果余下的页面还要被计算,那它将返回EVAL_PAGE,否则将会返回SKIP_PAGE。 kIS )*_  
_ -RqkRI  
以下是例子:对于标签 <tt:simple /> ,它的tag处理类实现如下: gWU#NRRc  
[VXQ&  
Y<W9LF  
public SimpleTag extends TagSupport ktqFgU#rT  
Jm CHwyUK?  
{ ? 0X$ox  
d>F7i~W  
public int doStartTag() throws JspException ;/+<N  
JzN "o'  
{ WDxcV%  
-x6_HibbD  
try{ [x 7Rq_^  
gnN>Rl 5_  
pageContext.getOut().print(“Hello.”); 'Y2$9qy-L  
X HJdynt/  
}catch(Exception e){ gKTCfD~  
e}2?)B`[  
throw new JspTagException(“SimpleTag: “ + e.getMessage()); A7Y CSjB  
N:3=G`Ws  
} Pn^:cr|  
[p'2#Et  
return SKIP_BODY; 51eZfJB  
A*0X ~6W  
} K3:z5j.X  
]~  N.  
public int doEndTag() "Fmq$.$%  
M/W9"N[ta  
{ *sp")h#Z  
~H\P0G5GA  
return EVAL_PAGE; ]vcT2lr]  
m $[:J  
} ? 3DFm  
5u9lKno  
} c(Y~5A{TXO  
m %+'St|qr  
qh>An;:u  
注意:如果tag标签没有内容的话,那必须定义body-content元素为空,例如 j^#\km B  
+/$&P3  
<body-content>empty</body-content> 5KB Z-,  
nWCJY:q;5  
/z^v% l  
带属性的tag标签
评价一下你浏览此帖子的感受

精彩

感动

搞笑

开心

愤怒

无聊

灌水
级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
只看该作者 1 发表于: 2007-01-01
tag处理类 =4x6v<  
ecl6>PS$'  
对于tag标签的每个属性,你必须依照JavaBeans规范来定义其属性,以及get和set方法。以struts的logic:present 标签为例, M1P;x._n  
cyd_xB5K  
<logic:present parameter=”Clear”> A#q.)8  
lu>G=uCJ  
与此相应,此tag处理类应有如下方法和定义: R+0fs$s u  
h;E.y   
76[ qFz  
protected String parameter = null; 8yI4=P"F,  
6&E[hvu  
public String getParameter() 5![ILa_  
nY;Sk#9  
{ 5<GeAW8ns]  
O '#FVZ.g  
return this.parameter; ,%/F,O+#  
<au_S\n  
} hUi5~;Q5Fi  
H]V(qq{  
public void setParameter(String parameter) L1` ^M  
\g]rOYW  
{ 3k_\ xQ  
Z{ YuX  
this.parameter = parameter; 56c3tgVF  
 ]E :L  
} "6WJj3h N  
kN<;*jHV  
8=f+`e  
注意:如果你的属性名为id,而且你的tag处理类是从TagSupport类继承的,那你就不需要定义它的属性和set和get方法,因为他们早已在TagSupport被定义过了。 }3 ~*/30V  
yhK9rcJq6}  
Attribute元素 B[&l<*O-y  
yIpgZ0:h  
对于tag标签的每个属性,你必须定义它是否必须的,它的值是否可以用诸如<%= …%>的表达式来获得,以及它的类型(可选),如果不指定它的类型,那就默认为是java.lang.String类型。如果rtexprvalue元素被定义为true或yes,那么在type元素中就定义了attribute的返回类型。 Y/mfBkh  
k<fR)o  
<attribute> ,,EG"Um6  
U;ujN8  
<name>attr1</name> !f!YMpN  
]*$o qn=m  
<required>true|false|yes|no</required> kMzDmgoxNg  
* kL>9  
<rtexprvalue>true|false|yes|no</rtexprvalue> ):+^893)  
k|]l2zlT  
<type>attribute的返回类型(只用当rtexprvalue为真是才有效)</type> }7%ol&<@  
YuoErP=P  
</attribute> M?gZKdj  
$y<`Jy]+)~  
如果tag的某个属性不是必须的,那tag处理类会自动提供一个缺省值。 _wg~5'w8  
6>)KiigZ\  
例如,在logic:present这个tag标签中定义了一个属性叫parameter,但它不是必须的,而且它可以被诸如<%= …%>的表达式来赋值。 _Co v>6_i  
iRW5*-66f  
<tag> .aK=z)  
[;toumv  
<name>present</name> 2l+'p[b0>  
02^\np  
<tag-class>org.apache.struts.taglib.logic.PresentTag</tag-class> Zia6m[^Q  
ex|)3|J  
<body-content>JSP</body-content> a(JtGjTf&  
y </i1qM  
~d3BVKP5  
#N=_-  
<attribute> 2gvS`+<TP  
Mns=X)/hc  
<name>parameter</name> E[CvxVCx  
%<q"&]e,  
<required>false</required> )5<dmK@  
V z5<Gr  
<rtexprvalue>true</rtexprvalue> DAN"&&  
u0uz~ s  
</attribute> 3WfZzb+  
Y8mv[+Z  
 >qI:  
ZkMHy1  
</tag> tJGPkeA  
N7s9"i  
k[1[Y{n.  
属性元素的校验 s, #$o3  
<dk9n}y<,  
!C.{nOfyv  
有关于tag标签的有效值可以从tag库的说明文档中获得,当JSP页面被编译时,jsp引擎会强制性地参照TLD中定义的规则进行检查。 K^I$05idi  
)gR3S%Ju  
还有一个方法也可以进行属性元素的校验,就是先继承类TagExtraInfo,然后调用它的isValid方法。这个类同时也起到提供tag中定义的脚本变量信息的作用。 dt>!=<|k  
Z%-uyT@a  
IsValid方法通过TagData对象来传递属性信息,它包括着tag的所有的属性名-值的信息。由于校验发生在运行时刻,因此这个属性的值将被赋值为TagData.REQUEST_TIME_VALUE。 ,*p(q/kJh~  
!<-+}X+o8$  
例如tag标签<tt:twa attr1=”value1” />在TLD中定义如下: x||b :2  
lnxA/[`a  
<attribute> Oo\~' I  
;ZrFy=Iv  
<name>attr1</name> 5kv]k?   
q 7+|U%!9  
<required>true</required> yg4ILL  
J2`OJsMwWe  
<rtexprvalue>true</rtexprvalue> O_SM!!,  
6& 9q6IIy  
</attribute> ?N%5c%oF  
mvtuV`  
WN#dR~>  
这个定义说明了attr1能在运行期间被赋值。 Hp fTuydU  
=0U"07%}  
以下的isValid方法检查attr1属性的值是否属于Boolean类型。注意由于attr1能在运行刻被赋值,那么isValid方法必须检查tag用户是否对此tag进行了运行时刻赋值。 j!"NEh78H  
5_L43-  
o{ | |Ig  
Public class TwaTEI extends TagExtraInfo MD+ eLA7  
PzLV}   
{ ^A;ec h7I  
AWmJm)   
public boolean isValid(Tagdata data) qSVg.<+  
rHtX4;f+><  
{ +d6Jrd*  
sy9YdPPE  
Object o = data.getAttribute(“attr1”); Y9(BxDP_+Y  
ewinG-hX_  
If(o != null && o != TagData.REQUEST_TIME_VALUE) IG@@CH  
?Vr~~v"fg8  
{ ]"1\z>Hg  
j)O8&[y=  
if( ( (String)o).toLowerCase().equals(“true”) || ;77q~_g$  
A'? W5~F  
((String)o).toLowerCase().equals(“false”) ) D-5~CK4`  
~/R}K g(  
return true; nx4E}8!Lh  
jM(!!A jpC  
else inx0W3d"T  
~_SVQ7P  
return false; 4b$m\hoN  
M$LzV}k  
} QjUojHz%Z  
;W#/;C _h  
else o Bp.|8-  
5s2/YG=  
return true; i>rsq[l  
; >>/}Jw\  
} P,Rqv)}X  
mZ t:  
} C;!h4l7L  
P~*v}A  
<Xj ,>2m;  
带body的tag AqP\g k  
l_*:StyR+  
X`n*M]  
tag处理类 g.O? 1bebe  
v&ZI<Xt+  
9!6yo  
如果tag标签含有内容,那处理方式会略微有些不同,而且还要视tag处理类是否要与body交互的情况而定。如果要与body交互,那我们认为tag处理类要可能要对body进行操作。 Z{.L_ ]$ I  
;%aWA  
Tag处理类不与body交互 ol8uV{:"  
6NqLo^ "g  
如果tag处理类不与body交互,tag处理类应该实现Tag接口或从TagSupport中派生,如果body要被计算,那么doStartTag方法应返回 EVAL_BODY_INCLUDE,否则应返回SKIP_BODY。 GUK3`}!%  
4?&CK  
如果tag处理类要对body反复运算,则它应该实现IterationTag或从TagSupport中派生。如果tag处理类认为body还未计算完的话,那它的doStartTag方法和doAfterBody方法必须返回EVAL_BODY_AGAIN。 &@xeWB  
vui{["  
Tag处理类与body交互  wZUR  
3H47 vm(`  
如果tag处理类与body交互,那tag处理类应实现BodyTag接口或从BodyTagSupport中派生。这种tag处理类一般要实现doInitBody和doAfterBody方法。 [ w1"  
\ 8X8N CM  
Body允许一些方法来读写它的内容。Tag处理类可以调用body内容的getString或getReader方法来从body中提取信息,也可用 writeOut(out) 方法来将body的内容写入到out对象中。其中out对象通过tag处理类的getPreviousOut方法来获得。 (vf5qF^  
1]XIF?_D m  
如果body的内容需要被计算,那么doStartTag方法必须返回EVAL_BODY_BUFFERED,否则,它将返回 SKIP_BODY。 j2|!h%{nI  
lf9_!`DGV  
doInitBody 方法 *C?x\.\C  
V.274e  
此方法在body内容已经设好,但未被计算之前被调用。你可以根据不同的body内容来制定初始化策略。 Pi|oO-M  
 =!Y{Mz  
doAfterBody方法 /%GMbO_  
OL"So u4  
此方法在body内容已被计算后进行调用。 _.Bite^  
) N"gW*  
和doStartTag方法一样,doAfterBody方法返回一个指示符指示是否要继续计算body,如果要继续计算,则doAfterBody应返回EVAL_BODY_BUFFERED,否则,它应返回SKIP_BODY。 MtO p][i  
0H{0aQQ  
release 方法 x5Ee'G(  
T)B1V,2j=  
tag处理类调用此方法将它的状态重置为初始状态,并释放所有的私有资源。 8M'6Kcr  
{ e %  
l+V5dZ8W  
以下的例子读取body的内容(其中含有一条sql语句),然后将它传递给一个对象,让它进行查询。由于此处body不须重新计算,所以doAfterBody会返回SKIP_BODY。 "ae55ft//  
/C}fE]n{X  
k||DcwO  
Public class QueryTag extends BodyTagSupport +#<"o#gZ  
RsDI7v  
{ #8d$%F))  
p{Gg,.f!HM  
public int doAfterBody() throws JspTagException s2ys>2k  
i(c'94M  
{ DP_ bB(  
N6<23kYM  
BodyContent bc = getBodyContent(); xX.Ox  
Mhw\i&*U  
//将body的内容以字符串的格式提取出来 8Lpy`He  
{\e wf_pFk  
String query = bc.getString(); g)iSC?H  
] H[FZY  
//清除body r4qFEFV3%  
8)k.lPoo.  
bc.clearBody(); w,.Hdd6  
T;< >""T  
try{  93(  
}a_: oR  
Statement stmt = connection.createStatement(); m"vV=6m|\  
[ @/[#p  
Result result = stmt.executeQuery(query); Va/ p   
=;$&:Zjy/%  
}catch(SQLException e){ ;mb 6i_  
c~|/,FZU'  
throw new JspTagException(“queryTag: “ + e.getMessage() ); hK$-R1O  
9aC>gye!  
return SKIP_BODY; HF\L`dJX?  
tIC_/ 6  
} q& Vt*  
Yazpfw 7'd  
} 6C/D&+4  
Z y7@"C  
d*,|?Ar*b  
body-content元素 VuZmX1x)N  
Ck.GN<#-^P  
( |5g`JDG  
由于tag可能会有body,你必须用body-content元素来指定body内容的类型: q#Qr@Jf  
GW{Nc !)  
<body-content>JSP|tagdependent</body-content>  Phgn|  
^j=_=Km]  
r/O(EW#=8  
如果body的内容是定制的或内部的tag、脚本元素、或HTML广本,则归类为JSP类型。其他的类型,比如上面代码所述的?D?D将sql statement类传给 query tag的这种类型应该标为tagdependent。 tY :-13F  
9AL\6 @<a*  
注意:实际上body-content的值并不影响tag处理类对body内容的处理,它仅仅是被tag编辑工具用来描述此body的内容。 )-a_,3x%j  
C>;yW7*g"  
r%'2a+}D  
用tags定义脚本变量 5#f&WL*U@  
 D#m+w  
D0k7)\puQ  
tag处理类 D1O7S]j  
Vq'&t<K#  
m9xu$z| e  
tag处理类负责创建或设置页面中定义的脚本变量,用pageContext.setAttribute(name,value,scope)或pageContext.setAttribute(name,value)方法来实现。一般来说,tag处理类通过脚本变量的名称来获取它,脚本变量的名称一般可用get方法来获得。 }}(~'  
ak;Z;  
如果脚本变量的值依赖于tag处理类中的上下文中某一对象,那它可用pageContext.getAttribute(name,scope)方法来找到那个对象。一般的处理过程是tag处理类先找到脚本变量,再对其进行处理,然后用pageContext.setAttribute(name,object)的方法来设置它的新值。 r$\g6m  
~0 FqY &4  
对象的生存周期(scope)如下表:   6^: l  
>uJrq""+  
对象的生存周期表 cdIy[ 1  
xSOL4  
名字 3^su%z_%  
可访问范围 f (n{7  
生存周期 U0N[~yW(t1  
]aakEU  
page -G Kelz?h>  
当前页面 LbYI{|_Js  
一直有效,除非页面向客户提交响应或重定向到一个新页面 ?n@PZL= ]  
(%fGS.TR  
request vP~F+z @g  
当前页面或当前页面重定向到的页面 " ^eq5?L  
一直有效,除非页面向客户提交响应 Q#g s)2  
ci^-0l_O  
session 4GHIRH C%[  
当前页面或在同一浏览器窗口中的页面 3P\I;xM  
一直有效,除非关闭当前浏览器、超时、网络故障 b]g.>$[nX  
O: BP35z_F  
application [7s5Vt|  
整个web应用程序的所有请求 @g=A\2  
一直有效,除非发生网络故障、服务器故障 ^3yjE/Wi"  
wA~Nfn ^  
提供关于脚本变量的信息 *<A;jP  
Om1z  
以下示例定义了一个名为“book”的脚本变量,用来访问程序中关于书的信息: M K[spV  
=0]Mc$Ih  
<bean:define id=”book” name=”bookDB” property=”bookDetails” type=”database.BookDetails” /> [ $"iO#oO  
/w!' [  
<font color=”red” size=”+2” > O@=mN*<gg0  
R\Q%_~1  
<%= messages.getString(“CartRemoved”) %> <zDe;&  
iN {TTy  
<strong><jsp:getProperty name=”book” property=”title” /></strong> h.Dk>H_G  
r?+u}uH  
</font> /Bwea];^Q  
8DI|+`OgW  
当包含此tag的JSP页面被编译时,jsp引擎会自动生成关于此book的同步的代码(同步可以避免几个客户同时访问此book时造成的冲突),要生成同步代码,jsp引擎需要知道此脚本变量的如下信息: 7kwG_0QO  
T i/iD2g  
· 脚本变量名称 (7wR*vO^  
|(H|2]b4 =  
· 脚本变量所属的类 S2s-TpjB<  
&S-& 'ZAY  
· 此脚本变量是否引用了一个新的或已存在的对象 0,A?*CO  
O#U"c5%  
· 此脚本变量的有效性 ) k2NF="o  
JZnWzqFw  
有两种办法可以向jsp引擎提供关于脚本变量的信息:在TLD中定义variable子元素,或用tei-class子元素定义一个额外tag信息类。用variable最简单,但可能降低了一些灵活性。 0Its;|  
+8Px` v1L  
Variable元素 q7PRJX  
Z{CL!  
Variable元素有如下子元素: jI V? p  
P3 Evv]sB@  
· name-given ?D?D 给出的名字,是一个常量 e S=k 48'U  
%7@H7^s}9  
· name-from-attribute?D?D 属性名,在编译时给出的属性名 J-f0  
cU6#^PFu  
name-given或name-from-attribute两者必须选一,但以下子元素是可选的: /uc/x+(_  
Iw:("A&~  
· variable-class?D?D变量的类型,缺省为java.lang.String。 v}Nx*%  
C}kJGi  
· declare?D?D此脚本变量是否引用了一个新对象,缺省为True。 k:qou})#4  
7fE V/j  
· scope?D?D脚本变量的范围,缺省为NESTED。下表描述了scope的几种类型: te''sydUS  
F@lpjW  
脚本变量的有效范围 UKBMGzu2:  
1G;Ns] u  
Rp|&1nS  
有效性 U;xWW9  
方法 @iceMD.  
3d<HIG^W}  
NESTED H44&u](8{  
在tag标签的开始和结束之间 |G@)B!>  
如果tag处理类实现BodyTag接口,则在doInitBody和doAfterBody中调用,否则在doStartTag中调用 '9dtIW6E  
Om"3Q/&  
AT_BEGIN Mfr#IzNHN  
从tag标签的开始一直到页面结束 //,'oh~W  
如果tag处理类实现BodyTag接口,则在doInitBody、doAfterBody和doEndTag中调用,否则在doStartTag和doEndTag中调用 vWovR`  
htRZ}e  
AT_END Pb;`'<*U  
从tag标签的结束一直到页面结束 H7= z%Y9y  
在doEndTag中调用 >z -(4Z  
t5APD?5 c  
以struts为例,它的bean:define标签的实现遵循JSP1.1规范,此规范要求使用额外tag信息类来定义脚本变量。Variable元素是JSP1.2规范中加入的。以bean:define标签为例,你可以定义如下variable元素: "3MUrIsB>  
4<K`yU]"  
<tag> *4:/<wI!  
xwxjj  
<variable> z{jAt6@7  
D5b _m|7%  
<name-from-attribute>id</name-from-attribute> c]r|I %D  
W>bW1h  
<variable-class>database.BookDetails</variable-class> kw~H%-,]  
$Ig,cTR.b  
<declare>true</declare> S: uEK  
SkA'+(  
<scope>AT_BEGIN</scope> XXcf!~uO  
EXcjF  
</variable> xi\RUAW  
wIj2 IAD  
</tag> E <SE Fn  
G0> Wk#or  
额外tag信息类 I yN9 +  
Y]K]]Ehp  
如果要定义一个额外tag信息类,你要继承javax.servlet.jsp.TagExtraInfo类。一个TagExtraInfo类必须实现getVariableInfo方法,此方法返回一个叫VariableInfo的数组类,它包括如下信息: =ol][)Bd  
F s\P/YX  
· 变量名 cB}2(`z9 B  
,O)\,tg  
· 变量所属类名 ZcRm5Du~:  
3/=QZ8HA&-  
· 此变量是否引用了一个新对象 jFT V\|C  
26VdRy{[  
· 此变量的有效范围 kw:D~E (  
j/pQSlV  
jsp引擎将一个名为data的参数传给getVariableInfo方法,data中包括tag标签中的所有“属性名?D?D属性值”对。它可以用来向VariableInfo对象提供脚本变量的名字和类名。 Le JlTWotC  
f{c[_OR  
以struts为例,它在bean:define标签中定义了一个名为DefineTei的额外tag信息类,用来向脚本变量提供信息。由于脚本变量的名称(book)和类名(database.BookDetails)是通过tag标签的属性来传递的,它们一般定义在VariableInfo的构建代码中,并且可用data.getAttributeString方法来得到这些信息。如果要允许book脚本变量能在从tag开始直到整个JSP页面结束的范围内都可用的话,那它的范围应设为AT_BEGIN。如下所示: 4Z9 3 g {  
mZVOf~9E  
5 hadA>d  
public class DefineTei extends TagExtraInfo Hk*cO;c  
}n%R l\p  
{ 'f7 *RSKqb  
ydqmuZ%2h#  
public VariableInfo[] getVariableInfo(TagData data) ]q7 LoH'S  
+%\j$Pv  
{ 7U`S9DDwq  
o>-v?Ug  
String type = data.getAttributeString(“type”); s7i.p]  
cgXF|'yI&l  
If( type == null) Z:J.FI@  
%*q0+_  
type = “java.lang.Object”; qg{<&V7fE  
u=}bq{  
return new VariableInfo[] { o[[r_v_d  
-b0'Q  
new VariableInfo(data.getAttributeString(“id”), "HfU,$[  
L{A-0Ffh  
type, ,1;8DfVZV  
^MHn2Cv/~  
true, *Yu\YjLPG  
-yQ\3wli`  
VariableInfo.AT_BEGIN) ^r_lj$:+$  
LA`V qJ  
}; `N.$LY;8  
eoe^t:5&  
} Qr%Jm{_o  
>[fVl 8G_0  
} G0 /vn9&  
~P#zhHw  
<N=p:e,aN,  
注意:关于额外tag信息类的类名必须要在TLD中的tag标签下的tei-class子元素中定义。因此,DefineTei的tei-class中的定义看起来如下: q[OTaSQ~u^  
<tei-class> .7gE^  
org.apache.struts.taglib.bean.DefineTagTei Qb't*2c%  
</tei-class> r82o[+$u0K  
o $`kpr  
UnWGMo?JEi  
具有协作关系的tag s P4 ,S(+e  
"SU-^z  
e_c;D2' F  
tag通过共享对象来进行协作,JSP技术支持2种方式的对象共享。 f THun?Vn  
YATdGLTeq  
第一种方法是使用pageContext对象进行对象的共享(可支持JSP页面和tag处理类之间的共享),如果在一个tag处理类中要调用由另一个tag处理类创建的对象,可调用pageContext.getAttribute(name, scope)方法。 9N D+w6"  
2ZG1n#  
第二各方式的共享是对于tag之间有嵌套关系而言的,外层的tag所创建的对象对于内层的tag来说是可以共用的。这种形式的共享的好处是减少了可能存在的重名冲突。 _|  
-+=:+LhSMb  
要访问一个嵌套tag创建的对象,tag处理类必须先找到此嵌套tag对象,可用TagSupport的静态方法 TagSupport.findAncestorWithClass(from, class)或TagSupport.getParent方法。前者在当不确定此tag是否为嵌套tag对象时使用。一旦它的父类被找到,它就能访问其所有动态或静态创建的对象。静态创建的对象是父类的成员,而动态创建的对象可能是父类的私有对象。诸如此类的对象可以用tag处理类的setValue方法来保存,用getValue方法来获得。 #H6g&)Z_  
j"IM,=  
下例阐述了以上两种共享对象的方法。在这个例子当中,一个查询tag检查一个名为connection的属性名是否在doStartTag中被设置。如果connection属性被设置,tag处理类从pageContext中得到这个connection对象。否则,此tag处理类先找到它的父tag处理类,然后从它的父tag处理类中找到connection对象。 _`Q It>R  
0 {JK4]C  
~d%;~_n  
public class QueryTag extends BodyTagSupport gGX0+L@E  
_/ }6  
{ ]AA%J@  
U\Ar*b)/T  
private String connectionId; d[]p_oIQq  
n1>,#|#  
public int doStartTag() throws JspException v^c<`i;  
z34>,0  
{ d$_q=ywc  
?5yH'9zE  
String cid = getConnection(); sjzXJ`s  
Sn0gTsZ  
if(cid != null) 0)oN[  
k<Tez{<  
{ G4`Ut1g ^  
ytve1<.Ff  
//存在一个connection id,使用它。 XJ h:U0  
7 ZL#f![{  
connection = (Connection) pageContext.getAttribute(cid); {y^|ET7  
)jk1S  
} .FKJ yzL  
xEiX<lguyN  
else uPFHlT  
II-$WJy  
{ B8UZ9I$n  
27a* H1iQ  
ConnectionTag ancestorTag = (ConnectionTag)findAncestorWithClass(this, 7/|F9fF@M  
i2:+h}o$e  
ConnectionTag.class); XW?ybH6  
9fuJJ3L[  
if(ancestorTag == null) .IH@_iX  
>nhE%:X>  
{ #$t}T@t>  
o3F|#op  
throw new JspTagException(“一个没有connection属性的查询标签必须被一个connection标记嵌套。”); ``|gcG  
o'eI(@{F=  
} G;Wkm|  
7V=MRf&xQ  
connection = ancestorTag.getConnection(); EDHg'q  
F:;!) H*  
} #H;hRl  
W{A #]r l  
} w<Yv`$-`  
CzSZ>E$%U  
} fK'.wX9  
x[vBK8  
~ThVap[*  
7?MB8tJ5r4  
此查询标签在JSP页面中的调用形式可以从以下2种定义中任选一种: 5c]}G.NV  
sOl>5:D6  
oSn! "<x  
<tt:connection id=”con01” ...> ... </tt:connection> Q sg/ V]  
5 o#<`_=J  
<tt:query id=”balances” connection=”con01” > {Z#e{~m#  
>I4p9y(u  
SELECT account, balance FROM acct_table ^XBzZ!h|  
i,#k}CNu  
where customer_num = <%= request.getCustno() %> h`5YA89  
J%\- 1  
</tt:query> AfRW=&xdT  
X&(<G  
N-2([v  
FjZc#\^9  
E.J 0fwyT  
<tt:connection ...> z.3<{-n}0i  
Qz@IK:B}  
<x:query id=”balances”> oTCzYY  
`/O`OrZ1K  
SELECT account, balance FROM acct_table Tm)GC_  
OJP5k/U$  
where customer_num = <%= request.getCustno() %> <b d1  
8K0X[-hs8  
</x:query> q^ a|wTC  
D<U 9m3  
</tt:connection> bmOqeUgB  
OXHvT/L`  
C$<"w,  
与此同时,在TLD中必须指定connection属性为可选的,定义如下: VEj$^bpp5s  
N] 14  
<tag> ZfPd0 p  
jt{9e:2%  
... >Mvka;T]  
yiV G ]s  
<attribute> (j' {~FB  
#:J: YMv  
<name>connection</name> *@_u4T7|{  
e-X HN  
<required>false</required> KD% TxK  
.u1X+P7  
</attribute> _eJXi,  
w6T[hZ 9  
</tag>
描述
快速回复

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