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

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

级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
标准的JSP 标记可以调用JavaBeans组件或者执行客户的请求,这大大降低了JSP开发的复杂度和维护量。JSP技术也允许你自定义taglib,其实换句话说,taglib可以看成是对JSP标记的一种扩展,正如xml是对html的一种扩展一样。taglib通常定义在tag标签库中,这种标签库存放着你自己定义的tag标签。简而言之,如果使用taglib,那么你可以设计自己的JSP标记!  E@b(1@  
wH@Ns~[MA  
一般来说,自定义tag标签主要用于操作隐藏对象、处理html提交表单、访问数据库或其它企业级的服务,诸如邮件和目录操作等等。自定义tag标签的使用者一般都是那些对java编程语言非常精通,而且对数据访问和企业级服务访问都非常熟悉的程序员,对于HTML设计者来说,使得他可以不去关注那些较复杂的商业逻辑,而将精力放在网页设计上。同时,它也将库开发者和库使用者进行合理分工,自定义tag标签将那些重复工作进行封装,从而大大提高了生产力,而且可以使得tag库可用于不同的项目中,完美地体现了软件复用的思想。 yNbjoFM.i  
pfI"36]F  
在这篇文章中,我们主要讨论: Nal9M[]c  
jB(|";G  
· 什么是自定义tag标签? 9B9(8PVG  
*I0T{~  
· 怎么使用tag标签? y_?Me]  
z5 YWt*nm  
o 声明要使用的tag库 -jiG7OL  
%QP0  
o 找到与之对应的tag处理类 2=^m9%  
.qZI$ l .  
o tag标签的类型 f=9|b  
j{Q9{}<e  
· 自定义tag标签 r% +V8o  
pS7w' H  
o tag处理类 aYSCw 3C<  
t)}scf&^x  
o tag库描述 _/tHD]um  
9c("x%nLpB  
o tag标签示例 tw9f%p  
l~$+,U&XNe  
o 带属性的tag B]l)++~  
y9Usn8  
o 带body的tag 5yz(>EVH  
@8I4[TE  
o 定义了脚本变量的tag ;N?]eM}yf  
(R("H/6xs  
o 具有协作关系的tag 53n^3M,qK  
U3dwI:cG  
· 自定义tag标签 K>@+m  
Ptdpj)oi&Q  
o 一个迭代tag的例子 e(<st r>  
W@I|Q -  
o 一个模板tag库 N <Xq]! K-  
@P?~KW6<|  
o tag处理类到底是怎样被调用的? io8'g3<  
ZNvEW  
"9Q40w\  
什么是自定义的tag? ]%u@TK7  
K42K!8$  
一个自定义的tag标签是用户定义的一种JSP标记。当一个含有自定义的tag标签的JSP页面被jsp引擎编译成servlet时,tag标签被转化成了对一个称为tag处理类的对象进行的操作。于是当JSP页面被jsp引擎转化为servlet后,实际上tag标签被转化成为了对tag处理类的操作。 @W"KVPd  
z+n,uHs  
自定义tag标签有很多特色,诸如: ybKWOp:O  
lE(a%'36  
· 可以在JSP页面中自定义tag标签的属性 W~7A+=&  
}xh$T'M8  
· 访问JSP页面中的所有对象 oc>{?.^  
B e0ND2oo  
· 可以动态地修改页面输出 [UWd W  
9j6QX ~,  
· 彼此这间可以相互通信。你可以先创建一个JavaBeans组件,然后在一个tag中调用此JavaBeans组件,同时可以在另一个tag中调用它。 !*B'?|a<\  
M# %a(Y3K)  
· tag允许相互嵌套,可以在一个JSP页面中完成一些复杂的交互。 S;286[oq@  
Rx=>6,)'  
]z/8KL  
使用tag标签 kZGRxp9  
Tq[kl'_  
lSVp%0jR  
本节主要描述怎样在JSP页面中使用tag标签,以及tag标签的不同类型。 fO[+LR 'ax  
7E79-r&n  
要使用tag标签,JSP程序员必须做2件事: ~yW4)4k;b  
%2{ %Obp'  
· 声明此tag标签的tag库 oUQ,61H  
^Xq 6:  
· 实现此tag标签 cmU1!2.1E  
1oW ED*B  
声明tag标签所在的tag库 `ux{;4q  
I7n"&{s"*  
如果要使用tag标签,则应用JSP的taglib指示符来指定其tag库(注意:taglib要在在使用此tag标签之前声明) (<xfCH F5  
EWkLXU6t  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> @a0DT=>dT  
Ni-xx9)=  
uri属性定义了唯一的标签库描述(以下简称TLD),它可以是直接是tld文件名或一个独一无二的名字。prefix是用来区别其它TLD中和本TLD中有重名的tag的一种手段。 Sp;G'*g  
Vg>dI&O  
TLD必须以.tld作为扩展名,并且存放在当前应用的WEB-INF目录或其子目录下。你可以通过它的文件名直接引用它,也可以通过别的方式间接地引用它。 ic#`N0s?  
VKG&Y_7N  
以下taglib指示符直接引用一个TLD: 8h*Icf  
'R'*kxf  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> L"1}V  
/)}q Xx&  
以下的taglib指示符通过一个逻辑名称间接地引用一个TLD: PuA9X[=  
K1+)4!}%U  
<%@ taglib uri=”/tutorial-template” prefix=”tt” %> BMG3|N^  
xg;+<iW  
如果是间接引用TLD的话,那你必须还要在web.xml中定义此逻辑名称与tld文件之间的映射,具体做法是在web.xml中加入一个名为taglib的元素: jN;@=COi  
DN-+osPi  
<taglib> q=Sgk>NA  
RbP6F*f  
<taglib-uri>/tutorial-template</taglib-uri> '}Z~JYa0  
Q/(K$6]j  
<taglib-location> lvBx\e;7P  
$Y/9SV,  
/WEB-INF/tutorial-template.tld ( +Q&[E"87  
W_\5nF  
</taglib-location> c|B.n]Z  
[ 0KlC1=  
</taglib> xy/`ZS2WPq  
{E9+WFz5  
mpU$ +  
实现此tag标签 V k  K  
8"2=U6*C  
;Q OBBF3HG  
为了实现tag标签,你有2种方法来存放tag处理类。一、让tag处理类以.class的方式存放于当前应用的WEB-INF/class子目录下,二、如果tag处理类是以JAR包的形式存在的话,那可以放在当前应用的WEB-INF/lib目录下,如果tag处理类要在多个应用中共享,那么它就应放在jsp服务器上的common/lib目录下,对于tomcat来说,就是tomcat/common/lib目录下。 9.gXzP H  
4~Vx3gEV:  
=JK@z  
tag标签类型 %,}A@H ,  
8QLj["   
C'.L20qW  
自定义的tag标签遵循XML语法。它有一个开始标记和一个结束标记,有的还有body(即文本节点): Bn#?zI  
* K D I}B>  
<tt:tag> Oj3.q#)`Z  
~=6xyc/c  
body CY s,`  
fzb29 -  
</tt:tag> 93("oBd[s(  
1{ ~#H<K  
p.v0D:@&  
一个不带body的tag标签如下: s E2D#D  
8 D3OOab  
<tt:tag /> )NXmn95  
cdl&9-}  
Zw5Ni Xj  
简单的tag标签 bpJ(XN}E  
;g5m0l5  
一个没有body和属性的tag标签如下: Ln')QN  
Ui_8)z _  
<tt:simple /> fk6%XO  
A+ZK4]xb  
)wam8k5  
带属性的tag标签 &:9c AIe]H  
 *'.|9W  
`scR*]f1+  
自定义标签可以有自己的属性。属性一般在开始标记中定义,语法为 attr=”value”。属性的作用相当于自定义标签的一个参数,它影响着tag处理类的行为。你可以在TLD中详细定义它。 #~}nFY.  
zZPuha8  
你可以用一个String常量给一个属性赋值,也可以通过表达式给它赋值,如<%= ...%>。以struts为例,它的logic:present标签就是用的String常量来给属性赋值: e6R}0w~G  
.h@rLorm>  
<loglic:present parameter = “Clear”> "7'J &^|  
nm5cpnNl  
而另一个标签logic:iterate是用表达式来给属性赋值: *4Thd:7 `  
?I_s0k I  
<logci:iterate collection=”<%= bookDB.getBooks() %>” %GjM(;Tk  
V:In>u$QJ!  
id=”book” type=”database.BookDetails”> ); !eow  
z&#SPH*  
8uc1iB  
带body的tag标签 +Mo9kC  
W>Y@^U&x`  
一个自定义标签可以包含其它自定义标签、脚本变量、HTML标记或其它内容。 tZ: _ag)o  
Z0x ar]4V  
在下述例子中,此JSP页面使用了struts的logic:present标签,如果些标签定义了parameter=”Clear”的属性,则将清除购物车的内容,然后打印出一条信息: fi-WZ  
*}F3M\  
<logic:present parameter=”Clear”> :|V$\!o'U  
\HxT@UQ)~  
<% cart.clear(); %> `5cKA;j>b  
&S{RGXj_  
<font color=”#ff0000” size=”+2”><strong> >kj`7GA  
qON|4+~u%  
你选择了清除购物车! @Owb?(6?  
cs,N <|  
</strong></font> :q$.,EZ4#n  
0%9 q8 M;  
</logic:present> 4IB9 ,?p  
p `8 s  
c]x1HvPE  
到底是用属性还是用body来传递信息? jSD#X3qp  
][gq#Vx@  
如上所述,我们既可以通过属性,也可以通过body来传递信息。但一般来说,比较简单的类型,如字符串或简单表达式最好采用属性来传递信息。 3GaQk-  
5,3'=mA6  
"Gfh,e  
定义脚本变量的tag标签 q+H%)kF  
1L%CJ+Q#0i  
所谓脚本变量,是指JSP中可以调用的变量或对象。它可由tag标签产生。以下示例阐述了一个tag标签定义了一个名为tx的由JNDI所定义的事务处理对象。脚本变量可以是ejb对象、事务、数据库连接等等: ocqU=^ta  
0Is,*Srr  
<tt:lookup id=”tx” type=”UserTransaction” name=”java:comp/UserTransaction” /> C]O(T2l{l  
>BR(Wd.  
<% tx.begin(); %> oX#Q<2z*  
`slL %j^"  
... Yl4^AR&  
R0P iv:  
nOt&pq7  
具有协作关系的tag标签 zvYq@Mhr  
N=4G=0 `ke  
自定义tag标签之间可以通过共享对象来实现协作。在下述例子中,标签tag1创建了一个名为obj1的对象,在标签tag2仍可以重复使用obj。 MW! srTQ_  
7L`A{L  
<tt:tag1 attr1=”obj1” value1=”value” /> )IP,;<  
iZ#!O* >  
<tt:tag2 attr1=”obj1” /> F3N?Nk/  
4,bv)Im+ `  
在以下这个例子当中,如果外层的tag标签创建了一个对象,那么其内层的所有tag标签都可以使用这个对象。由于这样产生的对象没有一个指定的名字,那么就可以将少重名的冲突。这个例子阐述了一系列协作的嵌套对象。 Ttu2skcv  
p#ol*m5wE  
<tt:outerTag> nno}e/zqf  
hv`~?n)D66  
<tt:innerTag /> N|8P)  
u!!Y=!y*<  
</tt:outerTag> oz,np@f)J  
Jv>gwV{  
opY@RJ]  
Tag处理类 gFeO}otm  
+DW~BS3  
j-4VB_N@  
Tag处理类必须实现Tag接口或BodyTag接口,不过现在一般都流行从TagSupport或BodyTagSupport类中继承,这些类或接口都可以在javax.servlet.jsp.tagext包中找到。 #ZJ _T`l  
h%o%fH&F!  
当JSP引擎看到自己的JSP页面中包含有tag标签时,它会调用doStartTag方法来处理tag标签的开头,调用doEndTag方法来处理tag标签的结束。 3AHlSX  
G! ]k#.^A,  
下表说明不同类型的tag所需要不同的处理过程: WQ~;;.v#  
<Y*+|T+&d  
Tag处理类的方法 v0 nj M  
`_BNy=`s*  
Tag标签类型 fL_4uC i\  
所调用的方法 #^`4DhQ/ 1  
w,.+IV$Kk  
基本标签 ~qcNEl\-y  
doStartTag, doEndTag, release .R) D3NZp  
j|4<i9^}  
带属性的标签 D8inB+/-  
doStartTag, doEndTag, set/getAttribute1...N, release KX76UW   
T m_bz&Q  
带内容的标签 yWg@v +  
doStartTag, doEndTag, release v/Py"hQ  
 J}htu  
