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

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

级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
标准的JSP 标记可以调用JavaBeans组件或者执行客户的请求,这大大降低了JSP开发的复杂度和维护量。JSP技术也允许你自定义taglib,其实换句话说,taglib可以看成是对JSP标记的一种扩展,正如xml是对html的一种扩展一样。taglib通常定义在tag标签库中,这种标签库存放着你自己定义的tag标签。简而言之,如果使用taglib,那么你可以设计自己的JSP标记! lXF7)H&T  
?PS?_+E\L  
一般来说,自定义tag标签主要用于操作隐藏对象、处理html提交表单、访问数据库或其它企业级的服务,诸如邮件和目录操作等等。自定义tag标签的使用者一般都是那些对java编程语言非常精通,而且对数据访问和企业级服务访问都非常熟悉的程序员,对于HTML设计者来说,使得他可以不去关注那些较复杂的商业逻辑,而将精力放在网页设计上。同时,它也将库开发者和库使用者进行合理分工,自定义tag标签将那些重复工作进行封装,从而大大提高了生产力,而且可以使得tag库可用于不同的项目中,完美地体现了软件复用的思想。 +0)M1!gK  
o>nw~_ H\  
在这篇文章中,我们主要讨论: _BY+Tfol  
vQp'bRR  
· 什么是自定义tag标签? xY/F)JOeG  
<;yS&8  
· 怎么使用tag标签? P(FlU]q  
'&hd^9]Lo  
o 声明要使用的tag库 B=;kC#Emtf  
2 S~(P  
o 找到与之对应的tag处理类 zc=G4F01  
Yi,`uJKh  
o tag标签的类型 t)Cf]]dV  
^ >&#F[aT  
· 自定义tag标签 ',xUU{5?  
5jso)`IL  
o tag处理类 KO7&dM  
pW@W-k:u  
o tag库描述 *r[V[9+y-D  
/g. c( -#]  
o tag标签示例 `"[qb ?z  
NiWAJ]Z  
o 带属性的tag Ynvf;qs  
@MVul_@6  
o 带body的tag NJE*/_S  
U]gUGD!5x  
o 定义了脚本变量的tag DO *  
=R' O5J  
o 具有协作关系的tag q?Csm\Y  
Y2XxfZ j  
· 自定义tag标签 MJqWc6{ n  
vpf.0!zh  
o 一个迭代tag的例子 WA,D=)GP  
[520!JhZY  
o 一个模板tag库 "^6Fh"]  
yU&;\'  
o tag处理类到底是怎样被调用的? I/O/*^T  
.4R.$`z4  
=k.%#h{  
什么是自定义的tag? ~G@YA8}  
xSd&xwP  
一个自定义的tag标签是用户定义的一种JSP标记。当一个含有自定义的tag标签的JSP页面被jsp引擎编译成servlet时,tag标签被转化成了对一个称为tag处理类的对象进行的操作。于是当JSP页面被jsp引擎转化为servlet后,实际上tag标签被转化成为了对tag处理类的操作。 {&>rKCi  
+|d]\WlJ  
自定义tag标签有很多特色,诸如: f$\ O:E=  
GJZjQH-#P  
· 可以在JSP页面中自定义tag标签的属性 {icTfPR4E  
OqIXFX"  
· 访问JSP页面中的所有对象 aIFlNS,y  
J_Tz\bZ3)  
· 可以动态地修改页面输出 po*8WSl9c[  
/P@%{y  
· 彼此这间可以相互通信。你可以先创建一个JavaBeans组件,然后在一个tag中调用此JavaBeans组件,同时可以在另一个tag中调用它。 6QY;t:/<  
ap )B%9  
· tag允许相互嵌套,可以在一个JSP页面中完成一些复杂的交互。 Rr %x;-  
M Zz21H  
FMeBsI9pL  
使用tag标签 QHZ",1F  
lTqlQ<`V  
f\dfKNm6  
本节主要描述怎样在JSP页面中使用tag标签,以及tag标签的不同类型。 J??AU0 vh  
y`buY+5l  
要使用tag标签,JSP程序员必须做2件事: eNK +)<PK(  
EZ .3Z`  
· 声明此tag标签的tag库 9D1WUUa  
]<f(@]R/d  
· 实现此tag标签 $\h-F8|JMX  
F!EiF&[\J  
声明tag标签所在的tag库 iOURS  
!`I@Rk]`c  
如果要使用tag标签,则应用JSP的taglib指示符来指定其tag库(注意:taglib要在在使用此tag标签之前声明) *"8Ls0!  
8i`>],,ch  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> {:uv}4Z  
|} b+$J  
uri属性定义了唯一的标签库描述(以下简称TLD),它可以是直接是tld文件名或一个独一无二的名字。prefix是用来区别其它TLD中和本TLD中有重名的tag的一种手段。 u3+B/ 5x  
h9ScN(|0y  
TLD必须以.tld作为扩展名,并且存放在当前应用的WEB-INF目录或其子目录下。你可以通过它的文件名直接引用它,也可以通过别的方式间接地引用它。 v>} +->f  
$!.>)n  
以下taglib指示符直接引用一个TLD:  rvd $4l^  
hOAZvrfQ4  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> #mu L-V  
+n;nvf}(  
以下的taglib指示符通过一个逻辑名称间接地引用一个TLD: f(m, !  
GmWr  
<%@ taglib uri=”/tutorial-template” prefix=”tt” %> ,sAAV%" >  
H\ejW@< ;h  
如果是间接引用TLD的话,那你必须还要在web.xml中定义此逻辑名称与tld文件之间的映射,具体做法是在web.xml中加入一个名为taglib的元素: 3MQZ)!6  
Xh;.T=/E|  
<taglib> (4R(5t  
|g3:+&  
<taglib-uri>/tutorial-template</taglib-uri> R}Lk$#S#  
]WDmx$"&e  
<taglib-location> 1^WGJ"1  
v<!S_7h  
/WEB-INF/tutorial-template.tld ?ZRF]\dP]  
;3cbXc@]  
</taglib-location> `sYFQ+D#O  
{\l  
</taglib> ls 5iE  
;AEfU^[  
Q[j| 2U  
实现此tag标签 Sf,z  
R#d~a;j  
|q77  
为了实现tag标签,你有2种方法来存放tag处理类。一、让tag处理类以.class的方式存放于当前应用的WEB-INF/class子目录下,二、如果tag处理类是以JAR包的形式存在的话,那可以放在当前应用的WEB-INF/lib目录下,如果tag处理类要在多个应用中共享,那么它就应放在jsp服务器上的common/lib目录下,对于tomcat来说,就是tomcat/common/lib目录下。 nTqU~'d'  
:G1ddb&0+  
QF"7.~~2  
tag标签类型 :DN!1~ZtW  
+'?Qph6o,7  
u-TT;k'  
自定义的tag标签遵循XML语法。它有一个开始标记和一个结束标记,有的还有body(即文本节点): l/X_CM8y~  
iNA3Y  
<tt:tag> j?.F-ar  
ii)# (b:V  
body ~wb1sn3  
uDDa >Ka#+  
</tt:tag> EMmgX*iu@  
"<ZV'z  
)5Khl"6!z  
一个不带body的tag标签如下: c|Ivet>3  
uYUFxm  
<tt:tag /> .{1$;K @  
b' o]Y  
~R!1{8HP  
简单的tag标签 *r`=hNr  
i1 E|lp)  
一个没有body和属性的tag标签如下: 7Aqg X0)  
n1f8jS+'}  
<tt:simple /> ?*fa5=ql  
Ma^jy.  
\H] |5fp*  
带属性的tag标签 2}vibDq p  
d6luksO*9  
Y=mr=]q  
自定义标签可以有自己的属性。属性一般在开始标记中定义,语法为 attr=”value”。属性的作用相当于自定义标签的一个参数,它影响着tag处理类的行为。你可以在TLD中详细定义它。 INg0[Lpc  
MKHnA|uQ](  
你可以用一个String常量给一个属性赋值,也可以通过表达式给它赋值,如<%= ...%>。以struts为例,它的logic:present标签就是用的String常量来给属性赋值: @?,x3\N-  
2@|`Ugjptl  
<loglic:present parameter = “Clear”> > G\0Z[<v,  
Qd} n4KF\  
而另一个标签logic:iterate是用表达式来给属性赋值: iGW|j>N  
DSrU7#  
<logci:iterate collection=”<%= bookDB.getBooks() %>” P3zUaN \c  
UUt"8]@[  
id=”book” type=”database.BookDetails”> F]$ Nu  
n1-p/a.  
(t4i&7-  
带body的tag标签 -$d?e%}#  
p _gN}v  
一个自定义标签可以包含其它自定义标签、脚本变量、HTML标记或其它内容。 b;i*}4h!  
'oa.-g5  
在下述例子中,此JSP页面使用了struts的logic:present标签,如果些标签定义了parameter=”Clear”的属性,则将清除购物车的内容,然后打印出一条信息: z74JyY  
{?qfH>oFA  
<logic:present parameter=”Clear”> t>bzo6cj  
NQdwj>_a  
<% cart.clear(); %> C;BO6$*_e  
X|of87  
<font color=”#ff0000” size=”+2”><strong> Xb _ V\b0  
km %r{  
你选择了清除购物车! jD S?p)&  
s9?mX@>h  
</strong></font>  ?8>a;0  
TFSdb\g  
</logic:present> pS?D~0Nb  
#VQZ"7nI@  
_J,**AZ~z  
到底是用属性还是用body来传递信息? V.~kG ,Ht  
j*%#~UFw  
如上所述,我们既可以通过属性,也可以通过body来传递信息。但一般来说,比较简单的类型,如字符串或简单表达式最好采用属性来传递信息。 zEQ]5>mG  
uYC^&siS<s  
g\aO::  
定义脚本变量的tag标签 x\yM|WGL  
T8 FW(Gw#  
所谓脚本变量,是指JSP中可以调用的变量或对象。它可由tag标签产生。以下示例阐述了一个tag标签定义了一个名为tx的由JNDI所定义的事务处理对象。脚本变量可以是ejb对象、事务、数据库连接等等: }<Ydj .85  
1mFH7A($  
<tt:lookup id=”tx” type=”UserTransaction” name=”java:comp/UserTransaction” /> _H| )g*]t  
(:iMs) iO{  
<% tx.begin(); %> [@K'}\U^+  
}?m0bM  
... 4 ]oe`yx  
Xu{y5 N  
m(f`=+lqI`  
具有协作关系的tag标签 zw<<st Bp  
]OpGD5jZ  
自定义tag标签之间可以通过共享对象来实现协作。在下述例子中,标签tag1创建了一个名为obj1的对象,在标签tag2仍可以重复使用obj。 c)EYX o  
S^s-md>  
<tt:tag1 attr1=”obj1” value1=”value” /> m[%356u  
$QiMA,  
<tt:tag2 attr1=”obj1” /> V9[_aP;  
U]Q 5};FK  
在以下这个例子当中,如果外层的tag标签创建了一个对象,那么其内层的所有tag标签都可以使用这个对象。由于这样产生的对象没有一个指定的名字,那么就可以将少重名的冲突。这个例子阐述了一系列协作的嵌套对象。 )!(gS,  
|$ PA  
<tt:outerTag> ^B.Z3Y  
&v:zS$m>  
<tt:innerTag /> +*.*bo  
)CXlPbhY?  
</tt:outerTag> AQ-PHv  
EW$drY@  
q/?*|4I  
Tag处理类 TG=A]--_a  
;adZ*'6u  
L|[i<s;  
Tag处理类必须实现Tag接口或BodyTag接口,不过现在一般都流行从TagSupport或BodyTagSupport类中继承,这些类或接口都可以在javax.servlet.jsp.tagext包中找到。 SU%O\ 4Ty  
+v/y{8Fu  
当JSP引擎看到自己的JSP页面中包含有tag标签时,它会调用doStartTag方法来处理tag标签的开头,调用doEndTag方法来处理tag标签的结束。 QMMpB{FZ`o  
qkfof{z  
下表说明不同类型的tag所需要不同的处理过程: smCACQ$ (  
gj;gl ="3  
Tag处理类的方法 F- kjv\  
j+!u=E  
Tag标签类型 '@t,G,FJ  
所调用的方法 w/NT 5  
_;}$/  
基本标签 } W]A`-Jv  
doStartTag, doEndTag, release zFOtOz`9H  
>s%Db<(P=  
带属性的标签 fBX@ MedC  
doStartTag, doEndTag, set/getAttribute1...N, release %:C6\4  
a;$V;3C{b&  
带内容的标签 2IJniS=[>  
doStartTag, doEndTag, release X au %v5r  
o?]Q&,tO  
带内容的标签,且内容重复循环 @<DRFP  
doStartTag, doAfterBody, doEndTag, release :%sG'_d  
oDS7do  
带内容的标签,且内容与JSP交互 k3&68+  
doStartTag, doEndTag, release, doInitBody, doAfterBody, release Bc!<!  
d8Vqmrc~  
一个tag处理类可以通过javax.servlet.jsp.PageContext来与JSP交互,通过javax.servlet.jsp.PageContext类,tag处理类可以访问JSP中的request、session和application对像。 {X?Aj >l  
D <~UaHfk  
如果tag标签是互相嵌套的,那内层的tag处理类可以通过它的parent属性来访问上层的tag处理类。 9#[,{2pJr  
2-m@-  
一般情况都将所有的tag处理类打成了JAR的包,以便于发布。 f['I4 /o  
l&\y]ZV={  
WG,Il/  
Tag库描述(简称TLD) W,8Uu1X =  
a[ ;L+  
N5 sR  
Tag库是用xml语言描述的,TLD包括了tag库中所有tag标签的描述,它一般用来被jsp服务器用来校验tag的语法正确性,或者被jsp开发者用来开发新的标签。 AXcmN  
z*HM_u  
TLD的文件扩展名必须为.tld,而且必须放在当前WEB应用的WEB-INF目录或其子目录中。 )4fQ~)  
(tO4UI5!  
一个TLD的内容的开头必须遵守标准的XML开头,用于描述DTD和xml的版本,例如: &SIf|IX.  
e!Z}aOeE  
<?xml version="1.0" encoding="ISO-8859-1" ?> M_0f{  
(KO]>!t  
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd"> -75mgOj.#  
TLD必须以<taglib>来作为它的根元素,<taglib>的子元素如下表: <Hv/1:k}  
b\^DQZmth  
RH,x);J|  
<taglib>的子元素 -[!t=qi  
2KO`+  
Element wv3*o10_w8  
Description q%d,E1  
ebEI%8p g  
tlib-version .3) 27Cjw  
Tag库的版本 \e'Vsy>q  
(Jb#'(~a  
jsp-version +Zi+ /9Z(H  
Tag库所需要的jsp的版本 )Q9Qo)D T  
[ 1G wcXr  
short-name L'Iw9RAJ  
助记符,tag的一个别名(可选) @|h9jx|  
RKrNmD*rk*  
uri zWPX  
用于确定一个唯一的tag库 DhxS@/  
`JV(ae0  
display-name FzOWM7+\  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) ;E{jn4B'  
7Z9'Y?[m  
small-icon yC ?p,Ci,  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) }e|cszNRd  
Z=$-S(>J  
large-icon &g}P)x r  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) {Zw;<1{E  
z 3[J sE%  
description 1tO96t^d%  
对tag库的描述(可选) v? 8i;[  
P cbhylKd  
listener +*W lj8  
参见下面listener元素 lA4-ZQ2Zp[  
.~ uKr^%  
tag (z;lNl(*C  
参见下面tag 元素 F6J]T6 Y  
.[eC w  
Listener元素 ,^n&Q'p3  
6? lAbW  
一个tag库可能定义一些类做为它的事件侦听类,这些类在TLD中被称为listener 元素,jsp服务器将会实例化这些侦听类,并且注册它们。Listener元素中有一个叫listener-class的子元素,这个元素的值必须是该侦听类的完整类名。 -vm1xp$  
E"[p_ALdC  
Tag元素 4cy,'B  
AEM;ZQU  
每个tag元素在tag库中都要指出它的名字、类名、脚本变量、tag的属性。其中脚本变量的值可以直接在TLD中定义或通过tag附加信息的类来取得。每个属性描述了这个属性是否可以省略,它的值是否可以通过<%= …%>这样的JSP语法来获得,以及属性的类型。 DXj>u9*%  
yQ^,>eh  
每一个tag在TLD中对应一个tag元素,下表是tag元素的子元素: QiA}0q3]0  
D HQxu4  
Tag元素的子元素 #Rfc p!  
#|+4`Gf^  
元素名称 I lO,Ql  
描述 6jm?d"9  
2aR9vmR  
name 3S#p4{3   
独一无二的元素名 A|K=>7n]U  
h$sOJs~6h  
tag-class !\VEUF,K?  
Tag标签对应的tag处理类 s% rmfIp"  
MrUjqv6a[  
tei-class =!DX,S7  
javax.servlet.jsp.tagext.TagExtraInfo的子类,用于表达脚本变量(可选) [So1`IA6  
n>,GmCo  
body-content m<#^c?u  
Tag标签body的类型 atd;)o0*0  
,j{tGj_  
display-name EF$ASNh"  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) Q3hSWXq'  
]5@n`;&#.  
small-icon OpazWcMoo  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) a0k;way  
]iW:YNvXA  
large-icon QoUdTIIL  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) _R]0S  
}M(xN6E  
description qGhg?u"n:  
此tag标签的描述 WqM| nX  
i/C% 1<  
variable cGm?F,/`  
提供脚本变量的信息(同tei-class)(可选) [;yH.wn#5  
V=fh;p  
attribute AB3OG*C9  
Tag标签的属性名 8kcMgCO  
Vp1ct06^  
以下章节介绍对于不同类型的tag,如何具体地实现它们。 B1FJAKI);  
+-),E.  
Odw'Ua  
简单的tag Wj!+ E{y<r  
*pD|N  
$8(QBZq  
tag处理类 a_0I)' ?  
w2s06`g  
简单的tag处理类必须实现Tag接口的doStartTag和doEndTag方法。当jsp引擎碰到tag标签的开头时,doStartTag被调用,因为简单的tag没有body,所以此方法将返回 SKIP_BODY。当jsp引擎碰到tag标签的结尾时,doEndTag被调用,如果余下的页面还要被计算,那它将返回EVAL_PAGE,否则将会返回SKIP_PAGE。 OXp N8Dh5  
fD(r/~Vu  
以下是例子:对于标签 <tt:simple /> ,它的tag处理类实现如下: 7@g0>1Fz  
RhB)AUAj  
%rhZH^2  
public SimpleTag extends TagSupport iF +@aA  
}=\?]9`  
{ 5|r*,! CF  
21Dc.t{  
public int doStartTag() throws JspException < @GO]vY  
2?6]Xbs{  
{ xR kw+  
x'\C'zeF  
try{ nhMxw @Z\  
xDl; tFI  
pageContext.getOut().print(“Hello.”); /TPtPq<7:#  
dG0zA D  
}catch(Exception e){ NZZy^p&O  
JF~9efWe>  
throw new JspTagException(“SimpleTag: “ + e.getMessage()); $kN=45SR  
oj{CNa  
} \1<|X].jNY  
!"yr;t>|Zb  
return SKIP_BODY; 7T6Zlp  
PCL ;Z  
} 9,JM$ Y {  
l(87s^_  
public int doEndTag() jDQ?b\^  
- G/qfd|s/  
{ Fx.Ly]L  
t_!p({  
return EVAL_PAGE; `C|];mf(#  
U$OI]Dd9  
}  7 FY2a  
+XO\#$o>W  
} H#V&5|K%  
>EFWevT{  
g"|>^90  
注意:如果tag标签没有内容的话,那必须定义body-content元素为空,例如 FP=27=  
+'5I8FE-  
<body-content>empty</body-content> Q~0>GOq*  
u;t~ z  
Z|x|8 !D  
带属性的tag标签
评价一下你浏览此帖子的感受

精彩

感动

搞笑

开心

愤怒

无聊

灌水
级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
只看该作者 1 发表于: 2007-01-01
tag处理类 3Ji$igL  
m }HaJ  
对于tag标签的每个属性,你必须依照JavaBeans规范来定义其属性,以及get和set方法。以struts的logic:present 标签为例,  P33xt~  
M+VWAh#uD  
<logic:present parameter=”Clear”> [yk-<}#B  
F{a;=h#@Q  
与此相应,此tag处理类应有如下方法和定义: t>?tWSNf  
*n EkbI/  
x,U_x  
protected String parameter = null; P$k*!j_W  
J+E,UiZU  
public String getParameter() }]mx Kz  
Kd^.>T-  
{ yCN_vrH>  
:zKMw=  
return this.parameter; 4L8hn4F  
R^/SBrWve  
} 0stc$~~v  
HrsG^x  
public void setParameter(String parameter) r#4/~a5i~  
=iKl<CqI$E  
{ Pb8@owG8  
"#o..?K  
this.parameter = parameter; `wtso  
77)WNL/ x  
} RM `qC  
$+7uB-KsU  
L0!CHP/nRS  
注意:如果你的属性名为id,而且你的tag处理类是从TagSupport类继承的,那你就不需要定义它的属性和set和get方法,因为他们早已在TagSupport被定义过了。 W!? h2[  
< z2wt  
Attribute元素 A)C)5W  
@lE'D":?  
对于tag标签的每个属性,你必须定义它是否必须的,它的值是否可以用诸如<%= …%>的表达式来获得,以及它的类型(可选),如果不指定它的类型,那就默认为是java.lang.String类型。如果rtexprvalue元素被定义为true或yes,那么在type元素中就定义了attribute的返回类型。 / }$n_N\!)  
|0=UZK7%O  
<attribute> +K'Hr: (  
ZzupK^5Z  
<name>attr1</name> ySmbX  
.nrllVG%`  
<required>true|false|yes|no</required> v}Ju2}IK  
rjK`t_(=  
<rtexprvalue>true|false|yes|no</rtexprvalue> u7[}pf$}  
4_=2|2Wz[  
<type>attribute的返回类型(只用当rtexprvalue为真是才有效)</type> _#:/ ~Jp  
*|dr-e_j  
</attribute> y')OmR2h  
TMj;NSc3  
如果tag的某个属性不是必须的,那tag处理类会自动提供一个缺省值。 _/I">/ivlM  
6qH0]7maI  
例如,在logic:present这个tag标签中定义了一个属性叫parameter,但它不是必须的,而且它可以被诸如<%= …%>的表达式来赋值。 nlNk  
/gZyl|kdy  
<tag> z2uL[deN'"  
=,(TP  
<name>present</name> -U=Ci  
_2!8,MX  
<tag-class>org.apache.struts.taglib.logic.PresentTag</tag-class> A<X?1$  
9KXL6#h  
<body-content>JSP</body-content> + GI906K  
zOs}v{8"  
R2Fjv@Egk  
 1[SG.  
<attribute> ai/|qYf  
BHUI1y5t  
<name>parameter</name> HYfGu1j?X  
q#W|fkfx+  
<required>false</required> a]T:wUYG'  
/D&&7;jJ  
<rtexprvalue>true</rtexprvalue> Ur(R[*2bx  
PW5]+ |#  
</attribute> gYB!KM *v  
gA!@oiq@  
%tyo(HZQ  
T+<.KvO-  
</tag> >[fu&r1  
*5%vU|9b  
B{nwQC b  
属性元素的校验 ^viabkf C  
$^ws#}j  
 K& #il  
有关于tag标签的有效值可以从tag库的说明文档中获得,当JSP页面被编译时,jsp引擎会强制性地参照TLD中定义的规则进行检查。 5qb93E"C  
U)/.wa>  
还有一个方法也可以进行属性元素的校验,就是先继承类TagExtraInfo,然后调用它的isValid方法。这个类同时也起到提供tag中定义的脚本变量信息的作用。 `x[Is$  
S(zp_  
IsValid方法通过TagData对象来传递属性信息,它包括着tag的所有的属性名-值的信息。由于校验发生在运行时刻,因此这个属性的值将被赋值为TagData.REQUEST_TIME_VALUE。 zt(lV  
f+h\RE=BGt  
例如tag标签<tt:twa attr1=”value1” />在TLD中定义如下: p0Jr{hM  
><<>4(eF p  
<attribute> |C [!A  
~3F'X  
<name>attr1</name> h'y%TOob  
[.gk{> #  
<required>true</required> g+ c*VmY  
D'g,<-ahl  
<rtexprvalue>true</rtexprvalue> ]`/>hH>+~9  
$ DL}jH^S  
</attribute> XX8HSw!w  
0bT j/0G?  
VdlT+'HF  
这个定义说明了attr1能在运行期间被赋值。 ^_WR) F'K  
!dLu($P  
以下的isValid方法检查attr1属性的值是否属于Boolean类型。注意由于attr1能在运行刻被赋值,那么isValid方法必须检查tag用户是否对此tag进行了运行时刻赋值。 _U s"   
F]ao Ty  
aM}9ZurI  
Public class TwaTEI extends TagExtraInfo 5\+*ml  
~g{j)"1  
{ Q{l,4P  
l0qaTpn  
public boolean isValid(Tagdata data) e"E8BU  
azPH~' E'  
{ g#5R|| r  
2n<Mu Q]  
Object o = data.getAttribute(“attr1”); fVbjU1N  
>y3FU1w5d  
If(o != null && o != TagData.REQUEST_TIME_VALUE) QAs)zl0  
,mHME~  
{ J @Hg7Faz  
|Y7SP]/`gB  
if( ( (String)o).toLowerCase().equals(“true”) || &dyQ6i$],  
yHeL&H  
((String)o).toLowerCase().equals(“false”) ) Q:-T' xk@  
,aP6ct  
return true; O$*lPA[  
1oQw)X  
else & l>nzJ5?  
{wqT$( (<  
return false; bb6x} jR  
(GJtTp~2C4  
} _Mw3>GNl  
D2$ 9$xeR  
else F>fCp  
w!F>fcm  
return true; s<I)THC  
CMj =4e  
} ,'8%'xit  
roADC?@r  
} %U\,IO`g  
lw@Yn>eza  
Hjm> I'9  
带body的tag c]6b|mHT  
6S`_L  
\<7Bx[/D4  
tag处理类 / Hr|u  
B2;P%B  
uo"<}>iJ  
如果tag标签含有内容,那处理方式会略微有些不同,而且还要视tag处理类是否要与body交互的情况而定。如果要与body交互,那我们认为tag处理类要可能要对body进行操作。 \Zj%eW!m  
H*=cw<  
Tag处理类不与body交互 }z` x-(V  
?;XO1cs  
如果tag处理类不与body交互,tag处理类应该实现Tag接口或从TagSupport中派生,如果body要被计算,那么doStartTag方法应返回 EVAL_BODY_INCLUDE,否则应返回SKIP_BODY。 Rl?1|$%  
.9J^\%JD  
如果tag处理类要对body反复运算,则它应该实现IterationTag或从TagSupport中派生。如果tag处理类认为body还未计算完的话,那它的doStartTag方法和doAfterBody方法必须返回EVAL_BODY_AGAIN。 y ``\^F  
:?M_U;;z2+  
Tag处理类与body交互 DQG%`-J  
GcV/_Y  
如果tag处理类与body交互,那tag处理类应实现BodyTag接口或从BodyTagSupport中派生。这种tag处理类一般要实现doInitBody和doAfterBody方法。 btW#ebm  
PmuG(qg  
Body允许一些方法来读写它的内容。Tag处理类可以调用body内容的getString或getReader方法来从body中提取信息,也可用 writeOut(out) 方法来将body的内容写入到out对象中。其中out对象通过tag处理类的getPreviousOut方法来获得。 fn}E1w  
~+Wx\:TT  
如果body的内容需要被计算,那么doStartTag方法必须返回EVAL_BODY_BUFFERED,否则,它将返回 SKIP_BODY。 Z RVt2  
~74Sq'j9Wt  
doInitBody 方法 LU6R"c11  
S?688  
此方法在body内容已经设好,但未被计算之前被调用。你可以根据不同的body内容来制定初始化策略。 #-L0.z(  
T?8BAxC?K  
doAfterBody方法 _XZ Gj:V  
lp`j3)  
此方法在body内容已被计算后进行调用。 j.=:S;  
9Yt|Wj  
和doStartTag方法一样,doAfterBody方法返回一个指示符指示是否要继续计算body,如果要继续计算,则doAfterBody应返回EVAL_BODY_BUFFERED,否则,它应返回SKIP_BODY。 '2lV(>"  
yYz{*hq  
release 方法 |` T7}U  
-.D?Z8e  
tag处理类调用此方法将它的状态重置为初始状态,并释放所有的私有资源。 v=k+MvX  
i}m'#b  
d{fd5jv;  
以下的例子读取body的内容(其中含有一条sql语句),然后将它传递给一个对象,让它进行查询。由于此处body不须重新计算,所以doAfterBody会返回SKIP_BODY。 AiHU*dp6  
%]P{)*y-?  
5226 &N  
Public class QueryTag extends BodyTagSupport |8 ` }8vo)  
ex>7f%\  
{ 9\8ektq}Z  
PQaTS*0SXJ  
public int doAfterBody() throws JspTagException dz^HN`AlzC  
}qWnn>h9xv  
{ KI9Pw]]{-  
 a*p|Ij  
BodyContent bc = getBodyContent(); 13?:a[~=Y  
*7AB0y0k  
//将body的内容以字符串的格式提取出来 Ii0\Skb  
B^2r4 9vC  
String query = bc.getString(); 5{=+S]  
/\1'.GR  
//清除body SdnnXEB7  
)Jt. Z^J<  
bc.clearBody(); mm>l:M TF  
B- @bU@H  
try{ ag'hHFV  
@`[e1KQ  
Statement stmt = connection.createStatement(); k$$SbStD  
L?ZSfm2<  
Result result = stmt.executeQuery(query); )@! fLA T  
!oH{=.w  
}catch(SQLException e){ 6 IvAs-%W  
-6)nQNj|  
throw new JspTagException(“queryTag: “ + e.getMessage() ); 'Xik2PaO  
`l45T~`]$  
return SKIP_BODY; c/ Pql!h+  
[]>rYZ9bv  
} )>~ jjR  
3EYEd39E  
} z</C)ObL  
?NA $<0  
B EwaQvQ!  
body-content元素 Zj[m  
S(.J  
vjX,7NY?  
由于tag可能会有body,你必须用body-content元素来指定body内容的类型: P5my]4|x  
M6wH$!zRa  
<body-content>JSP|tagdependent</body-content> 4q .;\n  
_|e&zr  
+.Vh<:?  
如果body的内容是定制的或内部的tag、脚本元素、或HTML广本,则归类为JSP类型。其他的类型,比如上面代码所述的?D?D将sql statement类传给 query tag的这种类型应该标为tagdependent。 <y7{bk~i  
X3sAy(q  
注意:实际上body-content的值并不影响tag处理类对body内容的处理,它仅仅是被tag编辑工具用来描述此body的内容。 (Z<@dkO?)  
|&K;*g|a  
y A5h^I  
用tags定义脚本变量 :2j`NyLI.  
RQ=rB9~:ZN  
U*+-#  
tag处理类 18X?CoM~  
I'xc$f_+  
J* !_O#  
tag处理类负责创建或设置页面中定义的脚本变量,用pageContext.setAttribute(name,value,scope)或pageContext.setAttribute(name,value)方法来实现。一般来说,tag处理类通过脚本变量的名称来获取它,脚本变量的名称一般可用get方法来获得。 GP+=b:C{E  
b'pwRKpx  
如果脚本变量的值依赖于tag处理类中的上下文中某一对象,那它可用pageContext.getAttribute(name,scope)方法来找到那个对象。一般的处理过程是tag处理类先找到脚本变量,再对其进行处理,然后用pageContext.setAttribute(name,object)的方法来设置它的新值。 e (]]  
 3?D, Wu  
对象的生存周期(scope)如下表: z#gebr~_\  
{N]WVp*R  
对象的生存周期表 :?~)P!/xl5  
8(`e\)%l0  
名字 $'l<2h>4  
可访问范围 h GA2.{  
生存周期 G^{~'TZv%  
(A=PDjP!  
page ou0TKE9 _  
当前页面 <Y6Vfee,&  
一直有效,除非页面向客户提交响应或重定向到一个新页面 by1q"\-,  
NK|U:p2H  
request u>;aQtK~  
当前页面或当前页面重定向到的页面 }Bv1fbD4U  
一直有效,除非页面向客户提交响应 xD*Zcw(vj~  
oL9<Fi  
session E 14DZ  
当前页面或在同一浏览器窗口中的页面 z wUC L  
一直有效,除非关闭当前浏览器、超时、网络故障 Mq~E'g4#  
TeuZVy8a  
application v 8F{qT50  
整个web应用程序的所有请求 62nmm/c  
一直有效,除非发生网络故障、服务器故障 Kz b-a$  
v RtERFL  
提供关于脚本变量的信息 yW?-Z[  
MgP|'H3\  
以下示例定义了一个名为“book”的脚本变量,用来访问程序中关于书的信息: B^9C}QB  
Sm[#L`eqW  
<bean:define id=”book” name=”bookDB” property=”bookDetails” type=”database.BookDetails” /> 'T^MaLK  
'bRf>=  
<font color=”red” size=”+2” > mNC?kp  
1q;R+65  
<%= messages.getString(“CartRemoved”) %> rXmrT%7k  
#}fvjJ{  
<strong><jsp:getProperty name=”book” property=”title” /></strong> +o3n%( ^~  
Z:^<NdKe  
</font> ax5n}  
K"[jrvZ=  
当包含此tag的JSP页面被编译时,jsp引擎会自动生成关于此book的同步的代码(同步可以避免几个客户同时访问此book时造成的冲突),要生成同步代码,jsp引擎需要知道此脚本变量的如下信息: gna!Q  
uxdB}H,  
· 脚本变量名称 R6X2d\l#  
8m H6?,@6  
· 脚本变量所属的类 xuHP4$<h3  
>"UXY)  
· 此脚本变量是否引用了一个新的或已存在的对象 -N/n|{+F  
DNj<:Pdd)  
· 此脚本变量的有效性 Ho}*Bn~ic  
/T qbl^[  
有两种办法可以向jsp引擎提供关于脚本变量的信息:在TLD中定义variable子元素,或用tei-class子元素定义一个额外tag信息类。用variable最简单,但可能降低了一些灵活性。 }^H(EHE  
5Bq;Vb  
Variable元素 d$ o m\@  
!!A(A^s  
Variable元素有如下子元素: [Y@}{[q5  
m!zv t  
· name-given ?D?D 给出的名字,是一个常量 Jv 5l   
aPe*@py3T  
· name-from-attribute?D?D 属性名,在编译时给出的属性名 O:+y/c  
iuqJPW^}  
name-given或name-from-attribute两者必须选一,但以下子元素是可选的: >r)UDa+  
_s-X5 xU  
· variable-class?D?D变量的类型,缺省为java.lang.String。 Y,mo}X<>  
.z$UNB(!M  
· declare?D?D此脚本变量是否引用了一个新对象,缺省为True。 tag)IWAiE  
%1cxZxGT  
· scope?D?D脚本变量的范围,缺省为NESTED。下表描述了scope的几种类型: M`#g>~bI#R  
kL s{B  
脚本变量的有效范围 %iPIgma  
sMAH;'`!Eu  
&Odrq#o?R  
有效性 _@?I)4n|  
方法 qDg`4yX.}  
T+0z.E!~I  
NESTED I_Z?'M  
在tag标签的开始和结束之间 g<F+Ldgj  
如果tag处理类实现BodyTag接口,则在doInitBody和doAfterBody中调用,否则在doStartTag中调用 I|bX;l  
Gn6\n'r0  
AT_BEGIN .@r{Tq,%q8  
从tag标签的开始一直到页面结束 H[g i`{c  
如果tag处理类实现BodyTag接口,则在doInitBody、doAfterBody和doEndTag中调用,否则在doStartTag和doEndTag中调用  ZJ)>gV  
1IgTJ" \  
AT_END CNj |vYj  
从tag标签的结束一直到页面结束 F*z>B >{)  
在doEndTag中调用 IN;!s#cl:  
UC`sq-n  
以struts为例,它的bean:define标签的实现遵循JSP1.1规范,此规范要求使用额外tag信息类来定义脚本变量。Variable元素是JSP1.2规范中加入的。以bean:define标签为例,你可以定义如下variable元素: ?3LV$S)U  
uFuH/(}K[  
<tag> Pvv7|AV   
%26HB w=JF  
<variable> .2P3 !KCL  
7"eIZ  
<name-from-attribute>id</name-from-attribute> kVeY} 8  
%;_EWs/z8  
<variable-class>database.BookDetails</variable-class> bA6^R If?  
x`p908S^  
<declare>true</declare> -NzOX"V]3  
^755 LW  
<scope>AT_BEGIN</scope> @VND}{j  
&H,UWtU+  
</variable> g C8 deC8  
PHez5}T  
</tag> '&|%^9O/"  
s)'+,lKw  
额外tag信息类 f/kYm\Zc  
4 q % Gc  
如果要定义一个额外tag信息类,你要继承javax.servlet.jsp.TagExtraInfo类。一个TagExtraInfo类必须实现getVariableInfo方法,此方法返回一个叫VariableInfo的数组类,它包括如下信息: -e51 /lhpd  
fP;I{AiN~  
· 变量名 SoCN.J30  
%0u5d$bq  
· 变量所属类名 &"1_n]JO  
8SiWAOQAL  
· 此变量是否引用了一个新对象 a*,V\l|6  
q`|E9  
· 此变量的有效范围 su60j^e*  
EcR[b@YI  
jsp引擎将一个名为data的参数传给getVariableInfo方法,data中包括tag标签中的所有“属性名?D?D属性值”对。它可以用来向VariableInfo对象提供脚本变量的名字和类名。 sBxCi~  
 )DW".c  
以struts为例,它在bean:define标签中定义了一个名为DefineTei的额外tag信息类,用来向脚本变量提供信息。由于脚本变量的名称(book)和类名(database.BookDetails)是通过tag标签的属性来传递的,它们一般定义在VariableInfo的构建代码中,并且可用data.getAttributeString方法来得到这些信息。如果要允许book脚本变量能在从tag开始直到整个JSP页面结束的范围内都可用的话,那它的范围应设为AT_BEGIN。如下所示: *xeJ4h  
C-Y7n5  
4&L,QSJ V  
public class DefineTei extends TagExtraInfo *rm[\  
|<8g 2A{X  
{ 2fm6G).m  
ZTGsZ}{5   
public VariableInfo[] getVariableInfo(TagData data) #)T'a  
I$TD[W  
{ s,laJf  
Q."rE"}<  
String type = data.getAttributeString(“type”); {v3@g[:|  
MzW!iG  
If( type == null) ~vZ1.y4  
TYxi &;w  
type = “java.lang.Object”; v9D[| 4  
c)QOgXv  
return new VariableInfo[] { .?F`H[^)^u  
7pH[_]1"  
new VariableInfo(data.getAttributeString(“id”), A~a7/N6s;  
TU| 0I  
type, Pj^Ccd'>=  
> LU !Z  
true, \3t)7.:4  
AUU(fy#<  
VariableInfo.AT_BEGIN) 1 x0)mt3  
;UQ&yj%x  
}; ' b,zE[Q  
T!pHT'J  
} 9\r5&#<(I  
*; 6LX  
} 5)4?i p  
5e'**tbKH  
taSYR$VJ  
注意:关于额外tag信息类的类名必须要在TLD中的tag标签下的tei-class子元素中定义。因此,DefineTei的tei-class中的定义看起来如下: aTLr%D:Ka  
<tei-class> %A@U7gqc  
org.apache.struts.taglib.bean.DefineTagTei F xXnX  
</tei-class> ]`@< I'?,X  
ehX4[j6  
KXo[;Db)k  
具有协作关系的tag {*Qx^e`h$.  
`LWbL*;Y0  
%C >Win)g  
tag通过共享对象来进行协作,JSP技术支持2种方式的对象共享。 PiX(Ase  
|P"kJ45  
第一种方法是使用pageContext对象进行对象的共享(可支持JSP页面和tag处理类之间的共享),如果在一个tag处理类中要调用由另一个tag处理类创建的对象,可调用pageContext.getAttribute(name, scope)方法。 AIwp2Fz  
Eo{js?1G_  
第二各方式的共享是对于tag之间有嵌套关系而言的,外层的tag所创建的对象对于内层的tag来说是可以共用的。这种形式的共享的好处是减少了可能存在的重名冲突。 J s,.$t  
`b5pa`\4  
要访问一个嵌套tag创建的对象,tag处理类必须先找到此嵌套tag对象,可用TagSupport的静态方法 TagSupport.findAncestorWithClass(from, class)或TagSupport.getParent方法。前者在当不确定此tag是否为嵌套tag对象时使用。一旦它的父类被找到,它就能访问其所有动态或静态创建的对象。静态创建的对象是父类的成员,而动态创建的对象可能是父类的私有对象。诸如此类的对象可以用tag处理类的setValue方法来保存,用getValue方法来获得。 Ed"p|5~  
;uU 8$  
下例阐述了以上两种共享对象的方法。在这个例子当中,一个查询tag检查一个名为connection的属性名是否在doStartTag中被设置。如果connection属性被设置,tag处理类从pageContext中得到这个connection对象。否则,此tag处理类先找到它的父tag处理类,然后从它的父tag处理类中找到connection对象。 HYmC3  
ff\~`n~WZ  
4VWk/HK-!  
public class QueryTag extends BodyTagSupport - {QU>`2  
`hi=y BO  
{ D(#f`Fj;  
G@[8P?M=Z  
private String connectionId;  5&&4-  
PgWWa*Ew  
public int doStartTag() throws JspException qd*}d)!  
&riGzU]  
{ IOcQI:4.`  
8Xot ly  
String cid = getConnection(); QF#w $%7  
]:<! (  
if(cid != null) ,#A(I#wL~  
;sZG=y@  
{ s[yWBew  
Cbw *? 9d  
//存在一个connection id,使用它。 6pt_cpbR  
L*(9Hti  
connection = (Connection) pageContext.getAttribute(cid); p,Ff, FfH  
l_vGp  
} z8Q!~NN-K  
*qd:f!Q3  
else <'a~Y3B"o  
k$w~JO!s  
{ EKwQ$?I  
\G" S7  
ConnectionTag ancestorTag = (ConnectionTag)findAncestorWithClass(this, lkn|>U[  
0bg"Q4  
ConnectionTag.class); 94u{k1d x  
.+9hm|  
if(ancestorTag == null) *@2Bh4  
VY0.]t  
{ n~N>;m P  
]gk1q{Ql<  
throw new JspTagException(“一个没有connection属性的查询标签必须被一个connection标记嵌套。”); Z*%;;&?  
m1"m KM  
} 8i#  
Rh!UbEPjC  
connection = ancestorTag.getConnection(); : \+xXb{  
>XD?zF)6  
} {3~VLdy  
?\}Gi(VVE  
} { "y/;x/  
_R4}\3}!  
} 9%!h/m>rW  
hi7_jl6  
ToXWFX  
`fu_){  
此查询标签在JSP页面中的调用形式可以从以下2种定义中任选一种: @I _cwUO  
I{Zb/}k-  
RLmOg{L  
<tt:connection id=”con01” ...> ... </tt:connection> WE<?y_0y&  
i"2OsGT  
<tt:query id=”balances” connection=”con01” > e7vm3<m4  
ejROJXB  
SELECT account, balance FROM acct_table ALF0d|>=uj  
/WrB>w  
where customer_num = <%= request.getCustno() %>  +\/Q  
|VBt:dd<  
</tt:query> Yh":>~k?SY  
{ZJO5*  
m|a9T#B(  
:RaQ =C  
C"{^wy{sL  
<tt:connection ...> U<Pjn)M~B  
Y[ G_OoU  
<x:query id=”balances”> .Ro/ioq  
zA,vp^  
SELECT account, balance FROM acct_table CWj_K2=d  
D tsZP (  
where customer_num = <%= request.getCustno() %> I= mz^c{  
M&Uy42,MR  
</x:query> /x<g$!`X  
mxa~JAlN_  
</tt:connection> ]-=L7a  
|.<_$[v[x  
C"hN2Z!CD|  
与此同时,在TLD中必须指定connection属性为可选的,定义如下: @KN+)qP  
#lYyL`B+~  
<tag> $%<{zWQm  
i! .]U@{k  
... |LHJRP-Z  
:ym?]EL4o  
<attribute> SeX]|?D  
o2/:e  
<name>connection</name> s\*L5{kiSl  
4>JSZ6i#n  
<required>false</required> Kkvc Zs'4m  
L 4By5)  
</attribute> o3J#hQrl  
H;Wrcf2  
</tag>
描述
快速回复

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