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

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

级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
标准的JSP 标记可以调用JavaBeans组件或者执行客户的请求,这大大降低了JSP开发的复杂度和维护量。JSP技术也允许你自定义taglib,其实换句话说,taglib可以看成是对JSP标记的一种扩展,正如xml是对html的一种扩展一样。taglib通常定义在tag标签库中,这种标签库存放着你自己定义的tag标签。简而言之,如果使用taglib,那么你可以设计自己的JSP标记! abuh`H#  
H3z: ZTI  
一般来说,自定义tag标签主要用于操作隐藏对象、处理html提交表单、访问数据库或其它企业级的服务,诸如邮件和目录操作等等。自定义tag标签的使用者一般都是那些对java编程语言非常精通,而且对数据访问和企业级服务访问都非常熟悉的程序员,对于HTML设计者来说,使得他可以不去关注那些较复杂的商业逻辑,而将精力放在网页设计上。同时,它也将库开发者和库使用者进行合理分工,自定义tag标签将那些重复工作进行封装,从而大大提高了生产力,而且可以使得tag库可用于不同的项目中,完美地体现了软件复用的思想。 +9M^7/}H  
:0Bq^G"ge  
在这篇文章中,我们主要讨论: C6VLy x  
6c}h(TkB  
· 什么是自定义tag标签? @@R7p  
,BH@j%Jmy  
· 怎么使用tag标签? z6U\axO6  
APvDP?  
o 声明要使用的tag库 W<bGDh  
@P#N2:jwj  
o 找到与之对应的tag处理类 '}9x\3E  
hpHr\g  
o tag标签的类型 #*D)Q/k  
=b%MXT  
· 自定义tag标签 1a?!@g )  
O9G[j=U  
o tag处理类 }u\])I3  
VrHv)lUr  
o tag库描述 m}C>ti`VD  
ap.K=-H  
o tag标签示例 bLB:MW\%  
Jb0`42  
o 带属性的tag tRs [ YK  
p)jk>j B  
o 带body的tag _t iujP  
:y+2*lV  
o 定义了脚本变量的tag ]s]vZ  
RmI]1S_=  
o 具有协作关系的tag <lgYcdJ   
u8'Zl8 g  
· 自定义tag标签 xqeyD*s  
tClg*A;|B  
o 一个迭代tag的例子 lNy.g{2f<m  
;!=G   
o 一个模板tag库 UxbjA- U[  
6@Y_*4$|  
o tag处理类到底是怎样被调用的? VF&(8X\   
ojafy}  
@D.}\(  
什么是自定义的tag? lAS#874dE  
9Z|jxy  
一个自定义的tag标签是用户定义的一种JSP标记。当一个含有自定义的tag标签的JSP页面被jsp引擎编译成servlet时,tag标签被转化成了对一个称为tag处理类的对象进行的操作。于是当JSP页面被jsp引擎转化为servlet后,实际上tag标签被转化成为了对tag处理类的操作。 44gPCW,u  
cA2V2S)  
自定义tag标签有很多特色,诸如: - \ 5v^l  
s6H]J{1F  
· 可以在JSP页面中自定义tag标签的属性 RM]\+BK  
fFMlDg[];  
· 访问JSP页面中的所有对象 NokU) O;x  
`[z<4"Os   
· 可以动态地修改页面输出 KT_!d*  
SOs:]U-T3  
· 彼此这间可以相互通信。你可以先创建一个JavaBeans组件,然后在一个tag中调用此JavaBeans组件,同时可以在另一个tag中调用它。 v]'ztFA  
/'Ass(=6  
· tag允许相互嵌套,可以在一个JSP页面中完成一些复杂的交互。 7TgOK   
} K7#Q  
GD&uQ`Y5  
使用tag标签 .!Qki@  
Za/-i"U  
/@wg>&L]  
本节主要描述怎样在JSP页面中使用tag标签,以及tag标签的不同类型。 DjCqh-&L  
bZ?v-fn\D,  
要使用tag标签,JSP程序员必须做2件事: +M./@U*g  
c#XXp"7k2  
· 声明此tag标签的tag库 !-z'2B*:^  
9`T)@Uj2n  
· 实现此tag标签 HD@$t)mn  
+dWDxguE{w  
声明tag标签所在的tag库 Y4OPEo5o  
[/PR\'|  
如果要使用tag标签,则应用JSP的taglib指示符来指定其tag库(注意:taglib要在在使用此tag标签之前声明) HeK/7IAqp  
[/,)  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> 3oBtP<yG.  
$'0u|Xy`  
uri属性定义了唯一的标签库描述(以下简称TLD),它可以是直接是tld文件名或一个独一无二的名字。prefix是用来区别其它TLD中和本TLD中有重名的tag的一种手段。 %r<rcY  
NC8t) X7  
TLD必须以.tld作为扩展名,并且存放在当前应用的WEB-INF目录或其子目录下。你可以通过它的文件名直接引用它,也可以通过别的方式间接地引用它。 0m7Y>0wC6T  
S(o#K|)>  
以下taglib指示符直接引用一个TLD: 9?A)n4b;  
k o5@qNq  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> #Z}Rf k(~  
Bz_^~b7  
以下的taglib指示符通过一个逻辑名称间接地引用一个TLD: }Q)#[#e  
~t@cO.c  
<%@ taglib uri=”/tutorial-template” prefix=”tt” %> \6S7T$$ 1m  
Km%]1X7T6  
如果是间接引用TLD的话,那你必须还要在web.xml中定义此逻辑名称与tld文件之间的映射,具体做法是在web.xml中加入一个名为taglib的元素: P!~MZ+7#&  
GSY(  
<taglib> P]<4R:yb  
<m!h&_eg  
<taglib-uri>/tutorial-template</taglib-uri> tf =6\p  
T!-\@PB !  
<taglib-location> y>R=`A1b  
4qN{n#{+]  
/WEB-INF/tutorial-template.tld hv)x=e<  
00<cYy  
</taglib-location> HpR]q05d  
d4m=0G`  
</taglib> Hj'xAtx5  
_ftI*ni:<  
R]Vt Y7}i,  
实现此tag标签 z(o,m3@v  
O ~(pg  
!ds"9w  
为了实现tag标签,你有2种方法来存放tag处理类。一、让tag处理类以.class的方式存放于当前应用的WEB-INF/class子目录下,二、如果tag处理类是以JAR包的形式存在的话,那可以放在当前应用的WEB-INF/lib目录下,如果tag处理类要在多个应用中共享,那么它就应放在jsp服务器上的common/lib目录下,对于tomcat来说,就是tomcat/common/lib目录下。 5(Cl1Yse=r  
8a &:6Zuo  
Zvhsyz|  
tag标签类型 JBD7h5|Lc  
UN7EF/!Zz  
zUDg&-J3  
自定义的tag标签遵循XML语法。它有一个开始标记和一个结束标记,有的还有body(即文本节点): V@\gS"Tu  
Nw:GCf-L  
<tt:tag> \Lq h j  
Y}@&h!  
body  |$+3a  
ZkgV_<M|  
</tt:tag> G=)i{oC  
:fKl]XO  
<i<J^-W  
一个不带body的tag标签如下: :KH g&ZX7  
Q.bXM?V)  
<tt:tag /> A_n7w  
Pih tf4i  
!y#"l$"xK  
简单的tag标签 sD<a+Lw}x  
ZjT,pOSyb  
一个没有body和属性的tag标签如下: []x#iOnC&  
I\hh8abAp  
<tt:simple /> l_3`G-`2  
 ,t}vz 7  
