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

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

级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
标准的JSP 标记可以调用JavaBeans组件或者执行客户的请求,这大大降低了JSP开发的复杂度和维护量。JSP技术也允许你自定义taglib,其实换句话说,taglib可以看成是对JSP标记的一种扩展,正如xml是对html的一种扩展一样。taglib通常定义在tag标签库中,这种标签库存放着你自己定义的tag标签。简而言之,如果使用taglib,那么你可以设计自己的JSP标记! 2@(Qd3N(  
vh~:{akR  
一般来说,自定义tag标签主要用于操作隐藏对象、处理html提交表单、访问数据库或其它企业级的服务,诸如邮件和目录操作等等。自定义tag标签的使用者一般都是那些对java编程语言非常精通,而且对数据访问和企业级服务访问都非常熟悉的程序员,对于HTML设计者来说,使得他可以不去关注那些较复杂的商业逻辑,而将精力放在网页设计上。同时,它也将库开发者和库使用者进行合理分工,自定义tag标签将那些重复工作进行封装,从而大大提高了生产力,而且可以使得tag库可用于不同的项目中,完美地体现了软件复用的思想。 Q7]VB p4  
I oz rZ  
在这篇文章中,我们主要讨论: ;b""N,  
+P~E54  
· 什么是自定义tag标签? @a1+  
?'_Q^O>  
· 怎么使用tag标签? z5CWgN  
q?=eD^]  
o 声明要使用的tag库 c !ybz{L  
"/)}Cc,L  
o 找到与之对应的tag处理类 z.9 #AN=&[  
AID}NQ Qj_  
o tag标签的类型 "KY9MBzPD  
?`hk0qX3  
· 自定义tag标签 o 6$Q>g`]  
3f{%IU(z  
o tag处理类 .g7ebh6D  
"Iy @PR?>  
o tag库描述 p[QF3)9F  
su`] l"[,]  
o tag标签示例 .>-`2B*/  
G B+U>nf  
o 带属性的tag U+!H/R)(  
R,hX *yVq  
o 带body的tag 2S1wL<qP  
xi6Fs, 2S  
o 定义了脚本变量的tag lrSo@JQ  
Sdc;jK 9d!  
o 具有协作关系的tag $+Hv5]/hb  
5Dy800.B2  
· 自定义tag标签 ")U`Wgx  
-4JdK O  
o 一个迭代tag的例子 9Q".166  
>s E5zj|V  
o 一个模板tag库 wR;_x x  
T x_n$ &  
o tag处理类到底是怎样被调用的? P]Z}% 8^O  
<dTo-P  
;X u&['  
什么是自定义的tag? )T6+}   
Riq5Au?*)  
一个自定义的tag标签是用户定义的一种JSP标记。当一个含有自定义的tag标签的JSP页面被jsp引擎编译成servlet时,tag标签被转化成了对一个称为tag处理类的对象进行的操作。于是当JSP页面被jsp引擎转化为servlet后,实际上tag标签被转化成为了对tag处理类的操作。 I3xx}^V  
2#nn}HEOC  
自定义tag标签有很多特色,诸如: n8zh;vuJ  
OC'cP[$ _  
· 可以在JSP页面中自定义tag标签的属性 1rV?^5  
{PHxm  
· 访问JSP页面中的所有对象 3<x_[0v`K1  
p&F=<<C  
· 可以动态地修改页面输出 P X](hc=  
P 7 [p$Z  
· 彼此这间可以相互通信。你可以先创建一个JavaBeans组件,然后在一个tag中调用此JavaBeans组件,同时可以在另一个tag中调用它。 g]C+uj^  
g eaeOERc  
· tag允许相互嵌套,可以在一个JSP页面中完成一些复杂的交互。 snTj!rV/_  
%Gn(b 1X  
35yhe:$nf  
使用tag标签 AZ5c^c)  
#Dx$KPD  
EIl _QV6  
本节主要描述怎样在JSP页面中使用tag标签,以及tag标签的不同类型。 a%f5dj+  
T7YzO,b/   
要使用tag标签,JSP程序员必须做2件事: VGBL<X  
SZ-%0z  
· 声明此tag标签的tag库 6^zuRY;  
R|{6JsjG10  
· 实现此tag标签 -aGv#!aIl  
Dj>.)n  
声明tag标签所在的tag库 H7)(<6b,z  
&adKKYN  
如果要使用tag标签,则应用JSP的taglib指示符来指定其tag库(注意:taglib要在在使用此tag标签之前声明) hHoc7  
#]I:}Q51  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> G%anot  
Y 3[<  
uri属性定义了唯一的标签库描述(以下简称TLD),它可以是直接是tld文件名或一个独一无二的名字。prefix是用来区别其它TLD中和本TLD中有重名的tag的一种手段。 WJ\YKXG  
(@`+Le  
TLD必须以.tld作为扩展名,并且存放在当前应用的WEB-INF目录或其子目录下。你可以通过它的文件名直接引用它,也可以通过别的方式间接地引用它。 *#EyfMz-B  
!.iA^D//]  
以下taglib指示符直接引用一个TLD: qwA: o-q"  
[HIg\N$I8C  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> G <m{o  
xJ%b<y{@  
以下的taglib指示符通过一个逻辑名称间接地引用一个TLD: h vGb9  
yq[C?N &N  
<%@ taglib uri=”/tutorial-template” prefix=”tt” %> LP_ !g  
>'Nrvy%&0  
如果是间接引用TLD的话,那你必须还要在web.xml中定义此逻辑名称与tld文件之间的映射,具体做法是在web.xml中加入一个名为taglib的元素: LPT5d 7K@  
HI']{2p2}t  
<taglib> V )1SZt@x  
L<QqQ"`  
<taglib-uri>/tutorial-template</taglib-uri> W3 2mAz;  
V|xR`Q  
<taglib-location> mRfF)  
`EU=u_N  
/WEB-INF/tutorial-template.tld Qo)>i0  
tb&{[|O^  
</taglib-location> j4H,*fc  
O|%><I?I  
</taglib> s qac>v  
<+sv7"a  
#)=P/N1  
实现此tag标签 lGjmw"/C  
) #Y*]  
lh~!cOm\=E  
为了实现tag标签,你有2种方法来存放tag处理类。一、让tag处理类以.class的方式存放于当前应用的WEB-INF/class子目录下,二、如果tag处理类是以JAR包的形式存在的话,那可以放在当前应用的WEB-INF/lib目录下,如果tag处理类要在多个应用中共享,那么它就应放在jsp服务器上的common/lib目录下,对于tomcat来说,就是tomcat/common/lib目录下。 $}W=O:L+D  
;% !'K~  
%S.R@C[3  
tag标签类型 GR O[&;d`  
+n^$4f  
u Dm=W36  
自定义的tag标签遵循XML语法。它有一个开始标记和一个结束标记,有的还有body(即文本节点): &bs/a] ?Z7  
.0.Ha}{6b  
<tt:tag> gGe `w  
F7#   
body Gnj|y?'  
D19uI&U4  
</tt:tag> lXW.G  
WZ@nuK.39T  
*"O7ml]  
一个不带body的tag标签如下: ./[%%"  
O)`R)MQ)  
<tt:tag /> 2@:Go`mg  
gHvxmIG  
l5D8DvJCj  
简单的tag标签 1/6G&RB  
vy1:>N?#5  
一个没有body和属性的tag标签如下: Po(9BRd7  
gAgzM?A1(  
<tt:simple /> rMfp%DMA  
8>6+]]O  
o}7`SYn  
带属性的tag标签 :s$ rD  
0z_e3H{P27  
V8`t7[r  
自定义标签可以有自己的属性。属性一般在开始标记中定义,语法为 attr=”value”。属性的作用相当于自定义标签的一个参数,它影响着tag处理类的行为。你可以在TLD中详细定义它。 MPT*[&\-  
2m[z4V@`  
你可以用一个String常量给一个属性赋值,也可以通过表达式给它赋值,如<%= ...%>。以struts为例,它的logic:present标签就是用的String常量来给属性赋值: & 2>W=h  
+<|6y46  
<loglic:present parameter = “Clear”> z[}[:H8  
=+'4u  
而另一个标签logic:iterate是用表达式来给属性赋值: EFqWnz  
@lDoMm,m'  
<logci:iterate collection=”<%= bookDB.getBooks() %>” -+#\WB{AI  
<8+.v6DCd  
id=”book” type=”database.BookDetails”> ^yu0Veypy  
p_) V@ 7  
.1[K\t)2  
带body的tag标签 :JxShF:M  
m:)v>vu  
一个自定义标签可以包含其它自定义标签、脚本变量、HTML标记或其它内容。 B;2os^*  
# x!47Y{  
在下述例子中,此JSP页面使用了struts的logic:present标签,如果些标签定义了parameter=”Clear”的属性,则将清除购物车的内容,然后打印出一条信息: ^6Hfq^ejt  
yFH)PQ_  
<logic:present parameter=”Clear”> xuv%mjQ  
LylB3BM  
<% cart.clear(); %> ;l7wme8Qk  
kDS4 t?Ig  
<font color=”#ff0000” size=”+2”><strong> j0Kj>  
nRPy)L{  
你选择了清除购物车! [- a2<E  
%'%ej^s-R  
</strong></font> 0}PW<lU-  
(@p E  
</logic:present> #K"jtAm  
!G 90oW  
tl (2=\  
到底是用属性还是用body来传递信息? KArR.o }  
_K_!(]t  
如上所述,我们既可以通过属性,也可以通过body来传递信息。但一般来说,比较简单的类型,如字符串或简单表达式最好采用属性来传递信息。 5nkx8JJ  
 .]k+hc`  
|K,9EM3  
定义脚本变量的tag标签 &Op, ?\   
vjhd|  
所谓脚本变量,是指JSP中可以调用的变量或对象。它可由tag标签产生。以下示例阐述了一个tag标签定义了一个名为tx的由JNDI所定义的事务处理对象。脚本变量可以是ejb对象、事务、数据库连接等等: YRfs8I^rg  
}'b 3'/MJ  
<tt:lookup id=”tx” type=”UserTransaction” name=”java:comp/UserTransaction” /> 7(QRG\G#  
FL,jlE_  
<% tx.begin(); %> kBS;SDl)  
g>1yQ  
... e>#*$4tg  
mawomna  
VL?ubt<  
具有协作关系的tag标签 SWN i@  
zy"L%i  
自定义tag标签之间可以通过共享对象来实现协作。在下述例子中,标签tag1创建了一个名为obj1的对象,在标签tag2仍可以重复使用obj。 {W)Kz_  
4h@jJm  
<tt:tag1 attr1=”obj1” value1=”value” /> (Ub=sC  
N&]v\MjI62  
<tt:tag2 attr1=”obj1” /> M$B9?N6  
_*>bf G  
在以下这个例子当中,如果外层的tag标签创建了一个对象,那么其内层的所有tag标签都可以使用这个对象。由于这样产生的对象没有一个指定的名字,那么就可以将少重名的冲突。这个例子阐述了一系列协作的嵌套对象。 +\fr3@Yc  
=!*e; L  
<tt:outerTag> j#f+0  
N/p9Ws  
<tt:innerTag /> 0k@4;BYu  
&BY%<h0c  
</tt:outerTag> V}. uF,>V  
d(3F:dbk  
X*KQWs.  
Tag处理类 =;W"Pi;*  
.0:BgM  
rjo/-910  
Tag处理类必须实现Tag接口或BodyTag接口,不过现在一般都流行从TagSupport或BodyTagSupport类中继承,这些类或接口都可以在javax.servlet.jsp.tagext包中找到。 D^baXp8  
J}c57$Z  
当JSP引擎看到自己的JSP页面中包含有tag标签时,它会调用doStartTag方法来处理tag标签的开头,调用doEndTag方法来处理tag标签的结束。 wZJpSkcEx  
yM}}mypS  
下表说明不同类型的tag所需要不同的处理过程: #g#vDR!  
WS/^WxRY  
Tag处理类的方法 *p`0dvXG2  
+iz5%Qe<f  
Tag标签类型 5Q#;4  
所调用的方法 J*o :RnB  
I L 'i7p  
基本标签 y>Zvose  
doStartTag, doEndTag, release ! @{rk p  
1P. W 34  
带属性的标签 W=c7>s0>  
doStartTag, doEndTag, set/getAttribute1...N, release Nwr.mtvh  
)@09Y_9r  
带内容的标签 X^r5su?  
doStartTag, doEndTag, release Y9Q-<~\z  
SpPG  
带内容的标签,且内容重复循环 ,24NMv7  
doStartTag, doAfterBody, doEndTag, release zl F*F8>m  
([R}s/)$  
带内容的标签,且内容与JSP交互 ]( V+ qj  
doStartTag, doEndTag, release, doInitBody, doAfterBody, release L-hK(W!8pt  
x|d Xa0=N_  
一个tag处理类可以通过javax.servlet.jsp.PageContext来与JSP交互,通过javax.servlet.jsp.PageContext类,tag处理类可以访问JSP中的request、session和application对像。 Z.am^Q^Y!  
A{iI,IFe  
如果tag标签是互相嵌套的,那内层的tag处理类可以通过它的parent属性来访问上层的tag处理类。 8/,m8UOY  
uSLO"\zysX  
一般情况都将所有的tag处理类打成了JAR的包,以便于发布。 ! E` Tt[  
vA2@Db}  
9uV/G7Geq  
Tag库描述(简称TLD) \(Dq=UzQI  
xphw0Es  
(# Z2  
Tag库是用xml语言描述的,TLD包括了tag库中所有tag标签的描述,它一般用来被jsp服务器用来校验tag的语法正确性,或者被jsp开发者用来开发新的标签。 7}OzTup  
Fvf308[  
TLD的文件扩展名必须为.tld,而且必须放在当前WEB应用的WEB-INF目录或其子目录中。 k_/hgO  
IT! a)d  
一个TLD的内容的开头必须遵守标准的XML开头,用于描述DTD和xml的版本,例如: WMnR+?q  
S+py \z%  
<?xml version="1.0" encoding="ISO-8859-1" ?> ] e!CH <N  
c9-$t d&  
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd"> f{xR s-u]  
TLD必须以<taglib>来作为它的根元素,<taglib>的子元素如下表: ?v-IN  
7F;"=DarOE  
]:i :QiYD  
<taglib>的子元素 O{zY(`[  
C7[ge&  
Element 0#lw?sv  
Description kq6S`~J^R  
RIOR%~U  
tlib-version +Mc kR  
Tag库的版本 vpcHJ^19  
wUWSW<  
jsp-version ^"7tfo8  
Tag库所需要的jsp的版本 d af$`  
S8*VjG?T\  
short-name ("0@_05OH  
助记符,tag的一个别名(可选) o90SXa&l/  
Qj5~ lX`W  
uri F@Y)yi?z  
用于确定一个唯一的tag库 eZ5UR014  
"~Twx]Z  
display-name xx0s`5  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) [hTGWT3  
lc>)7UF  
small-icon A`Q'I$fj  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) @P#uH5U  
%ANo^~8  
large-icon &f'\9lO  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) O( G|fs  
-FytkM^]6  
description + 5H9mk  
对tag库的描述(可选) FL% GW:  
CnruaN@  
listener rLs)*A!  
参见下面listener元素 xnmIo? hC  
Oe4 l` =2  
tag J;h4)w~9H3  
参见下面tag 元素 K&0op 4&  
[R CUP.  
Listener元素 |!{Q4<  
LWHP31{R  
一个tag库可能定义一些类做为它的事件侦听类,这些类在TLD中被称为listener 元素,jsp服务器将会实例化这些侦听类,并且注册它们。Listener元素中有一个叫listener-class的子元素,这个元素的值必须是该侦听类的完整类名。 WJ=DTON  
&I: [ 'l!  
Tag元素 Z.Lm[$/edn  
_5%SYxF*y  
每个tag元素在tag库中都要指出它的名字、类名、脚本变量、tag的属性。其中脚本变量的值可以直接在TLD中定义或通过tag附加信息的类来取得。每个属性描述了这个属性是否可以省略,它的值是否可以通过<%= …%>这样的JSP语法来获得,以及属性的类型。 =Xh^@ OR  
kF.!U/C  
每一个tag在TLD中对应一个tag元素,下表是tag元素的子元素: ^ AxU  
\bYuAE1q  
Tag元素的子元素 O&l(`*P  
K]' 84!l  
元素名称 p8K4^H  
描述 D.Rk{0se8  
.NcoST9a  
name wLC!vX.S  
独一无二的元素名 wH=  
r`XIn#o  
tag-class \s?OvqI:  
Tag标签对应的tag处理类 qH!}oPeU'  
;ZX P*M9  
tei-class <$wh@$PK  
javax.servlet.jsp.tagext.TagExtraInfo的子类,用于表达脚本变量(可选) ATCFdtNc  
"<ow;ciJF  
body-content In^MZ)?  
Tag标签body的类型 0cZyO$.  
dl;~-'0  
display-name v'Ce|.;  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) w]GoeIg({  
Dww]D|M  
small-icon r \H+=2E'  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) Uov%12  
Mm`jk%:%]  
large-icon au7%K5  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) *k==2figz  
\kcJF'JFA0  
description z_R^n#A~r  
此tag标签的描述 2 P+RfE`o  
 \o !  
variable rHPda?&H  
提供脚本变量的信息(同tei-class)(可选) K];nM}<  
O-Hu:KuIf  
attribute rB;` &)-  
Tag标签的属性名 eO;i1>  
y[[f?rxz>  
以下章节介绍对于不同类型的tag,如何具体地实现它们。 'EU{%\qM  
Z l.}=  
DLcfOOn1I  
简单的tag kf\n  
wVkms  
'<~rV  
tag处理类 (UDF^  
QEL^0c8~  
简单的tag处理类必须实现Tag接口的doStartTag和doEndTag方法。当jsp引擎碰到tag标签的开头时,doStartTag被调用,因为简单的tag没有body,所以此方法将返回 SKIP_BODY。当jsp引擎碰到tag标签的结尾时,doEndTag被调用,如果余下的页面还要被计算,那它将返回EVAL_PAGE,否则将会返回SKIP_PAGE。 )~xL_yW_X  
uMa: GDh7  
以下是例子:对于标签 <tt:simple /> ,它的tag处理类实现如下: NCYN .@J  
`GOxFDB.  
6g4CUP'Y  
public SimpleTag extends TagSupport #%z--xuJL  
#Z<pks2 y  
{ D 7 l&L  
u\=gps/Z  
public int doStartTag() throws JspException /tRzb8`  
n4\6\0jq6  
{ !Sr^4R+Z  
" ] 0ER  
try{ l=D E|:  
xal,j*  
pageContext.getOut().print(“Hello.”); ov: h4  
i@e.Uzn  
}catch(Exception e){ /*p4(D_A  
d,[.=Jqv[  
throw new JspTagException(“SimpleTag: “ + e.getMessage()); S+H#^WSt  
c\FyX\ i  
} W!q 'wrIx(  
;e;lPM{+  
return SKIP_BODY; f Z$<'(t  
/]%,C   
} u^a\02aV[  
>SpXB:wx  
public int doEndTag() x n)FE4  
q88p~Ccoa  
{ h`+Gs{1qw  
IrQ8t!  
return EVAL_PAGE; ~-x8@ /   
F7a &-  
} yq+<pfaqvK  
}l$M%Ps!a  
} 'D%No!+Py  
!VpZo*+   
#b\&Md|;  
注意:如果tag标签没有内容的话,那必须定义body-content元素为空,例如 xP*9UXZ4P  
wpu]{~Y  
<body-content>empty</body-content> GDw4=0u-  
)|,-l^lC  
zYpIG8"o5  
带属性的tag标签
评价一下你浏览此帖子的感受

精彩

感动

搞笑

开心

愤怒

无聊

灌水
级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
只看该作者 1 发表于: 2007-01-01
tag处理类 ^.Q{Aqu#.H  
y$s}-O]/-  
对于tag标签的每个属性,你必须依照JavaBeans规范来定义其属性,以及get和set方法。以struts的logic:present 标签为例, L`FsK64@  
^!k^=ST1J  
<logic:present parameter=”Clear”> S#0y\  
jjBcoQU$o  
与此相应,此tag处理类应有如下方法和定义: gXI_S9 z  
2g-'.w  
Y?%MPaN:  
protected String parameter = null; Lv,~Mf1|  
JfKhYRl  
public String getParameter() ~6U@*Svk  
3Zg=ZnF  
{ U@yrqT@;AU  
Rg)\o(J  
return this.parameter; &=|W95  
w3Aq[1U0  
} 9 pE)S^P  
^T'+dGU`  
public void setParameter(String parameter) M_MiY|%V/K  
~c ;7me.  
{ @ :Q];rc  
9;dP7o  
this.parameter = parameter; COv#dOw  
%#Wg>6  
} ;w4rwL  
Xn.zN>mB  
9Q=g]int u  
注意:如果你的属性名为id,而且你的tag处理类是从TagSupport类继承的,那你就不需要定义它的属性和set和get方法,因为他们早已在TagSupport被定义过了。 TC U |k ,  
z%ljEI"<C  
Attribute元素 kr8NKZ/  
6_;3   
对于tag标签的每个属性,你必须定义它是否必须的,它的值是否可以用诸如<%= …%>的表达式来获得,以及它的类型(可选),如果不指定它的类型,那就默认为是java.lang.String类型。如果rtexprvalue元素被定义为true或yes,那么在type元素中就定义了attribute的返回类型。 xp/u, q  
\s&w0V`Y  
<attribute> mDip P  
RTA9CR)JP4  
<name>attr1</name> @SPmb o  
<<(~'$~,L  
<required>true|false|yes|no</required> }llzO  
yHQ.EZ~%  
<rtexprvalue>true|false|yes|no</rtexprvalue> T7m rOp  
5yp~PhHf  
<type>attribute的返回类型(只用当rtexprvalue为真是才有效)</type> ; 5my(J*b  
`h$6MFC/g  
</attribute> *[ Wh9 ,H  
W~W^$A  
如果tag的某个属性不是必须的,那tag处理类会自动提供一个缺省值。 OI %v>ns  
@U;-5KYYi  
例如,在logic:present这个tag标签中定义了一个属性叫parameter,但它不是必须的,而且它可以被诸如<%= …%>的表达式来赋值。 [KWF7GQi  
`]5XY8^kI  
<tag> {eIE|   
wX#\\Jgi  
<name>present</name> U,iTURd  
g%j z,|  
<tag-class>org.apache.struts.taglib.logic.PresentTag</tag-class> s`C#=l4  
f: 7Y  
<body-content>JSP</body-content> ++,mM7a  
ZeWHSU  
Uo^s]H#:  
kKE 2~ q  
<attribute> j])iyn~-Ke  
Iay7Fkv  
<name>parameter</name> ,-] JCcH  
./#K@V1  
<required>false</required> Y+/ofk "  
&o4L;A#&  
<rtexprvalue>true</rtexprvalue> m{%_5nW  
2:p2u1Q O  
</attribute> 6J%SkuxR  
XF^c(*5  
ys+?+dY2  
#l;Ekjfz  
</tag> I_pA)P*Q(6  
0)ST_2Ci  
+Ya-h~7;g#  
属性元素的校验  C&e  
% Pa-fee  
`9K'I-hv<8  
有关于tag标签的有效值可以从tag库的说明文档中获得,当JSP页面被编译时,jsp引擎会强制性地参照TLD中定义的规则进行检查。 9%zR ? u  
DVTzN(gO*~  
还有一个方法也可以进行属性元素的校验,就是先继承类TagExtraInfo,然后调用它的isValid方法。这个类同时也起到提供tag中定义的脚本变量信息的作用。 4i~;Ql  
qh.c#t  
IsValid方法通过TagData对象来传递属性信息,它包括着tag的所有的属性名-值的信息。由于校验发生在运行时刻,因此这个属性的值将被赋值为TagData.REQUEST_TIME_VALUE。 J\;~(: ~  
M?nnpO  
例如tag标签<tt:twa attr1=”value1” />在TLD中定义如下:  .)cOu>  
&`>*3m(  
<attribute> {B\.8)&8  
&-cI|  
<name>attr1</name> MIR17%G  
Q&QR{?PMD  
<required>true</required> gLpWfT29V  
w_U5w  
<rtexprvalue>true</rtexprvalue> tD4IwX  
@~63%6r#4M  
</attribute> zZiB`%  
U4N S.`V  
`M7){  
这个定义说明了attr1能在运行期间被赋值。 Ce_Z &?  
~MhPzu&B  
以下的isValid方法检查attr1属性的值是否属于Boolean类型。注意由于attr1能在运行刻被赋值,那么isValid方法必须检查tag用户是否对此tag进行了运行时刻赋值。 ]KuK\(\  
x,7a xx6  
i"e) LJz  
Public class TwaTEI extends TagExtraInfo =<e#  2  
DdSUB  
{ RhQOl9  
Ix *KL=MG  
public boolean isValid(Tagdata data) V9<[v?.\  
AOWI`  
{ t?0=;.D  
YF:NRY[i  
Object o = data.getAttribute(“attr1”); W_DO8n X  
v>nJy~O]  
If(o != null && o != TagData.REQUEST_TIME_VALUE) 10[~ki-1;  
LXXxwIBS  
{ p19Zxh  
uWfse19  
if( ( (String)o).toLowerCase().equals(“true”) || U| N`X54  
]a:kP,  
((String)o).toLowerCase().equals(“false”) ) L7jz^g^  
pt0H*quwI  
return true; ol[{1KT{  
J,~)9Kh$  
else 5#d(_  
Me`"@{r|#  
return false; CZa9hsM  
p}Gk|Kjlq,  
} " 3^6  
($cu!$lY~  
else g{D&|qWj  
ol YSr .Q`  
return true; Vy/g;ZPU1  
NK4ven7/  
} 4\$Ze0tv  
/60[T@Mz  
} ;^*^ :L  
{:oZ&y)Ac  
*508PY  
带body的tag rmhCuY?f  
n!N;WL3k  
A>4k4*aFm#  
tag处理类 l y%**iN  
.K7A!;  
cX=` Tl  
如果tag标签含有内容,那处理方式会略微有些不同,而且还要视tag处理类是否要与body交互的情况而定。如果要与body交互,那我们认为tag处理类要可能要对body进行操作。 C>03P.s4c  
n >eIQaV  
Tag处理类不与body交互 +}Q4 g]M8  
z$<6;2  
如果tag处理类不与body交互,tag处理类应该实现Tag接口或从TagSupport中派生,如果body要被计算,那么doStartTag方法应返回 EVAL_BODY_INCLUDE,否则应返回SKIP_BODY。 {?jdPh  
z%AIv%  
如果tag处理类要对body反复运算,则它应该实现IterationTag或从TagSupport中派生。如果tag处理类认为body还未计算完的话,那它的doStartTag方法和doAfterBody方法必须返回EVAL_BODY_AGAIN。 J%A`M\  
\hq8/6=4s  
Tag处理类与body交互 \u/5&[;  
5Px.G*  
如果tag处理类与body交互,那tag处理类应实现BodyTag接口或从BodyTagSupport中派生。这种tag处理类一般要实现doInitBody和doAfterBody方法。 IB?A]oN1{  
Xt7'clr  
Body允许一些方法来读写它的内容。Tag处理类可以调用body内容的getString或getReader方法来从body中提取信息,也可用 writeOut(out) 方法来将body的内容写入到out对象中。其中out对象通过tag处理类的getPreviousOut方法来获得。 '&9 a%  
z`Q5J9_<cV  
如果body的内容需要被计算,那么doStartTag方法必须返回EVAL_BODY_BUFFERED,否则,它将返回 SKIP_BODY。  $}F]pa[  
g9 yCd(2<5  
doInitBody 方法 ^Qr P.l#pZ  
cPN7^*  
此方法在body内容已经设好,但未被计算之前被调用。你可以根据不同的body内容来制定初始化策略。 EjF}yuq[  
CVUJ(D&Q  
doAfterBody方法 1uH\Bn]p?  
I|ULf  
此方法在body内容已被计算后进行调用。 ~::R+Lh(  
fwnpmuJ  
和doStartTag方法一样,doAfterBody方法返回一个指示符指示是否要继续计算body,如果要继续计算,则doAfterBody应返回EVAL_BODY_BUFFERED,否则,它应返回SKIP_BODY。 Sx~_p3_5U  
RXof$2CZS  
release 方法 pts}?   
cp2fDn  
tag处理类调用此方法将它的状态重置为初始状态,并释放所有的私有资源。 HdLkof2i  
7]^ }  
I^wj7cFo5  
以下的例子读取body的内容(其中含有一条sql语句),然后将它传递给一个对象,让它进行查询。由于此处body不须重新计算,所以doAfterBody会返回SKIP_BODY。 )N6R#   
p/5!a~1'xN  
q-o>yjT~  
Public class QueryTag extends BodyTagSupport lt$7 97  
c,-x}i0c  
{ ps [6)d)o  
EiN.VU `  
public int doAfterBody() throws JspTagException 'wZy: c  
-'N#@Wdr  
{ C[KU~@  
E*I]v  
BodyContent bc = getBodyContent(); dSL %%  
S]o  
//将body的内容以字符串的格式提取出来 ?dmMGm0T9  
.;F+ QP0  
String query = bc.getString(); 0!VLPA:  
X or ,}. w  
//清除body 4l1=l#\S  
w2,T.3DT  
bc.clearBody(); =%u|8Ea*`  
NY;UI (<]  
try{ F@*lR(4C  
?% X9XH/!  
Statement stmt = connection.createStatement(); `%XgGHiE  
^kD? 0Fm  
Result result = stmt.executeQuery(query); xh6x B|Z  
VoyH:  
}catch(SQLException e){ M"vcF5q  
c6uKK h>  
throw new JspTagException(“queryTag: “ + e.getMessage() ); u7C{>  
2%qn !+.  
return SKIP_BODY; Wu4Nq+  
rO`g~>-  
} .apX72's,  
u20b+c4  
} '=~y'nPG7  
Z+dR(9otH3  
5 muW*7  
body-content元素 CU;nrd"  
z-gwNE{  
&0eB@8{N  
由于tag可能会有body,你必须用body-content元素来指定body内容的类型:  ke#;1  
w.Vynb  
<body-content>JSP|tagdependent</body-content> L@_">' pR  
j>Z]J'P  
>YBpB,WND  
如果body的内容是定制的或内部的tag、脚本元素、或HTML广本,则归类为JSP类型。其他的类型,比如上面代码所述的?D?D将sql statement类传给 query tag的这种类型应该标为tagdependent。 `eWc p^|  
0xxzhlKNL  
注意:实际上body-content的值并不影响tag处理类对body内容的处理,它仅仅是被tag编辑工具用来描述此body的内容。 @NNLzqqY  
>h[!gXL^  
/kA19E4  
用tags定义脚本变量 B R:  
r^E]GDz  
4 ufLP DH  
tag处理类 q-G|@6O  
(K6`nWk2  
@Y<tH,*  
tag处理类负责创建或设置页面中定义的脚本变量,用pageContext.setAttribute(name,value,scope)或pageContext.setAttribute(name,value)方法来实现。一般来说,tag处理类通过脚本变量的名称来获取它,脚本变量的名称一般可用get方法来获得。 uT/B}`md  
h*KHEg"+  
如果脚本变量的值依赖于tag处理类中的上下文中某一对象,那它可用pageContext.getAttribute(name,scope)方法来找到那个对象。一般的处理过程是tag处理类先找到脚本变量,再对其进行处理,然后用pageContext.setAttribute(name,object)的方法来设置它的新值。 a-E-hX2  
w~U`+2a3  
对象的生存周期(scope)如下表: rc$!$~|I3Z  
mVK9NK  
对象的生存周期表 v|I5Gz$qpa  
~8m>DSs)D  
名字 1D[P\r-  
可访问范围 T{<@MK%],d  
生存周期 ?66(t  
B -~&6D,  
page -k <9v.:  
当前页面 !ix<|F5  
一直有效,除非页面向客户提交响应或重定向到一个新页面 IOkC[([  
w;EXjl;X O  
request -p.*<y  
当前页面或当前页面重定向到的页面 Jo3(bl %u  
一直有效,除非页面向客户提交响应 unnx#e]  
dl6v <  
session klJ[ {p  
当前页面或在同一浏览器窗口中的页面 F!&pENQ  
一直有效,除非关闭当前浏览器、超时、网络故障 2]3HX3  
~Ex.Yp8.  
application :dguQ|e  
整个web应用程序的所有请求 3> #mO}\  
一直有效,除非发生网络故障、服务器故障 6eT'[Umx  
GWInN8.5  
提供关于脚本变量的信息 ZGpTw[5ql  
@pG lWw9*  
以下示例定义了一个名为“book”的脚本变量,用来访问程序中关于书的信息: 3Y{)(%I  
pRwGv  
<bean:define id=”book” name=”bookDB” property=”bookDetails” type=”database.BookDetails” /> UB$`;'|i  
2rCY&8  
<font color=”red” size=”+2” > }=hoATs  
%W4aKb?BT  
<%= messages.getString(“CartRemoved”) %> 2-V)>98  
;hA7<loY  
<strong><jsp:getProperty name=”book” property=”title” /></strong> 7_40_kwJi  
f4k5R  
</font> eq~c  
`MsYgd  
当包含此tag的JSP页面被编译时,jsp引擎会自动生成关于此book的同步的代码(同步可以避免几个客户同时访问此book时造成的冲突),要生成同步代码,jsp引擎需要知道此脚本变量的如下信息: >I& jurU#  
e$EF% cKH  
· 脚本变量名称 @y(Wy}  
Nr24[e G>d  
· 脚本变量所属的类 sk ?'^6Xh  
pTALhj#,  
· 此脚本变量是否引用了一个新的或已存在的对象 Ww96|m  
,![Du::1  
· 此脚本变量的有效性 ZJ9Jf2 c  
,B%fjcn  
有两种办法可以向jsp引擎提供关于脚本变量的信息:在TLD中定义variable子元素,或用tei-class子元素定义一个额外tag信息类。用variable最简单,但可能降低了一些灵活性。 t\pK`DM-[  
 C5+`<  
Variable元素 So=nB} b[?  
 oKYhE  
Variable元素有如下子元素: aw/7Z`   
@mx$sNDkL  
· name-given ?D?D 给出的名字,是一个常量 FGwnESCC  
:5S |x/  
· name-from-attribute?D?D 属性名,在编译时给出的属性名 x$n~f:1Y  
7<:Wq=e!r  
name-given或name-from-attribute两者必须选一,但以下子元素是可选的: 3_MS'&M  
AzW7tp;t =  
· variable-class?D?D变量的类型,缺省为java.lang.String。 qEJ8o.D-=  
u\XkXS`  
· declare?D?D此脚本变量是否引用了一个新对象,缺省为True。 8pPC 9ew\=  
^.#X<8hr  
· scope?D?D脚本变量的范围,缺省为NESTED。下表描述了scope的几种类型: 3kiE3*H  
x_<bK$OU  
脚本变量的有效范围 a_{io`h3&  
0TO_1 0D  
eOehgU5x  
有效性 )[^y t0%  
方法 {jhmp\PN  
"%E-X:Il#  
NESTED y|6@-:B.  
在tag标签的开始和结束之间 `~ _H=l9{  
如果tag处理类实现BodyTag接口,则在doInitBody和doAfterBody中调用,否则在doStartTag中调用 ?+n&hHRg  
PZuq'^p  
AT_BEGIN wb6L? t  
从tag标签的开始一直到页面结束 ahNX/3; y  
如果tag处理类实现BodyTag接口,则在doInitBody、doAfterBody和doEndTag中调用,否则在doStartTag和doEndTag中调用 Kx- s0cw  
hza> jR  
AT_END dK}WM46$   
从tag标签的结束一直到页面结束 #0bO)m+NZ  
在doEndTag中调用 7}ws |4Y  
ZU|6jI}  
以struts为例,它的bean:define标签的实现遵循JSP1.1规范,此规范要求使用额外tag信息类来定义脚本变量。Variable元素是JSP1.2规范中加入的。以bean:define标签为例,你可以定义如下variable元素: dP$8JI{  
)'[x)q  
<tag> "{A*(.  
;8*XOC;[  
<variable> *N-;V|{  
U~:N^Sc  
<name-from-attribute>id</name-from-attribute> U!&_mD# c  
UzgA26;  
<variable-class>database.BookDetails</variable-class> v /R[?H)  
+M'aWlPg,  
<declare>true</declare> .tRr?*V|l  
Ot`LZ"H:  
<scope>AT_BEGIN</scope> F qeV3 N  
Zc'|!pT _  
</variable> v2hZq-q  
*jM_wwG  
</tag> \3Dk5cSDk+  
<<=e9Lh  
额外tag信息类 *Y85DEA  
)jyq{Jb  
如果要定义一个额外tag信息类,你要继承javax.servlet.jsp.TagExtraInfo类。一个TagExtraInfo类必须实现getVariableInfo方法,此方法返回一个叫VariableInfo的数组类,它包括如下信息: O^9CV*]!n  
;rB6u_5"I.  
· 变量名 jR{-  
Rx6l|'e  
· 变量所属类名 TB7>s~)47E  
%G;0T;0L  
· 此变量是否引用了一个新对象 _wf5%(~b  
j G-  
· 此变量的有效范围 I|,pE**T  
@$qOW  
jsp引擎将一个名为data的参数传给getVariableInfo方法,data中包括tag标签中的所有“属性名?D?D属性值”对。它可以用来向VariableInfo对象提供脚本变量的名字和类名。 z`k El@  
No`|m0 :j  
以struts为例,它在bean:define标签中定义了一个名为DefineTei的额外tag信息类,用来向脚本变量提供信息。由于脚本变量的名称(book)和类名(database.BookDetails)是通过tag标签的属性来传递的,它们一般定义在VariableInfo的构建代码中,并且可用data.getAttributeString方法来得到这些信息。如果要允许book脚本变量能在从tag开始直到整个JSP页面结束的范围内都可用的话,那它的范围应设为AT_BEGIN。如下所示: .sM<6;  
m\>|C1oRy  
i2){xg~c  
public class DefineTei extends TagExtraInfo M.>^{n$ z  
0b/i r2  
{ *cbeyB{E  
e`i7ah;  
public VariableInfo[] getVariableInfo(TagData data) 5Sr4-F+@%  
V0K16#}1gM  
{ ! z11" c  
7~_I=-  
String type = data.getAttributeString(“type”); +I t#Z3  
>+cSPN'i>  
If( type == null) .VT;H1#  
d/3J' (cq  
type = “java.lang.Object”; XC[]E)8  
eR:b=%T8  
return new VariableInfo[] { <W>++< -  
aaDP9FW9e  
new VariableInfo(data.getAttributeString(“id”), dj'm, k b  
,7GWB:Sk  
type, gtiEhCF2W  
^ eQFg>  
true, '77~{jy  
|]`hXr  
VariableInfo.AT_BEGIN) \(I0wEQo$  
{esJ=FV\  
}; U{6oLqwq3Y  
`@[l\.Vt:  
} ]r4bRK[1  
qO-9 x0v#  
} X) V7bVW  
[4sEVu}  
y$X(S\W  
注意:关于额外tag信息类的类名必须要在TLD中的tag标签下的tei-class子元素中定义。因此,DefineTei的tei-class中的定义看起来如下: (n,u|}8Y  
<tei-class> 4({( i  
org.apache.struts.taglib.bean.DefineTagTei H~noJIw#  
</tei-class> JK]R*!{n  
h.)h@$d  
-KH)J  
具有协作关系的tag bB!#:j>(v  
`K*b?:0lp  
>nzu],U  
tag通过共享对象来进行协作,JSP技术支持2种方式的对象共享。 UiH!Dl}<  
cvnB!$eji  
第一种方法是使用pageContext对象进行对象的共享(可支持JSP页面和tag处理类之间的共享),如果在一个tag处理类中要调用由另一个tag处理类创建的对象,可调用pageContext.getAttribute(name, scope)方法。 ,R?np9wc  
$&{ti.l  
第二各方式的共享是对于tag之间有嵌套关系而言的,外层的tag所创建的对象对于内层的tag来说是可以共用的。这种形式的共享的好处是减少了可能存在的重名冲突。 =-NiO@5o  
:_5/u|{  
要访问一个嵌套tag创建的对象,tag处理类必须先找到此嵌套tag对象,可用TagSupport的静态方法 TagSupport.findAncestorWithClass(from, class)或TagSupport.getParent方法。前者在当不确定此tag是否为嵌套tag对象时使用。一旦它的父类被找到,它就能访问其所有动态或静态创建的对象。静态创建的对象是父类的成员,而动态创建的对象可能是父类的私有对象。诸如此类的对象可以用tag处理类的setValue方法来保存,用getValue方法来获得。 <3 TA>Dz  
nd ink$  
下例阐述了以上两种共享对象的方法。在这个例子当中,一个查询tag检查一个名为connection的属性名是否在doStartTag中被设置。如果connection属性被设置,tag处理类从pageContext中得到这个connection对象。否则,此tag处理类先找到它的父tag处理类,然后从它的父tag处理类中找到connection对象。 F>zl9Vi<  
rYY$wA@  
hn.bau[  
public class QueryTag extends BodyTagSupport $Az^Y0[D  
'fx UV<K&  
{ 9i5tVOhE  
]5}=^  
private String connectionId; 8S]".  
(hB?  
public int doStartTag() throws JspException "9IYB)Js  
(-0ePSOG  
{ %<"}y$J  
6sJw@Oa J  
String cid = getConnection(); ?^i1_v7 Bi  
&gtG~mp<L  
if(cid != null) 4[yIOs  
?WUF!Jk  
{ DZ$` 4;C[  
W#'c 5:m 4  
//存在一个connection id,使用它。 VA] e  
r@U3sO#N  
connection = (Connection) pageContext.getAttribute(cid); AH#4wPxF  
:XG;ru%i  
} 3*ixlO:qGk  
[kV;[c}  
else fpWg R4__  
oR .cSGh  
{ b| M3 `  
J-xS:Ha'l  
ConnectionTag ancestorTag = (ConnectionTag)findAncestorWithClass(this, yF13Of^l./  
:O-iykXyI  
ConnectionTag.class); :kMHRm@{  
x YfD()w<I  
if(ancestorTag == null) +JRF0T  
yNg9X(U  
{ G(iJi  
,CvG 20>  
throw new JspTagException(“一个没有connection属性的查询标签必须被一个connection标记嵌套。”); <eN_1NTH_  
'sh~,+g  
} o:S0*  
mYxyWB  
connection = ancestorTag.getConnection(); dq\FBwfe  
6at1bQ$  
} ^EELaG  
"9!d]2.-Vk  
} 2I/xJ+  
$e1=xSQp4  
} Fmyj*)J[Z  
O`G/=/GZ  
=,y |00l  
g{IF_ 1  
此查询标签在JSP页面中的调用形式可以从以下2种定义中任选一种: NVKC'==0  
6%,C_7j  
~y HU^5D  
<tt:connection id=”con01” ...> ... </tt:connection> DdQ;Q5|  
r]@0eb   
<tt:query id=”balances” connection=”con01” > (*p , T  
]rehW}  
SELECT account, balance FROM acct_table sRSz}]  
o*WY=  
where customer_num = <%= request.getCustno() %> =Prb'8 W  
: _e#  
</tt:query> Byl^?5  
_VE^/;$"l  
bmgncwlz  
$+JS&k/'m  
&H}r%%|A  
<tt:connection ...> Wj|alH9<  
gr-9l0u  
<x:query id=”balances”> FBx_c;)9Z  
o?L'Pg  
SELECT account, balance FROM acct_table YB<*"HxM)}  
;Uc0o!1  
where customer_num = <%= request.getCustno() %> ?eH&'m}-  
"@R>J ?Cc+  
</x:query> ^d}gpin  
}KUd7[s  
</tt:connection> Od+6 -J  
}%b;vzkG5  
]i(-I <`  
与此同时,在TLD中必须指定connection属性为可选的,定义如下: 8Jf.ECQT  
9. 'h^#C  
<tag> [(X y.L7x  
'c2W}$q  
... De7T s  
=4V&*go*\  
<attribute> ZkL8e  
dQoYCS}IaV  
<name>connection</name> O[tvR:Nh  
f-DL:@crU  
<required>false</required> Jk@]tAwoM  
7C#`6:tI  
</attribute> --;@2:lg{  
:w}{$v}#D;  
</tag>
描述
快速回复

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