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

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

级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
标准的JSP 标记可以调用JavaBeans组件或者执行客户的请求,这大大降低了JSP开发的复杂度和维护量。JSP技术也允许你自定义taglib,其实换句话说,taglib可以看成是对JSP标记的一种扩展,正如xml是对html的一种扩展一样。taglib通常定义在tag标签库中,这种标签库存放着你自己定义的tag标签。简而言之,如果使用taglib,那么你可以设计自己的JSP标记! hvV_xD8|  
$W8Cf[a  
一般来说,自定义tag标签主要用于操作隐藏对象、处理html提交表单、访问数据库或其它企业级的服务,诸如邮件和目录操作等等。自定义tag标签的使用者一般都是那些对java编程语言非常精通,而且对数据访问和企业级服务访问都非常熟悉的程序员,对于HTML设计者来说,使得他可以不去关注那些较复杂的商业逻辑,而将精力放在网页设计上。同时,它也将库开发者和库使用者进行合理分工,自定义tag标签将那些重复工作进行封装,从而大大提高了生产力,而且可以使得tag库可用于不同的项目中,完美地体现了软件复用的思想。 hwnJE958L  
YlK7;yrq(  
在这篇文章中,我们主要讨论: p3951-D  
F iAY\4  
· 什么是自定义tag标签? n> w`26MMp  
cNK)5- U  
· 怎么使用tag标签? ) ]6h y9<  
).412I  
o 声明要使用的tag库 )r6EW`$  
oy.[+EI`|  
o 找到与之对应的tag处理类 hUpnI@  
c/3$AUsuO  
o tag标签的类型 _k66Mkd#b  
s4LO&STh{  
· 自定义tag标签 rxZi8w>}  
7:=k`yS,  
o tag处理类 R[[ ,q:4  
m]Y;c_DO:  
o tag库描述 M!m?#xz'c  
j6:7AH|!)2  
o tag标签示例 K >tf,  
v({N:ya  
o 带属性的tag %Q"(/jm?  
P7 yq^|  
o 带body的tag q3e8#R)l  
} (FPV*mS  
o 定义了脚本变量的tag ]1`g^Z@ 0  
  WY  
o 具有协作关系的tag </zXA$m  
Y g|lq9gD  
· 自定义tag标签 ,I.WX,OR  
-%c<IX>z9  
o 一个迭代tag的例子 }%!tT\8  
^V*-1r1  
o 一个模板tag库 uBnoQ~Qd[z  
K!z`  
o tag处理类到底是怎样被调用的? kQ>^->w  
w!^~<{ Kz  
G7LIdn=  
什么是自定义的tag? Q\Kx"Y3i  
Td\o9  
一个自定义的tag标签是用户定义的一种JSP标记。当一个含有自定义的tag标签的JSP页面被jsp引擎编译成servlet时,tag标签被转化成了对一个称为tag处理类的对象进行的操作。于是当JSP页面被jsp引擎转化为servlet后,实际上tag标签被转化成为了对tag处理类的操作。 O'*@ Ytn  
afEF]i  
自定义tag标签有很多特色,诸如: 0$.m_0H  
|Bo .4lX  
· 可以在JSP页面中自定义tag标签的属性 _s.;eHp,  
 \[:/CxP  
· 访问JSP页面中的所有对象 n| !@1sd  
!vD{Df>  
· 可以动态地修改页面输出 I~* ? d  
( <*e  
· 彼此这间可以相互通信。你可以先创建一个JavaBeans组件,然后在一个tag中调用此JavaBeans组件,同时可以在另一个tag中调用它。 El2e~l9  
BHFY%6J!  
· tag允许相互嵌套,可以在一个JSP页面中完成一些复杂的交互。 }CGSEr4'w~  
Cr ? 4Ngw  
"hz\Z0zg2  
使用tag标签 yzsab ^]  
K{fsn4rk  
&K+0xnUH  
本节主要描述怎样在JSP页面中使用tag标签,以及tag标签的不同类型。 wNJzwC&iQ  
|`d0^(X  
要使用tag标签,JSP程序员必须做2件事: A Io|TD5{~  
'_P\#7$!MV  
· 声明此tag标签的tag库 ,zTb<g  
XL}"1lE  
· 实现此tag标签 ?`_jFj+<\S  
yCz|{=7"j  
声明tag标签所在的tag库 d4?d4;{  
RI n9(r  
如果要使用tag标签,则应用JSP的taglib指示符来指定其tag库(注意:taglib要在在使用此tag标签之前声明) 5sO@OV\ y  
 cgu~  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> h@{_duu  
 |J5 =J  
uri属性定义了唯一的标签库描述(以下简称TLD),它可以是直接是tld文件名或一个独一无二的名字。prefix是用来区别其它TLD中和本TLD中有重名的tag的一种手段。 9O*_L:4o  
8|?LN8rp  
TLD必须以.tld作为扩展名,并且存放在当前应用的WEB-INF目录或其子目录下。你可以通过它的文件名直接引用它,也可以通过别的方式间接地引用它。 &^&zR(o`  
+UN<Zp7I/  
以下taglib指示符直接引用一个TLD: m} ?rJ  
` Nh"  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> %qf  V+^  
u+t$l^S  
以下的taglib指示符通过一个逻辑名称间接地引用一个TLD: {LzH&qu  
7Z,opc  
<%@ taglib uri=”/tutorial-template” prefix=”tt” %> y@V_g'  
_6@hTen`  
如果是间接引用TLD的话,那你必须还要在web.xml中定义此逻辑名称与tld文件之间的映射,具体做法是在web.xml中加入一个名为taglib的元素: UaG1c%7?X  
3riw1r;Q  
<taglib> n.oUVr=nX  
@F*wg  
<taglib-uri>/tutorial-template</taglib-uri> fl\aqtF  
J8a*s`ik  
<taglib-location> "6ECgyD+E!  
`Mj}md;O"  
/WEB-INF/tutorial-template.tld -f1k0QwL  
0JuD ^  
</taglib-location> TJ8E"t*)  
1nknSw#  
</taglib> {:nQl}  
,|?CU r9Y  
g9fq5E<G  
实现此tag标签 `Hx~UH)  
@wmi 5oExc  
fU3`v\X  
为了实现tag标签,你有2种方法来存放tag处理类。一、让tag处理类以.class的方式存放于当前应用的WEB-INF/class子目录下,二、如果tag处理类是以JAR包的形式存在的话,那可以放在当前应用的WEB-INF/lib目录下,如果tag处理类要在多个应用中共享,那么它就应放在jsp服务器上的common/lib目录下,对于tomcat来说,就是tomcat/common/lib目录下。 qSCv )S(  
BKa- k!  
&)F*@C-  
tag标签类型 ikBYd }5  
G$zL)R8GE|  
f$HH:^#  
自定义的tag标签遵循XML语法。它有一个开始标记和一个结束标记,有的还有body(即文本节点): YZ$ZcfXDW  
NG&_?|OmV  
<tt:tag> 2Se?J)MN  
S"mcUU}}  
body `fXyWrz-k  
%?C8mA'w  
</tt:tag> J<gJc*Q  
h&3YGCl  
ZSy?T  
一个不带body的tag标签如下: X.F^$  
%#L]]-%  
<tt:tag /> 2?C`4AR[2H  
gwd (N  
1_'? JfY-  
简单的tag标签 jVgFZ,  
ma$Prd  
一个没有body和属性的tag标签如下: !}+tdT(y  
^vs=f 95  
<tt:simple /> |H}m4-+*  
ixm&aW6<  
iTh:N2/-vc  
带属性的tag标签 PYRd] %X  
^I6^g  
c)md  
自定义标签可以有自己的属性。属性一般在开始标记中定义,语法为 attr=”value”。属性的作用相当于自定义标签的一个参数,它影响着tag处理类的行为。你可以在TLD中详细定义它。 SHb(O<6  
I:V0Xxz5t  
你可以用一个String常量给一个属性赋值,也可以通过表达式给它赋值,如<%= ...%>。以struts为例,它的logic:present标签就是用的String常量来给属性赋值: )\;Z4x;]U  
q*![AzFh  
<loglic:present parameter = “Clear”> )QagS.L{z  
2g9 G{~,@g  
而另一个标签logic:iterate是用表达式来给属性赋值: RyB~Lm`ZK%  
g @I6$Z  
<logci:iterate collection=”<%= bookDB.getBooks() %>” dUznxZB  
V}o n|A  
id=”book” type=”database.BookDetails”> ,fIe&zq  
M~*u;vA/  
|IoB?^_h  
带body的tag标签 IL/Yc1  
-F"Q EL#  
一个自定义标签可以包含其它自定义标签、脚本变量、HTML标记或其它内容。 D'l5Zd  
I V%VU  
在下述例子中,此JSP页面使用了struts的logic:present标签,如果些标签定义了parameter=”Clear”的属性,则将清除购物车的内容,然后打印出一条信息: )Rat0$6  
8n BL\{'B[  
<logic:present parameter=”Clear”> Ioy  
4Tc&IwR  
<% cart.clear(); %> L\{IljA  
Lj\/Ji_  
<font color=”#ff0000” size=”+2”><strong> K ]OK:hY4  
Uawpfgc}  
你选择了清除购物车! "N:XzG  
:!;'J/B@..  
</strong></font> yL^UE=#C_  
?;YC'bF  
</logic:present> @pI5lh  
C'=k&#<-  
{y]mk?j  
到底是用属性还是用body来传递信息? '$As<LOEd/  
Q(d9n8  
如上所述,我们既可以通过属性,也可以通过body来传递信息。但一般来说,比较简单的类型,如字符串或简单表达式最好采用属性来传递信息。 oBq 49u1  
q{2I_[p  
}ZSQ>8a  
定义脚本变量的tag标签 49Df?sx  
MaBYk?TR~  
所谓脚本变量,是指JSP中可以调用的变量或对象。它可由tag标签产生。以下示例阐述了一个tag标签定义了一个名为tx的由JNDI所定义的事务处理对象。脚本变量可以是ejb对象、事务、数据库连接等等: vkS)E0s  
/:6Wzj  
<tt:lookup id=”tx” type=”UserTransaction” name=”java:comp/UserTransaction” /> C.^Ven  
+t4BQf  
<% tx.begin(); %> D9mz9  
2-zT$`[]J  
... V]c;^  
Ee1LO#^_6  
^[Ua46/"m  
具有协作关系的tag标签 ) yY6rI;:  
}),w1/#5u8  
自定义tag标签之间可以通过共享对象来实现协作。在下述例子中,标签tag1创建了一个名为obj1的对象,在标签tag2仍可以重复使用obj。 9%ii '{  
FEPXuCb  
<tt:tag1 attr1=”obj1” value1=”value” /> {u!)y?}I-  
&~UJf4b|A  
<tt:tag2 attr1=”obj1” /> OX%MP!#KU  
)5JU:jNy  
在以下这个例子当中,如果外层的tag标签创建了一个对象,那么其内层的所有tag标签都可以使用这个对象。由于这样产生的对象没有一个指定的名字,那么就可以将少重名的冲突。这个例子阐述了一系列协作的嵌套对象。 =K&\E2kA4  
6qe*@o  
<tt:outerTag> 6+V\t+aug  
w#JJXXQI  
<tt:innerTag /> M'`;{^<  
-S,ln  
</tt:outerTag> [>#*B9  
< XTU8G  
%;D+k  
Tag处理类 k *R<,  
4ww]9J  
)5%C3/Dl!  
Tag处理类必须实现Tag接口或BodyTag接口,不过现在一般都流行从TagSupport或BodyTagSupport类中继承,这些类或接口都可以在javax.servlet.jsp.tagext包中找到。 6*l^1;U  
cH<q:OYi  
当JSP引擎看到自己的JSP页面中包含有tag标签时,它会调用doStartTag方法来处理tag标签的开头,调用doEndTag方法来处理tag标签的结束。 gef6pfV  
-16K7yk  
下表说明不同类型的tag所需要不同的处理过程: j` E +qk  
sC00un%  
Tag处理类的方法 H$ftGwS8  
;v17K  
Tag标签类型 +6smsL~<#v  
所调用的方法 k"k J_(  
d_S*#/k  
基本标签 %8aC1x  
doStartTag, doEndTag, release Y=Z1Tdxa|  
'tN25$=V&W  
带属性的标签 iDl;!b&V.  
doStartTag, doEndTag, set/getAttribute1...N, release AeIrr*~]B  
&)i|$J 2.  
带内容的标签 &Gm$:T'~  
doStartTag, doEndTag, release +,:^5{9{  
R j~  
带内容的标签,且内容重复循环 w(L>#?  
doStartTag, doAfterBody, doEndTag, release ^1:U'jIXO  
oIGrA-T}  
带内容的标签,且内容与JSP交互 c/L>>t  
doStartTag, doEndTag, release, doInitBody, doAfterBody, release =H0vE7{*  
#{r#;+  
一个tag处理类可以通过javax.servlet.jsp.PageContext来与JSP交互,通过javax.servlet.jsp.PageContext类,tag处理类可以访问JSP中的request、session和application对像。 P+MA*:  
A392=:N+Q  
如果tag标签是互相嵌套的,那内层的tag处理类可以通过它的parent属性来访问上层的tag处理类。 nI*/Mhx  
FZd.L6q  
一般情况都将所有的tag处理类打成了JAR的包,以便于发布。 Mcw4!{l`  
n[Zz]IO,g  
, "jbq~  
Tag库描述(简称TLD) K|C^l;M6  
$@\mpwANl  
yix'rA-T  
Tag库是用xml语言描述的,TLD包括了tag库中所有tag标签的描述,它一般用来被jsp服务器用来校验tag的语法正确性,或者被jsp开发者用来开发新的标签。 : "6q,W  
|W$DVRA  
TLD的文件扩展名必须为.tld,而且必须放在当前WEB应用的WEB-INF目录或其子目录中。 l5Y/Ok0,  
nfb]VN~(  
一个TLD的内容的开头必须遵守标准的XML开头,用于描述DTD和xml的版本,例如: It_M@  
L?_7bX oD  
<?xml version="1.0" encoding="ISO-8859-1" ?> : FAH\  
Bhqft;Nuh  
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd"> /wQL  
TLD必须以<taglib>来作为它的根元素,<taglib>的子元素如下表: ]DFXPV  
U,/6;}  
eLwTaW !C  
<taglib>的子元素 QU{Ech'  
r8xyd"Axy  
Element * v8Ts  
Description Z'pQ^MO  
)oo~m\`  
tlib-version e73^#O&Xt  
Tag库的版本 d{et8N  
ogM%N  
jsp-version E{=2\Wkcp  
Tag库所需要的jsp的版本 _2fkb=2@  
0,*%vG?Q  
short-name k<w(i k1bi  
助记符,tag的一个别名(可选) 89{HJ9}  
=U OLT>!  
uri @vgG1w  
用于确定一个唯一的tag库 uBg 8h{>  
/)N@M  
display-name ^/wfXm  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) s )voII&  
aI zv  
small-icon ZA~Z1Mro#"  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) Uu6L~iB  
CZ 2`H[8  
large-icon M"q[p  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) "%WgT2)m.  
z2ms^Y=j  
description Ap&)6g   
对tag库的描述(可选) J MX6yV  
"wH)mQnd  
listener HDM<w+ZxX  
参见下面listener元素 L~{_!Q  
LiDvaF:@L!  
tag e"-X U@`k1  
参见下面tag 元素 W [[oSqp  
gOT+%Ab{_  
Listener元素 J?)RfK|!  
LCXO>MXN  
一个tag库可能定义一些类做为它的事件侦听类,这些类在TLD中被称为listener 元素,jsp服务器将会实例化这些侦听类,并且注册它们。Listener元素中有一个叫listener-class的子元素,这个元素的值必须是该侦听类的完整类名。 ZZ/cq:3$P  
@#+jMV$g  
Tag元素 OwzJO  
di9!lS$  
每个tag元素在tag库中都要指出它的名字、类名、脚本变量、tag的属性。其中脚本变量的值可以直接在TLD中定义或通过tag附加信息的类来取得。每个属性描述了这个属性是否可以省略,它的值是否可以通过<%= …%>这样的JSP语法来获得,以及属性的类型。 Hx^!:kxk  
\8uo{#cL8  
每一个tag在TLD中对应一个tag元素,下表是tag元素的子元素: KHKS$D  
q^8EOAvnZ  
Tag元素的子元素 k1z$e*u&r  
XA0 (f*  
元素名称 !yjo   
描述 !2Dy_U=  
|ifHSc.j<  
name u]C`6)>  
独一无二的元素名 O(2cWQ  
BOlAm*tFt  
tag-class [~5p>'  
Tag标签对应的tag处理类 maMHZ\ Q  
{hSGv   
tei-class /rB{[zk  
javax.servlet.jsp.tagext.TagExtraInfo的子类,用于表达脚本变量(可选) )!9Ifk0KH  
>(9F  
body-content dtM[E`PL  
Tag标签body的类型 NQTnhiM7$  
u'Q?T7  
display-name ]>##`X  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) [y) Fc IK}  
lYf+V8{  
small-icon : 2V^K&2L  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) -P=g3Q i  
p?(L'q"WK  
large-icon &Y|Xd4:  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) x!S;SU  
Ftb%{[0}u3  
description L/}iy}  
此tag标签的描述 ,cTgR78'  
"yb WDWu  
variable z,;;=V6j  
提供脚本变量的信息(同tei-class)(可选) >hMUr*j  
= Je>`{J  
attribute ~yJ4qp-  
Tag标签的属性名 %:6?Y%`*[  
l1_X(Z._V  
以下章节介绍对于不同类型的tag,如何具体地实现它们。 T~4mQuYi  
yT /EHmJ  
3EFD%9n  
简单的tag m/&i9A  
4\X||5.c  
suJ_nb  
tag处理类 S[M4ukYK  
A(6xg)_XQ  
简单的tag处理类必须实现Tag接口的doStartTag和doEndTag方法。当jsp引擎碰到tag标签的开头时,doStartTag被调用,因为简单的tag没有body,所以此方法将返回 SKIP_BODY。当jsp引擎碰到tag标签的结尾时,doEndTag被调用,如果余下的页面还要被计算,那它将返回EVAL_PAGE,否则将会返回SKIP_PAGE。 -H(vL=  
H(u+#PIIw  
以下是例子:对于标签 <tt:simple /> ,它的tag处理类实现如下: d<p2/aA  
@B1{r|-<^  
7l8[xV  
public SimpleTag extends TagSupport E +_&HG}a  
3 &&+Y X  
{ OTvROJP  
$j` $[tX6l  
public int doStartTag() throws JspException ( `' 8Ww  
6/ g%\ka  
{ (ClhbfzD  
V*n==Nb5L  
try{ 5vp|?-\h>  
JV"NZvjN7d  
pageContext.getOut().print(“Hello.”); IFNWS,:  
%Tcf6cK"  
}catch(Exception e){ ^%bBW6eZ  
>mu)/kl  
throw new JspTagException(“SimpleTag: “ + e.getMessage());  I?Y d   
mLL$|  
} %5</ d5.  
R|,7d:k  
return SKIP_BODY; x2wg^$F*oO  
w*LbH]l<-  
} Evu=M-?  
<zB*'m  
public int doEndTag() 7Ur?ep  
iv%w!3#  
{ 3><u*0qe%I  
9w ~cvlv[  
return EVAL_PAGE; I=dGq;Jaz  
?qHF}k|  
} eMMx8E)B  
pu;3nUH  
} 9/TY\?U  
<bmLy_":  
hq_~^/v\  
注意:如果tag标签没有内容的话,那必须定义body-content元素为空,例如 - V) R<  
3P=w =~e  
<body-content>empty</body-content> D5]{2z}k  
T-L5zu  
d+2daKi  
带属性的tag标签
评价一下你浏览此帖子的感受

精彩

感动

搞笑

开心

愤怒

无聊

灌水
级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
只看该作者 1 发表于: 2007-01-01
tag处理类 T!^Mvat  
#s"B-sWE  
对于tag标签的每个属性,你必须依照JavaBeans规范来定义其属性,以及get和set方法。以struts的logic:present 标签为例, "~$$  
1kFjas `g  
<logic:present parameter=”Clear”> [8]m8=n  
X , ZeD  
与此相应,此tag处理类应有如下方法和定义: "EPD2,%S  
jXIEp01  
p5*lEz|$  
protected String parameter = null; =MSu3<y,  
m6n hC  
public String getParameter() "bX4Q4Dq  
Eb@MfL  
{ LHi6:G"Y(  
!wh=dQgMe  
return this.parameter; m^tNqJs8  
:,F=w0O  
} h5onRa *7  
pMN<p[MB  
public void setParameter(String parameter) UC!5 wVY  
|~$7X  
{ iHz[Zw^.s  
hx!`F  
this.parameter = parameter; N lt4)  
f=ib9WbR#  
} TETsg5#  
.hN3`>*V  
p.Y$A if.  
注意:如果你的属性名为id,而且你的tag处理类是从TagSupport类继承的,那你就不需要定义它的属性和set和get方法,因为他们早已在TagSupport被定义过了。 YvTA+yL  
-CU,z|g+  
Attribute元素 |=3 *;}  
=lrN'$z?%  
对于tag标签的每个属性,你必须定义它是否必须的,它的值是否可以用诸如<%= …%>的表达式来获得,以及它的类型(可选),如果不指定它的类型,那就默认为是java.lang.String类型。如果rtexprvalue元素被定义为true或yes,那么在type元素中就定义了attribute的返回类型。 8XbR  
X <xqT  
<attribute> 878tI3-  
h)o]TV  
<name>attr1</name> u2lmwE  
*Q/E~4AW|t  
<required>true|false|yes|no</required> H1Xovr  
,OB&nN t>  
<rtexprvalue>true|false|yes|no</rtexprvalue> Nmf#`+7gCI  
<nA3Sd"QfV  
<type>attribute的返回类型(只用当rtexprvalue为真是才有效)</type> AQ}l%  
3wNN<R  
</attribute> \{>eOD_  
f[@#7,2~M  
如果tag的某个属性不是必须的,那tag处理类会自动提供一个缺省值。 :&$Xe1)i]  
"jGe^+9uT  
例如,在logic:present这个tag标签中定义了一个属性叫parameter,但它不是必须的,而且它可以被诸如<%= …%>的表达式来赋值。 tc/jY]'32  
dofR)"<p,^  
<tag> Mf7E72{D  
>sV Bj(f  
<name>present</name> :yD@5)  
c~oe, 9  
<tag-class>org.apache.struts.taglib.logic.PresentTag</tag-class> I"V3+2e  
GTFl}t  
<body-content>JSP</body-content> UCF[oO>v  
'%Dg{ zL  
ZOHRUm  
yS"0/Rm}  
<attribute> '%O\E{h  
& =sayP  
<name>parameter</name> !:J< pWN"  
qS82/e)7  
<required>false</required> s=jO; K$  
`w=!o.1  
<rtexprvalue>true</rtexprvalue> riEqW}{  
)`RZkCe  
</attribute> fiqj;GW  
^z?=?%{  
R7t bxC  
gD40y\9r  
</tag> "GBUQ}  
+2(Pc JR~  
Y D+QX@  
属性元素的校验 d.1Q~&`  
g[<uwknf  
ke</x+\F  
有关于tag标签的有效值可以从tag库的说明文档中获得,当JSP页面被编译时,jsp引擎会强制性地参照TLD中定义的规则进行检查。 |vN$"mp^a  
"j;!_v>=f`  
还有一个方法也可以进行属性元素的校验,就是先继承类TagExtraInfo,然后调用它的isValid方法。这个类同时也起到提供tag中定义的脚本变量信息的作用。 73#9NZ R  
-9i+@%{/  
IsValid方法通过TagData对象来传递属性信息,它包括着tag的所有的属性名-值的信息。由于校验发生在运行时刻,因此这个属性的值将被赋值为TagData.REQUEST_TIME_VALUE。 Q }8C  
nTQ (JDf  
例如tag标签<tt:twa attr1=”value1” />在TLD中定义如下: &`5 :G LV  
lc-*8eS  
<attribute> +{bh  
gU*I;s>  
<name>attr1</name> >hesxC!  
CY\mU_.b  
<required>true</required> y7 <(,uT  
/^WE@r[:  
<rtexprvalue>true</rtexprvalue> )xbqQW7%0+  
7dx4~dF  
</attribute> rr6"Y&v  
Z~B+*HF  
1r&AB!Z #  
这个定义说明了attr1能在运行期间被赋值。 IT7:QEfKU  
PE +qYCpP9  
以下的isValid方法检查attr1属性的值是否属于Boolean类型。注意由于attr1能在运行刻被赋值,那么isValid方法必须检查tag用户是否对此tag进行了运行时刻赋值。 )%1&/uN)  
M{y|7e%K  
c'[( d5^|  
Public class TwaTEI extends TagExtraInfo CTh1;U20  
f Y2l.H\f  
{ ;W =by2x*  
3pzOt&T|w  
public boolean isValid(Tagdata data) r6/<&1[  
s UvKA0  
{ ,7/\&X<`B  
4v i B=>  
Object o = data.getAttribute(“attr1”); ;+! xZOmm  
sd7Y6?_C  
If(o != null && o != TagData.REQUEST_TIME_VALUE) i@%L_[MtA  
$jDD0<F.#  
{ ;vZ*,q6  
ug>]U ~0  
if( ( (String)o).toLowerCase().equals(“true”) || !vi4* @:  
M|aQ)ivh3  
((String)o).toLowerCase().equals(“false”) ) Oym]&SrbS  
>4Fd xa  
return true; !WDn7j'A  
7E@$}&E  
else W'8J<VBD  
;%lJD"yF  
return false; HX z iDnj  
r{c5dQ  
} il<gjlyR]L  
)E_!rR  
else _p?I{1O  
3<yCe%I:  
return true; ggzAU6J  
P'KY.TjWb  
} vsxvHot=  
E%KC'T N^D  
} vjY);aQ  
iOE9FW|e  
.kz(V5  
带body的tag (p}9^Y  
:a#|  
#zh6=.,7  
tag处理类 |2tSUOZ  
kvY} yw7  
:ga 9Db9P  
如果tag标签含有内容,那处理方式会略微有些不同,而且还要视tag处理类是否要与body交互的情况而定。如果要与body交互,那我们认为tag处理类要可能要对body进行操作。 9iiU,}M`j  
w?*'vF_2:#  
Tag处理类不与body交互 4"rb&$E   
7 B4w.P,B  
如果tag处理类不与body交互,tag处理类应该实现Tag接口或从TagSupport中派生,如果body要被计算,那么doStartTag方法应返回 EVAL_BODY_INCLUDE,否则应返回SKIP_BODY。 m3x!*9h  
@|JPE%T   
如果tag处理类要对body反复运算,则它应该实现IterationTag或从TagSupport中派生。如果tag处理类认为body还未计算完的话,那它的doStartTag方法和doAfterBody方法必须返回EVAL_BODY_AGAIN。 )[F46?$vrk  
jLpgWt`8)E  
Tag处理类与body交互 xUV_2n+  
gogl[gHO  
如果tag处理类与body交互,那tag处理类应实现BodyTag接口或从BodyTagSupport中派生。这种tag处理类一般要实现doInitBody和doAfterBody方法。 U!3uaz'  
&^"s=g.  
Body允许一些方法来读写它的内容。Tag处理类可以调用body内容的getString或getReader方法来从body中提取信息,也可用 writeOut(out) 方法来将body的内容写入到out对象中。其中out对象通过tag处理类的getPreviousOut方法来获得。 +A;n*DF2  
) >-D={  
如果body的内容需要被计算,那么doStartTag方法必须返回EVAL_BODY_BUFFERED,否则,它将返回 SKIP_BODY。 K]lb8q}Z~  
_&6juBb  
doInitBody 方法 ~`a#h#  
h/fb<jIP1  
此方法在body内容已经设好,但未被计算之前被调用。你可以根据不同的body内容来制定初始化策略。 $u(M 4(}  
hPNQGVv  
doAfterBody方法 _%C_uBLi  
:K a^  
此方法在body内容已被计算后进行调用。 `"-`D!U?$  
F=' jmiVJ  
和doStartTag方法一样,doAfterBody方法返回一个指示符指示是否要继续计算body,如果要继续计算,则doAfterBody应返回EVAL_BODY_BUFFERED,否则,它应返回SKIP_BODY。 Lcm~QF7cd  
P W0q71  
release 方法 KR+aY.  
VhJyWH%(  
tag处理类调用此方法将它的状态重置为初始状态,并释放所有的私有资源。 i:NJ>b  
aH~x7N6!  
Z &ua,:5  
以下的例子读取body的内容(其中含有一条sql语句),然后将它传递给一个对象,让它进行查询。由于此处body不须重新计算,所以doAfterBody会返回SKIP_BODY。 0DW'(#`  
T/X?ZK(T  
F5om-tzy  
Public class QueryTag extends BodyTagSupport 4@ydK  
Y:#kel<  
{ ~`W6O>  
2xz%'X%  
public int doAfterBody() throws JspTagException '2i)#~YO<  
"m<eHz]D  
{ FN8=YUYK%  
o>QFd x  
BodyContent bc = getBodyContent(); DT1i2!  
Gff[c%I  
//将body的内容以字符串的格式提取出来 hA&j?{  
UGezo3}  
String query = bc.getString(); H_xQ>~b  
~ Iu21Q(*  
//清除body E: LQ!  
9|?(GG  
bc.clearBody(); ;Fwm1ezx0  
nATfmUN L  
try{ \I`=JKYT  
6>P  
Statement stmt = connection.createStatement(); xhp-4  
6O[wVaC1u  
Result result = stmt.executeQuery(query); A(_^_p.|  
av| 6r#  
}catch(SQLException e){ 1'@lg*^9  
eO[Cb]Dy:  
throw new JspTagException(“queryTag: “ + e.getMessage() ); (,)vak&t  
N";dG 3  
return SKIP_BODY; e-duZ o  
DftGy:Ah3  
} 0wa!pE"  
Ot8S'cB1,$  
} %o _0M^3W  
g)| ++?  
3 MI) E  
body-content元素 EY[Q%  
Bb2r95h}^  
aZ`_W|  
由于tag可能会有body,你必须用body-content元素来指定body内容的类型: DRFuvU+e  
^QL/m\zq@%  
<body-content>JSP|tagdependent</body-content> j@_) F^12  
wshp{ y  
qyG636i  
如果body的内容是定制的或内部的tag、脚本元素、或HTML广本,则归类为JSP类型。其他的类型,比如上面代码所述的?D?D将sql statement类传给 query tag的这种类型应该标为tagdependent。 e8ig[:B>+  
u^4"96aXJ  
注意:实际上body-content的值并不影响tag处理类对body内容的处理,它仅仅是被tag编辑工具用来描述此body的内容。 s poWdRM2  
(fI&(";t  
#B.w7y5*  
用tags定义脚本变量 Osvz 3UMY3  
(^s&#_w03  
PU/Br;2A  
tag处理类 "3KSmb   
^5'/ }iR2N  
O%q;,w{prW  
tag处理类负责创建或设置页面中定义的脚本变量,用pageContext.setAttribute(name,value,scope)或pageContext.setAttribute(name,value)方法来实现。一般来说,tag处理类通过脚本变量的名称来获取它,脚本变量的名称一般可用get方法来获得。 J#OE}xASoA  
zL!~,B8C  
如果脚本变量的值依赖于tag处理类中的上下文中某一对象,那它可用pageContext.getAttribute(name,scope)方法来找到那个对象。一般的处理过程是tag处理类先找到脚本变量,再对其进行处理,然后用pageContext.setAttribute(name,object)的方法来设置它的新值。 (gJ )]/n  
.8uwg@yD  
对象的生存周期(scope)如下表:  F>oxnhp6  
t5B|c<Hb\  
对象的生存周期表 l!2Z`D_MD  
U(&nh ?  
名字 '|A5a+[  
可访问范围 xvz5\s|b  
生存周期 ; K 6Fe)  
Z!=Pc$?  
page D A)0Y_  
当前页面 bCx1g/   
一直有效,除非页面向客户提交响应或重定向到一个新页面 cTIwA:)D  
CTrs\G  
request BQJ`vIa  
当前页面或当前页面重定向到的页面 D` `NQ`>A  
一直有效,除非页面向客户提交响应 *e"GQd?  
X!A]V:8dk  
session sz2SWk^&  
当前页面或在同一浏览器窗口中的页面 r/$)c_x`  
一直有效,除非关闭当前浏览器、超时、网络故障 22|M{  
7[.Q.3FL  
application ~1]2A[`s!  
整个web应用程序的所有请求 LU IT=+  
一直有效,除非发生网络故障、服务器故障 "qP^uno  
AqKx3p6  
提供关于脚本变量的信息 @7Rt[2"e  
9xS`@ "`  
以下示例定义了一个名为“book”的脚本变量,用来访问程序中关于书的信息: ;>8TNB e!  
+(P 43XO08  
<bean:define id=”book” name=”bookDB” property=”bookDetails” type=”database.BookDetails” /> !DUg"o3G>  
<{xAvN( :  
<font color=”red” size=”+2” > 5Z1Do^  
V-U  ^O45  
<%= messages.getString(“CartRemoved”) %> @ un  
;gu>;_  
<strong><jsp:getProperty name=”book” property=”title” /></strong> _x|8U'|Ce  
{hq ;7  
</font> ci NTYow  
j[Zni D  
当包含此tag的JSP页面被编译时,jsp引擎会自动生成关于此book的同步的代码(同步可以避免几个客户同时访问此book时造成的冲突),要生成同步代码,jsp引擎需要知道此脚本变量的如下信息: xW;[}t-QS  
G~hILW^  
· 脚本变量名称 > FcA ,  
wj5s5dH  
· 脚本变量所属的类 T]Td4T!  
qsRfG~Cg  
· 此脚本变量是否引用了一个新的或已存在的对象 _M4v1Hr48  
pz6- hi7  
· 此脚本变量的有效性 =|&"/$+s  
A_*Lo6uII  
有两种办法可以向jsp引擎提供关于脚本变量的信息:在TLD中定义variable子元素,或用tei-class子元素定义一个额外tag信息类。用variable最简单,但可能降低了一些灵活性。 9n\#s~,  
-/7=\kao%  
Variable元素 y!c7y]9__2  
=v`&iL~m  
Variable元素有如下子元素: y^|3]G3  
JOne&{h]J"  
· name-given ?D?D 给出的名字,是一个常量 hA1hE?c`  
vc{]c }  
· name-from-attribute?D?D 属性名,在编译时给出的属性名 w,#W&>+&  
l'lDzB+.*  
name-given或name-from-attribute两者必须选一,但以下子元素是可选的: 1Y"qQp  
Ri6 br  
· variable-class?D?D变量的类型,缺省为java.lang.String。 =ZIFS  
 eV=sDx  
· declare?D?D此脚本变量是否引用了一个新对象,缺省为True。 jqsktJw#i  
@.@#WHde  
· scope?D?D脚本变量的范围,缺省为NESTED。下表描述了scope的几种类型: i-vJ&}}  
tsC|R~wW  
脚本变量的有效范围 [_G0kiI}W"  
VP[!ji9P   
v%~ViOgL\  
有效性 |nZB/YZt  
方法 ? /X6x1PN  
MC)W?  
NESTED J0mCWtx&  
在tag标签的开始和结束之间 !4cdP2^P  
如果tag处理类实现BodyTag接口,则在doInitBody和doAfterBody中调用,否则在doStartTag中调用 OxGCpbh*7o  
G:ngio]G0  
AT_BEGIN b%t9a\0V  
从tag标签的开始一直到页面结束 E_uH' E  
如果tag处理类实现BodyTag接口,则在doInitBody、doAfterBody和doEndTag中调用,否则在doStartTag和doEndTag中调用  jy|xDQ  
ssbyvzQ  
AT_END aNU%OeQA  
从tag标签的结束一直到页面结束 6}lEeMRW  
在doEndTag中调用 Q>g$)-8  
R* G>)YH  
以struts为例,它的bean:define标签的实现遵循JSP1.1规范,此规范要求使用额外tag信息类来定义脚本变量。Variable元素是JSP1.2规范中加入的。以bean:define标签为例,你可以定义如下variable元素: /Z_ [)PTH  
gm$MEeC  
<tag> I2!HXMrp  
ddhTr i'f  
<variable> 3evfX[V#  
\gv x)S11  
<name-from-attribute>id</name-from-attribute> v") W@haU  
0=zS&xM  
<variable-class>database.BookDetails</variable-class> gCI'YEx  
&: 8&;vk  
<declare>true</declare> "$;:dfrU  
PH &ms  
<scope>AT_BEGIN</scope> $^ dk>Hj>4  
/ hdl  
</variable> U .h PC3  
!7*/lG  
</tag> \)kAhKtG  
?|YQtY  
额外tag信息类 MdjMTe s  
FdHWF|D  
如果要定义一个额外tag信息类,你要继承javax.servlet.jsp.TagExtraInfo类。一个TagExtraInfo类必须实现getVariableInfo方法,此方法返回一个叫VariableInfo的数组类,它包括如下信息: _u5U> w  
F>R)~;Ja  
· 变量名 1/J*ki+?  
r:Cid*~m  
· 变量所属类名 #T`+~tW'|  
j" .6  
· 此变量是否引用了一个新对象 l Nto9  
L<]P K4  
· 此变量的有效范围 e2ZUl` {g  
L KR,CPz  
jsp引擎将一个名为data的参数传给getVariableInfo方法,data中包括tag标签中的所有“属性名?D?D属性值”对。它可以用来向VariableInfo对象提供脚本变量的名字和类名。 ,R6$SrNcd  
ZWEzL$VWi  
以struts为例,它在bean:define标签中定义了一个名为DefineTei的额外tag信息类,用来向脚本变量提供信息。由于脚本变量的名称(book)和类名(database.BookDetails)是通过tag标签的属性来传递的,它们一般定义在VariableInfo的构建代码中,并且可用data.getAttributeString方法来得到这些信息。如果要允许book脚本变量能在从tag开始直到整个JSP页面结束的范围内都可用的话,那它的范围应设为AT_BEGIN。如下所示: ) hB*Hjh  
>maz t=,  
..mz!:Zs0  
public class DefineTei extends TagExtraInfo _J;a[Ky+[  
Hf|:A(vCx  
{ w2AWdO6  
R;2 -/MT-  
public VariableInfo[] getVariableInfo(TagData data) 7Wn]l!  
r5wXuA,Um  
{ %z(=GcWm  
X/749"23  
String type = data.getAttributeString(“type”); 7s3<}  
Nuq/_x  
If( type == null) XL9lB#v^  
a8$pc>2E  
type = “java.lang.Object”; 7J/3O[2  
A*;h}\n  
return new VariableInfo[] { m q9&To!  
V@f#/"u'  
new VariableInfo(data.getAttributeString(“id”), P .(X]+  
Us.jyg7_c  
type, 1Xc%%j  
ghiElsBU  
true, 7|Y8^T s  
 t/(j8w  
VariableInfo.AT_BEGIN) )}5r s  
b=EZtk6>  
}; 9Ua@-  
/% 1lJD  
} mJT m/C  
8=uljn/  
} 0[Aa2H*  
h 42?^mV4?  
;Yj&7k1  
注意:关于额外tag信息类的类名必须要在TLD中的tag标签下的tei-class子元素中定义。因此,DefineTei的tei-class中的定义看起来如下: <0}'#9>O  
<tei-class> z0Hh8*  
org.apache.struts.taglib.bean.DefineTagTei 0l*/_;wo  
</tei-class> MLX.MUS  
K.Z{4x=0  
|05LHwb>  
具有协作关系的tag @DR&e^Zz  
9hU@VPB~  
=h{2!Ah7 X  
tag通过共享对象来进行协作,JSP技术支持2种方式的对象共享。 dI|/Xm>  
dx}!]_mlZ  
第一种方法是使用pageContext对象进行对象的共享(可支持JSP页面和tag处理类之间的共享),如果在一个tag处理类中要调用由另一个tag处理类创建的对象,可调用pageContext.getAttribute(name, scope)方法。 :{2$X|f 3  
x]T;W&s  
第二各方式的共享是对于tag之间有嵌套关系而言的,外层的tag所创建的对象对于内层的tag来说是可以共用的。这种形式的共享的好处是减少了可能存在的重名冲突。 *^ BE1-  
yD"sYT   
要访问一个嵌套tag创建的对象,tag处理类必须先找到此嵌套tag对象,可用TagSupport的静态方法 TagSupport.findAncestorWithClass(from, class)或TagSupport.getParent方法。前者在当不确定此tag是否为嵌套tag对象时使用。一旦它的父类被找到,它就能访问其所有动态或静态创建的对象。静态创建的对象是父类的成员,而动态创建的对象可能是父类的私有对象。诸如此类的对象可以用tag处理类的setValue方法来保存,用getValue方法来获得。 1<5yG7SZ  
f^ qQ 5N  
下例阐述了以上两种共享对象的方法。在这个例子当中,一个查询tag检查一个名为connection的属性名是否在doStartTag中被设置。如果connection属性被设置,tag处理类从pageContext中得到这个connection对象。否则,此tag处理类先找到它的父tag处理类,然后从它的父tag处理类中找到connection对象。 TmiQq'm[b  
[XK"$C]jHJ  
cPSu!u}D  
public class QueryTag extends BodyTagSupport EbHeP  
2$=HDwv  
{ 3WS % H17  
C54)eT6  
private String connectionId; _u; UU$~  
B%/Pn 2  
public int doStartTag() throws JspException \Qn8"I83AV  
P2kZi=0  
{ huIr*)r&p  
~ 5b %~:  
String cid = getConnection(); 107SXYdhI  
EzaOg|  
if(cid != null) E3qX$|.$/  
~MX@-Ff  
{ ^y,ip=<5\3  
3ssio-X  
//存在一个connection id,使用它。 p"Y=  
H Vy^^$  
connection = (Connection) pageContext.getAttribute(cid); 0a5P@;"a  
MRc^lYj{  
} 19_F\32  
5YasD6l  
else Pcc%VQN  
{U9jA_XX  
{ $.kYAsZts  
Gex^\gf  
ConnectionTag ancestorTag = (ConnectionTag)findAncestorWithClass(this, ia[wVxd  
c=gUY~Rl  
ConnectionTag.class); Zl)|x%z  
Y~6pJNR  
if(ancestorTag == null) gE&f}M-  
E:ytdaiT  
{ 7blZAA?-  
='FEC-f95  
throw new JspTagException(“一个没有connection属性的查询标签必须被一个connection标记嵌套。”); <~3 a aO  
+-"#GL~cC  
} HFazqQ[  
tkmW\  
connection = ancestorTag.getConnection(); pP#?|  
tXx9N_/  
} LuVj9+1 S  
a5iMCmL+  
} SV~xNzo~  
y-U(`{[nM  
} #3S/TBy,  
yRtFUlm`  
Z7v~;JzC#  
}y1M0^M-$  
此查询标签在JSP页面中的调用形式可以从以下2种定义中任选一种: 'coqm8V[%  
yQ}~ aA#h  
&P;x<7h$t?  
<tt:connection id=”con01” ...> ... </tt:connection> =Y BJ7.Y  
I6\3wU~).  
<tt:query id=”balances” connection=”con01” > <j>@Fg#q  
d3\8BKp  
SELECT account, balance FROM acct_table I.>LG  
3 R m$  
where customer_num = <%= request.getCustno() %> AYi$LsLhO  
hug12Cu  
</tt:query> ,ZSuo4  
IO+z:D{  
U;31}'b  
bMZ0%(q  
Wwz>tE  
<tt:connection ...> PIA&s6U  
N  P"z  
<x:query id=”balances”> gR+Z"]  
;?rW`e2  
SELECT account, balance FROM acct_table Q*wx6Pu8  
%bsdC0xM  
where customer_num = <%= request.getCustno() %> sk5\"jna  
rk~/^(!  
</x:query> 5*CwQJC<  
0\m zGfd  
</tt:connection> Q -+jG7vT  
;(sb^O  
X:Zqgf  
与此同时,在TLD中必须指定connection属性为可选的,定义如下: [H& m@*UO  
; ^$RG  
<tag> B}Qo8i7 z  
\8pbPo=x  
... g/E;OcFaO  
@EQ{lGpU3  
<attribute> 23>?3-q  
B[$e;h*Aw[  
<name>connection</name> g (~&  
D"hiEz  
<required>false</required> yF:fxdpw  
aZ'p:9e  
</attribute> xnLfR6B  
8177x7UG2[  
</tag>
描述
快速回复

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