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

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

级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
标准的JSP 标记可以调用JavaBeans组件或者执行客户的请求,这大大降低了JSP开发的复杂度和维护量。JSP技术也允许你自定义taglib,其实换句话说,taglib可以看成是对JSP标记的一种扩展,正如xml是对html的一种扩展一样。taglib通常定义在tag标签库中,这种标签库存放着你自己定义的tag标签。简而言之,如果使用taglib,那么你可以设计自己的JSP标记! jpoNTl'  
dxtG3  
一般来说,自定义tag标签主要用于操作隐藏对象、处理html提交表单、访问数据库或其它企业级的服务,诸如邮件和目录操作等等。自定义tag标签的使用者一般都是那些对java编程语言非常精通,而且对数据访问和企业级服务访问都非常熟悉的程序员,对于HTML设计者来说,使得他可以不去关注那些较复杂的商业逻辑,而将精力放在网页设计上。同时,它也将库开发者和库使用者进行合理分工,自定义tag标签将那些重复工作进行封装,从而大大提高了生产力,而且可以使得tag库可用于不同的项目中,完美地体现了软件复用的思想。 f|)~_J H  
vg _PMy\  
在这篇文章中,我们主要讨论:  x\VP X  
8s-X H  
· 什么是自定义tag标签? `0!%jz=  
@U1t~f^  
· 怎么使用tag标签? P97i<pB Y_  
gkKNOus  
o 声明要使用的tag库 BW`;QF<  
`VDvxl@1  
o 找到与之对应的tag处理类 B7.&yXWgn  
+Z"[2Dm  
o tag标签的类型 `~41>mM%  
&!M6{O=~  
· 自定义tag标签  a3a:H  
q(1hY"S"}b  
o tag处理类 ~C3Ada@4  
Y4X`(\A  
o tag库描述 @e$EwCV,  
fE3%$M[V7  
o tag标签示例 }1lZW"{e[  
)V*`(dn'zm  
o 带属性的tag ?U1Nm~'UZ  
:hR^?{9Z4>  
o 带body的tag NX:\iJD)1U  
xj3{Ke`6  
o 定义了脚本变量的tag FT J{  
p1mAoVxR  
o 具有协作关系的tag && PZ;  
7  `c!  
· 自定义tag标签 YNKvR  
y|3("&)"S  
o 一个迭代tag的例子 'Z#>K*  
zG^$-L.n  
o 一个模板tag库 tT]mMlKJ  
e#F3KLSL`  
o tag处理类到底是怎样被调用的? 6BEDk!  
c>+68<H  
,pQ[e$u1  
什么是自定义的tag? 7m?fv Ky  
NGO?K?  
一个自定义的tag标签是用户定义的一种JSP标记。当一个含有自定义的tag标签的JSP页面被jsp引擎编译成servlet时,tag标签被转化成了对一个称为tag处理类的对象进行的操作。于是当JSP页面被jsp引擎转化为servlet后,实际上tag标签被转化成为了对tag处理类的操作。 8qxZ7|Y@  
|Z+qaq{X  
自定义tag标签有很多特色,诸如: %P(2uesd  
Py/~Q-8p  
· 可以在JSP页面中自定义tag标签的属性 S1C#5=  
"I{Lcn~!@  
· 访问JSP页面中的所有对象 ltNY8xrdGN  
6KD-nr{S  
· 可以动态地修改页面输出 z92Xc  
!:tr\L {  
· 彼此这间可以相互通信。你可以先创建一个JavaBeans组件,然后在一个tag中调用此JavaBeans组件,同时可以在另一个tag中调用它。 I#7H)^us  
<JvYCWX`  
· tag允许相互嵌套,可以在一个JSP页面中完成一些复杂的交互。 cjd-B:l  
S?VKzVDB.S  
7-\wr^ll3  
使用tag标签 y>d`cRy  
U!JmSP  
Xf mN/j2  
本节主要描述怎样在JSP页面中使用tag标签,以及tag标签的不同类型。 Wvl'O'R  
=@X?$>'  
要使用tag标签,JSP程序员必须做2件事: &h=f  
fGe"1MfU  
· 声明此tag标签的tag库 W2M[w_~QE  
MfKru,LSh  
· 实现此tag标签 P:1eWP  
6KPjZC<  
声明tag标签所在的tag库 TB84}  
QA)W(1  
如果要使用tag标签,则应用JSP的taglib指示符来指定其tag库(注意:taglib要在在使用此tag标签之前声明) |8GLS4.]t  
!0):g/2h  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> &+ H\ST(/  
I'N!j>5oX  
uri属性定义了唯一的标签库描述(以下简称TLD),它可以是直接是tld文件名或一个独一无二的名字。prefix是用来区别其它TLD中和本TLD中有重名的tag的一种手段。 "1%k"+&  
<DII%7q,6/  
TLD必须以.tld作为扩展名,并且存放在当前应用的WEB-INF目录或其子目录下。你可以通过它的文件名直接引用它,也可以通过别的方式间接地引用它。 PGVP0H+RV  
Vf=,@7  
以下taglib指示符直接引用一个TLD: l\d[S]  
QXEZ?gx  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> 6wXy;!2  
X?/32~\  
以下的taglib指示符通过一个逻辑名称间接地引用一个TLD: _.%g'=14f  
n3 Rf:j^R  
<%@ taglib uri=”/tutorial-template” prefix=”tt” %> lh!8u<yv*  
[TxvZq*4  
如果是间接引用TLD的话,那你必须还要在web.xml中定义此逻辑名称与tld文件之间的映射,具体做法是在web.xml中加入一个名为taglib的元素: .SSPJY(  
4! F$nmG)  
<taglib> V!e*J,g  
#$!^1yO  
<taglib-uri>/tutorial-template</taglib-uri> 54RexB o  
u^x<xw6f  
<taglib-location> Qp2~ `hD  
x@pzgqi3  
/WEB-INF/tutorial-template.tld =CCddLO  
mJH4M9WJ]  
</taglib-location> 'RNj5r  
&lxMVynL  
</taglib> LJt5?zQKrW  
Lw?>1rTT/  
o_ [I#PT  
实现此tag标签 yBv4 xKMH  
5Z#(C#  
TY` R_  
为了实现tag标签,你有2种方法来存放tag处理类。一、让tag处理类以.class的方式存放于当前应用的WEB-INF/class子目录下,二、如果tag处理类是以JAR包的形式存在的话,那可以放在当前应用的WEB-INF/lib目录下,如果tag处理类要在多个应用中共享,那么它就应放在jsp服务器上的common/lib目录下,对于tomcat来说,就是tomcat/common/lib目录下。 ?,[$8V  
g  b[.Ww  
2(Yt`3Go(  
tag标签类型 !MmbwB'  
n:H |=SF{  
%z"$?Iv  
自定义的tag标签遵循XML语法。它有一个开始标记和一个结束标记,有的还有body(即文本节点): *)HVK&'  
F`+S(APT8  
<tt:tag> oDG BC  
F:.8O ,%u  
body !9j6l 0  
l SuNZY aO  
</tt:tag> DLe>EU;vS  
]xIgP%  
>km$zfM2-  
一个不带body的tag标签如下: pNu?DF{ 3  
m+ #G*  
<tt:tag /> aFh'KPhe  
%0f*OC  
uF)^mT0D=  
简单的tag标签 ``kesz  
cwQ *P$n  
一个没有body和属性的tag标签如下: E|6@h8 #  
@9k/od@mW  
<tt:simple /> \Z~ <jv  
l9H-N*Wx  
vJ&35nF&  
带属性的tag标签 hIa,PZ/Q  
hWbjA[a/  
avXBCvP+h  
自定义标签可以有自己的属性。属性一般在开始标记中定义,语法为 attr=”value”。属性的作用相当于自定义标签的一个参数,它影响着tag处理类的行为。你可以在TLD中详细定义它。 I6S>*V  
VHL[Y  
你可以用一个String常量给一个属性赋值,也可以通过表达式给它赋值,如<%= ...%>。以struts为例,它的logic:present标签就是用的String常量来给属性赋值: ";n%^I}  
l[nf"'  
<loglic:present parameter = “Clear”> 5\ }QOL  
7CX5pRNL  
而另一个标签logic:iterate是用表达式来给属性赋值: a@?ebCE  
ma`sv<f4-!  
<logci:iterate collection=”<%= bookDB.getBooks() %>” 7a.iT-*  
Vu<mOuh  
id=”book” type=”database.BookDetails”> OSC_-[b-  
ye| 2gH  
=Prz|   
带body的tag标签 E6-~  
&G3$q,`H  
一个自定义标签可以包含其它自定义标签、脚本变量、HTML标记或其它内容。 GB6(WAmr  
+>% AG&Pc  
在下述例子中,此JSP页面使用了struts的logic:present标签,如果些标签定义了parameter=”Clear”的属性,则将清除购物车的内容,然后打印出一条信息: 'sk M$jr  
;b_<5S  
<logic:present parameter=”Clear”> Z_T~2t  
^vOEG;TR<-  
<% cart.clear(); %> 5?E;Yy A  
J%E0Wd  
<font color=”#ff0000” size=”+2”><strong> clIn}wQ  
X{h[    
你选择了清除购物车! 2D3mTpw  
Ka"1gbJ|  
</strong></font> oV~S4|9:  
z qd1G(tO  
</logic:present> | Y(  
,%y!F3m  
iX>)6)uJ  
到底是用属性还是用body来传递信息? |%(qaPA1  
=Q!V6+}nY^  
如上所述,我们既可以通过属性,也可以通过body来传递信息。但一般来说,比较简单的类型,如字符串或简单表达式最好采用属性来传递信息。 Jp~[Dm  
DuC_uNJ  
~UsE"5  
定义脚本变量的tag标签 gLbTZM4i  
)_Iu7b  
所谓脚本变量,是指JSP中可以调用的变量或对象。它可由tag标签产生。以下示例阐述了一个tag标签定义了一个名为tx的由JNDI所定义的事务处理对象。脚本变量可以是ejb对象、事务、数据库连接等等: ; y>}LGG  
$^#q0Yx  
<tt:lookup id=”tx” type=”UserTransaction” name=”java:comp/UserTransaction” /> ,awkL :  
L1q]  
<% tx.begin(); %> Q:Y`^jP   
"m}N hoD4  
... m`@~ZIa?>B  
2W63/kRbU  
Ye[Fu/0  
具有协作关系的tag标签 SQJ4}w>i  
#}UI  
自定义tag标签之间可以通过共享对象来实现协作。在下述例子中,标签tag1创建了一个名为obj1的对象,在标签tag2仍可以重复使用obj。 R ggZ'.\  
~jC$C2A0  
<tt:tag1 attr1=”obj1” value1=”value” /> &Hl w2^  
ZP.~Y;Ch;-  
<tt:tag2 attr1=”obj1” /> mDA1$fj"  
}O6E5YCm  
在以下这个例子当中,如果外层的tag标签创建了一个对象,那么其内层的所有tag标签都可以使用这个对象。由于这样产生的对象没有一个指定的名字,那么就可以将少重名的冲突。这个例子阐述了一系列协作的嵌套对象。 9;A9Q9Yr  
!1bATO:x  
<tt:outerTag> TZObjSm_v  
lhF)$M  
<tt:innerTag /> !@ )JqF.  
1Msc:7:L  
</tt:outerTag> 3 gW+|3E  
2(Nf$?U @0  
;^8X(R  
Tag处理类 ,B,0o*qc{K  
BR~+CBH  
 t&G #%  
Tag处理类必须实现Tag接口或BodyTag接口,不过现在一般都流行从TagSupport或BodyTagSupport类中继承,这些类或接口都可以在javax.servlet.jsp.tagext包中找到。 1kh()IrA  
^ pocbmg  
当JSP引擎看到自己的JSP页面中包含有tag标签时,它会调用doStartTag方法来处理tag标签的开头,调用doEndTag方法来处理tag标签的结束。 OX.g~M ig|  
qwd T= H  
下表说明不同类型的tag所需要不同的处理过程: Z%VgAV>>  
{XLRrU!*  
Tag处理类的方法 : )k|Onz  
rX|{nb  
Tag标签类型 Ys@\~?ym+  
所调用的方法 e~$aJO@B.R  
B)&z% +  
基本标签 Dwah_ p8  
doStartTag, doEndTag, release 4/&.N]  
er>@- F7w  
带属性的标签 x\5\KGw16  
doStartTag, doEndTag, set/getAttribute1...N, release QV=|' S  
TnPx.mwK\  
带内容的标签 4'L.I%#tZ  
doStartTag, doEndTag, release F\+!\b*lP  
ov'C0e+o  
带内容的标签,且内容重复循环 a &hj|  
doStartTag, doAfterBody, doEndTag, release stOD5yi  
:j;_Xw  
带内容的标签,且内容与JSP交互 )oMMDH w\  
doStartTag, doEndTag, release, doInitBody, doAfterBody, release ODPWFdRar  
G5$YXNV  
一个tag处理类可以通过javax.servlet.jsp.PageContext来与JSP交互,通过javax.servlet.jsp.PageContext类,tag处理类可以访问JSP中的request、session和application对像。 ezr'"1Ba}  
>NBwtF>  
如果tag标签是互相嵌套的,那内层的tag处理类可以通过它的parent属性来访问上层的tag处理类。 >uYGY{+j[  
F2$?[1^f  
一般情况都将所有的tag处理类打成了JAR的包,以便于发布。 y~rtYI  
G2FD'Sf  
PE2O$:b\  
Tag库描述(简称TLD) Kd3EZo.  
HhB' ^)  
w?M` gl8r  
Tag库是用xml语言描述的,TLD包括了tag库中所有tag标签的描述,它一般用来被jsp服务器用来校验tag的语法正确性,或者被jsp开发者用来开发新的标签。 h.aXW]]}(P  
r59BBW)M  
TLD的文件扩展名必须为.tld,而且必须放在当前WEB应用的WEB-INF目录或其子目录中。 g|x* sZR~Y  
#lx(F3  
一个TLD的内容的开头必须遵守标准的XML开头,用于描述DTD和xml的版本,例如: oMF[<Xf  
1K{hj%  
<?xml version="1.0" encoding="ISO-8859-1" ?> h%U,g 9_  
 5f_1 dn  
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd"> ]"U/3dL5  
TLD必须以<taglib>来作为它的根元素,<taglib>的子元素如下表: -VZ? c  
8?$XT  
Opf^#6'mq  
<taglib>的子元素 /m+.5Qz9)@  
dqw0ns.2  
Element mUwGr_)wj  
Description {o8K&XU#&t  
!]!J"!xg*  
tlib-version Qy| 6A@  
Tag库的版本 bN.U2%~!  
O BZ:C!  
jsp-version SHe547X1  
Tag库所需要的jsp的版本 Q%_MO`<]$  
~> 5  
short-name AF"XsEt.e  
助记符,tag的一个别名(可选) Rnk&:c  
M[Mx g  
uri WizVw&Iv  
用于确定一个唯一的tag库 v'u}%FC  
w(R+p/RF  
display-name ag"Nf-o/Y  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) S(hT3MAW  
O|0}m  
small-icon Xa&0j&AH  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) C )+%9Edg  
vN`JP`IBx  
large-icon ddvtBAX  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) rJc=&'{&)N  
Yj>ezFo  
description 8\e8$y3  
对tag库的描述(可选) E3h-?ugO'  
3 bl l9Ey  
listener *vIC9./  
参见下面listener元素 z]=jer  
=}YaV@g<f  
tag uE,j$d  
参见下面tag 元素 "o$)z'q  
k3r<']S^  
Listener元素 Eilo;-El  
qJEtB;J'  
一个tag库可能定义一些类做为它的事件侦听类,这些类在TLD中被称为listener 元素,jsp服务器将会实例化这些侦听类,并且注册它们。Listener元素中有一个叫listener-class的子元素,这个元素的值必须是该侦听类的完整类名。 ~DUOL ~E  
~X1<x4P\  
Tag元素 ^97\TmzP{  
l=^^l`  
每个tag元素在tag库中都要指出它的名字、类名、脚本变量、tag的属性。其中脚本变量的值可以直接在TLD中定义或通过tag附加信息的类来取得。每个属性描述了这个属性是否可以省略,它的值是否可以通过<%= …%>这样的JSP语法来获得,以及属性的类型。 U7d05y'  
2B=+p83<  
每一个tag在TLD中对应一个tag元素,下表是tag元素的子元素: ,:?=j80m  
jI,?*n<  
Tag元素的子元素 <+e&E9;>6  
q|N4d9/b  
元素名称 ,PZ[CX;H@  
描述 @d6N[?3;  
, @dhJ8/  
name }y#aO  
独一无二的元素名 j+NpQ}t:  
!9.`zW"40  
tag-class 0*8uo W t&  
Tag标签对应的tag处理类 3Vb/Mn!k  
bn0Rv  
tei-class aq%i:};  
javax.servlet.jsp.tagext.TagExtraInfo的子类,用于表达脚本变量(可选) (t2vt[A6ph  
)TyI~5>;  
body-content |FJc'&)J"  
Tag标签body的类型 BYWs\6vK  
YfU6 mQ  
display-name 'n!kqP  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) F48W8'un  
PZO8< d  
small-icon a #Pr)H  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) gl!F)RdH  
|NXe{q7{  
large-icon a3[lZPQe  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) $h8,QPy  
8WMGuv  
description ue"e><c6:  
此tag标签的描述 vB1nj<]&z  
xY1@Ja  
variable _gI1@uQw  
提供脚本变量的信息(同tei-class)(可选) ed4`n!3  
%2EHYBQjN  
attribute %3 VToj@`>  
Tag标签的属性名 1agI/R  
UaV8 !Z>  
以下章节介绍对于不同类型的tag,如何具体地实现它们。 ETtoY<`#  
&Vmx<w  
2N}h<Yd 9  
简单的tag Ls(l  
udGZ%Mr_  
qq[Enf|/y  
tag处理类 vy1N, 8a  
R#Hz%/:|A  
简单的tag处理类必须实现Tag接口的doStartTag和doEndTag方法。当jsp引擎碰到tag标签的开头时,doStartTag被调用,因为简单的tag没有body,所以此方法将返回 SKIP_BODY。当jsp引擎碰到tag标签的结尾时,doEndTag被调用,如果余下的页面还要被计算,那它将返回EVAL_PAGE,否则将会返回SKIP_PAGE。 TWT h!  
P_%kYcX'  
以下是例子:对于标签 <tt:simple /> ,它的tag处理类实现如下: rZ^VKO`~I1  
,U#FtOec  
Q DJe:\n  
public SimpleTag extends TagSupport .[>UkM0  
>'2=3L^Q  
{ 7DCu#Y[  
@8'LI8 \/  
public int doStartTag() throws JspException iVqXf;eB!5  
4dI =  
{ ]ppws3*Pa  
()%;s2>F  
try{ &(,-:"{pNR  
E8PlGQ~z{d  
pageContext.getOut().print(“Hello.”); xzOM\Nq?O  
`Fs-z  
}catch(Exception e){ c-bTf$6}  
R:t  
throw new JspTagException(“SimpleTag: “ + e.getMessage()); DzE_p- zs  
wBIhpiJX0  
} -%6Y&_5VK  
E_j=v \  
return SKIP_BODY; D|E,9|=v  
Lt\=E8&rh  
} OZi4S3k  
K:8. Dvn  
public int doEndTag() uEcK0>xp  
"|W``&pM  
{ `Uy'YfYF  
OIdoe0JR:O  
return EVAL_PAGE; H|/U0;s  
_/)HAw?k  
}  _V_GdQ  
F@u>5e^6  
} hxx`f-#=  
oiNt'HQ2/  
dEG1[QG  
注意:如果tag标签没有内容的话,那必须定义body-content元素为空,例如 TC^fyxq  
T +~ _D  
<body-content>empty</body-content> A N 'L- E  
YKG}4{T  
[pYjH+<  
带属性的tag标签
评价一下你浏览此帖子的感受

精彩

感动

搞笑

开心

愤怒

无聊

灌水
级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
只看该作者 1 发表于: 2007-01-01
tag处理类 9>hK4&m^  
2r>I,TNHl  
对于tag标签的每个属性,你必须依照JavaBeans规范来定义其属性,以及get和set方法。以struts的logic:present 标签为例, )w'GnUqWz  
M5<c HE  
<logic:present parameter=”Clear”> .[8g6:>  
~sbn"OS +  
与此相应,此tag处理类应有如下方法和定义: nh? ~S`  
fMZzR|_18  
Q _ M:v  
protected String parameter = null; l~*D jr~  
]Wdnr1d~8  
public String getParameter() <^Sp4J  
wzz> N@|  
{ ]aTF0 R  
 _)=eE  
return this.parameter; ,ou&WI yC  
w-?|6I}T  
}  ua] ?D2  
ry!0~ir  
public void setParameter(String parameter) zaMKwv}BR  
J1gLT $  
{ YH/3N(],  
y(h"0A1lW  
this.parameter = parameter; R"V^%z;8o  
APM!xX=N  
} )2mvW1M=7;  
xI(Y}>  
Yo;Mexo!  
注意:如果你的属性名为id,而且你的tag处理类是从TagSupport类继承的,那你就不需要定义它的属性和set和get方法,因为他们早已在TagSupport被定义过了。 l~c# X3E  
U t'r^  
Attribute元素 N@G~+GCxL  
wwVg'V;  
对于tag标签的每个属性,你必须定义它是否必须的,它的值是否可以用诸如<%= …%>的表达式来获得,以及它的类型(可选),如果不指定它的类型,那就默认为是java.lang.String类型。如果rtexprvalue元素被定义为true或yes,那么在type元素中就定义了attribute的返回类型。 >[a&,gS  
fe$OPl~  
<attribute> Ch,%xs.)G  
D ~LU3#n  
<name>attr1</name> KG9FR*"  
DfV'1s4y  
<required>true|false|yes|no</required> bFtzwa5Gc  
Ab/KVB  
<rtexprvalue>true|false|yes|no</rtexprvalue> vD'YLn%Q  
qF57T>v|  
<type>attribute的返回类型(只用当rtexprvalue为真是才有效)</type> )9'Zb`n  
PWbi`qF)r  
</attribute> N,~"8YSo  
%"g; K  
如果tag的某个属性不是必须的,那tag处理类会自动提供一个缺省值。 3?:?dy(3z  
z((9vi W  
例如,在logic:present这个tag标签中定义了一个属性叫parameter,但它不是必须的,而且它可以被诸如<%= …%>的表达式来赋值。 )h,-zAnZ  
j^qI~|#  
<tag> 3}25=%;[  
n+%tu"e  
<name>present</name> cL yed3uU  
fZF.eRP '  
<tag-class>org.apache.struts.taglib.logic.PresentTag</tag-class> `(Ij@8 4  
7zEpuw  
<body-content>JSP</body-content> Zq\Vq:MX  
Q3|I.I e  
… lJ/{.uK  
h(MS>=  
<attribute> MR-cOPn  
=VOl  *  
<name>parameter</name> c?XqSK`',Z  
0|D l/1  
<required>false</required> PuoN<9 #  
ZKco  
<rtexprvalue>true</rtexprvalue> _ pKWDMB$z  
m. DC  
</attribute> JDj^7\`  
$3D#U^7i  
… Bn?MlG;aA  
AB")aX2% E  
</tag> (3fU2{sm  
V^5Z9!  
w;(B4^?  
属性元素的校验 kV:C=MLI  
f+W8Gszi  
ruTj#tWSo  
有关于tag标签的有效值可以从tag库的说明文档中获得,当JSP页面被编译时,jsp引擎会强制性地参照TLD中定义的规则进行检查。 C8bv%9  
W9%B9~\G;+  
还有一个方法也可以进行属性元素的校验,就是先继承类TagExtraInfo,然后调用它的isValid方法。这个类同时也起到提供tag中定义的脚本变量信息的作用。 '1te(+;e@  
$mZpX:7/u8  
IsValid方法通过TagData对象来传递属性信息,它包括着tag的所有的属性名-值的信息。由于校验发生在运行时刻,因此这个属性的值将被赋值为TagData.REQUEST_TIME_VALUE。 CY i{WV(:  
bf&k:.v'8  
例如tag标签<tt:twa attr1=”value1” />在TLD中定义如下: c`x[C  
/!HFi>   
<attribute> 4,P!D3SH  
qk=0ovUzg  
<name>attr1</name> ^":Dk5gl  
;OD+6@Sr  
<required>true</required> M +Jcg b]  
9 &p;2/H  
<rtexprvalue>true</rtexprvalue> *&sXC@^@^  
Oxq} dX7S  
</attribute> *Qe{CE  
[[8.Xb  
sksop4gu5  
这个定义说明了attr1能在运行期间被赋值。 k<cv80lhK  
aB+B1YdY"  
以下的isValid方法检查attr1属性的值是否属于Boolean类型。注意由于attr1能在运行刻被赋值,那么isValid方法必须检查tag用户是否对此tag进行了运行时刻赋值。 Z4aK   
;?'=*+'>  
oYNp0Hc  
Public class TwaTEI extends TagExtraInfo $dgez#TPL  
.?CumaU  
{ ps=+wg?]  
6h_OxO&!U  
public boolean isValid(Tagdata data) H G)c\b  
$,L,VYN  
{ JU\wvP5j  
jXALN  
Object o = data.getAttribute(“attr1”); dgsD~.((A  
X*Dt<i};v  
If(o != null && o != TagData.REQUEST_TIME_VALUE) J~URv)g  
KQ\d$fX  
{ TDnbX_xC<  
P2^((c  
if( ( (String)o).toLowerCase().equals(“true”) || .ugQH<B  
~PAbtY9}U  
((String)o).toLowerCase().equals(“false”) ) <{yQNXf[  
4hh=z>$|l)  
return true; O)i]K`jk  
</B5^}  
else Jb4A!g5C  
UZq1qn@+  
return false; jQ[M4)>_k`  
+HxL>\  
} OlI{VszR  
eg vgi?y  
else Ul?92  
%B{NH~  
return true; &?@5G  
wBK%=7  
} uRu)iBd D  
M$Of.  
} o I6o$C  
gQ=g,X4  
QC\][I>  
带body的tag zkrcsc\Z~0  
E?+MM0  
Q]]5\C.  
tag处理类 I N'a5&..  
J}vxK H#=  
xjDV1Xf*  
如果tag标签含有内容,那处理方式会略微有些不同,而且还要视tag处理类是否要与body交互的情况而定。如果要与body交互,那我们认为tag处理类要可能要对body进行操作。 r+WY7'c  
1~# 2AdG  
Tag处理类不与body交互 CN"hx-f  
]{<`W5 b/  
如果tag处理类不与body交互,tag处理类应该实现Tag接口或从TagSupport中派生,如果body要被计算,那么doStartTag方法应返回 EVAL_BODY_INCLUDE,否则应返回SKIP_BODY。 Xu8_<%  
h&4f9HhS=  
如果tag处理类要对body反复运算,则它应该实现IterationTag或从TagSupport中派生。如果tag处理类认为body还未计算完的话,那它的doStartTag方法和doAfterBody方法必须返回EVAL_BODY_AGAIN。 -n`igC  
fQB>0RR2  
Tag处理类与body交互 g@jAIy]  
L9=D,C~  
如果tag处理类与body交互,那tag处理类应实现BodyTag接口或从BodyTagSupport中派生。这种tag处理类一般要实现doInitBody和doAfterBody方法。 /\_wDi+#  
*NDM{WB|)  
Body允许一些方法来读写它的内容。Tag处理类可以调用body内容的getString或getReader方法来从body中提取信息,也可用 writeOut(out) 方法来将body的内容写入到out对象中。其中out对象通过tag处理类的getPreviousOut方法来获得。 $MT'ZM  
Ka"Z,\T   
如果body的内容需要被计算,那么doStartTag方法必须返回EVAL_BODY_BUFFERED,否则,它将返回 SKIP_BODY。 o?$B<Cb"  
&4ScwK:  
doInitBody 方法 = NHzh!  
=(~UK9`  
此方法在body内容已经设好,但未被计算之前被调用。你可以根据不同的body内容来制定初始化策略。 h^D]@H  
- ^sbf.  
doAfterBody方法 9(/ ;Wutj"  
M9/c8zZ  
此方法在body内容已被计算后进行调用。 YIQm;E EG  
8,,$C7"EP  
和doStartTag方法一样,doAfterBody方法返回一个指示符指示是否要继续计算body,如果要继续计算,则doAfterBody应返回EVAL_BODY_BUFFERED,否则,它应返回SKIP_BODY。 9O+><x[i  
7.o:(P1??g  
release 方法 R]7-6  
z$>_c "D  
tag处理类调用此方法将它的状态重置为初始状态,并释放所有的私有资源。 fb8t9sAI  
(IXe5 55  
Q/,bEDc&  
以下的例子读取body的内容(其中含有一条sql语句),然后将它传递给一个对象,让它进行查询。由于此处body不须重新计算,所以doAfterBody会返回SKIP_BODY。 =k1 ,jn+  
d,G:+  
@L-3&~=  
Public class QueryTag extends BodyTagSupport ZO2$Aan  
`KgWaf-  
{ Y70[Nz  
%\ i 7  
public int doAfterBody() throws JspTagException \p-3P)U  
|@x^5Ab$T  
{ $`Z-,AJc  
hwaU;>F  
BodyContent bc = getBodyContent(); YFVNkB O%  
^0/FZ)V8  
//将body的内容以字符串的格式提取出来 +%'S>g0W=  
cVt MCgx  
String query = bc.getString(); GN4'LU  
3f2%+2Zjt,  
//清除body A?V[/  
ER O'{nT&  
bc.clearBody(); _JZw d9K  
Gyak?.@R  
try{ :K ^T@F5n  
=7JvS~s  
Statement stmt = connection.createStatement(); s0 ZF+6f  
!TH3oLd"  
Result result = stmt.executeQuery(query); *Op;].>E  
fAu^eS%>7  
}catch(SQLException e){ ^ 2"r't  
nVF?.c  
throw new JspTagException(“queryTag: “ + e.getMessage() ); <6]TazW?S  
^T[8j/9o^  
return SKIP_BODY; eC^UL5>%  
:Rh?#yO 5  
} p`jkyi  
SO #NWa<0|  
} i+$G=Z#3E  
BitP?6KX  
B&~#.<23:  
body-content元素 <n4T*  
v2e*mNK5  
S <C'#vj  
由于tag可能会有body,你必须用body-content元素来指定body内容的类型: p&SxR}h  
[*<F   
<body-content>JSP|tagdependent</body-content> d%:B,bck  
,9I %t%sb  
uXX3IE[  
如果body的内容是定制的或内部的tag、脚本元素、或HTML广本,则归类为JSP类型。其他的类型,比如上面代码所述的?D?D将sql statement类传给 query tag的这种类型应该标为tagdependent。 o5 UM)g  
+>#SB"'  
注意:实际上body-content的值并不影响tag处理类对body内容的处理,它仅仅是被tag编辑工具用来描述此body的内容。 v=A ]#O%  
'~HCYE:5  
Z*EK56.b  
用tags定义脚本变量 VQ5D?^'0/  
>+iJ(jqq  
*;Q IAd  
tag处理类 b ^wL{q  
PuvC MD  
Y40`~  
tag处理类负责创建或设置页面中定义的脚本变量,用pageContext.setAttribute(name,value,scope)或pageContext.setAttribute(name,value)方法来实现。一般来说,tag处理类通过脚本变量的名称来获取它,脚本变量的名称一般可用get方法来获得。 &@tD/Jw3  
}Ut*Y*  
如果脚本变量的值依赖于tag处理类中的上下文中某一对象,那它可用pageContext.getAttribute(name,scope)方法来找到那个对象。一般的处理过程是tag处理类先找到脚本变量,再对其进行处理,然后用pageContext.setAttribute(name,object)的方法来设置它的新值。 9qUc{ydt  
|H`}w2U[j  
对象的生存周期(scope)如下表: "|?zQ?E  
@6eM{3E.  
对象的生存周期表 nRYHp7`  
v71j1Q}6  
名字 "P) f,n  
可访问范围 &vf9Gp+MK  
生存周期 {9kH<,PJ;!  
S]E1+,-*  
page A>@ i TI  
当前页面 -nVQB146^  
一直有效,除非页面向客户提交响应或重定向到一个新页面 6w3z&5DY|  
k8 !|WqfP  
request P.L$qe>O  
当前页面或当前页面重定向到的页面 qPEtMvL #  
一直有效,除非页面向客户提交响应 E+LAE/v@  
\qx$h!<  
session ;D}8acQ  
当前页面或在同一浏览器窗口中的页面 S VCTiG8t  
一直有效,除非关闭当前浏览器、超时、网络故障 lSGtbSyDI  
toD v~v  
application 3uSj5+@q6  
整个web应用程序的所有请求 td*1  
一直有效,除非发生网络故障、服务器故障 i3bH^WwE&k  
?b?6/_W~R  
提供关于脚本变量的信息 ({XB,Rm  
K4 \{G  
以下示例定义了一个名为“book”的脚本变量,用来访问程序中关于书的信息: \ 5MD1r}  
4+rr3 $AY  
<bean:define id=”book” name=”bookDB” property=”bookDetails” type=”database.BookDetails” /> BE`{? -G  
z_Em%X  
<font color=”red” size=”+2” > LA!2!60R  
vL>cYbJ<  
<%= messages.getString(“CartRemoved”) %> _[D6 WY+  
*C/bf)w  
<strong><jsp:getProperty name=”book” property=”title” /></strong> ,t"?~Hl".  
=<,>dBs}\  
</font> ^HJvT)e4  
<>=A6  
当包含此tag的JSP页面被编译时,jsp引擎会自动生成关于此book的同步的代码(同步可以避免几个客户同时访问此book时造成的冲突),要生成同步代码,jsp引擎需要知道此脚本变量的如下信息: }e/#dMEi  
v5 |XyN"  
· 脚本变量名称  F#0y0|  
m2%OX"#e  
· 脚本变量所属的类 B|\pzWD%  
1r!o,0!d-'  
· 此脚本变量是否引用了一个新的或已存在的对象 $1aJdZC7  
 4RPc&%  
· 此脚本变量的有效性 o!nw/7|  
YJBlF2uD  
有两种办法可以向jsp引擎提供关于脚本变量的信息:在TLD中定义variable子元素,或用tei-class子元素定义一个额外tag信息类。用variable最简单,但可能降低了一些灵活性。 s|p,UK  
vpt*?eR  
Variable元素 Z7\}x"hk  
YkOl@l$D  
Variable元素有如下子元素: ]H ze  
Sz!mn  
· name-given ?D?D 给出的名字,是一个常量 S&yKi  
.b.p yVk  
· name-from-attribute?D?D 属性名,在编译时给出的属性名 `^:>sU  
r#8t @W  
name-given或name-from-attribute两者必须选一,但以下子元素是可选的: 1 u[a713O  
1L~y!il  
· variable-class?D?D变量的类型,缺省为java.lang.String。 U*P&O+(1'  
pr\wI?:k  
· declare?D?D此脚本变量是否引用了一个新对象,缺省为True。 Lek!5Ug  
7D5[ L  
· scope?D?D脚本变量的范围,缺省为NESTED。下表描述了scope的几种类型: 2O|jVGap5x  
f*Z8C9)  
脚本变量的有效范围 OTgctw1s  
i5PZ)&  
值 Ijg //=  
有效性 *Sd}cDCO%  
方法 3 pzp6o2  
}MUQO<=*  
NESTED 8iv0&91Z  
在tag标签的开始和结束之间 &c?q#-^)\+  
如果tag处理类实现BodyTag接口,则在doInitBody和doAfterBody中调用,否则在doStartTag中调用 a ~  
!?AgAsSmc  
AT_BEGIN U?@ s`.  
从tag标签的开始一直到页面结束 Ff eX;pi  
如果tag处理类实现BodyTag接口,则在doInitBody、doAfterBody和doEndTag中调用,否则在doStartTag和doEndTag中调用 D8OW|wVE  
71S~*"O0f  
AT_END <0EVq8h  
从tag标签的结束一直到页面结束 *5e"suS2  
在doEndTag中调用 ~__r- z  
cDkq@H:   
以struts为例,它的bean:define标签的实现遵循JSP1.1规范,此规范要求使用额外tag信息类来定义脚本变量。Variable元素是JSP1.2规范中加入的。以bean:define标签为例,你可以定义如下variable元素: A7`+XqG  
2F}D?] A  
<tag> vkR,Sn  
M%yeI{m  
<variable> ?* {Vn5aX{  
x=S8UKUx  
<name-from-attribute>id</name-from-attribute> 0A,u!"4[  
+69[06F  
<variable-class>database.BookDetails</variable-class> `G@(Z:]f,t  
QPD[uJ(I  
<declare>true</declare> `6No6.\J  
8QJ^@|7  
<scope>AT_BEGIN</scope> "c9T4=]&t  
=c-Y >  
</variable> /v<FH}  
0uZL*4A+C  
</tag> 8I>'x f  
??]b,f4CNa  
额外tag信息类 n_ 3g  
=<BPoGs5  
如果要定义一个额外tag信息类,你要继承javax.servlet.jsp.TagExtraInfo类。一个TagExtraInfo类必须实现getVariableInfo方法,此方法返回一个叫VariableInfo的数组类,它包括如下信息: S9 p*rk ~  
' ?4 \  
· 变量名 $D][_I  
w\K(kNd(  
· 变量所属类名 Wr j<}L|  
5bj9S  
· 此变量是否引用了一个新对象  Zra P\?  
pu"m(9  
· 此变量的有效范围 U } K]W>Z  
M?gc&2 Y  
jsp引擎将一个名为data的参数传给getVariableInfo方法,data中包括tag标签中的所有“属性名?D?D属性值”对。它可以用来向VariableInfo对象提供脚本变量的名字和类名。 G7qB   
pdw;SIoC  
以struts为例,它在bean:define标签中定义了一个名为DefineTei的额外tag信息类,用来向脚本变量提供信息。由于脚本变量的名称(book)和类名(database.BookDetails)是通过tag标签的属性来传递的,它们一般定义在VariableInfo的构建代码中,并且可用data.getAttributeString方法来得到这些信息。如果要允许book脚本变量能在从tag开始直到整个JSP页面结束的范围内都可用的话,那它的范围应设为AT_BEGIN。如下所示: 1B0+dxN`  
Jan~R ran  
GG=R!+p2  
public class DefineTei extends TagExtraInfo 4[XiD*  *  
Fkvf[!Ci  
{ =Hd+KvA  
K,f"Q<sU%  
public VariableInfo[] getVariableInfo(TagData data) mNQ~9OJ1  
nb30<h  
{ 0en Bq>vr  
_xmS$z)TO  
String type = data.getAttributeString(“type”); i-YSt5iq  
:Z R5<Y>  
If( type == null) U =i=E}'  
H %bXx-  
type = “java.lang.Object”; (i.7\$4  
/5wIbmz@I  
return new VariableInfo[] { %.rVIc"  
W<c95QD.  
new VariableInfo(data.getAttributeString(“id”), |?gO@?KDZ  
N<N uBtkA  
type, NI^jQS M]  
my}l?S[2d@  
true, t_"]n*zk1  
L; o$vI~U,  
VariableInfo.AT_BEGIN) r.ib"W#4  
U)Jwo O  
}; H/^t]bg,  
sK/Z 'h{|  
} Qn!KL0w  
khb/"VYd  
} \c\z 6;j  
$/FL)m8.3  
S\S31pYT  
注意:关于额外tag信息类的类名必须要在TLD中的tag标签下的tei-class子元素中定义。因此,DefineTei的tei-class中的定义看起来如下: 6 k6}SlN[  
<tei-class> "nA~/t=  
org.apache.struts.taglib.bean.DefineTagTei 8dUP_t~d#q  
</tei-class> OnND(YiX  
2EC<8}CG  
B1k;!@@1 4  
具有协作关系的tag }8Yu"P${Y  
V6!1(|  
PLueH/gC.  
tag通过共享对象来进行协作,JSP技术支持2种方式的对象共享。 .jv#<"DW  
?'^dYQ4  
第一种方法是使用pageContext对象进行对象的共享(可支持JSP页面和tag处理类之间的共享),如果在一个tag处理类中要调用由另一个tag处理类创建的对象,可调用pageContext.getAttribute(name, scope)方法。 ^|lw~F  
O!k C  
第二各方式的共享是对于tag之间有嵌套关系而言的,外层的tag所创建的对象对于内层的tag来说是可以共用的。这种形式的共享的好处是减少了可能存在的重名冲突。 c>b{/92%  
2u%YRrp  
要访问一个嵌套tag创建的对象,tag处理类必须先找到此嵌套tag对象,可用TagSupport的静态方法 TagSupport.findAncestorWithClass(from, class)或TagSupport.getParent方法。前者在当不确定此tag是否为嵌套tag对象时使用。一旦它的父类被找到,它就能访问其所有动态或静态创建的对象。静态创建的对象是父类的成员,而动态创建的对象可能是父类的私有对象。诸如此类的对象可以用tag处理类的setValue方法来保存,用getValue方法来获得。 :soR7oHZ  
jmJeu@(  
下例阐述了以上两种共享对象的方法。在这个例子当中,一个查询tag检查一个名为connection的属性名是否在doStartTag中被设置。如果connection属性被设置,tag处理类从pageContext中得到这个connection对象。否则,此tag处理类先找到它的父tag处理类,然后从它的父tag处理类中找到connection对象。 #/ HQ?3h]  
/=[hRn@)A  
{' UK> S  
public class QueryTag extends BodyTagSupport hkDew0k  
1wLEkp!~  
{ L(q~%  
Ve[[J"ze  
private String connectionId; m:)s UC0  
)ZMR4U$+v  
public int doStartTag() throws JspException 9CFh'>}$  
:;URLl0  
{ *[+{KJ  
nU,~*Us  
String cid = getConnection(); ^ 0g!,L  
l&_PsnU  
if(cid != null) ]T;  
l\_81oZ  
{ ]-{A"tJ  
m9mkZ:r(kV  
//存在一个connection id,使用它。 sI5S)^'IQ  
f/vsf&^O  
connection = (Connection) pageContext.getAttribute(cid); .c]@xoC  
I\<)9`O  
} $6~t|[7:%Y  
P{2j31u`  
else hiw>Q7W  
|lMc6C  
{ 7qL B9r  
M-/2{F[  
ConnectionTag ancestorTag = (ConnectionTag)findAncestorWithClass(this, #]*]qdQWV^  
'B;n&tJ   
ConnectionTag.class); Wg=qlux-  
a49t/  
if(ancestorTag == null)  ay,"MJ2  
u+m9DNPF  
{ 3XIL; 5  
PM3fJhx  
throw new JspTagException(“一个没有connection属性的查询标签必须被一个connection标记嵌套。”); jGEmf<q&u  
|F49<7XB[~  
} fS]Z`U"  
/kV5~i<1S  
connection = ancestorTag.getConnection(); qZ%0p*P#_  
er.;qV'Wz6  
} ,!QtViA7  
xm0(U0 >  
} ~Z}DN*S  
V?- ]ZkI  
} n um2HtU&%  
oC}2 Z{  
L}VQc9"gc  
_Jn@+NoO  
此查询标签在JSP页面中的调用形式可以从以下2种定义中任选一种: Rnw v/)  
%+oV-o\ #A  
=}%Q}aPp  
<tt:connection id=”con01” ...> ... </tt:connection> y]}N [l  
kC iOcl*$  
<tt:query id=”balances” connection=”con01” > Kidbc Z  
Tbj}04;I  
SELECT account, balance FROM acct_table q{XeRQ'/  
/hYFOZ  
where customer_num = <%= request.getCustno() %> d0YQLh  
XblZlWP#  
</tt:query> &#;lmYyaui  
{'6-;2&f  
%']`t-N8  
或 .>NPgd I  
{yM@3v~  
<tt:connection ...> T~~K~a \8  
3 (F+\4aRm  
<x:query id=”balances”> {Z}zT1kA  
>/'/^h  
SELECT account, balance FROM acct_table ]3d5kf  
iCy$ rC  
where customer_num = <%= request.getCustno() %> gp-rTdN  
}1|FES  
</x:query> W#foVAi .  
\{54mM~  
</tt:connection> u@T,8  
EMf"rGXu(  
w0 1u~"E  
与此同时,在TLD中必须指定connection属性为可选的,定义如下: (^$SM uC  
@@& ? ,3  
<tag> {-51rAyi  
>2mV {i&  
... fJ;1ii~  
pg3h>)$/  
<attribute> \9 k3;zw  
}'4aW_ta  
<name>connection</name> .q'{ 3  
WfYC`e7q  
<required>false</required> )D" 2Q:  
v[~Q   
</attribute> _.xicov  
,f$ftn\~j/  
</tag>
描述
快速回复

您目前还是游客,请 登录 或 注册
批量上传需要先选择文件,再选择上传
认证码:
验证问题:
10+5=?,请输入中文答案:十五