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

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

级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
标准的JSP 标记可以调用JavaBeans组件或者执行客户的请求,这大大降低了JSP开发的复杂度和维护量。JSP技术也允许你自定义taglib,其实换句话说,taglib可以看成是对JSP标记的一种扩展,正如xml是对html的一种扩展一样。taglib通常定义在tag标签库中,这种标签库存放着你自己定义的tag标签。简而言之,如果使用taglib,那么你可以设计自己的JSP标记! 8_/,`}9   
[*U.bRs  
一般来说,自定义tag标签主要用于操作隐藏对象、处理html提交表单、访问数据库或其它企业级的服务,诸如邮件和目录操作等等。自定义tag标签的使用者一般都是那些对java编程语言非常精通,而且对数据访问和企业级服务访问都非常熟悉的程序员,对于HTML设计者来说,使得他可以不去关注那些较复杂的商业逻辑,而将精力放在网页设计上。同时,它也将库开发者和库使用者进行合理分工,自定义tag标签将那些重复工作进行封装,从而大大提高了生产力,而且可以使得tag库可用于不同的项目中,完美地体现了软件复用的思想。 =z zmz7op  
`Z^\<{z  
在这篇文章中,我们主要讨论: LK+67Y{25  
@{{6Nd5  
· 什么是自定义tag标签? >S>B tR l  
tUi@'%>=5  
· 怎么使用tag标签? XaF;IS@A  
moRo>bvN~  
o 声明要使用的tag库 ?7uK:'8  
x %W%  
o 找到与之对应的tag处理类 X`28?  
Yk0/f|>O  
o tag标签的类型 +CN!3(r  
wvRwb   
· 自定义tag标签 hc*tQ2  
B?l 0u  
o tag处理类 C#n.hgo>I  
CsEU:v  
o tag库描述 Rxlz`&   
B#r"|x#[  
o tag标签示例 XtqhK"f%  
; )FmN[  
o 带属性的tag -"rANP-UI  
^hcK&  
o 带body的tag '^`iF,rg  
wZVLpF+7  
o 定义了脚本变量的tag XT?wCb41R  
Clb7=@f  
o 具有协作关系的tag Nq1YFI>W  
,P%i%YPj  
· 自定义tag标签 KM?w{ ~9  
-S#jOr  
o 一个迭代tag的例子 3_8W5J3I  
Qb|@DMq%  
o 一个模板tag库 .bUj  
YJ|U| [  
o tag处理类到底是怎样被调用的? p8FXlTk  
D$+g5u)  
4~1lP&  
什么是自定义的tag? 6^lix9q7  
0?cJ>)N  
一个自定义的tag标签是用户定义的一种JSP标记。当一个含有自定义的tag标签的JSP页面被jsp引擎编译成servlet时,tag标签被转化成了对一个称为tag处理类的对象进行的操作。于是当JSP页面被jsp引擎转化为servlet后,实际上tag标签被转化成为了对tag处理类的操作。 $,B;\PX  
q07H{{h/B  
自定义tag标签有很多特色,诸如: i*r ag0Mw  
Z*Rg ik  
· 可以在JSP页面中自定义tag标签的属性 N:;z~`  
.03Rp5+v  
· 访问JSP页面中的所有对象 tUt_Q;%yC  
p3>Md?e  
· 可以动态地修改页面输出 D#A6s32a  
TKQ^D  
· 彼此这间可以相互通信。你可以先创建一个JavaBeans组件,然后在一个tag中调用此JavaBeans组件,同时可以在另一个tag中调用它。 J9MAnYd)i  
Ym.{ {^=  
· tag允许相互嵌套,可以在一个JSP页面中完成一些复杂的交互。 {eVv%sbq  
`O5427Im  
-@ra~li,yQ  
使用tag标签 ^7a@?|,q8  
I^HwXp([  
$z`l{F4eMf  
本节主要描述怎样在JSP页面中使用tag标签,以及tag标签的不同类型。 "L!U7|9J  
'uF75C  
要使用tag标签,JSP程序员必须做2件事: B<ue}t  
> `mV^QD  
· 声明此tag标签的tag库 %=$Knc_!T^  
yy+:x/(N[  
· 实现此tag标签 &*74 5,e  
o=6 <?v7  
声明tag标签所在的tag库 e]5NA?2j  
^$X|Lq  
如果要使用tag标签,则应用JSP的taglib指示符来指定其tag库(注意:taglib要在在使用此tag标签之前声明) {u+=K-Bj  
[ . }Uzx  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> xz, o Mlw  
m>RtKCtP  
uri属性定义了唯一的标签库描述(以下简称TLD),它可以是直接是tld文件名或一个独一无二的名字。prefix是用来区别其它TLD中和本TLD中有重名的tag的一种手段。 `X)A$lLr  
[b_qC'K[  
TLD必须以.tld作为扩展名,并且存放在当前应用的WEB-INF目录或其子目录下。你可以通过它的文件名直接引用它,也可以通过别的方式间接地引用它。 o+.ySSBl+  
`F]  
以下taglib指示符直接引用一个TLD: pXvys] @  
nSRNd A  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> Zl{9G?abCT  
`sDLxgwI  
以下的taglib指示符通过一个逻辑名称间接地引用一个TLD: 2j#Dwa(lZQ  
@AM11v\:  
<%@ taglib uri=”/tutorial-template” prefix=”tt” %> OL%}C*Zq  
G4rzx%W?  
如果是间接引用TLD的话,那你必须还要在web.xml中定义此逻辑名称与tld文件之间的映射,具体做法是在web.xml中加入一个名为taglib的元素: hiEYIx  
PT }J.Dwx  
<taglib> @;x*~0GZ  
!8D>Bczq)  
<taglib-uri>/tutorial-template</taglib-uri> 7&D)+{g  
CO9PQ`9+  
<taglib-location> c2Exga_  
) iZU\2L  
/WEB-INF/tutorial-template.tld c&N;r|N  
IRueq @4  
</taglib-location> g5RH:]DV  
V]GF53D  
</taglib> ^tjw }sE  
! ,{zDMA  
S^;;\0#NK  
实现此tag标签 bWSc&/ 9y  
9 )!}  
|28'<BL  
为了实现tag标签,你有2种方法来存放tag处理类。一、让tag处理类以.class的方式存放于当前应用的WEB-INF/class子目录下,二、如果tag处理类是以JAR包的形式存在的话,那可以放在当前应用的WEB-INF/lib目录下,如果tag处理类要在多个应用中共享,那么它就应放在jsp服务器上的common/lib目录下,对于tomcat来说,就是tomcat/common/lib目录下。 ,i Y:#E  
[$pb  
jD%|@ux  
tag标签类型 |>[qC O  
CyS %11L  
H%etYpD  
自定义的tag标签遵循XML语法。它有一个开始标记和一个结束标记,有的还有body(即文本节点): G0~Z|P  
99(@O,*(Y  
<tt:tag> H=\Tse_.  
?@7!D8$9  
body ijUu{PG`X  
tTF<DD}8  
</tt:tag> <h;_:  
{}rnn$HQe  
5Zd oem  
一个不带body的tag标签如下: FJ4,|x3v[x  
N  /'  
<tt:tag /> .ZV='i()X  
Srz8sm;  
sp MYn&p  
简单的tag标签 q |FOU  
}+bo?~2E&  
一个没有body和属性的tag标签如下: dJ#go*Gn  
O9E:QN<U`*  
<tt:simple /> LokH4A17U  
J3~%9MCJ  
RwYFBc  
带属性的tag标签 ?{jey_]M  
&3;"$P  
#oFyi @U  
自定义标签可以有自己的属性。属性一般在开始标记中定义,语法为 attr=”value”。属性的作用相当于自定义标签的一个参数,它影响着tag处理类的行为。你可以在TLD中详细定义它。 YM6 J:89  
4c95G^dZ  
你可以用一个String常量给一个属性赋值,也可以通过表达式给它赋值,如<%= ...%>。以struts为例,它的logic:present标签就是用的String常量来给属性赋值: UCK;?]  
0[M2LF!m  
<loglic:present parameter = “Clear”> =[&+R9s  
6)*B%$?x  
而另一个标签logic:iterate是用表达式来给属性赋值: o ABrhK  
_)~1'tCs}h  
<logci:iterate collection=”<%= bookDB.getBooks() %>” F'sX ^/;  
]uMZvAjb  
id=”book” type=”database.BookDetails”> dP +wcl4  
U#]J5'i  
,|3_@tUl  
带body的tag标签 ?o$ t{AQ  
OzD\* ,{7  
一个自定义标签可以包含其它自定义标签、脚本变量、HTML标记或其它内容。 >j3':>\U  
7}y@VO6]  
在下述例子中,此JSP页面使用了struts的logic:present标签,如果些标签定义了parameter=”Clear”的属性,则将清除购物车的内容,然后打印出一条信息: 6wj o:I  
9(O eH7  
<logic:present parameter=”Clear”> d(TN(6g@  
B@NBN&Fr  
<% cart.clear(); %> h#KSKKNW  
bmK  
<font color=”#ff0000” size=”+2”><strong> 4L ]4WVc  
`GW&*[.7  
你选择了清除购物车! |59)6/i  
sNcU>qjj6  
</strong></font> p JT)X8K"  
/]'&cD 1  
</logic:present> od5nRb  
m;\nMdn  
\#LDX,=  
到底是用属性还是用body来传递信息? rab$[?]  
fP5i3[T  
如上所述,我们既可以通过属性,也可以通过body来传递信息。但一般来说,比较简单的类型,如字符串或简单表达式最好采用属性来传递信息。 5>+@.hPX  
TfT^.p*  
r~YBj>}  
定义脚本变量的tag标签 }$ySZa9  
.r{t&HO;Y  
所谓脚本变量,是指JSP中可以调用的变量或对象。它可由tag标签产生。以下示例阐述了一个tag标签定义了一个名为tx的由JNDI所定义的事务处理对象。脚本变量可以是ejb对象、事务、数据库连接等等: -j]c(Q MA]  
TWGn: mi  
<tt:lookup id=”tx” type=”UserTransaction” name=”java:comp/UserTransaction” /> 3<"j/9;K'  
@&`^#pok  
<% tx.begin(); %> i&^JG/a  
0kj5r*qA  
... ,[6Rmsk  
)W>$_QxbN  
T#i;=NP"  
具有协作关系的tag标签 x {Utf$|  
yP"}(!~m  
自定义tag标签之间可以通过共享对象来实现协作。在下述例子中,标签tag1创建了一个名为obj1的对象,在标签tag2仍可以重复使用obj。 |;xEK nF  
JbL3/h]  
<tt:tag1 attr1=”obj1” value1=”value” /> &9)/"  
v%AepK&  
<tt:tag2 attr1=”obj1” /> 5,s@K>9l;  
F-rhxJd  
在以下这个例子当中,如果外层的tag标签创建了一个对象,那么其内层的所有tag标签都可以使用这个对象。由于这样产生的对象没有一个指定的名字,那么就可以将少重名的冲突。这个例子阐述了一系列协作的嵌套对象。 ZD'mwj+K  
`h'l"3l  
<tt:outerTag> )^ZC'[93  
K>e-IxA);0  
<tt:innerTag /> >6jal?4u-  
@s cn ?t  
</tt:outerTag> k{#k:  
)Z1&`rv  
$Wj{B@k  
Tag处理类 _AX,}9  
T9& {s-3*  
}T(=tfv@  
Tag处理类必须实现Tag接口或BodyTag接口,不过现在一般都流行从TagSupport或BodyTagSupport类中继承,这些类或接口都可以在javax.servlet.jsp.tagext包中找到。 ~!~i_L\V  
%(p9AE  
当JSP引擎看到自己的JSP页面中包含有tag标签时,它会调用doStartTag方法来处理tag标签的开头,调用doEndTag方法来处理tag标签的结束。 `ovMfL.u  
KJ32L  
下表说明不同类型的tag所需要不同的处理过程: l7jen=(Zb;  
tc[Ld#  
Tag处理类的方法 H`fJ< So?  
}|2A6^FH.  
Tag标签类型 PN?;\k)"  
所调用的方法 COu5Tu^  
YW6a?f^!  
基本标签 RV_I&HD!  
doStartTag, doEndTag, release <=GZm}/]N  
Pg:xC9w4  
带属性的标签 &z40l['4bz  
doStartTag, doEndTag, set/getAttribute1...N, release 4gC(zJ  
@O'NJh{D`  
带内容的标签 U)Hc 7% e  
doStartTag, doEndTag, release X>yDj]*4P  
(wq8[1Wzup  
带内容的标签,且内容重复循环 #<"od'{U  
doStartTag, doAfterBody, doEndTag, release n nAtXVy  
035jU'  
带内容的标签,且内容与JSP交互 YR0AI l:L  
doStartTag, doEndTag, release, doInitBody, doAfterBody, release o*/;Zp==  
7F0J*M  
一个tag处理类可以通过javax.servlet.jsp.PageContext来与JSP交互,通过javax.servlet.jsp.PageContext类,tag处理类可以访问JSP中的request、session和application对像。 ,'HjL:r  
RHn3\N  
如果tag标签是互相嵌套的,那内层的tag处理类可以通过它的parent属性来访问上层的tag处理类。 M0xhcU_  
G.<0^q,  
一般情况都将所有的tag处理类打成了JAR的包,以便于发布。 LYL_Ah'=  
M>m!\bb%.  
[pEb`s  
Tag库描述(简称TLD) Vdx o  
`r-Jy{!y4  
v JGH8$%;,  
Tag库是用xml语言描述的,TLD包括了tag库中所有tag标签的描述,它一般用来被jsp服务器用来校验tag的语法正确性,或者被jsp开发者用来开发新的标签。 /huh}&NNu  
FCEmg0qdjD  
TLD的文件扩展名必须为.tld,而且必须放在当前WEB应用的WEB-INF目录或其子目录中。 C F','gPnc  
BK4S$B  
一个TLD的内容的开头必须遵守标准的XML开头,用于描述DTD和xml的版本,例如: z"yW):X  
=cS5f#0  
<?xml version="1.0" encoding="ISO-8859-1" ?> 1c#\CO1l  
9#P~cW?  
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd"> y7:f^4  
TLD必须以<taglib>来作为它的根元素,<taglib>的子元素如下表: n.8870.BW  
ejyx[CF  
9q$^x/z!  
<taglib>的子元素 I*Dj@f`  
As>Og  
Element 8CRbo24"s  
Description h7fytO  
|3E|VGm~  
tlib-version //|B?4kk  
Tag库的版本 ElpZzGj+  
x3FB`3y~s  
jsp-version r2+ZxMo|  
Tag库所需要的jsp的版本 Z T*}KJm  
b j@R[!ss  
short-name ?+7~ E8  
助记符,tag的一个别名(可选) S@3`H8 [  
n:wAxU  
uri o96c`a u  
用于确定一个唯一的tag库 de2G"'F  
fi>.X99(G  
display-name 7Ko*`-p  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) P.q7rk<  
dtY8>klI  
small-icon +u=VO#IA#  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) ?'a>?al%>  
]!^wB 3j  
large-icon "@ ^<~bw  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) -QJ8\/1>  
j*|0#q;e6  
description Mx6 yk,  
对tag库的描述(可选) =|Qxv`S1  
4Ol1T(J#  
listener mD% qDKI  
参见下面listener元素 LlgFQfu8  
. G25D  
tag w=!xTA  
参见下面tag 元素 m?yztm~u  
--"5yGOL  
Listener元素 [^}bc-9?i  
8$]SvfX  
一个tag库可能定义一些类做为它的事件侦听类,这些类在TLD中被称为listener 元素,jsp服务器将会实例化这些侦听类,并且注册它们。Listener元素中有一个叫listener-class的子元素,这个元素的值必须是该侦听类的完整类名。 _u6N aB  
Q%q;=a  
Tag元素 9]ZfSn)  
(-0d@eqw  
每个tag元素在tag库中都要指出它的名字、类名、脚本变量、tag的属性。其中脚本变量的值可以直接在TLD中定义或通过tag附加信息的类来取得。每个属性描述了这个属性是否可以省略,它的值是否可以通过<%= …%>这样的JSP语法来获得,以及属性的类型。 :}fA98S  
(D?4*9 =  
每一个tag在TLD中对应一个tag元素,下表是tag元素的子元素: }z/%b<o_  
hNYO+LrI)  
Tag元素的子元素 zQ,M795@EA  
I>l^lv&[+  
元素名称 Lz_.m  
描述 BjPU@rS .U  
jf1GYwuW*  
name PE6,9i0ee  
独一无二的元素名 /^jl||'H,:  
:oW 16m1`  
tag-class XSN=0N!GB  
Tag标签对应的tag处理类 P8h|2,c%  
JBHPI@Qt%  
tei-class XaE*$:   
javax.servlet.jsp.tagext.TagExtraInfo的子类,用于表达脚本变量(可选) H)Me!^@[D  
'j{o!T0  
body-content p ]jLs|tat  
Tag标签body的类型 n05GM.|*s  
A9]& w  
display-name \}n_Sk  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) 4noy!h  
.Ow8C  
small-icon W+8s>  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) r7V !M1  
-{Ar5) ?='  
large-icon GSSmlJ`  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) di+ |` O  
9^H.[t  
description Iy;"ht6  
此tag标签的描述 PU%f`)  
*PFQ  
variable %zY5'$v `  
提供脚本变量的信息(同tei-class)(可选) fD\Fq'29{  
#/H2p`5  
attribute |Bi7:w  
Tag标签的属性名 BUsxgs"),  
x%ccNP0  
以下章节介绍对于不同类型的tag,如何具体地实现它们。 -~JYfj@  
nvwf!iU6  
8BZ&-j{  
简单的tag OJA_OqVp$K  
j$s/YI:  
j$ lf>.[I  
tag处理类 WPpO(@sn  
Y d~J(  
简单的tag处理类必须实现Tag接口的doStartTag和doEndTag方法。当jsp引擎碰到tag标签的开头时,doStartTag被调用,因为简单的tag没有body,所以此方法将返回 SKIP_BODY。当jsp引擎碰到tag标签的结尾时,doEndTag被调用,如果余下的页面还要被计算,那它将返回EVAL_PAGE,否则将会返回SKIP_PAGE。 8_Uh h5[  
Qa:[iF  
以下是例子:对于标签 <tt:simple /> ,它的tag处理类实现如下: -O1$jBQ S  
]n"RPktx  
"LkBN0D  
public SimpleTag extends TagSupport Nr*X1lJ6  
w?8\9\ ;?  
{ 2v@B7r4}  
] `q]n  
public int doStartTag() throws JspException kMLJa=]$  
tEo-Mj5:  
{ n`w]?bL  
Pe\Obd8d  
try{ 2T?Y  
A*/8j\{n  
pageContext.getOut().print(“Hello.”); LxWd_B  
c1a$J`  
}catch(Exception e){ YIgHLM(  
\ %MsG  
throw new JspTagException(“SimpleTag: “ + e.getMessage()); b]xoXC6@t  
>O rIY  
} dcq18~  
`s UY$Q  
return SKIP_BODY; ^LB]  
(.Ak*  
}  CDuA2e  
*pnaj\  
public int doEndTag() Uz rf,I[  
6L\]Ee  
{ zd!%7 UP  
EVaHb;  
return EVAL_PAGE; K*,,j\Q.  
),Yk53G6c  
} P?|\Ig1Gk  
gzat!>*  
} , #GB  
"zXrfn  
{n|Uf 5  
注意:如果tag标签没有内容的话,那必须定义body-content元素为空,例如 &&LB0vH!J  
ir{ 4k  
<body-content>empty</body-content> H7Z`aQC  
{ 29aNm  
/#@tv~Z^  
带属性的tag标签
评价一下你浏览此帖子的感受

精彩

感动

搞笑

开心

愤怒

无聊

灌水
级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
只看该作者 1 发表于: 2007-01-01
tag处理类 NR8`nc1~  
ZS]Z0iZv9  
对于tag标签的每个属性,你必须依照JavaBeans规范来定义其属性,以及get和set方法。以struts的logic:present 标签为例, a:HN#P)12  
mDbTOtD  
<logic:present parameter=”Clear”> z9OpxW@Ou  
>!']w{G  
与此相应,此tag处理类应有如下方法和定义: +O9x8OPHW  
ZbdGI@  
>D~8iuy]8.  
protected String parameter = null; h2Th)&Fb>  
&^HVuYa.0  
public String getParameter() 0pEM0M  
(&v|,.c^)1  
{ nIfAG^?|*  
F |5Au>t  
return this.parameter; S|LY U!IWZ  
$^?VyHXvY  
} p19@to5l  
r`EjD}2d  
public void setParameter(String parameter) >s"/uo  
fvi0gE@bd  
{ 6\K\d_x  
h:?qd  
this.parameter = parameter; );t+~YPS  
CqZHs 9+e&  
} ]plp.f#av  
Ab j7  
</xf4.C  
注意:如果你的属性名为id,而且你的tag处理类是从TagSupport类继承的,那你就不需要定义它的属性和set和get方法,因为他们早已在TagSupport被定义过了。 EleJ$ `/  
,>kVVpu  
Attribute元素 1%N*GJlwJ  
'OP0#`6`  
对于tag标签的每个属性,你必须定义它是否必须的,它的值是否可以用诸如<%= …%>的表达式来获得,以及它的类型(可选),如果不指定它的类型,那就默认为是java.lang.String类型。如果rtexprvalue元素被定义为true或yes,那么在type元素中就定义了attribute的返回类型。 4Nt4(3Kf  
V!^0E.?a  
<attribute> ."B{U_P&  
&<uLr *+*  
<name>attr1</name> ~ @xPoD&  
>,3uu}s  
<required>true|false|yes|no</required> to&,d`k=-  
{!qnHv\S  
<rtexprvalue>true|false|yes|no</rtexprvalue> ~;Y Tz  
$)o0{HsL+  
<type>attribute的返回类型(只用当rtexprvalue为真是才有效)</type> qT5"r488  
,&M#[>\(3  
</attribute> wi jO2F  
+ls`;f  
如果tag的某个属性不是必须的,那tag处理类会自动提供一个缺省值。 g9VY{[ V  
g\.$4N  
例如,在logic:present这个tag标签中定义了一个属性叫parameter,但它不是必须的,而且它可以被诸如<%= …%>的表达式来赋值。 ,3f>-mP  
GCO: !,1  
<tag> `<>QKpAn  
kI@<H<  
<name>present</name> IHd W!q  
C:5d/9k  
<tag-class>org.apache.struts.taglib.logic.PresentTag</tag-class> K#X/j'$^  
v)_FiY QQ6  
<body-content>JSP</body-content> ?(d1;/0v>  
Y.Z:H!P);$  
… mS![J69(  
{xov8 M  
<attribute> #m?)XB^_  
5toa@#Bc%  
<name>parameter</name> AL3iNkEa  
J9]cs?`)  
<required>false</required> <anKw|  
"H`Be  
<rtexprvalue>true</rtexprvalue> Z10}xqi!X  
*DfOm`m  
</attribute> dr=Q9%  
Rb:<?&7ZzN  
… u|Mx}  
81s }4  
</tag> fDqT7}L  
]2)A/fOW  
JVy|SA&R  
属性元素的校验 0<~~0US  
?-mOAHW0q  
\ DZ.#=d  
有关于tag标签的有效值可以从tag库的说明文档中获得,当JSP页面被编译时,jsp引擎会强制性地参照TLD中定义的规则进行检查。 $'Mf$h  
;2 &"  
还有一个方法也可以进行属性元素的校验,就是先继承类TagExtraInfo,然后调用它的isValid方法。这个类同时也起到提供tag中定义的脚本变量信息的作用。 breF,d$  
LAf#Rco4  
IsValid方法通过TagData对象来传递属性信息,它包括着tag的所有的属性名-值的信息。由于校验发生在运行时刻,因此这个属性的值将被赋值为TagData.REQUEST_TIME_VALUE。 *OFG3uM  
&U|c=$!\  
例如tag标签<tt:twa attr1=”value1” />在TLD中定义如下: 3lpxh_  
ll X `  
<attribute> _Wg}#r  
4^2>K C_  
<name>attr1</name> Q9O_>mZy  
C2v_] ,]  
<required>true</required> !.mR]El{K  
4l %W]'  
<rtexprvalue>true</rtexprvalue> ~Y CH5,  
o68i0aFW  
</attribute> T pF [-fO  
DWKQ>X6  
xLoQ0rt 6  
这个定义说明了attr1能在运行期间被赋值。 X7L:cVBg  
[I4M K%YQ  
以下的isValid方法检查attr1属性的值是否属于Boolean类型。注意由于attr1能在运行刻被赋值,那么isValid方法必须检查tag用户是否对此tag进行了运行时刻赋值。 KU` *LB:  
T&]-p:mg^  
|JYb4J4Ni  
Public class TwaTEI extends TagExtraInfo 6 V0Ayxg7  
JJ?rVq1g  
{ j;coPehB  
..u{v}4&  
public boolean isValid(Tagdata data) \uPzj_kU6  
7mMGH(  
{ "*t6KXVaM  
uWdF7|PN7  
Object o = data.getAttribute(“attr1”); 04|ZwX$>+  
<.4(#Ebd  
If(o != null && o != TagData.REQUEST_TIME_VALUE) 0N>K4ho6{  
zQY ,}a  
{ ~CnnN[g(_  
g_syGQ\  
if( ( (String)o).toLowerCase().equals(“true”) || ")uKDq  
9!Mh (KtQ  
((String)o).toLowerCase().equals(“false”) ) (=7"zE Cq#  
j%nN*ms  
return true; f- 9t  
2n@`O g_0  
else [//i "Nm  
CipDeqau2  
return false; t7F0[E'=5\  
+X^GS^mz  
} W$zRUG-  
xo'!$a}I2  
else B0Wf$ s^7t  
v~L\[&|_  
return true; FJ~d&L\l  
/&#y-D_  
} nahq O|~  
AtCT  
} `3T=z{HR9g  
f't.?M  
4}; @QFT*  
带body的tag SQcic]Ep  
t(*n[7e  
6Oy:5Ps8a  
tag处理类 6;'[v}O^^  
?(=|!`IoO  
:gwmk9LZ  
如果tag标签含有内容,那处理方式会略微有些不同,而且还要视tag处理类是否要与body交互的情况而定。如果要与body交互,那我们认为tag处理类要可能要对body进行操作。 oa"Bpi9i  
I8J>>H'#A  
Tag处理类不与body交互 +S(# 7  
3/n?g7B  
如果tag处理类不与body交互,tag处理类应该实现Tag接口或从TagSupport中派生,如果body要被计算,那么doStartTag方法应返回 EVAL_BODY_INCLUDE,否则应返回SKIP_BODY。 ?Xypn#OPt  
Y`ip. Nx  
如果tag处理类要对body反复运算,则它应该实现IterationTag或从TagSupport中派生。如果tag处理类认为body还未计算完的话,那它的doStartTag方法和doAfterBody方法必须返回EVAL_BODY_AGAIN。 u$%C`v>  
%MHL@Nn>e  
Tag处理类与body交互 c%doNY9Q  
8+oc4~!A@n  
如果tag处理类与body交互,那tag处理类应实现BodyTag接口或从BodyTagSupport中派生。这种tag处理类一般要实现doInitBody和doAfterBody方法。 % E1r{`p  
Ly2,*\7  
Body允许一些方法来读写它的内容。Tag处理类可以调用body内容的getString或getReader方法来从body中提取信息,也可用 writeOut(out) 方法来将body的内容写入到out对象中。其中out对象通过tag处理类的getPreviousOut方法来获得。  : Z<\R0  
PDD2ouv4  
如果body的内容需要被计算,那么doStartTag方法必须返回EVAL_BODY_BUFFERED,否则,它将返回 SKIP_BODY。 }}TPu8Rl  
/8qR7Z^HZ  
doInitBody 方法 Wu$ryX  
Z. gb'  
此方法在body内容已经设好,但未被计算之前被调用。你可以根据不同的body内容来制定初始化策略。 EWDsBNZaI  
PM[W7g T  
doAfterBody方法 j? BL8E'   
" C0dZ  
此方法在body内容已被计算后进行调用。 *g+ ZXB  
?`?Tg&W  
和doStartTag方法一样,doAfterBody方法返回一个指示符指示是否要继续计算body,如果要继续计算,则doAfterBody应返回EVAL_BODY_BUFFERED,否则,它应返回SKIP_BODY。 i;%G Z8  
! I?C8)  
release 方法 2: gh q  
ivo><"Y(r  
tag处理类调用此方法将它的状态重置为初始状态,并释放所有的私有资源。 M 8WjqTq  
RG45S0Ygj  
lF(v<drkB  
以下的例子读取body的内容(其中含有一条sql语句),然后将它传递给一个对象,让它进行查询。由于此处body不须重新计算,所以doAfterBody会返回SKIP_BODY。 }XBF#BN  
9y6u&!PZ\  
LD[\eJ _  
Public class QueryTag extends BodyTagSupport GW>F:<p  
&qXobJRM  
{ =H;n$ -P  
d {U%q d  
public int doAfterBody() throws JspTagException +&G(AW  
|"LHo  H  
{ fU$Jh/#":  
P I"KY@>H  
BodyContent bc = getBodyContent(); G]aey>)  
W'vekuM  
//将body的内容以字符串的格式提取出来 $||WI}k3V  
p4z4[=-:  
String query = bc.getString(); *]yrN`  
_\+]/rY9o  
//清除body UiV#w#&P  
KU$,{Sn6@  
bc.clearBody(); 3<XuJ1V&  
"7%jv[  
try{ BT [|f[1  
L-?ty@-i  
Statement stmt = connection.createStatement(); Cty{   
*Ze0V9$'  
Result result = stmt.executeQuery(query); )KFxtM-  
||X3g"2W9  
}catch(SQLException e){ kBk>1jn"  
s*g qKQ;  
throw new JspTagException(“queryTag: “ + e.getMessage() ); HQ"T>xb  
'm*W<  
return SKIP_BODY; pl r@  
Gz{%Z$A~o  
} kB@gy}  
Lm}.+.O~d  
} ?=Ceo#Er  
_$$.5?4  
}w4OCN\1  
body-content元素 )=GPhC/sw  
#^VZJ:2=|  
@* vVc`;  
由于tag可能会有body,你必须用body-content元素来指定body内容的类型: &Pme4IHtm  
~vDa2D<9%  
<body-content>JSP|tagdependent</body-content> {c)\}s(}F  
V $I8iVGL  
%( 7##f_  
如果body的内容是定制的或内部的tag、脚本元素、或HTML广本,则归类为JSP类型。其他的类型,比如上面代码所述的?D?D将sql statement类传给 query tag的这种类型应该标为tagdependent。 Mu/(Xp62  
:u9'ZHkZ  
注意:实际上body-content的值并不影响tag处理类对body内容的处理,它仅仅是被tag编辑工具用来描述此body的内容。 DQ+6VPc^o  
\l(J6Tu  
8zeeC eIU  
用tags定义脚本变量 P0>2}/;o  
+:^l|6%}  
'v<v6vs  
tag处理类 tUH?N/qn  
T=YVG@fm?  
'9u?lA^9$  
tag处理类负责创建或设置页面中定义的脚本变量,用pageContext.setAttribute(name,value,scope)或pageContext.setAttribute(name,value)方法来实现。一般来说,tag处理类通过脚本变量的名称来获取它,脚本变量的名称一般可用get方法来获得。 H'#06zP>5  
h9 DUS,G9,  
如果脚本变量的值依赖于tag处理类中的上下文中某一对象,那它可用pageContext.getAttribute(name,scope)方法来找到那个对象。一般的处理过程是tag处理类先找到脚本变量,再对其进行处理,然后用pageContext.setAttribute(name,object)的方法来设置它的新值。 {K+f& 75  
| U0s1f  
对象的生存周期(scope)如下表: DQK?y=vf  
[(Z(8{3i  
对象的生存周期表 ^=^\=9" b  
KJyCfMH&:@  
名字 q n-f&R  
可访问范围 e bp t/q[  
生存周期 oQ -m  
"[7-1}l  
page mmJnE  
当前页面 O'(Us!aq  
一直有效,除非页面向客户提交响应或重定向到一个新页面 ( gg )?  
AJB NM  
request sm'_0EUg  
当前页面或当前页面重定向到的页面 j=T8 b  
一直有效,除非页面向客户提交响应 bDl#806PL  
iwM xTty  
session A'`F Rx(  
当前页面或在同一浏览器窗口中的页面 =| T^)J  
一直有效,除非关闭当前浏览器、超时、网络故障 mOj; 0 R  
tgG 8pL  
application !dwZ`D  
整个web应用程序的所有请求 P6kD tUXF  
一直有效,除非发生网络故障、服务器故障 h=`$ec  
kP$ E+L  
提供关于脚本变量的信息 ',g%L_8Sq  
C~4SPCU  
以下示例定义了一个名为“book”的脚本变量,用来访问程序中关于书的信息: E0RqY3  
{Ni]S$7  
<bean:define id=”book” name=”bookDB” property=”bookDetails” type=”database.BookDetails” /> Ojz'p5d`>  
3m75mny  
<font color=”red” size=”+2” > (" :Dz_  
`Gv\"|Gn  
<%= messages.getString(“CartRemoved”) %> N9|J\;fzT  
V~*>/2+  
<strong><jsp:getProperty name=”book” property=”title” /></strong> n[e C  
ynM:]*~K  
</font> \h3HaNC  
y}oA!<#3  
当包含此tag的JSP页面被编译时,jsp引擎会自动生成关于此book的同步的代码(同步可以避免几个客户同时访问此book时造成的冲突),要生成同步代码,jsp引擎需要知道此脚本变量的如下信息: *K_8=TIA*  
0IqGy}+VU  
· 脚本变量名称 d6*84'|!  
U - OD  
· 脚本变量所属的类 -V;Y4,:c  
ox`Zs2-a  
· 此脚本变量是否引用了一个新的或已存在的对象 ppn  8  
&4evh<z  
· 此脚本变量的有效性 }v}F8}4  
er24}G8  
有两种办法可以向jsp引擎提供关于脚本变量的信息:在TLD中定义variable子元素,或用tei-class子元素定义一个额外tag信息类。用variable最简单,但可能降低了一些灵活性。 ?" 4X&6xl  
>)C7IQ/  
Variable元素 xltN-<n7  
bL* b>R[x  
Variable元素有如下子元素: r e zp7  
&&l ZUR,`  
· name-given ?D?D 给出的名字,是一个常量 *cM=>3ws/  
uQH]  
· name-from-attribute?D?D 属性名,在编译时给出的属性名 {+#{Cha  
i|z=WnF$&  
name-given或name-from-attribute两者必须选一,但以下子元素是可选的: &)6}.$`  
2?%4|@*H?  
· variable-class?D?D变量的类型,缺省为java.lang.String。 jj2=|)w$3  
U[3w9  
· declare?D?D此脚本变量是否引用了一个新对象,缺省为True。 =(hBgNH  
mD7NQ2:wA  
· scope?D?D脚本变量的范围,缺省为NESTED。下表描述了scope的几种类型: `AE6s.p?  
p5E okh  
脚本变量的有效范围 !yj1X Ar  
 ij:a+T  
值 `q]' ^EzJ  
有效性 @mZK[*Ak<*  
方法 nI?*[y}  
]tu OWR  
NESTED U/{t "e  
在tag标签的开始和结束之间 e@V J-s  
如果tag处理类实现BodyTag接口,则在doInitBody和doAfterBody中调用,否则在doStartTag中调用 |DW^bv  
BMO,eQcB  
AT_BEGIN jt}oq%Bf  
从tag标签的开始一直到页面结束 n:4 0T1: q  
如果tag处理类实现BodyTag接口,则在doInitBody、doAfterBody和doEndTag中调用,否则在doStartTag和doEndTag中调用 ,=CipL9]  
\?v&JmEU  
AT_END qspGNu  
从tag标签的结束一直到页面结束 6R^F^<<  
在doEndTag中调用 l-W)? d  
-w2^26 ax  
以struts为例,它的bean:define标签的实现遵循JSP1.1规范,此规范要求使用额外tag信息类来定义脚本变量。Variable元素是JSP1.2规范中加入的。以bean:define标签为例,你可以定义如下variable元素: {J1rjrPo  
TJRp/BP  
<tag> M:OZWYQ  
<-N eusx%  
<variable> 5P #._Em  
T_2'=7  
<name-from-attribute>id</name-from-attribute> 3(J>aQZuI  
vcy1itY  
<variable-class>database.BookDetails</variable-class> yx`@f8Kr  
='D%c^;O8'  
<declare>true</declare> bE% Hm!  
'X+aYF }Ye  
<scope>AT_BEGIN</scope> H#GR*4x  
pW8?EGO@  
</variable> -SD:G]un  
.(Ux1.0C  
</tag> >.P* lT  
qU6!vgM&  
额外tag信息类 gmu.8  
b/*QV0(  
如果要定义一个额外tag信息类,你要继承javax.servlet.jsp.TagExtraInfo类。一个TagExtraInfo类必须实现getVariableInfo方法,此方法返回一个叫VariableInfo的数组类,它包括如下信息: q*R~gEi#yk  
i/ o  
· 变量名 m`zd0IRTP  
w7~]c,$y.  
· 变量所属类名 OO/>}? ob  
zx "EAF{  
· 此变量是否引用了一个新对象 Bi fI.2|  
D_<B^3w )  
· 此变量的有效范围 m8L %!6o  
\4$Nx/@Q}  
jsp引擎将一个名为data的参数传给getVariableInfo方法,data中包括tag标签中的所有“属性名?D?D属性值”对。它可以用来向VariableInfo对象提供脚本变量的名字和类名。 ?~.9: 93  
E l.eK9L  
以struts为例,它在bean:define标签中定义了一个名为DefineTei的额外tag信息类,用来向脚本变量提供信息。由于脚本变量的名称(book)和类名(database.BookDetails)是通过tag标签的属性来传递的,它们一般定义在VariableInfo的构建代码中,并且可用data.getAttributeString方法来得到这些信息。如果要允许book脚本变量能在从tag开始直到整个JSP页面结束的范围内都可用的话,那它的范围应设为AT_BEGIN。如下所示: anz7ae&P'K  
zQ<&[Tuwa  
W'k&DKhTqF  
public class DefineTei extends TagExtraInfo 5[zr(FuE  
A<H]uQ>  
{ n}Thc6f3D  
Rq(+zL(f  
public VariableInfo[] getVariableInfo(TagData data) +>it u J  
;w%g*S  
{ q{*[uJ}Xc"  
<F_w4!  
String type = data.getAttributeString(“type”); P/~dY  
Th,]nVsGs~  
If( type == null) 0j;|IU\  
y'f-4E<  
type = “java.lang.Object”; uJ=&++[  
ArX*3  
return new VariableInfo[] { Jp)PKS ![  
=#TQXm']Gi  
new VariableInfo(data.getAttributeString(“id”), Jnt r"a-4  
tMf5TiWu@  
type, K'e!BZm6Q  
"[A&S!  
true, #9"lL1  
b N>Ar  
VariableInfo.AT_BEGIN) b2F1^]p  
%E, -dw  
}; 79Q,XRWh|  
3s:)CXO  
} 0~<t :q!  
Vas Q/  
} cv_O2Q4,@  
cP/(h  
ZMyd+C_P2  
注意:关于额外tag信息类的类名必须要在TLD中的tag标签下的tei-class子元素中定义。因此,DefineTei的tei-class中的定义看起来如下: %iV\nFal>  
<tei-class> $\4Or  
org.apache.struts.taglib.bean.DefineTagTei c$A}mL_  
</tei-class> e!i.u'z  
3joMtRB>;  
3_VWtGQ  
具有协作关系的tag #lVSQZO~a  
mn<ea&  
S!}pL8OE  
tag通过共享对象来进行协作,JSP技术支持2种方式的对象共享。 Dhg/>@tw  
Eh_[8:dK  
第一种方法是使用pageContext对象进行对象的共享(可支持JSP页面和tag处理类之间的共享),如果在一个tag处理类中要调用由另一个tag处理类创建的对象,可调用pageContext.getAttribute(name, scope)方法。 U/(R_U>=  
yCg>]6B  
第二各方式的共享是对于tag之间有嵌套关系而言的,外层的tag所创建的对象对于内层的tag来说是可以共用的。这种形式的共享的好处是减少了可能存在的重名冲突。 H<b4B$/  
4f0dc\$  
要访问一个嵌套tag创建的对象,tag处理类必须先找到此嵌套tag对象,可用TagSupport的静态方法 TagSupport.findAncestorWithClass(from, class)或TagSupport.getParent方法。前者在当不确定此tag是否为嵌套tag对象时使用。一旦它的父类被找到,它就能访问其所有动态或静态创建的对象。静态创建的对象是父类的成员,而动态创建的对象可能是父类的私有对象。诸如此类的对象可以用tag处理类的setValue方法来保存,用getValue方法来获得。 y7*^H  
BYS>"  
下例阐述了以上两种共享对象的方法。在这个例子当中,一个查询tag检查一个名为connection的属性名是否在doStartTag中被设置。如果connection属性被设置,tag处理类从pageContext中得到这个connection对象。否则,此tag处理类先找到它的父tag处理类,然后从它的父tag处理类中找到connection对象。 9*|An  
Ke&fTK  
\v9<L'NP)  
public class QueryTag extends BodyTagSupport e8]mdU{)  
H~*[v"  
{ &P8Q|A-u  
Y50$ 2%kM  
private String connectionId; `+r5I5  
]}0+7Q  
public int doStartTag() throws JspException 7xT<|3 I  
p@znmn-  
{ ^h|'\-d\  
n_] OYG>U  
String cid = getConnection(); |om3*]7  
~Uz|sQ*G  
if(cid != null) :TWHmxch  
}S&SL)  
{ X_|} b[b  
}fxH>79g  
//存在一个connection id,使用它。 ]gj@r[  
.^1=*j(;  
connection = (Connection) pageContext.getAttribute(cid);  6Ue6b$xE  
&9g#Vq%   
} *KV] MdS  
qdu:kA:]  
else 1-gX=8]]  
C{S6Ri  
{ ln!KL'T]  
7~`6~qg.  
ConnectionTag ancestorTag = (ConnectionTag)findAncestorWithClass(this, ae1fCw3k  
]R]X#jm  
ConnectionTag.class); ')FNudsC  
PwNLJj+%  
if(ancestorTag == null) q+G1#5  
vqxTf)ys  
{ n#]G!7  
-)<Nd:A  
throw new JspTagException(“一个没有connection属性的查询标签必须被一个connection标记嵌套。”); /ci.IT$Q^  
g-(xuR^*  
} G6Fg<g9:  
)5V1H WjU  
connection = ancestorTag.getConnection(); C ILk  
IX3U\_I#  
} x[oYN9O  
>"nk}@  
} j+ys&pDczm  
Y2D) $  
} 0.5_,an3  
tpctz~ .  
YD%Kd&es  
G#*;3X$  
此查询标签在JSP页面中的调用形式可以从以下2种定义中任选一种: PrcM'Q  
$p@g#3X`  
h^)2:0#{I  
<tt:connection id=”con01” ...> ... </tt:connection> dd+).*  
xVP GlU  
<tt:query id=”balances” connection=”con01” >  Ui.F<,E  
^eRuj)$5A  
SELECT account, balance FROM acct_table WveFB%@`;  
1,J.  
where customer_num = <%= request.getCustno() %> 1XKk~G"D  
Sm,$~~iq}  
</tt:query> xl^'U/  
ZjK~s)RC  
$} Myj'`r  
或 |+bG~~~%j  
.,,73"  
<tt:connection ...> .wSAysiQ|P  
2P}RZvUd  
<x:query id=”balances”> #wyS?FP-  
UTt#ltun?  
SELECT account, balance FROM acct_table Id0F2  [  
;a`X|N9  
where customer_num = <%= request.getCustno() %> ~83P09\T%  
bW]+Og  
</x:query> ;z>YwRV  
BTyVfq sx  
</tt:connection> `<n:D`{dZ  
`dZ|}4[1  
%r"GL  
与此同时,在TLD中必须指定connection属性为可选的,定义如下: Ah`dt8t  
4@I]PG  
<tag> EUkNh>U?  
=)8Ct  
... 68*{Lo?U  
:6+~"7T  
<attribute> u"jnEKN0y  
LayU)TIt  
<name>connection</name> 2cg z n@  
M)7enp) F.  
<required>false</required> V]}b3Y!(  
De_</1Au!2  
</attribute> as4NvZ@+r  
F?kVW[h?q  
</tag>
描述
快速回复

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