s|@6S8E  
带属性的tag标签 -)s qc P  
KTK <gV9:  
(w&F/ynO:  
自定义标签可以有自己的属性。属性一般在开始标记中定义,语法为 attr=”value”。属性的作用相当于自定义标签的一个参数,它影响着tag处理类的行为。你可以在TLD中详细定义它。 Us%T;gW  
o-;E>N7t  
你可以用一个String常量给一个属性赋值,也可以通过表达式给它赋值,如<%= ...%>。以struts为例,它的logic:present标签就是用的String常量来给属性赋值: |HU@ >  
M\C"5%2Mu  
<loglic:present parameter = “Clear”> H!vax)%-\  
xE1 eT,  
而另一个标签logic:iterate是用表达式来给属性赋值: |yvQ[U~PQ  
&vHoRY  
<logci:iterate collection=”<%= bookDB.getBooks() %>” w|3z;-#Q;  
kTKq/G,Ft  
id=”book” type=”database.BookDetails”> 01[NX? qEa  
:Y-{Kn6`_  
z+x\(/  
带body的tag标签 2Fy>.*,?  
BW-`t-,E;  
一个自定义标签可以包含其它自定义标签、脚本变量、HTML标记或其它内容。 tv>>l%  
CF&NFSti^  
在下述例子中,此JSP页面使用了struts的logic:present标签,如果些标签定义了parameter=”Clear”的属性,则将清除购物车的内容,然后打印出一条信息: z|fmrwkN'$  
})uGRvz  
<logic:present parameter=”Clear”> 9s_vL9u  
:WQ^j!9'  
<% cart.clear(); %> ODZ5IO}v  
 0,r}o  
