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

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

级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
标准的JSP 标记可以调用JavaBeans组件或者执行客户的请求,这大大降低了JSP开发的复杂度和维护量。JSP技术也允许你自定义taglib,其实换句话说,taglib可以看成是对JSP标记的一种扩展,正如xml是对html的一种扩展一样。taglib通常定义在tag标签库中,这种标签库存放着你自己定义的tag标签。简而言之,如果使用taglib,那么你可以设计自己的JSP标记! Eh!%Ne O  
,h #!!j\j6  
一般来说,自定义tag标签主要用于操作隐藏对象、处理html提交表单、访问数据库或其它企业级的服务,诸如邮件和目录操作等等。自定义tag标签的使用者一般都是那些对java编程语言非常精通,而且对数据访问和企业级服务访问都非常熟悉的程序员,对于HTML设计者来说,使得他可以不去关注那些较复杂的商业逻辑,而将精力放在网页设计上。同时,它也将库开发者和库使用者进行合理分工,自定义tag标签将那些重复工作进行封装,从而大大提高了生产力,而且可以使得tag库可用于不同的项目中,完美地体现了软件复用的思想。 y z9`1R2c  
KfG%#2\G_  
在这篇文章中,我们主要讨论: _8 vxb  
bjm`u3 A  
· 什么是自定义tag标签? \#LKsQa  
,*E%D _  
· 怎么使用tag标签? J}._v\Q7P  
@tEVgyN  
o 声明要使用的tag库 E;VBoN [  
"sAR< 5b  
o 找到与之对应的tag处理类 thipfS  
O.& 6J/  
o tag标签的类型 Q, #M 0  
'x+0 yd  
· 自定义tag标签 C;dA?Es>R  
sx*1D9s_  
o tag处理类 g_0"T}09(  
tborRi)  
o tag库描述 n\,TW&3  
puZ<cV e/  
o tag标签示例 iL|*g3`-f  
l2VO=RDiW  
o 带属性的tag kgr:8 5  
O3bK>9<K  
o 带body的tag `Jm{K*&8Q  
4 3]6J]!)  
o 定义了脚本变量的tag :e+GtN?  
e!tgWYN  
o 具有协作关系的tag &Ei dc .  
k`oXo%  
· 自定义tag标签 B|:{.U@ne  
m9#u. Q*  
o 一个迭代tag的例子 U|{WtuR  
vbDw2  
o 一个模板tag库 :&?#~NFH  
o&(%:|  
o tag处理类到底是怎样被调用的? ni2H~{]z  
Ic#+*W\ZW  
/rv XCA)j  
什么是自定义的tag? ]3d&S5zU  
a Q`a>&R0  
一个自定义的tag标签是用户定义的一种JSP标记。当一个含有自定义的tag标签的JSP页面被jsp引擎编译成servlet时,tag标签被转化成了对一个称为tag处理类的对象进行的操作。于是当JSP页面被jsp引擎转化为servlet后,实际上tag标签被转化成为了对tag处理类的操作。 ( fdDFb#1  
;Ic3th%u  
自定义tag标签有很多特色,诸如: U?$v 1||  
&CUkR6  
· 可以在JSP页面中自定义tag标签的属性 >x2T '  
8^dGI9N  
· 访问JSP页面中的所有对象 L'aMXNO  
YgM6z K~  
· 可以动态地修改页面输出 O])/kS`  
=;Wkg4\5  
· 彼此这间可以相互通信。你可以先创建一个JavaBeans组件,然后在一个tag中调用此JavaBeans组件,同时可以在另一个tag中调用它。 PDD` eK}Fj  
*k+QX   
· tag允许相互嵌套,可以在一个JSP页面中完成一些复杂的交互。 :\4O9f*5+  
})mez[UmZ  
}ZVNDvGH  
使用tag标签 Z: T4Z}4N  
ZN1QTb  
GExG1n-  
本节主要描述怎样在JSP页面中使用tag标签,以及tag标签的不同类型。 5Qy,P kje  
NA/+bgyuT>  
要使用tag标签,JSP程序员必须做2件事: * +OAc `8  
zh/+1  
· 声明此tag标签的tag库 Bj@&c>  
QO#ZQ~  
· 实现此tag标签 rBr28_i   
Y Nq<%i!>  
声明tag标签所在的tag库 &v 5yo}s  
^f<f&V  
如果要使用tag标签,则应用JSP的taglib指示符来指定其tag库(注意:taglib要在在使用此tag标签之前声明) 5)T{iPU%X  
!Id F6 %  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> 6@l:(-(j2A  
"Ww^?"jQ)  
uri属性定义了唯一的标签库描述(以下简称TLD),它可以是直接是tld文件名或一个独一无二的名字。prefix是用来区别其它TLD中和本TLD中有重名的tag的一种手段。 zEO 9TuBO  
Ho \+xX  
TLD必须以.tld作为扩展名,并且存放在当前应用的WEB-INF目录或其子目录下。你可以通过它的文件名直接引用它,也可以通过别的方式间接地引用它。 / /wmJ |  
KJ9~"v  
以下taglib指示符直接引用一个TLD: ,(c="L4[  
FfD2 &(-R  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> 29av8eW?3  
HnY: gu  
以下的taglib指示符通过一个逻辑名称间接地引用一个TLD: 3_33@MM  
X,y$!2QI  
<%@ taglib uri=”/tutorial-template” prefix=”tt” %> c#Y9L+O  
Uj!L:u2b  
如果是间接引用TLD的话,那你必须还要在web.xml中定义此逻辑名称与tld文件之间的映射,具体做法是在web.xml中加入一个名为taglib的元素: 4 Qw;r  
@&EP& $*  
<taglib> <78> 6u/W%  
!2{MWj  
<taglib-uri>/tutorial-template</taglib-uri> ImF/RKI~ "  
xUSIck  
<taglib-location> dDm<'30?*v  
YDmFR,047  
/WEB-INF/tutorial-template.tld 0hNc#x6  
B"Fg`s+]U  
</taglib-location> -C8awtbC  
>Zr/U!W*?  
</taglib> Pc4sReo'  
l;|1C[V  
0j_!)B  
实现此tag标签 0;XnNz3&  
<?Lj!JGX  
~?L. n:wu  
为了实现tag标签,你有2种方法来存放tag处理类。一、让tag处理类以.class的方式存放于当前应用的WEB-INF/class子目录下,二、如果tag处理类是以JAR包的形式存在的话,那可以放在当前应用的WEB-INF/lib目录下,如果tag处理类要在多个应用中共享,那么它就应放在jsp服务器上的common/lib目录下,对于tomcat来说,就是tomcat/common/lib目录下。 DH 9?~|  
#vDe/o+=  
Q7Dkh KT  
tag标签类型 CX1'B0=\r  
oa9T3gQ?  
YEZ"BgUnbp  
自定义的tag标签遵循XML语法。它有一个开始标记和一个结束标记,有的还有body(即文本节点): +:Y6O'h.  
L3kms6ch  
<tt:tag> 99ZQlX  
%*s[s0$c  
body "arbUX~d  
gqC:r,a  
</tt:tag> `q5*VqIhs  
u;Z~Px4]v  
=E,*8O]  
一个不带body的tag标签如下: _Y~+ #Vc  
7M$>'PfO  
<tt:tag /> Fe/*U4xU  
IzL yn  
TnKe"TA|9  
简单的tag标签 Z#Zk)  
ZM)a4h,kcm  
一个没有body和属性的tag标签如下: 0#yo\McZ  
~Aq UT]l  
<tt:simple /> :_?>3c}L  
kj-S d^  
W}Z|v M$  
带属性的tag标签 s\KV\5\o  
S&QZ"4jq  
5q8bM.k\7N  
自定义标签可以有自己的属性。属性一般在开始标记中定义,语法为 attr=”value”。属性的作用相当于自定义标签的一个参数,它影响着tag处理类的行为。你可以在TLD中详细定义它。 ].Et&v  
k@wxN!w;  
你可以用一个String常量给一个属性赋值,也可以通过表达式给它赋值,如<%= ...%>。以struts为例,它的logic:present标签就是用的String常量来给属性赋值: y\@XW*_?  
0<P -`|X  
<loglic:present parameter = “Clear”> N:d" {k  
f-23.]`v  
而另一个标签logic:iterate是用表达式来给属性赋值: J@)6]d/,  
QGYmQ9m{kL  
<logci:iterate collection=”<%= bookDB.getBooks() %>” VvPTL8Z  
2} T" |56  
id=”book” type=”database.BookDetails”> -Ol/r=/&  
aIm\tPbb  
$I tehy  
带body的tag标签 my*/MC^O  
WJg?R^  
一个自定义标签可以包含其它自定义标签、脚本变量、HTML标记或其它内容。 g@S"!9[;U  
G_X'd  
在下述例子中,此JSP页面使用了struts的logic:present标签,如果些标签定义了parameter=”Clear”的属性,则将清除购物车的内容,然后打印出一条信息: ci*Z9&eS+  
^c-1w V` /  
<logic:present parameter=”Clear”> v4 c_UFEh<  
XLzHm&;  
<% cart.clear(); %> ~A6QX8a  
0_%u(?  
<font color=”#ff0000” size=”+2”><strong> BGUP-_&  
Dpof~o,f  
你选择了清除购物车! T"dEa-O  
^Ji5)c  
</strong></font> ffSecoX  
Rr:,'cXGi  
</logic:present> //AS44^IS  
#5'9T:8  
!qy/'v4  
到底是用属性还是用body来传递信息? )WBTqML[  
:.Np7[~{  
如上所述,我们既可以通过属性,也可以通过body来传递信息。但一般来说,比较简单的类型,如字符串或简单表达式最好采用属性来传递信息。 'KXvn0  
,!Q2^R   
CM~)\prks  
定义脚本变量的tag标签 B'&%EW]  
Cj ykM])  
所谓脚本变量,是指JSP中可以调用的变量或对象。它可由tag标签产生。以下示例阐述了一个tag标签定义了一个名为tx的由JNDI所定义的事务处理对象。脚本变量可以是ejb对象、事务、数据库连接等等: [S*bN!t  
d7l0;yR&+  
<tt:lookup id=”tx” type=”UserTransaction” name=”java:comp/UserTransaction” /> PiM@iS  
r0hu?3u1?  
<% tx.begin(); %>  4INO .  
F7L+bv   
... :,:r  
{HQ?  
NPKRX Li%  
具有协作关系的tag标签 p+A#t~K  
[['un\~r~  
自定义tag标签之间可以通过共享对象来实现协作。在下述例子中,标签tag1创建了一个名为obj1的对象,在标签tag2仍可以重复使用obj。 s_VP(Fe@K  
;JDxl-~  
<tt:tag1 attr1=”obj1” value1=”value” /> MT|}[|_  
9r8*'.K`Z  
<tt:tag2 attr1=”obj1” /> Q7f\ 5QjT  
A-4\;[P\  
在以下这个例子当中,如果外层的tag标签创建了一个对象,那么其内层的所有tag标签都可以使用这个对象。由于这样产生的对象没有一个指定的名字,那么就可以将少重名的冲突。这个例子阐述了一系列协作的嵌套对象。 q*-q5FE  
LiiQ;x  
<tt:outerTag> 347p2sK>  
4WDh8U  
<tt:innerTag /> nV GrW#'E  
3C2L _ K3  
</tt:outerTag> llI`"a  
`2U zJ~  
.3!=]=  
Tag处理类 a B%DIH,  
rT5dv3^MW!  
7pmhH%Dn$  
Tag处理类必须实现Tag接口或BodyTag接口,不过现在一般都流行从TagSupport或BodyTagSupport类中继承,这些类或接口都可以在javax.servlet.jsp.tagext包中找到。 vB KBMnSd  
>8HcCG  
当JSP引擎看到自己的JSP页面中包含有tag标签时,它会调用doStartTag方法来处理tag标签的开头,调用doEndTag方法来处理tag标签的结束。 - x@mS2  
IU/dY`J1  
下表说明不同类型的tag所需要不同的处理过程: vJ }^ p }  
BEN=/ v  
Tag处理类的方法 hcwKi  
WOR~tS  
Tag标签类型 V% psaT=)P  
所调用的方法 *N<~"D  
hb zU?_}  
基本标签 ;#cb%e3  
doStartTag, doEndTag, release ZB<goEg  
WHMt$W}%  
带属性的标签 KK}^E_v  
doStartTag, doEndTag, set/getAttribute1...N, release i5q VQo  
wjQu3 ,Cj  
带内容的标签 hH|3s-o  
doStartTag, doEndTag, release j:\MrYt0H  
9:IVSD&"Rf  
带内容的标签,且内容重复循环 GnkNoaU  
doStartTag, doAfterBody, doEndTag, release jL>IX`,+6  
8?h-H #h  
带内容的标签,且内容与JSP交互 +P81&CaY  
doStartTag, doEndTag, release, doInitBody, doAfterBody, release Hh4$Qr;R  
`(.K|l}  
一个tag处理类可以通过javax.servlet.jsp.PageContext来与JSP交互,通过javax.servlet.jsp.PageContext类,tag处理类可以访问JSP中的request、session和application对像。 Y6 &w0~?!  
oaM $<  
如果tag标签是互相嵌套的,那内层的tag处理类可以通过它的parent属性来访问上层的tag处理类。 zT*EpIa+LS  
vc5g 4ud  
一般情况都将所有的tag处理类打成了JAR的包,以便于发布。 O| ) [j@7  
VW$Hzx_z  
, 0MDkXb  
Tag库描述(简称TLD) IXe[JL:  
j"9bt GX  
uL\ B[<:  
Tag库是用xml语言描述的,TLD包括了tag库中所有tag标签的描述,它一般用来被jsp服务器用来校验tag的语法正确性,或者被jsp开发者用来开发新的标签。 r|:i: ii  
SBg BZm}%  
TLD的文件扩展名必须为.tld,而且必须放在当前WEB应用的WEB-INF目录或其子目录中。 3g`uLA X>u  
D:/^TEib  
一个TLD的内容的开头必须遵守标准的XML开头,用于描述DTD和xml的版本,例如: I|@%|sTW  
>/Gz*.  
<?xml version="1.0" encoding="ISO-8859-1" ?> db'Jl^  
M6[&od  
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd"> &2d^=fih  
TLD必须以<taglib>来作为它的根元素,<taglib>的子元素如下表: K}L-$B*i  
bb`GV  
|^[]Oy=  
<taglib>的子元素 # 4L[8(+V  
yn)K1f^  
Element L Me{5H  
Description z}&?^YU*)`  
nm_]2z O  
tlib-version $0~H~ -  
Tag库的版本 xlZ"F  
?4P*,c  
jsp-version  pQKR  
Tag库所需要的jsp的版本 yIC8Rl  
@7e h/|Y,  
short-name Ep>3%{V  
助记符,tag的一个别名(可选) s{4|eYR  
]v{f!r=}  
uri ;!v2kVuS]  
用于确定一个唯一的tag库 D pI)qg#>V  
n*D-01v YP  
display-name AK]{^Hvz  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) ) wtVFG  
ELZCrh6*  
small-icon 3Un q 9  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) J\^ZRu_K  
<C`qJP-  
large-icon ^1sX22k  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) lTBPq?4{  
$vlq]6V8  
description PGF=q|j9K  
对tag库的描述(可选)  \09eH[  
_~ZNX+4  
listener rXPq'k'h#-  
参见下面listener元素 w7 @fiH{  
 G?AZ%Yx  
tag ze@NqCF  
参见下面tag 元素 aVNBF`  
DK;p6_tT  
Listener元素 {4SwCN /  
{7.."@Ob<v  
一个tag库可能定义一些类做为它的事件侦听类,这些类在TLD中被称为listener 元素,jsp服务器将会实例化这些侦听类,并且注册它们。Listener元素中有一个叫listener-class的子元素,这个元素的值必须是该侦听类的完整类名。 ;[V_w/-u  
~8L*N>Y  
Tag元素 osPJ%I`^  
G0 Q} 1  
每个tag元素在tag库中都要指出它的名字、类名、脚本变量、tag的属性。其中脚本变量的值可以直接在TLD中定义或通过tag附加信息的类来取得。每个属性描述了这个属性是否可以省略,它的值是否可以通过<%= …%>这样的JSP语法来获得,以及属性的类型。 aw&:$twbM  
:8\!;!  
每一个tag在TLD中对应一个tag元素,下表是tag元素的子元素: ,K'>s<}  
VJmX@zX9  
Tag元素的子元素 YNyaz\L  
ZG:#r\a  
元素名称 |\;oFuCv##  
描述 +[C dd{2  
/`McKYIP  
name K<TVp;N  
独一无二的元素名 eM Ym@~4  
Y /$`vgqs  
tag-class g`I`q3EF)  
Tag标签对应的tag处理类 6 2GP1qH9  
"Ah (EZAR  
tei-class l$N b1&  
javax.servlet.jsp.tagext.TagExtraInfo的子类,用于表达脚本变量(可选) #-*7<wN   
sLrSi  
body-content o!!";q%DX  
Tag标签body的类型 *5?a% p  
t\Pn67t  
display-name nm5zX,  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) x(pq!+~K  
c@;$6WSG^  
small-icon ilJeI@  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) 8|*#r[x  
Z^5j.d{e$  
large-icon k`FCyO  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) feU]a5%XZ  
QFt7L  
description 4gbi?UAmX  
此tag标签的描述 9c9F C  
BNns#Q8a  
variable *W aL}i(P1  
提供脚本变量的信息(同tei-class)(可选) GO0Spf_Gh  
kzU;24"K  
attribute U'(}emh}  
Tag标签的属性名 `7_=2C  
=.NZ {G  
以下章节介绍对于不同类型的tag,如何具体地实现它们。 Au3> =x`  
x}o]R  
l}odW  
简单的tag |:yQOq|  
k.=67L  
Hbwjs?Vq?]  
tag处理类 q,6 y{RyS  
-wv5c  
简单的tag处理类必须实现Tag接口的doStartTag和doEndTag方法。当jsp引擎碰到tag标签的开头时,doStartTag被调用,因为简单的tag没有body,所以此方法将返回 SKIP_BODY。当jsp引擎碰到tag标签的结尾时,doEndTag被调用,如果余下的页面还要被计算,那它将返回EVAL_PAGE,否则将会返回SKIP_PAGE。 7.g)_W{7}  
2ED^uc: 0S  
以下是例子:对于标签 <tt:simple /> ,它的tag处理类实现如下: gSLwpIK%  
5dOA^P@`,M  
hpp>+=  
public SimpleTag extends TagSupport Xb +)@Y4h  
*%< Ku&C  
{ YF/@]6j  
BMPLL2I  
public int doStartTag() throws JspException cfI5KLG~#  
6!P];3&o\A  
{ ^@f%A<  
0w^\sf%s  
try{ 3S='/^l  
w}n:_e  
pageContext.getOut().print(“Hello.”); @gzm4  
3l5rUjRwj  
}catch(Exception e){ kB_uU !G  
] =ar&1}J  
throw new JspTagException(“SimpleTag: “ + e.getMessage()); gNk x]bm  
Y^5X>  
} c*MSd  
" a;z  
return SKIP_BODY; R7aS{8nn  
"j|}-a  
} b(&~f@% |  
+LddW0h+=8  
public int doEndTag() #:Z"V8n'  
K^z-G=|N  
{ qT]Bl+h2  
iw1((&^)"  
return EVAL_PAGE; Yc;cf% c1  
#k? Rl  
} _Y F~DU  
^pz3L'4n  
} T8Sgu6:*R  
,])@?TJb@  
J]uYXsC  
注意:如果tag标签没有内容的话,那必须定义body-content元素为空,例如 9D74/3b*  
^aVoH/q*C  
<body-content>empty</body-content> 'G z>X :  
mY"DYYR>  
pKK&+umg  
带属性的tag标签
评价一下你浏览此帖子的感受

精彩

感动

搞笑

开心

愤怒

无聊

灌水
级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
只看该作者 1 发表于: 2007-01-01
tag处理类 5vIuH+0  
0^44${bA  
对于tag标签的每个属性,你必须依照JavaBeans规范来定义其属性,以及get和set方法。以struts的logic:present 标签为例, 3}O.B r|  
g3{)AX[Uy  
<logic:present parameter=”Clear”> e #l/jFJU  
rN? L8  
与此相应,此tag处理类应有如下方法和定义: -F,o@5W>Y  
U,/NygB~  
R`=IYnoOA  
protected String parameter = null; ^5vFF@to  
)CS 7>Vx  
public String getParameter() h`&@>uEiq  
N^|r.J  
{ U@[P.y~J  
6$wS7Cu  
return this.parameter; ko!38BH`/  
n`f},.NM|  
} s%]-Sw9  
z.23i^Q  
public void setParameter(String parameter) tF)K$!GR[  
Lc^nNUzPo  
{ ( _]{[dFr%  
IBl}.o&]B#  
this.parameter = parameter; R7T"fN  
%kD WUJZ  
} AF D/ J  
Z91gAy^z<  
FM9b0qE  
注意:如果你的属性名为id,而且你的tag处理类是从TagSupport类继承的,那你就不需要定义它的属性和set和get方法,因为他们早已在TagSupport被定义过了。 W#'c6Hq2c  
xMg&>}5  
Attribute元素 MnFem $ @  
b0LjNO@<  
对于tag标签的每个属性,你必须定义它是否必须的,它的值是否可以用诸如<%= …%>的表达式来获得,以及它的类型(可选),如果不指定它的类型,那就默认为是java.lang.String类型。如果rtexprvalue元素被定义为true或yes,那么在type元素中就定义了attribute的返回类型。 FsZM_0>/s  
4s*P5w_'/  
<attribute> rPK?p J  
GN{\ccej  
<name>attr1</name> _%l+v  
pPCxa#OV  
<required>true|false|yes|no</required> $V?zJ:a>L  
eG # (9  
<rtexprvalue>true|false|yes|no</rtexprvalue> d%9I*Qo0,  
sAk~`(:4!  
<type>attribute的返回类型(只用当rtexprvalue为真是才有效)</type> S|;a=K&hS  
_5M!ec  
</attribute> Ed #%F-1sX  
EH3jzE3N  
如果tag的某个属性不是必须的,那tag处理类会自动提供一个缺省值。 g2C-)*'{yh  
`ZN@L<I6  
例如,在logic:present这个tag标签中定义了一个属性叫parameter,但它不是必须的,而且它可以被诸如<%= …%>的表达式来赋值。 =Z/'|;Vd_x  
+YT/od1t7  
<tag> hX)r%v:  
-a3+C,I8g  
<name>present</name> fh$U"  
/@FB;`'  
<tag-class>org.apache.struts.taglib.logic.PresentTag</tag-class> 5`oor86  
W_8 FzXA  
<body-content>JSP</body-content> 05*_h0}  
'DsfKR^ s  
&0f7>.y  
[k-7Kq  
<attribute> 8q7KqYu  
<t]c'  
<name>parameter</name> EBzg<-?o  
bXq,iX  
<required>false</required> 2 T{PIJg3  
\, n'D  
<rtexprvalue>true</rtexprvalue> BO[Q"g$Kon  
X_s;j5ur  
</attribute> #CV(F$\1{  
2)RW*Qu;+  
e_]1e 7t  
i )3Y\ u  
</tag> 4)2*|w  
Ms1\J2  
1sc #!^Oo  
属性元素的校验 HT?`PG  
g/z9bOgIX  
8f^URN<x  
有关于tag标签的有效值可以从tag库的说明文档中获得,当JSP页面被编译时,jsp引擎会强制性地参照TLD中定义的规则进行检查。 C==tJog[  
3Un/-4uL  
还有一个方法也可以进行属性元素的校验,就是先继承类TagExtraInfo,然后调用它的isValid方法。这个类同时也起到提供tag中定义的脚本变量信息的作用。 F]yclXf('  
r\],5x'xSu  
IsValid方法通过TagData对象来传递属性信息,它包括着tag的所有的属性名-值的信息。由于校验发生在运行时刻,因此这个属性的值将被赋值为TagData.REQUEST_TIME_VALUE。 ~R)w 9uq  
@{I55EQ]  
例如tag标签<tt:twa attr1=”value1” />在TLD中定义如下: "G6d'xkP  
idO3/>R [  
<attribute> G&C)`};  
?2EzNNcS  
<name>attr1</name> GU&XK7L  
I4|p;\`fK  
<required>true</required> cIM5;"gLP  
vp mSzh  
<rtexprvalue>true</rtexprvalue> 7C2/^x P  
Qg 6m  
</attribute> WtRy~5A2  
$<s@S;Ri  
5jNBt>.0  
这个定义说明了attr1能在运行期间被赋值。 t 1C{  
1b|<   
以下的isValid方法检查attr1属性的值是否属于Boolean类型。注意由于attr1能在运行刻被赋值,那么isValid方法必须检查tag用户是否对此tag进行了运行时刻赋值。 #s yP=  
HqYaQ~Dth  
y_$^Po  
Public class TwaTEI extends TagExtraInfo G#@<bg3  
;k/0N~  
{ P\zi:]h[Gh  
n+uq|sYVa  
public boolean isValid(Tagdata data) _IlL'c5  
(OG@]|-  
{ /-|xxy  
$ @1&G~x  
Object o = data.getAttribute(“attr1”); `SW`d<+L  
eHnC^W}|s  
If(o != null && o != TagData.REQUEST_TIME_VALUE) MeplM$9  
{{EQM +  
{ q6_1`Ew  
gu:..'V  
if( ( (String)o).toLowerCase().equals(“true”) || ;'o>6I7Ph  
?N|PgNu X  
((String)o).toLowerCase().equals(“false”) ) @XIwp2A{+  
'.kbXw0}  
return true; yp*kMC,3  
?,%N?  
else HYg _{  
xD1wHp!+  
return false; HKxrBQr78  
UVI=&y]c,p  
} n,HWVo>([  
~{NDtB)  
else fZ %ZV  
HPCA,*YR`  
return true; _v $mGZpGY  
W\KZFrV@  
} @ics  
Sr+1.77}  
} =)I{KT:y  
O/-OW: 03  
+M.|D,wg2  
带body的tag rW6w1  
*v5y]E%aW  
a9qZI  
tag处理类 g)p[A 4  
=G72`]#-  
cxv) LOl-  
如果tag标签含有内容,那处理方式会略微有些不同,而且还要视tag处理类是否要与body交互的情况而定。如果要与body交互,那我们认为tag处理类要可能要对body进行操作。 Hd2_Cg FB  
s~63JDy"E  
Tag处理类不与body交互 5rcno.~QO  
92tb`'  
如果tag处理类不与body交互,tag处理类应该实现Tag接口或从TagSupport中派生,如果body要被计算,那么doStartTag方法应返回 EVAL_BODY_INCLUDE,否则应返回SKIP_BODY。 [R:O'AP}@}  
ix/uV)]k`  
如果tag处理类要对body反复运算,则它应该实现IterationTag或从TagSupport中派生。如果tag处理类认为body还未计算完的话,那它的doStartTag方法和doAfterBody方法必须返回EVAL_BODY_AGAIN。 Z'j<wRf  
B"B  
Tag处理类与body交互 ^|\?vA  
&WRoNc  
如果tag处理类与body交互,那tag处理类应实现BodyTag接口或从BodyTagSupport中派生。这种tag处理类一般要实现doInitBody和doAfterBody方法。 ,}|V'y  
?<}qx`+%Q  
Body允许一些方法来读写它的内容。Tag处理类可以调用body内容的getString或getReader方法来从body中提取信息,也可用 writeOut(out) 方法来将body的内容写入到out对象中。其中out对象通过tag处理类的getPreviousOut方法来获得。 .ZJh-cd  
e| l?NXRX  
如果body的内容需要被计算,那么doStartTag方法必须返回EVAL_BODY_BUFFERED,否则,它将返回 SKIP_BODY。 2'}2r ~6  
=VSieh  
doInitBody 方法 {Y/  
02+^rqIx5  
此方法在body内容已经设好,但未被计算之前被调用。你可以根据不同的body内容来制定初始化策略。 r-0 7!A  
1%:A9%O)t  
doAfterBody方法 gSv<.fD"  
]E3g8?L  
此方法在body内容已被计算后进行调用。 pKJ[e@E^  
SwL\=nq+~  
和doStartTag方法一样,doAfterBody方法返回一个指示符指示是否要继续计算body,如果要继续计算,则doAfterBody应返回EVAL_BODY_BUFFERED,否则,它应返回SKIP_BODY。 EXi+pm  
q_K1L  
release 方法 ujSzm=_P  
 _HL3XT  
tag处理类调用此方法将它的状态重置为初始状态,并释放所有的私有资源。 [&4y@  
tw(2V$J  
ZEMo`O  
以下的例子读取body的内容(其中含有一条sql语句),然后将它传递给一个对象,让它进行查询。由于此处body不须重新计算,所以doAfterBody会返回SKIP_BODY。 ?@,:\ ,G  
z&:[.B   
u,]yd*  
Public class QueryTag extends BodyTagSupport df)1} /*L  
g bh:Y}_FU  
{ $R5-JvJJH  
~iSW^mi  
public int doAfterBody() throws JspTagException axl?t|~I  
+Q9HsfX/  
{ ?=G H{ %E  
[/kO >  
BodyContent bc = getBodyContent(); 3_>1j  
7/yd@#$X  
//将body的内容以字符串的格式提取出来 sd6Wmmo  
#}Cwn$  
String query = bc.getString(); 0t&H1xsxX  
sg y  
//清除body kO#`m ]  
)}aF=%  
bc.clearBody(); K_xOY *  
h ^c'L=dR  
try{ Qi}LV"&L  
][mc^eI0s|  
Statement stmt = connection.createStatement(); ?|/}~ nj7  
f:SF&t*  
Result result = stmt.executeQuery(query); }:irjeI,  
|)_R bqZ  
}catch(SQLException e){ %xruPWT:k  
&Y>u2OZ  
throw new JspTagException(“queryTag: “ + e.getMessage() ); +OmSR*fA0  
ig,|3(  
return SKIP_BODY; vOS0E^  
g=(+oK?  
} `iI"rlc  
nX S%>1o,  
} 525 >=h  
+NY4j-O  
]3,0 8JW=  
body-content元素 )X/Faje  
*X #e  
ZL>V9UWN  
由于tag可能会有body,你必须用body-content元素来指定body内容的类型: P(;c`   
,W-0qN&%/  
<body-content>JSP|tagdependent</body-content> X3nhqQTZ  
g2]-Q.  
O /&%`&2  
如果body的内容是定制的或内部的tag、脚本元素、或HTML广本,则归类为JSP类型。其他的类型,比如上面代码所述的?D?D将sql statement类传给 query tag的这种类型应该标为tagdependent。 a< EC]-nw  
Uu+C<j&-  
注意:实际上body-content的值并不影响tag处理类对body内容的处理,它仅仅是被tag编辑工具用来描述此body的内容。 M&FuXG%  
|gz ,Ip{  
EHHxCq?  
用tags定义脚本变量 H^g<`XEgw  
C] w< &o  
1sjn_fPz  
tag处理类 U!5*V9T~ J  
(n/1 :'  
)8SP$  
tag处理类负责创建或设置页面中定义的脚本变量,用pageContext.setAttribute(name,value,scope)或pageContext.setAttribute(name,value)方法来实现。一般来说,tag处理类通过脚本变量的名称来获取它,脚本变量的名称一般可用get方法来获得。 < &2,G5XA  
= 1VH5pVr}  
如果脚本变量的值依赖于tag处理类中的上下文中某一对象,那它可用pageContext.getAttribute(name,scope)方法来找到那个对象。一般的处理过程是tag处理类先找到脚本变量,再对其进行处理,然后用pageContext.setAttribute(name,object)的方法来设置它的新值。 m{ fQL  
ar|[D7Xrq\  
对象的生存周期(scope)如下表: \gkajY-?  
yh:,[<q  
对象的生存周期表 cZ>W8{G  
L'Zud,JKg  
名字 3c3Z"JV  
可访问范围 3Y-v1.^j  
生存周期 nS4S[|w"  
E2IVR]C2^  
page q1Sm#_7  
当前页面 -#6*T,f0P(  
一直有效,除非页面向客户提交响应或重定向到一个新页面 )mdNvb[*n  
7 L\?  
request to 6Q90(  
当前页面或当前页面重定向到的页面 W<VHv"?V  
一直有效,除非页面向客户提交响应 BT3O_X`u  
@E2nF|N  
session ntV >m*^  
当前页面或在同一浏览器窗口中的页面 NO^t/(Z  
一直有效,除非关闭当前浏览器、超时、网络故障 J"rwWIxO*  
 uN 62>  
application %ZyPK,("  
整个web应用程序的所有请求 % eRwH >  
一直有效,除非发生网络故障、服务器故障 &|'6-wD.  
VWy:U#;+8  
提供关于脚本变量的信息 lg >AWTW[  
lM*O+k  
以下示例定义了一个名为“book”的脚本变量,用来访问程序中关于书的信息: 2H[a Y%1T  
=7fh1XnW  
<bean:define id=”book” name=”bookDB” property=”bookDetails” type=”database.BookDetails” /> "ru1;I  
(N|xDl &;  
<font color=”red” size=”+2” > &o@5%Rz2/  
]4mj 1g&C  
<%= messages.getString(“CartRemoved”) %> - >I{ :#  
I%919  
<strong><jsp:getProperty name=”book” property=”title” /></strong> 3 ?F@jEQk  
>-lL -%N_  
</font> H$amt^|zQ4  
X&.$/xaT  
当包含此tag的JSP页面被编译时,jsp引擎会自动生成关于此book的同步的代码(同步可以避免几个客户同时访问此book时造成的冲突),要生成同步代码,jsp引擎需要知道此脚本变量的如下信息: [!? ,TGM}^  
-/c1qLdQ  
· 脚本变量名称 j#P4Le[t  
X-#mv|3  
· 脚本变量所属的类 JK"uj%  
.oj"ru  
· 此脚本变量是否引用了一个新的或已存在的对象 43=-pyp  
?]D+H%3[$i  
· 此脚本变量的有效性 o%PoSZZ  
YwWTv  
有两种办法可以向jsp引擎提供关于脚本变量的信息:在TLD中定义variable子元素,或用tei-class子元素定义一个额外tag信息类。用variable最简单,但可能降低了一些灵活性。 }#*zjMOz  
Z'dI!8(Nf  
Variable元素 r/sRXM:3cZ  
Ko|xEz=  
Variable元素有如下子元素: OW}j4-~wL  
oy bzD  
· name-given ?D?D 给出的名字,是一个常量 ( L\G!pP.  
s4`*0_n  
· name-from-attribute?D?D 属性名,在编译时给出的属性名 |/=p  
n UCk0:{  
name-given或name-from-attribute两者必须选一,但以下子元素是可选的: YCBML!L  
S aet";pf`  
· variable-class?D?D变量的类型,缺省为java.lang.String。 h$ iyclX  
jQeE07g  
· declare?D?D此脚本变量是否引用了一个新对象,缺省为True。 B9)qv>m  
p]|ME  
· scope?D?D脚本变量的范围,缺省为NESTED。下表描述了scope的几种类型: ":#x\;  
w^E]N  
脚本变量的有效范围 GdeR#%z  
4*XP;`  
A|_%'8  
有效性 [I<'E LX  
方法 MQH8Q$5D  
O\F^@;] F6  
NESTED 0*IY%=i  
在tag标签的开始和结束之间 | ,l=v`/  
如果tag处理类实现BodyTag接口,则在doInitBody和doAfterBody中调用,否则在doStartTag中调用 sFM>gG  
n[:AV  
AT_BEGIN Q0uO49sg  
从tag标签的开始一直到页面结束 pD_eo6xX  
如果tag处理类实现BodyTag接口,则在doInitBody、doAfterBody和doEndTag中调用,否则在doStartTag和doEndTag中调用 |DPpp/  
_& Uo|T  
AT_END M(WOxZ8  
从tag标签的结束一直到页面结束 `(Q_ 65y  
在doEndTag中调用 9g5{3N3  
%%,hR'+|  
以struts为例,它的bean:define标签的实现遵循JSP1.1规范,此规范要求使用额外tag信息类来定义脚本变量。Variable元素是JSP1.2规范中加入的。以bean:define标签为例,你可以定义如下variable元素: '`~(Fkj  
`{Di*  
<tag> p9}c6{Wp  
|XA aKZA  
<variable> t2%@py*bU  
2X;0z$  
<name-from-attribute>id</name-from-attribute> y#Za|nt  
JS7}K)A2B6  
<variable-class>database.BookDetails</variable-class> ($ B ]9*  
;7^j-6  
<declare>true</declare> }Oh'YX#[  
(:bCOEZ  
<scope>AT_BEGIN</scope> *ez~~ Y  
'"fU2M<.  
</variable> nP{sCH 1  
Z=Y_;dS9  
</tag> q,,>:]f#  
A"<)(M+kG  
额外tag信息类 Iam-'S5  
ny_ kr`$42  
如果要定义一个额外tag信息类,你要继承javax.servlet.jsp.TagExtraInfo类。一个TagExtraInfo类必须实现getVariableInfo方法,此方法返回一个叫VariableInfo的数组类,它包括如下信息: {p*hNi)0  
yH"$t/cU"R  
· 变量名 i&'^9"Z)O  
vb.Y8[  
· 变量所属类名 CbH T #  
$h]Y<&('G  
· 此变量是否引用了一个新对象 uZ`d&CEh  
GgpQ]rw  
· 此变量的有效范围 sHPwW5j/o'  
0jJ28.kOp  
jsp引擎将一个名为data的参数传给getVariableInfo方法,data中包括tag标签中的所有“属性名?D?D属性值”对。它可以用来向VariableInfo对象提供脚本变量的名字和类名。 zTBi{KrZ  
wI]R+.  
以struts为例,它在bean:define标签中定义了一个名为DefineTei的额外tag信息类,用来向脚本变量提供信息。由于脚本变量的名称(book)和类名(database.BookDetails)是通过tag标签的属性来传递的,它们一般定义在VariableInfo的构建代码中,并且可用data.getAttributeString方法来得到这些信息。如果要允许book脚本变量能在从tag开始直到整个JSP页面结束的范围内都可用的话,那它的范围应设为AT_BEGIN。如下所示: k E#_Pc  
PxVI {:Uz  
;GgQ@s@  
public class DefineTei extends TagExtraInfo 2*FWIHyf  
D.&eM4MZ  
{ gQpD]p%k  
mA] 84zO  
public VariableInfo[] getVariableInfo(TagData data) +?5Uy*$  
z1SMQLk  
{ oB{}-[G  
"J[i=~(  
String type = data.getAttributeString(“type”); : ` 6$/DK  
id#k!*$7  
If( type == null) G0; EbJ/&  
WP@JrnxO\`  
type = “java.lang.Object”; < ;,S"e  
Th;gps%b  
return new VariableInfo[] { Z/6'kE{l  
K'{W9~9Lq  
new VariableInfo(data.getAttributeString(“id”), ! N"L`RWD  
g"dZB2`C  
type, \l=KWa3Q  
Q1ABnacR  
true, qJFgbq4-  
<GT>s  
VariableInfo.AT_BEGIN) cxP9n8CuT  
mb~=Xyk&  
}; z^a!C#IX  
ahi57r[  
} C@UJOB  
S `m- 5  
} JX\T {\m#  
;*g*DIR  
H6PXx  
注意:关于额外tag信息类的类名必须要在TLD中的tag标签下的tei-class子元素中定义。因此,DefineTei的tei-class中的定义看起来如下: !AD0 -fZ  
<tei-class> TA@tRGP>  
org.apache.struts.taglib.bean.DefineTagTei )(?UA$"  
</tei-class> H?=pWB  
'[=yfh   
X4P}aC  
具有协作关系的tag UU;-q_H6  
f?>-yMR|  
;oY(I7  
tag通过共享对象来进行协作,JSP技术支持2种方式的对象共享。 s7UhC.>'@  
JJ N(M*;  
第一种方法是使用pageContext对象进行对象的共享(可支持JSP页面和tag处理类之间的共享),如果在一个tag处理类中要调用由另一个tag处理类创建的对象,可调用pageContext.getAttribute(name, scope)方法。 e1 {t0f  
we H@S  
第二各方式的共享是对于tag之间有嵌套关系而言的,外层的tag所创建的对象对于内层的tag来说是可以共用的。这种形式的共享的好处是减少了可能存在的重名冲突。 A}#]g>L  
|?fW!y  
要访问一个嵌套tag创建的对象,tag处理类必须先找到此嵌套tag对象,可用TagSupport的静态方法 TagSupport.findAncestorWithClass(from, class)或TagSupport.getParent方法。前者在当不确定此tag是否为嵌套tag对象时使用。一旦它的父类被找到,它就能访问其所有动态或静态创建的对象。静态创建的对象是父类的成员,而动态创建的对象可能是父类的私有对象。诸如此类的对象可以用tag处理类的setValue方法来保存,用getValue方法来获得。 CNpe8M=/3  
=ve*g&  
下例阐述了以上两种共享对象的方法。在这个例子当中,一个查询tag检查一个名为connection的属性名是否在doStartTag中被设置。如果connection属性被设置,tag处理类从pageContext中得到这个connection对象。否则,此tag处理类先找到它的父tag处理类,然后从它的父tag处理类中找到connection对象。 .^W\OJ`G  
(Xr_ np @  
 ENYF0wW  
public class QueryTag extends BodyTagSupport /50g3?X,  
;5Wx$Yfx  
{ _86*.3fQG  
S-M)MCL  
private String connectionId; !}L~@[v,uL  
i>]<*w  
public int doStartTag() throws JspException x '=3&vc4  
P+;CE|J`X  
{ B.Zm$JZ:  
veX"CY`hn  
String cid = getConnection(); ^ =/?<C4  
6 <qwP?WN  
if(cid != null) sx[&4 k[  
%eutfM-?6  
{ 2<6`TA*m  
\&\_>X.,  
//存在一个connection id,使用它。 20.-;jK  
u6iU[5  
connection = (Connection) pageContext.getAttribute(cid); 56bud3CVs  
EZ%w=  
} *793H\  
T]Tdx.B  
else fd5ZaE#f  
H4 }%;m%  
{ l}Q"Nb)  
E VN-<=i^  
ConnectionTag ancestorTag = (ConnectionTag)findAncestorWithClass(this, j]!7BHC  
+&7[lsD*  
ConnectionTag.class); RVgPH<1X@e  
PkPDVv  
if(ancestorTag == null) ?u_gXz;A  
qLQ <1>u  
{ kvW|=  
BrlzN='j}  
throw new JspTagException(“一个没有connection属性的查询标签必须被一个connection标记嵌套。”); q3AJwELXw  
n*vTVt)dJ  
} H{\.g=01  
fr}1_0DDz  
connection = ancestorTag.getConnection(); ,?xLT2>J_  
)h>\05|T  
} Z>(r9 R3{  
i}/e}s<-6  
} -y&v9OC2-  
E ;BPN  
} sJ))<,e5I  
[K cki+  
V>b2b5QAH,  
'%zN  
此查询标签在JSP页面中的调用形式可以从以下2种定义中任选一种: W>5vRwx00  
,hpH!J'5f/  
[x2JFS#4  
<tt:connection id=”con01” ...> ... </tt:connection> ^CZCZ,v  
d5@X#3Hd  
<tt:query id=”balances” connection=”con01” > ADv^eJJ|  
j[ J 5y#  
SELECT account, balance FROM acct_table YG0PxZmi  
7|&e[@B  
where customer_num = <%= request.getCustno() %> X,C*qw@  
:]P~.PD5,  
</tt:query> YSR mt/  
!_CX2|  
Awu$g.  
S  ~@r  
]pW86L%  
<tt:connection ...> O1GDugZ  
'|vD/Qf=&  
<x:query id=”balances”> ~Cjz29|gp  
"w}-?:# j  
SELECT account, balance FROM acct_table X+=-f^)&  
Nls83 W  
where customer_num = <%= request.getCustno() %> 8YuJ8KC  
-PNi^ K_  
</x:query> QWrIa1.JC  
j$3rJA%rN  
</tt:connection> /@ y;iJk;  
si_W:mLF{a  
c |>=S)|  
与此同时,在TLD中必须指定connection属性为可选的,定义如下: 21r= = H$  
'3A+"k-}mh  
<tag> 2O eshkE  
K(<$.  
... 8zhBA9Y#~  
y }\r#"Z`  
<attribute> rRB~=J"  
\HAJ\9*w)  
<name>connection</name> sX+`wc  
T4mv%zzS  
<required>false</required> J,f/fPaf7  
z{ptm7  
</attribute> 7;&(}  
y|$R`P  
</tag>
描述
快速回复

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