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

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

级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
标准的JSP 标记可以调用JavaBeans组件或者执行客户的请求,这大大降低了JSP开发的复杂度和维护量。JSP技术也允许你自定义taglib,其实换句话说,taglib可以看成是对JSP标记的一种扩展,正如xml是对html的一种扩展一样。taglib通常定义在tag标签库中,这种标签库存放着你自己定义的tag标签。简而言之,如果使用taglib,那么你可以设计自己的JSP标记! W6Mq:?+D  
pI:,Lt1B  
一般来说,自定义tag标签主要用于操作隐藏对象、处理html提交表单、访问数据库或其它企业级的服务,诸如邮件和目录操作等等。自定义tag标签的使用者一般都是那些对java编程语言非常精通,而且对数据访问和企业级服务访问都非常熟悉的程序员,对于HTML设计者来说,使得他可以不去关注那些较复杂的商业逻辑,而将精力放在网页设计上。同时,它也将库开发者和库使用者进行合理分工,自定义tag标签将那些重复工作进行封装,从而大大提高了生产力,而且可以使得tag库可用于不同的项目中,完美地体现了软件复用的思想。 ~nTj't2R  
kU+|QBA@  
在这篇文章中,我们主要讨论: L R\LC6kM  
pCDN9*0/  
· 什么是自定义tag标签? gW,hI>  
x_ /}R3d  
· 怎么使用tag标签? n1JtY75#,/  
tYXE$ i  
o 声明要使用的tag库 {l)$9!  
EJ>&\Iq  
o 找到与之对应的tag处理类 fZezDm(Q  
+J|H~`  
o tag标签的类型 pB4Uc<e  
@)BO`;*$fF  
· 自定义tag标签 WR3,woo  
`sCn4-$8  
o tag处理类 |mP};&b  
^$5 0[  
o tag库描述 A#6zI NK#B  
LQHL4jRXU  
o tag标签示例 (-g*U#   
1$8@CT^m  
o 带属性的tag ~_-]> SI  
jM&di  
o 带body的tag +Q[uq!<VJk  
L;* s-j6y  
o 定义了脚本变量的tag NNF"si\FE  
3*& Y'/!  
o 具有协作关系的tag 0:`|T jf_  
VJ=>2'I  
· 自定义tag标签 X%+lgm+  
i1|>JM[V  
o 一个迭代tag的例子 .G8>UXX  
K J\kR  
o 一个模板tag库 {BmqUoZrC  
G.H8 ><%  
o tag处理类到底是怎样被调用的? T#H^ }`  
!uQT4< g  
^3TNj  
什么是自定义的tag? N(Ru/9!y"  
Lx wi"ndP  
一个自定义的tag标签是用户定义的一种JSP标记。当一个含有自定义的tag标签的JSP页面被jsp引擎编译成servlet时,tag标签被转化成了对一个称为tag处理类的对象进行的操作。于是当JSP页面被jsp引擎转化为servlet后,实际上tag标签被转化成为了对tag处理类的操作。 rNR7}o~qo  
N^dQX,j  
自定义tag标签有很多特色,诸如: 0eNdKE  
%W"u4 NT7  
· 可以在JSP页面中自定义tag标签的属性  <@<bX  
? Bpnnwx  
· 访问JSP页面中的所有对象 a$ "nNmD?  
g5|~ i{"0  
· 可以动态地修改页面输出 ]:Gy]qkO  
)Cl>%9  
· 彼此这间可以相互通信。你可以先创建一个JavaBeans组件,然后在一个tag中调用此JavaBeans组件,同时可以在另一个tag中调用它。  ,\s`T O  
Z-Uu/GjB  
· tag允许相互嵌套,可以在一个JSP页面中完成一些复杂的交互。 lcie6'<  
)A$"COM4  
DxV=S0P  
使用tag标签 st;iGg  
b2OwLt9  
GLn=*Dh#  
本节主要描述怎样在JSP页面中使用tag标签,以及tag标签的不同类型。 r*+~(83k  
.`}TND~  
要使用tag标签,JSP程序员必须做2件事: 9h amxi  
q1T)H2S  
· 声明此tag标签的tag库 I&{T 4.B:U  
s`jlE|jtN  
· 实现此tag标签 l S)^8  
{+WBi(=W  
声明tag标签所在的tag库 w6i2>nu_O  
pM?~AYWb  
如果要使用tag标签,则应用JSP的taglib指示符来指定其tag库(注意:taglib要在在使用此tag标签之前声明) oI;ho6y)  
V 9Qt;]mQ  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> E{<#h9=>  
t,?, T~#9  
uri属性定义了唯一的标签库描述(以下简称TLD),它可以是直接是tld文件名或一个独一无二的名字。prefix是用来区别其它TLD中和本TLD中有重名的tag的一种手段。 q< XFw-Pv  
\ZZ6r^99  
TLD必须以.tld作为扩展名,并且存放在当前应用的WEB-INF目录或其子目录下。你可以通过它的文件名直接引用它,也可以通过别的方式间接地引用它。 =/Gd<qz3  
. vb##D  
以下taglib指示符直接引用一个TLD: 6sBt6?_T  
mol,iM*l  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> zr /v.$<  
HG;;M6  
以下的taglib指示符通过一个逻辑名称间接地引用一个TLD: "pM >TMAE  
@."K"i'Bl  
<%@ taglib uri=”/tutorial-template” prefix=”tt” %> w.q`E@ T*  
In1W/ ?  
如果是间接引用TLD的话,那你必须还要在web.xml中定义此逻辑名称与tld文件之间的映射,具体做法是在web.xml中加入一个名为taglib的元素: ;OlnIxH(W  
1'qXT{f/~  
<taglib> ~.: { Ik]  
6G2~'zqPc~  
<taglib-uri>/tutorial-template</taglib-uri> < D/K[mz-  
>qo!#vJc a  
<taglib-location> iT}>a30]B  
R iLl\S#  
/WEB-INF/tutorial-template.tld '#7k9\  
,~Mf2Y#m0p  
</taglib-location> ^%$IdDx  
9;+&}:IVS  
</taglib> -D~K9u]U_  
VcrMlcnO  
mD'nF1o Ly  
实现此tag标签 $|=| "/  
]lwf6'  
&<N8d(  
为了实现tag标签,你有2种方法来存放tag处理类。一、让tag处理类以.class的方式存放于当前应用的WEB-INF/class子目录下,二、如果tag处理类是以JAR包的形式存在的话,那可以放在当前应用的WEB-INF/lib目录下,如果tag处理类要在多个应用中共享,那么它就应放在jsp服务器上的common/lib目录下,对于tomcat来说,就是tomcat/common/lib目录下。 KnkmGy  
^ Kz ?SO  
:}e<  
tag标签类型 |M;Nq@bRv  
gw)4P tb!  
[P &B  
自定义的tag标签遵循XML语法。它有一个开始标记和一个结束标记,有的还有body(即文本节点): <[k3x8H'  
klUV&O+=%  
<tt:tag> ^ 8}P_  
l zFiZx  
body Wq A) V,E  
uOA/r@7I}S  
</tt:tag> k+9F;p7  
uppa`addK  
VW*%q0i-  
一个不带body的tag标签如下: R4'.QZ-x  
28"1ONs 3  
<tt:tag /> f6Y?),`  
sE?%;uBb  
|HycBTN#E  
简单的tag标签 OkciL]  
A;;#]]48  
一个没有body和属性的tag标签如下: @} r*KF-  
PaaMh[OmG  
<tt:simple /> Z?+ )ox  
,7B7X)m{3  
tx5bmF;b)  
带属性的tag标签 xw8k<`  
BQ6$T&  
p6- //0qb  
自定义标签可以有自己的属性。属性一般在开始标记中定义,语法为 attr=”value”。属性的作用相当于自定义标签的一个参数,它影响着tag处理类的行为。你可以在TLD中详细定义它。 gX{j$]^6G8  
}ppApJT  
你可以用一个String常量给一个属性赋值,也可以通过表达式给它赋值,如<%= ...%>。以struts为例,它的logic:present标签就是用的String常量来给属性赋值: ! v![K  
b$'%)\('g  
<loglic:present parameter = “Clear”> ^UvL1+  
0XA\Ag\`G  
而另一个标签logic:iterate是用表达式来给属性赋值: 8WytvwB}  
2U[/"JL  
<logci:iterate collection=”<%= bookDB.getBooks() %>” I0F [Z\U  
~T@E")uR  
id=”book” type=”database.BookDetails”> E <yQB39  
(d &" @  
4BMu0["6|s  
带body的tag标签 wo&IVy@s$  
"o- -MBq4  
一个自定义标签可以包含其它自定义标签、脚本变量、HTML标记或其它内容。 (f&V 7n  
+PYV-@q  
在下述例子中,此JSP页面使用了struts的logic:present标签,如果些标签定义了parameter=”Clear”的属性,则将清除购物车的内容,然后打印出一条信息: /(~ HHNnh  
(')t >B1Z  
<logic:present parameter=”Clear”> OAkqPG&w  
GG#-x$jK  
<% cart.clear(); %> vE[d& b[  
I;XM4a  
<font color=”#ff0000” size=”+2”><strong> XO;_F"H=  
D\G 8p;  
你选择了清除购物车! =_OJ 7K'  
r3Ol?p  
</strong></font> YHN6/k7H  
cUug}/!I  
</logic:present> !\'w>y7  
y;ey(  
c\. )vH  
到底是用属性还是用body来传递信息? 4M"'B A<  
Ue9d0#9  
如上所述,我们既可以通过属性,也可以通过body来传递信息。但一般来说,比较简单的类型,如字符串或简单表达式最好采用属性来传递信息。 |}77'w :  
glch06  
bD v& ;Z  
定义脚本变量的tag标签 Ge)G.>c  
(1=@.srAzK  
所谓脚本变量,是指JSP中可以调用的变量或对象。它可由tag标签产生。以下示例阐述了一个tag标签定义了一个名为tx的由JNDI所定义的事务处理对象。脚本变量可以是ejb对象、事务、数据库连接等等: |Gq3pL<jkC  
{%wrx'<  
<tt:lookup id=”tx” type=”UserTransaction” name=”java:comp/UserTransaction” /> #`@)lU+/  
I_B%F#X)  
<% tx.begin(); %> @u+LF]MY  
z/j*zU `  
... /*g0M2+OZo  
[ (Y@  
%Ok#~>c  
具有协作关系的tag标签 @w33u^  
9uxoMjR-  
自定义tag标签之间可以通过共享对象来实现协作。在下述例子中,标签tag1创建了一个名为obj1的对象,在标签tag2仍可以重复使用obj。 <1vogUDW  
AIP0PJI3  
<tt:tag1 attr1=”obj1” value1=”value” /> M7qg\1L  
|+h x2?Nv  
<tt:tag2 attr1=”obj1” /> k6 OO\=  
-wUT@a  
在以下这个例子当中,如果外层的tag标签创建了一个对象,那么其内层的所有tag标签都可以使用这个对象。由于这样产生的对象没有一个指定的名字,那么就可以将少重名的冲突。这个例子阐述了一系列协作的嵌套对象。 =n.&N   
{U9{*e$=  
<tt:outerTag> GB+$ed5@<  
7IUJHc?  
<tt:innerTag /> [?6+ r  
^E, #}cW  
</tt:outerTag> l )r^|9{  
1^AQLOiRE1  
sfVzVS[  
Tag处理类 c @lF*"4  
ke6,&s%{j  
cm!vuoB~~  
Tag处理类必须实现Tag接口或BodyTag接口,不过现在一般都流行从TagSupport或BodyTagSupport类中继承,这些类或接口都可以在javax.servlet.jsp.tagext包中找到。  2X`t&zg  
>uJu!+#  
当JSP引擎看到自己的JSP页面中包含有tag标签时,它会调用doStartTag方法来处理tag标签的开头,调用doEndTag方法来处理tag标签的结束。 W<#Kam:8e  
f3;[ZS  
下表说明不同类型的tag所需要不同的处理过程: 2n"-~'3\  
fda2dY;  
Tag处理类的方法 (;Bh7Ft  
)"Ujx`]4r  
Tag标签类型 87pu\(,'  
所调用的方法 #m{F*(%  
asW W@E  
基本标签 U8aNL sw  
doStartTag, doEndTag, release 7#HSe#0J  
HH3Z?g  
带属性的标签 4<EC50@.  
doStartTag, doEndTag, set/getAttribute1...N, release 6XAofN/5f  
t[HsqnP  
带内容的标签 pgUjje>#  
doStartTag, doEndTag, release *>GRU8_}  
%U[H`E  
带内容的标签,且内容重复循环 PE_JO(e;Xm  
doStartTag, doAfterBody, doEndTag, release n-?zH:]GG{  
ZP:+'\&J  
带内容的标签,且内容与JSP交互 uxX 3wY;M  
doStartTag, doEndTag, release, doInitBody, doAfterBody, release \R 3O39[  
'8 ^cl:X  
一个tag处理类可以通过javax.servlet.jsp.PageContext来与JSP交互,通过javax.servlet.jsp.PageContext类,tag处理类可以访问JSP中的request、session和application对像。 iYW<qgz  
`/G9*tIR8g  
如果tag标签是互相嵌套的,那内层的tag处理类可以通过它的parent属性来访问上层的tag处理类。 ZKS]BbMZa  
WK#c* rsij  
一般情况都将所有的tag处理类打成了JAR的包,以便于发布。 J6 A3Hrg  
~1Ffu x  
/+<G@+(  
Tag库描述(简称TLD) 6 G ,cc  
p`"Ic2xPJ  
uowdzJ7  
Tag库是用xml语言描述的,TLD包括了tag库中所有tag标签的描述,它一般用来被jsp服务器用来校验tag的语法正确性,或者被jsp开发者用来开发新的标签。 l >oJ^J  
: t D`e<  
TLD的文件扩展名必须为.tld,而且必须放在当前WEB应用的WEB-INF目录或其子目录中。 *\0h^^|@  
x9]vhR/av  
一个TLD的内容的开头必须遵守标准的XML开头,用于描述DTD和xml的版本,例如: nWd;XR6|  
eS%8WmCV9<  
<?xml version="1.0" encoding="ISO-8859-1" ?> fG@]G9Z  
] P_yN:~  
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd"> zq$0 ?vGd  
TLD必须以<taglib>来作为它的根元素,<taglib>的子元素如下表: bdBLfWe  
8NWuhRRrw  
I,/E.cRV<  
<taglib>的子元素 y :QnK0  
xjYH[PgfX  
Element O^~nf%  
Description a0k/R<4  
q:wz!~(>  
tlib-version WQ{^+C9g'1  
Tag库的版本 {(d 6of`C_  
(V}?y:)  
jsp-version )ItW}1[I  
Tag库所需要的jsp的版本 xd`\Ai  
7<*g'6JG[  
short-name |lIgvHgg  
助记符,tag的一个别名(可选) H:q;IYE+a  
U]M5&R=?  
uri VTO92Eo  
用于确定一个唯一的tag库 0,cU^HMA  
B}I9+/|{  
display-name d(vt0  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) ,W$&OD  
=+4om*  
small-icon `@&WELFv{  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) AgOti]`aR  
C)cuy7<  
large-icon _]< Tv3]RK  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) 1,n\Osd  
T'5MO\  
description +^$E)Ol  
对tag库的描述(可选) -;YhQxxC}L  
!#4b#l(e6  
listener Om8Sgy?  
参见下面listener元素 -c[fg+L9  
"i%=QON`  
tag HC$}KoZkC  
参见下面tag 元素 SS&G<3Ke  
@f#6Nu  
Listener元素 k4J Tc2b  
 fTGVG  
