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

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

级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
标准的JSP 标记可以调用JavaBeans组件或者执行客户的请求,这大大降低了JSP开发的复杂度和维护量。JSP技术也允许你自定义taglib,其实换句话说,taglib可以看成是对JSP标记的一种扩展,正如xml是对html的一种扩展一样。taglib通常定义在tag标签库中,这种标签库存放着你自己定义的tag标签。简而言之,如果使用taglib,那么你可以设计自己的JSP标记! RAJ |#I1  
&S`'o%B  
一般来说,自定义tag标签主要用于操作隐藏对象、处理html提交表单、访问数据库或其它企业级的服务,诸如邮件和目录操作等等。自定义tag标签的使用者一般都是那些对java编程语言非常精通,而且对数据访问和企业级服务访问都非常熟悉的程序员,对于HTML设计者来说,使得他可以不去关注那些较复杂的商业逻辑,而将精力放在网页设计上。同时,它也将库开发者和库使用者进行合理分工,自定义tag标签将那些重复工作进行封装,从而大大提高了生产力,而且可以使得tag库可用于不同的项目中,完美地体现了软件复用的思想。 +(hwe jyC  
sjbC~Te--  
在这篇文章中,我们主要讨论: jF2GHyB  
#pxet  
· 什么是自定义tag标签? ;C@^wI  
<. ]&FPJ  
· 怎么使用tag标签? ]$%4;o4O  
gf8U &;  
o 声明要使用的tag库 P bC>v  
}Z%{QJ$z  
o 找到与之对应的tag处理类 K":tr~V;  
-"b3q  
o tag标签的类型 IOsDVIXL\  
t ,Rn  
· 自定义tag标签 G@6,O-Sj  
Wam?(!{mOf  
o tag处理类 <cd%n-  
c35vjYQx0  
o tag库描述 o%s}jBo}  
Fd=`9N9  
o tag标签示例 @g` ,'r  
N`:b vr  
o 带属性的tag `'t;BXedz/  
bao5^t}  
o 带body的tag JHOBg{Wg  
G~j<I/)"  
o 定义了脚本变量的tag omU)hFvyS  
v[=E f  
o 具有协作关系的tag ]qT r4`.  
b-gVRf#F  
· 自定义tag标签 Ol^EQLO  
833t0Ml1A/  
o 一个迭代tag的例子 mqxy(zS]  
y^fU_L?p  
o 一个模板tag库 sX?7`n1U  
UjK&`a ;V  
o tag处理类到底是怎样被调用的? SQ.Wj?W)  
Dy'l]vN$  
8xz7S  
什么是自定义的tag? J#5o  
69w"$V k  
一个自定义的tag标签是用户定义的一种JSP标记。当一个含有自定义的tag标签的JSP页面被jsp引擎编译成servlet时,tag标签被转化成了对一个称为tag处理类的对象进行的操作。于是当JSP页面被jsp引擎转化为servlet后,实际上tag标签被转化成为了对tag处理类的操作。 [wxI X  
Oc=PJf%D#  
自定义tag标签有很多特色,诸如: L*Cf&c`8r  
qf{B  
· 可以在JSP页面中自定义tag标签的属性 &xT~;R^  
ZX}"  
· 访问JSP页面中的所有对象 gx.]4 v  
3Q"+ #Ob  
· 可以动态地修改页面输出 [l{eJ /W  
r\D8_S_  
· 彼此这间可以相互通信。你可以先创建一个JavaBeans组件,然后在一个tag中调用此JavaBeans组件,同时可以在另一个tag中调用它。 C\h<02  
)}lV41u  
· tag允许相互嵌套,可以在一个JSP页面中完成一些复杂的交互。 Gi2Ey37]O  
RlL,eU$CS  
f.CI.aozW  
使用tag标签 ^aMdbB  
~n\ea:.  
-L3RzX  
本节主要描述怎样在JSP页面中使用tag标签,以及tag标签的不同类型。 ${2fr&Tp  
XOFaS '.  
要使用tag标签,JSP程序员必须做2件事: H2KY$;X [  
d+)L\ `4  
· 声明此tag标签的tag库 |}Lgo"cTC  
(LPc\\Vv  
· 实现此tag标签 4(gf!U  
p-Btbhv  
声明tag标签所在的tag库 (`*wiu+i  
0_.hU^fP  
如果要使用tag标签,则应用JSP的taglib指示符来指定其tag库(注意:taglib要在在使用此tag标签之前声明) t fQq3#  
|`/uS;O  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> m^+ ~pC5  
ApBThW *E  
uri属性定义了唯一的标签库描述(以下简称TLD),它可以是直接是tld文件名或一个独一无二的名字。prefix是用来区别其它TLD中和本TLD中有重名的tag的一种手段。 ?V)6`St#C  
<us{4 %  
TLD必须以.tld作为扩展名,并且存放在当前应用的WEB-INF目录或其子目录下。你可以通过它的文件名直接引用它,也可以通过别的方式间接地引用它。 p+?WhxG)  
xo+z[OIlF  
以下taglib指示符直接引用一个TLD: %j; cXN  
G-<~I#k  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> aC` c^'5  
v Rs5-T  
以下的taglib指示符通过一个逻辑名称间接地引用一个TLD: PTqS L]  
TR20{8"  
<%@ taglib uri=”/tutorial-template” prefix=”tt” %> 8B9zo&  
4Fq}*QJ-  
如果是间接引用TLD的话,那你必须还要在web.xml中定义此逻辑名称与tld文件之间的映射,具体做法是在web.xml中加入一个名为taglib的元素: 3I(M<sB}  
%q^]./3p  
<taglib> v\FD~   
SsZzYj.d  
<taglib-uri>/tutorial-template</taglib-uri> CxV%/ChJ#  
B.jYU  
<taglib-location> g&wQ^  
v,B\+q/  
/WEB-INF/tutorial-template.tld _Y=yR2O  
i|GC 'XD@  
</taglib-location> a QFHB!  
j+/*NM_y3  
</taglib> >AJ|F)  
m ws.)  
A@r,A?(  
实现此tag标签 G.T1rUh=  
!HYqM(|{.  
cGKk2'v?  
为了实现tag标签,你有2种方法来存放tag处理类。一、让tag处理类以.class的方式存放于当前应用的WEB-INF/class子目录下,二、如果tag处理类是以JAR包的形式存在的话,那可以放在当前应用的WEB-INF/lib目录下,如果tag处理类要在多个应用中共享,那么它就应放在jsp服务器上的common/lib目录下,对于tomcat来说,就是tomcat/common/lib目录下。 4N&}hOM'S  
2D"/k'iA  
q4oZJ-`  
tag标签类型 ,,gYU_V  
e+TNG &_  
5c8x: e@  
自定义的tag标签遵循XML语法。它有一个开始标记和一个结束标记,有的还有body(即文本节点): N 5DS-gv  
b.&YUg[#  
<tt:tag> ^p/mJ1/s7  
cO9Aw!  
body K%;yFEZ  
~O6=dR  
</tt:tag> W{d/m;<@N  
1\uS~RR  
' iK0Wr  
一个不带body的tag标签如下: uip]K{/A!e  
1,,-R*x  
<tt:tag /> =UY@,*q:c  
S{6u\Vy  
`<q5RuU  
简单的tag标签 5"U7I{\  
Sy~1U  
一个没有body和属性的tag标签如下: @T"385>  
bv"S(  
<tt:simple /> (n\ cs$  
%<t/xAge  
4y]*"(sQ;  
带属性的tag标签 ?%(*bRV -  
b8&9pLl  
6s;x@g]  
自定义标签可以有自己的属性。属性一般在开始标记中定义,语法为 attr=”value”。属性的作用相当于自定义标签的一个参数,它影响着tag处理类的行为。你可以在TLD中详细定义它。 }=gGs  
<*P1Sd.  
你可以用一个String常量给一个属性赋值,也可以通过表达式给它赋值,如<%= ...%>。以struts为例,它的logic:present标签就是用的String常量来给属性赋值: O/Vue  
g,nEiL  
<loglic:present parameter = “Clear”> XJ9>a-{  
2Z~o frj  
而另一个标签logic:iterate是用表达式来给属性赋值: gN%R-e0  
`Ec+i  
<logci:iterate collection=”<%= bookDB.getBooks() %>” WyP1"e^ 9  
ZUycJ-[  
id=”book” type=”database.BookDetails”> #A!0KN;GC2  
cf9y0  
yyc&'J  
带body的tag标签 3B+Rx;>h  
O9Aooe4W=  
一个自定义标签可以包含其它自定义标签、脚本变量、HTML标记或其它内容。 \=)h6AG  
(!s[~O6  
在下述例子中,此JSP页面使用了struts的logic:present标签,如果些标签定义了parameter=”Clear”的属性,则将清除购物车的内容,然后打印出一条信息: jk@]d5  
i{2KMa{K  
<logic:present parameter=”Clear”> P;34Rd  
9EEHLx"  
<% cart.clear(); %> K4"as9oFP  
5> UgBA  
<font color=”#ff0000” size=”+2”><strong> E2MpMR  
DVd/OU  
你选择了清除购物车! X9R-GT  
A:f+x|[  
</strong></font> eR CGr?e4  
P\JpE  
</logic:present> f+ &yc'[  
|@RO&F  
n !QjptQ  
到底是用属性还是用body来传递信息? N@}U;x}  
$1e@3mzM  
如上所述,我们既可以通过属性,也可以通过body来传递信息。但一般来说,比较简单的类型,如字符串或简单表达式最好采用属性来传递信息。 H\T h4teE  
`8I&(k<wLe  
4.8,&{w<m  
定义脚本变量的tag标签 0^=S:~G  
7Do)++t  
所谓脚本变量,是指JSP中可以调用的变量或对象。它可由tag标签产生。以下示例阐述了一个tag标签定义了一个名为tx的由JNDI所定义的事务处理对象。脚本变量可以是ejb对象、事务、数据库连接等等:  DWI!\lK  
lk80)sTZ  
<tt:lookup id=”tx” type=”UserTransaction” name=”java:comp/UserTransaction” /> L<: ya  
dx^3(#B  
<% tx.begin(); %> yAOC<d9 E  
4?Io@[7A)  
... (&S v $L@  
WKG=d]5  
,3wo  
具有协作关系的tag标签 Vr'Z5F*@  
[kCn6\_<V  
自定义tag标签之间可以通过共享对象来实现协作。在下述例子中,标签tag1创建了一个名为obj1的对象,在标签tag2仍可以重复使用obj。 2rxdRg'YLQ  
z,)Fvs4U.  
<tt:tag1 attr1=”obj1” value1=”value” /> m#Cp.|>kP4  
\ys3&<;b  
<tt:tag2 attr1=”obj1” /> 2.6,c$2tB  
O1 z>A  
在以下这个例子当中,如果外层的tag标签创建了一个对象,那么其内层的所有tag标签都可以使用这个对象。由于这样产生的对象没有一个指定的名字,那么就可以将少重名的冲突。这个例子阐述了一系列协作的嵌套对象。 -&c@c@dC  
I ?1E}bv  
<tt:outerTag> ]n{2cPx5d  
xsfq[}eH<  
<tt:innerTag /> .D :v0Zm}m  
X_h+\ 7N>  
</tt:outerTag> YXvKDw'95  
t/3veDh@  
HV}NT~  
Tag处理类 Y !`H_Qo  
;j$84o{  
 *q^'%'  
Tag处理类必须实现Tag接口或BodyTag接口,不过现在一般都流行从TagSupport或BodyTagSupport类中继承,这些类或接口都可以在javax.servlet.jsp.tagext包中找到。 ! M bRI  
$z<CkMP!U7  
当JSP引擎看到自己的JSP页面中包含有tag标签时,它会调用doStartTag方法来处理tag标签的开头,调用doEndTag方法来处理tag标签的结束。 _?{2{^v  
&rn,[w_F[  
下表说明不同类型的tag所需要不同的处理过程: F?UL0Q|uv  
\1tce`+  
Tag处理类的方法 nP}/#Wy  
:A[ Gtc(_  
Tag标签类型 HjK|9  
所调用的方法 ^3e l-dZ  
'!_o`t@  
基本标签 uuq?0t2Z  
doStartTag, doEndTag, release VR'w$mp  
b c+' n  
带属性的标签 hJ|z8Sy@1  
doStartTag, doEndTag, set/getAttribute1...N, release WYq, i}S  
\UXQy{Ex  
带内容的标签 PgVM>_nHk  
doStartTag, doEndTag, release LE7o[<>  
MFC= oKD  
带内容的标签,且内容重复循环 iB\d `NUf  
doStartTag, doAfterBody, doEndTag, release ]Y3ALQr!  
>6@UjGj54  
带内容的标签,且内容与JSP交互 b&LhydaJ  
doStartTag, doEndTag, release, doInitBody, doAfterBody, release =/zQJzN  
|_O1V{Q=  
一个tag处理类可以通过javax.servlet.jsp.PageContext来与JSP交互,通过javax.servlet.jsp.PageContext类,tag处理类可以访问JSP中的request、session和application对像。 n44j]+P  
C ZJW`c/  
如果tag标签是互相嵌套的,那内层的tag处理类可以通过它的parent属性来访问上层的tag处理类。 ddw!FH2W (  
!XK p_v  
一般情况都将所有的tag处理类打成了JAR的包,以便于发布。 &oT]ycz%  
tvd/Y|bV=  
*bR _ C"-  
Tag库描述(简称TLD) FCg,p2  
W7.]V)$wM  
}+SnY8A=KZ  
Tag库是用xml语言描述的,TLD包括了tag库中所有tag标签的描述,它一般用来被jsp服务器用来校验tag的语法正确性,或者被jsp开发者用来开发新的标签。 sUg7  
3c6<JW  
TLD的文件扩展名必须为.tld,而且必须放在当前WEB应用的WEB-INF目录或其子目录中。 le*pd+>j  
W] RxRdY6[  
一个TLD的内容的开头必须遵守标准的XML开头,用于描述DTD和xml的版本,例如: -q-%)f  
k(T/yd rw  
<?xml version="1.0" encoding="ISO-8859-1" ?> Z rvb %  
P/^:IfuR  
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd"> Orz Dr  
TLD必须以<taglib>来作为它的根元素,<taglib>的子元素如下表: r> NgJf,  
\;Ii(3+v;  
J&lQ,T!?B  
<taglib>的子元素 T'w=v-(J  
y M>c**9  
Element r| YuHm  
Description ZVI.s U  
Lw3Z^G  
tlib-version 3uN;*f  
Tag库的版本 T;I a;<mfE  
CnJO]0Op3  
jsp-version q'PA2a:  
Tag库所需要的jsp的版本 m,-:(82  
vh((HS-)  
short-name J.~$^-&!  
助记符,tag的一个别名(可选) N8:vn0ww  
RFqbwPX  
uri U#YM)8;Iz  
用于确定一个唯一的tag库 ni9/7  
kGCd!$fsk  
display-name ujHqw Rh  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) ZU/6#pb  
e5MX5 T^  
small-icon ,*Sj7qb#  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) {gzL}KL  
Uh*V>HA#  
large-icon B1 'Ds  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) &g|-3)A  
3. Kh  
description ,LG6py&aT  
对tag库的描述(可选) $n!saPpxS  
5r@x$*>e  
listener )| 3?7?X  
参见下面listener元素 TN(1oJ:  
Xn4U!<RT"  
tag |6$6Za]:  
参见下面tag 元素 C}#JvNyQ  
/z`LB  
Listener元素 zuXJf+]  
UP^{'eh  
一个tag库可能定义一些类做为它的事件侦听类,这些类在TLD中被称为listener 元素,jsp服务器将会实例化这些侦听类,并且注册它们。Listener元素中有一个叫listener-class的子元素,这个元素的值必须是该侦听类的完整类名。 }~yhkt5K  
G,%R`Xns  
Tag元素 G|v{[>tr  
Yaht<Hy  
每个tag元素在tag库中都要指出它的名字、类名、脚本变量、tag的属性。其中脚本变量的值可以直接在TLD中定义或通过tag附加信息的类来取得。每个属性描述了这个属性是否可以省略,它的值是否可以通过<%= …%>这样的JSP语法来获得,以及属性的类型。 B xq(+^T  
^lf{IM-Y  
每一个tag在TLD中对应一个tag元素,下表是tag元素的子元素: Wfz&:J#  
e%SQ~n=H 9  
Tag元素的子元素 Q % )fuI  
,{=#  
元素名称 < OCy  
描述 3 rV)JA  
#D&eov?  
name WL+I)n8~  
独一无二的元素名 pvD\E  
SVo:%mX  
tag-class z\{y[3-  
Tag标签对应的tag处理类 *#w+*ywVZH  
i_Ab0vye  
tei-class w>J|416  
javax.servlet.jsp.tagext.TagExtraInfo的子类,用于表达脚本变量(可选) K#kU6/  
|-%[Z  
body-content C65( m  
Tag标签body的类型 q0&g.=;  
+g>)Bur  
display-name Rra<MOR  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) ".Luc 7  
3a_~18W  
small-icon Hcq?7_)  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) 5L'X3g  
t3 2 FNg  
large-icon 9s7sn*aB#5  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) M<4~ewWJ  
ssUWr=mD  
description -J[*fv@  
此tag标签的描述 sFuB[ JJ}  
4[v %]g`  
variable IZoS2^:yw  
提供脚本变量的信息(同tei-class)(可选) !8(: G6Ne  
9{]U6A*K0w  
attribute R<I)}<g(A3  
Tag标签的属性名 bk44 qL;8  
JmjqA Dex  
以下章节介绍对于不同类型的tag,如何具体地实现它们。 :q/%uca9  
K!;Z#$iw[  
9@/ X;zO  
简单的tag 6w|s1!B l  
Q$^oIFb  
Ru9QQaHE  
tag处理类 _8P0iC8Zg#  
b*&AIiT  
简单的tag处理类必须实现Tag接口的doStartTag和doEndTag方法。当jsp引擎碰到tag标签的开头时,doStartTag被调用,因为简单的tag没有body,所以此方法将返回 SKIP_BODY。当jsp引擎碰到tag标签的结尾时,doEndTag被调用,如果余下的页面还要被计算,那它将返回EVAL_PAGE,否则将会返回SKIP_PAGE。 Z9,-FO{#3-  
F[R Q6 PW  
以下是例子:对于标签 <tt:simple /> ,它的tag处理类实现如下: Nk*d=vj  
CB]#`|f  
^{lcj  
public SimpleTag extends TagSupport :c)N"EJlI2  
Fuq ;4UcbL  
{ dj>zy  
?S9? ?y/  
public int doStartTag() throws JspException fP# !ywgr%  
#eadkj #;  
{ ""q76cx  
589hfET  
try{ ^YiGvZJ  
z3x /Y/X$S  
pageContext.getOut().print(“Hello.”); ammlUWl  
'_oWpzpe  
}catch(Exception e){ (?4m0Sn>#h  
.5*5S[  
throw new JspTagException(“SimpleTag: “ + e.getMessage()); G'<:O(Imu  
dxfF.\BFDn  
} /vO8s??  
8T-/G9u  
return SKIP_BODY; cuzU*QW"g  
'-c *S]:r  
} /6",#B}%b  
|7ct2o~un  
public int doEndTag() xU<WUfS1  
!1(*D*31  
{ i[L5,%5<H  
t$~CLq5ad  
return EVAL_PAGE; 1seWR"  
rMr:\M]t  
} j}u b  
I(m*%>  
} I[nSf]Vm>  
!y_4.&C{  
 qHVZsZ  
注意:如果tag标签没有内容的话,那必须定义body-content元素为空,例如 Sq22]  
&`x1_*l  
<body-content>empty</body-content> hvW FzT5  
lEAf\T7  
# `L?24%  
带属性的tag标签
评价一下你浏览此帖子的感受

精彩

感动

搞笑

开心

愤怒

无聊

灌水
级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
只看该作者 1 发表于: 2007-01-01
tag处理类 (fNG51h!  
 GY`mF1b  
对于tag标签的每个属性,你必须依照JavaBeans规范来定义其属性,以及get和set方法。以struts的logic:present 标签为例, iy!SqC  
@=<B8VPJd  
<logic:present parameter=”Clear”> >G9YYt~  
*RYok{w  
与此相应,此tag处理类应有如下方法和定义: Q Uy7Q$W  
i8w/a  
~cv322N   
protected String parameter = null; b I"+b\K  
^iA_<@[`X[  
public String getParameter() NJ^Bv`  
m+|yk.md  
{ k%D|17I  
gUr #3#  
return this.parameter; Uc%kyTBm1  
 #nq$^H  
} G22{',#r8  
{"PIS&]tR  
public void setParameter(String parameter) 3QI.|;X  
Llf#g#T  
{ 43.Q);4  
jhR`%aH4  
this.parameter = parameter; >\?RYy,s$  
\X2r?   
} icK>|   
0?o<cC1Z  
P9 w);jp;  
注意:如果你的属性名为id,而且你的tag处理类是从TagSupport类继承的,那你就不需要定义它的属性和set和get方法,因为他们早已在TagSupport被定义过了。 d%Ls'[Y^_0  
K>2M*bGc p  
Attribute元素 -bd'sv  
iV5S[uy72.  
对于tag标签的每个属性,你必须定义它是否必须的,它的值是否可以用诸如<%= …%>的表达式来获得,以及它的类型(可选),如果不指定它的类型,那就默认为是java.lang.String类型。如果rtexprvalue元素被定义为true或yes,那么在type元素中就定义了attribute的返回类型。 1SF8D`3  
0fJz[;dV>n  
<attribute> &K*Kr=9N  
\/s0p  
<name>attr1</name> NR3h|'eC  
3*zywcTH  
<required>true|false|yes|no</required> Lm8uN?  
BaVooN~C  
<rtexprvalue>true|false|yes|no</rtexprvalue> =28ZSo^  
9^+E$V1@  
<type>attribute的返回类型(只用当rtexprvalue为真是才有效)</type> K+\2cf?bU  
dL]wu! wE  
</attribute> CzDV^Iv;Q{  
;&dMtYb  
如果tag的某个属性不是必须的,那tag处理类会自动提供一个缺省值。 QXu[<V  
!$NQF/Ol  
例如,在logic:present这个tag标签中定义了一个属性叫parameter,但它不是必须的,而且它可以被诸如<%= …%>的表达式来赋值。 w2SN=X~#  
Z'UhJuD5  
<tag> }Uu#N H  
}  fa  
<name>present</name> p%R+c  
+'/C(5y)0X  
<tag-class>org.apache.struts.taglib.logic.PresentTag</tag-class> %p:Z(zU  
z3c7  
<body-content>JSP</body-content> R=2"5Hy=  
esM r@Oc  
B[IWgvB(e  
k4PXH  
<attribute> |%oI,d=ycv  
:6:,s#av  
<name>parameter</name> $0gGRCCG;  
@_$Un&eo  
<required>false</required> R`J.vMT  
IISdC(5  
<rtexprvalue>true</rtexprvalue> Q@1SqK#-DQ  
"l{{H&d  
</attribute> E!RlH3})  
99tUw'w  
ix hF,F  
4T]A! y{  
</tag> ]!]B7|JFJ  
)Ma/] eZ^I  
*xjP^y":  
属性元素的校验 .}5qi;CA  
~h:(9q8NLC  
v@4vitbG9  
有关于tag标签的有效值可以从tag库的说明文档中获得,当JSP页面被编译时,jsp引擎会强制性地参照TLD中定义的规则进行检查。 :='I>Gn  
Z,tHyyF?j  
还有一个方法也可以进行属性元素的校验,就是先继承类TagExtraInfo,然后调用它的isValid方法。这个类同时也起到提供tag中定义的脚本变量信息的作用。 JEs@ky?{z  
o%!s/Z1  
IsValid方法通过TagData对象来传递属性信息,它包括着tag的所有的属性名-值的信息。由于校验发生在运行时刻,因此这个属性的值将被赋值为TagData.REQUEST_TIME_VALUE。 l"1*0jgBw  
D\Y,2!I  
例如tag标签<tt:twa attr1=”value1” />在TLD中定义如下: n[B[hAT  
gFd*\Dk  
<attribute> |c>.xt~  
DheQcM  
<name>attr1</name> 6RG63+G  
,^7] F"5  
<required>true</required> VsJKxa4  
FJ{/EloF  
<rtexprvalue>true</rtexprvalue> &2Ef:RZF  
wPX^P  
</attribute> O^PN{u  
7GTDe'T  
CpB,L  
这个定义说明了attr1能在运行期间被赋值。 YG /@=Z.  
n.i 8?:  
以下的isValid方法检查attr1属性的值是否属于Boolean类型。注意由于attr1能在运行刻被赋值,那么isValid方法必须检查tag用户是否对此tag进行了运行时刻赋值。 {V pk o  
mo+!79&  
uq/Fapl  
Public class TwaTEI extends TagExtraInfo l<p<\,nV$  
l-P6B9e|\  
{ 5KfrkZ  
Dlpmm2  
public boolean isValid(Tagdata data) G3 |x%/Fbp  
,!,tU7-H  
{ *$5p,m6G  
/+*N.D'`t,  
Object o = data.getAttribute(“attr1”); h$}PQ   
1]9w9! j  
If(o != null && o != TagData.REQUEST_TIME_VALUE) eY-h<K)y  
R={#V8D~  
{ 6$0<&')Yb  
OwEu S#-  
if( ( (String)o).toLowerCase().equals(“true”) || <5^m`F5  
PD^G$LT  
((String)o).toLowerCase().equals(“false”) ) Y9gw ('\w  
jABFdNjri  
return true; SME9hS$4  
=j{tFxJ  
else 4l{$dtKbI  
93Zij<bH?e  
return false; =@pD>h/~  
c%WO#}r|  
} xXc>YTK'  
?68~g<d,  
else icX4n  
c1r+?q$f  
return true; m)LI| v  
jO/cdLKX(  
} Faa>bc~E  
{6WG  
} Zk/ejhy0  
s7HKgj  
C/QmtT~`e  
带body的tag t|V<K^  
&AOGg\  
VdGVEDwz  
tag处理类 K a& 2>F  
PO8Z2"WI  
Z#B}#*<C  
如果tag标签含有内容,那处理方式会略微有些不同,而且还要视tag处理类是否要与body交互的情况而定。如果要与body交互,那我们认为tag处理类要可能要对body进行操作。 {%CW!Rc  
E#_2t)20  
Tag处理类不与body交互 x=IZ0@p  
7#d:TXS  
如果tag处理类不与body交互,tag处理类应该实现Tag接口或从TagSupport中派生,如果body要被计算,那么doStartTag方法应返回 EVAL_BODY_INCLUDE,否则应返回SKIP_BODY。 /a<UKh:A[  
6%h%h: e  
如果tag处理类要对body反复运算,则它应该实现IterationTag或从TagSupport中派生。如果tag处理类认为body还未计算完的话,那它的doStartTag方法和doAfterBody方法必须返回EVAL_BODY_AGAIN。 [\#ANA"  
sQj]#/yK:  
Tag处理类与body交互 y/ Bo 4fM  
<ch}]-_  
如果tag处理类与body交互,那tag处理类应实现BodyTag接口或从BodyTagSupport中派生。这种tag处理类一般要实现doInitBody和doAfterBody方法。 P3]K'*Dyd  
#g0_8>t  
Body允许一些方法来读写它的内容。Tag处理类可以调用body内容的getString或getReader方法来从body中提取信息,也可用 writeOut(out) 方法来将body的内容写入到out对象中。其中out对象通过tag处理类的getPreviousOut方法来获得。 #HH[D;z  
$,J}w%A  
如果body的内容需要被计算,那么doStartTag方法必须返回EVAL_BODY_BUFFERED,否则,它将返回 SKIP_BODY。 ,(a~vqNQW3  
.d}yQ#5z  
doInitBody 方法 4sntSlz)~k  
b_a k@LYiu  
此方法在body内容已经设好,但未被计算之前被调用。你可以根据不同的body内容来制定初始化策略。 6r`N\ :18  
FZn1$_Svr  
doAfterBody方法  ?ueL'4Mm  
sT"ICooc  
此方法在body内容已被计算后进行调用。 TIZ2'q5wg  
4r `I)  
和doStartTag方法一样,doAfterBody方法返回一个指示符指示是否要继续计算body,如果要继续计算,则doAfterBody应返回EVAL_BODY_BUFFERED,否则,它应返回SKIP_BODY。 <8;~4"'a  
38T] qz[Sn  
release 方法 1/m$#sz  
)DhE~  
tag处理类调用此方法将它的状态重置为初始状态,并释放所有的私有资源。 ;"u,G!  
W^h,O+vk  
fv#ov+B  
以下的例子读取body的内容(其中含有一条sql语句),然后将它传递给一个对象,让它进行查询。由于此处body不须重新计算,所以doAfterBody会返回SKIP_BODY。 " acI:cl?,  
xGQP*nZ  
W4&8  
Public class QueryTag extends BodyTagSupport k}F7Jw#.  
;Z"MO@9:  
{ f|M^UHt8*  
<W!nlh  
public int doAfterBody() throws JspTagException 2I}+AW!!=  
,*U-o}{8C?  
{ 717THci3Y  
Wz=& 0>Mm_  
BodyContent bc = getBodyContent(); E"_{S.Wc  
1HKA`]D"p  
//将body的内容以字符串的格式提取出来 0?8>{!I  
_hyqHvP  
String query = bc.getString(); -&`_bf%M  
E b:iym0  
//清除body i+mU(/l2{  
|9%~z0  
bc.clearBody(); {q`8+$Z;  
(J%4}Dm  
try{ ] 1pIIX}  
V\x'w*FP  
Statement stmt = connection.createStatement(); 2,q*8=?{6P  
oA[`| ji  
Result result = stmt.executeQuery(query); :0Jn`Ds4o  
gk6R#  
}catch(SQLException e){ X4 S| JT  
\Db;7wh  
throw new JspTagException(“queryTag: “ + e.getMessage() ); ]o]`X$n  
JyTETf,y  
return SKIP_BODY; h6?^rS8U  
m!G(vhA,_w  
} lAM)X&}0  
v5L+B`~  
} H[p~1%Lq  
G gA:;f46  
P$Vh{]4i{  
body-content元素 WN{8gL&y  
^8~TsK~  
rhQ+ylt8I  
由于tag可能会有body,你必须用body-content元素来指定body内容的类型: gh*k\0  
]gVA6B?&9  
<body-content>JSP|tagdependent</body-content> B=K<k+{6"  
.eg'Z@o  
*5BVL_:~J  
如果body的内容是定制的或内部的tag、脚本元素、或HTML广本,则归类为JSP类型。其他的类型,比如上面代码所述的?D?D将sql statement类传给 query tag的这种类型应该标为tagdependent。 jd ;)8^7K  
Qc-W2%  
注意:实际上body-content的值并不影响tag处理类对body内容的处理,它仅仅是被tag编辑工具用来描述此body的内容。 l<uI-RX "  
Uz,P^\8^$  
nw- -  
用tags定义脚本变量 4cSs=|m?+  
!PGCoI  
{ CR`~)v&  
tag处理类 yN{**?b  
*~6]IWN`  
q`{@@[/ (y  
tag处理类负责创建或设置页面中定义的脚本变量,用pageContext.setAttribute(name,value,scope)或pageContext.setAttribute(name,value)方法来实现。一般来说,tag处理类通过脚本变量的名称来获取它,脚本变量的名称一般可用get方法来获得。 w9GY/]  
75^*4[  
如果脚本变量的值依赖于tag处理类中的上下文中某一对象,那它可用pageContext.getAttribute(name,scope)方法来找到那个对象。一般的处理过程是tag处理类先找到脚本变量,再对其进行处理,然后用pageContext.setAttribute(name,object)的方法来设置它的新值。 Gdb0e]Vt+  
5)S;R,  
对象的生存周期(scope)如下表: K/C}  
iUh7eR9  
对象的生存周期表 OfBWf6b  
.Qn#wub  
名字 M5+R8ttc  
可访问范围 v"(6rZsa  
生存周期 #S/~1{   
hlV(jz  
page p+b9D  
当前页面 ~I> |f  
一直有效,除非页面向客户提交响应或重定向到一个新页面 /_cpS q  
2& Hl wpx  
request 6zU0 8z0-  
当前页面或当前页面重定向到的页面 rtvLLOIO  
一直有效,除非页面向客户提交响应 |>j^$^l~  
Et*LbU  
session "7+^`?  
当前页面或在同一浏览器窗口中的页面 dfVI*5[Z  
一直有效,除非关闭当前浏览器、超时、网络故障 ( zm!_~1  
V4"o.G3\o  
application 8i`T?KB  
整个web应用程序的所有请求 :%mls Nw  
一直有效,除非发生网络故障、服务器故障 \)\n5F:Zu  
E5P.x^  
提供关于脚本变量的信息 =r]_$r%gR  
!K*3bY`#  
以下示例定义了一个名为“book”的脚本变量,用来访问程序中关于书的信息: :jTbzDqQ  
#oEtLb@O  
<bean:define id=”book” name=”bookDB” property=”bookDetails” type=”database.BookDetails” /> b4$.uLY  
!?i9fYu  
<font color=”red” size=”+2” > 2xuU[  
Y(rQ032s  
<%= messages.getString(“CartRemoved”) %> (0 t{  
Dy. |bUB!f  
<strong><jsp:getProperty name=”book” property=”title” /></strong> }W " i{s/  
u];\v%b  
</font> kH0kf-4\  
-6F\=  
当包含此tag的JSP页面被编译时,jsp引擎会自动生成关于此book的同步的代码(同步可以避免几个客户同时访问此book时造成的冲突),要生成同步代码,jsp引擎需要知道此脚本变量的如下信息: u{W I 4n?  
aF"PB h=  
· 脚本变量名称 ]nIVP   
f~=e  
· 脚本变量所属的类 u5qaLHoEP  
su\Lxv  
· 此脚本变量是否引用了一个新的或已存在的对象 Aj\m57e,6  
QxEmuiN  
· 此脚本变量的有效性 O&.gc p!  
tJ d/u QJ  
有两种办法可以向jsp引擎提供关于脚本变量的信息:在TLD中定义variable子元素,或用tei-class子元素定义一个额外tag信息类。用variable最简单,但可能降低了一些灵活性。 ri"=)]  
<4?(|Vh[m]  
Variable元素 ;erxB6*  
yP@#1KLa+  
Variable元素有如下子元素: YL;*%XmAG  
=}0>S3a.7  
· name-given ?D?D 给出的名字,是一个常量 = "Lb5!  
Jn?ZJZ  
· name-from-attribute?D?D 属性名,在编译时给出的属性名 P6^\*xkMr  
='eQh\T)  
name-given或name-from-attribute两者必须选一,但以下子元素是可选的: wjID*s[  
[e.`M{(TB  
· variable-class?D?D变量的类型,缺省为java.lang.String。 2+(SR.oGq  
fEK%)Z:0  
· declare?D?D此脚本变量是否引用了一个新对象,缺省为True。 )J\ JAUj  
$Ovq}Rexc  
· scope?D?D脚本变量的范围,缺省为NESTED。下表描述了scope的几种类型: :Z;kMrU  
S|RUc}(  
脚本变量的有效范围 =%FhY^-  
_3KfY  
IU}g[O Cu  
有效性 `$;%%/tx  
方法 MGKSaP;x  
g( eA?  
NESTED w~9Y=|YI7  
在tag标签的开始和结束之间 [9CBTS r  
如果tag处理类实现BodyTag接口,则在doInitBody和doAfterBody中调用,否则在doStartTag中调用 4%jSqT@  
Z79Y$d>G<E  
AT_BEGIN %. IW H9P7  
从tag标签的开始一直到页面结束 |oOA;JC)(  
如果tag处理类实现BodyTag接口,则在doInitBody、doAfterBody和doEndTag中调用,否则在doStartTag和doEndTag中调用 pi*?fUg!W  
F*B^#AZg  
AT_END G"<} s mB  
从tag标签的结束一直到页面结束 ~|wh/]{b9  
在doEndTag中调用 ` NvJ  
''EFh&F  
以struts为例,它的bean:define标签的实现遵循JSP1.1规范,此规范要求使用额外tag信息类来定义脚本变量。Variable元素是JSP1.2规范中加入的。以bean:define标签为例,你可以定义如下variable元素: J]*?_>"#8  
;ahI}}  
<tag> JHVesX  
olDzmy(=W*  
<variable> 9qJ:h-?M  
&ujq6~#  
<name-from-attribute>id</name-from-attribute> )!`>Q|]}Zd  
+r =p ,leb  
<variable-class>database.BookDetails</variable-class> cC`PmDGq  
?0+J"FH# W  
<declare>true</declare> 2 mvp|< "  
:?gk =JH:  
<scope>AT_BEGIN</scope> !Ie={BpzbZ  
Q S.w#"X[  
</variable> Z2\Xe~{  
iJ`v3PP  
</tag> llBW*4'  
24_/JDz  
额外tag信息类 >R6>*|~S  
?)c9!hR  
如果要定义一个额外tag信息类,你要继承javax.servlet.jsp.TagExtraInfo类。一个TagExtraInfo类必须实现getVariableInfo方法,此方法返回一个叫VariableInfo的数组类,它包括如下信息: M*jn8OE  
1QuR7p  
· 变量名 v|r#  
klC48l  
· 变量所属类名 +Xr87x;  
UazUr=| e  
· 此变量是否引用了一个新对象 <Dp[F|r  
Nf{tC9l  
· 此变量的有效范围 bcprhb  
G`R2=bb8  
jsp引擎将一个名为data的参数传给getVariableInfo方法,data中包括tag标签中的所有“属性名?D?D属性值”对。它可以用来向VariableInfo对象提供脚本变量的名字和类名。 yYZ0o.<&T*  
]u O|YLWp  
以struts为例,它在bean:define标签中定义了一个名为DefineTei的额外tag信息类,用来向脚本变量提供信息。由于脚本变量的名称(book)和类名(database.BookDetails)是通过tag标签的属性来传递的,它们一般定义在VariableInfo的构建代码中,并且可用data.getAttributeString方法来得到这些信息。如果要允许book脚本变量能在从tag开始直到整个JSP页面结束的范围内都可用的话,那它的范围应设为AT_BEGIN。如下所示: <NX6m|DD  
4ze4{a^  
L{i|OK^e  
public class DefineTei extends TagExtraInfo +D+Rf,D  
w=75?3c7F  
{ 2SVJKX_V+  
z2A1h!Me  
public VariableInfo[] getVariableInfo(TagData data) 1:iT#~n  
?`D/#P  
{ XFN4m #  
V\o& {7!  
String type = data.getAttributeString(“type”); 0j|JyS:}G  
@460r  
If( type == null) Gl>_C@n0h  
!tofO|E5  
type = “java.lang.Object”; ::rKW *?  
-}*YfwK  
return new VariableInfo[] { MXU8QVSY"  
41`&/9:"_M  
new VariableInfo(data.getAttributeString(“id”), 4m$Xjj`vE  
vb Mv8Nk  
type, ];o[Yn'>o  
~~'UQnUN4  
true, zc#aQ.  
5S ?+03h~  
VariableInfo.AT_BEGIN) [S!_ubP5  
9i+SU|;j  
}; w[wrZ:[  
</8F  
} J'>i3e Lq  
tO ^KCnL  
} ~<#!yRy>r  
a5xp[TlXn.  
`[Xff24(eb  
注意:关于额外tag信息类的类名必须要在TLD中的tag标签下的tei-class子元素中定义。因此,DefineTei的tei-class中的定义看起来如下: A5> ,e|  
<tei-class> |cE 69UFB  
org.apache.struts.taglib.bean.DefineTagTei $>fMu   
</tei-class> ^h@1tFF  
2oFHP_HVfu  
As7Y4w*+  
具有协作关系的tag mN:p=.& <  
RK`C31Ws  
mxV0"$'Fm  
tag通过共享对象来进行协作,JSP技术支持2种方式的对象共享。 KoNJ;YiKtN  
5b2_{6t  
第一种方法是使用pageContext对象进行对象的共享(可支持JSP页面和tag处理类之间的共享),如果在一个tag处理类中要调用由另一个tag处理类创建的对象,可调用pageContext.getAttribute(name, scope)方法。 tk <R|i  
eO:wx.PW  
第二各方式的共享是对于tag之间有嵌套关系而言的,外层的tag所创建的对象对于内层的tag来说是可以共用的。这种形式的共享的好处是减少了可能存在的重名冲突。 IZkQmA=  
-?$Hr\  
要访问一个嵌套tag创建的对象,tag处理类必须先找到此嵌套tag对象,可用TagSupport的静态方法 TagSupport.findAncestorWithClass(from, class)或TagSupport.getParent方法。前者在当不确定此tag是否为嵌套tag对象时使用。一旦它的父类被找到,它就能访问其所有动态或静态创建的对象。静态创建的对象是父类的成员,而动态创建的对象可能是父类的私有对象。诸如此类的对象可以用tag处理类的setValue方法来保存,用getValue方法来获得。 z!GLug*j`  
\L: ;~L/  
下例阐述了以上两种共享对象的方法。在这个例子当中,一个查询tag检查一个名为connection的属性名是否在doStartTag中被设置。如果connection属性被设置,tag处理类从pageContext中得到这个connection对象。否则,此tag处理类先找到它的父tag处理类,然后从它的父tag处理类中找到connection对象。 -q.tU*xf'  
)!&7XL[  
m:7$"oq|  
public class QueryTag extends BodyTagSupport HsGyNkr?r  
4>&%N\$*  
{ ^l4=/=RR  
\We\*7^E  
private String connectionId; 8 3wa{m:  
q-fxs8+m|  
public int doStartTag() throws JspException C&vUZa[p  
Q,mmHw.`J  
{ q^_PR|  
Xn'{g  
String cid = getConnection(); 26,!HmtC  
CcZ\QOet&C  
if(cid != null) lklMdsIdj  
M 8BN'% S  
{ +JMB98+l  
iwl\&uNQU  
//存在一个connection id,使用它。 [y}0X^9,E  
;r_YEPlZ  
connection = (Connection) pageContext.getAttribute(cid); 2 R !1Vl  
RTW4r9~'  
} =;9*gDfD  
yqm^4)Dp  
else <I{)p;u1  
A@X&d y  
{ .*N,x0 B(  
E  K)7g~  
ConnectionTag ancestorTag = (ConnectionTag)findAncestorWithClass(this, VE<&0d<  
m\88Etl@  
ConnectionTag.class); o#-K,|-  
+d0&(b  
if(ancestorTag == null) \WnI&nu  
J<<0U;  
{ <= xmJx-V  
+|N!(H  
throw new JspTagException(“一个没有connection属性的查询标签必须被一个connection标记嵌套。”); ,[lS)`G  
PyD'lsV  
} vPn(~d_  
*.UM[Wo  
connection = ancestorTag.getConnection(); 6p X[m{  
yu'2  
} El~x$X*  
F8J;L](Dq  
} ,{ C   
"-'w,g  
} LP8Stj JP  
#[^?f[ 9r  
"0F =txduS  
}2^_Gaj  
此查询标签在JSP页面中的调用形式可以从以下2种定义中任选一种: OA\2ja~+  
$DmWK_A  
@tY)s  
<tt:connection id=”con01” ...> ... </tt:connection> ))" *[  
/Ot=GhN]  
<tt:query id=”balances” connection=”con01” > u.t(78N  
OKU9v{  
SELECT account, balance FROM acct_table dc MWCK  
_yq"F#,*  
where customer_num = <%= request.getCustno() %> :h1-i  
0Dj<-n{9  
</tt:query> ;IC:]Zu  
HB+\2jEE  
+)C?v&N  
GoI3hp(  
]bG8DEwD  
<tt:connection ...> `zNvZm-E  
p!MOp-;-  
<x:query id=”balances”> uFM]4v3  
uUUj?%  
SELECT account, balance FROM acct_table NrE&w H:  
6% @@~"  
where customer_num = <%= request.getCustno() %> }+K SZ,  
n{dl- P  
</x:query>  o *2TH2  
sjpcz4|K  
</tt:connection> bE-{ U/;  
`B+P$K<X  
iV!o)WvG,F  
与此同时,在TLD中必须指定connection属性为可选的,定义如下: c}a.  
3%?01$k  
<tag> bq/*99``  
=@U~ sl [  
... b{|Ha3;w  
x | =  
<attribute> NPws^  
-hav/7g  
<name>connection</name> Y_3 {\g|x  
uFDJRQJ<  
<required>false</required> (|_1ku3!  
#?)g?u%g=  
</attribute> SomA`y+ERn  
F V8K_xj  
</tag>
描述
快速回复

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