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

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

级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
标准的JSP 标记可以调用JavaBeans组件或者执行客户的请求,这大大降低了JSP开发的复杂度和维护量。JSP技术也允许你自定义taglib,其实换句话说,taglib可以看成是对JSP标记的一种扩展,正如xml是对html的一种扩展一样。taglib通常定义在tag标签库中,这种标签库存放着你自己定义的tag标签。简而言之,如果使用taglib,那么你可以设计自己的JSP标记! 4 Wd5Goe:  
RW^v{'o  
一般来说,自定义tag标签主要用于操作隐藏对象、处理html提交表单、访问数据库或其它企业级的服务,诸如邮件和目录操作等等。自定义tag标签的使用者一般都是那些对java编程语言非常精通,而且对数据访问和企业级服务访问都非常熟悉的程序员,对于HTML设计者来说,使得他可以不去关注那些较复杂的商业逻辑,而将精力放在网页设计上。同时,它也将库开发者和库使用者进行合理分工,自定义tag标签将那些重复工作进行封装,从而大大提高了生产力,而且可以使得tag库可用于不同的项目中,完美地体现了软件复用的思想。 z\d2T%^:g(  
=\7p0cq&*  
在这篇文章中,我们主要讨论: 3C[4!>|  
 n(xlad  
· 什么是自定义tag标签? :bDn.`KG#  
{^MAdC_  
· 怎么使用tag标签? xKzFrP;/{  
5T3>fw2G  
o 声明要使用的tag库 t% B!\]  
>d V@9  
o 找到与之对应的tag处理类 Vzm+Ew _  
Cj\+u\U#  
o tag标签的类型 KrG6z#)Uz  
i8@e}O I  
· 自定义tag标签 Y8{1?LO  
<FT\u{9$  
o tag处理类 #$C]0]|  
$<mL2$.L~  
o tag库描述 |aJ6363f.  
n$Fm~iPo,  
o tag标签示例 H{zuIN/.1  
oxXW`C<  
o 带属性的tag 0BE^qe  
ByvqwJY  
o 带body的tag [F{a-i-  
z9O/MHT[w  
o 定义了脚本变量的tag )K3 vzX  
tg3JU\  
o 具有协作关系的tag x%ag.g2I  
[4rMUS7-m"  
· 自定义tag标签 tvxcd*{  
F+S#m3X  
o 一个迭代tag的例子 ''Ec-b6Q-  
e`1s[ ^B  
o 一个模板tag库 =u"|qD  
Qug'B  
o tag处理类到底是怎样被调用的? >&Q. .`q  
Q.$h![`6  
OBQ!0NM_b  
什么是自定义的tag? ;FflEL<7Y  
H,` XCG  
一个自定义的tag标签是用户定义的一种JSP标记。当一个含有自定义的tag标签的JSP页面被jsp引擎编译成servlet时,tag标签被转化成了对一个称为tag处理类的对象进行的操作。于是当JSP页面被jsp引擎转化为servlet后,实际上tag标签被转化成为了对tag处理类的操作。 S*s9 ?  
G{=$/&St  
自定义tag标签有很多特色,诸如: 6dp_R2zH~o  
I;:_25WGC  
· 可以在JSP页面中自定义tag标签的属性 )p9n|C  
Gn4b\y%%  
· 访问JSP页面中的所有对象 $_5v^QL  
;#yz i2f  
· 可以动态地修改页面输出 j/|qge4  
X&X')hzIt  
· 彼此这间可以相互通信。你可以先创建一个JavaBeans组件,然后在一个tag中调用此JavaBeans组件,同时可以在另一个tag中调用它。 ' qS!n  
~kT{O!x}4  
· tag允许相互嵌套,可以在一个JSP页面中完成一些复杂的交互。 @?? 6)C  
*3Z#r  
tTp`e0L*m  
使用tag标签 XhV"<&v  
O#Hz5 A5  
N6%q%7F.:  
本节主要描述怎样在JSP页面中使用tag标签,以及tag标签的不同类型。 4 jro4B`  
)E2Lf ]  
要使用tag标签,JSP程序员必须做2件事: &r!>2$B\  
(oEA)yc|  
· 声明此tag标签的tag库 H9!*DA<W  
boovCW  
· 实现此tag标签 p:%E>K1<  
^ ?9 ~R"  
声明tag标签所在的tag库 XX6)(  
5] %kWV>  
如果要使用tag标签,则应用JSP的taglib指示符来指定其tag库(注意:taglib要在在使用此tag标签之前声明) ka%pS  
ox#4|<qM  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> $, 42h  
y-k-E/V}  
uri属性定义了唯一的标签库描述(以下简称TLD),它可以是直接是tld文件名或一个独一无二的名字。prefix是用来区别其它TLD中和本TLD中有重名的tag的一种手段。 HX*U2<^  
E#p6A5  
TLD必须以.tld作为扩展名,并且存放在当前应用的WEB-INF目录或其子目录下。你可以通过它的文件名直接引用它,也可以通过别的方式间接地引用它。 o!S_j^p[C  
_nq n|  
以下taglib指示符直接引用一个TLD: %*=FLtBjo  
G[,VPC=  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> C( ;7*]  
b6BIDuRb  
以下的taglib指示符通过一个逻辑名称间接地引用一个TLD: YO+d+5  
q[K)bg{HB  
<%@ taglib uri=”/tutorial-template” prefix=”tt” %> 6d8  
9z}kkYk  
如果是间接引用TLD的话,那你必须还要在web.xml中定义此逻辑名称与tld文件之间的映射,具体做法是在web.xml中加入一个名为taglib的元素: Wfy+7$14M  
hp}8 3.oA  
<taglib> ~VF,qspO  
Mq?21gW  
<taglib-uri>/tutorial-template</taglib-uri> 7?s>u937  
z[OEg HI  
<taglib-location> e(A&VIp  
BJ/%{ C`g  
/WEB-INF/tutorial-template.tld cG6+'=]3<  
\v Go5`  
</taglib-location>  ^k=[P  
n\U6oJN  
</taglib> ']x]X ,  
PnvLXE}F  
B4=gMVp1  
实现此tag标签 enM 3  
6m&I_icM  
J( 60eTwQ  
为了实现tag标签,你有2种方法来存放tag处理类。一、让tag处理类以.class的方式存放于当前应用的WEB-INF/class子目录下,二、如果tag处理类是以JAR包的形式存在的话,那可以放在当前应用的WEB-INF/lib目录下,如果tag处理类要在多个应用中共享,那么它就应放在jsp服务器上的common/lib目录下,对于tomcat来说,就是tomcat/common/lib目录下。 VF.S)='>Eu  
v<4zcMv  
4r$t}t gX  
tag标签类型 n2~rrQ \/p  
E)bP}:4V  
#D8)rs.9  
自定义的tag标签遵循XML语法。它有一个开始标记和一个结束标记,有的还有body(即文本节点): u 05O[>w  
z)Gr`SA<  
<tt:tag> ><HXd+- sd  
(ol 3vt  
body l|9`22G  
QH:i)v*  
</tt:tag> i8F~$6C  
1'U-n{fD  
:+n7oOV  
一个不带body的tag标签如下: 5Jp>2d  
M Cz3RZK  
<tt:tag /> k9 E ?5  
O"GzeEY7  
ZN^Q!v  
简单的tag标签 EBm\rM8  
+dRTHz  
一个没有body和属性的tag标签如下: '1aOdEZA*  
0vEa]ljS  
<tt:simple /> WD]dt!V%  
#'T@mA  
~QXNOtVsN  
带属性的tag标签 l8Ox]%F  
iC">F.9#  
6|9fcIh]B  
自定义标签可以有自己的属性。属性一般在开始标记中定义,语法为 attr=”value”。属性的作用相当于自定义标签的一个参数,它影响着tag处理类的行为。你可以在TLD中详细定义它。 dc* #?G6^  
nr}H;wB  
你可以用一个String常量给一个属性赋值,也可以通过表达式给它赋值,如<%= ...%>。以struts为例,它的logic:present标签就是用的String常量来给属性赋值: hLF@'ln  
@<+(40`*  
<loglic:present parameter = “Clear”> 'tc$#f^:  
&q+ %OPV  
而另一个标签logic:iterate是用表达式来给属性赋值: XOoND  
(1R,   
<logci:iterate collection=”<%= bookDB.getBooks() %>” 99x]DY  
x<].mx  
id=”book” type=”database.BookDetails”> EC7o 3LoND  
rmhB!Lo  
;X>KP,/r$  
带body的tag标签 u:k#1Nn!  
Ty5\zxC|  
一个自定义标签可以包含其它自定义标签、脚本变量、HTML标记或其它内容。 &'Ch[Wo]H  
XyhdsH5%3!  
在下述例子中,此JSP页面使用了struts的logic:present标签,如果些标签定义了parameter=”Clear”的属性,则将清除购物车的内容,然后打印出一条信息: wTLHg2'y^  
rYT3oqpfT  
<logic:present parameter=”Clear”> ]yyfE7{q  
ITTC}  
<% cart.clear(); %> v^pE= f*/  
L/shF}<  
<font color=”#ff0000” size=”+2”><strong> +] uY  
nt7ui*k  
你选择了清除购物车! _-^@Jx[  
0&Qn7L  
</strong></font> ($-o"y"x  
?tBEB5  
</logic:present> |tmD`ndO  
ky*-_  
#nnP.t m  
到底是用属性还是用body来传递信息? ][9M_.  
nt4>9;  
如上所述,我们既可以通过属性,也可以通过body来传递信息。但一般来说,比较简单的类型,如字符串或简单表达式最好采用属性来传递信息。 hFKYRZtP.8  
$`i&\O2*  
}=++Lr4*  
定义脚本变量的tag标签 SFuzH)+VO  
X|b~,X%N  
所谓脚本变量,是指JSP中可以调用的变量或对象。它可由tag标签产生。以下示例阐述了一个tag标签定义了一个名为tx的由JNDI所定义的事务处理对象。脚本变量可以是ejb对象、事务、数据库连接等等: FT=w`NE,+  
StE4n0V  
<tt:lookup id=”tx” type=”UserTransaction” name=”java:comp/UserTransaction” /> UJQ!~g.y]  
ks! G \<I  
<% tx.begin(); %> tTY(I1  
:f `1  
... *l|CrUa  
#fwG~Q(  
Ts^IA67&<  
具有协作关系的tag标签 yjr!8L:m  
>_R5Li  
自定义tag标签之间可以通过共享对象来实现协作。在下述例子中,标签tag1创建了一个名为obj1的对象,在标签tag2仍可以重复使用obj。 h><;TAp  
7Y_S%B:F  
<tt:tag1 attr1=”obj1” value1=”value” /> _M 7AQ5  
Lz4iLLP  
<tt:tag2 attr1=”obj1” /> HYtkSsXLN  
0 {w?u%'  
在以下这个例子当中,如果外层的tag标签创建了一个对象,那么其内层的所有tag标签都可以使用这个对象。由于这样产生的对象没有一个指定的名字,那么就可以将少重名的冲突。这个例子阐述了一系列协作的嵌套对象。 t4nAy)I)P  
\!-X&ws  
<tt:outerTag> k38Ds_sW6d  
mI l_ [  
<tt:innerTag /> yfq"atj  
=oSv=xY  
</tt:outerTag> %lvSO/F+  
[ %r :V"  
.L8S_Mz  
Tag处理类 H -`7T;t~  
K'y;j~`-  
jn]{|QZ  
Tag处理类必须实现Tag接口或BodyTag接口,不过现在一般都流行从TagSupport或BodyTagSupport类中继承,这些类或接口都可以在javax.servlet.jsp.tagext包中找到。 z}Xn>-N-  
?g!py[CrE  
当JSP引擎看到自己的JSP页面中包含有tag标签时,它会调用doStartTag方法来处理tag标签的开头,调用doEndTag方法来处理tag标签的结束。 l( "_JI  
h!$W^Tm2g  
下表说明不同类型的tag所需要不同的处理过程: )wAqaG_d  
x3]es"4Q  
Tag处理类的方法 ]zu" x9-`  
-\LB>\;qn  
Tag标签类型 ;]|Z8#s  
所调用的方法 )t =Cj?5  
G<$UcXg  
基本标签 JGJQ5zt  
doStartTag, doEndTag, release .HMO7n6)8l  
H!,#Z7s  
带属性的标签 <V9L AWeS  
doStartTag, doEndTag, set/getAttribute1...N, release 9Y~A2C  
<s  $~h  
带内容的标签 *V>Iv/(  
doStartTag, doEndTag, release U<*ZY`B3  
T-eeYw?Yf  
带内容的标签,且内容重复循环 Cdc6<8  
doStartTag, doAfterBody, doEndTag, release n pBpYtG  
dqnxhN+&  
带内容的标签,且内容与JSP交互 nx=Zl:Q}  
doStartTag, doEndTag, release, doInitBody, doAfterBody, release 3nxJ`W5j  
MAhcwmZNy  
一个tag处理类可以通过javax.servlet.jsp.PageContext来与JSP交互,通过javax.servlet.jsp.PageContext类,tag处理类可以访问JSP中的request、session和application对像。 J-hP4t&x  
8hGp?Ihu  
如果tag标签是互相嵌套的,那内层的tag处理类可以通过它的parent属性来访问上层的tag处理类。 |0dmdrKD  
(eSa{C\  
一般情况都将所有的tag处理类打成了JAR的包,以便于发布。 m>~%. (/x  
cs,%Zk.xjw  
<$_B J2Z  
Tag库描述(简称TLD) ]7Tjt A.\q  
+:;r} 7Zh  
GKSfr8US4  
Tag库是用xml语言描述的,TLD包括了tag库中所有tag标签的描述,它一般用来被jsp服务器用来校验tag的语法正确性,或者被jsp开发者用来开发新的标签。 8 yQjB-,#  
YX,y7Uhn  
TLD的文件扩展名必须为.tld,而且必须放在当前WEB应用的WEB-INF目录或其子目录中。 90&ld:97  
In5' (UHW:  
一个TLD的内容的开头必须遵守标准的XML开头,用于描述DTD和xml的版本,例如: GAV|x]R  
/`3< @{D  
<?xml version="1.0" encoding="ISO-8859-1" ?> 36e !je  
#"=_GA^.{  
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd"> "^yTH/m  
TLD必须以<taglib>来作为它的根元素,<taglib>的子元素如下表: ggfL d r  
W& w -yZ  
pX+`qxF\  
<taglib>的子元素 r1 )Og  
R6*:Us0\FJ  
Element Pqi>,c<&mL  
Description noV]+1#"V  
rXdI`l#  
tlib-version r1]shb%J?  
Tag库的版本 hU@ 9vU<U  
$xJVUV  
jsp-version Rcfh*"k  
Tag库所需要的jsp的版本 yuWoz*:t  
 5k{a(I  
short-name ANZD7v6a  
助记符,tag的一个别名(可选) }hv>LL  
22)2o lU  
uri 7FMO' 'x  
用于确定一个唯一的tag库 aHvTbpJ  
d#T~xGqz  
display-name KpA iKe  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) I MpEp}7  
QG$LbuZ`  
small-icon 0ZlF#PJA  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) <:fjWy  
:Em[> XA  
large-icon [RTB|0Q  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) 9K-=2hvv  
i!@L`h!rw  
description t ]7>' U  
对tag库的描述(可选) 8HS1^\~(6l  
`9SuDuw;s  
listener -Xb]=Yf-  
参见下面listener元素 < {$zOF}  
e?rp$kq7  
tag nJ<h}*[  
参见下面tag 元素 > r6`bh [4  
S;[9 hI+  
Listener元素 (hEqh nnm`  
g-q~0  
一个tag库可能定义一些类做为它的事件侦听类,这些类在TLD中被称为listener 元素,jsp服务器将会实例化这些侦听类,并且注册它们。Listener元素中有一个叫listener-class的子元素,这个元素的值必须是该侦听类的完整类名。 ,dOd3y'y  
wM8Gz.9,  
Tag元素 UJ3l8 %/`k  
O'a Srjl  
每个tag元素在tag库中都要指出它的名字、类名、脚本变量、tag的属性。其中脚本变量的值可以直接在TLD中定义或通过tag附加信息的类来取得。每个属性描述了这个属性是否可以省略,它的值是否可以通过<%= …%>这样的JSP语法来获得,以及属性的类型。 .gh3"  
L}7c{6!F7  
每一个tag在TLD中对应一个tag元素,下表是tag元素的子元素: -SnP+X!  
n.Iu|,?q  
Tag元素的子元素 icLf; @  
c;C:$B7  
元素名称 *_ {w0U)  
描述 ]{;=<t6  
]-FK6jw  
name qc;9{$?xV  
独一无二的元素名 f^z/s6I0  
f^\qDvPur  
tag-class 7vax[,a I  
Tag标签对应的tag处理类 $$_aHkI j  
@=B'<&g$Xv  
tei-class H48`z'o  
javax.servlet.jsp.tagext.TagExtraInfo的子类,用于表达脚本变量(可选) %Aq+t&-BCX  
ppH5>Y 6c  
body-content R`sU5:n  
Tag标签body的类型 3eX;T +|o  
|7KW'=O  
display-name PZmg7N  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) /2Q@M>  
m08:EX P  
small-icon ?UuJk  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) cD5c&+,&I  
(lBgW z  
large-icon hDTiXc  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) :d\ne  
7/%{7q3G>  
description oju)8H1o#  
此tag标签的描述 X;25G  
4 qMO@E_  
variable IMjz#|c  
提供脚本变量的信息(同tei-class)(可选) #Ux*":  
GAG=4 g  
attribute }#va#Nb(,  
Tag标签的属性名 #-?C{$2I  
0]%0wbY1  
以下章节介绍对于不同类型的tag,如何具体地实现它们。 {YnR]|0&  
n%GlO KC  
PEqO<a1Z8  
简单的tag ~$xLR/{y  
G Xx7/X  
)* 5R/oy,  
tag处理类 g#b[-)Qx  
r:Uqtqxh  
简单的tag处理类必须实现Tag接口的doStartTag和doEndTag方法。当jsp引擎碰到tag标签的开头时,doStartTag被调用,因为简单的tag没有body,所以此方法将返回 SKIP_BODY。当jsp引擎碰到tag标签的结尾时,doEndTag被调用,如果余下的页面还要被计算,那它将返回EVAL_PAGE,否则将会返回SKIP_PAGE。 /;>U0~K  
K8xwPoRL  
以下是例子:对于标签 <tt:simple /> ,它的tag处理类实现如下: G&8)5d[  
KZ_d..l*W  
,Yx"3i,  
public SimpleTag extends TagSupport L7oLV?k  
$=?1>zvF  
{ I!'PvIyO  
AfAg#75q  
public int doStartTag() throws JspException 3>LyEXOW  
U^+xCX<  
{ "f/91gIzm'  
 }NX9"}/  
try{ n/*BK;  
/Xa_Xg7  
pageContext.getOut().print(“Hello.”); ^Qrezl&  
*j9{+yO{ZE  
}catch(Exception e){ FgA'X<  
)c~1s  
throw new JspTagException(“SimpleTag: “ + e.getMessage()); /HCd52  
rw> X JE  
} 1HOYp*{#wP  
R1$O)A}k  
return SKIP_BODY; zzmZ`Ya  
VK)1/b=yT  
} sbnNk(XINQ  
l-|hvv5g  
public int doEndTag() oS3}xT" U  
={_.}   
{ ND);7  
Np$peT[  
return EVAL_PAGE; ':al4m"  
kT|{5Kn&s  
} x0aPY;,N0  
0a<:.}  
} ?1%/G<  
8z,i/:  
:5 XNV6^|  
注意:如果tag标签没有内容的话,那必须定义body-content元素为空,例如 'nH/Z 84  
(Uk1Rt*h  
<body-content>empty</body-content> eteq Mg}M  
Vf?+->-?{  
cspO5S>#  
带属性的tag标签
评价一下你浏览此帖子的感受

精彩

感动

搞笑

开心

愤怒

无聊

灌水
级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
只看该作者 1 发表于: 2007-01-01
tag处理类 8)I,WWj  
 B _;W!  