一个tag库可能定义一些类做为它的事件侦听类,这些类在TLD中被称为listener 元素,jsp服务器将会实例化这些侦听类,并且注册它们。Listener元素中有一个叫listener-class的子元素,这个元素的值必须是该侦听类的完整类名。 ]_m(q`_  
4SIS #m  
Tag元素 ^aqBL  
q3u:Tpn4%  
每个tag元素在tag库中都要指出它的名字、类名、脚本变量、tag的属性。其中脚本变量的值可以直接在TLD中定义或通过tag附加信息的类来取得。每个属性描述了这个属性是否可以省略,它的值是否可以通过<%= …%>这样的JSP语法来获得,以及属性的类型。 k P=~L=cK  
`cFNO:  
每一个tag在TLD中对应一个tag元素,下表是tag元素的子元素: g9F?j  
iG{xDj{CKv  
Tag元素的子元素 6^,;^   
FD8d-G  
元素名称 gS!zaD7Nr  
描述 QRdh2YH`  
P\$%p-G  
name \ Ju7.3.  
独一无二的元素名 PSU}fo  
Bf$` Hf6  
tag-class wd2z=^S~  
Tag标签对应的tag处理类 nz/cs n  
nR,QqIFFw  
tei-class g7v(g?  
javax.servlet.jsp.tagext.TagExtraInfo的子类,用于表达脚本变量(可选) `>HrO}x^  
S3y(' PeF  
body-content nx5I  
Tag标签body的类型 *dx E (dP  
6&"GTK  
display-name pE{Ecrc3|  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) B# o6UO\  
$g }aH(vf  
small-icon :;w#l"e7<  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) #z P-, 2!r  
obvE m[x!Z  
large-icon Z'i@;^=A  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) +QN4hJK  
=K:[26  
description s",Ea*  
此tag标签的描述 Fn5BWV  
z\eQB%aM  
variable ;n't:yQW  
提供脚本变量的信息(同tei-class)(可选) f9#zV2ke]  
~lV#- m*  
attribute wXUR9H|0(  
Tag标签的属性名 o<5`uV!f  
[3X\"x5@V  
以下章节介绍对于不同类型的tag,如何具体地实现它们。 }F]Z1('  
XHA|v^  
r:sa|+  
简单的tag byI" ?  
%1 )c{7  
k' 8q /]  
tag处理类 SA'g`  
ug,AvHEnB  
简单的tag处理类必须实现Tag接口的doStartTag和doEndTag方法。当jsp引擎碰到tag标签的开头时,doStartTag被调用,因为简单的tag没有body,所以此方法将返回 SKIP_BODY。当jsp引擎碰到tag标签的结尾时,doEndTag被调用,如果余下的页面还要被计算,那它将返回EVAL_PAGE,否则将会返回SKIP_PAGE。 f(y+1  
45 ^ Z5t  
以下是例子:对于标签 <tt:simple /> ,它的tag处理类实现如下: gs1yWnSv5  
A l;a~45  
8)S)!2_h  
public SimpleTag extends TagSupport ^$'{:i  
b"X1  
{ +2{ f>KZ  
rfonM~3?'  
public int doStartTag() throws JspException f:M^q ;  
'=;e# C`<{  
{ F`4W5~`  
x:-NTW -g  
try{ @A6iY  
s={>{,E  
pageContext.getOut().print(“Hello.”); KH,f'`  
#;8)UNc)}  
}catch(Exception e){ _jX,1+M  
}36AeJ7L  
throw new JspTagException(“SimpleTag: “ + e.getMessage()); K{d3)lVYCS  
9<3(  QR  
} ,esEh5=Ir  
m%.4OXX"&  
return SKIP_BODY; 80Y% C-Y:  
qoZi1,i'  
} 5:r AWq  
/}1|'?P  
public int doEndTag() z9 0JZA  
"81'{\(I_  
{ <6;M\:Y*T  
rd&d~R6  
return EVAL_PAGE; $W|JQ h  
,~cK]!:>s  
} 5 Y&`ZJ  
9gA@D%0  
} V06*qQ[  
f&$Bjq  
v FL$wr  
注意:如果tag标签没有内容的话,那必须定义body-content元素为空,例如 s 4rva G@a  
jUE:QOfRib  
<body-content>empty</body-content> D`QMlRzXy  
n=j) M  
#jBmWaP.  
带属性的tag标签
评价一下你浏览此帖子的感受

精彩

感动

搞笑

开心

愤怒

无聊

灌水
级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
只看该作者 1 发表于: 2007-01-01
tag处理类 #qVvh3#g  
V(kK2az  
对于tag标签的每个属性,你必须依照JavaBeans规范来定义其属性,以及get和set方法。以struts的logic:present 标签为例, N^B7<~ bD  
;S^"Y:7)  
<logic:present parameter=”Clear”> \ o2oQ3  
KPy)%i  
与此相应,此tag处理类应有如下方法和定义: (@N ILK  
M>=@Z*u/+  
ZzK^ bNx)0  
protected String parameter = null; RUr ~u  
g:RS7od=,  
public String getParameter() 6v{&,q  
fahQ^#&d`  
{ fwUvFK1G  
.]exY i  
return this.parameter; kj|Oj+&  
)j'Qi^;(D  
} )}$rgYKJ  
{QG6ldI  
public void setParameter(String parameter) 3KqRw (BK  
i9 CQ~  
{ zdem}kBIe  
w!*ZS~v/r  
this.parameter = parameter; m~;.kc  
U$DZht4>u  
} >lmqPuf  
aVHID{Gf Z  
+uF}mZ S^  
注意:如果你的属性名为id,而且你的tag处理类是从TagSupport类继承的,那你就不需要定义它的属性和set和get方法,因为他们早已在TagSupport被定义过了。 \a0{9Xx F  
fph+ 05.%  
Attribute元素 ^+%bh/2_W  
r[):'ys,C  
对于tag标签的每个属性,你必须定义它是否必须的,它的值是否可以用诸如<%= …%>的表达式来获得,以及它的类型(可选),如果不指定它的类型,那就默认为是java.lang.String类型。如果rtexprvalue元素被定义为true或yes,那么在type元素中就定义了attribute的返回类型。 J|jvqt9C  
% dFz[b  
<attribute> a(IE8:yU`  
DMA7eZf'Hv  
<name>attr1</name> %npLgCF  
P;(@"gD8z5  
<required>true|false|yes|no</required> O_s /BoB@  
%gn@B2z  
<rtexprvalue>true|false|yes|no</rtexprvalue> q9x@Pc29d  
cl#XiyK>  
<type>attribute的返回类型(只用当rtexprvalue为真是才有效)</type> @Wd (>*"zw  
5jK|  
</attribute> (eb65F@P  
k"7ZA>5jk  
如果tag的某个属性不是必须的,那tag处理类会自动提供一个缺省值。 CUTjRWQ  
M'|[:I.V  
例如,在logic:present这个tag标签中定义了一个属性叫parameter,但它不是必须的,而且它可以被诸如<%= …%>的表达式来赋值。 MZ0cZv$v!~  
5o{U$  
<tag> dVq9'{[3  
Jo qhmn$j  
<name>present</name> =KO]w9+\  
@fA| y  
<tag-class>org.apache.struts.taglib.logic.PresentTag</tag-class> `B&E?x  
XRM/d5  
<body-content>JSP</body-content> Jo8fMG\P  
G \a`F'Oo  
|,KsJ2hD  
(' %Y3z;  
<attribute> 8d1qRCIz  
yL<u>S0  
<name>parameter</name> r9-ayp#pC  
+5-|6  
<required>false</required> F~fN7<9R  
Ht43G_.j  
<rtexprvalue>true</rtexprvalue> r 25VcY  
LdOqV'&r  
</attribute> \N0wf-qa=  
|0p@'X1  
w&}<b%l  
vx6lud0k}  
</tag> nIlx?(=pu  
eo;MFd%;  
AD!w:jT9  
属性元素的校验 f"\klfrRI_  
IuFr:3(  
TUGD!b{  
有关于tag标签的有效值可以从tag库的说明文档中获得,当JSP页面被编译时,jsp引擎会强制性地参照TLD中定义的规则进行检查。 ( +S-  
7C Sn79E  
还有一个方法也可以进行属性元素的校验,就是先继承类TagExtraInfo,然后调用它的isValid方法。这个类同时也起到提供tag中定义的脚本变量信息的作用。 :Eh}]_  
GXLh(d!C  
IsValid方法通过TagData对象来传递属性信息,它包括着tag的所有的属性名-值的信息。由于校验发生在运行时刻,因此这个属性的值将被赋值为TagData.REQUEST_TIME_VALUE。 uZf 6W<a  
~tL:r=  
例如tag标签<tt:twa attr1=”value1” />在TLD中定义如下: B<myt79F_[  
JSq3)o9?/  
<attribute> LO%e1y  
FwKY;^`!d  
<name>attr1</name> 9A{D<h}yk  
n}9<7e~/  
<required>true</required> 9I5AYa?  
L|D9+u L  
<rtexprvalue>true</rtexprvalue> npytb*[|c  
zSMM?g^T  
</attribute> n<)A5UB5-  
39[ylR|\  
2ER_?y  
这个定义说明了attr1能在运行期间被赋值。 37IHn6r\  
$\k)Y(&  
以下的isValid方法检查attr1属性的值是否属于Boolean类型。注意由于attr1能在运行刻被赋值,那么isValid方法必须检查tag用户是否对此tag进行了运行时刻赋值。 S^i8VYK,C5  
K5<2jl3S  
it>Bf;  
Public class TwaTEI extends TagExtraInfo B`nI] _  
qxyY2&  
{ 3z#> 1HD$  
ut]&3f''  
public boolean isValid(Tagdata data) iBWEZw)  
ME)='~E  
{ W! |_ hL  
fMHw=wJQ  
Object o = data.getAttribute(“attr1”); HdY#cVxy  
Y[VXx8"p  
If(o != null && o != TagData.REQUEST_TIME_VALUE) AfZGI'%4[a  
\Lbwfd=  
{ grI#'x  
03iy[~Y2  
if( ( (String)o).toLowerCase().equals(“true”) || AU}|o0Ur  
2A*,9S|Y  
((String)o).toLowerCase().equals(“false”) ) 4QPHT#eqX  
>#;_Ebl@  
return true; 3*{l^<`:gA  
8"LM:0x  
else [EVyCIcY,h  
&{#6Z  
return false; 5yJ~ q  
J?E!\V&U  
} ^%6f%]_  
QYj 4D  
else ",5=LW&,  
1o_Zw.  
return true; !K=$Q Uq  
pvWj)4e  
} |Ul4n@+2  
%k"hzjXAw  
} wT3D9N.  
S,'ekWVD  
K0@bh/i/^  
带body的tag :YLYCVi|  
GsD?Z%t~%  
o5+7Lt]  
tag处理类 $QT% -9&  
E+ XR[p  
7bVKH[  
如果tag标签含有内容,那处理方式会略微有些不同,而且还要视tag处理类是否要与body交互的情况而定。如果要与body交互,那我们认为tag处理类要可能要对body进行操作。 u#V;  
gH"a MEC  
Tag处理类不与body交互 zT!.5qd  
V sL*&Fk  
如果tag处理类不与body交互,tag处理类应该实现Tag接口或从TagSupport中派生,如果body要被计算,那么doStartTag方法应返回 EVAL_BODY_INCLUDE,否则应返回SKIP_BODY。 )$pqe|,  
P;X0L{u0H  
如果tag处理类要对body反复运算,则它应该实现IterationTag或从TagSupport中派生。如果tag处理类认为body还未计算完的话,那它的doStartTag方法和doAfterBody方法必须返回EVAL_BODY_AGAIN。 6%o@!|=I  
uzp\<\d-t  
Tag处理类与body交互 g<w1d{Td  
d;3f80Kd*  
如果tag处理类与body交互,那tag处理类应实现BodyTag接口或从BodyTagSupport中派生。这种tag处理类一般要实现doInitBody和doAfterBody方法。 ^"uD:f)  
n"~K",~P  
Body允许一些方法来读写它的内容。Tag处理类可以调用body内容的getString或getReader方法来从body中提取信息,也可用 writeOut(out) 方法来将body的内容写入到out对象中。其中out对象通过tag处理类的getPreviousOut方法来获得。 iH dX  
<P*7u\9&  
如果body的内容需要被计算,那么doStartTag方法必须返回EVAL_BODY_BUFFERED,否则,它将返回 SKIP_BODY。 tqt~F2u  
Xp6Z<Z&N  
doInitBody 方法 fkk9&QB%(  
iP9Dr<P  
此方法在body内容已经设好,但未被计算之前被调用。你可以根据不同的body内容来制定初始化策略。 ;?-{Uk  
plzwk>b_  
doAfterBody方法 Hg\H>Z  
hPKutx  
此方法在body内容已被计算后进行调用。 tPw7zFy6r  
nxm*.&#p?  
和doStartTag方法一样,doAfterBody方法返回一个指示符指示是否要继续计算body,如果要继续计算,则doAfterBody应返回EVAL_BODY_BUFFERED,否则,它应返回SKIP_BODY。 11!4#z6w  
a6d|Ps.\!  
release 方法 f?@M"p@T  
p-z!i+  
tag处理类调用此方法将它的状态重置为初始状态,并释放所有的私有资源。 (f* r  
Idj Z2)$  
OaByfo<S  
以下的例子读取body的内容(其中含有一条sql语句),然后将它传递给一个对象,让它进行查询。由于此处body不须重新计算,所以doAfterBody会返回SKIP_BODY。 f8f|'v|  
O`~L*h_  
XNBzA3W  
Public class QueryTag extends BodyTagSupport rdX;  
o 7V&HJ[  
{ 5["n] i  
((BdT:T\_  
public int doAfterBody() throws JspTagException pC&i!la{o}  
09iD| $~  
{ [eDRghK  
g)<[-Q1  
BodyContent bc = getBodyContent(); /pGx !  
i-sm9K'ns  
//将body的内容以字符串的格式提取出来 TP`"x}ACa?  
K$$%j"s  
String query = bc.getString(); S;{[];  
9q^7%b,  
//清除body 3 "|A5>Vo  
e.|t12)L "  
bc.clearBody(); L_=3`xE _  
^<aj~0v  
try{ a uve&y"R  
G<~P||Lu^  
Statement stmt = connection.createStatement(); 2%pe.s tQ  
`ih#>i_ &  
Result result = stmt.executeQuery(query); '?E@H.""  
*m 6*sIR  
}catch(SQLException e){ n8&x=Z}Xs  
]/mRMm9"3h  
throw new JspTagException(“queryTag: “ + e.getMessage() ); Yp $@i20  
w#sP5qKv8  
return SKIP_BODY; z2dW)_fU$  
JNA_*3 '  
} 4DGKZh'm"  
\JF 2'm\M  
} b]WvKdq  
r+MqjdXG  
:O*62olC5  
body-content元素 Tz/[P:O3  
7{[i)  
.R@euIva  
由于tag可能会有body,你必须用body-content元素来指定body内容的类型: 3TKl  
~HBx5Cpi  
<body-content>JSP|tagdependent</body-content> %bhFl,tL  
W6yz/{Rf  
/ DS T|2  
如果body的内容是定制的或内部的tag、脚本元素、或HTML广本,则归类为JSP类型。其他的类型,比如上面代码所述的?D?D将sql statement类传给 query tag的这种类型应该标为tagdependent。 >LFj@YW_)  
;:Y/"5h  
注意:实际上body-content的值并不影响tag处理类对body内容的处理,它仅仅是被tag编辑工具用来描述此body的内容。 :*Z@UY   
8WG_4e  
qh wl  
用tags定义脚本变量 2\[ Q{T=Qe  
e" p5hpl  
y)`q% J&  
tag处理类 pf_`{2.\uO  
\j vS`+  
3,@|kN<  
tag处理类负责创建或设置页面中定义的脚本变量,用pageContext.setAttribute(name,value,scope)或pageContext.setAttribute(name,value)方法来实现。一般来说,tag处理类通过脚本变量的名称来获取它,脚本变量的名称一般可用get方法来获得。 Z ^yn S  
R)GDsgXy  
如果脚本变量的值依赖于tag处理类中的上下文中某一对象,那它可用pageContext.getAttribute(name,scope)方法来找到那个对象。一般的处理过程是tag处理类先找到脚本变量,再对其进行处理,然后用pageContext.setAttribute(name,object)的方法来设置它的新值。 sO&eV68 [  
h)?Km{u%  
对象的生存周期(scope)如下表: #pMpGw$  
w8-L2)Q}I  
对象的生存周期表 #Xun>0  
m^a0JR}u9  
名字 E._/PB  
可访问范围 6IL-S%EGK1  
生存周期 Q".p5(<  
I]N!cEr;@-  
page '\LU 8VC  
当前页面 UeSPwY  
一直有效,除非页面向客户提交响应或重定向到一个新页面  bzX/Zts  
elb}] +  
request JU-eoB}m  
当前页面或当前页面重定向到的页面 z-h7v5i"  
一直有效,除非页面向客户提交响应 ^|%7}=e  
?*U:=|  
session rj;~SC{  
当前页面或在同一浏览器窗口中的页面 boIFN;Aq"  
一直有效,除非关闭当前浏览器、超时、网络故障 q%Lw#f  
M_F4I$V4  
application DOW Z hD  
整个web应用程序的所有请求 Z , 98  
一直有效,除非发生网络故障、服务器故障 VD2o#.7*eu  
RS  Vt  
提供关于脚本变量的信息 uulzJbV,K  
O>arCr=H  
以下示例定义了一个名为“book”的脚本变量,用来访问程序中关于书的信息: fH;lh-   
Oat #%  
<bean:define id=”book” name=”bookDB” property=”bookDetails” type=”database.BookDetails” /> D?9EO=  
jD_B&MQz  
<font color=”red” size=”+2” > #0/^v*  
\'Ca%j  
<%= messages.getString(“CartRemoved”) %> R&1 xZFj  
2rX}A3%9^^  
<strong><jsp:getProperty name=”book” property=”title” /></strong> /d1V&Lj  
_." X# }W  
</font> is=|rY9$  
_zFJ]7Ym.)  
当包含此tag的JSP页面被编译时,jsp引擎会自动生成关于此book的同步的代码(同步可以避免几个客户同时访问此book时造成的冲突),要生成同步代码,jsp引擎需要知道此脚本变量的如下信息: coc :$Sr%  
P, SI0$Z  
· 脚本变量名称 Kr;F4G|Qt  
aW$))J)0  
· 脚本变量所属的类 )mRKIM}*W  
A-qpuI;f  
· 此脚本变量是否引用了一个新的或已存在的对象 W:=CpbwENX  
ZY> u4v.  
· 此脚本变量的有效性 ;F>I+l_X  
 2dBjc{  
有两种办法可以向jsp引擎提供关于脚本变量的信息:在TLD中定义variable子元素,或用tei-class子元素定义一个额外tag信息类。用variable最简单,但可能降低了一些灵活性。 )N]%cO(^  
azp XE  
Variable元素 ju;Myi}a  
; WsV.n  
Variable元素有如下子元素: f n\&%`U  
~Uaz;<"j0  
· name-given ?D?D 给出的名字,是一个常量 !EO 2  
kpO+  
· name-from-attribute?D?D 属性名,在编译时给出的属性名 ^]?Yd)v  
kZvh<NFh_  
name-given或name-from-attribute两者必须选一,但以下子元素是可选的: Q02:qn?T  
Ph C{Gg  
· variable-class?D?D变量的类型,缺省为java.lang.String。 ~dj4Q eu  
.2STBh.;  
· declare?D?D此脚本变量是否引用了一个新对象,缺省为True。 jQ\/R~)O  
I K Dh)Zm  
· scope?D?D脚本变量的范围,缺省为NESTED。下表描述了scope的几种类型: i]n ?zWo_h  
. aqP=  
脚本变量的有效范围 =J&aN1Hgt  
2HJGp+H  
f%TP>)jag!  
有效性 D z5(v1I9A  
方法 3` \)Qm  
X+k`UM~  
NESTED v@E/?\k"  
在tag标签的开始和结束之间 |oJ R+  
如果tag处理类实现BodyTag接口,则在doInitBody和doAfterBody中调用,否则在doStartTag中调用 s$;IR c5!6  
Y@M l}43  
AT_BEGIN rlVo}kc7:  
从tag标签的开始一直到页面结束 i"C?6R  
如果tag处理类实现BodyTag接口,则在doInitBody、doAfterBody和doEndTag中调用,否则在doStartTag和doEndTag中调用 Ol. rjz9  
de?lO ;8  
AT_END <\S j5  
从tag标签的结束一直到页面结束 z[ N_3n  
在doEndTag中调用 $ *^E  
'l3K*lck  
以struts为例,它的bean:define标签的实现遵循JSP1.1规范,此规范要求使用额外tag信息类来定义脚本变量。Variable元素是JSP1.2规范中加入的。以bean:define标签为例,你可以定义如下variable元素: {V9}W<  
(Qys`D   
<tag> }X*.Vv A  
)VCRbz"[g  
<variable> H(Q|qckj  
w*s#=]6  
<name-from-attribute>id</name-from-attribute> #pw=HHq*(  
( -rw]=Qu  
<variable-class>database.BookDetails</variable-class> /Q[M2DN@  
}]?U. ]-  
<declare>true</declare> B3|rO  
]&/KAk  
<scope>AT_BEGIN</scope> 1)f~OL8o  
Sk,9<@  
</variable> -a$7b;gF  
ec` $2u  
</tag> tpi>$:e  
spt='!)4  
额外tag信息类 Ev;ocb,  
vVi))%&S(  
如果要定义一个额外tag信息类,你要继承javax.servlet.jsp.TagExtraInfo类。一个TagExtraInfo类必须实现getVariableInfo方法,此方法返回一个叫VariableInfo的数组类,它包括如下信息: g$ oe00b  
)z#M_[zC>  
· 变量名 ]w=6.LzO*  
juuV3et  
· 变量所属类名 iy_\1jB0  
zx{O/v KG  
· 此变量是否引用了一个新对象 |+MV%QG;  
5=.EngG  
· 此变量的有效范围 q#~]Hp=W5  
35[8XD  
jsp引擎将一个名为data的参数传给getVariableInfo方法,data中包括tag标签中的所有“属性名?D?D属性值”对。它可以用来向VariableInfo对象提供脚本变量的名字和类名。 XK5qE"  
s GP}>w-JZ  
以struts为例,它在bean:define标签中定义了一个名为DefineTei的额外tag信息类,用来向脚本变量提供信息。由于脚本变量的名称(book)和类名(database.BookDetails)是通过tag标签的属性来传递的,它们一般定义在VariableInfo的构建代码中,并且可用data.getAttributeString方法来得到这些信息。如果要允许book脚本变量能在从tag开始直到整个JSP页面结束的范围内都可用的话,那它的范围应设为AT_BEGIN。如下所示: h}_1cev?  
*AU"FI> V  
{E~ MqrX  
public class DefineTei extends TagExtraInfo xBC:%kG~#  
IlcFW  
{ rn?:utP  
 }[<eg>9#  
public VariableInfo[] getVariableInfo(TagData data) :K6(`J3Y"^  
o= %Fh  
{ uvrfR?%QK  
1=t\|Th-  
String type = data.getAttributeString(“type”); emV@kN.  
"kjjq~l  
If( type == null) 1Bz'$u;  
FT* o;&_QS  
type = “java.lang.Object”; F W# S.<  
:oH"  
return new VariableInfo[] { !Ax7k;T  
=R^V[zTn_  
new VariableInfo(data.getAttributeString(“id”), ?_F,HhQ  
0F<O \  
type, o?J>mpC  
ZC1U  
true, iM Xl}3  
nV0"q|0K;  
VariableInfo.AT_BEGIN) B94mh  
;Db89Nc$  
}; 1& k_&o  
3a4 ]{  
} 8F<Qc*'  
X3:-+]6,d  
} j]"Yz t~u  
UP]J `\$o  
m GWT</=[$  
注意:关于额外tag信息类的类名必须要在TLD中的tag标签下的tei-class子元素中定义。因此,DefineTei的tei-class中的定义看起来如下: "l&sDh%Lk<  
<tei-class> &0 VM <  
org.apache.struts.taglib.bean.DefineTagTei {=,?]Z+  
</tei-class> 8fdK|l w  
F~ n}Ep~1  
}q(IKH\&  
具有协作关系的tag iw(\]tMt  
V\kf6E  
qb ^4G  
tag通过共享对象来进行协作,JSP技术支持2种方式的对象共享。 v5t`?+e  
5|-(Ic  
第一种方法是使用pageContext对象进行对象的共享(可支持JSP页面和tag处理类之间的共享),如果在一个tag处理类中要调用由另一个tag处理类创建的对象,可调用pageContext.getAttribute(name, scope)方法。 G2kr~FG  
4\?I4|{pC  
第二各方式的共享是对于tag之间有嵌套关系而言的,外层的tag所创建的对象对于内层的tag来说是可以共用的。这种形式的共享的好处是减少了可能存在的重名冲突。 ujcNSX*  
PL8eM]XS  
要访问一个嵌套tag创建的对象,tag处理类必须先找到此嵌套tag对象,可用TagSupport的静态方法 TagSupport.findAncestorWithClass(from, class)或TagSupport.getParent方法。前者在当不确定此tag是否为嵌套tag对象时使用。一旦它的父类被找到,它就能访问其所有动态或静态创建的对象。静态创建的对象是父类的成员,而动态创建的对象可能是父类的私有对象。诸如此类的对象可以用tag处理类的setValue方法来保存,用getValue方法来获得。 'B"kUh%3$5  
g2hxWf"  
下例阐述了以上两种共享对象的方法。在这个例子当中,一个查询tag检查一个名为connection的属性名是否在doStartTag中被设置。如果connection属性被设置,tag处理类从pageContext中得到这个connection对象。否则,此tag处理类先找到它的父tag处理类,然后从它的父tag处理类中找到connection对象。 2WIbu-"l  
%rT XT  
9`)NFy?  
public class QueryTag extends BodyTagSupport w<awCp  
KW.S)+<H&  
{ P$@5&/]  
UG+wRX :dA  
private String connectionId; mV;Egm{A\  
4kA/W0 VG  
public int doStartTag() throws JspException h"YIAQ',  
ZBJYpeGe  
{ b=QO^  
=? xA*_^  
String cid = getConnection(); "_C^Bc  
11 .RG *  
if(cid != null) -)?~5Z   
u9>.x zYG  
{ 5Lt&P 5BY  
9r7QE&.  
//存在一个connection id,使用它。 D|Z,eench  
vdNh25a<h  
connection = (Connection) pageContext.getAttribute(cid); @-;-DB]j  
Xig+[2zS  
} 7BF't!-2F  
^$_a_ft#  
else e9q/[xMi  
wLU w'Ai  
{ ^<<( }3  
5gV8=Ml"V  
ConnectionTag ancestorTag = (ConnectionTag)findAncestorWithClass(this, ag?@5q3J}  
L"tj DAV  
ConnectionTag.class); ^?toTU   
_q=$L eO5  
if(ancestorTag == null) /Yx 1S'5  
mxQS9y  
{ s+^o[R T3  
>lyUr*4PX  
throw new JspTagException(“一个没有connection属性的查询标签必须被一个connection标记嵌套。”); mb?DnP,z  
i2$U##-ro]  
} d Z"bc]z{  
)u ]<8  
connection = ancestorTag.getConnection(); Tc\^=e^N?  
S_6`.@B}  
} 7esG$sVj(  
tZU"Ud  
} A@_F ;4X  
"`,PLC  
} E] t:_v  
J(M0t~RZ  
ez86+  
T[<llh'+  
此查询标签在JSP页面中的调用形式可以从以下2种定义中任选一种: eJ%~6c`@!  
QKZm<lUL  
S5v>WI^0h  
<tt:connection id=”con01” ...> ... </tt:connection> Q_6./.GQ  
Gr?"okaA  
<tt:query id=”balances” connection=”con01” > C3bZ3vcW$  
?GD{}f33  
SELECT account, balance FROM acct_table ozkN&0  
rgIJ]vmy<H  
where customer_num = <%= request.getCustno() %> J}`K&DtM9  
.K}u`v T  
</tt:query> g=b[V   
g;v{JB  
DD|%F  
\(Zdd \,  
Si*Pi  
<tt:connection ...> GMgsM6.R  
d)r=W@tF]  
<x:query id=”balances”> \D,0  
,`/!0Wmt  
SELECT account, balance FROM acct_table ui G7  
Fdu0?H2TL  
where customer_num = <%= request.getCustno() %> yKOf]m>#  
5&2=;?EO  
</x:query> `W?aq]4x5  
2;[75(l6|}  
</tt:connection> >|@ /GpD  
f5wOk& G  
IDE@{Dy  
与此同时,在TLD中必须指定connection属性为可选的,定义如下: #B`"B  
?*,N ?s(U  
<tag> AUS?P t[w  
N.xmHvPk  
...  wx o(  
l%fnGe` _  
<attribute> StP6G ]x  
fBD5K3  
<name>connection</name> yql+N[  
og. dYs7W4  
<required>false</required> : [aUpX=  
A+Y>1-=JO  
</attribute> Lkk'y})/  
yn!LJT[~2  
</tag>
描述
快速回复

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