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

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

级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
标准的JSP 标记可以调用JavaBeans组件或者执行客户的请求,这大大降低了JSP开发的复杂度和维护量。JSP技术也允许你自定义taglib,其实换句话说,taglib可以看成是对JSP标记的一种扩展,正如xml是对html的一种扩展一样。taglib通常定义在tag标签库中,这种标签库存放着你自己定义的tag标签。简而言之,如果使用taglib,那么你可以设计自己的JSP标记! S~LT Lv:>  
[ 6t!}q  
一般来说,自定义tag标签主要用于操作隐藏对象、处理html提交表单、访问数据库或其它企业级的服务,诸如邮件和目录操作等等。自定义tag标签的使用者一般都是那些对java编程语言非常精通,而且对数据访问和企业级服务访问都非常熟悉的程序员,对于HTML设计者来说,使得他可以不去关注那些较复杂的商业逻辑,而将精力放在网页设计上。同时,它也将库开发者和库使用者进行合理分工,自定义tag标签将那些重复工作进行封装,从而大大提高了生产力,而且可以使得tag库可用于不同的项目中,完美地体现了软件复用的思想。 rN^P//  
~,.}@XlgT.  
在这篇文章中,我们主要讨论: 4 U`5=BI  
>T~d uwS  
· 什么是自定义tag标签? O:,Fif?;  
KFMEY\6\h  
· 怎么使用tag标签? A `n:q;my  
-%x9^oQwY  
o 声明要使用的tag库 ^aG=vXK`b  
;iEFG^'tG  
o 找到与之对应的tag处理类 pI|H9  
wsNM'~(  
o tag标签的类型 7 V+rQ  
()v{HB i  
· 自定义tag标签 !EQMTF=(  
T&`H )o  
o tag处理类 U$(AZ|0  
PH}^RR{H[  
o tag库描述 q9&d24|  
7EAkY`Op  
o tag标签示例 "Aq-H g  
p$cSES>r:  
o 带属性的tag *Q8d &$ ^  
?0VLx,kp  
o 带body的tag a_0G4@=T  
ES#K'Lf  
o 定义了脚本变量的tag fXHN m$"n  
_ %HyXd  
o 具有协作关系的tag c*g(R.!  
>@BvyZ)i  
· 自定义tag标签 A,T3%TE  
EI29;  
o 一个迭代tag的例子 [=Yfdh M8S  
zV }-_u.  
o 一个模板tag库 v5 yOh5  
? N|B,F  
o tag处理类到底是怎样被调用的? FFNv'\)  
MyOdWD&7  
X192Lar  
什么是自定义的tag? 0r+%5}|-K  
!.'@3-w]  
一个自定义的tag标签是用户定义的一种JSP标记。当一个含有自定义的tag标签的JSP页面被jsp引擎编译成servlet时,tag标签被转化成了对一个称为tag处理类的对象进行的操作。于是当JSP页面被jsp引擎转化为servlet后,实际上tag标签被转化成为了对tag处理类的操作。 hD>O LoO  
V}>0r+NL<  
自定义tag标签有很多特色,诸如: Z=Oo%lM6B  
46dh@&U  
· 可以在JSP页面中自定义tag标签的属性 }>w;(R  
oh5fNx  
· 访问JSP页面中的所有对象 @Kd lX>i  
Iky'x[p,D  
· 可以动态地修改页面输出 yp=2nU"o  
* SG0-_S  
· 彼此这间可以相互通信。你可以先创建一个JavaBeans组件,然后在一个tag中调用此JavaBeans组件,同时可以在另一个tag中调用它。 )h ~MIpWR  
`bGAc&,&  
· tag允许相互嵌套,可以在一个JSP页面中完成一些复杂的交互。 {}ZQK  
EV@xUq!x .  
Vl!Z|}z  
使用tag标签 uE>2 *u\  
rBP!RSl1  
D'>yu"  
本节主要描述怎样在JSP页面中使用tag标签,以及tag标签的不同类型。 MdWT[  
h!f7/) |[o  
要使用tag标签,JSP程序员必须做2件事: '(kySf[  
j0k"iv  
· 声明此tag标签的tag库 e/WR\B'1  
:Q\b$=,:  
· 实现此tag标签 w$7*za2  
tLpDIA_8  
声明tag标签所在的tag库 M[0@3"}}  
aT#R#7<Eg  
如果要使用tag标签,则应用JSP的taglib指示符来指定其tag库(注意:taglib要在在使用此tag标签之前声明) a`CsLBv&  
o_<o8!]l"  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> EeKEw Sg  
=@m|g )  
uri属性定义了唯一的标签库描述(以下简称TLD),它可以是直接是tld文件名或一个独一无二的名字。prefix是用来区别其它TLD中和本TLD中有重名的tag的一种手段。 c8gdY`  
3_IuK 6K2  
TLD必须以.tld作为扩展名,并且存放在当前应用的WEB-INF目录或其子目录下。你可以通过它的文件名直接引用它,也可以通过别的方式间接地引用它。 i`Es7 }  
er}/~@JJ  
以下taglib指示符直接引用一个TLD: [t /hjm"$  
Z-b^{uP  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> L^ VG?J  
Xb42R1  
以下的taglib指示符通过一个逻辑名称间接地引用一个TLD: -lyT8qZ:(  
vcAs!ls+  
<%@ taglib uri=”/tutorial-template” prefix=”tt” %> S@zsPzw  
"!gd)^<e  
如果是间接引用TLD的话,那你必须还要在web.xml中定义此逻辑名称与tld文件之间的映射,具体做法是在web.xml中加入一个名为taglib的元素: C}+w<  
K.] *:fd  
<taglib> a[)in ,3  
B5!$5 Qc  
<taglib-uri>/tutorial-template</taglib-uri> MZE8Cvq0  
HW{osav9  
<taglib-location> $CO^dFf  
KLs%{'[7:  
/WEB-INF/tutorial-template.tld p SASMc@  
K%>uSS?  
</taglib-location> bxO8q57  
)2z (l-$.  
</taglib> ow ~(k5k:  
F`U%xn,  
^l ~i>:V  
实现此tag标签 \no[>L]  
x+"~-KO8q$  
$\$5::}r  
为了实现tag标签,你有2种方法来存放tag处理类。一、让tag处理类以.class的方式存放于当前应用的WEB-INF/class子目录下,二、如果tag处理类是以JAR包的形式存在的话,那可以放在当前应用的WEB-INF/lib目录下,如果tag处理类要在多个应用中共享,那么它就应放在jsp服务器上的common/lib目录下,对于tomcat来说,就是tomcat/common/lib目录下。 C2,,+* v  
cI'&gT5  
W=o90TwbN  
tag标签类型 NZ'S~Lr   
) ]U-7  
/_?Ly$>'  
自定义的tag标签遵循XML语法。它有一个开始标记和一个结束标记,有的还有body(即文本节点): S[{#AX=0  
_;{n+i[  
<tt:tag> y_38;8ex  
h{yqNl  
body t&wtw  
rFSLTbTf  
</tt:tag> R|ViLty  
m ,)4k&d  
.3A66 O~zT  
一个不带body的tag标签如下: Ej ip%m  
7Xm pq&g  
<tt:tag /> I)]wi%  
S-npJh 6  
%s%v|HDs  
简单的tag标签 ITRv^IlF  
"ZNiTND  
一个没有body和属性的tag标签如下: o';sHa'  
"44VvpQC  
<tt:simple /> S>aN#  
u}JL*}Q  
VieC+Kk  
带属性的tag标签 T c4N\Cy  
k;R*mg*K  
g9H~\w  
自定义标签可以有自己的属性。属性一般在开始标记中定义,语法为 attr=”value”。属性的作用相当于自定义标签的一个参数,它影响着tag处理类的行为。你可以在TLD中详细定义它。 OOGqtA;  
.KGW#Qk8  
你可以用一个String常量给一个属性赋值,也可以通过表达式给它赋值,如<%= ...%>。以struts为例,它的logic:present标签就是用的String常量来给属性赋值: @U_w:Q<9u  
x1]^].#Eo  
<loglic:present parameter = “Clear”> !%_Z>a  
H ZIJKk(  
而另一个标签logic:iterate是用表达式来给属性赋值: <bWhTNOb  
@ O5-w  
<logci:iterate collection=”<%= bookDB.getBooks() %>” 0iinr:=u  
Di<KRg1W]}  
id=”book” type=”database.BookDetails”> Rgw\qOb  
!1]72%k[  
(!&cfabL  
带body的tag标签 :Oo(w%BD]  
fKf5i@CvB@  
一个自定义标签可以包含其它自定义标签、脚本变量、HTML标记或其它内容。 :;t*:iG  
@mW: FVI  
在下述例子中,此JSP页面使用了struts的logic:present标签,如果些标签定义了parameter=”Clear”的属性,则将清除购物车的内容,然后打印出一条信息: :se o0w]  
En&ESW N  
<logic:present parameter=”Clear”> GN /]^{D  
^1BQejD  
<% cart.clear(); %> ``)ys^V  
.vj`[?T  
<font color=”#ff0000” size=”+2”><strong> <- Q=h?D  
mEmznA  
你选择了清除购物车! 1D&Q{?RM  
TggM/ @k  
</strong></font> M2(+}gv;7p  
3XYCtp8  
</logic:present> ZMy0iQ@  
2i;G3"\  
k]!Fh^O~,  
到底是用属性还是用body来传递信息? ~C6d5\  
5m!FtHvm1  
如上所述,我们既可以通过属性,也可以通过body来传递信息。但一般来说,比较简单的类型,如字符串或简单表达式最好采用属性来传递信息。 H-~V:OCB~  
QM=M<~<Voh  
8 sZ~3  
定义脚本变量的tag标签 UM(tM9  
jxU1u"WU  
所谓脚本变量,是指JSP中可以调用的变量或对象。它可由tag标签产生。以下示例阐述了一个tag标签定义了一个名为tx的由JNDI所定义的事务处理对象。脚本变量可以是ejb对象、事务、数据库连接等等: Mf Dna>,Y  
TYGUB%A  
<tt:lookup id=”tx” type=”UserTransaction” name=”java:comp/UserTransaction” /> ]y>)es1  
XZLo*C!MG  
<% tx.begin(); %> Jiyt,D*wX  
dElOy?v  
... X}Bo[YoY$  
H'Bor\;[>  
ATp7:Q  
具有协作关系的tag标签 i[/g&fx  
wN\%b}pp  
自定义tag标签之间可以通过共享对象来实现协作。在下述例子中,标签tag1创建了一个名为obj1的对象,在标签tag2仍可以重复使用obj。 1O>wXq7q  
(= } cc  
<tt:tag1 attr1=”obj1” value1=”value” /> I *YO  
 h%0/j  
<tt:tag2 attr1=”obj1” /> I ugYlt  
,f8<s-y4Sg  
在以下这个例子当中,如果外层的tag标签创建了一个对象,那么其内层的所有tag标签都可以使用这个对象。由于这样产生的对象没有一个指定的名字,那么就可以将少重名的冲突。这个例子阐述了一系列协作的嵌套对象。 jFY6}WY)}7  
(lq7 ct  
<tt:outerTag> Gx ci  
\Y&*sfQ  
<tt:innerTag /> w?)v#]<-  
kNP.0  
</tt:outerTag>  17AJT  
j/`- x  
+e?mKLw14  
Tag处理类 d0$dQg  
p\T9 q  
/4J2F9:f  
Tag处理类必须实现Tag接口或BodyTag接口,不过现在一般都流行从TagSupport或BodyTagSupport类中继承,这些类或接口都可以在javax.servlet.jsp.tagext包中找到。 jX}}^XwX  
.}n,  
当JSP引擎看到自己的JSP页面中包含有tag标签时,它会调用doStartTag方法来处理tag标签的开头,调用doEndTag方法来处理tag标签的结束。 xdb9oH  
,#3u. =IR[  
下表说明不同类型的tag所需要不同的处理过程: DG,CL8bv  
-\6nT'P  
Tag处理类的方法 DFKFsu8s  
~V&4<=r`  
Tag标签类型 >Y=HP&A<  
所调用的方法 g^ZsV:D  
~WXT0-,  
基本标签 6X2>zUHR  
doStartTag, doEndTag, release "~j SG7h  
:9un6A9JS  
带属性的标签 Rj 2N+59rg  
doStartTag, doEndTag, set/getAttribute1...N, release hT4 u;3xE  
|M]#D0v  
带内容的标签 ,RIGV[u  
doStartTag, doEndTag, release u3)Oj7cX  
/+2;".  
带内容的标签,且内容重复循环 os6p1"_\f  
doStartTag, doAfterBody, doEndTag, release R|aA6} /I  
:U)>um34e  
带内容的标签,且内容与JSP交互 ^*.S7.;2o  
doStartTag, doEndTag, release, doInitBody, doAfterBody, release c&r8q]u  
4np,"^c  
一个tag处理类可以通过javax.servlet.jsp.PageContext来与JSP交互,通过javax.servlet.jsp.PageContext类,tag处理类可以访问JSP中的request、session和application对像。 ,0 +%ji^V  
H%N !;Jz=  
如果tag标签是互相嵌套的,那内层的tag处理类可以通过它的parent属性来访问上层的tag处理类。 F F<xsoZJ  
VeK^hz R^Z  
一般情况都将所有的tag处理类打成了JAR的包,以便于发布。 q] g'rO'  
q>:>f+4  
(O{5L(  
Tag库描述(简称TLD) 0I_A$Z,x  
w{uq y]  
bl@0+NiM  
Tag库是用xml语言描述的,TLD包括了tag库中所有tag标签的描述,它一般用来被jsp服务器用来校验tag的语法正确性,或者被jsp开发者用来开发新的标签。 E*VUP 5E  
#;FHyKx  
TLD的文件扩展名必须为.tld,而且必须放在当前WEB应用的WEB-INF目录或其子目录中。 <[{Ty+  
%gj's-!!  
一个TLD的内容的开头必须遵守标准的XML开头,用于描述DTD和xml的版本,例如: l%"[857  
wq &|V  
<?xml version="1.0" encoding="ISO-8859-1" ?> xbJ@z {  
8B ZTHlUB  
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd"> )=VSERs  
TLD必须以<taglib>来作为它的根元素,<taglib>的子元素如下表: ghvF%-."1  
}p-<+sFo  
]D|sQPi]F  
<taglib>的子元素 1(!w xJ  
p\lS ) 9  
Element wI'8B{[  
Description qh}M!p2  
i! G^=N  
tlib-version vqh@)B+)  
Tag库的版本 Ju5<wjQR\  
H':dLR  
jsp-version VYw vT0  
Tag库所需要的jsp的版本 i8R.Wl$l  
'VA\dpa{J  
short-name 4k'2FkDA  
助记符,tag的一个别名(可选) (ov=D7>t0  
d{_tOj$  
uri 0l#{7^e  
用于确定一个唯一的tag库 \m @8$MK  
uv*OiB"  
display-name sO7$b@"u.  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) ~F7 +R   
RFF&-M]  
small-icon v~-z["=}!  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) ow:}NI  
:ie7HF  
large-icon (WT0 j  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) J/(3: a>  
:UjHP}s  
description $<^4G  
对tag库的描述(可选) v5"5UPi-  
}\5^$[p  
listener S<^*jheO5  
参见下面listener元素 dRg1I=|{_  
n"B"Aysz  
tag "B`yk/GM]  
参见下面tag 元素 y7M"Dr%t^  
1g`$[wp|  
Listener元素 x7$U  
#5HJW[9  
一个tag库可能定义一些类做为它的事件侦听类,这些类在TLD中被称为listener 元素,jsp服务器将会实例化这些侦听类,并且注册它们。Listener元素中有一个叫listener-class的子元素,这个元素的值必须是该侦听类的完整类名。 iN%\wkx*N  
V^Wo%e7#u[  
Tag元素 <qH>[ \  
;w1?EdaO  
每个tag元素在tag库中都要指出它的名字、类名、脚本变量、tag的属性。其中脚本变量的值可以直接在TLD中定义或通过tag附加信息的类来取得。每个属性描述了这个属性是否可以省略,它的值是否可以通过<%= …%>这样的JSP语法来获得,以及属性的类型。 u?[P@_i<  
xQs2 )  
每一个tag在TLD中对应一个tag元素,下表是tag元素的子元素: (bH*i\W  
?! dp0<  
Tag元素的子元素  8.D$J  
b{H&%Jx)  
元素名称 (mXV5IM  
描述 }x % ;y]S  
RW 23lRA6  
name nIVPh99  
独一无二的元素名 Y604peUF  
+) 2c\1  
tag-class k^I4z^O=-;  
Tag标签对应的tag处理类 xy`aR< L  
%)_R>.>  
tei-class jM1|+o*Wr  
javax.servlet.jsp.tagext.TagExtraInfo的子类,用于表达脚本变量(可选) Eugt~j3  
K V ^ `  
body-content N(mhgC<O  
Tag标签body的类型 *g&[?y`UC  
MO)N0{.b  
display-name "PGEiLY  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) '/ 3..3k  
(PU0\bGA  
small-icon UMUr"-l =  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) A"`6 2  
reLYtv  
large-icon y6Xfddd61  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) Uj}iMw,  
pc}Q_~e  
description 7dI+aJ  
此tag标签的描述 k{Yj!C> #  
g<oSTA w  
variable g':mM*j&  
提供脚本变量的信息(同tei-class)(可选) <jU[&~p  
dUeM+(s1  
attribute O?NAbxkp  
Tag标签的属性名 a #?% I#  
C)`ZI8  
以下章节介绍对于不同类型的tag,如何具体地实现它们。 ?m#X";^V  
}K9Vr!  
2-nL2f!a{p  
简单的tag 2;.7c+r0  
Y cE:KRy  
F>&Q5Kl R  
tag处理类 C/%umazP9  
8m1 @l$  
简单的tag处理类必须实现Tag接口的doStartTag和doEndTag方法。当jsp引擎碰到tag标签的开头时,doStartTag被调用,因为简单的tag没有body,所以此方法将返回 SKIP_BODY。当jsp引擎碰到tag标签的结尾时,doEndTag被调用,如果余下的页面还要被计算,那它将返回EVAL_PAGE,否则将会返回SKIP_PAGE。 4%2QF F @  
DIodQkF  
以下是例子:对于标签 <tt:simple /> ,它的tag处理类实现如下: q5:-?|jXJ  
("o <D{A  
VztalwI  
public SimpleTag extends TagSupport Rj9ME,u  
<||F$t  
{ F7UY>z3jL  
h;f5@#F  
public int doStartTag() throws JspException ')I/D4v  
V| z|H$-  
{ sxJKu  
YnuC<y &p  
try{ fHYEK~!C04  
1t=Y+|vA9  
pageContext.getOut().print(“Hello.”); i}ypEp  
h>$,97EU  
}catch(Exception e){ wlBdA  
Sj(uc#  
throw new JspTagException(“SimpleTag: “ + e.getMessage()); )ruC_)  
8e)k5[\m  
} b,/fz6 {N  
WaF<qhu*  
return SKIP_BODY; c`mJrS:  
<M=U @  
} ,XCC#F(d1  
4fw>(d(2  
public int doEndTag() Xj"/6|X  
neJNMdv@T  
{ ;r>?V2,tm  
JT&CJ&#[h  
return EVAL_PAGE; 75wQH*  
c>{X( Z=2  
} 1F-o3\  
3lhXD_Y  
} Df02#493  
QkZT%!7  
|uV1S^ !A  
注意:如果tag标签没有内容的话,那必须定义body-content元素为空,例如 uNl<= 1  
8^&)A b  
<body-content>empty</body-content> ~el#pf~  
#>O,w0<qM  
(\.[pj%-O  
带属性的tag标签
评价一下你浏览此帖子的感受

精彩

感动

搞笑

开心

愤怒

无聊

灌水
级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
只看该作者 1 发表于: 2007-01-01
tag处理类 EK_NN<So#  
*58<.L|  
对于tag标签的每个属性,你必须依照JavaBeans规范来定义其属性,以及get和set方法。以struts的logic:present 标签为例, h eZJ(mR  
HB{w:  
<logic:present parameter=”Clear”> !;pmql  
7on$}=%  
与此相应,此tag处理类应有如下方法和定义: 1Ls@|   
+VDwDJ)lG  
6.~HbN  
protected String parameter = null; 8\!0yM#yK  
R}llj$?  
public String getParameter() 8<0H(lj7_  
jr~ +}|@{  
{ Y<:%_]]  
VaJX,Q  
return this.parameter; #p&iH9c_  
>*,Zc  
} D(Zux8l  
kR7IZo" q  
public void setParameter(String parameter) %<O'\&!,  
Y~dRvt0_w  
{ QB#f'X  
v+znKpE  
this.parameter = parameter; "Vho`x3  
K_Y0;!W  
} jkQv cU  
eg~$WB;1  
!-2nIY!  
注意:如果你的属性名为id,而且你的tag处理类是从TagSupport类继承的,那你就不需要定义它的属性和set和get方法,因为他们早已在TagSupport被定义过了。 %FT F  
=+T{!+|6P  
Attribute元素 ScQJsFE6  
zu(/ c  
对于tag标签的每个属性,你必须定义它是否必须的,它的值是否可以用诸如<%= …%>的表达式来获得,以及它的类型(可选),如果不指定它的类型,那就默认为是java.lang.String类型。如果rtexprvalue元素被定义为true或yes,那么在type元素中就定义了attribute的返回类型。 z[0L?~$  
8UwL%"?YB  
<attribute> !O@qqg(>  
D *Siy;  
<name>attr1</name> j +@1frp  
j,/OzVm9  
<required>true|false|yes|no</required> tQ5gmj  
<\8dh(>  
<rtexprvalue>true|false|yes|no</rtexprvalue> 1{_tV^3@  
aN ). G1  
<type>attribute的返回类型(只用当rtexprvalue为真是才有效)</type> {(o\G"\<XY  
#AyM!   
</attribute> <po.:c Ce  
j8M}*1  
如果tag的某个属性不是必须的,那tag处理类会自动提供一个缺省值。 $ n`<,;^l  
(+4gq6b  
例如,在logic:present这个tag标签中定义了一个属性叫parameter,但它不是必须的,而且它可以被诸如<%= …%>的表达式来赋值。 U;i:k%Bzy  
MM|&B`v@;  
<tag> 2[[ pd&MJZ  
(=CV")tF  
<name>present</name> _T6WA&;8  
64#~p)  
<tag-class>org.apache.struts.taglib.logic.PresentTag</tag-class> ORs<<H.d  
/_xwHiA  
<body-content>JSP</body-content> 28d:  
D4}WJMQ7s  
A{: a kK  
<uU AAHi  
<attribute> 1FjA   
{}D8Y_=9\  
<name>parameter</name> ~YlbS-  
!R//"{k0?  
<required>false</required> ZUQ1\Iw  
KG'4;Z5J  
<rtexprvalue>true</rtexprvalue> g 4=}].  
>9esZA^';  
</attribute> Fq&@dxN3  
4Mi*bN,  
Dgc[WsCEW  
K~+y<z E  
</tag> ?WG9}R[qE/  
;pU9ov4)  
wDem }uO  
属性元素的校验 jsf=S{^2  
}{ pNasAU  
+@cf@}W6QC  
有关于tag标签的有效值可以从tag库的说明文档中获得,当JSP页面被编译时,jsp引擎会强制性地参照TLD中定义的规则进行检查。 ! D'U:)  
RB\>$D  
还有一个方法也可以进行属性元素的校验,就是先继承类TagExtraInfo,然后调用它的isValid方法。这个类同时也起到提供tag中定义的脚本变量信息的作用。 j Z3N+_J1  
xRv1zHZ  
IsValid方法通过TagData对象来传递属性信息,它包括着tag的所有的属性名-值的信息。由于校验发生在运行时刻,因此这个属性的值将被赋值为TagData.REQUEST_TIME_VALUE。 xHJ+!   
A>%fE 6FY  
例如tag标签<tt:twa attr1=”value1” />在TLD中定义如下: g/lv>*+gS  
BpDf4)|  
<attribute> :?RooJ~#  
C&NoEtL>s  
<name>attr1</name> F{[2|u(4  
bV@53_)N2  
<required>true</required> cI?dvfU?  
WWrD r  
<rtexprvalue>true</rtexprvalue> _&XT =SW}  
_t:rWC"X  
</attribute> :QUZ7^u  
< hZA$.W3  
}qc[ysDK]  
这个定义说明了attr1能在运行期间被赋值。 (vz)GrH>  
^\e:j7@z  
以下的isValid方法检查attr1属性的值是否属于Boolean类型。注意由于attr1能在运行刻被赋值,那么isValid方法必须检查tag用户是否对此tag进行了运行时刻赋值。 Y_p   
}f^K}*sK$5  
[9z<*@$-  
Public class TwaTEI extends TagExtraInfo hAfRHd  
e|):%6#  
{ 6%U1%;  
I = qd\  
public boolean isValid(Tagdata data) uTbI\iq  
fyYv}z  
{ >P>.j+o/  
cw/g1,p  
Object o = data.getAttribute(“attr1”); UG Fx  
~)tMR9=wX  
If(o != null && o != TagData.REQUEST_TIME_VALUE) S?OK@UEJ  
JI3AR e?y  
{ %Q1v8l.}  
gO*cX&  
if( ( (String)o).toLowerCase().equals(“true”) || 89`AF1  
'}P)iS2  
((String)o).toLowerCase().equals(“false”) ) 67 7p9{:  
> :!faWX  
return true; ;?=nr5;q  
<C+ :hsS=  
else H<}<f:  
.3{S6#  
return false; ]=WJ%p1l  
3hO` GM  
} @`wBe#+\  
z.e%AcX  
else .{5)$w>  
 R(k6S  
return true; gBYL.^H^l  
z|+L>O-8  
} 'bY^=9&|  
45/f}kvy  
} q,aWF5m@  
Arir=q^2  
"!p#8jR^  
带body的tag eU@yw1N  
^yy\CtG  
nP 2rN_:4  
tag处理类 >^|\wy  
6}C4 SZ  
^w8H=UkP!+  
如果tag标签含有内容,那处理方式会略微有些不同,而且还要视tag处理类是否要与body交互的情况而定。如果要与body交互,那我们认为tag处理类要可能要对body进行操作。 :Q+ rEjw+  
r5lp<md  
Tag处理类不与body交互 Ip.5I!h[Xb  
>p\IC  
如果tag处理类不与body交互,tag处理类应该实现Tag接口或从TagSupport中派生,如果body要被计算,那么doStartTag方法应返回 EVAL_BODY_INCLUDE,否则应返回SKIP_BODY。 >5/dmHPc  
2?Q IK3"v  
如果tag处理类要对body反复运算,则它应该实现IterationTag或从TagSupport中派生。如果tag处理类认为body还未计算完的话,那它的doStartTag方法和doAfterBody方法必须返回EVAL_BODY_AGAIN。 :/~`"`#1  
*r:8=^C7S  
Tag处理类与body交互 MA(\ r  
wMt?yc:X  
如果tag处理类与body交互,那tag处理类应实现BodyTag接口或从BodyTagSupport中派生。这种tag处理类一般要实现doInitBody和doAfterBody方法。 <%>Q$b5  
\dIIZSN  
Body允许一些方法来读写它的内容。Tag处理类可以调用body内容的getString或getReader方法来从body中提取信息,也可用 writeOut(out) 方法来将body的内容写入到out对象中。其中out对象通过tag处理类的getPreviousOut方法来获得。 0e q>  
_m3PAD4  
如果body的内容需要被计算,那么doStartTag方法必须返回EVAL_BODY_BUFFERED,否则,它将返回 SKIP_BODY。 dMeDQ`c`W  
j,6dGb  
doInitBody 方法 yHr/i) c  
U g]6i+rp  
此方法在body内容已经设好,但未被计算之前被调用。你可以根据不同的body内容来制定初始化策略。 nt "VH5  
?h1]s&^| 2  
doAfterBody方法 #4%,09+  
ReZ|q5*  
此方法在body内容已被计算后进行调用。 pL-p  
E^A9u |x  
和doStartTag方法一样,doAfterBody方法返回一个指示符指示是否要继续计算body,如果要继续计算,则doAfterBody应返回EVAL_BODY_BUFFERED,否则,它应返回SKIP_BODY。 ThJLaNS  
:'1ePq  
release 方法 1k{ E7eL  
*ubLuC+b  
tag处理类调用此方法将它的状态重置为初始状态,并释放所有的私有资源。 ofcoNLX5c  
)3h=V^rm  
qIA!m .GC  
以下的例子读取body的内容(其中含有一条sql语句),然后将它传递给一个对象,让它进行查询。由于此处body不须重新计算,所以doAfterBody会返回SKIP_BODY。 $w+g%y)  
[FF%HRce,.  
:E4i@ O7%  
Public class QueryTag extends BodyTagSupport [7|}h/  
i @+Cr7K,  
{ (yc$W9  
2NIK0%6  
public int doAfterBody() throws JspTagException a(d'iAU8^  
H'?Bx>X  
{ kRSu6r9  
>,uof?  
BodyContent bc = getBodyContent(); Gp; [WY\  
0/{-X[z  
//将body的内容以字符串的格式提取出来 v SHb\V#  
/A|ofAr)  
String query = bc.getString(); Qs#v/r  
;&Eu< %y  
//清除body UupQ* ,dJ  
N<"_5  
bc.clearBody(); L G{N  
<JF78MD\  
try{ sl |S9Ix  
|I)xK@7  
Statement stmt = connection.createStatement(); *7BY$q  
*v l_3S5_  
Result result = stmt.executeQuery(query); rZ:  
6$fC R  
}catch(SQLException e){ r;upJbSX  
qLA  
throw new JspTagException(“queryTag: “ + e.getMessage() ); }-: d*YtK  
]$0{PBndW  
return SKIP_BODY; ;)"r^M)):  
AWD &K!  
} >=C)\Yfu)  
<(3Uu()   
} )z7. S"U  
oUltr  
hl6al:Y  
body-content元素 c?jjY4u  
ScZ$&n  
F3';oyy  
由于tag可能会有body,你必须用body-content元素来指定body内容的类型: rLh490@  
P,I3E?! j  
<body-content>JSP|tagdependent</body-content> R;I}#b cJ  
V&h ,v%$  
*DDfdn  
如果body的内容是定制的或内部的tag、脚本元素、或HTML广本,则归类为JSP类型。其他的类型,比如上面代码所述的?D?D将sql statement类传给 query tag的这种类型应该标为tagdependent。 D!qtb6<.  
RDzL@xCcn  
注意:实际上body-content的值并不影响tag处理类对body内容的处理,它仅仅是被tag编辑工具用来描述此body的内容。 >%Y.X38Z[  
Og30&a!~F  
Pbm ;@ V  
用tags定义脚本变量 bTHJbpt*-  
`Bkba:  
e<iTU?eJM  
tag处理类 FY#`]124*  
F^A1'J  
(:-DuUt  
tag处理类负责创建或设置页面中定义的脚本变量,用pageContext.setAttribute(name,value,scope)或pageContext.setAttribute(name,value)方法来实现。一般来说,tag处理类通过脚本变量的名称来获取它,脚本变量的名称一般可用get方法来获得。 "]zq<LmX  
,,fLK1  
如果脚本变量的值依赖于tag处理类中的上下文中某一对象,那它可用pageContext.getAttribute(name,scope)方法来找到那个对象。一般的处理过程是tag处理类先找到脚本变量,再对其进行处理,然后用pageContext.setAttribute(name,object)的方法来设置它的新值。 Pvbw>k;  
b*P \a  
对象的生存周期(scope)如下表: ag|d_;  
K{q(/>:  
对象的生存周期表  ^B1vvb  
k E6\G}zj  
名字 BtU,1`El5  
可访问范围 6JK;]Ah  
生存周期 aL#b8dCy'  
Fo~C,@/Qt  
page Ij#%Qu  
当前页面 ~a/yLI"'g  
一直有效,除非页面向客户提交响应或重定向到一个新页面 Kq-y1h]7H  
/91H! s  
request Y`lC4*g  
当前页面或当前页面重定向到的页面 Hb!Q}V+Kb8  
一直有效,除非页面向客户提交响应 W=F?+Kg L  
x%cKTpDh!  
session w5qhKu!1  
当前页面或在同一浏览器窗口中的页面 u@==Ut  
一直有效,除非关闭当前浏览器、超时、网络故障 Y;-"Z  
RsTpjY*Xb  
application f"k/j?e*  
整个web应用程序的所有请求 i$%;z~#wW  
一直有效,除非发生网络故障、服务器故障 |6_<4lmTxF  
}=XL^a|V  
提供关于脚本变量的信息 K")-P9I6-f  
n6|}^O7  
以下示例定义了一个名为“book”的脚本变量,用来访问程序中关于书的信息: mRQ F5W6  
=_ -@1 1a  
<bean:define id=”book” name=”bookDB” property=”bookDetails” type=”database.BookDetails” /> xA&G91|s  
H Qf[T@  
<font color=”red” size=”+2” > {H"gp?Z-  
+twBFhS7k  
<%= messages.getString(“CartRemoved”) %> [Hn+r &  
?P"ht  
<strong><jsp:getProperty name=”book” property=”title” /></strong> y1k""75  
N;Hf7K  
</font> D5AKOM!`  
J5|Dduv  
当包含此tag的JSP页面被编译时,jsp引擎会自动生成关于此book的同步的代码(同步可以避免几个客户同时访问此book时造成的冲突),要生成同步代码,jsp引擎需要知道此脚本变量的如下信息: d/R:-{J)c  
Zu~ #d)l3N  
· 脚本变量名称 )O2^?Q quS  
-*?a*q/#nQ  
· 脚本变量所属的类 vQBfT% &Q-  
/l:3* u  
· 此脚本变量是否引用了一个新的或已存在的对象 HC!$Z`}Y  
= @ph  
· 此脚本变量的有效性 oleRQ=  
3R4-MK  
有两种办法可以向jsp引擎提供关于脚本变量的信息:在TLD中定义variable子元素,或用tei-class子元素定义一个额外tag信息类。用variable最简单,但可能降低了一些灵活性。 ;=UrIA@y;=  
I?F^c6M=  
Variable元素 of{wZU\J+9  
rBgLj,/`U/  
Variable元素有如下子元素: ;O{AYF?,N  
=;@5Ue J  
· name-given ?D?D 给出的名字,是一个常量  299; N  
c#CX~  
· name-from-attribute?D?D 属性名,在编译时给出的属性名 !7 *X{D v  
LZ\}Kgi(!T  
name-given或name-from-attribute两者必须选一,但以下子元素是可选的: E;-R<X5n  
UXIq>[2Z1  
· variable-class?D?D变量的类型,缺省为java.lang.String。 _CI!7%  
6S`eN\s  
· declare?D?D此脚本变量是否引用了一个新对象,缺省为True。 %)q5hB  
N],A&}30  
· scope?D?D脚本变量的范围,缺省为NESTED。下表描述了scope的几种类型: }tj@*n_  
JNX7]j\  
脚本变量的有效范围 G4<'G c  
dc%+f  
9>%f99n  
有效性 s "*Cb*  
方法 WW==  
LD^V="d  
NESTED P8;|>OLZ)  
在tag标签的开始和结束之间 u-jGv| ,|  
如果tag处理类实现BodyTag接口,则在doInitBody和doAfterBody中调用,否则在doStartTag中调用 >`s2s@Mx  
3G5i+9Nt.L  
AT_BEGIN z@<`]  
从tag标签的开始一直到页面结束 M;3uG/E\  
如果tag处理类实现BodyTag接口,则在doInitBody、doAfterBody和doEndTag中调用,否则在doStartTag和doEndTag中调用 #^Sd r-   
)v ['p  
AT_END =b !f  
从tag标签的结束一直到页面结束 ^*}L9Ot~  
在doEndTag中调用 ]j_S2lt  
UY)YhXW  
以struts为例,它的bean:define标签的实现遵循JSP1.1规范,此规范要求使用额外tag信息类来定义脚本变量。Variable元素是JSP1.2规范中加入的。以bean:define标签为例,你可以定义如下variable元素: hQl3F6-ud  
9\Yj`,i5  
<tag> WR~uy|mX  
3haY{CEr  
<variable> LFg<j1Gk`  
rD<@$KpP  
<name-from-attribute>id</name-from-attribute> yuKfhg7  
O!/J2SfuDH  
<variable-class>database.BookDetails</variable-class> E: XzX Fxx  
[/5>)HK} C  
<declare>true</declare> N:gS]OI*  
t{84ioJ"$  
<scope>AT_BEGIN</scope> QGLfZvTT  
k)y0V:ZY]O  
</variable> 9[$g;}w  
,:;nq>;  
</tag> DB%=/ \U  
oPre$YT}h  
额外tag信息类 Ep?a1&b  
sV3/8W13  
如果要定义一个额外tag信息类,你要继承javax.servlet.jsp.TagExtraInfo类。一个TagExtraInfo类必须实现getVariableInfo方法,此方法返回一个叫VariableInfo的数组类,它包括如下信息: "o[\Aec:  
%2/WyD$U  
· 变量名 0g`WRe  
V^?+|8_(  
· 变量所属类名 97$y,a{6  
%&e5i  
· 此变量是否引用了一个新对象 WY<ip<  
% J+'7'g  
· 此变量的有效范围 Vs9fAAXS4  
SU H^]4>  
jsp引擎将一个名为data的参数传给getVariableInfo方法,data中包括tag标签中的所有“属性名?D?D属性值”对。它可以用来向VariableInfo对象提供脚本变量的名字和类名。 8!:4m"Y  
^@L  
以struts为例,它在bean:define标签中定义了一个名为DefineTei的额外tag信息类,用来向脚本变量提供信息。由于脚本变量的名称(book)和类名(database.BookDetails)是通过tag标签的属性来传递的,它们一般定义在VariableInfo的构建代码中,并且可用data.getAttributeString方法来得到这些信息。如果要允许book脚本变量能在从tag开始直到整个JSP页面结束的范围内都可用的话,那它的范围应设为AT_BEGIN。如下所示: qYbod+UX  
I#$u(2.H  
5_=&U-? H  
public class DefineTei extends TagExtraInfo bjD0y cB[  
HHg=:>L z  
{ q]'VVlP)  
pMs%`j#T  
public VariableInfo[] getVariableInfo(TagData data) S{ fNeK  
dd98v Vj  
{ E%/E%9-7\  
?WUu@Z  
String type = data.getAttributeString(“type”); ( 8H "'  
nFxogCn   
If( type == null) Z$6W)~;,  
@GjWeOj]  
type = “java.lang.Object”; *:GoS?Ma  
&w LI:x5  
return new VariableInfo[] { k('2K2P  
Pm" ,7  
new VariableInfo(data.getAttributeString(“id”), 5n?fZ?6(  
_gw~A {O  
type, MF%9  
K$f~Fft  
true, J#'c+\B<2X  
K<\TF+  
VariableInfo.AT_BEGIN) ,X9Y/S l  
YzEa?F*$  
}; l_QpPo!a  
FnL~8otPF'  
} lD 9'^J  
C 5)G^  
} OG}0{?  
IsnC_"f  
>&Bg F*mm  
注意:关于额外tag信息类的类名必须要在TLD中的tag标签下的tei-class子元素中定义。因此,DefineTei的tei-class中的定义看起来如下: wGb{O  
<tei-class> |)GE7y0Q  
org.apache.struts.taglib.bean.DefineTagTei qmJFXnf  
</tei-class> fa"eyBO50  
+| Cvv]Tx1  
/5zzzaj {  
具有协作关系的tag rK)%n!Z  
0( /eSmet  
h:j-Xd$H+  
tag通过共享对象来进行协作,JSP技术支持2种方式的对象共享。 q$U;\Mg)  
K;S&91V)=  
第一种方法是使用pageContext对象进行对象的共享(可支持JSP页面和tag处理类之间的共享),如果在一个tag处理类中要调用由另一个tag处理类创建的对象,可调用pageContext.getAttribute(name, scope)方法。 8fZ\})t  
Ml0d^l}'  
第二各方式的共享是对于tag之间有嵌套关系而言的,外层的tag所创建的对象对于内层的tag来说是可以共用的。这种形式的共享的好处是减少了可能存在的重名冲突。 2u#{K9g  
=cqaA^HQL  
要访问一个嵌套tag创建的对象,tag处理类必须先找到此嵌套tag对象,可用TagSupport的静态方法 TagSupport.findAncestorWithClass(from, class)或TagSupport.getParent方法。前者在当不确定此tag是否为嵌套tag对象时使用。一旦它的父类被找到,它就能访问其所有动态或静态创建的对象。静态创建的对象是父类的成员,而动态创建的对象可能是父类的私有对象。诸如此类的对象可以用tag处理类的setValue方法来保存,用getValue方法来获得。 .KK"KO5k  
&W|'rA'r  
下例阐述了以上两种共享对象的方法。在这个例子当中,一个查询tag检查一个名为connection的属性名是否在doStartTag中被设置。如果connection属性被设置,tag处理类从pageContext中得到这个connection对象。否则,此tag处理类先找到它的父tag处理类,然后从它的父tag处理类中找到connection对象。 .6  
ilpg()  
Vv6xVX  
public class QueryTag extends BodyTagSupport $mp7IZE|  
jZ.+b j >  
{ CbK7="48  
]Jv Z:'g}  
private String connectionId; kZf7  
$F\&?B1.  
public int doStartTag() throws JspException Tcr&{S&o  
e#&[4tQF  
{ qfN<w&P  
9$S2:2(G  
String cid = getConnection(); ~5]AXi'e~  
@WFjM  
if(cid != null) `4Nc(aUr  
b\H(Lq17  
{ WV?iYX!  
-hhE`Y  
//存在一个connection id,使用它。 zXZy:SD  
{TUCa  
connection = (Connection) pageContext.getAttribute(cid); s7df<dBC  
;#f_e;  
} h :NHReMT  
_VR4 |)1g  
else x7{,4js  
} vcr71u  
{ 8>O'_6Joj  
:UFf6T?  
ConnectionTag ancestorTag = (ConnectionTag)findAncestorWithClass(this, |%zhwDQ.  
@RT yCr  
ConnectionTag.class); T /[)U  
Zj`eR\7~  
if(ancestorTag == null) V<ODt%  
o&I 0*~ sN  
{ 5Ko "-  
Oi l>bv8  
throw new JspTagException(“一个没有connection属性的查询标签必须被一个connection标记嵌套。”); ]l+2Ca:-[j  
uiHlaMf  
} | b@?]M  
S7N54X2JwL  
connection = ancestorTag.getConnection(); vs6`oW"{#  
/[{?zS{  
} QHtpCNTVb  
kC LeHH|K  
} KHF5Nt  
Z < uwqA  
} i-niRu<  
:5@7z9 >  
<NS= <'U  
Z/Mp=273  
此查询标签在JSP页面中的调用形式可以从以下2种定义中任选一种: bh+R9~  
#9 } Oqm  
FVF: 1DT  
<tt:connection id=”con01” ...> ... </tt:connection> XUMCz7&j  
D8Ni=.ALL  
<tt:query id=”balances” connection=”con01” > eZ  ]6 Q  
q{KRM\ooYs  
SELECT account, balance FROM acct_table _#N~$   
cH2 nG:H  
where customer_num = <%= request.getCustno() %> \a|gzC1G  
8U\ +b?}  
</tt:query> D(Xv shQ  
a&Z|3+ZA  
+8 6\&y)  
@6t3Us~/  
Of:e6N  
<tt:connection ...> ugMJ}IGq  
QW~o+N~~  
<x:query id=”balances”> CsuSg*#X+  
a?+) K  
SELECT account, balance FROM acct_table ,[cWG)-  
FIG5]u  
where customer_num = <%= request.getCustno() %> YZ*Si3L   
p&ow\A O  
</x:query> ^!kv gm<{$  
b[BSUdCB  
</tt:connection> drb_GT  
@&h<jM{D  
eeL%Yp3+  
与此同时,在TLD中必须指定connection属性为可选的,定义如下: L6Ynid.k  
UbMcXH8=F  
<tag> 4H\O&pSS  
U ][.ioc  
... }Pw5*duq  
5i1>z{  
<attribute> [a+?z6qI\}  
R` X$@iM  
<name>connection</name> [ >vS+G  
$xloB  
<required>false</required> /Ee0S8!Z!1  
]JhtO{  
</attribute> VN$#y4  
M{nz~W80  
</tag>
描述
快速回复

您目前还是游客,请 登录注册
欢迎提供真实交流,考虑发帖者的感受
认证码:
验证问题:
10+5=?,请输入中文答案:十五