带内容的标签,且内容重复循环 3/aMJR:o  
doStartTag, doAfterBody, doEndTag, release Hc!  mB  
?+_Gs;DGVE  
带内容的标签,且内容与JSP交互 txJr;  
doStartTag, doEndTag, release, doInitBody, doAfterBody, release dU6ou'p f  
,p4&g)o  
一个tag处理类可以通过javax.servlet.jsp.PageContext来与JSP交互,通过javax.servlet.jsp.PageContext类,tag处理类可以访问JSP中的request、session和application对像。 |*oZ _gI  
WB?jRYp  
如果tag标签是互相嵌套的,那内层的tag处理类可以通过它的parent属性来访问上层的tag处理类。 NE"@Bk cm  
xO$lsZPG  
一般情况都将所有的tag处理类打成了JAR的包,以便于发布。 $:cE ^8K  
9*2[B"5  
C\3y {s  
Tag库描述(简称TLD) MC?,UDNd%  
gcE|#1>  
#D<C )Q  
Tag库是用xml语言描述的,TLD包括了tag库中所有tag标签的描述,它一般用来被jsp服务器用来校验tag的语法正确性,或者被jsp开发者用来开发新的标签。 bP8Sj16q  
nc~F_i=  
TLD的文件扩展名必须为.tld,而且必须放在当前WEB应用的WEB-INF目录或其子目录中。 s:OFVlC%\  
o}$XH,-9&  
一个TLD的内容的开头必须遵守标准的XML开头,用于描述DTD和xml的版本,例如: aK&b{d  
 W,4QzcQR  
<?xml version="1.0" encoding="ISO-8859-1" ?> '= _/1F*q  
!2 LCLN\  
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd"> NMW#AZVd  
TLD必须以<taglib>来作为它的根元素,<taglib>的子元素如下表: kjW+QT?T&  
DQNnNsP:M-  
8}c$XmCM  
<taglib>的子元素 ?{\nf7Y  
| h`0u'#  
Element {HL3<2=o  
Description ZRv*!n(Ug<  
u6M.'  
tlib-version g$7{-OpB  
Tag库的版本 c]$i\i#  
qHsUP;7  
jsp-version FYOD Upn  
Tag库所需要的jsp的版本 , `wXg  
pM^9c7@!:  
short-name Y&[1`:-~-  
助记符,tag的一个别名(可选) 3 ;)>Fs;  
:}yi -/_8!  
uri |M>eEE*F<  
用于确定一个唯一的tag库 6BY-^"W5`  
oeKHqP wg  
display-name K\>tA)IPSV  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) kd=GCO  
XUM!Qv  
small-icon VcAue!MN  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) _.>QEh5"5  
k ]W[`  
large-icon aiQ>xen5C5  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) YCdS!&^UN  
9iXeBC  
description G3{Q"^S"  
对tag库的描述(可选) ,/YF-L$(t  
BS /G("oZ[  
listener mYxuA0/k  
参见下面listener元素 il}%7b-  
-mC0+}h  
tag w3#Wh|LQ-  
参见下面tag 元素 IN4=YrM^  
s4G|_==  
Listener元素 nnCG g+l  
~1cnE:x;V  
一个tag库可能定义一些类做为它的事件侦听类,这些类在TLD中被称为listener 元素,jsp服务器将会实例化这些侦听类,并且注册它们。Listener元素中有一个叫listener-class的子元素,这个元素的值必须是该侦听类的完整类名。 R#xCkl-  
'Hc-~l>D  
Tag元素 lwHzj&/ ~  
&yGaCq;0  
每个tag元素在tag库中都要指出它的名字、类名、脚本变量、tag的属性。其中脚本变量的值可以直接在TLD中定义或通过tag附加信息的类来取得。每个属性描述了这个属性是否可以省略,它的值是否可以通过<%= …%>这样的JSP语法来获得,以及属性的类型。 $h^wG)s2P  
_6O\W%it  
每一个tag在TLD中对应一个tag元素,下表是tag元素的子元素: |s)Rxq){"V  
L>MLi3{  
Tag元素的子元素 ,O.3&Nz,c  
CJ(NgYC h  
元素名称 0FGe=$vD  
描述 Uh.oErHQD  
HqI t74+  
name hD\rtW  
独一无二的元素名 2GFLnz  
`o<' x.I  
tag-class =2[7 E  
Tag标签对应的tag处理类 lFa02p0  
z8{a(nKP  
tei-class =6woWlfb  
javax.servlet.jsp.tagext.TagExtraInfo的子类,用于表达脚本变量(可选) F4It/  
W^fuScG)c  
body-content ">~.$Jp_4  
Tag标签body的类型 >G);j@Q  
g1XZ5P} f  
display-name S7=Bd[4  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) q+P|l5_ t  
aT_&x@x  
small-icon >fe- d#!{  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) umD!2 w  
Fp@TCPe#  
large-icon 6^uq?  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) {88)~  
eyefWn&  
description kdCUORMK  
此tag标签的描述 fYp'&Btb]x  
D|@/yDQ  
variable J%x6  
提供脚本变量的信息(同tei-class)(可选) xm%Um\Pb7  
D<|qaHB=  
attribute e "/;7:J5\  
Tag标签的属性名 ;epV<{e$q4  
FQT~pfY  
以下章节介绍对于不同类型的tag,如何具体地实现它们。 dA@'b5N{"  
&$"i,~q^b  
W.z;B<  
简单的tag !vX D  
yMyE s8  
7G.#O}).b  
tag处理类 *&?c(JU;<  
` jzTmt  
简单的tag处理类必须实现Tag接口的doStartTag和doEndTag方法。当jsp引擎碰到tag标签的开头时,doStartTag被调用,因为简单的tag没有body,所以此方法将返回 SKIP_BODY。当jsp引擎碰到tag标签的结尾时,doEndTag被调用,如果余下的页面还要被计算,那它将返回EVAL_PAGE,否则将会返回SKIP_PAGE。 /b]oa !  
vLR~'" `F  
以下是例子:对于标签 <tt:simple /> ,它的tag处理类实现如下: *\=.<|HZ  
h]og*(  
.{ 44a$)  
public SimpleTag extends TagSupport *F ? 8c  
M>&%(4K  
{ A:aE|v/T&  
:/:.Kb  
public int doStartTag() throws JspException #k_HN}B  
$Z|ffc1  
{ fQ/ 0R  
hQ]H /+\  
try{ =0^Ruh  
HFwN  
pageContext.getOut().print(“Hello.”); H2Z1TIh  
]?3un!o3o  
}catch(Exception e){ 4Fp0ZVT  
&C_' p{G  
throw new JspTagException(“SimpleTag: “ + e.getMessage()); ~vXaqCX  
4D[ '^q  
} ZQ)>s>-  
Yu?95qktP  
return SKIP_BODY; ^&bRX4pYo  
vr0WS3  
} , #U .j  
5O~HWBX.  
public int doEndTag() Mr?Xp(.}G  
j6>.n49_  
{ .u:81I=w(  
r) $+   
return EVAL_PAGE; (4'$y`Z  
'rMN=1:iu"  
} M&N B/  
<@}I0  
} } @K FB  
hF@Gn/  
pX&pLaF  
注意:如果tag标签没有内容的话,那必须定义body-content元素为空,例如 LEW'G"+  
*g y{]  
<body-content>empty</body-content> $ "E).j  
8wVY0oRnU  
uHAT#\m:  
带属性的tag标签
评价一下你浏览此帖子的感受

