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

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

级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
标准的JSP 标记可以调用JavaBeans组件或者执行客户的请求,这大大降低了JSP开发的复杂度和维护量。JSP技术也允许你自定义taglib,其实换句话说,taglib可以看成是对JSP标记的一种扩展,正如xml是对html的一种扩展一样。taglib通常定义在tag标签库中,这种标签库存放着你自己定义的tag标签。简而言之,如果使用taglib,那么你可以设计自己的JSP标记! tI5*0  
EVE"F'Ww,_  
一般来说,自定义tag标签主要用于操作隐藏对象、处理html提交表单、访问数据库或其它企业级的服务,诸如邮件和目录操作等等。自定义tag标签的使用者一般都是那些对java编程语言非常精通,而且对数据访问和企业级服务访问都非常熟悉的程序员,对于HTML设计者来说,使得他可以不去关注那些较复杂的商业逻辑,而将精力放在网页设计上。同时,它也将库开发者和库使用者进行合理分工,自定义tag标签将那些重复工作进行封装,从而大大提高了生产力,而且可以使得tag库可用于不同的项目中,完美地体现了软件复用的思想。 &.PAIe.  
c= ?Tu  
在这篇文章中,我们主要讨论: BqDsf5}jpA  
SLp nVD:'1  
· 什么是自定义tag标签? D(WV k  
F`,Hf Cb\  
· 怎么使用tag标签? Nq|y\3]  
SR_ -wD  
o 声明要使用的tag库 M1T.  
m"6K_4r]  
o 找到与之对应的tag处理类 'I:_}q  
Bwu?DK  
o tag标签的类型 IkxoW:L  
Ocn@JOg  
· 自定义tag标签 qE VpkvEq  
*SpE XO  
o tag处理类 s,l*=<  
=W>a~e]/  
o tag库描述 PWquu`  
P# U|  
o tag标签示例 c#>:U,j  
C5jt(!pi  
o 带属性的tag 4W<[& )7  
7#X`D  
o 带body的tag [Z&<# -  
Zq H-]?)  
o 定义了脚本变量的tag t:v>W8N53  
4ElS_u^cP7  
o 具有协作关系的tag 5 +j):_  
V|*3*W  
· 自定义tag标签 [57`V &c5  
x<@i3Y{[  
o 一个迭代tag的例子 7]i6 Gk  
\< a^5'  
o 一个模板tag库 T)Q_dF.N  
6Q{OM:L/;.  
o tag处理类到底是怎样被调用的? mS49l  
!D V0u)k(  
$BG]is,&5  
什么是自定义的tag? f zL5C2d  
z46Sh&+  
一个自定义的tag标签是用户定义的一种JSP标记。当一个含有自定义的tag标签的JSP页面被jsp引擎编译成servlet时,tag标签被转化成了对一个称为tag处理类的对象进行的操作。于是当JSP页面被jsp引擎转化为servlet后,实际上tag标签被转化成为了对tag处理类的操作。 } :gi<#-:G  
[HQ/MkP-Z  
自定义tag标签有很多特色,诸如: }_H\ 75Iv  
U-U(_W5&  
· 可以在JSP页面中自定义tag标签的属性 kf#S"[/E  
 +ZFN8  
· 访问JSP页面中的所有对象 _a_T`fE&de  
;ZMIYFXRqh  
· 可以动态地修改页面输出 fZ^ad1o  
~y whl'"k  
· 彼此这间可以相互通信。你可以先创建一个JavaBeans组件,然后在一个tag中调用此JavaBeans组件,同时可以在另一个tag中调用它。 ] ;HCt=I~  
^t$uDQ[hA  
· tag允许相互嵌套,可以在一个JSP页面中完成一些复杂的交互。 ;Cjj_9e,:  
n36iY'<)G  
"$ISun=8  
使用tag标签 gA3f@7}d  
}]<|`FNc  
@x;(yqOb  
本节主要描述怎样在JSP页面中使用tag标签,以及tag标签的不同类型。 S@y?E}  
{A5$8)nl|  
要使用tag标签,JSP程序员必须做2件事: ;lt8~ea  
uD[T l  
· 声明此tag标签的tag库 77wod}h!:  
,DEcCHr,  
· 实现此tag标签 563ExibH  
Vi0D>4{+  
声明tag标签所在的tag库 QjYw^[o  
%;<g!Vw.k  
如果要使用tag标签,则应用JSP的taglib指示符来指定其tag库(注意:taglib要在在使用此tag标签之前声明) L|;sB=$'{  
JxEz1~WK &  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> !DHfw-1K  
P^U.VXY}  
uri属性定义了唯一的标签库描述(以下简称TLD),它可以是直接是tld文件名或一个独一无二的名字。prefix是用来区别其它TLD中和本TLD中有重名的tag的一种手段。 H^vA}F`  
4$U^)\06W  
TLD必须以.tld作为扩展名,并且存放在当前应用的WEB-INF目录或其子目录下。你可以通过它的文件名直接引用它,也可以通过别的方式间接地引用它。 /;!I.|j  
E]S:F3  
以下taglib指示符直接引用一个TLD: K$r)^K=s  
/x_AWnU  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> @2hOy@V  
Y]5MM:mI  
以下的taglib指示符通过一个逻辑名称间接地引用一个TLD: `)MKCw$e  
fvV"H{V,  
<%@ taglib uri=”/tutorial-template” prefix=”tt” %> >;VZB/ d  
zz(EH<>  
如果是间接引用TLD的话,那你必须还要在web.xml中定义此逻辑名称与tld文件之间的映射,具体做法是在web.xml中加入一个名为taglib的元素: nwqA\  
Y0m?ZVt  
<taglib> yJ6g{#X4K<  
q|r*4={^!*  
<taglib-uri>/tutorial-template</taglib-uri> ;vbM C74J#  
"" _B3'  
<taglib-location> 6Ypc]ym=J  
] ;CJ6gM~  
/WEB-INF/tutorial-template.tld <Z\{ijfvD  
 5PC:4  
</taglib-location> {wDe#c{_  
x3.,zfWs  
</taglib> !\O!Du  
FJxb!- 0&  
vo2GFo  
实现此tag标签 m}S}fH(  
W5~!)Ec  
?{5}3a bB`  
为了实现tag标签,你有2种方法来存放tag处理类。一、让tag处理类以.class的方式存放于当前应用的WEB-INF/class子目录下,二、如果tag处理类是以JAR包的形式存在的话,那可以放在当前应用的WEB-INF/lib目录下,如果tag处理类要在多个应用中共享,那么它就应放在jsp服务器上的common/lib目录下,对于tomcat来说,就是tomcat/common/lib目录下。 X|QokAR{$>  
.])X.7@x  
 Vo%Z|  
