社区应用 最新帖子 精华区 社区服务 会员列表 统计排行 社区论坛任务 迷你宠物
  • 3521阅读
  • 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%cfJe_k  
H$@5\pP>  
一般来说,自定义tag标签主要用于操作隐藏对象、处理html提交表单、访问数据库或其它企业级的服务,诸如邮件和目录操作等等。自定义tag标签的使用者一般都是那些对java编程语言非常精通,而且对数据访问和企业级服务访问都非常熟悉的程序员,对于HTML设计者来说,使得他可以不去关注那些较复杂的商业逻辑,而将精力放在网页设计上。同时,它也将库开发者和库使用者进行合理分工,自定义tag标签将那些重复工作进行封装,从而大大提高了生产力,而且可以使得tag库可用于不同的项目中,完美地体现了软件复用的思想。 \]:}lVtxS  
hXAgT!ZD  
在这篇文章中,我们主要讨论: v0aV>-v  
H\>0jr `  
· 什么是自定义tag标签? "r+v^  
T"bH{|:%*=  
· 怎么使用tag标签? bmid;X|  
fen~k#|l  
o 声明要使用的tag库 +VSq[P  
o[A y2"e?  
o 找到与之对应的tag处理类 /r8'stRzv  
og?>Q i Tr  
o tag标签的类型 -22]|$f  
W{El^')F  
· 自定义tag标签 ',_E;(  
Tr6J+hS  
o tag处理类 n%Rl$  
$~;h}I  
o tag库描述 )'1rZb5  
1H-d<G0)  
o tag标签示例 n)<S5P?  
uY_vX\;67z  
o 带属性的tag nt:d,H<p  
L vPcH  
o 带body的tag w;OvZo|  
yIq. m=  
o 定义了脚本变量的tag  %"jp':  
&^7^7:Y=?  
o 具有协作关系的tag Yk^clCB{A(  
prdc}~J8{  
· 自定义tag标签 lSG"c+iV  
sw\O\%^  
o 一个迭代tag的例子 rYK GBo8"  
W'xJh0o  
o 一个模板tag库 #Fwf]{J  
*.,G;EC^  
o tag处理类到底是怎样被调用的? pYBY"r  
<E&8g[x6  
f(*ygI  
什么是自定义的tag? VpO+52&  
\RF{ITV$kD  
一个自定义的tag标签是用户定义的一种JSP标记。当一个含有自定义的tag标签的JSP页面被jsp引擎编译成servlet时,tag标签被转化成了对一个称为tag处理类的对象进行的操作。于是当JSP页面被jsp引擎转化为servlet后,实际上tag标签被转化成为了对tag处理类的操作。 j3Yz=bsQ{c  
;1MRBk,  
自定义tag标签有很多特色,诸如: |19zjhl  
C f(g  
· 可以在JSP页面中自定义tag标签的属性 dI%#cf1  
S|Yz5)*  
· 访问JSP页面中的所有对象 vmGGdj5aI  
a W9_[#z5  
· 可以动态地修改页面输出 nYb{?{_ca8  
+ e3{J_  
· 彼此这间可以相互通信。你可以先创建一个JavaBeans组件,然后在一个tag中调用此JavaBeans组件,同时可以在另一个tag中调用它。 n85d g  
DGJt$o=&@  
· tag允许相互嵌套,可以在一个JSP页面中完成一些复杂的交互。 |Bhj L,  
05ZF>`g*  
8WP|cF]  
使用tag标签 6>d0i S@R  
Hs#q 7  
U3tA"X.K  
本节主要描述怎样在JSP页面中使用tag标签,以及tag标签的不同类型。 S2\|bs7;J,  
&_o.:SL|  
要使用tag标签,JSP程序员必须做2件事: [dIlt"2fV  
*RllKPY)  
· 声明此tag标签的tag库 GE!fh1[[u  
q(s&2|  
· 实现此tag标签 KmX?W/%R  
xsERnF>`  
声明tag标签所在的tag库 >g+e`!;6  
2 )F~  
如果要使用tag标签,则应用JSP的taglib指示符来指定其tag库(注意:taglib要在在使用此tag标签之前声明) EG#mNpxE  
A>Y#-e;<d  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> #\T5r*W  
!?aL_{7J  
uri属性定义了唯一的标签库描述(以下简称TLD),它可以是直接是tld文件名或一个独一无二的名字。prefix是用来区别其它TLD中和本TLD中有重名的tag的一种手段。  K?]c  
'\wZKY VN  
TLD必须以.tld作为扩展名,并且存放在当前应用的WEB-INF目录或其子目录下。你可以通过它的文件名直接引用它,也可以通过别的方式间接地引用它。 hhr!FQ.+/  
2JR$  
以下taglib指示符直接引用一个TLD: d) $B  
k.6gX<T  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> o/\f+iz7  
5)=YTUCk  
以下的taglib指示符通过一个逻辑名称间接地引用一个TLD: x&d:V  
&fRZaq'2R  
<%@ taglib uri=”/tutorial-template” prefix=”tt” %> *t_JR  
:(TOtrK@  
如果是间接引用TLD的话,那你必须还要在web.xml中定义此逻辑名称与tld文件之间的映射,具体做法是在web.xml中加入一个名为taglib的元素: ZQN%!2  
N#&/d nV  
<taglib> J5#shs[M:  
[eLU}4v{  
<taglib-uri>/tutorial-template</taglib-uri> Z` zyE P A  
\sc's7  
<taglib-location> >mCS`D8  
#,jw! HO]  
/WEB-INF/tutorial-template.tld i7jI(VvB^  
l|" SM6  
</taglib-location> /DE`>eJY  
e .(  
</taglib> 1MYA/l$  
TO]7%aB  
zi?G wh~  
实现此tag标签 F- l!i/  
=g^k$ Rc  
\Pt_5.bTs[  
为了实现tag标签,你有2种方法来存放tag处理类。一、让tag处理类以.class的方式存放于当前应用的WEB-INF/class子目录下,二、如果tag处理类是以JAR包的形式存在的话,那可以放在当前应用的WEB-INF/lib目录下,如果tag处理类要在多个应用中共享,那么它就应放在jsp服务器上的common/lib目录下,对于tomcat来说,就是tomcat/common/lib目录下。 P~9y}7Q\0  
'nP;IuMP  
9*CJWS;  
tag标签类型 9 lH00n+'  
3aERfIJyE  
C|g]Y 7  
自定义的tag标签遵循XML语法。它有一个开始标记和一个结束标记,有的还有body(即文本节点): )mh,F# "L  
Nu4PY@m]C  
<tt:tag> ]S0sjN  
3v,Bg4[i  
body ?L(y8b}F(  
T(q/$p&q  
</tt:tag> f~Ve7   
?3; 0 SAh  
>,A&(\rO  
一个不带body的tag标签如下: e;r?g67  
(>M@Ukam:  
<tt:tag /> sV$Zf `X)  
bU{lV<R,  
`S:LuU8e  
简单的tag标签 F&)(G\  
~7O.}RP0  
一个没有body和属性的tag标签如下: g"|/^G_6S  
4) z*Vux  
<tt:simple /> /;V:<mekf  
_d*QA{  
jrLV\(p  
带属性的tag标签 0s o27k  
t(r}jU=qw  
vI5'npM  
自定义标签可以有自己的属性。属性一般在开始标记中定义,语法为 attr=”value”。属性的作用相当于自定义标签的一个参数,它影响着tag处理类的行为。你可以在TLD中详细定义它。 Tp&7CNl|  
%C =?Xhnv  
你可以用一个String常量给一个属性赋值,也可以通过表达式给它赋值,如<%= ...%>。以struts为例,它的logic:present标签就是用的String常量来给属性赋值: /PTk296@  
=BVBCh  
<loglic:present parameter = “Clear”> } U_z XuUz  
mgI7zJX  
而另一个标签logic:iterate是用表达式来给属性赋值: _eg&j  
Og/@w&  
<logci:iterate collection=”<%= bookDB.getBooks() %>” .EdQ]c-E=  
<}n"gk1is  
id=”book” type=”database.BookDetails”> \\v1 \  
54>gr1B  
z z2'h>  
带body的tag标签 &!0%"4  
ZK$<"z6{  
一个自定义标签可以包含其它自定义标签、脚本变量、HTML标记或其它内容。 {/Qg4pc!  
Rpou.RrXR7  
在下述例子中,此JSP页面使用了struts的logic:present标签,如果些标签定义了parameter=”Clear”的属性,则将清除购物车的内容,然后打印出一条信息: )I(2t 6i  
&p83X  
<logic:present parameter=”Clear”> #:M <<gk  
D?`|`Mu  
<% cart.clear(); %> !6pE0(V^+4  
1qN+AT  
<font color=”#ff0000” size=”+2”><strong> W_Eur,/`  
w+G+&ak<  
你选择了清除购物车! Fh U*mAX)  
WLA LXJ7  
</strong></font> atYe$Db  
m=Fk  
</logic:present> _6Qb 3tl  
(\*+HZ`(Uu  
?r/)s()ALf  
到底是用属性还是用body来传递信息? U%H6jVE  
SioP`*,}  
如上所述,我们既可以通过属性,也可以通过body来传递信息。但一般来说,比较简单的类型,如字符串或简单表达式最好采用属性来传递信息。 Msl8o c  
tEjT$`6hp  
G{4lgkyy  
定义脚本变量的tag标签 p?e-`xs  
C)qy=lx%  
所谓脚本变量,是指JSP中可以调用的变量或对象。它可由tag标签产生。以下示例阐述了一个tag标签定义了一个名为tx的由JNDI所定义的事务处理对象。脚本变量可以是ejb对象、事务、数据库连接等等: HqoCl  
dH_g:ocA  
<tt:lookup id=”tx” type=”UserTransaction” name=”java:comp/UserTransaction” /> 3}gf %U]L  
g#s hd~e  
<% tx.begin(); %> z=pGu_`2  
! w2BD^V-  
...  >Q% FW  
^Y?Y5`! Q  
Ew>lk9La(  
具有协作关系的tag标签 $4u8"ne)  
=+"=|cQ  
自定义tag标签之间可以通过共享对象来实现协作。在下述例子中,标签tag1创建了一个名为obj1的对象,在标签tag2仍可以重复使用obj。 K3-Cuku  
AroYDR,3+  
<tt:tag1 attr1=”obj1” value1=”value” /> |Wz`#<t  
CaqqH`/E4  
<tt:tag2 attr1=”obj1” /> Gf\u%S!%  
8}>s{u;W  
在以下这个例子当中,如果外层的tag标签创建了一个对象,那么其内层的所有tag标签都可以使用这个对象。由于这样产生的对象没有一个指定的名字,那么就可以将少重名的冲突。这个例子阐述了一系列协作的嵌套对象。 6 TSC7jO  
1/<Z6 ?U  
<tt:outerTag> p$_X\,F  
t;L7H E@Y  
<tt:innerTag /> EU4j'1!&g<  
.g52p+Z#  
</tt:outerTag> a`_w9r+v  
d8% sGH  
qfa[KD)!aB  
Tag处理类 zelM}/d  
x A"V!8C  
^gdv:[ m  
Tag处理类必须实现Tag接口或BodyTag接口,不过现在一般都流行从TagSupport或BodyTagSupport类中继承,这些类或接口都可以在javax.servlet.jsp.tagext包中找到。 7 ?a!x$-U(  
bXRSKp[$  
当JSP引擎看到自己的JSP页面中包含有tag标签时,它会调用doStartTag方法来处理tag标签的开头,调用doEndTag方法来处理tag标签的结束。 >@uFye$  
B0$.oavC  
下表说明不同类型的tag所需要不同的处理过程: k.Q4oyei  
Kl]LnN%A{  
Tag处理类的方法 /\ u1q<  
8G?OZ47k#  
Tag标签类型 _ Y8j l,J  
所调用的方法 J*m ~fZ^  
l$DQkbOj  
基本标签 R~H+.Vh  
doStartTag, doEndTag, release y7/=-~   
CN!~(1v  
带属性的标签 H0?Vq8I?  
doStartTag, doEndTag, set/getAttribute1...N, release BX-fV|  
>%i]p  
带内容的标签 NK$BF(HBi  
doStartTag, doEndTag, release =At)?A9[  
\oy8)o/Gb  
带内容的标签,且内容重复循环 0S$6j-"  
doStartTag, doAfterBody, doEndTag, release TT3\c,cs  
`z~L0h  
带内容的标签,且内容与JSP交互 r(DW,xoK0  
doStartTag, doEndTag, release, doInitBody, doAfterBody, release `PI?RU[g*  
f}uW(:f  
一个tag处理类可以通过javax.servlet.jsp.PageContext来与JSP交互,通过javax.servlet.jsp.PageContext类,tag处理类可以访问JSP中的request、session和application对像。 Lu9`(+  
zIy&gOX  
如果tag标签是互相嵌套的,那内层的tag处理类可以通过它的parent属性来访问上层的tag处理类。 Rs;Y|W4'  
I.hy"y2&  
一般情况都将所有的tag处理类打成了JAR的包,以便于发布。 B f"L;L  
S7f"\[Aw  
j5V{,lf  
Tag库描述(简称TLD) WdJJt2'  
EJaGz\\  
s]Qo'q2  
Tag库是用xml语言描述的,TLD包括了tag库中所有tag标签的描述,它一般用来被jsp服务器用来校验tag的语法正确性,或者被jsp开发者用来开发新的标签。 {RHa1wc  
= sh3&8  
TLD的文件扩展名必须为.tld,而且必须放在当前WEB应用的WEB-INF目录或其子目录中。 ~xU\%@I\  
Be~In~~  
一个TLD的内容的开头必须遵守标准的XML开头,用于描述DTD和xml的版本,例如: [[' (,,r  
dz=pL$C  
<?xml version="1.0" encoding="ISO-8859-1" ?> meArS*d  
;Wedj\Kkp  
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd"> erdA ?  
TLD必须以<taglib>来作为它的根元素,<taglib>的子元素如下表: #v}pn2g%>  
+5qY*$dn  
EVW\Z 2N.  
<taglib>的子元素 2b^E8+r9  
~U<=SyZYo  
Element WIYWql>*  
Description xa$4P [  
B)=)@h[f  
tlib-version + 3c (CTz  
Tag库的版本 I,@ 6w  
Tjj-8cg  
jsp-version O 2W2&vY  
Tag库所需要的jsp的版本 R-OQ(]<*  
7p[NuU*Gg  
short-name :?f^D,w_B  
助记符,tag的一个别名(可选) )2: ,E  
~__rI-/_  
uri ).8NZ Aj  
用于确定一个唯一的tag库 /5"RedP<  
NXSjN~aG2  
display-name [J +5  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) MD>xRs   
KU 98"b5  
small-icon 'QQa :3<x  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) DQ9}( '^  
z(Q 5?+P  
large-icon mae@L  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) \.Z /  
n7(/ml+Q_  
description ?#Y1E~N  
对tag库的描述(可选) u -A_l<K  
wrAcVR  
listener bD<hzOa  
参见下面listener元素 P`OZoI$bV  
K?eY<L  
tag L)9uBdF  
参见下面tag 元素 ((T6z$:hA  
9a0|iy  
Listener元素 UaXWHCm`  
X{tfF!+iy  
一个tag库可能定义一些类做为它的事件侦听类,这些类在TLD中被称为listener 元素,jsp服务器将会实例化这些侦听类,并且注册它们。Listener元素中有一个叫listener-class的子元素,这个元素的值必须是该侦听类的完整类名。 rL|9Xru  
.9@y*_ 9  
Tag元素 !;E{D  
&Rt^G  
每个tag元素在tag库中都要指出它的名字、类名、脚本变量、tag的属性。其中脚本变量的值可以直接在TLD中定义或通过tag附加信息的类来取得。每个属性描述了这个属性是否可以省略,它的值是否可以通过<%= …%>这样的JSP语法来获得,以及属性的类型。 6@-O#,]J  
LZ z]4Mf  
每一个tag在TLD中对应一个tag元素,下表是tag元素的子元素: v{oHC4  
r;SOAucX  
Tag元素的子元素 uL |O<  
8om)A0S  
元素名称 |DLmMsS4  
描述 Oz-@e%8L  
j71RlS73  
name }E#1Z\)  
独一无二的元素名 g^[BnP)I  
b{a\j%  
tag-class > 8%O;3-m#  
Tag标签对应的tag处理类 _l=X?/  
Uu~~-5  
tei-class Nbd[xs-lw  
javax.servlet.jsp.tagext.TagExtraInfo的子类,用于表达脚本变量(可选) {)PgN  
"HtaJVp//  
body-content 1R"Z+tNB  
Tag标签body的类型 (\H^ KEy  
 wkKSL  
display-name /TY=ig1z  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) x bD]EC  
DvY)n<U1qA  
small-icon hGb SN_F  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) G!E1N(%o  
FZx.Yuv  
large-icon q" @%WK  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) T0"q,lrdxV  
,"?xy-6  
description  |Fe*t  
此tag标签的描述 Huf;A1.  
:ioD  *k  
variable AYv7- !Yk  
提供脚本变量的信息(同tei-class)(可选) Ypwn@?xeP  
]:.9:RmEV  
attribute x\5v^$  
Tag标签的属性名 %s ">:  
@o>3 Bv.  
以下章节介绍对于不同类型的tag,如何具体地实现它们。 #PQhgli  
cXbQ  
z9JZV`dNgz  
简单的tag _[,7DA.qc  
X1o=rT  
1ZO/R%[  
tag处理类 >j)y7DSE  
Mi047-% (  
简单的tag处理类必须实现Tag接口的doStartTag和doEndTag方法。当jsp引擎碰到tag标签的开头时,doStartTag被调用,因为简单的tag没有body,所以此方法将返回 SKIP_BODY。当jsp引擎碰到tag标签的结尾时,doEndTag被调用,如果余下的页面还要被计算,那它将返回EVAL_PAGE,否则将会返回SKIP_PAGE。 z?  Ck9  
7',WLuD  
以下是例子:对于标签 <tt:simple /> ,它的tag处理类实现如下: . H9a  
FQM9>l@6)>  
jf=\\*64r4  
public SimpleTag extends TagSupport "z4V@gk   
'wVi>{?  
{ t)hi j&wzu  
A>%mJ3M  
public int doStartTag() throws JspException \?"p]&2UcB  
='Yg^:n  
{ |'](zEwq  
MS;^@>|wj  
try{ u1ahAk7  
U:uF rb,  
pageContext.getOut().print(“Hello.”); =DwY-Ex  
}Apn.DYbbf  
}catch(Exception e){ 6-QcHJ>m6U  
r=S,/N(1  
throw new JspTagException(“SimpleTag: “ + e.getMessage()); 4rUOk"li  
,P^4??' o  
} r>g5_"FL  
e@{Rlz   
return SKIP_BODY; Y?\PU{ O  
Un Ocw  
} *H~&hs>k  
3M5wF6nY[[  
public int doEndTag()  I}u&iV`  
qkBCI,X_Y  
{ GuKiNYI_  
`NCH^)  
return EVAL_PAGE; J }|6m9k!  
i=jY l  
} @.} @K  
m.Ki4NUm  
} t^"8 v3'h  
Zty9O8g  
23/;W|   
注意:如果tag标签没有内容的话,那必须定义body-content元素为空,例如 naVbcY  
HM &"2c  
<body-content>empty</body-content> 3|=L1Pw#  
c+501's  
i!yE#zew  
带属性的tag标签
评价一下你浏览此帖子的感受

精彩

感动

搞笑

开心

愤怒

无聊

灌水
级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
只看该作者 1 发表于: 2007-01-01
tag处理类 z oZ10?ojC  
ei(S&u<  
对于tag标签的每个属性,你必须依照JavaBeans规范来定义其属性,以及get和set方法。以struts的logic:present 标签为例, iJS7g  
kY{;(b3Q  
<logic:present parameter=”Clear”> \ `R8s_S  
Fb6d1I^wR  
与此相应,此tag处理类应有如下方法和定义: rDv`E^\  
=b#:j:r  
sBLOrbo  
protected String parameter = null; {'yr)(:2M  
+P<#6<gR  
public String getParameter() 8~AL+*hn  
! =*k+gpF  
{ t]E@AJO K  
009Q#[A  
return this.parameter; 3EH7H W  
2yV^'o)  
} P4fnBH4OQ  
mI5!rrRD|  
public void setParameter(String parameter) PxA OKUpI  
+#9 4 X)*  
{ 2YK2t<EO  
+!)_[ zo  
this.parameter = parameter; 1AQy 8n*  
}#6~/ W  
} i':a|#e>  
6N[X:F 3`,  
fWyXy%Qq  
注意:如果你的属性名为id,而且你的tag处理类是从TagSupport类继承的,那你就不需要定义它的属性和set和get方法,因为他们早已在TagSupport被定义过了。 h)Ol1[y`  
zBc |gx  
Attribute元素 U04&z 91"  
W0<2*7s  
对于tag标签的每个属性,你必须定义它是否必须的,它的值是否可以用诸如<%= …%>的表达式来获得,以及它的类型(可选),如果不指定它的类型,那就默认为是java.lang.String类型。如果rtexprvalue元素被定义为true或yes,那么在type元素中就定义了attribute的返回类型。  vUR gR  
Xn02p,,  
<attribute> 6pbtE]  
9ePom'1f1  
<name>attr1</name> 77-G*PI*I  
>L433qR  
<required>true|false|yes|no</required> ~.CmiG.7  
k|^`0~E  
<rtexprvalue>true|false|yes|no</rtexprvalue> 5]K2to)>`  
0<+eN8od.  
<type>attribute的返回类型(只用当rtexprvalue为真是才有效)</type> G\K!7k`)!  
Nka 3H7 `  
</attribute> XrI$@e*  
~~q>]4>  
如果tag的某个属性不是必须的,那tag处理类会自动提供一个缺省值。 38GZ_ z}r  
WZ=$c]gG  
例如,在logic:present这个tag标签中定义了一个属性叫parameter,但它不是必须的,而且它可以被诸如<%= …%>的表达式来赋值。 ._q<~_~R  
0cq<!{d  
<tag> 9-!GYa'Z  
ZE9.r`  
<name>present</name> "O~kIT?/v  
-t: U4r(  
<tag-class>org.apache.struts.taglib.logic.PresentTag</tag-class> "[0.a\ d<  
q@1xYz:J  
<body-content>JSP</body-content> <GLn!~Px@5  
.-)kIFMi  
iXL?ic  
nO#x "  
<attribute> e-#V s{?|r  
/@&#U bN\  
<name>parameter</name> |,tKw4  
&0]5zQ  
<required>false</required> vRH2[{KQ9  
qB3E  
<rtexprvalue>true</rtexprvalue> *MQ`&;Qa,  
`1uGU[{x  
</attribute> ] !n3j=*   
Pbt7T Q  
IyAD>Q^  
@M"( r"ab  
</tag> :*s@L2D6  
D 9UM8Hxi  
k 7:Z\RGy  
属性元素的校验 U+zntB  
V[n,fEPBr  
J$lfI^^  
有关于tag标签的有效值可以从tag库的说明文档中获得,当JSP页面被编译时,jsp引擎会强制性地参照TLD中定义的规则进行检查。 %M:$ML6b<  
fk!9` p'  
还有一个方法也可以进行属性元素的校验,就是先继承类TagExtraInfo,然后调用它的isValid方法。这个类同时也起到提供tag中定义的脚本变量信息的作用。 sG\K$GP!  
sKk+^.K}|  
IsValid方法通过TagData对象来传递属性信息,它包括着tag的所有的属性名-值的信息。由于校验发生在运行时刻,因此这个属性的值将被赋值为TagData.REQUEST_TIME_VALUE。 *K BaKS  
<v=s:^;C0  
例如tag标签<tt:twa attr1=”value1” />在TLD中定义如下: p(nEcu  
y+KAL{AGK  
<attribute> uW2  q\  
yCN?kHG  
<name>attr1</name> ^?*<.rsG  
1 J}ML}h)  
<required>true</required> s+(@UUl  
vM50H  
<rtexprvalue>true</rtexprvalue> [LO=k|&R  
i.\ e/9]f  
</attribute> iB`EJftI!  
v0?SN>fZ  
vmh>|N4a7  
这个定义说明了attr1能在运行期间被赋值。 3gnO)"$  
3W{ !\  
以下的isValid方法检查attr1属性的值是否属于Boolean类型。注意由于attr1能在运行刻被赋值,那么isValid方法必须检查tag用户是否对此tag进行了运行时刻赋值。 nLx|$=W  
6OoOkNWF  
6b9J3~d\E  
Public class TwaTEI extends TagExtraInfo a$Hq<~46  
~+ 9v z  
{ * eX/Z Cn  
Ubgn^+AI  
public boolean isValid(Tagdata data) wJ7^)tTRF  
+bT[lJ2O>G  
{ (L yKo  
$x,EPRNs  
Object o = data.getAttribute(“attr1”); ,HI% ym  
Io[NN aF|  
If(o != null && o != TagData.REQUEST_TIME_VALUE) _GrifGU\  
:wG )  
{ kdp^{zW}  
#Ge_3^'  
if( ( (String)o).toLowerCase().equals(“true”) || i,S1|R  
^bP`Iv  
((String)o).toLowerCase().equals(“false”) ) y#th&YC_b  
1z4_QZZ.NG  
return true; -y{(h% 6  
pb)kN%  
else gS8+S\2  
~X3x- nAt  
return false; v1Q 78P  
w`=O '0d  
} n1PBpM9!  
k61mRO  
else ZhoV,/\+  
 !Q*w]  
return true; xVgm 9s$"c  
]:b52Z  
} b*H*(}A6"'  
\KzJNCOT  
} +I3O/=)  
kD?@nx>  
P|Gwt&  
带body的tag V1pBKr)v  
.g1x$cQ1<  
6q>}M  
tag处理类 &9|L Z9K  
:`Ut.E~.  
,.}%\GhY  
如果tag标签含有内容,那处理方式会略微有些不同,而且还要视tag处理类是否要与body交互的情况而定。如果要与body交互,那我们认为tag处理类要可能要对body进行操作。 j/fniyJ)  
%ek0NBE7  
Tag处理类不与body交互 fGqX dlP  
AI|+*amTd  
如果tag处理类不与body交互,tag处理类应该实现Tag接口或从TagSupport中派生,如果body要被计算,那么doStartTag方法应返回 EVAL_BODY_INCLUDE,否则应返回SKIP_BODY。 p$qk\efv*4  
W`NF40)  
如果tag处理类要对body反复运算,则它应该实现IterationTag或从TagSupport中派生。如果tag处理类认为body还未计算完的话,那它的doStartTag方法和doAfterBody方法必须返回EVAL_BODY_AGAIN。 <oV[[wl  
EwkSUA>Tm  
Tag处理类与body交互 ^+v1[U@  
^m&I^ \  
如果tag处理类与body交互,那tag处理类应实现BodyTag接口或从BodyTagSupport中派生。这种tag处理类一般要实现doInitBody和doAfterBody方法。 :8hI3]9  
Rb.vyQ  
Body允许一些方法来读写它的内容。Tag处理类可以调用body内容的getString或getReader方法来从body中提取信息,也可用 writeOut(out) 方法来将body的内容写入到out对象中。其中out对象通过tag处理类的getPreviousOut方法来获得。 }z$_!)/i  
dR;N3KwY  
如果body的内容需要被计算,那么doStartTag方法必须返回EVAL_BODY_BUFFERED,否则,它将返回 SKIP_BODY。 4d cm)Xr  
E}v8Q~A(  
doInitBody 方法 } Z FoCMM  
sZT~ 5c8  
此方法在body内容已经设好,但未被计算之前被调用。你可以根据不同的body内容来制定初始化策略。 'Grii,  
ge:a{L  
doAfterBody方法 2[HPU M2>  
GK!@|Kk8q7  
此方法在body内容已被计算后进行调用。 6<$.Z-,  
oBo*<6  
和doStartTag方法一样,doAfterBody方法返回一个指示符指示是否要继续计算body,如果要继续计算,则doAfterBody应返回EVAL_BODY_BUFFERED,否则,它应返回SKIP_BODY。 x\(#  
[P =P8-5  
release 方法 d}':7Np  
MP)Prl>  
tag处理类调用此方法将它的状态重置为初始状态,并释放所有的私有资源。 ()bQmNqmO=  
u~ipB*Zf  
aHmg!s}&  
以下的例子读取body的内容(其中含有一条sql语句),然后将它传递给一个对象,让它进行查询。由于此处body不须重新计算,所以doAfterBody会返回SKIP_BODY。 7QNx*8p  
X:$vP'B>  
Fa[^D~$l*  
Public class QueryTag extends BodyTagSupport )Uy%iE*  
!Q15qvRS  
{ t!*[nfR  
1n[)({OQ  
public int doAfterBody() throws JspTagException :PW"7|c!  
8=TC 3]  
{ \fiy[W/k  
/51$o\4 S  
BodyContent bc = getBodyContent(); kN Ll|in@  
6QCV i  
//将body的内容以字符串的格式提取出来 W"\}##  
6j XDLI  
String query = bc.getString(); #~)A#~4O  
_.Hj:nFHz  
//清除body `;+x\0@<  
kSzap+nB?  
bc.clearBody(); GEF's#YWK  
j?m(l,YD|*  
try{ /MY's&D(  
vj%"x/TP  
Statement stmt = connection.createStatement(); #e-K It  
QK[^G6TI  
Result result = stmt.executeQuery(query); \}v@!PQl  
q i yK  
}catch(SQLException e){ O>qlWPht  
41<h|WA  
throw new JspTagException(“queryTag: “ + e.getMessage() ); z$R&u=J  
;mQ|+|F6X  
return SKIP_BODY; ))f@9m  
g:ky;-G8b  
} -0kMh.JYR  
pxgf%P<7  
} R}gdN-941  
\efDY[j/  
L?+N:G  
body-content元素 K~,!IU_QG  
J<"K`|F  
5>.ATfAsV  
由于tag可能会有body,你必须用body-content元素来指定body内容的类型: Ie/_gz^  
<<u]WsW{C  
<body-content>JSP|tagdependent</body-content> (m:Q'4Ep  
) hs&?: )  
\tYImh  
如果body的内容是定制的或内部的tag、脚本元素、或HTML广本,则归类为JSP类型。其他的类型,比如上面代码所述的?D?D将sql statement类传给 query tag的这种类型应该标为tagdependent。 jq%<Z,rh  
H\oxj,+N  
注意:实际上body-content的值并不影响tag处理类对body内容的处理,它仅仅是被tag编辑工具用来描述此body的内容。 ]jxyaE&%4  
~*/ >8R(Y  
@i!+Z  
用tags定义脚本变量 <Y7j'n  
/~u^@@.  
@3KSoA"^  
tag处理类 )VkVZf | S  
6Q7=6  
nt$P A(Y  
tag处理类负责创建或设置页面中定义的脚本变量,用pageContext.setAttribute(name,value,scope)或pageContext.setAttribute(name,value)方法来实现。一般来说,tag处理类通过脚本变量的名称来获取它,脚本变量的名称一般可用get方法来获得。 En9J7es_  
,$:u^;V(  
如果脚本变量的值依赖于tag处理类中的上下文中某一对象,那它可用pageContext.getAttribute(name,scope)方法来找到那个对象。一般的处理过程是tag处理类先找到脚本变量,再对其进行处理,然后用pageContext.setAttribute(name,object)的方法来设置它的新值。 k- 9i  
:XFQ}Cl  
对象的生存周期(scope)如下表: LF!KP  
\O"H#gt  
对象的生存周期表 y,`n9[$K\  
= K}Pfh  
名字 PL&> p M  
可访问范围 pLCj"D).M  
生存周期 j!i* &  
8xAIn>,_  
page oQ r.cKD ?  
当前页面 STjb2t,a  
一直有效,除非页面向客户提交响应或重定向到一个新页面 d.~ns4bt9  
A?#i{R  
request xjbI1qCfe  
当前页面或当前页面重定向到的页面 9 nc_$H{  
一直有效,除非页面向客户提交响应 H"? 5]!p  
#;a+)~3*O  
session c=\_[G(  
当前页面或在同一浏览器窗口中的页面 wi7Br&bGi  
一直有效,除非关闭当前浏览器、超时、网络故障 #~-Xt! I  
*W\3cS  
application qfl!>  
整个web应用程序的所有请求 KJoa^e;~  
一直有效,除非发生网络故障、服务器故障 hbJy<e1W  
=t-Ud^3  
提供关于脚本变量的信息 !9 kNL  
|OF3O,5z  
以下示例定义了一个名为“book”的脚本变量,用来访问程序中关于书的信息: #oTVfY#  
"KK}} $>  
<bean:define id=”book” name=”bookDB” property=”bookDetails” type=”database.BookDetails” /> ,H"}Rw  
1q!k#Cliu  
<font color=”red” size=”+2” > 1$03:ve1  
J' P:SC1  
<%= messages.getString(“CartRemoved”) %> k 6[   
YU-wE';H6  
<strong><jsp:getProperty name=”book” property=”title” /></strong> Tx K v!-1  
6jc5B#  
</font> #Y7iJPO  
1$E[`` n  
当包含此tag的JSP页面被编译时,jsp引擎会自动生成关于此book的同步的代码(同步可以避免几个客户同时访问此book时造成的冲突),要生成同步代码,jsp引擎需要知道此脚本变量的如下信息: /]z #V'  
Fz(;Eo3  
· 脚本变量名称 N\ Mdia  
4h!yh2c..  
· 脚本变量所属的类 A,EG0yb  
n$SL"iezW?  
· 此脚本变量是否引用了一个新的或已存在的对象 2EpQ(G J  
h )Y .jY  
· 此脚本变量的有效性 y|O3*`&m  
T DR|*Cs  
有两种办法可以向jsp引擎提供关于脚本变量的信息:在TLD中定义variable子元素,或用tei-class子元素定义一个额外tag信息类。用variable最简单,但可能降低了一些灵活性。 Q3l>xh  
V)~b+D  
Variable元素 Z1q<) O1QX  
!%t@wQ]\hG  
Variable元素有如下子元素: =p[Sd*d  
%IVM1  
· name-given ?D?D 给出的名字,是一个常量 Xk%eU>d  
vo }4N[]Sb  
· name-from-attribute?D?D 属性名,在编译时给出的属性名 o'$-  
.jP|b~  
name-given或name-from-attribute两者必须选一,但以下子元素是可选的: P??P"^hU  
Vbp@n  
· variable-class?D?D变量的类型,缺省为java.lang.String。 .$cX:"_Mk  
n%36a(] t  
· declare?D?D此脚本变量是否引用了一个新对象,缺省为True。 <(Ar[Rp  
2 oL$I(83  
· scope?D?D脚本变量的范围,缺省为NESTED。下表描述了scope的几种类型: C<a&]dN/  
&?QKWxN  
脚本变量的有效范围 IxWi>8  
*y<eK0  
'j'6x'[> ]  
有效性 THOYx :Nr;  
方法 .{t5_,P  
jNX6Ct?  
NESTED W7|nc,i0\  
在tag标签的开始和结束之间 _X?_|!;J  
如果tag处理类实现BodyTag接口,则在doInitBody和doAfterBody中调用,否则在doStartTag中调用 [^a7l$fmi  
#B?lU"f8q^  
AT_BEGIN Adiw@q1&  
从tag标签的开始一直到页面结束 |qQ6>IZ  
如果tag处理类实现BodyTag接口,则在doInitBody、doAfterBody和doEndTag中调用,否则在doStartTag和doEndTag中调用 '@KH@~OzRS  
Dj=$Q44  
AT_END ]]r ;}$  
从tag标签的结束一直到页面结束 j-/$e,xX  
在doEndTag中调用 uYlyU~M:D  
|4/rVj"  
以struts为例,它的bean:define标签的实现遵循JSP1.1规范,此规范要求使用额外tag信息类来定义脚本变量。Variable元素是JSP1.2规范中加入的。以bean:define标签为例,你可以定义如下variable元素:  rwSR  
P*;[&Nn4  
<tag> 9wfE^E1  
?Mo)&,__  
<variable> F# 9^RA)9  
ZGh6- /  
<name-from-attribute>id</name-from-attribute> ;>ml@@Z  
#o~C0`8!B=  
<variable-class>database.BookDetails</variable-class> %?V~7tHm>  
_M8'~$Sg  
<declare>true</declare> EVqqOp1$v4  
au=@]n#<(  
<scope>AT_BEGIN</scope> )xU+M{p-os  
6X'0 T}  
</variable> 7fWZ/;p  
8H};pu2  
</tag> |ul{d|  
% mPv1$FH  
额外tag信息类 'e<8j  
FU*q9s`  
如果要定义一个额外tag信息类,你要继承javax.servlet.jsp.TagExtraInfo类。一个TagExtraInfo类必须实现getVariableInfo方法,此方法返回一个叫VariableInfo的数组类,它包括如下信息: PQ_A^95  
AwuhF PG  
· 变量名 w#BT/6W&G  
OD Ry  
· 变量所属类名 2H8\P+  
-0`n(`2  
· 此变量是否引用了一个新对象 er BerbEEH  
Y evd h<  
· 此变量的有效范围 *@@dO_%6  
"-:g.x*d  
jsp引擎将一个名为data的参数传给getVariableInfo方法,data中包括tag标签中的所有“属性名?D?D属性值”对。它可以用来向VariableInfo对象提供脚本变量的名字和类名。 j)ln"u0R^B  
"tJ[M  
以struts为例,它在bean:define标签中定义了一个名为DefineTei的额外tag信息类,用来向脚本变量提供信息。由于脚本变量的名称(book)和类名(database.BookDetails)是通过tag标签的属性来传递的,它们一般定义在VariableInfo的构建代码中,并且可用data.getAttributeString方法来得到这些信息。如果要允许book脚本变量能在从tag开始直到整个JSP页面结束的范围内都可用的话,那它的范围应设为AT_BEGIN。如下所示: t}}Ti$$>  
~S~+'V,d  
@6!Myez'  
public class DefineTei extends TagExtraInfo ryz NM3  
iSOyp\E|  
{ _XT;   
2Gj)fMK38  
public VariableInfo[] getVariableInfo(TagData data) _@)-#7  
^u90N>Dvq  
{ p/LV^TQ  
GHi'ek<?^  
String type = data.getAttributeString(“type”); @+Nf@LJ  
fY =:geB  
If( type == null) fO#nSB/ 8  
:! $+dr(d  
type = “java.lang.Object”; #Ddo` >`&  
/Trbr]lWy  
return new VariableInfo[] { 7&jq  =  
3TV4|&W;  
new VariableInfo(data.getAttributeString(“id”), D\J.6W  
x<w-j[{k_K  
type, 6e.l# c!1}  
l*CCnqE  
true, h{\S'8  
hfc~HKLC  
VariableInfo.AT_BEGIN) =?]S8cth  
][//G|9  
}; ;2 ?fz@KZ  
XCyb[(4  
} m#_M"B.cm  
L"c.15\  
} e^;:iJS  
E}0g  
1jBIi  
注意:关于额外tag信息类的类名必须要在TLD中的tag标签下的tei-class子元素中定义。因此,DefineTei的tei-class中的定义看起来如下: Xyz/CZPi  
<tei-class> e*I92  
org.apache.struts.taglib.bean.DefineTagTei iW9  
</tei-class> 5TeGdfu @  
\v{HjqVkC  
QAl4w)F  
具有协作关系的tag 6N Ogi  
mL#$8wUdt{  
/c!^(5K fT  
tag通过共享对象来进行协作,JSP技术支持2种方式的对象共享。 <dXeP/1w`  
I+3=|Ve f  
第一种方法是使用pageContext对象进行对象的共享(可支持JSP页面和tag处理类之间的共享),如果在一个tag处理类中要调用由另一个tag处理类创建的对象,可调用pageContext.getAttribute(name, scope)方法。 fX\y/C  
e:N;Jx#  
第二各方式的共享是对于tag之间有嵌套关系而言的,外层的tag所创建的对象对于内层的tag来说是可以共用的。这种形式的共享的好处是减少了可能存在的重名冲突。 |RXXj[z  
o1{3[=G  
要访问一个嵌套tag创建的对象,tag处理类必须先找到此嵌套tag对象,可用TagSupport的静态方法 TagSupport.findAncestorWithClass(from, class)或TagSupport.getParent方法。前者在当不确定此tag是否为嵌套tag对象时使用。一旦它的父类被找到,它就能访问其所有动态或静态创建的对象。静态创建的对象是父类的成员,而动态创建的对象可能是父类的私有对象。诸如此类的对象可以用tag处理类的setValue方法来保存,用getValue方法来获得。 ;/ |tU o$  
psiuoYf  
下例阐述了以上两种共享对象的方法。在这个例子当中,一个查询tag检查一个名为connection的属性名是否在doStartTag中被设置。如果connection属性被设置,tag处理类从pageContext中得到这个connection对象。否则,此tag处理类先找到它的父tag处理类,然后从它的父tag处理类中找到connection对象。 heWQPM|s  
IZQ*D)  
n8\88d  
public class QueryTag extends BodyTagSupport K2v[_a~@  
?-0, x|ul  
{ qrZ3`@C4k  
d|W=_7 z  
private String connectionId; ,E%O_:}R  
@S5HMJ2=  
public int doStartTag() throws JspException *].qm g%  
j]-_kjt  
{ P_p\OK*l]o  
hc9 ON&L\>  
String cid = getConnection(); jWvi% I qi  
xd"+ &YT  
if(cid != null) N<Ym&$xR  
L0{ [L  
{ (?GW/pLK]  
$i!r> .Jo  
//存在一个connection id,使用它。 S$40nM  
7dE.\#6r  
connection = (Connection) pageContext.getAttribute(cid); ![I|hB  
DV>;sCMJ %  
} LU@1Gol  
f+)LVT8p  
else '9Q#%E!*  
rmWs o b  
{ CQ{{J{pU"  
JIYzk]Tj  
ConnectionTag ancestorTag = (ConnectionTag)findAncestorWithClass(this, 68<W6z  
_sL;E<)y(  
ConnectionTag.class); U(OkTJxv+  
7@k3-?q  
if(ancestorTag == null) G-:7,9  
7>0/$i#'Vl  
{ n`jG[{3t&  
6T_Ya)  
throw new JspTagException(“一个没有connection属性的查询标签必须被一个connection标记嵌套。”); cc1M9kVi  
0$=U\[og  
} +n%8*F&  
sK/ymEfRv  
connection = ancestorTag.getConnection(); FGm!|iI  
TnKOr~@*  
} hOFvM&$  
>r}?v3QW  
} }!|$;3t+c  
>@-. rkd(  
} J!3;\  
hl)jE 06  
XW^Pz (  
,I]]52+?4  
此查询标签在JSP页面中的调用形式可以从以下2种定义中任选一种: tqpi{e  
0G Q8} r  
2#/sIu-L  
<tt:connection id=”con01” ...> ... </tt:connection> X(8LhsP  
iO18FfM_  
<tt:query id=”balances” connection=”con01” > -r~9'aEs  
Lm1JiP s d  
SELECT account, balance FROM acct_table eIf-7S]m  
,[dvs&-*  
where customer_num = <%= request.getCustno() %> Dk2Zl  
~,8#\]xR  
</tt:query> q@ wX=  
kK:Wr&X0H  
E7w^A  
. _Jypk8  
cbzS7q<)  
<tt:connection ...> C}L2'l,  
@$%.iQ7A;  
<x:query id=”balances”> yOP$~L#TWs  
0&\71txrzg  
SELECT account, balance FROM acct_table DPmY_[OAE  
.vi0DuD6  
where customer_num = <%= request.getCustno() %> ^4Se=Hr z2  
uFlf#t =  
</x:query> :C0)[L  
yB{1&S5 C  
</tt:connection> nhZ/^`Y<  
PTXS8e4  
/_8nZVu  
与此同时,在TLD中必须指定connection属性为可选的,定义如下: m?8o\|i,  
;l < amB  
<tag> *o(bB!q"c  
CEzdH!nP  
... f^IB:e#j;  
Q+_z*  
<attribute> !u4eI0?R?  
mGmZ}H'{  
<name>connection</name> "W9z>ezp  
^![7X'!;pt  
<required>false</required> ^ 6Yt2Bhs  
VrhHcvnZ  
</attribute> I9#l2<DYlX  
t47;X}y f  
</tag>
描述
快速回复

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