精彩

感动

搞笑

开心

愤怒

无聊

灌水
级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
只看该作者 1 发表于: 2007-01-01
tag处理类 AZa 6 C w  
TUHi5K  
对于tag标签的每个属性,你必须依照JavaBeans规范来定义其属性,以及get和set方法。以struts的logic:present 标签为例, wD68tG$  
\[gReaI  
<logic:present parameter=”Clear”> {?J/c{=/P  
HPb]Zj  
与此相应,此tag处理类应有如下方法和定义: ,$'])A?$  
Ps%qfL\  
NZ/yBOD(  
protected String parameter = null; J9\a{c;.  
Pcu#lWC$  
public String getParameter() $aN-Y?U%  
N@Y ljz|  
{ TF 'U  
<$F\Nk|x  
return this.parameter; yY[<0|o u  
fv`O4  
} taFn![}/!g  
s<9RKfm  
public void setParameter(String parameter) 5B&;uY  
C?i >.t  
{ _~q?_'kx  
v^zu:Z*  
this.parameter = parameter; p/U+0f  
bYi`R)  
} +)j1.X  
h$.:Uj8/  
9lGOWRxR)  
注意:如果你的属性名为id,而且你的tag处理类是从TagSupport类继承的,那你就不需要定义它的属性和set和get方法,因为他们早已在TagSupport被定义过了。 jM$`(Y  
abJ" [  
Attribute元素 AJSx%?h:6  
O~59FuL  
对于tag标签的每个属性,你必须定义它是否必须的,它的值是否可以用诸如<%= …%>的表达式来获得,以及它的类型(可选),如果不指定它的类型,那就默认为是java.lang.String类型。如果rtexprvalue元素被定义为true或yes,那么在type元素中就定义了attribute的返回类型。 +T=(6dr  
rg{9UVj  
<attribute>  ?p(/_@  
5v?;PX  
<name>attr1</name> ;x:rZV/  
;=<-5;rI  
<required>true|false|yes|no</required> [8Qro8  
q^A+<d  
<rtexprvalue>true|false|yes|no</rtexprvalue> ' Hi : 2Wh  
W-.pmU e2  
<type>attribute的返回类型(只用当rtexprvalue为真是才有效)</type> {}QB|IH`  
-S$1Yn  
</attribute> 8me ]JRw  
$&<uT  
如果tag的某个属性不是必须的,那tag处理类会自动提供一个缺省值。 j'aHF#_  
+V{7")px6  
例如,在logic:present这个tag标签中定义了一个属性叫parameter,但它不是必须的,而且它可以被诸如<%= …%>的表达式来赋值。 8E4mA5@   
"=6v&G]U4  
<tag> E\IlF 6  
n+BJxu?  
<name>present</name> 3/b;7\M  
+,yK;^b  
<tag-class>org.apache.struts.taglib.logic.PresentTag</tag-class> OM|Fwr$  
.Wq@gV  
<body-content>JSP</body-content> : C b&v07  
AgRjr"hF*e  
1fo U  
rp6q?3=g  
<attribute> j6  
jMbC Y07v  
<name>parameter</name> o$[z],RO  
!!4Qj  
<required>false</required> V^hE}`>z&  
E[O<S B I  
<rtexprvalue>true</rtexprvalue> n @?4b8"  
_:X|.W  
</attribute> p|Q*5TO  
"Vr[4&`  
G NS`.fS  
+8v9flh  
</tag> V\})3i8  
8ZCoc5  
P ~#>H{  
属性元素的校验 etoo #h"]1  
Qc[3Fq,f  
/sr2mt-Q  
有关于tag标签的有效值可以从tag库的说明文档中获得,当JSP页面被编译时,jsp引擎会强制性地参照TLD中定义的规则进行检查。 E;d7ch  
"wlt> SU  
还有一个方法也可以进行属性元素的校验,就是先继承类TagExtraInfo,然后调用它的isValid方法。这个类同时也起到提供tag中定义的脚本变量信息的作用。  )@ ~J  
n.sbr  
IsValid方法通过TagData对象来传递属性信息,它包括着tag的所有的属性名-值的信息。由于校验发生在运行时刻,因此这个属性的值将被赋值为TagData.REQUEST_TIME_VALUE。 2P]L9'N{Y  
zNY)'  
例如tag标签<tt:twa attr1=”value1” />在TLD中定义如下: <\0vR20/  
}lK3-2Pk  
<attribute> Ja SI^go  
_DrJVC~6@  
<name>attr1</name> r?CI)Y;  
? tfT8$  
<required>true</required> 7HVZZ!>~  
`\X+ Ud|  
<rtexprvalue>true</rtexprvalue> _:+ KMR  
`+t.!tv!  
</attribute> CiR%Ujf  
<$N"q  
GZ{]0$9I'  
这个定义说明了attr1能在运行期间被赋值。  PlYm&  
?=VOD#)  
以下的isValid方法检查attr1属性的值是否属于Boolean类型。注意由于attr1能在运行刻被赋值,那么isValid方法必须检查tag用户是否对此tag进行了运行时刻赋值。 W5^.-B,(K  
{QbvR*gv  
[xh*"wT#g  
Public class TwaTEI extends TagExtraInfo =?h~.lo  
QI]Ih  
{ SxK:]Aw  
~2d:Q6  
public boolean isValid(Tagdata data) k|BHnj  
vA)O {W\o  
{ k8,?hX:  
cEe? *\G  
Object o = data.getAttribute(“attr1”); *cTO7$\[  
8 4i_k  
If(o != null && o != TagData.REQUEST_TIME_VALUE) 3+J0!FVla  
v|ox!0:#  
{ w'X]M#Q><  
oo=#XZkk  
if( ( (String)o).toLowerCase().equals(“true”) || *_ +7ni  
Gn)y> AN  
((String)o).toLowerCase().equals(“false”) ) "lNzGi-H  
tA$)cg+.  
return true; ~^ ^ NHq  
.)|a2d ~F  
else G pbC M~x  
|0{u->+ )  
return false; jKZt~I  
Y F:2>w<  
} h;V,n  
w[_x(Ojq;  
else =SD\Q!fA  
y fSM  
return true; WZ!WxX>zO  
- O"i3>C  
} yAL1O94  
]NhS=3*i+  
} fWF |,A>>b  
^). )  
D;Gq)]O  
带body的tag OzT#1T1'c  
Dml*T(WM>  
{F N;'Uc  
tag处理类 iqhOi|!  
G5D2oQa=8  
CK_(b"  
如果tag标签含有内容,那处理方式会略微有些不同,而且还要视tag处理类是否要与body交互的情况而定。如果要与body交互,那我们认为tag处理类要可能要对body进行操作。 /D_+{dtE  
!3oKmL5  
Tag处理类不与body交互 $KjTa#[RX7  
^MD;"A<  
如果tag处理类不与body交互,tag处理类应该实现Tag接口或从TagSupport中派生,如果body要被计算,那么doStartTag方法应返回 EVAL_BODY_INCLUDE,否则应返回SKIP_BODY。 19(Dj&x  
Fg/dS6=n`?  
如果tag处理类要对body反复运算,则它应该实现IterationTag或从TagSupport中派生。如果tag处理类认为body还未计算完的话,那它的doStartTag方法和doAfterBody方法必须返回EVAL_BODY_AGAIN。 wA`"\MWm  
wFlvi=n/  
Tag处理类与body交互 e75UMWaeC  
j<pw\k{i  
如果tag处理类与body交互,那tag处理类应实现BodyTag接口或从BodyTagSupport中派生。这种tag处理类一般要实现doInitBody和doAfterBody方法。 AGYm';z3  
,}xbAA#  
Body允许一些方法来读写它的内容。Tag处理类可以调用body内容的getString或getReader方法来从body中提取信息,也可用 writeOut(out) 方法来将body的内容写入到out对象中。其中out对象通过tag处理类的getPreviousOut方法来获得。 P6Bl *@G  
9Q W&$n^  
如果body的内容需要被计算,那么doStartTag方法必须返回EVAL_BODY_BUFFERED,否则,它将返回 SKIP_BODY。 kC$&:\Rh  
u)Q;8$`  
doInitBody 方法 )a=/8ofe  
^D@b;EyK  
此方法在body内容已经设好,但未被计算之前被调用。你可以根据不同的body内容来制定初始化策略。 ;r=b|B9c  
BO.dz06(Rw  
doAfterBody方法 f>$h@/-*  
&~B5.sppnB  
此方法在body内容已被计算后进行调用。 ]%RNA:(F'  
P&*sB%B  
和doStartTag方法一样,doAfterBody方法返回一个指示符指示是否要继续计算body,如果要继续计算,则doAfterBody应返回EVAL_BODY_BUFFERED,否则,它应返回SKIP_BODY。 %;z((3F  
IGFGa@C  
release 方法 I~'*$l  
ZX b}91rzt  
tag处理类调用此方法将它的状态重置为初始状态,并释放所有的私有资源。 -Uo?WXP]B'  
o@lWBfB*%e  
5 waw`F  
以下的例子读取body的内容(其中含有一条sql语句),然后将它传递给一个对象,让它进行查询。由于此处body不须重新计算,所以doAfterBody会返回SKIP_BODY。 ,]Zp+>{  
}8'&r(cN4  
|0bc$ZY:  
Public class QueryTag extends BodyTagSupport <Wl(9$  
,/&Zw01dGN  
{ }tST)=M`  
^T4Ay=~{  
public int doAfterBody() throws JspTagException ;52'}%5  
Jf:,y~mV  
{ %@ mGK8  
<XQ.A3SG!  
BodyContent bc = getBodyContent(); c\cZ]RZ  
d]0a%Xh[  
//将body的内容以字符串的格式提取出来 W( *V2<$o  
Em13dem  
String query = bc.getString(); N~=A  
7N2\8kP  
//清除body Q"J-tP!  
:ipoD%@  
bc.clearBody(); m4ApHM2  
NB8&   
try{ ul5|.C  
!)NidG  
Statement stmt = connection.createStatement(); ]Ql 0v"` F  
OCyG_DLT$5  
Result result = stmt.executeQuery(query); !UV5zmS  
J/D|4fC  
}catch(SQLException e){ ),@f6](  
/k:$l9C[  
throw new JspTagException(“queryTag: “ + e.getMessage() ); 83 ]PA<R  
'bW5Fr>W  
return SKIP_BODY; ]]iO- }  
qFR dg V>8  
} 96|[}:+$&:  
cep$_J a  
} ~waNPjPRG  
M<8ML!N0;t  
)JgC$ <  
body-content元素 eE:&qy^  
LhJa)jFQ  
Z/ bB h  
由于tag可能会有body,你必须用body-content元素来指定body内容的类型: ysXx%k  
B0mLI%B  
<body-content>JSP|tagdependent</body-content> gb-{2p>}  
Yx?aC!5M  
-rY 7)=  
如果body的内容是定制的或内部的tag、脚本元素、或HTML广本,则归类为JSP类型。其他的类型,比如上面代码所述的?D?D将sql statement类传给 query tag的这种类型应该标为tagdependent。 s_wUM)!  
J?712=9  
注意:实际上body-content的值并不影响tag处理类对body内容的处理,它仅仅是被tag编辑工具用来描述此body的内容。 2P~)I)3V  
sy<iKCM\  
ahIE;Y\j'  
用tags定义脚本变量 mVH,HqsXa  
H:oQ  
SX+RBVZU  
tag处理类 H/cTJ9zz  
h_ ! >yK  
Q .RO  
tag处理类负责创建或设置页面中定义的脚本变量,用pageContext.setAttribute(name,value,scope)或pageContext.setAttribute(name,value)方法来实现。一般来说,tag处理类通过脚本变量的名称来获取它,脚本变量的名称一般可用get方法来获得。 jMpa?Jp1  
SN]LeXesS  
如果脚本变量的值依赖于tag处理类中的上下文中某一对象,那它可用pageContext.getAttribute(name,scope)方法来找到那个对象。一般的处理过程是tag处理类先找到脚本变量,再对其进行处理,然后用pageContext.setAttribute(name,object)的方法来设置它的新值。 ,jh~;, w2  
-l*A  
对象的生存周期(scope)如下表: \aSz2lxEHn  
ZCiY,;c  
对象的生存周期表 oKKz4  
Pern*x9$  
名字 {sc[RRN~C  
可访问范围 3o8\/-*<  
生存周期 Y)p4]>lT+8  
Gbb \h  
page INNAYQ  
当前页面 f]_mzF=&  
一直有效,除非页面向客户提交响应或重定向到一个新页面 lmFA&s"m  
F1u)i  
request #\FT EY!  
当前页面或当前页面重定向到的页面 Q-('5a19J  
一直有效,除非页面向客户提交响应 pt!'v$G/*  
3IyZunFT  
session Pz~q%J  
当前页面或在同一浏览器窗口中的页面 H7e /  
一直有效,除非关闭当前浏览器、超时、网络故障 ?JqjYI{$  
v}`1)BUeF  
application 9m!7|(QV  
整个web应用程序的所有请求 |cTpw1%I~  
一直有效,除非发生网络故障、服务器故障 ' iQ9hQjD  
G=$}5; t  
提供关于脚本变量的信息 3V-6)V{KaE  
cf*zejbw  
以下示例定义了一个名为“book”的脚本变量,用来访问程序中关于书的信息: 9)ea.Gu  
{e9Y !oFg  
<bean:define id=”book” name=”bookDB” property=”bookDetails” type=”database.BookDetails” /> L+R >%d s  
vfbe$4mH  
<font color=”red” size=”+2” > TA)LPBG  
k^*$^;z  
<%= messages.getString(“CartRemoved”) %> 1X:&* a"5  
h3 @s2 fK  
<strong><jsp:getProperty name=”book” property=”title” /></strong> p{C9`wi)  
=R9*;6?N  
</font> T|+$@o  
R+Lk~X^*l'  
当包含此tag的JSP页面被编译时,jsp引擎会自动生成关于此book的同步的代码(同步可以避免几个客户同时访问此book时造成的冲突),要生成同步代码,jsp引擎需要知道此脚本变量的如下信息: >l2w::l%  
>UN vkQ:  
· 脚本变量名称 hWxT!  
84Zgo=P}  
· 脚本变量所属的类 'G Y/Q5  
8A/>JD3^  
· 此脚本变量是否引用了一个新的或已存在的对象 ;Q90Y&{L=$  
TcZN %  
· 此脚本变量的有效性 H-a^BZ&iU  
-A;w$j6*  
有两种办法可以向jsp引擎提供关于脚本变量的信息:在TLD中定义variable子元素,或用tei-class子元素定义一个额外tag信息类。用variable最简单,但可能降低了一些灵活性。 "^"'uO$  
@XBH.A^7r  
Variable元素  q)oN 2-  
E\! n49  
Variable元素有如下子元素: !3x *k;0  
ewQe/Fq  
· name-given ?D?D 给出的名字,是一个常量 ,>w}xWSYpG  
xMsGs  
· name-from-attribute?D?D 属性名,在编译时给出的属性名 nP u`;no  
+2yF|/WW#  
name-given或name-from-attribute两者必须选一,但以下子元素是可选的: "WP% REE!  
QK7e|M  
· variable-class?D?D变量的类型,缺省为java.lang.String。 =h[yA f  
7vNtv9  
· declare?D?D此脚本变量是否引用了一个新对象,缺省为True。 @\$Keg=>:  
`,m7xJZ?y  
· scope?D?D脚本变量的范围,缺省为NESTED。下表描述了scope的几种类型: xppkLoPK  
;+9(;  
脚本变量的有效范围 EE9vk*[@C  
K P6PQgc  
`oPLl0  
有效性 -pX|U~a[  
方法 jJ-d/"(  
V0T<eH<  
NESTED oT!/J  
在tag标签的开始和结束之间 :p$EiR  
如果tag处理类实现BodyTag接口,则在doInitBody和doAfterBody中调用,否则在doStartTag中调用 D"`[6EN[  
] umZJZ#Y  
AT_BEGIN F,.Q|.nN  
从tag标签的开始一直到页面结束 *I/A,#4r  
如果tag处理类实现BodyTag接口,则在doInitBody、doAfterBody和doEndTag中调用,否则在doStartTag和doEndTag中调用 $owb3g(%4  
& qL<C  
AT_END #'iPDRYy  
从tag标签的结束一直到页面结束  Q>[Ce3  
在doEndTag中调用 X\'E4  
$2is3;h  
以struts为例,它的bean:define标签的实现遵循JSP1.1规范,此规范要求使用额外tag信息类来定义脚本变量。Variable元素是JSP1.2规范中加入的。以bean:define标签为例,你可以定义如下variable元素: \ %_)_"Q  
4JSZ0:O  
<tag> d/4ubf+$k  
)^(P@D.L  
<variable> 6d};|#}  
k%!VP=c4s  
<name-from-attribute>id</name-from-attribute> v*XkWH5  
h,.fM}=H  
<variable-class>database.BookDetails</variable-class> OsB?1;:  
soxfk+ 9  
<declare>true</declare> 6~3jn+K$1  
H.9yT\f.  
<scope>AT_BEGIN</scope> }M?|,N6  
{YBl:rMz  
</variable> 'DeW<Sa~  
a>?p.!BM  
</tag> LhZZc`|7t  
YPG,9iZ&f  
额外tag信息类 <oZ(ng@X  
A$N+9n\  
如果要定义一个额外tag信息类,你要继承javax.servlet.jsp.TagExtraInfo类。一个TagExtraInfo类必须实现getVariableInfo方法,此方法返回一个叫VariableInfo的数组类,它包括如下信息: oL)lyUVT  
&p )@8HY  
· 变量名 1oB$u!6P  
LVoyA/ F  
· 变量所属类名 $)l2G;&  
>mew"0Q  
· 此变量是否引用了一个新对象 KZZOi:  
bu_/R~&3{  
· 此变量的有效范围 YV4 : 8At1  
:+<t2^)rD  
jsp引擎将一个名为data的参数传给getVariableInfo方法,data中包括tag标签中的所有“属性名?D?D属性值”对。它可以用来向VariableInfo对象提供脚本变量的名字和类名。 EZ*t$3.T  
Dl&PL  
以struts为例,它在bean:define标签中定义了一个名为DefineTei的额外tag信息类,用来向脚本变量提供信息。由于脚本变量的名称(book)和类名(database.BookDetails)是通过tag标签的属性来传递的,它们一般定义在VariableInfo的构建代码中,并且可用data.getAttributeString方法来得到这些信息。如果要允许book脚本变量能在从tag开始直到整个JSP页面结束的范围内都可用的话,那它的范围应设为AT_BEGIN。如下所示: x g{VP7  
U-1VnX9m  
@OY1`Eu O  
public class DefineTei extends TagExtraInfo nZ541o@t9  
(;C$gnr.C  
{ JR!Q,7S2!N  
T<XfZZ)l<`  
public VariableInfo[] getVariableInfo(TagData data) 8F\~Wz7K  
m'3OGvd  
{ [#7D~Lx/  
F68},N>vr@  
String type = data.getAttributeString(“type”); ruzMag)  
"-28[a3q  
If( type == null) T\)dt?Tv#\  
5"$e=y/  
type = “java.lang.Object”; ~37R0`C  
48H5_9>:  
return new VariableInfo[] { loR,XW7z  
)CFk`57U  
new VariableInfo(data.getAttributeString(“id”), +jv }\Jt  
=obt"K%n  
type, PIgGXNo  
3,%nkW  
true, 9) jo7,VM  
@>+^W&  
VariableInfo.AT_BEGIN) .zQ4/  
; A x=]Q  
}; =jsx (3V   
ZUv ZN f  
} =kwb` Z/a  
7Y%!,ff  
} 3L?WTS6(u  
!?S5IGLOj  
FK-}i|di  
注意:关于额外tag信息类的类名必须要在TLD中的tag标签下的tei-class子元素中定义。因此,DefineTei的tei-class中的定义看起来如下: wEZ,49  
<tei-class> >-UD]?>  
org.apache.struts.taglib.bean.DefineTagTei BvSdp6z9Iv  
</tei-class> \)uy"+ Z`  
7E;>E9 '  
$,}Qf0(S  
具有协作关系的tag &"sX^6t  
r(PJ~8)(=  
*Ro8W-+  
tag通过共享对象来进行协作,JSP技术支持2种方式的对象共享。 XCW+ pUX  
( P  
第一种方法是使用pageContext对象进行对象的共享(可支持JSP页面和tag处理类之间的共享),如果在一个tag处理类中要调用由另一个tag处理类创建的对象,可调用pageContext.getAttribute(name, scope)方法。 v!nm &"  
N-]\oMc2  
第二各方式的共享是对于tag之间有嵌套关系而言的,外层的tag所创建的对象对于内层的tag来说是可以共用的。这种形式的共享的好处是减少了可能存在的重名冲突。 N9`y,Cos0  
X@i+&Nv"<  
要访问一个嵌套tag创建的对象,tag处理类必须先找到此嵌套tag对象,可用TagSupport的静态方法 TagSupport.findAncestorWithClass(from, class)或TagSupport.getParent方法。前者在当不确定此tag是否为嵌套tag对象时使用。一旦它的父类被找到,它就能访问其所有动态或静态创建的对象。静态创建的对象是父类的成员,而动态创建的对象可能是父类的私有对象。诸如此类的对象可以用tag处理类的setValue方法来保存,用getValue方法来获得。  =|^X$H  
'Na|#tPYI  
下例阐述了以上两种共享对象的方法。在这个例子当中,一个查询tag检查一个名为connection的属性名是否在doStartTag中被设置。如果connection属性被设置,tag处理类从pageContext中得到这个connection对象。否则,此tag处理类先找到它的父tag处理类,然后从它的父tag处理类中找到connection对象。 (qNco8QKu3  
U p_>y>x  
Ngn\nkf  
public class QueryTag extends BodyTagSupport I/u'bDq  
#Y/97_2 xa  
{ 2qt=jz\s  
qPp1:a"   
private String connectionId; 0Ei\VVK>  
LBW.*PHW  
public int doStartTag() throws JspException z~GVvgd  
e_YW~z=6t  
{ ^nG1/}  
J& 1X  
String cid = getConnection(); \/? ! 6~  
sZ0g99eX  
if(cid != null) _JfJ%YXy  
l*~"5f03  
{ ~+sne7 6 U  
j:3A;r\  
//存在一个connection id,使用它。 ]$*$0  
HY*l4QK  
connection = (Connection) pageContext.getAttribute(cid); Q3 K;kS  
k/$Ja;  
} SS >:Sw  
h<PYE]?l  
else ]s1TJw [B  
4U}.Skzq  
{ cRs{=RGc  
'?&B5C  
ConnectionTag ancestorTag = (ConnectionTag)findAncestorWithClass(this, 'e+-,CGdY\  
{LR#(q$1  
ConnectionTag.class); daaga}]d  
U)&H.^@r$  
if(ancestorTag == null) $M:4\E5(  
Z\ "Kd  
{ 3MS3O.0]/  
j<. <S {  
throw new JspTagException(“一个没有connection属性的查询标签必须被一个connection标记嵌套。”); !Ei Ze.K  
@ef//G+Z"  
} \#h})`  
*Y| lO  
connection = ancestorTag.getConnection(); V Z4nAG  
mafAC73  
} fS;m+D!j@  
avYh\xZ  
} n?TO!5RZK  
;XD>$t@  
} IqR[&T)lj  
O3sla bE#  
Yke<Wy1  
{[(W4NAlH  
此查询标签在JSP页面中的调用形式可以从以下2种定义中任选一种: \t&n jMWpZ  
0lvb{Zd  
R47I\{  
<tt:connection id=”con01” ...> ... </tt:connection> LH?gJ8`  
oT9XJwqnv  
<tt:query id=”balances” connection=”con01” > MY0[Oq cm=  
+oxqS&$L  
SELECT account, balance FROM acct_table FvtM~[Q  
jk WBw.(  
where customer_num = <%= request.getCustno() %>  RU3_Fso  
"GIg| 3  
</tt:query> [4V|UvKz  
VNOK>+  
VfJX<e=k  
J.CZR[XF#  
zD#+[XI]K  
<tt:connection ...> XY$cx~  
=6"hj,[Q  
<x:query id=”balances”> ynOc~TN  
)VSGqYr#  
SELECT account, balance FROM acct_table _zVbqRHlw  
g*"J10hyP  
where customer_num = <%= request.getCustno() %> y$;zTH_6j  
3V8j>&  
</x:query> 7+A-7ci  
_S%OX_UMn^  
</tt:connection> \k$]GK-  
.PA ?N{z  
-Y!=Iw 4  
与此同时,在TLD中必须指定connection属性为可选的,定义如下: t&p:vXF2  
$yR{ZFo  
<tag> @eG#%6">  
^YB\\a9  
... T^f&58{ 7  
0X}w[^f  
<attribute> !Cv<>_N).  
[8om9 Z3  
<name>connection</name> BhhK| U/  
.[eSKtbc)  
<required>false</required> FHnHhB[  
$yxIE}  
</attribute> CO6XIgTe  
zL[U;  
</tag>
描述
快速回复

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