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

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

级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
标准的JSP 标记可以调用JavaBeans组件或者执行客户的请求,这大大降低了JSP开发的复杂度和维护量。JSP技术也允许你自定义taglib,其实换句话说,taglib可以看成是对JSP标记的一种扩展,正如xml是对html的一种扩展一样。taglib通常定义在tag标签库中,这种标签库存放着你自己定义的tag标签。简而言之,如果使用taglib,那么你可以设计自己的JSP标记! I16FVdUun4  
I8H3*DE  
一般来说,自定义tag标签主要用于操作隐藏对象、处理html提交表单、访问数据库或其它企业级的服务,诸如邮件和目录操作等等。自定义tag标签的使用者一般都是那些对java编程语言非常精通,而且对数据访问和企业级服务访问都非常熟悉的程序员,对于HTML设计者来说,使得他可以不去关注那些较复杂的商业逻辑,而将精力放在网页设计上。同时,它也将库开发者和库使用者进行合理分工,自定义tag标签将那些重复工作进行封装,从而大大提高了生产力,而且可以使得tag库可用于不同的项目中,完美地体现了软件复用的思想。 ^z,3#gK  
uU  d"l,V  
在这篇文章中,我们主要讨论: dwj?;  
rYUIFPN  
· 什么是自定义tag标签? $H:!3 -/  
:;?$5h*|`  
· 怎么使用tag标签? 2a d|v]  
2D\ pt  
o 声明要使用的tag库 F>;Wbk&[|  
U)}]Z@I-  
o 找到与之对应的tag处理类 )&Ii! tm3  
SX4*804a_  
o tag标签的类型 A#U! KX  
E^8|xT'h6  
· 自定义tag标签 xd Z$|{,  
l u=a e<M  
o tag处理类 wMa8HeBE\  
%ms%0%  
o tag库描述 U-|]A\`)I  
lyn%r  
o tag标签示例 TrI+F+;  
hgU;7R,?ir  
o 带属性的tag ]jT}]9Q$  
6<&~ R 3dQ  
o 带body的tag KsDS!O  
U}92%W?  
o 定义了脚本变量的tag "t|)Kl  
dX(JV' 18A  
o 具有协作关系的tag Z |$#  
HoI6(t  
· 自定义tag标签 O&!R7T  
&raqrY|V  
o 一个迭代tag的例子 3%vXB=>T!  
|Xt G9A>  
o 一个模板tag库 xAm tm"  
Q14zc0N  
o tag处理类到底是怎样被调用的? ay"jWL-  
{C |R@S  
v,4{:y]p  
什么是自定义的tag? g`fG84  
*s6 x  
一个自定义的tag标签是用户定义的一种JSP标记。当一个含有自定义的tag标签的JSP页面被jsp引擎编译成servlet时,tag标签被转化成了对一个称为tag处理类的对象进行的操作。于是当JSP页面被jsp引擎转化为servlet后,实际上tag标签被转化成为了对tag处理类的操作。 zs$r>rlO  
G e;67  
自定义tag标签有很多特色,诸如: }'[>~&/"  
bY_'B5$.^2  
· 可以在JSP页面中自定义tag标签的属性 C'R9Nn'  
qqDg2,Yb  
· 访问JSP页面中的所有对象 Z\ hcK:  
)O'LE&kQ|  
· 可以动态地修改页面输出 {f06Ki  
Gxr\a2Z&r%  
· 彼此这间可以相互通信。你可以先创建一个JavaBeans组件,然后在一个tag中调用此JavaBeans组件,同时可以在另一个tag中调用它。 Xv1vq -cM  
m*^)#  
· tag允许相互嵌套,可以在一个JSP页面中完成一些复杂的交互。 x $uhkP  
7# AIX],  
=D<0&M9C  
使用tag标签 ]545:)Q1  
Ft5A(P >  
Emlj,c<?j  
本节主要描述怎样在JSP页面中使用tag标签,以及tag标签的不同类型。 *)m:u:   
5c- P lm%  
要使用tag标签,JSP程序员必须做2件事: \`Hp/D1  
?N kKDvv  
· 声明此tag标签的tag库 Ny^ 1#R  
!73y(Y%TE  
· 实现此tag标签 *g5bdQ:Av~  
~${~To8$CW  
声明tag标签所在的tag库 OG$n C  
Q2 q~m8(  
如果要使用tag标签,则应用JSP的taglib指示符来指定其tag库(注意:taglib要在在使用此tag标签之前声明) e5_Hmuk|  
4`O[U#?  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> w>W#cTt  
20Zxv!  
uri属性定义了唯一的标签库描述(以下简称TLD),它可以是直接是tld文件名或一个独一无二的名字。prefix是用来区别其它TLD中和本TLD中有重名的tag的一种手段。 Zue3Z{31T  
OP/DWf  
TLD必须以.tld作为扩展名,并且存放在当前应用的WEB-INF目录或其子目录下。你可以通过它的文件名直接引用它,也可以通过别的方式间接地引用它。 JFv70rBe  
$dfc@Fn^x  
以下taglib指示符直接引用一个TLD: T//xxH]w-  
s|C[{n<_  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> s8-RXEPb  
M0 z%<_<}  
以下的taglib指示符通过一个逻辑名称间接地引用一个TLD: 0/HFLz'  
M9)4ihK  
<%@ taglib uri=”/tutorial-template” prefix=”tt” %> Wf c/?{  
P2n8HFi  
如果是间接引用TLD的话,那你必须还要在web.xml中定义此逻辑名称与tld文件之间的映射,具体做法是在web.xml中加入一个名为taglib的元素: cSL6V2F  
*\ii +f-  
<taglib> !}Xoqamm  
Snr(<u  
<taglib-uri>/tutorial-template</taglib-uri> l";Yw]:^  
|5u~L#P  
<taglib-location> KL \>-  
rLTBBvV  
/WEB-INF/tutorial-template.tld \$9C1@B@  
2"&GH1  
</taglib-location> 7@@g|l]  
gvP-doA7W  
</taglib> N~/ 'EaO  
=3-=p&*  
3IYFvq~  
实现此tag标签 ^E}?YgNp  
 h,/Aq  
?:r?K|Ku  
为了实现tag标签,你有2种方法来存放tag处理类。一、让tag处理类以.class的方式存放于当前应用的WEB-INF/class子目录下,二、如果tag处理类是以JAR包的形式存在的话,那可以放在当前应用的WEB-INF/lib目录下,如果tag处理类要在多个应用中共享,那么它就应放在jsp服务器上的common/lib目录下,对于tomcat来说,就是tomcat/common/lib目录下。 =lAjQt  
IfmQP s+f  
=g+}4P  
tag标签类型 O Z ./suR)  
jNj;#C)  
Pmv@  
自定义的tag标签遵循XML语法。它有一个开始标记和一个结束标记,有的还有body(即文本节点): BX/3{5Y>{  
nDn J}`k  
<tt:tag> l uP;P&  
uV:R3#^  
body IiE6i43  
T)P)B6q   
</tt:tag> HOx4FXPs  
I>?oVY6M@u  
|]-Zz7N)  
一个不带body的tag标签如下: q>_<\|?%x  
mZ71_4X#  
<tt:tag /> *RkUF!)(  
k`5I"-e  
Avw=*ZW  
简单的tag标签 ///Lg{ ie  
96w2qgc2  
一个没有body和属性的tag标签如下: bK:U:vpYm  
0?54 8yH  
<tt:simple /> ?^VPO%  
ZR1U&<0c@  
FKO2UY#&7  
带属性的tag标签 `D;*.zrA  
oU|G74e6  
V'9.l6l   
自定义标签可以有自己的属性。属性一般在开始标记中定义,语法为 attr=”value”。属性的作用相当于自定义标签的一个参数,它影响着tag处理类的行为。你可以在TLD中详细定义它。 4Y(@ KUb  
iC3z5_g*@  
你可以用一个String常量给一个属性赋值,也可以通过表达式给它赋值,如<%= ...%>。以struts为例,它的logic:present标签就是用的String常量来给属性赋值: &tH?m;V  
TuQGF$n@  
<loglic:present parameter = “Clear”> xM%4/QE+  
tp`1S+'~j  
而另一个标签logic:iterate是用表达式来给属性赋值: d,GOP_N8I  
"3^tVX%$\[  
<logci:iterate collection=”<%= bookDB.getBooks() %>” 9FDu{4:  
6f +aGz  
id=”book” type=”database.BookDetails”> f<8Hvumw  
lpG%rN!  
~N!HxQ  
带body的tag标签 k6CXuU  
'xH^ksb"  
一个自定义标签可以包含其它自定义标签、脚本变量、HTML标记或其它内容。 `X<B+:>v-  
>Y>R1b%  
在下述例子中,此JSP页面使用了struts的logic:present标签,如果些标签定义了parameter=”Clear”的属性,则将清除购物车的内容,然后打印出一条信息: JP8}+  
Et3I(X3  
<logic:present parameter=”Clear”> }JFTe g  
t5{P'v9J  
<% cart.clear(); %> 6x^$W ]R  
=TD`Pet  
<font color=”#ff0000” size=”+2”><strong> Z:9Q~}x8  
sZrVANyqb  
你选择了清除购物车! gGM fy]]R  
1Ms]\<^j  
</strong></font> g-qXS]y7  
>NUbk9}J4  
</logic:present> u%C oo  
f\_RW;y|m  
c|/HX%Y  
到底是用属性还是用body来传递信息? <UGaIb  
N|DfE{,  
如上所述,我们既可以通过属性,也可以通过body来传递信息。但一般来说,比较简单的类型,如字符串或简单表达式最好采用属性来传递信息。 nL 5tHz:e  
-PV1x1|  
x*Z'i<;B  
定义脚本变量的tag标签 )9H5'Wh#  
irQ'Rm [  
所谓脚本变量,是指JSP中可以调用的变量或对象。它可由tag标签产生。以下示例阐述了一个tag标签定义了一个名为tx的由JNDI所定义的事务处理对象。脚本变量可以是ejb对象、事务、数据库连接等等: L('1NN 2  
$e+sqgU  
<tt:lookup id=”tx” type=”UserTransaction” name=”java:comp/UserTransaction” /> 7I;kh`H$(f  
aDdxR:  
<% tx.begin(); %> *$=i1w  
4<Vi`X7[F  
... M FIb-*wT  
cK'g2S  
vK!`#W`X  
具有协作关系的tag标签 necY/&Ld-  
[Vs\r&qL  
自定义tag标签之间可以通过共享对象来实现协作。在下述例子中,标签tag1创建了一个名为obj1的对象,在标签tag2仍可以重复使用obj。 iaL@- dg  
~ YH?wdT  
<tt:tag1 attr1=”obj1” value1=”value” /> i >3`V6  
?W'z5'|  
<tt:tag2 attr1=”obj1” /> nkHl;;WJ  
F;Q,cg M  
在以下这个例子当中,如果外层的tag标签创建了一个对象,那么其内层的所有tag标签都可以使用这个对象。由于这样产生的对象没有一个指定的名字,那么就可以将少重名的冲突。这个例子阐述了一系列协作的嵌套对象。 s!(R  
L3{(B u  
<tt:outerTag> G|,&V0*  
-K/+}4i3N  
<tt:innerTag /> ^xHKoOTj[  
Xc-["y64  
</tt:outerTag> mI8EeMa{  
`Na()r$T  
( eKgc  
Tag处理类 aMI;; iL^  
LhO\a  
0%bCP/  
Tag处理类必须实现Tag接口或BodyTag接口,不过现在一般都流行从TagSupport或BodyTagSupport类中继承,这些类或接口都可以在javax.servlet.jsp.tagext包中找到。 NQqw|3  
)M0`dy{1  
当JSP引擎看到自己的JSP页面中包含有tag标签时,它会调用doStartTag方法来处理tag标签的开头,调用doEndTag方法来处理tag标签的结束。 ^BF}wQb :j  
&ZD@-"@  
下表说明不同类型的tag所需要不同的处理过程: 8xB-cE  
wlNL;W@w  
Tag处理类的方法 dWn6-es  
WX4sTxJK  
Tag标签类型 TO Hz3=  
所调用的方法 >SXSrXyYX  
k>ErD v8  
基本标签 b/_Zw^DPC  
doStartTag, doEndTag, release Hf('BagBL  
SRfh{u  
带属性的标签 [~N;d9H+*1  
doStartTag, doEndTag, set/getAttribute1...N, release =RWTjTZ   
h@`Rk   
带内容的标签 VgbNZ{qk@  
doStartTag, doEndTag, release g}%ODa !H  
;7\Fx8"s[  
带内容的标签,且内容重复循环 h8(#\E  
doStartTag, doAfterBody, doEndTag, release eKr>>4,-P  
KZ2[.[(Ph  
带内容的标签,且内容与JSP交互 3A,N1OXG  
doStartTag, doEndTag, release, doInitBody, doAfterBody, release Q# hRnM  
N|i>|2EB  
一个tag处理类可以通过javax.servlet.jsp.PageContext来与JSP交互,通过javax.servlet.jsp.PageContext类,tag处理类可以访问JSP中的request、session和application对像。 eV"%(<{  
Ke4oLF2  
如果tag标签是互相嵌套的,那内层的tag处理类可以通过它的parent属性来访问上层的tag处理类。 7RT{RE  
wm@j(h4  
一般情况都将所有的tag处理类打成了JAR的包,以便于发布。 Onx6Fy]L  
3#t9pI4  
$$ND]qM$M  
Tag库描述(简称TLD) #ksDU  
$^Xxn.B9  
qlcd[Y*B  
Tag库是用xml语言描述的,TLD包括了tag库中所有tag标签的描述,它一般用来被jsp服务器用来校验tag的语法正确性,或者被jsp开发者用来开发新的标签。 ~DD _n  
"]"0d[d  
TLD的文件扩展名必须为.tld,而且必须放在当前WEB应用的WEB-INF目录或其子目录中。 C@Wzg  
I7vP*YE 7F  
一个TLD的内容的开头必须遵守标准的XML开头,用于描述DTD和xml的版本,例如: 5.^pD9[mT  
JA4Zg*7I  
<?xml version="1.0" encoding="ISO-8859-1" ?> k^oSG1F  
bkJ bnW=  
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd"> .6gx|V+  
TLD必须以<taglib>来作为它的根元素,<taglib>的子元素如下表:  ,t 2CQ  
uUfw"*D  
P' VHga  
<taglib>的子元素 )>M L7y  
&m--}  
Element l-w4E"n3  
Description 3}}/,pGSc  
JM;bNW8  
tlib-version eP~3m  
Tag库的版本 | va@&;#wf  
)#AYb   
jsp-version ;Pk"mC  
Tag库所需要的jsp的版本 OD'~t,St  
:kHk'.V1(  
short-name lH3.q4D 5  
助记符,tag的一个别名(可选) #)S}z+I  
b]]k\b  
uri 4>(K~v5;N  
用于确定一个唯一的tag库 Mg\588cI  
H s)]  
display-name r)S:= Is5  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) F,_cci`p  
),{3LIr  
small-icon 2M+RA}dX  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) lSR\wz*Fk  
L~ax`i1:"  
large-icon XF: wsC  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) &3/`cl[+  
Sp[9vlo8  
description q5g_5^csM{  
对tag库的描述(可选) HZ<#H3_ix  
il >+jVr  
listener }F1Asn  
参见下面listener元素 .U(6])%;@  
iY>x x~V  
tag 8GxT!  
参见下面tag 元素 ybJa:  
wSjy31  
Listener元素 7eq.UyUxs  
PE7V1U#$o,  
一个tag库可能定义一些类做为它的事件侦听类,这些类在TLD中被称为listener 元素,jsp服务器将会实例化这些侦听类,并且注册它们。Listener元素中有一个叫listener-class的子元素,这个元素的值必须是该侦听类的完整类名。 hak#Iz0[C  
jEKa9rt  
Tag元素 =pe O %  
9I 6^-m@:  
每个tag元素在tag库中都要指出它的名字、类名、脚本变量、tag的属性。其中脚本变量的值可以直接在TLD中定义或通过tag附加信息的类来取得。每个属性描述了这个属性是否可以省略,它的值是否可以通过<%= …%>这样的JSP语法来获得,以及属性的类型。 "^t7]=q  
4oF,;o+v\4  
每一个tag在TLD中对应一个tag元素,下表是tag元素的子元素: 36'J9h\  
rKPsv*w  
Tag元素的子元素 }c/#WA|b  
QPVr:+\B{  
元素名称 8;=?F>]xn  
描述 W=2.0QmW  
IF>v -Z  
name ? Zv5iI  
独一无二的元素名 &/EZn xl  
akw:3+`  
tag-class \yymp70w  
Tag标签对应的tag处理类 %|@?)[;  
R(Vd[EGY  
tei-class _6FDuCVD-  
javax.servlet.jsp.tagext.TagExtraInfo的子类,用于表达脚本变量(可选) *RkvM?o@jC  
y3*IF2G  
body-content N cHCcc  
Tag标签body的类型 J'cE@(US  
.WOF:Nu4  
display-name IwFf8? 3  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) M-Nn \h$,  
>VjtKSN  
small-icon f].z.  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) PmId #2f  
ZbH6$2r  
large-icon D622:Y886  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) Zo-Au  
zh !/24p9  
description JmF`5  
此tag标签的描述 J!rZs kd  
-'W:P'BG  
variable UL7%6v{'*  
提供脚本变量的信息(同tei-class)(可选) ]H:K$nmX  
Zfu" 8fX  
attribute YVY(uq)d  
Tag标签的属性名 r~;.8qs  
h\-jqaq  
以下章节介绍对于不同类型的tag,如何具体地实现它们。 a(o[ bH.|;  
Y!E| X 3  
zJ0'KHF}o  
简单的tag d@|j>Z  
gvZLW!={  
XeBSHvO_  
tag处理类 OQX ek@~2  
L3Q1az!Ct  
简单的tag处理类必须实现Tag接口的doStartTag和doEndTag方法。当jsp引擎碰到tag标签的开头时,doStartTag被调用,因为简单的tag没有body,所以此方法将返回 SKIP_BODY。当jsp引擎碰到tag标签的结尾时,doEndTag被调用,如果余下的页面还要被计算,那它将返回EVAL_PAGE,否则将会返回SKIP_PAGE。 6a`_i  
qf] OSd  
以下是例子:对于标签 <tt:simple /> ,它的tag处理类实现如下: 6 ud<B  
NOmSLIgt7  
PzTTL=G +  
public SimpleTag extends TagSupport ]*;+ U6/?  
RZE:WE;5  
{  K[TMTn  
;v+CQx  
public int doStartTag() throws JspException 7e#|=e *I!  
a( {`<F  
{ Zr 2QeLQC(  
1J *wW# e  
try{ N<Q}4%^c  
uJp}9B60_  
pageContext.getOut().print(“Hello.”); l1_X5DI  
dl$l5z\  
}catch(Exception e){ <ct{D|mm  
f&cG;Y  
throw new JspTagException(“SimpleTag: “ + e.getMessage()); "AVj]jR  
.r*b+rc;]  
} s*#|EdD6@  
a m zw  
return SKIP_BODY; ;09J;sf  
|]\bgh  
} +[ }]a3)  
/~tfP  
public int doEndTag() 6k3l/~R  
fAUsJ[  
{ s* YFN#Wuc  
17Gdu[E  
return EVAL_PAGE; ?h3Ow`1G  
m<f{7]fi5  
} ?H c A&  
246lFx G.  
} /+1Fa):  
22r01qH  
Pd;ClMa%  
注意:如果tag标签没有内容的话,那必须定义body-content元素为空,例如 mVL,J=2  
< 5_Ys  
<body-content>empty</body-content> | uZ=S]V@  
tr/dd&(Y1  
y?@Y\ b  
带属性的tag标签
评价一下你浏览此帖子的感受

精彩

感动

搞笑

开心

愤怒

无聊

灌水
级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
只看该作者 1 发表于: 2007-01-01
tag处理类 E$>e< T  
2,;t%GB  
对于tag标签的每个属性,你必须依照JavaBeans规范来定义其属性,以及get和set方法。以struts的logic:present 标签为例, !Cy2>6v7  
*pD;AU  
<logic:present parameter=”Clear”> lmcDA,7  
 ck~xj0  
与此相应,此tag处理类应有如下方法和定义: c-=0l)&'D=  
^Q,/C8qeb  
wqOhJYc  
protected String parameter = null; ,;-*q}U  
L K~,  
public String getParameter() Qd4T?5 vG  
V6{xX0'b*m  
{ =|%T E   
W7o/  
return this.parameter; qU n>  
ui{_w @o  
} {LD8ie|x1`  
y4L9Cxvs  
public void setParameter(String parameter) NFc8"7Mz}  
ksaC[G;}:  
{ A,e^bM  
_MEv*Q@o  
this.parameter = parameter; 'X,V  
\veL5  
} 8vw]u_e  
Xt84Evo  
KxwLKaImI  
注意:如果你的属性名为id,而且你的tag处理类是从TagSupport类继承的,那你就不需要定义它的属性和set和get方法,因为他们早已在TagSupport被定义过了。 n_Y]iAoc`  
UVJ(iNK"  
Attribute元素 VC(|t} L4  
sEN@q   
对于tag标签的每个属性,你必须定义它是否必须的,它的值是否可以用诸如<%= …%>的表达式来获得,以及它的类型(可选),如果不指定它的类型,那就默认为是java.lang.String类型。如果rtexprvalue元素被定义为true或yes,那么在type元素中就定义了attribute的返回类型。 0cUt"(]  
~m?~eJK#a  
<attribute> K-u/q6ufK  
B ,Brmn  
<name>attr1</name> ? $ c  
i=oa"^c4  
<required>true|false|yes|no</required> WCu%@hh=h  
,GnU]f  
<rtexprvalue>true|false|yes|no</rtexprvalue> fO>~V1  
g:M7/- "  
<type>attribute的返回类型(只用当rtexprvalue为真是才有效)</type> b]#d04]  
$@k w>2  
</attribute> F8Wq&X#r  
1[`<JCFClc  
如果tag的某个属性不是必须的,那tag处理类会自动提供一个缺省值。 6{X>9hD  
.A/H+.H;  
例如,在logic:present这个tag标签中定义了一个属性叫parameter,但它不是必须的,而且它可以被诸如<%= …%>的表达式来赋值。 }2,#[m M  
ItPK  
<tag> 3= zQ U  
`=DCX%Vw  
<name>present</name> 8|NJ(D-$  
yo,!u\^x  
<tag-class>org.apache.struts.taglib.logic.PresentTag</tag-class> r&sOM_BUF  
p&mtKLv  
<body-content>JSP</body-content> G9inNz*Cx  
np^<HfYV  
… p'k+0=  
a?~csP^?}  
<attribute> ONiI:Z>%  
o~&!M_ED  
<name>parameter</name> MwqT`;lb  
Jk`)`94 I  
<required>false</required> iBC>w+t14  
QS*cd|7J;  
<rtexprvalue>true</rtexprvalue> ><R.z( 4%  
AuipK*&g  
</attribute> H<}eoU.  
:&)/vq  
… ld}$Tsy0  
A i){,nh`0  
</tag> >wO$Vu `t  
]G PJ(+5  
otD?J= B  
属性元素的校验 B~z g"  
=L),V~b  
{WeXURp&nF  
有关于tag标签的有效值可以从tag库的说明文档中获得,当JSP页面被编译时,jsp引擎会强制性地参照TLD中定义的规则进行检查。 `lezJ (Xm  
s[@>uP  
还有一个方法也可以进行属性元素的校验,就是先继承类TagExtraInfo,然后调用它的isValid方法。这个类同时也起到提供tag中定义的脚本变量信息的作用。 2\B9o `Y  
A=d$ir K[  
IsValid方法通过TagData对象来传递属性信息,它包括着tag的所有的属性名-值的信息。由于校验发生在运行时刻,因此这个属性的值将被赋值为TagData.REQUEST_TIME_VALUE。 6H,=S`V]EK  
/JubiLEK  
例如tag标签<tt:twa attr1=”value1” />在TLD中定义如下: :;;WK~* #  
6oh@$.ThG  
<attribute> m<"fRT!Y  
RLOQ>vYY  
<name>attr1</name> yUmsE-W  
I''R\B p  
<required>true</required> A{x 7  
>04>rn#},,  
<rtexprvalue>true</rtexprvalue> *3`oU\r  
DE\bYxJ  
</attribute> uE#,c\[8  
g)?g7{&?>?  
zZ"U9!T  
这个定义说明了attr1能在运行期间被赋值。 )]c3bMVE-  
s[2ZxCrCw  
以下的isValid方法检查attr1属性的值是否属于Boolean类型。注意由于attr1能在运行刻被赋值,那么isValid方法必须检查tag用户是否对此tag进行了运行时刻赋值。 )1nCw  
)QCM2  
&_/%2qs  
Public class TwaTEI extends TagExtraInfo "=\_++  
6eYf2sZ;J  
{ =l2Dm  
uV}WSoq[  
public boolean isValid(Tagdata data) 0O,T=z[+>  
oA;Ty7s  
{ ^h6$> n5  
W({TC  
Object o = data.getAttribute(“attr1”); H4'DL'83  
''OInfd?  
If(o != null && o != TagData.REQUEST_TIME_VALUE) wYO"znd  
sC5uA .?>9  
{ Jp3di&x  
Qj<{oZp&  
if( ( (String)o).toLowerCase().equals(“true”) || YG 5Z8@kH  
0SY f<$  
((String)o).toLowerCase().equals(“false”) ) _p J_V>l  
ca/o#9:N`:  
return true; yaRcBT?  
!\#Wk0Ku  
else %:w% o$  
yvoo M'R  
return false; "vOfAo]`  
`,Y[Z  
} 0YpiHoM  
2@R8P~^W  
else fQW_YQsb  
IFrb}yH  
return true; GtM( Y  
7}'A)C>J;  
} Vv yrty  
?)mhJ/IT  
} _@/C~  
I51oG:6fR?  
J(EaE2  
带body的tag X(y  
YF! &*6m  
JU'WiR bcb  
tag处理类 /}nrF4S  
_D>as\dP  
88#qu.  
如果tag标签含有内容,那处理方式会略微有些不同,而且还要视tag处理类是否要与body交互的情况而定。如果要与body交互,那我们认为tag处理类要可能要对body进行操作。 hk@`N;dn  
B]|6`UfB  
Tag处理类不与body交互 RF4$  
\U!@OX.R'M  
如果tag处理类不与body交互,tag处理类应该实现Tag接口或从TagSupport中派生,如果body要被计算,那么doStartTag方法应返回 EVAL_BODY_INCLUDE,否则应返回SKIP_BODY。 Ac[|MBaF  
S"P9Nf?9  
如果tag处理类要对body反复运算,则它应该实现IterationTag或从TagSupport中派生。如果tag处理类认为body还未计算完的话,那它的doStartTag方法和doAfterBody方法必须返回EVAL_BODY_AGAIN。 (lN;xT`=  
HCJ8@nki  
Tag处理类与body交互 P^8^1-b  
V/3 {^Fcr  
如果tag处理类与body交互,那tag处理类应实现BodyTag接口或从BodyTagSupport中派生。这种tag处理类一般要实现doInitBody和doAfterBody方法。 ~[zFQ)([  
3"'# |6O9  
Body允许一些方法来读写它的内容。Tag处理类可以调用body内容的getString或getReader方法来从body中提取信息,也可用 writeOut(out) 方法来将body的内容写入到out对象中。其中out对象通过tag处理类的getPreviousOut方法来获得。 rmPne8D=c(  
lk[G;=K:.  
如果body的内容需要被计算,那么doStartTag方法必须返回EVAL_BODY_BUFFERED,否则,它将返回 SKIP_BODY。 B0)`wsb_  
i5 L:L  
doInitBody 方法 <o&o=Y8  
DIG0:)4R.  
此方法在body内容已经设好,但未被计算之前被调用。你可以根据不同的body内容来制定初始化策略。 a1g6}ym\  
c{mKra  
doAfterBody方法 Mhe |eD#)  
I%}L@fZ  
此方法在body内容已被计算后进行调用。 <AI>8j6#B  
cQ(}^KO  
和doStartTag方法一样,doAfterBody方法返回一个指示符指示是否要继续计算body,如果要继续计算,则doAfterBody应返回EVAL_BODY_BUFFERED,否则,它应返回SKIP_BODY。 g>~cs_N@  
(VYR!(17  
release 方法 9Hf*cQ  
cW)Oi^q%o2  
tag处理类调用此方法将它的状态重置为初始状态,并释放所有的私有资源。 NZo<IKD$  
<I7(eh6d  
{H=oxa  
以下的例子读取body的内容(其中含有一条sql语句),然后将它传递给一个对象,让它进行查询。由于此处body不须重新计算,所以doAfterBody会返回SKIP_BODY。 :cc[Jco@w  
}rz dm9  
xdd:yrC   
Public class QueryTag extends BodyTagSupport ~~C6)N~1  
Ky[bX  
{ kqVg2#<@M  
8^/+wa+G  
public int doAfterBody() throws JspTagException cT-K@dg  
3yTQ  
{ M!N` Orz  
4 ,p#:!  
BodyContent bc = getBodyContent(); eM?rc55|  
t a&Q4v&-  
//将body的内容以字符串的格式提取出来 >j50 ;</  
l^k+E-w\  
String query = bc.getString(); %{R _^Y8t  
|x &Z~y  
//清除body XVQL.A7  
?^LG hdR  
bc.clearBody(); YF}9k  
8#+`9GI  
try{ sS, zzx<  
o"|O ]  
Statement stmt = connection.createStatement(); .aNO( /kO  
7w "sJ  
Result result = stmt.executeQuery(query); f5@.^hi[  
p QluGIX0V  
}catch(SQLException e){ [J~aAB  
z*6$&sS\>  
throw new JspTagException(“queryTag: “ + e.getMessage() ); ZV!R#Xv  
@&?a]>L  
return SKIP_BODY; ]{YN{  
! L4dUMo  
} Dba+z-3Nzy  
H}vn$$ O  
} VR "u*  
hIR@^\?  
qh%i5Mu  
body-content元素 oG!6}5  
7egq4gN]2Y  
lZ}P{d'f.  
由于tag可能会有body,你必须用body-content元素来指定body内容的类型: F(deu^s%{  
uu}'i\Q  
<body-content>JSP|tagdependent</body-content> 8{oZi]ob  
F4Rr26M  
);=Q] >  
如果body的内容是定制的或内部的tag、脚本元素、或HTML广本,则归类为JSP类型。其他的类型,比如上面代码所述的?D?D将sql statement类传给 query tag的这种类型应该标为tagdependent。 Q}=fVY  
s4 (Wp3>3i  
注意:实际上body-content的值并不影响tag处理类对body内容的处理,它仅仅是被tag编辑工具用来描述此body的内容。 $h,d? .u6w  
ZQ|5W6c  
PmHd9^C  
用tags定义脚本变量 ]de\i=?|  
Ujf,6=M  
/K f L+"^|  
tag处理类 iBucT"d]  
5i6VZv  
(I[s3EnhS  
tag处理类负责创建或设置页面中定义的脚本变量,用pageContext.setAttribute(name,value,scope)或pageContext.setAttribute(name,value)方法来实现。一般来说,tag处理类通过脚本变量的名称来获取它,脚本变量的名称一般可用get方法来获得。 8`}l\ Y  
W/sY#"  
如果脚本变量的值依赖于tag处理类中的上下文中某一对象,那它可用pageContext.getAttribute(name,scope)方法来找到那个对象。一般的处理过程是tag处理类先找到脚本变量,再对其进行处理,然后用pageContext.setAttribute(name,object)的方法来设置它的新值。 RF:04d  
\UOm]z  
对象的生存周期(scope)如下表: j(sLK &  
W;qP=DK2  
对象的生存周期表 C?/r;  
J2m"1gq,  
名字 <P- $RX  
可访问范围 >zQNHSi  
生存周期 Uls+n@\!  
DE%fF,Hk3  
page VrVDm*AGQ  
当前页面 @a0Q0M  
一直有效,除非页面向客户提交响应或重定向到一个新页面 975 _d_U  
xpAok]  
request ^CUSlnB\(  
当前页面或当前页面重定向到的页面 I`NUurQTX  
一直有效,除非页面向客户提交响应 n,CD  
!:3^ hb  
session M_Bu,<q^  
当前页面或在同一浏览器窗口中的页面 Y17hOKc`  
一直有效,除非关闭当前浏览器、超时、网络故障 7#ofNH J  
ul$,q05nb  
application iUTU*El>  
整个web应用程序的所有请求 n&$/Q$d&  
一直有效,除非发生网络故障、服务器故障 uxb:^d?D!  
F_ 81l<  
提供关于脚本变量的信息 1eHe~p ,  
2 L:$aZ  
以下示例定义了一个名为“book”的脚本变量,用来访问程序中关于书的信息: D^|9/qm$  
K3L"^a  
<bean:define id=”book” name=”bookDB” property=”bookDetails” type=”database.BookDetails” /> `"c'z;  
W!91tzs:  
<font color=”red” size=”+2” > "TNVD"RLY  
QXs8:;T  
<%= messages.getString(“CartRemoved”) %> q6R Eh;$  
Cc Y7$D  
<strong><jsp:getProperty name=”book” property=”title” /></strong> NO2(vE  
Vc _:*  
</font> W qE '(  
!>3LGu,  
当包含此tag的JSP页面被编译时,jsp引擎会自动生成关于此book的同步的代码(同步可以避免几个客户同时访问此book时造成的冲突),要生成同步代码,jsp引擎需要知道此脚本变量的如下信息: 2e59Ez%k6  
^&Q< tN 7  
· 脚本变量名称 E=]]b;u-n  
&<Zdyf?[Ou  
· 脚本变量所属的类 8eN7VT eb  
\x(^]/@  
· 此脚本变量是否引用了一个新的或已存在的对象 f}iU& 3S  
dw9T f^V  
· 此脚本变量的有效性 +P)ys#=  
{~'H  
有两种办法可以向jsp引擎提供关于脚本变量的信息:在TLD中定义variable子元素,或用tei-class子元素定义一个额外tag信息类。用variable最简单,但可能降低了一些灵活性。 gfN2/TDC]P  
epkD*7  
Variable元素 R!6=7  
6]n/+[ ks  
Variable元素有如下子元素: o/^1Wm=  
:^#vxdIC?  
· name-given ?D?D 给出的名字,是一个常量 A?A9`w  
DZk1ZLz  
· name-from-attribute?D?D 属性名,在编译时给出的属性名 f@d9Hqr+l;  
yQ%"U^.m  
name-given或name-from-attribute两者必须选一,但以下子元素是可选的: nxfoWy  
~8{sA5y  
· variable-class?D?D变量的类型,缺省为java.lang.String。 KP{3iUqvO  
gi$XB}L+X  
· declare?D?D此脚本变量是否引用了一个新对象,缺省为True。 I]9 C_  
\f%.n]>  
· scope?D?D脚本变量的范围,缺省为NESTED。下表描述了scope的几种类型: 8EI:(NE*J  
$gvr -~  
脚本变量的有效范围 ?:uNN  
VD [pZ2;4  
值 "VTF}#Uo  
有效性 )R &,'`\  
方法 DpvrMI~I_  
<#*.}w~  
NESTED w7 *V^B  
在tag标签的开始和结束之间 )/>A6A:  
如果tag处理类实现BodyTag接口,则在doInitBody和doAfterBody中调用,否则在doStartTag中调用 ~*-qX$gr  
`5l01nOxJ  
AT_BEGIN T$mbk3P  
从tag标签的开始一直到页面结束 2hq\n<  
如果tag处理类实现BodyTag接口,则在doInitBody、doAfterBody和doEndTag中调用,否则在doStartTag和doEndTag中调用 )];aIA$  
tJ'iX>9I  
AT_END snC/H G7  
从tag标签的结束一直到页面结束 FnE6?~xa  
在doEndTag中调用 G3a7`CD  
s`;f2B/|  
以struts为例,它的bean:define标签的实现遵循JSP1.1规范,此规范要求使用额外tag信息类来定义脚本变量。Variable元素是JSP1.2规范中加入的。以bean:define标签为例,你可以定义如下variable元素: +~35G:&:  
jatr/  
<tag> +TSSi em  
v* ~3Z1  
<variable> suVmg-d  
FFvCi@oT  
<name-from-attribute>id</name-from-attribute> *x(Jq?5O7X  
BJy;-(JP  
<variable-class>database.BookDetails</variable-class> +>tUz D  
Fr [7  
<declare>true</declare> ;gB`YNL  
yWb4Ify  
<scope>AT_BEGIN</scope> q-_' W,  
Z a(|(M H  
</variable> ahGT4d`)9  
/XbW<dfl  
</tag> c^9tYNn  
*C2R`gpBI  
额外tag信息类 {HrZ4xQnpV  
d5!!Ut  
如果要定义一个额外tag信息类,你要继承javax.servlet.jsp.TagExtraInfo类。一个TagExtraInfo类必须实现getVariableInfo方法,此方法返回一个叫VariableInfo的数组类,它包括如下信息: J ^ G  
Apfnx7Fv  
· 变量名 S v`qB'e2  
MbA\pG'T  
· 变量所属类名 4 b,N8  
2?DRLF]  
· 此变量是否引用了一个新对象 {x@|VuL=  
xDjV `E]  
· 此变量的有效范围 T?wzwGp-[  
|"Z{I3Umg  
jsp引擎将一个名为data的参数传给getVariableInfo方法,data中包括tag标签中的所有“属性名?D?D属性值”对。它可以用来向VariableInfo对象提供脚本变量的名字和类名。 <+tD z(  
Adx`8}N8  
以struts为例,它在bean:define标签中定义了一个名为DefineTei的额外tag信息类,用来向脚本变量提供信息。由于脚本变量的名称(book)和类名(database.BookDetails)是通过tag标签的属性来传递的,它们一般定义在VariableInfo的构建代码中,并且可用data.getAttributeString方法来得到这些信息。如果要允许book脚本变量能在从tag开始直到整个JSP页面结束的范围内都可用的话,那它的范围应设为AT_BEGIN。如下所示: $/Ov2z  
eUBrzoCO  
~ ?^/u8  
public class DefineTei extends TagExtraInfo | C+o;  
VR0=SE  
{ 1cC1*c0Z  
c0rk<V%5+  
public VariableInfo[] getVariableInfo(TagData data) m9":{JI.w  
Im?LIgt$  
{ 'EhBRU%  
L%h/OD  
String type = data.getAttributeString(“type”); >I'% !E;  
}NCL>l;q  
If( type == null) -x*2t;%z{U  
B\CN<<N>dD  
type = “java.lang.Object”; o\=n4;S  
HdX2YPYn;  
return new VariableInfo[] { 8%:]W^  
zm#nV Y`  
new VariableInfo(data.getAttributeString(“id”), A :e;k{J  
X#p Wyo~  
type, l#qv 5f  
^@6q  
true, PK2~fJB  
QP(BZJC  
VariableInfo.AT_BEGIN) (z7+|JE.  
`/IKdO*!S  
}; q|(W-h+  
(< c7<_-H  
} = |U@  
TzG]WsY_  
} o l ({AYB  
sen=0SB/  
27Emm c  
注意:关于额外tag信息类的类名必须要在TLD中的tag标签下的tei-class子元素中定义。因此,DefineTei的tei-class中的定义看起来如下: ccJM>9  
<tei-class> [\e@_vY@OH  
org.apache.struts.taglib.bean.DefineTagTei EbQa?  
</tei-class> LIpEQ7;  
L 3XB"A#  
wdas1  
具有协作关系的tag 3HC  
1KE:[YQ1  
H)(jh  
tag通过共享对象来进行协作,JSP技术支持2种方式的对象共享。 Ey `h1 Y  
Gc,_v3\  
第一种方法是使用pageContext对象进行对象的共享(可支持JSP页面和tag处理类之间的共享),如果在一个tag处理类中要调用由另一个tag处理类创建的对象,可调用pageContext.getAttribute(name, scope)方法。 K|r Lkl9  
,H kj1x  
第二各方式的共享是对于tag之间有嵌套关系而言的,外层的tag所创建的对象对于内层的tag来说是可以共用的。这种形式的共享的好处是减少了可能存在的重名冲突。 aaW]J mRb  
nv/[I,nw  
要访问一个嵌套tag创建的对象,tag处理类必须先找到此嵌套tag对象,可用TagSupport的静态方法 TagSupport.findAncestorWithClass(from, class)或TagSupport.getParent方法。前者在当不确定此tag是否为嵌套tag对象时使用。一旦它的父类被找到,它就能访问其所有动态或静态创建的对象。静态创建的对象是父类的成员,而动态创建的对象可能是父类的私有对象。诸如此类的对象可以用tag处理类的setValue方法来保存,用getValue方法来获得。 6 ,b"  
3iNkoBCg  
下例阐述了以上两种共享对象的方法。在这个例子当中,一个查询tag检查一个名为connection的属性名是否在doStartTag中被设置。如果connection属性被设置,tag处理类从pageContext中得到这个connection对象。否则,此tag处理类先找到它的父tag处理类,然后从它的父tag处理类中找到connection对象。 $lwz-^1t.  
,_ 2x{0w:>  
N_gD>6I  
public class QueryTag extends BodyTagSupport Bi%x`4Lf  
1NLg _UBOK  
{ {S.>BXX  
V"KS[>>f  
private String connectionId; :#t*K6dz  
*%FA:Y  
public int doStartTag() throws JspException j;~%lg=)  
A*yi"{FLi  
{ ;{Ux_JEg  
QG gF|c7  
String cid = getConnection(); A;X=bj _&a  
45 >XKr.%  
if(cid != null) chI.{Rj  
 :$r ^_  
{ YA]5~ ZE\  
2f:^S/.A  
//存在一个connection id,使用它。 evuZY X@  
ef"?|sn  
connection = (Connection) pageContext.getAttribute(cid); Dt}rR[yJ  
bZwnaM4"F  
} ~l E _L1-c  
b{7E;KyY,  
else IVxWxM*N<  
V|D] M{O  
{ X@A1#z+s0]  
%eWqQ3{P]  
ConnectionTag ancestorTag = (ConnectionTag)findAncestorWithClass(this, ){;02^tX  
kL*0M<0 (  
ConnectionTag.class); qdD)e$XW,  
N@T.T=r  
if(ancestorTag == null) ed!>)Cb  
vIGw6BJI  
{ T]9\VW4  
es:2M |#O  
throw new JspTagException(“一个没有connection属性的查询标签必须被一个connection标记嵌套。”); 6QQfQ,  
tOl e>]  
} u{H?4|'(  
!  NV#U  
connection = ancestorTag.getConnection(); *?p|F&J  
z_|oCT!6  
} 5z$,6T  
kLSrj\6I[  
} ?)4?V\$  
y(jg#7)  
} ^ZRYRA  
cQN sL  
]2SI!Ai7  
/B3R1kNf|  
此查询标签在JSP页面中的调用形式可以从以下2种定义中任选一种: ^C)n$L>C0  
a}yXC<}$  
g=@_Z"  
<tt:connection id=”con01” ...> ... </tt:connection> >pL2*O^{9  
q>!L6h5]t  
<tt:query id=”balances” connection=”con01” > lEjwgk {  
/! ajsn  
SELECT account, balance FROM acct_table F'RUel_%  
=3xE:  
where customer_num = <%= request.getCustno() %> 7E$&2U^Js  
iP@6hG`:  
</tt:query> iPG0o %  
OW;tT=ql  
$^/0<i$   
或 <i\A_qqc/  
C@\{ehG  
<tt:connection ...> knp>m,w  
cR7wx 0Aj  
<x:query id=”balances”> R[tC^]ai  
l: |D,q  
SELECT account, balance FROM acct_table 1%[_`J;>Z  
X@N$Z{  
where customer_num = <%= request.getCustno() %> q<vf,D@{ !  
I&yVx8aH}  
</x:query> Wzq>JNn y  
c~}l8M %  
</tt:connection> )Q;978:  
{2d_"lHBt  
$RX'(/  
与此同时,在TLD中必须指定connection属性为可选的,定义如下: lJ;J~>  
Z4TL6 ]^R  
<tag> w42OF7f  
b,H[I!. %  
... ;zTuKex~  
Ol /\t  
<attribute> nwI3|&  
gO?44^hMe  
<name>connection</name> @LE[ac  
f7urJ'!V  
<required>false</required> K-vWa2  
H;ZHqcUX  
</attribute> 7u.|XmUz  
R{Z-m2La  
</tag>
描述
快速回复

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