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

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

级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
标准的JSP 标记可以调用JavaBeans组件或者执行客户的请求,这大大降低了JSP开发的复杂度和维护量。JSP技术也允许你自定义taglib,其实换句话说,taglib可以看成是对JSP标记的一种扩展,正如xml是对html的一种扩展一样。taglib通常定义在tag标签库中,这种标签库存放着你自己定义的tag标签。简而言之,如果使用taglib,那么你可以设计自己的JSP标记! L#J2J$ =  
nh"dPE7^  
一般来说,自定义tag标签主要用于操作隐藏对象、处理html提交表单、访问数据库或其它企业级的服务,诸如邮件和目录操作等等。自定义tag标签的使用者一般都是那些对java编程语言非常精通,而且对数据访问和企业级服务访问都非常熟悉的程序员,对于HTML设计者来说,使得他可以不去关注那些较复杂的商业逻辑,而将精力放在网页设计上。同时,它也将库开发者和库使用者进行合理分工,自定义tag标签将那些重复工作进行封装,从而大大提高了生产力,而且可以使得tag库可用于不同的项目中,完美地体现了软件复用的思想。 y7%SHYC p[  
#dD0vYT&od  
在这篇文章中,我们主要讨论: ~*9Ue@  
hJD3G |E  
· 什么是自定义tag标签? o)]O  
B2'TRXIm1U  
· 怎么使用tag标签? l2}X\N&q  
|\/\FK]?]  
o 声明要使用的tag库 =8%*Rrj^  
jA[Ir3  
o 找到与之对应的tag处理类 >EZZEd   
- ZyY95E<  
o tag标签的类型 ek]nLN  
E@n~ @|10  
· 自定义tag标签 lI+^}-<  
8n-Xt7z  
o tag处理类 IV1Y+Z )  
Dln1 R[  
o tag库描述 TbN{ex*  
,D]g]#Lq  
o tag标签示例 72.Msnn  
pnyu&@e  
o 带属性的tag Bq1}"092  
ewHs ]V+U  
o 带body的tag ';c 6  
?Zsh\^k.g  
o 定义了脚本变量的tag ^8J`*R8CL  
*Ms"{+C  
o 具有协作关系的tag IkjJqz  
6x=w-32+ y  
· 自定义tag标签 zSU,le  
}6<5mq)%  
o 一个迭代tag的例子 [u37 Hy_Gi  
j"aY\cLr t  
o 一个模板tag库 8DY:a['-d  
pek=!nZ  
o tag处理类到底是怎样被调用的? 4d}=g]P  
/f Q}Ls\  
&q9=0So4\  
什么是自定义的tag? +^&i(7a[?  
R5%CK_  
一个自定义的tag标签是用户定义的一种JSP标记。当一个含有自定义的tag标签的JSP页面被jsp引擎编译成servlet时,tag标签被转化成了对一个称为tag处理类的对象进行的操作。于是当JSP页面被jsp引擎转化为servlet后,实际上tag标签被转化成为了对tag处理类的操作。 [#RFdn<  
5E1`qof  
自定义tag标签有很多特色,诸如: `9+R]C]z8  
u@`a~  
· 可以在JSP页面中自定义tag标签的属性 G%;>_E  
6H5o/)Q~  
· 访问JSP页面中的所有对象 pe2:~}WB  
w6)Q5H53)  
· 可以动态地修改页面输出 f1+  
VB#&`]r do  
· 彼此这间可以相互通信。你可以先创建一个JavaBeans组件,然后在一个tag中调用此JavaBeans组件,同时可以在另一个tag中调用它。 R! On  
Lo#G. s|  
· tag允许相互嵌套,可以在一个JSP页面中完成一些复杂的交互。 c@"FV,L>  
4,Oa(b  
<\O8D0.d  
使用tag标签 dJQK|/  
W5= j&&|!  
EhM=wfGKw  
本节主要描述怎样在JSP页面中使用tag标签,以及tag标签的不同类型。 bgKC^Q/F  
FI.F6d)E$  
要使用tag标签,JSP程序员必须做2件事: -!\%##r7~  
P=KhR&gwV~  
· 声明此tag标签的tag库 x<Gjr}  
N N1}P'6Ha  
· 实现此tag标签 nqo1+OR  
:KA)4[#;W  
声明tag标签所在的tag库 O(!; 7v}  
h6^|f%\w*i  
如果要使用tag标签,则应用JSP的taglib指示符来指定其tag库(注意:taglib要在在使用此tag标签之前声明) sgGA0af  
a0gg<Ml  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %>  ;<B  
s%`l>#H  
uri属性定义了唯一的标签库描述(以下简称TLD),它可以是直接是tld文件名或一个独一无二的名字。prefix是用来区别其它TLD中和本TLD中有重名的tag的一种手段。 OKK Ko`RN  
sQkijo.  
TLD必须以.tld作为扩展名,并且存放在当前应用的WEB-INF目录或其子目录下。你可以通过它的文件名直接引用它,也可以通过别的方式间接地引用它。 s-+-?$K  
C.ji]P#  
以下taglib指示符直接引用一个TLD: H!u8+  
ge.>#1f}  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> KK2YT/K$SG  
!4=_l6kg~+  
以下的taglib指示符通过一个逻辑名称间接地引用一个TLD: ^v'0\(H?P  
yiI oqvP  
<%@ taglib uri=”/tutorial-template” prefix=”tt” %> {wj%WSQj/y  
L 6fbR-&Lt  
如果是间接引用TLD的话,那你必须还要在web.xml中定义此逻辑名称与tld文件之间的映射,具体做法是在web.xml中加入一个名为taglib的元素: strM3j##x  
2,`X@N`\  
<taglib> X&LJ"ahK  
W;2J~V!c  
<taglib-uri>/tutorial-template</taglib-uri> 3nc\6v%  
O6)Po  
<taglib-location> B5vLV@>]  
")\V  
/WEB-INF/tutorial-template.tld KN`k+!@/7  
C$~ly=@  
</taglib-location> &*ocr&  
Ky,upU  
</taglib> o5DT1>h  
Z_4%Oi  
QOYMT( j  
实现此tag标签 {d;z3AB  
,52 IR[I<T  
S`zu.8%5  
为了实现tag标签,你有2种方法来存放tag处理类。一、让tag处理类以.class的方式存放于当前应用的WEB-INF/class子目录下,二、如果tag处理类是以JAR包的形式存在的话,那可以放在当前应用的WEB-INF/lib目录下,如果tag处理类要在多个应用中共享,那么它就应放在jsp服务器上的common/lib目录下,对于tomcat来说,就是tomcat/common/lib目录下。 [J}eNprg  
fuv{2[N V  
Y z&!0Hfd  
tag标签类型 Z'y&11  
=FV(m S  
P(b[|QF  
自定义的tag标签遵循XML语法。它有一个开始标记和一个结束标记,有的还有body(即文本节点): u*P@Nuy6  
uGb+ *tD  
<tt:tag> BA1uo0S `S  
.!0Rh9yyl  
body F I[BZZW  
em3+V  
</tt:tag> *nJ,|T  
d]O:VghY\  
SsW<,T  
一个不带body的tag标签如下: `14@dk  
F%o!+%&7  
<tt:tag /> d/OP+yzgZ  
;#9?3O s  
1~K'r&  
简单的tag标签 z{ V;bi;  
Q\kWQOB_  
一个没有body和属性的tag标签如下: #U L75  
T*%GeY [  
<tt:simple /> ]-{ fr+  
Z+y'w#MZL  
r[}nrH&8  
带属性的tag标签 /96lvn]8lO  
T[1iZ  
dX)a D $m  
自定义标签可以有自己的属性。属性一般在开始标记中定义,语法为 attr=”value”。属性的作用相当于自定义标签的一个参数,它影响着tag处理类的行为。你可以在TLD中详细定义它。 [.xY>\e  
jGz~}&B  
你可以用一个String常量给一个属性赋值,也可以通过表达式给它赋值,如<%= ...%>。以struts为例,它的logic:present标签就是用的String常量来给属性赋值: K=0xR*ll5  
4>V@+#Ec5  
<loglic:present parameter = “Clear”> YFJaf"?8g  
c:.5@eq^  
而另一个标签logic:iterate是用表达式来给属性赋值: <Qih&P9;>  
 mih}?oi  
<logci:iterate collection=”<%= bookDB.getBooks() %>” mJ<`/p?:  
&-Ch>:[  
id=”book” type=”database.BookDetails”> 0~RD@>]  
( `bb1gz  
b5=|1SjR  
带body的tag标签 yXDjM2oR/2  
iQ:eR]7X  
一个自定义标签可以包含其它自定义标签、脚本变量、HTML标记或其它内容。 Bh=t%#y|`  
81y<Uz 6  
在下述例子中,此JSP页面使用了struts的logic:present标签,如果些标签定义了parameter=”Clear”的属性,则将清除购物车的内容,然后打印出一条信息: zX*5yNd  
K |=o-  
<logic:present parameter=”Clear”> ANBuX6q  
Oo; ]j)z  
<% cart.clear(); %> vi^YtA  
&t<g K D  
<font color=”#ff0000” size=”+2”><strong> B2]52Fg-"  
p P@q `  
你选择了清除购物车! t{iRCj  
iZfZF  
</strong></font> oH0g>E;  
d)!'5Zr M  
</logic:present> d"?"(Q_8n  
SJP3mq/^K  
}hg=#*  
到底是用属性还是用body来传递信息? myX&Z F_9  
H}~K51  
如上所述,我们既可以通过属性,也可以通过body来传递信息。但一般来说,比较简单的类型,如字符串或简单表达式最好采用属性来传递信息。 MF'Z?M  
yOEy3d=*  
Za!KM  
定义脚本变量的tag标签 `mteU"{bx  
+ho=0 >  
所谓脚本变量,是指JSP中可以调用的变量或对象。它可由tag标签产生。以下示例阐述了一个tag标签定义了一个名为tx的由JNDI所定义的事务处理对象。脚本变量可以是ejb对象、事务、数据库连接等等: Mo N/?VA  
W3!-;l  
<tt:lookup id=”tx” type=”UserTransaction” name=”java:comp/UserTransaction” /> <bhGpLh-E  
s(Gs?6}>T  
<% tx.begin(); %> +d=f_@i  
,5W u  
... h?/E/>  
P ah@d!%A  
- JEPh!oTt  
具有协作关系的tag标签 dpq(=s`s  
&PV%=/ -J  
自定义tag标签之间可以通过共享对象来实现协作。在下述例子中,标签tag1创建了一个名为obj1的对象,在标签tag2仍可以重复使用obj。 U=KUx  
sjLMM_'  
<tt:tag1 attr1=”obj1” value1=”value” /> Rl cL(HM  
<B|b'XVH2  
<tt:tag2 attr1=”obj1” /> x1g-@{8]j  
rucw{) _  
在以下这个例子当中,如果外层的tag标签创建了一个对象,那么其内层的所有tag标签都可以使用这个对象。由于这样产生的对象没有一个指定的名字,那么就可以将少重名的冲突。这个例子阐述了一系列协作的嵌套对象。 >e/>@ J*  
vd#)+  
<tt:outerTag> 0/ 33Z Oc  
# A4WFZ  
<tt:innerTag /> HRE?uBkjf  
dh6kj-^;Cf  
</tt:outerTag> &AxtSIpucP  
Ewkx4,`Ff  
"AjC2P],  
Tag处理类 rWJ5C\R  
o?/H<k\5  
{jYVA~.|Z  
Tag处理类必须实现Tag接口或BodyTag接口,不过现在一般都流行从TagSupport或BodyTagSupport类中继承,这些类或接口都可以在javax.servlet.jsp.tagext包中找到。 P^F3,'N  
\e4AxLP  
当JSP引擎看到自己的JSP页面中包含有tag标签时,它会调用doStartTag方法来处理tag标签的开头,调用doEndTag方法来处理tag标签的结束。 }U'9 d#N  
9a=:e=q3#  
下表说明不同类型的tag所需要不同的处理过程: =gSc{ i|  
30WOH 'n  
Tag处理类的方法 0/] h"5H3  
Y5CkCF  
Tag标签类型 O&/n BHu\  
所调用的方法 ~ :{mKc  
vde!k_,wZ  
基本标签 LyvR].p=5*  
doStartTag, doEndTag, release {_(R?V]w,  
'vt Jl  
带属性的标签 +`"Tn`O  
doStartTag, doEndTag, set/getAttribute1...N, release a Tm R~k  
zx8@4?bK  
带内容的标签 }XUI1H]jk  
doStartTag, doEndTag, release 4=^Ha%l  
g?xXX /Qe  
带内容的标签,且内容重复循环 ?QKD YH(  
doStartTag, doAfterBody, doEndTag, release `'iO+/;GY  
AfO.D ?4x  
带内容的标签,且内容与JSP交互 Tz6I7S-w  
doStartTag, doEndTag, release, doInitBody, doAfterBody, release w2b(,w  
V[%IU'{:  
一个tag处理类可以通过javax.servlet.jsp.PageContext来与JSP交互,通过javax.servlet.jsp.PageContext类,tag处理类可以访问JSP中的request、session和application对像。 99:.j=  
>3b< Fq$  
如果tag标签是互相嵌套的,那内层的tag处理类可以通过它的parent属性来访问上层的tag处理类。 ~kV>nx2  
_VgFuU$h  
一般情况都将所有的tag处理类打成了JAR的包,以便于发布。 W.{+0xx  
Qh8pOUD0l}  
32 j){[PL3  
Tag库描述(简称TLD) `x?_yogPM  
bYQ@!  
xv147"w'v  
Tag库是用xml语言描述的,TLD包括了tag库中所有tag标签的描述,它一般用来被jsp服务器用来校验tag的语法正确性,或者被jsp开发者用来开发新的标签。 J3oUtu  
73!NoDxb  
TLD的文件扩展名必须为.tld,而且必须放在当前WEB应用的WEB-INF目录或其子目录中。 .EWjeVq  
=ePwGm1:c  
一个TLD的内容的开头必须遵守标准的XML开头,用于描述DTD和xml的版本,例如: :8bq0iqsV  
lBG=jOS  
<?xml version="1.0" encoding="ISO-8859-1" ?> Rq2bj_j  
ncUhCp?'  
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd"> so.}WU  
TLD必须以<taglib>来作为它的根元素,<taglib>的子元素如下表: lUq `t K8  
9i_@3OVl  
IY!.j5q8  
<taglib>的子元素 "UY34a^I  
 nXy"  
Element n87Uf$  
Description p;o"i_!  
&'PLOyWw  
tlib-version L?a4>uVY  
Tag库的版本 2\64~a^  
RFe># o  
jsp-version Y@UW\d*'%I  
Tag库所需要的jsp的版本 'Q]Wk75  
d7g$9&/q  
short-name 46l*ui_  
助记符,tag的一个别名(可选) gL| 9hvHr[  
s^)(.e_  
uri Oi C|~8  
用于确定一个唯一的tag库 9ec#'i=  
^f(El(w  
display-name \zA3H$Df~  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) `T%nGVl>\  
LoJEchRK  
small-icon 0#8lg@e8  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) =b)!l9TX  
71<4q {n  
large-icon -c0*  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) qgWsf-di=  
K-.%1d@$y  
description 0iMfyW:  
对tag库的描述(可选) & R<K>i  
i(# Fjp  
listener ]E.FBGT  
参见下面listener元素 m\=Cw&(  
7<8'7<X  
tag 4w 7vgB  
参见下面tag 元素 //$^~} wt  
&d!ASa  
Listener元素 :q2RgZE  
L&5zr_  
一个tag库可能定义一些类做为它的事件侦听类,这些类在TLD中被称为listener 元素,jsp服务器将会实例化这些侦听类,并且注册它们。Listener元素中有一个叫listener-class的子元素,这个元素的值必须是该侦听类的完整类名。 5ry[Lgg  
=(,kjw88w  
Tag元素 YAi@EvzCVy  
`X =[ m>  
每个tag元素在tag库中都要指出它的名字、类名、脚本变量、tag的属性。其中脚本变量的值可以直接在TLD中定义或通过tag附加信息的类来取得。每个属性描述了这个属性是否可以省略,它的值是否可以通过<%= …%>这样的JSP语法来获得,以及属性的类型。 {@" F/G+  
O15~\8#'  
每一个tag在TLD中对应一个tag元素,下表是tag元素的子元素: _|{pO7x]oG  
zJ8jJFL+Y  
Tag元素的子元素 %~Ymb&ugg  
6UPGE",u  
元素名称 UrS%t>6k  
描述 =k!F`H`/%'  
8rz ,MsFR  
name ZGd7e.u=  
独一无二的元素名 u<+RA  
MLDAr dvK  
tag-class Zc9S[ivq  
Tag标签对应的tag处理类 eQ#"-i  
U!lWP#m  
tei-class R~d Wblv  
javax.servlet.jsp.tagext.TagExtraInfo的子类,用于表达脚本变量(可选) EiA_9%<  
ar`}+2Qh0  
body-content 2m&?t_W  
Tag标签body的类型 /w*HxtwFmD  
eX^ F^(   
display-name M!PK3  
被可视化工具(诸如Jbuilder)用来显示的名称(可选)  t|:XSJ9  
Fow{-cs_p  
small-icon E3_ 5~>  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) ~~,#<g[  
iSMVV<7  
large-icon 3KKq1][  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) TfNm0=|  
H"V)dEm  
description Aacj?   
此tag标签的描述 lI[O!Vu Kc  
,z$ U=u o  
variable z&|sks7  
提供脚本变量的信息(同tei-class)(可选) '&y+,2?;Y[  
rAu@`H?  
attribute \#'m([<e  
Tag标签的属性名 hl+ T  
 !h* F58  
以下章节介绍对于不同类型的tag,如何具体地实现它们。 wA%,_s/U  
dM5N1$1,  
QnH~' k  
简单的tag jpfFJon)w  
8{-bG8L> 5  
B o[aiT  
tag处理类 G4f%=Z  
[sG!|@r  
简单的tag处理类必须实现Tag接口的doStartTag和doEndTag方法。当jsp引擎碰到tag标签的开头时,doStartTag被调用,因为简单的tag没有body,所以此方法将返回 SKIP_BODY。当jsp引擎碰到tag标签的结尾时,doEndTag被调用,如果余下的页面还要被计算,那它将返回EVAL_PAGE,否则将会返回SKIP_PAGE。 {/qq*0wa  
cvnRd.&  
以下是例子:对于标签 <tt:simple /> ,它的tag处理类实现如下: $Mqw)X&q  
O#b%&s"o  
!~f!O"n)3r  
public SimpleTag extends TagSupport ?OWJUmQ  
r1xhplHH@  
{ :YN,cId*  
6\/(TW&  
public int doStartTag() throws JspException 2-u9%  
7Dx <Sr!  
{ ^WIGd"^  
?(j:F2dU~  
try{ 5!d'RBO   
G9a6 $K)b  
pageContext.getOut().print(“Hello.”); Ha20g/ UN.  
H5p&dNO  
}catch(Exception e){ >[gNQJ6  
p3{ 3[fDx  
throw new JspTagException(“SimpleTag: “ + e.getMessage()); 8 gzf$Oc  
6 VuMx7W1  
} A;C)#Q/  
Y**|e4  
return SKIP_BODY; l)( 3]  
Kh2!c+Mw  
} S -KHot ?  
$/;;}|hqi  
public int doEndTag() 6.g k6  
*4|]=yPU  
{ Eh&HN-&  
g\lEdxm6Sj  
return EVAL_PAGE; 16R0#Q/{+*  
*.F4?i2D  
} ptEChoZ6  
Y|96K2BR  
} L4-v'Z;  
OtFGo 8  
@fG 'X  
注意:如果tag标签没有内容的话,那必须定义body-content元素为空,例如 x C+TO  
r:Rk!z*  
<body-content>empty</body-content> }:a:E~5y  
8[xl3=  
8xN+LL'T{  
带属性的tag标签
评价一下你浏览此帖子的感受

精彩

感动

搞笑

开心

愤怒

无聊

灌水
级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
只看该作者 1 发表于: 2007-01-01
tag处理类 ,37\8y?o\  
's_[ #a;Vp  
对于tag标签的每个属性,你必须依照JavaBeans规范来定义其属性,以及get和set方法。以struts的logic:present 标签为例, @UCr`>  
;fGh]i  
<logic:present parameter=”Clear”> '$\O*e'  
Vx*O^cM  
与此相应,此tag处理类应有如下方法和定义: ].r~?9'/  
{IA3`y~  
::R5F4  
protected String parameter = null;  \qj(`0HG  
SM8Wg>  
public String getParameter() |Pj]sh[^Y  
AD^Q`7K?uR  
{ !$L~/<&0g  
FH7h?!|t  
return this.parameter; ee\QK,QV  
#$0*Gd-N  
} !}PZCbDhL  
BH\!yxK  
public void setParameter(String parameter) <b#1L  
BOdd~f%&tn  
{ &f($= 68  
PJ3M,2H1b.  
this.parameter = parameter; :^H2D=z@  
5VZZk%oy  
} PQJw"[N/YM  
It:,8  
z,xGjS P  
注意:如果你的属性名为id,而且你的tag处理类是从TagSupport类继承的,那你就不需要定义它的属性和set和get方法,因为他们早已在TagSupport被定义过了。 WiiAIv&  
u1;sH{YK>  
Attribute元素  BDfJ  
'|J~2rbyr  
对于tag标签的每个属性,你必须定义它是否必须的,它的值是否可以用诸如<%= …%>的表达式来获得,以及它的类型(可选),如果不指定它的类型,那就默认为是java.lang.String类型。如果rtexprvalue元素被定义为true或yes,那么在type元素中就定义了attribute的返回类型。 x|`BF%e/v  
~`X$b F  
<attribute> A"i $.dR{  
!q!5D`  
<name>attr1</name> AjD? _DPc  
B]u!BBjC  
<required>true|false|yes|no</required> -BcnJK0  
;u;_\k<qK  
<rtexprvalue>true|false|yes|no</rtexprvalue> = P$Q;d  
bJoP@s  
<type>attribute的返回类型(只用当rtexprvalue为真是才有效)</type> (tvfF0~  
D6,Ol4d  
</attribute> /tj_WO_  
Y^tUcBm\  
如果tag的某个属性不是必须的,那tag处理类会自动提供一个缺省值。 @Y !Jm  
(;9j#x  
例如,在logic:present这个tag标签中定义了一个属性叫parameter,但它不是必须的,而且它可以被诸如<%= …%>的表达式来赋值。 >u+%H vzc  
P,@/ap7J  
<tag> DT3"uJTt  
d <RJH  
<name>present</name> K_F"j!0  
V3(8?Fz.  
<tag-class>org.apache.struts.taglib.logic.PresentTag</tag-class> ~S\8 '  
S!66t?vHB  
<body-content>JSP</body-content> aC94g7)`  
bbT1p :RF  
xnxNc5$oE  
Rxlz`&   
<attribute> EY^?@D_<  
Je4hQJ<h  
<name>parameter</name> o .( Gja4  
; )FmN[  
<required>false</required> tyFsnc k  
4%#q.qI  
<rtexprvalue>true</rtexprvalue> '^`iF,rg  
wZVLpF+7  
</attribute> XT?wCb41R  
Clb7=@f  
Nq1YFI>W  
,P%i%YPj  
</tag> hP}-yW6]  
5zOC zm  
mt~E&Z(A  
属性元素的校验 .bUj  
YJ|U| [  
p8FXlTk  
有关于tag标签的有效值可以从tag库的说明文档中获得,当JSP页面被编译时,jsp引擎会强制性地参照TLD中定义的规则进行检查。 rl,i,1t  
_nM 7SK  
还有一个方法也可以进行属性元素的校验,就是先继承类TagExtraInfo,然后调用它的isValid方法。这个类同时也起到提供tag中定义的脚本变量信息的作用。 Hk'R!X  
/U} )mdFm  
IsValid方法通过TagData对象来传递属性信息,它包括着tag的所有的属性名-值的信息。由于校验发生在运行时刻,因此这个属性的值将被赋值为TagData.REQUEST_TIME_VALUE。 <G'M/IR a  
0g9y4z{H  
例如tag标签<tt:twa attr1=”value1” />在TLD中定义如下: Xk!wT2;  
\-SC-c  
<attribute> %C_c%3d  
kbo9nY1k g  
<name>attr1</name> &?}A/(#  
~C>clkZ  
<required>true</required> rv`GOta*  
1 @i/N  
<rtexprvalue>true</rtexprvalue> Nt\0) &b  
^*w}+tB  
</attribute> "T*1C=  
sX-@ >%l  
c dWg_WBC  
这个定义说明了attr1能在运行期间被赋值。 KciN"g|X  
XRHngW_A  
以下的isValid方法检查attr1属性的值是否属于Boolean类型。注意由于attr1能在运行刻被赋值,那么isValid方法必须检查tag用户是否对此tag进行了运行时刻赋值。 uPxJwWXO  
`{m,&[ n  
%j/pln&  
Public class TwaTEI extends TagExtraInfo KcUR /o5K  
9Y@ eXP  
{ B#?rW*yEe  
'S|7<<>4k  
public boolean isValid(Tagdata data) WrS>^\:  
q\-P/aN_  
{ F]fXS-@ c  
z,bK.KFSs  
Object o = data.getAttribute(“attr1”); ym+Ezb#o  
xz, o Mlw  
If(o != null && o != TagData.REQUEST_TIME_VALUE) m>RtKCtP  
`X)A$lLr  
{ [b_qC'K[  
o+.ySSBl+  
if( ( (String)o).toLowerCase().equals(“true”) || `F]  
pXvys] @  
((String)o).toLowerCase().equals(“false”) ) 9kB R/{  
A!Tm[oqu  
return true; *(qj!U43  
zXU g(xu  
else [%O f  
pRzL}-[/v  
return false; nM ?Nf}  
Lz!JLiMEET  
} @|5B}%!  
ioEjbqD<  
else n/x((d%"E  
/='Q-`?9  
return true; 81C;D`!K  
M6bM`wHH>  
} '1(6@5tyWk  
mHV{9J  
} R:3=!zav  
IRueq @4  
g5RH:]DV  
带body的tag p<zeaf0W  
5S, Kq35$(  
)8oN$2 0  
tag处理类 J_fs}Y1q\  
Pd-LDs+Ga  
`HO] kJpX  
如果tag标签含有内容,那处理方式会略微有些不同,而且还要视tag处理类是否要与body交互的情况而定。如果要与body交互,那我们认为tag处理类要可能要对body进行操作。 s 0_*^cZ  
(> _Lb  
Tag处理类不与body交互 |rG)Q0H,  
!dUdz7  
如果tag处理类不与body交互,tag处理类应该实现Tag接口或从TagSupport中派生,如果body要被计算,那么doStartTag方法应返回 EVAL_BODY_INCLUDE,否则应返回SKIP_BODY。 00{a }@n  
B:Ft(,  
如果tag处理类要对body反复运算,则它应该实现IterationTag或从TagSupport中派生。如果tag处理类认为body还未计算完的话,那它的doStartTag方法和doAfterBody方法必须返回EVAL_BODY_AGAIN。 a 9{:ot8,  
_aBy>=2c$  
Tag处理类与body交互 RRpY%-8M  
 wlsx|  
如果tag处理类与body交互,那tag处理类应实现BodyTag接口或从BodyTagSupport中派生。这种tag处理类一般要实现doInitBody和doAfterBody方法。 ;^u,[d  
_C (fz CK  
Body允许一些方法来读写它的内容。Tag处理类可以调用body内容的getString或getReader方法来从body中提取信息,也可用 writeOut(out) 方法来将body的内容写入到out对象中。其中out对象通过tag处理类的getPreviousOut方法来获得。 {}rnn$HQe  
rS+) )!  
如果body的内容需要被计算,那么doStartTag方法必须返回EVAL_BODY_BUFFERED,否则,它将返回 SKIP_BODY。 {M7`"+~w  
.6LRg  
doInitBody 方法 D9NQ3[R 9  
5gII|8>rQ  
此方法在body内容已经设好,但未被计算之前被调用。你可以根据不同的body内容来制定初始化策略。 mRm}7p  
D4C:%D  
doAfterBody方法 =mF"D:s*  
LokH4A17U  
此方法在body内容已被计算后进行调用。 J3~%9MCJ  
j7QK8O$XL  
和doStartTag方法一样,doAfterBody方法返回一个指示符指示是否要继续计算body,如果要继续计算,则doAfterBody应返回EVAL_BODY_BUFFERED,否则,它应返回SKIP_BODY。 LnKgT1  
Aj=GekX{  
release 方法 !h|,wq]k  
,Q3OQ[Nmh  
tag处理类调用此方法将它的状态重置为初始状态,并释放所有的私有资源。 /}J_2  
Qe\vx1GRLH  
*W 2)!C|  
以下的例子读取body的内容(其中含有一条sql语句),然后将它传递给一个对象,让它进行查询。由于此处body不须重新计算,所以doAfterBody会返回SKIP_BODY。 4(VV@:_%  
ExSM=  
F\^8k/0  
Public class QueryTag extends BodyTagSupport SDV#p];u  
 @;$cX2  
{ :CK`v6 Qs  
D B65vM  
public int doAfterBody() throws JspTagException ,|3_@tUl  
?o$ t{AQ  
{ OzD\* ,{7  
W h)  
BodyContent bc = getBodyContent(); U\B9Ab  
_P!b0x~\  
//将body的内容以字符串的格式提取出来 K;WQV,  
ok0ZI>=,  
String query = bc.getString(); |m6rF7Q  
bmK  
//清除body Yj*T'<e  
aL*MCgb'  
bc.clearBody(); [Eccj`\e g  
ep?D;g  
try{ U._fb=  
W]DGt|JP  
Statement stmt = connection.createStatement(); yg H)U.  
/} z9(  
Result result = stmt.executeQuery(query); s]O Z+^Z  
rks"y&&Nc  
}catch(SQLException e){ cTzR<Yr  
?upd  
throw new JspTagException(“queryTag: “ + e.getMessage() ); t-o,iaPG3  
t&Eiz H$  
return SKIP_BODY; 4H%#Sn#L^!  
f<iK%  
} )[J!{$&y  
~tyqvHC  
} 9#:fQ!3`  
+_$s9`@]6  
xw_klHL-o  
body-content元素 pe0ax- Zv  
2T)k-3  
C?>d$G8  
由于tag可能会有body,你必须用body-content元素来指定body内容的类型: Q~qM;l\i  
pfHjs3A=  
<body-content>JSP|tagdependent</body-content> egSs=\  
L.yM"  
|;xEK nF  
如果body的内容是定制的或内部的tag、脚本元素、或HTML广本,则归类为JSP类型。其他的类型,比如上面代码所述的?D?D将sql statement类传给 query tag的这种类型应该标为tagdependent。 JbL3/h]  
Dy,MQIM|!  
注意:实际上body-content的值并不影响tag处理类对body内容的处理,它仅仅是被tag编辑工具用来描述此body的内容。 8s2y!pn7Q  
U5wh( vi  
O/FI>RT\H  
用tags定义脚本变量 [j5+PV  
NK/y,f6  
Yj>4*C9  
tag处理类 a>W++8t1 ;  
Md@x2Ja  
S|)atJJ0G"  
tag处理类负责创建或设置页面中定义的脚本变量,用pageContext.setAttribute(name,value,scope)或pageContext.setAttribute(name,value)方法来实现。一般来说,tag处理类通过脚本变量的名称来获取它,脚本变量的名称一般可用get方法来获得。 3@\/5I xn  
X/cb1#  
如果脚本变量的值依赖于tag处理类中的上下文中某一对象,那它可用pageContext.getAttribute(name,scope)方法来找到那个对象。一般的处理过程是tag处理类先找到脚本变量,再对其进行处理,然后用pageContext.setAttribute(name,object)的方法来设置它的新值。 BJb,  
NJgu`@YoI  
对象的生存周期(scope)如下表: WZn;u3,R  
;Ivv4u  
对象的生存周期表 %(p9AE  
`ovMfL.u  
名字 KJ32L  
可访问范围 Q"D  
生存周期 j0~am,yZ  
jT$J~M pHh  
page 6xtgnl#T  
当前页面 uA[ :  
一直有效,除非页面向客户提交响应或重定向到一个新页面 k(^TXUK\o  
|v8h g])I+  
request & [@)Er=  
当前页面或当前页面重定向到的页面 %LP4RZ  
一直有效,除非页面向客户提交响应 , +J)`+pJx  
<uB)u>3   
session i 0/QfB%O  
当前页面或在同一浏览器窗口中的页面 b way+lh  
一直有效,除非关闭当前浏览器、超时、网络故障 <!FcQVH+L  
]s0wJD=  
application zps =~|  
整个web应用程序的所有请求 / 7\q#qIm:  
一直有效,除非发生网络故障、服务器故障 ]r 0j  
f4\$<g/~  
提供关于脚本变量的信息 jY%.t)>)  
au+Jz_$)  
以下示例定义了一个名为“book”的脚本变量,用来访问程序中关于书的信息: A :KZyd"Z  
)Cj1VjAg  
<bean:define id=”book” name=”bookDB” property=”bookDetails” type=”database.BookDetails” /> *(1 <J2j  
-*KKrte  
<font color=”red” size=”+2” > $%\6"P/64  
qMVuFw Phi  
<%= messages.getString(“CartRemoved”) %> yOQae m^O  
q MrM^ ~  
<strong><jsp:getProperty name=”book” property=”title” /></strong> Ul /m]b6-  
\1joW#  
</font> 9%|skTgIqH  
^ '|y^t  
当包含此tag的JSP页面被编译时,jsp引擎会自动生成关于此book的同步的代码(同步可以避免几个客户同时访问此book时造成的冲突),要生成同步代码,jsp引擎需要知道此脚本变量的如下信息: LH_H yP_  
|[iO./ zP  
· 脚本变量名称 3%(r,AD  
/"st sF  
· 脚本变量所属的类 "GZ}+K*GG  
0j4n1 1#  
· 此脚本变量是否引用了一个新的或已存在的对象 A|1xK90^XT  
KCbJ^Rln  
· 此脚本变量的有效性 >'q]ypA1  
L-E?1qhP>  
有两种办法可以向jsp引擎提供关于脚本变量的信息:在TLD中定义variable子元素,或用tei-class子元素定义一个额外tag信息类。用variable最简单,但可能降低了一些灵活性。 qx1Js3%  
j>;1jzr2}  
Variable元素 -ak. wwx\  
FWW@t1)  
Variable元素有如下子元素: kP[fhOpn  
}"WovU{*s  
· name-given ?D?D 给出的名字,是一个常量 (_ :82@c  
Zl&ED{k<  
· name-from-attribute?D?D 属性名,在编译时给出的属性名 2;"vF9WMm  
8%u|[Si;  
name-given或name-from-attribute两者必须选一,但以下子元素是可选的: $`7Fk%#+e  
ysK J=  
· variable-class?D?D变量的类型,缺省为java.lang.String。 ysG1{NOl  
CKZEX*mPC  
· declare?D?D此脚本变量是否引用了一个新对象,缺省为True。 0Yq_B+IC  
eL"'-d+]  
· scope?D?D脚本变量的范围,缺省为NESTED。下表描述了scope的几种类型: KzV|::S^  
3bezYk  
脚本变量的有效范围 iOEBjj;C  
IoJI|lP  
.wq j  
有效性 (nmsw6 X  
方法 go yDG/  
U4-RI]Cpf  
NESTED $$.q6  
在tag标签的开始和结束之间 ,.( :b82$  
如果tag处理类实现BodyTag接口,则在doInitBody和doAfterBody中调用,否则在doStartTag中调用 BC_<1 c  
R\3v=PR[  
AT_BEGIN ;}f {o^]'  
从tag标签的开始一直到页面结束 |-{e!&  
如果tag处理类实现BodyTag接口,则在doInitBody、doAfterBody和doEndTag中调用,否则在doStartTag和doEndTag中调用 bws}'#-*  
zE1=P/N  
AT_END QnBWZUI  
从tag标签的结束一直到页面结束 +U J~/XV  
在doEndTag中调用 ga\ s5  
\F`>zY2$%  
以struts为例,它的bean:define标签的实现遵循JSP1.1规范,此规范要求使用额外tag信息类来定义脚本变量。Variable元素是JSP1.2规范中加入的。以bean:define标签为例,你可以定义如下variable元素: F7jkl4  
=J)-#|eZG  
<tag> SC%HHu\l  
hM!g6\ w  
<variable> zj2y=A| Y  
!m~r0M7  
<name-from-attribute>id</name-from-attribute> %pOxt<  
9v;[T%%  
<variable-class>database.BookDetails</variable-class> HU/4K7e`  
bXOM=T  
<declare>true</declare> {aV,h@>  
>6&Rytcc]  
<scope>AT_BEGIN</scope>  q9{ h@y  
ltk ARc3  
</variable> :d35?[  
TAOsg0  
</tag> "{E%Y*  
}jC^&%|  
额外tag信息类 .p=J_%K}0x  
LqI&1$#  
如果要定义一个额外tag信息类,你要继承javax.servlet.jsp.TagExtraInfo类。一个TagExtraInfo类必须实现getVariableInfo方法,此方法返回一个叫VariableInfo的数组类,它包括如下信息: N-2_kjb!  
B f  y  
· 变量名 EX!`Zejf  
xbw;s}B  
· 变量所属类名 q>K3a1x  
XaE*$:   
· 此变量是否引用了一个新对象 H)Me!^@[D  
'j{o!T0  
· 此变量的有效范围 p ]jLs|tat  
J9tV|0  
jsp引擎将一个名为data的参数传给getVariableInfo方法,data中包括tag标签中的所有“属性名?D?D属性值”对。它可以用来向VariableInfo对象提供脚本变量的名字和类名。 K/Y"oQ2  
( 1  
以struts为例,它在bean:define标签中定义了一个名为DefineTei的额外tag信息类,用来向脚本变量提供信息。由于脚本变量的名称(book)和类名(database.BookDetails)是通过tag标签的属性来传递的,它们一般定义在VariableInfo的构建代码中,并且可用data.getAttributeString方法来得到这些信息。如果要允许book脚本变量能在从tag开始直到整个JSP页面结束的范围内都可用的话,那它的范围应设为AT_BEGIN。如下所示: 5c}loOq  
}BT0dKx  
0/|Ax-dK  
public class DefineTei extends TagExtraInfo sl@>GbnS  
6A =k;do  
{ xH` VX-X3  
gzvgXZ1q"  
public VariableInfo[] getVariableInfo(TagData data) 1'p=yHw  
*'H\`@L  
{ m*B4a9 f  
)f^^hEIS  
String type = data.getAttributeString(“type”); tK uJ &I~  
~@Bw(!  
If( type == null)  `5(F'o  
iT| 7**+3  
type = “java.lang.Object”; sd B(sbSF  
|Bi7:w  
return new VariableInfo[] { h$9ut@I  
.]4MtG  
new VariableInfo(data.getAttributeString(“id”), 9a+Y )?z  
:eL[nyQr  
type, U}Puq5[ ?  
pZ*%zt]-a  
true, h:G>w`X  
>L "+8N6  
VariableInfo.AT_BEGIN) Z 1wtOL  
B:UM2Jl   
}; KlS#f  
GB}=  
} dP_bFUzg  
,gG RCp  
} pJ1\@G  
jy>?+hm?  
8b-mW>xsA  
注意:关于额外tag信息类的类名必须要在TLD中的tag标签下的tei-class子元素中定义。因此,DefineTei的tei-class中的定义看起来如下: }:$ot18  
<tei-class> NySa%7@CD  
org.apache.struts.taglib.bean.DefineTagTei #U w X~  
</tei-class> 8EdaxeDq  
.=-a1p/  
O/#uQn}  
具有协作关系的tag +03/A`PKrB  
6;s[dw5T  
W?kJ+1"(  
tag通过共享对象来进行协作,JSP技术支持2种方式的对象共享。 m`$Q/SyvG  
)/Eu=+d  
第一种方法是使用pageContext对象进行对象的共享(可支持JSP页面和tag处理类之间的共享),如果在一个tag处理类中要调用由另一个tag处理类创建的对象,可调用pageContext.getAttribute(name, scope)方法。 q=`n3+N_H~  
#rr!A pJ  
第二各方式的共享是对于tag之间有嵌套关系而言的,外层的tag所创建的对象对于内层的tag来说是可以共用的。这种形式的共享的好处是减少了可能存在的重名冲突。 0J466H_d{  
S#yGqN0i  
要访问一个嵌套tag创建的对象,tag处理类必须先找到此嵌套tag对象,可用TagSupport的静态方法 TagSupport.findAncestorWithClass(from, class)或TagSupport.getParent方法。前者在当不确定此tag是否为嵌套tag对象时使用。一旦它的父类被找到,它就能访问其所有动态或静态创建的对象。静态创建的对象是父类的成员,而动态创建的对象可能是父类的私有对象。诸如此类的对象可以用tag处理类的setValue方法来保存,用getValue方法来获得。 XHJ` C\xR  
YIgHLM(  
下例阐述了以上两种共享对象的方法。在这个例子当中,一个查询tag检查一个名为connection的属性名是否在doStartTag中被设置。如果connection属性被设置,tag处理类从pageContext中得到这个connection对象。否则,此tag处理类先找到它的父tag处理类,然后从它的父tag处理类中找到connection对象。 \ %MsG  
[YODyf}M>\  
:O&jm.2m  
public class QueryTag extends BodyTagSupport *[b>]GXd49  
dcq18~  
{ :06.b:_  
/|H9Gm  
private String connectionId; 7mXXMm  
zAklS 7L  
public int doStartTag() throws JspException L{r4hL [  
kc=Z6(=  
{ L$);50E  
|`o1B;lc  
String cid = getConnection(); w8UUeF  
t18j2P>`  
if(cid != null) EVaHb;  
K*,,j\Q.  
{ ),Yk53G6c  
P?|\Ig1Gk  
//存在一个connection id,使用它。 gzat!>*  
[dFcxzM-N  
connection = (Connection) pageContext.getAttribute(cid); |nLq 4.  
='qVwM['  
} o37oRv]  
IDos4nM27]  
else yk5K8D[tV  
B B69U  
{ 5|pF*8*  
 #$2/<  
ConnectionTag ancestorTag = (ConnectionTag)findAncestorWithClass(this, } d8\ Jg  
LA 2/<:  
ConnectionTag.class); &hL2xx=  
(^g XO  
if(ancestorTag == null) A! HJ  
Kj3Gm>B<y  
{ Ac|dmu  
%t!S 7UD  
throw new JspTagException(“一个没有connection属性的查询标签必须被一个connection标记嵌套。”); .o C! ~'  
YtWw)IK  
} !plu;w  
OQ wO7Z  
connection = ancestorTag.getConnection(); O_.!qk1R  
qAbmQ{|w  
} fXl2i]L(^B  
C%]qK(9vvd  
} #s\kF *  
SRk!HuXh  
} U  yV5A  
$>yfu=]?  
L'aB/5_%  
NR k~  
此查询标签在JSP页面中的调用形式可以从以下2种定义中任选一种: 7(tsmP  
e`7>QS ;.  
VX8CEO  
<tt:connection id=”con01” ...> ... </tt:connection> pO:]3qv  
C8Mx>6  
<tt:query id=”balances” connection=”con01” > F?H=2mzKbz  
fvi0gE@bd  
SELECT account, balance FROM acct_table 6\K\d_x  
Y[}A4`  
where customer_num = <%= request.getCustno() %> );t+~YPS  
CqZHs 9+e&  
</tt:query> i+~BVb  
2?Jw0Wq5D  
.S/zxf~h  
0}`-vOLd-  
##xvuLy-6  
<tt:connection ...> 3Os0<1@H  
t[X^4bZd  
<x:query id=”balances”> \**j \m   
!yrh50tD  
SELECT account, balance FROM acct_table iZeq l1O  
W,CAg7:*  
where customer_num = <%= request.getCustno() %> ' F9gp!s8~  
&<uLr *+*  
</x:query> +YW;63"o  
`#`jU"T|  
</tt:connection> X~"p]V_  
c6c@ Xd V  
o}/|"(K  
与此同时,在TLD中必须指定connection属性为可选的,定义如下: Ma$~B0!;s  
l*&N<Yu  
<tag> "qR, V9\  
S!z3$@o  
... J+ S]Qoz  
rQ]JM  
<attribute> F4z#u2~TC  
Vym0|cW  
<name>connection</name> w"dKOdY  
(g X8iKl  
<required>false</required> WR"1d\m:  
:0 n+RL*5  
</attribute> |D/a}Av>B  
$^{#hYq)o  
</tag>
描述
快速回复

您目前还是游客,请 登录注册
温馨提示:欢迎交流讨论,请勿纯表情、纯引用!
认证码:
验证问题:
3+5=?,请输入中文答案:八 正确答案:八