对于tag标签的每个属性,你必须依照JavaBeans规范来定义其属性,以及get和set方法。以struts的logic:present 标签为例, B I9~% dm  
77y_?di^I  
<logic:present parameter=”Clear”> SCbN(OBN!  
z=ItKoM*<  
与此相应,此tag处理类应有如下方法和定义: MF+J3)  
~lB im$o  
j9)WInYc:  
protected String parameter = null; 3@u<Sa  
GE+ %V7  
public String getParameter() $@ /K/"  
b-sbRR  
{ 5HWVK.  
Z0yy<9q]2  
return this.parameter; ?_Sf  
:4o08M%  
} i={ :6K?^  
Q_p!;3  
public void setParameter(String parameter) 7D5;lM[_  
v0pyyUqS  
{ pz'l9Gp;@  
\etuIFQ#U  
this.parameter = parameter; %onUCN<O`  
g? 7%  
} 7MX nt5qUh  
/SLAg&  
e_Cns&  
注意:如果你的属性名为id,而且你的tag处理类是从TagSupport类继承的,那你就不需要定义它的属性和set和get方法,因为他们早已在TagSupport被定义过了。 ?Bg<74  
` oBlv  
Attribute元素 "S$4pj`<  
?QzA;8H  
对于tag标签的每个属性,你必须定义它是否必须的,它的值是否可以用诸如<%= …%>的表达式来获得,以及它的类型(可选),如果不指定它的类型,那就默认为是java.lang.String类型。如果rtexprvalue元素被定义为true或yes,那么在type元素中就定义了attribute的返回类型。 Z#8O)GK  
Y yI4T/0s_  
<attribute> ZY%]F,Y  
,,*i!%Adw  
<name>attr1</name> V{51wnxT  
jY.iQBhjEB  
<required>true|false|yes|no</required> C[cNwvz  
NzRpI5\.  
<rtexprvalue>true|false|yes|no</rtexprvalue> BIx Z4Ft  
PFP/Pe Ng;  
<type>attribute的返回类型(只用当rtexprvalue为真是才有效)</type> XS!mtd<q  
WU}?8\?U%  
</attribute> \Qa6mt2h  
lYZ5FacqC  
如果tag的某个属性不是必须的,那tag处理类会自动提供一个缺省值。 CuE>=y- "I  
_)4YxmK%  
例如,在logic:present这个tag标签中定义了一个属性叫parameter,但它不是必须的,而且它可以被诸如<%= …%>的表达式来赋值。 J N5<=x5r  
_ZgIm3p0A  
<tag> GWs[a$|  
x50,4J%J'r  
<name>present</name> .(!> *ka|  
U p1&(  
<tag-class>org.apache.struts.taglib.logic.PresentTag</tag-class> y1DP`Ro  
&p\fdR4e  
<body-content>JSP</body-content> /mELnJ^  
yFfa/d  
9Q 4m9}  
[K2\e N~g  
<attribute> k0;ND  
} Qjp,(ye  
<name>parameter</name> 76i)m!  
Nr.maucny  
<required>false</required> 3q*y~5&I  
I`%\ "bF@  
<rtexprvalue>true</rtexprvalue> A aLj.HR  
"^A4!.  
</attribute> fJ!i%</V  
~T<yp  
EC6&#)g;CO  
$4yv)6G  
</tag> v?Q|;<   
} $:uN  
OLAw Rha  
属性元素的校验 2t h\%  
n[zP}YRr  
k(Z+(Y'{q~  
有关于tag标签的有效值可以从tag库的说明文档中获得,当JSP页面被编译时,jsp引擎会强制性地参照TLD中定义的规则进行检查。 /|{Yot e  
y=!"++T]B<  
还有一个方法也可以进行属性元素的校验,就是先继承类TagExtraInfo,然后调用它的isValid方法。这个类同时也起到提供tag中定义的脚本变量信息的作用。 p1B~:9y9X  
]<z4p'F1%  
IsValid方法通过TagData对象来传递属性信息,它包括着tag的所有的属性名-值的信息。由于校验发生在运行时刻,因此这个属性的值将被赋值为TagData.REQUEST_TIME_VALUE。 dQfVdqg  
i#I+   
例如tag标签<tt:twa attr1=”value1” />在TLD中定义如下: hdB.u^!  
a9rn[n1Q  
<attribute> m>4jRr6sF  
?2ZggV  
<name>attr1</name> b-}nv`9C  
>h3r\r\n3  
<required>true</required> +dWx?$n  
K\5'pp1  
<rtexprvalue>true</rtexprvalue> : `D[0  
0i}4T:J@`  
</attribute> pDr%uL  
%U]_1"d,<\  
]d#Lfgo  
这个定义说明了attr1能在运行期间被赋值。 3`@alhD'  
(eS/Q%ZGK  
以下的isValid方法检查attr1属性的值是否属于Boolean类型。注意由于attr1能在运行刻被赋值,那么isValid方法必须检查tag用户是否对此tag进行了运行时刻赋值。 KjR^6v  
_%G)Uz{3  
# 4E@y<l$  
Public class TwaTEI extends TagExtraInfo "bFt+N  
HJl$v#]#+  
{ T( @y#09  
y74Ph:^ k  
public boolean isValid(Tagdata data) C`F*00M{  
fuM+{1}/E  
{ MS{purD  
FC.d]XA%/d  
Object o = data.getAttribute(“attr1”); ` aTkIo:ms  
YxH"*)N  
If(o != null && o != TagData.REQUEST_TIME_VALUE) Kp") %p#  
H\A!oB,sw  
{ Q9X7- \n  
bSmF"H0cP  
if( ( (String)o).toLowerCase().equals(“true”) || FY%v \`@1*  
i3I'n*  
((String)o).toLowerCase().equals(“false”) ) XGE:ZVpW  
tqLn  A  
return true; (fON\)l  
[;M31b3  
else [u[`!L=  
f$a%&X6"-  
return false; ~2xC.DF_N  
iTTe`Zr5y  
} '0_Z:\ laU  
d#:&Uw  
else @MIBW)P<  
jRN*W2]V  
return true; 0ra VC=[  
UkrqHHpy  
} W69 -,w/  
l,Un7]*  
} |He,v/r  
l,}{Y4\G  
KE\p|Xi  
带body的tag t ZUZNKODW  
B<c7&!B  
2 g"_ *[  
tag处理类 910Ym!\{:  
O[Xl*9P  
P<b.;Oz__-  
如果tag标签含有内容,那处理方式会略微有些不同,而且还要视tag处理类是否要与body交互的情况而定。如果要与body交互,那我们认为tag处理类要可能要对body进行操作。 )'8DK$.  
,)mqd2)+"  
Tag处理类不与body交互 6|U0"C#]  
BCV<( @c  
如果tag处理类不与body交互,tag处理类应该实现Tag接口或从TagSupport中派生,如果body要被计算,那么doStartTag方法应返回 EVAL_BODY_INCLUDE,否则应返回SKIP_BODY。 X%"P0P  
)e.Y"5My  
如果tag处理类要对body反复运算,则它应该实现IterationTag或从TagSupport中派生。如果tag处理类认为body还未计算完的话,那它的doStartTag方法和doAfterBody方法必须返回EVAL_BODY_AGAIN。 v)@EK6Nty  
fr S1<+  
Tag处理类与body交互 <VV./W8e9  
%Kd&A*  
如果tag处理类与body交互,那tag处理类应实现BodyTag接口或从BodyTagSupport中派生。这种tag处理类一般要实现doInitBody和doAfterBody方法。 ,]@K6  
gwk$|aT@  
Body允许一些方法来读写它的内容。Tag处理类可以调用body内容的getString或getReader方法来从body中提取信息,也可用 writeOut(out) 方法来将body的内容写入到out对象中。其中out对象通过tag处理类的getPreviousOut方法来获得。 ia15r\4j)  
<{@?c  
如果body的内容需要被计算,那么doStartTag方法必须返回EVAL_BODY_BUFFERED,否则,它将返回 SKIP_BODY。 MdK!Y  
.J' 8d"+  
doInitBody 方法 "'H$YhY]  
Ju$=Tn  
此方法在body内容已经设好,但未被计算之前被调用。你可以根据不同的body内容来制定初始化策略。 `Z]Tp1U  
FUzIuz 6  
doAfterBody方法 &fA`Od6l"  
^,zE Nqg7  
此方法在body内容已被计算后进行调用。 q q}EXq^  
{<~0nLyJS  
和doStartTag方法一样,doAfterBody方法返回一个指示符指示是否要继续计算body,如果要继续计算,则doAfterBody应返回EVAL_BODY_BUFFERED,否则,它应返回SKIP_BODY。 }J .f 5WaG  
a,o)i8G9R<  
release 方法 nd 'K4q  
2V(ye9  
tag处理类调用此方法将它的状态重置为初始状态,并释放所有的私有资源。 A+%oE  
F\ !;}z  
=W)Fa6P3j(  
以下的例子读取body的内容(其中含有一条sql语句),然后将它传递给一个对象,让它进行查询。由于此处body不须重新计算,所以doAfterBody会返回SKIP_BODY。 hGi"=Oud2  
MfUG@  
'U]= T<  
Public class QueryTag extends BodyTagSupport LXj2gsURu%  
>nmby|XtW  
{ E",s]  
5)4*J.  
public int doAfterBody() throws JspTagException *leQd^47  
"UVqkw,vt  
{ DUf=\p6`f  
m`C(y$8fU  
BodyContent bc = getBodyContent(); V x1C4  
k$kq|  
//将body的内容以字符串的格式提取出来 TF 6_4t6  
Hno@  
String query = bc.getString(); N'R^S98x  
~/1kCZB  
//清除body y [e $  
:~loy'  
bc.clearBody(); 2|F.JG^  
Mj |)KDL  
try{ pH.wCD:1n  
6}mbj=E`  
Statement stmt = connection.createStatement(); " |RP_v2  
<4}zl'.  
Result result = stmt.executeQuery(query); /b,M492  
`L`*jA+_  
}catch(SQLException e){ ghd~p@4  
<lZyUd  
throw new JspTagException(“queryTag: “ + e.getMessage() ); [P)'LY6F  
=-jkp  
return SKIP_BODY; (V @g?|LZ  
&'V_80vA  
} x|*v(,7b]!  
*A2J[,?c  
} gWA)V*}f  
+B^ / =3P  
aB<~T[H%h  
body-content元素 gT-'#K2qT  
UK+;/Mtg  
qdh;zAMx  
由于tag可能会有body,你必须用body-content元素来指定body内容的类型: "L.)ML  
.6SdSB ^M  
<body-content>JSP|tagdependent</body-content>  WwbE xn<  
ntkTrei ]  
XyJ*>;q  
如果body的内容是定制的或内部的tag、脚本元素、或HTML广本,则归类为JSP类型。其他的类型,比如上面代码所述的?D?D将sql statement类传给 query tag的这种类型应该标为tagdependent。 leyhiL<  
 CJg &  
注意:实际上body-content的值并不影响tag处理类对body内容的处理,它仅仅是被tag编辑工具用来描述此body的内容。 T+NEw8C?/  
raY5 nc{  
S$\l M<M  
用tags定义脚本变量 0trVmWQ8  
w=d#y )1  
8lI#D)}  
tag处理类 mk_cub@  
7{f&L '  
+o(t5O[G  
tag处理类负责创建或设置页面中定义的脚本变量,用pageContext.setAttribute(name,value,scope)或pageContext.setAttribute(name,value)方法来实现。一般来说,tag处理类通过脚本变量的名称来获取它,脚本变量的名称一般可用get方法来获得。 4][m!dsU  
t5N@ z  
如果脚本变量的值依赖于tag处理类中的上下文中某一对象,那它可用pageContext.getAttribute(name,scope)方法来找到那个对象。一般的处理过程是tag处理类先找到脚本变量,再对其进行处理,然后用pageContext.setAttribute(name,object)的方法来设置它的新值。 84)$ CA+NX  
3v;o`Em&  
对象的生存周期(scope)如下表: ??12 J#  
~\4l*$3(^  
对象的生存周期表 )v;>6(  
('Wo#3b$  
名字 )u]J`.OA  
可访问范围 4;Z`u.1  
生存周期 ZH/^``[.  
{"!V&}  
page VJBVk8P  
当前页面 OGg9e  
一直有效,除非页面向客户提交响应或重定向到一个新页面 Htl6Mr*{  
^DXERt&3  
request Mcc774'*9  
当前页面或当前页面重定向到的页面 jVL<7@_*  
一直有效,除非页面向客户提交响应 ^"v~hjM#  
UevbLt1Y  
session TYWajcch  
当前页面或在同一浏览器窗口中的页面 |M#b`g$JO,  
一直有效,除非关闭当前浏览器、超时、网络故障 K`* 8 *k{  
cy7GiB2'  
application Tk $rwTCl  
整个web应用程序的所有请求 !I]fNTv<  
一直有效,除非发生网络故障、服务器故障 W=}l=o!G.  
p.TR1BHw  
提供关于脚本变量的信息 \$ ^z.  
\lCr~D5  
以下示例定义了一个名为“book”的脚本变量,用来访问程序中关于书的信息: r J ?Y~Q  
mm/U9hbp%  
<bean:define id=”book” name=”bookDB” property=”bookDetails” type=”database.BookDetails” /> I? dh"*Js&  
-VD[iH  
<font color=”red” size=”+2” > 8Fx~i#FT  
FMhwk"4L  
<%= messages.getString(“CartRemoved”) %> )`F? {Sg  
#Bj{ 4OeV  
<strong><jsp:getProperty name=”book” property=”title” /></strong> LdR}v%EH  
*ntq;]  
</font> 4Cke(G  
~cy/\/oO  
当包含此tag的JSP页面被编译时,jsp引擎会自动生成关于此book的同步的代码(同步可以避免几个客户同时访问此book时造成的冲突),要生成同步代码,jsp引擎需要知道此脚本变量的如下信息: WRZi^B8 @  
O7ceSz  
· 脚本变量名称 [Av87!kJ!X  
!vfjo[v  
· 脚本变量所属的类 ySP1WK  
uljd)kLy4O  
· 此脚本变量是否引用了一个新的或已存在的对象 Gv>,Ad ka  
flIdL,  
· 此脚本变量的有效性 iHr{ VQ  
VF!?B>  
有两种办法可以向jsp引擎提供关于脚本变量的信息:在TLD中定义variable子元素,或用tei-class子元素定义一个额外tag信息类。用variable最简单,但可能降低了一些灵活性。 RO'MFU<g  
ZJsc?*@  
Variable元素 gSEj/?  
0`"]mYH  
Variable元素有如下子元素: 6g8{;6x  
sn_]7d+ Q  
· name-given ?D?D 给出的名字,是一个常量 5X\3y4  
,Bp\ i  
· name-from-attribute?D?D 属性名,在编译时给出的属性名 Un^QNd>  
!jMa%;/  
name-given或name-from-attribute两者必须选一,但以下子元素是可选的: P[n` X  
3m#v|52oj  
· variable-class?D?D变量的类型,缺省为java.lang.String。 Z66akr  
r1EccY  
· declare?D?D此脚本变量是否引用了一个新对象,缺省为True。 gR.zL>=_5e  
yU\&\fD>j  
· scope?D?D脚本变量的范围,缺省为NESTED。下表描述了scope的几种类型: Nz#T)MGO`  
{2R b^K  
脚本变量的有效范围 %*e6@Hm  
?,%vndI  
)s,L:{<  
有效性 !~04^(  
方法 p&B98c  
&zlwV"W  
NESTED UA>~xJp=  
在tag标签的开始和结束之间 2al%J%  
如果tag处理类实现BodyTag接口,则在doInitBody和doAfterBody中调用,否则在doStartTag中调用 !Y!Cv %  
@JT9utct  
AT_BEGIN 5(1Zj`>'  
从tag标签的开始一直到页面结束 Ul^/Dh  
如果tag处理类实现BodyTag接口,则在doInitBody、doAfterBody和doEndTag中调用,否则在doStartTag和doEndTag中调用 Z*.fSmT8)  
3^q,'!PfB  
AT_END 4} 'Xrg  
从tag标签的结束一直到页面结束 O;ZU{VY  
在doEndTag中调用 7]d396%  
Yb%H9A  
以struts为例,它的bean:define标签的实现遵循JSP1.1规范,此规范要求使用额外tag信息类来定义脚本变量。Variable元素是JSP1.2规范中加入的。以bean:define标签为例,你可以定义如下variable元素: j*x8K,fN  
b9)%,3-  
<tag> UAnq|NJO  
jiYYDGs77  
<variable> %h g=@7,|  
~1`.iA  
<name-from-attribute>id</name-from-attribute> SOE#@{IXBa  
dI5Z*"`R9  
<variable-class>database.BookDetails</variable-class> lu`\6  
mG7Wu{~=U  
<declare>true</declare> Z6!MX_ep  
UA!h[+Z  
<scope>AT_BEGIN</scope> D5\$xdlJy  
dD1`[%  
</variable> %Xh/16X${  
chQt8Ar3  
</tag> <wFR%Y/j  
&Sj<X`^  
额外tag信息类 .S`Ue,H  
"Fy34T0N  
如果要定义一个额外tag信息类,你要继承javax.servlet.jsp.TagExtraInfo类。一个TagExtraInfo类必须实现getVariableInfo方法,此方法返回一个叫VariableInfo的数组类,它包括如下信息: >J[g)$,  
>"f,'S5*  
· 变量名 BXO(B'1)]  
VE& ?Zd~  
· 变量所属类名 >{~W"  
=<_xUh.  
· 此变量是否引用了一个新对象 Ra'0 ^4t  
}el. qZ  
· 此变量的有效范围 e7t).s)b{  
>1`FR w<  
jsp引擎将一个名为data的参数传给getVariableInfo方法,data中包括tag标签中的所有“属性名?D?D属性值”对。它可以用来向VariableInfo对象提供脚本变量的名字和类名。 P1vr}J  
Vpt)?];P  
以struts为例,它在bean:define标签中定义了一个名为DefineTei的额外tag信息类,用来向脚本变量提供信息。由于脚本变量的名称(book)和类名(database.BookDetails)是通过tag标签的属性来传递的,它们一般定义在VariableInfo的构建代码中,并且可用data.getAttributeString方法来得到这些信息。如果要允许book脚本变量能在从tag开始直到整个JSP页面结束的范围内都可用的话,那它的范围应设为AT_BEGIN。如下所示: R<Ojaj=V  
ta> g:  
1Z'cL~9  
public class DefineTei extends TagExtraInfo `FH Hh  
FviLlly6  
{ -TU7GCb=  
Nb>|9nu O  
public VariableInfo[] getVariableInfo(TagData data) %:h)8e-;  
w (W+Y+up  
{ W=j/2c/  
@X>k@M  
String type = data.getAttributeString(“type”); ^b~&}uU  
Kf76./  
If( type == null) b3wE8Co  
$)mq  
type = “java.lang.Object”; a^'1o9  
$yIcut7  
return new VariableInfo[] { VQZ3&]o  
F8;M++  
new VariableInfo(data.getAttributeString(“id”), LG [ 2u  
;9q3FuR  
type, YPDc /  
?1xBhKq  
true, 3P6pQm'.f  
F 71  
VariableInfo.AT_BEGIN) +uM1#-+h  
KZ6}),p  
}; Bz_['7D  
1.o-2:]E  
} s{NEP/QQJ  
p)f OAr  
} >@[`,  
Y$--Hp4   
KunK.m  
注意:关于额外tag信息类的类名必须要在TLD中的tag标签下的tei-class子元素中定义。因此,DefineTei的tei-class中的定义看起来如下: yUq,9.6Ig  
<tei-class> NZ e3 m  
org.apache.struts.taglib.bean.DefineTagTei lN,b@;  
</tei-class> Y:^~KS=Uz  
N:)`+}  
]}<.Y[!S  
具有协作关系的tag !w[<?+%%n  
`=^29LC#  
 $hPAp}  
tag通过共享对象来进行协作,JSP技术支持2种方式的对象共享。 qDM/ 6xO  
Wcz{": [  
第一种方法是使用pageContext对象进行对象的共享(可支持JSP页面和tag处理类之间的共享),如果在一个tag处理类中要调用由另一个tag处理类创建的对象,可调用pageContext.getAttribute(name, scope)方法。 oIt.Pc~;'#  
zG[fPD  
第二各方式的共享是对于tag之间有嵌套关系而言的,外层的tag所创建的对象对于内层的tag来说是可以共用的。这种形式的共享的好处是减少了可能存在的重名冲突。 doBfpQ2  
S6 $S%$  
要访问一个嵌套tag创建的对象,tag处理类必须先找到此嵌套tag对象,可用TagSupport的静态方法 TagSupport.findAncestorWithClass(from, class)或TagSupport.getParent方法。前者在当不确定此tag是否为嵌套tag对象时使用。一旦它的父类被找到,它就能访问其所有动态或静态创建的对象。静态创建的对象是父类的成员,而动态创建的对象可能是父类的私有对象。诸如此类的对象可以用tag处理类的setValue方法来保存,用getValue方法来获得。 ?|%^'(U}  
/R''R:j  
下例阐述了以上两种共享对象的方法。在这个例子当中,一个查询tag检查一个名为connection的属性名是否在doStartTag中被设置。如果connection属性被设置,tag处理类从pageContext中得到这个connection对象。否则,此tag处理类先找到它的父tag处理类,然后从它的父tag处理类中找到connection对象。  / >Wh  
N;F1Z-9  
0'Tq W9P  
public class QueryTag extends BodyTagSupport +%>s\W+?]  
PkLRQ}  
{ C(3yJzg>y  
i`gsT[JQRX  
private String connectionId; P~#!-9?  
X@b$C~+  
public int doStartTag() throws JspException :t(gD8;  
b)en/mz  
{ jHT4I>\  
YUF!Y9!  
String cid = getConnection(); R 9o:{U]  
F] +t/  
if(cid != null) DGC -`z  
Eg3rbqM- 8  
{ YZ7rs] A  
R# 8D}5[&  
//存在一个connection id,使用它。 r4gkSwy  
5dMIv<#T`  
connection = (Connection) pageContext.getAttribute(cid); C N"V w  
Vt5%A}.VQ  
} j+*VP  
+IuV8XT2(  
else vROl}s;  
#dqZdj@  
{ HLN rI0  
7WiVor$g-  
ConnectionTag ancestorTag = (ConnectionTag)findAncestorWithClass(this, 6](vnS;  
RoxzCFsI\  
ConnectionTag.class); 3hmuF6y~  
3SpDV'}  
if(ancestorTag == null) FMwT4]y  
&m5WmEz>`  
{ ";`ddN3  
{uM0J$P:  
throw new JspTagException(“一个没有connection属性的查询标签必须被一个connection标记嵌套。”); E;$t|~ #  
Ufq"_^4  
} !#rZ eDmw  
~`#.ZMO  
connection = ancestorTag.getConnection(); )FMpfC>An  
3a:(\:?z  
} Y5-X)f  
'an{<82i  
} b/"gkFe#  
kmy?`P10(z  
} W$EX6jTGI  
K *{C:Y  
3_fLaf A  
cK(}B_D$  
此查询标签在JSP页面中的调用形式可以从以下2种定义中任选一种: IQGIU3O  
<!y_L5S|   
.W,< ]L '  
<tt:connection id=”con01” ...> ... </tt:connection> A{>]M@QC2  
izY,t!  
<tt:query id=”balances” connection=”con01” > f4/!iiS}r  
>%qGK-_  
SELECT account, balance FROM acct_table ^M,t`r{  
;1NZY.pyc  
where customer_num = <%= request.getCustno() %> ppR_y  
r4J4|&ym  
</tt:query> 3 V8SKBS  
Uk S86`.  
pA4/ '7nCl  
01H3@0Q6  
>/6v` 8F  
<tt:connection ...> /{>ds-;-  
,PJl32  
<x:query id=”balances”> 0w< iz;30  
t82Bp[t  
SELECT account, balance FROM acct_table &4O"Xs`ka  
OMJr.u  
where customer_num = <%= request.getCustno() %> ] X%bU*4  
_]j=[|q 9  
</x:query> cn<9!2a  
`WWf?g  
</tt:connection> 4yQ4lU,r  
VY=~cVkzS  
GY@Np^>[a  
与此同时,在TLD中必须指定connection属性为可选的,定义如下: 9rn!U2  
]K XknEaxl  
<tag> 0 v/+%%4}  
d^ipf*aLC  
... A |NX"  
OTN"XKa$  
<attribute> U=Z@Ipu5T  
'! yyg#  
<name>connection</name> b2U[W#  
`"GD'Oa  
<required>false</required> (cC5zv*E  
nqgfAQsE)  
</attribute> w V;y]'  
#xYkG5`lm  
</tag>
描述
快速回复

您目前还是游客,请 登录注册
如果您提交过一次失败了,可以用”恢复数据”来恢复帖子内容
认证码:
验证问题:
3+5=?,请输入中文答案:八 正确答案:八