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

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

级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
标准的JSP 标记可以调用JavaBeans组件或者执行客户的请求,这大大降低了JSP开发的复杂度和维护量。JSP技术也允许你自定义taglib,其实换句话说,taglib可以看成是对JSP标记的一种扩展,正如xml是对html的一种扩展一样。taglib通常定义在tag标签库中,这种标签库存放着你自己定义的tag标签。简而言之,如果使用taglib,那么你可以设计自己的JSP标记! h~pQ  
9 ;Qgby  
一般来说,自定义tag标签主要用于操作隐藏对象、处理html提交表单、访问数据库或其它企业级的服务,诸如邮件和目录操作等等。自定义tag标签的使用者一般都是那些对java编程语言非常精通,而且对数据访问和企业级服务访问都非常熟悉的程序员,对于HTML设计者来说,使得他可以不去关注那些较复杂的商业逻辑,而将精力放在网页设计上。同时,它也将库开发者和库使用者进行合理分工,自定义tag标签将那些重复工作进行封装,从而大大提高了生产力,而且可以使得tag库可用于不同的项目中,完美地体现了软件复用的思想。 #J'V,_ wH  
7TtDI=f  
在这篇文章中,我们主要讨论: B4/\=MXb  
()^tw5e'^  
· 什么是自定义tag标签? Og-v][  
oL U!x  
· 怎么使用tag标签? {%Rntb  
sa?s[  
o 声明要使用的tag库 .^xQtnq  
hG2WxYk  
o 找到与之对应的tag处理类 |mQC-=6t;Y  
qm/#kPlM  
o tag标签的类型 H krhd   
XUVBD;"f!  
· 自定义tag标签 RF}R~m9]  
<:>[24LJ{  
o tag处理类 "_0sW3rG  
zI= 9  
o tag库描述 Z&|Dp*Z  
eGW h]%  
o tag标签示例  G){A&F  
OUhlQq\  
o 带属性的tag .I Io   
e}NB ,o  
o 带body的tag \E1CQP-  
=F% <W7  
o 定义了脚本变量的tag 1* ?XI  
2)Q%lEm`SP  
o 具有协作关系的tag ;TKsAU  
R8>17w.  
· 自定义tag标签 X`C ozyYuD  
KK?R|1VK9  
o 一个迭代tag的例子 u p zBd]  
]E|E4K6g  
o 一个模板tag库 q*!Vyk  
gb=tc`  
o tag处理类到底是怎样被调用的? q{}U5(,{0  
h AJ^(|  
d@? zCFD  
什么是自定义的tag? YF(bl1>YC  
F?Fxm*Wa/  
一个自定义的tag标签是用户定义的一种JSP标记。当一个含有自定义的tag标签的JSP页面被jsp引擎编译成servlet时,tag标签被转化成了对一个称为tag处理类的对象进行的操作。于是当JSP页面被jsp引擎转化为servlet后,实际上tag标签被转化成为了对tag处理类的操作。 UNA!vzOb  
 _ 'K6S  
自定义tag标签有很多特色,诸如: z s\N)LyM  
FwV5{-(  
· 可以在JSP页面中自定义tag标签的属性 7O~hA*Z  
.[ s6x5M  
· 访问JSP页面中的所有对象 HggINMG  
qFp]jbU  
· 可以动态地修改页面输出  GPrq(  
a+B3`6  
· 彼此这间可以相互通信。你可以先创建一个JavaBeans组件,然后在一个tag中调用此JavaBeans组件,同时可以在另一个tag中调用它。 xB_7 8X1  
S]ed96V v  
· tag允许相互嵌套,可以在一个JSP页面中完成一些复杂的交互。 )0\D1IFJ  
"td ,YVK  
je74As[  
使用tag标签 H on,-<  
 GG(}#Z5h  
b?-KC\}v  
本节主要描述怎样在JSP页面中使用tag标签,以及tag标签的不同类型。 NftR2  
3 jghV?I{T  
要使用tag标签,JSP程序员必须做2件事: -+0!Fkt@,  
Ny$N5/b!!  
· 声明此tag标签的tag库 bwK1XlfD.s  
u)~::2BXAn  
· 实现此tag标签 L2%npps  
ybcCq]cgt  
声明tag标签所在的tag库 +FC+nE}O  
2UMX%+ "J  
如果要使用tag标签,则应用JSP的taglib指示符来指定其tag库(注意:taglib要在在使用此tag标签之前声明) 8#|PJc  
^V"08  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> 2E.D0E Cu  
z>HM$n`YD  
uri属性定义了唯一的标签库描述(以下简称TLD),它可以是直接是tld文件名或一个独一无二的名字。prefix是用来区别其它TLD中和本TLD中有重名的tag的一种手段。 #TIlM]5%  
L-|u=c-6  
TLD必须以.tld作为扩展名,并且存放在当前应用的WEB-INF目录或其子目录下。你可以通过它的文件名直接引用它,也可以通过别的方式间接地引用它。 CtHsi8m  
2 U3WH.o  
以下taglib指示符直接引用一个TLD: IIAm"=*  
Y+C6+I<3  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> ?^U1~5ff)  
&g!yRvM!;Q  
以下的taglib指示符通过一个逻辑名称间接地引用一个TLD: p@3 <{kLm  
iwfH~  
<%@ taglib uri=”/tutorial-template” prefix=”tt” %> .G>6_n3  
} O:l]O`  
如果是间接引用TLD的话,那你必须还要在web.xml中定义此逻辑名称与tld文件之间的映射,具体做法是在web.xml中加入一个名为taglib的元素: qJK6S4O]  
U3pMv|b  
<taglib> ei @$_w*TH  
Sj;:*jk!h  
<taglib-uri>/tutorial-template</taglib-uri> X1="1{8H  
KS;Wr6]@(O  
<taglib-location> +2m\Sv V  
Cdc=1,U(  
/WEB-INF/tutorial-template.tld \O\veB8  
R}$A>)%dx  
</taglib-location> 4Z/ ]7Ie  
{WuUzq`  
</taglib> #Qd"d3QG  
?ehUGvV2  
(y?`|=G-xT  
实现此tag标签 wTn"  
cC$E"m  
`3vt.b  
为了实现tag标签,你有2种方法来存放tag处理类。一、让tag处理类以.class的方式存放于当前应用的WEB-INF/class子目录下,二、如果tag处理类是以JAR包的形式存在的话,那可以放在当前应用的WEB-INF/lib目录下,如果tag处理类要在多个应用中共享,那么它就应放在jsp服务器上的common/lib目录下,对于tomcat来说,就是tomcat/common/lib目录下。 R-5e9vyS  
/&RS+By(i  
XtIY8wsP  
tag标签类型 ^oZD44$  
KCfcEz  
$B@K  
自定义的tag标签遵循XML语法。它有一个开始标记和一个结束标记,有的还有body(即文本节点): #.<(/D+  
AeEF/*  
<tt:tag> 'In qa;TQz  
88+J(^y>  
body r%II` i  
CQ#%v%  
</tt:tag> 5x}Or fDU  
v H vwH  
UzUt=s!^H  
一个不带body的tag标签如下: X-5&c$hv  
6M@m`c  
<tt:tag /> Zc*gRC  
^4tz*i  
} "AGX  
简单的tag标签 E" b" VB  
vU, ]UJ}  
一个没有body和属性的tag标签如下: } mEsb?  
G `JXi/#`  
<tt:simple /> 2_;3B4GDF  
.8Gmy07  
/qO?)p3gk  
带属性的tag标签 M-NY&@Nj  
Z#062NL "  
fQ~YBFhlr  
自定义标签可以有自己的属性。属性一般在开始标记中定义,语法为 attr=”value”。属性的作用相当于自定义标签的一个参数,它影响着tag处理类的行为。你可以在TLD中详细定义它。 4vf,RjB-5  
!e:HE/&>i  
你可以用一个String常量给一个属性赋值,也可以通过表达式给它赋值,如<%= ...%>。以struts为例,它的logic:present标签就是用的String常量来给属性赋值: WAp#[mW.fx  
n*i1QC  
<loglic:present parameter = “Clear”> G1:2MPH  
Qrt> vOUE7  
而另一个标签logic:iterate是用表达式来给属性赋值: wvNddu>@  
ceGo:Aa<)  
<logci:iterate collection=”<%= bookDB.getBooks() %>”  JS!  
+vCW${U  
id=”book” type=”database.BookDetails”> [&p^h  
%-~T;_.  
){XG%nC  
带body的tag标签 JheF}/Bx  
UZqk2D  
一个自定义标签可以包含其它自定义标签、脚本变量、HTML标记或其它内容。 V7i1BR8G  
|.[4$C  
在下述例子中,此JSP页面使用了struts的logic:present标签,如果些标签定义了parameter=”Clear”的属性,则将清除购物车的内容,然后打印出一条信息: #[ hJm'G  
0Xw3h^%  
<logic:present parameter=”Clear”> $5a%hK  
b7? 2Pu  
<% cart.clear(); %> [lX3":)  
-( +/u .  
<font color=”#ff0000” size=”+2”><strong> @~`2L o/  
QyX ?  
你选择了清除购物车! Kly`V]XE  
&d^u$Y5  
</strong></font> 3ws}E6\D  
'1yy&QUZq  
</logic:present> tL~?)2uEN  
JOJ? .H&su  
*,d>(\&[f  
到底是用属性还是用body来传递信息? #35@YMF  
6dq*ncNin  
如上所述,我们既可以通过属性,也可以通过body来传递信息。但一般来说,比较简单的类型,如字符串或简单表达式最好采用属性来传递信息。 CGkCLd*s]  
0`dMT>&I  
o`]u&  
定义脚本变量的tag标签 XK4idC  
4`#3p@-  
所谓脚本变量,是指JSP中可以调用的变量或对象。它可由tag标签产生。以下示例阐述了一个tag标签定义了一个名为tx的由JNDI所定义的事务处理对象。脚本变量可以是ejb对象、事务、数据库连接等等: /|2#s%|-=  
-wjvD8fL  
<tt:lookup id=”tx” type=”UserTransaction” name=”java:comp/UserTransaction” /> UP}5Eh  
yp:_W@  
<% tx.begin(); %> ONw;NaE,  
tJ,x>s?Y  
... ?4i:$.A Y  
4#BoS9d2I<  
)R`w{V  
具有协作关系的tag标签 aPMqJ#fIr  
Q1?G7g]N  
自定义tag标签之间可以通过共享对象来实现协作。在下述例子中,标签tag1创建了一个名为obj1的对象,在标签tag2仍可以重复使用obj。 9@."Y>1G  
+aWI"d--h  
<tt:tag1 attr1=”obj1” value1=”value” /> uk~4R@=&H  
;/8oP ;X2  
<tt:tag2 attr1=”obj1” /> __,1;=  
1 k}U+  
在以下这个例子当中,如果外层的tag标签创建了一个对象,那么其内层的所有tag标签都可以使用这个对象。由于这样产生的对象没有一个指定的名字,那么就可以将少重名的冲突。这个例子阐述了一系列协作的嵌套对象。 HrZ\=1RB  
#}rv)  
<tt:outerTag> Q@-7{3  
BI,j/SRK  
<tt:innerTag /> ~rX2oLw{&  
4^0L2BVcv  
</tt:outerTag> G.} 3hd0  
s]=s|  
;h"?h*}m!\  
Tag处理类 ,HFoy-Yq  
}#/,nJm'  
YkKq}DXj  
Tag处理类必须实现Tag接口或BodyTag接口,不过现在一般都流行从TagSupport或BodyTagSupport类中继承,这些类或接口都可以在javax.servlet.jsp.tagext包中找到。 <([1(SY2e  
.iB?:  
当JSP引擎看到自己的JSP页面中包含有tag标签时,它会调用doStartTag方法来处理tag标签的开头,调用doEndTag方法来处理tag标签的结束。 'e4  ;,m  
RqIic\aD  
下表说明不同类型的tag所需要不同的处理过程: /f7Fv*z/  
`"<} B"s  
Tag处理类的方法 6/Coi,om  
|*im$[g=-  
Tag标签类型 e'c~;Z\A  
所调用的方法 FN&.PdRT  
U>z8gdzu  
基本标签 pA*cF!tq 7  
doStartTag, doEndTag, release /f9jLY +  
@i9T),@  
带属性的标签 >~5>)yN_a1  
doStartTag, doEndTag, set/getAttribute1...N, release pOn>m1|  
.1.Bf26}d  
带内容的标签 8S>T1st  
doStartTag, doEndTag, release J['paHSF  
&\$l%icuo  
带内容的标签,且内容重复循环 &r6VF/  
doStartTag, doAfterBody, doEndTag, release ~(xIG  
c D+IMlT  
带内容的标签,且内容与JSP交互 Mlp[xk|  
doStartTag, doEndTag, release, doInitBody, doAfterBody, release '[fo  
VR>;{>~  
一个tag处理类可以通过javax.servlet.jsp.PageContext来与JSP交互,通过javax.servlet.jsp.PageContext类,tag处理类可以访问JSP中的request、session和application对像。 fL8+J]6A6  
p*rBT,'  
如果tag标签是互相嵌套的,那内层的tag处理类可以通过它的parent属性来访问上层的tag处理类。 pNo<:p  
05\A7.iy  
一般情况都将所有的tag处理类打成了JAR的包,以便于发布。 'Dq!o[2y  
7B$iM,}.b  
x8 sSb:N  
Tag库描述(简称TLD) (L?fYSP!  
yFT)R hN  
"$? f&*  
Tag库是用xml语言描述的,TLD包括了tag库中所有tag标签的描述,它一般用来被jsp服务器用来校验tag的语法正确性,或者被jsp开发者用来开发新的标签。 d FF[2  
 ? {Lp  
TLD的文件扩展名必须为.tld,而且必须放在当前WEB应用的WEB-INF目录或其子目录中。 &Z_W*D  
W^W^5-'"D,  
一个TLD的内容的开头必须遵守标准的XML开头,用于描述DTD和xml的版本,例如: J3fcnI  
'Pudy\Ab  
<?xml version="1.0" encoding="ISO-8859-1" ?> $-$^r;  
oXg KuR  
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd"> 32=Gq5pOc  
TLD必须以<taglib>来作为它的根元素,<taglib>的子元素如下表: N9D<wAK##)  
A-O@e e  
U3 e3  
<taglib>的子元素 *f:^6h  
bmotR8d  
Element cbl2D5s+i]  
Description _yyQ^M/  
Gw*n,*pz  
tlib-version 0+0+%#?  
Tag库的版本 e g#.f`  
u0^: XwZ!  
jsp-version E0^~i:M k  
Tag库所需要的jsp的版本 *r)/.rK_  
E8WOXoP(  
short-name D L_{q6ZK  
助记符,tag的一个别名(可选)  M SU|T  
B~cQl  
uri q28i9$Yqj\  
用于确定一个唯一的tag库 %_wX9Z T  
2l#Ogn`k  
display-name MJJy mi'b  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) SUXRWFl  
T^8t<S@`  
small-icon udDhJ?  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) F kp;G  
nZa.3/7dJ  
large-icon z!5^UD8"W  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) mxhO: .l  
sn&y;Vc[$  
description `'[u%UE  
对tag库的描述(可选) LQ"56PP<  
*ta ``q  
listener NIeT.!  
参见下面listener元素 5 fjeBfy  
_*1/4^  
tag w{Wz^=';  
参见下面tag 元素  /E/J<  
etj8M y6=  
Listener元素 ;BqYhi  
"jzU`  
一个tag库可能定义一些类做为它的事件侦听类,这些类在TLD中被称为listener 元素,jsp服务器将会实例化这些侦听类,并且注册它们。Listener元素中有一个叫listener-class的子元素,这个元素的值必须是该侦听类的完整类名。 !CROc}  
7=t4;8|j;  
Tag元素 rl9YB %P  
DPJ#Y -0  
每个tag元素在tag库中都要指出它的名字、类名、脚本变量、tag的属性。其中脚本变量的值可以直接在TLD中定义或通过tag附加信息的类来取得。每个属性描述了这个属性是否可以省略,它的值是否可以通过<%= …%>这样的JSP语法来获得,以及属性的类型。 M"2Tuwz  
~k?7XF I  
每一个tag在TLD中对应一个tag元素,下表是tag元素的子元素: L,| 60*  
u-3A6Q  
Tag元素的子元素 c4oQ4  
jEsP: H(0^  
元素名称 S,m)yh.  
描述 Mxn>WCPo  
d6-a\]gF  
name ahA21W` k  
独一无二的元素名 Zf |%t  
|B njT*_9  
tag-class s_ -G`xT>{  
Tag标签对应的tag处理类 $*^Ms>Pa_  
R+FBCVU&TJ  
tei-class V& <vRIsN  
javax.servlet.jsp.tagext.TagExtraInfo的子类,用于表达脚本变量(可选) ^$SI5WK&)  
* VH!<k[n  
body-content cj@Ygc)n  
Tag标签body的类型 n5A0E2!  
0'`>20Y  
display-name Iodk1Y;  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) >6Y\CixN  
/=A?O\B7  
small-icon ('pNAn!]  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) t\E#8  
%geiJ z  
large-icon T>s~bIzL*e  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) :l8n)O3  
D ::),,  
description -! Hn,93  
此tag标签的描述 L6Ykv/V  
NS @j`6/U  
variable abkl)X>k  
提供脚本变量的信息(同tei-class)(可选) W"+*%x  
"5u*C#T2$  
attribute BpZE  
Tag标签的属性名 uyMxBc%6  
qc\]~]H]r  
以下章节介绍对于不同类型的tag,如何具体地实现它们。 "  m<]B  
LO<R<zz  
@6 uB78U4O  
简单的tag k'{'6JR  
.ml24SeC  
fEE[h uG  
tag处理类 DcA{E8Y  
*,X;4?:,  
简单的tag处理类必须实现Tag接口的doStartTag和doEndTag方法。当jsp引擎碰到tag标签的开头时,doStartTag被调用,因为简单的tag没有body,所以此方法将返回 SKIP_BODY。当jsp引擎碰到tag标签的结尾时,doEndTag被调用,如果余下的页面还要被计算,那它将返回EVAL_PAGE,否则将会返回SKIP_PAGE。 jIwz G+)$P  
0P^RciC f  
以下是例子:对于标签 <tt:simple /> ,它的tag处理类实现如下: (:Rj:8{  
AJt *48H*G  
T;qP"KWZ  
public SimpleTag extends TagSupport /) Bk r/  
x zu)``?  
{ .'JO7of  
_Q,`Qn@|BD  
public int doStartTag() throws JspException z^+f3-Z  
U|. kAI*  
{ Ecp]fUQK  
Y~#m-y  
try{ 4Ei*\:  
=mxG[zDtQ  
pageContext.getOut().print(“Hello.”); XQ]noaU  
#4iSQ$0  
}catch(Exception e){ ^JZ]?iny  
e/JbRbZX  
throw new JspTagException(“SimpleTag: “ + e.getMessage()); 5xe} ljo  
\,)('tUE  
} L,c@Z@  
r18eu B%  
return SKIP_BODY;  P_6oMR  
42E]&=Cet  
} H)z}6[`  
p;cNmMm  
public int doEndTag() :,%~R2  
$(B|$e^:(  
{ ^N#B( F  
>Q#h,x~vu  
return EVAL_PAGE; Wsya:9|  
{Qbg'|HO=l  
} 7{>mm$^|V  
9$ZQuHSw 7  
} _0dm?=  
_|reo6  
H <41H;m  
注意:如果tag标签没有内容的话,那必须定义body-content元素为空,例如 ewHk (ru  
%^tKt  
<body-content>empty</body-content> wb~B Y  
b>SG5EqU@  
l =~EweuM  
带属性的tag标签
评价一下你浏览此帖子的感受

精彩

感动

搞笑

开心

愤怒

无聊

灌水
级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
只看该作者 1 发表于: 2007-01-01
tag处理类 +l'l*<  
MYNNeO  
对于tag标签的每个属性,你必须依照JavaBeans规范来定义其属性,以及get和set方法。以struts的logic:present 标签为例, VwJ A  
[`pp[J-~7  
<logic:present parameter=”Clear”> sZ,xbfZby  
8Ld{Xg  
与此相应,此tag处理类应有如下方法和定义: SQ&nQzL  
A$d)xq-]K  
*} @Y"y  
protected String parameter = null; Wk<heF  
I)7STzlMj.  
public String getParameter() b>g&Pf#N!  
2OT RP4U  
{ CVUA7eG+  
*Rm"3S  
return this.parameter; ws}cMX]*  
; '6`hZ  
} RE)!b  
2kukQj (n  
public void setParameter(String parameter) h[eC i  
C7PVJnY0  
{ 0xE37Ld,  
2S%[YR>>  
this.parameter = parameter; 0F48T<i  
Aw?i6d  
} RHO | g0  
rdj_3Utv  
fv@mA--  
注意:如果你的属性名为id,而且你的tag处理类是从TagSupport类继承的,那你就不需要定义它的属性和set和get方法,因为他们早已在TagSupport被定义过了。 _{Z!$q6,  
9ZXkuP9vm  
Attribute元素 \vg(@)$q   
 ;IV  
对于tag标签的每个属性,你必须定义它是否必须的,它的值是否可以用诸如<%= …%>的表达式来获得,以及它的类型(可选),如果不指定它的类型,那就默认为是java.lang.String类型。如果rtexprvalue元素被定义为true或yes,那么在type元素中就定义了attribute的返回类型。 LAs#g||M  
*LuR <V  
<attribute> BQWhTS7  
d `MTc  
<name>attr1</name> J!{"^^*  
GgT 5'e;N  
<required>true|false|yes|no</required> +lYo5\1=  
'%Fg+cZN\  
<rtexprvalue>true|false|yes|no</rtexprvalue> t+9[ki  
-d-vzri  
<type>attribute的返回类型(只用当rtexprvalue为真是才有效)</type> ~,Y xUn8@  
Fw{:fFZC[  
</attribute> h@kq>no  
WZ@hP'Zc  
如果tag的某个属性不是必须的,那tag处理类会自动提供一个缺省值。 rgo#mTQ_  
yP<ngi^s=  
例如,在logic:present这个tag标签中定义了一个属性叫parameter,但它不是必须的,而且它可以被诸如<%= …%>的表达式来赋值。  ujin+;1  
z6'Cz}%EP'  
<tag> 3#\++h]QZ  
IvZ,|R?  
<name>present</name> 7{z\^R^O  
@n|Mr/PAj  
<tag-class>org.apache.struts.taglib.logic.PresentTag</tag-class> -G'U\EXT  
UY5wef2sF  
<body-content>JSP</body-content> 8'sT zB]  
w]@H]>sHd  
?T1vc  
q g2 fTe  
<attribute> og[cwa_  
lwSZ pS  
<name>parameter</name> }yzCq+  
QG1+*J76b@  
<required>false</required> !l(D0 C  
?8U#,qq#`  
<rtexprvalue>true</rtexprvalue> s7d4)A%  
?d!*[Ke8  
</attribute> ?2(5 2?cJ  
!+FrU'^  
Q6 oM$qiM  
z@<OR$/`L  
</tag> u+7S/9q8  
REg&[e+%  
n[K LY!  
属性元素的校验 bmzY^ %a  
tFEY8ut{  
OH >#f6`[  
有关于tag标签的有效值可以从tag库的说明文档中获得,当JSP页面被编译时,jsp引擎会强制性地参照TLD中定义的规则进行检查。 }/bxe0px  
]Y3NmL  
还有一个方法也可以进行属性元素的校验,就是先继承类TagExtraInfo,然后调用它的isValid方法。这个类同时也起到提供tag中定义的脚本变量信息的作用。 PQd*)6K:A  
wPE\?en  
IsValid方法通过TagData对象来传递属性信息,它包括着tag的所有的属性名-值的信息。由于校验发生在运行时刻,因此这个属性的值将被赋值为TagData.REQUEST_TIME_VALUE。 88&M8T'AP  
]qd$rX   
例如tag标签<tt:twa attr1=”value1” />在TLD中定义如下: &wa2MNCG8  
,*kh{lJ  
<attribute> tE8aL{<R  
]5O]=^ u0  
<name>attr1</name> ^? V9  
^7Rc\   
<required>true</required> Yi?v |H<a  
ZX8 AB  
<rtexprvalue>true</rtexprvalue> 1j*E/L  
y3 "+4e  
</attribute> 5La' I7q  
eH_< <Xh!v  
XfQK kol  
这个定义说明了attr1能在运行期间被赋值。 gs"w 0[$  
I}sb0 Q&  
以下的isValid方法检查attr1属性的值是否属于Boolean类型。注意由于attr1能在运行刻被赋值,那么isValid方法必须检查tag用户是否对此tag进行了运行时刻赋值。 _. &N@k  
["_+~*  
I~ 1Rt+:  
Public class TwaTEI extends TagExtraInfo m9=93W?   
Pi hpo  
{ J#DN2y <  
)Drif\FF)  
public boolean isValid(Tagdata data) +;ylld  
#|"M  
{ (zX75QSKV  
*!.anbo@?z  
Object o = data.getAttribute(“attr1”); 8|{d1dy  
r i/CLq^D  
If(o != null && o != TagData.REQUEST_TIME_VALUE) dw>1Ut{"3  
z*)kK  
{ N(l  
$DlO<  
if( ( (String)o).toLowerCase().equals(“true”) || K=Z.<f  
onU\[VvM  
((String)o).toLowerCase().equals(“false”) ) {O6yJckH  
'Rb tcFb   
return true; QuIZpP=  
f+lPQIB  
else +a"f)4\  
gtnu/ Q  
return false; (DkfLadB  
w|1O-k`  
} Mi} .  
Bm5\*Xd1(  
else 4-?zW  
!'#GdRstv  
return true; @\WeI"^F8  
8shx7"  
} B|"-Ed  
{kghZur  
} z22:O"UHa  
(]` rri*^  
 20]p<  
带body的tag jp7cPpk:LG  
NRT@"3,1YP  
z?@N+||,.  
tag处理类 =gB8(1g8  
>9NC2%61S  
j[A:So  
如果tag标签含有内容,那处理方式会略微有些不同,而且还要视tag处理类是否要与body交互的情况而定。如果要与body交互,那我们认为tag处理类要可能要对body进行操作。 [:zP]l.|  
^'n;W<\p)  
Tag处理类不与body交互 Q*hXFayx  
p^1~o/  
如果tag处理类不与body交互,tag处理类应该实现Tag接口或从TagSupport中派生,如果body要被计算,那么doStartTag方法应返回 EVAL_BODY_INCLUDE,否则应返回SKIP_BODY。 @ qS Z=  
X"sJiFS  
如果tag处理类要对body反复运算,则它应该实现IterationTag或从TagSupport中派生。如果tag处理类认为body还未计算完的话,那它的doStartTag方法和doAfterBody方法必须返回EVAL_BODY_AGAIN。 H*P[tyz$  
{DapXx  
Tag处理类与body交互 @)C.IQ~  
`pjB^--w  
如果tag处理类与body交互,那tag处理类应实现BodyTag接口或从BodyTagSupport中派生。这种tag处理类一般要实现doInitBody和doAfterBody方法。 w*]FJ-b<.j  
HQNpf1=D  
Body允许一些方法来读写它的内容。Tag处理类可以调用body内容的getString或getReader方法来从body中提取信息,也可用 writeOut(out) 方法来将body的内容写入到out对象中。其中out对象通过tag处理类的getPreviousOut方法来获得。 F5y&"Y_  
6 ZAZJn|  
如果body的内容需要被计算,那么doStartTag方法必须返回EVAL_BODY_BUFFERED,否则,它将返回 SKIP_BODY。 PQ{5*}$N  
CQPq5/@Y4  
doInitBody 方法 XE]"RD<z  
4y.qtiIP>$  
此方法在body内容已经设好,但未被计算之前被调用。你可以根据不同的body内容来制定初始化策略。 &smZ;yb|'h  
!4T!@"#  
doAfterBody方法 m8V}E& 6  
lL&U ioo}D  
此方法在body内容已被计算后进行调用。 s!S_Bt):3  
g4y& 6!g  
和doStartTag方法一样,doAfterBody方法返回一个指示符指示是否要继续计算body,如果要继续计算,则doAfterBody应返回EVAL_BODY_BUFFERED,否则,它应返回SKIP_BODY。 I_ AFHrj  
(*_lLM@Cd  
release 方法 z8XWp[K  
{.?pl]Zl6  
tag处理类调用此方法将它的状态重置为初始状态,并释放所有的私有资源。 dvM%" k  
.%!^L#g  
TT no  
以下的例子读取body的内容(其中含有一条sql语句),然后将它传递给一个对象,让它进行查询。由于此处body不须重新计算,所以doAfterBody会返回SKIP_BODY。 %OsxXO?  
B}"V.Msv/  
<'QI_mP*  
Public class QueryTag extends BodyTagSupport )}P/xY0  
l&*= .Zc7!  
{ ^]D+H9Tl  
JLt%G^W >  
public int doAfterBody() throws JspTagException ^X?uAX-RP|  
:5F(,Z_  
{ l"7#(a  
;XQ27,K&  
BodyContent bc = getBodyContent(); !zsrORF{  
kZ PL$ \/A  
//将body的内容以字符串的格式提取出来 CvR-lKV<  
K {  FZ/  
String query = bc.getString(); |+KwyHE`9  
_ds;:*N+qA  
//清除body %E"v@  
JL>frS3M  
bc.clearBody(); UZs'H"K  
:>/6:c?atG  
try{ CYlS8j  
-$X4RS  
Statement stmt = connection.createStatement(); h#c7v !g  
zkiwFEHA=  
Result result = stmt.executeQuery(query); !??g:2  
xI.0m  
}catch(SQLException e){ Zu<S<??Jf  
-w>ss&  
throw new JspTagException(“queryTag: “ + e.getMessage() ); ~ivOSr7s}  
:wN !E{0j  
return SKIP_BODY; 1J72*`4OK  
S;y4Z:!  
} E [6:}z<  
>t<\zC|~w  
} r6R@"1/  
3Fxr=  
E NCWOj  
body-content元素 AW E ab  
awI{%u_(nA  
Y%?*Lj|  
由于tag可能会有body,你必须用body-content元素来指定body内容的类型: bdY:-8!3  
6(BgnH8oc  
<body-content>JSP|tagdependent</body-content> ^}{x).  
1;DRcVyS+  
V#b=mp  
如果body的内容是定制的或内部的tag、脚本元素、或HTML广本,则归类为JSP类型。其他的类型,比如上面代码所述的?D?D将sql statement类传给 query tag的这种类型应该标为tagdependent。 @OGG]0 J  
fUGappb  
注意:实际上body-content的值并不影响tag处理类对body内容的处理,它仅仅是被tag编辑工具用来描述此body的内容。 Zxhbnl6  
YaL:6[6  
,tcUJ}l  
用tags定义脚本变量 89;@#9  
6Ol9P56j  
H9PnJr8 \  
tag处理类 1q@R04i  
4P"bOt5izR  
FUlhEH  
tag处理类负责创建或设置页面中定义的脚本变量,用pageContext.setAttribute(name,value,scope)或pageContext.setAttribute(name,value)方法来实现。一般来说,tag处理类通过脚本变量的名称来获取它,脚本变量的名称一般可用get方法来获得。 )TKn5[<4  
(Li0*wRb  
如果脚本变量的值依赖于tag处理类中的上下文中某一对象,那它可用pageContext.getAttribute(name,scope)方法来找到那个对象。一般的处理过程是tag处理类先找到脚本变量,再对其进行处理,然后用pageContext.setAttribute(name,object)的方法来设置它的新值。 zsd1n`r  
6}?d%K  
对象的生存周期(scope)如下表: p:K%-^  
~;a \S3  
对象的生存周期表 HsUh5;  
@K+gh#  
名字 uo J0wG.  
可访问范围 f$6N  
生存周期 h6OQeZ.  
]@ke_' "  
page i;U*Y *f  
当前页面 "M!m-]  
一直有效,除非页面向客户提交响应或重定向到一个新页面 6 Bdxdx*zt  
%Zbm%YaW5  
request /PeT4hW}  
当前页面或当前页面重定向到的页面 eU@Mv5&6  
一直有效,除非页面向客户提交响应 5 7t.Ud  
1kw*Q:   
session )dqNN tS  
当前页面或在同一浏览器窗口中的页面 eBs.RR ]O  
一直有效,除非关闭当前浏览器、超时、网络故障 7s#8-i  
oI[rxr  
application xVbRCu#Z  
整个web应用程序的所有请求 1:<(Q2X%  
一直有效,除非发生网络故障、服务器故障 rhy-o?  
} `r.fD  
提供关于脚本变量的信息 jx}'M$TA  
Kx&" 9g$  
以下示例定义了一个名为“book”的脚本变量,用来访问程序中关于书的信息: 4xr^4\ lk  
d1/9 A-{  
<bean:define id=”book” name=”bookDB” property=”bookDetails” type=”database.BookDetails” /> @ci..::5  
BWy-R6br  
<font color=”red” size=”+2” > X-_VuM_p  
l>b'b e9  
<%= messages.getString(“CartRemoved”) %> .=TXi<8Brw  
 \20} /&  
<strong><jsp:getProperty name=”book” property=”title” /></strong> "mQcc }8  
:;yrYAyT3  
</font> }O>1tauI  
`G/g/>y  
当包含此tag的JSP页面被编译时,jsp引擎会自动生成关于此book的同步的代码(同步可以避免几个客户同时访问此book时造成的冲突),要生成同步代码,jsp引擎需要知道此脚本变量的如下信息: kj[box N  
)J> dGIb  
· 脚本变量名称 1=C12  
NWvIwt{  
· 脚本变量所属的类 _<FUS'"  
ThgJ '  
· 此脚本变量是否引用了一个新的或已存在的对象 G^#>HE|  
?z#*eoPr  
· 此脚本变量的有效性 Fd\uTxykp  
]6[+tpx  
有两种办法可以向jsp引擎提供关于脚本变量的信息:在TLD中定义variable子元素,或用tei-class子元素定义一个额外tag信息类。用variable最简单,但可能降低了一些灵活性。 3CjixXaA$  
QfAmGDaYQ  
Variable元素 _^#eO`4"  
+cqUp6x.  
Variable元素有如下子元素: q,@# cQBV  
h!%y,4IBR  
· name-given ?D?D 给出的名字,是一个常量 2O Ur">_  
< $e#o H  
· name-from-attribute?D?D 属性名,在编译时给出的属性名 69)"T{7  
&Wcz~Gx3Q  
name-given或name-from-attribute两者必须选一,但以下子元素是可选的: <tF q^qB  
(,#m+  
· variable-class?D?D变量的类型,缺省为java.lang.String。 a;Y:UwD9*  
&RARK8 ^  
· declare?D?D此脚本变量是否引用了一个新对象,缺省为True。 xS tsw5d  
6h)_{| L)  
· scope?D?D脚本变量的范围,缺省为NESTED。下表描述了scope的几种类型: ]"uG04"Vk  
*>:phs~r{  
脚本变量的有效范围 \f? K74  
_Ffg"xoC  
" WQ6[;&V  
有效性 ]zaTX?F:  
方法 IiqqdU]  
,o%by5j"^N  
NESTED UIyLtoxu  
在tag标签的开始和结束之间 %p )"_q!ge  
如果tag处理类实现BodyTag接口,则在doInitBody和doAfterBody中调用,否则在doStartTag中调用 cMZy~>  
2SC-c `9)  
AT_BEGIN M.t,o\xl  
从tag标签的开始一直到页面结束 U|tacO5w`  
如果tag处理类实现BodyTag接口,则在doInitBody、doAfterBody和doEndTag中调用,否则在doStartTag和doEndTag中调用 Od~uYOL/B  
f0sLe 3  
AT_END 03v+eT  
从tag标签的结束一直到页面结束 j;@a~bks6z  
在doEndTag中调用 heou\;GI"  
+5*bU1}O  
以struts为例,它的bean:define标签的实现遵循JSP1.1规范,此规范要求使用额外tag信息类来定义脚本变量。Variable元素是JSP1.2规范中加入的。以bean:define标签为例,你可以定义如下variable元素: fEXFnQ#  
\ opM}qZ  
<tag> e[u}Vf  
bKM*4M=k  
<variable> C0N}B1-MU  
NL$z4m0  
<name-from-attribute>id</name-from-attribute> }k-8PG =  
^rO"U[To  
<variable-class>database.BookDetails</variable-class> 1bQO:n):~  
c.Sd~k:3  
<declare>true</declare> |YROxY"ML  
>P~*@>e  
<scope>AT_BEGIN</scope> *{#C;"  
!'^l}K>  
</variable> 4jebx jZ  
k-=lt \?  
</tag> 6R<+_e+v  
rIcgf1v70  
额外tag信息类 yjL+1_"B  
?SFQx \/  
如果要定义一个额外tag信息类,你要继承javax.servlet.jsp.TagExtraInfo类。一个TagExtraInfo类必须实现getVariableInfo方法,此方法返回一个叫VariableInfo的数组类,它包括如下信息: j [lS.Lb  
06^/zr  
· 变量名 z6@8IszU  
[?I<$f"  
· 变量所属类名 HP]5"ziA  
AJEbiP  
· 此变量是否引用了一个新对象 igA?E56?  
NT 5=%X]  
· 此变量的有效范围 I*.nwV<  
:Q("  
jsp引擎将一个名为data的参数传给getVariableInfo方法,data中包括tag标签中的所有“属性名?D?D属性值”对。它可以用来向VariableInfo对象提供脚本变量的名字和类名。 Ue 9Y+'-x  
_-y1>{]H  
以struts为例,它在bean:define标签中定义了一个名为DefineTei的额外tag信息类,用来向脚本变量提供信息。由于脚本变量的名称(book)和类名(database.BookDetails)是通过tag标签的属性来传递的,它们一般定义在VariableInfo的构建代码中,并且可用data.getAttributeString方法来得到这些信息。如果要允许book脚本变量能在从tag开始直到整个JSP页面结束的范围内都可用的话,那它的范围应设为AT_BEGIN。如下所示: 1k4\zVgi  
;hDk gp  
,Kj>F2{  
public class DefineTei extends TagExtraInfo a)pc+w#  
mbkt7. ,P  
{ a($7J6]M  
(@XQ]S}L  
public VariableInfo[] getVariableInfo(TagData data) Tph^o^  
E8r6P:5d`  
{ N Nk  
"NA<^2W@J  
String type = data.getAttributeString(“type”); %Hd[,duwO  
^@*`vz^_  
If( type == null) 2kVZlt'y  
9zqo!&  
type = “java.lang.Object”; r'{N_|:vv  
A&fh0E (t  
return new VariableInfo[] { }tZA7),L  
\it<]BN  
new VariableInfo(data.getAttributeString(“id”), OL"So u4  
gb0ZGnI  
type, MtO p][i  
<ByDT$E_  
true, T)B1V,2j=  
P1l@K2r  
VariableInfo.AT_BEGIN) DV~1gr,\  
DWH)<\?  
}; Q,`Y  
wen6"  
} QcQ|,lA.HI  
6Gs,-Kb:  
} H{T)?J~  
62LQUl]<  
T {lJ[M  
注意:关于额外tag信息类的类名必须要在TLD中的tag标签下的tei-class子元素中定义。因此,DefineTei的tei-class中的定义看起来如下: 8Lpy`He  
<tei-class> j{'@g[HW  
org.apache.struts.taglib.bean.DefineTagTei !f\6=Z?>3  
</tei-class> w65 $ R  
w,.Hdd6  
G:rM_q9\u  
具有协作关系的tag }a_: oR  
rbP3&L  
0,;FiOp  
tag通过共享对象来进行协作,JSP技术支持2种方式的对象共享。 Cst> 'g-yB  
Z@8amT;Y  
第一种方法是使用pageContext对象进行对象的共享(可支持JSP页面和tag处理类之间的共享),如果在一个tag处理类中要调用由另一个tag处理类创建的对象,可调用pageContext.getAttribute(name, scope)方法。 7_/.a9$G  
GOwd=]e  
第二各方式的共享是对于tag之间有嵌套关系而言的,外层的tag所创建的对象对于内层的tag来说是可以共用的。这种形式的共享的好处是减少了可能存在的重名冲突。 u;:N 4d=f'  
}H ,A T  
要访问一个嵌套tag创建的对象,tag处理类必须先找到此嵌套tag对象,可用TagSupport的静态方法 TagSupport.findAncestorWithClass(from, class)或TagSupport.getParent方法。前者在当不确定此tag是否为嵌套tag对象时使用。一旦它的父类被找到,它就能访问其所有动态或静态创建的对象。静态创建的对象是父类的成员,而动态创建的对象可能是父类的私有对象。诸如此类的对象可以用tag处理类的setValue方法来保存,用getValue方法来获得。 2s6Hr;^w.1  
"v3u$-xN1  
下例阐述了以上两种共享对象的方法。在这个例子当中,一个查询tag检查一个名为connection的属性名是否在doStartTag中被设置。如果connection属性被设置,tag处理类从pageContext中得到这个connection对象。否则,此tag处理类先找到它的父tag处理类,然后从它的父tag处理类中找到connection对象。 MOmp{@  
/HDX[R   
^j=_=Km]  
public class QueryTag extends BodyTagSupport FM7N|] m  
1^Zx-p3J  
{ 73.o{V  
>)pwmIn<  
private String connectionId; vFCp= 8h  
*G~c6B Z  
public int doStartTag() throws JspException ($W9 ?  
HKcipDW  
{ 4'rk3nT8  
Il;'s  
String cid = getConnection(); cdIy[ 1  
b8v$*{  
if(cid != null) TPEZ"%=Hg  
>v<}$v6D~  
{ {Ue6DK %  
Z21XlbK   
//存在一个connection id,使用它。 ) L{Tn 8  
kh,M'XbTo  
connection = (Connection) pageContext.getAttribute(cid); @xkM|N?  
X}usyO'pW  
} ! 6 $>|  
Jc%>=`f  
else P|(J]/  
2iG(v._x  
{ 7T2W% JT-,  
rP\ 7C+  
ConnectionTag ancestorTag = (ConnectionTag)findAncestorWithClass(this, ev guw*u  
bL[PNUG  
ConnectionTag.class); ~V|!\CB  
wRiP5U,  
if(ancestorTag == null) sw@2 ?+  
0'~b<>G%  
{ 8\V-aow  
$cy:G  
throw new JspTagException(“一个没有connection属性的查询标签必须被一个connection标记嵌套。”); (7wR*vO^  
;_SS3q  
} 4 ?c1c  
BxT~1SBFq  
connection = ancestorTag.getConnection(); 8|tm`r`*Az  
OLR1/t`V  
} q7PRJX  
y-X'eCUz  
} z$V8<&q  
h9-Ky@X`  
} 0*"j:V  
g`6wj|@ =W  
G7202(w <  
Iw:("A&~  
此查询标签在JSP页面中的调用形式可以从以下2种定义中任选一种: 2Ee1mbZVw8  
,q HG1#^  
,Df36-74v5  
<tt:connection id=”con01” ...> ... </tt:connection> 2~U+PyeNz  
WuQYEbap  
<tt:query id=”balances” connection=”con01” > Jqj6L993e  
4|L@oTzx  
SELECT account, balance FROM acct_table (KMobIP^  
/ IS WC   
where customer_num = <%= request.getCustno() %> //,'oh~W  
\|t0~sRwh  
</tt:query> *!/#39  
n6Zx0ad?  
)89jP088V  
C941 @I  
T6r~OV5  
<tt:connection ...> !dH&IEP~  
kZ}u  
<x:query id=”balances”> NXNon*"  
L# 1vf  
SELECT account, balance FROM acct_table zs:7!  
N8q Z{CWn  
where customer_num = <%= request.getCustno() %> n1>nnH]G  
|Z^g\l.j{  
</x:query> z{0;%E  
Y]K]]Ehp  
</tt:connection> !q\w"p0X  
,b(S=r  
-b}S3<15@  
与此同时,在TLD中必须指定connection属性为可选的,定义如下: Lp)8SmN  
26VdRy{[  
<tag> f4T0Y["QA  
z]|[VM?4L  
... :*'?Ac ?  
ZC*d^n]x.  
<attribute> R<HZC;x  
-*fYR#VQQB  
<name>connection</name> }n%R l\p  
786_QV  
<required>false</required> 08?MS_  
o'C.,ic?C  
</attribute> 2\\3<  
KBq aI((  
</tag>
描述
快速回复

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