tag标签类型 {z;4t&5  
" SP6o  
Xs'qwL~{`  
自定义的tag标签遵循XML语法。它有一个开始标记和一个结束标记,有的还有body(即文本节点): >$)~B 4  
wfcR[  
<tt:tag> 1?.NJ<)F  
{vZAOz7#  
body w ykaf   
6UL9+9[C  
</tt:tag> N.ZuSkRM  
2"%f:?xV{  
H0.A;`  
一个不带body的tag标签如下: %Z,n3iND  
Z+[W@5q  
<tt:tag /> f/4DFs{  
rw0s$~'  
.j=mT[N,I  
简单的tag标签 %Y5F@=>&  
f&RjvVP?s  
一个没有body和属性的tag标签如下: 2iOYC0`!  
]D=fvvST  
<tt:simple /> )%f]P<kq6  
475g-t2"@  
XD_!5+\H1  
带属性的tag标签 h^''ue"  
W )Ps2  
i&DUlmt)f  
自定义标签可以有自己的属性。属性一般在开始标记中定义,语法为 attr=”value”。属性的作用相当于自定义标签的一个参数,它影响着tag处理类的行为。你可以在TLD中详细定义它。 y7GgTC/H  
B ?y[ %i  
你可以用一个String常量给一个属性赋值,也可以通过表达式给它赋值,如<%= ...%>。以struts为例,它的logic:present标签就是用的String常量来给属性赋值: 'T3xZ?*q=  
%=\*OIhl  
<loglic:present parameter = “Clear”> e$JATA:j  
Dk8@x8  
而另一个标签logic:iterate是用表达式来给属性赋值: Kxz|0l  
4mpcI  
<logci:iterate collection=”<%= bookDB.getBooks() %>” G|"m-.9F  
UISsiiG(  
id=”book” type=”database.BookDetails”> #uCfXJ-  
% I2JS  
gFfKK`)}D'  
带body的tag标签 .WuSW[g  
v-Q>I5D;:  
一个自定义标签可以包含其它自定义标签、脚本变量、HTML标记或其它内容。 /q'-.-bo  
(NJ.\m  
在下述例子中,此JSP页面使用了struts的logic:present标签,如果些标签定义了parameter=”Clear”的属性,则将清除购物车的内容,然后打印出一条信息: wwJs_f\  
GMoz$c6n_  
<logic:present parameter=”Clear”> #CB Kt,  
|oe  
<% cart.clear(); %> <E^;RG  
4MtRI  
<font color=”#ff0000” size=”+2”><strong> wrK@1F9!  
E&U_@ bc-  
你选择了清除购物车! ZA@zs,o%  
i*A_Po  
</strong></font> GxC\Nj#  
HEhBOER?  
</logic:present> |+>U91!  
I9`ZK2S  
!67xN?b  
到底是用属性还是用body来传递信息? tAujm*|&  
aH8]$e8_,\  
如上所述,我们既可以通过属性,也可以通过body来传递信息。但一般来说,比较简单的类型,如字符串或简单表达式最好采用属性来传递信息。 ;W FiMM\  
ez5>V7Y  
yMD0Tj5ZQ  
定义脚本变量的tag标签 /V#? d  
+V[;DOlll  
所谓脚本变量,是指JSP中可以调用的变量或对象。它可由tag标签产生。以下示例阐述了一个tag标签定义了一个名为tx的由JNDI所定义的事务处理对象。脚本变量可以是ejb对象、事务、数据库连接等等: 'Z#>K*  
-C!m#"PDW  
<tt:lookup id=”tx” type=”UserTransaction” name=”java:comp/UserTransaction” /> tT]mMlKJ  
5Nbq9YY  
<% tx.begin(); %> =ReSlt  
u|D L?c>W  
... E]r<t#  
KDA2 H>  
s vS)7]{cU  
具有协作关系的tag标签 {/>uc,8O  
[UB*39D7  
自定义tag标签之间可以通过共享对象来实现协作。在下述例子中,标签tag1创建了一个名为obj1的对象,在标签tag2仍可以重复使用obj。 0W+RVp=TL1  
[8oX[oP  
<tt:tag1 attr1=”obj1” value1=”value” /> wL6G&6]</W  
HYY+Fv5  
<tt:tag2 attr1=”obj1” /> Ae1b`%To  
NZFUCD)  
在以下这个例子当中,如果外层的tag标签创建了一个对象,那么其内层的所有tag标签都可以使用这个对象。由于这样产生的对象没有一个指定的名字,那么就可以将少重名的冲突。这个例子阐述了一系列协作的嵌套对象。 :()K2<E  
OIjG`~Rx  
<tt:outerTag> L&uPNcZ`-  
_?$w8 S%  
<tt:innerTag /> =e9<.{]S/  
a( N;| <  
</tt:outerTag> @uG/2'B(  
;z+}|>!  
: Cli8#  
Tag处理类 0~W6IGE~  
UDnCHGq  
,\d03wha  
Tag处理类必须实现Tag接口或BodyTag接口,不过现在一般都流行从TagSupport或BodyTagSupport类中继承,这些类或接口都可以在javax.servlet.jsp.tagext包中找到。 eW}-UeT  
uX&h~qE/  
当JSP引擎看到自己的JSP页面中包含有tag标签时,它会调用doStartTag方法来处理tag标签的开头,调用doEndTag方法来处理tag标签的结束。 pigu]mj  
SxcE@WM  
下表说明不同类型的tag所需要不同的处理过程: %*IH~/Ld;]  
`49!di[  
Tag处理类的方法 }h8U.k?v  
Lc "{ePFh  
Tag标签类型 w]V684[>  
所调用的方法 G9K& }_,  
8H8Q  
基本标签 \]\h,Y8  
doStartTag, doEndTag, release K2V?[O#  
t?=V<Yd1  
带属性的标签 lEb H4 g  
doStartTag, doEndTag, set/getAttribute1...N, release $~?)E;S  
^v:XON<  
带内容的标签 mmCGIX  
doStartTag, doEndTag, release lTtc#  
mGoC8t}iP  
带内容的标签,且内容重复循环 mD*!<<Sw  
doStartTag, doAfterBody, doEndTag, release yD8Qy+6L  
\{ C ~B;=  
带内容的标签,且内容与JSP交互 ![MtJo5  
doStartTag, doEndTag, release, doInitBody, doAfterBody, release .G"T;w 6d  
tq=M 9c  
一个tag处理类可以通过javax.servlet.jsp.PageContext来与JSP交互,通过javax.servlet.jsp.PageContext类,tag处理类可以访问JSP中的request、session和application对像。 WE-+WC!!:  
w]N;HlU  
如果tag标签是互相嵌套的,那内层的tag处理类可以通过它的parent属性来访问上层的tag处理类。 1W}k>t8?h'  
k ,r*xt  
一般情况都将所有的tag处理类打成了JAR的包,以便于发布。  J&+"  
O~6AX)|&=  
qQ,(O5$|  
Tag库描述(简称TLD) dwiLu&]u  
+8GxX$  
f}?p Y"yvO  
Tag库是用xml语言描述的,TLD包括了tag库中所有tag标签的描述,它一般用来被jsp服务器用来校验tag的语法正确性,或者被jsp开发者用来开发新的标签。 ^1aY,6I:  
N%u4uLP5k  
TLD的文件扩展名必须为.tld,而且必须放在当前WEB应用的WEB-INF目录或其子目录中。 _eH@G(W(  
GSH,;cY  
一个TLD的内容的开头必须遵守标准的XML开头,用于描述DTD和xml的版本,例如: BA T.>  
[?g}<fa  
<?xml version="1.0" encoding="ISO-8859-1" ?> pK/RkA1  
#sbW^Q'I  
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd"> %L-{4Z!"sI  
TLD必须以<taglib>来作为它的根元素,<taglib>的子元素如下表: fQ_tXY  
n-<`Z NMU  
T~p>Ed9  
<taglib>的子元素 ma"M?aM  
A v;NQt8ut  
Element dKw[#(m5v  
Description %uo#<Ny/ I  
&[yYgfsp  
tlib-version >gn@NJ2N  
Tag库的版本 !!Yf>0u#  
-; i:bE  
jsp-version F>%,}Y~B:  
Tag库所需要的jsp的版本 XZ3M~cD q  
blaXAqe  
short-name h_g "F@  
助记符,tag的一个别名(可选) 6r[pOl:  
e%0IE X  
uri _LWMz=U=J/  
用于确定一个唯一的tag库 6QPT  
B>cx[.#!  
display-name x@> ~&eP  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) 8%MF <   
zNEN[  
small-icon 8. %g&% S  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) =2} bQW  
H3Zt 3l1u+  
large-icon 1Eryw~,,9i  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) +hH7|:JQ  
A!$sO p  
description j1ap,<\.k  
对tag库的描述(可选) Ct3+ga$  
=~dsIG  
listener ER4#5gd  
参见下面listener元素 G2:.8 ok  
vQDR;T"]  
tag c5[ ~2e  
参见下面tag 元素 R F;u1vEQ8  
E <r;J  
Listener元素 :`4LV  
kkj_k:Eah  
一个tag库可能定义一些类做为它的事件侦听类,这些类在TLD中被称为listener 元素,jsp服务器将会实例化这些侦听类,并且注册它们。Listener元素中有一个叫listener-class的子元素,这个元素的值必须是该侦听类的完整类名。 $u)#-X;x  
|Y2n6gkH[  
Tag元素 KT<N ;[;  
ItAC=/(d  
每个tag元素在tag库中都要指出它的名字、类名、脚本变量、tag的属性。其中脚本变量的值可以直接在TLD中定义或通过tag附加信息的类来取得。每个属性描述了这个属性是否可以省略,它的值是否可以通过<%= …%>这样的JSP语法来获得,以及属性的类型。 Xxm7s S  
/5\{(=0  
每一个tag在TLD中对应一个tag元素,下表是tag元素的子元素: Prv=f@  
oL9ELtb ]s  
Tag元素的子元素 Kf6D$}  
JNu+e#.Y  
元素名称 dcE(uf  
描述 nyG5sWMpe  
q1/mp){  
name hm1.UE  
独一无二的元素名 ;*20b@  
:a( Oc'T  
tag-class mt-t8~A  
Tag标签对应的tag处理类 =]<X6!0mR  
!~-@sq  
tei-class ^)3=WD'!  
javax.servlet.jsp.tagext.TagExtraInfo的子类,用于表达脚本变量(可选) ,^@/I:  
~UsE"5  
body-content ,JJ1sf2A  
Tag标签body的类型 )_Iu7b  
?.nD!S@  
display-name _Vr}ipx-k  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) ,awkL :  
Jb8%A@Z+  
small-icon U8zs=tA  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) }</"~Kw!  
op_ 1J;RF  
large-icon j<L!(6B  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) O%Qz6R  
sWP_fb1  
description |j$$0N  
此tag标签的描述 t & 5s.  
miY=xwK&  
variable ED A6b]  
提供脚本变量的信息(同tei-class)(可选) (~:ip)v  
+n|@'= ]  
attribute tYUo;V  
Tag标签的属性名 9;A9Q9Yr  
!1bATO:x  
以下章节介绍对于不同类型的tag,如何具体地实现它们。 +1Rz+  
lhF)$M  
!@ )JqF.  
简单的tag 1Msc:7:L  
3 gW+|3E  
2(Nf$?U @0  
tag处理类 ;^8X(R  
d ?,wEfwp  
简单的tag处理类必须实现Tag接口的doStartTag和doEndTag方法。当jsp引擎碰到tag标签的开头时,doStartTag被调用,因为简单的tag没有body,所以此方法将返回 SKIP_BODY。当jsp引擎碰到tag标签的结尾时,doEndTag被调用,如果余下的页面还要被计算,那它将返回EVAL_PAGE,否则将会返回SKIP_PAGE。 <!?ZH"F0  
,u.A[{@py  
以下是例子:对于标签 <tt:simple /> ,它的tag处理类实现如下: !\q'{x5C  
Acb %)Y  
;]%Syrzp  
public SimpleTag extends TagSupport >i2WYT  
In}~bNv?  
{ biH ZyUJ  
BM02k\%  
public int doStartTag() throws JspException : )k|Onz  
3+I"Dm,  
{ Ys@\~?ym+  
e~$aJO@B.R  
try{ B)&z% +  
0-Wv$o[  
pageContext.getOut().print(“Hello.”); sTi3x)#xB  
#-g2p?+i&  
}catch(Exception e){ U+@rLQ.-  
?a~#`<  
throw new JspTagException(“SimpleTag: “ + e.getMessage()); u9ue>I /  
FF30 VlJ  
} /I0}(;^y  
U{3Pk0rZ  
return SKIP_BODY; ->@iw!5xu  
eXtlqU$  
} WAGU|t#."  
ET~^P  
public int doEndTag() 9:*a9xT,  
s&-dLkis{u  
{ VCUsvhI  
AH# Dk5#G  
return EVAL_PAGE; ? UBE0C  
5Yx 7Q:D  
} 2 57q%"  
eg>]{`WQ  
} oD%B'{Zs4  
;VgB!  
Yg]!`(db  
注意:如果tag标签没有内容的话,那必须定义body-content元素为空,例如 EA<x$O  
NO.5Vy  
<body-content>empty</body-content> b!z=:  
Ng\]  
S6c>D&Q  
带属性的tag标签
评价一下你浏览此帖子的感受

精彩

感动

搞笑

开心

愤怒

无聊

灌水
级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
只看该作者 1 发表于: 2007-01-01
tag处理类 kC0^2./p  
^xF-IA#ZeB  
对于tag标签的每个属性,你必须依照JavaBeans规范来定义其属性,以及get和set方法。以struts的logic:present 标签为例, *Q,9 [k  
s^-o_K\*c  
<logic:present parameter=”Clear”> 8"J6(KS  
v c b}Gk  
与此相应,此tag处理类应有如下方法和定义: ~> 5  
O3(H_(P  
Rnk&:c  
protected String parameter = null; nbSu|sX~r5  
HmRmZ3~  
public String getParameter() 3aEO9v,n  
QZ_8r#2x  
{ lA ZBlO  
Zs}EGC~&  
return this.parameter; #|acRZ9 }  
-o`|A767  
} $R/@%U)-o  
WD?COUEox  
public void setParameter(String parameter) &^])iG,Ew  
p`oHF  5  
{ kr5'a:F)  
_SQ0`=+  
this.parameter = parameter; X6EnC57  
5@{~8 30  
} g42Z*+P6N  
RRR=R]  
pL{:8Ed  
注意:如果你的属性名为id,而且你的tag处理类是从TagSupport类继承的,那你就不需要定义它的属性和set和get方法,因为他们早已在TagSupport被定义过了。 5s1XO*s)>X  
^%m~VLH  
Attribute元素 =42NQ{%@;  
?bl9e&/!  
对于tag标签的每个属性,你必须定义它是否必须的,它的值是否可以用诸如<%= …%>的表达式来获得,以及它的类型(可选),如果不指定它的类型,那就默认为是java.lang.String类型。如果rtexprvalue元素被定义为true或yes,那么在type元素中就定义了attribute的返回类型。 !v]~ut !p  
_Wo(;'.  
<attribute> j9$kaEf  
fZrB!\Q  
<name>attr1</name> 5Q@4@b{C  
+cx(Q(HD\  
<required>true|false|yes|no</required> AR5)Uw s  
N##- vV  
<rtexprvalue>true|false|yes|no</rtexprvalue> )r:gDd#/X  
?F@X>zR2  
<type>attribute的返回类型(只用当rtexprvalue为真是才有效)</type> +We=- e7  
+&8'@v$  
</attribute> 1Et{lrgh f  
MF.$E?_R  
如果tag的某个属性不是必须的,那tag处理类会自动提供一个缺省值。 \$D41_Wt|  
;F\sMf{  
例如,在logic:present这个tag标签中定义了一个属性叫parameter,但它不是必须的,而且它可以被诸如<%= …%>的表达式来赋值。 >&uR=Yd  
>I;J!{  
<tag> qwHP8GU  
[35>T3Ku  
<name>present</name> <5sP%Fs)  
EJJW  
<tag-class>org.apache.struts.taglib.logic.PresentTag</tag-class> [fr!J?/@  
x.aqy'/`  
<body-content>JSP</body-content> uKd79[1  
t%]b`ad  
rb<9/z5-  
dZ'H'm;,!  
<attribute> c"^g*i2&0  
xX2/uxi8  
<name>parameter</name> k= oCpXq^  
R'p- 4  
<required>false</required> P(Q}r 7F~(  
a #Pr)H  
<rtexprvalue>true</rtexprvalue> o.KE=zp&z  
m[6c{$A/w  
</attribute> tf?"AY4  
K8|>"c~  
CeW}z kcT  
l08JL  
</tag> Z6_E/S  
nO .:f  
K.::P84m;  
属性元素的校验 3B[u2o>  
;$rh&ET  
be:=-B7!  
有关于tag标签的有效值可以从tag库的说明文档中获得,当JSP页面被编译时,jsp引擎会强制性地参照TLD中定义的规则进行检查。 )dZ1$MC[  
3C(V<R?  
还有一个方法也可以进行属性元素的校验,就是先继承类TagExtraInfo,然后调用它的isValid方法。这个类同时也起到提供tag中定义的脚本变量信息的作用。 jin XK  
.+dego:  
IsValid方法通过TagData对象来传递属性信息,它包括着tag的所有的属性名-值的信息。由于校验发生在运行时刻,因此这个属性的值将被赋值为TagData.REQUEST_TIME_VALUE。 =z +iI;  
Q@? {|7:  
例如tag标签<tt:twa attr1=”value1” />在TLD中定义如下: g WHjI3;  
q;H5S<]/  
<attribute> }X^CH2,R  
Bz*6M  
<name>attr1</name> T{mIk p<  
Cw]bhaG g  
<required>true</required> ThJ`-Ro  
^<QF* !  
<rtexprvalue>true</rtexprvalue> Q DJe:\n  
.[>UkM0  
</attribute> >'2=3L^Q  
7DCu#Y[  
@8'LI8 \/  
这个定义说明了attr1能在运行期间被赋值。 iVqXf;eB!5  
4dI =  
以下的isValid方法检查attr1属性的值是否属于Boolean类型。注意由于attr1能在运行刻被赋值,那么isValid方法必须检查tag用户是否对此tag进行了运行时刻赋值。 C9"yu&l  
|A19IXZ\  
a qIpO  
Public class TwaTEI extends TagExtraInfo LQ.0"6oj  
Xrd-/('2  
{ T96M=?wh!  
P'D'+qS  
public boolean isValid(Tagdata data) %~^:[@xa*  
'w~e>$WI  
{ [eO6 H2@=z  
XZ[3v9?&n  
Object o = data.getAttribute(“attr1”); [Cf{2WB:7  
>19j_[n@VC  
If(o != null && o != TagData.REQUEST_TIME_VALUE) V( SRw  
SH#!Y  
{ ]8ob`F`m,  
P~7p~ke  
if( ( (String)o).toLowerCase().equals(“true”) || uT 2w2A;  
`Uy'YfYF  
((String)o).toLowerCase().equals(“false”) ) OIdoe0JR:O  
/[#5<;  
return true; ]sG^a7Z.X  
|^$?9Dn9.L  
else j<C p&}X  
Sx}61?  
return false; 40R7@Vaf  
71!'k>]h  
} xr).ZswQ  
`} :~,E  
else |;MW98 A  
>\5IB5'j  
return true; h\PybSW4s  
rv;is=#1  
} 8u4FagQ,  
lko k2  
} $7'KcG  
G>w+J'7  
1QJB4|5R#  
带body的tag L#9g ~>~  
Vf] ;hm  
g.d~`R@v  
tag处理类 qhqqCVrsW  
l F*x\AT  
$V2.@ X  
如果tag标签含有内容,那处理方式会略微有些不同,而且还要视tag处理类是否要与body交互的情况而定。如果要与body交互,那我们认为tag处理类要可能要对body进行操作。 h;S?  
 a5@XD_b  
Tag处理类不与body交互 );oE^3]f  
`}|$eF&  
如果tag处理类不与body交互,tag处理类应该实现Tag接口或从TagSupport中派生,如果body要被计算,那么doStartTag方法应返回 EVAL_BODY_INCLUDE,否则应返回SKIP_BODY。 `as6IMqJD  
Z }s56{!.  
如果tag处理类要对body反复运算,则它应该实现IterationTag或从TagSupport中派生。如果tag处理类认为body还未计算完的话,那它的doStartTag方法和doAfterBody方法必须返回EVAL_BODY_AGAIN。 |tqYRWn0  
`sPH7^R  
Tag处理类与body交互 ewORb  
4+'d">+|  
如果tag处理类与body交互,那tag处理类应实现BodyTag接口或从BodyTagSupport中派生。这种tag处理类一般要实现doInitBody和doAfterBody方法。 u:GDM   
66%4p%#b4  
Body允许一些方法来读写它的内容。Tag处理类可以调用body内容的getString或getReader方法来从body中提取信息,也可用 writeOut(out) 方法来将body的内容写入到out对象中。其中out对象通过tag处理类的getPreviousOut方法来获得。 \1mTKw)S  
r0/o{Y|l6  
如果body的内容需要被计算,那么doStartTag方法必须返回EVAL_BODY_BUFFERED,否则,它将返回 SKIP_BODY。 J1gLT $  
,%EGM+  
doInitBody 方法 h1jEulcMtq  
Z]x)d|3;  
此方法在body内容已经设好,但未被计算之前被调用。你可以根据不同的body内容来制定初始化策略。 +je{%,*  
@]xH t&j  
doAfterBody方法 drK &  
,R2;oF_  
此方法在body内容已被计算后进行调用。 Lc5I?}:;L  
[ %:%C]4  
和doStartTag方法一样,doAfterBody方法返回一个指示符指示是否要继续计算body,如果要继续计算,则doAfterBody应返回EVAL_BODY_BUFFERED,否则,它应返回SKIP_BODY。 XL!^tMk  
\+Pk"M  
release 方法 q$BS@   
gO,2:,  
tag处理类调用此方法将它的状态重置为初始状态,并释放所有的私有资源。 6h3TU,$r  
fs;pX/:FR  
4NxI:d$&*  
以下的例子读取body的内容(其中含有一条sql语句),然后将它传递给一个对象,让它进行查询。由于此处body不须重新计算,所以doAfterBody会返回SKIP_BODY。 ePxwN?  
vD'YLn%Q  
qF57T>v|  
Public class QueryTag extends BodyTagSupport )9'Zb`n  
PWbi`qF)r  
{ odNHyJS0  
c3q @]|aI  
public int doAfterBody() throws JspTagException [2Ot=t6]  
CWW|?  
{ WpPI6bd  
MMS#Ci=Lj  
BodyContent bc = getBodyContent(); | +r5D4]e  
-5TMV#i {  
//将body的内容以字符串的格式提取出来 T }^2IJ]  
6 ~d\+aV  
String query = bc.getString(); yOr5kWqX  
U9]&~jR  
//清除body nMU[S +  
i $W E1-  
bc.clearBody(); y~/i{a;1y  
[y(AdZ0*  
try{ X Cf!xIv  
`6QQS3fk!  
Statement stmt = connection.createStatement(); l_z@.</8P@  
-VPda @@w  
Result result = stmt.executeQuery(query); %^ g(2^  
; 6*Ag#Z  
}catch(SQLException e){ CyEEE2cV  
TATH,Sz:x  
throw new JspTagException(“queryTag: “ + e.getMessage() ); FErK r)  
5B,HJax  
return SKIP_BODY; [>wvVv  
:Yy8Ie#  
} {u_2L_  
'Bb@K[=s  
} /woC{J)4p  
<N}*|z7=b  
n9x&Ws;  
body-content元素 z}f;_NX  
\r7gubD  
``* !b >)  
由于tag可能会有body,你必须用body-content元素来指定body内容的类型: -e(,>9Q  
6> Ca O  
<body-content>JSP|tagdependent</body-content> o; N s-=  
StWF66u34&  
6kM'f}t[C  
如果body的内容是定制的或内部的tag、脚本元素、或HTML广本,则归类为JSP类型。其他的类型,比如上面代码所述的?D?D将sql statement类传给 query tag的这种类型应该标为tagdependent。 ;gmfWHB<  
Y%A KN  
注意:实际上body-content的值并不影响tag处理类对body内容的处理,它仅仅是被tag编辑工具用来描述此body的内容。 g"o),$tm  
?2$0aq  
 Im8c  
用tags定义脚本变量 KuohUH+  
.,7ZD O9{  
U)y~{E~c34  
tag处理类 [V_?`M  
JHIXTy__  
3PU'd^  
tag处理类负责创建或设置页面中定义的脚本变量,用pageContext.setAttribute(name,value,scope)或pageContext.setAttribute(name,value)方法来实现。一般来说,tag处理类通过脚本变量的名称来获取它,脚本变量的名称一般可用get方法来获得。 Mh;rhQ  
g1zX^^nd,V  
如果脚本变量的值依赖于tag处理类中的上下文中某一对象,那它可用pageContext.getAttribute(name,scope)方法来找到那个对象。一般的处理过程是tag处理类先找到脚本变量,再对其进行处理,然后用pageContext.setAttribute(name,object)的方法来设置它的新值。 "}'Sk(  
Q]NGd 0J  
对象的生存周期(scope)如下表: ^tY$pPA  
#Y'svn1H  
对象的生存周期表 .vJ t&@NO  
_z(ydL*  
名字 UZ}>@0  
可访问范围 UOtrq=y  
生存周期 {%Ujp9i  
I'%(f@u~  
page D"RxI)"HP  
当前页面 Vuu_Sd  
一直有效,除非页面向客户提交响应或重定向到一个新页面 5xF R7%_&  
'YUx&F cM  
request 9}DF*np`G  
当前页面或当前页面重定向到的页面 LwL\CE_6+  
一直有效,除非页面向客户提交响应 0nOp'Ky\k  
=gb(<`{>  
session [J6 b5  
当前页面或在同一浏览器窗口中的页面 6ISDY>p  
一直有效,除非关闭当前浏览器、超时、网络故障 L.M|o  
BL Q&VI4  
application mbm|~UwD  
整个web应用程序的所有请求  ;%tu;  
一直有效,除非发生网络故障、服务器故障 :\+\/HTbh  
ZFsJeF'"  
提供关于脚本变量的信息 \r+8}8  
G oJ\6& "  
以下示例定义了一个名为“book”的脚本变量,用来访问程序中关于书的信息: |L"!^Y#=D  
byUz  
<bean:define id=”book” name=”bookDB” property=”bookDetails” type=”database.BookDetails” /> qn4jy6  
<dA1n:3o  
<font color=”red” size=”+2” > 7 /$s!pV  
A"8"e*  
<%= messages.getString(“CartRemoved”) %> b!ea(D!:  
d3|oKP6  
<strong><jsp:getProperty name=”book” property=”title” /></strong> r=3knCEWK  
@JL+xfz  
</font> Q4JvFy0'  
:n?K[f?LfY  
当包含此tag的JSP页面被编译时,jsp引擎会自动生成关于此book的同步的代码(同步可以避免几个客户同时访问此book时造成的冲突),要生成同步代码,jsp引擎需要知道此脚本变量的如下信息: P,[O32i#  
*1 [v08?!  
· 脚本变量名称 '!6Py1i  
7~V,=WEe  
· 脚本变量所属的类 dq{wFI)  
AqzPwO^  
· 此脚本变量是否引用了一个新的或已存在的对象 }`,}e259  
oIP<7gz  
· 此脚本变量的有效性 < <vE.  
lV0\UySH  
有两种办法可以向jsp引擎提供关于脚本变量的信息:在TLD中定义variable子元素,或用tei-class子元素定义一个额外tag信息类。用variable最简单,但可能降低了一些灵活性。 NHCdf*  
~e!b81  
Variable元素 02~+$R]L  
Pkbx /\  
Variable元素有如下子元素: ]E+deM  
8C{mV^cn~  
· name-given ?D?D 给出的名字,是一个常量 =+qtk(p  
V~uH)IMkh7  
· name-from-attribute?D?D 属性名,在编译时给出的属性名 ]$>O--  
i: ZL0nH-  
name-given或name-from-attribute两者必须选一,但以下子元素是可选的: jB17]OCN  
H -sJt:  
· variable-class?D?D变量的类型,缺省为java.lang.String。 1.Ximom  
8SGFzb! h  
· declare?D?D此脚本变量是否引用了一个新对象,缺省为True。 WYb\vm =r  
v{}i`|~J  
· scope?D?D脚本变量的范围,缺省为NESTED。下表描述了scope的几种类型: ZO2$Aan  
aJC,  
脚本变量的有效范围 +hIStA  
}!i#1uHUH:  
w< hw>e^.  
有效性 KKd S h1  
方法 )-_]y|/D:r  
OeuM9c{  
NESTED WUM&Lq k"  
在tag标签的开始和结束之间 dT%$"sj5  
如果tag处理类实现BodyTag接口,则在doInitBody和doAfterBody中调用,否则在doStartTag中调用 $EB&]t+  
^0/FZ)V8  
AT_BEGIN +%'S>g0W=  
从tag标签的开始一直到页面结束 cVt MCgx  
如果tag处理类实现BodyTag接口,则在doInitBody、doAfterBody和doEndTag中调用,否则在doStartTag和doEndTag中调用 ]Fc<% wzp  
G 1 rsd  
AT_END N;9m&)@JR'  
从tag标签的结束一直到页面结束 93-UA.+g  
在doEndTag中调用 ) /kf  
' {L5 3cH=  
以struts为例,它的bean:define标签的实现遵循JSP1.1规范,此规范要求使用额外tag信息类来定义脚本变量。Variable元素是JSP1.2规范中加入的。以bean:define标签为例,你可以定义如下variable元素: S`Jo^!VJ4  
:)UF#  
<tag> TU-4+o%;  
I]"wT2@T;7  
<variable> bm>,$GW(  
QQso<.d&  
<name-from-attribute>id</name-from-attribute> v>FsP$p4yE  
"eq{_4dL  
<variable-class>database.BookDetails</variable-class> :@:i*2=  
brA\Fp^  
<declare>true</declare> ^T[8j/9o^  
eC^UL5>%  
<scope>AT_BEGIN</scope> :Rh?#yO 5  
p`jkyi  
</variable> bqHR~4 #IR  
2g elmQnc  
</tag> .a%D:4GYR  
,Jy@n]x  
额外tag信息类 +!'\}"q  
OSk+l  
如果要定义一个额外tag信息类,你要继承javax.servlet.jsp.TagExtraInfo类。一个TagExtraInfo类必须实现getVariableInfo方法,此方法返回一个叫VariableInfo的数组类,它包括如下信息: [i 18$q5D  
HJVi:;o  
· 变量名 HuPw?8w=  
.Vm!Ng )j  
· 变量所属类名 >~-8RM  
L> ehL(]!  
· 此变量是否引用了一个新对象 uES|jU{]b  
o5 UM)g  
· 此变量的有效范围 +>#SB"'  
v=A ]#O%  
jsp引擎将一个名为data的参数传给getVariableInfo方法,data中包括tag标签中的所有“属性名?D?D属性值”对。它可以用来向VariableInfo对象提供脚本变量的名字和类名。 '~HCYE:5  
7~@9=e8G  
以struts为例,它在bean:define标签中定义了一个名为DefineTei的额外tag信息类,用来向脚本变量提供信息。由于脚本变量的名称(book)和类名(database.BookDetails)是通过tag标签的属性来传递的,它们一般定义在VariableInfo的构建代码中,并且可用data.getAttributeString方法来得到这些信息。如果要允许book脚本变量能在从tag开始直到整个JSP页面结束的范围内都可用的话,那它的范围应设为AT_BEGIN。如下所示: ^t&S?_DSZ  
'u6T^YS  
mXd,{b'  
public class DefineTei extends TagExtraInfo PuvC MD  
Y40`~  
{ &@tD/Jw3  
:a M ZJm  
public VariableInfo[] getVariableInfo(TagData data) *f%uc  
,f@$a3}'Lx  
{ "HCJ!  
cFcn61x-  
String type = data.getAttributeString(“type”); rBd}u+:*  
v71j1Q}6  
If( type == null) "P) f,n  
&vf9Gp+MK  
type = “java.lang.Object”; {9kH<,PJ;!  
S]E1+,-*  
return new VariableInfo[] { A>@ i TI  
-nVQB146^  
new VariableInfo(data.getAttributeString(“id”), 6w3z&5DY|  
k8 !|WqfP  
type, #wXq'yi  
qPEtMvL #  
true, E+LAE/v@  
\qx$h!<  
VariableInfo.AT_BEGIN) kvWP[! j?)  
k3F* D  
}; ~*OQRl6F  
\J*~AT~5q  
} (twwDI  
p"A2N +  
} P9Ye e!*H  
X$aN:!1  
F't4Q  
注意:关于额外tag信息类的类名必须要在TLD中的tag标签下的tei-class子元素中定义。因此,DefineTei的tei-class中的定义看起来如下: x=1Iuc;&3  
<tei-class> f{ ;L"*L  
org.apache.struts.taglib.bean.DefineTagTei ,$"*X-1  
</tei-class> =Q\z*.5j.  
Rra3)i`*  
=L,s6J8_'  
具有协作关系的tag i2. +E&3v  
%gK@ R3p  
!GB\-(  
tag通过共享对象来进行协作,JSP技术支持2种方式的对象共享。 > -P UY  
asDk@G cu  
第一种方法是使用pageContext对象进行对象的共享(可支持JSP页面和tag处理类之间的共享),如果在一个tag处理类中要调用由另一个tag处理类创建的对象,可调用pageContext.getAttribute(name, scope)方法。 {y5v"GR{YM  
cK( )_RB#  
第二各方式的共享是对于tag之间有嵌套关系而言的,外层的tag所创建的对象对于内层的tag来说是可以共用的。这种形式的共享的好处是减少了可能存在的重名冲突。 uY{zZ4iw  
}BTK+Tk8  
要访问一个嵌套tag创建的对象,tag处理类必须先找到此嵌套tag对象,可用TagSupport的静态方法 TagSupport.findAncestorWithClass(from, class)或TagSupport.getParent方法。前者在当不确定此tag是否为嵌套tag对象时使用。一旦它的父类被找到,它就能访问其所有动态或静态创建的对象。静态创建的对象是父类的成员,而动态创建的对象可能是父类的私有对象。诸如此类的对象可以用tag处理类的setValue方法来保存,用getValue方法来获得。 s"hSn_m  
W6~aL\[  
下例阐述了以上两种共享对象的方法。在这个例子当中,一个查询tag检查一个名为connection的属性名是否在doStartTag中被设置。如果connection属性被设置,tag处理类从pageContext中得到这个connection对象。否则,此tag处理类先找到它的父tag处理类,然后从它的父tag处理类中找到connection对象。 ['<Q402:.  
5<Ly^Na:  
W 9i}w&  
public class QueryTag extends BodyTagSupport %2H0JXKa,  
?8ZOiY(  
{ #b u]@/  
#%Z 0!  
private String connectionId; 3X &'hz@  
O!uZykdX4!  
public int doStartTag() throws JspException K fM6(f:  
OZDd  
{ R^v-%mG9  
uu5AW=j  
String cid = getConnection(); MR=dQc  
EESGU(  
if(cid != null) +<l6!r2Z  
6wIo95`  
{ ]2:w?+T  
UweXz.x7  
//存在一个connection id,使用它。 (d9G`  
54X=58Q  
connection = (Connection) pageContext.getAttribute(cid); *$%ch=  
ld*W\  
} h/'b(9fS  
CcGE4BB  
else cSbyVC[r  
HPGIz!o  
{ kn$2_I9  
.|$:%"O&X  
ConnectionTag ancestorTag = (ConnectionTag)findAncestorWithClass(this, Fe r&X  
O4)'78ATp  
ConnectionTag.class); }u3Q*oAGl  
; 9n}P@  
if(ancestorTag == null) %4bGI/\/  
z%FBHj  
{ S*aVcyDEP  
6_G[&   
throw new JspTagException(“一个没有connection属性的查询标签必须被一个connection标记嵌套。”); yj:<3_-C*  
*5e"suS2  
} B//2R)HS  
MNuBZnO  
connection = ancestorTag.getConnection(); `_MRf[Z}  
I{/}pr>  
} 3np |\i  
_Wb3,E a=  
} 5L?_AUL  
'' Pu  
} U4$}8~o4  
Jw+k=>  
tv]^k]n{rf  
2|6E{o  
此查询标签在JSP页面中的调用形式可以从以下2种定义中任选一种: !iNN6-v%  
",v!geMvu  
j3-^,r t4  
<tt:connection id=”con01” ...> ... </tt:connection> sYfiC`9SO  
**,(>4j  
<tt:query id=”balances” connection=”con01” > 0Z.X;1=  
MH0xD  
SELECT account, balance FROM acct_table O:% ,.??<%  
q0m> NA   
where customer_num = <%= request.getCustno() %> MvCB|N"qy  
xYLTz8g=  
</tt:query> [=EmDP:@  
/h]#}y j  
No\3kRB4bi  
qUS y0SQ/l  
b41f7t=  
<tt:connection ...> x(]Um!  
5~R1KjjvA  
<x:query id=”balances”> GJr1[  
.!`y(N0hc  
SELECT account, balance FROM acct_table -X]?ql*%`  
F.Sc2n@7-  
where customer_num = <%= request.getCustno() %> .or1*-B K  
RJ+["[k  
</x:query> za,JCI  
Md*~hb8J  
</tt:connection> /bSAVSKR  
iB XS   
a_T3<  
与此同时,在TLD中必须指定connection属性为可选的,定义如下: J< vVsz+7:  
'kBq@>  
<tag> x/d(" Bb  
s7Z+--I)L  
... CMiE$yC  
Tlar@lC|u  
<attribute> nOm-Yb+F  
V [#$Sz[G  
<name>connection</name> 8[B0[2O  
BO%aCK&  
<required>false</required> Y00hc8<  
"y7IH GJ\3  
</attribute> 4!U)a  
lf9mdbm  
</tag>
描述
快速回复

您目前还是游客,请 登录注册
如果您提交过一次失败了,可以用”恢复数据”来恢复帖子内容
认证码:
验证问题:
10+5=?,请输入中文答案:十五