<font color=”#ff0000” size=”+2”><strong> tzZ63@cm  
J5*tJoCYS  
你选择了清除购物车! _a_7,bk5  
$ oTdfb  
</strong></font> & SiP\65N  
MRQ.`IoS  
</logic:present> -8'C\R|J+  
h1:aKm!  
|}2 3>l7  
到底是用属性还是用body来传递信息? v. %R}Pa  
ekI2icD  
如上所述,我们既可以通过属性,也可以通过body来传递信息。但一般来说,比较简单的类型,如字符串或简单表达式最好采用属性来传递信息。 A2^\q>_#  
jATI&oX  
 R=.4  
定义脚本变量的tag标签 S2n39 3  
yPM3a7-Bm  
所谓脚本变量,是指JSP中可以调用的变量或对象。它可由tag标签产生。以下示例阐述了一个tag标签定义了一个名为tx的由JNDI所定义的事务处理对象。脚本变量可以是ejb对象、事务、数据库连接等等: za#s/b$[  
"mX\&%i6\p  
<tt:lookup id=”tx” type=”UserTransaction” name=”java:comp/UserTransaction” /> ~SQ?BoCI[  
N03G>fZ  
<% tx.begin(); %> V7#Ffi  
6W@UJx}w5  
... '[J<=2&  
Tskq)NU  
u83J@nDQ  
具有协作关系的tag标签 P-`M  
Q=BZ N]g2  
自定义tag标签之间可以通过共享对象来实现协作。在下述例子中,标签tag1创建了一个名为obj1的对象,在标签tag2仍可以重复使用obj。 OQ8 bI=?[x  
m#ZO`W  
<tt:tag1 attr1=”obj1” value1=”value” /> U ?'vXa  
YRv&1!VLE  
<tt:tag2 attr1=”obj1” /> HN_d{ 3  
Tq NadHQ  
在以下这个例子当中,如果外层的tag标签创建了一个对象,那么其内层的所有tag标签都可以使用这个对象。由于这样产生的对象没有一个指定的名字,那么就可以将少重名的冲突。这个例子阐述了一系列协作的嵌套对象。 d\%WgH  
&P.4(1sC  
<tt:outerTag> wpN k+;  
GGe,fb<k  
<tt:innerTag /> ;?W|#*=R  
D*Ik7Pe  
</tt:outerTag> ?aC'.jH+  
y[>;]R7'  
f?oa"   
Tag处理类 ng:kA%! Q  
n$U#:aQE  
9 Yx]=n  
Tag处理类必须实现Tag接口或BodyTag接口,不过现在一般都流行从TagSupport或BodyTagSupport类中继承,这些类或接口都可以在javax.servlet.jsp.tagext包中找到。 ;WgJ<&33  
0~HKiH-  
当JSP引擎看到自己的JSP页面中包含有tag标签时,它会调用doStartTag方法来处理tag标签的开头,调用doEndTag方法来处理tag标签的结束。 KQcs3F@t  
u4.ngjJ  
下表说明不同类型的tag所需要不同的处理过程: *"WDb|PBb  
J\J?yo 6  
Tag处理类的方法 @)-sTgn  
a UxGzMZ  
Tag标签类型 Kh(ZU^{n  
所调用的方法 .U"8mP=&  
p>vn7;s2#  
基本标签 I96C i2)m  
doStartTag, doEndTag, release !h(|\" }  
Qhs/E`k4  
带属性的标签 I6j$X6u  
doStartTag, doEndTag, set/getAttribute1...N, release ,QC{3i~  
XGJj3-eW {  
带内容的标签 3k|oK'l  
doStartTag, doEndTag, release cUqke+!  
H_EB1"C;\  
带内容的标签,且内容重复循环 kxp) ;  
doStartTag, doAfterBody, doEndTag, release 0E?jW7yr  
YhbZ'SJ  
带内容的标签,且内容与JSP交互 \ W?R  
doStartTag, doEndTag, release, doInitBody, doAfterBody, release v.Q(v\KV5  
ZeUvyIG  
一个tag处理类可以通过javax.servlet.jsp.PageContext来与JSP交互,通过javax.servlet.jsp.PageContext类,tag处理类可以访问JSP中的request、session和application对像。 '7D,m H  
4%2~Wi8  
如果tag标签是互相嵌套的,那内层的tag处理类可以通过它的parent属性来访问上层的tag处理类。 !l|5z G  
baJxU:Y=p  
一般情况都将所有的tag处理类打成了JAR的包,以便于发布。 W3Dc r@Dy  
v$(lZa1  
9Q(+ZG=JkV  
Tag库描述(简称TLD) 5K^69mx  
Na$Is'F &p  
b8$gx:aJ>$  
Tag库是用xml语言描述的,TLD包括了tag库中所有tag标签的描述,它一般用来被jsp服务器用来校验tag的语法正确性,或者被jsp开发者用来开发新的标签。 CSGz3uC2D  
^Y u6w\QM  
TLD的文件扩展名必须为.tld,而且必须放在当前WEB应用的WEB-INF目录或其子目录中。 nt;haeJ  
@mE)|.f  
一个TLD的内容的开头必须遵守标准的XML开头,用于描述DTD和xml的版本,例如: af#pR&4}   
#Y0-BYa^  
<?xml version="1.0" encoding="ISO-8859-1" ?> %uJ<M-@r=u  
%)[+%57{  
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd"> Jg]'+>,J  
TLD必须以<taglib>来作为它的根元素,<taglib>的子元素如下表: o }3uo6GIB  
BBH0OiV=  
YoN*:jB<M  
<taglib>的子元素 =8r 0 (c  
%|^OOU}  
Element >ELlnE8  
Description 'xhcuVl  
c1$ngH0  
tlib-version 1z&Ly3  
Tag库的版本 6(]tYcC  
Q:|l`*.R  
jsp-version %FS$zOsgGK  
Tag库所需要的jsp的版本 Eo\UAc  
mNb ?*3\  
short-name TMs,j!w?I  
助记符,tag的一个别名(可选) Mva3+T  
O(tX8P Q5N  
uri W%.v.0   
用于确定一个唯一的tag库 L KCb_9  
U\veOQ;mW  
display-name rsF\JQk  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) J4"mK1N(  
-+7uy.@cS  
small-icon VtzI9CD  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) pM{nh00[  
Z.W66\8~}^  
large-icon s[K^9wz  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) RlqQ  
~by]xE1Eg  
description UOGuqV-  
对tag库的描述(可选) :l2g#* c  
1iX)d)(b  
listener Nru7(ag1~  
参见下面listener元素 G0`h%  
#l4)HV  
tag Kx. X7R  
参见下面tag 元素 f'<Q.Vh<  
Mmo6MZ^  
Listener元素 Q\GDrdA  
yfj K2  
一个tag库可能定义一些类做为它的事件侦听类,这些类在TLD中被称为listener 元素,jsp服务器将会实例化这些侦听类,并且注册它们。Listener元素中有一个叫listener-class的子元素,这个元素的值必须是该侦听类的完整类名。 &K43x&mFF  
uQ=^~K:Z~  
Tag元素 ]c<qM_HWg  
ew;ur?  
每个tag元素在tag库中都要指出它的名字、类名、脚本变量、tag的属性。其中脚本变量的值可以直接在TLD中定义或通过tag附加信息的类来取得。每个属性描述了这个属性是否可以省略,它的值是否可以通过<%= …%>这样的JSP语法来获得,以及属性的类型。 ]J* ,g,  
\S*$UE]uG  
每一个tag在TLD中对应一个tag元素,下表是tag元素的子元素: cFN'bftH4  
|\dZ'   
Tag元素的子元素 4-kZJ\]  
!IC-)C,q  
元素名称 v?0r`<Mn  
描述 &-czStQ  
[U@ *1  
name /erN;Oo%<  
独一无二的元素名 Dy]I8_  
>6~k9>nDb<  
tag-class ?9HhG?_x  
Tag标签对应的tag处理类 RP 2_l$  
WpS1a440  
tei-class ^A][)*SZ  
javax.servlet.jsp.tagext.TagExtraInfo的子类,用于表达脚本变量(可选) YXU|h  
$B#6tk~u  
body-content b1gaj"]  
Tag标签body的类型 \.f}W_OF  
G/d4f?RU  
display-name 7_wJpTz  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) T"p(]@Ng  
?\U!huu  
small-icon yJsH=5A  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) &f>eQ S=(  
Gy,u^lkk:  
large-icon j7MO'RX`&  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) Xt{*N-v\  
-UZ@G~K  
description ]&ixhW  
此tag标签的描述 4D$;KokZ  
g|Y] wd  
variable Q\Gq|e*  
提供脚本变量的信息(同tei-class)(可选) 9Ew7A(BG_3  
B-*E:O0y  
attribute SVa6V}"Iv  
Tag标签的属性名 FZ|CqD"#  
.}k(L4T|=  
以下章节介绍对于不同类型的tag,如何具体地实现它们。 \ A%eG&  
5tv<8~:K  
6CC&Z>  
简单的tag -ZW3  
.c^ ggy%  
l;"Ab?P\  
tag处理类 *9 Q^5;y  
[EY`am8[  
简单的tag处理类必须实现Tag接口的doStartTag和doEndTag方法。当jsp引擎碰到tag标签的开头时,doStartTag被调用,因为简单的tag没有body,所以此方法将返回 SKIP_BODY。当jsp引擎碰到tag标签的结尾时,doEndTag被调用,如果余下的页面还要被计算,那它将返回EVAL_PAGE,否则将会返回SKIP_PAGE。 nRb^<cZf  
c=[q(|+O!  
以下是例子:对于标签 <tt:simple /> ,它的tag处理类实现如下: [U8$HQ+x  
1z*kc)=JF8  
b?Pj< tA  
public SimpleTag extends TagSupport -h-oMqgu(  
,&7Wa-vf  
{ G\/"}B:(  
mmEp'E  
public int doStartTag() throws JspException Q}*y$se!  
]DvO:tM  
{ |2`"1gt  
H]\Zn%.#  
try{ 0rokR&Y-d  
9p@C4oen  
pageContext.getOut().print(“Hello.”); ?/M_~e.P  
m7=1%6FN3  
}catch(Exception e){ #FYAV%pi  
L{ho*^b  
throw new JspTagException(“SimpleTag: “ + e.getMessage()); ?$z.K>S5  
!r+IXuqV,!  
} S2C]?6cTq  
p T[gdhc  
return SKIP_BODY; K"<*a"1I  
JR9$. fGJ  
} (QB+%2v  
tZ2K$!/B  
public int doEndTag() 2 ?|gnbE:  
PzZZ>7_6S  
{ Y&*x4&Lb  
G",.,Px  
return EVAL_PAGE; K?u(1  
P2 0|RvE  
} k_GP> b\"k  
YCy22@C  
} PoShQR<  
J?n<ydZSH  
Zt@Z=r:&  
注意:如果tag标签没有内容的话,那必须定义body-content元素为空,例如 Gzt=u"FV  
E1Q0k5@  
<body-content>empty</body-content> e kQrW%\3  
BF8"rq}r0  
X6RQqen3:  
带属性的tag标签
评价一下你浏览此帖子的感受

精彩

感动

搞笑

开心

愤怒

无聊

灌水
级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
只看该作者 1 发表于: 2007-01-01
tag处理类 ~# 7wdP  
qJ8-9^E,L  
对于tag标签的每个属性,你必须依照JavaBeans规范来定义其属性,以及get和set方法。以struts的logic:present 标签为例, }Ia 0"J4  
H5nS%D  
<logic:present parameter=”Clear”> ^m7~:=K7WG  
3+YbA)i;  
与此相应,此tag处理类应有如下方法和定义: h ?#@~  
jB@4b 'y  
!rTmR@e$/  
protected String parameter = null; (:\LWJX0=  
G+"8l!dC?  
public String getParameter() ,#'7)M D8  
8*!|8 BPj^  
{ R[A5JQ$[  
[cU,!={  
return this.parameter; aW{L7N%  
EZ#gp^$  
} 8&}~'4[b[$  
xRDiRj  
public void setParameter(String parameter) &K:' #[3V  
#iis/6"  
{ m/USC'U%  
tLX,+P2|  
this.parameter = parameter; VRS 2cc  
's@MQ! *  
} FMu!z  
'M'w,sID  
d,'!.#e  
注意:如果你的属性名为id,而且你的tag处理类是从TagSupport类继承的,那你就不需要定义它的属性和set和get方法,因为他们早已在TagSupport被定义过了。 l+ T, 2sd  
s3lJu/Xe{  
Attribute元素 @?2n]n6  
WOndE=(V  
对于tag标签的每个属性,你必须定义它是否必须的,它的值是否可以用诸如<%= …%>的表达式来获得,以及它的类型(可选),如果不指定它的类型,那就默认为是java.lang.String类型。如果rtexprvalue元素被定义为true或yes,那么在type元素中就定义了attribute的返回类型。 RfbdBsL  
z] @W[MHY  
<attribute> G%w_CMfH  
izt^Wi|  
<name>attr1</name> 9NIy#  
& 5 <**  
<required>true|false|yes|no</required> rFXSO=P?Z  
{-*\w-~G  
<rtexprvalue>true|false|yes|no</rtexprvalue> c%<2z  
IUhp;iH  
<type>attribute的返回类型(只用当rtexprvalue为真是才有效)</type> (iDBhC;/B  
G8NRj9k?  
</attribute> 6 S*zzJ.0K  
zW'/2W.  
如果tag的某个属性不是必须的,那tag处理类会自动提供一个缺省值。 4DML  
b!~TAT&8  
例如,在logic:present这个tag标签中定义了一个属性叫parameter,但它不是必须的,而且它可以被诸如<%= …%>的表达式来赋值。  *q"G }  
-qn[HXq  
<tag> 5~\Kj#PBx  
N+>'J23d!  
<name>present</name> ,OBQv.D3>a  
t* z'c  
<tag-class>org.apache.struts.taglib.logic.PresentTag</tag-class> 5upShtC  
w yD%x(  
<body-content>JSP</body-content> I #l;~a<9z  
>_#)3K1y8  
g.*&BXZi  
{a4xF2  
<attribute> Pe,;MP\2  
#1l7FT?q  
<name>parameter</name> 5LMj!)3  
!V( `ZH  
<required>false</required> oYq,u@oM  
sQ(1/"gb  
<rtexprvalue>true</rtexprvalue> lS{4dvr?w  
lV7IHX1P  
</attribute> 4 ?2g&B\  
n2 na9dX)w  
[a D:A  
xT+ ;w[s  
</tag> Z}f^qc+  
C5B=NAc  
Dh8(HiXf:  
属性元素的校验 -M`D >  
CveWl$T12  
/Hk07:"c  
有关于tag标签的有效值可以从tag库的说明文档中获得,当JSP页面被编译时,jsp引擎会强制性地参照TLD中定义的规则进行检查。 ;E2kT GT  
XZBj=2~-3  
还有一个方法也可以进行属性元素的校验,就是先继承类TagExtraInfo,然后调用它的isValid方法。这个类同时也起到提供tag中定义的脚本变量信息的作用。 j&llrN  
AFtCqq#[  
IsValid方法通过TagData对象来传递属性信息,它包括着tag的所有的属性名-值的信息。由于校验发生在运行时刻,因此这个属性的值将被赋值为TagData.REQUEST_TIME_VALUE。 El1:?4;  
zPE#[\O21B  
例如tag标签<tt:twa attr1=”value1” />在TLD中定义如下: %Ht ^yemQ  
b7f0#*(?  
<attribute> 0Q*-g}wXfS  
.q0AoM  
<name>attr1</name> U$@83?O{iM  
Z]e4pR6!  
<required>true</required> ~GYpa t  
G* Ib^;$u  
<rtexprvalue>true</rtexprvalue> |)';CBb  
4d6% t2  
</attribute> ;:^ Lv  
1bDJ}M~]z  
\SzGzCJ  
这个定义说明了attr1能在运行期间被赋值。 t_Z _!Qy  
>~>{;Wq(p+  
以下的isValid方法检查attr1属性的值是否属于Boolean类型。注意由于attr1能在运行刻被赋值,那么isValid方法必须检查tag用户是否对此tag进行了运行时刻赋值。 dWIZ37w+D  
|3"NwM>  
$OT}`Te~  
Public class TwaTEI extends TagExtraInfo E.4n}s  
<q1'Li)_R  
{ k{qLkcOg=  
d"p2Kx'*3  
public boolean isValid(Tagdata data) @!-aR u  
mj,qQ=n;p  
{ tbRE/L<  
v?%0~!  
Object o = data.getAttribute(“attr1”); ?bn;{c;E  
CElPU`J,\[  
If(o != null && o != TagData.REQUEST_TIME_VALUE) xf[z EEt  
5@CpP-W#  
{ y 2cL2c$BT  
u& AQl.u  
if( ( (String)o).toLowerCase().equals(“true”) || qU}lGf!dVn  
hQP6@KIe)  
((String)o).toLowerCase().equals(“false”) ) o9~h%&  
`6n!$Cxo  
return true; D@}St:m}  
PGMv(}%;  
else % Mw'e/?  
T&mbXMN  
return false; e%'z=%(  
T^+1rG  
} q!9^#c  
@OBHAoz%/  
else J]$er0`LY  
)Xq@v']%~9  
return true; HgS<Vxmq  
65;|cmjv  
} 4LJ]l:m  
zuU Q."#i  
} A-X  
u~ Vs wXc4  
JO}#f+w}  
带body的tag f<) Ro$   
(0X,Qwx  
_+}-H'7=  
tag处理类 <!$dp9y.  
'MSEki67  
A8#.1uEgNb  
如果tag标签含有内容,那处理方式会略微有些不同,而且还要视tag处理类是否要与body交互的情况而定。如果要与body交互,那我们认为tag处理类要可能要对body进行操作。 /0Rt+`  
d?Ia#K9 3G  
Tag处理类不与body交互 s+(l7xH$  
%_]=i@Y~  
如果tag处理类不与body交互,tag处理类应该实现Tag接口或从TagSupport中派生,如果body要被计算,那么doStartTag方法应返回 EVAL_BODY_INCLUDE,否则应返回SKIP_BODY。 3$MYS^D  
YG-Z.{d5Z  
如果tag处理类要对body反复运算,则它应该实现IterationTag或从TagSupport中派生。如果tag处理类认为body还未计算完的话,那它的doStartTag方法和doAfterBody方法必须返回EVAL_BODY_AGAIN。 9"[!EKW  
wxH (&CB-{  
Tag处理类与body交互 -B<O_*wOj  
DN4fP-m-  
如果tag处理类与body交互,那tag处理类应实现BodyTag接口或从BodyTagSupport中派生。这种tag处理类一般要实现doInitBody和doAfterBody方法。 E~rs11  
:5$xh  
Body允许一些方法来读写它的内容。Tag处理类可以调用body内容的getString或getReader方法来从body中提取信息,也可用 writeOut(out) 方法来将body的内容写入到out对象中。其中out对象通过tag处理类的getPreviousOut方法来获得。 )[e%wPu4e  
ZTN:|IKT  
如果body的内容需要被计算,那么doStartTag方法必须返回EVAL_BODY_BUFFERED,否则,它将返回 SKIP_BODY。 W\nHX I  
lNq:JVJ#\r  
doInitBody 方法 Jslk  
Q x9>,e6+  
此方法在body内容已经设好,但未被计算之前被调用。你可以根据不同的body内容来制定初始化策略。 +3NlkN#  
./7&_9| <  
doAfterBody方法 }<6oFUZ  
T][-'0!  
此方法在body内容已被计算后进行调用。 "$`wk  
D2>hMc  
和doStartTag方法一样,doAfterBody方法返回一个指示符指示是否要继续计算body,如果要继续计算,则doAfterBody应返回EVAL_BODY_BUFFERED,否则,它应返回SKIP_BODY。 4.,KEt'H  
<K=@-4/Bp  
release 方法 Eqz4{\   
?|%\<h@;  
tag处理类调用此方法将它的状态重置为初始状态,并释放所有的私有资源。 TBoM{s=.  
<`oCz Q1  
+Q@/F~1@6@  
以下的例子读取body的内容(其中含有一条sql语句),然后将它传递给一个对象,让它进行查询。由于此处body不须重新计算,所以doAfterBody会返回SKIP_BODY。 EX+={U|ua$  
,\\%EZ%a  
2rPcNh9  
Public class QueryTag extends BodyTagSupport fcgDU *A%  
@Fm{6^  
{ i6meY$l  
N#<zEAB  
public int doAfterBody() throws JspTagException O;"*_Xq(`  
~rVKQ-+4&  
{ &4w\6IR  
V6DBKq  
BodyContent bc = getBodyContent(); XgwMppacw  
[u`17hyX  
//将body的内容以字符串的格式提取出来 o 2[vM$]  
z5|e\Z  
String query = bc.getString(); hLDch5J5~  
c+,7Zu!  
//清除body x>1iIpBv^  
aB$y+`f)@  
bc.clearBody(); ]Ssw32yn  
VJ~X#Q  
try{ \Owful  
nG4Uk2>  
Statement stmt = connection.createStatement(); yFPaWW  
8o8b'tW^  
Result result = stmt.executeQuery(query); b7W=HR  
`:-@E2  
}catch(SQLException e){ 3/A!_Uc(  
;~'cITL  
throw new JspTagException(“queryTag: “ + e.getMessage() ); 7- *( a  
}[=xe(4]D  
return SKIP_BODY; 'S%} ?#J  
[*Aqy76Qa  
} Yj^avO=;  
m>Yo 9/XpZ  
} 7d M6;`V^  
/ZIJ<#o[  
'[M^f+H|  
body-content元素 H|rX$P  
 uu WY4j6  
 K$37}S5  
由于tag可能会有body,你必须用body-content元素来指定body内容的类型: o+"0.B  
t?du+:  
<body-content>JSP|tagdependent</body-content> `wn<3#  
0i5T] )r  
a=:{{\1o  
如果body的内容是定制的或内部的tag、脚本元素、或HTML广本,则归类为JSP类型。其他的类型,比如上面代码所述的?D?D将sql statement类传给 query tag的这种类型应该标为tagdependent。 5v Uz  
|1<]o;:  
注意:实际上body-content的值并不影响tag处理类对body内容的处理,它仅仅是被tag编辑工具用来描述此body的内容。 xzMeKC `  
D^N#E>,  
BST7y4R)BS  
用tags定义脚本变量 +qh< Fj>  
!BvTJ-e)F  
,E/Y@sajn+  
tag处理类 r {/ G\  
JA SR  
ABq{<2iYN  
tag处理类负责创建或设置页面中定义的脚本变量,用pageContext.setAttribute(name,value,scope)或pageContext.setAttribute(name,value)方法来实现。一般来说,tag处理类通过脚本变量的名称来获取它,脚本变量的名称一般可用get方法来获得。 `\RX~ $^  
nyl8=F:V  
如果脚本变量的值依赖于tag处理类中的上下文中某一对象,那它可用pageContext.getAttribute(name,scope)方法来找到那个对象。一般的处理过程是tag处理类先找到脚本变量,再对其进行处理,然后用pageContext.setAttribute(name,object)的方法来设置它的新值。 3gPD(r1g  
E.H,1 {  
对象的生存周期(scope)如下表: .@8m\  
%X0NHta ~@  
对象的生存周期表 l~Ie#vak  
9A* ?E  
名字 Wd^F%)(  
可访问范围 Bah.\ZsYQP  
生存周期  ^ :  
[U3D`V$xD  
page MW",r;l<aM  
当前页面 XRz%KVysp  
一直有效,除非页面向客户提交响应或重定向到一个新页面 D_ Bx>G9  
O%fp;Y{`  
request |$SvD2^  
当前页面或当前页面重定向到的页面 |=^#d\?]j  
一直有效,除非页面向客户提交响应 *Sz{DE1U  
@ (u?=x;  
session },Y; (n'  
当前页面或在同一浏览器窗口中的页面 ~J. Fl[  
一直有效,除非关闭当前浏览器、超时、网络故障 Vk N[=0a,  
  Tk v  
application v]`A_)[  
整个web应用程序的所有请求 \:_.N8"  
一直有效,除非发生网络故障、服务器故障 Y#SmZ*zok  
fa+W9  
提供关于脚本变量的信息 C#**)  
;Xd\$)n  
以下示例定义了一个名为“book”的脚本变量,用来访问程序中关于书的信息: $)TF,-#x  
ExOB P  
<bean:define id=”book” name=”bookDB” property=”bookDetails” type=”database.BookDetails” /> ]"7DV3_  
4xAlaOw5M  
<font color=”red” size=”+2” > TOPPa?=vk  
F~Z 0  
<%= messages.getString(“CartRemoved”) %> "k6IV&0 3x  
picP_1L  
<strong><jsp:getProperty name=”book” property=”title” /></strong> $*v20  
!6tC[W`  
</font> 8SCW.;0  
~0^,L3M  
当包含此tag的JSP页面被编译时,jsp引擎会自动生成关于此book的同步的代码(同步可以避免几个客户同时访问此book时造成的冲突),要生成同步代码,jsp引擎需要知道此脚本变量的如下信息: LA=>g/+i.X  
|IcxegE  
· 脚本变量名称 ev: !,}]w  
,~j$rs`Z  
· 脚本变量所属的类 Q~w G(0'8  
1$!RKqT  
· 此脚本变量是否引用了一个新的或已存在的对象 #Z=)=  
n;k97>m${x  
· 此脚本变量的有效性 9+is?Pj  
wx"6",M  
有两种办法可以向jsp引擎提供关于脚本变量的信息:在TLD中定义variable子元素,或用tei-class子元素定义一个额外tag信息类。用variable最简单,但可能降低了一些灵活性。 Rvz.ym:F  
]6VUqFO)  
Variable元素 t0V_ c'm  
}DUDA%U  
Variable元素有如下子元素: j]?0}Z*  
*liPJ29C[  
· name-given ?D?D 给出的名字,是一个常量 AINFua4A  
M(h H#_ $  
· name-from-attribute?D?D 属性名,在编译时给出的属性名 J2 rLsNC]0  
=<'iLQb1  
name-given或name-from-attribute两者必须选一,但以下子元素是可选的: Kf?{GNE7  
F;Xq:e8  
· variable-class?D?D变量的类型,缺省为java.lang.String。 6P*)rye  
+|"n4iZ!)  
· declare?D?D此脚本变量是否引用了一个新对象,缺省为True。 B]KLn?zt5  
eRx[&-c  
· scope?D?D脚本变量的范围,缺省为NESTED。下表描述了scope的几种类型: $W_o$'crW  
)p^jsv.  
脚本变量的有效范围 /XW0`FF  
W];6u  
!VJa$>,  
有效性 x"wM_hl5L  
方法 \lbiz4^>  
\IZ4( Z  
NESTED Tvx8l m '  
在tag标签的开始和结束之间 (&]15 FJ$1  
如果tag处理类实现BodyTag接口,则在doInitBody和doAfterBody中调用,否则在doStartTag中调用 &G,o guo  
6 % y)  
AT_BEGIN NdSxWrD`m  
从tag标签的开始一直到页面结束 '5,,XhP  
如果tag处理类实现BodyTag接口,则在doInitBody、doAfterBody和doEndTag中调用,否则在doStartTag和doEndTag中调用 {kRC!}  
e "adkV  
AT_END Z8dN0AqZ  
从tag标签的结束一直到页面结束 y0&HXX#\  
在doEndTag中调用 ] xLb )Z  
>scS wT  
以struts为例,它的bean:define标签的实现遵循JSP1.1规范,此规范要求使用额外tag信息类来定义脚本变量。Variable元素是JSP1.2规范中加入的。以bean:define标签为例,你可以定义如下variable元素: N evvA(M  
XsN#<"f;i  
<tag> ccRk4xR  
4%v+ark8  
<variable> ,WDAcQ8\  
muX4Y1M_  
<name-from-attribute>id</name-from-attribute> 5WJkeG ba  
pvR& ~g  
<variable-class>database.BookDetails</variable-class> bSmaE7  
}NBJ T4R  
<declare>true</declare> iCSM1W3  
YTPmS\ H _  
<scope>AT_BEGIN</scope> B*iz+"H  
Isgk  
</variable> *pC -`k  
Q|<?$.FN"8  
</tag> VaI P  
` dUiz5o'  
额外tag信息类 S 2 h  
;Kq?*H  
如果要定义一个额外tag信息类,你要继承javax.servlet.jsp.TagExtraInfo类。一个TagExtraInfo类必须实现getVariableInfo方法,此方法返回一个叫VariableInfo的数组类,它包括如下信息: DPxu3,Y  
BG8)bh k;/  
· 变量名 0o=)&%G  
,0~ {nQj]  
· 变量所属类名 8B t-  
fh)`kZDk  
· 此变量是否引用了一个新对象 n03SX aU~V  
g5|\G%dOt  
· 此变量的有效范围 #DRt Mrfat  
2P=~3g*  
jsp引擎将一个名为data的参数传给getVariableInfo方法,data中包括tag标签中的所有“属性名?D?D属性值”对。它可以用来向VariableInfo对象提供脚本变量的名字和类名。 Iy4M MU  
WblV`"~e  
以struts为例,它在bean:define标签中定义了一个名为DefineTei的额外tag信息类,用来向脚本变量提供信息。由于脚本变量的名称(book)和类名(database.BookDetails)是通过tag标签的属性来传递的,它们一般定义在VariableInfo的构建代码中,并且可用data.getAttributeString方法来得到这些信息。如果要允许book脚本变量能在从tag开始直到整个JSP页面结束的范围内都可用的话,那它的范围应设为AT_BEGIN。如下所示: FC(cXPX}  
ZznWs+  
RH4n0 =2  
public class DefineTei extends TagExtraInfo "l,EcZRjTz  
Lm{ o=v  
{ 99>yaW  
t RyGxqiG  
public VariableInfo[] getVariableInfo(TagData data) *Z2Q]?:{ i  
nkj'AH"2  
{ 842+KLS  
2b,TkG8K  
String type = data.getAttributeString(“type”); @Be:+01z  
%R"/`N9R,  
If( type == null) yaYt/?|  
>`|uc  
type = “java.lang.Object”; &2]D+aL|h  
S^VV^O5 ^  
return new VariableInfo[] { a[cH@7W.#  
&8i{'k,l  
new VariableInfo(data.getAttributeString(“id”), 9qy 9  
}o:sx/=u_  
type, N,,2 VSUr  
^k<$N  
true, =<h=">}5'  
QGj5\{E_  
VariableInfo.AT_BEGIN) gq1Y]t|4F  
1WN93 SQ=  
}; UnF4RF:A2&  
VEEeQy  
} {-`OE  
/)4r2x  
} )t ch>.EQ_  
0i `Zy!  
 +5mkMZ  
注意:关于额外tag信息类的类名必须要在TLD中的tag标签下的tei-class子元素中定义。因此,DefineTei的tei-class中的定义看起来如下: CscJy0dB  
<tei-class> 3i}B\ {  
org.apache.struts.taglib.bean.DefineTagTei |3@Pt>Ikl  
</tei-class> Du4#\OK  
L5uI31  
x2wWp-Z  
具有协作关系的tag '|?r&-5 h  
D?F5o^e"h<  
,VsCRp  
tag通过共享对象来进行协作,JSP技术支持2种方式的对象共享。 13kb~'+&r  
z))[Lg  
第一种方法是使用pageContext对象进行对象的共享(可支持JSP页面和tag处理类之间的共享),如果在一个tag处理类中要调用由另一个tag处理类创建的对象,可调用pageContext.getAttribute(name, scope)方法。 7uNI  
be#"517  
第二各方式的共享是对于tag之间有嵌套关系而言的,外层的tag所创建的对象对于内层的tag来说是可以共用的。这种形式的共享的好处是减少了可能存在的重名冲突。 ^!Jm/-  
<Pt\)"JA  
要访问一个嵌套tag创建的对象,tag处理类必须先找到此嵌套tag对象,可用TagSupport的静态方法 TagSupport.findAncestorWithClass(from, class)或TagSupport.getParent方法。前者在当不确定此tag是否为嵌套tag对象时使用。一旦它的父类被找到,它就能访问其所有动态或静态创建的对象。静态创建的对象是父类的成员,而动态创建的对象可能是父类的私有对象。诸如此类的对象可以用tag处理类的setValue方法来保存,用getValue方法来获得。 s9bP6N!,  
)II,HT-LY  
下例阐述了以上两种共享对象的方法。在这个例子当中,一个查询tag检查一个名为connection的属性名是否在doStartTag中被设置。如果connection属性被设置,tag处理类从pageContext中得到这个connection对象。否则,此tag处理类先找到它的父tag处理类,然后从它的父tag处理类中找到connection对象。 *)D*iU&  
kP@OIhRe  
OSIp  
public class QueryTag extends BodyTagSupport R0d|j#vP  
oXkhj,{y5  
{ /n7,B}  
O;?~#E<6w  
private String connectionId; Bcon4  
I>Yp=R  
public int doStartTag() throws JspException 6l7a9IJ  
bLF0MVLM  
{ v[3sg2.  
d`7] reh  
String cid = getConnection(); 8E%*o  
x,_Ucc.  
if(cid != null) |YFlJ2w  
uhLm yK  
{ NmF2E+'  
Z+4Oa f!  
//存在一个connection id,使用它。 hI{Yg$H1  
Lpf=VyqC  
connection = (Connection) pageContext.getAttribute(cid); ?EAqv]  
(Z +C  
} ,SwaDWNO  
<);u]0  
else Ec 7M'~1  
)yZE>>3-  
{ QjU"|$  
>@uYleD(  
ConnectionTag ancestorTag = (ConnectionTag)findAncestorWithClass(this, ]#.#]}=  
 B4ze$#  
ConnectionTag.class); n #/m7  
our5k   
if(ancestorTag == null) qJj5J;k  
f BOG#-a}  
{ P'~3WL4MKs  
{HnOUc\4  
throw new JspTagException(“一个没有connection属性的查询标签必须被一个connection标记嵌套。”); o]U ==  
]NsaFDi\  
} rRel\8  
V= PoQ9d  
connection = ancestorTag.getConnection(); ^]gl#&"D  
@CDRbXoFk  
} #JucOWxjY  
'~J6 mojE  
} 3)\qt s5  
_4Pi>  
} Hefqzu  
{!h[@f4  
>,vuC4v-  
.R5z>:A  
此查询标签在JSP页面中的调用形式可以从以下2种定义中任选一种: j(JI$  
E}2[P b)e  
h+(s/o?\  
<tt:connection id=”con01” ...> ... </tt:connection> 7RJW  
B.#0kjA}  
<tt:query id=”balances” connection=”con01” > kGP?Jx\PkH  
.`XA6e(8KR  
SELECT account, balance FROM acct_table N>Y3[G+  
iwJgU b  
where customer_num = <%= request.getCustno() %> W0k q>s4  
8<!9mgh  
</tt:query> UUq9UV-h  
yr'`~[oSCy  
kq-RM#Dj:  
E@KK\m \e  
lUd,-  
<tt:connection ...> hd-ds~ve  
"(qO}&b>  
<x:query id=”balances”> my6T@0R  
(eP)>G]  
SELECT account, balance FROM acct_table t:7jlD!d  
WgB,,L,  
where customer_num = <%= request.getCustno() %> owhht98y(  
Rim}DfO/  
</x:query> &YNhKm@"  
ZT#G:a  
</tt:connection> ><qE5D[  
1S:H!h3  
:9Pqy pd+  
与此同时,在TLD中必须指定connection属性为可选的,定义如下: Fu$sfq  
'P#I<?vB  
<tag> 9nE%r\H  
5hMiCod  
... )j'b7)W\  
.O^|MhBJu  
<attribute> 0 CS_-  
{5h_$a!TaU  
<name>connection</name> (%Rs&/vU~  
~fe0Ba4  
<required>false</required> !k63 `(Ti  
oL;/Qan  
</attribute> 9HP--Z=  
H@:@zD!G[  
</tag>
描述
快速回复

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