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

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

级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
标准的JSP 标记可以调用JavaBeans组件或者执行客户的请求,这大大降低了JSP开发的复杂度和维护量。JSP技术也允许你自定义taglib,其实换句话说,taglib可以看成是对JSP标记的一种扩展,正如xml是对html的一种扩展一样。taglib通常定义在tag标签库中,这种标签库存放着你自己定义的tag标签。简而言之,如果使用taglib,那么你可以设计自己的JSP标记! M7-piRnd4  
[]/=!?5B  
一般来说,自定义tag标签主要用于操作隐藏对象、处理html提交表单、访问数据库或其它企业级的服务,诸如邮件和目录操作等等。自定义tag标签的使用者一般都是那些对java编程语言非常精通,而且对数据访问和企业级服务访问都非常熟悉的程序员,对于HTML设计者来说,使得他可以不去关注那些较复杂的商业逻辑,而将精力放在网页设计上。同时,它也将库开发者和库使用者进行合理分工,自定义tag标签将那些重复工作进行封装,从而大大提高了生产力,而且可以使得tag库可用于不同的项目中,完美地体现了软件复用的思想。 :0$(umW@I"  
Vy.A`Hz  
在这篇文章中,我们主要讨论: 0 60<wjX6  
W"?|OQ'  
· 什么是自定义tag标签? C(Ujx=G+3  
-sm{Hpf_b  
· 怎么使用tag标签? [wG?&l$.KB  
9:4PJ%R9  
o 声明要使用的tag库 5\8Ig f>  
&&4av*\I  
o 找到与之对应的tag处理类 {>tgNW>)  
B;XFPQ#b  
o tag标签的类型  *>j u1f  
rp u9  
· 自定义tag标签 767xCP  
IE.JIi^w  
o tag处理类 ks< gSCB  
%Ez%pT0TQ#  
o tag库描述 1,=U^W.G  
uy)iB'st&  
o tag标签示例 u4bPj2N8I  
\!j{&cJ  
o 带属性的tag o)F^0t  
NX&mEz  
o 带body的tag lTW5> %  
I$xfCu  
o 定义了脚本变量的tag VJ;n0*/  
_;3xG0+  
o 具有协作关系的tag J @C8;]  
g#ubxC7t<  
· 自定义tag标签 N(q%|h<Z/=  
<^6|ZgR  
o 一个迭代tag的例子 0M(\xO  
Rd|};-  
o 一个模板tag库 -1d2Qed  
e#JJd=  
o tag处理类到底是怎样被调用的? 5jD2%"YUV  
)%Z<9k  
XSC._)ztEE  
什么是自定义的tag? !:t}8  
>M[wh>  
一个自定义的tag标签是用户定义的一种JSP标记。当一个含有自定义的tag标签的JSP页面被jsp引擎编译成servlet时,tag标签被转化成了对一个称为tag处理类的对象进行的操作。于是当JSP页面被jsp引擎转化为servlet后,实际上tag标签被转化成为了对tag处理类的操作。 Ql&5fyW  
RX}6H<5R  
自定义tag标签有很多特色,诸如: <iVn!P  
W(a31d  
· 可以在JSP页面中自定义tag标签的属性 u!?cKZw  
(Em^qN  
· 访问JSP页面中的所有对象 ^M6xRkI  
LPX@oha  
· 可以动态地修改页面输出 H(9%SP@[c  
LnP={s  
· 彼此这间可以相互通信。你可以先创建一个JavaBeans组件,然后在一个tag中调用此JavaBeans组件,同时可以在另一个tag中调用它。 ' _Ij9{M  
IOmQ1X7,  
· tag允许相互嵌套,可以在一个JSP页面中完成一些复杂的交互。 @N,dA#  
pYIm43r H  
'bVDmm).  
使用tag标签 VCfa<hn  
5D 9I;L{  
)!J0e-T-8O  
本节主要描述怎样在JSP页面中使用tag标签,以及tag标签的不同类型。 aF1i!Z  
swV/M i>  
要使用tag标签,JSP程序员必须做2件事: \9T CP;{  
p'z fo!  
· 声明此tag标签的tag库 1uBnU2E  
m[7@l  
· 实现此tag标签 5:v"^"Sz  
G6wBZ?)k  
声明tag标签所在的tag库 D]n9+!Ec1f  
?4v&TB@  
如果要使用tag标签,则应用JSP的taglib指示符来指定其tag库(注意:taglib要在在使用此tag标签之前声明) ``KimeA~  
]FV,}EZ  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> MebL Y $&8  
w:%3]2c  
uri属性定义了唯一的标签库描述(以下简称TLD),它可以是直接是tld文件名或一个独一无二的名字。prefix是用来区别其它TLD中和本TLD中有重名的tag的一种手段。 uz-O%R-  
`Mx&,;x  
TLD必须以.tld作为扩展名,并且存放在当前应用的WEB-INF目录或其子目录下。你可以通过它的文件名直接引用它,也可以通过别的方式间接地引用它。 CUIT)mF:  
A (z lX_  
以下taglib指示符直接引用一个TLD: %_Gc9SI  
x&>zD0\ :\  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> @vzv9c[  
?t<yk(q  
以下的taglib指示符通过一个逻辑名称间接地引用一个TLD: :uwB)G  
]M%kt+u!  
<%@ taglib uri=”/tutorial-template” prefix=”tt” %> > Q[L, I  
d +0(H   
如果是间接引用TLD的话,那你必须还要在web.xml中定义此逻辑名称与tld文件之间的映射,具体做法是在web.xml中加入一个名为taglib的元素: b5WtL+Z  
 peW4J<,  
<taglib> 7;0$UYDU*  
M.B0)  
<taglib-uri>/tutorial-template</taglib-uri> "Z xM,kI  
'u"r^o?  
<taglib-location> F?"#1j e  
v&}+ps_W  
/WEB-INF/tutorial-template.tld U Px7u%Do  
iIrH&}2  
</taglib-location> !<`}m E!:  
*\W *,D.I  
</taglib> 7-Bttv{  
|S0]qt?  
)X-~+X91 S  
实现此tag标签 PeCU V6  
79}voDFd  
08*O|Ym,  
为了实现tag标签,你有2种方法来存放tag处理类。一、让tag处理类以.class的方式存放于当前应用的WEB-INF/class子目录下,二、如果tag处理类是以JAR包的形式存在的话,那可以放在当前应用的WEB-INF/lib目录下,如果tag处理类要在多个应用中共享,那么它就应放在jsp服务器上的common/lib目录下,对于tomcat来说,就是tomcat/common/lib目录下。 g+CTF67  
VI:EjZ/|a  
> wsS75n1  
tag标签类型 ^)-* Ubzz  
St9+/Md=jQ  
]<y _ =>  
自定义的tag标签遵循XML语法。它有一个开始标记和一个结束标记,有的还有body(即文本节点): snU $Na3  
AH?T}t2  
<tt:tag> HI+87f_Q  
gie.K1@|  
body w?u4-GT  
K8>-%ns  
</tt:tag> h7 uv0a~0  
_4!SO5T  
y]9PLch]vZ  
一个不带body的tag标签如下: kd0~@rPL  
^5BLuN6  
<tt:tag /> BNA`Cc1VV  
ykq9]Xqhv  
i^Ba?r;*  
简单的tag标签 {R5{v6m_  
vsFRWpq  
一个没有body和属性的tag标签如下: g7>p,  
 D I` M  
<tt:simple /> Z.!tp  
SLCV|@G  
Y$tgz)  
带属性的tag标签 A'jw;{8NpF  
hU 3z4|~+  
+i %,+3#6  
自定义标签可以有自己的属性。属性一般在开始标记中定义,语法为 attr=”value”。属性的作用相当于自定义标签的一个参数,它影响着tag处理类的行为。你可以在TLD中详细定义它。 P:`tL)W_  
[1Os.G2  
你可以用一个String常量给一个属性赋值,也可以通过表达式给它赋值,如<%= ...%>。以struts为例,它的logic:present标签就是用的String常量来给属性赋值: |Wo_5|E  
f76bEe/B9  
<loglic:present parameter = “Clear”> Ds}ctL{6"  
J~\`8cds  
而另一个标签logic:iterate是用表达式来给属性赋值:  P5&mpl1  
-Odk'{nW  
<logci:iterate collection=”<%= bookDB.getBooks() %>” iJIDx9 )Z  
T3-8AUCK8?  
id=”book” type=”database.BookDetails”> >n`!S`)9{  
jsXj9:X I  
%cPz>PTW@  
带body的tag标签 !a(#G7zA  
)_7OHV *3  
一个自定义标签可以包含其它自定义标签、脚本变量、HTML标记或其它内容。 mAI<zh&SQ  
>Ei-Spy>Xl  
在下述例子中,此JSP页面使用了struts的logic:present标签,如果些标签定义了parameter=”Clear”的属性,则将清除购物车的内容,然后打印出一条信息: U}r^M( s!  
ig] hY/uT  
<logic:present parameter=”Clear”> \|OW`7Q)k  
"CS {fyJ  
<% cart.clear(); %> )ifEgBT  
%Pz'D6 /  
<font color=”#ff0000” size=”+2”><strong> &7gL&AY8  
'Z<V(;W  
你选择了清除购物车! |~6X: M61  
<Z8I#IPl  
</strong></font> wZ^ 7#yX>  
2N,<~L`FX'  
</logic:present> . q=sC?D  
dc ]+1 A  
im}=  
到底是用属性还是用body来传递信息? |'C {nTX  
Ym)8L.  
如上所述,我们既可以通过属性,也可以通过body来传递信息。但一般来说,比较简单的类型,如字符串或简单表达式最好采用属性来传递信息。 'CTvKW  
6NvdFss'A{  
pi'w40!:  
定义脚本变量的tag标签 OS X5S:XS  
` 0YI?$G1  
所谓脚本变量,是指JSP中可以调用的变量或对象。它可由tag标签产生。以下示例阐述了一个tag标签定义了一个名为tx的由JNDI所定义的事务处理对象。脚本变量可以是ejb对象、事务、数据库连接等等: Rh:@@4<  
(x.O]8GKP  
<tt:lookup id=”tx” type=”UserTransaction” name=”java:comp/UserTransaction” /> eyx;8v cM  
xz @/^Cj  
<% tx.begin(); %> r306`)kX  
c<'Pt4LY  
... ac/=%om8u  
>&1MD}  
8z?q4  
具有协作关系的tag标签 Cg~GlZk}  
JWu^7}@~=  
自定义tag标签之间可以通过共享对象来实现协作。在下述例子中,标签tag1创建了一个名为obj1的对象,在标签tag2仍可以重复使用obj。 yK1Z&7>J>  
:3,aR\  
<tt:tag1 attr1=”obj1” value1=”value” /> {AJcYZV  
U1+X!&OCp  
<tt:tag2 attr1=”obj1” /> QQ+?J~  
qqm7p ,j  
在以下这个例子当中,如果外层的tag标签创建了一个对象,那么其内层的所有tag标签都可以使用这个对象。由于这样产生的对象没有一个指定的名字,那么就可以将少重名的冲突。这个例子阐述了一系列协作的嵌套对象。 Y#'?3  
&&N]u e@>  
<tt:outerTag> ) o)k~6uT  
*3S ./ C}  
<tt:innerTag /> )czuJ5  
H#/}FoBiS  
</tt:outerTag> ^Fy{Q*p`(  
'?q \mi  
8s,B,s.  
Tag处理类 U!GG8;4  
tMWDKatb  
m=Z1DJG  
Tag处理类必须实现Tag接口或BodyTag接口,不过现在一般都流行从TagSupport或BodyTagSupport类中继承,这些类或接口都可以在javax.servlet.jsp.tagext包中找到。 R7/"ye:7J  
DPrFBy  
当JSP引擎看到自己的JSP页面中包含有tag标签时,它会调用doStartTag方法来处理tag标签的开头,调用doEndTag方法来处理tag标签的结束。 RHV& m()Q  
-ejH%CT  
下表说明不同类型的tag所需要不同的处理过程: gAy,uP~,  
@O;gKFx  
Tag处理类的方法 ryd*Ha">I  
s!\:%N  
Tag标签类型 @`qhQ  
所调用的方法 :hre|$@{a  
w7.I0)MH  
基本标签 ZH9sf~7  
doStartTag, doEndTag, release Q4gsOx P  
Up61Xn  
带属性的标签 -}liG  
doStartTag, doEndTag, set/getAttribute1...N, release N :#"4e  
F,Ls1  
带内容的标签 (T1)7%Xs  
doStartTag, doEndTag, release <NV[8B#k]  
gNon*\a,-B  
带内容的标签,且内容重复循环 xWY%-CWY.  
doStartTag, doAfterBody, doEndTag, release -Y#YwBy;M  
YlI/~J  
带内容的标签,且内容与JSP交互 ?v]EXV3  
doStartTag, doEndTag, release, doInitBody, doAfterBody, release fc'NU(70c  
(#Vkk]-p  
一个tag处理类可以通过javax.servlet.jsp.PageContext来与JSP交互,通过javax.servlet.jsp.PageContext类,tag处理类可以访问JSP中的request、session和application对像。 Ap&Bwo 8b  
_f9XY  
如果tag标签是互相嵌套的,那内层的tag处理类可以通过它的parent属性来访问上层的tag处理类。 qpo3b7(N  
efj[7K.h  
一般情况都将所有的tag处理类打成了JAR的包,以便于发布。 wS*An4%G  
[P5+}@t  
+,`Cv_O  
Tag库描述(简称TLD) dLV>FpA\  
L&[uE;ro  
;pK/t=$  
Tag库是用xml语言描述的,TLD包括了tag库中所有tag标签的描述,它一般用来被jsp服务器用来校验tag的语法正确性,或者被jsp开发者用来开发新的标签。 f(Vr&X  
-;/;dz;  
TLD的文件扩展名必须为.tld,而且必须放在当前WEB应用的WEB-INF目录或其子目录中。 h n:  
(vX+ Yw  
一个TLD的内容的开头必须遵守标准的XML开头,用于描述DTD和xml的版本,例如: &xK ln1z'  
+Y7"!wYR>  
<?xml version="1.0" encoding="ISO-8859-1" ?> Igowz7  
AE1EZ#  
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd"> 9i hB;m'C)  
TLD必须以<taglib>来作为它的根元素,<taglib>的子元素如下表: q~*9A-MH  
{q=(x]C  
11%<bmJ]Q3  
<taglib>的子元素 W(^R-&av  
8y9oj9 ;E]  
Element c&!EsMsU  
Description H7&>cM  
)tB:g.2k  
tlib-version 5F#Q1gP-  
Tag库的版本 4/6?wX  
TQXp9juK  
jsp-version }$6;g-|HX  
Tag库所需要的jsp的版本 CC Z'(Tkq  
gXrPZ|iS  
short-name O=2"t%Gc  
助记符,tag的一个别名(可选) 8ZmU(m  
N~c Y~a  
uri \UBTNY,  
用于确定一个唯一的tag库 `:=af[n   
0K+a/G@ n\  
display-name s L;  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) "eqNd"~  
{51<EvyE*  
small-icon ;ps 0wswX  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) \6]Uj+  
@xKfqKoqg  
large-icon $K_G|Wyi  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) /z'fFl^6O  
c34s(>AC  
description 4z {jWNM)N  
对tag库的描述(可选) Z/ Vb_  
hUL5V1-j  
listener : `Nh}Ka0  
参见下面listener元素 &bh%>[  
NeG$;z7  
tag $mH'%YDIl  
参见下面tag 元素 UbWeE,T~S  
w6b\l1Z  
Listener元素  1rnbUE  
Qyh_o  
一个tag库可能定义一些类做为它的事件侦听类,这些类在TLD中被称为listener 元素,jsp服务器将会实例化这些侦听类,并且注册它们。Listener元素中有一个叫listener-class的子元素,这个元素的值必须是该侦听类的完整类名。 @51!vQwqR  
rMV<}C ^  
Tag元素 >gj%q$@  
<i<[TPv";  
每个tag元素在tag库中都要指出它的名字、类名、脚本变量、tag的属性。其中脚本变量的值可以直接在TLD中定义或通过tag附加信息的类来取得。每个属性描述了这个属性是否可以省略,它的值是否可以通过<%= …%>这样的JSP语法来获得,以及属性的类型。 $w:7$:k  
!(%^Tg=  
每一个tag在TLD中对应一个tag元素,下表是tag元素的子元素: M1>2Q[h7  
TGSUbBgU  
Tag元素的子元素 u]<7}R@s  
\Z?.Po`!j  
元素名称 .>/Tc  
描述 J83{&N2u  
`W& :*  
name [/P}1 c[)U  
独一无二的元素名 Qp]-:b  
8w 2$H  
tag-class IJ#G/<ZJZ  
Tag标签对应的tag处理类 4u!<3-3Zy  
{ \r1A  
tei-class l(o;O.dLt  
javax.servlet.jsp.tagext.TagExtraInfo的子类,用于表达脚本变量(可选) @Czj] t`  
:)djHPP*  
body-content zi7>!#(  
Tag标签body的类型 -GqMis}c  
834E ]2  
display-name "OdR"M(G\  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) -pF3q2zb  
rM{3]v{~  
small-icon Z'u:Em  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) %-A#7\  
*E"OQsIl  
large-icon *[@k=!73  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) ;|.~'':  
`S&$y4|Vs  
description W5&;PkhQ6  
此tag标签的描述 !yfQ^a_ O  
=m+'orJ1  
variable 9rd7l6$R"  
提供脚本变量的信息(同tei-class)(可选) xlhc`wdm  
e>GX]tK  
attribute )|d]0/<  
Tag标签的属性名 N~Kl{" >`  
 C0Oe$& _  
以下章节介绍对于不同类型的tag,如何具体地实现它们。 O<H5W|cM  
Em(&cra  
0\Q/$#3  
简单的tag b }^ylm  
!8z,}HUdK  
M6X`]R'  
tag处理类 e2P ds`  
@Yl&Jg2l'  
简单的tag处理类必须实现Tag接口的doStartTag和doEndTag方法。当jsp引擎碰到tag标签的开头时,doStartTag被调用,因为简单的tag没有body,所以此方法将返回 SKIP_BODY。当jsp引擎碰到tag标签的结尾时,doEndTag被调用,如果余下的页面还要被计算,那它将返回EVAL_PAGE,否则将会返回SKIP_PAGE。 <c X\|dM  
R cz;|h8  
以下是例子:对于标签 <tt:simple /> ,它的tag处理类实现如下: +H'{!:e5  
9:]w|lE:D  
|z5`h  
public SimpleTag extends TagSupport Kgb 3>r  
figCeJ!W4  
{ `<3/k  
"IvFkS=*Q  
public int doStartTag() throws JspException 7Zf * T  
YpGG^;M$  
{ k9'`<82Y  
*[QFIDn:  
try{ C `>1x`n  
-=+@/@nV  
pageContext.getOut().print(“Hello.”); !:N&tuJEv  
) vKZs:  
}catch(Exception e){ @5C!`:f  
ly8IrgtKy  
throw new JspTagException(“SimpleTag: “ + e.getMessage()); LzS)WjEN  
=:5o"g  
} +TWk}#G   
g aq"+@fH  
return SKIP_BODY; 8,l~e8&  
Pf4b/w/  
} AMm)E  
:B(vk3;U!  
public int doEndTag() qkg`4'rLg  
zFq8xw  
{ y\M Kd[G7  
}3Mnq?.-  
return EVAL_PAGE; BwpSw\\?@  
\d,wcL  
} soTmKqj E  
%:DH _0  
} -%g$~MZ?'  
?KKu1~a_  
Z#1 'STg  
注意:如果tag标签没有内容的话,那必须定义body-content元素为空,例如 4|]0%H~n6  
V=?qU&r<+  
<body-content>empty</body-content> 'Pm.b}p<  
z"vI-~,YU  
~kJ}Z<e  
带属性的tag标签
评价一下你浏览此帖子的感受

