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

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

级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
标准的JSP 标记可以调用JavaBeans组件或者执行客户的请求,这大大降低了JSP开发的复杂度和维护量。JSP技术也允许你自定义taglib,其实换句话说,taglib可以看成是对JSP标记的一种扩展,正如xml是对html的一种扩展一样。taglib通常定义在tag标签库中,这种标签库存放着你自己定义的tag标签。简而言之,如果使用taglib,那么你可以设计自己的JSP标记! >8/Otg+h  
D zD5n  
一般来说,自定义tag标签主要用于操作隐藏对象、处理html提交表单、访问数据库或其它企业级的服务,诸如邮件和目录操作等等。自定义tag标签的使用者一般都是那些对java编程语言非常精通,而且对数据访问和企业级服务访问都非常熟悉的程序员,对于HTML设计者来说,使得他可以不去关注那些较复杂的商业逻辑,而将精力放在网页设计上。同时,它也将库开发者和库使用者进行合理分工,自定义tag标签将那些重复工作进行封装,从而大大提高了生产力,而且可以使得tag库可用于不同的项目中,完美地体现了软件复用的思想。 U LS>v  
B!mHO*g  
在这篇文章中,我们主要讨论: 3PkZXeH/  
|"K%Tvxe  
· 什么是自定义tag标签? {*;8`+R&  
7l7VT?<:  
· 怎么使用tag标签? _1?uAQ3,  
29grbP  
o 声明要使用的tag库 HKbV@NW  
R'Ue>k  
o 找到与之对应的tag处理类 KAZ<w~55c  
:uAL(3pQ  
o tag标签的类型 (^W}uDPCB  
cS Lj\'`b  
· 自定义tag标签 q5r7 KYH{  
q+[ )i6!?  
o tag处理类 .=YV  
g5#LoGc  
o tag库描述 +F NGRL  
;uAh)|;S#  
o tag标签示例 >e;jGk?-  
/ xv5we~  
o 带属性的tag 1 K}gX>F  
~Q=;L>Qd  
o 带body的tag 97 SS0J  
5@l5exuG*m  
o 定义了脚本变量的tag #CLjQJ  
:g$"Xc8Zn  
o 具有协作关系的tag wxB HlgK4z  
s:'>G;p  
· 自定义tag标签 >&HW6 c  
8L:AmpQdpA  
o 一个迭代tag的例子 mKtMI!FR  
U;3t{~Ym  
o 一个模板tag库 }o]}R#|  
A)~ oD_ooQ  
o tag处理类到底是怎样被调用的? ;F1y!h67<  
xpp nBnu$7  
+8ib928E  
什么是自定义的tag? $G <r2lPy  
[<i3l'V/[  
一个自定义的tag标签是用户定义的一种JSP标记。当一个含有自定义的tag标签的JSP页面被jsp引擎编译成servlet时,tag标签被转化成了对一个称为tag处理类的对象进行的操作。于是当JSP页面被jsp引擎转化为servlet后,实际上tag标签被转化成为了对tag处理类的操作。 5 `TMqrk  
M>=@Z*u/+  
自定义tag标签有很多特色,诸如: ZzK^ bNx)0  
RUr ~u  
· 可以在JSP页面中自定义tag标签的属性 zU[o_[+7^  
dlyGgaV*X  
· 访问JSP页面中的所有对象 fwUvFK1G  
x]YzVJ=Y  
· 可以动态地修改页面输出 b,:^\HKC  
#<Y3*^~5d  
· 彼此这间可以相互通信。你可以先创建一个JavaBeans组件,然后在一个tag中调用此JavaBeans组件,同时可以在另一个tag中调用它。 3VU4E|s>  
hTO5*5]0zP  
· tag允许相互嵌套,可以在一个JSP页面中完成一些复杂的交互。 5Kd"W,  
t0cS.hi  
sh,4n{+  
使用tag标签 RCa1S^.  
W8`6O2  
hwk] ;6[  
本节主要描述怎样在JSP页面中使用tag标签,以及tag标签的不同类型。 M%54FsV  
W`LG.`JW  
要使用tag标签,JSP程序员必须做2件事: \="U|LzG  
:BR_%$  
· 声明此tag标签的tag库 851BOkRal4  
`dF~'  
· 实现此tag标签 N/lEfy<&g:  
LV9R ]  
声明tag标签所在的tag库 ({Yfsf,  
~9rNP{+  
如果要使用tag标签,则应用JSP的taglib指示符来指定其tag库(注意:taglib要在在使用此tag标签之前声明) D4"<suU|.  
Otr=+i ZI  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> :?EZ\WM7  
Lm!]m\LRZD  
uri属性定义了唯一的标签库描述(以下简称TLD),它可以是直接是tld文件名或一个独一无二的名字。prefix是用来区别其它TLD中和本TLD中有重名的tag的一种手段。 ox<6qW  
C:&Sk\   
TLD必须以.tld作为扩展名,并且存放在当前应用的WEB-INF目录或其子目录下。你可以通过它的文件名直接引用它,也可以通过别的方式间接地引用它。 wGMoh.GTh  
;*K;)C  
以下taglib指示符直接引用一个TLD: XU<owk  
h('5x,G%  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> !m=Js"  
GYy8kp84  
以下的taglib指示符通过一个逻辑名称间接地引用一个TLD: ~ecN4Oo4q;  
?.ObHV*k  
<%@ taglib uri=”/tutorial-template” prefix=”tt” %> x_8sV?F  
 \aof  
如果是间接引用TLD的话,那你必须还要在web.xml中定义此逻辑名称与tld文件之间的映射,具体做法是在web.xml中加入一个名为taglib的元素: 6qQ_I 0f  
\+Qd=,!i(  
<taglib> V!*1F1  
[< 9%IGH  
<taglib-uri>/tutorial-template</taglib-uri> fb0)("_V  
%qJgtu"8  
<taglib-location> Qu/f>tJN;  
_&G_SNa  
/WEB-INF/tutorial-template.tld +5-|6  
6f0o'  
</taglib-location> >8{{H"$;(  
bCTN^  
</taglib> 3 P75:v  
O|Vc  
D\ZH1C!d  
实现此tag标签 Tw%1m  
Z;u3G4XlF  
w?3ww7yf`  
为了实现tag标签,你有2种方法来存放tag处理类。一、让tag处理类以.class的方式存放于当前应用的WEB-INF/class子目录下,二、如果tag处理类是以JAR包的形式存在的话,那可以放在当前应用的WEB-INF/lib目录下,如果tag处理类要在多个应用中共享,那么它就应放在jsp服务器上的common/lib目录下,对于tomcat来说,就是tomcat/common/lib目录下。 _"H\,7E  
&RuTq6)r  
$uwz` N:  
tag标签类型 b'FTy i  
m0 W3pf  
lZkJ<*z#  
自定义的tag标签遵循XML语法。它有一个开始标记和一个结束标记,有的还有body(即文本节点): ?t}s3P!Q3w  
]) v61B  
<tt:tag> IrRe6nf@K  
F `F|.TX  
body Y1AZ%{^0a  
7uUq+dp  
</tt:tag> C\Ob!sv%H  
`CL\-  
d@8: f  
一个不带body的tag标签如下: 247vU1  
`6YN/"unfp  
<tt:tag /> 1NTx?JJfW  
@yQ1F> t  
xU{0rM"  
简单的tag标签 dB&<P[$+8  
FKe/xz  
一个没有body和属性的tag标签如下: ,T ^A?t  
DqI"B  
<tt:simple /> 2w~Vb0  
8"LM:0x  
[EVyCIcY,h  
带属性的tag标签 C>-}BeY!  
S,,Wb &A$  
iB~dO @  
自定义标签可以有自己的属性。属性一般在开始标记中定义,语法为 attr=”value”。属性的作用相当于自定义标签的一个参数,它影响着tag处理类的行为。你可以在TLD中详细定义它。 S<*1b 6%D  
uHZjpMoM  
你可以用一个String常量给一个属性赋值,也可以通过表达式给它赋值,如<%= ...%>。以struts为例,它的logic:present标签就是用的String常量来给属性赋值: 'm<L}d  
]A+t@/k  
<loglic:present parameter = “Clear”> EronNtu8i  
X=Y(,ZR(&  
而另一个标签logic:iterate是用表达式来给属性赋值: o8A8fHl  
wvxqgXnB\  
<logci:iterate collection=”<%= bookDB.getBooks() %>” KB~`3Wj|Z  
 *ni0.  
id=”book” type=”database.BookDetails”> " :[;}f;  
,s}7KE  
*.A-UoHa  
带body的tag标签 (KvN#d 1\  
%Zfh6Bl\X  
一个自定义标签可以包含其它自定义标签、脚本变量、HTML标记或其它内容。 U3M;{_g  
5ff5M=M  
在下述例子中,此JSP页面使用了struts的logic:present标签,如果些标签定义了parameter=”Clear”的属性,则将清除购物车的内容,然后打印出一条信息: 1} _<qk9  
1?"Zrd  
<logic:present parameter=”Clear”> \O~WMN  
?}uvpB1}  
<% cart.clear(); %> \|4F?Y  
p2O[r  
<font color=”#ff0000” size=”+2”><strong> 1b7?6CqV  
P=E10  
你选择了清除购物车! TL -AL tG  
KZ=5"a  
</strong></font> V.+a}J=Cw  
Fy>g*3  
</logic:present> E3x<o<v  
:a=]<_*x  
Ir- 1@_1Q  
到底是用属性还是用body来传递信息? sP9{tk2K  
.7Pp'-hK  
如上所述,我们既可以通过属性,也可以通过body来传递信息。但一般来说,比较简单的类型,如字符串或简单表达式最好采用属性来传递信息。 DU5rB\!.~  
^|!\IzDp  
e-xT.RnQ  
定义脚本变量的tag标签 AXo)(\  
G!D~*B9 G  
所谓脚本变量,是指JSP中可以调用的变量或对象。它可由tag标签产生。以下示例阐述了一个tag标签定义了一个名为tx的由JNDI所定义的事务处理对象。脚本变量可以是ejb对象、事务、数据库连接等等: 6@d/k.3p  
96gaun J  
<tt:lookup id=”tx” type=”UserTransaction” name=”java:comp/UserTransaction” /> xo-{N[r  
]N1,"W}  
<% tx.begin(); %> hbx+*KM  
,oEAWNbgQ  
... b$*G&d5  
Jcp=<z*0  
daf-B-  
具有协作关系的tag标签 ,z((?h,nm  
e)L!4Y44K  
自定义tag标签之间可以通过共享对象来实现协作。在下述例子中,标签tag1创建了一个名为obj1的对象,在标签tag2仍可以重复使用obj。 q#8z%/~k  
!:_krLB<  
<tt:tag1 attr1=”obj1” value1=”value” /> !l9 #a{#6l  
6Tq2WZ}<'  
<tt:tag2 attr1=”obj1” /> Pi%-bD/w  
V Kc`mE  
在以下这个例子当中,如果外层的tag标签创建了一个对象,那么其内层的所有tag标签都可以使用这个对象。由于这样产生的对象没有一个指定的名字,那么就可以将少重名的冲突。这个例子阐述了一系列协作的嵌套对象。 O=u.J8S2  
:19s=0  
<tt:outerTag> {D]I[7f8Ev  
N B8Yn\{B  
<tt:innerTag /> u)D!RhV&  
7i=ER*F~  
</tt:outerTag> SS;'g4h\6  
+~;#!I@Di  
!_&;#j](  
Tag处理类 On+0@hh  
j{m{hVa  
S2=x,c$  
Tag处理类必须实现Tag接口或BodyTag接口,不过现在一般都流行从TagSupport或BodyTagSupport类中继承,这些类或接口都可以在javax.servlet.jsp.tagext包中找到。 RS7J~Q  
Vl:M6d1  
当JSP引擎看到自己的JSP页面中包含有tag标签时,它会调用doStartTag方法来处理tag标签的开头,调用doEndTag方法来处理tag标签的结束。 (g tOYEqx  
MR* % lZpB  
下表说明不同类型的tag所需要不同的处理过程: (Q|Y*yI  
woU3WS0  
Tag处理类的方法 r6+IJxUd  
8ePzU c\#  
Tag标签类型 HDhG1B"NL  
所调用的方法 EOGz;:b&  
+C4NhA2  
基本标签 q(5  
doStartTag, doEndTag, release Lo9 \[4FP  
h*mKS -TC  
带属性的标签 z9zo5Xc=  
doStartTag, doEndTag, set/getAttribute1...N, release lF$$~G  
p"n3JV.~k+  
带内容的标签 m&Y?]nbq  
doStartTag, doEndTag, release w`Rt"d_B  
tQ2S*]"f  
带内容的标签,且内容重复循环 W6yz/{Rf  
doStartTag, doAfterBody, doEndTag, release / DS T|2  
x=1Sbs w{  
带内容的标签,且内容与JSP交互 pzDz@lAwR  
doStartTag, doEndTag, release, doInitBody, doAfterBody, release V##TG0  
O$Dj_R#  
一个tag处理类可以通过javax.servlet.jsp.PageContext来与JSP交互,通过javax.servlet.jsp.PageContext类,tag处理类可以访问JSP中的request、session和application对像。 J]&nZud`  
2u} ns8wn  
如果tag标签是互相嵌套的,那内层的tag处理类可以通过它的parent属性来访问上层的tag处理类。 ^cojETOv  
/5:qS\Zl  
一般情况都将所有的tag处理类打成了JAR的包,以便于发布。 @])}+4D(S  
35SL*zS@-  
'G3|PA7v  
Tag库描述(简称TLD) X'cm0}2  
~rbJtz  
 p;vrPS  
Tag库是用xml语言描述的,TLD包括了tag库中所有tag标签的描述,它一般用来被jsp服务器用来校验tag的语法正确性,或者被jsp开发者用来开发新的标签。 c=IjR3F  
PW-sF  
TLD的文件扩展名必须为.tld,而且必须放在当前WEB应用的WEB-INF目录或其子目录中。 p/jAr+XM  
9Cw !<  
一个TLD的内容的开头必须遵守标准的XML开头,用于描述DTD和xml的版本,例如: v/G^yZa  
??Dv\yLZI  
<?xml version="1.0" encoding="ISO-8859-1" ?> Ozc9yy!%  
ze#ncnMo  
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd"> M`@Es#s  
TLD必须以<taglib>来作为它的根元素,<taglib>的子元素如下表: V8z*mnD  
{?uswbk.  
^}hSsE  
<taglib>的子元素 x1QL!MB  
Ua>.k|>0  
Element V5]\|?=  
Description rK cr1VFy  
au7@-_  
tlib-version bY=Yb  
Tag库的版本 z-h7v5i"  
yc@ :*Z  
jsp-version bKPjxN?!9  
Tag库所需要的jsp的版本 #r80FVwiD  
G4,BcCPQ  
short-name .J9\Fr@  
助记符,tag的一个别名(可选) 8"x\kSMb  
h,2?+}Fn  
uri H~ =;yy  
用于确定一个唯一的tag库 4' <y  
C3 (PI,,  
display-name BlfW~l'mx  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) c *Pt;m  
5ZHO+@HiFH  
small-icon wRE2rsXoU  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) ._}Dqg$  
unkA%x{W;  
large-icon X0%BE!  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) Z-z(SKL  
&d[%  
description 3+:uV  
对tag库的描述(可选) ltXGm)+  
6)#%36rP  
listener ]4&B*]j  
参见下面listener元素 A,GJ6qp3  
z_9q T"vF  
tag ^p #bxN")  
参见下面tag 元素  1O@ cev;  
hHqsI`7c  
Listener元素 ~=pyA#VVJ"  
Bd*\|M  
一个tag库可能定义一些类做为它的事件侦听类,这些类在TLD中被称为listener 元素,jsp服务器将会实例化这些侦听类,并且注册它们。Listener元素中有一个叫listener-class的子元素,这个元素的值必须是该侦听类的完整类名。 Fk&A2C}$b  
L"V~M F  
Tag元素 wHhIa3_v  
DBzF\-  
每个tag元素在tag库中都要指出它的名字、类名、脚本变量、tag的属性。其中脚本变量的值可以直接在TLD中定义或通过tag附加信息的类来取得。每个属性描述了这个属性是否可以省略,它的值是否可以通过<%= …%>这样的JSP语法来获得,以及属性的类型。 ZZF\;  
0Ewt >~n  
每一个tag在TLD中对应一个tag元素,下表是tag元素的子元素: [ r=U-  
* uZ'MS  
Tag元素的子元素 lyrwm{&  
o|c"W}W  
元素名称 c jBHczkY  
描述 F5f1j]c  
{]:B80I;2  
name ^]?Yd)v  
独一无二的元素名 kZvh<NFh_  
J~rjI24  
tag-class #+PfrS=  
Tag标签对应的tag处理类 82Nw 6om6i  
08E,U  
tei-class `v$Bib)  
javax.servlet.jsp.tagext.TagExtraInfo的子类,用于表达脚本变量(可选) {c:ef@'U  
h5m6 )0"  
body-content 3ocRq %%K  
Tag标签body的类型 +N!!Z2  
5v-o2  
display-name 0i9C\'W`  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) Nx4X1j?-n  
}WG -R  
small-icon z`rW2UO#a`  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) .(8eWc YK  
W/I D8+:i  
large-icon +\`t@Ht#  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) h}(GOY S)  
Kkz2N  
description $^"_Fox]A\  
此tag标签的描述 dq$C COC^F  
'QEQyJ0EB  
variable ^,;8ra*h  
提供脚本变量的信息(同tei-class)(可选) KdTna6nY  
r$.v"Wh)  
attribute  al:c2o  
Tag标签的属性名 Q\<^ih51  
}x}JzA+2  
以下章节介绍对于不同类型的tag,如何具体地实现它们。 Oe%jV,S|V  
I`}<1~ue  
Qz?r4kR  
简单的tag 4'-GcH  
HxH=~B1"P  
s_N]$3'[E  
tag处理类 h^6Yjy  
2VNfnk  
简单的tag处理类必须实现Tag接口的doStartTag和doEndTag方法。当jsp引擎碰到tag标签的开头时,doStartTag被调用,因为简单的tag没有body,所以此方法将返回 SKIP_BODY。当jsp引擎碰到tag标签的结尾时,doEndTag被调用,如果余下的页面还要被计算,那它将返回EVAL_PAGE,否则将会返回SKIP_PAGE。 #2*2xt  
t#[u X?  
以下是例子:对于标签 <tt:simple /> ,它的tag处理类实现如下: lw"5p)aB  
A4uDuB;;ZQ  
,\ RxKSU  
public SimpleTag extends TagSupport E8.xmTq  
#5.L%F  
{ :,(ZMx\  
M.R] hI  
public int doStartTag() throws JspException N%&D(_  
)C CrO   
{ V2?&3Z) W  
xd`!z`X!,s  
try{ !56gJJ-r  
R]{AJ"p  
pageContext.getOut().print(“Hello.”); NQ(}rr'.  
tcxs%yWO1  
}catch(Exception e){ )\TI^%s  
5=.EngG  
throw new JspTagException(“SimpleTag: “ + e.getMessage()); ZXj;ymC'  
Tse Pdkk  
} Wd_cNR\  
#D{//P|;  
return SKIP_BODY; gZr/Dfy  
O/=i'0X v  
} kDG'5X;+  
grhwPnKl  
public int doEndTag() {E~ MqrX  
vYNh0)$%F  
{ J12 ZdC'O  
#}A >B  
return EVAL_PAGE; 61J01(+|  
x@]pUA1  
} 6A& f  
k&1~yW  
} '.wyfSH@  
y[l19eU  
RZ[r XV5  
注意:如果tag标签没有内容的话,那必须定义body-content元素为空,例如 #?z 1cgCg  
L_rKVoKjt  
<body-content>empty</body-content> a,U =irBA  
$v6dB {%Qu  
,SAS\!hsE  
带属性的tag标签
评价一下你浏览此帖子的感受

精彩

感动

搞笑

开心

愤怒

无聊

灌水
级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
只看该作者 1 发表于: 2007-01-01
tag处理类 (r^IW{IndX  
e.0vh?{\  
对于tag标签的每个属性,你必须依照JavaBeans规范来定义其属性,以及get和set方法。以struts的logic:present 标签为例, 9zkR)C  
eD, 7gC-  
<logic:present parameter=”Clear”> yoj5XBM  
r^?%N3  
与此相应,此tag处理类应有如下方法和定义: >Tld:  
0=8.8LnN(  
F^=|NlU&%  
protected String parameter = null; 5U[;T]{)e  
)(&g\  
public String getParameter() X!n-nms  
Kk~0jP_B9  
{ U"xI1fg%b  
Z8=4cWI~;  
return this.parameter; [j5 ^Zb&0  
V&_5q`L  
} I@ch 5vl4  
(*%+!PS  
public void setParameter(String parameter) u+zq:2)H6  
HPT9B?^  
{ }b YiyG\  
zk4yh%Cd_  
this.parameter = parameter; Fa9]!bW  
UJ)\E ^Hp  
} t9PS5O ;  
?#\?&uFJ}  
SF;;4og  
注意:如果你的属性名为id,而且你的tag处理类是从TagSupport类继承的,那你就不需要定义它的属性和set和get方法,因为他们早已在TagSupport被定义过了。 8jjJ/Mz`  
-{ZTp8P>  
Attribute元素 AdB5D_ Ir  
+gOCl*L  
对于tag标签的每个属性,你必须定义它是否必须的,它的值是否可以用诸如<%= …%>的表达式来获得,以及它的类型(可选),如果不指定它的类型,那就默认为是java.lang.String类型。如果rtexprvalue元素被定义为true或yes,那么在type元素中就定义了attribute的返回类型。 j~"X`:=  
6yF4%Sz9  
<attribute> H#G~b""mY  
y-"*[5{W  
<name>attr1</name> F5J=+Q%8[&  
;G~0 VM2|  
<required>true|false|yes|no</required> 9h$-:y3  
o"v> BhpC  
<rtexprvalue>true|false|yes|no</rtexprvalue> $<]y.nr|CX  
lE[LdmwDrb  
<type>attribute的返回类型(只用当rtexprvalue为真是才有效)</type> >.#uoW4ZV  
JPiC/  
</attribute> '&3Sl?E  
B\}E v&  
如果tag的某个属性不是必须的,那tag处理类会自动提供一个缺省值。 W?'!}g(~  
x-U^U.i@  
例如,在logic:present这个tag标签中定义了一个属性叫parameter,但它不是必须的,而且它可以被诸如<%= …%>的表达式来赋值。 $;+B)#  
q[b-vTzI  
<tag> slHlfWHq  
5\f*xY  
<name>present</name> qB7.LR*'  
P,~a'_w:|D  
<tag-class>org.apache.struts.taglib.logic.PresentTag</tag-class> qEf )TW(  
PF!Q2t5c3  
<body-content>JSP</body-content> >lyUr*4PX  
mb?DnP,z  
… i2$U##-ro]  
d Z"bc]z{  
<attribute> dp2".  
bK("8T\?  
<name>parameter</name> r#]gAG4t\  
=X>3C"]  
<required>false</required> +&a2aEXF  
ygUvO3Z  
<rtexprvalue>true</rtexprvalue> 0'|#Hi7@  
*H&a_s/{Nb  
</attribute> Y.i<7pBt  
KE16BjX@  
… '4FS.0*_  
PQvq$|q  
</tag> 3VA8K@QiRm  
S5v>WI^0h  
ui70|  
属性元素的校验 Iu(T@",Q#  
klUxt?-  
!U,qr0h  
有关于tag标签的有效值可以从tag库的说明文档中获得,当JSP页面被编译时,jsp引擎会强制性地参照TLD中定义的规则进行检查。 cPI #XPM=  
}.2pR*W  
还有一个方法也可以进行属性元素的校验,就是先继承类TagExtraInfo,然后调用它的isValid方法。这个类同时也起到提供tag中定义的脚本变量信息的作用。 VrO$SmH  
[4Glt>Nj>  
IsValid方法通过TagData对象来传递属性信息,它包括着tag的所有的属性名-值的信息。由于校验发生在运行时刻,因此这个属性的值将被赋值为TagData.REQUEST_TIME_VALUE。 nf /iZ &  
%nOBsln  
例如tag标签<tt:twa attr1=”value1” />在TLD中定义如下: HC4ad0Gs+{  
cGsxfwD  
<attribute> \ fU{$  
x7Ly,  
<name>attr1</name> zmf5!77  
A>OL5TCl  
<required>true</required> 7x-k-F3  
N iNZh;  
<rtexprvalue>true</rtexprvalue> '_r|L1  
YcRjbF,|6  
</attribute> ?8! 4!P%n  
2;[75(l6|}  
>|@ /GpD  
这个定义说明了attr1能在运行期间被赋值。 f5wOk& G  
1uMnlimr  
以下的isValid方法检查attr1属性的值是否属于Boolean类型。注意由于attr1能在运行刻被赋值,那么isValid方法必须检查tag用户是否对此tag进行了运行时刻赋值。 Qh/yPOSm:  
in#qV  
na  $z\C\  
Public class TwaTEI extends TagExtraInfo vT%rg r  
)@1_Dm@0b  
{ n?Gm 5##  
x gaN0!  
public boolean isValid(Tagdata data) !pw%l4]/t  
"@GopD  
{ ^o:0 Y}v=  
*M+:GH/5  
Object o = data.getAttribute(“attr1”); 8xg:ItJaA0  
bMkn(_H)\  
If(o != null && o != TagData.REQUEST_TIME_VALUE) <LZvG IMl  
3 {on$\  
{ #dW$"u   
f:"es: Fb  
if( ( (String)o).toLowerCase().equals(“true”) || mN3%;$ND7  
$L:g7?)k  
((String)o).toLowerCase().equals(“false”) ) 4^70r9hV9  
fgn*3 pg  
return true; kt X(\Hf!  
jc Ie<i;  
else xC<OFpI\  
T"9`[Lzva  
return false; &ks>.l\  
a_QO)  
} w|?Nq?KA  
NqhRJa63  
else R\0]\JEc  
c 0!bn b  
return true; q* Ns]f'a  
((EN&X,v  
} C"IPCJYn  
0~Yg={IKhK  
} _jU6[y|XLh  
cQgmRHZ]  
q+gqa<kM  
带body的tag jh\q2E~,`  
X?4tOsd  
% OiSuw  
tag处理类 QE< 63|  
RG:ct{i  
?$-OdABXHK  
如果tag标签含有内容,那处理方式会略微有些不同,而且还要视tag处理类是否要与body交互的情况而定。如果要与body交互,那我们认为tag处理类要可能要对body进行操作。 MfeW|  
w{2V7*+l  
Tag处理类不与body交互 e *;"$7o9  
mtmBL 2?  
如果tag处理类不与body交互,tag处理类应该实现Tag接口或从TagSupport中派生,如果body要被计算,那么doStartTag方法应返回 EVAL_BODY_INCLUDE,否则应返回SKIP_BODY。 ':o.vQdJ  
#0G9{./C  
如果tag处理类要对body反复运算,则它应该实现IterationTag或从TagSupport中派生。如果tag处理类认为body还未计算完的话,那它的doStartTag方法和doAfterBody方法必须返回EVAL_BODY_AGAIN。 f_D1zU^  
/,E%)K;  
Tag处理类与body交互 6sQ"go$}  
QnaMjDh$6  
如果tag处理类与body交互,那tag处理类应实现BodyTag接口或从BodyTagSupport中派生。这种tag处理类一般要实现doInitBody和doAfterBody方法。 I|Z5*iXqCm  
fB  
Body允许一些方法来读写它的内容。Tag处理类可以调用body内容的getString或getReader方法来从body中提取信息,也可用 writeOut(out) 方法来将body的内容写入到out对象中。其中out对象通过tag处理类的getPreviousOut方法来获得。 ;EL!TzL:8  
z ; :E~;  
如果body的内容需要被计算,那么doStartTag方法必须返回EVAL_BODY_BUFFERED,否则,它将返回 SKIP_BODY。 7zR 7v  
' 'UiQ   
doInitBody 方法 1__p1  
R8o9$&4_  
此方法在body内容已经设好,但未被计算之前被调用。你可以根据不同的body内容来制定初始化策略。 ru'Xet  
B Sb!{|]  
doAfterBody方法 O_F<VV*MFQ  
`Ph4!-6#  
此方法在body内容已被计算后进行调用。 aWe H,A%  
=B<g_9d4  
和doStartTag方法一样,doAfterBody方法返回一个指示符指示是否要继续计算body,如果要继续计算,则doAfterBody应返回EVAL_BODY_BUFFERED,否则,它应返回SKIP_BODY。 w:M faN*  
<ezvz..g  
release 方法 2!]':(8mR  
!WVF{L,/I  
tag处理类调用此方法将它的状态重置为初始状态,并释放所有的私有资源。 q3scz  
&~$^a1D6  
er l_Gg  
以下的例子读取body的内容(其中含有一条sql语句),然后将它传递给一个对象,让它进行查询。由于此处body不须重新计算,所以doAfterBody会返回SKIP_BODY。 :Q?xNY%  
& r\z9!   
Qo;$iLt  
Public class QueryTag extends BodyTagSupport [|k@Suv |z  
O$$s]R6  
{ V)N9V|O'  
IWm|6@y  
public int doAfterBody() throws JspTagException aeH 9:GQ6  
?1OS%RBF  
{ l Fzb$k}_{  
Q^fli"_ :  
BodyContent bc = getBodyContent(); (]mN09uE  
l6l)M  
//将body的内容以字符串的格式提取出来 @#8F5G#  
3b#KrN'  
String query = bc.getString(); 8uT@$ ./  
5zfaqt`  
//清除body KS(s<ip|  
{CQA@p:Y}  
bc.clearBody(); lQ! 6n  
!u\X,.h  
try{ n~K_|  
s=U_tfpH  
Statement stmt = connection.createStatement(); ZL1[Khr,s  
lXv{+ic  
Result result = stmt.executeQuery(query); "V?U^L>SF  
\i`/k(  
}catch(SQLException e){ E8FS jLZ  
(F$q|qZ%  
throw new JspTagException(“queryTag: “ + e.getMessage() ); {:{NK%  
AO8`ItNZdT  
return SKIP_BODY; ]<z>YyBA  
h\D y(\  
} 5OKbW!  
q'c'rN^  
} pmQ9i A@=  
(hd2&mSy  
QabF(}61  
body-content元素 K-p1v!IC  
bS* "C,b~s  
K[T? --H  
由于tag可能会有body,你必须用body-content元素来指定body内容的类型: 5;dnxhf  
l4r09"S|V  
<body-content>JSP|tagdependent</body-content> uv9cOd  
,/o<OjR  
M@8 <^CK  
如果body的内容是定制的或内部的tag、脚本元素、或HTML广本,则归类为JSP类型。其他的类型,比如上面代码所述的?D?D将sql statement类传给 query tag的这种类型应该标为tagdependent。 ZIpL4y =_  
H$1R\rE`  
注意:实际上body-content的值并不影响tag处理类对body内容的处理,它仅仅是被tag编辑工具用来描述此body的内容。 %3z-^#B=  
zy+|)^E  
4HkOg)a  
用tags定义脚本变量 f&{2G2 O%  
nJ'O(Wh,)  
10}\7p8  
tag处理类 XQlK}AK  
aSKI %<?xN  
mNcTO0p&  
tag处理类负责创建或设置页面中定义的脚本变量,用pageContext.setAttribute(name,value,scope)或pageContext.setAttribute(name,value)方法来实现。一般来说,tag处理类通过脚本变量的名称来获取它,脚本变量的名称一般可用get方法来获得。 oryoGy=(yk  
^U:pv0Qz  
如果脚本变量的值依赖于tag处理类中的上下文中某一对象,那它可用pageContext.getAttribute(name,scope)方法来找到那个对象。一般的处理过程是tag处理类先找到脚本变量,再对其进行处理,然后用pageContext.setAttribute(name,object)的方法来设置它的新值。 '>2xP<ct!&  
mj S)*@F  
对象的生存周期(scope)如下表: qBKIl= ne  
mm:\a-8j  
对象的生存周期表 Os?~U/  
8BLtTpu  
名字 x*bM C&Ea  
可访问范围 KcNEB_i  
生存周期 Td"f(&Hk&  
oDM}h +  
page <P}{0Y~@*W  
当前页面 HPr5mWs:  
一直有效,除非页面向客户提交响应或重定向到一个新页面 A*MlK"  
H.wp{m{  
request dO rgqz`e  
当前页面或当前页面重定向到的页面 [^~Fu9+"  
一直有效,除非页面向客户提交响应 K~v"%sG{`  
*4]I#N  
session EV2whs2g  
当前页面或在同一浏览器窗口中的页面 *9?-JBT&F  
一直有效,除非关闭当前浏览器、超时、网络故障 ~~:i+-[  
G~u94rw|:  
application ~i6tc d  
整个web应用程序的所有请求 _YO` x  
一直有效,除非发生网络故障、服务器故障 ?sp  
S-'iOJ 1]  
提供关于脚本变量的信息 MCL5a@BX)  
ykX}T6T  
以下示例定义了一个名为“book”的脚本变量,用来访问程序中关于书的信息: ~A [ Ju%R  
}UQBaqDH  
<bean:define id=”book” name=”bookDB” property=”bookDetails” type=”database.BookDetails” /> LnrR#fF]Z  
xr)kHJ:v  
<font color=”red” size=”+2” > hp Lo  
+a nNpy  
<%= messages.getString(“CartRemoved”) %> &7|=8Z[o  
sT'wps2  
<strong><jsp:getProperty name=”book” property=”title” /></strong> 1&Nk  
4vp,izNW  
</font> _@jl9<t=_  
WR gAc%  
当包含此tag的JSP页面被编译时,jsp引擎会自动生成关于此book的同步的代码(同步可以避免几个客户同时访问此book时造成的冲突),要生成同步代码,jsp引擎需要知道此脚本变量的如下信息: 8Z FPs/HP  
/Q})%j1S0  
· 脚本变量名称 O2ety2}?f  
4N*Fq!k~  
· 脚本变量所属的类 jJ|u!a  
3DMfR ofg  
· 此脚本变量是否引用了一个新的或已存在的对象 VX2bC(E'%  
vr=iG xD  
· 此脚本变量的有效性 yhgHwES"  
~\:+y  
有两种办法可以向jsp引擎提供关于脚本变量的信息:在TLD中定义variable子元素,或用tei-class子元素定义一个额外tag信息类。用variable最简单,但可能降低了一些灵活性。 HrEZ]iQ@O0  
hY/SR'8  
Variable元素 u{tjB/K&  
.2[>SI  
Variable元素有如下子元素: !)_80O1  
6&$z!60  
· name-given ?D?D 给出的名字,是一个常量 ^\ {%(i9  
/|`;|0/2  
· name-from-attribute?D?D 属性名,在编译时给出的属性名 c i_XcG  
zZ OoPE  
name-given或name-from-attribute两者必须选一,但以下子元素是可选的: V5qvH"^  
2EycFjO  
· variable-class?D?D变量的类型,缺省为java.lang.String。 pkjL2U:  
mS&[<[x  
· declare?D?D此脚本变量是否引用了一个新对象,缺省为True。 .nKyB'uV  
qW $IpuK  
· scope?D?D脚本变量的范围,缺省为NESTED。下表描述了scope的几种类型: )Xl/|YD  
k]ptk^  
脚本变量的有效范围 vC&y:XMt,`  
- :*PXu  
值 EX=+TOkAf  
有效性 HiILJyb  
方法 .e"De-u  
k "'q   
NESTED )=[K$>0k  
在tag标签的开始和结束之间 % 7/XZQ  
如果tag处理类实现BodyTag接口,则在doInitBody和doAfterBody中调用,否则在doStartTag中调用 91jv=>=DM  
:-ax5,J>q  
AT_BEGIN ofj7$se  
从tag标签的开始一直到页面结束 V.: a6>]  
如果tag处理类实现BodyTag接口,则在doInitBody、doAfterBody和doEndTag中调用,否则在doStartTag和doEndTag中调用 J0C<Qb[  
>p}d:t/  
AT_END KFCuv15w,3  
从tag标签的结束一直到页面结束 xJJlVP  
在doEndTag中调用 n|yl3v  
 Pb+oV  
以struts为例,它的bean:define标签的实现遵循JSP1.1规范,此规范要求使用额外tag信息类来定义脚本变量。Variable元素是JSP1.2规范中加入的。以bean:define标签为例,你可以定义如下variable元素: uy~5!i&  
$/Zsy6q:  
<tag> #W~5M ?+  
WK:~2m&y  
<variable> `jvIcu5c  
Ej F<lw  
<name-from-attribute>id</name-from-attribute> #HJF==  
F, %qG,  
<variable-class>database.BookDetails</variable-class> :BC 0f9  
OzX\ s=  
<declare>true</declare> F2AM/m^!q  
J=Ak+  J  
<scope>AT_BEGIN</scope> V7[Dvg:W  
NA]7qb%%<  
</variable> &z 1A-O v  
~i fq_Ag.  
</tag> DSizr4R  
8}{';k  
额外tag信息类 }rn}r4_a  
Ys+Dw-  
如果要定义一个额外tag信息类,你要继承javax.servlet.jsp.TagExtraInfo类。一个TagExtraInfo类必须实现getVariableInfo方法,此方法返回一个叫VariableInfo的数组类,它包括如下信息: eW1$;.^  
4)]g=-3  
· 变量名 xX{uDMYa;  
TEh]-x`  
· 变量所属类名 7 I&7YhFI  
5#80`/w^U  
· 此变量是否引用了一个新对象 a_`E'BkgU  
wkdd&Nw;  
· 此变量的有效范围 pyT+ba#  
LJc w->  
jsp引擎将一个名为data的参数传给getVariableInfo方法,data中包括tag标签中的所有“属性名?D?D属性值”对。它可以用来向VariableInfo对象提供脚本变量的名字和类名。 7B"J x^  
GH7{_@pv8  
以struts为例,它在bean:define标签中定义了一个名为DefineTei的额外tag信息类,用来向脚本变量提供信息。由于脚本变量的名称(book)和类名(database.BookDetails)是通过tag标签的属性来传递的,它们一般定义在VariableInfo的构建代码中,并且可用data.getAttributeString方法来得到这些信息。如果要允许book脚本变量能在从tag开始直到整个JSP页面结束的范围内都可用的话,那它的范围应设为AT_BEGIN。如下所示: `JG~%0Z?}  
l0U6eOx  
U4 m[@wF  
public class DefineTei extends TagExtraInfo 5caYA&R  
Ua5m2&U1  
{ `]LaX&u  
%,K|v  
public VariableInfo[] getVariableInfo(TagData data) lE?e1mz{  
~XsS00TL`G  
{ Dr6Br<yi  
0Y)b319B  
String type = data.getAttributeString(“type”); YUT"A{L  
mIFS/C  
If( type == null) )_GM&-  
9`4h"9dO  
type = “java.lang.Object”; ,*E%D _  
i_`YZ7Hxp  
return new VariableInfo[] { @!0j)5%  
**_VNDK+  
new VariableInfo(data.getAttributeString(“id”), M0=ZAsN  
 7z<!2  
type, 2}$Vi$ R  
0WF(Ga/o  
true, (pi7TSJ  
f#eTi&w  
VariableInfo.AT_BEGIN) }2`S@Rq.WW  
e&; c^Z  
}; _q6+]  
Se0/ysVB  
} ^>%=/RX  
j"94hWb  
} j@GMZz<  
1yX&iO^d  
M?[lpH3  
注意:关于额外tag信息类的类名必须要在TLD中的tag标签下的tei-class子元素中定义。因此,DefineTei的tei-class中的定义看起来如下: D1o 8Wo  
<tei-class> |i|YlWQS  
org.apache.struts.taglib.bean.DefineTagTei Zr}`W \  
</tei-class> gvoK  
;lYO)Z`3\  
lz{>c.Ll[  
具有协作关系的tag }Lb];hww1  
YQQ!1 hw  
v|{*y  
tag通过共享对象来进行协作,JSP技术支持2种方式的对象共享。 JYv&It  
D|e6$O5o  
第一种方法是使用pageContext对象进行对象的共享(可支持JSP页面和tag处理类之间的共享),如果在一个tag处理类中要调用由另一个tag处理类创建的对象,可调用pageContext.getAttribute(name, scope)方法。 2mU}"gf[  
?ZDx9*f  
第二各方式的共享是对于tag之间有嵌套关系而言的,外层的tag所创建的对象对于内层的tag来说是可以共用的。这种形式的共享的好处是减少了可能存在的重名冲突。 ?MpGz CPa  
p-*BB_J"  
要访问一个嵌套tag创建的对象,tag处理类必须先找到此嵌套tag对象,可用TagSupport的静态方法 TagSupport.findAncestorWithClass(from, class)或TagSupport.getParent方法。前者在当不确定此tag是否为嵌套tag对象时使用。一旦它的父类被找到,它就能访问其所有动态或静态创建的对象。静态创建的对象是父类的成员,而动态创建的对象可能是父类的私有对象。诸如此类的对象可以用tag处理类的setValue方法来保存,用getValue方法来获得。 * +OAc `8  
cgz'6q'T  
下例阐述了以上两种共享对象的方法。在这个例子当中,一个查询tag检查一个名为connection的属性名是否在doStartTag中被设置。如果connection属性被设置,tag处理类从pageContext中得到这个connection对象。否则,此tag处理类先找到它的父tag处理类,然后从它的父tag处理类中找到connection对象。 h(G&X9*  
8$G$Rdn  
m.V mS7_I  
public class QueryTag extends BodyTagSupport 0 |F (qR  
"H G:by  
{ ;P2~cQjD;  
~gBqkZ# y?  
private String connectionId; 4a!L/m *  
H.>KYiv+  
public int doStartTag() throws JspException E"L'm0i[[  
E+~~d6nB  
{ HH+rib'u  
i^QcW!X&  
String cid = getConnection(); brTB /(E  
JBoo7a1  
if(cid != null) \ [>Rt  
Z>M*!mQi  
{ YO,GZD`-o  
2l\Oufer"  
//存在一个connection id,使用它。 ^8MgNVoJ)  
l;|1C[V  
connection = (Connection) pageContext.getAttribute(cid); v WhtClJ3  
HuK'tU#  
} c69C=WQ  
DD~8:\QD  
else ol:_2G2xQ  
;c;;cJc!  
{ lT(MywNsg  
qY0Ic5wCY  
ConnectionTag ancestorTag = (ConnectionTag)findAncestorWithClass(this, +:Y6O'h.  
T 7 h C]R  
ConnectionTag.class); G7),!Qol  
zF{ z_c#3@  
if(ancestorTag == null) u;Z~Px4]v  
=j}00,WH  
{ t;4{l`dk  
i^gzl_!  
throw new JspTagException(“一个没有connection属性的查询标签必须被一个connection标记嵌套。”); J7l1-  
\,_%e[g49  
} 9xWeVlfQ  
GJ((eAS)  
connection = ancestorTag.getConnection(); 8<g5.$xyz  
t=yM}#r$  
} XGO_n{ x  
Qp< 6qM35  
} R"82=">v  
9pk<=F  
} 4W1"=VL[g  
Z-/ E$j  
aIm\tPbb  
p oNQ<ijK  
此查询标签在JSP页面中的调用形式可以从以下2种定义中任选一种: .IG(Y!cB  
g.,IQ4o  
hx:x5L>  
<tt:connection id=”con01” ...> ... </tt:connection> EmH2 Dbw  
p~M^' k=d  
<tt:query id=”balances” connection=”con01” > 0_%u(?  
m"xw5aa>  
SELECT account, balance FROM acct_table @=@WRPGM*9  
,c7 8O8|  
where customer_num = <%= request.getCustno() %> &| ',o ?'F  
;up89a-,9  
</tt:query> )WBTqML[  
a|66[  
Blf;_e~=[j  
或 n*'|7#;  
/<M08ze  
<tt:connection ...> yyBy|7QgO  
fpzC#  
<x:query id=”balances”> Rb\\6 BU0  
i"zWv@1z  
SELECT account, balance FROM acct_table 8wwD\1pLS  
[['un\~r~  
where customer_num = <%= request.getCustno() %> qL3*H\9N  
Au:Q4x.  
</x:query> Oi=kL{DG:s  
Joe k4t&0<  
</tt:connection> dRt]9gIsx  
Eiwo== M  
HP&+ 8  
与此同时,在TLD中必须指定connection属性为可选的,定义如下: 8g&uCv/Uk  
gNN{WFHQX:  
<tag> rT5dv3^MW!  
NtSa# $A  
... mmEr2\L  
kcI3pmgj  
<attribute> 3fM~R+p  
De\&r~bTW9  
<name>connection</name> V% psaT=)P  
b`fPP{mG  
<required>false</required> mq su8ti  
A2g +m  
</attribute> /J8y[aa  
fD]}&xc  
</tag>
描述
快速回复

您目前还是游客,请 登录 或 注册
如果您在写长篇帖子又不马上发表,建议存为草稿
认证码:
验证问题:
10+5=?,请输入中文答案:十五