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

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

级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
标准的JSP 标记可以调用JavaBeans组件或者执行客户的请求,这大大降低了JSP开发的复杂度和维护量。JSP技术也允许你自定义taglib,其实换句话说,taglib可以看成是对JSP标记的一种扩展,正如xml是对html的一种扩展一样。taglib通常定义在tag标签库中,这种标签库存放着你自己定义的tag标签。简而言之,如果使用taglib,那么你可以设计自己的JSP标记! w0O(>  
U J uz  
一般来说,自定义tag标签主要用于操作隐藏对象、处理html提交表单、访问数据库或其它企业级的服务,诸如邮件和目录操作等等。自定义tag标签的使用者一般都是那些对java编程语言非常精通,而且对数据访问和企业级服务访问都非常熟悉的程序员,对于HTML设计者来说,使得他可以不去关注那些较复杂的商业逻辑,而将精力放在网页设计上。同时,它也将库开发者和库使用者进行合理分工,自定义tag标签将那些重复工作进行封装,从而大大提高了生产力,而且可以使得tag库可用于不同的项目中,完美地体现了软件复用的思想。 KP`Pzx   
O<J<)_W)  
在这篇文章中,我们主要讨论: \D-X _.v  
g'9~T8i& ^  
· 什么是自定义tag标签? VHLt, ?G  
!Ld[`d.|R!  
· 怎么使用tag标签? ltv ~Kh  
fjMmlp  
o 声明要使用的tag库 [[O4_)?el  
;3iWV"&_A  
o 找到与之对应的tag处理类 JH#p;7;  
^}UFtL i  
o tag标签的类型 ny0]Q@  
P=a&>i  
· 自定义tag标签 wjTW{Bg~G  
[sK'jQo-[1  
o tag处理类 RSx{Gbd4X  
!/]z-z2>  
o tag库描述 y"iK)SH  
94?/Rhs5  
o tag标签示例 mln%Rd6u/  
S3Fj /2Q8  
o 带属性的tag s~A:*2\  
F5+!Gb En  
o 带body的tag a :CeI  
OX}ZdM!&f  
o 定义了脚本变量的tag V"T5<HA9  
w6ck wn,  
o 具有协作关系的tag 4 g8t  
8\+XtS  
· 自定义tag标签 <.ZD.u  
Z^.qX\<M  
o 一个迭代tag的例子 (rQ)0g@  
`j'gt&  
o 一个模板tag库 id)J;!^;J  
H{uR+&<  
o tag处理类到底是怎样被调用的? ,nWZJ&B  
of'H]IZ  
U%KgLg#  
什么是自定义的tag? [4-u{Tu  
Jmu oYlf|  
一个自定义的tag标签是用户定义的一种JSP标记。当一个含有自定义的tag标签的JSP页面被jsp引擎编译成servlet时,tag标签被转化成了对一个称为tag处理类的对象进行的操作。于是当JSP页面被jsp引擎转化为servlet后,实际上tag标签被转化成为了对tag处理类的操作。 g@m__   
@2eH;?uO  
自定义tag标签有很多特色,诸如: /S9n!H:MT  
6?-,@e  
· 可以在JSP页面中自定义tag标签的属性 `a8&7 J(  
[9Hrpo]tU:  
· 访问JSP页面中的所有对象 GXR7Ug}k  
6Z-[-0o+g  
· 可以动态地修改页面输出 ^oEaE#I  
JY9hD;`6y  
· 彼此这间可以相互通信。你可以先创建一个JavaBeans组件,然后在一个tag中调用此JavaBeans组件,同时可以在另一个tag中调用它。 ^t[br6G  
7 .xejz  
· tag允许相互嵌套,可以在一个JSP页面中完成一些复杂的交互。 E6xWo)`%5s  
Oe0dC9H  
GFZx[*+%%z  
使用tag标签 +}C M2>M  
8u Z4[  
% %QAC4  
本节主要描述怎样在JSP页面中使用tag标签,以及tag标签的不同类型。 Ifj%"RI  
r]%.,i7~8  
要使用tag标签,JSP程序员必须做2件事: 7T?7KS  
yjucR Fl  
· 声明此tag标签的tag库 4OdK@+-8U  
w*AXD!}  
· 实现此tag标签 BtP*R,>  
leEzfbb{'.  
声明tag标签所在的tag库 .DcuJC=  
8;P_KRaE  
如果要使用tag标签,则应用JSP的taglib指示符来指定其tag库(注意:taglib要在在使用此tag标签之前声明) fQ,(,^!;  
yXA]E.K!  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> G/8G`teAZ  
7h.:XlUm|  
uri属性定义了唯一的标签库描述(以下简称TLD),它可以是直接是tld文件名或一个独一无二的名字。prefix是用来区别其它TLD中和本TLD中有重名的tag的一种手段。 $]iRfXv,l!  
u=6{P(5$j  
TLD必须以.tld作为扩展名,并且存放在当前应用的WEB-INF目录或其子目录下。你可以通过它的文件名直接引用它,也可以通过别的方式间接地引用它。 WR>2t&;E  
}u'O<d~z?  
以下taglib指示符直接引用一个TLD: XJf1LGT5  
2@ f E!  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %>   S?m4  
.:jfNp~jt  
以下的taglib指示符通过一个逻辑名称间接地引用一个TLD: [u`9R<>c"U  
FZtILlw  
<%@ taglib uri=”/tutorial-template” prefix=”tt” %> w5}2$r  
_:9-x;0H2  
如果是间接引用TLD的话,那你必须还要在web.xml中定义此逻辑名称与tld文件之间的映射,具体做法是在web.xml中加入一个名为taglib的元素: "zN]gz=OV>  
)IZ~!N|-w  
<taglib> vM2\tL@"  
JY@x.?N5$  
<taglib-uri>/tutorial-template</taglib-uri> \JEI+A PY*  
O:G-I$F|  
<taglib-location> {~:F1J~=  
VUGVIy.  
/WEB-INF/tutorial-template.tld 5>[ j^g+@  
>a1 ovKF  
</taglib-location> g,cl|]/\d  
h3:dO|Z  
</taglib> |CjE }5Op>  
 W,)qE^+  
