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

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

级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
标准的JSP 标记可以调用JavaBeans组件或者执行客户的请求,这大大降低了JSP开发的复杂度和维护量。JSP技术也允许你自定义taglib,其实换句话说,taglib可以看成是对JSP标记的一种扩展,正如xml是对html的一种扩展一样。taglib通常定义在tag标签库中,这种标签库存放着你自己定义的tag标签。简而言之,如果使用taglib,那么你可以设计自己的JSP标记! a[>/h3  
~IY%  
一般来说,自定义tag标签主要用于操作隐藏对象、处理html提交表单、访问数据库或其它企业级的服务,诸如邮件和目录操作等等。自定义tag标签的使用者一般都是那些对java编程语言非常精通,而且对数据访问和企业级服务访问都非常熟悉的程序员,对于HTML设计者来说,使得他可以不去关注那些较复杂的商业逻辑,而将精力放在网页设计上。同时,它也将库开发者和库使用者进行合理分工,自定义tag标签将那些重复工作进行封装,从而大大提高了生产力,而且可以使得tag库可用于不同的项目中,完美地体现了软件复用的思想。 +G$4pt|=  
>f|||H}Snw  
在这篇文章中,我们主要讨论: P9/q|>F  
`}D,5^9]  
· 什么是自定义tag标签? kI,yU}<Fq  
]Oe2JfJwx  
· 怎么使用tag标签? ^6jV_QM#  
Q1T$k$n  
o 声明要使用的tag库 IDad9 Bx  
] vz%iv_  
o 找到与之对应的tag处理类 a1g,@0s  
gI&#o@Pm  
o tag标签的类型 e+=y*OmQ  
,L|%"K]yM  
· 自定义tag标签 t*=CZE-  
EH- sZAv  
o tag处理类 w_aknt T  
 03L]  
o tag库描述 %p Ynnfr  
SUMrFd~  
o tag标签示例 o5u3Fjz3  
,dv+p&Tz2  
o 带属性的tag -{KQr1{5UM  
CLxynZ \;  
o 带body的tag {yBs7[Wn  
1m'k|Ka  
o 定义了脚本变量的tag ,[N%Q#  
kC:uG0sW  
o 具有协作关系的tag nB_?ckj,  
C>]0YO k2  
· 自定义tag标签 raW>xOivR  
g!|=%(G=  
o 一个迭代tag的例子 k 9_`(nx  
$CRm3#+ ~  
o 一个模板tag库 kPKB|kP\  
! :Y:pu0  
o tag处理类到底是怎样被调用的? *Hg>[@dP0  
7dN*lks  
LHyB3V  
什么是自定义的tag? 'I`&Yo~c9  
`oAW7q)~  
一个自定义的tag标签是用户定义的一种JSP标记。当一个含有自定义的tag标签的JSP页面被jsp引擎编译成servlet时,tag标签被转化成了对一个称为tag处理类的对象进行的操作。于是当JSP页面被jsp引擎转化为servlet后,实际上tag标签被转化成为了对tag处理类的操作。 g6y B6vk  
|sa]F5  
自定义tag标签有很多特色,诸如: n#cC+>*>+  
%7QV&[4!  
· 可以在JSP页面中自定义tag标签的属性 }cM}Oavh  
V~UN  
· 访问JSP页面中的所有对象 "0$a)4]  
 FK^p")i  
· 可以动态地修改页面输出 3(``#7  
`b?R#:G  
· 彼此这间可以相互通信。你可以先创建一个JavaBeans组件,然后在一个tag中调用此JavaBeans组件,同时可以在另一个tag中调用它。 Av$]|b  
Vk` h2BV  
· tag允许相互嵌套,可以在一个JSP页面中完成一些复杂的交互。 mJ<=n?{Z  
Qu"8(Jk/  
S\^P ha q  
使用tag标签 32(^Te]:  
t;){D:]k  
&]Q@7Nl7:l  
本节主要描述怎样在JSP页面中使用tag标签,以及tag标签的不同类型。 o m!!Sl3  
Juo^,  
要使用tag标签,JSP程序员必须做2件事: $&Gu)4'+  
?(xnSW@r  
· 声明此tag标签的tag库 J; S (>c  
&PL8|w  
· 实现此tag标签 !:)s"|=  
3 D6RLu  
声明tag标签所在的tag库 -TLlwxc^%  
I"xo*}  
如果要使用tag标签,则应用JSP的taglib指示符来指定其tag库(注意:taglib要在在使用此tag标签之前声明) BIH-"vTy  
O6@j &*jS  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> .7^c@i[  
.4S.>~^7  
uri属性定义了唯一的标签库描述(以下简称TLD),它可以是直接是tld文件名或一个独一无二的名字。prefix是用来区别其它TLD中和本TLD中有重名的tag的一种手段。 ]z;P9B3@&  
)tG\vk=@  
TLD必须以.tld作为扩展名,并且存放在当前应用的WEB-INF目录或其子目录下。你可以通过它的文件名直接引用它,也可以通过别的方式间接地引用它。 NxfOF  
*=) cQeJ  
以下taglib指示符直接引用一个TLD: LhN|1f:9:  
 Ii6<b6-  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> `34zkPB??  
j 'FVz&  
以下的taglib指示符通过一个逻辑名称间接地引用一个TLD: ?}qttj  
'|ad_M  
<%@ taglib uri=”/tutorial-template” prefix=”tt” %> Ig$(3p  
?llXd4  
如果是间接引用TLD的话,那你必须还要在web.xml中定义此逻辑名称与tld文件之间的映射,具体做法是在web.xml中加入一个名为taglib的元素: i|c'Lbre`  
U1Q:= yD  
<taglib> rUTcpGH  
}pDqe;a{  
<taglib-uri>/tutorial-template</taglib-uri> XWDL5K  
Ltv]pH}YN  
<taglib-location> \Bz_p'[G  
Y21g{$~Q{  
/WEB-INF/tutorial-template.tld AW%50V  
[<7@{;r  
</taglib-location> %W'v}p  
#akpXdXs  
</taglib> -N6f1>}pE  
; a/X<  
%) /s;Q,  
实现此tag标签 t9nqu!);  
[v7F1@6b  
wrviR  
为了实现tag标签,你有2种方法来存放tag处理类。一、让tag处理类以.class的方式存放于当前应用的WEB-INF/class子目录下,二、如果tag处理类是以JAR包的形式存在的话,那可以放在当前应用的WEB-INF/lib目录下,如果tag处理类要在多个应用中共享,那么它就应放在jsp服务器上的common/lib目录下,对于tomcat来说,就是tomcat/common/lib目录下。 DP[IZ C  
s:?SF.  
+ndaLhj'  
tag标签类型 Y)1PB+  
N1Ng^aY0  
?U%QG5/>  
自定义的tag标签遵循XML语法。它有一个开始标记和一个结束标记,有的还有body(即文本节点): v>:Ur}u!D  
f< ia(d  
<tt:tag> >q#rw  
_uWpJhCT  
body F7A=GF'  
ZLc -RM  
</tt:tag> %}[i'rT>  
AmvEf  
@_-hk|Nl@  
一个不带body的tag标签如下: $>G8_q  
'g6\CZw(#  
<tt:tag /> tG:25T0  
,ly\Ka?zO  
=FlDb 5t{  
简单的tag标签 Z|%_&M  
r~E=4oB7  
一个没有body和属性的tag标签如下: XywE1}3  
#[,IsEpDO1  
<tt:simple /> >c1!p]&V  
EtJHR  
@V(*65b2  
带属性的tag标签 eds o2  
cT<1V!L4  
+:8fC$vVfC  
自定义标签可以有自己的属性。属性一般在开始标记中定义,语法为 attr=”value”。属性的作用相当于自定义标签的一个参数,它影响着tag处理类的行为。你可以在TLD中详细定义它。 "K  ~  
O&vVv _zh  
你可以用一个String常量给一个属性赋值,也可以通过表达式给它赋值,如<%= ...%>。以struts为例,它的logic:present标签就是用的String常量来给属性赋值: &?W0mW(  
2I%MAb&1@  
<loglic:present parameter = “Clear”> [6pD  
pN!}UqfI-  
而另一个标签logic:iterate是用表达式来给属性赋值: 'ZT^PV \  
1Y/s%L  
<logci:iterate collection=”<%= bookDB.getBooks() %>” +vvv[  
;QWIsVz  
id=”book” type=”database.BookDetails”> V\t.3vT  
BD68$y  
4 kn|^  
带body的tag标签 ]|!OP  
F{Z~ R  
一个自定义标签可以包含其它自定义标签、脚本变量、HTML标记或其它内容。 }e!x5g   
g@rb  
在下述例子中,此JSP页面使用了struts的logic:present标签,如果些标签定义了parameter=”Clear”的属性,则将清除购物车的内容,然后打印出一条信息: VkvB<3  
E4xj?m^(y=  
<logic:present parameter=”Clear”> +lm{Olm'^  
4F)-"ck  
<% cart.clear(); %> =V-A@_^!c  
a,xycX:U  
<font color=”#ff0000” size=”+2”><strong> ks"|}9\%<  
Z&#('Z  
你选择了清除购物车! 0M*Z'n +  
rw: c  
</strong></font> B&\IGWG(  
FR$:"  
</logic:present> OPwtV9%  
.}^g!jm~h  
'w!Cn>  
到底是用属性还是用body来传递信息? _/F7 ?^j  
Y ?S!8-z  
如上所述,我们既可以通过属性,也可以通过body来传递信息。但一般来说,比较简单的类型,如字符串或简单表达式最好采用属性来传递信息。 %Qc La//  
6 2'j!"xv  
D'7SAFOM  
定义脚本变量的tag标签 E7NV ^4h  
XDsx3Ws  
所谓脚本变量,是指JSP中可以调用的变量或对象。它可由tag标签产生。以下示例阐述了一个tag标签定义了一个名为tx的由JNDI所定义的事务处理对象。脚本变量可以是ejb对象、事务、数据库连接等等: esHg'8?U  
U@g4w!$r  
<tt:lookup id=”tx” type=”UserTransaction” name=”java:comp/UserTransaction” /> )+l\w3^6  
l9}3XI.=  
<% tx.begin(); %> q'|rgT  
pczug-nB  
... ;fsZ7k4]do  
<<@bl@9'  
5Eg1Q YVt  
具有协作关系的tag标签 n.T&}ZPz\v  
=5Q]m6-SgV  
自定义tag标签之间可以通过共享对象来实现协作。在下述例子中,标签tag1创建了一个名为obj1的对象,在标签tag2仍可以重复使用obj。 2-7IJ\  
yGWxpzmRS  
<tt:tag1 attr1=”obj1” value1=”value” /> @*OZx9  
@<&5J7fb  
<tt:tag2 attr1=”obj1” /> j2ve^F:Q  
u2[ iMd  
在以下这个例子当中,如果外层的tag标签创建了一个对象,那么其内层的所有tag标签都可以使用这个对象。由于这样产生的对象没有一个指定的名字,那么就可以将少重名的冲突。这个例子阐述了一系列协作的嵌套对象。 rQk<90Ar  
K!:azP,bZ  
<tt:outerTag> ozAS[B6  
^?U!pq -`  
<tt:innerTag /> T@G?t0  
i'4B3  
</tt:outerTag> w,w{/T+B  
!6BW@GeF]  
:ZTc7 }  
Tag处理类 DSC$i|  
: e]a$  
Qc gRAo+u  
Tag处理类必须实现Tag接口或BodyTag接口,不过现在一般都流行从TagSupport或BodyTagSupport类中继承,这些类或接口都可以在javax.servlet.jsp.tagext包中找到。 *i]=f6G  
GKOD/,  
当JSP引擎看到自己的JSP页面中包含有tag标签时,它会调用doStartTag方法来处理tag标签的开头,调用doEndTag方法来处理tag标签的结束。 ugo.@   
]+(6,ct&.  
下表说明不同类型的tag所需要不同的处理过程: s8-<m,*  
_(Sa4Vb=Q6  
Tag处理类的方法 H GXt  
%C$% !C  
Tag标签类型 M4zm,>?K  
所调用的方法 Ey_" ~OB  
ZYI{i?Te#  
基本标签 /]=C{)8  
doStartTag, doEndTag, release #N#'5w-G  
0*rQ3Z  
带属性的标签 N03HQp)g  
doStartTag, doEndTag, set/getAttribute1...N, release 2r!s*b\Ix  
Zw*v  
带内容的标签 KAC6Snu1  
doStartTag, doEndTag, release {. 2k6_1[  
'ixwD^x  
带内容的标签,且内容重复循环 {XNREjhm  
doStartTag, doAfterBody, doEndTag, release hJn%mdx~w|  
crqpV F]1]  
带内容的标签,且内容与JSP交互 V=zi >o`   
doStartTag, doEndTag, release, doInitBody, doAfterBody, release Y,W uBH  
#cnq(S=.  
一个tag处理类可以通过javax.servlet.jsp.PageContext来与JSP交互,通过javax.servlet.jsp.PageContext类,tag处理类可以访问JSP中的request、session和application对像。 L[^9E'L$  
{p;zuCF1  
如果tag标签是互相嵌套的,那内层的tag处理类可以通过它的parent属性来访问上层的tag处理类。 ~;1l9^N|  
~KW,kyXBnD  
一般情况都将所有的tag处理类打成了JAR的包,以便于发布。 +s,Qmmb7)  
g6Q!8  
7N-w eX  
Tag库描述(简称TLD) :,Pn3xl  
y=`2\L" O  
N$h{Yvbn  
Tag库是用xml语言描述的,TLD包括了tag库中所有tag标签的描述,它一般用来被jsp服务器用来校验tag的语法正确性,或者被jsp开发者用来开发新的标签。 wT `a3Ymm  
Q7R~{5r>W  
TLD的文件扩展名必须为.tld,而且必须放在当前WEB应用的WEB-INF目录或其子目录中。 j<u@j+V  
vg D77  
一个TLD的内容的开头必须遵守标准的XML开头,用于描述DTD和xml的版本,例如: OlAs'TE^  
Q?3Gk%T0[  
<?xml version="1.0" encoding="ISO-8859-1" ?> Qk\A c  
5"HV BfFk  
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd"> ?*E'^~,H)  
TLD必须以<taglib>来作为它的根元素,<taglib>的子元素如下表: t"k*PA  
?mWw@6G,  
Gs9:6  
<taglib>的子元素 (@t(?Js  
WpF2)R}G=  
Element '<rZm=48  
Description u#Z#)3P  
[* @5\NWR}  
tlib-version nx8a$vI-TY  
Tag库的版本 c:-!'l$ !  
Q.]}]QE   
jsp-version U}MXT <6  
Tag库所需要的jsp的版本 31rx-D8o  
3H|_mX  
short-name bKrhIU[  
助记符,tag的一个别名(可选) D+]a.& {p  
cgm81+[%r  
uri qxFB%KqU  
用于确定一个唯一的tag库 eU<]o< \Qo  
O+?<h{"  
display-name c3:,Ab|  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) UVw~8o9s  
ag*mG*Z  
small-icon BO~PT,QrF  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) ^1Zeb$Nw'  
+RnkJ* l  
large-icon 4W3\P9p=  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) .a._NW  
\RvvHty-V  
description jFA{+Yr1  
对tag库的描述(可选) 7N:Y?Hi\  
CAcS~ "  
listener "\}@gV#r$A  
参见下面listener元素 xER\ZpA :,  
-[6z 1"*  
tag *d"DA[(  
参见下面tag 元素 <5NF;  
\ C+(~9@|  
Listener元素 #a`a$A  
Bx/L<J@  
一个tag库可能定义一些类做为它的事件侦听类,这些类在TLD中被称为listener 元素,jsp服务器将会实例化这些侦听类,并且注册它们。Listener元素中有一个叫listener-class的子元素,这个元素的值必须是该侦听类的完整类名。 `e(vH`VZ  
[k6nW:C  
Tag元素 [ { bV4  
mnmP<<8C,  
每个tag元素在tag库中都要指出它的名字、类名、脚本变量、tag的属性。其中脚本变量的值可以直接在TLD中定义或通过tag附加信息的类来取得。每个属性描述了这个属性是否可以省略,它的值是否可以通过<%= …%>这样的JSP语法来获得,以及属性的类型。 =$nB/K,8AX  
.G+Pe'4a  
每一个tag在TLD中对应一个tag元素,下表是tag元素的子元素: yi l[gPy4B  
M#~Cc~oT  
Tag元素的子元素 ``OD.aY^s  
VUhbD  
元素名称 L{(QpgHZ  
描述 Yc,7tUz#  
91$]Qg,lB  
name ^4,a8`  
独一无二的元素名 Sqo : -  
G}FIjBE  
tag-class G3rj`Sg^c  
Tag标签对应的tag处理类 JaK}|  
L+CyQq  
tei-class TZ2=O<Kj  
javax.servlet.jsp.tagext.TagExtraInfo的子类,用于表达脚本变量(可选) :'*DPB-  
4dhvFGlW  
body-content |37 g ~  
Tag标签body的类型 K91)qI;BD  
P&b19K'  
display-name e_/b2"{  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) j{NNSi3  
f|R"u W +  
small-icon u%/goxA  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) #*TEq  
[o.B  
large-icon 3bDQk :L  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) 'k4E4OB  
cOPB2\,  
description "dI;  
此tag标签的描述 xia|+  
ap{2$k ,  
variable aBNZdX]vzO  
提供脚本变量的信息(同tei-class)(可选) PJ2qfYsH=>  
dw TMq*e  
attribute I('Un@hS  
Tag标签的属性名 i:u1s"3~  
Rr!Y3)f;  
以下章节介绍对于不同类型的tag,如何具体地实现它们。 D<V~f B  
=e8bNg  
qQ0cJIISb\  
简单的tag \mV'mZ9>  
|]aE<`D  
KyzFnVH3)  
tag处理类 e'=MQ,EWd  
C-Ht(x|  
简单的tag处理类必须实现Tag接口的doStartTag和doEndTag方法。当jsp引擎碰到tag标签的开头时,doStartTag被调用,因为简单的tag没有body,所以此方法将返回 SKIP_BODY。当jsp引擎碰到tag标签的结尾时,doEndTag被调用,如果余下的页面还要被计算,那它将返回EVAL_PAGE,否则将会返回SKIP_PAGE。 zkO<-w  
jq+A-T}@  
以下是例子:对于标签 <tt:simple /> ,它的tag处理类实现如下: $d,0=Ci  
lhtZaU~V  
c wOJy >  
public SimpleTag extends TagSupport jiYmb8Q4D  
ZKXo-~=>  
{ fgBM_c&9T  
1&P<  
public int doStartTag() throws JspException cKn`/\.H  
`\m*+Bk[5  
{ :OW ;?{ ~j  
r" K':O6y  
try{ lRv eHB&V  
L*Me."*  
pageContext.getOut().print(“Hello.”); /__PSK  
HgBGV0  
}catch(Exception e){ aM{xdTYaU  
&m[Qn!>i6  
throw new JspTagException(“SimpleTag: “ + e.getMessage()); Wy ZL9K{?  
> ]8a3x  
} "3<da*D1  
9 JWa$iBH@  
return SKIP_BODY; Rcawc Y  
\4AM*lZ  
} ?_ dIIQ  
!H2QjW  
public int doEndTag() +Y V|ij  
yB3;  
{ '(dz"PL.  
hRq3C1 mR  
return EVAL_PAGE; !wWJ^Oz=  
]r-C1bKD`  
} 11,!XD*"  
efD)S92  
} %%Qo2^-  
rY p3(k3  
iR\Hv'|  
注意:如果tag标签没有内容的话,那必须定义body-content元素为空,例如 [2dn\z28  
/"?HZ% W  
<body-content>empty</body-content> oX4q`rt  
~`D|IWMDq  
Z(ZiFPx2Z  
带属性的tag标签
评价一下你浏览此帖子的感受

精彩

感动

搞笑

开心

愤怒

无聊

灌水
级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
只看该作者 1 发表于: 2007-01-01
tag处理类 Lgz$]Jbl8  
gaf$uT2  
对于tag标签的每个属性,你必须依照JavaBeans规范来定义其属性,以及get和set方法。以struts的logic:present 标签为例, @A+RVg*=  
ex<O]kPFE  
<logic:present parameter=”Clear”> suH&jE$x  
Nk[2nyeO>  
与此相应,此tag处理类应有如下方法和定义: :d8W +|1u  
cv(PP-'\  
{,cCEXag%  
protected String parameter = null; k/03ZxC-  
)?2e  
public String getParameter() #eN{!Niy&U  
)9S>Z ZF  
{ @ a4/ELx  
z`6fotL  
return this.parameter; 2..,Sk  
I2 a6w<b  
} ?go:e#  
l_j4DQBRV  
public void setParameter(String parameter) O}[PJfvBHo  
Jjl%R[mI  
{ DOz\n|8S  
`+#G+Vu5  
this.parameter = parameter; xBFJ} v  
}P3tn  
} 'u4ezwF;  
O'GG Ti]e  
vfB2XVc  
注意:如果你的属性名为id,而且你的tag处理类是从TagSupport类继承的,那你就不需要定义它的属性和set和get方法,因为他们早已在TagSupport被定义过了。 KvQ,;A  
+x]9+D&  
Attribute元素 azP+GM=i7  
h8 G5GRD  
对于tag标签的每个属性,你必须定义它是否必须的,它的值是否可以用诸如<%= …%>的表达式来获得,以及它的类型(可选),如果不指定它的类型,那就默认为是java.lang.String类型。如果rtexprvalue元素被定义为true或yes,那么在type元素中就定义了attribute的返回类型。 /j"sS2$U  
^>?CMcN4*  
<attribute> n}mR~YqD  
JjXobNQf  
<name>attr1</name> 9e U[*S  
E(Rh#+]Y5  
<required>true|false|yes|no</required> =&dW(uyzY  
7DKz;o  
<rtexprvalue>true|false|yes|no</rtexprvalue> Kd3?I5t  
0Y]0!}  
<type>attribute的返回类型(只用当rtexprvalue为真是才有效)</type> B$KwkhMe  
&t(0E:^TRU  
</attribute> #tdf>?  
^+SkCO  
如果tag的某个属性不是必须的,那tag处理类会自动提供一个缺省值。 PS S?|Vk  
O8U<{jgAG  
例如,在logic:present这个tag标签中定义了一个属性叫parameter,但它不是必须的,而且它可以被诸如<%= …%>的表达式来赋值。 `d2,*KR  
ki;UY~  
<tag> dP]1tAO,y  
{m8+Wju}  
<name>present</name> K={qU[_O  
OTB$V k  
<tag-class>org.apache.struts.taglib.logic.PresentTag</tag-class> qpJ{2Q  
t!1$$e?`r  
<body-content>JSP</body-content> 7*wVI+  
: t$l.+B  
U"f ??y%)  
fQnwy!-\  
<attribute> sP'0Sl~NU  
c~ <1':  
<name>parameter</name> $[@0^IJq=K  
hIJ)MZU|  
<required>false</required> ~^)^q8  
`A/j1UWJ  
<rtexprvalue>true</rtexprvalue> wzjU,Mw e  
w> xV  
</attribute> ]+DI.%   
.w6eJ4 ]  
O)R(==P26P  
uqyB5V0gh  
</tag> "k$JP  
d h^^G^  
$!A:5jech  
属性元素的校验 f]8I64  
+~sd"v6  
=wi*Nd7L  
有关于tag标签的有效值可以从tag库的说明文档中获得,当JSP页面被编译时,jsp引擎会强制性地参照TLD中定义的规则进行检查。 '[P}&<ie,  
Z< b"`ty.  
还有一个方法也可以进行属性元素的校验,就是先继承类TagExtraInfo,然后调用它的isValid方法。这个类同时也起到提供tag中定义的脚本变量信息的作用。 4\ /*jA  
G&eP5'B4i  
IsValid方法通过TagData对象来传递属性信息,它包括着tag的所有的属性名-值的信息。由于校验发生在运行时刻,因此这个属性的值将被赋值为TagData.REQUEST_TIME_VALUE。 qu6DQ@ ~YC  
$t rAC@3O@  
例如tag标签<tt:twa attr1=”value1” />在TLD中定义如下: r!N]$lB  
w-N1.^  
<attribute> @LD6:gy  
[LM^), J?  
<name>attr1</name> \'?#i @O  
oh#N 0 0X  
<required>true</required> &ogt2<1W  
]"fsW 9s  
<rtexprvalue>true</rtexprvalue> &B{8uge1  
|`yZIY_  
</attribute> +$z]w(lbT  
t@bt6J .{  
`BZ&~vJ_  
这个定义说明了attr1能在运行期间被赋值。 |I[7,`C~  
^%oUmwP<$  
以下的isValid方法检查attr1属性的值是否属于Boolean类型。注意由于attr1能在运行刻被赋值,那么isValid方法必须检查tag用户是否对此tag进行了运行时刻赋值。 mZ0J!QYk  
pF=g||gS  
cm>E[SHr  
Public class TwaTEI extends TagExtraInfo K=u0nrG*  
m)?5}ZwAH  
{ 1ywU@].6J]  
J_#R 87  
public boolean isValid(Tagdata data) 0_<Nc/(P  
@u4=e4eF`  
{ ? S=W&  
Sj 3oV  
Object o = data.getAttribute(“attr1”); i&+w _hD  
>N`6;gn*l  
If(o != null && o != TagData.REQUEST_TIME_VALUE) _94s(~g:  
IvBGpT"(I  
{ msTB'0  
Vj^dD9:  
if( ( (String)o).toLowerCase().equals(“true”) || {gy+3  
q{4|Kpx@  
((String)o).toLowerCase().equals(“false”) ) fJ80tt?r  
+`| *s3M  
return true; :9d\Uj,  
ZKbDp~  
else V/#v\*JHFc  
nf%4sIQ*x  
return false; d;suACW  
~\_T5/I%  
} wgd<3 X  
cz.3|Lby  
else whkJpK(  
L=1 ~ f-  
return true; $-pbw@7  
b 6W#SpCF  
} 4Z%Y"PL(K  
X.J  
} /#q")4Mf  
/(6zsq'v|  
}ymvC  
带body的tag #Q6w+"  
=Lw3 \5l  
3XVk#)lw  
tag处理类 I"Q<n[g0'  
ua& @GXvZ  
U}P,EP%p  
如果tag标签含有内容,那处理方式会略微有些不同,而且还要视tag处理类是否要与body交互的情况而定。如果要与body交互,那我们认为tag处理类要可能要对body进行操作。 ~w.2 -D  
pzEABA   
Tag处理类不与body交互 ,nE&Me&#J  
ckwF|:e 7*  
如果tag处理类不与body交互,tag处理类应该实现Tag接口或从TagSupport中派生,如果body要被计算,那么doStartTag方法应返回 EVAL_BODY_INCLUDE,否则应返回SKIP_BODY。 ?n*fy  
(|0b7 |'T  
如果tag处理类要对body反复运算,则它应该实现IterationTag或从TagSupport中派生。如果tag处理类认为body还未计算完的话,那它的doStartTag方法和doAfterBody方法必须返回EVAL_BODY_AGAIN。 #S?c ;3-  
?M"HXu  
Tag处理类与body交互 h DtK nF  
6lU|mJ`M  
如果tag处理类与body交互,那tag处理类应实现BodyTag接口或从BodyTagSupport中派生。这种tag处理类一般要实现doInitBody和doAfterBody方法。 7\/u&  
Y +qus  
Body允许一些方法来读写它的内容。Tag处理类可以调用body内容的getString或getReader方法来从body中提取信息,也可用 writeOut(out) 方法来将body的内容写入到out对象中。其中out对象通过tag处理类的getPreviousOut方法来获得。 N !IzB]  
|Y{PO&-?r  
如果body的内容需要被计算,那么doStartTag方法必须返回EVAL_BODY_BUFFERED,否则,它将返回 SKIP_BODY。  1~EO+  
D=9}|b/  
doInitBody 方法 `E;)`J8b  
qhxC 5f4Z  
此方法在body内容已经设好,但未被计算之前被调用。你可以根据不同的body内容来制定初始化策略。 Ki 3_N*z  
]PVt o\B=  
doAfterBody方法 TolrEcI  
<UK5eVQn  
此方法在body内容已被计算后进行调用。 w{P6i<J  
Z!)f*  
和doStartTag方法一样,doAfterBody方法返回一个指示符指示是否要继续计算body,如果要继续计算,则doAfterBody应返回EVAL_BODY_BUFFERED,否则,它应返回SKIP_BODY。 p,s&61]  
IDmsz  
release 方法 5 ZUy:  
[Pqn 3I[  
tag处理类调用此方法将它的状态重置为初始状态,并释放所有的私有资源。 }z{wQ\  
X8.y4{5  
$O]^Xm3{@  
以下的例子读取body的内容(其中含有一条sql语句),然后将它传递给一个对象,让它进行查询。由于此处body不须重新计算,所以doAfterBody会返回SKIP_BODY。 KDaN-r^{%  
%(NN *o9"q  
s<#N]mp'   
Public class QueryTag extends BodyTagSupport \!7*(&yly  
f@*>P_t  
{ M/)B" q  
Wa}"SqYr h  
public int doAfterBody() throws JspTagException >gGil|I  
%O Fj  
{ Bpas[2gYC  
U_}hfLILi  
BodyContent bc = getBodyContent(); -PXoMZx%  
:4]J2U\@  
//将body的内容以字符串的格式提取出来 mOSCkp{<e  
s/PhXf\MN  
String query = bc.getString(); q@w"yz>  
~RCg.&[ou  
//清除body >OTl2F}4 !  
Fi/jR0]e2  
bc.clearBody(); +qZc} 7rJF  
=lm nzu<  
try{ g X8**g'  
_4Ii5CNNU  
Statement stmt = connection.createStatement(); ?}v}U^  
J[MVE4&  
Result result = stmt.executeQuery(query); *H?t;,\  
e-jw^   
}catch(SQLException e){ 2$  
xLZMpP5c  
throw new JspTagException(“queryTag: “ + e.getMessage() ); 9G+y.^/6  
!b'IfDp[-!  
return SKIP_BODY; )L|C'dJ<k`  
=}"R5  
} s ?5 d  
>Rr!rtc'x  
} ` -yhl3si  
XS3{R   
QW,cn7  
body-content元素 .byc;9M%  
{GAsFnZk  
eC.w?(RB  
由于tag可能会有body,你必须用body-content元素来指定body内容的类型: C1n? ?Y[  
J/L)3y   
<body-content>JSP|tagdependent</body-content> R2SBhs,+R  
yg`E22  
>Sh0dFqeT  
如果body的内容是定制的或内部的tag、脚本元素、或HTML广本,则归类为JSP类型。其他的类型,比如上面代码所述的?D?D将sql statement类传给 query tag的这种类型应该标为tagdependent。 f>p; siR)  
hJ<:-u+yk}  
注意:实际上body-content的值并不影响tag处理类对body内容的处理,它仅仅是被tag编辑工具用来描述此body的内容。 }WA<=9e  
f>|9 l  
|e~u!V\m  
用tags定义脚本变量 #&}%70R)  
JThk Wx  
\f6lT3"VN  
tag处理类 sw[<VsxjR  
5 Xk~,%-C  
LH bZjZ2  
tag处理类负责创建或设置页面中定义的脚本变量,用pageContext.setAttribute(name,value,scope)或pageContext.setAttribute(name,value)方法来实现。一般来说,tag处理类通过脚本变量的名称来获取它,脚本变量的名称一般可用get方法来获得。 d$4WK)U  
t;h+Cf4  
如果脚本变量的值依赖于tag处理类中的上下文中某一对象,那它可用pageContext.getAttribute(name,scope)方法来找到那个对象。一般的处理过程是tag处理类先找到脚本变量,再对其进行处理,然后用pageContext.setAttribute(name,object)的方法来设置它的新值。 U`:lAG  
_F! :(@}  
对象的生存周期(scope)如下表: D`1I;Tb#  
G[ ,,L  
对象的生存周期表 [SKP|`I>I  
o]dK^[/*  
名字 (MZ A  
可访问范围 e6Wl7&@6  
生存周期 ?SHc}iaU#  
w2.qT+; v  
page J11dqj  
当前页面 pHq{S;R2G  
一直有效,除非页面向客户提交响应或重定向到一个新页面 L~'^W/N  
H Jnv'^yn  
request J,CJPUf&  
当前页面或当前页面重定向到的页面 Y+|L 3'H  
一直有效,除非页面向客户提交响应 $_4oN(WSz  
kxcgOjrmI  
session Uh<H*o6e 9  
当前页面或在同一浏览器窗口中的页面  "Nk`RsW  
一直有效,除非关闭当前浏览器、超时、网络故障 B7NmET4  
Tb>IHoil  
application 5JJg"yuY"  
整个web应用程序的所有请求 3(oZZz  
一直有效,除非发生网络故障、服务器故障 %#[r_QQ^  
.Y=Z!Q  
提供关于脚本变量的信息 DW'0j$;  
SQz$kIZR  
以下示例定义了一个名为“book”的脚本变量,用来访问程序中关于书的信息: ^EnNbFI  
}TXp<E"\  
<bean:define id=”book” name=”bookDB” property=”bookDetails” type=”database.BookDetails” /> Requ.?!fG;  
a!s.850@  
<font color=”red” size=”+2” > JKEXYE  
fRca"vV  
<%= messages.getString(“CartRemoved”) %> /6Jy'"+'0  
gPA>*;?E;@  
<strong><jsp:getProperty name=”book” property=”title” /></strong> 2 zmQp  
'<*CD_2t-  
</font> Kt/+PS  
\4]zNV ~x  
当包含此tag的JSP页面被编译时,jsp引擎会自动生成关于此book的同步的代码(同步可以避免几个客户同时访问此book时造成的冲突),要生成同步代码,jsp引擎需要知道此脚本变量的如下信息: Mp DdJ,  
WF3DGqs_]  
· 脚本变量名称 |wyJh"4!  
Ty e$na&$}  
· 脚本变量所属的类 q9g[+*9]$  
P!>{>r4  
· 此脚本变量是否引用了一个新的或已存在的对象 }uV?  
O?4vC5x  
· 此脚本变量的有效性 2Be?5+  
~%8Q75tn.  
有两种办法可以向jsp引擎提供关于脚本变量的信息:在TLD中定义variable子元素,或用tei-class子元素定义一个额外tag信息类。用variable最简单,但可能降低了一些灵活性。 >yPFL'  
3<~2"@J  
Variable元素 h1G*y  
/z.7: <gZ(  
Variable元素有如下子元素: E<98ahZ?l  
oZ\qT0*eb  
· name-given ?D?D 给出的名字,是一个常量 J;Z>fAE7  
`lV  
· name-from-attribute?D?D 属性名,在编译时给出的属性名 f3%^-Uy*b  
|4?}W ,  
name-given或name-from-attribute两者必须选一,但以下子元素是可选的: Zh fD`@>&  
9$\;voo  
· variable-class?D?D变量的类型,缺省为java.lang.String。 ,:dEEL+>c  
_L `N^I.  
· declare?D?D此脚本变量是否引用了一个新对象,缺省为True。 #<PA- y  
]L%R[Z!3  
· scope?D?D脚本变量的范围,缺省为NESTED。下表描述了scope的几种类型: n'&`9M['%d  
|)72E[lL  
脚本变量的有效范围 9qu24zz$P  
H2FFw-xW  
4 HJZ^bq9|  
有效性 +~i+k~{`H  
方法 33,JUQ2u  
y T1Qep  
NESTED PhI6dB`  
在tag标签的开始和结束之间 SJ WP8+  
如果tag处理类实现BodyTag接口,则在doInitBody和doAfterBody中调用,否则在doStartTag中调用 BJ.8OU*9]S  
4W//Oc@e  
AT_BEGIN rO?x/{;ai  
从tag标签的开始一直到页面结束 X\$W'^np  
如果tag处理类实现BodyTag接口,则在doInitBody、doAfterBody和doEndTag中调用,否则在doStartTag和doEndTag中调用 ,;=( )-  
sY;gh`4h  
AT_END S'-`\%@7  
从tag标签的结束一直到页面结束 "aCb;2Rs  
在doEndTag中调用 b]g&rwXYt  
J PzQBc5e  
以struts为例,它的bean:define标签的实现遵循JSP1.1规范,此规范要求使用额外tag信息类来定义脚本变量。Variable元素是JSP1.2规范中加入的。以bean:define标签为例,你可以定义如下variable元素: N5rG.6K  
ch,Zk )y:_  
<tag> h@m n GE  
5q_OuZ/6  
<variable> y'2kV6TtqD  
)`+@j.75  
<name-from-attribute>id</name-from-attribute> .dKRIFo  
1={Tcq\]  
<variable-class>database.BookDetails</variable-class> WO(&<(?  
t{S{!SF4  
<declare>true</declare> 72`/xryY  
gM5p1?E  
<scope>AT_BEGIN</scope> /E4}d =5L  
`TlUJ]d)  
</variable> ?'/5%f`  
ATmqq)\s  
</tag> !|:q@|- %@  
SX=0f^  
额外tag信息类 j.'"CU  
{|J2clL  
如果要定义一个额外tag信息类,你要继承javax.servlet.jsp.TagExtraInfo类。一个TagExtraInfo类必须实现getVariableInfo方法,此方法返回一个叫VariableInfo的数组类,它包括如下信息: ! 7*_Z=  
.kKwdqO+zB  
· 变量名 yDyeP{  
Mm7n?kb6  
· 变量所属类名 d,rEEc Y  
|o=\9:wV  
· 此变量是否引用了一个新对象 WKIiJ{@L  
6u, 0y$3  
· 此变量的有效范围 s^?sJUj  
|m 5;M$M)  
jsp引擎将一个名为data的参数传给getVariableInfo方法,data中包括tag标签中的所有“属性名?D?D属性值”对。它可以用来向VariableInfo对象提供脚本变量的名字和类名。 n `T[eb~  
)4_6\VaM  
以struts为例,它在bean:define标签中定义了一个名为DefineTei的额外tag信息类,用来向脚本变量提供信息。由于脚本变量的名称(book)和类名(database.BookDetails)是通过tag标签的属性来传递的,它们一般定义在VariableInfo的构建代码中,并且可用data.getAttributeString方法来得到这些信息。如果要允许book脚本变量能在从tag开始直到整个JSP页面结束的范围内都可用的话,那它的范围应设为AT_BEGIN。如下所示: +$QL0|RL  
Fx99"3`3  
Cz);mOb%M%  
public class DefineTei extends TagExtraInfo I.0P7eA-  
s>``- ]3  
{ fQ.>G+0 I>  
^}7t:  
public VariableInfo[] getVariableInfo(TagData data) D:vUy*  
F4<2.V)#-  
{ |wb(rua  
MirBJL  
String type = data.getAttributeString(“type”); W>wi;Gf#  
c2mt<DtWW  
If( type == null) H'\EA(v+  
RrpF i'R  
type = “java.lang.Object”; R|$`MX}'z  
Y9L6W+=T  
return new VariableInfo[] { [gdPHXs  
J'c9577$  
new VariableInfo(data.getAttributeString(“id”), qq_,"~  
yj+b/9My   
type, w:zC/5x`  
7-IeJ6,D  
true, :Fd9N).%  
4bzn^  
VariableInfo.AT_BEGIN) 2\tjeg  
G(\1{"!  
}; v ]U;5Uo  
UBHQzc+,  
} ^|{fB,B  
KmOa^vY1.T  
} _1c_TMh}9  
AR6vc  
*9(1:N;#  
注意:关于额外tag信息类的类名必须要在TLD中的tag标签下的tei-class子元素中定义。因此,DefineTei的tei-class中的定义看起来如下: .%Q Ea_\  
<tei-class> jF_I4H  
org.apache.struts.taglib.bean.DefineTagTei y]4 `d  
</tei-class> `#8R+c=$  
BIf].RY  
Y(Ezw !a  
具有协作关系的tag =T4 w:  
O~'yP @&`  
iX6jvnJ:/  
tag通过共享对象来进行协作,JSP技术支持2种方式的对象共享。 z35Rjhj9  
.LR>&N_U  
第一种方法是使用pageContext对象进行对象的共享(可支持JSP页面和tag处理类之间的共享),如果在一个tag处理类中要调用由另一个tag处理类创建的对象,可调用pageContext.getAttribute(name, scope)方法。 aBi:S3 qk  
1W<_5 j_  
第二各方式的共享是对于tag之间有嵌套关系而言的,外层的tag所创建的对象对于内层的tag来说是可以共用的。这种形式的共享的好处是减少了可能存在的重名冲突。 /-4B)mL  
-Ep6 .v  
要访问一个嵌套tag创建的对象,tag处理类必须先找到此嵌套tag对象,可用TagSupport的静态方法 TagSupport.findAncestorWithClass(from, class)或TagSupport.getParent方法。前者在当不确定此tag是否为嵌套tag对象时使用。一旦它的父类被找到,它就能访问其所有动态或静态创建的对象。静态创建的对象是父类的成员,而动态创建的对象可能是父类的私有对象。诸如此类的对象可以用tag处理类的setValue方法来保存,用getValue方法来获得。 }c5`~ LLK  
fr2w k}/b  
下例阐述了以上两种共享对象的方法。在这个例子当中,一个查询tag检查一个名为connection的属性名是否在doStartTag中被设置。如果connection属性被设置,tag处理类从pageContext中得到这个connection对象。否则,此tag处理类先找到它的父tag处理类,然后从它的父tag处理类中找到connection对象。 NWK_(=n  
hP<qKVy  
ta., 4R&K  
public class QueryTag extends BodyTagSupport r!,V_a4n  
):ZumG#o  
{ oz@6%3+  
i]?xM2(N  
private String connectionId; XO~^*[K  
as!j0j%  
public int doStartTag() throws JspException >{Z=cv/6o  
eJp-s" %  
{ ;}'<`(f&nX  
[`\Qte%UH  
String cid = getConnection(); {U-EBXV  
.Kwl8xRg  
if(cid != null) dwMwd@*j  
rapca'&#  
{ Uk\U*\.  
8:fiO|~%  
//存在一个connection id,使用它。 K.m[S[cy  
/z:K#  
connection = (Connection) pageContext.getAttribute(cid); 4HE4e  
 +'.Q-  
} hj,x~^cS  
 |?A-?-  
else F| Q#KwN  
^T,cXpx|  
{ BG=_i#V  
c$fM6M }  
ConnectionTag ancestorTag = (ConnectionTag)findAncestorWithClass(this, P,_E 4y  
1hij4m$b  
ConnectionTag.class); a"aV&t  
l:f sZO4  
if(ancestorTag == null) ?s33x#  
gwNkjI= ,  
{ musxX58%  
Zh^w)}(W  
throw new JspTagException(“一个没有connection属性的查询标签必须被一个connection标记嵌套。”);  64fG,b  
Kjw\SQ)2~  
} #KW:OFT  
 ?~IZ{!  
connection = ancestorTag.getConnection(); '7s!N F2  
54w-yY  
} a"0~_=  
55p=veq \  
} 90}B*3x  
 U2$T}/@  
} I r~X#$Upc  
n]Y _C^  
}DaYO\:yK*  
kM`#U *j  
此查询标签在JSP页面中的调用形式可以从以下2种定义中任选一种: 9l]IE,u  
3(5Y-.aK}^  
9<S-b |!@  
<tt:connection id=”con01” ...> ... </tt:connection> Dzr5qP?#  
jq{Ix  
<tt:query id=”balances” connection=”con01” > 2wQ CQ"  
>qA&;M  
SELECT account, balance FROM acct_table SZvsJ)  
[_n|n"M  
where customer_num = <%= request.getCustno() %> G2D<LRWt4  
$ cSZX#\  
</tt:query> n4johV.#  
?f..N,s  
Kq$1lPI  
7ZZt|bl  
K#r` ^aUc  
<tt:connection ...> I]X<L2  
)A%Y wI$  
<x:query id=”balances”> jQ*Qh  
o@. !Z8  
SELECT account, balance FROM acct_table s8Oz^5p(  
#SueT"F  
where customer_num = <%= request.getCustno() %> WM26-nR  
A_%w (7o"  
</x:query> M .,|cx  
UlrY  
</tt:connection> ikQ2x]Sp  
rNc>1}DDS  
2lRZ/xaF%P  
与此同时,在TLD中必须指定connection属性为可选的,定义如下: {y'k wU  
d yd_dK/  
<tag> jLTs1`I/F  
zYgLGwi{  
... GcuZPIN%D  
GCHssw~P'v  
<attribute> .+yJ'*i$d  
wal }[F#  
<name>connection</name> Sgj6tH2M  
}_ E  
<required>false</required> ]7;;uhn`  
']Z8C)tK  
</attribute> xpz Jt2S  
P}gh-5x  
</tag>
描述
快速回复

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