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

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

级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
标准的JSP 标记可以调用JavaBeans组件或者执行客户的请求,这大大降低了JSP开发的复杂度和维护量。JSP技术也允许你自定义taglib,其实换句话说,taglib可以看成是对JSP标记的一种扩展,正如xml是对html的一种扩展一样。taglib通常定义在tag标签库中,这种标签库存放着你自己定义的tag标签。简而言之,如果使用taglib,那么你可以设计自己的JSP标记! 79s6U^vv"  
W ;P1T"*A  
一般来说,自定义tag标签主要用于操作隐藏对象、处理html提交表单、访问数据库或其它企业级的服务,诸如邮件和目录操作等等。自定义tag标签的使用者一般都是那些对java编程语言非常精通,而且对数据访问和企业级服务访问都非常熟悉的程序员,对于HTML设计者来说,使得他可以不去关注那些较复杂的商业逻辑,而将精力放在网页设计上。同时,它也将库开发者和库使用者进行合理分工,自定义tag标签将那些重复工作进行封装,从而大大提高了生产力,而且可以使得tag库可用于不同的项目中,完美地体现了软件复用的思想。 j+Y4>fL$  
u5H#(&Om  
在这篇文章中,我们主要讨论: }<2F]UuR  
\S=!la_T@m  
· 什么是自定义tag标签? SjtGU47$!  
>u*woNw(XM  
· 怎么使用tag标签? d=oOMXYa   
I%e7:cs>  
o 声明要使用的tag库 JV36@DVQ  
c5;YKON  
o 找到与之对应的tag处理类 cuq7eMG6z  
i_`YZ7Hxp  
o tag标签的类型 DECX18D  
/ v5Pk.!o  
· 自定义tag标签 7KRc^ *pZs  
~e 6yaX8S  
o tag处理类 t<ftEJU"'w  
S/~6%uJ  
o tag库描述 r;|Bc$P  
~1|sf8  
o tag标签示例 C;dA?Es>R  
sx*1D9s_  
o 带属性的tag Jgtv ia  
2mu~hJ  
o 带body的tag n\,TW&3  
wS``Q8K+dM  
o 定义了脚本变量的tag ~q4DePVE  
*VHBTO9  
o 具有协作关系的tag 4TwU0N+>  
_q6+]  
· 自定义tag标签 ua|qL!L+  
h,FP,w;G  
o 一个迭代tag的例子 +}mj6I  
6Wc eDY  
o 一个模板tag库 j"94hWb  
4fzq C)  
o tag处理类到底是怎样被调用的? xBgf)'W_Z  
2-j|q6m5  
Qi=rhN`  
什么是自定义的tag? M?[lpH3  
R&ou4Y:DG  
一个自定义的tag标签是用户定义的一种JSP标记。当一个含有自定义的tag标签的JSP页面被jsp引擎编译成servlet时,tag标签被转化成了对一个称为tag处理类的对象进行的操作。于是当JSP页面被jsp引擎转化为servlet后,实际上tag标签被转化成为了对tag处理类的操作。 lmH!I )5  
rt^z#2$  
自定义tag标签有很多特色,诸如: *ivbk /8  
Zr}`W \  
· 可以在JSP页面中自定义tag标签的属性 ,J}lyvkd  
M8KfC!  
· 访问JSP页面中的所有对象 / sH*if  
Sw5H+!  
· 可以动态地修改页面输出 lz{>c.Ll[  
1 _5[5K^  
· 彼此这间可以相互通信。你可以先创建一个JavaBeans组件,然后在一个tag中调用此JavaBeans组件,同时可以在另一个tag中调用它。 C>T6{$xkC  
!~ -^s  
· tag允许相互嵌套,可以在一个JSP页面中完成一些复杂的交互。 x-tA {_:  
v|{*y  
X){F^1CT{  
使用tag标签 et9 c<'  
hp,T(D|  
HoRLy*nU  
本节主要描述怎样在JSP页面中使用tag标签,以及tag标签的不同类型。 2mU}"gf[  
7DOAG[gH  
要使用tag标签,JSP程序员必须做2件事: Z: T4Z}4N  
,l0s(Cg  
· 声明此tag标签的tag库 GExG1n-  
5Qy,P kje  
· 实现此tag标签 f1=8I_>=  
* +OAc `8  
声明tag标签所在的tag库 XJ?@l3D:  
+Kf::[wP7  
如果要使用tag标签,则应用JSP的taglib指示符来指定其tag库(注意:taglib要在在使用此tag标签之前声明) J,7_5V@jJ  
a#uJzYB0  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> 1"v;w!uh  
i3e|j(Gs4  
uri属性定义了唯一的标签库描述(以下简称TLD),它可以是直接是tld文件名或一个独一无二的名字。prefix是用来区别其它TLD中和本TLD中有重名的tag的一种手段。 *,'"\n  
t8?+yG;  
TLD必须以.tld作为扩展名,并且存放在当前应用的WEB-INF目录或其子目录下。你可以通过它的文件名直接引用它,也可以通过别的方式间接地引用它。 []dRDe;#  
QtN0|q{af  
以下taglib指示符直接引用一个TLD: 3>L1}zyM]  
L {B#x@9tQ  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> 'kx{0J?  
!%Z1" FDm/  
以下的taglib指示符通过一个逻辑名称间接地引用一个TLD: /f# rN_4  
U]R7=  
<%@ taglib uri=”/tutorial-template” prefix=”tt” %> *Gu=O|Mm  
E"L'm0i[[  
如果是间接引用TLD的话,那你必须还要在web.xml中定义此逻辑名称与tld文件之间的映射,具体做法是在web.xml中加入一个名为taglib的元素: :-6_X<  
@F3d9t-  
<taglib> .S?,%4v%%  
|?g2k:fzB7  
<taglib-uri>/tutorial-template</taglib-uri> BwEL\*$g  
8\I(a]kM`  
<taglib-location> N#[/h96F  
JBoo7a1  
/WEB-INF/tutorial-template.tld <n6/np!  
}:jXl!:V  
</taglib-location> ZT^PL3j+  
[Xz7.<0#U  
</taglib> Mm/GI a  
O$&p<~  
n"dT^ g  
实现此tag标签 V).M\  
.pdgRjlSn  
?^"S%Vb  
为了实现tag标签,你有2种方法来存放tag处理类。一、让tag处理类以.class的方式存放于当前应用的WEB-INF/class子目录下,二、如果tag处理类是以JAR包的形式存在的话,那可以放在当前应用的WEB-INF/lib目录下,如果tag处理类要在多个应用中共享,那么它就应放在jsp服务器上的common/lib目录下,对于tomcat来说,就是tomcat/common/lib目录下。 7gJy xQ  
0;XnNz3&  
/1OhW>W3eH  
tag标签类型 c69C=WQ  
~z< ? Wh  
SnXYq 7`t  
自定义的tag标签遵循XML语法。它有一个开始标记和一个结束标记,有的还有body(即文本节点): F[?t"d  
DH 9?~|  
<tt:tag> KRXe\Sx  
g8qN+Gg  
body l7x%G@1#~W  
Y: byb68  
</tt:tag> eA+6-'qN  
0&mz'xra  
Zmp ^!|=X!  
一个不带body的tag标签如下: 5 |>jz `  
> 5 i8 %r  
<tt:tag /> 5k\61(*s  
kwyvd`J8  
^T<<F}@q  
简单的tag标签 #K4wO!d  
6'Lij&,f?{  
一个没有body和属性的tag标签如下: 7M$>'PfO  
T %cN(0 @  
<tt:simple /> i^gzl_!  
|5FyfDaFBX  
^(6.M\Q  
带属性的tag标签 ml3]CcKn  
/#Xz+#SqY  
9wI1/>  
自定义标签可以有自己的属性。属性一般在开始标记中定义,语法为 attr=”value”。属性的作用相当于自定义标签的一个参数,它影响着tag处理类的行为。你可以在TLD中详细定义它。 RWoa'lnu  
C"F(kgL  
你可以用一个String常量给一个属性赋值,也可以通过表达式给它赋值,如<%= ...%>。以struts为例,它的logic:present标签就是用的String常量来给属性赋值: 8<g5.$xyz  
#cmj?y()  
<loglic:present parameter = “Clear”> 7,(:vjIXd  
].Et&v  
而另一个标签logic:iterate是用表达式来给属性赋值: \?GMtM,  
3-Ti'xM  
<logci:iterate collection=”<%= bookDB.getBooks() %>” 7%?A0%>6G  
y t<K!=7&  
id=”book” type=”database.BookDetails”> ^ 5UIbA(  
Qb SX'mx<  
c5t?S@b  
带body的tag标签 "0]i4d1l  
V= .'Db2D  
一个自定义标签可以包含其它自定义标签、脚本变量、HTML标记或其它内容。 W{0<ro`  
D vK}UAj=  
在下述例子中,此JSP页面使用了struts的logic:present标签,如果些标签定义了parameter=”Clear”的属性,则将清除购物车的内容,然后打印出一条信息: r<~1:/F|  
av5lgv)3  
<logic:present parameter=”Clear”> PVU(R J  
{j^}"8GB  
<% cart.clear(); %> D&]SPhX  
hZyz5aZ)K  
<font color=”#ff0000” size=”+2”><strong> 9cj:'KG)!  
>Ks|yNJ  
你选择了清除购物车! #|gt(p]C  
S(rA96n  
</strong></font> hsVWD,w  
3|@Ske1%Y  
</logic:present> pET5BMxGG  
<)"Mi}Q[)p  
gE:qMs;  
到底是用属性还是用body来传递信息? v'DL >Y  
8Y&(o-R0  
如上所述,我们既可以通过属性,也可以通过body来传递信息。但一般来说,比较简单的类型,如字符串或简单表达式最好采用属性来传递信息。 $_<,bC1[  
QZd ,GY5{  
{ \Q'eL8  
定义脚本变量的tag标签 k.rZj|7 L  
A3h[VnuG,  
所谓脚本变量,是指JSP中可以调用的变量或对象。它可由tag标签产生。以下示例阐述了一个tag标签定义了一个名为tx的由JNDI所定义的事务处理对象。脚本变量可以是ejb对象、事务、数据库连接等等: 3g} ]nj:N  
}9@ ,EEhg  
<tt:lookup id=”tx” type=”UserTransaction” name=”java:comp/UserTransaction” /> }t]CDa_n  
s K s D  
<% tx.begin(); %> /<M08ze  
>0u4>=#  
... \5O4}sm$*  
:}j{NM#  
J;G+6C$:  
具有协作关系的tag标签 zf6k%  
:,:r  
自定义tag标签之间可以通过共享对象来实现协作。在下述例子中,标签tag1创建了一个名为obj1的对象,在标签tag2仍可以重复使用obj。 ` NcWy  
7]G3yt->  
<tt:tag1 attr1=”obj1” value1=”value” /> iGm[fxQ|  
+]Ydf^rF  
<tt:tag2 attr1=”obj1” /> NbfV6$jo  
*R8q)Q  
在以下这个例子当中,如果外层的tag标签创建了一个对象,那么其内层的所有tag标签都可以使用这个对象。由于这样产生的对象没有一个指定的名字,那么就可以将少重名的冲突。这个例子阐述了一系列协作的嵌套对象。 qM]eK\q 1  
up`!r;5-  
<tt:outerTag> /Wk\ 6  
LUJKR6oT{>  
<tt:innerTag /> l*/I ; a$  
@@_f''f$  
</tt:outerTag> {3!v<CY'  
\~U8<z  
JZN'U<R  
Tag处理类 >H?8?a D  
rsA K0R+  
%?R}sUo  
Tag处理类必须实现Tag接口或BodyTag接口,不过现在一般都流行从TagSupport或BodyTagSupport类中继承,这些类或接口都可以在javax.servlet.jsp.tagext包中找到。 ZOfyy E  
IU/dY`J1  
当JSP引擎看到自己的JSP页面中包含有tag标签时,它会调用doStartTag方法来处理tag标签的开头,调用doEndTag方法来处理tag标签的结束。 pT.iQ J|  
c`AtK s)u  
下表说明不同类型的tag所需要不同的处理过程: @)|62Dv /  
b`fPP{mG  
Tag处理类的方法 X> =`{JS1  
B&`#`]  
Tag标签类型 dz&8$(f,  
所调用的方法 i5q VQo  
&+d>xy\^/  
基本标签 ojUBa/  
doStartTag, doEndTag, release K`768 %q  
9UZKL@KC  
带属性的标签 R/xeC [r  
doStartTag, doEndTag, set/getAttribute1...N, release %fo+Y+t  
U,~\}$<I  
带内容的标签 gI<TfcC  
doStartTag, doEndTag, release 5fA<I _ D  
h /@G[5E  
带内容的标签,且内容重复循环 k*[["u^u]  
doStartTag, doAfterBody, doEndTag, release Kbrb;r59  
E9YR *P4$  
带内容的标签,且内容与JSP交互 |fOQm  
doStartTag, doEndTag, release, doInitBody, doAfterBody, release {-09,Q4[&  
IXe[JL:  
一个tag处理类可以通过javax.servlet.jsp.PageContext来与JSP交互,通过javax.servlet.jsp.PageContext类,tag处理类可以访问JSP中的request、session和application对像。 j"9bt GX  
uL\ B[<:  
如果tag标签是互相嵌套的,那内层的tag处理类可以通过它的parent属性来访问上层的tag处理类。 r|:i: ii  
SBg BZm}%  
一般情况都将所有的tag处理类打成了JAR的包,以便于发布。 3g`uLA X>u  
D:/^TEib  
I|@%|sTW  
Tag库描述(简称TLD) >/Gz*.  
8lg $]  
Zchs/C 9{  
Tag库是用xml语言描述的,TLD包括了tag库中所有tag标签的描述,它一般用来被jsp服务器用来校验tag的语法正确性,或者被jsp开发者用来开发新的标签。 2X!O '  
&2d^=fih  
TLD的文件扩展名必须为.tld,而且必须放在当前WEB应用的WEB-INF目录或其子目录中。 K}L-$B*i  
`rN,*kcP  
一个TLD的内容的开头必须遵守标准的XML开头,用于描述DTD和xml的版本,例如: I>B-[QEC  
# 4L[8(+V  
<?xml version="1.0" encoding="ISO-8859-1" ?> yn)K1f^  
O=?WI  
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd"> d dkh*[  
TLD必须以<taglib>来作为它的根元素,<taglib>的子元素如下表: D4$;jz,,  
?<STt 9  
4#1[i|:M  
<taglib>的子元素 MuQyHEDF  
uckag/tv  
Element yF8 av=<{  
Description K*xqQ]&  
LJt#c+]Li  
tlib-version q;3.pRw(  
Tag库的版本 N0,wT6.  
*/;[ -9  
jsp-version F#*vJb)  
Tag库所需要的jsp的版本 *$1M= $  
%QCh#v=ks  
short-name @`^+XPK\  
助记符,tag的一个别名(可选) 0&} "!)  
u%3D{Dj  
uri B"ZW.jMaI  
用于确定一个唯一的tag库 .DiH)  
AKk6kI8F  
display-name K[!OfP  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) 8D@H4O.  
}RowAGWL  
small-icon w7 @fiH{  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) 3(0k!o0 "  
ze@NqCF  
large-icon (A|Gb2X  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) @KfFt R-;  
D~E1hr&Vd>  
description a|Io)Qhr  
对tag库的描述(可选) tpOMKh.`  
h,o/(GNnW  
listener $O9Nprf  
参见下面listener元素 EnnT)qos  
AIgJ,=9K  
tag bi;?)7p&ZY  
参见下面tag 元素 ,5$V;|  
{/#^v?,  
Listener元素 ? FGzw  
~w_4 nE  
一个tag库可能定义一些类做为它的事件侦听类,这些类在TLD中被称为listener 元素,jsp服务器将会实例化这些侦听类,并且注册它们。Listener元素中有一个叫listener-class的子元素,这个元素的值必须是该侦听类的完整类名。 bw\fKZ  
&MKG#Y}  
Tag元素 1D%3|_id^  
5 0uYU[W  
每个tag元素在tag库中都要指出它的名字、类名、脚本变量、tag的属性。其中脚本变量的值可以直接在TLD中定义或通过tag附加信息的类来取得。每个属性描述了这个属性是否可以省略,它的值是否可以通过<%= …%>这样的JSP语法来获得,以及属性的类型。 M0zJGIT~b  
t{Ck"4Cg  
每一个tag在TLD中对应一个tag元素,下表是tag元素的子元素: PeT _Ty  
(C>FM8$J  
Tag元素的子元素 4=!SG4~o  
U ]jHe  
元素名称 (N{Rda*8  
描述 `@1y|j:m  
lO3W:,3_a  
name QWz5iM  
独一无二的元素名 a$H*C(wL  
D;VQoO  
tag-class &/R`\(hEA  
Tag标签对应的tag处理类 {\3k(NdEX  
/I&Hq7SW`  
tei-class `B'*ln'r5  
javax.servlet.jsp.tagext.TagExtraInfo的子类,用于表达脚本变量(可选) $8zsqd 4?  
G|MjKe4}  
body-content ^K*uP^B=  
Tag标签body的类型 ?@8[1$1a  
.@KpN*`KH  
display-name hqrI%%  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) S81Z\=eK  
+EK(r@eV  
small-icon b~dm+5W7  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) mC OJ1}  
erTb9`N4  
large-icon f'P}]_3(  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) GG%X1c8K  
{uH 4j4)2  
description \9k$pC+l  
此tag标签的描述 l`=).k   
WwG +Xa  
variable jR-DH]@y  
提供脚本变量的信息(同tei-class)(可选) &U q++f6  
o_; pEe  
attribute o (fZZ`6Y  
Tag标签的属性名 g-lF{Z  
WvSh i=  
以下章节介绍对于不同类型的tag,如何具体地实现它们。 >`L)E,=/  
."b=dkx  
C/V{&/5w  
简单的tag gSLwpIK%  
5dOA^P@`,M  
%.^8&4$+  
tag处理类 Xb +)@Y4h  
b[p<kMTir  
简单的tag处理类必须实现Tag接口的doStartTag和doEndTag方法。当jsp引擎碰到tag标签的开头时,doStartTag被调用,因为简单的tag没有body,所以此方法将返回 SKIP_BODY。当jsp引擎碰到tag标签的结尾时,doEndTag被调用,如果余下的页面还要被计算,那它将返回EVAL_PAGE,否则将会返回SKIP_PAGE。 ;ELQIHnD"  
{T|sU\|Q  
以下是例子:对于标签 <tt:simple /> ,它的tag处理类实现如下: ZfalB  
U U!M/QJ  
Cx$C+  
public SimpleTag extends TagSupport v\7k  
ZK,}3b{  
{ M7z>ugk"  
CY2DxP%  
public int doStartTag() throws JspException L$zI_ z  
!#cZ!  
{ 8was/^9;  
jCdKau&9  
try{ HRS|VC$tz  
kcT?<r  
pageContext.getOut().print(“Hello.”); \%\b* OO  
4 4%jz-m  
}catch(Exception e){ r"#h6lYK&  
5<Mht6"H  
throw new JspTagException(“SimpleTag: “ + e.getMessage()); X&qRanOP;z  
qT]Bl+h2  
} o %#Z  
K0B J  
return SKIP_BODY; _Y F~DU  
d bU  
} 5MY+O\  
V+M2Gf  
public int doEndTag() "o#N6Qu71  
+wd} '4)  
{ ]:TX> X!  
H -('!^  
return EVAL_PAGE; R<W#.mpo6  
L'=e /&  
} xTQV?g J  
,Ie~zZE&  
} /Z<"6g?  
Dz, Fu:)  
.N~qpynY  
注意:如果tag标签没有内容的话,那必须定义body-content元素为空,例如 a(CZGIB  
p '{ `Uvr  
<body-content>empty</body-content> $t5 0<1  
G3QB Rh{  
Q"c!%`\  
带属性的tag标签
评价一下你浏览此帖子的感受

精彩

感动

搞笑

开心

愤怒

无聊

灌水
级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
只看该作者 1 发表于: 2007-01-01
tag处理类 AEkgm^t.{  
|7WzTz  
对于tag标签的每个属性,你必须依照JavaBeans规范来定义其属性,以及get和set方法。以struts的logic:present 标签为例, &|<~J (L;  
.UbmU^y|  
<logic:present parameter=”Clear”> vj0`[X   
j}8IT  
与此相应,此tag处理类应有如下方法和定义: /1++ 8=  
gUDd2T#  
EVmQ"PKL'  
protected String parameter = null; %z! w- u+  
K/oPfD]  
public String getParameter() :j$K.3n  
1DcYc-k#  
{ SqY;2:  
jM J[6qj  
return this.parameter; M0o=bYI  
Y%qhgzz?/  
} sBp|Lo  
FsZM_0>/s  
public void setParameter(String parameter) 4s*P5w_'/  
Mr:*l`b_  
{ GN{\ccej  
)<4o"R:*  
this.parameter = parameter; W"Dj+/uS  
9.e?<u*-z  
} n]4)~ZIAU  
heZ)+}U~  
P&| =  
注意:如果你的属性名为id,而且你的tag处理类是从TagSupport类继承的,那你就不需要定义它的属性和set和get方法,因为他们早已在TagSupport被定义过了。 s9'g'O5  
DMcvu*A  
Attribute元素 xTD6?X'4  
O60jC;{F  
对于tag标签的每个属性,你必须定义它是否必须的,它的值是否可以用诸如<%= …%>的表达式来获得,以及它的类型(可选),如果不指定它的类型,那就默认为是java.lang.String类型。如果rtexprvalue元素被定义为true或yes,那么在type元素中就定义了attribute的返回类型。 IgEg  
5WP[-J)  
<attribute> 9}X3Q!iFb  
mL+}Ka  
<name>attr1</name> Ndi'b_Sh\  
uW;Uq=UN  
<required>true|false|yes|no</required> =B1t ?( "  
h0n0Dc{4  
<rtexprvalue>true|false|yes|no</rtexprvalue> k_V1x0sZ  
,Z_nV+l_  
<type>attribute的返回类型(只用当rtexprvalue为真是才有效)</type> |NtT-T)7  
{114 [  
</attribute> z1!ya#,$  
M; zRf3S  
如果tag的某个属性不是必须的,那tag处理类会自动提供一个缺省值。 doc5;?6   
K1O/>dN_\O  
例如,在logic:present这个tag标签中定义了一个属性叫parameter,但它不是必须的,而且它可以被诸如<%= …%>的表达式来赋值。 9b]*R.x:$&  
SfJ/(q  
<tag> k;zb q  
0x# 6L  
<name>present</name> b9|F>3?r>  
^1,]?F^  
<tag-class>org.apache.struts.taglib.logic.PresentTag</tag-class> \+GXUnkj  
)2YU|  
<body-content>JSP</body-content> 9 K$F.{cx  
%9mB4Fc6b)  
B>X+eK  
1sc #!^Oo  
<attribute> mm#U a/~1u  
&%u,b~cL?  
<name>parameter</name> 3}g?d/^E3  
k`)LO`))  
<required>false</required> M#S8x@U  
i04Sf^  
<rtexprvalue>true</rtexprvalue> Si]Z`_  
4)Pt]#Ti  
</attribute> 8SAz,m!W)  
0 {{7"  
]CC~Eo-%-  
w?M*n<) O  
</tag> +\Q6Onqr  
.E;6Xx_+r  
7M;Y#=sR  
属性元素的校验 8x,;B_Zu  
9U}EVpD  
(-dJ0!  
有关于tag标签的有效值可以从tag库的说明文档中获得,当JSP页面被编译时,jsp引擎会强制性地参照TLD中定义的规则进行检查。 qwFn(pK[  
m$LZ3=v%8  
还有一个方法也可以进行属性元素的校验,就是先继承类TagExtraInfo,然后调用它的isValid方法。这个类同时也起到提供tag中定义的脚本变量信息的作用。 W\~ZmA.  
"r"]NyM  
IsValid方法通过TagData对象来传递属性信息,它包括着tag的所有的属性名-值的信息。由于校验发生在运行时刻,因此这个属性的值将被赋值为TagData.REQUEST_TIME_VALUE。 T>f-b3dk  
)STt3.  
例如tag标签<tt:twa attr1=”value1” />在TLD中定义如下: _%zU ^aE  
W]Ph:O ^5c  
<attribute> PY z | d  
$Uewv +  
<name>attr1</name> HwST^\Ao  
g1zqh,  
<required>true</required> Tg:NeAN7(  
3;:xEPb._6  
<rtexprvalue>true</rtexprvalue> 4zf#zJw  
H8\{ GGg  
</attribute> fI$, ?>  
|?8CV\D!  
g X(QRQ  
这个定义说明了attr1能在运行期间被赋值。 v?LJ_>hw*T  
=?*V3e3{  
以下的isValid方法检查attr1属性的值是否属于Boolean类型。注意由于attr1能在运行刻被赋值,那么isValid方法必须检查tag用户是否对此tag进行了运行时刻赋值。 3J,/bgL5  
*c3 o&-ke9  
9oq(5BG,  
Public class TwaTEI extends TagExtraInfo cQ+, F2  
qA30z%#z_  
{ sL/Lw WH  
\17)=W  
public boolean isValid(Tagdata data) ?,%N?  
HYg _{  
{ xD1wHp!+  
Y(A?ib~K  
Object o = data.getAttribute(“attr1”); |g;XC^!%=o  
sJM}p5V  
If(o != null && o != TagData.REQUEST_TIME_VALUE) IBF>4q m"  
i-ogeR?  
{ czZ-C +}%  
A(s/Nz>  
if( ( (String)o).toLowerCase().equals(“true”) || g:,4Kd|  
`7 B [<  
((String)o).toLowerCase().equals(“false”) ) J| DWT+$#Z  
6kDU}]c:H]  
return true; *M`[YG19!e  
q?0goL  
else aPb!-o{  
iTK1I0  
return false; QiRzA4-zq  
9QX{b+}"e  
} D 3HB`{  
>=Rb:#UM  
else jgMWjM6.  
EhVnt#`Si  
return true; r}5GJ|p0  
1Gqtd^*;  
} dl;A'/(t  
|ITg-t  
} U NAuF8>K  
?PQiVL  
&WRoNc  
带body的tag {MEU|9@ Y  
,`Mlo  
b~~}(^Bg  
tag处理类 0WPxzmY  
4OIN@n*4  
8'quQCx*=  
如果tag标签含有内容,那处理方式会略微有些不同,而且还要视tag处理类是否要与body交互的情况而定。如果要与body交互,那我们认为tag处理类要可能要对body进行操作。 7SM/bJ-M#  
6/n;u{|  
Tag处理类不与body交互 mcR!P~"i  
E nUo B<  
如果tag处理类不与body交互,tag处理类应该实现Tag接口或从TagSupport中派生,如果body要被计算,那么doStartTag方法应返回 EVAL_BODY_INCLUDE,否则应返回SKIP_BODY。 p_nrua?  
#]'V#[;~  
如果tag处理类要对body反复运算,则它应该实现IterationTag或从TagSupport中派生。如果tag处理类认为body还未计算完的话,那它的doStartTag方法和doAfterBody方法必须返回EVAL_BODY_AGAIN。 [a Z)*L ;  
M1>a,va8Zq  
Tag处理类与body交互 "bO]  
vaU7tJ:  
如果tag处理类与body交互,那tag处理类应实现BodyTag接口或从BodyTagSupport中派生。这种tag处理类一般要实现doInitBody和doAfterBody方法。 hg&AQk  
Fca?'^X  
Body允许一些方法来读写它的内容。Tag处理类可以调用body内容的getString或getReader方法来从body中提取信息,也可用 writeOut(out) 方法来将body的内容写入到out对象中。其中out对象通过tag处理类的getPreviousOut方法来获得。 wvYxL c#p0  
Bl1I "B  
如果body的内容需要被计算,那么doStartTag方法必须返回EVAL_BODY_BUFFERED,否则,它将返回 SKIP_BODY。 ]fc:CR  
q>X:z0H  
doInitBody 方法 \ lKQ'_  
<;T7q EIlo  
此方法在body内容已经设好,但未被计算之前被调用。你可以根据不同的body内容来制定初始化策略。 @kK=|(OB'  
XDWERv Ij  
doAfterBody方法 $R5-JvJJH  
~iSW^mi  
此方法在body内容已被计算后进行调用。 axl?t|~I  
+Q9HsfX/  
和doStartTag方法一样,doAfterBody方法返回一个指示符指示是否要继续计算body,如果要继续计算,则doAfterBody应返回EVAL_BODY_BUFFERED,否则,它应返回SKIP_BODY。 2U+&F'&Q  
0jS/U|0  
release 方法 JU6np4  
Z`!pU"O9l  
tag处理类调用此方法将它的状态重置为初始状态,并释放所有的私有资源。 hh{liS% 10  
d"cfSH;h  
 (M=Br  
以下的例子读取body的内容(其中含有一条sql语句),然后将它传递给一个对象,让它进行查询。由于此处body不须重新计算,所以doAfterBody会返回SKIP_BODY。 uXC?fMWp.  
JQCwI`%i  
!K2[S J  
Public class QueryTag extends BodyTagSupport W | }Hl{}  
7wnzef?)  
{ `sXx,sV?B  
e{O5y8,  
public int doAfterBody() throws JspTagException :Ry 24X  
%qHT!aP  
{ =V , _  
[4t KJ+v  
BodyContent bc = getBodyContent(); Y>%NuL|s  
 %!S  
//将body的内容以字符串的格式提取出来 P&YaJUq.u  
Y^G3<.B  
String query = bc.getString(); IO'Q}bU4vs  
^`7t@G$ D  
//清除body t<7WM'2<y  
Rt|Hma  
bc.clearBody(); n\YxRs7 hF  
`3KprpE8v  
try{ L_r & 'B  
CvJm7c  
Statement stmt = connection.createStatement(); ZL>V9UWN  
P(;c`   
Result result = stmt.executeQuery(query); ,W-0qN&%/  
X3nhqQTZ  
}catch(SQLException e){ SMFW]I2T/  
5HN<*u%z  
throw new JspTagException(“queryTag: “ + e.getMessage() ); m [g}vwS  
dNobvK  
return SKIP_BODY; Y<+4>Eh  
m0"\3@kB  
} 6T s`5$e  
"=(;l3-o  
} {Jc!T:vJ  
aiHr2x6  
d/&|%Z r  
body-content元素 \_E.%K  
fz3*oJ'  
/WfVG\NF  
由于tag可能会有body,你必须用body-content元素来指定body内容的类型: g@k9w{_  
(ZK >WoV  
<body-content>JSP|tagdependent</body-content> jh G7sS|  
DE ws+y-*  
m =}X$QF`^  
如果body的内容是定制的或内部的tag、脚本元素、或HTML广本,则归类为JSP类型。其他的类型,比如上面代码所述的?D?D将sql statement类传给 query tag的这种类型应该标为tagdependent。 Anv8)J!9u  
uH[0kh  
注意:实际上body-content的值并不影响tag处理类对body内容的处理,它仅仅是被tag编辑工具用来描述此body的内容。 OpLSjr  
N 3c*S"1  
<^Tj}5 )n  
用tags定义脚本变量 j%;)CV G"  
ArYF\7P  
];;w/$zke  
tag处理类 `1@[uWl  
W<VHv"?V  
&*aU2{,s,;  
tag处理类负责创建或设置页面中定义的脚本变量,用pageContext.setAttribute(name,value,scope)或pageContext.setAttribute(name,value)方法来实现。一般来说,tag处理类通过脚本变量的名称来获取它,脚本变量的名称一般可用get方法来获得。 T6$<o\g'  
cloI 6%5r  
如果脚本变量的值依赖于tag处理类中的上下文中某一对象,那它可用pageContext.getAttribute(name,scope)方法来找到那个对象。一般的处理过程是tag处理类先找到脚本变量,再对其进行处理,然后用pageContext.setAttribute(name,object)的方法来设置它的新值。 %#9~V  
Yk Pt*?,P/  
对象的生存周期(scope)如下表: dO,05?q|  
63S1ed [  
对象的生存周期表 RHVv}N0  
'.yWL  
名字 &|'6-wD.  
可访问范围 a7\L-T+  
生存周期 XB-|gPk  
j*4S]!  
page `uA&w}(G  
当前页面 =7fh1XnW  
一直有效,除非页面向客户提交响应或重定向到一个新页面 "ru1;I  
(N|xDl &;  
request &o@5%Rz2/  
当前页面或当前页面重定向到的页面 k+$4?/A  
一直有效,除非页面向客户提交响应 PAV2w_X~  
~iZF~PQ1_  
session HDyZzjgG  
当前页面或在同一浏览器窗口中的页面 \STvBI?  
一直有效,除非关闭当前浏览器、超时、网络故障 H$amt^|zQ4  
X&.$/xaT  
application [!? ,TGM}^  
整个web应用程序的所有请求 -/c1qLdQ  
一直有效,除非发生网络故障、服务器故障 j#P4Le[t  
tcEf ~|3  
提供关于脚本变量的信息 lO> 7`2x=F  
HF+fk*_Q  
以下示例定义了一个名为“book”的脚本变量,用来访问程序中关于书的信息: ' u};z:t  
sDm},=X}  
<bean:define id=”book” name=”bookDB” property=”bookDetails” type=”database.BookDetails” /> y%bqeo L~  
Z4ov  
<font color=”red” size=”+2” > So%1RY{ )  
G@EjWZQ  
<%= messages.getString(“CartRemoved”) %> sFCs_u1tNN  
j :Jdwf  
<strong><jsp:getProperty name=”book” property=”title” /></strong> E)wT+\  
zl 0^EltiU  
</font> ( L\G!pP.  
s4`*0_n  
当包含此tag的JSP页面被编译时,jsp引擎会自动生成关于此book的同步的代码(同步可以避免几个客户同时访问此book时造成的冲突),要生成同步代码,jsp引擎需要知道此脚本变量的如下信息: |/=p  
n UCk0:{  
· 脚本变量名称 YCBML!L  
rqe_zyc&  
· 脚本变量所属的类 6XL9 qb~X  
>ha Ixs`9  
· 此脚本变量是否引用了一个新的或已存在的对象 zMzf=~  
b%f2"e0g  
· 此脚本变量的有效性 1=5'R/k  
zRoEx1  
有两种办法可以向jsp引擎提供关于脚本变量的信息:在TLD中定义variable子元素,或用tei-class子元素定义一个额外tag信息类。用variable最简单,但可能降低了一些灵活性。 x ETVt q  
R 4QwWSBJ  
Variable元素 A|_%'8  
[I<'E LX  
Variable元素有如下子元素: MQH8Q$5D  
O\F^@;] F6  
· name-given ?D?D 给出的名字,是一个常量 0*IY%=i  
:'rZZeb'  
· name-from-attribute?D?D 属性名,在编译时给出的属性名 bA^: p3  
[-Tt11  
name-given或name-from-attribute两者必须选一,但以下子元素是可选的: %802H%+  
YZ:'8<  
· variable-class?D?D变量的类型,缺省为java.lang.String。 m\Fb ,  
5`'au61/2  
· declare?D?D此脚本变量是否引用了一个新对象,缺省为True。 M(WOxZ8  
`(Q_ 65y  
· scope?D?D脚本变量的范围,缺省为NESTED。下表描述了scope的几种类型: bc=u1=~w  
_B7?C:8Q-  
脚本变量的有效范围 `{Di*  
NT9- j#V  
!na0Y  
有效性 hOLy*%  
方法 >`?+FDOJ,  
+JAfHQm-  
NESTED VBsFT2XiL  
在tag标签的开始和结束之间 iLd"tn'  
如果tag处理类实现BodyTag接口,则在doInitBody和doAfterBody中调用,否则在doStartTag中调用 f+aS2k(e>  
Ta\8 >\6  
AT_BEGIN RQ)!KlY  
从tag标签的开始一直到页面结束 9Bvn>+_K  
如果tag处理类实现BodyTag接口,则在doInitBody、doAfterBody和doEndTag中调用,否则在doStartTag和doEndTag中调用 F;&f x(  
9k+&fyy  
AT_END (T#(A4:6S  
从tag标签的结束一直到页面结束 vl{_M*w ;  
在doEndTag中调用 ;0Ct\[eh  
OG?j6q hpl  
以struts为例,它的bean:define标签的实现遵循JSP1.1规范,此规范要求使用额外tag信息类来定义脚本变量。Variable元素是JSP1.2规范中加入的。以bean:define标签为例,你可以定义如下variable元素: tqwk?[y}+l  
IJBJebqL  
<tag> p<0kmA<B/  
)>X|o$2  
<variable> . I&)MZ>n  
C|~JPcl  
<name-from-attribute>id</name-from-attribute> D7_Hu'y<o  
Jn@Mbl  
<variable-class>database.BookDetails</variable-class> cM<hG:4%wX  
0@e}hv;  
<declare>true</declare> {Fp`l\,  
;$tv8%_L[  
<scope>AT_BEGIN</scope> q~' K9  
V.QzMF"o  
</variable> L3=YlX`UL  
fF9oYOh|  
</tag> ^I0GZG  
>]XaUQ-  
额外tag信息类 "J[i=~(  
: ` 6$/DK  
如果要定义一个额外tag信息类,你要继承javax.servlet.jsp.TagExtraInfo类。一个TagExtraInfo类必须实现getVariableInfo方法,此方法返回一个叫VariableInfo的数组类,它包括如下信息: id#k!*$7  
pJ$N@ID  
· 变量名 WP@JrnxO\`  
< ;,S"e  
· 变量所属类名 Th;gps%b  
Z/6'kE{l  
· 此变量是否引用了一个新对象 K'{W9~9Lq  
! N"L`RWD  
· 此变量的有效范围 g"dZB2`C  
\l=KWa3Q  
jsp引擎将一个名为data的参数传给getVariableInfo方法,data中包括tag标签中的所有“属性名?D?D属性值”对。它可以用来向VariableInfo对象提供脚本变量的名字和类名。 Q1ABnacR  
}2BH_  2  
以struts为例,它在bean:define标签中定义了一个名为DefineTei的额外tag信息类,用来向脚本变量提供信息。由于脚本变量的名称(book)和类名(database.BookDetails)是通过tag标签的属性来传递的,它们一般定义在VariableInfo的构建代码中,并且可用data.getAttributeString方法来得到这些信息。如果要允许book脚本变量能在从tag开始直到整个JSP页面结束的范围内都可用的话,那它的范围应设为AT_BEGIN。如下所示: [>M*_1F  
4z0R\tjT  
w1"gl0ga$  
public class DefineTei extends TagExtraInfo M8",t{7  
8NAWA3^B  
{ bUAR<R'E  
?;r8SowZ7  
public VariableInfo[] getVariableInfo(TagData data) X.T\=dm%v  
=6Kv`  
{ =S[FJaIu7  
6Er0o{iI  
String type = data.getAttributeString(“type”); e2-70UvW^  
+Sdx8 Z5  
If( type == null) vA "`0  
#EQx  
type = “java.lang.Object”; k}f<'g<H  
VNxpOoV=S  
return new VariableInfo[] { A"bSNHCKF  
]2xx+P#Y  
new VariableInfo(data.getAttributeString(“id”), 5;K-,"UQ  
74}eF)(me  
type, 8%2rgA  
I"F .%re  
true, ><#2O  
mS)|6=Y  
VariableInfo.AT_BEGIN) J^g,jBk  
0,~6TV<K  
}; GOZQ5m -  
q(jkit~`A  
} vU8FHVytV  
7i+!^Qj?y  
} 6L:tr LuQ  
}4\!7]FVYX  
\%-E"[!  
注意:关于额外tag信息类的类名必须要在TLD中的tag标签下的tei-class子元素中定义。因此,DefineTei的tei-class中的定义看起来如下: b5n]Gp  
<tei-class> ].k+Nzf_  
org.apache.struts.taglib.bean.DefineTagTei z3vsz  
</tei-class> MKVfy:g%So  
)4'x7Qg/  
M~ i+F0  
具有协作关系的tag Q2[prrk%j  
Hlt8al3  
4(Cd  
tag通过共享对象来进行协作,JSP技术支持2种方式的对象共享。  zU4V^N'  
Mg a@JA"  
第一种方法是使用pageContext对象进行对象的共享(可支持JSP页面和tag处理类之间的共享),如果在一个tag处理类中要调用由另一个tag处理类创建的对象,可调用pageContext.getAttribute(name, scope)方法。 'd2qa`H'}B  
y} $ P,  
第二各方式的共享是对于tag之间有嵌套关系而言的,外层的tag所创建的对象对于内层的tag来说是可以共用的。这种形式的共享的好处是减少了可能存在的重名冲突。 ]8xc?*i8  
c4ZuW_&:  
要访问一个嵌套tag创建的对象,tag处理类必须先找到此嵌套tag对象,可用TagSupport的静态方法 TagSupport.findAncestorWithClass(from, class)或TagSupport.getParent方法。前者在当不确定此tag是否为嵌套tag对象时使用。一旦它的父类被找到,它就能访问其所有动态或静态创建的对象。静态创建的对象是父类的成员,而动态创建的对象可能是父类的私有对象。诸如此类的对象可以用tag处理类的setValue方法来保存,用getValue方法来获得。 T<TcV9vM  
_X,[]+ziu%  
下例阐述了以上两种共享对象的方法。在这个例子当中,一个查询tag检查一个名为connection的属性名是否在doStartTag中被设置。如果connection属性被设置,tag处理类从pageContext中得到这个connection对象。否则,此tag处理类先找到它的父tag处理类,然后从它的父tag处理类中找到connection对象。 )y%jLiQv  
]< s\V-y  
S/nj5Lh  
public class QueryTag extends BodyTagSupport \ifK~?  
jSwtf  
{ 5q(]1|Se i  
Z#OhYm+y  
private String connectionId; !^)wPmk  
`?zg3GD_  
public int doStartTag() throws JspException o[bE  
96"yNqBf  
{ M1/M}~  
+{")E)  
String cid = getConnection(); <fC@KY>#  
` j&0VIU>>  
if(cid != null) ()QOZ+x_!  
FG DGWcRw~  
{ 7K>D@O  
"EcX_>  
//存在一个connection id,使用它。 |+Hp+9J  
~ Ho{p Oq  
connection = (Connection) pageContext.getAttribute(cid); kCaO\#ta  
kf%&d}2to  
} "*++55  
T3USNc51  
else .>mH]/]m  
]>R`;"(  
{ JmU<y  
V;h=8C5J  
ConnectionTag ancestorTag = (ConnectionTag)findAncestorWithClass(this, e/"yGQu  
X q}Ucpj  
ConnectionTag.class); HE#,(;1i  
lZ|L2Yg3uB  
if(ancestorTag == null) ||-nmOy  
Vs#"SpH{'  
{ z-EwXE  
jd%Len&p  
throw new JspTagException(“一个没有connection属性的查询标签必须被一个connection标记嵌套。”); n S_Ta  
@~m=5C  
} <Rcu%&;i  
[[R7~.;  
connection = ancestorTag.getConnection(); !dU9sB2  
;y>S7n>n:  
} o"rq/\ovv  
'|vD/Qf=&  
} Tub1S v>J  
"w}-?:# j  
} f4]N0  
s kN9O"^A  
uh]"(h(>  
z$JX'(<Z7  
此查询标签在JSP页面中的调用形式可以从以下2种定义中任选一种: +hE',i.  
a q3~!T;W  
3lo;^KX !  
<tt:connection id=”con01” ...> ... </tt:connection> 2 \^G['9  
@ Ii-NmOr  
<tt:query id=”balances” connection=”con01” > HXQ e\r  
:P3{Nxa  
SELECT account, balance FROM acct_table +c^_^Z$_4o  
s|Z:}W?{  
where customer_num = <%= request.getCustno() %> PG{i,xq_B{  
?b||Cr  
</tt:query> =43I1&_   
D`6iDi t  
s}6+8fE"  
ze`1fO|%  
n[!;yO  
<tt:connection ...> ;Vg^!]LL#  
1EVfowIl  
<x:query id=”balances”> ^>C 11v  
= 96G8hlT  
SELECT account, balance FROM acct_table Zp?4uQ)[W  
7ftR 4  
where customer_num = <%= request.getCustno() %> ,4[dLWU  
\gLxC  
</x:query> k`Nyi )AGe  
lC0~c=?J  
</tt:connection> Q"40#RFA  
l , ..5   
qu_)`wB  
与此同时,在TLD中必须指定connection属性为可选的,定义如下: u*2fP]n  
]kx-,M(  
<tag> P0^c?s"I  
PgMbMH  
... "'m)VG  
(8.{+8o  
<attribute> v:E;^$6Vn  
Yu'a<5f  
<name>connection</name> L>dkrr)e  
r'/\HWNP  
<required>false</required> Hkdf$$\  
B`fH^N  
</attribute> 2 nv[1@M  
5F2_xH$5  
</tag>
描述
快速回复

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