精彩

感动

搞笑

开心

愤怒

无聊

灌水
级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
只看该作者 1 发表于: 2007-01-01
tag处理类 `/4 R$E{  
v"K #  
对于tag标签的每个属性,你必须依照JavaBeans规范来定义其属性,以及get和set方法。以struts的logic:present 标签为例, 3`mM0,fY  
A'=,q  
<logic:present parameter=”Clear”> Bc!ZHW *&  
YWXY4*G  
与此相应,此tag处理类应有如下方法和定义: Pcs62aE  
V(5=-8k  
'PBuf:9lN  
protected String parameter = null; ayR;|S  
jMP!/t :w  
public String getParameter() 1\{_bUZ&  
H/I1n\  
{ \{RMj"w:  
8do7`mN  
return this.parameter; !VXs yH3r5  
"{lw;AA5F  
} 4uV,$/  
Q6e;hl  
public void setParameter(String parameter) {=q$k=ib  
w9c^IS  
{ -<jd/ 5  
n-5@<y^  
this.parameter = parameter; @}r2xY1  
@8jc|X<A  
} M#U#I :z%  
$X;wj5oj  
bY>JLRQJ-  
注意:如果你的属性名为id,而且你的tag处理类是从TagSupport类继承的,那你就不需要定义它的属性和set和get方法,因为他们早已在TagSupport被定义过了。 yE6EoC^  
|LwW/>I  
Attribute元素 Jy?#@/~  
VY#:IE:T  
对于tag标签的每个属性,你必须定义它是否必须的,它的值是否可以用诸如<%= …%>的表达式来获得,以及它的类型(可选),如果不指定它的类型,那就默认为是java.lang.String类型。如果rtexprvalue元素被定义为true或yes,那么在type元素中就定义了attribute的返回类型。 DsI{*#  
sgRD]SF  
<attribute> &E{i#r)'T  
* I{)8  
<name>attr1</name> [:MpOl-KIz  
_Q $D6+  
<required>true|false|yes|no</required> "\:ZH[j  
3H'+7[~qH  
<rtexprvalue>true|false|yes|no</rtexprvalue> rP=!!fC1;  
4wa8Vw`  
<type>attribute的返回类型(只用当rtexprvalue为真是才有效)</type> $:aKb#l)  
J(s%"d  
</attribute> #;#r4sJwU  
jl:dKL@  
如果tag的某个属性不是必须的,那tag处理类会自动提供一个缺省值。 Rw R.*?#  
,fQs+*j  
例如,在logic:present这个tag标签中定义了一个属性叫parameter,但它不是必须的,而且它可以被诸如<%= …%>的表达式来赋值。 c[DC  
:M%s:,]R  
<tag> bO:m^*  
>h+G$&8[ y  
<name>present</name> yQ3*~d~U|L  
qZ8 V/  
<tag-class>org.apache.struts.taglib.logic.PresentTag</tag-class> KioD/  
-54  
<body-content>JSP</body-content> 5nhc|E)C  
=h"*1`  
j1LL[+G-"_  
Q%AD6G(7  
<attribute> dF- d  
`T;M=S^y*E  
<name>parameter</name> z [qO5z~I  
4*<27  
<required>false</required> b,7@)sZ*  
xP1`FSO8=  
<rtexprvalue>true</rtexprvalue> |0wUOs*5  
F>F&+63Q-  
</attribute> h2Pvj37  
+QqEUf<U*,  
`B^ HW8  
 ?2g\y@  
</tag> u/@dWeY[]  
Xu1tN9:oE  
.-:R mYGR  
属性元素的校验 ">? y\#O A  
oXR%A7  
ye9-%~sjX  
有关于tag标签的有效值可以从tag库的说明文档中获得,当JSP页面被编译时,jsp引擎会强制性地参照TLD中定义的规则进行检查。 *d,u)l :S  
FL 5tIfV+  
还有一个方法也可以进行属性元素的校验,就是先继承类TagExtraInfo,然后调用它的isValid方法。这个类同时也起到提供tag中定义的脚本变量信息的作用。 "~f=7  
\mt0mv;c  
IsValid方法通过TagData对象来传递属性信息,它包括着tag的所有的属性名-值的信息。由于校验发生在运行时刻,因此这个属性的值将被赋值为TagData.REQUEST_TIME_VALUE。 e3L<;MAt  
R ks3L  
例如tag标签<tt:twa attr1=”value1” />在TLD中定义如下: >D';i\2j&  
O?ZCX_R:L  
<attribute> |7jUf$Q\p  
s -Mzl?o  
<name>attr1</name> 4g.y$  
XK)qDg  
<required>true</required> #_tixg  
F:8cd^d~u  
<rtexprvalue>true</rtexprvalue> nnU &R  
& >AXB6  
</attribute> @x>J-Owd]J  
}5RCks;)*  
y@|gG&f T  
这个定义说明了attr1能在运行期间被赋值。 B6gSt3w.  
=NH p%|  
以下的isValid方法检查attr1属性的值是否属于Boolean类型。注意由于attr1能在运行刻被赋值,那么isValid方法必须检查tag用户是否对此tag进行了运行时刻赋值。 * Yr)>;^  
> dJvl|  
zkdyfl5  
Public class TwaTEI extends TagExtraInfo 3wEVjT-  
5PPV`7Xm9  
{ 7W[}7Y   
+h6c Aqm]  
public boolean isValid(Tagdata data) 9HlRf6S  
 R1YRqk  
{ BzqM$F( L,  
i/nA(%_  
Object o = data.getAttribute(“attr1”); d/8I&{.  
-d+q+l>0  
If(o != null && o != TagData.REQUEST_TIME_VALUE) F/\w4T  
s%nx8"   
{ _MfB,CS  
7m6@]S6  
if( ( (String)o).toLowerCase().equals(“true”) || VRYj&s'@  
CT@JNG$<"  
((String)o).toLowerCase().equals(“false”) ) [YY[E 7  
Y!LcS48X  
return true; QvK-3w;=  
vMsb@@O\\  
else nV-A0"z_&  
O|J`M2r  
return false; p4;A[2Ot`:  
LL+ROX^M  
} [kx_Izi/T  
nz:I\yA  
else 4tTK5`7N  
Ey$J.qw3  
return true; 9FT;?~,  
"VxZnT  
} , ;L  
R9o3T)9V  
} `s (A&=g\  
A.<HOx&#  
%  (R10G  
带body的tag <o^_il$W  
~9JU_R^%m  
N\?%944R  
tag处理类 Qi' ,[Xmf  
6LRI~*F=3  
 E%\jR  
如果tag标签含有内容,那处理方式会略微有些不同,而且还要视tag处理类是否要与body交互的情况而定。如果要与body交互,那我们认为tag处理类要可能要对body进行操作。 F i?2sa  
LuQ4TT  
Tag处理类不与body交互 {dV#"+  
]w.:K*_=  
如果tag处理类不与body交互,tag处理类应该实现Tag接口或从TagSupport中派生,如果body要被计算,那么doStartTag方法应返回 EVAL_BODY_INCLUDE,否则应返回SKIP_BODY。 8;YeEW 5  
f?T6Ne'  
如果tag处理类要对body反复运算,则它应该实现IterationTag或从TagSupport中派生。如果tag处理类认为body还未计算完的话,那它的doStartTag方法和doAfterBody方法必须返回EVAL_BODY_AGAIN。 %"~\Pu*>  
<>`+" O}  
Tag处理类与body交互 TQDb\d8,f  
6/@"K HHVe  
如果tag处理类与body交互,那tag处理类应实现BodyTag接口或从BodyTagSupport中派生。这种tag处理类一般要实现doInitBody和doAfterBody方法。 R{.5Z/Vp6E  
ru,]!YPJE2  
Body允许一些方法来读写它的内容。Tag处理类可以调用body内容的getString或getReader方法来从body中提取信息,也可用 writeOut(out) 方法来将body的内容写入到out对象中。其中out对象通过tag处理类的getPreviousOut方法来获得。 euO!+9p  
d?(#NP#;  
如果body的内容需要被计算,那么doStartTag方法必须返回EVAL_BODY_BUFFERED,否则,它将返回 SKIP_BODY。 (SV(L~ T_  
nYG$V)iCb  
doInitBody 方法 x g~q'>  
B RF=TL5Z  
此方法在body内容已经设好,但未被计算之前被调用。你可以根据不同的body内容来制定初始化策略。 Mp*")N,  
3+_? /}<  
doAfterBody方法 :Xc%_&)  
8`Fo^c=j  
此方法在body内容已被计算后进行调用。 jPg8>Z&D  
DytH } U"  
和doStartTag方法一样,doAfterBody方法返回一个指示符指示是否要继续计算body,如果要继续计算,则doAfterBody应返回EVAL_BODY_BUFFERED,否则,它应返回SKIP_BODY。 `2\vDy1,j  
]Y Q[ )  
release 方法 Y<M,/Y_ !  
?1JVzZ4H  
tag处理类调用此方法将它的状态重置为初始状态,并释放所有的私有资源。 WUx}+3eWv  
\tTZ N  
3eQ-P8LS  
以下的例子读取body的内容(其中含有一条sql语句),然后将它传递给一个对象,让它进行查询。由于此处body不须重新计算,所以doAfterBody会返回SKIP_BODY。 +h^>?U,  
#?.Yc%5B  
S(Md  
Public class QueryTag extends BodyTagSupport N*w/\|  
ss'#sPX  
{ 4VINu9\V  
UR6.zE4=_  
public int doAfterBody() throws JspTagException p@]\ N  
YIo $  
{ _2+}_ >d  
"1>I/CM  
BodyContent bc = getBodyContent(); /,dcr*  
@ qWgokf  
//将body的内容以字符串的格式提取出来 KCd}N  
1 zIFQ@  
String query = bc.getString(); j#d=V@=a  
)$K )`uqb  
//清除body <a7y]Py  
PPO*&=!]  
bc.clearBody(); e9/:q"*)/  
^lhV\YxJ  
try{ j:K>3?   
= #]^H c  
Statement stmt = connection.createStatement(); qeLfO  
8px@sXI*`  
Result result = stmt.executeQuery(query);  " Mzb  
8enlF\I8g  
}catch(SQLException e){ "&*O7cs$pA  
eS(\E0%QI  
throw new JspTagException(“queryTag: “ + e.getMessage() ); - &u]B$  
bb}zn'xC  
return SKIP_BODY; $qG;^1$  
8A/"ia  
} | Qo`K%8  
0o~? ]C  
} FrBoE#  
-N;$L~`iAt  
Oz(0$c  
body-content元素 :VpRpj4f  
8qGK"%{ ~  
HwTb753  
由于tag可能会有body,你必须用body-content元素来指定body内容的类型: [4 L[.N@  
~t7?5b?*\  
<body-content>JSP|tagdependent</body-content> "8}p>gS  
C3q}Dh+]  
l,j7I3&~%  
如果body的内容是定制的或内部的tag、脚本元素、或HTML广本,则归类为JSP类型。其他的类型,比如上面代码所述的?D?D将sql statement类传给 query tag的这种类型应该标为tagdependent。 _b8&$\>  
_'DT)%K  
注意:实际上body-content的值并不影响tag处理类对body内容的处理,它仅仅是被tag编辑工具用来描述此body的内容。 "SC}C  
-|;{/ s5  
 *R1 m=  
用tags定义脚本变量 <QbD ;(%  
eV:I :::  
"TW%-67  
tag处理类 T-e'r  
iAD'MB  
YaiogA  
tag处理类负责创建或设置页面中定义的脚本变量,用pageContext.setAttribute(name,value,scope)或pageContext.setAttribute(name,value)方法来实现。一般来说,tag处理类通过脚本变量的名称来获取它,脚本变量的名称一般可用get方法来获得。 kI7c22OJ  
i) v ]  
如果脚本变量的值依赖于tag处理类中的上下文中某一对象,那它可用pageContext.getAttribute(name,scope)方法来找到那个对象。一般的处理过程是tag处理类先找到脚本变量,再对其进行处理,然后用pageContext.setAttribute(name,object)的方法来设置它的新值。 `-@8IZ7  
fA"N5qQI(  
对象的生存周期(scope)如下表: O[%"zO"S  
q.sErr[zc  
对象的生存周期表 >h:rYEsh8V  
Ze+p;v  
名字 u5D@,wSNz  
可访问范围 *IBT!@*Q&  
生存周期 ,:6gp3  
.. jc^'L  
page %oPW`r  
当前页面 Do1 Ip&X  
一直有效,除非页面向客户提交响应或重定向到一个新页面 .*FBr7rE\  
@yc/1u $r  
request P?|F+RoX$  
当前页面或当前页面重定向到的页面 r{NCI  
一直有效,除非页面向客户提交响应 t Qo) *z  
\dvzL(,  
session Y9V%eFY5E  
当前页面或在同一浏览器窗口中的页面 Fuq MT`  
一直有效,除非关闭当前浏览器、超时、网络故障 WcRTv"4&  
>]b>gc?3  
application k;EG28   
整个web应用程序的所有请求 as#_Fer`U  
一直有效,除非发生网络故障、服务器故障 C8ss6+k&  
r 0m A  
提供关于脚本变量的信息 e !V3/*F  
)?_x$GKY  
以下示例定义了一个名为“book”的脚本变量,用来访问程序中关于书的信息: R=Qa54  
2;8I0BH*'  
<bean:define id=”book” name=”bookDB” property=”bookDetails” type=”database.BookDetails” /> ;MSdTHN"  
Eo h4#fZ\N  
<font color=”red” size=”+2” > Buxn!s  
.T!R&#]n  
<%= messages.getString(“CartRemoved”) %> :Q\Es:y  
3K)12x$.K  
<strong><jsp:getProperty name=”book” property=”title” /></strong> >.sdLA Si  
a4a/]q4T  
</font> (i3V  
}uZtAH|  
当包含此tag的JSP页面被编译时,jsp引擎会自动生成关于此book的同步的代码(同步可以避免几个客户同时访问此book时造成的冲突),要生成同步代码,jsp引擎需要知道此脚本变量的如下信息: s,z$Vt"h*K  
MxXf.iX&  
· 脚本变量名称 He&7(mQ0^  
&\n<pXQ  
· 脚本变量所属的类 Z}X oWT2f  
aL)}S%5o?  
· 此脚本变量是否引用了一个新的或已存在的对象 $*k(h|XfwW  
f{i~hVF  
· 此脚本变量的有效性 |gV$ks\<  
!UzMuGj  
有两种办法可以向jsp引擎提供关于脚本变量的信息:在TLD中定义variable子元素,或用tei-class子元素定义一个额外tag信息类。用variable最简单,但可能降低了一些灵活性。 "c+j2f'f  
)Bz2-|\  
Variable元素 )Z/L  
yW =I*f  
Variable元素有如下子元素: MC'2;,  
SRP.Mqg9  
· name-given ?D?D 给出的名字,是一个常量 E \p Qh  
< bvbfS  
· name-from-attribute?D?D 属性名,在编译时给出的属性名 ~8oti4  
{zck Y  
name-given或name-from-attribute两者必须选一,但以下子元素是可选的: -(oFO'Lbg  
m2{DLw".  
· variable-class?D?D变量的类型,缺省为java.lang.String。  L- '{   
. X:  
· declare?D?D此脚本变量是否引用了一个新对象,缺省为True。 >$/<~j]  
q.}M^iDe  
· scope?D?D脚本变量的范围,缺省为NESTED。下表描述了scope的几种类型: CjQ)Bu *4  
z~m{'O`  
脚本变量的有效范围 -22]|$f  
g +RgDt9  
q HU}EEv  
有效性 <<SUIY@X  
方法 z+5ZUS2~&  
qOqU CRUe:  
NESTED 1(YEOZ  
在tag标签的开始和结束之间 qN=l$_UD  
如果tag处理类实现BodyTag接口,则在doInitBody和doAfterBody中调用,否则在doStartTag中调用 q,Nhfo(  
39yp1  
AT_BEGIN gs:V4$(p4  
从tag标签的开始一直到页面结束 X]1Q# $b  
如果tag处理类实现BodyTag接口,则在doInitBody、doAfterBody和doEndTag中调用,否则在doStartTag和doEndTag中调用 o5(~nQ  
cWU9mzsE  
AT_END m) q e  
从tag标签的结束一直到页面结束 A &tMj?  
在doEndTag中调用 qlU"v)Mx  
AY(z9 &;6  
以struts为例,它的bean:define标签的实现遵循JSP1.1规范,此规范要求使用额外tag信息类来定义脚本变量。Variable元素是JSP1.2规范中加入的。以bean:define标签为例,你可以定义如下variable元素: 6OPYq*|  
a5dc#f Kf  
<tag> l~C=yP(~  
6rll0c~  
<variable> JVe!(L4H  
EpCT !e  
<name-from-attribute>id</name-from-attribute> !uc"|S?  
-tH^Deo  
<variable-class>database.BookDetails</variable-class> sQ aP:@  
v?L`aj1ox  
<declare>true</declare> 4Q?3gA1  
*RllKPY)  
<scope>AT_BEGIN</scope> ,3,(/%=k  
W }  
</variable> Oh'C [  
r^ Mu`*x*  
</tag> rYfN  
Z[GeU>?P  
额外tag信息类 B.Y8O^rx  
tPz!C&.=  
如果要定义一个额外tag信息类,你要继承javax.servlet.jsp.TagExtraInfo类。一个TagExtraInfo类必须实现getVariableInfo方法,此方法返回一个叫VariableInfo的数组类,它包括如下信息: 2PDU(R  
-R BH5+SS2  
· 变量名 n1Fp$9%  
mGC!7^_D`  
· 变量所属类名 grZ?F~P8  
1=Y pNXX  
· 此变量是否引用了一个新对象 ZQN%!2  
_!C M  
· 此变量的有效范围 7f_tH_(  
7\<}378/^  
jsp引擎将一个名为data的参数传给getVariableInfo方法,data中包括tag标签中的所有“属性名?D?D属性值”对。它可以用来向VariableInfo对象提供脚本变量的名字和类名。 =;m;r!,K  
~ \3j{pr  
以struts为例,它在bean:define标签中定义了一个名为DefineTei的额外tag信息类,用来向脚本变量提供信息。由于脚本变量的名称(book)和类名(database.BookDetails)是通过tag标签的属性来传递的,它们一般定义在VariableInfo的构建代码中,并且可用data.getAttributeString方法来得到这些信息。如果要允许book脚本变量能在从tag开始直到整个JSP页面结束的范围内都可用的话,那它的范围应设为AT_BEGIN。如下所示: O!ngQrI  
d3&l!DoX  
AD@-H0Y  
public class DefineTei extends TagExtraInfo NA{?DSP  
+sm9H"_0  
{ i"GCm`  
!wr2OxK*  
public VariableInfo[] getVariableInfo(TagData data) 3aERfIJyE  
h/xV;oj  
{ Nu4PY@m]C  
<E1ngG  
String type = data.getAttributeString(“type”); Br}0dha3E  
b Sm*/Q  
If( type == null) )o N#%%SB<  
w<$0n#5  
type = “java.lang.Object”; MzpDvnI9  
wdLlQD  
return new VariableInfo[] {  .H7xG'$  
Y8@TY?  
new VariableInfo(data.getAttributeString(“id”), jImw_Q  
GI[XcK^*w  
type, +I[Hxf~  
^hyp}WN  
true, 5o2vj8::  
K<~J*k<v  
VariableInfo.AT_BEGIN) BQF7S<O+  
;Vlt4,s)  
}; b X'.hHR  
n"|1A..^  
} M0Vs9K=  
&A)u!l Ue  
} +GFK!Pf  
z z2'h>  
' "I-! +  
注意:关于额外tag信息类的类名必须要在TLD中的tag标签下的tei-class子元素中定义。因此,DefineTei的tei-class中的定义看起来如下: {/Qg4pc!  
<tei-class> 0;n}{26a  
org.apache.struts.taglib.bean.DefineTagTei L3|~ i&k  
</tei-class>  K>S:Z  
#8sv*8&  
i=aK ?^+  
具有协作关系的tag bd[%=5  
rlP?Uh  
Uk<2XGj  
tag通过共享对象来进行协作,JSP技术支持2种方式的对象共享。  ;)ji3M  
Eq/oq\(/6  
第一种方法是使用pageContext对象进行对象的共享(可支持JSP页面和tag处理类之间的共享),如果在一个tag处理类中要调用由另一个tag处理类创建的对象,可调用pageContext.getAttribute(name, scope)方法。 h-6zQs   
u~\l~v^mj  
第二各方式的共享是对于tag之间有嵌套关系而言的,外层的tag所创建的对象对于内层的tag来说是可以共用的。这种形式的共享的好处是减少了可能存在的重名冲突。 (^9dp[2  
`2PvE4]%p  
要访问一个嵌套tag创建的对象,tag处理类必须先找到此嵌套tag对象,可用TagSupport的静态方法 TagSupport.findAncestorWithClass(from, class)或TagSupport.getParent方法。前者在当不确定此tag是否为嵌套tag对象时使用。一旦它的父类被找到,它就能访问其所有动态或静态创建的对象。静态创建的对象是父类的成员,而动态创建的对象可能是父类的私有对象。诸如此类的对象可以用tag处理类的setValue方法来保存,用getValue方法来获得。 ,); -v4$  
-E,p[Sp  
下例阐述了以上两种共享对象的方法。在这个例子当中,一个查询tag检查一个名为connection的属性名是否在doStartTag中被设置。如果connection属性被设置,tag处理类从pageContext中得到这个connection对象。否则,此tag处理类先找到它的父tag处理类,然后从它的父tag处理类中找到connection对象。 fUa[3)I  
"c*&~GSE4  
D'Y=}I)8Dn  
public class QueryTag extends BodyTagSupport *Fu;sR2y%:  
:WHbwu,L$  
{ tVqc!][   
1`v$R0 `!  
private String connectionId; vD3j(d  
M\6u4p!G!  
public int doStartTag() throws JspException L{uQ: ;w1  
hjx= ?  
{ 1/<Z6 ?U  
_t.Ub:  
String cid = getConnection(); Z<W`5sop^  
d8% sGH  
if(cid != null) WR5W0!'Tf  
5KRI}f  
{ x A"V!8C  
=5u;\b>*  
//存在一个connection id,使用它。 /6yH ,{(a  
SPo}!&p$~  
connection = (Connection) pageContext.getAttribute(cid); &hSF  
6y   
} ZP;WXB`  
d6+{^v$#  
else [$FiXH J  
/Q\|u:oO,  
{ HrH! 'bd  
BX-fV|  
ConnectionTag ancestorTag = (ConnectionTag)findAncestorWithClass(this, 4)+L(KyB2  
%w#8t#[,6  
ConnectionTag.class); ^_!2-QY.~  
dZ%rmTE(H  
if(ancestorTag == null) qJYEsI2M  
$@@@</VbP  
{ ;noZmPa  
f&88N<)  
throw new JspTagException(“一个没有connection属性的查询标签必须被一个connection标记嵌套。”); @D7/u88|  
DE!P[$J  
} -PLh|  
ve@E.`  
connection = ancestorTag.getConnection(); Yrmd hSY  
s]Qo'q2  
} =v49[i  
35Cm>X  
} /\d@AB^5I  
FN"Ye*d  
} mWX{I2  
7 jiy9 [  
S9lT4  
#kRt\Fzq  
此查询标签在JSP页面中的调用形式可以从以下2种定义中任选一种: vG#,J&aW  
I/Q~rVt  
lCiRvh1K  
<tt:connection id=”con01” ...> ... </tt:connection> `!lQd}W  
3fdqFJ O  
<tt:query id=”balances” connection=”con01” > *r].EBJ\  
NEff`mwm5)  
SELECT account, balance FROM acct_table ~__rI-/_  
T/iZ"\(~w  
where customer_num = <%= request.getCustno() %> C1po]Ott*  
jWcfQ  
</tt:query> y[d>7fcf  
BT* {&'\/  
Fb<fQIa  
}-T :   
mae@L  
<tt:connection ...> 2g$;ZBHO|8  
IyoitIbLl  
<x:query id=”balances”> "V{v*Aei0  
yt1dYF0Xq  
SELECT account, balance FROM acct_table E3QyiW  
/A1qTG=Br  
where customer_num = <%= request.getCustno() %> `[F[0fY-  
DQ hstXX  
</x:query> \vF*n Z5/  
 %&pd`A/  
</tt:connection> !;E{D  
5m9;'SF  
~vB dq Yj  
与此同时,在TLD中必须指定connection属性为可选的,定义如下: O>[B"mM t  
sjG@4Or  
<tag> grTwo  
sPRo=LB  
... )}i|)^J  
qv)%)n  
<attribute> 3.w &e0Es  
jq( QL%)_O  
<name>connection</name> Uu~~-5  
/kNSB;  
<required>false</required> QS%t:,0lp  
2!? =I'uMA  
</attribute> {C5-M!D{<  
CSlPrx2\  
</tag>
描述
快速回复

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