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

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

级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
标准的JSP 标记可以调用JavaBeans组件或者执行客户的请求,这大大降低了JSP开发的复杂度和维护量。JSP技术也允许你自定义taglib,其实换句话说,taglib可以看成是对JSP标记的一种扩展,正如xml是对html的一种扩展一样。taglib通常定义在tag标签库中,这种标签库存放着你自己定义的tag标签。简而言之,如果使用taglib,那么你可以设计自己的JSP标记! R:LT hFx  
MJ+]\(  
一般来说,自定义tag标签主要用于操作隐藏对象、处理html提交表单、访问数据库或其它企业级的服务,诸如邮件和目录操作等等。自定义tag标签的使用者一般都是那些对java编程语言非常精通,而且对数据访问和企业级服务访问都非常熟悉的程序员,对于HTML设计者来说,使得他可以不去关注那些较复杂的商业逻辑,而将精力放在网页设计上。同时,它也将库开发者和库使用者进行合理分工,自定义tag标签将那些重复工作进行封装,从而大大提高了生产力,而且可以使得tag库可用于不同的项目中,完美地体现了软件复用的思想。 82bOiN15  
`mfN3Q*[c  
在这篇文章中,我们主要讨论: z]J pvw`p  
'Oe}Ja  
· 什么是自定义tag标签? "ccP,#Y  
7P2?SW^  
· 怎么使用tag标签? +UTs2*H/^  
?TXe.h|u  
o 声明要使用的tag库 V9"?}cR/W;  
tLzX L *  
o 找到与之对应的tag处理类 TnvX&Y'  
<RMrp@[  
o tag标签的类型 5yhfCe m|  
ETA 1\  
· 自定义tag标签 ayb fBC  
'n)]"G|  
o tag处理类 %O<  qw  
[H!8m7i;  
o tag库描述 W r%E}mX-  
iq!u}# x_  
o tag标签示例 07?|"c.  
/4f4H?A -  
o 带属性的tag 3;h%mk KQ+  
\D]H>i$  
o 带body的tag qL03iV#h*V  
8@f=GJf  
o 定义了脚本变量的tag gZ^NdDBO  
pxs#OP  
o 具有协作关系的tag d&'}~C`~k  
#<\A[Po  
· 自定义tag标签 dt efDsK  
O\(0{qu  
o 一个迭代tag的例子 @%5$x]^  
NzP5s&,C69  
o 一个模板tag库 9mT;> mE  
>**7ck  
o tag处理类到底是怎样被调用的? A+N%A] 2  
|Ir&C[QS{y  
$ 4& )  
什么是自定义的tag? U6pG  
)ww#dJn  
一个自定义的tag标签是用户定义的一种JSP标记。当一个含有自定义的tag标签的JSP页面被jsp引擎编译成servlet时,tag标签被转化成了对一个称为tag处理类的对象进行的操作。于是当JSP页面被jsp引擎转化为servlet后,实际上tag标签被转化成为了对tag处理类的操作。 h!"| Q"18  
T%\f$jh6  
自定义tag标签有很多特色,诸如: 4l6+8/Y  
@AgV7#  
· 可以在JSP页面中自定义tag标签的属性 .<!Jhf$  
Ba9le|c5  
· 访问JSP页面中的所有对象 iA^GA8dn  
XA$Z 7_gu3  
· 可以动态地修改页面输出 b\U p(]  
tw`{\kWG  
· 彼此这间可以相互通信。你可以先创建一个JavaBeans组件,然后在一个tag中调用此JavaBeans组件,同时可以在另一个tag中调用它。 `oxs;;P  
Of*z9 YI  
· tag允许相互嵌套,可以在一个JSP页面中完成一些复杂的交互。 ^@&RJa-kb  
BpGK`0H  
UqP %S$9  
使用tag标签 %:P&! F\?  
d4h, +OU  
6uU2+I  
本节主要描述怎样在JSP页面中使用tag标签,以及tag标签的不同类型。 TzCNY@y  
m),3J4(q  
要使用tag标签,JSP程序员必须做2件事: #_, l7q8U  
$Y mD;  
· 声明此tag标签的tag库 >q:0w{.TU  
^E5[~C*o3  
· 实现此tag标签 `;@#yyj:_  
<]u~;e57  
声明tag标签所在的tag库 ]Y%?kQ^  
6n 2LG  
如果要使用tag标签,则应用JSP的taglib指示符来指定其tag库(注意:taglib要在在使用此tag标签之前声明) !i|]OnJY  
er0hf2N]  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> O%(E 6 n  
q x1}e  
uri属性定义了唯一的标签库描述(以下简称TLD),它可以是直接是tld文件名或一个独一无二的名字。prefix是用来区别其它TLD中和本TLD中有重名的tag的一种手段。 ~t $zypw  
8?L7h\)-  
TLD必须以.tld作为扩展名,并且存放在当前应用的WEB-INF目录或其子目录下。你可以通过它的文件名直接引用它,也可以通过别的方式间接地引用它。 g]=w_  
N* C"+2  
以下taglib指示符直接引用一个TLD: (>OCLmV$  
Puu O2TZ  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> =]OG5b_-Y  
!Ol>![  
以下的taglib指示符通过一个逻辑名称间接地引用一个TLD: 9K>$  
6<h?%j(  
<%@ taglib uri=”/tutorial-template” prefix=”tt” %> v\Y362Xv  
6%K,3R-d  
如果是间接引用TLD的话,那你必须还要在web.xml中定义此逻辑名称与tld文件之间的映射,具体做法是在web.xml中加入一个名为taglib的元素: !;YmLJk;hN  
?0Qm  
<taglib> )1>fQ9   
)1KlcF  
<taglib-uri>/tutorial-template</taglib-uri> 6o_t;cpT  
TZT1nj"n  
<taglib-location> +,xl_,Z6  
|kHPk)}I]  
/WEB-INF/tutorial-template.tld _$+lyea   
l%aiG+z%6}  
</taglib-location> )$*T>.JA  
o*OaYF'8  
</taglib> RtrESwtR  
>k6RmN  
!$:lv)y  
实现此tag标签 '$]u?m  
PQmgv&!DP  
; 7`y##  
为了实现tag标签,你有2种方法来存放tag处理类。一、让tag处理类以.class的方式存放于当前应用的WEB-INF/class子目录下,二、如果tag处理类是以JAR包的形式存在的话,那可以放在当前应用的WEB-INF/lib目录下,如果tag处理类要在多个应用中共享,那么它就应放在jsp服务器上的common/lib目录下,对于tomcat来说,就是tomcat/common/lib目录下。 m)A~1+M$)L  
'NM$<<0  
n]/7UH}(<&  
tag标签类型 (z}q6Lfa  
DQ{Yr>J  
>f [Lb|t  
自定义的tag标签遵循XML语法。它有一个开始标记和一个结束标记,有的还有body(即文本节点):  )"im|9  
L}bS"=B[&W  
<tt:tag> ?jywW$   
!+?,y/*5(  
body ,FvBZ.4c3=  
IH;+pN  
</tt:tag> AXV+8$ :R  
: -@o3Syg  
z@lUaMm:F  
一个不带body的tag标签如下: !BN7 B  
~aK@M4  
<tt:tag /> Wx;`=9  
/7$3RV(  
s V70a 3#  
简单的tag标签 TSQ/{=r  
`TM[7'  
一个没有body和属性的tag标签如下: :nuMakZZ  
w6k\po=  
<tt:simple /> {iGk~qN  
2=3pV!)4}  
IK%fX/tDyc  
带属性的tag标签 =?U"#a  
QU/Q5k  
MtYi8"+<e.  
自定义标签可以有自己的属性。属性一般在开始标记中定义,语法为 attr=”value”。属性的作用相当于自定义标签的一个参数,它影响着tag处理类的行为。你可以在TLD中详细定义它。 D8otU DB{  
T@PtO "r  
你可以用一个String常量给一个属性赋值,也可以通过表达式给它赋值,如<%= ...%>。以struts为例,它的logic:present标签就是用的String常量来给属性赋值: WXqrx*?*+  
X\?e=rUfn  
<loglic:present parameter = “Clear”> -5Qsc/ s&  
Hq.ys>_  
而另一个标签logic:iterate是用表达式来给属性赋值: mK3U*)A   
rBv  
<logci:iterate collection=”<%= bookDB.getBooks() %>” S!0ocS!t  
{wWh;  
id=”book” type=”database.BookDetails”> x)M=_u2 _  
T{1Z(M+  
Mf0XQ3n`H  
带body的tag标签 y{~l&zrl  
~/hyf]*j  
一个自定义标签可以包含其它自定义标签、脚本变量、HTML标记或其它内容。 M@e&uz!Rx  
V+/Vk1  
在下述例子中,此JSP页面使用了struts的logic:present标签,如果些标签定义了parameter=”Clear”的属性,则将清除购物车的内容,然后打印出一条信息: ^<0u~u)%T  
%,u_ `P  
<logic:present parameter=”Clear”> zG_e=   
|fXwH>'sw  
<% cart.clear(); %> WlHw\\ur  
(>THN*i  
<font color=”#ff0000” size=”+2”><strong> WH F>J  
qRMH[F$`  
你选择了清除购物车! Jsee8^_~  
^c1%$@H  
</strong></font> |k~\E|^  
gkdd#Nrk  
</logic:present> 4qtjP8Zv[  
6Sh0%F s  
K252l,;|  
到底是用属性还是用body来传递信息? $42C4I*E  
r>N5 ^  
如上所述,我们既可以通过属性,也可以通过body来传递信息。但一般来说,比较简单的类型,如字符串或简单表达式最好采用属性来传递信息。 Dp 0   
_w+ix9Fr?  
2| u'J  
定义脚本变量的tag标签 9/OB!<*V|  
(\ `knsE!  
所谓脚本变量,是指JSP中可以调用的变量或对象。它可由tag标签产生。以下示例阐述了一个tag标签定义了一个名为tx的由JNDI所定义的事务处理对象。脚本变量可以是ejb对象、事务、数据库连接等等: dQ97O{O:i  
KsM2?aqwf_  
<tt:lookup id=”tx” type=”UserTransaction” name=”java:comp/UserTransaction” /> ?MevPy`H  
&DdFK.lt  
<% tx.begin(); %> |I7-7d-; /  
.aWEXJ  
... A~ugx~S0  
C' C'@?]  
SRq0y,d  
具有协作关系的tag标签 OM!CP'u#{  
 WDr'w'  
自定义tag标签之间可以通过共享对象来实现协作。在下述例子中,标签tag1创建了一个名为obj1的对象,在标签tag2仍可以重复使用obj。 ^Z7])arA  
^7C?yC  
<tt:tag1 attr1=”obj1” value1=”value” /> Yr@)W~  
?pdvFM  
<tt:tag2 attr1=”obj1” /> 7bioLE  
Ug=8:a(U.  
在以下这个例子当中,如果外层的tag标签创建了一个对象,那么其内层的所有tag标签都可以使用这个对象。由于这样产生的对象没有一个指定的名字,那么就可以将少重名的冲突。这个例子阐述了一系列协作的嵌套对象。 /[YH  W]  
M9{?gM9  
<tt:outerTag> Ob+L|FbnN  
EB'(%dH  
<tt:innerTag /> tp2CMJc{L  
;\=W=wL(  
</tt:outerTag> 8M m,a  
* ";A~XNx  
"WOY`su>  
Tag处理类 Pb$ep|`u  
0R~{|RHM  
#z{9:o7[-  
Tag处理类必须实现Tag接口或BodyTag接口,不过现在一般都流行从TagSupport或BodyTagSupport类中继承,这些类或接口都可以在javax.servlet.jsp.tagext包中找到。 vKppXm1  
1_ uq46  
当JSP引擎看到自己的JSP页面中包含有tag标签时,它会调用doStartTag方法来处理tag标签的开头,调用doEndTag方法来处理tag标签的结束。 hPt(7E2ke~  
 ]qCAog  
下表说明不同类型的tag所需要不同的处理过程: +D|y))fE  
y?W8FL  
Tag处理类的方法 d_BO&k<+I  
rt] @Z`w  
Tag标签类型 cF_hU"  
所调用的方法 b'`8$;MII  
GuMsw*{>  
基本标签 b]hP;QK`U$  
doStartTag, doEndTag, release 2`,{IHu*!  
0IoS|P}6a  
带属性的标签 6P;JF%{J  
doStartTag, doEndTag, set/getAttribute1...N, release N<ww&GXBX  
_@0>y MZ^  
带内容的标签 e"^* ~'mJ  
doStartTag, doEndTag, release l+S08IZ  
jJ-j   
带内容的标签,且内容重复循环 b@@`2O3"  
doStartTag, doAfterBody, doEndTag, release 6R% I)  
(NUwkAO M}  
带内容的标签,且内容与JSP交互 'M2Jw8i  
doStartTag, doEndTag, release, doInitBody, doAfterBody, release UX=JWb_uGm  
RWf4Wh?d  
一个tag处理类可以通过javax.servlet.jsp.PageContext来与JSP交互,通过javax.servlet.jsp.PageContext类,tag处理类可以访问JSP中的request、session和application对像。 ('!90  
&G?b|Tb2  
如果tag标签是互相嵌套的,那内层的tag处理类可以通过它的parent属性来访问上层的tag处理类。 +hg|!SS@5  
zRsG$)B  
一般情况都将所有的tag处理类打成了JAR的包,以便于发布。 A<.`HCv2  
S5]rIcM  
s<x2*yVUA  
Tag库描述(简称TLD) %^}3:0G  
<N^2|*3  
ipfiarT~)  
Tag库是用xml语言描述的,TLD包括了tag库中所有tag标签的描述,它一般用来被jsp服务器用来校验tag的语法正确性,或者被jsp开发者用来开发新的标签。 `WHP#z  
iF2/:iP  
TLD的文件扩展名必须为.tld,而且必须放在当前WEB应用的WEB-INF目录或其子目录中。 y8jk9Tv  
+~RiCZt  
一个TLD的内容的开头必须遵守标准的XML开头,用于描述DTD和xml的版本,例如: b 8v?@s~  
a2 fV0d6*l  
<?xml version="1.0" encoding="ISO-8859-1" ?> *,!6#Z7  
$d.UF!s  
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd"> 1{R 1:`  
TLD必须以<taglib>来作为它的根元素,<taglib>的子元素如下表: X.V7od>  
R+IT)2  
:.Vn  
<taglib>的子元素 XEM i~L+  
n?vrsqmZ  
Element h_L-M}{OG  
Description bY7d  
K:/%7A_{  
tlib-version eZs34${fN  
Tag库的版本 i[A$K~f  
,o\v umx  
jsp-version Yd:8i JA  
Tag库所需要的jsp的版本 fLl~a[(5  
::N'tcZ^2  
short-name "#^11o8  
助记符,tag的一个别名(可选) 4Y8/>uL  
62Yi1<kV@  
uri 9r!psRA:`)  
用于确定一个唯一的tag库 <<K GS  
Ul7)CT2:  
display-name 7a 4G:  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) [5^"U+`{x  
z 7OTL<h  
small-icon d(zBd=;  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) _c?&G`  
o7E?A  
large-icon 6}A1^RB+w  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) 8@ck" LUzD  
a=\r~Z7E  
description @D&VOJV  
对tag库的描述(可选) 9/TF #  
;muxIr`?  
listener m[,! orq  
参见下面listener元素 xpt*S~  
8W Mhe=[  
tag $NzD&b$7  
参见下面tag 元素 v)>R)bzqe  
57^ X@ra$  
Listener元素  RSXYz8{  
yZ=wT,Y  
一个tag库可能定义一些类做为它的事件侦听类,这些类在TLD中被称为listener 元素,jsp服务器将会实例化这些侦听类,并且注册它们。Listener元素中有一个叫listener-class的子元素,这个元素的值必须是该侦听类的完整类名。 `=8g%O|T  
@#$5_uU8\(  
Tag元素 a,IE;5kG  
uFNVV;~RFI  
每个tag元素在tag库中都要指出它的名字、类名、脚本变量、tag的属性。其中脚本变量的值可以直接在TLD中定义或通过tag附加信息的类来取得。每个属性描述了这个属性是否可以省略,它的值是否可以通过<%= …%>这样的JSP语法来获得,以及属性的类型。 gtWJR  
3G|n`dj  
每一个tag在TLD中对应一个tag元素,下表是tag元素的子元素: pq$`T|6^  
vK z/-9im  
Tag元素的子元素 mnswG vY  
 chW 1UE  
元素名称 y`!~JL*  
描述 }stc]L{79  
~]P_Yd-|  
name =B_vQJF2  
独一无二的元素名 4% )I[-sH  
)J#7:s]eo  
tag-class 0L1NZY^!  
Tag标签对应的tag处理类 oF[l<OY4  
'Y{fah  
tei-class fF37P8Ir  
javax.servlet.jsp.tagext.TagExtraInfo的子类,用于表达脚本变量(可选) ={y Mk  
< TJzp  
body-content ],9%QE  
Tag标签body的类型 nn!W-Bsqjh  
&OD)e@Tc  
display-name E!w%oTx{OR  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) H@o 3u>}  
Ha{#  
small-icon xG i,\K\:  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) CL oc  
:G\f(2@  
large-icon n!e4"|4~z  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) hOjy$Z  
o8c4h<,  
description Cc7PhoPK  
此tag标签的描述 ~YO99PP  
r=l hYn  
variable 3:1 h:Yc<  
提供脚本变量的信息(同tei-class)(可选) Xi`K`Cu+  
}DiMt4!ZC!  
attribute 9B gR@b  
Tag标签的属性名 QQ^P IQj  
;(AVZxCM  
以下章节介绍对于不同类型的tag,如何具体地实现它们。 wd&Tf R4!  
ew8f7S[  
udYk 6  
简单的tag $6Z@0H@X  
9M{z@H/  
53X H|Ap  
tag处理类 X;/~d>@  
G\4h4% a  
简单的tag处理类必须实现Tag接口的doStartTag和doEndTag方法。当jsp引擎碰到tag标签的开头时,doStartTag被调用,因为简单的tag没有body,所以此方法将返回 SKIP_BODY。当jsp引擎碰到tag标签的结尾时,doEndTag被调用,如果余下的页面还要被计算,那它将返回EVAL_PAGE,否则将会返回SKIP_PAGE。 2;N)>[3*J  
*CG-F=  
以下是例子:对于标签 <tt:simple /> ,它的tag处理类实现如下: W,'30:#Fr7  
H|&[,&M>  
w3oh8NRs_  
public SimpleTag extends TagSupport T@0\z1,~S  
cC@B\Q  
{ k4Ed7T-  
AdV&w: ^yf  
public int doStartTag() throws JspException H<bYm]a%  
j t9fcw  
{ *m$P17/C  
H]2cw{2  
try{ dNd(57  
;s m )f  
pageContext.getOut().print(“Hello.”); J eCKnt=  
NJ\ID=3l  
}catch(Exception e){ n@IpO i$Q  
^)|8N44O  
throw new JspTagException(“SimpleTag: “ + e.getMessage()); `rEu8u  
"i3wc&9!?W  
} ^]_[dqd  
z&x ^ Dl  
return SKIP_BODY; fHK`u'  
|/rms`YQ  
} S[g{ )p)  
hfzmv~*  
public int doEndTag() |Et8FR3[m  
\/E+nn\)  
{ M'gw-^(  
Xtv^q> !  
return EVAL_PAGE; M:&g5y&  
RlJt+lnV  
} S+aXlb  
"_!D b&AH  
} GZ xG!r -  
3^NHV g  
BC|=-^(  
注意:如果tag标签没有内容的话,那必须定义body-content元素为空,例如 [Aqy%mbG  
:Y/>] tS4  
<body-content>empty</body-content> VHwAO:+-  
_`'VOY`o  
Wx~N1+  
带属性的tag标签
评价一下你浏览此帖子的感受

精彩

感动

搞笑

开心

愤怒

无聊

灌水
级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
只看该作者 1 发表于: 2007-01-01
tag处理类 `v;9!ReZV  
T["(wPrt  
对于tag标签的每个属性,你必须依照JavaBeans规范来定义其属性,以及get和set方法。以struts的logic:present 标签为例, 8n_!WDD  
954!ED|F(  
<logic:present parameter=”Clear”> B{x`^3q R  
tb#9TF  
与此相应,此tag处理类应有如下方法和定义: LBO3){=J  
cOz8YVR-  
yDmNPk/  
protected String parameter = null; W@"s~I6  
Fog4m=b`g  
public String getParameter() Y8$Y]2  
k&TZ   
{ ;/hR#>ib  
:!',o]"4,k  
return this.parameter; q.xt%`@aA  
~8fy qE$  
} 7sgK+ ip  
&A}@@d  
public void setParameter(String parameter) Q7V*~{  
Nu}x`Qkmr  
{ G3[X.%g`  
v@_^h}h/,=  
this.parameter = parameter; |AgdD  
j%_{tB  
} ?%)G%2  
;^fGQ]`4  
`;X~$uS  
注意:如果你的属性名为id,而且你的tag处理类是从TagSupport类继承的,那你就不需要定义它的属性和set和get方法,因为他们早已在TagSupport被定义过了。 _SVIY@K|/  
)1E[CIaXK  
Attribute元素 \W%Aeg*c  
cOhx  
对于tag标签的每个属性,你必须定义它是否必须的,它的值是否可以用诸如<%= …%>的表达式来获得,以及它的类型(可选),如果不指定它的类型,那就默认为是java.lang.String类型。如果rtexprvalue元素被定义为true或yes,那么在type元素中就定义了attribute的返回类型。 ,drbj.0-  
g4p-$WyT8>  
<attribute> c4\Nuy  
abs\Ku9  
<name>attr1</name> H@-txO1`::  
g3fxf(iY(  
<required>true|false|yes|no</required> c%?31 t  
hU: 9zLe  
<rtexprvalue>true|false|yes|no</rtexprvalue> `=}w(V8pc  
->H4!FS  
<type>attribute的返回类型(只用当rtexprvalue为真是才有效)</type> /RWQ+Zf-Y]  
YTb/ LeuT  
</attribute> S5%I+G3  
3vcKK;qCB  
如果tag的某个属性不是必须的,那tag处理类会自动提供一个缺省值。 `lI(SS]w  
1]DPy+  
例如,在logic:present这个tag标签中定义了一个属性叫parameter,但它不是必须的,而且它可以被诸如<%= …%>的表达式来赋值。 gfr y5e  
 gAFu  
<tag> [.ya&E)x  
\my5E\  
<name>present</name> aRt`IcZYz  
\Uz7ar#,  
<tag-class>org.apache.struts.taglib.logic.PresentTag</tag-class> qwf97pg$  
|8m2i1XG  
<body-content>JSP</body-content> 4y: pj7h  
lMn1e6~K  
[wLK*9@&  
S)n+E\c  
<attribute> 9Q*T'+V  
&1Zq C;  
<name>parameter</name> /V>q(Q  
Xyz w.%4c  
<required>false</required> 1o Z!Up0  
#0:N$'SZ  
<rtexprvalue>true</rtexprvalue> gG?sLgL:  
" A4.2  
</attribute> Tgf\f%,h  
`l%)0)T  
m|/q o  
g`n5-D@3  
</tag> w$`[C+L  
],?$&  
3RbPc8($Y  
属性元素的校验 neLQ>WT L  
^KlW"2:  
NKyKsu  
有关于tag标签的有效值可以从tag库的说明文档中获得,当JSP页面被编译时,jsp引擎会强制性地参照TLD中定义的规则进行检查。 "ZHA.M]`  
h<1pGQV  
还有一个方法也可以进行属性元素的校验,就是先继承类TagExtraInfo,然后调用它的isValid方法。这个类同时也起到提供tag中定义的脚本变量信息的作用。 F{'lF^Dc  
NKX,[o1  
IsValid方法通过TagData对象来传递属性信息,它包括着tag的所有的属性名-值的信息。由于校验发生在运行时刻,因此这个属性的值将被赋值为TagData.REQUEST_TIME_VALUE。 sY%nPf~9q'  
&"R`:`XF  
例如tag标签<tt:twa attr1=”value1” />在TLD中定义如下: G\PFh&  
]YF_c,Q  
<attribute> y\C_HCU H  
NUQ?Q Q  
<name>attr1</name> 79yF {  
F5+)=P#  
<required>true</required> gfPR3%EXs  
cYeC7l "  
<rtexprvalue>true</rtexprvalue> eX 0due  
\LEU reTn  
</attribute> g> <*qd?t  
izvwXC  
';vL j1v  
这个定义说明了attr1能在运行期间被赋值。 _U<r@  
E3~Wyfd7  
以下的isValid方法检查attr1属性的值是否属于Boolean类型。注意由于attr1能在运行刻被赋值,那么isValid方法必须检查tag用户是否对此tag进行了运行时刻赋值。 x("V +y*  
1SwKd*aRR?  
phc9esz  
Public class TwaTEI extends TagExtraInfo JNx;/6'd,  
3~ptD5@WF  
{ ^sP-6 ^  
"<=HmE-;  
public boolean isValid(Tagdata data) |jhu  
m\DI6O"u'  
{ C25EIIdRb  
b" PRa|]  
Object o = data.getAttribute(“attr1”); |z 8Wh  
QI WfGVc-  
If(o != null && o != TagData.REQUEST_TIME_VALUE) a0/[L  
>OotgJnhC  
{ Z'cL"n\9R]  
K1oSoD8c  
if( ( (String)o).toLowerCase().equals(“true”) || Qw@_.I  
u|Tg*B  
((String)o).toLowerCase().equals(“false”) ) ZR*Dl.GWY  
I%b}qC"5M  
return true; >S[NI<=8S  
ZDl6 F`  
else p|&9#?t4A  
cxB{EH,2Um  
return false; |.~0Ulk,  
)1ct%rue  
} \-Ipa59U  
6}"t;4@$x  
else Ty5}5)CRZ  
vd FP ^06  
return true; Q^@z]Sc[  
wticA#mb  
} >&?k^nI}J  
[IRWm N-  
} k@=w? m  
RbN# dI'  
.ZVADVg\  
带body的tag SMMvRF`7  
)ePQN~#K}  
lG/h[  
tag处理类 d>-k-X-[  
0)HZ5^J  
L^%jR=  
如果tag标签含有内容,那处理方式会略微有些不同,而且还要视tag处理类是否要与body交互的情况而定。如果要与body交互,那我们认为tag处理类要可能要对body进行操作。 NU/:jr.W#  
,5Nf9z!hk(  
Tag处理类不与body交互 P7|x=Ew;`  
T*bBw  
如果tag处理类不与body交互,tag处理类应该实现Tag接口或从TagSupport中派生,如果body要被计算,那么doStartTag方法应返回 EVAL_BODY_INCLUDE,否则应返回SKIP_BODY。 T~G~M/  
tEl_a~s*3?  
如果tag处理类要对body反复运算,则它应该实现IterationTag或从TagSupport中派生。如果tag处理类认为body还未计算完的话,那它的doStartTag方法和doAfterBody方法必须返回EVAL_BODY_AGAIN。 fZNWJo# `.  
VPI;{0kh  
Tag处理类与body交互 ^E}};CsT  
Sft+Gb6  
如果tag处理类与body交互,那tag处理类应实现BodyTag接口或从BodyTagSupport中派生。这种tag处理类一般要实现doInitBody和doAfterBody方法。 r zO5 3\  
V'm4DR#M  
Body允许一些方法来读写它的内容。Tag处理类可以调用body内容的getString或getReader方法来从body中提取信息,也可用 writeOut(out) 方法来将body的内容写入到out对象中。其中out对象通过tag处理类的getPreviousOut方法来获得。  }0f"SWO>  
svj0;x5  
如果body的内容需要被计算,那么doStartTag方法必须返回EVAL_BODY_BUFFERED,否则,它将返回 SKIP_BODY。 E%np-is{1  
sF!nSr  
doInitBody 方法 \ QE?.Fx  
:@c\a99Kx  
此方法在body内容已经设好,但未被计算之前被调用。你可以根据不同的body内容来制定初始化策略。 *L+)R*|:&  
 WgayH  
doAfterBody方法 xwe^_7  
01&J7A2  
此方法在body内容已被计算后进行调用。 $^Z ugD  
oJln"-M1nx  
和doStartTag方法一样,doAfterBody方法返回一个指示符指示是否要继续计算body,如果要继续计算,则doAfterBody应返回EVAL_BODY_BUFFERED,否则,它应返回SKIP_BODY。 dHJ#xmE!pP  
*)0-N!N#)  
release 方法 J<27w3bs~p  
}N`m7PSf  
tag处理类调用此方法将它的状态重置为初始状态,并释放所有的私有资源。 [~U CYYl  
3 6-Sw  
g|V md  
以下的例子读取body的内容(其中含有一条sql语句),然后将它传递给一个对象,让它进行查询。由于此处body不须重新计算,所以doAfterBody会返回SKIP_BODY。 HTw7l]]  
s;!Tz)  
T$vDw|KSVP  
Public class QueryTag extends BodyTagSupport M_Z(+k{Gy  
%D $+Z(  
{ %[J|n~8_Z  
/AhN$)(O  
public int doAfterBody() throws JspTagException Api<q2@R  
 /gUD!@  
{ 's7 (^1hH  
{6Qd,CX  
BodyContent bc = getBodyContent(); ! 1wf/C;=  
I] vCra  
//将body的内容以字符串的格式提取出来 0k):OVfm=  
:o=a@Rqx  
String query = bc.getString(); TW)~&;1l  
kD{qW=Lpn  
//清除body 2PVtyV3;  
&vHfuM`  
bc.clearBody(); $CP_oEb  
, HHCgN  
try{ e%K oecq  
>xK!J?!K  
Statement stmt = connection.createStatement(); V0)F/qY  
5A`T}~"X  
Result result = stmt.executeQuery(query); V^/]h u  
p*OpO&oodu  
}catch(SQLException e){ <o:|0=Sw b  
n7*.zI]%&  
throw new JspTagException(“queryTag: “ + e.getMessage() ); DVLF8]5  
t IO 'ky  
return SKIP_BODY;  OK\F  
Nub)]S>_/t  
} bUS"1Tg]*6  
wN^$8m5\T^  
} V+- ]txu|  
ON q=bI*  
eR*y<K(d  
body-content元素 Aat-938FP6  
#s]'2O  
VY]L<4BfGL  
由于tag可能会有body,你必须用body-content元素来指定body内容的类型: [)L)R`  
l.@&B@5F  
<body-content>JSP|tagdependent</body-content> -er8(snDQ  
w</qUOx  
,p7W4;?4  
如果body的内容是定制的或内部的tag、脚本元素、或HTML广本,则归类为JSP类型。其他的类型,比如上面代码所述的?D?D将sql statement类传给 query tag的这种类型应该标为tagdependent。 u{d\3-]/  
ux=0N]lc  
注意:实际上body-content的值并不影响tag处理类对body内容的处理,它仅仅是被tag编辑工具用来描述此body的内容。 #V#sg}IhM?  
}<KQ +  
8 bpYop7 L  
用tags定义脚本变量 7f,!xh$  
2SHS!6:Rl  
5ON\Ve_H  
tag处理类 e3!0<A[X  
at5>h   
Lj#K^c Ee  
tag处理类负责创建或设置页面中定义的脚本变量,用pageContext.setAttribute(name,value,scope)或pageContext.setAttribute(name,value)方法来实现。一般来说,tag处理类通过脚本变量的名称来获取它,脚本变量的名称一般可用get方法来获得。 /hksESiU  
g+  P  
如果脚本变量的值依赖于tag处理类中的上下文中某一对象,那它可用pageContext.getAttribute(name,scope)方法来找到那个对象。一般的处理过程是tag处理类先找到脚本变量,再对其进行处理,然后用pageContext.setAttribute(name,object)的方法来设置它的新值。 8 O% ?t  
w4%yCp[,  
对象的生存周期(scope)如下表: y)]L>o~  
7v{s?h->$  
对象的生存周期表 \;F_QV  
*Z:'jV<  
名字 o b,%); m  
可访问范围 I {&8iUN  
生存周期 WPbG3FrL!  
>J,y1jzJ  
page \Uh$%#}.  
当前页面 GO<,zOqvU  
一直有效,除非页面向客户提交响应或重定向到一个新页面 ~]LkQQ'  
8\])p sb9  
request &8R !`uh1  
当前页面或当前页面重定向到的页面 :,[=g$CT:  
一直有效,除非页面向客户提交响应 d]!`II  
5?M d  
session 'vc>uY  
当前页面或在同一浏览器窗口中的页面 io^ L[  
一直有效,除非关闭当前浏览器、超时、网络故障 'j27.Ry.  
2(5<Wj"  
application LzE$z,  
整个web应用程序的所有请求 fq,LXQ#G  
一直有效,除非发生网络故障、服务器故障 `%oJa`  
2n|]&D3V"'  
提供关于脚本变量的信息 5wgeA^HE2y  
hiBZZ+^[  
以下示例定义了一个名为“book”的脚本变量,用来访问程序中关于书的信息: Li8$Rb~q  
&K@ RTgb  
<bean:define id=”book” name=”bookDB” property=”bookDetails” type=”database.BookDetails” /> mNDz|Ln  
Ap)[;_9BD  
<font color=”red” size=”+2” > f9FEH7S68  
Fh0cOp(  
<%= messages.getString(“CartRemoved”) %> waRK$/b (  
^Pp2T   
<strong><jsp:getProperty name=”book” property=”title” /></strong> S%{^@L+V  
|ryV7VJ8  
</font> <A+n[h  
W3aFao>!OZ  
当包含此tag的JSP页面被编译时,jsp引擎会自动生成关于此book的同步的代码(同步可以避免几个客户同时访问此book时造成的冲突),要生成同步代码,jsp引擎需要知道此脚本变量的如下信息: *47',Qy  
SNl% ?j| f  
· 脚本变量名称 _ 0g\g~[  
q47:kB{d  
· 脚本变量所属的类 .XTR HL*:  
]~!?(d!J/  
· 此脚本变量是否引用了一个新的或已存在的对象 ).l`N&_peM  
PT/TQW  
· 此脚本变量的有效性 '2X6 >6`w  
:Y)jf  
有两种办法可以向jsp引擎提供关于脚本变量的信息:在TLD中定义variable子元素,或用tei-class子元素定义一个额外tag信息类。用variable最简单,但可能降低了一些灵活性。 %3;vDB*L$  
$vjl-1x&  
Variable元素 MIF`|3$,  
vA"MTncv  
Variable元素有如下子元素: D6L5X/#  
.0]\a~x  
· name-given ?D?D 给出的名字,是一个常量 6zR9(c:a~  
(RBzpAiH  
· name-from-attribute?D?D 属性名,在编译时给出的属性名 7uq/C#N  
8urX]#  
name-given或name-from-attribute两者必须选一,但以下子元素是可选的: [QZ g=."  
t]14bf$*Q  
· variable-class?D?D变量的类型,缺省为java.lang.String。 IF~E;  
ZlG|U]mM5  
· declare?D?D此脚本变量是否引用了一个新对象,缺省为True。 Ef~Ar@4fA  
6>=yX6U1q^  
· scope?D?D脚本变量的范围,缺省为NESTED。下表描述了scope的几种类型: bbe$6xwi  
mi]bS  
脚本变量的有效范围 :XFr"aSt  
!9p;%Ny`  
AS? ESDC  
有效性 'JK"3m}nT  
方法 ]9]o*{_+(f  
 oo4aw1d  
NESTED :/<SJ({q  
在tag标签的开始和结束之间 @]F1J  
如果tag处理类实现BodyTag接口,则在doInitBody和doAfterBody中调用,否则在doStartTag中调用 h'm-]v  
;vuqI5k  
AT_BEGIN ,$A'Y  
从tag标签的开始一直到页面结束 {a9( Qi  
如果tag处理类实现BodyTag接口,则在doInitBody、doAfterBody和doEndTag中调用,否则在doStartTag和doEndTag中调用 ' Ih f|;r  
='G-wX&k  
AT_END 3LW_qX  
从tag标签的结束一直到页面结束 0aM&+j\q}  
在doEndTag中调用 ^I y'G44  
6 @A'N(I=O  
以struts为例,它的bean:define标签的实现遵循JSP1.1规范,此规范要求使用额外tag信息类来定义脚本变量。Variable元素是JSP1.2规范中加入的。以bean:define标签为例,你可以定义如下variable元素: Mv?$zV"`#  
w Sd|-e  
<tag> ;Y9-0W  
?[VL 2dP0  
<variable> #UesXv  
&m=73 RN  
<name-from-attribute>id</name-from-attribute> j[Q9_0R~lR  
R(AS$<p{!>  
<variable-class>database.BookDetails</variable-class> h ]6: `5-  
H~:EPFi.(  
<declare>true</declare> N5d)&a 7?  
gzd<D}2F~  
<scope>AT_BEGIN</scope> Kg6[  
e%_J O7  
</variable> f1w_Cl  
f>hA+  
</tag> *hvC0U@3  
F?+\J =LT  
额外tag信息类 C2}f'  
4H4ui&|7u6  
如果要定义一个额外tag信息类,你要继承javax.servlet.jsp.TagExtraInfo类。一个TagExtraInfo类必须实现getVariableInfo方法,此方法返回一个叫VariableInfo的数组类,它包括如下信息: 7z;X@+O}s  
3ZUME\U  
· 变量名 q,m+W='  
v8l3{qq  
· 变量所属类名 =JNCQu  
LE}V{%)xD  
· 此变量是否引用了一个新对象 h<<uef9  
'4ip~>3?w  
· 此变量的有效范围 .L@gq/x)  
CuT50N;tk  
jsp引擎将一个名为data的参数传给getVariableInfo方法,data中包括tag标签中的所有“属性名?D?D属性值”对。它可以用来向VariableInfo对象提供脚本变量的名字和类名。 38#Zlc f  
8_Nyy/K#F  
以struts为例,它在bean:define标签中定义了一个名为DefineTei的额外tag信息类,用来向脚本变量提供信息。由于脚本变量的名称(book)和类名(database.BookDetails)是通过tag标签的属性来传递的,它们一般定义在VariableInfo的构建代码中,并且可用data.getAttributeString方法来得到这些信息。如果要允许book脚本变量能在从tag开始直到整个JSP页面结束的范围内都可用的话,那它的范围应设为AT_BEGIN。如下所示: of=N+ W  
H):(8/> (  
10d.&vNw  
public class DefineTei extends TagExtraInfo IhjZ{oV/@  
XY^]nm-{I  
{ #IR,KX3]A  
%E2b{Y;  
public VariableInfo[] getVariableInfo(TagData data) ~JQ6V?fucD  
p|+TgOYOc  
{ $W]}m"l  
")YD~ZA%)  
String type = data.getAttributeString(“type”); = 6'Fm$R  
]{| wU.  
If( type == null) |/;;uK,y  
p1N3AhXY  
type = “java.lang.Object”; bRD-[)  
GIZw/L7Yb  
return new VariableInfo[] { Ge7Uety  
Nsn~mY%  
new VariableInfo(data.getAttributeString(“id”), cq0-D d9^&  
ryNe=9p  
type, %<0'xJ%%Q  
[\3W_jR  
true, |Kb m74Z%  
FBxg^g%PB@  
VariableInfo.AT_BEGIN) MfZamu5+F  
$p|Im,  
}; ^Na3VP  
M}e}3w  
} '*B%&QC-  
ON9L+"vqv0  
} !oa/\p  
Tq?7-_MLC$  
5=#2@qp  
注意:关于额外tag信息类的类名必须要在TLD中的tag标签下的tei-class子元素中定义。因此,DefineTei的tei-class中的定义看起来如下: $5:I~ -mx  
<tei-class> :s*t\09V7  
org.apache.struts.taglib.bean.DefineTagTei K7R!E,oPg  
</tei-class> )FN\jo!!.  
2<9&OL  
6UI6E)g  
具有协作关系的tag A0,h 7<i  
a<J< Oc!  
]nNn"_qh  
tag通过共享对象来进行协作,JSP技术支持2种方式的对象共享。 21O@yNpS$  
D"gv:RojD  
第一种方法是使用pageContext对象进行对象的共享(可支持JSP页面和tag处理类之间的共享),如果在一个tag处理类中要调用由另一个tag处理类创建的对象,可调用pageContext.getAttribute(name, scope)方法。 D-FT3Culw  
{53|X=D64  
第二各方式的共享是对于tag之间有嵌套关系而言的,外层的tag所创建的对象对于内层的tag来说是可以共用的。这种形式的共享的好处是减少了可能存在的重名冲突。 8*;>:g  
iJH?Z,Tjf  
要访问一个嵌套tag创建的对象,tag处理类必须先找到此嵌套tag对象,可用TagSupport的静态方法 TagSupport.findAncestorWithClass(from, class)或TagSupport.getParent方法。前者在当不确定此tag是否为嵌套tag对象时使用。一旦它的父类被找到,它就能访问其所有动态或静态创建的对象。静态创建的对象是父类的成员,而动态创建的对象可能是父类的私有对象。诸如此类的对象可以用tag处理类的setValue方法来保存,用getValue方法来获得。 8<Pi}RH  
~b @"ir+g4  
下例阐述了以上两种共享对象的方法。在这个例子当中,一个查询tag检查一个名为connection的属性名是否在doStartTag中被设置。如果connection属性被设置,tag处理类从pageContext中得到这个connection对象。否则,此tag处理类先找到它的父tag处理类,然后从它的父tag处理类中找到connection对象。 Z((e-T#,  
5"y)<VLJX  
A4g,)  
public class QueryTag extends BodyTagSupport K~4bT=   
+ }$(j#h  
{ )t((x  
l9e=dV:pH  
private String connectionId; 9k \M<jA  
*cZ7?  
public int doStartTag() throws JspException M@JW/~p'  
nDcH;_<;9a  
{ h$mGaw vZ~  
PhAD: A  
String cid = getConnection(); \l%##7DRp]  
a6@k*9D>  
if(cid != null) jvxCCYXR  
=YIosmr  
{ YYL3a=;`a  
E 6+ ooB[  
//存在一个connection id,使用它。 P%ThW9^vnj  
, `PYU[  
connection = (Connection) pageContext.getAttribute(cid); $4*gi&  
P_5G'[  
} Cn0s?3Fm  
-/ G#ls|?  
else `n@;%*6/  
hXvC>ie(i  
{ ;66{S'*[  
*pDS%,$xe  
ConnectionTag ancestorTag = (ConnectionTag)findAncestorWithClass(this, p( )LQT!  
!L( )3=  
ConnectionTag.class); k{O bm g  
1_TniR3z1  
if(ancestorTag == null) hYh~%^0dt  
S=W^iA6>  
{ wwv+s~(0  
)3R5cq  
throw new JspTagException(“一个没有connection属性的查询标签必须被一个connection标记嵌套。”); v_WF.sb~  
8H1&=)M=  
} QeN7~ J  
rp^:{6O  
connection = ancestorTag.getConnection(); XD" 4t4~>  
@+1AYVz(k  
} B`gH({U  
I2krxLPd  
} 0dQ\Y]b  
:wEy""*N0  
} q&}+O  
i9V,  
c$lZ\r"  
!x\\# 9  
此查询标签在JSP页面中的调用形式可以从以下2种定义中任选一种: .s?^y+e_  
: sw@1  
z`eMb  
<tt:connection id=”con01” ...> ... </tt:connection> GXk |p8  
f]mVM(XZN  
<tt:query id=”balances” connection=”con01” > R\Ckk;<$  
OI8}v  
SELECT account, balance FROM acct_table \%9QE  
Q,Y^9g"B`~  
where customer_num = <%= request.getCustno() %> E^A!k=>  
>vR2K^  
</tt:query> 6$kh5$[  
I0><IaFy  
ef!f4u\  
tv Zq):c  
lon9oraF'  
<tt:connection ...> -r]L MQ  
|lk:(~DM  
<x:query id=”balances”> a]Y9;(  
2<@g *  
SELECT account, balance FROM acct_table  -PU.Uw]  
gyPwNE  
where customer_num = <%= request.getCustno() %> fW[RCd  
o\PHs4Ws'7  
</x:query>  D F=Rd#  
gX$gUB) x  
</tt:connection> xJnN95`R@  
;.rY`<|  
JStEOQF4  
与此同时,在TLD中必须指定connection属性为可选的,定义如下: ^.  
CJDNS21m  
<tag> HIt9W]koO  
K r<UPr  
... T\ukJ25!  
I~Qi):&x  
<attribute> 9]lyV  
`Q/\w1-Q  
<name>connection</name> `I4E': ZG  
ImD&~^-_<  
<required>false</required> SSyARR+;c  
f"NWv!  
</attribute> SG1AYUs V  
9qB4\ONXZ  
</tag>
描述
快速回复

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