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

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

级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
标准的JSP 标记可以调用JavaBeans组件或者执行客户的请求,这大大降低了JSP开发的复杂度和维护量。JSP技术也允许你自定义taglib,其实换句话说,taglib可以看成是对JSP标记的一种扩展,正如xml是对html的一种扩展一样。taglib通常定义在tag标签库中,这种标签库存放着你自己定义的tag标签。简而言之,如果使用taglib,那么你可以设计自己的JSP标记! 's e 9|:  
-5Ccuk>6  
一般来说,自定义tag标签主要用于操作隐藏对象、处理html提交表单、访问数据库或其它企业级的服务,诸如邮件和目录操作等等。自定义tag标签的使用者一般都是那些对java编程语言非常精通,而且对数据访问和企业级服务访问都非常熟悉的程序员,对于HTML设计者来说,使得他可以不去关注那些较复杂的商业逻辑,而将精力放在网页设计上。同时,它也将库开发者和库使用者进行合理分工,自定义tag标签将那些重复工作进行封装,从而大大提高了生产力,而且可以使得tag库可用于不同的项目中,完美地体现了软件复用的思想。 >`6^1j(3  
g'mkhF(  
在这篇文章中,我们主要讨论: 5Wn6a$^  
i G<|3I  
· 什么是自定义tag标签? js>6Du  
d 5Il0sG  
· 怎么使用tag标签? ?"L>jr(  
9 /9,[A  
o 声明要使用的tag库 r*WdD/r|  
x[)S3U J  
o 找到与之对应的tag处理类 =P5SFMPN  
#|'8O  
o tag标签的类型 2[W Qq)\  
K[ylyQ1  
· 自定义tag标签 C~l5D4D#  
Sm-nb*ZyC  
o tag处理类 s_RYYaM  
(Q\w4?ci  
o tag库描述 7}nOF{RH]  
/A_ IS`  
o tag标签示例 M14pg0Q  
)of_"gZ$3A  
o 带属性的tag MT0}MMr  
,x_g|J _Y  
o 带body的tag w| >Y&/IX  
/a]+xL  
o 定义了脚本变量的tag 3 \kT#nr  
`pLp+#1 `R  
o 具有协作关系的tag {8t;nsdm!  
6k ^vF~  
· 自定义tag标签 u]zb<)'_  
E fqa*,k  
o 一个迭代tag的例子 c>]_,Br~  
mNV4"lNR  
o 一个模板tag库 TsR20P@  
X.JB&~/rO  
o tag处理类到底是怎样被调用的? (2%C% #]8  
O *jNeYA  
p4t(xm2T  
什么是自定义的tag? BL]^+KnP  
S?D2`b  
一个自定义的tag标签是用户定义的一种JSP标记。当一个含有自定义的tag标签的JSP页面被jsp引擎编译成servlet时,tag标签被转化成了对一个称为tag处理类的对象进行的操作。于是当JSP页面被jsp引擎转化为servlet后,实际上tag标签被转化成为了对tag处理类的操作。 ^%\p; yhL  
(s}9N   
自定义tag标签有很多特色,诸如:  *A_  
A@`C<O ^  
· 可以在JSP页面中自定义tag标签的属性 L*FnFRhU  
d *H-l3N  
· 访问JSP页面中的所有对象 8o~\L= l  
5Lue.U%a  
· 可以动态地修改页面输出 8l?]UFM>C  
TN l$P~X>  
· 彼此这间可以相互通信。你可以先创建一个JavaBeans组件,然后在一个tag中调用此JavaBeans组件,同时可以在另一个tag中调用它。 GifD>c |z  
]bRu8kn  
· tag允许相互嵌套,可以在一个JSP页面中完成一些复杂的交互。 LxMOs Nv  
bG\1<:6B  
{0e5<"i  
使用tag标签 !vG._7lPp  
h7o{l7`)  
1P6~IZVN  
本节主要描述怎样在JSP页面中使用tag标签,以及tag标签的不同类型。 YP#OI 6u  
0{Tf;a<  
要使用tag标签,JSP程序员必须做2件事: CMTy(Z8_)  
|rNm_L2  
· 声明此tag标签的tag库 L5U>`lx6$  
HI:E&20y  
· 实现此tag标签 b"x:IDW qG  
ujwI4oj"c  
声明tag标签所在的tag库 a z`5{hK  
15SIZ:Q  
如果要使用tag标签,则应用JSP的taglib指示符来指定其tag库(注意:taglib要在在使用此tag标签之前声明) CIV6 Qe"<  
\2~.r/`1  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> 's*UU:R  
4u:{PN  
uri属性定义了唯一的标签库描述(以下简称TLD),它可以是直接是tld文件名或一个独一无二的名字。prefix是用来区别其它TLD中和本TLD中有重名的tag的一种手段。 _&yQW&vH#  
QAu^]1;  
TLD必须以.tld作为扩展名,并且存放在当前应用的WEB-INF目录或其子目录下。你可以通过它的文件名直接引用它,也可以通过别的方式间接地引用它。 k"AY7vq@!P  
HLk/C[`u,  
以下taglib指示符直接引用一个TLD: O  89BN6p  
\)r#?qn4z;  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> ,(lD5iN  
Q}I. UG_  
以下的taglib指示符通过一个逻辑名称间接地引用一个TLD: K)^.96{/@  
H#6J7\xcS  
<%@ taglib uri=”/tutorial-template” prefix=”tt” %> !n !~Bw  
smk0*m4  
如果是间接引用TLD的话,那你必须还要在web.xml中定义此逻辑名称与tld文件之间的映射,具体做法是在web.xml中加入一个名为taglib的元素: 4;%=ohD:!  
<Qwi 0$  
<taglib>  eYS  
CVu'uyy  
<taglib-uri>/tutorial-template</taglib-uri> @ '<lD*W  
=. OW sFv  
<taglib-location> *r(iegO$  
Oi7:J> [  
/WEB-INF/tutorial-template.tld M8 ++JI  
F2+lwycY  
</taglib-location> {'{ssCL  
g%^Zq"  
</taglib> h~<#1'/<  
.llAiv  
rJZ-/]Xf!6  
实现此tag标签 ]\Ez{MdAT  
mz/KGZ5t  
LG51e7_gFi  
为了实现tag标签,你有2种方法来存放tag处理类。一、让tag处理类以.class的方式存放于当前应用的WEB-INF/class子目录下,二、如果tag处理类是以JAR包的形式存在的话,那可以放在当前应用的WEB-INF/lib目录下,如果tag处理类要在多个应用中共享,那么它就应放在jsp服务器上的common/lib目录下,对于tomcat来说,就是tomcat/common/lib目录下。 n) `4*d$`  
6s>PZh  
Qza[~6  
tag标签类型 8B\,*JGY2  
_*&<hAZj  
qB"y'UW8  
自定义的tag标签遵循XML语法。它有一个开始标记和一个结束标记,有的还有body(即文本节点): i"_JF-IbN  
r\L:JTZ$  
<tt:tag> GVFD_;j'  
bx`(d@  
body 40+E#z)  
>N44&W  
</tt:tag> ? BBDk  
8vnU!r  
VRMlr.T +  
一个不带body的tag标签如下: WqwD"WX+w  
5MiWM2"X\  
<tt:tag /> qOkw6jfluh  
i"U3wt |A  
R:OoQ^c  
简单的tag标签 yp!Xwq#n  
?p\'S w:  
一个没有body和属性的tag标签如下: NW^}u~-f  
;Q-sie(#  
<tt:simple /> mo <g'|0  
hZ$* sf  
l *pCG`@J#  
带属性的tag标签 v]vrD2L  
.\< \J|3  
`/Z8mFs Y  
自定义标签可以有自己的属性。属性一般在开始标记中定义,语法为 attr=”value”。属性的作用相当于自定义标签的一个参数,它影响着tag处理类的行为。你可以在TLD中详细定义它。 ~d>O.*Q)  
w[loV  
你可以用一个String常量给一个属性赋值,也可以通过表达式给它赋值,如<%= ...%>。以struts为例,它的logic:present标签就是用的String常量来给属性赋值: JQI`9$asuC  
ijC;"j/(  
<loglic:present parameter = “Clear”> OB5{EILej  
 M3u[E  
而另一个标签logic:iterate是用表达式来给属性赋值: CYG'WFvZZ  
=]"[?a >  
<logci:iterate collection=”<%= bookDB.getBooks() %>” *:)#'cenI  
sE]eIN  
id=”book” type=”database.BookDetails”> `5h$@  
`s@1'IG;R_  
qC IZW  
带body的tag标签 OB5(4TY  
Cf8(J k`v|  
一个自定义标签可以包含其它自定义标签、脚本变量、HTML标记或其它内容。 )]rGGNF*  
R%}OZJ_  
在下述例子中,此JSP页面使用了struts的logic:present标签,如果些标签定义了parameter=”Clear”的属性,则将清除购物车的内容,然后打印出一条信息: Jd/ 5Kx  
h&[!CtPm  
<logic:present parameter=”Clear”> )V~<8/)  
DR^mT$  
<% cart.clear(); %> FL0[V,  
*}3~8fu{  
<font color=”#ff0000” size=”+2”><strong> @4hxGk=  
7;c{lQOj}  
你选择了清除购物车! ^8E/I]-  
'X{7b <  
</strong></font> %p^C,B{7w  
b(K.p?bt  
</logic:present> 3{~h Rd  
nL@P {,J  
[Fj h  
到底是用属性还是用body来传递信息? ; N!K/[p=  
k&@JF@_TI  
如上所述,我们既可以通过属性,也可以通过body来传递信息。但一般来说,比较简单的类型,如字符串或简单表达式最好采用属性来传递信息。 l&5| =  
q0SvZw]f1  
#P18vK5  
定义脚本变量的tag标签 =yfr{5}R  
7zpwP  
所谓脚本变量,是指JSP中可以调用的变量或对象。它可由tag标签产生。以下示例阐述了一个tag标签定义了一个名为tx的由JNDI所定义的事务处理对象。脚本变量可以是ejb对象、事务、数据库连接等等: 5v!Uec'+  
Km pX^Se[  
<tt:lookup id=”tx” type=”UserTransaction” name=”java:comp/UserTransaction” /> R3%T}^;f  
,O $F`0>9A  
<% tx.begin(); %> 4jO~kcad  
5+giT5K*h  
... Xs*~ [k'  
G2rxr  
C[<&% =  
具有协作关系的tag标签 :cIE8<\%  
v" y e\ZG  
自定义tag标签之间可以通过共享对象来实现协作。在下述例子中,标签tag1创建了一个名为obj1的对象,在标签tag2仍可以重复使用obj。 ml\7JW6Rx  
Je+L8TB  
<tt:tag1 attr1=”obj1” value1=”value” /> !|,=rM9x  
o %Pi;8  
<tt:tag2 attr1=”obj1” /> >8 VfijK  
\ssuO  
在以下这个例子当中,如果外层的tag标签创建了一个对象,那么其内层的所有tag标签都可以使用这个对象。由于这样产生的对象没有一个指定的名字,那么就可以将少重名的冲突。这个例子阐述了一系列协作的嵌套对象。 <&b ~(f  
V|<qO-#.  
<tt:outerTag> ';zLh  
?Q:se  
<tt:innerTag /> Y==# yNwM  
SAly~(r?/  
</tt:outerTag> |M0 XLCNd_  
hW _NARA  
+1F@vag7  
Tag处理类 es&+5  
oa1&9  
l&U3jeW-o  
Tag处理类必须实现Tag接口或BodyTag接口,不过现在一般都流行从TagSupport或BodyTagSupport类中继承,这些类或接口都可以在javax.servlet.jsp.tagext包中找到。 eHd{'J<  
[uZU p*.V  
当JSP引擎看到自己的JSP页面中包含有tag标签时,它会调用doStartTag方法来处理tag标签的开头,调用doEndTag方法来处理tag标签的结束。 oKzV!~{0M;  
3l<)|!f]g  
下表说明不同类型的tag所需要不同的处理过程: st/Tb/  
f}nGWV%,  
Tag处理类的方法 W>;AMun  
nolTvqMT  
Tag标签类型 3J%jD  
所调用的方法 T|ZT&x$z  
||9f@9  
基本标签 ?W%3>A  
doStartTag, doEndTag, release Wb/@~!+i`  
5j,)}AYO  
带属性的标签 .J&~u0g  
doStartTag, doEndTag, set/getAttribute1...N, release ",Ek| z  
JI@~FD&  
带内容的标签 tj{rSg7{  
doStartTag, doEndTag, release sfa T`q  
I`DdhMi7  
带内容的标签,且内容重复循环 +- c#UO>  
doStartTag, doAfterBody, doEndTag, release qt/"$6]%  
/xj'Pq((}p  
带内容的标签,且内容与JSP交互 y)Ip\.KV\  
doStartTag, doEndTag, release, doInitBody, doAfterBody, release \`|,wLgH  
&hjrJ/'^  
一个tag处理类可以通过javax.servlet.jsp.PageContext来与JSP交互,通过javax.servlet.jsp.PageContext类,tag处理类可以访问JSP中的request、session和application对像。 ax7u b  
ft:/-$&H  
如果tag标签是互相嵌套的,那内层的tag处理类可以通过它的parent属性来访问上层的tag处理类。 WNlWigwYl  
ls 'QfJm  
一般情况都将所有的tag处理类打成了JAR的包,以便于发布。 C @hnT<e  
6Q>:g"_  
'00DUUa  
Tag库描述(简称TLD) ax'Dp{Q  
LTBqXh  
t~,!a?S7  
Tag库是用xml语言描述的,TLD包括了tag库中所有tag标签的描述,它一般用来被jsp服务器用来校验tag的语法正确性,或者被jsp开发者用来开发新的标签。 :,]%W $f=  
tul5:}x3  
TLD的文件扩展名必须为.tld,而且必须放在当前WEB应用的WEB-INF目录或其子目录中。 - uliND  
h`&mW w  
一个TLD的内容的开头必须遵守标准的XML开头,用于描述DTD和xml的版本,例如: ]V><gZ  
%6kD^K-  
<?xml version="1.0" encoding="ISO-8859-1" ?> j%~UU0(J  
N[dhNK"  
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd"> }*IX34  
TLD必须以<taglib>来作为它的根元素,<taglib>的子元素如下表: n3~xiQ'  
)x?F1/  
:m@(S6T m  
<taglib>的子元素 ~cU,3g  
3Mr)oM< Q  
Element v\$XhOK  
Description F RS@-P  
H)t8d_^|j  
tlib-version vA(3H/)-  
Tag库的版本 %+>I1G  
9~Q.[ A  
jsp-version k3^S^Bv\  
Tag库所需要的jsp的版本 *Fp )/Ih  
tGv4 S\  
short-name ,i,f1XJ|  
助记符,tag的一个别名(可选) aMh2[I  
> YN<~z-  
uri dwB-WF%k  
用于确定一个唯一的tag库 ,B!u*  
GMB%A  
display-name CQ#p2  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) 7}TjOWC  
EQu M|4$ix  
small-icon Z78&IbR  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) /$+ifiFT  
:+!hR4Z~\;  
large-icon CO 5?UgA  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) 'DRyOJnr  
O_KL#xo  
description _oe2 pL&  
对tag库的描述(可选) mw?,oiT,)  
_g$6vx&  
listener {9_CH<$W%U  
参见下面listener元素 4`!(M]u=  
Jw"'ZW#W  
tag "sL#)<%  
参见下面tag 元素 J&{E  
 Ur]5AJ  
Listener元素 9K FWa0G  
L!-T`R8'c  
一个tag库可能定义一些类做为它的事件侦听类,这些类在TLD中被称为listener 元素,jsp服务器将会实例化这些侦听类,并且注册它们。Listener元素中有一个叫listener-class的子元素,这个元素的值必须是该侦听类的完整类名。 \CU.'|X  
-DU[dU*~  
Tag元素 'OkF.bs  
CW, Kw  
每个tag元素在tag库中都要指出它的名字、类名、脚本变量、tag的属性。其中脚本变量的值可以直接在TLD中定义或通过tag附加信息的类来取得。每个属性描述了这个属性是否可以省略,它的值是否可以通过<%= …%>这样的JSP语法来获得,以及属性的类型。 l(%bdy  
OC"W=[Myl  
每一个tag在TLD中对应一个tag元素,下表是tag元素的子元素: J"I{0>@  
^om(6JL2  
Tag元素的子元素 s.Yywy  
.i@e6JE~;  
元素名称 ECU:3KH>MF  
描述 ? 0nbvV5v7  
gQ,PG  
name /':kJOk<[  
独一无二的元素名  A5Y z|  
S :9zz  
tag-class * J~N  
Tag标签对应的tag处理类 0u -'{6  
Jr 9\j3J{  
tei-class 6S<J'9sE  
javax.servlet.jsp.tagext.TagExtraInfo的子类,用于表达脚本变量(可选) +<8r?d2  
e9N"{kDs6  
body-content &YqgMC  
Tag标签body的类型 %3'80u6BCJ  
e"[o2=v;5  
display-name V mKMj'  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) Hco [p+  
M(I 2M  
small-icon g2w0#-  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) b@z/6y!  
hPD2/M  
large-icon dhsQfWg#}  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) }3=]1jH6  
),dXaP[  
description R279=sO,J  
此tag标签的描述 d,+d8X  
>g8Tl`P,iN  
variable *%\z#Bje@  
提供脚本变量的信息(同tei-class)(可选) |BF4 F5wC?  
D{ @x  
attribute to]1QjW-  
Tag标签的属性名 GC#3{71  
b!ot%uZZ  
以下章节介绍对于不同类型的tag,如何具体地实现它们。 q\[f$==p  
>%'|@75K  
/nGsl<  
简单的tag hJ+>Xm@@!  
yH@W6'.  
I>b!4?h  
tag处理类 ON] z-  
#R'm|En'  
简单的tag处理类必须实现Tag接口的doStartTag和doEndTag方法。当jsp引擎碰到tag标签的开头时,doStartTag被调用,因为简单的tag没有body,所以此方法将返回 SKIP_BODY。当jsp引擎碰到tag标签的结尾时,doEndTag被调用,如果余下的页面还要被计算,那它将返回EVAL_PAGE,否则将会返回SKIP_PAGE。 N1+%[Uh9)  
Th'6z#h:U  
以下是例子:对于标签 <tt:simple /> ,它的tag处理类实现如下: :hCp@{  
OAR#* ~q  
7p@qzE  
public SimpleTag extends TagSupport /wH]OD{  
iK= {pd  
{ 3dQV5E.  
s?7g3H5#0k  
public int doStartTag() throws JspException f9X*bEl9;`  
yA \C3r'  
{ a 0Hzf  
pRc@0^G  
try{ _{C:aIl[2  
*:aJlvk  
pageContext.getOut().print(“Hello.”); aQ46euth  
Y(-4Agq  
}catch(Exception e){ /\_0daUx  
oCXBek?\  
throw new JspTagException(“SimpleTag: “ + e.getMessage()); rRly0H  
wh[XJ_xY  
} 11Pm lzy  
mJ)o-BV  
return SKIP_BODY; j%#n}H  
<p-R{}8  
} ' DCrSa>  
Qpe&_.&RE  
public int doEndTag() t' o:aI  
E5/-?(N  
{ M(0:>G  
pg [F{T<  
return EVAL_PAGE; 1|q$Wn:*  
)$]_;JFr  
} uIiE,.Uu}  
v<HhB.t.  
} {^1D|y  
(kK6=Mrf  
^8ZVB.Fv  
注意:如果tag标签没有内容的话,那必须定义body-content元素为空,例如 J-au{eP^  
Z)~.OqRw]  
<body-content>empty</body-content> aP>%iRk'J!  
)lTkqz8v  
Z455g/=ye  
带属性的tag标签
评价一下你浏览此帖子的感受

精彩

感动

搞笑

开心

愤怒

无聊

灌水
级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
只看该作者 1 发表于: 2007-01-01
tag处理类 W`*S?QGzl@  
Q"h/o"-h  
对于tag标签的每个属性,你必须依照JavaBeans规范来定义其属性,以及get和set方法。以struts的logic:present 标签为例, 2,{m>fF  
ypSW9n  
<logic:present parameter=”Clear”> f\c%G=y  
EQ2HQz ]  
与此相应,此tag处理类应有如下方法和定义: l4Qv$  
p ^U#1c  
M<cm]  
protected String parameter = null; 2br~Vn0N  
Ctpc]lJ}  
public String getParameter() eZ;DNZK av  
&d i=alvv1  
{ _NB8>v  
@+(a{%~7y  
return this.parameter; A =l1_8,`h  
C.Re*;EI,  
} (qg~l@rf  
nWsR;~pK  
public void setParameter(String parameter) ~)%DiGW&  
P(Z\y^S  
{ .tt=\R  
p5 )+R/  
this.parameter = parameter; T(iL#2^  
K])| V  
} vH/ Y]Am  
sZYTpZgW4L  
AW/)R"+  
注意:如果你的属性名为id,而且你的tag处理类是从TagSupport类继承的,那你就不需要定义它的属性和set和get方法,因为他们早已在TagSupport被定义过了。 *&vi3#ur  
| sZu1K  
Attribute元素 jW0aIS2O  
{p M3f  
对于tag标签的每个属性,你必须定义它是否必须的,它的值是否可以用诸如<%= …%>的表达式来获得,以及它的类型(可选),如果不指定它的类型,那就默认为是java.lang.String类型。如果rtexprvalue元素被定义为true或yes,那么在type元素中就定义了attribute的返回类型。 rK r2 K'  
jS'hs>Ot  
<attribute> GN ?1dwI  
kH>^3( Q\  
<name>attr1</name> 2Wq/_:  
Q2K)Nl >_  
<required>true|false|yes|no</required> ?8aPd"x  
~7"6Y ]  
<rtexprvalue>true|false|yes|no</rtexprvalue> d&5GkD.P  
9S$?2z".2  
<type>attribute的返回类型(只用当rtexprvalue为真是才有效)</type> TCS^nBEE  
aIABx!83>  
</attribute> Ehf3L |9   
E!v^j=h$u  
如果tag的某个属性不是必须的,那tag处理类会自动提供一个缺省值。 }doJ= lc  
G?QU|<mj<  
例如,在logic:present这个tag标签中定义了一个属性叫parameter,但它不是必须的,而且它可以被诸如<%= …%>的表达式来赋值。 TLiA>`r=  
3+| {O  
<tag> 1$a dX  
L}5IX)#gH  
<name>present</name> ,Jh('r7  
V;SXa|,  
<tag-class>org.apache.struts.taglib.logic.PresentTag</tag-class> <u85>x  
_I}rQfPJ  
<body-content>JSP</body-content> <6)  w  
~TEKxgU  
@C fxPA  
~'2im[f J  
<attribute> :i_k A'dl&  
x#s=eeP1  
<name>parameter</name> IRW%*W#  
Uv"GG: K_  
<required>false</required> 6X.lncE@p  
m+/-SG  
<rtexprvalue>true</rtexprvalue> 34P5[j!h  
qg;f h]j%  
</attribute> >f*[U/{ K  
4?a!6  
1@Zjv>jy[  
_F1{<" 4  
</tag> \PB~ 6  
'ehJr/0&g  
&JpFt^IHi  
属性元素的校验 gB?~!J?  
#j{!&4M  
wGC)gW  
有关于tag标签的有效值可以从tag库的说明文档中获得,当JSP页面被编译时,jsp引擎会强制性地参照TLD中定义的规则进行检查。 ]8XY "2b  
]'UO]i/  
还有一个方法也可以进行属性元素的校验,就是先继承类TagExtraInfo,然后调用它的isValid方法。这个类同时也起到提供tag中定义的脚本变量信息的作用。 U-#t&yjh#  
{m/\AG)1I  
IsValid方法通过TagData对象来传递属性信息,它包括着tag的所有的属性名-值的信息。由于校验发生在运行时刻,因此这个属性的值将被赋值为TagData.REQUEST_TIME_VALUE。 $I7/FZP  
NgnHo\)  
例如tag标签<tt:twa attr1=”value1” />在TLD中定义如下: $MmCh&V  
fr0iEO_  
<attribute> Hop$w  
kxg]sr"  
<name>attr1</name> PIuk]&L^  
dsP1Zq  
<required>true</required> `1NxS35u  
h !~u9  
<rtexprvalue>true</rtexprvalue> J(\"\Z  
gq6C6   
</attribute> IA|V^Wmt;  
'wAO Y  
.d5|Fs~B  
这个定义说明了attr1能在运行期间被赋值。 OjCT*qyU<  
=De%]]>   
以下的isValid方法检查attr1属性的值是否属于Boolean类型。注意由于attr1能在运行刻被赋值,那么isValid方法必须检查tag用户是否对此tag进行了运行时刻赋值。 &DFe+y~PR  
X?b]5?K;r  
~4wbIE_r N  
Public class TwaTEI extends TagExtraInfo Lrr^obc  
(9BjZ&ej  
{ Wx&AY"J  
Oah}7!a)  
public boolean isValid(Tagdata data) <GShm~XD2  
1{%EQhNd  
{ XQ<2(}]4  
B7TA:K  
Object o = data.getAttribute(“attr1”); 6:B[8otQ  
,{7wvXP  
If(o != null && o != TagData.REQUEST_TIME_VALUE) 7g5sJj  
0K, *FdA  
{ ~fs{Ff'  
K$Y!d"D  
if( ( (String)o).toLowerCase().equals(“true”) || Nora<  
A5Yfm.Jy  
((String)o).toLowerCase().equals(“false”) ) @4h .?  
MyuFZ7Q4$  
return true; 'M+iVF6  
>  K,Q`sS  
else W)V"QrFK  
qSMST mnQ  
return false; -zHJ#  
Y{@ez  
} p0uQ>[NV0  
?D\6CsNp(2  
else D(}v`q{Y  
/bVU^vo  
return true; a`GoNh,  
hti)<#f  
} A;w,m{9<  
bWwc2##7jo  
} tp_*U,  
uFb&WIo1  
2M= gpy  
带body的tag >mT2g  
KCDEMs}}zM  
Oh~J yrZy  
tag处理类 RMmDcvM"k  
+QuaQ% lA  
(<(8(} x  
如果tag标签含有内容,那处理方式会略微有些不同,而且还要视tag处理类是否要与body交互的情况而定。如果要与body交互,那我们认为tag处理类要可能要对body进行操作。 D>~z{H%\  
xgL*O>l)  
Tag处理类不与body交互 UbJ_'>hK6  
*xM4nUu<~  
如果tag处理类不与body交互,tag处理类应该实现Tag接口或从TagSupport中派生,如果body要被计算,那么doStartTag方法应返回 EVAL_BODY_INCLUDE,否则应返回SKIP_BODY。 1'R]An BV  
?H0 #{!s  
如果tag处理类要对body反复运算,则它应该实现IterationTag或从TagSupport中派生。如果tag处理类认为body还未计算完的话,那它的doStartTag方法和doAfterBody方法必须返回EVAL_BODY_AGAIN。 d"Hh9O}6  
jw5Bbyk  
Tag处理类与body交互 yiSv#wD9  
|JSj<~1ki  
如果tag处理类与body交互,那tag处理类应实现BodyTag接口或从BodyTagSupport中派生。这种tag处理类一般要实现doInitBody和doAfterBody方法。 Obrv5 %'  
5"c#O U  
Body允许一些方法来读写它的内容。Tag处理类可以调用body内容的getString或getReader方法来从body中提取信息,也可用 writeOut(out) 方法来将body的内容写入到out对象中。其中out对象通过tag处理类的getPreviousOut方法来获得。 I/<aY*R4  
0tC+?  
如果body的内容需要被计算,那么doStartTag方法必须返回EVAL_BODY_BUFFERED,否则,它将返回 SKIP_BODY。 N{tNe-5  
bB->\  
doInitBody 方法 |(*ReQ?=  
O2us+DhQ  
此方法在body内容已经设好,但未被计算之前被调用。你可以根据不同的body内容来制定初始化策略。 :xm, Ok  
PiMh]  0  
doAfterBody方法 AwAUm 2^  
A|I7R -  
此方法在body内容已被计算后进行调用。 ^0R.'XL  
kTT!gZP$  
和doStartTag方法一样,doAfterBody方法返回一个指示符指示是否要继续计算body,如果要继续计算,则doAfterBody应返回EVAL_BODY_BUFFERED,否则,它应返回SKIP_BODY。 "Up3W%]SB  
xJa  
release 方法 ?gY^,Ckj  
?V4?r2$c  
tag处理类调用此方法将它的状态重置为初始状态,并释放所有的私有资源。 c]v $C&FX  
)AEJ` xC  
 btJ:Wt}  
以下的例子读取body的内容(其中含有一条sql语句),然后将它传递给一个对象,让它进行查询。由于此处body不须重新计算,所以doAfterBody会返回SKIP_BODY。 #;)Oi9{9;  
%(MaH  
) kfA5xi[  
Public class QueryTag extends BodyTagSupport WolkW:(Cg  
NGOc:>}k>  
{ ARGtWW~:  
n#Q;b Sw  
public int doAfterBody() throws JspTagException __fa,kK{?  
U$&G_&*0a  
{ Ly"u }e  
l E=(6Q  
BodyContent bc = getBodyContent(); LuM:dJ  
T!0o(Pp<  
//将body的内容以字符串的格式提取出来 Hm!ffqO_  
?& qMC  
String query = bc.getString(); XZD9vFj1Z  
0}C> e`<'  
//清除body thy)J.<J  
dQT A^m  
bc.clearBody(); 1O]'iS"  
 S {oW  
try{ 8yij=T*  
VW:WB.K$  
Statement stmt = connection.createStatement(); AiKja>Fl<  
cH%qoHgx  
Result result = stmt.executeQuery(query); W/DSj :  
XVr>\T4  
}catch(SQLException e){ _uwM%M;  
h_#x@p  
throw new JspTagException(“queryTag: “ + e.getMessage() ); sQUJ]h  
yw2Mr+9I  
return SKIP_BODY; P'%#B&LZo  
5x856RQ'  
} g@0<`g  
+yYxHIOZ(  
} ;w>Dqem  
KZrg4TEVi  
011 N  
body-content元素 x-27rGN  
_=0%3Sh  
E)w6ZwV  
由于tag可能会有body,你必须用body-content元素来指定body内容的类型: #J=^CE  
"/H B#  
<body-content>JSP|tagdependent</body-content> U}f"a!  
X 4L"M%i  
)(b, v/:  
如果body的内容是定制的或内部的tag、脚本元素、或HTML广本,则归类为JSP类型。其他的类型,比如上面代码所述的?D?D将sql statement类传给 query tag的这种类型应该标为tagdependent。 JTGA\K  
9dS<^E(ZF  
注意:实际上body-content的值并不影响tag处理类对body内容的处理,它仅仅是被tag编辑工具用来描述此body的内容。 03N|@Tu  
?{=& Ro  
RJ}%pA4I  
用tags定义脚本变量 <&w(%<;  
M2Q*#U>6r  
eBT+|  
tag处理类 !m]_tB  
YQ? "~[mL  
ZG(.Q:1  
tag处理类负责创建或设置页面中定义的脚本变量,用pageContext.setAttribute(name,value,scope)或pageContext.setAttribute(name,value)方法来实现。一般来说,tag处理类通过脚本变量的名称来获取它,脚本变量的名称一般可用get方法来获得。 d23;c )'  
I{nrOb1G(  
如果脚本变量的值依赖于tag处理类中的上下文中某一对象,那它可用pageContext.getAttribute(name,scope)方法来找到那个对象。一般的处理过程是tag处理类先找到脚本变量,再对其进行处理,然后用pageContext.setAttribute(name,object)的方法来设置它的新值。 g \.O5H9Od  
 N>V\  
对象的生存周期(scope)如下表: DP@F-Q4  
`@<>"ff#F  
对象的生存周期表 pu-X -j  
Pzt 5'O@dA  
名字 3A&: c/  
可访问范围 x*'2%3C~  
生存周期 g9~QNA  
4De2m iq  
page q%S^3C&  
当前页面 z:1"d R   
一直有效,除非页面向客户提交响应或重定向到一个新页面 R1cOUV,y[/  
$y$E1A6h+  
request $G<!+^T  
当前页面或当前页面重定向到的页面 aM5Hp>'nI  
一直有效,除非页面向客户提交响应 D[p_uDIz  
5M v<8P~  
session MA1y@  
当前页面或在同一浏览器窗口中的页面 b?U2g?lN:  
一直有效,除非关闭当前浏览器、超时、网络故障 W?H-Ng3E  
V}aZ}m{J  
application zhZ!!b^6<  
整个web应用程序的所有请求 a&z$4!wQB  
一直有效,除非发生网络故障、服务器故障 \"7U,y',  
9Zj9e  
提供关于脚本变量的信息 )+ (GE  
1j_ 6Sw(  
以下示例定义了一个名为“book”的脚本变量,用来访问程序中关于书的信息: <Z j>}  
0/5{v6_rG  
<bean:define id=”book” name=”bookDB” property=”bookDetails” type=”database.BookDetails” /> Xmny(j)g  
Ud:;kI%Vj  
<font color=”red” size=”+2” > dbG902dR  
 9dCf@5]  
<%= messages.getString(“CartRemoved”) %> GHR r+  
7Z< 2`&c7  
<strong><jsp:getProperty name=”book” property=”title” /></strong> M@]@1Q.p  
.b|!FWHNS  
</font> U|~IJU3-  
s 9n_s=w  
当包含此tag的JSP页面被编译时,jsp引擎会自动生成关于此book的同步的代码(同步可以避免几个客户同时访问此book时造成的冲突),要生成同步代码,jsp引擎需要知道此脚本变量的如下信息: ' OXL'_Xl  
{d '>J<Da  
· 脚本变量名称 BHf7\ +Ul  
G'T: l("l  
· 脚本变量所属的类 K3^2;j1F Q  
{k uC+~R  
· 此脚本变量是否引用了一个新的或已存在的对象 z P8rW5/  
sTmdoqTK!  
· 此脚本变量的有效性 8 3Tv-X  
M@=VIrX,m  
有两种办法可以向jsp引擎提供关于脚本变量的信息:在TLD中定义variable子元素,或用tei-class子元素定义一个额外tag信息类。用variable最简单,但可能降低了一些灵活性。 +>QD4z#  
RjxFlKs8  
Variable元素 |.?$:D&6  
y:YJv x6&4  
Variable元素有如下子元素: 4Z0Y8y8)  
xM:9XhH1  
· name-given ?D?D 给出的名字,是一个常量 H~; s$!lG  
avb'dx*q>  
· name-from-attribute?D?D 属性名,在编译时给出的属性名 | Zj=E$  
/s Bs eI  
name-given或name-from-attribute两者必须选一,但以下子元素是可选的: b[^|.>b  
dmYgv^t  
· variable-class?D?D变量的类型,缺省为java.lang.String。 ! i8'gq'q  
%\B@!4]  
· declare?D?D此脚本变量是否引用了一个新对象,缺省为True。 " +A8w  
^WUG\@B  
· scope?D?D脚本变量的范围,缺省为NESTED。下表描述了scope的几种类型: 5Ve T8/7Q  
;Dp<|n  
脚本变量的有效范围 ^=arKp,?5  
@n;$Edza/  
jJ3dZ<#  
有效性 u}|+p+  
方法 _ q^JjR  
W3A9uk6  
NESTED fjLS_Q ;h  
在tag标签的开始和结束之间 Xcb'qU!2-^  
如果tag处理类实现BodyTag接口,则在doInitBody和doAfterBody中调用,否则在doStartTag中调用 cd.|>  
/TScYE:$HE  
AT_BEGIN <P_B|Y4N/  
从tag标签的开始一直到页面结束 zRFvWOxC\  
如果tag处理类实现BodyTag接口,则在doInitBody、doAfterBody和doEndTag中调用,否则在doStartTag和doEndTag中调用 g]9A?#GyE  
pwmH(94$0  
AT_END bG/[mZpRT  
从tag标签的结束一直到页面结束 .&rL>A2U  
在doEndTag中调用 ; mwU>l,4  
~IQw?a.E  
以struts为例,它的bean:define标签的实现遵循JSP1.1规范,此规范要求使用额外tag信息类来定义脚本变量。Variable元素是JSP1.2规范中加入的。以bean:define标签为例,你可以定义如下variable元素: /{!?e<N>  
z K6'wL!!I  
<tag> u5A$VRMN  
=6xxZy[  
<variable> 1? Im"  
]L_h3Xz\X  
<name-from-attribute>id</name-from-attribute> u .,l_D_  
b$N&sZ  
<variable-class>database.BookDetails</variable-class> 94xWMX2  
^gY3))2_  
<declare>true</declare> WoWmmZ  
Pvz\zRq  
<scope>AT_BEGIN</scope> ,XYtoZa  
Mb'Tx  
</variable> KVp3 pUO  
e2"gzZ4;g  
</tag> n0opb [?  
E\vW>g*W  
额外tag信息类 T*qSk!  
!c;BOCqa  
如果要定义一个额外tag信息类,你要继承javax.servlet.jsp.TagExtraInfo类。一个TagExtraInfo类必须实现getVariableInfo方法,此方法返回一个叫VariableInfo的数组类,它包括如下信息: ,m1F<Pdts  
h.)o4(bO  
· 变量名 CQ:38l\`gd  
QN^AihsPi  
· 变量所属类名 qORRpWyx&  
xMHu:,ND  
· 此变量是否引用了一个新对象 e<r}{=1w  
UOcO\EA+  
· 此变量的有效范围 ( !0fmL  
[6f(3|"  
jsp引擎将一个名为data的参数传给getVariableInfo方法,data中包括tag标签中的所有“属性名?D?D属性值”对。它可以用来向VariableInfo对象提供脚本变量的名字和类名。 #?fKi$fS;L  
}S6"$R  
以struts为例,它在bean:define标签中定义了一个名为DefineTei的额外tag信息类,用来向脚本变量提供信息。由于脚本变量的名称(book)和类名(database.BookDetails)是通过tag标签的属性来传递的,它们一般定义在VariableInfo的构建代码中,并且可用data.getAttributeString方法来得到这些信息。如果要允许book脚本变量能在从tag开始直到整个JSP页面结束的范围内都可用的话,那它的范围应设为AT_BEGIN。如下所示: I3d!!L2ma  
@aUQy;  
s}bv o  
public class DefineTei extends TagExtraInfo LyG&FOf?  
L<0eIw  
{ #T$yQ;eQ  
rVv4R/3+   
public VariableInfo[] getVariableInfo(TagData data) w=QW8q?  
G!.%Qqs  
{ H1-eMDe  
@w73U; 9\  
String type = data.getAttributeString(“type”); VQ^}f/A  
wAF<_NG#  
If( type == null) ?C(3TKH  
o+F < r#  
type = “java.lang.Object”; [(m+Ejzi%  
I8Q!`K J  
return new VariableInfo[] { @ ('/NjTZ  
ZiaHLpk  
new VariableInfo(data.getAttributeString(“id”), f]48>LRE8  
XB;C~:  
type, rObg:(z&\  
AI#.G7'O  
true, +jb<=ERV[  
0$=w8tP)  
VariableInfo.AT_BEGIN) )6*)u/x:  
S,vh  
}; Qm>2,={h  
tA{h x -  
} v4vIcHDs  
):7mK03J  
} .qS(-7<  
hj,yl&  
NM+ (ss'  
注意:关于额外tag信息类的类名必须要在TLD中的tag标签下的tei-class子元素中定义。因此,DefineTei的tei-class中的定义看起来如下: v \dP  
<tei-class> x Tf|u  
org.apache.struts.taglib.bean.DefineTagTei (D2N_l(`<  
</tei-class> 2Z+:^5  
_&e$?hY  
~PyZh5x  
具有协作关系的tag :: s k)  
\S0QZQbz/  
>hO9b;F}  
tag通过共享对象来进行协作,JSP技术支持2种方式的对象共享。 Mb=j'H<N@  
L\xR<m<,  
第一种方法是使用pageContext对象进行对象的共享(可支持JSP页面和tag处理类之间的共享),如果在一个tag处理类中要调用由另一个tag处理类创建的对象,可调用pageContext.getAttribute(name, scope)方法。 Yht |^ =a  
'$5Qdaj  
第二各方式的共享是对于tag之间有嵌套关系而言的,外层的tag所创建的对象对于内层的tag来说是可以共用的。这种形式的共享的好处是减少了可能存在的重名冲突。 zKfY0A R  
c7A]\1 ~  
要访问一个嵌套tag创建的对象,tag处理类必须先找到此嵌套tag对象,可用TagSupport的静态方法 TagSupport.findAncestorWithClass(from, class)或TagSupport.getParent方法。前者在当不确定此tag是否为嵌套tag对象时使用。一旦它的父类被找到,它就能访问其所有动态或静态创建的对象。静态创建的对象是父类的成员,而动态创建的对象可能是父类的私有对象。诸如此类的对象可以用tag处理类的setValue方法来保存,用getValue方法来获得。 nQ#NW8*Fs  
D[dI_|59a  
下例阐述了以上两种共享对象的方法。在这个例子当中,一个查询tag检查一个名为connection的属性名是否在doStartTag中被设置。如果connection属性被设置,tag处理类从pageContext中得到这个connection对象。否则,此tag处理类先找到它的父tag处理类,然后从它的父tag处理类中找到connection对象。 GDYFhH7H  
S,f:nLT  
\.YJs"<3  
public class QueryTag extends BodyTagSupport /YHnt-}v,  
P c'\  
{ }aL&3[>>  
) u1=, D  
private String connectionId; B^Hh rz!  
ak\[+wQ  
public int doStartTag() throws JspException RG:_:%@%}  
pkc*toW  
{ |?t}7V#[  
!+ (H(,gI  
String cid = getConnection(); Dlg9PyQ  
%ZX3:2  
if(cid != null) d "25e"(~F  
b1EY6'R2  
{ A8 !&Y;d  
7*>,BhF#  
//存在一个connection id,使用它。 4VhKV JX  
A().1h1_k  
connection = (Connection) pageContext.getAttribute(cid); Bh;N:{&^Eu  
7n7UL0Oc1  
} %[on.Q'1]2  
krRnE7\m  
else WNSEc%  
~0rvrDDg  
{ d$y?py  
T:g%b @  
ConnectionTag ancestorTag = (ConnectionTag)findAncestorWithClass(this, p21li}Iu  
B?9"Ztb  
ConnectionTag.class); Z  GrDa  
JhvT+"~  
if(ancestorTag == null) aa}U87]k  
i4m P*RwC  
{ 9>= S@hVMd  
6Oy6r  
throw new JspTagException(“一个没有connection属性的查询标签必须被一个connection标记嵌套。”); n@J>,K_B  
EAoq2_(`a  
} <MJ-w1A  
ne%(`XY{Q]  
connection = ancestorTag.getConnection(); DK1{Z;Z  
LeYI<a@n@$  
} /]2I%Q  
Se>v|6  
} Y^eF(  
]3uj~la  
} WTu!/J<\  
.\8LL,zT  
5 Q,j+  
r ?z}TtDp  
此查询标签在JSP页面中的调用形式可以从以下2种定义中任选一种: Mg&<W#$K  
t?Q  
1i;Cw/mr  
<tt:connection id=”con01” ...> ... </tt:connection> fYlqaO4[  
bd[iD?epD]  
<tt:query id=”balances” connection=”con01” > rLA^ &P:  
ynJ)6n7a  
SELECT account, balance FROM acct_table K;]Dh?  
f{h2>nEj \  
where customer_num = <%= request.getCustno() %> ~|{_Go{ Q  
'rrnTd c  
</tt:query> q oEZ>  
ps33&  
qyjVB/ko  
,_ @) IN  
|Rz}bsrZ  
<tt:connection ...>  p]jG ,S  
7Ac.^rv5  
<x:query id=”balances”> YTg8Zg-Z  
E5\>mf ,;u  
SELECT account, balance FROM acct_table !w/]V{9`X  
Ss:'H H4  
where customer_num = <%= request.getCustno() %> G> s qfYkK  
O6ltGtF  
</x:query> K6,d{n  
C|]Zpn#{K  
</tt:connection> fC/P W`4Ae  
k=X)ax t1  
yO@@-)$[y  
与此同时,在TLD中必须指定connection属性为可选的,定义如下: QV -ZP'e^  
<3x:nH @  
<tag> y2nT)nL  
\"d\b><R  
...  WfQZ7e  
Fe2t[y:8h  
<attribute> <2wC)l3j*  
TRr%]qd{Hr  
<name>connection</name> #-l+c u{  
dwb^z+   
<required>false</required> \)W Z D  
cDz^jC   
</attribute> /1eeNbd  
lInf,Q7W  
</tag>
描述
快速回复

您目前还是游客,请 登录注册
批量上传需要先选择文件,再选择上传
认证码:
验证问题:
3+5=?,请输入中文答案:八 正确答案:八