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

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

级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
标准的JSP 标记可以调用JavaBeans组件或者执行客户的请求,这大大降低了JSP开发的复杂度和维护量。JSP技术也允许你自定义taglib,其实换句话说,taglib可以看成是对JSP标记的一种扩展,正如xml是对html的一种扩展一样。taglib通常定义在tag标签库中,这种标签库存放着你自己定义的tag标签。简而言之,如果使用taglib,那么你可以设计自己的JSP标记! P2pdXNV  
9HrT>{@  
一般来说,自定义tag标签主要用于操作隐藏对象、处理html提交表单、访问数据库或其它企业级的服务,诸如邮件和目录操作等等。自定义tag标签的使用者一般都是那些对java编程语言非常精通,而且对数据访问和企业级服务访问都非常熟悉的程序员,对于HTML设计者来说,使得他可以不去关注那些较复杂的商业逻辑,而将精力放在网页设计上。同时,它也将库开发者和库使用者进行合理分工,自定义tag标签将那些重复工作进行封装,从而大大提高了生产力,而且可以使得tag库可用于不同的项目中,完美地体现了软件复用的思想。 HpY-7QTPJ~  
o^FlQy\  
在这篇文章中,我们主要讨论: Aon 3G  
L#mf[a@pCn  
· 什么是自定义tag标签? $(B|$e^:(  
UIgs/  
· 怎么使用tag标签? RhR{EO  
7{>mm$^|V  
o 声明要使用的tag库 =]jc{Y%o  
#&<>|m  
o 找到与之对应的tag处理类 ,Z*&QR  
? cU9~=  
o tag标签的类型 5<ZE.'O  
"j-Z<F]]  
· 自定义tag标签 xa#;<8 iV  
Pj(Dl C7G,  
o tag处理类 hB/4.K]8  
k?]`PUrV  
o tag库描述 BUB$k7{z  
Gy 0 m  
o tag标签示例 B8A-|S!,U  
r Q)?Bhf  
o 带属性的tag APY^A6^:j  
MYNNeO  
o 带body的tag e$kBpG"D  
SR)jJ=R3  
o 定义了脚本变量的tag SQ&nQzL  
iQs^2z#Bd  
o 具有协作关系的tag ZcJa:  
ybk~m  
· 自定义tag标签 Y$JGpeq8w  
L_4c~4  
o 一个迭代tag的例子 Z*uv~0a>9Q  
u}_,4J  
o 一个模板tag库 xib?XzxGo  
_[%2QwAUj*  
o tag处理类到底是怎样被调用的? 'k^d-Mh>h  
 vVvx g0  
X=C*PWa7  
什么是自定义的tag? \vg(@)$q   
Oly"ll*K  
一个自定义的tag标签是用户定义的一种JSP标记。当一个含有自定义的tag标签的JSP页面被jsp引擎编译成servlet时,tag标签被转化成了对一个称为tag处理类的对象进行的操作。于是当JSP页面被jsp引擎转化为servlet后,实际上tag标签被转化成为了对tag处理类的操作。 |!t &ZpdD  
FR*CiaD1  
自定义tag标签有很多特色,诸如: zEM  c)  
sr S2v\1:  
· 可以在JSP页面中自定义tag标签的属性 GgT 5'e;N  
0FN;^hP5|  
· 访问JSP页面中的所有对象 stxei 6  
~,Y xUn8@  
· 可以动态地修改页面输出 S7!+8$2mc_  
%_P[ C}4  
· 彼此这间可以相互通信。你可以先创建一个JavaBeans组件,然后在一个tag中调用此JavaBeans组件,同时可以在另一个tag中调用它。 zv%]j0 ?  
z6'Cz}%EP'  
· tag允许相互嵌套,可以在一个JSP页面中完成一些复杂的交互。 ~Un+Zs%24  
7C;oMh5  
|.#G G7F^S  
使用tag标签 Fal##6B  
nu(;yIRP  
WHF[l1  
本节主要描述怎样在JSP页面中使用tag标签,以及tag标签的不同类型。 W( 4Mvd  
isBtJ7\Sc  
要使用tag标签,JSP程序员必须做2件事: 8(3n v[  
9ZJn 8ki  
· 声明此tag标签的tag库 iY,Ffu E  
NZb}n`:  
· 实现此tag标签 omP\qOc  
B}(r>8?dm  
声明tag标签所在的tag库 M&[bb $00j  
&xWej2a!  
如果要使用tag标签,则应用JSP的taglib指示符来指定其tag库(注意:taglib要在在使用此tag标签之前声明) d6+$[4w  
:kMF.9U:  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> ikd1KF+I  
FG:t2ea  
uri属性定义了唯一的标签库描述(以下简称TLD),它可以是直接是tld文件名或一个独一无二的名字。prefix是用来区别其它TLD中和本TLD中有重名的tag的一种手段。 8P?p  
ROhhd.  
TLD必须以.tld作为扩展名,并且存放在当前应用的WEB-INF目录或其子目录下。你可以通过它的文件名直接引用它,也可以通过别的方式间接地引用它。 u<['9U  
,*kh{lJ  
以下taglib指示符直接引用一个TLD: MvKr~  
c4f3Dr'xw  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> 6!Q,X Hs  
WR"?j 9y_q  
以下的taglib指示符通过一个逻辑名称间接地引用一个TLD: x%'5 rnm|  
bu8AOtY9E-  
<%@ taglib uri=”/tutorial-template” prefix=”tt” %> .fgVzDR|+  
f6,?Yex8B  
如果是间接引用TLD的话,那你必须还要在web.xml中定义此逻辑名称与tld文件之间的映射,具体做法是在web.xml中加入一个名为taglib的元素: J))U YJO  
/:;"rnvq  
<taglib> rT|wZz9$@  
^~1Z"kAnT  
<taglib-uri>/tutorial-template</taglib-uri> <y=+Gh  
.3'U(U  
<taglib-location> 50CjH"3PZ`  
8|{d1dy  
/WEB-INF/tutorial-template.tld 9vckQCLM  
Z8ds`KZM  
</taglib-location> eakQZ-Q  
2b/Cs#-  
</taglib> BR-4L2[  
!%'"l{R  
yNhRh>l  
实现此tag标签 ?J@P0(M#  
g/ 4ipcG;N  
\ZtKaEXnx  
为了实现tag标签,你有2种方法来存放tag处理类。一、让tag处理类以.class的方式存放于当前应用的WEB-INF/class子目录下,二、如果tag处理类是以JAR包的形式存在的话,那可以放在当前应用的WEB-INF/lib目录下,如果tag处理类要在多个应用中共享,那么它就应放在jsp服务器上的common/lib目录下,对于tomcat来说,就是tomcat/common/lib目录下。 !C@+CZXLx  
(h|E@gRa  
^kK% 8 u  
tag标签类型 1+#E|YWJ  
sDB,+1"Y$  
Vb)NWXmyu  
自定义的tag标签遵循XML语法。它有一个开始标记和一个结束标记,有的还有body(即文本节点): twox.@"U  
NRT@"3,1YP  
<tt:tag> qfX26<q  
&I:ZJuQ4  
body h=4 GSU  
iS< ^MD  
</tt:tag> 81H9d6hqcD  
$)eS Gslz  
`n RF"T_  
一个不带body的tag标签如下: g2?yT ?  
M0T z('~s  
<tt:tag /> F5y&"Y_  
BV6B:=E0  
of {K{(M7@  
简单的tag标签 4y.qtiIP>$  
DkSs^ym  
一个没有body和属性的tag标签如下: A&A{Thz  
4Y{;%;-i  
<tt:simple /> eM@xs<BR  
lD{*Z spz  
D"2bgw  
带属性的tag标签 oQ A,57B  
BT`g'#O  
.K]Uk/W  
自定义标签可以有自己的属性。属性一般在开始标记中定义,语法为 attr=”value”。属性的作用相当于自定义标签的一个参数,它影响着tag处理类的行为。你可以在TLD中详细定义它。 ROXa/  
^]D+H9Tl  
你可以用一个String常量给一个属性赋值,也可以通过表达式给它赋值,如<%= ...%>。以struts为例,它的logic:present标签就是用的String常量来给属性赋值: PuhvJHT  
"lrQC`?  
<loglic:present parameter = “Clear”> gWL`J=DiU  
>=:^N-a  
而另一个标签logic:iterate是用表达式来给属性赋值:  d0i|^  
,"F0#5  
<logci:iterate collection=”<%= bookDB.getBooks() %>” +&dkJ 4g[  
:>/6:c?atG  
id=”book” type=”database.BookDetails”> :[CEHRc7x  
*<[zG7+&[  
, 6Jw   
带body的tag标签 m\XG7uo~  
Zu<S<??Jf  
一个自定义标签可以包含其它自定义标签、脚本变量、HTML标记或其它内容。 V/:2xT  
(tX)r4VU  
在下述例子中,此JSP页面使用了struts的logic:present标签,如果些标签定义了parameter=”Clear”的属性,则将清除购物车的内容,然后打印出一条信息: gX7R-&[UD  
t-5 Y,}j  
<logic:present parameter=”Clear”> &r,)4q+  
!.-u'6e  
<% cart.clear(); %> Ndmw/ae  
B,&QI&k`~  
<font color=”#ff0000” size=”+2”><strong> E NCWOj  
O;5lF  
你选择了清除购物车! HOF=qE*p  
3m9b  
</strong></font> :5.F  
Nu OxEyC  
</logic:present> FE]UqB  
YRCs&tgs  
[q C0YM  
到底是用属性还是用body来传递信息? ]31=8+D  
hSR+7qN<e  
如上所述,我们既可以通过属性,也可以通过body来传递信息。但一般来说,比较简单的类型,如字符串或简单表达式最好采用属性来传递信息。 7(oA(l1V  
sei2\l8q  
"wuO[c&%/  
定义脚本变量的tag标签 R&BWCC{  
lG Bg8/[  
所谓脚本变量,是指JSP中可以调用的变量或对象。它可由tag标签产生。以下示例阐述了一个tag标签定义了一个名为tx的由JNDI所定义的事务处理对象。脚本变量可以是ejb对象、事务、数据库连接等等: p:K%-^  
F>3 o0ke}  
<tt:lookup id=”tx” type=”UserTransaction” name=”java:comp/UserTransaction” /> <9piKtb|L  
."=%]l 0  
<% tx.begin(); %> cJv/)hRaz  
,[t? $Cy ;  
... beC%Tnb7  
SOOJqC  
1YJ?Y  
具有协作关系的tag标签 # =tw ,S  
)dqNN tS  
自定义tag标签之间可以通过共享对象来实现协作。在下述例子中,标签tag1创建了一个名为obj1的对象,在标签tag2仍可以重复使用obj。 > *VvV/UU  
S2;^  
<tt:tag1 attr1=”obj1” value1=”value” /> C}pm>(F~  
\~z$'3H`  
<tt:tag2 attr1=”obj1” /> 5lJL[{  
abm 3q!a-  
在以下这个例子当中,如果外层的tag标签创建了一个对象,那么其内层的所有tag标签都可以使用这个对象。由于这样产生的对象没有一个指定的名字,那么就可以将少重名的冲突。这个例子阐述了一系列协作的嵌套对象。 -{ 1P`&G  
7U_ob"`JV  
<tt:outerTag> FRZ]E)9Z]b  
-l57!s~V  
<tt:innerTag /> m7g*zu2#  
1(dKb  
</tt:outerTag> t@9-LYbL  
7/51_=%kR  
NytTyk)  
Tag处理类 !?0C(VL(:  
g:a[N%[C  
|[Fb&x  
Tag处理类必须实现Tag接口或BodyTag接口,不过现在一般都流行从TagSupport或BodyTagSupport类中继承,这些类或接口都可以在javax.servlet.jsp.tagext包中找到。 |xcC'1WU  
q%e'WMG~n  
当JSP引擎看到自己的JSP页面中包含有tag标签时,它会调用doStartTag方法来处理tag标签的开头,调用doEndTag方法来处理tag标签的结束。 ~M-L+XZl(  
2=n`z) R  
下表说明不同类型的tag所需要不同的处理过程: 6bhb_U'f  
Y;_F,4H  
Tag处理类的方法 <tF q^qB  
1:](=%oM&k  
Tag标签类型 ~Yi4?B<  
所调用的方法 4RB%r  
#eOHe4Vt  
基本标签 8Iw)]}T'  
doStartTag, doEndTag, release P@ew' JL%  
} SW p~3P  
带属性的标签 Ovk=s,a)K  
doStartTag, doEndTag, set/getAttribute1...N, release V~j^   
CU\gx*=E  
带内容的标签 x>Q% hl  
doStartTag, doEndTag, release vw;a L#PP  
t e-xhJ&K  
带内容的标签,且内容重复循环 !>> A@3  
doStartTag, doAfterBody, doEndTag, release cYK:Y!|`F  
%'s_ =r`  
带内容的标签,且内容与JSP交互 (KyOo,a  
doStartTag, doEndTag, release, doInitBody, doAfterBody, release 2e%\aP`D2  
E-.X%xfO  
一个tag处理类可以通过javax.servlet.jsp.PageContext来与JSP交互,通过javax.servlet.jsp.PageContext类,tag处理类可以访问JSP中的request、session和application对像。 5H XF3  
sED"}F)  
如果tag标签是互相嵌套的,那内层的tag处理类可以通过它的parent属性来访问上层的tag处理类。 ?[zw5fUDS  
?8H{AuLB  
一般情况都将所有的tag处理类打成了JAR的包,以便于发布。 zu{K"7Bx  
4z( B`t~7  
rIcgf1v70  
Tag库描述(简称TLD) z+Fu{<#(  
"NLuAB. P  
s=(q#Z  
Tag库是用xml语言描述的,TLD包括了tag库中所有tag标签的描述,它一般用来被jsp服务器用来校验tag的语法正确性,或者被jsp开发者用来开发新的标签。 (Q=o 9o:b  
OS@uGp=  
TLD的文件扩展名必须为.tld,而且必须放在当前WEB应用的WEB-INF目录或其子目录中。 ]dNNw`1\V  
R&.&x'<  
一个TLD的内容的开头必须遵守标准的XML开头,用于描述DTD和xml的版本,例如: 5s3QN{h8  
Y,0Z&6 <  
<?xml version="1.0" encoding="ISO-8859-1" ?> #W)m({}  
lb'tVO  
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd"> uxD3+Q  
TLD必须以<taglib>来作为它的根元素,<taglib>的子元素如下表: S!u8JG1  
aq_K,li #w  
7>gjq'0  
<taglib>的子元素 _J6 Xq\  
|8CxMs  
Element W..*!UGl  
Description jdJTOT  
E Ou[X'gLr  
tlib-version ,M{G X  
Tag库的版本 tNr'@ls  
3S+9LOrhY  
jsp-version MF<ZB_@  
Tag库所需要的jsp的版本 $aJ6i7C,j}  
*:xOenI  
short-name J";N^OR{A%  
助记符,tag的一个别名(可选) } uS0N$4  
Y|r7gy9%  
uri Fdhgm{Y2s  
用于确定一个唯一的tag库 ZtO$kK%q;  
<!>\ n\A  
display-name [G$#jUt/O  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) J/e]  
.o`Io[io  
small-icon $k0(iFzR1  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) 9qCE{ [(  
k/{WlLN  
large-icon ]P wS3:x  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) YOLzCnI4  
.kU^)H" l  
description ow9a^|@a  
对tag库的描述(可选) \ZADY.ha  
5GScqY,aB  
listener >R]M:Wx  
参见下面listener元素 b)'CP Cu*  
RKzty=j4  
tag ,o n]Fts  
参见下面tag 元素 1Z c=QJw@  
kE<CuO  
Listener元素 /5Qh*.(S  
W !j-/ql  
一个tag库可能定义一些类做为它的事件侦听类,这些类在TLD中被称为listener 元素,jsp服务器将会实例化这些侦听类,并且注册它们。Listener元素中有一个叫listener-class的子元素,这个元素的值必须是该侦听类的完整类名。 n-8/CBEH(  
 Ll; v[Y  
Tag元素 9#U]?^DJ@  
o%~fJx:]y  
每个tag元素在tag库中都要指出它的名字、类名、脚本变量、tag的属性。其中脚本变量的值可以直接在TLD中定义或通过tag附加信息的类来取得。每个属性描述了这个属性是否可以省略,它的值是否可以通过<%= …%>这样的JSP语法来获得,以及属性的类型。 &zy%_U2%  
_1E c54D  
每一个tag在TLD中对应一个tag元素,下表是tag元素的子元素: "|Q.{(|kO1  
1+$F= M~  
Tag元素的子元素 jw{N#QDh  
BkB _?^Nv8  
元素名称 <rgK}&q  
描述 C8|Ls(4Ck  
36OQHv;&  
name id9QfJ9t  
独一无二的元素名 7<]&pSt=  
c>D~MCNxg  
tag-class .q MxShUU  
Tag标签对应的tag处理类 neM)(` gp  
y%%VJ}'X!  
tei-class .TA)|df ^  
javax.servlet.jsp.tagext.TagExtraInfo的子类,用于表达脚本变量(可选) sG#Os  
H6`k%O*  
body-content c\o_U9=n  
Tag标签body的类型  DlCN  
rT4Q^t"  
display-name MV$E_@pg  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) YQ:$m5ai  
" J9  
small-icon W[J2>`k9  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) )x\%*ewY  
N~/X.D4e#  
large-icon I>.pkf<V  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) TW& s c9  
YM;ro5_KF  
description =Ks&m4  
此tag标签的描述 $=\=80u/  
=:g\I6'a  
variable -x6_HibbD  
提供脚本变量的信息(同tei-class)(可选) 7#"NKxb  
Y S7lB  
attribute KtAEM;g  
Tag标签的属性名 I52nQCXi  
c}OveR$'&  
以下章节介绍对于不同类型的tag,如何具体地实现它们。 I \1E=6"  
dl=)\mSFjF  
4ZUtK/i+r  
简单的tag <fBJ@>  
AoGpM,W]5  
yj_/:eX  
tag处理类 SPb`Q"  
^3sv2wh^|8  
简单的tag处理类必须实现Tag接口的doStartTag和doEndTag方法。当jsp引擎碰到tag标签的开头时,doStartTag被调用,因为简单的tag没有body,所以此方法将返回 SKIP_BODY。当jsp引擎碰到tag标签的结尾时,doEndTag被调用,如果余下的页面还要被计算,那它将返回EVAL_PAGE,否则将会返回SKIP_PAGE。 t9<BQg  
a+z>pV|  
以下是例子:对于标签 <tt:simple /> ,它的tag处理类实现如下: Y_]y :H  
~ a 2A"#f  
z<t2yh(DF  
public SimpleTag extends TagSupport %6fnL~ A  
lv] U)p  
{ k2->Z);X  
*fi`DiO  
public int doStartTag() throws JspException BIMX2.S1o  
,O.iOT0=;  
{ @)Vb?|3  
ozS'n]8*  
try{ B_Gcz5  
_\dC<K *>  
pageContext.getOut().print(“Hello.”); \``w>Xy8  
?-&k?I  
}catch(Exception e){ 'Sd+CXS  
G $*=9`  
throw new JspTagException(“SimpleTag: “ + e.getMessage()); (Q `Ps /  
ok,O/|E}?  
} (@T{ [\  
C-49u<; ,  
return SKIP_BODY; e 0$m<5  
.I{u[ "  
} cc=_KYZ1k  
p{qA%D  
public int doEndTag() r.LOj6c  
,?K5/3ss  
{ jbg9 EtQ!*  
:O,,fJ<x.O  
return EVAL_PAGE; x=K'Jj  
yIpgZ0:h  
} CO ZfR~}  
-{?xl*D  
} !f!YMpN  
w5-^Py  
* kL>9  
注意:如果tag标签没有内容的话,那必须定义body-content元素为空,例如 iH>JR[A  
(Ww SisC~  
<body-content>empty</body-content> DKlHXEt>  
<#Fex'4  
=fy.'+  
带属性的tag标签
评价一下你浏览此帖子的感受

精彩

感动

搞笑

开心

愤怒

无聊

灌水
级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
只看该作者 1 发表于: 2007-01-01
tag处理类 (hY^E(D  
5(\[Gke  
对于tag标签的每个属性,你必须依照JavaBeans规范来定义其属性,以及get和set方法。以struts的logic:present 标签为例, oY@]&A^ah  
aO<H!hK  
<logic:present parameter=”Clear”> FzBny[F  
p7*7V.>X  
与此相应,此tag处理类应有如下方法和定义: ybB<AkYc  
`lO/I+8  
{#{nU NW  
protected String parameter = null; D{t0OvQag  
uMC0XE|S  
public String getParameter() (ubK i[)  
B)-P# ,}  
{ 8,m:  
/hyCR___  
return this.parameter; I|mxyyf  
%ZlnGr  
} ! }awlv;  
XoiZ"zE  
public void setParameter(String parameter) YGq-AB  
0*u X2*  
{ eR8>5:V_  
.aIFm5N3?  
this.parameter = parameter; Yr:$)ap  
&cx]7:;  
} K;f=l5  
a@gm r%C  
23UXOY0BW  
注意:如果你的属性名为id,而且你的tag处理类是从TagSupport类继承的,那你就不需要定义它的属性和set和get方法,因为他们早已在TagSupport被定义过了。 OoAZ t  
v\COl*  
Attribute元素 m9m~2   
~_SVQ7P  
对于tag标签的每个属性,你必须定义它是否必须的,它的值是否可以用诸如<%= …%>的表达式来获得,以及它的类型(可选),如果不指定它的类型,那就默认为是java.lang.String类型。如果rtexprvalue元素被定义为true或yes,那么在type元素中就定义了attribute的返回类型。 p WKpc  
IRDD   
<attribute> O[')[uo8s  
[6Nzz]yy  
<name>attr1</name> }4I;<%L3`  
x6*.zo5e  
<required>true|false|yes|no</required> ,%]s:vk[u  
j(=zc6m  
<rtexprvalue>true|false|yes|no</rtexprvalue> qS2]|7q?Tc  
/K#J63 ,  
<type>attribute的返回类型(只用当rtexprvalue为真是才有效)</type> \"@`Rf   
9!6yo  
</attribute> |=}v^o ZC  
,}42]%$ G  
如果tag的某个属性不是必须的,那tag处理类会自动提供一个缺省值。 }\\6"90g*  
WN?meZ/N/  
例如,在logic:present这个tag标签中定义了一个属性叫parameter,但它不是必须的,而且它可以被诸如<%= …%>的表达式来赋值。 vui{["  
nnO@$T  
<tag> fYv{M;  
('px X+  
<name>present</name> ( G6N@>V(`  
./;*L D  
<tag-class>org.apache.struts.taglib.logic.PresentTag</tag-class> j k}m  
1&}^{ Ys  
<body-content>JSP</body-content> /%GMbO_  
Y_Lsmq2!  
4.mbW  
ui6B  
<attribute> @$'1  
D+  **o  
<name>parameter</name> #[#dc]D  
gBG.3\[  
<required>false</required> :O}<Q  
rJm%qSZz  
<rtexprvalue>true</rtexprvalue> -0doL ^A  
wbId}!  
</attribute> W\<5'9LNb  
YR`Mi.,Sfm  
D r$N{d  
K\ \U F  
</tag> .*g;2.-qv&  
i=<(fq  
" ,rA  
属性元素的校验 }a_: oR  
jWW2&cBm\  
*lG$B@;rc|  
有关于tag标签的有效值可以从tag库的说明文档中获得,当JSP页面被编译时,jsp引擎会强制性地参照TLD中定义的规则进行检查。 6dmTv9e  
afc?a-~Z  
还有一个方法也可以进行属性元素的校验,就是先继承类TagExtraInfo,然后调用它的isValid方法。这个类同时也起到提供tag中定义的脚本变量信息的作用。 Z{n7z$s*  
i9M6%R1m}E  
IsValid方法通过TagData对象来传递属性信息,它包括着tag的所有的属性名-值的信息。由于校验发生在运行时刻,因此这个属性的值将被赋值为TagData.REQUEST_TIME_VALUE。 Yazpfw 7'd  
$P@P}%2  
例如tag标签<tt:twa attr1=”value1” />在TLD中定义如下: Urx gKTry  
Ck.GN<#-^P  
<attribute> s}9aZ  
}%R6Su]y  
<name>attr1</name> xI~\15PhG  
^J~}KOH  
<required>true</required> _L!"3  
1ck2Gxn  
<rtexprvalue>true</rtexprvalue> Z?hBn`.  
g}qK$>EPS  
</attribute> {YbqB6zaM  
w-CuO4P  
a3lo;Cfp  
这个定义说明了attr1能在运行期间被赋值。 uR)@v^$FE  
$C)@GGY  
以下的isValid方法检查attr1属性的值是否属于Boolean类型。注意由于attr1能在运行刻被赋值,那么isValid方法必须检查tag用户是否对此tag进行了运行时刻赋值。 +ic~Sar  
!P92e1  
l2`8]Qr   
Public class TwaTEI extends TagExtraInfo {2:H`|x  
d=4MqX r  
{ "msg./iC  
;LrKXp  
public boolean isValid(Tagdata data) v*BA\&  
Iwn@%?7  
{ ?I@3`?'  
7_Q86o  
Object o = data.getAttribute(“attr1”); Y]gt86  
iGU N$  
If(o != null && o != TagData.REQUEST_TIME_VALUE) Vd1K{rH#  
*<A;jP  
{ rP\ 7C+  
\qTn"1b Q  
if( ( (String)o).toLowerCase().equals(“true”) || W>Rv  
Z.mV fy%  
((String)o).toLowerCase().equals(“false”) ) v S+~4Q41  
+`4}bc ,G  
return true; 0'~b<>G%  
~fUSmc  
else YI|G pq  
,/ig8~u'c  
return false; q,(&2./  
O#U"c5%  
} Cg|uHI*  
C1do]1VH  
else 7S7!  
T8(wzs  
return true; Ni)#tz_9  
&Egn`QU  
} m{5$4v,[  
AP7W)S  
} QO>*3,(H,q  
[;2:lbPx  
v}Nx*%  
带body的tag %N  
7fE V/j  
PmY:sJ{M  
tag处理类 2&d&$Jg  
m pivg  
(j I|F-i  
如果tag标签含有内容,那处理方式会略微有些不同,而且还要视tag处理类是否要与body交互的情况而定。如果要与body交互,那我们认为tag处理类要可能要对body进行操作。 :V2 Q n-N  
iL gt_@g  
Tag处理类不与body交互 !491 \W0ZH  
[-gKkOT8E  
如果tag处理类不与body交互,tag处理类应该实现Tag接口或从TagSupport中派生,如果body要被计算,那么doStartTag方法应返回 EVAL_BODY_INCLUDE,否则应返回SKIP_BODY。 7EO&:b]  
K{ P#[X*5  
如果tag处理类要对body反复运算,则它应该实现IterationTag或从TagSupport中派生。如果tag处理类认为body还未计算完的话,那它的doStartTag方法和doAfterBody方法必须返回EVAL_BODY_AGAIN。 *!/#39  
|K-lg rA  
Tag处理类与body交互 6V?RES;X  
7 tpZE+OX  
如果tag处理类与body交互,那tag处理类应实现BodyTag接口或从BodyTagSupport中派生。这种tag处理类一般要实现doInitBody和doAfterBody方法。 ]e`_.>U  
eM"mP&TTL  
Body允许一些方法来读写它的内容。Tag处理类可以调用body内容的getString或getReader方法来从body中提取信息,也可用 writeOut(out) 方法来将body的内容写入到out对象中。其中out对象通过tag处理类的getPreviousOut方法来获得。 B3t>M) 9  
>[: 2  
如果body的内容需要被计算,那么doStartTag方法必须返回EVAL_BODY_BUFFERED,否则,它将返回 SKIP_BODY。 oI~Qo*4eh  
7qz-RF#s8  
doInitBody 方法 9tEKA|8  
@R&D["!  
此方法在body内容已经设好,但未被计算之前被调用。你可以根据不同的body内容来制定初始化策略。 5; [|k$ v  
EI.Pk>ZIm  
doAfterBody方法 O*{H;7Pv  
g0OS<,:  
此方法在body内容已被计算后进行调用。 6<$|;w-OV  
xm0#4GFUS  
和doStartTag方法一样,doAfterBody方法返回一个指示符指示是否要继续计算body,如果要继续计算,则doAfterBody应返回EVAL_BODY_BUFFERED,否则,它应返回SKIP_BODY。 RT"2Us]*  
:t S"sM  
release 方法 I?g__u=n~  
r(T/^<  
tag处理类调用此方法将它的状态重置为初始状态,并释放所有的私有资源。 WN/#9]` P  
mZVOf~9E  
'm5(MC,  
以下的例子读取body的内容(其中含有一条sql语句),然后将它传递给一个对象,让它进行查询。由于此处body不须重新计算,所以doAfterBody会返回SKIP_BODY。 }C"*ACjF   
l1Q+hz5"*U  
PB67 ?d~  
Public class QueryTag extends BodyTagSupport 6CmFmc,  
2\\3<  
{ G?d,$NMo|  
0P40K  
public int doAfterBody() throws JspTagException )9*3^v  
r{R7"  
{ ~o'#AP#N~  
\u-e\w  
BodyContent bc = getBodyContent(); 7jH`_58  
K!c@aD:#  
//将body的内容以字符串的格式提取出来 H!.D2J   
kz;_f  
String query = bc.getString(); 51 +M_ ~  
qZsddll  
//清除body UZ\*]mxT  
y*b.eO  
bc.clearBody(); 5 t`ap  
mhLRi\[c )  
try{ ?g;ZbD  
%SO%{.}Z f  
Statement stmt = connection.createStatement(); SslY]d]  
jc.JX_/  
Result result = stmt.executeQuery(query); wV[V#KpX8-  
}j(2Dl  
}catch(SQLException e){ -y*_.Ws9  
k gu[!hD1  
throw new JspTagException(“queryTag: “ + e.getMessage() ); /3[ 9{r  
c\MsVH2 |  
return SKIP_BODY; XCIa2Syo  
r%,H*DOu  
} ff}a <w  
 4SffP/  
} Lcs{OW,  
,#bb8+z&p  
'#N5i  
body-content元素 $?)3&\)R  
U7"BlT!V\  
lke~>0;  
由于tag可能会有body,你必须用body-content元素来指定body内容的类型: ytve1<.Ff  
ft/^4QcyAM  
<body-content>JSP|tagdependent</body-content> 5M Wvu,'%8  
u.kYp  
=`1m-   
如果body的内容是定制的或内部的tag、脚本元素、或HTML广本,则归类为JSP类型。其他的类型,比如上面代码所述的?D?D将sql statement类传给 query tag的这种类型应该标为tagdependent。 SCurO9RN  
YXzZ-28,<  
注意:实际上body-content的值并不影响tag处理类对body内容的处理,它仅仅是被tag编辑工具用来描述此body的内容。 -H4+ur JJ  
\POnsM)+l  
iTLW<wG  
用tags定义脚本变量 '8l yj&  
!b7'>b'J<1  
3@yTzaq6  
tag处理类 G;Wkm|  
JEsLF{  
`.>k)=F&  
tag处理类负责创建或设置页面中定义的脚本变量,用pageContext.setAttribute(name,value,scope)或pageContext.setAttribute(name,value)方法来实现。一般来说,tag处理类通过脚本变量的名称来获取它,脚本变量的名称一般可用get方法来获得。 W{A #]r l  
|)-|2cPRur  
如果脚本变量的值依赖于tag处理类中的上下文中某一对象,那它可用pageContext.getAttribute(name,scope)方法来找到那个对象。一般的处理过程是tag处理类先找到脚本变量,再对其进行处理,然后用pageContext.setAttribute(name,object)的方法来设置它的新值。 If-,c^i  
z+k=|RMau  
对象的生存周期(scope)如下表: /bmXDDYH4  
RVkU+7  
对象的生存周期表 l`b1%0y  
qx2E-PDL;<  
名字 V#NG+U.B  
可访问范围 e"fN~`NhY  
生存周期 b " ")BT  
j2 }  
page FjZc#\^9  
当前页面 /mn-+u`K  
一直有效,除非页面向客户提交响应或重定向到一个新页面 w; 4jx(  
bo@,4xw  
request )N" Ew0U  
当前页面或当前页面重定向到的页面 <b d1  
一直有效,除非页面向客户提交响应 7v_i>_m]  
bmOqeUgB  
session >ZT& `E  
当前页面或在同一浏览器窗口中的页面 u5w&X8x  
一直有效,除非关闭当前浏览器、超时、网络故障 wG1y,u'  
>Mvka;T]  
application j8GY`f#  
整个web应用程序的所有请求 Kt W6AZJ  
一直有效,除非发生网络故障、服务器故障 T[;; 9z  
mn]-rTr  
提供关于脚本变量的信息 Vb@ 4(Q  
A4G,}r *n  
以下示例定义了一个名为“book”的脚本变量,用来访问程序中关于书的信息: kE/`n],1U  
TUh&d5a9H  
<bean:define id=”book” name=”bookDB” property=”bookDetails” type=”database.BookDetails” /> "S5S|dBc  
vSOT*0r  
<font color=”red” size=”+2” > 0YzsA#yv  
TQP+>nS,  
<%= messages.getString(“CartRemoved”) %> `SV"ElRV  
$<B +K  
<strong><jsp:getProperty name=”book” property=”title” /></strong> +TC1nkX  
N.Dhu~V  
</font> .xO _E1Ku;  
\6sqyWI %  
当包含此tag的JSP页面被编译时,jsp引擎会自动生成关于此book的同步的代码(同步可以避免几个客户同时访问此book时造成的冲突),要生成同步代码,jsp引擎需要知道此脚本变量的如下信息: b~7Jh:%@;  
,c>N}*6h=W  
· 脚本变量名称 AZ[75>  
6*IpAIh  
· 脚本变量所属的类 (;a B!(_  
9UwLF`XM  
· 此脚本变量是否引用了一个新的或已存在的对象 9)`amhf>  
9)+@0fG)  
· 此脚本变量的有效性 ;7Y[c}V1^  
$>*Yhz `  
有两种办法可以向jsp引擎提供关于脚本变量的信息:在TLD中定义variable子元素,或用tei-class子元素定义一个额外tag信息类。用variable最简单,但可能降低了一些灵活性。 Ekv89swl`i  
mwh{"FL(  
Variable元素 Py|;kF~![  
rK7W(D}  
Variable元素有如下子元素: #'@i lk/.  
ak;6z]f8[  
· name-given ?D?D 给出的名字,是一个常量 MIq"Wy|Zs  
\fZiL!E^7  
· name-from-attribute?D?D 属性名,在编译时给出的属性名 {.st`n|xz  
-v+&pG?m  
name-given或name-from-attribute两者必须选一,但以下子元素是可选的: q-nER<  
i9rS6<V'  
· variable-class?D?D变量的类型,缺省为java.lang.String。 ?}}qu'N:N  
@x1 %)1  
· declare?D?D此脚本变量是否引用了一个新对象,缺省为True。 vJ"i.:Gf4  
 G2`${aMS  
· scope?D?D脚本变量的范围,缺省为NESTED。下表描述了scope的几种类型: u%u&F^y  
}aF  
脚本变量的有效范围 ~i ,"87$[  
^T6S()G  
gbDX7r-  
有效性 {$d<1y^  
方法 j8++R&1f]  
` #OSl  
NESTED \'Ssn(s  
在tag标签的开始和结束之间 2N5`'  
如果tag处理类实现BodyTag接口,则在doInitBody和doAfterBody中调用,否则在doStartTag中调用 bFY~oa%C  
x5h~G  
AT_BEGIN -)v@jlg02  
从tag标签的开始一直到页面结束 w##^}nHOR  
如果tag处理类实现BodyTag接口,则在doInitBody、doAfterBody和doEndTag中调用,否则在doStartTag和doEndTag中调用 :@eHX&  
|A\a4f 'G  
AT_END 3BdX  
从tag标签的结束一直到页面结束 B4h5[fPX  
在doEndTag中调用 =wVJ%  
_{4^|{>Pv  
以struts为例,它的bean:define标签的实现遵循JSP1.1规范,此规范要求使用额外tag信息类来定义脚本变量。Variable元素是JSP1.2规范中加入的。以bean:define标签为例,你可以定义如下variable元素: xwi\  
X(@uwX$m  
<tag> 7b[wu~'( n  
8`=v.   
<variable> V`kMCE;?l  
o*5U:'=5}  
<name-from-attribute>id</name-from-attribute> t$J.+}}I  
MSw$_d  
<variable-class>database.BookDetails</variable-class> ]fBUT6  
M f~}/h  
<declare>true</declare> aC%&U4OS  
.iG&Lw\,  
<scope>AT_BEGIN</scope> z//VlB  
! | #83  
</variable> :|+Qe e  
8|6 4R:  
</tag> _n;;][]S  
`R"~v/x  
额外tag信息类 a5Y IUVCv  
i,I B!x  
如果要定义一个额外tag信息类,你要继承javax.servlet.jsp.TagExtraInfo类。一个TagExtraInfo类必须实现getVariableInfo方法,此方法返回一个叫VariableInfo的数组类,它包括如下信息: rV6/Tdy  
.,0bE  
· 变量名 Hc^W%t~  
#P<N^[m  
· 变量所属类名 m3bCZ 9iE  
D^ Jk@<*  
· 此变量是否引用了一个新对象 [F!Y%Zp  
1r Ky@9   
· 此变量的有效范围 ]\ !5}L  
nKa$1RMO  
jsp引擎将一个名为data的参数传给getVariableInfo方法,data中包括tag标签中的所有“属性名?D?D属性值”对。它可以用来向VariableInfo对象提供脚本变量的名字和类名。 |`Or'%|PR  
ziPR>iz-  
以struts为例,它在bean:define标签中定义了一个名为DefineTei的额外tag信息类,用来向脚本变量提供信息。由于脚本变量的名称(book)和类名(database.BookDetails)是通过tag标签的属性来传递的,它们一般定义在VariableInfo的构建代码中,并且可用data.getAttributeString方法来得到这些信息。如果要允许book脚本变量能在从tag开始直到整个JSP页面结束的范围内都可用的话,那它的范围应设为AT_BEGIN。如下所示: qz?mh4Oh  
d.UQW yLG  
Rk!X]-`=  
public class DefineTei extends TagExtraInfo =X\^J  
WHXj8*]6  
{ s\!>"J bAQ  
BTgG4F/)  
public VariableInfo[] getVariableInfo(TagData data) LUB${0BrA  
.p0Clr!  
{ 2 3OC2|  
) e5 @  
String type = data.getAttributeString(“type”); 7 d LuX   
Xs: 3'ua  
If( type == null) Mmpfto%i  
~ab:/!Z  
type = “java.lang.Object”; PB;eHy  
!;?+>R)h  
return new VariableInfo[] { !*R qCS,  
, ]bB9tid  
new VariableInfo(data.getAttributeString(“id”), AbZKYF P  
~e6Brq  
type, /c uLc^(X  
EoK~S\dS  
true, Fu!RhsW5j  
0c}  }Q  
VariableInfo.AT_BEGIN) :POj6j/  
9eH$XYy  
}; 5[c^TJ3  
 }Y;K~J  
} .l.a(_R  
1t)il^p4[;  
} Y "/]|'p  
oYukLr  
Q%xC}||1s"  
注意:关于额外tag信息类的类名必须要在TLD中的tag标签下的tei-class子元素中定义。因此,DefineTei的tei-class中的定义看起来如下: s&RVJX>Rt  
<tei-class> Hy^N!rBxfO  
org.apache.struts.taglib.bean.DefineTagTei zux{S; :?  
</tei-class> AvfNwE  
4O35 "1  
V$ ps>  
具有协作关系的tag -3Hy*1A.  
ZpnxecJUJ  
S:O O0<W  
tag通过共享对象来进行协作,JSP技术支持2种方式的对象共享。 8P|D13- Q  
DQ r Y*nH  
第一种方法是使用pageContext对象进行对象的共享(可支持JSP页面和tag处理类之间的共享),如果在一个tag处理类中要调用由另一个tag处理类创建的对象,可调用pageContext.getAttribute(name, scope)方法。 g*_cP U0~m  
*{L)dW+:  
第二各方式的共享是对于tag之间有嵌套关系而言的,外层的tag所创建的对象对于内层的tag来说是可以共用的。这种形式的共享的好处是减少了可能存在的重名冲突。 C#Na&m  
XCBL}pNkR  
要访问一个嵌套tag创建的对象,tag处理类必须先找到此嵌套tag对象,可用TagSupport的静态方法 TagSupport.findAncestorWithClass(from, class)或TagSupport.getParent方法。前者在当不确定此tag是否为嵌套tag对象时使用。一旦它的父类被找到,它就能访问其所有动态或静态创建的对象。静态创建的对象是父类的成员,而动态创建的对象可能是父类的私有对象。诸如此类的对象可以用tag处理类的setValue方法来保存,用getValue方法来获得。 b45-:mi!&#  
7_inJ$  
下例阐述了以上两种共享对象的方法。在这个例子当中,一个查询tag检查一个名为connection的属性名是否在doStartTag中被设置。如果connection属性被设置,tag处理类从pageContext中得到这个connection对象。否则,此tag处理类先找到它的父tag处理类,然后从它的父tag处理类中找到connection对象。 %5"9</a&G  
8~@c)Z;  
^f4s"T  
public class QueryTag extends BodyTagSupport P&*2pX:  
SC)g^E#  
{ ]H+8rY%+  
@~"h62=] -  
private String connectionId; $#9;)8J  
fof TP1  
public int doStartTag() throws JspException 2{H@(Vgpbr  
1SCR.@ k<  
{ 4R1<nZ"e~  
l 3ko?k  
String cid = getConnection(); Z8K?  
.$+#1-  
if(cid != null) Qp_isU  
R6;=n"Ueb  
{ "Q@ronP(~  
+M\`#i\g>  
//存在一个connection id,使用它。 3TeY%5iVt  
YIQ 4t  
connection = (Connection) pageContext.getAttribute(cid); aBNc(?ri  
| *2w5iR  
} )rn*iJ.e8  
^ *k?pJ5  
else !Qu"BF   
Yg%I?  
{  *x@Onj  
w0rRSD4S8B  
ConnectionTag ancestorTag = (ConnectionTag)findAncestorWithClass(this, x[ ~b2o  
"O3tq =Q  
ConnectionTag.class); ~ =M7 3U#  
v_+{'F  
if(ancestorTag == null) \XCe22x]  
M?Y;a5{  
{ [8 ]z|bM  
"l3_=Gua  
throw new JspTagException(“一个没有connection属性的查询标签必须被一个connection标记嵌套。”); pjKWtY@=X  
_.tVSV p  
} 89pEfl j2  
,<(}|go   
connection = ancestorTag.getConnection(); 4gI/!,J(b  
<wN}X#M  
} ;DqWh0  
Ns>- o  
} P+@/O  
6Zm# bFQ  
} dk[!V1x4\  
_mqL8ho  
'f!8DGix  
:%t U'w  
此查询标签在JSP页面中的调用形式可以从以下2种定义中任选一种: #xsE3Wj-X  
eVjBGJ=2e  
% L$bf#  
<tt:connection id=”con01” ...> ... </tt:connection> _<n~n]%  
_C%3h5  
<tt:query id=”balances” connection=”con01” > '\l"   
S'Q@ScJ  
SELECT account, balance FROM acct_table >,V9H$n  
s 1 A.+  
where customer_num = <%= request.getCustno() %> $ Xv*,Bq  
q(  
</tt:query> B]nEkO'a:  
b6 cBg  
}MJy +Z8&  
5kc/Y/4o  
}^ApJS(FQ  
<tt:connection ...> 1!xQ=DU"  
'F+C4QAq  
<x:query id=”balances”> b1(T4w6  
[^WC lRF  
SELECT account, balance FROM acct_table B~1 _28\  
K0u|U`   
where customer_num = <%= request.getCustno() %> /C:Y94B-z  
m~iXl,r  
</x:query> zU5v /'h>d  
b.2aHu( 3  
</tt:connection> CuaVb1r  
&|s0P   
nD_GL  
与此同时,在TLD中必须指定connection属性为可选的,定义如下: <wk!hTm W  
j@n)kPo,1  
<tag> {c6=<Kv  
9g9HlB&Ze  
... zIqU,n|]s  
, Rk9N  
<attribute> T;Lkaxsn  
ui< N[  
<name>connection</name> -RE^tW*Yy  
J?*1*h  
<required>false</required> 1h^:[[!c  
F6|TP.VY_.  
</attribute> :vmH]{R  
!S$:*5=&  
</tag>
描述
快速回复

您目前还是游客,请 登录注册
欢迎提供真实交流,考虑发帖者的感受
认证码:
验证问题:
10+5=?,请输入中文答案:十五