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

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

级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
标准的JSP 标记可以调用JavaBeans组件或者执行客户的请求,这大大降低了JSP开发的复杂度和维护量。JSP技术也允许你自定义taglib,其实换句话说,taglib可以看成是对JSP标记的一种扩展,正如xml是对html的一种扩展一样。taglib通常定义在tag标签库中,这种标签库存放着你自己定义的tag标签。简而言之,如果使用taglib,那么你可以设计自己的JSP标记! 9T24dofkJ  
K=v:qY4Z  
一般来说,自定义tag标签主要用于操作隐藏对象、处理html提交表单、访问数据库或其它企业级的服务,诸如邮件和目录操作等等。自定义tag标签的使用者一般都是那些对java编程语言非常精通,而且对数据访问和企业级服务访问都非常熟悉的程序员,对于HTML设计者来说,使得他可以不去关注那些较复杂的商业逻辑,而将精力放在网页设计上。同时,它也将库开发者和库使用者进行合理分工,自定义tag标签将那些重复工作进行封装,从而大大提高了生产力,而且可以使得tag库可用于不同的项目中,完美地体现了软件复用的思想。 @q/g%-WNz  
t n5  
在这篇文章中,我们主要讨论: G!r)N0?_f  
p#ar`-vQ  
· 什么是自定义tag标签? \BXzmok  
iT4*~(p 3  
· 怎么使用tag标签? HN{c)DIm]  
)P:^A9&_n=  
o 声明要使用的tag库 1" cv5U  
Jd>~gA}l  
o 找到与之对应的tag处理类 D'#Q`H  
lZcNio  
o tag标签的类型 g8%O^)d=>  
.="X vVdkp  
· 自定义tag标签 8I#ir4z#<  
"+"=iwEAz  
o tag处理类 \@:,A]  
!rM~   
o tag库描述 <'I["Um  
'3(^Zv  
o tag标签示例 pD732L@q  
oY18a*_>M1  
o 带属性的tag Z nc(Q  
`um,S  
o 带body的tag ~ y!'\d>q<  
tF0jH+7J-  
o 定义了脚本变量的tag @0?!bua_|  
\beO5]KS<  
o 具有协作关系的tag vjGQ!xF  
7z{wYCw  
· 自定义tag标签 hi0HEm\  
$RPW/Lyiq  
o 一个迭代tag的例子 Q6@<7E]y  
yLX $SR  
o 一个模板tag库 Nz,yd%ua  
@^W`Yg)C  
o tag处理类到底是怎样被调用的? h4? x_"V"  
$"^K~5Q  
)u)=@@k21  
什么是自定义的tag? <$(B[T  
L[ G O6l  
一个自定义的tag标签是用户定义的一种JSP标记。当一个含有自定义的tag标签的JSP页面被jsp引擎编译成servlet时,tag标签被转化成了对一个称为tag处理类的对象进行的操作。于是当JSP页面被jsp引擎转化为servlet后,实际上tag标签被转化成为了对tag处理类的操作。 %iN>4;T8  
?['!0PF  
自定义tag标签有很多特色,诸如: 7~/cz_  
RdTM5ANT  
· 可以在JSP页面中自定义tag标签的属性 Eah6"j!B8n  
j9+$hu#a  
· 访问JSP页面中的所有对象 wHc my  
,kN;d}bg  
· 可以动态地修改页面输出 (jgk! 6  
!~@GIr  
· 彼此这间可以相互通信。你可以先创建一个JavaBeans组件,然后在一个tag中调用此JavaBeans组件,同时可以在另一个tag中调用它。 +&Ld` d!n  
J-F".6i5  
· tag允许相互嵌套,可以在一个JSP页面中完成一些复杂的交互。 "F<CGSo  
q+ $6D;9  
(yOkf-e2y  
使用tag标签 >qjV{M  
6o 3 bq|  
CLb6XnkcA\  
本节主要描述怎样在JSP页面中使用tag标签,以及tag标签的不同类型。 'y8{, R4C  
a|aVc'j  
要使用tag标签,JSP程序员必须做2件事: a&y^Ps6=  
l>?c AB[  
· 声明此tag标签的tag库 d2 ^}ooE  
7|P kc(O  
· 实现此tag标签 S&op|Z)1  
Y?T{>"_W  
声明tag标签所在的tag库 mP(3[a_Q  
t8Zo9q>  
如果要使用tag标签,则应用JSP的taglib指示符来指定其tag库(注意:taglib要在在使用此tag标签之前声明) o\AnM5  
pm&TH d  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> m7 =$*1k  
sGvbL-S-f:  
uri属性定义了唯一的标签库描述(以下简称TLD),它可以是直接是tld文件名或一个独一无二的名字。prefix是用来区别其它TLD中和本TLD中有重名的tag的一种手段。 S2~cAhR|M  
.1x04Np!  
TLD必须以.tld作为扩展名,并且存放在当前应用的WEB-INF目录或其子目录下。你可以通过它的文件名直接引用它,也可以通过别的方式间接地引用它。 y}Ky<%A!P  
vh9* >[i  
以下taglib指示符直接引用一个TLD: XZ rI w  
(JhX:1  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> 8!g `bC#%  
X|M!Nt0'  
以下的taglib指示符通过一个逻辑名称间接地引用一个TLD: bQAznd0  
!XA3G`}p6s  
<%@ taglib uri=”/tutorial-template” prefix=”tt” %> dj|5'<l2  
30Yis_l2h  
如果是间接引用TLD的话,那你必须还要在web.xml中定义此逻辑名称与tld文件之间的映射,具体做法是在web.xml中加入一个名为taglib的元素: h$>F}n j  
2EY"[xK|  
<taglib> B*7kX&Uq  
|Lq8cA)|y  
<taglib-uri>/tutorial-template</taglib-uri> #m+!<  
SGd]o"VF  
<taglib-location> 0bNvmZ$  
e5h*GKF  
/WEB-INF/tutorial-template.tld >%JPgr/ 8  
'nJF:+30ZH  
</taglib-location> bRC243]g*A  
FoefBo?g65  
</taglib> L\yVE J9x  
JuRoeq.  
fSh5u/F!  
实现此tag标签 _MBa&XEM  
sE9FT#iE  
B( [x8A]  
为了实现tag标签,你有2种方法来存放tag处理类。一、让tag处理类以.class的方式存放于当前应用的WEB-INF/class子目录下,二、如果tag处理类是以JAR包的形式存在的话,那可以放在当前应用的WEB-INF/lib目录下,如果tag处理类要在多个应用中共享,那么它就应放在jsp服务器上的common/lib目录下,对于tomcat来说,就是tomcat/common/lib目录下。 Vla,avON  
E3L?6Qfx>  
O9gq <d  
tag标签类型 H/8^Fvd  
l =^A41L_  
O-- p)\   
自定义的tag标签遵循XML语法。它有一个开始标记和一个结束标记,有的还有body(即文本节点): !`ol&QQ#  
#GsOE#*>T  
<tt:tag> R^Rc!G}  
>hKsj{=R7  
body MsB >3  
eK8H5YE  
</tt:tag> 77e*9/6@  
Y~~Dg?e  
0V%c%]PH  
一个不带body的tag标签如下: &K[*vyD  
337.' |ZE  
<tt:tag /> *[MWvs:,  
!U`&a=k  
K2m>D=w  
简单的tag标签 _ %s#Cb  
I-v} DuM  
一个没有body和属性的tag标签如下: FOaA}D `]  
7KT*p&xm  
<tt:simple /> 6fwNlC/9  
4^_6~YP7  
vz^ ] g  
带属性的tag标签 *MJm:  
AbU`wr/h 4  
mq:k |w^6  
自定义标签可以有自己的属性。属性一般在开始标记中定义,语法为 attr=”value”。属性的作用相当于自定义标签的一个参数,它影响着tag处理类的行为。你可以在TLD中详细定义它。 !0 7jr%-~  
Bz+oM N#XJ  
你可以用一个String常量给一个属性赋值,也可以通过表达式给它赋值,如<%= ...%>。以struts为例,它的logic:present标签就是用的String常量来给属性赋值: W5j wD  
!_glZ*tL  
<loglic:present parameter = “Clear”> I2}W/}  
! FcGa  
而另一个标签logic:iterate是用表达式来给属性赋值: .=y=Fv6X  
z*3b2nV  
<logci:iterate collection=”<%= bookDB.getBooks() %>” = XZU9df  
x/QqG1q  
id=”book” type=”database.BookDetails”> YV>a 3  
UBo0c?,4  
lH fZw})d  
带body的tag标签 q|5WHB  
SH*'<  
一个自定义标签可以包含其它自定义标签、脚本变量、HTML标记或其它内容。 9~ p;iiKGG  
:J;U~emq  
在下述例子中,此JSP页面使用了struts的logic:present标签,如果些标签定义了parameter=”Clear”的属性,则将清除购物车的内容,然后打印出一条信息: J%bNt)K}  
7uBx  
<logic:present parameter=”Clear”> --HDEc|  
(6%T~|a  
<% cart.clear(); %> b,~'wm8:A  
B'/U#>/  
<font color=”#ff0000” size=”+2”><strong> gI:g/ R  
pEB3 qGA  
你选择了清除购物车! ^&3vGu9  
bLT3:q#s  
</strong></font> Quth5  
+U fw  
</logic:present> Ff<cY%t  
] 0i[=  
mR}8}K]L  
到底是用属性还是用body来传递信息? Aez2n(yac  
%Z;RY5  
如上所述,我们既可以通过属性,也可以通过body来传递信息。但一般来说,比较简单的类型,如字符串或简单表达式最好采用属性来传递信息。 $G=^cNB|JB  
<3Ftq=  
LP3#f{U  
定义脚本变量的tag标签 6/!:vsa"3  
Z<U,]iZB  
所谓脚本变量,是指JSP中可以调用的变量或对象。它可由tag标签产生。以下示例阐述了一个tag标签定义了一个名为tx的由JNDI所定义的事务处理对象。脚本变量可以是ejb对象、事务、数据库连接等等: zJ`u>:*$  
[[T7s(3  
<tt:lookup id=”tx” type=”UserTransaction” name=”java:comp/UserTransaction” /> jMT[+f  
e]<Syrk  
<% tx.begin(); %> GtRpgM  
4DIU7#GG  
... k_g@4x1y*  
?!ap @)9  
/X8a3Eqp9  
具有协作关系的tag标签  ;LS.  
LM<*VhX  
自定义tag标签之间可以通过共享对象来实现协作。在下述例子中,标签tag1创建了一个名为obj1的对象,在标签tag2仍可以重复使用obj。 sBlq)h;G?6  
3P_.SF  
<tt:tag1 attr1=”obj1” value1=”value” /> n'rq  
P IG,a~  
<tt:tag2 attr1=”obj1” /> %+r(*Q+0$f  
.)*&NY!nsl  
在以下这个例子当中,如果外层的tag标签创建了一个对象,那么其内层的所有tag标签都可以使用这个对象。由于这样产生的对象没有一个指定的名字,那么就可以将少重名的冲突。这个例子阐述了一系列协作的嵌套对象。 zkt~[-jm}  
4lo7yx  
<tt:outerTag> i7RK*{  
n%r>W^2j  
<tt:innerTag /> 8] LF{Obz[  
=K@LEZZ'/<  
</tt:outerTag> mmQC9nZ  
clDn=k<  
|@d(2f8  
Tag处理类 b'( AVA  
fD%/]`y  
\m`IgP*  
Tag处理类必须实现Tag接口或BodyTag接口,不过现在一般都流行从TagSupport或BodyTagSupport类中继承,这些类或接口都可以在javax.servlet.jsp.tagext包中找到。 <mX5VGY9^  
7Kym|Zg  
当JSP引擎看到自己的JSP页面中包含有tag标签时,它会调用doStartTag方法来处理tag标签的开头,调用doEndTag方法来处理tag标签的结束。 hGFi|9/-u  
+ s}!+I8 P  
下表说明不同类型的tag所需要不同的处理过程: OL1xxzo  
\Vv)(/q{  
Tag处理类的方法 do`'K3a"  
3SM'vV0[  
Tag标签类型 padV|hF3(e  
所调用的方法 .0nT*LF  
oVqx)@$K  
基本标签 QAI=nrlp  
doStartTag, doEndTag, release yS)k"XNb  
M5[#YG'FlQ  
带属性的标签 '"Cqq{*  
doStartTag, doEndTag, set/getAttribute1...N, release =$}`B{(H  
2SU'lh\E  
带内容的标签 (9bU\4F\  
doStartTag, doEndTag, release .KYs5Qu  
#WA7}tHb  
带内容的标签,且内容重复循环 )~P<ruk>,C  
doStartTag, doAfterBody, doEndTag, release y**L^uvr  
`?:{aOI  
带内容的标签,且内容与JSP交互 !}A`6z  
doStartTag, doEndTag, release, doInitBody, doAfterBody, release ~#EXb?#uS  
]Y & 2&  
一个tag处理类可以通过javax.servlet.jsp.PageContext来与JSP交互,通过javax.servlet.jsp.PageContext类,tag处理类可以访问JSP中的request、session和application对像。 SdufI_'B  
Qe<c@i"  
如果tag标签是互相嵌套的,那内层的tag处理类可以通过它的parent属性来访问上层的tag处理类。 QD[l 6  
kr ?`GQm  
一般情况都将所有的tag处理类打成了JAR的包,以便于发布。 %D^j7`Z  
,"5p=JX`  
@iz6)2z  
Tag库描述(简称TLD) RML'C:1  
3'Z+PPd!  
^q~.5c|  
Tag库是用xml语言描述的,TLD包括了tag库中所有tag标签的描述,它一般用来被jsp服务器用来校验tag的语法正确性,或者被jsp开发者用来开发新的标签。 T/7[hj  
V> eJ  
TLD的文件扩展名必须为.tld,而且必须放在当前WEB应用的WEB-INF目录或其子目录中。 H% c{ }F  
2wh{[Q2f  
一个TLD的内容的开头必须遵守标准的XML开头,用于描述DTD和xml的版本,例如: RA62Z&W3  
%hzNkyD)Y  
<?xml version="1.0" encoding="ISO-8859-1" ?> {' |yb  
q->46{s|  
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd"> #lm1"~`5  
TLD必须以<taglib>来作为它的根元素,<taglib>的子元素如下表: @}N;C ..Y$  
\-s'H:  
M8lR#2n|  
<taglib>的子元素 p&\x*~6u  
<Gudx>I  
Element [[u&=.Au  
Description d3C*]|gQ  
$VJ=A<  
tlib-version P(r}<SM  
Tag库的版本 Y-,1&$&  
w4+bzdZ  
jsp-version \+w -{"u$  
Tag库所需要的jsp的版本 {GH 0 J"  
D &wm7,  
short-name IV:Knh+ ?  
助记符,tag的一个别名(可选) >b/0i$8  
ODM<$Yo:d  
uri vexQP}N0  
用于确定一个唯一的tag库 D058=}^HE  
Z;i^h,j?$1  
display-name { lLUZM  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) fr\UX}o  
n/UyMO3=  
small-icon p<6pmW3  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) =RUKN38  
_Oq (&I  
large-icon $0K9OF9$  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) 5kJ>pb$/  
4Kt?; y ;  
description U1rh[A>  
对tag库的描述(可选) w>rglm&  
9!FV. yp%F  
listener )mZ`j.  
参见下面listener元素 tL;;Yt  
]]%CO$`T [  
tag 4- 6'  
参见下面tag 元素 /{1xpR  
P5vMy'1X  
Listener元素 JUU0Tx:`9)  
 Jb {m  
一个tag库可能定义一些类做为它的事件侦听类,这些类在TLD中被称为listener 元素,jsp服务器将会实例化这些侦听类,并且注册它们。Listener元素中有一个叫listener-class的子元素,这个元素的值必须是该侦听类的完整类名。 <v[,A8Q  
K| Y r  
Tag元素 J/wot,j^  
2@ACmh  
每个tag元素在tag库中都要指出它的名字、类名、脚本变量、tag的属性。其中脚本变量的值可以直接在TLD中定义或通过tag附加信息的类来取得。每个属性描述了这个属性是否可以省略,它的值是否可以通过<%= …%>这样的JSP语法来获得,以及属性的类型。 i' |S g  
!OWV* v2  
每一个tag在TLD中对应一个tag元素,下表是tag元素的子元素: haa [ob6T  
FQ(=Fnqn  
Tag元素的子元素 o &LNtl;  
9[6*FAFJPP  
元素名称 -_pI:K[  
描述 +\.gdL)  
 HPwmi[  
name D@d/O  
独一无二的元素名 bUz7!M$  
8<?60sj  
tag-class G'q7@d {'  
Tag标签对应的tag处理类 Pk T&zSQA  
oOy@X =cw  
tei-class _SjS^z~  
javax.servlet.jsp.tagext.TagExtraInfo的子类,用于表达脚本变量(可选) >Y?B(I2e  
e2*0NT^R  
body-content yc8FEn!)&  
Tag标签body的类型 x-:vpv%6y  
}P#%aE&-  
display-name Na=9 ju  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) JXUnhjB,B  
8s-RNA>7^  
small-icon ;Jr6  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选)  V7%G?  
EShc1KPqc  
large-icon c!T^JZBb  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) zLc.4k  
E D*=8 s2  
description P5* :r3>  
此tag标签的描述 e]!Vxn3  
d*,% -Io  
variable 7)O?jc  
提供脚本变量的信息(同tei-class)(可选) TDBWYppM  
!I-+wc{ss  
attribute =xQ 7:TB  
Tag标签的属性名 8 Mp2MZ*p  
)|@b GEk  
以下章节介绍对于不同类型的tag,如何具体地实现它们。 9"52b 9U  
%P0dY:L~  
"5 PP<A,F(  
简单的tag  ^ 'FC.  
<Q/^[  
[6K2V:6:  
tag处理类 C$){H"#  
Wg[?i C*~  
简单的tag处理类必须实现Tag接口的doStartTag和doEndTag方法。当jsp引擎碰到tag标签的开头时,doStartTag被调用,因为简单的tag没有body,所以此方法将返回 SKIP_BODY。当jsp引擎碰到tag标签的结尾时,doEndTag被调用,如果余下的页面还要被计算,那它将返回EVAL_PAGE,否则将会返回SKIP_PAGE。 k^Zpb&`Hx  
R?qVFMQ  
以下是例子:对于标签 <tt:simple /> ,它的tag处理类实现如下: il<D e]G  
F')T:;,s  
z}.!q{Q  
public SimpleTag extends TagSupport MVg`6&oH  
t>7t4>X  
{ gGw6c" FRQ  
-}%'I ]R=  
public int doStartTag() throws JspException Q-F'-@`(C  
</t_<I0{  
{ bv;&oc:r  
QtJe){(z+  
try{ 3:<+9X  
F+*>q  
pageContext.getOut().print(“Hello.”); 1B'i7  
hghtF  
}catch(Exception e){ *U.$=4Az  
 twz  
throw new JspTagException(“SimpleTag: “ + e.getMessage()); 4U<'3~RN  
pWSYbN+d  
} ?4Lb*{R  
h#zx^F1  
return SKIP_BODY; to[EA6J8l  
=}\]i*  
} |~8\{IcZ  
2]eh[fRQ  
public int doEndTag() ' :g8a=L  
KD$P\(5#  
{ w!:u|  
e~$MIHBY]  
return EVAL_PAGE; C@pDX>~2=b  
,Ot3N\%yn  
} Id]WKL:  
$ 8_t.~q  
} V J){@  
.Y_RI&B!L  
c1wgb8  
注意:如果tag标签没有内容的话,那必须定义body-content元素为空,例如 \>cZ=  
`>?\MWyu  
<body-content>empty</body-content> hOfd<k\A  
S#jH2fRo  
]j*o&6cQf  
带属性的tag标签
评价一下你浏览此帖子的感受

精彩

感动

搞笑

开心

愤怒

无聊

灌水
级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
只看该作者 1 发表于: 2007-01-01
tag处理类 A6lf-8ncx  
6 Y&OG>_\  
对于tag标签的每个属性,你必须依照JavaBeans规范来定义其属性,以及get和set方法。以struts的logic:present 标签为例, -jC. dz  
. Nog.  
<logic:present parameter=”Clear”> F`Q,pBl1p6  
"^_p>C)T  
与此相应,此tag处理类应有如下方法和定义: #A:I|Q1$g  
}5Y.N7F  
bRNE:))r_  
protected String parameter = null; Ug_zyfr  
)KXLL;]  
public String getParameter() <+_OgF1G  
jXZKR(L  
{ rxP^L(q0*  
g'pE z  
return this.parameter; O(&EnNm[2  
G9E?   
} eDaVoc3  
O;H/15j:sK  
public void setParameter(String parameter) . s? ''/(  
U?#6I-  
{ aEZl ICpU7  
eWwSD#N#  
this.parameter = parameter; R#1m_6I  
m?[F)<~a  
} Lb2Bu>  
qmxkmO+Qur  
]t(g7lc}U  
注意:如果你的属性名为id,而且你的tag处理类是从TagSupport类继承的,那你就不需要定义它的属性和set和get方法,因为他们早已在TagSupport被定义过了。 *:\QD 8^  
BAm{Gb  
Attribute元素 L?al2aopF  
i]Kq  
对于tag标签的每个属性,你必须定义它是否必须的,它的值是否可以用诸如<%= …%>的表达式来获得,以及它的类型(可选),如果不指定它的类型,那就默认为是java.lang.String类型。如果rtexprvalue元素被定义为true或yes,那么在type元素中就定义了attribute的返回类型。 .YS[Md{  
K<s\:$VVh  
<attribute> o"[qPZd>  
v+Mt/8  
<name>attr1</name> {_k 6t  
rTmcP23]  
<required>true|false|yes|no</required> &p=~=&g=  
3*8#cSQ/6o  
<rtexprvalue>true|false|yes|no</rtexprvalue> E(u[?  
"}PmAr e  
<type>attribute的返回类型(只用当rtexprvalue为真是才有效)</type> |nm,5gPNC  
zaoZCyJT%  
</attribute> 1 #EmZ{*  
P_b00",S  
如果tag的某个属性不是必须的,那tag处理类会自动提供一个缺省值。 !_x-aro3<  
(q +Q.Q  
例如,在logic:present这个tag标签中定义了一个属性叫parameter,但它不是必须的,而且它可以被诸如<%= …%>的表达式来赋值。 -O(.J'=8  
N18Zsdrp  
<tag> A`OU} 'v?L  
v{%2`_c  
<name>present</name> _Z8zD[l  
[k1N`K(M  
<tag-class>org.apache.struts.taglib.logic.PresentTag</tag-class> Cs*u{O  
hP 9+|am%  
<body-content>JSP</body-content> JY>]u*=  
E; RI.6y  
@8/-^Rh*  
:k(aH Ua  
<attribute> B&.XGo)  
a<vCAFQ  
<name>parameter</name> Gia_B6*Y[  
lIOLR-:4j  
<required>false</required> YpNTq_S1,  
e%UFY-2  
<rtexprvalue>true</rtexprvalue> *,Y+3yM  
jfgAI7;b  
</attribute> M+nz~,![  
FQ O6w'  
8+GlM+>4  
L {\B9b2  
</tag> O<o_MZN  
9nd'"$  
Ng;E]2"  
属性元素的校验 r[~K m5  
$Cf_RFH0  
vH7"tz&RIp  
有关于tag标签的有效值可以从tag库的说明文档中获得,当JSP页面被编译时,jsp引擎会强制性地参照TLD中定义的规则进行检查。 \mv7"TM  
JO1c9NyKr  
还有一个方法也可以进行属性元素的校验,就是先继承类TagExtraInfo,然后调用它的isValid方法。这个类同时也起到提供tag中定义的脚本变量信息的作用。 .s, hl(w,  
'MsxZqW"~  
IsValid方法通过TagData对象来传递属性信息,它包括着tag的所有的属性名-值的信息。由于校验发生在运行时刻,因此这个属性的值将被赋值为TagData.REQUEST_TIME_VALUE。 BBy/b c!  
e `_ [+y  
例如tag标签<tt:twa attr1=”value1” />在TLD中定义如下: j7uiZU;3Rx  
E#_}y}7JY  
<attribute> BU])@~$  
9~>;sjJk  
<name>attr1</name>  8tPq5i  
#PtV=Ee1  
<required>true</required> +]*?J1 Y8Z  
wRUpQ~=B2  
<rtexprvalue>true</rtexprvalue> "K~+T\^|k  
 ZY keW  
</attribute> _X;5ORH"  
m",$M>  
5/Swn9vwl  
这个定义说明了attr1能在运行期间被赋值。 0$* z   
\+S~N:@><k  
以下的isValid方法检查attr1属性的值是否属于Boolean类型。注意由于attr1能在运行刻被赋值,那么isValid方法必须检查tag用户是否对此tag进行了运行时刻赋值。 IXX^C}\,  
voV=}.(p  
1<fEz  
Public class TwaTEI extends TagExtraInfo j'CRm5O  
Z\O ,9  
{ m5f/vb4l  
fl+ [(x<  
public boolean isValid(Tagdata data) Uj6R?E{Jt  
0(-'L\<>x  
{ jw#'f%*  
WihOGdUS6  
Object o = data.getAttribute(“attr1”); > NK?!!A_  
){R_o5  
If(o != null && o != TagData.REQUEST_TIME_VALUE) Qn<J@%  
(a]'}c$X9`  
{ U}7$:hO"dX  
pk(<],0]X  
if( ( (String)o).toLowerCase().equals(“true”) || F!j@b!J8  
Y( D d7`c  
((String)o).toLowerCase().equals(“false”) ) )!p=0&z@{  
<}N0 y*m  
return true; mMu3B2nke=  
"uqa~R{  
else >x&$lT{OY  
#C4  
return false; Yy>%dL  
M _$pqVm  
} tCtR(mG=A  
BalOph4M[  
else U: gE:tf  
U-X  
return true; {HvR24#  
#=Q/<r.~G  
} 8p>%}LX/  
bHWy9-  
} <w.V!"!  
:a#]"z0  
9BNAj-Xa  
带body的tag 9%kY8#%SV  
: gv[X  
0%`\ 8  
tag处理类 m{(D*Vuqd  
Y\sLwLLlG  
.l !:|Fd  
如果tag标签含有内容,那处理方式会略微有些不同,而且还要视tag处理类是否要与body交互的情况而定。如果要与body交互,那我们认为tag处理类要可能要对body进行操作。 qPH]DabpI  
`S{< $:D  
Tag处理类不与body交互 :[|`&_D9J  
;oWhTj`  
如果tag处理类不与body交互,tag处理类应该实现Tag接口或从TagSupport中派生,如果body要被计算,那么doStartTag方法应返回 EVAL_BODY_INCLUDE,否则应返回SKIP_BODY。 ^X"G~#v=q  
g4RkkoZ>)  
如果tag处理类要对body反复运算,则它应该实现IterationTag或从TagSupport中派生。如果tag处理类认为body还未计算完的话,那它的doStartTag方法和doAfterBody方法必须返回EVAL_BODY_AGAIN。 yTkYPx  
/M v\~vg$1  
Tag处理类与body交互  .;iXe  
`H+ 7Hj  
如果tag处理类与body交互,那tag处理类应实现BodyTag接口或从BodyTagSupport中派生。这种tag处理类一般要实现doInitBody和doAfterBody方法。 g%1!YvS3v  
')Ozz<{  
Body允许一些方法来读写它的内容。Tag处理类可以调用body内容的getString或getReader方法来从body中提取信息,也可用 writeOut(out) 方法来将body的内容写入到out对象中。其中out对象通过tag处理类的getPreviousOut方法来获得。 v?fB:[dG  
hLYSYMUb  
如果body的内容需要被计算,那么doStartTag方法必须返回EVAL_BODY_BUFFERED,否则,它将返回 SKIP_BODY。 _ CXKJ]m4  
B~u{Lv TE  
doInitBody 方法 zP rT0  
WI[6 l6  
此方法在body内容已经设好,但未被计算之前被调用。你可以根据不同的body内容来制定初始化策略。 ZV_mP'1*  
pb_mW;JVu  
doAfterBody方法 {nm#aA%,  
hSp[BsF`,  
此方法在body内容已被计算后进行调用。 '[`.&-;  
mr E^D|  
和doStartTag方法一样,doAfterBody方法返回一个指示符指示是否要继续计算body,如果要继续计算,则doAfterBody应返回EVAL_BODY_BUFFERED,否则,它应返回SKIP_BODY。 qECc[)B  
JNuo+Pq  
release 方法 <kPU*P,  
o@EV>4e y  
tag处理类调用此方法将它的状态重置为初始状态,并释放所有的私有资源。 qqS-0U2  
TLPy/,  
= fuF]yL%  
以下的例子读取body的内容(其中含有一条sql语句),然后将它传递给一个对象,让它进行查询。由于此处body不须重新计算,所以doAfterBody会返回SKIP_BODY。 *~prI1e(  
oel3H5Nz  
i3rvD ch  
Public class QueryTag extends BodyTagSupport l \xIGs  
X~]eQaJ  
{ vyN =X]p  
F{bET  
public int doAfterBody() throws JspTagException #9#N+  
FL(gwfL  
{ $hg W>e  
i.0}qS?  
BodyContent bc = getBodyContent(); HPVT$EJ  
.6(Bf$E  
//将body的内容以字符串的格式提取出来 7:mM`0g!  
xfos>|0N  
String query = bc.getString(); ,Y &Q,  
&>i+2c~  
//清除body g#9KG  
- FA#hUK$  
bc.clearBody(); ,5t.0XqS  
Ocx=)WKdW  
try{ _BHb0zeot  
i. `S0  
Statement stmt = connection.createStatement(); )nQpO"+M  
)I.[@#-  
Result result = stmt.executeQuery(query); CuT[V?^iD  
vRRi"bo  
}catch(SQLException e){ i?4vdL8M  
SobK<6  
throw new JspTagException(“queryTag: “ + e.getMessage() ); G)5%f\&  
)q&uvfQ1(  
return SKIP_BODY; }4A+J"M4y  
QOy+T6en  
} #x':qBv#  
W O|2x0K  
} .CQ IN]iD  
C1r]kF  
)Qp?N<&'  
body-content元素 VAsaJ`vcb  
nCGLuZn  
/3'-+bp^=  
由于tag可能会有body,你必须用body-content元素来指定body内容的类型: v)okVyv  
^|>vK,q$I  
<body-content>JSP|tagdependent</body-content> B=u@u([.  
iNd 8M V  
NU I|4X  
如果body的内容是定制的或内部的tag、脚本元素、或HTML广本,则归类为JSP类型。其他的类型,比如上面代码所述的?D?D将sql statement类传给 query tag的这种类型应该标为tagdependent。 }`h)+Im=  
hgfCM  
注意:实际上body-content的值并不影响tag处理类对body内容的处理,它仅仅是被tag编辑工具用来描述此body的内容。 yZUB8erb.  
 x)THeH@  
aoI{<,(  
用tags定义脚本变量 7MOjZD4?  
MftX~+  
{-7];e  
tag处理类 eaYQyMv@  
! Hdg $,  
BqCBH!^x  
tag处理类负责创建或设置页面中定义的脚本变量,用pageContext.setAttribute(name,value,scope)或pageContext.setAttribute(name,value)方法来实现。一般来说,tag处理类通过脚本变量的名称来获取它,脚本变量的名称一般可用get方法来获得。 aOyAP-m,  
zw7=:<z=  
如果脚本变量的值依赖于tag处理类中的上下文中某一对象,那它可用pageContext.getAttribute(name,scope)方法来找到那个对象。一般的处理过程是tag处理类先找到脚本变量,再对其进行处理,然后用pageContext.setAttribute(name,object)的方法来设置它的新值。 q 1Rk'k4+  
TL1pv l  
对象的生存周期(scope)如下表: ,Hch->?Og  
xzz[!yJjG  
对象的生存周期表 %_KNAuM  
;jo,&C  
名字 g5; W6QX  
可访问范围 -KCm#!  
生存周期 >e>Q'g{  
~Q0jz/#c  
page 5ok3q@1_]{  
当前页面 hz>&E,<8q  
一直有效,除非页面向客户提交响应或重定向到一个新页面 TStu)6%`  
=V/$&96Q  
request g(;t,Vy,I  
当前页面或当前页面重定向到的页面 x5c pv  
一直有效,除非页面向客户提交响应 D?) "Z$  
"m3u}!`3  
session %)i?\(/  
当前页面或在同一浏览器窗口中的页面 [6FCbzS_W  
一直有效,除非关闭当前浏览器、超时、网络故障 rk-}@vp  
N|h`}*:x=  
application s~Ni\SF  
整个web应用程序的所有请求 =L 7scv%i  
一直有效,除非发生网络故障、服务器故障 ZgcA[P  
di "rvw;R  
提供关于脚本变量的信息 @j K7bab:  
R1! {,*Gy  
以下示例定义了一个名为“book”的脚本变量,用来访问程序中关于书的信息: B=(m;A#G  
53=VIN]  
<bean:define id=”book” name=”bookDB” property=”bookDetails” type=”database.BookDetails” /> <ij;^ygYD  
k =ru) _$2  
<font color=”red” size=”+2” > ']Nw{}eS`  
lo,?mj%M  
<%= messages.getString(“CartRemoved”) %> {[m %1O1  
@-NdgM<  
<strong><jsp:getProperty name=”book” property=”title” /></strong> 2w$o;zz1  
IMmoq={ (z  
</font> $"!"=v%B  
XTG*56IzL  
当包含此tag的JSP页面被编译时,jsp引擎会自动生成关于此book的同步的代码(同步可以避免几个客户同时访问此book时造成的冲突),要生成同步代码,jsp引擎需要知道此脚本变量的如下信息: pfe9 n[  
c]P`U(q9TV  
· 脚本变量名称 DDwH9*  
#VgPg5k.<  
· 脚本变量所属的类 Q$iYhR  
5 UpN/\He  
· 此脚本变量是否引用了一个新的或已存在的对象 GO.mT/rB  
razVO]]E  
· 此脚本变量的有效性 RC sQLKqF  
z:ue]7(.  
有两种办法可以向jsp引擎提供关于脚本变量的信息:在TLD中定义variable子元素,或用tei-class子元素定义一个额外tag信息类。用variable最简单,但可能降低了一些灵活性。 6#MIt:#  
+t({:>E  
Variable元素 7H:1c=U  
L%# #U'e3  
Variable元素有如下子元素: AMp[f%X  
9fp1*d  
· name-given ?D?D 给出的名字,是一个常量 ~c%H3e>Jcq  
YLVIn_\}  
· name-from-attribute?D?D 属性名,在编译时给出的属性名 %G1kkcdH<  
JK4vQWy  
name-given或name-from-attribute两者必须选一,但以下子元素是可选的: ow,I|A  
%a{$M{s  
· variable-class?D?D变量的类型,缺省为java.lang.String。 bF;g.-.2  
y m<3  
· declare?D?D此脚本变量是否引用了一个新对象,缺省为True。 .S>:-j'u  
YDE;mIW  
· scope?D?D脚本变量的范围,缺省为NESTED。下表描述了scope的几种类型: cs `T7?>  
-& I)3  
脚本变量的有效范围 paF$ o6\  
9^h0D}#@  
HP}d`C5<R  
有效性 GD<xmuo  
方法 M<hX !B  
:8cp]v dW  
NESTED `bw>.Ay  
在tag标签的开始和结束之间 ^  ry   
如果tag处理类实现BodyTag接口,则在doInitBody和doAfterBody中调用,否则在doStartTag中调用 2fM*6CaS  
~1jSz-s  
AT_BEGIN ;^za/h>r  
从tag标签的开始一直到页面结束 O>9+ tQ  
如果tag处理类实现BodyTag接口,则在doInitBody、doAfterBody和doEndTag中调用,否则在doStartTag和doEndTag中调用 RoCX*3d  
49q\/  
AT_END jHBzZ!<  
从tag标签的结束一直到页面结束 uH7 $/  
在doEndTag中调用 pT\>kqmj  
8R<2I1xn2  
以struts为例,它的bean:define标签的实现遵循JSP1.1规范,此规范要求使用额外tag信息类来定义脚本变量。Variable元素是JSP1.2规范中加入的。以bean:define标签为例,你可以定义如下variable元素: gM~ dPM|  
`./$hh  
<tag> kXK D>."E*  
]f#1G$  
<variable> 2MaHD}1Jw  
\6~(# y  
<name-from-attribute>id</name-from-attribute> y ,e# e`  
nA$zp  
<variable-class>database.BookDetails</variable-class> ;LSdY}*%0  
`IL''eJug_  
<declare>true</declare> f'._{"  
xV@/z5Tq  
<scope>AT_BEGIN</scope> d;1%Ei3K  
fR[kjwX)<1  
</variable> `(NMHXgG+  
kH:! 7L_=  
</tag> $*a'[Qot#  
yU'Fyul  
额外tag信息类 CJ0{>?  
X.TsOoy  
如果要定义一个额外tag信息类,你要继承javax.servlet.jsp.TagExtraInfo类。一个TagExtraInfo类必须实现getVariableInfo方法,此方法返回一个叫VariableInfo的数组类,它包括如下信息: sswYwU  
[AgS@^"sf5  
· 变量名 h^QicvZ  
h2M>4c  
· 变量所属类名 -:Up$6PR  
RE~:+.eB  
· 此变量是否引用了一个新对象 7\ELr 5  
}s i{  
· 此变量的有效范围 ]3UEju8$  
%^1@c f?.  
jsp引擎将一个名为data的参数传给getVariableInfo方法,data中包括tag标签中的所有“属性名?D?D属性值”对。它可以用来向VariableInfo对象提供脚本变量的名字和类名。 l!U F`C0g  
yKSvg5lLy  
以struts为例,它在bean:define标签中定义了一个名为DefineTei的额外tag信息类,用来向脚本变量提供信息。由于脚本变量的名称(book)和类名(database.BookDetails)是通过tag标签的属性来传递的,它们一般定义在VariableInfo的构建代码中,并且可用data.getAttributeString方法来得到这些信息。如果要允许book脚本变量能在从tag开始直到整个JSP页面结束的范围内都可用的话,那它的范围应设为AT_BEGIN。如下所示: VsLlPw{  
Z :51Q  
)q#1C]7m*  
public class DefineTei extends TagExtraInfo xB.h#x>_`  
II(7U3  
{ :v-&}?  
<<a1a  
public VariableInfo[] getVariableInfo(TagData data) Ci{,e%  
gKyYBr  
{ B[2 qI7D$  
ean_/E  
String type = data.getAttributeString(“type”); +v$,/~$tI  
!yxb=>A  
If( type == null) UvwO/A\Gv  
!2]eVO  
type = “java.lang.Object”; 7Q_AZR 4  
~CTe5PX c  
return new VariableInfo[] { 7;]n+QRfm  
%qN_<W&Ze  
new VariableInfo(data.getAttributeString(“id”), kl(id8r  
Rn] `_[)*~  
type, G.#`DaP  
tXZE@JyuC  
true, h%2;B;p]  
xV]eEOiLM  
VariableInfo.AT_BEGIN) cu)ssT  
Z %?: CA  
}; @(k}q3b<  
ui _nvD:  
} 6 GL.bS  
1Z. D3@  
} dS+/G9X^  
s"tyCDc.c  
P~"e=NL5  
注意:关于额外tag信息类的类名必须要在TLD中的tag标签下的tei-class子元素中定义。因此,DefineTei的tei-class中的定义看起来如下: >gQJ6q  
<tei-class> d<x7* OW)  
org.apache.struts.taglib.bean.DefineTagTei e|6kgj3/  
</tei-class> 6oh\#v3zV  
NI^=cN,l  
+0{$J\s  
具有协作关系的tag %3"xn!'vf  
k/U1 :9  
% s|` 1`c  
tag通过共享对象来进行协作,JSP技术支持2种方式的对象共享。 '>8IOC  
C2l=7+X#W  
第一种方法是使用pageContext对象进行对象的共享(可支持JSP页面和tag处理类之间的共享),如果在一个tag处理类中要调用由另一个tag处理类创建的对象,可调用pageContext.getAttribute(name, scope)方法。 )qyJw N .D  
uItzFX*   
第二各方式的共享是对于tag之间有嵌套关系而言的,外层的tag所创建的对象对于内层的tag来说是可以共用的。这种形式的共享的好处是减少了可能存在的重名冲突。 P@LFX[HtM  
S-^:p5{r  
要访问一个嵌套tag创建的对象,tag处理类必须先找到此嵌套tag对象,可用TagSupport的静态方法 TagSupport.findAncestorWithClass(from, class)或TagSupport.getParent方法。前者在当不确定此tag是否为嵌套tag对象时使用。一旦它的父类被找到,它就能访问其所有动态或静态创建的对象。静态创建的对象是父类的成员,而动态创建的对象可能是父类的私有对象。诸如此类的对象可以用tag处理类的setValue方法来保存,用getValue方法来获得。 5X4 #T&.  
*9XKkR<r  
下例阐述了以上两种共享对象的方法。在这个例子当中,一个查询tag检查一个名为connection的属性名是否在doStartTag中被设置。如果connection属性被设置,tag处理类从pageContext中得到这个connection对象。否则,此tag处理类先找到它的父tag处理类,然后从它的父tag处理类中找到connection对象。 F!N D  
;7;=)/-  
Z}b25)  
public class QueryTag extends BodyTagSupport n5Coxvy1  
 BVJ6U[h`  
{ zCpsGr  
w)nFH)f  
private String connectionId; @pV~Q2%  
4@qHS0$  
public int doStartTag() throws JspException jyLE  
+n'-%?LD&  
{ Bv=  
2aDjt{7P  
String cid = getConnection(); zp4aiMn1F  
t9QnEP'  
if(cid != null) >e'Hz(~'/  
b6]MJ0do  
{ 5 R*  
\f!j9O9S  
//存在一个connection id,使用它。 XCN^>ToD  
Y&![2o.Q  
connection = (Connection) pageContext.getAttribute(cid); ep,"@,,  
# $N)  
} VR'R7  
EF8~rKO3  
else :l;SG=scx  
7NFRCCXHQ  
{ ?q*,,+'0  
:j<ij]rsI  
ConnectionTag ancestorTag = (ConnectionTag)findAncestorWithClass(this, _aaQ1A`p  
4#MPD  
ConnectionTag.class); e`7dRnx&0  
+";<Kd-  
if(ancestorTag == null) e I^Q!b8n  
Xc}~_.]  
{ `mt x+C  
]di^H>,xU  
throw new JspTagException(“一个没有connection属性的查询标签必须被一个connection标记嵌套。”); -(;<Q_'s{"  
L>ruNw'-K  
} W,D$=Bg  
QnZ7e#@UP  
connection = ancestorTag.getConnection(); Z'<I Is:J  
32S5Ai@Cd"  
} S9;:)  
5*#3v:l/9  
} gm1 7VrC  
ExW3LM9(  
} NDo>"in  
M3EB=tU  
;;]^d_  
aGx[?}=  
此查询标签在JSP页面中的调用形式可以从以下2种定义中任选一种: &2Q0ii#Aa  
9x]yu6  
-]-?>gkN5  
<tt:connection id=”con01” ...> ... </tt:connection> 3;F+.{Icc  
v K7J;U+cJ  
<tt:query id=”balances” connection=”con01” > !]l!I9  
g-NfZj?  
SELECT account, balance FROM acct_table C%ZSsp u  
Mv1V Vk  
where customer_num = <%= request.getCustno() %> WWtksi,  
';J><z{>  
</tt:query> fEYo<@5c]  
uupfL>h  
wF.S ,|  
;#+Se,)  
a'prlXr\4  
<tt:connection ...> `U6bI`l  
g>&b&X&Y_  
<x:query id=”balances”> -6yFE- X/  
XT<{J8 0z  
SELECT account, balance FROM acct_table JZom#A. dt  
4/+P7.}ea-  
where customer_num = <%= request.getCustno() %> G8hq;W4@]/  
,f3Ck*M  
</x:query> d~za%2{  
q s 0'}>  
</tt:connection> /t;Kn m  
#$*l#j"#A  
vN8Xq+  
与此同时,在TLD中必须指定connection属性为可选的,定义如下: j{: >"6  
9?i~4&EY  
<tag> <}z, !w8  
m! H7;S-(  
... o?]g  
o0`|r+E\  
<attribute> n+94./Mh  
^Ss4<  
<name>connection</name> WY`hNT6M  
(Tbw@BFk  
<required>false</required> jxdxIkAHZc  
j?gsc Q3  
</attribute> 8Z1pQx-P2C  
\}9GK`oR  
</tag>
描述
快速回复

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