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

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

级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
标准的JSP 标记可以调用JavaBeans组件或者执行客户的请求,这大大降低了JSP开发的复杂度和维护量。JSP技术也允许你自定义taglib,其实换句话说,taglib可以看成是对JSP标记的一种扩展,正如xml是对html的一种扩展一样。taglib通常定义在tag标签库中,这种标签库存放着你自己定义的tag标签。简而言之,如果使用taglib,那么你可以设计自己的JSP标记! awxzP*6  
xMsSZ{j%5  
一般来说,自定义tag标签主要用于操作隐藏对象、处理html提交表单、访问数据库或其它企业级的服务,诸如邮件和目录操作等等。自定义tag标签的使用者一般都是那些对java编程语言非常精通,而且对数据访问和企业级服务访问都非常熟悉的程序员,对于HTML设计者来说,使得他可以不去关注那些较复杂的商业逻辑,而将精力放在网页设计上。同时,它也将库开发者和库使用者进行合理分工,自定义tag标签将那些重复工作进行封装,从而大大提高了生产力,而且可以使得tag库可用于不同的项目中,完美地体现了软件复用的思想。 g?&_5)&  
1?%Q"*Y&  
在这篇文章中,我们主要讨论: ;n]GHqzY_  
x8x8T $  
· 什么是自定义tag标签? #[Z ToE4  
Zq1Z rwPF  
· 怎么使用tag标签? B?n 6o|8  
{| ~  
o 声明要使用的tag库 v% a)nv  
utOATjB.z  
o 找到与之对应的tag处理类 @{/GdB,}  
Sp/t[\,'  
o tag标签的类型 r{2V`h1/|  
cBcfGNTJ~  
· 自定义tag标签 5^lFksZ  
 t~_vzG  
o tag处理类 ggn C #$  
>1uo5,wrF  
o tag库描述 [.:SV|AF#  
XK#~w:/fB  
o tag标签示例 h.T]J9;9  
q9+`pj  
o 带属性的tag X% JQ_Z  
zNG]v?JAh  
o 带body的tag ',+YWlW  
st4z+$L  
o 定义了脚本变量的tag 3mef;!q  
8[v9|r  
o 具有协作关系的tag y950Q%B]  
{o>51fXc)  
· 自定义tag标签 b^s978qn#  
>I*)0tE  
o 一个迭代tag的例子 ={g.Fn(_  
t"# .I?S0  
o 一个模板tag库 <9f;\+zA  
[Ey[A|g  
o tag处理类到底是怎样被调用的? a9LK}xc={  
=f~8"j  
_EHz>DJ9  
什么是自定义的tag? omd oH?  
\G4L+Q/13  
一个自定义的tag标签是用户定义的一种JSP标记。当一个含有自定义的tag标签的JSP页面被jsp引擎编译成servlet时,tag标签被转化成了对一个称为tag处理类的对象进行的操作。于是当JSP页面被jsp引擎转化为servlet后,实际上tag标签被转化成为了对tag处理类的操作。 A$ 2AYQ  
0nOkQVMk>  
自定义tag标签有很多特色,诸如: SfTTB'9  
;@ <E  
· 可以在JSP页面中自定义tag标签的属性 &BOq%*+  
K<3,=gL9[  
· 访问JSP页面中的所有对象 iEx sGn]2  
fl@=h[g#t  
· 可以动态地修改页面输出 |; [XZ ZZ  
p9X{E%A<:  
· 彼此这间可以相互通信。你可以先创建一个JavaBeans组件,然后在一个tag中调用此JavaBeans组件,同时可以在另一个tag中调用它。 r< MW8  
[KcF0%a  
· tag允许相互嵌套,可以在一个JSP页面中完成一些复杂的交互。 vD-m FC)  
Kx4_`;>  
YzA6*2  
使用tag标签 yV.E+~y  
#!.26RM:P  
wqnrN6$jf  
本节主要描述怎样在JSP页面中使用tag标签,以及tag标签的不同类型。  eeMeV>  
sOVbz2 \yb  
要使用tag标签,JSP程序员必须做2件事: ;15 j\{r  
]#NJ[IZb  
· 声明此tag标签的tag库 %>io$o  
npCiqO  
· 实现此tag标签 ,vcg%~-  
y,/Arl}yc  
声明tag标签所在的tag库 W^e"()d/Z  
JX)%iJq#  
如果要使用tag标签,则应用JSP的taglib指示符来指定其tag库(注意:taglib要在在使用此tag标签之前声明) wjzR 8g0bQ  
Qr.SPNUFK  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %>  Uf,fd  
l@W1b S  
uri属性定义了唯一的标签库描述(以下简称TLD),它可以是直接是tld文件名或一个独一无二的名字。prefix是用来区别其它TLD中和本TLD中有重名的tag的一种手段。 *DDqa?gQb  
DYf3>xh>xb  
TLD必须以.tld作为扩展名,并且存放在当前应用的WEB-INF目录或其子目录下。你可以通过它的文件名直接引用它,也可以通过别的方式间接地引用它。 (J6>]MZ#)  
/}\Uw  
以下taglib指示符直接引用一个TLD: y1 qJ  
faIHmU  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> _8 C:Md`  
{,X}Btnwp  
以下的taglib指示符通过一个逻辑名称间接地引用一个TLD: F[@M?  
)lh Pl  
<%@ taglib uri=”/tutorial-template” prefix=”tt” %> #@UzOQ>  
^{}$o#iof  
如果是间接引用TLD的话,那你必须还要在web.xml中定义此逻辑名称与tld文件之间的映射,具体做法是在web.xml中加入一个名为taglib的元素: XM#xxf* Y  
fW3 awR{  
<taglib> ~bD'QMk  
L,\wB7t  
<taglib-uri>/tutorial-template</taglib-uri> b[/uSwvi  
p)e?0m26  
<taglib-location> .P:mY C  
w<|Qezi3 w  
/WEB-INF/tutorial-template.tld xJ rKH  
Spm0DqqR?  
</taglib-location> }!_ofe  
wZnv*t_  
</taglib> 2kfX_RK  
)`z{T  
,9.-A-Yw  
实现此tag标签 =O o4O CF2  
AZH= r S`  
'$0~PH&  
为了实现tag标签,你有2种方法来存放tag处理类。一、让tag处理类以.class的方式存放于当前应用的WEB-INF/class子目录下,二、如果tag处理类是以JAR包的形式存在的话,那可以放在当前应用的WEB-INF/lib目录下,如果tag处理类要在多个应用中共享,那么它就应放在jsp服务器上的common/lib目录下,对于tomcat来说,就是tomcat/common/lib目录下。 U(6=;+q  
/idrb c  
*Dhy a g  
tag标签类型 o+0x1Ct3P  
(#K u`  
yx\I&\i  
自定义的tag标签遵循XML语法。它有一个开始标记和一个结束标记,有的还有body(即文本节点): ^q}cy1"j"  
zgn~UC6&  
<tt:tag> 9Hm>@dBhM  
Oz1S*<]=,~  
body b haYbiX?  
U6xs'0  
</tt:tag> ;&} rO.0  
^Q9!DF m  
*=b36M   
一个不带body的tag标签如下: |aX1PC)o_  
WNO!6*+  
<tt:tag /> I&JjyR  
&UxI62[k  
mmvo >F"  
简单的tag标签 :vXlni7N[M  
cCB YM  
一个没有body和属性的tag标签如下: G$oi>zt3  
mx=2lL`  
<tt:simple /> xgq `l#  
Wz+7CRpeP  
x='T`*HD  
带属性的tag标签 > }fw7X  
a+=.(g  
FQe82tfV+  
自定义标签可以有自己的属性。属性一般在开始标记中定义,语法为 attr=”value”。属性的作用相当于自定义标签的一个参数,它影响着tag处理类的行为。你可以在TLD中详细定义它。 ?B['8ju  
~cH3RFV  
你可以用一个String常量给一个属性赋值,也可以通过表达式给它赋值,如<%= ...%>。以struts为例,它的logic:present标签就是用的String常量来给属性赋值: 8<:.DFq  
J e"~/+  
<loglic:present parameter = “Clear”> 4N[KmNi<  
i(m QbWpN  
而另一个标签logic:iterate是用表达式来给属性赋值: 4apaUP=Jp  
Ka/*Z4"  
<logci:iterate collection=”<%= bookDB.getBooks() %>” d1BE;9*/7  
^_ST#fFS  
id=”book” type=”database.BookDetails”> FNR<=M  
m&a 8/5  
 Op5S'  
带body的tag标签 ?2nF1>1  
x2h5,.K  
一个自定义标签可以包含其它自定义标签、脚本变量、HTML标记或其它内容。 }8eu 9~   
{?RVw`g&f  
在下述例子中,此JSP页面使用了struts的logic:present标签,如果些标签定义了parameter=”Clear”的属性,则将清除购物车的内容,然后打印出一条信息: w#^z:7fI  
!4mg]~G  
<logic:present parameter=”Clear”> <! Z06  
% 3Tz%>n  
<% cart.clear(); %> ;"w?@ELE  
jxqKPMf>@%  
<font color=”#ff0000” size=”+2”><strong> x%RG>),U  
@Yj+u2!  
你选择了清除购物车! yllEg9L0z  
W|CZA  
</strong></font> W,f XHYst  
9/#?]LJ  
</logic:present> !]C=5~B BI  
$(fhO   
u3vM!  
到底是用属性还是用body来传递信息? ),(HCzK`  
m <'&`B;  
如上所述,我们既可以通过属性,也可以通过body来传递信息。但一般来说,比较简单的类型,如字符串或简单表达式最好采用属性来传递信息。 <`?V:};Q  
qAW?\*n5N  
TD-o-*mO  
定义脚本变量的tag标签 v}sk %f  
svvl`|n%  
所谓脚本变量,是指JSP中可以调用的变量或对象。它可由tag标签产生。以下示例阐述了一个tag标签定义了一个名为tx的由JNDI所定义的事务处理对象。脚本变量可以是ejb对象、事务、数据库连接等等: M2!2 J  
y8j6ttQv=t  
<tt:lookup id=”tx” type=”UserTransaction” name=”java:comp/UserTransaction” /> YR-Ge  
>/.w80<'  
<% tx.begin(); %> #?C.%kD  
2y5d  
... de_%#k1:L  
O)$Pvll  
tA8O( 9OV  
具有协作关系的tag标签 Xe2Zf  
*!^l ZpF  
自定义tag标签之间可以通过共享对象来实现协作。在下述例子中,标签tag1创建了一个名为obj1的对象,在标签tag2仍可以重复使用obj。 enT[#f[{  
b'%)?{E  
<tt:tag1 attr1=”obj1” value1=”value” /> I7XJPc4}   
?egZkg=U  
<tt:tag2 attr1=”obj1” /> ZxB7H{  
"'74GY8,  
在以下这个例子当中,如果外层的tag标签创建了一个对象,那么其内层的所有tag标签都可以使用这个对象。由于这样产生的对象没有一个指定的名字,那么就可以将少重名的冲突。这个例子阐述了一系列协作的嵌套对象。 '!<gPAVTzV  
jSMxba]  
<tt:outerTag> 8(>2+#exw  
2 9#jKh  
<tt:innerTag /> N?2C*|%f  
-pW*6??+?  
</tt:outerTag> ./35_Vy/O  
G| b I$   
Sjp ]TWj  
Tag处理类 \b*z<Odv  
7yQw$zG,Iz  
yJ4ZB/ZQ  
Tag处理类必须实现Tag接口或BodyTag接口,不过现在一般都流行从TagSupport或BodyTagSupport类中继承,这些类或接口都可以在javax.servlet.jsp.tagext包中找到。 L*FQ`:lZ  
X/ lmj_v  
当JSP引擎看到自己的JSP页面中包含有tag标签时,它会调用doStartTag方法来处理tag标签的开头,调用doEndTag方法来处理tag标签的结束。 tID=I0D  
"\+.S]~  
下表说明不同类型的tag所需要不同的处理过程: 6d(D >a  
I8f='  
Tag处理类的方法 <,*3Av  
U:0Ma 6<  
Tag标签类型 [`kk<$=,&  
所调用的方法 >%H(0G#X  
2b K1.BD  
基本标签 /B<QYvv  
doStartTag, doEndTag, release an2Yluc;  
~P BJ~j+G  
带属性的标签 dh_c`{9  
doStartTag, doEndTag, set/getAttribute1...N, release ^[6el_mj  
..7 "<"uH  
带内容的标签 ^^B~v<uK  
doStartTag, doEndTag, release <Hr~|oG  
I-^C6~  
带内容的标签,且内容重复循环 $!$,cK Pl5  
doStartTag, doAfterBody, doEndTag, release d7S?"JpV  
 &2bqL!k  
带内容的标签,且内容与JSP交互 "7Z-ACyF5  
doStartTag, doEndTag, release, doInitBody, doAfterBody, release rK\9#[?x  
F+ %l= fs  
一个tag处理类可以通过javax.servlet.jsp.PageContext来与JSP交互,通过javax.servlet.jsp.PageContext类,tag处理类可以访问JSP中的request、session和application对像。 C55Av%-=  
L'w]O -86  
如果tag标签是互相嵌套的,那内层的tag处理类可以通过它的parent属性来访问上层的tag处理类。 l5#SOo\  
=!\Y;rk  
一般情况都将所有的tag处理类打成了JAR的包,以便于发布。 p\R&vof*  
!Df>Q5~g  
.C` YO2,  
Tag库描述(简称TLD) zpjE_|  
]$=#:uf  
x4K A8  
Tag库是用xml语言描述的,TLD包括了tag库中所有tag标签的描述,它一般用来被jsp服务器用来校验tag的语法正确性,或者被jsp开发者用来开发新的标签。 @N ]]Cf>x  
Lg~ll$ U  
TLD的文件扩展名必须为.tld,而且必须放在当前WEB应用的WEB-INF目录或其子目录中。 G6dUm_iB  
m}7Nu  
一个TLD的内容的开头必须遵守标准的XML开头,用于描述DTD和xml的版本,例如: cn Oh j  
A*g-pJ h  
<?xml version="1.0" encoding="ISO-8859-1" ?> msY6zJc`  
c:[ ZknnCe  
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd"> S_TD o  
TLD必须以<taglib>来作为它的根元素,<taglib>的子元素如下表: X'U~g$"(+  
]!j%Ad  
]T6pH7~  
<taglib>的子元素 v[r 8-0c  
m%=*3gH]&  
Element y,/i3^y#_  
Description ]GO=8$Z  
l 0U23i  
tlib-version 4fL`.n1^  
Tag库的版本 g^^pPV K_  
VVDW=G  
jsp-version 5M/~ |"xk  
Tag库所需要的jsp的版本 dI|D c  
!ewT#afyu(  
short-name t3h){jZ  
助记符,tag的一个别名(可选) Sy' ]fGvx  
%DA&txX}w  
uri o7s!ti\G  
用于确定一个唯一的tag库 <PiO %w{  
^qzH(~g{M  
display-name Qj'Ik`o  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) 9w~SzpJ%  
F0~<p[9Nx  
small-icon &B ]1 VZUp  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) }m'n1tm;  
f!{@{\  
large-icon Ch\__t*v!  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) " :f]egq -  
S+#|j  
description |#sOa  
对tag库的描述(可选) (k8}9[3G  
+H28F_ #  
listener KK6n"&TVa  
参见下面listener元素 wSw> UU  
 6']HmM  
tag )XHn.>]nc  
参见下面tag 元素 U E$Ix  
@mmnr?_w  
Listener元素 $rlrR'[H  
y/5GY,z%aL  
一个tag库可能定义一些类做为它的事件侦听类,这些类在TLD中被称为listener 元素,jsp服务器将会实例化这些侦听类,并且注册它们。Listener元素中有一个叫listener-class的子元素,这个元素的值必须是该侦听类的完整类名。 Rw|'LaW  
v`{N0R  
Tag元素 . !Pg)|  
#?V rt,n  
每个tag元素在tag库中都要指出它的名字、类名、脚本变量、tag的属性。其中脚本变量的值可以直接在TLD中定义或通过tag附加信息的类来取得。每个属性描述了这个属性是否可以省略,它的值是否可以通过<%= …%>这样的JSP语法来获得,以及属性的类型。 Inn{mmz 1  
%pxO<O  
每一个tag在TLD中对应一个tag元素,下表是tag元素的子元素: /M+Du,  
+VNk#Z i  
Tag元素的子元素 =~k c7f{  
9?8PMh.  
元素名称 b+|3nc!  
描述 tU5uL.( O  
dt^h9I2O  
name fvcS=nRQv  
独一无二的元素名 ?^M,Mt  
7Y R|6{@  
tag-class y$_@C8?H  
Tag标签对应的tag处理类 &!OEd ]  
*ziR&Fr!  
tei-class yIrJaS-  
javax.servlet.jsp.tagext.TagExtraInfo的子类,用于表达脚本变量(可选) OZ+v ~'oD  
[:FiA?O]  
body-content E5$]0#jB  
Tag标签body的类型 ?3p7MjvZ  
;AE-=/<  
display-name 4(|yl^w  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) nYFrp)DLK  
wD=]U@t`,  
small-icon YZj*F-}  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) NC#F:M;b  
<S041KF.{6  
large-icon *8WB($T}  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) |1RVm?~i  
LP=j/qf|  
description T!8^R|!a6  
此tag标签的描述 ](A2,F 9(U  
T*f/M  
variable >WIc"y.  
提供脚本变量的信息(同tei-class)(可选) xbm%+  
G[A3H> >  
attribute o87kF!x  
Tag标签的属性名 %VH,(}i  
nuXL{tg6  
以下章节介绍对于不同类型的tag,如何具体地实现它们。  }:Gs ,  
sVK?sBs]  
o`,~#P|  
简单的tag IQRuqp KL  
qyv=ot0"~F  
B*,)@h  
tag处理类 0Gc@AG{  
d<6F'F^w.7  
简单的tag处理类必须实现Tag接口的doStartTag和doEndTag方法。当jsp引擎碰到tag标签的开头时,doStartTag被调用,因为简单的tag没有body,所以此方法将返回 SKIP_BODY。当jsp引擎碰到tag标签的结尾时,doEndTag被调用,如果余下的页面还要被计算,那它将返回EVAL_PAGE,否则将会返回SKIP_PAGE。 1^4:l!0D  
,VHqZ'6  
以下是例子:对于标签 <tt:simple /> ,它的tag处理类实现如下: @kqxN\DE  
?9kC[4G  
BG+i tyH  
public SimpleTag extends TagSupport $2Whb!7Z(  
4P&2Z0  
{ "FWx;65CR  
\&5V';  
public int doStartTag() throws JspException njF$1? )sq  
?: yz/9(  
{  ch8a  
:<t=??4m  
try{ wQSye*ec  
[b:&y(  
pageContext.getOut().print(“Hello.”); N2v/<  
NO o?  
}catch(Exception e){ x,!Dd  
Do/R.Mgy*  
throw new JspTagException(“SimpleTag: “ + e.getMessage()); }l|S]m!  
U`%t&7)  
} j#1G?MF  
`m7<_#Y  
return SKIP_BODY; *Jd"3Si/  
q(?+01  
}  bDkZU  
L"qJZU  
public int doEndTag() tWIs |n  
:&IHdf0+  
{ ;=Ma+d#  
#ES[),+|mB  
return EVAL_PAGE; >R+-mP!nj  
]JrD@ Vy  
} c ZYy+  
w+g29  
} h2ROQKL"B  
jE\ G_>  
UK ':%LeL  
注意:如果tag标签没有内容的话,那必须定义body-content元素为空,例如 m,k 0 h%  
?woL17Gt  
<body-content>empty</body-content> 42NfD/"g+s  
CS7b3p!I  
x>yqEdR=o  
带属性的tag标签
评价一下你浏览此帖子的感受

精彩

感动

搞笑

开心

愤怒

无聊

灌水
级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
只看该作者 1 发表于: 2007-01-01
tag处理类 QVT0.GzR  
D!`[fjs6A  
对于tag标签的每个属性,你必须依照JavaBeans规范来定义其属性,以及get和set方法。以struts的logic:present 标签为例, :Awwt0  
#{6VdWZ  
<logic:present parameter=”Clear”> 8W&1"h`  
/TMVPnvz.  
与此相应,此tag处理类应有如下方法和定义: -H6 0T,o  
n {?Du  
3r~8:F"g  
protected String parameter = null; G8repY  
7P$*qj~Vh  
public String getParameter() EXSH{P O+  
YEv\!%B  
{ !X}+JeU '  
H:G``Vq;0m  
return this.parameter; qz` -?,pF  
Ftyxz&-4$p  
} ;~F* 2)  
CEj_{uf|  
public void setParameter(String parameter) !zK"y[V  
y;az&T  
{ {MtJP:8Jp  
jZ~girA  
this.parameter = parameter; w"v96%"Y  
o "r  
} dw6ysOR@  
JrBPx/?(,;  
Aw7N'0K9UN  
注意:如果你的属性名为id,而且你的tag处理类是从TagSupport类继承的,那你就不需要定义它的属性和set和get方法,因为他们早已在TagSupport被定义过了。 mU[\//  
:a8Sy("  
Attribute元素 %qV:h#  
myo4`oH  
对于tag标签的每个属性,你必须定义它是否必须的,它的值是否可以用诸如<%= …%>的表达式来获得,以及它的类型(可选),如果不指定它的类型,那就默认为是java.lang.String类型。如果rtexprvalue元素被定义为true或yes,那么在type元素中就定义了attribute的返回类型。 @kSfF[4H  
2z;nPup,  
<attribute> _#~D{91 j:  
/%g@ ;  
<name>attr1</name> U/Cc!WXV]  
xZ'C(~t  
<required>true|false|yes|no</required> ;-JF1p7;  
"y8W5R5kL4  
<rtexprvalue>true|false|yes|no</rtexprvalue> 6 (7 56  
` { Ox=+]M  
<type>attribute的返回类型(只用当rtexprvalue为真是才有效)</type> :H>I`)bw  
o5]-Kuw`  
</attribute> $JOtUB{  
e=##X}4zZ  
如果tag的某个属性不是必须的,那tag处理类会自动提供一个缺省值。 iklZ[G%A0  
[m! P(o  
例如,在logic:present这个tag标签中定义了一个属性叫parameter,但它不是必须的,而且它可以被诸如<%= …%>的表达式来赋值。 `j {q  
ByE@4+9  
<tag> <XrXs  
oHfr glGX  
<name>present</name> E#d~.#uH  
;0| :.q  
<tag-class>org.apache.struts.taglib.logic.PresentTag</tag-class> aQHR=.S]X  
k"=*'  
<body-content>JSP</body-content> M:.+^.h  
XlXt,  
le_a IbB"P  
'Jek< 5  
<attribute> "C3J[) qC  
Y4N7# 5  
<name>parameter</name> 7'At_oG  
G'Wp)W;])\  
<required>false</required> 3zmbx~| =\  
$U/lm;{%  
<rtexprvalue>true</rtexprvalue> B&7:=t,m(  
o; 6^:  
</attribute> JPL`/WA 0  
CL`+\ .  
$v_&j E  
z&c}  
</tag> Af@\g-<W_  
}l}_'FmQ  
o&M.9V?~~  
属性元素的校验 RnC+]J+?4  
<5Ll<0  
+BO kHXk1  
有关于tag标签的有效值可以从tag库的说明文档中获得,当JSP页面被编译时,jsp引擎会强制性地参照TLD中定义的规则进行检查。 XgXXBKf$  
7K&Uu3m  
还有一个方法也可以进行属性元素的校验,就是先继承类TagExtraInfo,然后调用它的isValid方法。这个类同时也起到提供tag中定义的脚本变量信息的作用。 EUh_`R  
o\><e1P  
IsValid方法通过TagData对象来传递属性信息,它包括着tag的所有的属性名-值的信息。由于校验发生在运行时刻,因此这个属性的值将被赋值为TagData.REQUEST_TIME_VALUE。 IMM+g]#e  
3.P7GbN  
例如tag标签<tt:twa attr1=”value1” />在TLD中定义如下: ZI4dD.B  
RX_f[  
<attribute> p(="73  
6WIs*$T2*  
<name>attr1</name> @(*A<2;N  
UqsOG<L'6  
<required>true</required> !Ea9 fe  
oa=TlBk<  
<rtexprvalue>true</rtexprvalue> x![.C,O  
]t&^o**  
</attribute> aO(iKlZ$  
] >w@@A  
}CZw'fhVWO  
这个定义说明了attr1能在运行期间被赋值。 /:{4,aX2  
}kItVx  
以下的isValid方法检查attr1属性的值是否属于Boolean类型。注意由于attr1能在运行刻被赋值,那么isValid方法必须检查tag用户是否对此tag进行了运行时刻赋值。 oclU)f.,  
X<$DNRN  
sV5") /~  
Public class TwaTEI extends TagExtraInfo zkqn>  
3` oOoKX  
{ OAiv3"p  
UU[z\^w| E  
public boolean isValid(Tagdata data) \o72VHG66  
Nmt~1.J  
{ '3sySsD&O  
f)a0!U 44  
Object o = data.getAttribute(“attr1”);  h 7l>(3  
}(XKy!G6  
If(o != null && o != TagData.REQUEST_TIME_VALUE) k.c.7%|~;  
Fsx<Sa  
{ _/%,cYVc8!  
Px*<-t|R-  
if( ( (String)o).toLowerCase().equals(“true”) || b5 NlL`g  
34N~<-9AY  
((String)o).toLowerCase().equals(“false”) ) ,d*hhe  
`F&~SU,  
return true; IFS_DW  
u-:3C<&>  
else ,=[% #gS  
$)8,dS  
return false; N#-pl:J(  
jf)l; \u  
} g*LD}`X/-  
:Y1;= W  
else Sl^PELU  
3/ }  
return true; 10c.#9$  
Vq{3:QBR  
} ^->S7[N?  
BbC O K  
} MpZ\ j  
NT5'U  
7[u>#8  
带body的tag udLIAV*  
|K-`  
qnj'*]ysBC  
tag处理类 xz5A[)N  
fbbbTZy  
9`Fw}yAt  
如果tag标签含有内容,那处理方式会略微有些不同,而且还要视tag处理类是否要与body交互的情况而定。如果要与body交互,那我们认为tag处理类要可能要对body进行操作。 Bi :!"Nw[X  
:N$-SV  
Tag处理类不与body交互 PRTjXq6)5  
hEsi AbTyF  
如果tag处理类不与body交互,tag处理类应该实现Tag接口或从TagSupport中派生,如果body要被计算,那么doStartTag方法应返回 EVAL_BODY_INCLUDE,否则应返回SKIP_BODY。 dpNERc5  
p e+h8  
如果tag处理类要对body反复运算,则它应该实现IterationTag或从TagSupport中派生。如果tag处理类认为body还未计算完的话,那它的doStartTag方法和doAfterBody方法必须返回EVAL_BODY_AGAIN。 y*-_  
rZaO^}u]  
Tag处理类与body交互 b"N!#&O]  
`V\?YS}  
如果tag处理类与body交互,那tag处理类应实现BodyTag接口或从BodyTagSupport中派生。这种tag处理类一般要实现doInitBody和doAfterBody方法。 7>F{.\Z  
\ I523$a  
Body允许一些方法来读写它的内容。Tag处理类可以调用body内容的getString或getReader方法来从body中提取信息,也可用 writeOut(out) 方法来将body的内容写入到out对象中。其中out对象通过tag处理类的getPreviousOut方法来获得。 |llJ%JhF  
tLfhW1"  
如果body的内容需要被计算,那么doStartTag方法必须返回EVAL_BODY_BUFFERED,否则,它将返回 SKIP_BODY。 Tsa]SN14  
Ihf :k_;  
doInitBody 方法 q=BljSX  
t S]  
此方法在body内容已经设好,但未被计算之前被调用。你可以根据不同的body内容来制定初始化策略。 TSsZzsdr2  
zN|k*}j1J  
doAfterBody方法  L1 /`/  
^9q#,6  
此方法在body内容已被计算后进行调用。 V<H9KA  
0C/ZcfFU~  
和doStartTag方法一样,doAfterBody方法返回一个指示符指示是否要继续计算body,如果要继续计算,则doAfterBody应返回EVAL_BODY_BUFFERED,否则,它应返回SKIP_BODY。 oYStf5  
y@!o&,,mq  
release 方法 P%(9`A  
Ws@'2i\;  
tag处理类调用此方法将它的状态重置为初始状态,并释放所有的私有资源。 \?^2}K/  
Rxd4{L )n  
9 =;mY  
以下的例子读取body的内容(其中含有一条sql语句),然后将它传递给一个对象,让它进行查询。由于此处body不须重新计算,所以doAfterBody会返回SKIP_BODY。 4Qf sxg  
AT~,  
GN(<$,~g  
Public class QueryTag extends BodyTagSupport 71c[ `h*0{  
8a P/vToa  
{ bhpku=ov  
YoKyiO!   
public int doAfterBody() throws JspTagException UDg' s  
8v& \F  
{ X&qx4 DL  
5h#h>0F  
BodyContent bc = getBodyContent(); UPfO;Z`hJ  
= (F   
//将body的内容以字符串的格式提取出来 U@mznf* J  
[fa4  
String query = bc.getString(); ?W'p&(;  
YS9RfK/  
//清除body +JU , ^A#X  
.Q*X5Fc  
bc.clearBody(); S13cQ?4  
oY18a*_>M1  
try{ }p7iv:P=3  
y~ =H`PAE  
Statement stmt = connection.createStatement(); `um,S  
^hC'\09=c  
Result result = stmt.executeQuery(query); 2nd n8_l  
\j>7x  
}catch(SQLException e){ B;1qy[  
LmF,en5  
throw new JspTagException(“queryTag: “ + e.getMessage() ); FLqN3D=yQ  
f V. c6  
return SKIP_BODY; !.] JiT'o  
n~*".ZC'Y  
} %X{EupiFA  
\c}(rqT  
} M<fhQJ  
PLyity-L[7  
2@D`^]]  
body-content元素 *glZb;_  
*x"80UXL  
'-;[8:y.  
由于tag可能会有body,你必须用body-content元素来指定body内容的类型: _>;Wz7  
p~qe/  
<body-content>JSP|tagdependent</body-content> g>@JGzMLP  
0M_oFx  
W7i|uTM  
如果body的内容是定制的或内部的tag、脚本元素、或HTML广本,则归类为JSP类型。其他的类型,比如上面代码所述的?D?D将sql statement类传给 query tag的这种类型应该标为tagdependent。 Tu#< {'1$  
<\aeC2~M  
注意:实际上body-content的值并不影响tag处理类对body内容的处理,它仅仅是被tag编辑工具用来描述此body的内容。 yGZsNd {a&  
7;"0:eX  
Lx^ eaP5  
用tags定义脚本变量 e#(Ck{e  
~U9K<_U  
UNdD2Fd9  
tag处理类 ISbs l =F  
dj0; tQ=C  
J!6FlcsZm  
tag处理类负责创建或设置页面中定义的脚本变量,用pageContext.setAttribute(name,value,scope)或pageContext.setAttribute(name,value)方法来实现。一般来说,tag处理类通过脚本变量的名称来获取它,脚本变量的名称一般可用get方法来获得。 }h5i Tc  
<uH8Fivb  
如果脚本变量的值依赖于tag处理类中的上下文中某一对象,那它可用pageContext.getAttribute(name,scope)方法来找到那个对象。一般的处理过程是tag处理类先找到脚本变量,再对其进行处理,然后用pageContext.setAttribute(name,object)的方法来设置它的新值。 h+f>#O+:  
157_0  
对象的生存周期(scope)如下表: <B"sp r&1  
XpIiJry!6  
对象的生存周期表 ^QB[;g.O  
kI\m0];KnQ  
名字 }'X=&3m  
可访问范围 \oQ]=dDCd%  
生存周期 Ykbg5Z  
R?2sbK4Cz  
page y7R#PkQ~  
当前页面 uy'ghF  
一直有效,除非页面向客户提交响应或重定向到一个新页面 pm&TH d  
{|+Y;V`  
request Lpchla$  
当前页面或当前页面重定向到的页面 ${+u-Wfau  
一直有效,除非页面向客户提交响应 ;SR ESW  
h6 \P&Z  
session 0&.CAHb}  
当前页面或在同一浏览器窗口中的页面 WeI+|V$  
一直有效,除非关闭当前浏览器、超时、网络故障 QFyL2Xes/  
8!g `bC#%  
application wucdXj{%  
整个web应用程序的所有请求 {Z.6\G&q  
一直有效,除非发生网络故障、服务器故障 &c`-/8c  
Gn]36~)*H  
提供关于脚本变量的信息 h$>F}n j  
73WSW/^F  
以下示例定义了一个名为“book”的脚本变量,用来访问程序中关于书的信息: T:|/ux3  
o<2GtF1"o  
<bean:define id=”book” name=”bookDB” property=”bookDetails” type=”database.BookDetails” /> zd?@xno  
8OfQ :   
<font color=”red” size=”+2” > Rd?}<L  
&4'< {  
<%= messages.getString(“CartRemoved”) %>  s>rR\`  
@nxo Bc !P  
<strong><jsp:getProperty name=”book” property=”title” /></strong> 5:Qz  
xVvUx,t  
</font> \?:L>-&h8  
b^Hr zn  
当包含此tag的JSP页面被编译时,jsp引擎会自动生成关于此book的同步的代码(同步可以避免几个客户同时访问此book时造成的冲突),要生成同步代码,jsp引擎需要知道此脚本变量的如下信息: yu?5t?vf  
$o6/dEKQ  
· 脚本变量名称 yIw}n67  
QWmE:F[M~  
· 脚本变量所属的类 NGra/s,9 |  
N&8TG  
· 此脚本变量是否引用了一个新的或已存在的对象 wZrFu(_  
BEZ~<E&0H  
· 此脚本变量的有效性 &9k~\;x  
gfk)`>E  
有两种办法可以向jsp引擎提供关于脚本变量的信息:在TLD中定义variable子元素,或用tei-class子元素定义一个额外tag信息类。用variable最简单,但可能降低了一些灵活性。 >hKsj{=R7  
MsB >3  
Variable元素 6*8Wtq  
ia6 jiW x  
Variable元素有如下子元素: 5'lVh/  
sW^M  ]  
· name-given ?D?D 给出的名字,是一个常量 p_r`"  
2 a<\4w'  
· name-from-attribute?D?D 属性名,在编译时给出的属性名 npP C;KD  
{+N< 9(O  
name-given或name-from-attribute两者必须选一,但以下子元素是可选的: :\T Mm>%q  
3CUQQ_  
· variable-class?D?D变量的类型,缺省为java.lang.String。 `CK~x =  
%lKw+D  
· declare?D?D此脚本变量是否引用了一个新对象,缺省为True。 Z0|5VLk,<{  
Pz]WT1J0  
· scope?D?D脚本变量的范围,缺省为NESTED。下表描述了scope的几种类型: $Dg-;I  
C|{Sj`,XG  
脚本变量的有效范围 l,ny=Q$[1'  
]l7W5$26 @  
iIfiv<(ChM  
有效性 "+DA)K  
方法 o Rfb4+H&  
?o<vmIge  
NESTED :J;U~emq  
在tag标签的开始和结束之间 7o4E_ .*  
如果tag处理类实现BodyTag接口,则在doInitBody和doAfterBody中调用,否则在doStartTag中调用 [d`Jw/4n  
5- dt0I@<  
AT_BEGIN D@=]mh6vl  
从tag标签的开始一直到页面结束 Q\oa<R D5  
如果tag处理类实现BodyTag接口,则在doInitBody、doAfterBody和doEndTag中调用,否则在doStartTag和doEndTag中调用 2"0VXtv6  
4+olyBht  
AT_END bGh&@&dHr  
从tag标签的结束一直到页面结束 ra^</o/  
在doEndTag中调用 \Y#  
G<Z}G8FW^  
以struts为例,它的bean:define标签的实现遵循JSP1.1规范,此规范要求使用额外tag信息类来定义脚本变量。Variable元素是JSP1.2规范中加入的。以bean:define标签为例,你可以定义如下variable元素: j/V_h'}  
a%q,P @8  
<tag> -]%EX:bm  
`&;#A*C0  
<variable> 2%/F`_XbP  
a[ULSYEi  
<name-from-attribute>id</name-from-attribute> & -/J~b)"  
A;!5c;ftj,  
<variable-class>database.BookDetails</variable-class> ]t[%.^5#  
A-x^JC=  
<declare>true</declare> eI-fH  
}$?FR  
<scope>AT_BEGIN</scope> o!xCM:+J  
``xm##K  
</variable> ft"-  
o HK   
</tag> J~x]~}V&  
gD$&OkH  
额外tag信息类 St;9&A  
G>~/  
如果要定义一个额外tag信息类,你要继承javax.servlet.jsp.TagExtraInfo类。一个TagExtraInfo类必须实现getVariableInfo方法,此方法返回一个叫VariableInfo的数组类,它包括如下信息: [_N1 .}e  
h]zok}$  
· 变量名 Yjg$o:M  
Vy& X1lG:  
· 变量所属类名 Hc/7x).  
VnuG^)S  
· 此变量是否引用了一个新对象 >A )Sl'  
"t2T*'j{  
· 此变量的有效范围 5a |R  
(U\o0LI  
jsp引擎将一个名为data的参数传给getVariableInfo方法,data中包括tag标签中的所有“属性名?D?D属性值”对。它可以用来向VariableInfo对象提供脚本变量的名字和类名。 df{?E):  
$#^3>u  
以struts为例,它在bean:define标签中定义了一个名为DefineTei的额外tag信息类,用来向脚本变量提供信息。由于脚本变量的名称(book)和类名(database.BookDetails)是通过tag标签的属性来传递的,它们一般定义在VariableInfo的构建代码中,并且可用data.getAttributeString方法来得到这些信息。如果要允许book脚本变量能在从tag开始直到整个JSP页面结束的范围内都可用的话,那它的范围应设为AT_BEGIN。如下所示: qJ" (:~  
tFcQ.1  
&4E|c[HN  
public class DefineTei extends TagExtraInfo X&Oo[Z  
kwi$%  
{ \m`IgP*  
&"u(0q  
public VariableInfo[] getVariableInfo(TagData data)  2  
gvVy0nJI~  
{ ?;=7{E j  
LBio$67F  
String type = data.getAttributeString(“type”); E[hSL#0  
tE>FL  
If( type == null) (,"%fc7<i  
)g=mv*9>  
type = “java.lang.Object”; 0ytAn+/"x  
aT/2rMKPF  
return new VariableInfo[] { QM!UMqdj  
bLTX_ R  
new VariableInfo(data.getAttributeString(“id”), Zn1((J7  
||2%N/?  
type, f$</BND  
TaF*ZT2  
true, 6oKlr,.  
`-nSH)GBM  
VariableInfo.AT_BEGIN) `B?+1Gv  
=Q"thsR  
}; EAY+#>L*  
VK9E{~0=  
} !'\(OFv9Im  
&=zJ MGa  
} Jv(E '"H  
SdufI_'B  
JAW7Y:XB  
注意:关于额外tag信息类的类名必须要在TLD中的tag标签下的tei-class子元素中定义。因此,DefineTei的tei-class中的定义看起来如下: HJr*\%D}1  
<tei-class> XffHF^l9F  
org.apache.struts.taglib.bean.DefineTagTei * *A JFc  
</tei-class> qPN  
5m;pHgkb  
9U9ghWH8  
具有协作关系的tag 1>_$O|dE  
AB!({EIi  
lYS4Q`z$  
tag通过共享对象来进行协作,JSP技术支持2种方式的对象共享。 {3Gj rE  
YC{7;=P f  
第一种方法是使用pageContext对象进行对象的共享(可支持JSP页面和tag处理类之间的共享),如果在一个tag处理类中要调用由另一个tag处理类创建的对象,可调用pageContext.getAttribute(name, scope)方法。 Jx3a7CpX  
9( &$Gwi  
第二各方式的共享是对于tag之间有嵌套关系而言的,外层的tag所创建的对象对于内层的tag来说是可以共用的。这种形式的共享的好处是减少了可能存在的重名冲突。 4P2p|Gc3  
a$"Z\F:x  
要访问一个嵌套tag创建的对象,tag处理类必须先找到此嵌套tag对象,可用TagSupport的静态方法 TagSupport.findAncestorWithClass(from, class)或TagSupport.getParent方法。前者在当不确定此tag是否为嵌套tag对象时使用。一旦它的父类被找到,它就能访问其所有动态或静态创建的对象。静态创建的对象是父类的成员,而动态创建的对象可能是父类的私有对象。诸如此类的对象可以用tag处理类的setValue方法来保存,用getValue方法来获得。 s5b<KQ.  
TR?jT U  
下例阐述了以上两种共享对象的方法。在这个例子当中,一个查询tag检查一个名为connection的属性名是否在doStartTag中被设置。如果connection属性被设置,tag处理类从pageContext中得到这个connection对象。否则,此tag处理类先找到它的父tag处理类,然后从它的父tag处理类中找到connection对象。 11J:>A5zt  
RplcM%YJn  
qyIy xJ  
public class QueryTag extends BodyTagSupport Yk4ah$}%-^  
+SRM?av  
{ }Ny~.EV5^  
X bV?=  
private String connectionId; g2lv4Tiq-  
ZDr TPnA[  
public int doStartTag() throws JspException [o'}R`5)  
a 8jG')zg  
{ bF@iO316H  
yErvgf  
String cid = getConnection(); KueI*\ p  
z Hj_q%A  
if(cid != null) 7_7^&.Hh  
Zfr?(y+3  
{ X<"#=u(  
TwE&5F*  
//存在一个connection id,使用它。 9e 1KH'  
b~G|Bhxa  
connection = (Connection) pageContext.getAttribute(cid); iu,Bmf^oD  
TLzcQ|  
} )3_g&&  
Z Q9's  
else #`Et{6W S  
20uR?/|@  
{ 7W#9ki1  
hmd,g>J:<  
ConnectionTag ancestorTag = (ConnectionTag)findAncestorWithClass(this,  )2,\Y  
\RP=Gf  
ConnectionTag.class); (au 7wI{  
b+}*@xhl  
if(ancestorTag == null) q} R"  
w3IU'(|G  
{ ;,&1  
k@R)_,2HH  
throw new JspTagException(“一个没有connection属性的查询标签必须被一个connection标记嵌套。”); Y-,1&$&  
?+#E&F  
} whg?X&j\V  
sXSZ#@u,WN  
connection = ancestorTag.getConnection(); RT2a:3f  
ZjJEjw  
} mE]W#?   
BPKeG0F7  
} *o[*,1Pw  
}F R yG%  
} QSy#k~  
B6Tn8@O  
Hw/1~O$T  
IV:Knh+ ?  
此查询标签在JSP页面中的调用形式可以从以下2种定义中任选一种: A|@d4+  
ODM<$Yo:d  
_hLM\L  
<tt:connection id=”con01” ...> ... </tt:connection> @ B3@M  
|^@TA=_  
<tt:query id=”balances” connection=”con01” > G";yqG  
zUxF"g-W  
SELECT account, balance FROM acct_table )5X7|*LP  
d=wzN3 ;-  
where customer_num = <%= request.getCustno() %> I#f<YbzD  
*-Y|qS%  
</tt:query> 0:nQGX!N  
YKUs>tQ!  
I\DT(9 'E  
Md[nlz  
c{#lKD<7  
<tt:connection ...> n|L.d BAs]  
z0Gh |N@)  
<x:query id=”balances”> Q_1EAxt  
M>_S%V4a  
SELECT account, balance FROM acct_table |)IN20  
"$:nz}  
where customer_num = <%= request.getCustno() %> /sdkQ{J!.  
( {zp$P}  
</x:query> .'7o,)pJ<  
z/rN+ ,  
</tt:connection> TiF$',WMv  
!Nl"y'B|  
JVTG3:zD  
与此同时,在TLD中必须指定connection属性为可选的,定义如下: K22W=B)Ln  
WE`Y!  
<tag> F=^vu7rf  
G*wn[o(^j  
... [?Aq#av  
1/w['d4l!  
<attribute> NRq jn; ,+  
UmQ 9_H7  
<name>connection</name> Pd^ilRB  
m2<sVTN`^  
<required>false</required> w},k~5U^s  
3r^i>r8B  
</attribute> R^_/iy  
Te!q(;L`4  
</tag>
描述
快速回复

您目前还是游客,请 登录注册
如果您提交过一次失败了,可以用”恢复数据”来恢复帖子内容
认证码:
验证问题:
3+5=?,请输入中文答案:八 正确答案:八