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

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

级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
标准的JSP 标记可以调用JavaBeans组件或者执行客户的请求,这大大降低了JSP开发的复杂度和维护量。JSP技术也允许你自定义taglib,其实换句话说,taglib可以看成是对JSP标记的一种扩展,正如xml是对html的一种扩展一样。taglib通常定义在tag标签库中,这种标签库存放着你自己定义的tag标签。简而言之,如果使用taglib,那么你可以设计自己的JSP标记! Xlpu_H|  
G@oY2sM"  
一般来说,自定义tag标签主要用于操作隐藏对象、处理html提交表单、访问数据库或其它企业级的服务,诸如邮件和目录操作等等。自定义tag标签的使用者一般都是那些对java编程语言非常精通,而且对数据访问和企业级服务访问都非常熟悉的程序员,对于HTML设计者来说,使得他可以不去关注那些较复杂的商业逻辑,而将精力放在网页设计上。同时,它也将库开发者和库使用者进行合理分工,自定义tag标签将那些重复工作进行封装,从而大大提高了生产力,而且可以使得tag库可用于不同的项目中,完美地体现了软件复用的思想。 @>_`g=  
h)"PPI  
在这篇文章中,我们主要讨论: D%N^iJC,9  
b!J21cg<L  
· 什么是自定义tag标签? j~(rG^T  
I&U?8  
· 怎么使用tag标签? KtUI(*$`  
scCOiK)  
o 声明要使用的tag库 p)N=  
8xs[{?|:  
o 找到与之对应的tag处理类 AdesR-e$R  
DmM<Kkg.J  
o tag标签的类型 PGsXB"k<8  
iE, I\TY[  
· 自定义tag标签 r ioNP(  
r]sv50Fy  
o tag处理类 7JD jJQy  
[nJ),9$z_  
o tag库描述 z/)HJo2#  
(GJ)FWen0"  
o tag标签示例 fD  
YQvN;W  
o 带属性的tag $*V:; -H  
<->Nex  
o 带body的tag ~&4Hc%*IB  
bX:Y5o49  
o 定义了脚本变量的tag l Ot3^`  
r9sW:cM:e  
o 具有协作关系的tag )d!,,o  
V~tq _  
· 自定义tag标签 1hw1AJ}(F  
aB;syl{  
o 一个迭代tag的例子 ,o& &d.  
^&MMtWR  
o 一个模板tag库 3 k py3z[%  
jxU1u"WU  
o tag处理类到底是怎样被调用的? %Wkvo-rOq  
R"EX$Zj^E  
$-[V)]h  
什么是自定义的tag? xAw$bJj~s  
I$9^i#O'3  
一个自定义的tag标签是用户定义的一种JSP标记。当一个含有自定义的tag标签的JSP页面被jsp引擎编译成servlet时,tag标签被转化成了对一个称为tag处理类的对象进行的操作。于是当JSP页面被jsp引擎转化为servlet后,实际上tag标签被转化成为了对tag处理类的操作。 Jp=eh   
?D]4*qsIlu  
自定义tag标签有很多特色,诸如: tI0d!8K  
1T a48  
· 可以在JSP页面中自定义tag标签的属性 , \ |S BS  
s]Nh9h  
· 访问JSP页面中的所有对象 ;|6kFBGC"+  
m!3b.2/h  
· 可以动态地修改页面输出 +!6aB|-  
"rOe J~4 X  
· 彼此这间可以相互通信。你可以先创建一个JavaBeans组件,然后在一个tag中调用此JavaBeans组件,同时可以在另一个tag中调用它。 $@"o BCc  
yT%"<m6Y*\  
· tag允许相互嵌套,可以在一个JSP页面中完成一些复杂的交互。 3`S|I_$(T"  
lG/M%i  
G.OAzA13!t  
使用tag标签 1{i)7 :Y  
Kv^ez%I  
fNNkc[YTZI  
本节主要描述怎样在JSP页面中使用tag标签,以及tag标签的不同类型。 ^I=c]D]);  
!qsk;Vk7Z  
要使用tag标签,JSP程序员必须做2件事: tfW/Mf  
19Xc0ez  
· 声明此tag标签的tag库 DvCs 5  
u[q1]]   
· 实现此tag标签 -B-?z?+(O  
l2QO\O I9m  
声明tag标签所在的tag库 ]fvU}4!  
$_CE!_G&)  
如果要使用tag标签,则应用JSP的taglib指示符来指定其tag库(注意:taglib要在在使用此tag标签之前声明) =p,+a/*  
W L$nchS9  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> aT1T.3 a  
9otA5I^v  
uri属性定义了唯一的标签库描述(以下简称TLD),它可以是直接是tld文件名或一个独一无二的名字。prefix是用来区别其它TLD中和本TLD中有重名的tag的一种手段。 e6f:@ O?  
~G|un}g=  
TLD必须以.tld作为扩展名,并且存放在当前应用的WEB-INF目录或其子目录下。你可以通过它的文件名直接引用它,也可以通过别的方式间接地引用它。 SN+B8*!  
bCr) 3,  
以下taglib指示符直接引用一个TLD: _xT=AF9~o  
-.-j e"E  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> ,e{(r0  
83~ Gu[  
以下的taglib指示符通过一个逻辑名称间接地引用一个TLD: .V G$`g"  
V#["Z}  
<%@ taglib uri=”/tutorial-template” prefix=”tt” %> \]ouQR.t@\  
X]ow5{e  
如果是间接引用TLD的话,那你必须还要在web.xml中定义此逻辑名称与tld文件之间的映射,具体做法是在web.xml中加入一个名为taglib的元素: Dnn$-W|NC  
gpW3zDJ  
<taglib> JRt^YX  
Pw i6Ly`  
<taglib-uri>/tutorial-template</taglib-uri> q"xIW0Pc  
ngJi;9X8*t  
<taglib-location> T\ZWKx*#  
D%GB2-j R  
/WEB-INF/tutorial-template.tld ^j&'2n@ 9a  
/nEt%YYh;x  
</taglib-location> 8 #fzL7  
7hwl[knyB  
</taglib> =<mpZ'9gW  
hT4 u;3xE  
gdkl,z3N3  
实现此tag标签 7Gb1[3  
 SbQ Ri  
k~f3~-"  
为了实现tag标签,你有2种方法来存放tag处理类。一、让tag处理类以.class的方式存放于当前应用的WEB-INF/class子目录下,二、如果tag处理类是以JAR包的形式存在的话,那可以放在当前应用的WEB-INF/lib目录下,如果tag处理类要在多个应用中共享,那么它就应放在jsp服务器上的common/lib目录下,对于tomcat来说,就是tomcat/common/lib目录下。 M:x?I_JG8  
u&/[sq x  
sk !92mQ  
tag标签类型 r2A%.bL#  
vH/<!jtI  
37GJ}%Qs  
自定义的tag标签遵循XML语法。它有一个开始标记和一个结束标记,有的还有body(即文本节点): EN6a? }5  
$MD|YW5  
<tt:tag> .J:04t1  
Gh}k9-L  
body ,0 +%ji^V  
V?AHj<  
</tt:tag> >^}nk04  
zy\p,  
YoiM\gw  
一个不带body的tag标签如下: GyI(1O AW  
6(Za}H  
<tt:tag /> *#+e_)d  
3]xe7F'`  
<Wc98m  
简单的tag标签 k$ k /U  
v,t;!u,40  
一个没有body和属性的tag标签如下: &2IrST{d:V  
/N6sH!w  
<tt:simple /> Q- ( [3%  
AZ' "M{wiI  
2,,zN-9mt  
带属性的tag标签 ]-h$CJSY  
fFP>$  
VK\ Bjru9  
自定义标签可以有自己的属性。属性一般在开始标记中定义,语法为 attr=”value”。属性的作用相当于自定义标签的一个参数,它影响着tag处理类的行为。你可以在TLD中详细定义它。 "#bL/b'{  
bB^% O^:  
你可以用一个String常量给一个属性赋值,也可以通过表达式给它赋值,如<%= ...%>。以struts为例,它的logic:present标签就是用的String常量来给属性赋值: 3 $7TeqfAC  
z d 9Gi5&  
<loglic:present parameter = “Clear”> _~!*|<A_  
l{oAqTN  
而另一个标签logic:iterate是用表达式来给属性赋值: )6mx\t  
-L e:%q2  
<logci:iterate collection=”<%= bookDB.getBooks() %>” 3=o^Vv  
!z@QoD  
id=”book” type=”database.BookDetails”> =f'MiU!p6  
*zoAD|0N  
Fx#0 :p  
带body的tag标签 )=VSERs  
;#c|ZnX  
一个自定义标签可以包含其它自定义标签、脚本变量、HTML标记或其它内容。 ]D|sQPi]F  
JqWMO!1  
在下述例子中,此JSP页面使用了struts的logic:present标签,如果些标签定义了parameter=”Clear”的属性,则将清除购物车的内容,然后打印出一条信息: "0x"X w#I  
9_Tk8L#  
<logic:present parameter=”Clear”> `:WVp~fn  
yNp l0 d  
<% cart.clear(); %> Cb}hE ro  
,VZ;=  
<font color=”#ff0000” size=”+2”><strong> dm3cQ<0  
j" wX7  
你选择了清除购物车! YrAaL"20  
Mazjn?f  
</strong></font> 9L3#aE]C  
i8R.Wl$l  
</logic:present> *&p`8:  
g1U   
`P1jg$(eA  
到底是用属性还是用body来传递信息? (ov=D7>t0  
}'HJVB_  
如上所述,我们既可以通过属性,也可以通过body来传递信息。但一般来说,比较简单的类型,如字符串或简单表达式最好采用属性来传递信息。 :%GxU;<E{  
.#n1p:}[  
0{|ib !  
定义脚本变量的tag标签 ?^iX%   
z 9mmZqhK\  
所谓脚本变量,是指JSP中可以调用的变量或对象。它可由tag标签产生。以下示例阐述了一个tag标签定义了一个名为tx的由JNDI所定义的事务处理对象。脚本变量可以是ejb对象、事务、数据库连接等等: & sbA:xZBA  
(lv|-Phc.  
<tt:lookup id=”tx” type=”UserTransaction” name=”java:comp/UserTransaction” /> GCx1lm  
#PYTFB%  
<% tx.begin(); %> G<.p".o4  
'Y23U7 n0B  
... ydp?%RB3w  
HfN-WYiR  
6itp Mck  
具有协作关系的tag标签 ^bpxhf x  
', -4o-  
自定义tag标签之间可以通过共享对象来实现协作。在下述例子中,标签tag1创建了一个名为obj1的对象,在标签tag2仍可以重复使用obj。 v=Ep  
aYQ!`mS::M  
<tt:tag1 attr1=”obj1” value1=”value” /> 4-^LC<}k  
g Z3VT{  
<tt:tag2 attr1=”obj1” /> AHsp:0Ma#  
E<]l]?  
在以下这个例子当中,如果外层的tag标签创建了一个对象,那么其内层的所有tag标签都可以使用这个对象。由于这样产生的对象没有一个指定的名字,那么就可以将少重名的冲突。这个例子阐述了一系列协作的嵌套对象。 jJ% *hDZ6t  
f(q^R  
<tt:outerTag> S-[]z*  
w <zO  
<tt:innerTag /> b~\gV_Z  
>T3HkOT  
</tt:outerTag> ;OW`(jC  
FG8genCH@  
| >xUgpQi  
Tag处理类 :CEhc7gU  
>W 2Z]V  
"kyy>H9)  
Tag处理类必须实现Tag接口或BodyTag接口,不过现在一般都流行从TagSupport或BodyTagSupport类中继承,这些类或接口都可以在javax.servlet.jsp.tagext包中找到。 (:3rANY|  
|6LC>'  
当JSP引擎看到自己的JSP页面中包含有tag标签时,它会调用doStartTag方法来处理tag标签的开头,调用doEndTag方法来处理tag标签的结束。 Ve>*KHDSt  
_%Q\G,a;  
下表说明不同类型的tag所需要不同的处理过程: )fSQTbB;0  
-L7Q,"a$  
Tag处理类的方法 (bH*i\W  
N*JWd  
Tag标签类型 WE$Pi;q1  
所调用的方法 ^T\JFzV  
\ ?['pB  
基本标签 cWIX!tc8  
doStartTag, doEndTag, release r.M8#YL  
{UT>> *C  
带属性的标签 $?p^ m`t_  
doStartTag, doEndTag, set/getAttribute1...N, release qe!`LeT#  
HKO00p7  
带内容的标签 ~X;r}l=k<  
doStartTag, doEndTag, release yI\  
yBO88rfh>  
带内容的标签,且内容重复循环 A S;ra,x  
doStartTag, doAfterBody, doEndTag, release ?}^e,.M0?s  
Q1V4bmM  
带内容的标签,且内容与JSP交互 Pz3jc|Ga  
doStartTag, doEndTag, release, doInitBody, doAfterBody, release N(mhgC<O  
E@QsuS2&  
一个tag处理类可以通过javax.servlet.jsp.PageContext来与JSP交互,通过javax.servlet.jsp.PageContext类,tag处理类可以访问JSP中的request、session和application对像。 ?bbu^;2*f  
?b, eZ+t  
如果tag标签是互相嵌套的,那内层的tag处理类可以通过它的parent属性来访问上层的tag处理类。 6 )eO%M`  
&,Dh*)k  
一般情况都将所有的tag处理类打成了JAR的包,以便于发布。 K' N`rx.7  
* EOIgQp  
B]]_rl,  
Tag库描述(简称TLD) y6Xfddd61  
M9*7r\hqYV  
<x DD*u  
Tag库是用xml语言描述的,TLD包括了tag库中所有tag标签的描述,它一般用来被jsp服务器用来校验tag的语法正确性,或者被jsp开发者用来开发新的标签。 w#k'RuOw5  
QFIdp R.  
TLD的文件扩展名必须为.tld,而且必须放在当前WEB应用的WEB-INF目录或其子目录中。 X tZ0z?  
%,%s09tO  
一个TLD的内容的开头必须遵守标准的XML开头,用于描述DTD和xml的版本,例如: C$ cX{hV  
S*rgYe!E  
<?xml version="1.0" encoding="ISO-8859-1" ?> w'ZL'/d  
EL80f>K  
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd"> +g ovnx  
TLD必须以<taglib>来作为它的根元素,<taglib>的子元素如下表: ~Bn#A kL  
I"*g-ji0  
/HH5Mn*  
<taglib>的子元素 (qHI>3tpY  
n5"rSgUtE  
Element 2-nL2f!a{p  
Description %YefTk8cr,  
'wz*GMGWC  
tlib-version D8slSX`6j  
Tag库的版本 O-:#Q(H!  
C/%umazP9  
jsp-version ftsr-3!Vm  
Tag库所需要的jsp的版本 -tZ2 N  
^dH#n~Wx0  
short-name u*`acmS>N  
助记符,tag的一个别名(可选) *>rpcS<l  
a^i`DrX  
uri /Q5pA n-u  
用于确定一个唯一的tag库 -wlob`3  
=UA-&x@  
display-name \tLJ( <8  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) @5Q}o3.zA-  
i%>]$*  
small-icon /lDW5;d  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) T=: &W3  
y!GjC]/  
large-icon \\ M2_mT  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) 5gZ0a4  
K,%H*1YKK  
description IJO`"da  
对tag库的描述(可选) vp &jSfQ^  
>[,Rt"[V  
listener 1 9a"@WB@  
参见下面listener元素 j(6:   
+pc_KR  
tag wA) NB  
参见下面tag 元素 qrO] t\  
b,/fz6 {N  
Listener元素 6'395x_ .\  
K+Al8L?K_  
一个tag库可能定义一些类做为它的事件侦听类,这些类在TLD中被称为listener 元素,jsp服务器将会实例化这些侦听类,并且注册它们。Listener元素中有一个叫listener-class的子元素,这个元素的值必须是该侦听类的完整类名。 d|]F^DDuI  
ukv _bw  
Tag元素 ,XCC#F(d1  
R+8+L|\wHv  
每个tag元素在tag库中都要指出它的名字、类名、脚本变量、tag的属性。其中脚本变量的值可以直接在TLD中定义或通过tag附加信息的类来取得。每个属性描述了这个属性是否可以省略,它的值是否可以通过<%= …%>这样的JSP语法来获得,以及属性的类型。 8dq{.B?  
01 6l$K4  
每一个tag在TLD中对应一个tag元素,下表是tag元素的子元素: o+`W  
bP&o] ?dN  
Tag元素的子元素 u-Ct-0  
vlIet$ k  
元素名称 rX%#Q\0h  
描述 Q bfm*JP~  
P1 =bbMk  
name 6tI7vLmG  
独一无二的元素名 ~-lIOQ.v  
Tz+2g&+  
tag-class QkZT%!7  
Tag标签对应的tag处理类 IyIh0B~i  
%~J90a  
tei-class PHi'&)|  
javax.servlet.jsp.tagext.TagExtraInfo的子类,用于表达脚本变量(可选) REB8_H"  
?(>7v[=iT  
body-content -r]s #$  
Tag标签body的类型 D}vgXzD  
6Z ~>d;&9  
display-name >FFZ8=  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) D; H</5#Q  
vTQQ d@  
small-icon *ZyIbT  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) mJ<rzX  
RW48>4f/+  
large-icon gWqmK/.U.0  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) oh%T4 $  
;gy_Qf2U  
description u!oHP  
此tag标签的描述 a+)Yk8%KY  
"w= p@/C  
variable DUEA"m h  
提供脚本变量的信息(同tei-class)(可选) U# Y ?'3:  
wd~e3%JM  
attribute ,!F'h:   
Tag标签的属性名 ?+D_*'65D  
%MU<S9k  
以下章节介绍对于不同类型的tag,如何具体地实现它们。 1sYwFr5  
X&MO}  
,f0cy\.?  
简单的tag `x~k}  
1Ls@|   
Dd<gYPC  
tag处理类 Vm_y,;/(-R  
8\!0yM#yK  
简单的tag处理类必须实现Tag接口的doStartTag和doEndTag方法。当jsp引擎碰到tag标签的开头时,doStartTag被调用,因为简单的tag没有body,所以此方法将返回 SKIP_BODY。当jsp引擎碰到tag标签的结尾时,doEndTag被调用,如果余下的页面还要被计算,那它将返回EVAL_PAGE,否则将会返回SKIP_PAGE。 cz OhSbmc  
(k6=o';y  
以下是例子:对于标签 <tt:simple /> ,它的tag处理类实现如下: /],:sS7  
P9:7_Vc  
G~a;q+7v'$  
public SimpleTag extends TagSupport *y5d&4G2  
Otj=vGr0  
{ %bZ3^ ub}t  
;H_yNrwA  
public int doStartTag() throws JspException # Fw<R'c  
t< $9!"  
{ Xp1xhb*^  
Zg5@l3w  
try{ )M#~/~^f+  
<d# 9d.<  
pageContext.getOut().print(“Hello.”); (3 8.s:-  
60[f- 0X  
}catch(Exception e){ 8xDS eXh;  
jkQv cU  
throw new JspTagException(“SimpleTag: “ + e.getMessage()); &.an-  
)AXTi4MNp  
} ;T/W7=4CZ  
8II-'%S6q  
return SKIP_BODY; +>KWY PH  
U&C\5N]  
} ^>h 9<  
j^llO1i/  
public int doEndTag() 3T# zxu  
Ayc}uuu  
{ P-K\)65{Y  
!O@qqg(>  
return EVAL_PAGE; uKo)iB6D  
_jy*`$"q (  
} !lm^(SSv  
q-/A_5>!;f  
} tQ5gmj  
0gm+R3;k^  
1& YcCN\k  
注意:如果tag标签没有内容的话,那必须定义body-content元素为空,例如 l@q.4hT  
<'v?WV_  
<body-content>empty</body-content> h\Op|#gIT  
, =IbZ  
']u w,b  
带属性的tag标签
评价一下你浏览此帖子的感受

精彩

感动

搞笑

开心

愤怒

无聊

灌水
级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
只看该作者 1 发表于: 2007-01-01
tag处理类 L,[0*h  
LV0g *ng  
对于tag标签的每个属性,你必须依照JavaBeans规范来定义其属性,以及get和set方法。以struts的logic:present 标签为例, ZWG$MFEjl  
]d9;YVAU  
<logic:present parameter=”Clear”> lD6hL8[  
&w*.S@  ;  
与此相应,此tag处理类应有如下方法和定义: 6f?5/hq  
!a[ voUS  
QVL92"  
protected String parameter = null; :o*{.  
Fb*^GH)J  
public String getParameter() AVOqW0Z+y  
8 fVI33  
{ @+syD  
3VCyq7 B^  
return this.parameter; Kk!D|NKLC  
R7KHfXy'm  
} #h /-  
Rr^<Q:#"<|  
public void setParameter(String parameter) r}WV"/]p  
8niQG']  
{ }z,4IHNn  
x(hUQu 6  
this.parameter = parameter; Wgq*|teW  
"}\z7^.W>  
} -[~{c]/c  
s_.q/D@vu  
M98dQ%4I  
注意:如果你的属性名为id,而且你的tag处理类是从TagSupport类继承的,那你就不需要定义它的属性和set和get方法,因为他们早已在TagSupport被定义过了。 ! D'U:)  
pb{'t2kk  
Attribute元素 uCNQ.Nbf C  
cwz %LKh  
对于tag标签的每个属性,你必须定义它是否必须的,它的值是否可以用诸如<%= …%>的表达式来获得,以及它的类型(可选),如果不指定它的类型,那就默认为是java.lang.String类型。如果rtexprvalue元素被定义为true或yes,那么在type元素中就定义了attribute的返回类型。 KB&t31aq  
@>qzRo  
<attribute> Pgr>qcbql  
wQ2'%T|t  
<name>attr1</name> y 8];MTl  
7eQ7\,^H  
<required>true|false|yes|no</required> PP[{ c  
"h_n/}r=  
<rtexprvalue>true|false|yes|no</rtexprvalue> s+yBxgQ/  
'@AK0No\W  
<type>attribute的返回类型(只用当rtexprvalue为真是才有效)</type>  3iV/7~ O  
W7l/{a @  
</attribute> {tu* ="d=  
%ia/i :  
如果tag的某个属性不是必须的,那tag处理类会自动提供一个缺省值。 .<u<!fL2  
_66zXfM<  
例如,在logic:present这个tag标签中定义了一个属性叫parameter,但它不是必须的,而且它可以被诸如<%= …%>的表达式来赋值。 =k2+VI  
H }uT'  
<tag>  >pv~$  
2(5wFc  
<name>present</name> `2J6Dz"W  
`;hsOfo  
<tag-class>org.apache.struts.taglib.logic.PresentTag</tag-class>  3i?{E ^  
&hB~Z(zS!  
<body-content>JSP</body-content> ?.v!RdM+  
S%Pk@n`z]  
6%U1%;  
w{F8]N>0<  
<attribute> cGsP0LkHC  
cP$b>3O  
<name>parameter</name> G&/}P$  
fyYv}z  
<required>false</required> . 2.$Rq  
p % 3B^  
<rtexprvalue>true</rtexprvalue> ^5 F-7R8Q  
{KeHqM}e  
</attribute> K\IS"b3X  
,{%/$7)  
wjq f u /  
5>KAVtYvc  
</tag>  Ca@[]-_H  
70lb6A  
-66|Y  
属性元素的校验 "LaNXZ9  
.DHZs#R  
.{5)$w>  
有关于tag标签的有效值可以从tag库的说明文档中获得,当JSP页面被编译时,jsp引擎会强制性地参照TLD中定义的规则进行检查。 wCMsaW  
Z)P x6\?+  
还有一个方法也可以进行属性元素的校验,就是先继承类TagExtraInfo,然后调用它的isValid方法。这个类同时也起到提供tag中定义的脚本变量信息的作用。 L(`^T`  
I y8gQdI  
IsValid方法通过TagData对象来传递属性信息,它包括着tag的所有的属性名-值的信息。由于校验发生在运行时刻,因此这个属性的值将被赋值为TagData.REQUEST_TIME_VALUE。 K?-K<3]9f  
45/f}kvy  
例如tag标签<tt:twa attr1=”value1” />在TLD中定义如下: ^zs CF0  
`r_qvrC  
<attribute> "!p#8jR^  
eU@yw1N  
<name>attr1</name> U6jlv3  
-CtA\< 7I  
<required>true</required> BB--UM{7  
JF: QQ\  
<rtexprvalue>true</rtexprvalue> |A'8'z&q  
R!*UU'se  
</attribute> bt%k;Z]  
f@\ k_  
cX7xG U  
这个定义说明了attr1能在运行期间被赋值。 L.U [eH  
>9+@oGe(E  
以下的isValid方法检查attr1属性的值是否属于Boolean类型。注意由于attr1能在运行刻被赋值,那么isValid方法必须检查tag用户是否对此tag进行了运行时刻赋值。 ~K:#a$!%,  
Bwb3@vNA  
(G#)[0<fX  
Public class TwaTEI extends TagExtraInfo wMt?yc:X  
HY5g>wv@  
{ (}4tj4d  
\dIIZSN  
public boolean isValid(Tagdata data) @,M!&l  
P8DJv-f`  
{ 8@6:UR.)  
mEz&:A  
Object o = data.getAttribute(“attr1”); j,6dGb  
q$:T<mFK$  
If(o != null && o != TagData.REQUEST_TIME_VALUE) nHD4J;l  
F3H)B:  
{ pA(@gisg  
*Z|!%C  
if( ( (String)o).toLowerCase().equals(“true”) || <G2;nvRr  
S$BwOx3QF  
((String)o).toLowerCase().equals(“false”) ) 2~R"3c+^  
Z(/jQ=ozQ  
return true; vB/MnEKR  
ua`2 & ;T=  
else e{To&gy~  
kn+`2-0  
return false; jl3RE|M\<  
;OPzT9  
} ws?p2$Cla  
}(op;7  
else sb4r\[?  
b=K    
return true; W zy8  
NkNw9?:#4  
} bi#o1jR  
o2a`4K  
} (d4zNYK  
 yZmQBh$  
$w+g%y)  
带body的tag [g&Q_+,j  
8* >6+"w  
RUX!(Xw  
tag处理类 h!yF   
qO&:J\d  
e3) rF5pp  
如果tag标签含有内容,那处理方式会略微有些不同,而且还要视tag处理类是否要与body交互的情况而定。如果要与body交互,那我们认为tag处理类要可能要对body进行操作。 C*kZ>mbc  
W`6nMFg  
Tag处理类不与body交互 78dmXOZ'_h  
.Pxb9mW  
如果tag处理类不与body交互,tag处理类应该实现Tag接口或从TagSupport中派生,如果body要被计算,那么doStartTag方法应返回 EVAL_BODY_INCLUDE,否则应返回SKIP_BODY。 JS({au  
*bmk(%g  
如果tag处理类要对body反复运算,则它应该实现IterationTag或从TagSupport中派生。如果tag处理类认为body还未计算完的话,那它的doStartTag方法和doAfterBody方法必须返回EVAL_BODY_AGAIN。 A){kitx-i)  
I0m/   
Tag处理类与body交互 /A|ofAr)  
"^22 Y}VB  
如果tag处理类与body交互,那tag处理类应实现BodyTag接口或从BodyTagSupport中派生。这种tag处理类一般要实现doInitBody和doAfterBody方法。 si3i#l&.b_  
qi7dcn@d  
Body允许一些方法来读写它的内容。Tag处理类可以调用body内容的getString或getReader方法来从body中提取信息,也可用 writeOut(out) 方法来将body的内容写入到out对象中。其中out对象通过tag处理类的getPreviousOut方法来获得。 ?#pL\1"E  
u"X8(\pOn  
如果body的内容需要被计算,那么doStartTag方法必须返回EVAL_BODY_BUFFERED,否则,它将返回 SKIP_BODY。 >@ h0@N  
(;~[}"  
doInitBody 方法 YCw^u  
MZv&$KG4m@  
此方法在body内容已经设好,但未被计算之前被调用。你可以根据不同的body内容来制定初始化策略。 t8]u#bx"?  
oo- ^BG  
doAfterBody方法 h-lMrI)U?h  
YDs/BF Z  
此方法在body内容已被计算后进行调用。 cS QUK  
WDE_"Mm  
和doStartTag方法一样,doAfterBody方法返回一个指示符指示是否要继续计算body,如果要继续计算,则doAfterBody应返回EVAL_BODY_BUFFERED,否则,它应返回SKIP_BODY。 cl:*Q{(Cjk  
AGK+~EjL@  
release 方法 g@B9i =  
#\%Gr tM  
tag处理类调用此方法将它的状态重置为初始状态,并释放所有的私有资源。 ^row=5]E  
,dZ 9=]  
3w!oJB  
以下的例子读取body的内容(其中含有一条sql语句),然后将它传递给一个对象,让它进行查询。由于此处body不须重新计算,所以doAfterBody会返回SKIP_BODY。 \&ERSk2  
GlQ=M ) E  
aH'^`]'_=  
Public class QueryTag extends BodyTagSupport /\ ~{  
V %Y.N4H  
{ Lm,io\z  
ax>en]rNP  
public int doAfterBody() throws JspTagException ]y-r I  
cpu+"/\  
{ >4LX!^V"  
I`Rxijz  
BodyContent bc = getBodyContent(); )bPNL$O  
u`E_Q8  
//将body的内容以字符串的格式提取出来 ^h^j:!76j  
+n2x@ 0op  
String query = bc.getString(); 9L!Vj J  
4.H!rkMM  
//清除body <XCH{Te1  
47$JN}qI0  
bc.clearBody(); >s[}f6*2@  
c{||l+B  
try{ mc!3FJ  
bTHJbpt*-  
Statement stmt = connection.createStatement(); GN=F-*2  
~;bwfp_  
Result result = stmt.executeQuery(query); w<\N-J|m  
dn%/SJC  
}catch(SQLException e){ bsqoR8  
Q6Jb]>g\H  
throw new JspTagException(“queryTag: “ + e.getMessage() ); G!0|ocE}  
O}#*U+j  
return SKIP_BODY; M 80Us.  
iDHmS6_c  
} RoJ&dK  
;#r tV;  
} `z+:Z>>  
 "thfd"-  
szmjp{g0  
body-content元素 Br-y`s~cP  
#cjB <APY  
#BT= K  
由于tag可能会有body,你必须用body-content元素来指定body内容的类型: UT[KwM{y  
JhB{aW>  
<body-content>JSP|tagdependent</body-content> {oz04KGsH  
v oC< /}E  
|mMW"(~  
如果body的内容是定制的或内部的tag、脚本元素、或HTML广本,则归类为JSP类型。其他的类型,比如上面代码所述的?D?D将sql statement类传给 query tag的这种类型应该标为tagdependent。 tkNuM0  
':.d,x)  
注意:实际上body-content的值并不影响tag处理类对body内容的处理,它仅仅是被tag编辑工具用来描述此body的内容。 qDcl;{L  
F\,3z7s  
Y`lC4*g  
用tags定义脚本变量 MzJ5_}  
"uZ'oN  
x6:$lZ(  
tag处理类 "* 'rzd  
w5qhKu!1  
v[ F_r  
tag处理类负责创建或设置页面中定义的脚本变量,用pageContext.setAttribute(name,value,scope)或pageContext.setAttribute(name,value)方法来实现。一般来说,tag处理类通过脚本变量的名称来获取它,脚本变量的名称一般可用get方法来获得。 {(xNC#   
1AoBsEnd  
如果脚本变量的值依赖于tag处理类中的上下文中某一对象,那它可用pageContext.getAttribute(name,scope)方法来找到那个对象。一般的处理过程是tag处理类先找到脚本变量,再对其进行处理,然后用pageContext.setAttribute(name,object)的方法来设置它的新值。 e^Jy-?E  
f"k/j?e*  
对象的生存周期(scope)如下表: j}0*`[c  
Nm\I_wjX  
对象的生存周期表 }=XL^a|V  
}o)GBWqHR  
名字 2Ybz`O!  
可访问范围 ,:=E+sS  
生存周期 ]!0*k#i_.  
=_ -@1 1a  
page 5%tIAbGW  
当前页面 nNBxT+3*i  
一直有效,除非页面向客户提交响应或重定向到一个新页面 KwpNS(]I  
atl0#FBd  
request IGv>0LOd@  
当前页面或当前页面重定向到的页面 V4V TP]'n  
一直有效,除非页面向客户提交响应 "8{u_+_B*  
I&>R]DV  
session iW)FjDTP  
当前页面或在同一浏览器窗口中的页面 vcV=9q8P1  
一直有效,除非关闭当前浏览器、超时、网络故障 Mc76)  
@iWIgL  
application Q#:,s8TW[  
整个web应用程序的所有请求 &Hh%pY"  
一直有效,除非发生网络故障、服务器故障 (`>4~?|+T  
27,WP-qie  
提供关于脚本变量的信息 ^f3F~XhY3  
/l:3* u  
以下示例定义了一个名为“book”的脚本变量,用来访问程序中关于书的信息: kFuaLEJi  
gI\J sN  
<bean:define id=”book” name=”bookDB” property=”bookDetails” type=”database.BookDetails” /> oleRQ=  
LX*T<|c`'  
<font color=”red” size=”+2” > `"-)ObOj}  
A!iV iX &y  
<%= messages.getString(“CartRemoved”) %> C7qbofoV  
of{wZU\J+9  
<strong><jsp:getProperty name=”book” property=”title” /></strong> L & PhABZ  
LuQ=i`eXx  
</font> /!7m@P|&D  
nM}X1^PiK"  
当包含此tag的JSP页面被编译时,jsp引擎会自动生成关于此book的同步的代码(同步可以避免几个客户同时访问此book时造成的冲突),要生成同步代码,jsp引擎需要知道此脚本变量的如下信息: #C !8a  
{u9VHAXCf  
· 脚本变量名称 V3I&0P k  
2psLX  
· 脚本变量所属的类 ,F:l?dfB\I  
qx`*]lX  
· 此脚本变量是否引用了一个新的或已存在的对象 ,Sz*]X  
J0|/g2%0  
· 此脚本变量的有效性 q/%f2U%4:  
.&}}ro48  
有两种办法可以向jsp引擎提供关于脚本变量的信息:在TLD中定义variable子元素,或用tei-class子元素定义一个额外tag信息类。用variable最简单,但可能降低了一些灵活性。 sfVtYIu  
Kr]F+erJe  
Variable元素 LvW9kL+WiQ  
$C^94$W  
Variable元素有如下子元素: S=M$g#X`5  
JNX7]j\  
· name-given ?D?D 给出的名字,是一个常量 "v ^Q !  
$i~DUT(  
· name-from-attribute?D?D 属性名,在编译时给出的属性名 Pf@8C{I  
i~l0XjQbs  
name-given或name-from-attribute两者必须选一,但以下子元素是可选的: $?;aW^E  
OZk(VMuI  
· variable-class?D?D变量的类型,缺省为java.lang.String。 8$3Tu "+;  
^pZ(^  
· declare?D?D此脚本变量是否引用了一个新对象,缺省为True。 C/ ;f)k<  
Y Xn)?  
· scope?D?D脚本变量的范围,缺省为NESTED。下表描述了scope的几种类型: VCvuZU{<  
4-cnkv\~  
脚本变量的有效范围 =I7#Vtd^K<  
M;3uG/E\  
O '$:wc#  
有效性 pD`7N<F 3  
方法 Ng+k{vAj  
v*]|1q%/  
NESTED 5=Gq d4&*  
在tag标签的开始和结束之间 =@{H7z(p&  
如果tag处理类实现BodyTag接口,则在doInitBody和doAfterBody中调用,否则在doStartTag中调用 = #ocp  
8 +uOYNXsA  
AT_BEGIN *^" 4 )  
从tag标签的开始一直到页面结束 fn;7Nf7{  
如果tag处理类实现BodyTag接口,则在doInitBody、doAfterBody和doEndTag中调用,否则在doStartTag和doEndTag中调用 ZJ+q<n_4}  
j.ANBE96>  
AT_END 3haY{CEr  
从tag标签的结束一直到页面结束 Pi)`[\{  
在doEndTag中调用 xN2{Vi{ad  
?c=l"\^x  
以struts为例,它的bean:define标签的实现遵循JSP1.1规范,此规范要求使用额外tag信息类来定义脚本变量。Variable元素是JSP1.2规范中加入的。以bean:define标签为例,你可以定义如下variable元素: f]o DZO%^  
9e8@0?0  
<tag> oa;[[2c  
=_L"x~0I-  
<variable> 1Qf5H!5vx  
Mgf80r=  
<name-from-attribute>id</name-from-attribute> &)\0mpLK9  
JJ7-$h'0q  
<variable-class>database.BookDetails</variable-class> <\Y>y+$3  
p~=%CG^5  
<declare>true</declare> 8(uxz84ce  
n;O 3.2  
<scope>AT_BEGIN</scope> DB%=/ \U  
3(vI{[yhT  
</variable> @c7 On)sy  
##R]$-<4dQ  
</tag> G^ n|9)CVW  
"o[\Aec:  
额外tag信息类 .;*0odxv  
i,* DWD+  
如果要定义一个额外tag信息类,你要继承javax.servlet.jsp.TagExtraInfo类。一个TagExtraInfo类必须实现getVariableInfo方法,此方法返回一个叫VariableInfo的数组类,它包括如下信息: > -k$:[l  
\ m 2[  
· 变量名 97$y,a{6  
ScM2_k`D  
· 变量所属类名 F"a,[i,[W  
1a#wUd3  
· 此变量是否引用了一个新对象 zPhNV8k-  
zif()i   
· 此变量的有效范围 CEI#x~Oq  
C5;"mo-  
jsp引擎将一个名为data的参数传给getVariableInfo方法,data中包括tag标签中的所有“属性名?D?D属性值”对。它可以用来向VariableInfo对象提供脚本变量的名字和类名。 7xWX:2l*?  
]iPTB  
以struts为例,它在bean:define标签中定义了一个名为DefineTei的额外tag信息类,用来向脚本变量提供信息。由于脚本变量的名称(book)和类名(database.BookDetails)是通过tag标签的属性来传递的,它们一般定义在VariableInfo的构建代码中,并且可用data.getAttributeString方法来得到这些信息。如果要允许book脚本变量能在从tag开始直到整个JSP页面结束的范围内都可用的话,那它的范围应设为AT_BEGIN。如下所示: ?uh7m 2l0D  
5+,&9;'Y^  
qK(? \ t$  
public class DefineTei extends TagExtraInfo S }fIZ1  
t {x&|%u  
{ M{hA`  
'4N[bRCn  
public VariableInfo[] getVariableInfo(TagData data)  (lt/ t  
 !X |Tf  
{ @bD,^3U  
^ "*r'  
String type = data.getAttributeString(“type”); sQTW?KA-Te  
NhpGa@[D  
If( type == null) B4U+q|OD#  
5r`g6@  
type = “java.lang.Object”; 5TzMv3;in2  
Av+R~&h  
return new VariableInfo[] { `?`\!uP"  
mxDy!:@=  
new VariableInfo(data.getAttributeString(“id”), INcJXlv  
U_oMR$/Z  
type, l_QpPo!a  
|bB..b  
true, 6VCw>x  
vgsu~(L;  
VariableInfo.AT_BEGIN) IvH0sS`F  
MPNBA1s  
}; bha_bj  
~Dgui/r9J  
} Sh{odrMj*  
|)GE7y0Q  
} P+oCcYp  
=}_c=z?UY  
|p3]9H  
注意:关于额外tag信息类的类名必须要在TLD中的tag标签下的tei-class子元素中定义。因此,DefineTei的tei-class中的定义看起来如下: /I".n]  
<tei-class> Neey myW  
org.apache.struts.taglib.bean.DefineTagTei sF(U?)48  
</tei-class> K;S&91V)=  
%~$4[,=  
ygT,I+7\  
具有协作关系的tag QWfwoe&;R:  
IKAF%0[R|j  
a08B8  
tag通过共享对象来进行协作,JSP技术支持2种方式的对象共享。 RC\TPG/8!  
*/?L_\7  
第一种方法是使用pageContext对象进行对象的共享(可支持JSP页面和tag处理类之间的共享),如果在一个tag处理类中要调用由另一个tag处理类创建的对象,可调用pageContext.getAttribute(name, scope)方法。 lzl4pnj  
gy~M]u{  
第二各方式的共享是对于tag之间有嵌套关系而言的,外层的tag所创建的对象对于内层的tag来说是可以共用的。这种形式的共享的好处是减少了可能存在的重名冲突。 WMl_$Fd6  
kZf7  
要访问一个嵌套tag创建的对象,tag处理类必须先找到此嵌套tag对象,可用TagSupport的静态方法 TagSupport.findAncestorWithClass(from, class)或TagSupport.getParent方法。前者在当不确定此tag是否为嵌套tag对象时使用。一旦它的父类被找到,它就能访问其所有动态或静态创建的对象。静态创建的对象是父类的成员,而动态创建的对象可能是父类的私有对象。诸如此类的对象可以用tag处理类的setValue方法来保存,用getValue方法来获得。 .r]n<  
/`2VJw  
下例阐述了以上两种共享对象的方法。在这个例子当中,一个查询tag检查一个名为connection的属性名是否在doStartTag中被设置。如果connection属性被设置,tag处理类从pageContext中得到这个connection对象。否则,此tag处理类先找到它的父tag处理类,然后从它的父tag处理类中找到connection对象。 $?I ^Dk  
LF{qI?LG  
`M"b L|[R  
public class QueryTag extends BodyTagSupport b\H(Lq17  
QT^( oog=  
{ [xM07%:  
QDxLy aL  
private String connectionId; h7(twct  
m0/J3  
public int doStartTag() throws JspException v  mw7H  
qY#*zx  
{ z,/dYvT<  
x7{,4js  
String cid = getConnection(); _%<7!|"  
8v(Xr}q,r  
if(cid != null) 8>O'_6Joj  
BWw7o{d  
{ BAqu@F\):  
r]8tl  
//存在一个connection id,使用它。 w )DO"Z7  
"D@m/l  
connection = (Connection) pageContext.getAttribute(cid); y]cx}9~  
EKwS~G.b!  
} '[Nu;(>a  
?Vt$  
else V 9=y@`;  
NP%ll e,l  
{ *7!}[ v_  
NW!e@;E+i  
ConnectionTag ancestorTag = (ConnectionTag)findAncestorWithClass(this, /R@(yT=t  
t@)~{W {  
ConnectionTag.class); H]@Zp"7  
7W}~c/%  
if(ancestorTag == null) S7N54X2JwL  
i.K}(bo;b  
{ /D)@y548~~  
,9W0fm \t  
throw new JspTagException(“一个没有connection属性的查询标签必须被一个connection标记嵌套。”); YXD1B`23  
n=hz7tjaz  
} 4.??U!r>KI  
~zYp(#0op  
connection = ancestorTag.getConnection(); p'xj:bB  
;Oe6SNquT  
} q+ )KY  
;5y!,OF6  
} Vvv -f  
r Ld,Izi  
} M c@p~5!M  
b\^Sz{  
XV+BSW7}  
"q]v2t  
此查询标签在JSP页面中的调用形式可以从以下2种定义中任选一种: fI}-?@  
s'LG3YV-<  
vz@QGgQ9~2  
<tt:connection id=”con01” ...> ... </tt:connection> JziMjR  
=E |[8 U)  
<tt:query id=”balances” connection=”con01” > H<1C5-  
#yU4X\oO  
SELECT account, balance FROM acct_table Xwx;m/  
q$EVd9aN  
where customer_num = <%= request.getCustno() %> ^!kv gm<{$  
$g 1p!  
</tt:query> nz>A\H  
,ew<T{PL  
CWC*bkd5a  
<u^41  
*NXwllrci  
<tt:connection ...> R` X$@iM  
av`b8cGg  
<x:query id=”balances”> x`B :M7+\  
b_wb!_  
SELECT account, balance FROM acct_table /~AwX8X  
P *%bG 4  
where customer_num = <%= request.getCustno() %> M{nz~W80  
4)XN1r:  
</x:query> E]ZM`bex&  
4J I;NN  
</tt:connection> x/9`2X`~  
ngdVRJL  
w#JF7;  
与此同时,在TLD中必须指定connection属性为可选的,定义如下: dC.uK^FuJ  
o'H$g%  
<tag> '{7A1yJnY%  
mTs[3opg  
... m{V @Om  
9k83wACry  
<attribute> 2;kab^iv'  
071w o7  
<name>connection</name> &/7GhZRt  
kdoE)C   
<required>false</required> IE,g  
_L: /2  
</attribute> xt3IR0  
w$& 10  
</tag>
描述
快速回复

您目前还是游客,请 登录注册
欢迎提供真实交流,考虑发帖者的感受
认证码:
验证问题:
10+5=?,请输入中文答案:十五