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

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

级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
标准的JSP 标记可以调用JavaBeans组件或者执行客户的请求,这大大降低了JSP开发的复杂度和维护量。JSP技术也允许你自定义taglib,其实换句话说,taglib可以看成是对JSP标记的一种扩展,正如xml是对html的一种扩展一样。taglib通常定义在tag标签库中,这种标签库存放着你自己定义的tag标签。简而言之,如果使用taglib,那么你可以设计自己的JSP标记! S17iYjy#8T  
@K=:f  
一般来说,自定义tag标签主要用于操作隐藏对象、处理html提交表单、访问数据库或其它企业级的服务,诸如邮件和目录操作等等。自定义tag标签的使用者一般都是那些对java编程语言非常精通,而且对数据访问和企业级服务访问都非常熟悉的程序员,对于HTML设计者来说,使得他可以不去关注那些较复杂的商业逻辑,而将精力放在网页设计上。同时,它也将库开发者和库使用者进行合理分工,自定义tag标签将那些重复工作进行封装,从而大大提高了生产力,而且可以使得tag库可用于不同的项目中,完美地体现了软件复用的思想。 9Sb[5_Q  
GLBzlZ?  
在这篇文章中,我们主要讨论: Eo) #t{{  
U } K]W>Z  
· 什么是自定义tag标签? s)A=hB-V  
?hFG+`"W  
· 怎么使用tag标签? .or1*-B K  
%&iY5A  
o 声明要使用的tag库 e{Y8m Xu  
VYo2m  
o 找到与之对应的tag处理类 X/8TRiTFv  
 LBIsj}e  
o tag标签的类型 TOH+JL8L  
O0Pb"ou_h.  
· 自定义tag标签 2lu AF2  
n:8<Ijrh  
o tag处理类 )c<X.4  
eZ G#op  
o tag库描述 "y7IH GJ\3  
"\~d!"n|2  
o tag标签示例 N51e.;  
9F "^MzZ  
o 带属性的tag l+r3|b  
KsDovy<  
o 带body的tag )JXlPU  
sK/Z 'h{|  
o 定义了脚本变量的tag Q/%]%d  
]kir@NMv>  
o 具有协作关系的tag -Q MO*PY  
}Y&|v q  
· 自定义tag标签 9=}&evGm89  
F@ld#O  
o 一个迭代tag的例子 \LYNrL~?J  
2{9%E6%#  
o 一个模板tag库 %0_}usrsk  
 nJ|M  
o tag处理类到底是怎样被调用的? {%BPP{OFk  
c\.7Z=D  
<i ";5+  
什么是自定义的tag? "KKw\i  
O"ebrv  
一个自定义的tag标签是用户定义的一种JSP标记。当一个含有自定义的tag标签的JSP页面被jsp引擎编译成servlet时,tag标签被转化成了对一个称为tag处理类的对象进行的操作。于是当JSP页面被jsp引擎转化为servlet后,实际上tag标签被转化成为了对tag处理类的操作。 >|rU*+I`  
V'8Rz#Gc5  
自定义tag标签有很多特色,诸如: }G ^nK m  
*cy!PF&  
· 可以在JSP页面中自定义tag标签的属性 G0lg5iA<fC  
r E&}B5PN=  
· 访问JSP页面中的所有对象 2o<aEn&7|e  
W}P9I&3  
· 可以动态地修改页面输出 DR(/|?k+  
Oq[YbQ'GE  
· 彼此这间可以相互通信。你可以先创建一个JavaBeans组件,然后在一个tag中调用此JavaBeans组件,同时可以在另一个tag中调用它。 giH WC%/  
0]Qk*u<  
· tag允许相互嵌套,可以在一个JSP页面中完成一些复杂的交互。 y7T<Auue`  
NI85|*h  
,DD}o  
使用tag标签 ho%G  
4XgzNwm  
f/vsf&^O  
本节主要描述怎样在JSP页面中使用tag标签,以及tag标签的不同类型。 .c]@xoC  
I\<)9`O  
要使用tag标签,JSP程序员必须做2件事: $6~t|[7:%Y  
P{2j31u`  
· 声明此tag标签的tag库 hiw>Q7W  
|lMc6C  
· 实现此tag标签 B4eV$~<  
PB;j4  
声明tag标签所在的tag库 Zq{TY)PI]  
^IqD^(Kb  
如果要使用tag标签,则应用JSP的taglib指示符来指定其tag库(注意:taglib要在在使用此tag标签之前声明) {.r #j|  
giHqc7-PaX  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> * zc[t  
3a0% J'  
uri属性定义了唯一的标签库描述(以下简称TLD),它可以是直接是tld文件名或一个独一无二的名字。prefix是用来区别其它TLD中和本TLD中有重名的tag的一种手段。 K6 c[W%Va  
?D+H2[n\a  
TLD必须以.tld作为扩展名,并且存放在当前应用的WEB-INF目录或其子目录下。你可以通过它的文件名直接引用它,也可以通过别的方式间接地引用它。 _BI[F m  
}=fls=c/0  
以下taglib指示符直接引用一个TLD: u,JUMH]@  
}$` PZUw>  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> cuh Z_l  
}oL l? L  
以下的taglib指示符通过一个逻辑名称间接地引用一个TLD: VK% j45D`  
A-l[f\  
<%@ taglib uri=”/tutorial-template” prefix=”tt” %> 4"s/T0C  
9.wZhcqqU  
如果是间接引用TLD的话,那你必须还要在web.xml中定义此逻辑名称与tld文件之间的映射,具体做法是在web.xml中加入一个名为taglib的元素: FyqsFTh_  
P-\65]`C  
<taglib> 3'!*/UnU  
IweNe`Z  
<taglib-uri>/tutorial-template</taglib-uri> vu~7Z;y(<j  
ot,=.%O  
<taglib-location> nq:'jdY5|  
KT0Pmpp5  
/WEB-INF/tutorial-template.tld l{Xy %8  
g(l:>=g]?  
</taglib-location> TU^s!Tj  
P\%aJ'f~  
</taglib> ^!Tq(t5V  
5l]qhi3f  
[tkP2%1  
实现此tag标签 BFQ`Ab+  
 QB#_Wn  
+wcif-  
为了实现tag标签,你有2种方法来存放tag处理类。一、让tag处理类以.class的方式存放于当前应用的WEB-INF/class子目录下,二、如果tag处理类是以JAR包的形式存在的话,那可以放在当前应用的WEB-INF/lib目录下,如果tag处理类要在多个应用中共享,那么它就应放在jsp服务器上的common/lib目录下,对于tomcat来说,就是tomcat/common/lib目录下。 'H(khS  
Vo%DoZg  
5P[urOvV  
tag标签类型 dMK\ y4#i  
1IN^,A]r2h  
)CD-cz6n  
自定义的tag标签遵循XML语法。它有一个开始标记和一个结束标记,有的还有body(即文本节点): )v %tyU  
11B8 LX  
<tt:tag>  g^))  
`V{'GF&[  
body /%AA\`: 6  
"QmlW2ysi  
</tt:tag> P,)\#([vc  
Je~`{n  
q>m[vvt"  
一个不带body的tag标签如下: 2+|U!X  
x{3q'2  
<tt:tag /> hw1J <Pl*  
l%# z  
ZOy^TR  
简单的tag标签 G|j8iV O  
fJ;1ii~  
一个没有body和属性的tag标签如下: ~:N 1[  
$s,(-C   
<tt:simple /> m}]\^$d  
wu3p2#-Z  
wRJ`RKJ-T  
带属性的tag标签 9'A^n~JHF  
[_HOD^  
w sbzGW~=  
自定义标签可以有自己的属性。属性一般在开始标记中定义,语法为 attr=”value”。属性的作用相当于自定义标签的一个参数,它影响着tag处理类的行为。你可以在TLD中详细定义它。 toel!+  
8@]vvZ2/gj  
你可以用一个String常量给一个属性赋值,也可以通过表达式给它赋值,如<%= ...%>。以struts为例,它的logic:present标签就是用的String常量来给属性赋值: XhmUtbs  
vP^V3  
<loglic:present parameter = “Clear”> R(IYb%L  
CK8!7=>}^  
而另一个标签logic:iterate是用表达式来给属性赋值: @O8X )  
V eLGxc  
<logci:iterate collection=”<%= bookDB.getBooks() %>” iZ9ed ]mf  
zd3^k<  
id=”book” type=”database.BookDetails”> eV\VR !!i  
U,V+qnS  
*rmM2{6  
带body的tag标签 S'=}eeG  
Wux[h8G  
一个自定义标签可以包含其它自定义标签、脚本变量、HTML标记或其它内容。 uE'Kk8  
C /w]B[H  
在下述例子中,此JSP页面使用了struts的logic:present标签,如果些标签定义了parameter=”Clear”的属性,则将清除购物车的内容,然后打印出一条信息: *#j_nNM4  
gb/<(I )  
<logic:present parameter=”Clear”> _*n 4W^8  
k; ned  
<% cart.clear(); %> #NWS)^&1b  
qsdgG1<  
<font color=”#ff0000” size=”+2”><strong> HAAU2A9B2  
Wo~;h (6  
你选择了清除购物车! g1&q6wCg|  
%(>,eee_  
</strong></font> z)%]# QO  
;+rcT;_^/  
</logic:present> O|*-J  
`It3X.^}  
WU~L#Ih.V  
到底是用属性还是用body来传递信息? Zo@  
)pG*_q  
如上所述,我们既可以通过属性,也可以通过body来传递信息。但一般来说,比较简单的类型,如字符串或简单表达式最好采用属性来传递信息。 A }d\ ND  
/-Nq DRmJ  
n7L|XkaQ  
定义脚本变量的tag标签 H4uHCkj  
dg4q+  
所谓脚本变量,是指JSP中可以调用的变量或对象。它可由tag标签产生。以下示例阐述了一个tag标签定义了一个名为tx的由JNDI所定义的事务处理对象。脚本变量可以是ejb对象、事务、数据库连接等等: FBS]U$1  
GxA[N  
<tt:lookup id=”tx” type=”UserTransaction” name=”java:comp/UserTransaction” /> $J*lD -h-  
ilwIqj  
<% tx.begin(); %> {11xjvAD  
mj&$+zM>  
... f}7/UGd  
9S8V`aC  
vAfYONU  
具有协作关系的tag标签 nTr{ D&JS  
0+Q; a  
自定义tag标签之间可以通过共享对象来实现协作。在下述例子中,标签tag1创建了一个名为obj1的对象,在标签tag2仍可以重复使用obj。 =21m|8c  
K$5mDScoJ  
<tt:tag1 attr1=”obj1” value1=”value” /> t"X^|!hKIF  
0}WDB_L  
<tt:tag2 attr1=”obj1” /> :Q"p!,X=-  
!wH'dsriD  
在以下这个例子当中,如果外层的tag标签创建了一个对象,那么其内层的所有tag标签都可以使用这个对象。由于这样产生的对象没有一个指定的名字,那么就可以将少重名的冲突。这个例子阐述了一系列协作的嵌套对象。 HrHtA]  
f'O cW* t  
<tt:outerTag> ov,[F< GT  
1'b}Y 8YO  
<tt:innerTag /> 63c\1]YB.  
S%3&Y3S  
</tt:outerTag> !&R|P|7qN}  
"]U_o<V  
UL`% Xx  
Tag处理类 l{hO"fzy  
ISg-?h/  
'L C0hoV  
Tag处理类必须实现Tag接口或BodyTag接口,不过现在一般都流行从TagSupport或BodyTagSupport类中继承,这些类或接口都可以在javax.servlet.jsp.tagext包中找到。 MC%!>,tC  
\  `|  
当JSP引擎看到自己的JSP页面中包含有tag标签时,它会调用doStartTag方法来处理tag标签的开头,调用doEndTag方法来处理tag标签的结束。 83_vo0@<6  
a2B9 .;F  
下表说明不同类型的tag所需要不同的处理过程: EOo,olklC  
=" pNE#  
Tag处理类的方法 #&ayWef  
pV/5w<_x?  
Tag标签类型 CRu {Ie5B  
所调用的方法 %:\GYs(Y  
t4+bRmS`_  
基本标签 nf,Ez  
doStartTag, doEndTag, release m3=Cg$n  
qq>Qi(>  
带属性的标签 7towjw r  
doStartTag, doEndTag, set/getAttribute1...N, release vCn\_Nu;W&  
U+:Mu]97  
带内容的标签 VM w[M^  
doStartTag, doEndTag, release [FeN(8hGS  
*|6*jU  
带内容的标签,且内容重复循环 ICzcV };$  
doStartTag, doAfterBody, doEndTag, release lF~!F<^9  
R/l/GNm  
带内容的标签,且内容与JSP交互 hI,+J>  
doStartTag, doEndTag, release, doInitBody, doAfterBody, release pet q6)g?  
C;oO=R3r  
一个tag处理类可以通过javax.servlet.jsp.PageContext来与JSP交互,通过javax.servlet.jsp.PageContext类,tag处理类可以访问JSP中的request、session和application对像。 9b)'vr*Hy7  
yZ,S$tSR  
如果tag标签是互相嵌套的,那内层的tag处理类可以通过它的parent属性来访问上层的tag处理类。 {VKP&{~O  
ksF4m_E>YB  
一般情况都将所有的tag处理类打成了JAR的包,以便于发布。 rAS2qt  
Vn?|\3KY  
69N8COLB  
Tag库描述(简称TLD) >Y;[+#H[  
S%o6cl=  
scZ&}Ni  
Tag库是用xml语言描述的,TLD包括了tag库中所有tag标签的描述,它一般用来被jsp服务器用来校验tag的语法正确性,或者被jsp开发者用来开发新的标签。 <%S[6*6U  
o^Qy71Uj  
TLD的文件扩展名必须为.tld,而且必须放在当前WEB应用的WEB-INF目录或其子目录中。 '25zb+ -  
<=@6UPsn2  
一个TLD的内容的开头必须遵守标准的XML开头,用于描述DTD和xml的版本,例如: Xw&vi\*m  
QsyM[;\j:  
<?xml version="1.0" encoding="ISO-8859-1" ?> m.c2y6<=  
X)S4vqf}  
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd"> Kc+TcC  
TLD必须以<taglib>来作为它的根元素,<taglib>的子元素如下表: :a_MT  
yD Avl+  
-+kTw06_C  
<taglib>的子元素 @-.Tgpe@a  
;R^=($X  
Element _g6H&no[  
Description k]S`A,~  
.5iXOS0 G  
tlib-version yH]w(z5Z  
Tag库的版本 oWBjPsQ  
0r]-Ltvl?}  
jsp-version 0[ZwtfL1  
Tag库所需要的jsp的版本 U\dLq&=V  
Z._%T$8aJv  
short-name bDnT><eH  
助记符,tag的一个别名(可选) Wo6C0Z3g}  
I|_U|H!`  
uri h&z(;B!;y.  
用于确定一个唯一的tag库 ;Ngu(es6  
L<p.2[3  
display-name >z k6{kC  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) A#nSK#wS61  
NUX$)c  
small-icon nBzju?X)I  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) >g2Z t;*@w  
ogG:Ai)90  
large-icon h&x;#.SYK  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) VF g"AJf  
3<}r+,j  
description _A6e|(.ll  
对tag库的描述(可选) GW0e=Y=LR  
K'b #}N\  
listener QaSRD/,M  
参见下面listener元素 bH.f4-.u>)  
fn Pej?f:  
tag 5wb R}`8  
参见下面tag 元素 i?6#>;f  
#fq&yjl#A  
Listener元素 6d;RtCENo  
'@WS7`@-y  
一个tag库可能定义一些类做为它的事件侦听类,这些类在TLD中被称为listener 元素,jsp服务器将会实例化这些侦听类,并且注册它们。Listener元素中有一个叫listener-class的子元素,这个元素的值必须是该侦听类的完整类名。 Je=k.pO1  
<UbLds{+Uo  
Tag元素 h3MZLPe  
1=mb2A  
每个tag元素在tag库中都要指出它的名字、类名、脚本变量、tag的属性。其中脚本变量的值可以直接在TLD中定义或通过tag附加信息的类来取得。每个属性描述了这个属性是否可以省略,它的值是否可以通过<%= …%>这样的JSP语法来获得,以及属性的类型。 p s_o:*$l  
7:n OAN}%  
每一个tag在TLD中对应一个tag元素,下表是tag元素的子元素: #Wely~  
D}nIF7r2N  
Tag元素的子元素 "(vm0@8><  
VIuzBmR|\  
元素名称 vd0uI#g%#  
描述 .`/6[Zp  
c='uyx  
name 2@:Ztt6~  
独一无二的元素名 jB3Rue:+g  
kD#hfYs)i  
tag-class 1!A 'mkk8  
Tag标签对应的tag处理类 fDKV`  
w %R=kY)o  
tei-class )J1xO^tE  
javax.servlet.jsp.tagext.TagExtraInfo的子类,用于表达脚本变量(可选) 0> U7]wZKc  
ShJBOaE; -  
body-content J@o$V- KK  
Tag标签body的类型 ,XsBm+Q(  
]".SW5b_  
display-name 7? qRz  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) _dwJ;j`2  
Y#rd' 8  
small-icon c<5(c%a  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) r^;1Sm  
/C/I_S}H  
large-icon YkI_i(  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) hd#MV!ti  
U2*kuP+n  
description )CG,Udu  
此tag标签的描述 Us4#O&  
o=Ia{@   
variable 7-4S'rq+  
提供脚本变量的信息(同tei-class)(可选) *iXaQuT  
DUvF  
attribute C$^WW}S  
Tag标签的属性名 AO]1`b:  
KWH:tFL.  
以下章节介绍对于不同类型的tag,如何具体地实现它们。 ZW`wA2R0   
m&k l_f7  
b}Wm-]|+  
简单的tag husk\  
H*h4D+Kxv  
AzFS6<_  
tag处理类 I Ab-O  
=90)=Pxd  
简单的tag处理类必须实现Tag接口的doStartTag和doEndTag方法。当jsp引擎碰到tag标签的开头时,doStartTag被调用,因为简单的tag没有body,所以此方法将返回 SKIP_BODY。当jsp引擎碰到tag标签的结尾时,doEndTag被调用,如果余下的页面还要被计算,那它将返回EVAL_PAGE,否则将会返回SKIP_PAGE。 ,W5!=\Gg(  
z;Dc#SZnO(  
以下是例子:对于标签 <tt:simple /> ,它的tag处理类实现如下: lBNB8c0e"{  
.t$1B5  
i`7:^v;  
public SimpleTag extends TagSupport UUqA^yJ  
}/M`G]wT#  
{ ?Y_!Fr3V  
lh*!f$2 ~  
public int doStartTag() throws JspException (dAE  
rz.`$  
{ WU{9lL=  
|/~ISB  
try{ pU[5f5_  
3(=QY)  
pageContext.getOut().print(“Hello.”); jDCf]NvOPM  
e6_`  
}catch(Exception e){ ]s}9-!{O  
K'S \$  
throw new JspTagException(“SimpleTag: “ + e.getMessage()); A9ZK :i7  
UiH5iZ<r;  
} Z>J3DH  
SfUbjs@a  
return SKIP_BODY; =iE)vY,?"}  
Gw?ueui<  
} -[ xbGSj{  
/gq\.+'{  
public int doEndTag() "hLm wz|a  
~otV'=/my  
{ `2@f=$B  
0"DS>:Ntk  
return EVAL_PAGE; |!*abc\`(`  
(n4Uc308  
} &f<Ltdw  
?HP{>l0r  
} K8/I+#j  
QUz_2rN^  
j:xm>X'  
注意:如果tag标签没有内容的话,那必须定义body-content元素为空,例如 uF<\|y rFt  
YL9Tsw  
<body-content>empty</body-content> DUyUA'*4n|  
 n[  
X{;5jnpG  
带属性的tag标签
评价一下你浏览此帖子的感受

精彩

感动

搞笑

开心

愤怒

无聊

灌水
级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
只看该作者 1 发表于: 2007-01-01
tag处理类 (V# *}eGy  
y.?Q  
对于tag标签的每个属性,你必须依照JavaBeans规范来定义其属性,以及get和set方法。以struts的logic:present 标签为例, ANXN.V  
K"g`,G6S  
<logic:present parameter=”Clear”> vKTCS  
!=(M P:  
与此相应,此tag处理类应有如下方法和定义: .oz(,$CS"  
e\ O&Xe  
`;z;=A*  
protected String parameter = null; `lN Z|U  
8M7pc{  
public String getParameter() - xQJY)  
&z%DX   
{  7K &j  
D]WU,a[$Bc  
return this.parameter; q=_tjg  
xI^nA2g  
} %y R~dt'  
^li(q]g1!  
public void setParameter(String parameter) ~:):.5o  
k"J=CDP\  
{ )*_n/^m  
h"ko4b3^'@  
this.parameter = parameter; Rb_+C  
?8R  
} G,A;`:/  
Wup%.yT~Ds  
h/\/dp/tt  
注意:如果你的属性名为id,而且你的tag处理类是从TagSupport类继承的,那你就不需要定义它的属性和set和get方法,因为他们早已在TagSupport被定义过了。 FHbw &  
If%**o  
Attribute元素 1}b1RKKj<  
L6"?p-:@'  
对于tag标签的每个属性,你必须定义它是否必须的,它的值是否可以用诸如<%= …%>的表达式来获得,以及它的类型(可选),如果不指定它的类型,那就默认为是java.lang.String类型。如果rtexprvalue元素被定义为true或yes,那么在type元素中就定义了attribute的返回类型。 _dynqF8*  
4dUr8]BkG  
<attribute> J5*(PxDF  
Xsv^GmP+  
<name>attr1</name> =YeI,KbA)  
t7b\#o  
<required>true|false|yes|no</required> a OTrng  
$Qq5Fx9kU  
<rtexprvalue>true|false|yes|no</rtexprvalue> 9$e6?<`(Y  
]6TX)1  
<type>attribute的返回类型(只用当rtexprvalue为真是才有效)</type> J)a^3>  
- u'5xn7  
</attribute> L$s ;tJ   
h|Udw3N1L  
如果tag的某个属性不是必须的,那tag处理类会自动提供一个缺省值。 i`HXBq!|w  
.GNl31f0  
例如,在logic:present这个tag标签中定义了一个属性叫parameter,但它不是必须的,而且它可以被诸如<%= …%>的表达式来赋值。 _U/CG<n  
rc)vVv  
<tag> yB,{:kq7D  
:gacP?  
<name>present</name> /2AeJH\-  
D-4\AzIb  
<tag-class>org.apache.struts.taglib.logic.PresentTag</tag-class> Vh;P,no#  
">NPp\t>/Z  
<body-content>JSP</body-content> + hKH\]  
l?swW+ x\  
O5?3 nYHa  
!:w&eFC6  
<attribute> PR*qyELu  
zwpgf  
<name>parameter</name> |!?`KO{  
|4A938'4j  
<required>false</required> ck\gazo~q  
Yeb-u+23  
<rtexprvalue>true</rtexprvalue> 0@*EwI  
x\2N @*I:  
</attribute> Hy0l"CA*|  
V( bU=;Qo  
K18Sj,]B  
jbK<"T5  
</tag> o5 |P5h  
!'T,%8']  
ECEDNib  
属性元素的校验 u[ 2B0a  
`#w`-  
@F%_{6h  
有关于tag标签的有效值可以从tag库的说明文档中获得,当JSP页面被编译时,jsp引擎会强制性地参照TLD中定义的规则进行检查。 !BikqTM  
b<?A  
还有一个方法也可以进行属性元素的校验,就是先继承类TagExtraInfo,然后调用它的isValid方法。这个类同时也起到提供tag中定义的脚本变量信息的作用。 ? {vY3~  
VN!+r7w'  
IsValid方法通过TagData对象来传递属性信息,它包括着tag的所有的属性名-值的信息。由于校验发生在运行时刻,因此这个属性的值将被赋值为TagData.REQUEST_TIME_VALUE。 4Hcds9y9  
 {]=oOy1  
例如tag标签<tt:twa attr1=”value1” />在TLD中定义如下: ThmN^N  
(&t8.7O  
<attribute> ]@bu%_s"  
@-F[3`HeA  
<name>attr1</name> ?v$kq}Rg  
~G*eJc0S:  
<required>true</required> /QK H30E  
&fu J%  
<rtexprvalue>true</rtexprvalue> Bfz]PN78.G  
[_SV$Jz  
</attribute> wSP'pM{#2  
0?d}Oj  
5u3SP?.&  
这个定义说明了attr1能在运行期间被赋值。  ]6 ]Nr  
.B|a.-oA4  
以下的isValid方法检查attr1属性的值是否属于Boolean类型。注意由于attr1能在运行刻被赋值,那么isValid方法必须检查tag用户是否对此tag进行了运行时刻赋值。 M<"H1>q@  
e[AwR?=  
xfJ&11fG2  
Public class TwaTEI extends TagExtraInfo K{#1O=Gi  
I3$/ #  
{ C~#ndl Ij  
C=|X]"*:u0  
public boolean isValid(Tagdata data) H[KTM'n  
q"sD>Yh&  
{ 8F*"z^vD=  
GVl TW?5  
Object o = data.getAttribute(“attr1”); ui#K`.dn  
w~I;4p~(N  
If(o != null && o != TagData.REQUEST_TIME_VALUE) dN)!B!*aI  
&!pG1Fp9  
{ ZyQ+}rO  
.qjdi`v  
if( ( (String)o).toLowerCase().equals(“true”) || (fJ.o-LQ  
rxVJB3P9  
((String)o).toLowerCase().equals(“false”) ) W n43TSs-  
a="\?L5  
return true; 4RYvI!  
,V}Vxq3  
else .*>pD/  
v)AadtZ0d  
return false; r=o\!sh[  
FaUc"J  
} :0)nL  
-<GSHckD  
else 6*92I  
ka$oUB)iQ  
return true; "Yu';&  
+zup+=0e  
} '7Aj0U(  
ID1/N)5 6  
} f/Q7WXl0  
IR<`OA  
L% cr `<~  
带body的tag nB+ e2e&  
OG&X7>'3I{  
UPI'O %  
tag处理类 D^%DYp  
}*ZOD1j  
,{_;q:  
如果tag标签含有内容,那处理方式会略微有些不同,而且还要视tag处理类是否要与body交互的情况而定。如果要与body交互,那我们认为tag处理类要可能要对body进行操作。 -P5M(Rt  
\X?GzQkr  
Tag处理类不与body交互 9:l@8^_o  
R6KS&Ge_  
如果tag处理类不与body交互,tag处理类应该实现Tag接口或从TagSupport中派生,如果body要被计算,那么doStartTag方法应返回 EVAL_BODY_INCLUDE,否则应返回SKIP_BODY。 ==z,vxr  
;:)?@IuSy  
如果tag处理类要对body反复运算,则它应该实现IterationTag或从TagSupport中派生。如果tag处理类认为body还未计算完的话,那它的doStartTag方法和doAfterBody方法必须返回EVAL_BODY_AGAIN。 &InMI#0mV  
9 yE   
Tag处理类与body交互 gU^2;C  
j;+!BKWy4  
如果tag处理类与body交互,那tag处理类应实现BodyTag接口或从BodyTagSupport中派生。这种tag处理类一般要实现doInitBody和doAfterBody方法。 Ea7LPHE#  
4xE [S  
Body允许一些方法来读写它的内容。Tag处理类可以调用body内容的getString或getReader方法来从body中提取信息,也可用 writeOut(out) 方法来将body的内容写入到out对象中。其中out对象通过tag处理类的getPreviousOut方法来获得。 STxreW1  
(Z72 3)  
如果body的内容需要被计算,那么doStartTag方法必须返回EVAL_BODY_BUFFERED,否则,它将返回 SKIP_BODY。 AX= 4{b'  
s{]2~Z^2od  
doInitBody 方法 a#qC.,$A  
edW:(19}  
此方法在body内容已经设好,但未被计算之前被调用。你可以根据不同的body内容来制定初始化策略。 Z} 8 m]I  
0f<$S$~h  
doAfterBody方法 5yhfCe m|  
 h'_@  
此方法在body内容已被计算后进行调用。 1tNmiAu  
[$D4U@mRp  
和doStartTag方法一样,doAfterBody方法返回一个指示符指示是否要继续计算body,如果要继续计算,则doAfterBody应返回EVAL_BODY_BUFFERED,否则,它应返回SKIP_BODY。 mCY+V~^~kz  
1ukCH\YgU  
release 方法 'n)]"G|  
CA PP Oh  
tag处理类调用此方法将它的状态重置为初始状态,并释放所有的私有资源。 oNfNe^/T  
wv eej@zs  
JN Ur?+g  
以下的例子读取body的内容(其中含有一条sql语句),然后将它传递给一个对象,让它进行查询。由于此处body不须重新计算,所以doAfterBody会返回SKIP_BODY。 k^ZcgHHgb  
nd 5w|83  
 !AGjiP$  
Public class QueryTag extends BodyTagSupport E2D}F@<]  
h 'F\9t  
{ 5l&9BS&  
4X5Tyv(Dp  
public int doAfterBody() throws JspTagException EZ.|6oug\  
kZsat4r  
{ }8W5m(Zq9n  
S1R:/9 z  
BodyContent bc = getBodyContent(); nDh D"rc  
y^SDt3Am  
//将body的内容以字符串的格式提取出来 V+M=@Pvp9  
#!WD1a?L  
String query = bc.getString(); AxOn~fZ!  
hu G]kv3F:  
//清除body 1gZW~6a}  
6IVa(;  
bc.clearBody(); ;3D[[*n9  
,/qS1W(  
try{ D\Nhq Vw  
o$=D`B  
Statement stmt = connection.createStatement(); ?1f(@  
.\?)O+J!  
Result result = stmt.executeQuery(query); 2 P=c1;  
"[*W=6m0  
}catch(SQLException e){ z}" Xt=G?  
&mM[q 'V  
throw new JspTagException(“queryTag: “ + e.getMessage() ); 2[Ja|W\If  
k3 65.nc  
return SKIP_BODY; \*C}[D  
$ +`   
} Xiyh3/%yy  
jE !W&0  
} )i;o\UU  
5Z`9L| 3d  
.mse.$TK.^  
body-content元素 w<3g1n7R  
vPV=K+1  
%Tn0r|K  
由于tag可能会有body,你必须用body-content元素来指定body内容的类型: ,pgpu !  
nI-^   
<body-content>JSP|tagdependent</body-content> ;JK !dzi}  
<oE(I)r4,  
,DHiM-v  
如果body的内容是定制的或内部的tag、脚本元素、或HTML广本,则归类为JSP类型。其他的类型,比如上面代码所述的?D?D将sql statement类传给 query tag的这种类型应该标为tagdependent。 4;*o}E  
{hr+ENgV  
注意:实际上body-content的值并不影响tag处理类对body内容的处理,它仅仅是被tag编辑工具用来描述此body的内容。 Wa8?o~0"L  
@"6dq;"  
J(\]39y  
用tags定义脚本变量 m|RA@sY%`  
p.gaw16}>  
gX}(6RP_!  
tag处理类 Y+k)d^6r  
&wlSOC')j  
P(1 bd"Q  
tag处理类负责创建或设置页面中定义的脚本变量,用pageContext.setAttribute(name,value,scope)或pageContext.setAttribute(name,value)方法来实现。一般来说,tag处理类通过脚本变量的名称来获取它,脚本变量的名称一般可用get方法来获得。 pMB~Lt9  
5df~] -=0Y  
如果脚本变量的值依赖于tag处理类中的上下文中某一对象,那它可用pageContext.getAttribute(name,scope)方法来找到那个对象。一般的处理过程是tag处理类先找到脚本变量,再对其进行处理,然后用pageContext.setAttribute(name,object)的方法来设置它的新值。 {~"&$DY2  
2VNMz[W'  
对象的生存周期(scope)如下表: v$O%U[e<  
\` |*i$  
对象的生存周期表 A&$oiLc  
a-t}L{~  
名字 :\+;5Se+l  
可访问范围 Tn~b#-0  
生存周期 {jOCz1J  
Hd1e9Q,:|  
page ;t.LLd  
当前页面 8( ^;h2O!  
一直有效,除非页面向客户提交响应或重定向到一个新页面 >taC_f06  
#gw ys  
request o*OaYF'8  
当前页面或当前页面重定向到的页面 RtrESwtR  
一直有效,除非页面向客户提交响应 >k6RmN  
!$:lv)y  
session '$]u?m  
当前页面或在同一浏览器窗口中的页面 B u ~N)^  
一直有效,除非关闭当前浏览器、超时、网络故障 IT3xX=|b  
0 ttM_]#q  
application "Q:m0P xb  
整个web应用程序的所有请求 vGK'U*gGD  
一直有效,除非发生网络故障、服务器故障 /$7_*4e  
D (MolsKc?  
提供关于脚本变量的信息  )"im|9  
AeqxH1%  
以下示例定义了一个名为“book”的脚本变量,用来访问程序中关于书的信息: Z/-!-  
pU4 B6KTW  
<bean:define id=”book” name=”bookDB” property=”bookDetails” type=”database.BookDetails” /> O\64)V 0  
YQzs0t ,  
<font color=”red” size=”+2” > D&0@k'  
\BT8-}  
<%= messages.getString(“CartRemoved”) %> ZiBTe,;  
\X5>HPB  
<strong><jsp:getProperty name=”book” property=”title” /></strong> 7b,5*]oZ  
: QK )Ym  
</font> qwlIz/j  
7|A9  
当包含此tag的JSP页面被编译时,jsp引擎会自动生成关于此book的同步的代码(同步可以避免几个客户同时访问此book时造成的冲突),要生成同步代码,jsp引擎需要知道此脚本变量的如下信息: FK MuRy|  
PYldqY   
· 脚本变量名称 T@[(FVA N  
OY'490  
· 脚本变量所属的类 sLE@Cm]k  
:%M[|Fj  
· 此脚本变量是否引用了一个新的或已存在的对象 x0ZEVa0`4  
p{knQ],   
· 此脚本变量的有效性 E\5cb[Y  
w l.#{@J]<  
有两种办法可以向jsp引擎提供关于脚本变量的信息:在TLD中定义variable子元素,或用tei-class子元素定义一个额外tag信息类。用variable最简单,但可能降低了一些灵活性。 A$K>:Tt>  
;?/v}$Pa  
Variable元素 [p%@ pV  
^^[MDjNy@  
Variable元素有如下子元素: U*G9fpVy  
`!?SA<a:  
· name-given ?D?D 给出的名字,是一个常量 DP=4<ES%+  
?QGAiu0  
· name-from-attribute?D?D 属性名,在编译时给出的属性名 #P,mZ}G\  
b?#k  
name-given或name-from-attribute两者必须选一,但以下子元素是可选的: S ^?&a5{o  
>gAq/'.Q  
· variable-class?D?D变量的类型,缺省为java.lang.String。 KmoPFlw  
@\,WJmW  
· declare?D?D此脚本变量是否引用了一个新对象,缺省为True。 V j\1 HQ  
.6Swc?  
· scope?D?D脚本变量的范围,缺省为NESTED。下表描述了scope的几种类型: &8R%W"<K  
g{&a|NU^  
脚本变量的有效范围 :IFTiq5a;  
GdFTKOq  
"]}+QK_  
有效性 -ec ~~95  
方法 Las4ux[_  
B;A^5~b  
NESTED ][8ZeM9&p  
在tag标签的开始和结束之间 Xp <RG p7E  
如果tag处理类实现BodyTag接口,则在doInitBody和doAfterBody中调用,否则在doStartTag中调用 wv>uT{g#  
Z~}=q  
AT_BEGIN M{S7tMX  
从tag标签的开始一直到页面结束 30 Vv Zb  
如果tag处理类实现BodyTag接口,则在doInitBody、doAfterBody和doEndTag中调用,否则在doStartTag和doEndTag中调用 5b9v`6Kq  
$QQv$  
AT_END bd[zdL#4K  
从tag标签的结束一直到页面结束 o<f[K}t9  
在doEndTag中调用 _@3?yv~ D  
C' C'@?]  
以struts为例,它的bean:define标签的实现遵循JSP1.1规范,此规范要求使用额外tag信息类来定义脚本变量。Variable元素是JSP1.2规范中加入的。以bean:define标签为例,你可以定义如下variable元素: SRq0y,d  
Ea@N:t?(8=  
<tag> KDP7u  
[\NyBc  
<variable> /esSM~*H  
>#z*gCO5,  
<name-from-attribute>id</name-from-attribute> pEIc ?i*  
rf"%D<bb  
<variable-class>database.BookDetails</variable-class> *S.R#4w  
uX*H2"A  
<declare>true</declare> t?p[w&@M2  
KQ<pQkhv  
<scope>AT_BEGIN</scope> ,?;q$Xoi  
riqvv1Nce  
</variable> O/M\Q  
8=x{>&Jr&#  
</tag> yyJ4r}TE  
_K{hq<g  
额外tag信息类 *9}2Bmojv  
"J(#|v0  
如果要定义一个额外tag信息类,你要继承javax.servlet.jsp.TagExtraInfo类。一个TagExtraInfo类必须实现getVariableInfo方法,此方法返回一个叫VariableInfo的数组类,它包括如下信息: mBgMu@zt)  
}PGl8F !  
· 变量名 @)mH"u!(7  
4CO:*qG)o  
· 变量所属类名 (9x8,f0z  
)P\Vd #  
· 此变量是否引用了一个新对象 ,mH2S/<}S  
]Lq9Ompf(t  
· 此变量的有效范围 cCN[c)[c|  
L_uliBn  
jsp引擎将一个名为data的参数传给getVariableInfo方法,data中包括tag标签中的所有“属性名?D?D属性值”对。它可以用来向VariableInfo对象提供脚本变量的名字和类名。 O#Ab1FQn  
\?)@ #Qs  
以struts为例,它在bean:define标签中定义了一个名为DefineTei的额外tag信息类,用来向脚本变量提供信息。由于脚本变量的名称(book)和类名(database.BookDetails)是通过tag标签的属性来传递的,它们一般定义在VariableInfo的构建代码中,并且可用data.getAttributeString方法来得到这些信息。如果要允许book脚本变量能在从tag开始直到整个JSP页面结束的范围内都可用的话,那它的范围应设为AT_BEGIN。如下所示: 6P;JF%{J  
HaI  
T!eb=oy  
public class DefineTei extends TagExtraInfo Jq)!)={  
#imMkvx?  
{ {,p<!Jq~G  
5DKR1z:  
public VariableInfo[] getVariableInfo(TagData data) s  bV6}  
v/6QE;BY&Q  
{ 7>`QX%  
"YD<pRVB  
String type = data.getAttributeString(“type”); n'ft@7>%h  
{'8a' 9\  
If( type == null) P X ?!R4S  
:|xV}  
type = “java.lang.Object”; jvn:W{'Q  
%76N$`{u  
return new VariableInfo[] { n\ aG@X%oq  
f,z_|e  
new VariableInfo(data.getAttributeString(“id”), 'bj$ZM9  
OpmI" 4{+  
type, :WejY`}H%  
:i+Tf~k{  
true, Kr`Cr5v  
RP&H9>  
VariableInfo.AT_BEGIN) wYZFW'5p  
3B95t-  
}; -%"Kxe  
_ v\=ag  
} Y( n# =  
-#= v~vE  
} z>+@pj   
lil1$K: i  
a%DnRkRr  
注意:关于额外tag信息类的类名必须要在TLD中的tag标签下的tei-class子元素中定义。因此,DefineTei的tei-class中的定义看起来如下: D]resk  
<tei-class> 5=/H2T!F  
org.apache.struts.taglib.bean.DefineTagTei I$v* SeVHE  
</tei-class> 75}BI&t3k  
Yd:8i JA  
fLl~a[(5  
具有协作关系的tag ::N'tcZ^2  
"#^11o8  
4Y8/>uL  
tag通过共享对象来进行协作,JSP技术支持2种方式的对象共享。 A?'Tigi  
9r!psRA:`)  
第一种方法是使用pageContext对象进行对象的共享(可支持JSP页面和tag处理类之间的共享),如果在一个tag处理类中要调用由另一个tag处理类创建的对象,可调用pageContext.getAttribute(name, scope)方法。 <<K GS  
EXUjdJs"  
第二各方式的共享是对于tag之间有嵌套关系而言的,外层的tag所创建的对象对于内层的tag来说是可以共用的。这种形式的共享的好处是减少了可能存在的重名冲突。 5 rkIK  
W\gu"g`u  
要访问一个嵌套tag创建的对象,tag处理类必须先找到此嵌套tag对象,可用TagSupport的静态方法 TagSupport.findAncestorWithClass(from, class)或TagSupport.getParent方法。前者在当不确定此tag是否为嵌套tag对象时使用。一旦它的父类被找到,它就能访问其所有动态或静态创建的对象。静态创建的对象是父类的成员,而动态创建的对象可能是父类的私有对象。诸如此类的对象可以用tag处理类的setValue方法来保存,用getValue方法来获得。 U#R=y:O?  
]Ow A>fb  
下例阐述了以上两种共享对象的方法。在这个例子当中,一个查询tag检查一个名为connection的属性名是否在doStartTag中被设置。如果connection属性被设置,tag处理类从pageContext中得到这个connection对象。否则,此tag处理类先找到它的父tag处理类,然后从它的父tag处理类中找到connection对象。 7:t+  
Hj"`z6@7  
_c?&G`  
public class QueryTag extends BodyTagSupport J< BBM.^]  
b_@MoL@A!  
{ dM8`!~#&PI  
4v cUHa|4  
private String connectionId; yhg^1l|t,  
5Og.:4  
public int doStartTag() throws JspException ,Hn{nVU1R=  
OF'y]W&  
{ $NzD&b$7  
v)>R)bzqe  
String cid = getConnection(); 57^ X@ra$  
LC)-aw>-  
if(cid != null) |13UJ vR  
s,O:l0  
{ Q1?  !,a  
Nw'i;}0v7r  
//存在一个connection id,使用它。 Q)S0z2  
$+qJ#0OE$  
connection = (Connection) pageContext.getAttribute(cid); gH5E+J_$  
I5PI;t+  
} > f,G3Ay  
rkh+$*t@i7  
else :hB/|H*=  
~#+ Hhc(  
{  +T02AS  
^=@L(;Y  
ConnectionTag ancestorTag = (ConnectionTag)findAncestorWithClass(this, M \rW  
Kf#9-.}?  
ConnectionTag.class); S*<+vIo  
7<['4*u  
if(ancestorTag == null) Uc]S7F#  
X-O/&WRYQ  
{ CEjMHP$=  
fvg jqiT  
throw new JspTagException(“一个没有connection属性的查询标签必须被一个connection标记嵌套。”); M q;m+{B  
H@o 3u>}  
} Ha{#  
^%tmHDNL.  
connection = ancestorTag.getConnection(); G$&SlJZEk  
v:kTZB  
} ["VUSa  
"HSAwe`5jU  
} A46z2  
[`^5Zb  
} '=}F}[d"kk  
J P'|v"  
&y"e|aE  
Y}BT| "  
此查询标签在JSP页面中的调用形式可以从以下2种定义中任选一种: JJ_77i  
7xidBVx  
q_K8vGm4e  
<tt:connection id=”con01” ...> ... </tt:connection> A7,TM&  
R,?7|x  
<tt:query id=”balances” connection=”con01” > U 1!6%x  
s 8O"U%  
SELECT account, balance FROM acct_table <Uf?7  
^"N]i`dIF  
where customer_num = <%= request.getCustno() %> kX!TOlk3  
FY  U)sQ  
</tt:query> ,tBb$T)7<  
v;4l*)$)  
#wn`choT'  
H|&[,&M>  
w3oh8NRs_  
<tt:connection ...> Ux5pw  
f&x7g.I  
<x:query id=”balances”> \UZlFE  
2Ur9*#~kGp  
SELECT account, balance FROM acct_table DY| s |:d  
#1c%3KaZ I  
where customer_num = <%= request.getCustno() %> b`M  2VZu  
CYD&#+o  
</x:query> 8wJfG Y  
;G!JKg  
</tt:connection> oqeA15k$  
%!Z9: +;B  
{x$WBy9  
与此同时,在TLD中必须指定connection属性为可选的,定义如下: 3gN#[P  
P:,@2el  
<tag> eiE36+'>b  
zi M~V'  
... 0~2~^A#]\  
08*bYJu  
<attribute> t;g= @o9YA  
<49Gsm&0  
<name>connection</name> ?86q8E3;&  
A"Q6GM2;Io  
<required>false</required> LDilrG)  
h8#14?  
</attribute> ft$@':F  
'a8{YT4  
</tag>
描述
快速回复

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