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

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

级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
标准的JSP 标记可以调用JavaBeans组件或者执行客户的请求,这大大降低了JSP开发的复杂度和维护量。JSP技术也允许你自定义taglib,其实换句话说,taglib可以看成是对JSP标记的一种扩展,正如xml是对html的一种扩展一样。taglib通常定义在tag标签库中,这种标签库存放着你自己定义的tag标签。简而言之,如果使用taglib,那么你可以设计自己的JSP标记! V)#rP?Y  
C~q&  
一般来说,自定义tag标签主要用于操作隐藏对象、处理html提交表单、访问数据库或其它企业级的服务,诸如邮件和目录操作等等。自定义tag标签的使用者一般都是那些对java编程语言非常精通,而且对数据访问和企业级服务访问都非常熟悉的程序员,对于HTML设计者来说,使得他可以不去关注那些较复杂的商业逻辑,而将精力放在网页设计上。同时,它也将库开发者和库使用者进行合理分工,自定义tag标签将那些重复工作进行封装,从而大大提高了生产力,而且可以使得tag库可用于不同的项目中,完美地体现了软件复用的思想。 D?`|`Mu  
!6pE0(V^+4  
在这篇文章中,我们主要讨论: 1qN+AT  
W_Eur,/`  
· 什么是自定义tag标签? k:* (..!0z  
&+Yoob]P  
· 怎么使用tag标签?  ie4BE'  
u[+/WFH  
o 声明要使用的tag库 U "kD)\  
XTS%:S  
o 找到与之对应的tag处理类 ?A2jj`N1x  
M) Z3q  
o tag标签的类型 P`]p&:  
q-R'5p\C?|  
· 自定义tag标签 3Ued>8Gv  
YAJr@v+Ls  
o tag处理类 >8=rD  
:~4 M9  
o tag库描述 .xV^%e?H  
3.E3}Jz`  
o tag标签示例 fUa[3)I  
4elA<<  
o 带属性的tag Jx3fS2  
o~tL;(sz  
o 带body的tag  >Q% FW  
^Y?Y5`! Q  
o 定义了脚本变量的tag Ew>lk9La(  
$4u8"ne)  
o 具有协作关系的tag =+"=|cQ  
K3-Cuku  
· 自定义tag标签 8XhGo2zf  
|Wz`#<t  
o 一个迭代tag的例子 CaqqH`/E4  
L{uQ: ;w1  
o 一个模板tag库 8}>s{u;W  
94b* !Z  
o tag处理类到底是怎样被调用的? 1/<Z6 ?U  
6hAMk<kx?i  
&T2qi'  
什么是自定义的tag? 1 ILA Utf)  
ix!4s613w  
一个自定义的tag标签是用户定义的一种JSP标记。当一个含有自定义的tag标签的JSP页面被jsp引擎编译成servlet时,tag标签被转化成了对一个称为tag处理类的对象进行的操作。于是当JSP页面被jsp引擎转化为servlet后,实际上tag标签被转化成为了对tag处理类的操作。 Z[G:  
+xn59V  
自定义tag标签有很多特色,诸如: >NjgLJh  
tA{?-5  
· 可以在JSP页面中自定义tag标签的属性 E-"b":@:  
x A"V!8C  
· 访问JSP页面中的所有对象 )Oix$B!-  
D9;s%  
· 可以动态地修改页面输出  LAO2Py#  
GjeRp|_Qd<  
· 彼此这间可以相互通信。你可以先创建一个JavaBeans组件,然后在一个tag中调用此JavaBeans组件,同时可以在另一个tag中调用它。 VK3e(7 b  
=x5k5NIF  
· tag允许相互嵌套,可以在一个JSP页面中完成一些复杂的交互。 SJ).L.Cm6  
:!<U"AC  
Rb l4aB+   
使用tag标签 J8#3?Lp  
*7G5\[gI$  
.$N8cYu0  
本节主要描述怎样在JSP页面中使用tag标签,以及tag标签的不同类型。 3Q~zli:  
]o2 Z 14  
要使用tag标签,JSP程序员必须做2件事: W $EAo+V  
sQgJ`+Y8_  
· 声明此tag标签的tag库 LypBS]r u  
|nT+ W| 0U  
· 实现此tag标签 #1<Jwt+  
;`:A(yN]T  
声明tag标签所在的tag库 /`VrV{\/!  
tq&CJvJ4  
如果要使用tag标签,则应用JSP的taglib指示符来指定其tag库(注意:taglib要在在使用此tag标签之前声明) A_}6J,*u  
%hV]vm  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> {LoNp0i1a  
*4?%Y8;bF6  
uri属性定义了唯一的标签库描述(以下简称TLD),它可以是直接是tld文件名或一个独一无二的名字。prefix是用来区别其它TLD中和本TLD中有重名的tag的一种手段。 U2kl-E:  
thrv_^A  
TLD必须以.tld作为扩展名,并且存放在当前应用的WEB-INF目录或其子目录下。你可以通过它的文件名直接引用它,也可以通过别的方式间接地引用它。 2R>!Wj'G+o  
Dhzm C  
以下taglib指示符直接引用一个TLD: Tv /?-`Y  
8Q\ T,C  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> Xn* >qm  
8Y&_X0T|  
以下的taglib指示符通过一个逻辑名称间接地引用一个TLD: "d c- !  
S7f"\[Aw  
<%@ taglib uri=”/tutorial-template” prefix=”tt” %> ve@E.`  
WdJJt2'  
如果是间接引用TLD的话,那你必须还要在web.xml中定义此逻辑名称与tld文件之间的映射,具体做法是在web.xml中加入一个名为taglib的元素: r>Cv@4/j  
s]Qo'q2  
<taglib> {RHa1wc  
= sh3&8  
<taglib-uri>/tutorial-template</taglib-uri> ~xU\%@I\  
Be~In~~  
<taglib-location> JHCXUT-r{  
dz=pL$C  
/WEB-INF/tutorial-template.tld -i*]Sgese  
/j;HM[  
</taglib-location> MoMxKmI  
WI\jm&H r  
</taglib> $[{YE[a  
7Kn}KO!Y8  
uE-|]QQo  
实现此tag标签 W'L  
) $=!e%{  
"s.s(TR8  
为了实现tag标签,你有2种方法来存放tag处理类。一、让tag处理类以.class的方式存放于当前应用的WEB-INF/class子目录下,二、如果tag处理类是以JAR包的形式存在的话,那可以放在当前应用的WEB-INF/lib目录下,如果tag处理类要在多个应用中共享,那么它就应放在jsp服务器上的common/lib目录下,对于tomcat来说,就是tomcat/common/lib目录下。 Bf8[(oc~  
)POU58$  
!1[ZfTX^a  
tag标签类型 U}^`R,C  
w'zSV1  
9Z lfY1=  
自定义的tag标签遵循XML语法。它有一个开始标记和一个结束标记,有的还有body(即文本节点): $3yn-'o'A  
eh}I?:(a?  
<tt:tag> cs7K^D;.V  
G}#p4 \/  
body /[,0,B9!3  
pv@w 8*  
</tt:tag> N.dcQQ_iS  
,FWsgqL{l  
!T RU  
一个不带body的tag标签如下: y[d>7fcf  
KkyZd9  
<tt:tag /> $_Q]3"U  
a|kEza,]  
gRg8D{  
简单的tag标签 Q 1[E iM3  
IA^*?,AZy  
一个没有body和属性的tag标签如下: \.Z /  
&*9 ' 0  
<tt:simple /> ?#Y1E~N  
"mB /"  
wrAcVR  
带属性的tag标签 3B?7h/f  
P`OZoI$bV  
K?eY<L  
自定义标签可以有自己的属性。属性一般在开始标记中定义,语法为 attr=”value”。属性的作用相当于自定义标签的一个参数,它影响着tag处理类的行为。你可以在TLD中详细定义它。 JGQ)/(  
,)Z1&J?  
你可以用一个String常量给一个属性赋值,也可以通过表达式给它赋值,如<%= ...%>。以struts为例,它的logic:present标签就是用的String常量来给属性赋值: *Z2#U ?_  
#@}wl  
<loglic:present parameter = “Clear”> rL|9Xru  
)W |_f  
而另一个标签logic:iterate是用表达式来给属性赋值: M=#g_*d  
.RN2os{  
<logci:iterate collection=”<%= bookDB.getBooks() %>” LjPpnjU  
WuMr";2*E  
id=”book” type=”database.BookDetails”> 'Oa(]Br[  
I;+>@Cn(g<  
*s$:"g-  
带body的tag标签 sPRo=LB  
D),hSqJ"  
一个自定义标签可以包含其它自定义标签、脚本变量、HTML标记或其它内容。 F`M`c%  
= PIarUJ  
在下述例子中,此JSP页面使用了struts的logic:present标签,如果些标签定义了parameter=”Clear”的属性,则将清除购物车的内容,然后打印出一条信息: }$@E pM  
{"mb)zr  
<logic:present parameter=”Clear”> >N-l2?rE  
b/obHB+:  
<% cart.clear(); %> DMiB \o  
B~47mw&b  
<font color=”#ff0000” size=”+2”><strong> A+ LX37B  
h]DzX8r}  
你选择了清除购物车! XU6SYC"t%~  
/5m~t.Z9M  
</strong></font> wPxtQv  
y)mtSA8  
</logic:present> M+-1/vR *@  
Cp^`-=r+  
m(CAXq-t  
到底是用属性还是用body来传递信息? 2k+u_tj>  
)uC5  
如上所述,我们既可以通过属性,也可以通过body来传递信息。但一般来说,比较简单的类型,如字符串或简单表达式最好采用属性来传递信息。 A@)ou0[n@  
[ ]42$5eof  
UAOH9*9*  
定义脚本变量的tag标签 %6E:SI 4  
gp NAM"  
所谓脚本变量,是指JSP中可以调用的变量或对象。它可由tag标签产生。以下示例阐述了一个tag标签定义了一个名为tx的由JNDI所定义的事务处理对象。脚本变量可以是ejb对象、事务、数据库连接等等: 5v"Sv  
Esdw^MGL2  
<tt:lookup id=”tx” type=”UserTransaction” name=”java:comp/UserTransaction” /> <8BNqbX  
%:yVjb,Yf  
<% tx.begin(); %> CtE <9?  
 J7p?9  
... pReSvF}}C  
M"5S  
!NTt' 4/F{  
具有协作关系的tag标签 2-beq<I  
RSBk^  
自定义tag标签之间可以通过共享对象来实现协作。在下述例子中,标签tag1创建了一个名为obj1的对象,在标签tag2仍可以重复使用obj。 zszx~LSvIT  
h~s h!W8  
<tt:tag1 attr1=”obj1” value1=”value” /> =O>E>Q  
:Hj #1-U  
<tt:tag2 attr1=”obj1” /> d'[]  
pZ5eGA=  
在以下这个例子当中,如果外层的tag标签创建了一个对象,那么其内层的所有tag标签都可以使用这个对象。由于这样产生的对象没有一个指定的名字,那么就可以将少重名的冲突。这个例子阐述了一系列协作的嵌套对象。 ~'0W(~Q8  
7uq^TO>9f  
<tt:outerTag> Ny G?^  
#]z_pp:  
<tt:innerTag /> \CrWKBL  
=`.OKUAn  
</tt:outerTag> wW|[Im&  
ZiC~8p_f  
M`H@ % M  
Tag处理类 tC\(H=ecP  
!YIW8SP)  
oa6&?4K?F  
Tag处理类必须实现Tag接口或BodyTag接口,不过现在一般都流行从TagSupport或BodyTagSupport类中继承,这些类或接口都可以在javax.servlet.jsp.tagext包中找到。 y=LN| vkQ  
B~2M/&rM\  
当JSP引擎看到自己的JSP页面中包含有tag标签时,它会调用doStartTag方法来处理tag标签的开头,调用doEndTag方法来处理tag标签的结束。 f7I!o, /  
-;iCe7|Twf  
下表说明不同类型的tag所需要不同的处理过程: ?63ep:QEk  
pMzlpmW;P  
Tag处理类的方法 p{[(4}ql  
tgC)vZ&a  
Tag标签类型 j> dL:V&`  
所调用的方法 3]h*6 V1$  
e#(X++G  
基本标签 qv3% v3\4  
doStartTag, doEndTag, release w]O,xO  
n a+P|'6  
带属性的标签 }s:~E2?In  
doStartTag, doEndTag, set/getAttribute1...N, release eDY)i9"W  
PLRMW 2  
带内容的标签 }-~LXL%!3  
doStartTag, doEndTag, release 3u[5T|D'  
6&_K;  
带内容的标签,且内容重复循环 a([8r- zP  
doStartTag, doAfterBody, doEndTag, release U\i7'9w]3  
?<1~KLPMhY  
带内容的标签,且内容与JSP交互 lH/7m;M  
doStartTag, doEndTag, release, doInitBody, doAfterBody, release q,>4#J[2;s  
nIGElt]  
一个tag处理类可以通过javax.servlet.jsp.PageContext来与JSP交互,通过javax.servlet.jsp.PageContext类,tag处理类可以访问JSP中的request、session和application对像。 YR u#JYti  
,$Xhwr  
如果tag标签是互相嵌套的,那内层的tag处理类可以通过它的parent属性来访问上层的tag处理类。 Lm*PHG  
\e~5Dx1  
一般情况都将所有的tag处理类打成了JAR的包,以便于发布。 dgT(]H  
E <\\/Q%w  
<aQ5chf7  
Tag库描述(简称TLD) tv%B=E!r  
#3_ @aq*  
d[oHjWk  
Tag库是用xml语言描述的,TLD包括了tag库中所有tag标签的描述,它一般用来被jsp服务器用来校验tag的语法正确性,或者被jsp开发者用来开发新的标签。 ~8U0(n:^  
pyp0SGCM:  
TLD的文件扩展名必须为.tld,而且必须放在当前WEB应用的WEB-INF目录或其子目录中。 >tE6^7B*  
#,9#x]U#v  
一个TLD的内容的开头必须遵守标准的XML开头,用于描述DTD和xml的版本,例如: J$i.^|hE/  
GezMqt;2  
<?xml version="1.0" encoding="ISO-8859-1" ?> ^/~C\ (  
R)6"P?h._4  
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd"> ]E^)d|_  
TLD必须以<taglib>来作为它的根元素,<taglib>的子元素如下表: 5A+r^xN  
1 Q*AQYVY  
JC iB;!y  
<taglib>的子元素 Rw)=<XV)6  
(e4 #9  
Element Y|ErVf4  
Description QypUBf  
#'BPW<Ob  
tlib-version %Ot*k%F  
Tag库的版本 }J $\<ZT  
!Y10UmMu  
jsp-version ]Rj?OSok  
Tag库所需要的jsp的版本 .yB{+  
RcOfesW o  
short-name C(kL=WD   
助记符,tag的一个别名(可选) 395`Wkv  
Q096M 0m  
uri f /t`B^}@  
用于确定一个唯一的tag库 )j. .)o  
\|CuTb;0  
display-name c^stfFE&  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) ydMSL25<+  
K9ek  
small-icon @a,} k<@E  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) 1} ~`g ED  
m]Mm (7v(  
large-icon "-S@R=bi  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) v^B2etiX_  
^O,r8K{1n  
description ,n$NF0^l  
对tag库的描述(可选) &Qq|  
U#|6n ,  
listener ZqX p f  
参见下面listener元素 (XEJd4r  
b-RuUfUn0  
tag I8Y #l'z  
参见下面tag 元素 0+/ew8~$  
a}X. ewg  
Listener元素 I.it4~]H  
%Z*N /nU  
一个tag库可能定义一些类做为它的事件侦听类,这些类在TLD中被称为listener 元素,jsp服务器将会实例化这些侦听类,并且注册它们。Listener元素中有一个叫listener-class的子元素,这个元素的值必须是该侦听类的完整类名。 w<Bw2c  
z fu)X!t^  
Tag元素 U:bnX51D4  
b4 Pa5 w  
每个tag元素在tag库中都要指出它的名字、类名、脚本变量、tag的属性。其中脚本变量的值可以直接在TLD中定义或通过tag附加信息的类来取得。每个属性描述了这个属性是否可以省略,它的值是否可以通过<%= …%>这样的JSP语法来获得,以及属性的类型。 #3?}MC  
biENRJQ.  
每一个tag在TLD中对应一个tag元素,下表是tag元素的子元素: =yWdtBng  
!C ZFbz~:  
Tag元素的子元素 }=|plz}  
/7x1Z*Hg  
元素名称 gux?P2f  
描述 <`WcI`IA b  
d>V#?1$h  
name sgRWjrc/  
独一无二的元素名 a%5/Oc[[  
+ ]iK^y-.r  
tag-class 7"1]5\p^g  
Tag标签对应的tag处理类 $g),|[ x+(  
\2CEEs'  
tei-class Yr[& *>S  
javax.servlet.jsp.tagext.TagExtraInfo的子类,用于表达脚本变量(可选) R?M>uaxn  
L_o/fTz4  
body-content @M"( r"ab  
Tag标签body的类型 '$ [%x  
D 9UM8Hxi  
display-name k 7:Z\RGy  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) U+zntB  
O=6[/oc '  
small-icon "28zLo3  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) zbgGK7  
]E6r )C  
large-icon !t}yoN n|  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) BN~ndWRK  
RFX{]bQp9  
description !(gSXe)*  
此tag标签的描述 =.w~qL  
qae|?z  
variable MBAj.J  
提供脚本变量的信息(同tei-class)(可选) Qe-PW9C  
hVAatn[  
attribute 0o:R:*  
Tag标签的属性名 3R-5&!i  
M6GiohI_"P  
以下章节介绍对于不同类型的tag,如何具体地实现它们。 P#D|CP/Cu  
v7\rW{~Jd&  
G#M0 C>n  
简单的tag }F"98s W  
8H|ac[hXK2  
`YqXF=-  
tag处理类 `jVRabZ0  
.R l7,1\  
简单的tag处理类必须实现Tag接口的doStartTag和doEndTag方法。当jsp引擎碰到tag标签的开头时,doStartTag被调用,因为简单的tag没有body,所以此方法将返回 SKIP_BODY。当jsp引擎碰到tag标签的结尾时,doEndTag被调用,如果余下的页面还要被计算,那它将返回EVAL_PAGE,否则将会返回SKIP_PAGE。 Pm,.[5uc  
_07$TC1  
以下是例子:对于标签 <tt:simple /> ,它的tag处理类实现如下: LR';cR;  
#jd.i  
`?b'.Z_J  
public SimpleTag extends TagSupport O<E8,MCA[a  
%k~ezn  
{ +bT[lJ2O>G  
X?XB!D7[  
public int doStartTag() throws JspException K)5j  
=3`|D0E  
{ ]k'^yc{5  
gA% A})  
try{ #sxv?r  
)@P*F) g~  
pageContext.getOut().print(“Hello.”); %ZX9YuXQ  
:(wFNK/0{  
}catch(Exception e){ a=`] L`|N  
/0$fYrg>J  
throw new JspTagException(“SimpleTag: “ + e.getMessage()); OzwJ 52  
\j5`6}zm  
} -m@PqJF^  
"eqzn KT%u  
return SKIP_BODY; 'GT^araz  
gS8+S\2  
} *,IK4F6>:  
- Ry+WS=  
public int doEndTag() w`=O '0d  
r)OiiD"  
{ -/V(Z+dj  
E AZX  
return EVAL_PAGE; e<*qaUI  
F-oe49p5e  
} ?5/7 @V  
iJZNSRQJ}r  
} EW1,&H  
GdY@$&z{i  
?c+$9  
注意:如果tag标签没有内容的话,那必须定义body-content元素为空,例如 *8po0s  
s]|tKQGl,  
<body-content>empty</body-content> 79D~Mau#  
t 7o4 aBl"  
ZO/u3&gU  
带属性的tag标签
评价一下你浏览此帖子的感受

精彩

感动

搞笑

开心

愤怒

无聊

灌水
级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
只看该作者 1 发表于: 2007-01-01
tag处理类 k sXQ}BE  
euVDrJ^  
对于tag标签的每个属性,你必须依照JavaBeans规范来定义其属性,以及get和set方法。以struts的logic:present 标签为例, C\~}ySQc.e  
V7r_Ubg@K  
<logic:present parameter=”Clear”> RL/y7M1j  
2l+L96  
与此相应,此tag处理类应有如下方法和定义: )#cZ& O  
nq8XVT.m^\  
()bQmNqmO=  
protected String parameter = null; 2#sFY/@  
[DH4iG5  
public String getParameter() $ P 5K   
 Pd\4hy  
{ NsP=l]  
<kPNe>-f  
return this.parameter; PJ0~ymE1~G  
]%HxzJ  
} FHw%ynC  
4\u`M R  
public void setParameter(String parameter) yn_f%^!G  
-0#"<!N  
{ -grmmE]/  
#dL,d6a  
this.parameter = parameter; &1yJrj9y  
0NGth(2  
} z k/`Uz  
6QCV i  
1W{oj  
注意:如果你的属性名为id,而且你的tag处理类是从TagSupport类继承的,那你就不需要定义它的属性和set和get方法,因为他们早已在TagSupport被定义过了。 J8p;1-C"  
n]`]gLF\i  
Attribute元素 ndzADVP  
a1y<Y`SC9  
对于tag标签的每个属性,你必须定义它是否必须的,它的值是否可以用诸如<%= …%>的表达式来获得,以及它的类型(可选),如果不指定它的类型,那就默认为是java.lang.String类型。如果rtexprvalue元素被定义为true或yes,那么在type元素中就定义了attribute的返回类型。 'ia-h7QWS  
3qf#NJN}  
<attribute> I9qFXvqL  
_<#92v !F  
<name>attr1</name> 3*~`z9-z  
SsTBjIX  
<required>true|false|yes|no</required> v_EgY2l(  
IDT\hTPIs  
<rtexprvalue>true|false|yes|no</rtexprvalue> ?'+]d;UO&  
5L[imOM0  
<type>attribute的返回类型(只用当rtexprvalue为真是才有效)</type> D]fuX|f~ul  
m+;U,[%[*E  
</attribute> n=V|NrU  
<O0tg[ub  
如果tag的某个属性不是必须的,那tag处理类会自动提供一个缺省值。 i0K 2#}=^  
P dqvXc  
例如,在logic:present这个tag标签中定义了一个属性叫parameter,但它不是必须的,而且它可以被诸如<%= …%>的表达式来赋值。 os"R'GYmf  
[*p;+&+/ZM  
<tag> 2A; i  
%%}l[W  
<name>present</name> AXHY$f|  
BInSS*L  
<tag-class>org.apache.struts.taglib.logic.PresentTag</tag-class> Lv['/!DJ|  
dN3^PK  
<body-content>JSP</body-content> RU7+$Z0K  
C/Tk`C&  
N=Ct3  
`e<IO_cg  
<attribute> 9dNkKMc@  
SNOc1c<~  
<name>parameter</name> rIPfO'T?  
<q$Tk,  
<required>false</required> 7HH@7vpJ^  
E> GmFw  
<rtexprvalue>true</rtexprvalue> <b,WxR`  
2PyuM=(Wt  
</attribute> s_/@`kd{  
v77UE"4|c  
2=fM\G  
QOktIH  
</tag> `WOoC   
v)_c*+6u  
jn|NrvrX  
属性元素的校验 GqL&hbpi  
5@%Gq)z5  
\ YF@r7  
有关于tag标签的有效值可以从tag库的说明文档中获得,当JSP页面被编译时,jsp引擎会强制性地参照TLD中定义的规则进行检查。 4;J.$  
>~Zj  
还有一个方法也可以进行属性元素的校验,就是先继承类TagExtraInfo,然后调用它的isValid方法。这个类同时也起到提供tag中定义的脚本变量信息的作用。 X}(X\rp  
[-VH%OM  
IsValid方法通过TagData对象来传递属性信息,它包括着tag的所有的属性名-值的信息。由于校验发生在运行时刻,因此这个属性的值将被赋值为TagData.REQUEST_TIME_VALUE。 j!i* &  
I F6$@Q  
例如tag标签<tt:twa attr1=”value1” />在TLD中定义如下: 8|)!E`TKSV  
g $Y]{VM.J  
<attribute> d.~ns4bt9  
G{fPQ=  
<name>attr1</name> ]vz6DJs  
8%m\J:e R  
<required>true</required> H"? 5]!p  
#;a+)~3*O  
<rtexprvalue>true</rtexprvalue> hzr, %r  
_]o7iqtv  
</attribute> w/o^OjwQ  
Y+Z+Y)K  
tq h)yr;  
这个定义说明了attr1能在运行期间被赋值。 ,\"x#Cc f  
DSRc4 |L  
以下的isValid方法检查attr1属性的值是否属于Boolean类型。注意由于attr1能在运行刻被赋值,那么isValid方法必须检查tag用户是否对此tag进行了运行时刻赋值。 i4D]>  
;%2+Tc-7I  
g]L8Jli  
Public class TwaTEI extends TagExtraInfo e8 ]CB  
1$03:ve1  
{ J' P:SC1  
k 6[   
public boolean isValid(Tagdata data) eK1l~W%  
d^RcJ3w  
{ HN NeH;L  
? bWc<]  
Object o = data.getAttribute(“attr1”); k8}fKVU;  
ASoBa&vX  
If(o != null && o != TagData.REQUEST_TIME_VALUE) W?zj^y[w  
j:1N&7<FU  
{ 153*b^iDBh  
18%$Z$K,  
if( ( (String)o).toLowerCase().equals(“true”) || A,EG0yb  
8Gy]nD  
((String)o).toLowerCase().equals(“false”) ) 2EpQ(G J  
i=n;rT  
return true; liPrxuP`  
$!9U\Au>2  
else A}9^,C$#  
3l~7  
return false; 1YMi4.  
=p[Sd*d  
} %IVM1  
Xk%eU>d  
else b*h:e.q  
Kn$E{F\  
return true; .jP|b~  
P??P"^hU  
} Vbp@n  
}|Q\@3&  
} n%36a(] t  
<(Ar[Rp  
2 oL$I(83  
带body的tag C<a&]dN/  
&?QKWxN  
IxWi>8  
tag处理类 Gq1C"s$4'  
'j'6x'[> ]  
THOYx :Nr;  
如果tag标签含有内容,那处理方式会略微有些不同,而且还要视tag处理类是否要与body交互的情况而定。如果要与body交互,那我们认为tag处理类要可能要对body进行操作。 uaP5(hUI  
nX7F<k4G2  
Tag处理类不与body交互 -2}ons(  
y{(Dv}   
如果tag处理类不与body交互,tag处理类应该实现Tag接口或从TagSupport中派生,如果body要被计算,那么doStartTag方法应返回 EVAL_BODY_INCLUDE,否则应返回SKIP_BODY。 j07A>G-=  
Cd^1E]O0{  
如果tag处理类要对body反复运算,则它应该实现IterationTag或从TagSupport中派生。如果tag处理类认为body还未计算完的话,那它的doStartTag方法和doAfterBody方法必须返回EVAL_BODY_AGAIN。 !U4YA1>>  
3:WHC3}W  
Tag处理类与body交互 Ew.6y=Ba  
3%9XJ]Qao  
如果tag处理类与body交互,那tag处理类应实现BodyTag接口或从BodyTagSupport中派生。这种tag处理类一般要实现doInitBody和doAfterBody方法。 u{uqK7]+  
90abA,U@  
Body允许一些方法来读写它的内容。Tag处理类可以调用body内容的getString或getReader方法来从body中提取信息,也可用 writeOut(out) 方法来将body的内容写入到out对象中。其中out对象通过tag处理类的getPreviousOut方法来获得。 <n k/w5nKL  
#o~C0`8!B=  
如果body的内容需要被计算,那么doStartTag方法必须返回EVAL_BODY_BUFFERED,否则,它将返回 SKIP_BODY。 %?V~7tHm>  
_M8'~$Sg  
doInitBody 方法 EVqqOp1$v4  
au=@]n#<(  
此方法在body内容已经设好,但未被计算之前被调用。你可以根据不同的body内容来制定初始化策略。 W^HE1Dt]  
a|y'-r90  
doAfterBody方法 7fWZ/;p  
8H};pu2  
此方法在body内容已被计算后进行调用。 e:MbMj6`  
/: -&b#+  
和doStartTag方法一样,doAfterBody方法返回一个指示符指示是否要继续计算body,如果要继续计算,则doAfterBody应返回EVAL_BODY_BUFFERED,否则,它应返回SKIP_BODY。 ,\+N}F^  
FU*q9s`  
release 方法 45-x$o  
\kI{#   
tag处理类调用此方法将它的状态重置为初始状态,并释放所有的私有资源。 X<Xiva85  
WaX!y$/z  
4yTgH0(T  
以下的例子读取body的内容(其中含有一条sql语句),然后将它传递给一个对象,让它进行查询。由于此处body不须重新计算,所以doAfterBody会返回SKIP_BODY。 R9-mq; u+  
p {. 6  
fbdpDVmpU  
Public class QueryTag extends BodyTagSupport I4qS8~+#  
H^o_B1  
{ @>ys,dy  
$P8AU81  
public int doAfterBody() throws JspTagException Rc9>^>w  
1)97AkN(O  
{ a|]deJU^  
.*"KCQGOgM  
BodyContent bc = getBodyContent(); \TzBu?,v8  
#:Q\   
//将body的内容以字符串的格式提取出来 {Qd oI Pr3  
@R;k@b   
String query = bc.getString(); yfqe6-8U  
7zN7PHT=$t  
//清除body k`'*niz  
Ke#Rkt  
bc.clearBody(); C %j%>X`  
g 6?y{(1  
try{ fWIWRsy%  
lOb(XH9  
Statement stmt = connection.createStatement(); X<W${L$G  
b ~]v'|5[  
Result result = stmt.executeQuery(query); V4Qy^nn1  
PD^ 6Ywn>s  
}catch(SQLException e){ !H)!b#_  
l*CCnqE  
throw new JspTagException(“queryTag: “ + e.getMessage() ); h{\S'8  
hfc~HKLC  
return SKIP_BODY; =?]S8cth  
gCRPaF6  
} ;2 ?fz@KZ  
XCyb[(4  
} m#_M"B.cm  
L"c.15\  
e^;:iJS  
body-content元素 E}0g  
L|b[6[XTHL  
lc [)Ev  
由于tag可能会有body,你必须用body-content元素来指定body内容的类型: p,(W?.ZDN?  
c*R\fQd  
<body-content>JSP|tagdependent</body-content> Ed-3-vJej6  
g#1 Y4  
]TtID4qL  
如果body的内容是定制的或内部的tag、脚本元素、或HTML广本,则归类为JSP类型。其他的类型,比如上面代码所述的?D?D将sql statement类传给 query tag的这种类型应该标为tagdependent。 muK.x7zyl  
e6 <9`Xg  
注意:实际上body-content的值并不影响tag处理类对body内容的处理,它仅仅是被tag编辑工具用来描述此body的内容。 TZg1,Z  
I 5ZDP|  
&oZU=CN  
用tags定义脚本变量 77+3CME{'  
@x[A ^  
z.h;}QRJ,@  
tag处理类 \j.l1O  
T.%yeJiE  
y^Q);siSy  
tag处理类负责创建或设置页面中定义的脚本变量,用pageContext.setAttribute(name,value,scope)或pageContext.setAttribute(name,value)方法来实现。一般来说,tag处理类通过脚本变量的名称来获取它,脚本变量的名称一般可用get方法来获得。 sUiO~<Ozpk  
oxnI/Z  
如果脚本变量的值依赖于tag处理类中的上下文中某一对象,那它可用pageContext.getAttribute(name,scope)方法来找到那个对象。一般的处理过程是tag处理类先找到脚本变量,再对其进行处理,然后用pageContext.setAttribute(name,object)的方法来设置它的新值。 +l]> (k.2  
M,oZ_tY%  
对象的生存周期(scope)如下表: Ui1s ]R  
-i91nMi]  
对象的生存周期表 Cd6th F)  
33~8@]b  
名字 z'O+B}  
可访问范围 k1P'Q&Na  
生存周期 ]j*uD317  
kPAg *  
page rY@9nQ\>g  
当前页面 {+5Ud#\y  
一直有效,除非页面向客户提交响应或重定向到一个新页面 Q_0_6,Opb  
k`z]l;:  
request S|6i]/  
当前页面或当前页面重定向到的页面 xj AU Csq  
一直有效,除非页面向客户提交响应  VS7  
f?16%Rk<  
session f1U8 b*F<  
当前页面或在同一浏览器窗口中的页面 v7hw%9(=  
一直有效,除非关闭当前浏览器、超时、网络故障 m9D Tz$S.  
v<(+ l)Ln  
application $|[N3  
整个web应用程序的所有请求 VH+3o?nrT  
一直有效,除非发生网络故障、服务器故障 1TGE>HG  
w7q6v>  
提供关于脚本变量的信息 E1w8d4P,G  
c7[Ba\Cr4h  
以下示例定义了一个名为“book”的脚本变量,用来访问程序中关于书的信息: zR/mz)6_  
~oK0k_{~  
<bean:define id=”book” name=”bookDB” property=”bookDetails” type=”database.BookDetails” /> !4Sd^"  
zITxJx  
<font color=”red” size=”+2” > /Ah'KN|EN  
NweGK  
<%= messages.getString(“CartRemoved”) %> im)r4={ 9  
P{J9#.Zq&s  
<strong><jsp:getProperty name=”book” property=”title” /></strong> 6V6Mo}QF s  
+o0yx U 7t  
</font> V_n tS& 2o  
=@hCc  
当包含此tag的JSP页面被编译时,jsp引擎会自动生成关于此book的同步的代码(同步可以避免几个客户同时访问此book时造成的冲突),要生成同步代码,jsp引擎需要知道此脚本变量的如下信息: PJ<qqA`!  
}1CvbB%,A  
· 脚本变量名称 )1GJ^h$l  
!\Cu J5U  
· 脚本变量所属的类 0pH$Mk Q  
@~5Fcfmm  
· 此脚本变量是否引用了一个新的或已存在的对象 _^ n>kLd$  
*xj2Z,u  
· 此脚本变量的有效性 ^Q+z^zlC  
|942#rM  
有两种办法可以向jsp引擎提供关于脚本变量的信息:在TLD中定义variable子元素,或用tei-class子元素定义一个额外tag信息类。用variable最简单,但可能降低了一些灵活性。 Z0XQ|gkH  
<y7Hy&&y-  
Variable元素 -H|!KnR  
YV>&v.x0;  
Variable元素有如下子元素: W+4Bx=Mj  
(Gapv9R  
· name-given ?D?D 给出的名字,是一个常量 VpY,@qh  
J*6B~)Sp@  
· name-from-attribute?D?D 属性名,在编译时给出的属性名 XgeUS;qtta  
7xWJw  
name-given或name-from-attribute两者必须选一,但以下子元素是可选的: `fG<iBD  
:2wT)wz  
· variable-class?D?D变量的类型,缺省为java.lang.String。 *1:kIi7_  
Q]RE,ZZ  
· declare?D?D此脚本变量是否引用了一个新对象,缺省为True。 DFRgn  
+Oo-8f*  
· scope?D?D脚本变量的范围,缺省为NESTED。下表描述了scope的几种类型: ^'+#BPo9@  
Znh;#%n|  
脚本变量的有效范围 vkG%w;  
yWT1CID  
CC$rt2\e  
有效性 g]BA/Dw  
方法 nT}i&t!q8@  
3.ShAL  
NESTED v5?ct?q  
在tag标签的开始和结束之间 P"@^BQ4  
如果tag处理类实现BodyTag接口,则在doInitBody和doAfterBody中调用,否则在doStartTag中调用 TXs&*\  
WqCj;Tj|  
AT_BEGIN N_+D#Z.g  
从tag标签的开始一直到页面结束 CEzdH!nP  
如果tag处理类实现BodyTag接口,则在doInitBody、doAfterBody和doEndTag中调用,否则在doStartTag和doEndTag中调用 f^IB:e#j;  
Q+_z*  
AT_END ]'hel#L;l  
从tag标签的结束一直到页面结束 mGmZ}H'{  
在doEndTag中调用 "W9z>ezp  
^![7X'!;pt  
以struts为例,它的bean:define标签的实现遵循JSP1.1规范,此规范要求使用额外tag信息类来定义脚本变量。Variable元素是JSP1.2规范中加入的。以bean:define标签为例,你可以定义如下variable元素: ~~t >;  
]xJ. OUJy  
<tag> "kIlxf3  
+<B"g{dLuX  
<variable> 4((p?jb C  
{Dy,u%W?  
<name-from-attribute>id</name-from-attribute> BmYX8j]  
}%42Ty  
<variable-class>database.BookDetails</variable-class> *#?9@0b@  
;DKJ#tS}"  
<declare>true</declare> 6Tm7|2R  
)?LZg<<   
<scope>AT_BEGIN</scope> >dwWqcP  
Lso%1M  
</variable> mW,b#'hy  
Aq>?G+  
</tag> /h]ru SI  
*Z2Ko5&Y2  
额外tag信息类 `ooHABC  
rx<P#y]3)  
如果要定义一个额外tag信息类,你要继承javax.servlet.jsp.TagExtraInfo类。一个TagExtraInfo类必须实现getVariableInfo方法,此方法返回一个叫VariableInfo的数组类,它包括如下信息: =fB"T+  
$_\x}`c~.  
· 变量名 \E05qk_;K  
]<Q&  
· 变量所属类名 fy&u[Jd{  
qamq9F$V  
· 此变量是否引用了一个新对象 M}=>~TA@  
!g#y$  
· 此变量的有效范围 KhL%ov  
1jPh0?BY  
jsp引擎将一个名为data的参数传给getVariableInfo方法,data中包括tag标签中的所有“属性名?D?D属性值”对。它可以用来向VariableInfo对象提供脚本变量的名字和类名。 l=$?#^^ /  
Wk!<P" nHd  
以struts为例,它在bean:define标签中定义了一个名为DefineTei的额外tag信息类,用来向脚本变量提供信息。由于脚本变量的名称(book)和类名(database.BookDetails)是通过tag标签的属性来传递的,它们一般定义在VariableInfo的构建代码中,并且可用data.getAttributeString方法来得到这些信息。如果要允许book脚本变量能在从tag开始直到整个JSP页面结束的范围内都可用的话,那它的范围应设为AT_BEGIN。如下所示: qHd7C3  
W}%[i+  
<HpUP!q8v  
public class DefineTei extends TagExtraInfo l$R9c+L=  
3&+nV1  
{ P1Iy >%3  
'Ddzlip  
public VariableInfo[] getVariableInfo(TagData data) 6 Pdao{P  
:wUi&xw  
{ 'cc{sjG  
Np$ue }yr  
String type = data.getAttributeString(“type”); l2Rnyb<;;  
it-2]Nw  
If( type == null) E!L_"GW  
J 5xZL v  
type = “java.lang.Object”; T~g`;Q%i  
-"#jRP]#  
return new VariableInfo[] { _U^G*EqL*  
vCOtED*<  
new VariableInfo(data.getAttributeString(“id”), 2gEF$?+q?  
?<Mx*l  
type, nm %7e!{m  
Re*~C:  
true, 4 DV,f2:R4  
\,lIPA/L  
VariableInfo.AT_BEGIN) ;(K"w*  
,<s:* k  
}; aH_FBY  
k_gl$`A  
} >CHb;*U  
T?tZ?!6  
} la^K|!|  
^7=h%{ >=  
|M18/{  
注意:关于额外tag信息类的类名必须要在TLD中的tag标签下的tei-class子元素中定义。因此,DefineTei的tei-class中的定义看起来如下: QpS7 nGev  
<tei-class> jI<_(T  
org.apache.struts.taglib.bean.DefineTagTei {*<%6?  
</tei-class> 82o|(pw  
sNMF(TY  
S?c<Lf~W  
具有协作关系的tag f=7[GZoDn  
,8!'jE[d  
= U[$i"+  
tag通过共享对象来进行协作,JSP技术支持2种方式的对象共享。 H%i [;  
2NB $(4/  
第一种方法是使用pageContext对象进行对象的共享(可支持JSP页面和tag处理类之间的共享),如果在一个tag处理类中要调用由另一个tag处理类创建的对象,可调用pageContext.getAttribute(name, scope)方法。 8CH9&N5W5t  
/1Ss |.  
第二各方式的共享是对于tag之间有嵌套关系而言的,外层的tag所创建的对象对于内层的tag来说是可以共用的。这种形式的共享的好处是减少了可能存在的重名冲突。 g?cxqC<  
)a%E $`   
要访问一个嵌套tag创建的对象,tag处理类必须先找到此嵌套tag对象,可用TagSupport的静态方法 TagSupport.findAncestorWithClass(from, class)或TagSupport.getParent方法。前者在当不确定此tag是否为嵌套tag对象时使用。一旦它的父类被找到,它就能访问其所有动态或静态创建的对象。静态创建的对象是父类的成员,而动态创建的对象可能是父类的私有对象。诸如此类的对象可以用tag处理类的setValue方法来保存,用getValue方法来获得。 n{M-t@r7  
)d|s$l$?7  
下例阐述了以上两种共享对象的方法。在这个例子当中,一个查询tag检查一个名为connection的属性名是否在doStartTag中被设置。如果connection属性被设置,tag处理类从pageContext中得到这个connection对象。否则,此tag处理类先找到它的父tag处理类,然后从它的父tag处理类中找到connection对象。 #6pJw?[  
,)VAKrSg  
d vo|9 >  
public class QueryTag extends BodyTagSupport lB!M;2^)X  
gQ<{NQMzvd  
{ Xxj<Ai 2  
4RH>i+)pS\  
private String connectionId; 5s>>] .%  
B^{~,'  
public int doStartTag() throws JspException dh%DALZ8t  
Rv.IHSQUo  
{ 6l2Os $  
u}rJqZ  
String cid = getConnection(); NH*"AE;  
0vMKyT3 c  
if(cid != null) vTL/% SJ8  
`_BmVms  
{ BbPRPkV  
GXRW"4eF5  
//存在一个connection id,使用它。 sN) xNz  
en6;I[\  
connection = (Connection) pageContext.getAttribute(cid); :Smyk.B2!  
uWP0(6 %  
} aNwx~t]G  
UXw I?2L  
else [<d_#(]h'  
+G,_|C2J  
{ <)Y jVGG  
<Ynrw4[)t  
ConnectionTag ancestorTag = (ConnectionTag)findAncestorWithClass(this, 9Sl5jn  
xmfZ5nVL  
ConnectionTag.class); 0;]VTz?P  
ZoCk]hk  
if(ancestorTag == null) +6^hp-G7  
6 B7 F  
{ mXyg\5  
q%,y66pFr  
throw new JspTagException(“一个没有connection属性的查询标签必须被一个connection标记嵌套。”); 9hJ a K  
ZkNet>9  
} =-qYp0sVP  
$if(n||  
connection = ancestorTag.getConnection(); rX)_!mR  
]u:Ij|.'y0  
} kxmsrQ>av  
tJGK9!MH{(  
} {s6hi#R>  
}%^3  
} c6iFha;db  
7 h>,  
Zlygx  
R0G!5>1i  
此查询标签在JSP页面中的调用形式可以从以下2种定义中任选一种: qca=a }  
Pu'NSNT  
K@{R?j/+  
<tt:connection id=”con01” ...> ... </tt:connection> xqauSW  
(UTA3Db  
<tt:query id=”balances” connection=”con01” > WmRu3O  
IGlM} ?x  
SELECT account, balance FROM acct_table -U\s.FI.AR  
$+,kibk*R  
where customer_num = <%= request.getCustno() %> R3.8Dr 0f  
42:,*4t(  
</tt:query> RVF<l?EI4R  
/2Ok;!.  
def\=WyK  
iRM ?_|  
&v feBth  
<tt:connection ...> ?=HoU3  
J0o,ZH9  
<x:query id=”balances”> <~u-zaN<W  
3{TE6&HIa  
SELECT account, balance FROM acct_table zy|h1 .gd  
Z!4B=?(  
where customer_num = <%= request.getCustno() %> B3I0H6O  
>LB*5  
</x:query> z$Qy<_l  
\3hFb,/4k  
</tt:connection> y(Em+YTD  
6=*n$l# }  
f>m ! }F:  
与此同时,在TLD中必须指定connection属性为可选的,定义如下: #IJ6pg>K  
X+ /^s)  
<tag> q 2;CvoF  
.k%/JF91n  
... 98vn"=3  
K?yMy,9%Yw  
<attribute> R?Ch8mW.!  
};f^*KZ=0  
<name>connection</name> 162Dj$  
&G?w*w_n  
<required>false</required> ~ cI`$kJ  
j9BcoEl:;  
</attribute> 3ik~PgGoKQ  
}|nEbM]#  
</tag>
描述
快速回复

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