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

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

级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
标准的JSP 标记可以调用JavaBeans组件或者执行客户的请求,这大大降低了JSP开发的复杂度和维护量。JSP技术也允许你自定义taglib,其实换句话说,taglib可以看成是对JSP标记的一种扩展,正如xml是对html的一种扩展一样。taglib通常定义在tag标签库中,这种标签库存放着你自己定义的tag标签。简而言之,如果使用taglib,那么你可以设计自己的JSP标记! [/_+>M  
!JBae2Z  
一般来说,自定义tag标签主要用于操作隐藏对象、处理html提交表单、访问数据库或其它企业级的服务,诸如邮件和目录操作等等。自定义tag标签的使用者一般都是那些对java编程语言非常精通,而且对数据访问和企业级服务访问都非常熟悉的程序员,对于HTML设计者来说,使得他可以不去关注那些较复杂的商业逻辑,而将精力放在网页设计上。同时,它也将库开发者和库使用者进行合理分工,自定义tag标签将那些重复工作进行封装,从而大大提高了生产力,而且可以使得tag库可用于不同的项目中,完美地体现了软件复用的思想。 A!63p$VT;  
)J(q49  
在这篇文章中,我们主要讨论: .4l/_4,s_  
#Z~C`n u  
· 什么是自定义tag标签? Bg8#qv  
z 5]bia,  
· 怎么使用tag标签? *{o UWt  
=?X$Yaw*  
o 声明要使用的tag库 ~l~Tk6EM  
B[9 (FRX  
o 找到与之对应的tag处理类 KL'zXkS  
<:|3rfm#  
o tag标签的类型 tU/k-W3X  
q:8_]Qt  
· 自定义tag标签 voe7l+Xk  
3CE[(   
o tag处理类 ueG|*[  
yA[({2%  
o tag库描述 x&A vUJ  
`)4a[thp  
o tag标签示例 l?*r5[O>n  
rbqo"g`  
o 带属性的tag ,LOQDIyn  
N]YtLa,t  
o 带body的tag Jg$xO@.  
Cz^Q5F`  
o 定义了脚本变量的tag fYrGpW( `  
(ozb%a#B  
o 具有协作关系的tag O''y>N9  
o0z67(N&g  
· 自定义tag标签 "'Z- UV  
)$x_!=@1  
o 一个迭代tag的例子 $(q>mg:H  
] q~<=   
o 一个模板tag库 P|jF6?C  
=GR 'V  
o tag处理类到底是怎样被调用的? Dmdy=&G  
8n?kZY$,  
9j|gdfb%ml  
什么是自定义的tag? %zo= K}u  
l+y-Fo@  
一个自定义的tag标签是用户定义的一种JSP标记。当一个含有自定义的tag标签的JSP页面被jsp引擎编译成servlet时,tag标签被转化成了对一个称为tag处理类的对象进行的操作。于是当JSP页面被jsp引擎转化为servlet后,实际上tag标签被转化成为了对tag处理类的操作。 34|a:5c  
AN9[G  
自定义tag标签有很多特色,诸如: 5c -N0@\  
(S^ck%]]a!  
· 可以在JSP页面中自定义tag标签的属性 EqM;LgE=  
F:37MUQi  
· 访问JSP页面中的所有对象 2)/NFZ  
g\M5:Qm  
· 可以动态地修改页面输出 `^U&#K  
XT@Mzo49z\  
· 彼此这间可以相互通信。你可以先创建一个JavaBeans组件,然后在一个tag中调用此JavaBeans组件,同时可以在另一个tag中调用它。 '7I g.K&  
}{],GHCjQ  
· tag允许相互嵌套,可以在一个JSP页面中完成一些复杂的交互。 t"s5\;IJ  
^O%9yEo  
J^3H7 ]  
使用tag标签 `EMi0hm&H  
#2%([w  
]re'LC!d  
本节主要描述怎样在JSP页面中使用tag标签,以及tag标签的不同类型。 ^lO76Dz~a  
M1u{A^d.Z  
要使用tag标签,JSP程序员必须做2件事: ms~8QL  
7!2 HNg  
· 声明此tag标签的tag库 PJ 9%/Nrh  
E20 :uZ7\  
· 实现此tag标签  U w Eiz  
U=!@Db5k~  
声明tag标签所在的tag库 &2.+I go|G  
C}CKnkMMD  
如果要使用tag标签,则应用JSP的taglib指示符来指定其tag库(注意:taglib要在在使用此tag标签之前声明) V,LVB_6  
m4/}Jx[  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> p#H]\ P'  
v$$]Gv(  
uri属性定义了唯一的标签库描述(以下简称TLD),它可以是直接是tld文件名或一个独一无二的名字。prefix是用来区别其它TLD中和本TLD中有重名的tag的一种手段。 m@ oUvxcd  
d5U; $q{o  
TLD必须以.tld作为扩展名,并且存放在当前应用的WEB-INF目录或其子目录下。你可以通过它的文件名直接引用它,也可以通过别的方式间接地引用它。  93w~.p  
)mkS5j`5\  
以下taglib指示符直接引用一个TLD: MD'>jO;n  
YU\Gj S~>&  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> \{PNwF?  
<d@pmh  
以下的taglib指示符通过一个逻辑名称间接地引用一个TLD: {j6g@Vd6lx  
-i_En^Fi  
<%@ taglib uri=”/tutorial-template” prefix=”tt” %> ~b8a^6:R"  
]C *10S`  
如果是间接引用TLD的话,那你必须还要在web.xml中定义此逻辑名称与tld文件之间的映射,具体做法是在web.xml中加入一个名为taglib的元素: Q\#UWsN(T/  
`fW{yb  
<taglib> _+zVpZ  
1!/-)1t  
<taglib-uri>/tutorial-template</taglib-uri> jp m#hH{R  
|NEd@  
<taglib-location> Bxv8RB  
H~m]nV,r  
/WEB-INF/tutorial-template.tld #AncOo  
u7muaSy  
</taglib-location> `-D$Fsl  
VG#Q;Xd}  
</taglib> V.,bwPb{9  
K+mU_+KRp  
R`Qp d3  
实现此tag标签 sx-F8:Qa  
c)3O/`  
ahp1!=Z-=  
为了实现tag标签,你有2种方法来存放tag处理类。一、让tag处理类以.class的方式存放于当前应用的WEB-INF/class子目录下,二、如果tag处理类是以JAR包的形式存在的话,那可以放在当前应用的WEB-INF/lib目录下,如果tag处理类要在多个应用中共享,那么它就应放在jsp服务器上的common/lib目录下,对于tomcat来说,就是tomcat/common/lib目录下。 u33zceE8  
UB&2f>  
J~dTVBx  
tag标签类型 o>!JrH  
^/{4'\p  
I*c;hfu  
自定义的tag标签遵循XML语法。它有一个开始标记和一个结束标记,有的还有body(即文本节点): 9Dq.lr^  
U_*3>Q  
<tt:tag> yqBa_XPV8  
l"L+e!B~  
body KnFQ)sX^  
ITn;m  
</tt:tag> yfq>,  
yiO31uQt  
qvTKfIl{  
一个不带body的tag标签如下: Ws>i)6[  
ZeTL$E[E}  
<tt:tag /> FF@`+T  
irmwc'n]  
hfh.eL  
简单的tag标签 x3;jWg~'  
s7|3zqi  
一个没有body和属性的tag标签如下: R2Yl)2 D  
Jy`G]]?  
<tt:simple /> \-G5l+!  
j]HE>  
uTw|Q{f  
带属性的tag标签 {jhcZ"#>\  
&oc_ a1 R  
5U;nhDmM  
自定义标签可以有自己的属性。属性一般在开始标记中定义,语法为 attr=”value”。属性的作用相当于自定义标签的一个参数,它影响着tag处理类的行为。你可以在TLD中详细定义它。 5m 3'Gt4  
/Tcb\:`9  
你可以用一个String常量给一个属性赋值,也可以通过表达式给它赋值,如<%= ...%>。以struts为例,它的logic:present标签就是用的String常量来给属性赋值: ^yD"d =z  
&vkp?UH  
<loglic:present parameter = “Clear”> fMzYFM'i  
lrn+d$!@  
而另一个标签logic:iterate是用表达式来给属性赋值: Zx9.pFc"  
r8+*|$K  
<logci:iterate collection=”<%= bookDB.getBooks() %>” )(.%QSA\C  
X}?ESjZJ  
id=”book” type=”database.BookDetails”> (NM6micc  
<>&89E%j'  
c&A]pLn+x  
带body的tag标签 z0;9SZ9  
4)E|&)-fu8  
一个自定义标签可以包含其它自定义标签、脚本变量、HTML标记或其它内容。 d v[\.T`LY  
J 5- rp|  
在下述例子中,此JSP页面使用了struts的logic:present标签,如果些标签定义了parameter=”Clear”的属性,则将清除购物车的内容,然后打印出一条信息: 3z$HKG  
/evaTQPz  
<logic:present parameter=”Clear”> Kv1vx*>  
_&K\D p&@  
<% cart.clear(); %> gTuX *7w  
XX:q|?6_ 4  
<font color=”#ff0000” size=”+2”><strong> V-:`+&S{^  
5{HtJ?sKc5  
你选择了清除购物车! 6s&qZ+v-  
{ $X X  
</strong></font> Jtpa@!M  
\ bC}&Iz6  
</logic:present> Kj=;>u  
8`DO[Z  
pB[%:w/@l:  
到底是用属性还是用body来传递信息? .oEFX8  
EuLXtq  
如上所述,我们既可以通过属性,也可以通过body来传递信息。但一般来说,比较简单的类型,如字符串或简单表达式最好采用属性来传递信息。 A mvw`u>  
0|GpZuGO9  
a2[ 8wv1  
定义脚本变量的tag标签 $xQ"PJ2  
yX3PUO9  
所谓脚本变量,是指JSP中可以调用的变量或对象。它可由tag标签产生。以下示例阐述了一个tag标签定义了一个名为tx的由JNDI所定义的事务处理对象。脚本变量可以是ejb对象、事务、数据库连接等等: phe"JNML  
IF& PGo  
<tt:lookup id=”tx” type=”UserTransaction” name=”java:comp/UserTransaction” /> G1p43  
\N4d_ fPj  
<% tx.begin(); %> `|uoqKv  
~DK F%}E  
... vB=;_=^i 1  
Bmmb  
::0aY ;D2  
具有协作关系的tag标签 G^ K*+  
AmgWj/>  
自定义tag标签之间可以通过共享对象来实现协作。在下述例子中,标签tag1创建了一个名为obj1的对象,在标签tag2仍可以重复使用obj。 m&,bC)}  
#!wsD7;  
<tt:tag1 attr1=”obj1” value1=”value” /> 9N<*S'Z  
zLo;.X[Y  
<tt:tag2 attr1=”obj1” /> }z8{B3K  
B,w:DX  
在以下这个例子当中,如果外层的tag标签创建了一个对象,那么其内层的所有tag标签都可以使用这个对象。由于这样产生的对象没有一个指定的名字,那么就可以将少重名的冲突。这个例子阐述了一系列协作的嵌套对象。 vP-3j  
VPdwSW[eM  
<tt:outerTag> ^P]?3U\nj  
7:#  
<tt:innerTag /> O{Dm;@J-aM  
*O!T!J  
</tt:outerTag> >pN;J)H  
 7N!tp,?  
_w\Y{(k  
Tag处理类 q"P5,:W  
Q%+ }  
#aj|vox}  
Tag处理类必须实现Tag接口或BodyTag接口,不过现在一般都流行从TagSupport或BodyTagSupport类中继承,这些类或接口都可以在javax.servlet.jsp.tagext包中找到。 Ii,~HH  
~:2&/MOP?  
当JSP引擎看到自己的JSP页面中包含有tag标签时,它会调用doStartTag方法来处理tag标签的开头,调用doEndTag方法来处理tag标签的结束。 v/]Qq  
l t&$8jh  
下表说明不同类型的tag所需要不同的处理过程: OTnu{<.a  
%3ou^mcj  
Tag处理类的方法 7s0)3HR}  
z7| s%&  
Tag标签类型 |*Of^IkG0  
所调用的方法 -m E  
 { VS''Lv  
基本标签 hEVjeC  
doStartTag, doEndTag, release bcUC4g\9N  
qPL^zM+  
带属性的标签 r9+E'\  
doStartTag, doEndTag, set/getAttribute1...N, release H&~5sEGa  
B>{|'z?%>  
带内容的标签 FLVbkW-G.  
doStartTag, doEndTag, release PbbXi  
|= tJ|  
带内容的标签,且内容重复循环 iTj"lA  
doStartTag, doAfterBody, doEndTag, release UY1JB^J$  
YCirOge  
带内容的标签,且内容与JSP交互 dMey/A/VYt  
doStartTag, doEndTag, release, doInitBody, doAfterBody, release pp*bqY  
aJEbAs}  
一个tag处理类可以通过javax.servlet.jsp.PageContext来与JSP交互,通过javax.servlet.jsp.PageContext类,tag处理类可以访问JSP中的request、session和application对像。 tniPEmeS  
8f /T!5  
如果tag标签是互相嵌套的,那内层的tag处理类可以通过它的parent属性来访问上层的tag处理类。 a v'd%LZP  
[`y:M&@  
一般情况都将所有的tag处理类打成了JAR的包,以便于发布。 C}n[?R  
MMd0O X)P  
?SB[lbU  
Tag库描述(简称TLD)  $&ex\_W  
sI^@A=.@  
$,8CH)w  
Tag库是用xml语言描述的,TLD包括了tag库中所有tag标签的描述,它一般用来被jsp服务器用来校验tag的语法正确性,或者被jsp开发者用来开发新的标签。 Y1#-^,qg  
c-[Q,c  
TLD的文件扩展名必须为.tld,而且必须放在当前WEB应用的WEB-INF目录或其子目录中。 aQl?d<|+lk  
P%.`c?olbs  
一个TLD的内容的开头必须遵守标准的XML开头,用于描述DTD和xml的版本,例如: L 2[Ei|9_  
6U;Jg_zS  
<?xml version="1.0" encoding="ISO-8859-1" ?> 9@$tiDV  
#H'sZv  
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd"> 6V.awg,  
TLD必须以<taglib>来作为它的根元素,<taglib>的子元素如下表: (eC F>Wh^m  
9 Q0#We*  
_F}IF9{?G  
<taglib>的子元素 _#/!s]$d#  
[ c ~LY4:  
Element H.jLGe>  
Description :5TXA  
0C lX  
tlib-version uAW*5 `[  
Tag库的版本 u5u0*c  
B, QC -Tn  
jsp-version A8_\2'b  
Tag库所需要的jsp的版本 kS@9c _3S  
I>A^5nk  
short-name bs<WH`P  
助记符,tag的一个别名(可选) Y{%4F%Oy  
)ZS:gD  
uri K*([9VZ  
用于确定一个唯一的tag库 _7-"Vo X  
QV nO  
display-name XD_P\z  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) &4mfzpK  
[_g#x(=  
small-icon 1TK #eU  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) j\XX:uU_  
c,6<7  
large-icon sh',"S#=@  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) L#t-KLJ  
^ I{R[O'8  
description a}5vY  
对tag库的描述(可选) O0K@M  
H]% mP|  
listener 4f@havFIJ  
参见下面listener元素 J]n7| L  
u\Nw:Uu i  
tag "'Q"(S  
参见下面tag 元素 kr/1Dsr4  
{u(}ED#p  
Listener元素 x?k  
A^T~@AO  
一个tag库可能定义一些类做为它的事件侦听类,这些类在TLD中被称为listener 元素,jsp服务器将会实例化这些侦听类,并且注册它们。Listener元素中有一个叫listener-class的子元素,这个元素的值必须是该侦听类的完整类名。 zxk??0] /  
%4|n-`:  
Tag元素 _'?8s6 H  
RT.wTJS;  
每个tag元素在tag库中都要指出它的名字、类名、脚本变量、tag的属性。其中脚本变量的值可以直接在TLD中定义或通过tag附加信息的类来取得。每个属性描述了这个属性是否可以省略,它的值是否可以通过<%= …%>这样的JSP语法来获得,以及属性的类型。 WU+Jo@]y  
"}]GQt< F  
每一个tag在TLD中对应一个tag元素,下表是tag元素的子元素: EWu iaw.  
_0DXQS\  
Tag元素的子元素 beN>5coP%A  
"6`)vgI~  
元素名称 wu&|~@_s@  
描述 'T&=$9g7  
? e9XVQ*  
name P+*rWJ8gQ  
独一无二的元素名 y]z)jqX<  
?1-n\ka  
tag-class ="#:=i]  
Tag标签对应的tag处理类 Y\z^\k  
,p[\fT($]  
tei-class nJ'>#9~a'>  
javax.servlet.jsp.tagext.TagExtraInfo的子类,用于表达脚本变量(可选) VurP1@e&  
`&|l;zsS  
body-content (/9.+V_  
Tag标签body的类型 aIn)']  
+eV4g2w)  
display-name jza}-=&+e  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) }\`-G+i{W  
Z3X&<Y5  
small-icon /JK-}E  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) /VhE<}OtH  
;EE&~&*w  
large-icon wB1|r{  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) U&Sbm~Qi  
K=!ZI/+ju  
description 2-c U -i4  
此tag标签的描述 8 ACY uN\  
HdY3DdC%q  
variable !SO$k%b}!  
提供脚本变量的信息(同tei-class)(可选) j &0fC!k  
=E"kv!e   
attribute |`q)/ 08b  
Tag标签的属性名 % L %1g  
iS:PRa1  
以下章节介绍对于不同类型的tag,如何具体地实现它们。 rr07\;  
FkJ>]k  
!Z+*",]_  
简单的tag 5ykk11!p$  
TY54e T  
JT.\f,z&  
tag处理类 fo!Lp*'0  
7=QC+XSO  
简单的tag处理类必须实现Tag接口的doStartTag和doEndTag方法。当jsp引擎碰到tag标签的开头时,doStartTag被调用,因为简单的tag没有body,所以此方法将返回 SKIP_BODY。当jsp引擎碰到tag标签的结尾时,doEndTag被调用,如果余下的页面还要被计算,那它将返回EVAL_PAGE,否则将会返回SKIP_PAGE。 \ ]kb&Qw  
DiYJlD&  
以下是例子:对于标签 <tt:simple /> ,它的tag处理类实现如下: @T,H.#bL  
7fN&Q~.  
7&RJDa:a7T  
public SimpleTag extends TagSupport PPj6QJ]R0  
cvs"WX3  
{ ~-`BSR  
njwR~aL`|  
public int doStartTag() throws JspException ) v[Knp'  
{>UMw>T[  
{ '^-4{Y^2E  
RBK>Lws6  
try{ cDQw`ORP*g  
G0 nH Z6  
pageContext.getOut().print(“Hello.”); LDi ez i  
o+X'(!Trw  
}catch(Exception e){ eJ=Y6;d$  
u\1Wkxj  
throw new JspTagException(“SimpleTag: “ + e.getMessage()); PGv}fEH"  
:)J~FVLy  
} } ^GV(]K  
$5Y^fwIK  
return SKIP_BODY; f_5R!;  
hPqapz]HcP  
} z)<pqN  
2=/g~rp*  
public int doEndTag() Kz3h]/A.  
j]F#p R}p  
{ #/B~G.+(  
O275AxaN  
return EVAL_PAGE; [Tb3z:UUvf  
tEWj}rX   
} N5w]2xz!  
uZ2v;]\Y6  
} s=y9!rr  
'/yx_R K2?  
$ Op/5j  
注意:如果tag标签没有内容的话,那必须定义body-content元素为空,例如 {^$"/hj  
VQ,\O  
<body-content>empty</body-content> WEV{C(u<k!  
Y%?!AmER  
$Pb[ c%'  
带属性的tag标签
评价一下你浏览此帖子的感受

精彩

感动

搞笑

开心

愤怒

无聊

灌水
级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
只看该作者 1 发表于: 2007-01-01
tag处理类 a+a%}76N  
#u=O 5%.  
对于tag标签的每个属性,你必须依照JavaBeans规范来定义其属性,以及get和set方法。以struts的logic:present 标签为例, M4hN#0("4  
%C E@}  
<logic:present parameter=”Clear”> ubCJZ"!  
aXK%m  
与此相应,此tag处理类应有如下方法和定义: EPd.atA  
U5ud?z()OA  
{}_Oo%IVGK  
protected String parameter = null; n,Mw# r?y  
Y)j,(9  
public String getParameter() 5$"[gdt)T  
{8bY7NH|  
{ +$mskj0s  
HG3>RcB  
return this.parameter; qP^0($  
by y1MgQd  
} sImxa`kb  
_467~5JkU  
public void setParameter(String parameter) A[$wxdc  
C^42=?  
{ /h.3<HI."*  
wsGq>F~  
this.parameter = parameter; NMY!-Kv 5  
&qI5*aQ8T  
} }?qnwx.  
.HyiPx3^  
O7CYpn4<7  
注意:如果你的属性名为id,而且你的tag处理类是从TagSupport类继承的,那你就不需要定义它的属性和set和get方法,因为他们早已在TagSupport被定义过了。 ']6#7NU  
UUEDCtF)  
Attribute元素 cCbr-Z&  
6exlb:  
对于tag标签的每个属性,你必须定义它是否必须的,它的值是否可以用诸如<%= …%>的表达式来获得,以及它的类型(可选),如果不指定它的类型,那就默认为是java.lang.String类型。如果rtexprvalue元素被定义为true或yes,那么在type元素中就定义了attribute的返回类型。 -K'84 bZ  
0_zSQn9c  
<attribute> AA& dZjz  
MLIQ 8=  
<name>attr1</name> C<=p"pWw  
[Z G j7  
<required>true|false|yes|no</required> zt?w n* _  
o-CJdOS  
<rtexprvalue>true|false|yes|no</rtexprvalue> "N/K*  
6=lQT 9u{  
<type>attribute的返回类型(只用当rtexprvalue为真是才有效)</type> fu "z%h]   
vAhO!5]>\  
</attribute> :pjK\  
eD1MP<>h  
如果tag的某个属性不是必须的,那tag处理类会自动提供一个缺省值。  p|8Fl  
rHdP4:n  
例如,在logic:present这个tag标签中定义了一个属性叫parameter,但它不是必须的,而且它可以被诸如<%= …%>的表达式来赋值。 7<Js'\Z  
|Gs-9+'y  
<tag> 2?nyPqT3AM  
{}C7VS1  
<name>present</name> -Jrc'e4K  
1:s~ ]F@  
<tag-class>org.apache.struts.taglib.logic.PresentTag</tag-class> ,v5>sL  
&+{xR79+&  
<body-content>JSP</body-content> 0|Ft0y`+  
^A<.s_  
… h=y(2xA  
b`Ek;nYek  
<attribute> qhf/B)  
<0qY8  
<name>parameter</name> ]G&\L~P  
K:50?r_-6  
<required>false</required> %t|2GIu  
zw9ULQ$#  
<rtexprvalue>true</rtexprvalue> ;S27m]Q?  
XN%D`tbvJ  
</attribute> 3:Egqw  
$/#)  
… uOUw8  
2}\sj'0&  
</tag> ZS>/ 5  
n?fC_dy  
H.~+{jTr  
属性元素的校验 g^^m a}i  
C4TD@  
)4~XZt1r  
有关于tag标签的有效值可以从tag库的说明文档中获得,当JSP页面被编译时,jsp引擎会强制性地参照TLD中定义的规则进行检查。 |Qq'_4:  
^n5QK HD  
还有一个方法也可以进行属性元素的校验,就是先继承类TagExtraInfo,然后调用它的isValid方法。这个类同时也起到提供tag中定义的脚本变量信息的作用。 vjWgR9 4/{  
)tg*dE  
IsValid方法通过TagData对象来传递属性信息,它包括着tag的所有的属性名-值的信息。由于校验发生在运行时刻,因此这个属性的值将被赋值为TagData.REQUEST_TIME_VALUE。 xW )8mv?4n  
`fVA. %  
例如tag标签<tt:twa attr1=”value1” />在TLD中定义如下: 8(K~QvE~  
V"p*Jd"w  
<attribute> B>L^XGq  
ky"7 ^  
<name>attr1</name> fb=vO U  
l{ { #tW  
<required>true</required> X KeK;+  
EqwA8? M  
<rtexprvalue>true</rtexprvalue> OU=IV;V{  
n!orM5=:O  
</attribute> Y(mwJud|  
UM^hF%  
5S?Xl|8E  
这个定义说明了attr1能在运行期间被赋值。 Ek\Zi#f<  
w5R9\<3L  
以下的isValid方法检查attr1属性的值是否属于Boolean类型。注意由于attr1能在运行刻被赋值,那么isValid方法必须检查tag用户是否对此tag进行了运行时刻赋值。 YWd(xm"4  
kQcQi}e  
|EU08b]P29  
Public class TwaTEI extends TagExtraInfo wC@ U/?  
aa3YtNpP  
{ F&Z>B};  
N.J:Qn`(  
public boolean isValid(Tagdata data) EE{%hGb  
TJa%zi  
{ z$,hdZ]  
(VR nv  
Object o = data.getAttribute(“attr1”); a[#BlH  
tjL#?j  
If(o != null && o != TagData.REQUEST_TIME_VALUE) wQ95tN  
yZ6X$I:C  
{ PSvRO% &  
nI` 1@ vB&  
if( ( (String)o).toLowerCase().equals(“true”) || artS*fv3r  
N4FG_  N  
((String)o).toLowerCase().equals(“false”) ) 'a9.JS[pj  
u(qpdG||7  
return true; Y*Rqgpu $  
hD=D5LYAZ  
else 8 F 1ga15  
!"">'}E1  
return false; 4^A'A.0  
'/@VG_9L]  
} |1$X`|S  
B W1O1zIh\  
else v7RDoO]I  
TR;-xst@  
return true; <]J5AdJ  
[:Y^0[2  
} {rr\hl-$  
E_#&L({|@  
} q9Wtu7/  
tp0*W _<4  
=Ih_[$1dw  
带body的tag oWT0WS  
8A qe'2IH=  
^Y!`wp2vn  
tag处理类 w-m2N-"= '  
3x$#L!VuU  
&'j77tqOk  
如果tag标签含有内容,那处理方式会略微有些不同,而且还要视tag处理类是否要与body交互的情况而定。如果要与body交互,那我们认为tag处理类要可能要对body进行操作。 *+ayC{!  
=^{+h>#s@  
Tag处理类不与body交互 {M5IJt"{4b  
dzap]RpB  
如果tag处理类不与body交互,tag处理类应该实现Tag接口或从TagSupport中派生,如果body要被计算,那么doStartTag方法应返回 EVAL_BODY_INCLUDE,否则应返回SKIP_BODY。 ^8*.r+7p  
P=GM7  
如果tag处理类要对body反复运算,则它应该实现IterationTag或从TagSupport中派生。如果tag处理类认为body还未计算完的话,那它的doStartTag方法和doAfterBody方法必须返回EVAL_BODY_AGAIN。 / ffWmb_4  
R2{X? 2|$  
Tag处理类与body交互 LNW p$"  
_7VU ,  
如果tag处理类与body交互,那tag处理类应实现BodyTag接口或从BodyTagSupport中派生。这种tag处理类一般要实现doInitBody和doAfterBody方法。 2I5@zm ea  
$1F9TfA  
Body允许一些方法来读写它的内容。Tag处理类可以调用body内容的getString或getReader方法来从body中提取信息,也可用 writeOut(out) 方法来将body的内容写入到out对象中。其中out对象通过tag处理类的getPreviousOut方法来获得。 4O'ho0w7  
k3w#^ "i  
如果body的内容需要被计算,那么doStartTag方法必须返回EVAL_BODY_BUFFERED,否则,它将返回 SKIP_BODY。 1F-L( \oKm  
a7R7Ks|q  
doInitBody 方法 n1V*VQV  
$MR4jnTT  
此方法在body内容已经设好,但未被计算之前被调用。你可以根据不同的body内容来制定初始化策略。 :JmNy <  
Yy5F'RY  
doAfterBody方法 UKdzJEhG  
GWsFW[T?~  
此方法在body内容已被计算后进行调用。 `,z{70  
w ;O '6"  
和doStartTag方法一样,doAfterBody方法返回一个指示符指示是否要继续计算body,如果要继续计算,则doAfterBody应返回EVAL_BODY_BUFFERED,否则,它应返回SKIP_BODY。 a'r\e2/e?H  
2TO1i0  
release 方法 b(F`$N@7C  
0!T $Ef   
tag处理类调用此方法将它的状态重置为初始状态,并释放所有的私有资源。 :/08}!_:  
"@_f>3z  
p_D)=Ef|&  
以下的例子读取body的内容(其中含有一条sql语句),然后将它传递给一个对象,让它进行查询。由于此处body不须重新计算,所以doAfterBody会返回SKIP_BODY。 0&|-wduR=  
sT ONkd  
hi%>&i*  
Public class QueryTag extends BodyTagSupport {WChD&v  
~V5jjx*  
{ Wh7nli7f_  
%$U+?lk}  
public int doAfterBody() throws JspTagException {$JIR}4S  
>ZT3gp?E  
{ uFgw eOJ  
%$Uw]a  
BodyContent bc = getBodyContent(); 'DPSM?]fA  
F~6[DqF\|  
//将body的内容以字符串的格式提取出来 W0Vjs|/  
U-d&q>_@A  
String query = bc.getString(); aE}u5L$#  
TqC"lO>:Q  
//清除body uQ}kq7gd  
!{+(oDN  
bc.clearBody(); -ydT%x  
u=5^xpI<D  
try{ k 'o?/  
`Bx CTwc  
Statement stmt = connection.createStatement(); 4R.#=]F  
)!Bv8&;e  
Result result = stmt.executeQuery(query); 2zAS \Y  
e): &pqA  
}catch(SQLException e){ ! d(,t[cV  
3z#16*  
throw new JspTagException(“queryTag: “ + e.getMessage() ); "&~Um U4CN  
wiZK-#\x  
return SKIP_BODY; 3i<*,@CY  
*Zln\Sx  
} {|50&]m  
FD8Hx\oF  
} :7maN^  
U-(d~]$  
= 619+[fK  
body-content元素 0< !BzG  
fa)G$Q  
Xg"=,j2  
由于tag可能会有body,你必须用body-content元素来指定body内容的类型: Gh.02  
LY7'wONx  
<body-content>JSP|tagdependent</body-content> (_D#gr{S=  
rTcH~s D`  
4r %NtXAa  
如果body的内容是定制的或内部的tag、脚本元素、或HTML广本,则归类为JSP类型。其他的类型,比如上面代码所述的?D?D将sql statement类传给 query tag的这种类型应该标为tagdependent。 <D?`*#K  
uKplPze?  
注意:实际上body-content的值并不影响tag处理类对body内容的处理,它仅仅是被tag编辑工具用来描述此body的内容。 u+N[Cgh  
'<O& :  
-7u4f y{T  
用tags定义脚本变量 -Rmz`yOq}  
  ~*RNJ  
h c "n?  
tag处理类 Wh7$')@  
dPS}\&1  
eD(#zfP/+  
tag处理类负责创建或设置页面中定义的脚本变量,用pageContext.setAttribute(name,value,scope)或pageContext.setAttribute(name,value)方法来实现。一般来说,tag处理类通过脚本变量的名称来获取它,脚本变量的名称一般可用get方法来获得。 #R &F  
%',. K)IR  
如果脚本变量的值依赖于tag处理类中的上下文中某一对象,那它可用pageContext.getAttribute(name,scope)方法来找到那个对象。一般的处理过程是tag处理类先找到脚本变量,再对其进行处理,然后用pageContext.setAttribute(name,object)的方法来设置它的新值。 F2#^5s(  
>R6Me*VR  
对象的生存周期(scope)如下表: E/ Pa0.  
L(iWFy1& T  
对象的生存周期表 hTF]-& hZ  
AV?*r-vWL.  
名字 ;Q ]bV52  
可访问范围 ]P-;]*&=  
生存周期 h[Hw9$31  
MD&Ebq5V  
page 4:7z9h]  
当前页面 tjGQ0-Lo  
一直有效,除非页面向客户提交响应或重定向到一个新页面 E[ ,Ur`>:  
\D0Pik@?  
request S%'t )tt,  
当前页面或当前页面重定向到的页面 s i C/k*  
一直有效,除非页面向客户提交响应 9R!.U\sq  
0nC%tCV'  
session cxVnlgq1  
当前页面或在同一浏览器窗口中的页面 ,+0_kndR  
一直有效,除非关闭当前浏览器、超时、网络故障 dx|j,1e  
kZeb^Q+,  
application v~j21`  
整个web应用程序的所有请求 |]V0sgpoZ  
一直有效,除非发生网络故障、服务器故障 \S _ycn  
(@]{=q<  
提供关于脚本变量的信息 ~G"5!,J  
Rc @p!Xi  
以下示例定义了一个名为“book”的脚本变量,用来访问程序中关于书的信息: 3(X"IoNQ  
lbMb  
<bean:define id=”book” name=”bookDB” property=”bookDetails” type=”database.BookDetails” /> 4]B(2FR[8  
XB2[{XH,  
<font color=”red” size=”+2” > .(D-vkz'  
$Z #  
<%= messages.getString(“CartRemoved”) %> w18kTa!4@  
zbrDDkZ1  
<strong><jsp:getProperty name=”book” property=”title” /></strong> 0} uH  
Y*0mC"n}  
</font>  ,_HVPE  
W EZ)7H  
当包含此tag的JSP页面被编译时,jsp引擎会自动生成关于此book的同步的代码(同步可以避免几个客户同时访问此book时造成的冲突),要生成同步代码,jsp引擎需要知道此脚本变量的如下信息: sdrALl;w|  
A^xD Axk  
· 脚本变量名称 +n7bbuxj(X  
X180_Kt2  
· 脚本变量所属的类 ^2=11  
TX$j-TM'  
· 此脚本变量是否引用了一个新的或已存在的对象 #Fq6-]y1")  
{eL XVNR7R  
· 此脚本变量的有效性 ;V@o 2a  
YjAwt;%-D  
有两种办法可以向jsp引擎提供关于脚本变量的信息:在TLD中定义variable子元素,或用tei-class子元素定义一个额外tag信息类。用variable最简单,但可能降低了一些灵活性。 re:=fC:t5A  
;>bcI).  
Variable元素 EHmw(%a|+  
}}@x x&  
Variable元素有如下子元素: id'E_]r  
NLRgL'+F  
· name-given ?D?D 给出的名字,是一个常量 z^bv)u  
*Mk5*_  
· name-from-attribute?D?D 属性名,在编译时给出的属性名 NvY%sx,  
sSU p7V  
name-given或name-from-attribute两者必须选一,但以下子元素是可选的: Y<odXFIS  
M, f6UYo=  
· variable-class?D?D变量的类型,缺省为java.lang.String。 n'>`2 s  
4@- 'p  
· declare?D?D此脚本变量是否引用了一个新对象,缺省为True。 bejvw?)S.  
_46 y  
· scope?D?D脚本变量的范围,缺省为NESTED。下表描述了scope的几种类型: *>I4X=  
v,^2'C$o  
脚本变量的有效范围 qf-0 | w  
rZEL7{  
值 Dn1aaN6  
有效性 f5'Cq)Vw_  
方法 _NA[g:DZ&O  
ye4 T2=  
NESTED %v5IR  
在tag标签的开始和结束之间 HJ~0_n&  
如果tag处理类实现BodyTag接口,则在doInitBody和doAfterBody中调用,否则在doStartTag中调用 rE)lt0mkv  
K?`Fpg (  
AT_BEGIN  Em?bV(  
从tag标签的开始一直到页面结束 $DBJ"8n2  
如果tag处理类实现BodyTag接口,则在doInitBody、doAfterBody和doEndTag中调用,否则在doStartTag和doEndTag中调用 D<% /:M  
Wb4+U;C^!'  
AT_END Gf*|f"O  
从tag标签的结束一直到页面结束 <A"[Wk  
在doEndTag中调用 _9*3Mr)2N  
^VabXGzo#  
以struts为例,它的bean:define标签的实现遵循JSP1.1规范,此规范要求使用额外tag信息类来定义脚本变量。Variable元素是JSP1.2规范中加入的。以bean:define标签为例,你可以定义如下variable元素: :@K 1pAh4  
r2"B"%;  
<tag> UaG })  
d.>Zn?u4L  
<variable> :%!` R72  
6ZKSet8  
<name-from-attribute>id</name-from-attribute> kbu.KU+  
@M=xdZNyJ  
<variable-class>database.BookDetails</variable-class> B*B}eXUph  
, !0-;H.Y  
<declare>true</declare> q.I  
?Pbh&!  
<scope>AT_BEGIN</scope> )/Z% HBn  
PLoD^3uG)  
</variable> n;QMiz:yY  
qGivRDR$  
</tag> 3;v%78[&P  
'z\$.L  
额外tag信息类 V[#eeH)/  
m6+4}=Cn  
如果要定义一个额外tag信息类,你要继承javax.servlet.jsp.TagExtraInfo类。一个TagExtraInfo类必须实现getVariableInfo方法,此方法返回一个叫VariableInfo的数组类,它包括如下信息: B\*"rSP\  
ebv"`0K$  
· 变量名 KF!?; q0J  
A*b>@>2  
· 变量所属类名 T*pcS'?'  
N./l\NtZ  
· 此变量是否引用了一个新对象 :^bjn3b  
a]NH >d  
· 此变量的有效范围 Ga,+  
dkUh[yo"H  
jsp引擎将一个名为data的参数传给getVariableInfo方法,data中包括tag标签中的所有“属性名?D?D属性值”对。它可以用来向VariableInfo对象提供脚本变量的名字和类名。 W[BwHNxyg  
K-X@3&X}  
以struts为例,它在bean:define标签中定义了一个名为DefineTei的额外tag信息类,用来向脚本变量提供信息。由于脚本变量的名称(book)和类名(database.BookDetails)是通过tag标签的属性来传递的,它们一般定义在VariableInfo的构建代码中,并且可用data.getAttributeString方法来得到这些信息。如果要允许book脚本变量能在从tag开始直到整个JSP页面结束的范围内都可用的话,那它的范围应设为AT_BEGIN。如下所示: Q&\(m[:)  
KdN+$fe*g  
v2K6y|6,  
public class DefineTei extends TagExtraInfo k z{_H`5.  
0Tp,b (; n  
{ C] dK/~Z#r  
L>@:Xo@  
public VariableInfo[] getVariableInfo(TagData data) Fx!NRY_  
g._`"c  
{ &[#iM0;)W0  
9lU"m_ QT4  
String type = data.getAttributeString(“type”); &GKtD)  
1[4 2f#  
If( type == null) v#X l  
F4:giu ht  
type = “java.lang.Object”; ^ s.necg0  
vXI2u;=y  
return new VariableInfo[] { {)K H%  
"Qci+Qq  
new VariableInfo(data.getAttributeString(“id”), iCX Ki7  
RvXK?mL4F  
type, vHmsS\\~9  
?j:U<TY)  
true, K3*8-Be  
)y#~eYn  
VariableInfo.AT_BEGIN) ;:Kd?Tz$  
A,fPl R  
}; Gq)E,Ln&d  
`2I<V7SF$  
} k\/idd[  
qi51'@  
} #^i.[7p  
:@oy5zib  
i!KZg74V  
注意:关于额外tag信息类的类名必须要在TLD中的tag标签下的tei-class子元素中定义。因此,DefineTei的tei-class中的定义看起来如下: + $Yld{i  
<tei-class> **KkPjAO?  
org.apache.struts.taglib.bean.DefineTagTei L;%_r)  
</tei-class> 7%` \E9t  
*h9S\Pv>j  
Q |1-j  
具有协作关系的tag 4).i4]%LH  
7c8A|E0\mF  
  mN^/  
tag通过共享对象来进行协作,JSP技术支持2种方式的对象共享。 '.$va<  
hO?RsYJ.F  
第一种方法是使用pageContext对象进行对象的共享(可支持JSP页面和tag处理类之间的共享),如果在一个tag处理类中要调用由另一个tag处理类创建的对象,可调用pageContext.getAttribute(name, scope)方法。 /\-iV)h1@  
N3U.62  
第二各方式的共享是对于tag之间有嵌套关系而言的,外层的tag所创建的对象对于内层的tag来说是可以共用的。这种形式的共享的好处是减少了可能存在的重名冲突。 Xg^9k00C  
Tm) (?y  
要访问一个嵌套tag创建的对象,tag处理类必须先找到此嵌套tag对象,可用TagSupport的静态方法 TagSupport.findAncestorWithClass(from, class)或TagSupport.getParent方法。前者在当不确定此tag是否为嵌套tag对象时使用。一旦它的父类被找到,它就能访问其所有动态或静态创建的对象。静态创建的对象是父类的成员,而动态创建的对象可能是父类的私有对象。诸如此类的对象可以用tag处理类的setValue方法来保存,用getValue方法来获得。 kD?lMA__  
a}p}G\b|  
下例阐述了以上两种共享对象的方法。在这个例子当中,一个查询tag检查一个名为connection的属性名是否在doStartTag中被设置。如果connection属性被设置,tag处理类从pageContext中得到这个connection对象。否则,此tag处理类先找到它的父tag处理类,然后从它的父tag处理类中找到connection对象。 >Y>>lE! k  
ZIr&_x#e  
iVdY\+N!<  
public class QueryTag extends BodyTagSupport "54t7  
&l-1.muQ  
{ 6 {j}Z*)m  
:*<UCn""  
private String connectionId; 552yzn1  
}]BH "  
public int doStartTag() throws JspException + r<d z  
I}hY @  
{ V;-$k@$b.  
2leTEs5aK`  
String cid = getConnection(); kKlcK_b;  
*= ;M',nx  
if(cid != null) _X/`7!f  
7FB aN7l  
{ r0'6\MS13  
:GBM`f@  
//存在一个connection id,使用它。 m]"13E0*x  
}j\_XaB  
connection = (Connection) pageContext.getAttribute(cid); y} W-OLE  
jwQ(E  
} sc)}r_|g  
GB&^<@  
else qh)10*FB  
s k>E(Myo  
{ +[_mSt  
PgMU|O7To  
ConnectionTag ancestorTag = (ConnectionTag)findAncestorWithClass(this, sCrOdJ6|  
yzH[~O7  
ConnectionTag.class); 8x/]H(J  
RASPOc/]   
if(ancestorTag == null) \.l8]LH  
?BA~$|lfxu  
{ @ )< 3Z  
?P>3~3 B  
throw new JspTagException(“一个没有connection属性的查询标签必须被一个connection标记嵌套。”); eY'< UO  
u301xc,N<z  
} fFiFS\''V  
='z4bU  
connection = ancestorTag.getConnection(); Yb? L:,a(I  
zho$g9*  
} ,)beK*Iw  
8?z7!k]  
} Eb.k:8?Tn  
1Vi3/JM @  
} D\CjR6DE  
N:% }KAc  
|J+oz7l?-  
2zN"*Wkn  
此查询标签在JSP页面中的调用形式可以从以下2种定义中任选一种: ekV|a1)  
X1Vj"4'wT  
tOT(!yz  
<tt:connection id=”con01” ...> ... </tt:connection> p?idl`?^3  
ih\=mB  
<tt:query id=”balances” connection=”con01” > ra]lC7<H  
15dbM/Gj  
SELECT account, balance FROM acct_table 2b89th  
`"RT(` m  
where customer_num = <%= request.getCustno() %> LEn+0^hX  
2T&n6t$p  
</tt:query> f:u3fL  
gF53[\w^v  
X Z4q{^o  
或 7^<{aE:  
Nay&cOz  
<tt:connection ...> S:YQVj  
dHO8 bYBH  
<x:query id=”balances”> .sBwJZ  
W^8MsdM  
SELECT account, balance FROM acct_table =b_/_b$q  
Zv|TvlyT"  
where customer_num = <%= request.getCustno() %> Uw5AHq).  
u !@(u!Qz  
</x:query> <yg! D21Y  
B$D7}=|kc  
</tt:connection> 8lZB3p]X  
@F/yc  
mK_2VZj&  
与此同时,在TLD中必须指定connection属性为可选的,定义如下: qS?uMms7w  
`E:&a]ul  
<tag> /kH 7I  
e?yrx6  
... LE]mguvs  
Sece#K2J|  
<attribute> HY>zgf,0  
?Jy /]j5fI  
<name>connection</name> 5e|yW0o  
=tQ^t4_  
<required>false</required> 8D:0Vhx\I  
Y:#nk.}>  
</attribute> oUNuM%g9Dy  
Dhze2q)o  
</tag>
描述
快速回复

您目前还是游客,请 登录 或 注册
如果您在写长篇帖子又不马上发表,建议存为草稿
认证码:
验证问题:
10+5=?,请输入中文答案:十五