5VPP 2;J  
实现此tag标签 GGchNt  
pxs`g&3yd  
~0@+8%^>;  
为了实现tag标签,你有2种方法来存放tag处理类。一、让tag处理类以.class的方式存放于当前应用的WEB-INF/class子目录下,二、如果tag处理类是以JAR包的形式存在的话,那可以放在当前应用的WEB-INF/lib目录下,如果tag处理类要在多个应用中共享,那么它就应放在jsp服务器上的common/lib目录下,对于tomcat来说,就是tomcat/common/lib目录下。 %O3 r>o=  
j!<RY>u  
k`Ifd:V.y  
tag标签类型 +']S  
>|So`C3:e  
,b8q$ R~\  
自定义的tag标签遵循XML语法。它有一个开始标记和一个结束标记,有的还有body(即文本节点): =24<d!R  
c\pPwG  
<tt:tag> &O.S ;b*+  
sGD b<  
body /.aDQ>  
oXkxd3  
</tt:tag> -!]dU`:(X  
(S#4y  
.v:K`y;f\(  
一个不带body的tag标签如下: {?9s~{Dl  
Tfl4MDZb  
<tt:tag /> O{9h'JU  
Pc4FEH/  
If_S_A c  
简单的tag标签 6 4da~SEn  
m ,U`hPJ  
一个没有body和属性的tag标签如下: -3<5,Q{G+  
8PV`4=,OI  
<tt:simple /> @E$PjdB5M  
5E/z.5 q  
mSzBNvc i  
带属性的tag标签 jo4*,B1x  
dZ7+Iw;m  
Osdw\NNH~M  
自定义标签可以有自己的属性。属性一般在开始标记中定义,语法为 attr=”value”。属性的作用相当于自定义标签的一个参数,它影响着tag处理类的行为。你可以在TLD中详细定义它。  98os4}r  
(SLAq$gvd  
你可以用一个String常量给一个属性赋值,也可以通过表达式给它赋值,如<%= ...%>。以struts为例,它的logic:present标签就是用的String常量来给属性赋值: )vK %LmP  
DT@6Q.  
<loglic:present parameter = “Clear”> yjVPaEu]aU  
( {H5k''  
而另一个标签logic:iterate是用表达式来给属性赋值: %Y` @>P'  
451r!U1Z  
<logci:iterate collection=”<%= bookDB.getBooks() %>” N}>XBZy  
'Z+~G  
id=”book” type=”database.BookDetails”> y.~y*c6,g  
0*"auGuX  
^Q]*CU+C  
带body的tag标签 gaC^<\J  
D!~-53f@  
一个自定义标签可以包含其它自定义标签、脚本变量、HTML标记或其它内容。 "| <\\HR  
*/n)_  
在下述例子中,此JSP页面使用了struts的logic:present标签,如果些标签定义了parameter=”Clear”的属性,则将清除购物车的内容,然后打印出一条信息: 0EYK3<k9!  
p IXBJk  
<logic:present parameter=”Clear”> 8Z!+1b  
H'$g!Pg  
<% cart.clear(); %> DA@YjebP'  
dvk? A$  
<font color=”#ff0000” size=”+2”><strong> DEaO= p|  
0}c *u) ,  
你选择了清除购物车! Z^>[{|lIA  
=/" Of  
</strong></font> d^IOB|6Q  
su(y*187A  
</logic:present> H>e?FDs0*R  
vt[4"eU  
5,'?NEyw  
到底是用属性还是用body来传递信息? \@Gyl_6^  
/!UuGm   
如上所述,我们既可以通过属性,也可以通过body来传递信息。但一般来说,比较简单的类型,如字符串或简单表达式最好采用属性来传递信息。 +}X?+Epm  
7ju7QyR  
tq?lF$mM:  
定义脚本变量的tag标签 ~ -Rr[O=E  
%L{H_;z  
所谓脚本变量,是指JSP中可以调用的变量或对象。它可由tag标签产生。以下示例阐述了一个tag标签定义了一个名为tx的由JNDI所定义的事务处理对象。脚本变量可以是ejb对象、事务、数据库连接等等: N<:5 r  
m~#S76!w  
<tt:lookup id=”tx” type=”UserTransaction” name=”java:comp/UserTransaction” /> $GUSTV  
,:QG%Et  
<% tx.begin(); %> %$I\\q q>{  
R5G~A{w0  
... O%A:2Y79  
52tIe|KwL  
GdR>S('  
具有协作关系的tag标签 ji`N1e,l  
/]T#@>('  
自定义tag标签之间可以通过共享对象来实现协作。在下述例子中,标签tag1创建了一个名为obj1的对象,在标签tag2仍可以重复使用obj。 A7 .C  
|v}"UW(y  
<tt:tag1 attr1=”obj1” value1=”value” /> W{Ie(hf  
YU[93@mCh  
<tt:tag2 attr1=”obj1” /> 6J6MR<5'  
1okL]VrI  
在以下这个例子当中,如果外层的tag标签创建了一个对象,那么其内层的所有tag标签都可以使用这个对象。由于这样产生的对象没有一个指定的名字,那么就可以将少重名的冲突。这个例子阐述了一系列协作的嵌套对象。 gCgMmD=AZ  
*(s+u~, I  
<tt:outerTag> ;Mc\>i/  
U#+S9jWe  
<tt:innerTag /> r`i<XGPJ%  
e\k=T}  
</tt:outerTag> C!B2 .:ja  
1a| q&L`o  
f$iv+7<B^  
Tag处理类 ~kYUp5f  
mmAikT#k  
wtetB')yD  
Tag处理类必须实现Tag接口或BodyTag接口,不过现在一般都流行从TagSupport或BodyTagSupport类中继承,这些类或接口都可以在javax.servlet.jsp.tagext包中找到。 HW"|Hm$Y(  
7NMQUN7k '  
当JSP引擎看到自己的JSP页面中包含有tag标签时,它会调用doStartTag方法来处理tag标签的开头,调用doEndTag方法来处理tag标签的结束。 y^pk)`y8  
lOPCM1Se  
下表说明不同类型的tag所需要不同的处理过程: gf2l19aP  
utQE$0F  
Tag处理类的方法 O!lZ%j@%  
._~_OVU  
Tag标签类型 +e`f|OQ  
所调用的方法 1@P/h#_Vr  
c\-5vw||b  
基本标签 0V"r$7(}  
doStartTag, doEndTag, release b~Op1p  
4Ucg<Z&%  
带属性的标签 {^Vkxf]  
doStartTag, doEndTag, set/getAttribute1...N, release "'4R _R  
tjBs>w  
带内容的标签 rBkLwJ]  
doStartTag, doEndTag, release :mX c|W3  
#gMMh B=  
带内容的标签,且内容重复循环 Z%y>q|:  
doStartTag, doAfterBody, doEndTag, release .|JJyjRA+  
}BKEz[G(  
带内容的标签,且内容与JSP交互 9s6@AJf  
doStartTag, doEndTag, release, doInitBody, doAfterBody, release 2xhwi.u  
T,@.RF  
一个tag处理类可以通过javax.servlet.jsp.PageContext来与JSP交互,通过javax.servlet.jsp.PageContext类,tag处理类可以访问JSP中的request、session和application对像。 #25Z,UU  
6B)(kPW  
如果tag标签是互相嵌套的,那内层的tag处理类可以通过它的parent属性来访问上层的tag处理类。 ~.u}v~ F  
T(MS,AyD]  
一般情况都将所有的tag处理类打成了JAR的包,以便于发布。 Sav]Kxq{  
lTv I;zy  
,3.E]_3 xX  
Tag库描述(简称TLD) L)a8W   
OKNA36cU'  
h=.|!u  
Tag库是用xml语言描述的,TLD包括了tag库中所有tag标签的描述,它一般用来被jsp服务器用来校验tag的语法正确性,或者被jsp开发者用来开发新的标签。 FAfk;<#'n+  
x9Y1v1!5Pu  
TLD的文件扩展名必须为.tld,而且必须放在当前WEB应用的WEB-INF目录或其子目录中。 $HF. 02{|  
01g=Cg  
一个TLD的内容的开头必须遵守标准的XML开头,用于描述DTD和xml的版本,例如: {UX?z?0T  
(wEaa'XL  
<?xml version="1.0" encoding="ISO-8859-1" ?> 1"?KQU  
Y;8Ys&/t  
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd">  U":hJ*F)  
TLD必须以<taglib>来作为它的根元素,<taglib>的子元素如下表: mTz %;+|L  
((Ak/qz  
D*6v.`]X  
<taglib>的子元素 _G|hKk^,  
U&yXs'3a&  
Element =dx!R ,Bw  
Description -=iGl5P?  
BAG) -  
tlib-version lqn7$  
Tag库的版本 4 sasf94  
RbzSQr>a\  
jsp-version >A5R  
Tag库所需要的jsp的版本 M$~3`n*^  
cjAKc|NJ  
short-name px %xoY  
助记符,tag的一个别名(可选) id<i|  
Qz\yoI8JA,  
uri . <`i!Ls  
用于确定一个唯一的tag库 +%Q:  
,yus44w[  
display-name T]-yTsto  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) 6E/>]3~!  
0B fqEAl  
small-icon "[2CV!_  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) Oo |*q+{  
wI><kdz  
large-icon x;)bp7  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) JBfDz0P  
gNF8&T  
description tvXoF;Yq  
对tag库的描述(可选) yI/2 e[  
PPk\W7G  
listener oFM\L^Y?$$  
参见下面listener元素 qzS 9ls>>  
yTzP{I  
tag )]WWx-Uf'  
参见下面tag 元素 9zSHn.y  
q9fCoz  
Listener元素 =sy>_   
0 zm)MSg  
一个tag库可能定义一些类做为它的事件侦听类,这些类在TLD中被称为listener 元素,jsp服务器将会实例化这些侦听类,并且注册它们。Listener元素中有一个叫listener-class的子元素,这个元素的值必须是该侦听类的完整类名。 Mx<z34(T  
Ot}fGiio  
Tag元素 rE0?R( _  
u$ [R>l9  
每个tag元素在tag库中都要指出它的名字、类名、脚本变量、tag的属性。其中脚本变量的值可以直接在TLD中定义或通过tag附加信息的类来取得。每个属性描述了这个属性是否可以省略,它的值是否可以通过<%= …%>这样的JSP语法来获得,以及属性的类型。 D^Ahw"X)  
\$:KfN>WY  
每一个tag在TLD中对应一个tag元素,下表是tag元素的子元素: f0p+l -iEv  
zvjVM"=G  
Tag元素的子元素 N<lejZ}!q  
T'\B17 :*  
元素名称 0^'A^  
描述 ?xEQ'(UBQ  
3ThBy'  
name } 8ZCWmd  
独一无二的元素名 .N2yn`  
OQzJRu)mF#  
tag-class 3jF#f'*  
Tag标签对应的tag处理类 ~^d. zIN!  
UjibQl 3:m  
tei-class 272j$T  
javax.servlet.jsp.tagext.TagExtraInfo的子类,用于表达脚本变量(可选) C yg e  
#o Rm-yDr  
body-content )E;+C2G  
Tag标签body的类型 Y `4AML  
1'ne[@i^/  
display-name s X&.8  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) d"3S[_U  
tHNvb\MR$  
small-icon jVP70c  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) *hVbjI$  
GC?X>AC:  
large-icon I9O9V[  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) V3;4,^=6Dd  
s( @w1tS.  
description +pYrAqmO-  
此tag标签的描述 F) w.q  
<p@c %e,_  
variable XL[/)lX{  
提供脚本变量的信息(同tei-class)(可选) (vte8uQe  
bqug o  
attribute s2Gi4fY?  
Tag标签的属性名 UeWEncN(  
1I({2@C  
以下章节介绍对于不同类型的tag,如何具体地实现它们。 G| 7\[!R  
'[#a-8-JY_  
~3}Gu^@  
简单的tag g\MHv#v*k  
Pn@k)g  
%bI(   
tag处理类 |8I #`  
8r '  
简单的tag处理类必须实现Tag接口的doStartTag和doEndTag方法。当jsp引擎碰到tag标签的开头时,doStartTag被调用,因为简单的tag没有body,所以此方法将返回 SKIP_BODY。当jsp引擎碰到tag标签的结尾时,doEndTag被调用,如果余下的页面还要被计算,那它将返回EVAL_PAGE,否则将会返回SKIP_PAGE。 .DSn H6O  
(IX iwu  
以下是例子:对于标签 <tt:simple /> ,它的tag处理类实现如下: ^l1tQnj)7  
shW$V93<  
eUQ.,mP  
public SimpleTag extends TagSupport #PnuR2s7.  
Z09FW>"u  
{ WqN=  D5  
\m-fLX  
public int doStartTag() throws JspException ~~:w^(s9  
j,Sg?&"%=  
{ [c4.E"  
j]7|5mC78  
try{ [vki^M5i|Z  
v-6" *EP  
pageContext.getOut().print(“Hello.”); f.V;Hl,  
Ke-Q>sm2Q  
}catch(Exception e){ Q,Tet&in )  
2mL1BG=Yk  
throw new JspTagException(“SimpleTag: “ + e.getMessage()); I( BG%CO9  
<*L=u;  
} F\1nc"K/(  
D|I(2%aC  
return SKIP_BODY; ^q6H =Dl  
"^-U#f>k  
} @k~?h=o\b  
VlW#_.  
public int doEndTag() ~^/zCPy[w  
ja$>>5<q  
{ xO'I*)  
GZT}aMMSJ  
return EVAL_PAGE; j&E4|g (  
N_<sCRd]9  
} ,oe e'  
a?'3  
} zjgK78!<  
oR}ir  
m^ zx &  
注意:如果tag标签没有内容的话,那必须定义body-content元素为空,例如 { frEVHw  
9[DQ[bL  
<body-content>empty</body-content> 5_Yv>tx  
(ohkM`83k  
Wm:3_C +j  
带属性的tag标签
评价一下你浏览此帖子的感受

精彩

感动

搞笑

开心

愤怒

无聊

灌水
级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
只看该作者 1 发表于: 2007-01-01
tag处理类 w|WZEu:0|  
V$ 38  
对于tag标签的每个属性,你必须依照JavaBeans规范来定义其属性,以及get和set方法。以struts的logic:present 标签为例, j-gLX  
p@i U}SUaE  
<logic:present parameter=”Clear”> >0 !J]gK  
{%D "0*^  
与此相应,此tag处理类应有如下方法和定义: 7~\Dzcfk"P  
S !c/"~X+  
%fP^Fh   
protected String parameter = null; ?Z4& j'z<  
XeDU ,  
public String getParameter() {\|? {8f  
(m;P,*  
{ lk.Q6saI1  
3JW9G04.  
return this.parameter; t{~"vD9Am  
#a#~YSnG  
} mMN oR]  
x(}tr27o  
public void setParameter(String parameter) 0IDHoNaT<  
q,nj|9z V  
{ EoU}@MjM~  
CyG@  
this.parameter = parameter; bG^eP :r  
`m2F.^qrr  
} 6/4OFvL1  
b@YSrjJ  
tHoFnPd\|  
注意:如果你的属性名为id,而且你的tag处理类是从TagSupport类继承的,那你就不需要定义它的属性和set和get方法,因为他们早已在TagSupport被定义过了。 p00\C  
{h9#JMIA  
Attribute元素 oeIB1DaI  
@Jm$<E  
对于tag标签的每个属性,你必须定义它是否必须的,它的值是否可以用诸如<%= …%>的表达式来获得,以及它的类型(可选),如果不指定它的类型,那就默认为是java.lang.String类型。如果rtexprvalue元素被定义为true或yes,那么在type元素中就定义了attribute的返回类型。 :@: R4Ac  
s #L1:L  
<attribute> 8.k"kXU@n  
Fi5,y;]R  
<name>attr1</name> BOwkC;Q[  
&)s A(  
<required>true|false|yes|no</required> !@VmaAT  
NmB0CbB  
<rtexprvalue>true|false|yes|no</rtexprvalue> Y}1|/6eJ  
U7PA%  
<type>attribute的返回类型(只用当rtexprvalue为真是才有效)</type> B/5C jHz  
Kq{s^G  
</attribute> uaU!V4-  
&7@6Y{!/  
如果tag的某个属性不是必须的,那tag处理类会自动提供一个缺省值。 ?R,^prW{  
8: s3Q`O  
例如,在logic:present这个tag标签中定义了一个属性叫parameter,但它不是必须的,而且它可以被诸如<%= …%>的表达式来赋值。  h@W}xT  
*3 9sh[*}  
<tag> &q":o 'q  
tOspDPSXX  
<name>present</name> a'T|p)N.;T  
kdmVHiGF  
<tag-class>org.apache.struts.taglib.logic.PresentTag</tag-class> xY!]eLZ)&  
V7lDuiAI  
<body-content>JSP</body-content> '|FM|0~-J  
E#HO0 ]S  
*f4KmiQ~ %  
'kh%^_FH7  
<attribute> q1?2 U<  
siD Sm  
<name>parameter</name> "jeJV,%  
|Cen5s W&  
<required>false</required> .IKK.G  
8AefgjE  
<rtexprvalue>true</rtexprvalue> !o.g2  
&rNXn?>b  
</attribute> LG,RF:  
t8P>s})[4  
(yXVp2k  
@{ nT4{  
</tag> x%(!+  
BR0bf5T/  
Cog:6Gnw  
属性元素的校验 _8S).*  
o<g (%ncr  
+6;OB@  
有关于tag标签的有效值可以从tag库的说明文档中获得,当JSP页面被编译时,jsp引擎会强制性地参照TLD中定义的规则进行检查。 N7;E 2 X  
2#E;5UYu  
还有一个方法也可以进行属性元素的校验,就是先继承类TagExtraInfo,然后调用它的isValid方法。这个类同时也起到提供tag中定义的脚本变量信息的作用。 yGD0}\!n  
S((8DSt*  
IsValid方法通过TagData对象来传递属性信息,它包括着tag的所有的属性名-值的信息。由于校验发生在运行时刻,因此这个属性的值将被赋值为TagData.REQUEST_TIME_VALUE。 gq0gr?  
P0z "Eq0S  
例如tag标签<tt:twa attr1=”value1” />在TLD中定义如下: 1gt[_P2u  
FcWu#}.p}  
<attribute> _n_i*p '2  
WYh7Y  
<name>attr1</name> QU#/(N(U#T  
kh5V&%>?  
<required>true</required> 3$kZu  
}YSH8d  
<rtexprvalue>true</rtexprvalue> ZtvU~'Q  
d@l;dos),  
</attribute> 1u` Z?S(  
2xnOWW   
u(~s$ENl  
这个定义说明了attr1能在运行期间被赋值。  LSfj7j`  
l%U9g  
以下的isValid方法检查attr1属性的值是否属于Boolean类型。注意由于attr1能在运行刻被赋值,那么isValid方法必须检查tag用户是否对此tag进行了运行时刻赋值。 3n/L; T,X  
'+eP%Y[W%  
"*T)L<G  
Public class TwaTEI extends TagExtraInfo x``!t>)O  
vIG,!^*3  
{ MUo?ajbqOd  
+amvQ];?Q8  
public boolean isValid(Tagdata data) zH_q6@4  
l9jcoVo .  
{ tT v@8f  
S2NsqHJr  
Object o = data.getAttribute(“attr1”); bHMlh^{`%  
_9-Ajv  
If(o != null && o != TagData.REQUEST_TIME_VALUE) ]I]dwi_g)  
K)v(Z"  
{ :{AN@zC0\  
hlVP_h"z  
if( ( (String)o).toLowerCase().equals(“true”) || [L\w] 6  
0hv[Ff  
((String)o).toLowerCase().equals(“false”) ) k]JLk"K  
s R~&S))  
return true; %z.G3\s0  
%z2nas$$g  
else F+6ZD5/  
p!691LI  
return false; lfKknp#B/O  
ZHBwoC#5}  
} 54OYAkPCk  
tyDtwV|  
else z6!X+`&  
-`;8~wMN  
return true; _+. t7q^  
u,pm\  
} {NFeX'5bP  
}+B7C2_\  
} f&`*x t/  
\?g%>D:O;  
%MIu;u FR  
带body的tag = MXF`k^}  
*K)v&}uw  
_E%[D(  
tag处理类 mSzwx/3"  
w iq{ Jo#  
}iC~B}  
如果tag标签含有内容,那处理方式会略微有些不同,而且还要视tag处理类是否要与body交互的情况而定。如果要与body交互,那我们认为tag处理类要可能要对body进行操作。 ~ U1iB  
SN+Bmdup  
Tag处理类不与body交互 V?"^Ff3m!  
=UV?Pi*M>  
如果tag处理类不与body交互,tag处理类应该实现Tag接口或从TagSupport中派生,如果body要被计算,那么doStartTag方法应返回 EVAL_BODY_INCLUDE,否则应返回SKIP_BODY。 A/QVotcU  
YO Y+z\Q  
如果tag处理类要对body反复运算,则它应该实现IterationTag或从TagSupport中派生。如果tag处理类认为body还未计算完的话,那它的doStartTag方法和doAfterBody方法必须返回EVAL_BODY_AGAIN。 U %4g:s  
Y}Dp{  
Tag处理类与body交互 DYl^6 ]  
70NHU;&N  
如果tag处理类与body交互,那tag处理类应实现BodyTag接口或从BodyTagSupport中派生。这种tag处理类一般要实现doInitBody和doAfterBody方法。 k`t'P6 bU  
BOWTH{KR<<  
Body允许一些方法来读写它的内容。Tag处理类可以调用body内容的getString或getReader方法来从body中提取信息,也可用 writeOut(out) 方法来将body的内容写入到out对象中。其中out对象通过tag处理类的getPreviousOut方法来获得。 bXW)n<y  
J.&q[  
如果body的内容需要被计算,那么doStartTag方法必须返回EVAL_BODY_BUFFERED,否则,它将返回 SKIP_BODY。 SUEw5qitB  
-r2cK{Hhp&  
doInitBody 方法 5bw]cv$i  
T/K.'92S  
此方法在body内容已经设好,但未被计算之前被调用。你可以根据不同的body内容来制定初始化策略。 K c<z;  
zm:=d>D..  
doAfterBody方法 *"5a5.`%,  
`%Ghtm*  
此方法在body内容已被计算后进行调用。 y"hM6JI  
MT5A%|He  
和doStartTag方法一样,doAfterBody方法返回一个指示符指示是否要继续计算body,如果要继续计算,则doAfterBody应返回EVAL_BODY_BUFFERED,否则,它应返回SKIP_BODY。 I%&9`ceWY  
EH3G|3^xz  
release 方法 yI%> w4Z  
EzyIsp> _  
tag处理类调用此方法将它的状态重置为初始状态,并释放所有的私有资源。 G225Nz;Y*  
]UI+6}r  
t[maUy _A  
以下的例子读取body的内容(其中含有一条sql语句),然后将它传递给一个对象,让它进行查询。由于此处body不须重新计算,所以doAfterBody会返回SKIP_BODY。 >R: +ml  
b[k 1)R"  
GlZ9k-ZRF  
Public class QueryTag extends BodyTagSupport [E^X=+Jnz  
@Otc$hj  
{ KC u6:)6'  
^ZlV1G;/W@  
public int doAfterBody() throws JspTagException Rf^cw}jU  
nsp K.*?  
{ 8.^U6xA  
Psa8OJan  
BodyContent bc = getBodyContent(); kziBHis!  
a(~Yr A%~  
//将body的内容以字符串的格式提取出来 u s0'7|{q  
>2:Sv1T  
String query = bc.getString(); c 2@@Rd~M  
##_Za6/n  
//清除body  =s]{  
9vTQ^*b m  
bc.clearBody(); ~ t H s+  
TxvPfU?  
try{ kn"x[{d  
=QfKDA  
Statement stmt = connection.createStatement(); aX%Zuyny  
hN53=X:  
Result result = stmt.executeQuery(query); hn|E<  
%MJ7u}  
}catch(SQLException e){ $te,\$&}  
\i+h P1 mz  
throw new JspTagException(“queryTag: “ + e.getMessage() ); ,m?D\Pru  
b1u'ukDP\  
return SKIP_BODY; E?mp6R]}%  
Q75^7Ga_  
} ?<?C*W_  
KUutC :  
} +I n"OR%  
g)A0PvEu  
f B96Q  
body-content元素 mv.I.EL  
I0vn d7  
D,j5k3< #  
由于tag可能会有body,你必须用body-content元素来指定body内容的类型:  {Yk20Zn  
&] 6T^.  
<body-content>JSP|tagdependent</body-content> J\+gd%  
T:">,* |  
Iq]6]  
如果body的内容是定制的或内部的tag、脚本元素、或HTML广本,则归类为JSP类型。其他的类型,比如上面代码所述的?D?D将sql statement类传给 query tag的这种类型应该标为tagdependent。 !O6Is'%B  
ls\E%d  
注意:实际上body-content的值并不影响tag处理类对body内容的处理,它仅仅是被tag编辑工具用来描述此body的内容。 6a7iLQA  
{l&2Kd*  
%QgAilj,  
用tags定义脚本变量 d`<^+p)oy  
=k= 2~ j  
YiuOu(X  
tag处理类 pf@}4PN}  
*.c9$`s  
(I ds<n"  
tag处理类负责创建或设置页面中定义的脚本变量,用pageContext.setAttribute(name,value,scope)或pageContext.setAttribute(name,value)方法来实现。一般来说,tag处理类通过脚本变量的名称来获取它,脚本变量的名称一般可用get方法来获得。 [0ffOTy  
Ju7C?)x  
如果脚本变量的值依赖于tag处理类中的上下文中某一对象,那它可用pageContext.getAttribute(name,scope)方法来找到那个对象。一般的处理过程是tag处理类先找到脚本变量,再对其进行处理,然后用pageContext.setAttribute(name,object)的方法来设置它的新值。 $ cK B+}  
zZc@;S#  
对象的生存周期(scope)如下表: w a<C*o  
{U '&9_y  
对象的生存周期表 %Dls36F  
2 `h!:0  
名字 B;]5,`#!  
可访问范围 )UZ0gfx  
生存周期 ~: <@`  
!b->u_  
page 7 eQoc2X2  
当前页面 {kl{mJ*  
一直有效,除非页面向客户提交响应或重定向到一个新页面 w1#jVcUQ  
kr`BUW3  
request ';\gR/L  
当前页面或当前页面重定向到的页面 <GgtP55  
一直有效,除非页面向客户提交响应 \seG2vw$  
Rfc&OV  
session ]|t.wr3AU  
当前页面或在同一浏览器窗口中的页面 E:4P1,%01+  
一直有效,除非关闭当前浏览器、超时、网络故障 s!/holu  
JX/4=..  
application _#D\*0J  
整个web应用程序的所有请求 XVDd1#h  
一直有效,除非发生网络故障、服务器故障 +%qSB9_>N{  
QiE<[QP{g  
提供关于脚本变量的信息 )cK  tc  
nuO3UD3  
以下示例定义了一个名为“book”的脚本变量,用来访问程序中关于书的信息: $jed{N7Y  
\*%i#]wO@  
<bean:define id=”book” name=”bookDB” property=”bookDetails” type=”database.BookDetails” /> 9X$#x90  
uWB:"&!^  
<font color=”red” size=”+2” > T E&Q6  
vMX6Bg8  
<%= messages.getString(“CartRemoved”) %> a5}44/%  
9^QYuf3O  
<strong><jsp:getProperty name=”book” property=”title” /></strong> wz*A<iU  
#}!>iFBcH  
</font> r d6F"W  
Ls>u` hG  
当包含此tag的JSP页面被编译时,jsp引擎会自动生成关于此book的同步的代码(同步可以避免几个客户同时访问此book时造成的冲突),要生成同步代码,jsp引擎需要知道此脚本变量的如下信息: &:;;u\  
f;Bfh3  
· 脚本变量名称 .eabtGO,  
R=amKLD?  
· 脚本变量所属的类 8gbm"!  
B3>Uba*-)}  
· 此脚本变量是否引用了一个新的或已存在的对象 \l]pe|0EW  
'y6!%k*  
· 此脚本变量的有效性 {y&\?'L'  
:#\B {)(  
有两种办法可以向jsp引擎提供关于脚本变量的信息:在TLD中定义variable子元素,或用tei-class子元素定义一个额外tag信息类。用variable最简单,但可能降低了一些灵活性。 (' Ko#3b  
8PoHBOxpc  
Variable元素 'lN*Ys iDi  
Z cTL#OTP  
Variable元素有如下子元素: c2/R]%`)9  
zyZok*s  
· name-given ?D?D 给出的名字,是一个常量 "37@Zt  
{yHB2=nI  
· name-from-attribute?D?D 属性名,在编译时给出的属性名 0^&(u:~  
RO%tuU,-  
name-given或name-from-attribute两者必须选一,但以下子元素是可选的: K=c=/`E  
Wj4^W<IO  
· variable-class?D?D变量的类型,缺省为java.lang.String。 !2Xr~u7a  
Oj"pj:fB  
· declare?D?D此脚本变量是否引用了一个新对象,缺省为True。  !u53 3  
U1>  
· scope?D?D脚本变量的范围,缺省为NESTED。下表描述了scope的几种类型: jom} _  
hC|5e|S  
脚本变量的有效范围 UAx.Qq  
hY.e[+  
jSie&V@px  
有效性 )l#%.Z9  
方法  :Hzz{'  
(:?5 i`  
NESTED GJC!0{8;  
在tag标签的开始和结束之间 *(d6Z#  
如果tag处理类实现BodyTag接口,则在doInitBody和doAfterBody中调用,否则在doStartTag中调用 O&#S4]Y   
`;5VH]V  
AT_BEGIN "%oH@ =  
从tag标签的开始一直到页面结束 _K0izKTA.  
如果tag处理类实现BodyTag接口,则在doInitBody、doAfterBody和doEndTag中调用,否则在doStartTag和doEndTag中调用 HPtTv}l  
"Ju /[#VCJ  
AT_END k5 aa>6K  
从tag标签的结束一直到页面结束 R=vbUA  
在doEndTag中调用 U|Bsa(?nx  
)IFl 0<d  
以struts为例,它的bean:define标签的实现遵循JSP1.1规范,此规范要求使用额外tag信息类来定义脚本变量。Variable元素是JSP1.2规范中加入的。以bean:define标签为例,你可以定义如下variable元素: ;wJ7oj<  
smfG, TI  
<tag> !2zo]v4?  
FJsK5-  
<variable> E!zd(  
%\}dbYS '  
<name-from-attribute>id</name-from-attribute> | rE!  
n|70x5Z?}J  
<variable-class>database.BookDetails</variable-class> "x#]i aDjf  
L_THU4^j  
<declare>true</declare> mL:m;>JJ n  
DKy >]Hca  
<scope>AT_BEGIN</scope> {{V ;:+62  
});cX$  
</variable> ^))PCn_zb  
u}K5/hC  
</tag> 35Ai;mU'  
je&dioZ>  
额外tag信息类 !,cQ'*<W8-  
Z/2,al\  
如果要定义一个额外tag信息类,你要继承javax.servlet.jsp.TagExtraInfo类。一个TagExtraInfo类必须实现getVariableInfo方法,此方法返回一个叫VariableInfo的数组类,它包括如下信息: 3]O`[P,*%  
IL~]m?'V(  
· 变量名 P0%N Q1bn  
n-b>m7O(  
· 变量所属类名 k{gl^  
42rj6m\  
· 此变量是否引用了一个新对象 y z[%MXI  
+1otn~(E  
· 此变量的有效范围 Nb~,`bu,2  
+ ,@ FxZl  
jsp引擎将一个名为data的参数传给getVariableInfo方法,data中包括tag标签中的所有“属性名?D?D属性值”对。它可以用来向VariableInfo对象提供脚本变量的名字和类名。 {0is wq'J  
Km6Ub?/7o  
以struts为例,它在bean:define标签中定义了一个名为DefineTei的额外tag信息类,用来向脚本变量提供信息。由于脚本变量的名称(book)和类名(database.BookDetails)是通过tag标签的属性来传递的,它们一般定义在VariableInfo的构建代码中,并且可用data.getAttributeString方法来得到这些信息。如果要允许book脚本变量能在从tag开始直到整个JSP页面结束的范围内都可用的话,那它的范围应设为AT_BEGIN。如下所示: K0tV'Ml#"  
;_mgiKHg  
o3Mf:;2cC  
public class DefineTei extends TagExtraInfo BZovtm3 E  
k$ZRZ{ E+  
{ )Rjb/3*!  
.)LZ`Ge3F  
public VariableInfo[] getVariableInfo(TagData data) 9{_8cpm4  
b;S6'7Jf9  
{ N]B)Fb  
w Y8@1>ah  
String type = data.getAttributeString(“type”); a?5WKO  
0CPxIF&  
If( type == null) kUNj4xp)  
M{C6rm|  
type = “java.lang.Object”; GwcI0~5  
fuq( 2&^  
return new VariableInfo[] { "6?lQw e  
iaY5JEV:CA  
new VariableInfo(data.getAttributeString(“id”), aXMv(e+  
yC0C`oC  
type, JZ`>|<W  
IikG /8lP  
true, V?OuIg%=:  
:1:3Svb<Y  
VariableInfo.AT_BEGIN) 8]S,u:E:N  
Z:K+I+:t  
}; $z*@2Non  
>BBl 7  
} cppL0myJ  
7$!yfMttu  
} z8IPhE@  
^;.T}c%N  
4w 'lu"U  
注意:关于额外tag信息类的类名必须要在TLD中的tag标签下的tei-class子元素中定义。因此,DefineTei的tei-class中的定义看起来如下: ,Kuk_@(}5~  
<tei-class> ~|h lE z  
org.apache.struts.taglib.bean.DefineTagTei b)N[[sOt  
</tei-class> :*^:T_U  
Vzpt(_><  
59.$ULQVMY  
具有协作关系的tag &,J*_F<s2<  
9X(Sk%  
YQ; cJ$  
tag通过共享对象来进行协作,JSP技术支持2种方式的对象共享。 =/[ltUKs:a  
aYqm0HCT  
第一种方法是使用pageContext对象进行对象的共享(可支持JSP页面和tag处理类之间的共享),如果在一个tag处理类中要调用由另一个tag处理类创建的对象,可调用pageContext.getAttribute(name, scope)方法。 Bp :~bHf  
uS~#4;R   
第二各方式的共享是对于tag之间有嵌套关系而言的,外层的tag所创建的对象对于内层的tag来说是可以共用的。这种形式的共享的好处是减少了可能存在的重名冲突。 |pJC:woq  
t#Th9G]1  
要访问一个嵌套tag创建的对象,tag处理类必须先找到此嵌套tag对象,可用TagSupport的静态方法 TagSupport.findAncestorWithClass(from, class)或TagSupport.getParent方法。前者在当不确定此tag是否为嵌套tag对象时使用。一旦它的父类被找到,它就能访问其所有动态或静态创建的对象。静态创建的对象是父类的成员,而动态创建的对象可能是父类的私有对象。诸如此类的对象可以用tag处理类的setValue方法来保存,用getValue方法来获得。 %dc3z"u  
u#1%P5r&X  
下例阐述了以上两种共享对象的方法。在这个例子当中,一个查询tag检查一个名为connection的属性名是否在doStartTag中被设置。如果connection属性被设置,tag处理类从pageContext中得到这个connection对象。否则,此tag处理类先找到它的父tag处理类,然后从它的父tag处理类中找到connection对象。 z 5'ZN+  
X/l;s  
o+NMA (  
public class QueryTag extends BodyTagSupport mb&lCd ^-  
wqUQ"d  
{ >)Ioo$B  
+]c/&Xo!  
private String connectionId; WSRy%#  
n0Go p^3  
public int doStartTag() throws JspException Jy]Id*u9  
6JhMkB^h  
{ @D)Z{=>{=5  
joqWh!kv7U  
String cid = getConnection(); uMvb-8  
g5i#YW  
if(cid != null) []zua14F6  
8'_ 0g[s  
{ 6gnbkpYi  
+c--&tBo  
//存在一个connection id,使用它。 i\)3l%AK]T  
Ql8bt77eI-  
connection = (Connection) pageContext.getAttribute(cid); b._m8z ~  
m[spn@SF  
} #n3ykzoqIX  
dy<27=  
else b HE7yv [  
nU2V]-qY  
{ b0rX QMu  
\:Za[6  
ConnectionTag ancestorTag = (ConnectionTag)findAncestorWithClass(this, ; DDe.f"  
Q8q@Y R#  
ConnectionTag.class); Zsj`F9*e  
e`iEy=W  
if(ancestorTag == null) :lgi>^  
RP! X8~8  
{ %?9Ok  
UX2lPgKdLz  
throw new JspTagException(“一个没有connection属性的查询标签必须被一个connection标记嵌套。”); @E%DP9.I  
K*Ks"Vx  
} &J$##B  
OX\$nQ\o  
connection = ancestorTag.getConnection(); T_LLJ}6M  
_'!kuE,*1  
} e)@3m.  
};b1ahaG  
} /7/0x ./{  
1$pb (OK  
} BMFF=  
S_ b/DO  
@0NJ{  
=lp1Z>  
此查询标签在JSP页面中的调用形式可以从以下2种定义中任选一种: ;b0NGa(k  
=-#G8L%Q  
z-r2!^q27  
<tt:connection id=”con01” ...> ... </tt:connection> r2\c'9uH  
-Q"hZ9  
<tt:query id=”balances” connection=”con01” > j}f[W [2  
HC*?DJ,  
SELECT account, balance FROM acct_table RLVAT M5  
lG:kAtx4  
where customer_num = <%= request.getCustno() %> !L$x:/R9M  
Y@uh[aS!  
</tt:query> )C~9E 5E  
Q@S-f:!  
$IX\O  
O )d[8jw"  
F #`=oM $5  
<tt:connection ...> fjG&`m#"  
wTc)S6%7  
<x:query id=”balances”> j:,9%tg  
91Z'  
SELECT account, balance FROM acct_table =(o']ZaaA  
d`y!cu2}  
where customer_num = <%= request.getCustno() %> 5,)vJ,fs  
(xpn`NA  
</x:query> *O~e T  
lDU_YEQ>  
</tt:connection> Um` !%  
W 7sn+g \  
[?0d~Q(R#  
与此同时,在TLD中必须指定connection属性为可选的,定义如下: cU.9}-)  
pUYM}&dX  
<tag> (?0`d  
>''U  
... A8r^)QJP{  
/F)H\*  
<attribute> :-T*gqj|  
-NJ!g/ >mM  
<name>connection</name> 7[pBUDA  
neZ.`"LV  
<required>false</required> u]*0;-tz  
UL$}{2N,_  
</attribute> j<<3Pr  
O`[aU%4b  
</tag>
描述
快速回复

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