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

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

级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
标准的JSP 标记可以调用JavaBeans组件或者执行客户的请求,这大大降低了JSP开发的复杂度和维护量。JSP技术也允许你自定义taglib,其实换句话说,taglib可以看成是对JSP标记的一种扩展,正如xml是对html的一种扩展一样。taglib通常定义在tag标签库中,这种标签库存放着你自己定义的tag标签。简而言之,如果使用taglib,那么你可以设计自己的JSP标记! 6B$q,"%S@  
Wl^R8w#Z$  
一般来说,自定义tag标签主要用于操作隐藏对象、处理html提交表单、访问数据库或其它企业级的服务,诸如邮件和目录操作等等。自定义tag标签的使用者一般都是那些对java编程语言非常精通,而且对数据访问和企业级服务访问都非常熟悉的程序员,对于HTML设计者来说,使得他可以不去关注那些较复杂的商业逻辑,而将精力放在网页设计上。同时,它也将库开发者和库使用者进行合理分工,自定义tag标签将那些重复工作进行封装,从而大大提高了生产力,而且可以使得tag库可用于不同的项目中,完美地体现了软件复用的思想。 U-wLt(Y<  
t)oapIeIe  
在这篇文章中,我们主要讨论: 6pE :A@  
^0W(hA  
· 什么是自定义tag标签? 52zGJ I*  
zm9TvoC%}  
· 怎么使用tag标签? CBf7]n0H  
CLKov\U\  
o 声明要使用的tag库 CGw--`#\  
pO<-.,  
o 找到与之对应的tag处理类 6)\dBOz  
mxSKG> O  
o tag标签的类型 "HM{b?N  
OEr:xK2T  
· 自定义tag标签 IGX:H)&*  
O gmO&cE  
o tag处理类 8|twV35  
NkxCs  
o tag库描述 tNs~M4TVVH  
 &K^MN d  
o tag标签示例 `P+(&taT  
 0JRD  
o 带属性的tag T)7TyE|"2g  
z1 i &Ge  
o 带body的tag (B>Zaro#  
>zY \Llv  
o 定义了脚本变量的tag F)$K  
wN37zPnV~  
o 具有协作关系的tag 5TBI<K  
:&'{mJW*{t  
· 自定义tag标签 u"$a>S_  
0BkV/v1Uc  
o 一个迭代tag的例子 PM$Ee #62R  
&ntBU]< q  
o 一个模板tag库 \o3"~\|6C  
BX;5wKfA  
o tag处理类到底是怎样被调用的? 2^exL h  
&A!KJ.  
BH0!6Oq  
什么是自定义的tag? jj\[7 O*  
{gf>*  
一个自定义的tag标签是用户定义的一种JSP标记。当一个含有自定义的tag标签的JSP页面被jsp引擎编译成servlet时,tag标签被转化成了对一个称为tag处理类的对象进行的操作。于是当JSP页面被jsp引擎转化为servlet后,实际上tag标签被转化成为了对tag处理类的操作。 ;Hm'6TR!  
rqCa 2  
自定义tag标签有很多特色,诸如: wCZO9sU:6=  
QL"gWr`R  
· 可以在JSP页面中自定义tag标签的属性 D_|B2gdZY  
hQJWKAf,/  
· 访问JSP页面中的所有对象 a! Yb1[  
nN`"z3o  
· 可以动态地修改页面输出 w#PZu+  
ZofHi c  
· 彼此这间可以相互通信。你可以先创建一个JavaBeans组件,然后在一个tag中调用此JavaBeans组件,同时可以在另一个tag中调用它。 U2*6}c<  
`0BdMKjA  
· tag允许相互嵌套,可以在一个JSP页面中完成一些复杂的交互。 SA6hbcYk  
FyD.>ot7M  
@%i>XAe#0  
使用tag标签 %/0gWG  
Zcd7*EBdx  
UPCQs",  
本节主要描述怎样在JSP页面中使用tag标签,以及tag标签的不同类型。 coQ[@vu  
){Z  
要使用tag标签,JSP程序员必须做2件事: DM7}&~  
1JTbCS  
· 声明此tag标签的tag库 9+CFRYC  
zjbE 7^ N  
· 实现此tag标签 PN F4>)  
bLG]Wa  
声明tag标签所在的tag库 Wb=Jj 9;  
z<C[nR$N  
如果要使用tag标签,则应用JSP的taglib指示符来指定其tag库(注意:taglib要在在使用此tag标签之前声明) ]H2R  
=xEk7'W6k  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> 5S/>l_od$2  
f==*"?6\  
uri属性定义了唯一的标签库描述(以下简称TLD),它可以是直接是tld文件名或一个独一无二的名字。prefix是用来区别其它TLD中和本TLD中有重名的tag的一种手段。 R$b,h  
y~#\#w {  
TLD必须以.tld作为扩展名,并且存放在当前应用的WEB-INF目录或其子目录下。你可以通过它的文件名直接引用它,也可以通过别的方式间接地引用它。 Md(JIlh3  
`\FI7s3b  
以下taglib指示符直接引用一个TLD: .A<sr  
j)D-BK&+  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> {Qtq7q.  
&zN@5m$k;  
以下的taglib指示符通过一个逻辑名称间接地引用一个TLD: < tQc_  
%<U{K;  
<%@ taglib uri=”/tutorial-template” prefix=”tt” %> OCx5/ 88X  
dXP6"V@iI  
如果是间接引用TLD的话,那你必须还要在web.xml中定义此逻辑名称与tld文件之间的映射,具体做法是在web.xml中加入一个名为taglib的元素: 0M!0JJy#*  
Fe= "EDh  
<taglib> Z*bC#s?  
CM 9P"-  
<taglib-uri>/tutorial-template</taglib-uri> D3?N<9g  
;/Q6 i  
<taglib-location> R`He^  
?iln<% G  
/WEB-INF/tutorial-template.tld ZO7bSxAN-  
Ex,JB +  
</taglib-location> O_CT+Ou  
x}"Q8kD  
</taglib> >~&(P_<b  
xYT}>#[  
3_J>y  
实现此tag标签 +Jw{qQR/*  
i| xt f  
aF])"9  
为了实现tag标签,你有2种方法来存放tag处理类。一、让tag处理类以.class的方式存放于当前应用的WEB-INF/class子目录下,二、如果tag处理类是以JAR包的形式存在的话,那可以放在当前应用的WEB-INF/lib目录下,如果tag处理类要在多个应用中共享,那么它就应放在jsp服务器上的common/lib目录下,对于tomcat来说,就是tomcat/common/lib目录下。 6GOg_P  
$r"A@69^RS  
]18Ucf  
tag标签类型 Iq,v  
uYTCdZQh  
#{>uC&jD  
自定义的tag标签遵循XML语法。它有一个开始标记和一个结束标记,有的还有body(即文本节点): I<`V_  
>ITEd  
<tt:tag> nO_!:6o".  
IO[^z v4F  
body u{+!& 2}k  
6^ik|k|  
</tt:tag> DQ5W6W  
<3Fz>}V32  
J 9a $AU*  
一个不带body的tag标签如下: {5 Kz'FT  
Qtnv#9%Vi  
<tt:tag /> EW;1`x  
P!>g7X  
U?EG6t  
简单的tag标签 (fd[P|G_]  
 QT_^M1%  
一个没有body和属性的tag标签如下: )d_U)b7i  
#01/(:7  
<tt:simple /> #ko6L3Pi  
sy.:T]ZH  
cKpQr7]ur  
带属性的tag标签 AY@k-4  
5Jd` ^U  
;*`_#Rn#  
自定义标签可以有自己的属性。属性一般在开始标记中定义,语法为 attr=”value”。属性的作用相当于自定义标签的一个参数,它影响着tag处理类的行为。你可以在TLD中详细定义它。 -R74/GBg  
&NP6%}bR`  
你可以用一个String常量给一个属性赋值,也可以通过表达式给它赋值,如<%= ...%>。以struts为例,它的logic:present标签就是用的String常量来给属性赋值: ~*kK4]lP  
bZXlJa`'S  
<loglic:present parameter = “Clear”> Wbd_a R (  
&[)D]UL  
而另一个标签logic:iterate是用表达式来给属性赋值: 7?"9J `*  
}6@%((9E 2  
<logci:iterate collection=”<%= bookDB.getBooks() %>” Xr2 Wa  
(-'PD_|  
id=”book” type=”database.BookDetails”> [U']kt  
q06@SD$   
D{3fhPNU<b  
带body的tag标签 8'% +G  
gQ,4xTX  
一个自定义标签可以包含其它自定义标签、脚本变量、HTML标记或其它内容。 @aUZ#,(<  
D zE E:&*=  
在下述例子中,此JSP页面使用了struts的logic:present标签,如果些标签定义了parameter=”Clear”的属性,则将清除购物车的内容,然后打印出一条信息: Uk|9@Auav  
|} 9GHjG  
<logic:present parameter=”Clear”> ja:\W\xhJ  
YOlH*cZtg  
<% cart.clear(); %> g!\QIv1D  
>!<V\ Fj1  
<font color=”#ff0000” size=”+2”><strong> T5V$wmB\W  
g.=!3e&z%  
你选择了清除购物车! eoJFh  
hN}5u"pS  
</strong></font> #e*$2+`[A  
lvG3<ls0K$  
</logic:present> W >Kp\tD  
nT)~w s  
}:"R-s  
到底是用属性还是用body来传递信息? ELD +:b  
P0Aas)!  
如上所述,我们既可以通过属性,也可以通过body来传递信息。但一般来说,比较简单的类型,如字符串或简单表达式最好采用属性来传递信息。 83X/"2-K  
75PS^5T,  
oX2r?.j#M  
定义脚本变量的tag标签 )y5iH){ !  
FmR\`yY_,  
所谓脚本变量,是指JSP中可以调用的变量或对象。它可由tag标签产生。以下示例阐述了一个tag标签定义了一个名为tx的由JNDI所定义的事务处理对象。脚本变量可以是ejb对象、事务、数据库连接等等: cx<h_  
Mru~<:9  
<tt:lookup id=”tx” type=”UserTransaction” name=”java:comp/UserTransaction” /> ^=3 ^HQ'Zm  
hg!x_Eq|  
<% tx.begin(); %> 2Sv>C `FMU  
miWw6!()  
... f)qPFM]%z  
zab w!@]  
%jpH:-8'2  
具有协作关系的tag标签 Z#%}K Z  
w:n(pLc<  
自定义tag标签之间可以通过共享对象来实现协作。在下述例子中,标签tag1创建了一个名为obj1的对象,在标签tag2仍可以重复使用obj。 eO~eu]r  
D_zcOq9  
<tt:tag1 attr1=”obj1” value1=”value” /> ;Kt'Sit  
xMLrLXy  
<tt:tag2 attr1=”obj1” /> bW} b<(y  
ya;@<b  
在以下这个例子当中,如果外层的tag标签创建了一个对象,那么其内层的所有tag标签都可以使用这个对象。由于这样产生的对象没有一个指定的名字,那么就可以将少重名的冲突。这个例子阐述了一系列协作的嵌套对象。 `AB~YX%(  
'! #On/  
<tt:outerTag> L,tZh0  
]U#JsMS  
<tt:innerTag /> 6Uch 0xha!  
p^}L  
</tt:outerTag> ^"PfDTyA  
:A,O(   
e?|d9;BO  
Tag处理类 ~>lOl/n5  
nqBG]y aI  
:LU"5g  
Tag处理类必须实现Tag接口或BodyTag接口,不过现在一般都流行从TagSupport或BodyTagSupport类中继承,这些类或接口都可以在javax.servlet.jsp.tagext包中找到。 !>?4[|?n<  
JvT %R`i  
当JSP引擎看到自己的JSP页面中包含有tag标签时,它会调用doStartTag方法来处理tag标签的开头,调用doEndTag方法来处理tag标签的结束。 N;e}dwh&  
!^n1  
下表说明不同类型的tag所需要不同的处理过程: eUi> Mp  
PV5-^Y"v  
Tag处理类的方法 &II JKn|_  
D:+)uX}MOf  
Tag标签类型 S5zpUF=  
所调用的方法 CD*f4I#d  
f6@^ Mg  
基本标签 +qE,<c}}  
doStartTag, doEndTag, release p`shY yE  
n U+pnkMj  
带属性的标签 &h98.A*&  
doStartTag, doEndTag, set/getAttribute1...N, release MHC.k=  
IS3e|o*]MP  
带内容的标签 U]+b` m  
doStartTag, doEndTag, release GG@iKL V  
sDW"j\  
带内容的标签,且内容重复循环 {Q}!NkF 1  
doStartTag, doAfterBody, doEndTag, release "FD<^  
#JHy[!4  
带内容的标签,且内容与JSP交互 {ILp[ &sL  
doStartTag, doEndTag, release, doInitBody, doAfterBody, release \HBVNBY  
!3O,DhH>MC  
一个tag处理类可以通过javax.servlet.jsp.PageContext来与JSP交互,通过javax.servlet.jsp.PageContext类,tag处理类可以访问JSP中的request、session和application对像。 /F\>Z]  
){?mKB5  
如果tag标签是互相嵌套的,那内层的tag处理类可以通过它的parent属性来访问上层的tag处理类。 liBAJx  
"H wVK  
一般情况都将所有的tag处理类打成了JAR的包,以便于发布。 Q"x`+?!  
v4nv Z6  
0(Yh~{   
Tag库描述(简称TLD) oAIY=z  
*93l${'  
Tw`F?i~  
Tag库是用xml语言描述的,TLD包括了tag库中所有tag标签的描述,它一般用来被jsp服务器用来校验tag的语法正确性,或者被jsp开发者用来开发新的标签。 Z1XUYe62  
(CKhY~,/u  
TLD的文件扩展名必须为.tld,而且必须放在当前WEB应用的WEB-INF目录或其子目录中。 Vu_7uSp,)  
My'9S2Y8nv  
一个TLD的内容的开头必须遵守标准的XML开头,用于描述DTD和xml的版本,例如: ^K1~eb*K  
: HQ8M*o  
<?xml version="1.0" encoding="ISO-8859-1" ?> +H2m<  
xMO[3 D&D  
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd"> g] 7{ 5  
TLD必须以<taglib>来作为它的根元素,<taglib>的子元素如下表: /y+;g{  
vWPM:1A  
'Qp&,xK  
<taglib>的子元素 \}]=?}(  
9&|12x$  
Element wdN>KS2!  
Description <-Kb@V3  
bUY:XmA  
tlib-version ,)B~cic'u  
Tag库的版本 =rf )yp-D  
(r#5O9|S  
jsp-version llTQ\7zP  
Tag库所需要的jsp的版本 /6i Tq^.%  
Mm:a+T  
short-name   2  
助记符,tag的一个别名(可选) 0{^l2?mgSb  
L@d]RMNv  
uri  :V5!C$QV  
用于确定一个唯一的tag库 wI1M0@}PV  
&sr:\Qn X/  
display-name PU]7c2.y  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) 5p#o1I  
iZDb.9@&t  
small-icon t ?Njw7  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) U#UVenp@  
Kd AR)EU>  
large-icon )eTnR:=  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) nsr _\F\  
@4W\RwD  
description di)noQXkB-  
对tag库的描述(可选) 'AAF/9  
EDP I*@>  
listener x0AqhT5}  
参见下面listener元素 \pBYWf  
@@&@}IQcR1  
tag /jK17}j  
参见下面tag 元素 it/C y\f  
]XpU'/h>q;  
Listener元素 }R(0[0NQe-  
~]6Oz;~<3  
一个tag库可能定义一些类做为它的事件侦听类,这些类在TLD中被称为listener 元素,jsp服务器将会实例化这些侦听类,并且注册它们。Listener元素中有一个叫listener-class的子元素,这个元素的值必须是该侦听类的完整类名。 0IT20.~  
fmZzBZ_  
Tag元素 Q9x` Uy  
MZ|c7f&`  
每个tag元素在tag库中都要指出它的名字、类名、脚本变量、tag的属性。其中脚本变量的值可以直接在TLD中定义或通过tag附加信息的类来取得。每个属性描述了这个属性是否可以省略,它的值是否可以通过<%= …%>这样的JSP语法来获得,以及属性的类型。 jiw`i  
R"8})a gw  
每一个tag在TLD中对应一个tag元素,下表是tag元素的子元素: ^,ZvKA"}+/  
YDZ1@N}^B  
Tag元素的子元素 L&3Ar'  
!)51v {  
元素名称 W~+!"^<n  
描述 g[D,\  
VQG  /g\  
name q6m87O9  
独一无二的元素名 pO7{3%  
4/mj"PBKL  
tag-class vt(}ga  
Tag标签对应的tag处理类 F_M~!]<na  
Xx9~  
tei-class =E6i1x%j  
javax.servlet.jsp.tagext.TagExtraInfo的子类,用于表达脚本变量(可选) yo Q?lh  
wZ\e3H z  
body-content n_!]B_Vd$  
Tag标签body的类型 ([4{n  
fDm}J  
display-name dTU.XgX)1^  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) k{u%p<  
]( U%1  
small-icon oN1wrf}Sh  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) l66ipgw_^I  
no\}aTx  
large-icon -c<1H)W  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) Tr}$Pb1  
|]]pHC_/W  
description 2}xFv2X  
此tag标签的描述 ,{mf+ 3&$,  
gp|7{}Q{  
variable E6wST@ r  
提供脚本变量的信息(同tei-class)(可选) "`1of8$X7  
;Cp/2A}Xx  
attribute KSpC%_LC  
Tag标签的属性名 [0,q7d?"  
oE|{|27X  
以下章节介绍对于不同类型的tag,如何具体地实现它们。 C{I8Pio{b  
S;AnpiBM8  
uK&wS#uY  
简单的tag qwq+?fj={  
(=&bo p  
+/_B/[e<>  
tag处理类 G]3ML)l  
EA@$^e[  
简单的tag处理类必须实现Tag接口的doStartTag和doEndTag方法。当jsp引擎碰到tag标签的开头时,doStartTag被调用,因为简单的tag没有body,所以此方法将返回 SKIP_BODY。当jsp引擎碰到tag标签的结尾时,doEndTag被调用,如果余下的页面还要被计算,那它将返回EVAL_PAGE,否则将会返回SKIP_PAGE。 yfw>y=/p  
g J[q {b  
以下是例子:对于标签 <tt:simple /> ,它的tag处理类实现如下: cwD*>[j  
4`5Qt=}  
]zR;%p  
public SimpleTag extends TagSupport qu~"C,   
{pJ@I=q  
{ ThqfZl=V  
m&jt[   
public int doStartTag() throws JspException dgqJ=+z 0y  
^9V8M9  
{ e !x-:F#4j  
6_}){ZR  
try{ :>-sITeY  
!m O] zn  
pageContext.getOut().print(“Hello.”); [F-u'h< *l  
>p#d;wK4_  
}catch(Exception e){ U@t?jTMBkO  
VEYKrZA  
throw new JspTagException(“SimpleTag: “ + e.getMessage()); uB&I56  
cS;=_%~  
} &/#Tk>:  
j]F3[gpc  
return SKIP_BODY; E?5B>Jer#  
;NVTn<Uj  
} U!UX"r  
qx CL  
public int doEndTag() 2dJ)4  
Pv$"DEXA2  
{ 6g,3s?aT  
]=XL9MI  
return EVAL_PAGE; @_:?N(%(  
v&/-&(+  
} zSvHvs  
]( 6vG$\  
} >U Ich  
g:6}zHK  
]X;*\-  
注意:如果tag标签没有内容的话,那必须定义body-content元素为空,例如 *z:lq2"G  
MKYE]D;  
<body-content>empty</body-content> 8\t7}8f  
f7AJSHe  
yW,#&>]# |  
带属性的tag标签
评价一下你浏览此帖子的感受

精彩

感动

搞笑

开心

愤怒

无聊

灌水
级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
只看该作者 1 发表于: 2007-01-01
tag处理类 6D]G*gwk[  
l{x#*~g a  
对于tag标签的每个属性,你必须依照JavaBeans规范来定义其属性,以及get和set方法。以struts的logic:present 标签为例, BQmafpp`  
.Eyk?"^  
<logic:present parameter=”Clear”> HSFf&|qqx  
gG>^h1_o~  
与此相应,此tag处理类应有如下方法和定义: ?PtRb:RHt  
-^yc yZ  
1ORi]`  
protected String parameter = null; Q"_T040B  
,'DrFlI  
public String getParameter() kF~e3A7C  
:rc[j@|pH  
{ X51$5%  
Fd.d(  
return this.parameter; PS;*N 8  
dV*rnpN  
} +W[#;)ea(  
:u+#:8u  
public void setParameter(String parameter) <G=@Gl  
&!fcLJd  
{ nezbmpL4  
QRa6*AYm  
this.parameter = parameter; AQU: 0  
"lb!m9F{  
} P&,cCR>  
V!tBipX%  
zg Ti Az  
注意:如果你的属性名为id,而且你的tag处理类是从TagSupport类继承的,那你就不需要定义它的属性和set和get方法,因为他们早已在TagSupport被定义过了。 qnV9TeU)  
>5W"a?(  
Attribute元素 L 'Rapu  
1caod0gor  
对于tag标签的每个属性,你必须定义它是否必须的,它的值是否可以用诸如<%= …%>的表达式来获得,以及它的类型(可选),如果不指定它的类型,那就默认为是java.lang.String类型。如果rtexprvalue元素被定义为true或yes,那么在type元素中就定义了attribute的返回类型。 [m&ZAq  
q9]L!V 9Rv  
<attribute> LZ dNG\-  
r}Av"  
<name>attr1</name> _ 9]3S>Rn  
I"?&X4%e  
<required>true|false|yes|no</required> >&z+ih  
u6d~d\  
<rtexprvalue>true|false|yes|no</rtexprvalue> =i %w_ e  
RL8 wSK  
<type>attribute的返回类型(只用当rtexprvalue为真是才有效)</type> ?saVk7Z[|5  
Ka2tr]+s  
</attribute> SXF_)1QO\W  
!}48;Pl  
如果tag的某个属性不是必须的,那tag处理类会自动提供一个缺省值。 /a)=B)NH  
8nR,GW\  
例如,在logic:present这个tag标签中定义了一个属性叫parameter,但它不是必须的,而且它可以被诸如<%= …%>的表达式来赋值。 P#oV ^  
{Oszq(A  
<tag> >:|q J$J.  
nP5fh_/  
<name>present</name> _3>zi.J/  
]iX$p~riH  
<tag-class>org.apache.struts.taglib.logic.PresentTag</tag-class> nmrk-#._@9  
feHAZ.8rp+  
<body-content>JSP</body-content> f/m6q8!L{  
?!-im*~w  
pSUp"wch  
54%}JA][  
<attribute> 11+_OC2-   
!7?wd^C'f  
<name>parameter</name> L<`g}iw  
9x,+G['Zt  
<required>false</required> ^q2zqC  
ywte \}  
<rtexprvalue>true</rtexprvalue> ZeV)/g,w  
v21?  
</attribute> ~Wv?p4  
!~v>&bCG>9  
(P8oXb+%  
&i RX-)^u  
</tag> j]SkBZgik  
?yK\L-ad  
]aL}&GlHt  
属性元素的校验 $vz%   
^Yz05\  
)FPbE^s(  
有关于tag标签的有效值可以从tag库的说明文档中获得,当JSP页面被编译时,jsp引擎会强制性地参照TLD中定义的规则进行检查。 m,O !M t  
:LG%8Z{R  
还有一个方法也可以进行属性元素的校验,就是先继承类TagExtraInfo,然后调用它的isValid方法。这个类同时也起到提供tag中定义的脚本变量信息的作用。 {Wo7=aR  
miqCUbcU  
IsValid方法通过TagData对象来传递属性信息,它包括着tag的所有的属性名-值的信息。由于校验发生在运行时刻,因此这个属性的值将被赋值为TagData.REQUEST_TIME_VALUE。 bux-t3g7+  
Eq{TZV  
例如tag标签<tt:twa attr1=”value1” />在TLD中定义如下: l[k$O$jo  
?Q2pD!L{  
<attribute> \f#ao<vQm  
l-EQh*!j  
<name>attr1</name> w4a7c  
ak [)+_k_  
<required>true</required> wt;aO_l  
W[s>TDc`v  
<rtexprvalue>true</rtexprvalue> B?Skw{&  
/G;yxdb  
</attribute> >Z% `&D~u  
:_*Q IyW  
4fswx@l  
这个定义说明了attr1能在运行期间被赋值。 Pa<X^&  
;\N*iN#K  
以下的isValid方法检查attr1属性的值是否属于Boolean类型。注意由于attr1能在运行刻被赋值,那么isValid方法必须检查tag用户是否对此tag进行了运行时刻赋值。 HxaUVg0  
z^.0eP8\j  
y rk#)@/m  
Public class TwaTEI extends TagExtraInfo flqTx)xE  
5@ug1F&   
{ wn&2-m*a  
|{T2|iJI  
public boolean isValid(Tagdata data) }__+[-  
A$cbH.  
{ h;->i]  
-yeT$P&|  
Object o = data.getAttribute(“attr1”); ZI7<E  
)RFeF!("  
If(o != null && o != TagData.REQUEST_TIME_VALUE) Sqs`E[G*  
x#D=?/~/Kv  
{ nmr>Aj8[  
/&yT2p  
if( ( (String)o).toLowerCase().equals(“true”) || a 2TC,   
}|,y`ui\  
((String)o).toLowerCase().equals(“false”) ) "T|\  
;H lv  
return true; #eYVZ=E  
oWmla*nCKL  
else V_!i KEU  
}JD(e}8$!  
return false; Npqbxb  
%:*HzYf  
} / <p HDY  
0N.*c  
else jPfoI-  
$$a"A(Y  
return true; tF|bxXs Z  
h.*|4;  
} N2>JG]G  
bb{+  
} 8{C3ijR  
!_@%/I6  
D_Y;N3E/rS  
带body的tag c+JlM1p@  
z( wXs&z;  
jJ|;Nwm<[  
tag处理类 w8qI7/  
cc[w%jlA#  
yWzTHW`)Mr  
如果tag标签含有内容,那处理方式会略微有些不同,而且还要视tag处理类是否要与body交互的情况而定。如果要与body交互,那我们认为tag处理类要可能要对body进行操作。 &>o)7H];  
:R)IaJ6)  
Tag处理类不与body交互 5 S 1m&s5k  
 <CFu r  
如果tag处理类不与body交互,tag处理类应该实现Tag接口或从TagSupport中派生,如果body要被计算,那么doStartTag方法应返回 EVAL_BODY_INCLUDE,否则应返回SKIP_BODY。 $dR%8@.H  
tz,FK;8  
如果tag处理类要对body反复运算,则它应该实现IterationTag或从TagSupport中派生。如果tag处理类认为body还未计算完的话,那它的doStartTag方法和doAfterBody方法必须返回EVAL_BODY_AGAIN。 F r~xN!  
<  -Nj  
Tag处理类与body交互 D)5wGp  
p.G7Cs  
如果tag处理类与body交互,那tag处理类应实现BodyTag接口或从BodyTagSupport中派生。这种tag处理类一般要实现doInitBody和doAfterBody方法。 h>wU';5#f  
t.cplJF&Ue  
Body允许一些方法来读写它的内容。Tag处理类可以调用body内容的getString或getReader方法来从body中提取信息,也可用 writeOut(out) 方法来将body的内容写入到out对象中。其中out对象通过tag处理类的getPreviousOut方法来获得。 ydt1ED0Q-  
6XP>p$-  
如果body的内容需要被计算,那么doStartTag方法必须返回EVAL_BODY_BUFFERED,否则,它将返回 SKIP_BODY。 ZU`"^FQ3A  
.NKN2  
doInitBody 方法 ;>~iCF k]?  
L|<Mtw  
此方法在body内容已经设好,但未被计算之前被调用。你可以根据不同的body内容来制定初始化策略。 &~i1 @\]  
R:Lu)d>=  
doAfterBody方法 gisZmu0  
_#+i;$cO-X  
此方法在body内容已被计算后进行调用。 *$QUE0  
&b_duWs  
和doStartTag方法一样,doAfterBody方法返回一个指示符指示是否要继续计算body,如果要继续计算,则doAfterBody应返回EVAL_BODY_BUFFERED,否则,它应返回SKIP_BODY。 WI%,m~  
6vDgM fw  
release 方法 }sFHb[I &  
SC#  
tag处理类调用此方法将它的状态重置为初始状态,并释放所有的私有资源。 vQ;Z 0_  
c0@v`-9  
u>BR WN  
以下的例子读取body的内容(其中含有一条sql语句),然后将它传递给一个对象,让它进行查询。由于此处body不须重新计算,所以doAfterBody会返回SKIP_BODY。 4h|vd.t  
H_{Yr+p  
!59q@M ya[  
Public class QueryTag extends BodyTagSupport j0J6ySlY  
u URf  
{ di|l?l^l  
K$4Ky&89  
public int doAfterBody() throws JspTagException k20tn ew  
7*sB"_U2  
{ e. [h  
WaYT\CG7y  
BodyContent bc = getBodyContent(); `W5f'RU  
}q^CR(h (R  
//将body的内容以字符串的格式提取出来 *p"%cas  
% 74}H8q_z  
String query = bc.getString(); k3&Wv  
\n}cx~j  
//清除body [,VD^\  
|g~.]2az  
bc.clearBody(); ZPXxrmq%  
\QVL%,.%M  
try{ ,ecFHkT>  
]\{EUx9  
Statement stmt = connection.createStatement(); _o;alt  
G3q\Z`|3h  
Result result = stmt.executeQuery(query); u BvN*LQ  
oYW:p tJ  
}catch(SQLException e){ 4g|}]K1s  
FbF P  
throw new JspTagException(“queryTag: “ + e.getMessage() ); (f7R~le  
JMXCyDy;  
return SKIP_BODY; Wa wOap  
Ls( &.  
} H d :2  
\]zH M.E1  
} u-D%: lz85  
Ay[6rUO  
8/k* "^3  
body-content元素 F8q|$[nH  
rAgb<D@,H  
>mz<=n  
由于tag可能会有body,你必须用body-content元素来指定body内容的类型: HZ/e^"cpM  
KrB"2e+J  
<body-content>JSP|tagdependent</body-content> 3qP! (*  
f mf(5  
q.*k J/L  
如果body的内容是定制的或内部的tag、脚本元素、或HTML广本,则归类为JSP类型。其他的类型,比如上面代码所述的?D?D将sql statement类传给 query tag的这种类型应该标为tagdependent。 G#UO>i0jy  
Y-v6xUc{F  
注意:实际上body-content的值并不影响tag处理类对body内容的处理,它仅仅是被tag编辑工具用来描述此body的内容。 g/eE^o ~;  
arm26YA-,  
5LR k)@t  
用tags定义脚本变量 G@s rQum(  
xtyOG  
05Ak[OOU>  
tag处理类 w=,bF$:fIW  
voiWf?X  
`@RTfBB g  
tag处理类负责创建或设置页面中定义的脚本变量,用pageContext.setAttribute(name,value,scope)或pageContext.setAttribute(name,value)方法来实现。一般来说,tag处理类通过脚本变量的名称来获取它,脚本变量的名称一般可用get方法来获得。 ",Mr+;;:[  
vr"O9L w  
如果脚本变量的值依赖于tag处理类中的上下文中某一对象,那它可用pageContext.getAttribute(name,scope)方法来找到那个对象。一般的处理过程是tag处理类先找到脚本变量,再对其进行处理,然后用pageContext.setAttribute(name,object)的方法来设置它的新值。 Ko: <@h  
Dr)B0]KG  
对象的生存周期(scope)如下表:  Vmt$]/  
jBb:)  
对象的生存周期表 PKJw%.-  
{{qu:(_g  
名字 6o6I]QL  
可访问范围 1aDx 6Mq  
生存周期 *mby fu0q  
LtW}R4}3  
page :<hM@>eFn  
当前页面 FN\*x:g  
一直有效,除非页面向客户提交响应或重定向到一个新页面 \,D>zF  
*PM#ngLX}r  
request l|v`B6(  
当前页面或当前页面重定向到的页面 xa8;"Y~"bg  
一直有效,除非页面向客户提交响应 Kl_(4kQE_  
~bf4_5  
session zncKd{Q\tP  
当前页面或在同一浏览器窗口中的页面 - ({h @  
一直有效,除非关闭当前浏览器、超时、网络故障 4 K5  
52ExRG S  
application 0Xb,ne 7  
整个web应用程序的所有请求 2ci[L:U  
一直有效,除非发生网络故障、服务器故障 z.lIlp2:  
=U'!<w<-  
提供关于脚本变量的信息 > 9.%hSy  
V_zU?}lZ^  
以下示例定义了一个名为“book”的脚本变量,用来访问程序中关于书的信息: V/`vX;%  
jh(T?t$&  
<bean:define id=”book” name=”bookDB” property=”bookDetails” type=”database.BookDetails” /> LY-,cXm&|  
zG{P5@:.R  
<font color=”red” size=”+2” > z^vfha  
bb  M^J  
<%= messages.getString(“CartRemoved”) %> uP G\1  
>v2/0>U  
<strong><jsp:getProperty name=”book” property=”title” /></strong> u8.F_'`z  
_AzI\8m  
</font> .do8\  
~[%_]/#&%z  
当包含此tag的JSP页面被编译时,jsp引擎会自动生成关于此book的同步的代码(同步可以避免几个客户同时访问此book时造成的冲突),要生成同步代码,jsp引擎需要知道此脚本变量的如下信息: zzK<>@c  
90#* el  
· 脚本变量名称 <2N{oK.  
JR8|!Of@B  
· 脚本变量所属的类 'i',M+0>jC  
hjyM xg;Q?  
· 此脚本变量是否引用了一个新的或已存在的对象 By waD?  
%_."JT$v{  
· 此脚本变量的有效性 k3K*{"z  
q #mBNe62p  
有两种办法可以向jsp引擎提供关于脚本变量的信息:在TLD中定义variable子元素,或用tei-class子元素定义一个额外tag信息类。用variable最简单,但可能降低了一些灵活性。 i\<S ;  
Z_[ P7P  
Variable元素 )(0if0D4  
k@ <dru  
Variable元素有如下子元素: URceq2_  
f0vO(@I  
· name-given ?D?D 给出的名字,是一个常量 C$q};7b1N  
3~{I/ft  
· name-from-attribute?D?D 属性名,在编译时给出的属性名 LaO8)lqR  
"4\k1H"_  
name-given或name-from-attribute两者必须选一,但以下子元素是可选的: "\i H/  
M!+J[q  
· variable-class?D?D变量的类型,缺省为java.lang.String。 E*O($tS  
NB1KsvD{  
· declare?D?D此脚本变量是否引用了一个新对象,缺省为True。 ,`JYFh M  
b"uO BB  
· scope?D?D脚本变量的范围,缺省为NESTED。下表描述了scope的几种类型: ~P#mvQE)  
2TU V9Z  
脚本变量的有效范围 & XmaGtt  
^R=`<jx   
;89kL]  
有效性 8T1zL.u>q  
方法 VcGl8~#9  
-nXP<v=V  
NESTED :h5G|^  
在tag标签的开始和结束之间 +}O -WX?  
如果tag处理类实现BodyTag接口,则在doInitBody和doAfterBody中调用,否则在doStartTag中调用 w]t'2p-'  
pJx7S sW  
AT_BEGIN 2HtsSS#0Q  
从tag标签的开始一直到页面结束 T:u>7?8o  
如果tag处理类实现BodyTag接口,则在doInitBody、doAfterBody和doEndTag中调用,否则在doStartTag和doEndTag中调用 s]% C z\  
f[1cN`|z  
AT_END E/g"}yR  
从tag标签的结束一直到页面结束 o!:Z?.!  
在doEndTag中调用 1l$2T y+ =  
(IBT|K  
以struts为例,它的bean:define标签的实现遵循JSP1.1规范,此规范要求使用额外tag信息类来定义脚本变量。Variable元素是JSP1.2规范中加入的。以bean:define标签为例,你可以定义如下variable元素: XjF@kQeM=  
j1KNgAo<4  
<tag> Qn7T{ BW  
'{cSWa| #  
<variable> Rjq Xz6  
ss[`*89  
<name-from-attribute>id</name-from-attribute> ?OLd }8y  
KEtV  
<variable-class>database.BookDetails</variable-class> Iz1x|EQ  
(B>/LsTu  
<declare>true</declare> b%0p<*:a/  
`*Yw-HL  
<scope>AT_BEGIN</scope> UB.1xcI  
JcWp14~e  
</variable> 4d`YZNvZW/  
qFD ZD)K  
</tag> 3Rc*vVnI  
)[ A-d(y=  
额外tag信息类 (iX8YP$%  
!gve]>M  
如果要定义一个额外tag信息类,你要继承javax.servlet.jsp.TagExtraInfo类。一个TagExtraInfo类必须实现getVariableInfo方法,此方法返回一个叫VariableInfo的数组类,它包括如下信息: !\X9$4po@  
aOH|[  
· 变量名 1ZI1+TDH  
8@;]@c)m  
· 变量所属类名 zMR)w77  
>E>yA d  
· 此变量是否引用了一个新对象 5Jbwl$mZ  
~ubvdQEW  
· 此变量的有效范围 #B;P4n3  
c,4~zN8Ou  
jsp引擎将一个名为data的参数传给getVariableInfo方法,data中包括tag标签中的所有“属性名?D?D属性值”对。它可以用来向VariableInfo对象提供脚本变量的名字和类名。 wAKHD*M)  
f`n4'dG  
以struts为例,它在bean:define标签中定义了一个名为DefineTei的额外tag信息类,用来向脚本变量提供信息。由于脚本变量的名称(book)和类名(database.BookDetails)是通过tag标签的属性来传递的,它们一般定义在VariableInfo的构建代码中,并且可用data.getAttributeString方法来得到这些信息。如果要允许book脚本变量能在从tag开始直到整个JSP页面结束的范围内都可用的话,那它的范围应设为AT_BEGIN。如下所示: Z^_qXerjP  
au{) 5W4~  
i)?7+<X  
public class DefineTei extends TagExtraInfo mux/\TII  
#RBrii-,  
{ rP:g`?*V  
S MWXP  
public VariableInfo[] getVariableInfo(TagData data) UGSZg|&6#*  
n9'3~qVZ  
{ |}z)>E  
m\56BP-AM  
String type = data.getAttributeString(“type”); C|V7ZL>W  
<E2 IU~e  
If( type == null) fB8, )&  
w\)K0RN  
type = “java.lang.Object”; 3YHEH\60^  
ib=)N)l  
return new VariableInfo[] { Dh8ECy5k<*  
gQ_<;'m)2  
new VariableInfo(data.getAttributeString(“id”), )2&3D"V  
+<a\0FsD  
type, jE*{^+n  
7*l$ i/!  
true, z`zz8hK.  
geme_  
VariableInfo.AT_BEGIN) 1&|]8=pG7  
50cVS)hG6d  
}; '^UHY[mX8  
 0k (-  
} P8eCaZg?(3  
C[L 5H  
} NoiB9 8g  
EhxpMTS  
}u_D{bz  
注意:关于额外tag信息类的类名必须要在TLD中的tag标签下的tei-class子元素中定义。因此,DefineTei的tei-class中的定义看起来如下: `HX:U3/  
<tei-class> o{PG& }K  
org.apache.struts.taglib.bean.DefineTagTei !*-|!Vz  
</tei-class> S(gr>eC5  
cnu&!>8V  
I L*B@E8  
具有协作关系的tag (/A.,8Ad  
I0m7;M7 P  
Gyq 6?  
tag通过共享对象来进行协作,JSP技术支持2种方式的对象共享。 ?()*"+N(ck  
W'C>Fn}lO?  
第一种方法是使用pageContext对象进行对象的共享(可支持JSP页面和tag处理类之间的共享),如果在一个tag处理类中要调用由另一个tag处理类创建的对象,可调用pageContext.getAttribute(name, scope)方法。 7hHID>,o9%  
0V:H/qu8>  
第二各方式的共享是对于tag之间有嵌套关系而言的,外层的tag所创建的对象对于内层的tag来说是可以共用的。这种形式的共享的好处是减少了可能存在的重名冲突。 |'h (S|  
L/i'6(="  
要访问一个嵌套tag创建的对象,tag处理类必须先找到此嵌套tag对象,可用TagSupport的静态方法 TagSupport.findAncestorWithClass(from, class)或TagSupport.getParent方法。前者在当不确定此tag是否为嵌套tag对象时使用。一旦它的父类被找到,它就能访问其所有动态或静态创建的对象。静态创建的对象是父类的成员,而动态创建的对象可能是父类的私有对象。诸如此类的对象可以用tag处理类的setValue方法来保存,用getValue方法来获得。 6u, g  
_%e8GWf  
下例阐述了以上两种共享对象的方法。在这个例子当中,一个查询tag检查一个名为connection的属性名是否在doStartTag中被设置。如果connection属性被设置,tag处理类从pageContext中得到这个connection对象。否则,此tag处理类先找到它的父tag处理类,然后从它的父tag处理类中找到connection对象。 Xdn&%5rI  
B4y_{V  
Fi i(dmn  
public class QueryTag extends BodyTagSupport t<45[~[  
$|~ <6A{y  
{ uj8saNu  
287j,'vR  
private String connectionId; ^B<-.(F  
4fi4F1f  
public int doStartTag() throws JspException mkSu $c  
A (2 0+  
{ r8EJ@pOF2w  
@Tu`0 =8  
String cid = getConnection(); " .7@  
cfTT7O#Dc  
if(cid != null) y\??cjWb]  
|/Vq{gxp+  
{ eKiDc=@  
3~`P8 9  
//存在一个connection id,使用它。 "S;4hO  
j9fBl:Fr  
connection = (Connection) pageContext.getAttribute(cid); 2xNR=u`  
{8m&Z36E  
} W>jKWi,{  
*y4DK6OFe  
else xm{?h,U,  
 .\oz  
{ Ic'D# m  
G#%Sokkb'  
ConnectionTag ancestorTag = (ConnectionTag)findAncestorWithClass(this, & DP"RWT/  
Oe Q[-e  
ConnectionTag.class); -HF?1c  
k6#$Nb606  
if(ancestorTag == null) e|tx`yA  
7m#EqF$P  
{ E-WpsNJ)X  
lf=G  
throw new JspTagException(“一个没有connection属性的查询标签必须被一个connection标记嵌套。”); EB3/o7)L  
f&vMv.  
} !KI^Z1dP(  
Fg`<uW]TFZ  
connection = ancestorTag.getConnection(); p*<Jg l  
\|>% /P  
} XJo.^<m  
KpGx<+0p  
} ep8UWxB5  
|sGJum&=  
} ,a>Dv@$Y  
vv)q&,<c  
;pm/nu  
N^QxqQ~  
此查询标签在JSP页面中的调用形式可以从以下2种定义中任选一种: `+Nv =vk  
vd%AV(]<LJ  
"nz\YQdg  
<tt:connection id=”con01” ...> ... </tt:connection> r5gqRh}+  
'-"[>`[q  
<tt:query id=”balances” connection=”con01” > Z` kVyuQ  
2sGKn a  
SELECT account, balance FROM acct_table : ;8L1'  
^|<>`i6  
where customer_num = <%= request.getCustno() %> 7)U ik}0  
3FvVM0l"  
</tt:query> o}=*E  
P].Eb7I  
>~ *wPoW  
,|*Gr"Q=  
"EpH02{i  
<tt:connection ...> ,x\qYz+7|  
%vO(.A+  
<x:query id=”balances”> `\@n&y[`7  
:?UcD_F  
SELECT account, balance FROM acct_table <oXBkCi0r  
#e.x]v:  
where customer_num = <%= request.getCustno() %> 4Q!%16 P  
3^P;mQ$p1  
</x:query> <zpxodM@T  
&j~9{ C  
</tt:connection> f@`|2wG  
/S J><  
N4 x5!00  
与此同时,在TLD中必须指定connection属性为可选的,定义如下: 8pEA3py  
`Hw][qy#  
<tag> G+fo'ThG  
[Q:mq=<Z%  
... =oVC*b  
a( ~X  
<attribute> @(c^u;  
8 AW}7.<5  
<name>connection</name> |fyzb=Lg  
)@9Eq|jMC  
<required>false</required> ^/2HH  
gdCit-3  
</attribute> H*G(`Zl}  
}bRn&)e  
</tag>
描述
快速回复

您目前还是游客,请 登录注册
温馨提示:欢迎交流讨论,请勿纯表情、纯引用!
认证码:
验证问题:
10+5=?,请输入中文答案:十五