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

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

级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
标准的JSP 标记可以调用JavaBeans组件或者执行客户的请求,这大大降低了JSP开发的复杂度和维护量。JSP技术也允许你自定义taglib,其实换句话说,taglib可以看成是对JSP标记的一种扩展,正如xml是对html的一种扩展一样。taglib通常定义在tag标签库中,这种标签库存放着你自己定义的tag标签。简而言之,如果使用taglib,那么你可以设计自己的JSP标记! LFCTr/,  
GA.BI"l  
一般来说,自定义tag标签主要用于操作隐藏对象、处理html提交表单、访问数据库或其它企业级的服务,诸如邮件和目录操作等等。自定义tag标签的使用者一般都是那些对java编程语言非常精通,而且对数据访问和企业级服务访问都非常熟悉的程序员,对于HTML设计者来说,使得他可以不去关注那些较复杂的商业逻辑,而将精力放在网页设计上。同时,它也将库开发者和库使用者进行合理分工,自定义tag标签将那些重复工作进行封装,从而大大提高了生产力,而且可以使得tag库可用于不同的项目中,完美地体现了软件复用的思想。 + Qt[1Xq  
]x1p!TSU  
在这篇文章中,我们主要讨论: ^rL ,&rk  
v#zPH5xo  
· 什么是自定义tag标签? d{W}p~UbH  
rqF"QU=l  
· 怎么使用tag标签?  G]b8]3^  
mj)PLZ]  
o 声明要使用的tag库 L*P_vCC  
}qG#N  
o 找到与之对应的tag处理类 _HwpPRVP/  
]22C )<  
o tag标签的类型 qc3~cH.@  
])C>\@c6Gm  
· 自定义tag标签 }xqXd%uz  
$)Wb#B  
o tag处理类 @\ }sb]  
TfL4_IAG.  
o tag库描述 G=1m] >I8  
-)X{n?i  
o tag标签示例 w5,6$#  
RYt6=R+f  
o 带属性的tag rw&y,%2  
}f0u5:;Zth  
o 带body的tag JfkTw~'R  
q'.;W@m  
o 定义了脚本变量的tag =Ci13< KQ  
K<#-"Xe;  
o 具有协作关系的tag 3)y{n%3L  
Lj iI+NJ  
· 自定义tag标签 .?f:Nb.O  
Ee8--  
o 一个迭代tag的例子 }S,-uggz  
#'C/Gya  
o 一个模板tag库 c -w0  
2\5cjdy  
o tag处理类到底是怎样被调用的? n? ]f@OR  
!Vb,zQ  
3EmcYC  
什么是自定义的tag? D{R/#vM jk  
@m?{80;uQ  
一个自定义的tag标签是用户定义的一种JSP标记。当一个含有自定义的tag标签的JSP页面被jsp引擎编译成servlet时,tag标签被转化成了对一个称为tag处理类的对象进行的操作。于是当JSP页面被jsp引擎转化为servlet后,实际上tag标签被转化成为了对tag处理类的操作。 >{QdMn  
' X}7]y  
自定义tag标签有很多特色,诸如: @LcT-3u  
qp\BV#E  
· 可以在JSP页面中自定义tag标签的属性 [yC"el6PM  
` VwN!B:  
· 访问JSP页面中的所有对象 QhCY}Q?X  
v`SY6;<2  
· 可以动态地修改页面输出 C%]."R cMC  
E`tQe5K  
· 彼此这间可以相互通信。你可以先创建一个JavaBeans组件,然后在一个tag中调用此JavaBeans组件,同时可以在另一个tag中调用它。 FZpsL-yx^N  
9 Va40X1  
· tag允许相互嵌套,可以在一个JSP页面中完成一些复杂的交互。 EMh r6</  
TMww  
{ UOhVJy  
使用tag标签 V}SyD(8~  
=5Wp&SM6  
\e|U9;Mf  
本节主要描述怎样在JSP页面中使用tag标签,以及tag标签的不同类型。 izf~w^/  
fe';b[q)#  
要使用tag标签,JSP程序员必须做2件事: 3%2jwR  
PPj[;(A  
· 声明此tag标签的tag库 xZyeX34{M;  
/$Z m~Mp  
· 实现此tag标签 \6:>{0\  
6b<+8w  
声明tag标签所在的tag库 C3)|<E  
/VO^5Dnb  
如果要使用tag标签,则应用JSP的taglib指示符来指定其tag库(注意:taglib要在在使用此tag标签之前声明) wLUF v(&C  
U{}!y3[wK  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> Af9+HI O  
"J !}3)n  
uri属性定义了唯一的标签库描述(以下简称TLD),它可以是直接是tld文件名或一个独一无二的名字。prefix是用来区别其它TLD中和本TLD中有重名的tag的一种手段。 yb?{LL-uy  
 uB;_vC  
TLD必须以.tld作为扩展名,并且存放在当前应用的WEB-INF目录或其子目录下。你可以通过它的文件名直接引用它,也可以通过别的方式间接地引用它。 /[iG5~G  
69/?7r  
以下taglib指示符直接引用一个TLD: (zC   
/l6\^Xf{  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> H|`R4hAk  
&bLC(e ]  
以下的taglib指示符通过一个逻辑名称间接地引用一个TLD: ?q!FG(  
~.6|dw\p!  
<%@ taglib uri=”/tutorial-template” prefix=”tt” %> 7]s%r ya  
!}5*?k g  
如果是间接引用TLD的话,那你必须还要在web.xml中定义此逻辑名称与tld文件之间的映射,具体做法是在web.xml中加入一个名为taglib的元素:  ,1 P[  
5B{k\H;  
<taglib> +T2HE\  
Qci$YTwl>  
<taglib-uri>/tutorial-template</taglib-uri> jTfi@5aPY  
o%`npi1y  
<taglib-location> ik5|,#}m&  
|1l&@#j!2  
/WEB-INF/tutorial-template.tld %`+'v_iu  
ej52AK7  
</taglib-location> jo_ sAb  
E:w:4[neh  
</taglib> Qn.[{rw  
P"F{=\V1`<  
jV^C19  
实现此tag标签 {6O0.}q]&  
)o jDRJ&  
hwVAXsF~  
为了实现tag标签,你有2种方法来存放tag处理类。一、让tag处理类以.class的方式存放于当前应用的WEB-INF/class子目录下,二、如果tag处理类是以JAR包的形式存在的话,那可以放在当前应用的WEB-INF/lib目录下,如果tag处理类要在多个应用中共享,那么它就应放在jsp服务器上的common/lib目录下,对于tomcat来说,就是tomcat/common/lib目录下。 h!e2 +4{4{  
P'tMu6+)  
*d>vR1  
tag标签类型 eh<rRx"[  
]*;F. pZ  
=VSkl;(O  
自定义的tag标签遵循XML语法。它有一个开始标记和一个结束标记,有的还有body(即文本节点): O R #7"  
V7C1FV2  
<tt:tag> :6lwO%=F  
yU7I;]YP  
body sx5r(0Z  
Jq .L:>x  
</tt:tag> 5+K;_)   
:<GfETIs  
>vujZw_0>  
一个不带body的tag标签如下: jK3\K/ob(  
/\J|Uj  
<tt:tag /> I60DUuF  
xmr|'}Pt[  
p)3nyN=|_  
简单的tag标签 #mLuU  
ia4k:\  
一个没有body和属性的tag标签如下: ntGq" o  
})[($$f/  
<tt:simple /> ]1sNmi$T  
DZs^ 2Zc  
Q\9K2=4  
带属性的tag标签 c!Dc8=nE0m  
xU}M;4kH~  
73 V"s  
自定义标签可以有自己的属性。属性一般在开始标记中定义,语法为 attr=”value”。属性的作用相当于自定义标签的一个参数,它影响着tag处理类的行为。你可以在TLD中详细定义它。 }Hy ~i  
PZ,z15PG]  
你可以用一个String常量给一个属性赋值,也可以通过表达式给它赋值,如<%= ...%>。以struts为例,它的logic:present标签就是用的String常量来给属性赋值: >uy%-aXiVa  
P`TIaP9%E  
<loglic:present parameter = “Clear”> +xj "hX>3  
\.<KA  
而另一个标签logic:iterate是用表达式来给属性赋值: PAZ$_eSK6  
V=}1[^  
<logci:iterate collection=”<%= bookDB.getBooks() %>” ~R.dPUr  
n"G`b  
id=”book” type=”database.BookDetails”> maC>LBa2/  
>"("*3AO  
Zw$ OKU  
带body的tag标签 \[#t<dD  
G{RTH_p  
一个自定义标签可以包含其它自定义标签、脚本变量、HTML标记或其它内容。 Mw^ *yW  
M35Ax],:^  
在下述例子中,此JSP页面使用了struts的logic:present标签,如果些标签定义了parameter=”Clear”的属性,则将清除购物车的内容,然后打印出一条信息: Bo r7]#  
^$Krub{|  
<logic:present parameter=”Clear”> ssl&5AS  
8h.V4/?  
<% cart.clear(); %> ^%#grX#  
'Kz9ygZy  
<font color=”#ff0000” size=”+2”><strong> {'R)4hL  
Y=2Un).&  
你选择了清除购物车! JsQ6l%9  
kX2d7yQZz  
</strong></font> l,d, T  
6RK\}@^=K  
</logic:present> 5~r2sCDPk  
>I<PO.c!  
G7-!`-Nk  
到底是用属性还是用body来传递信息? - k`.j  
Gt~JA0+C)7  
如上所述,我们既可以通过属性,也可以通过body来传递信息。但一般来说,比较简单的类型,如字符串或简单表达式最好采用属性来传递信息。 nQ=aLV+'  
qLjT.7 .x  
YG[w@u  
定义脚本变量的tag标签 MzTW8  
'4u v3)P  
所谓脚本变量,是指JSP中可以调用的变量或对象。它可由tag标签产生。以下示例阐述了一个tag标签定义了一个名为tx的由JNDI所定义的事务处理对象。脚本变量可以是ejb对象、事务、数据库连接等等: }9&9G%  
8eyl,W=dn  
<tt:lookup id=”tx” type=”UserTransaction” name=”java:comp/UserTransaction” /> JNo8>aFOb  
9B/1*+ M  
<% tx.begin(); %> Gv~p  
T PYDs+U  
... <DZcra  
yA;W/I4  
YV([2  
具有协作关系的tag标签 8;n_TMb  
6E^~n  
自定义tag标签之间可以通过共享对象来实现协作。在下述例子中,标签tag1创建了一个名为obj1的对象,在标签tag2仍可以重复使用obj。  `w<J25  
QUOKThY?  
<tt:tag1 attr1=”obj1” value1=”value” /> sN/+   
Gi7RMql6Q  
<tt:tag2 attr1=”obj1” /> `# ^0cW  
QxpKX_@Q5  
在以下这个例子当中,如果外层的tag标签创建了一个对象,那么其内层的所有tag标签都可以使用这个对象。由于这样产生的对象没有一个指定的名字,那么就可以将少重名的冲突。这个例子阐述了一系列协作的嵌套对象。 YYUe)j{T  
#Ufo)\x  
<tt:outerTag> )^/0cQcJ  
fgCT!s7z  
<tt:innerTag /> `\b+[Nes  
cm@;*  
</tt:outerTag> Vb)zZ^va+  
91d }, Mq:  
4Z5#F]OA7  
Tag处理类 r>|-2}{N/  
 .i/m  
ht6244:  
Tag处理类必须实现Tag接口或BodyTag接口,不过现在一般都流行从TagSupport或BodyTagSupport类中继承,这些类或接口都可以在javax.servlet.jsp.tagext包中找到。 vg\/DbI'  
`_qK&&s  
当JSP引擎看到自己的JSP页面中包含有tag标签时,它会调用doStartTag方法来处理tag标签的开头,调用doEndTag方法来处理tag标签的结束。 Z4q~@|+%  
U A-7nb  
下表说明不同类型的tag所需要不同的处理过程: pn%#w*'  
<hvRP!~<)  
Tag处理类的方法 1>pe&n/  
$G !R,eQ  
Tag标签类型 q``wt  
所调用的方法 }[!92WS/ee  
T|){<  
基本标签 lU.Kc  
doStartTag, doEndTag, release rAukHeH  
j]5WK_~M  
带属性的标签 ZFxLBb:  
doStartTag, doEndTag, set/getAttribute1...N, release zx%X~U   
Vfs $ VY2.  
带内容的标签 !:0v{ZQ  
doStartTag, doEndTag, release IVjU`ij  
7@;">`zvm  
带内容的标签,且内容重复循环 ^mPPyT,(  
doStartTag, doAfterBody, doEndTag, release (03pJV&K  
Xe1P- 6 0  
带内容的标签,且内容与JSP交互 ^&[+H8$  
doStartTag, doEndTag, release, doInitBody, doAfterBody, release ")UwkF  
#h'@5 l  
一个tag处理类可以通过javax.servlet.jsp.PageContext来与JSP交互,通过javax.servlet.jsp.PageContext类,tag处理类可以访问JSP中的request、session和application对像。 :td ~g;w  
N4{nG,Mo]  
如果tag标签是互相嵌套的,那内层的tag处理类可以通过它的parent属性来访问上层的tag处理类。 s] au/T6b  
4IsG=7   
一般情况都将所有的tag处理类打成了JAR的包,以便于发布。 Pq p *  
w"zE_9I\  
=$^MQ\S0p  
Tag库描述(简称TLD) Ew,T5GG  
fZN><3MO>  
uzU{z;  
Tag库是用xml语言描述的,TLD包括了tag库中所有tag标签的描述,它一般用来被jsp服务器用来校验tag的语法正确性,或者被jsp开发者用来开发新的标签。 -_0?_Cb  
a. %LHb  
TLD的文件扩展名必须为.tld,而且必须放在当前WEB应用的WEB-INF目录或其子目录中。 fi%r<]@  
p{tK_ZBy]c  
一个TLD的内容的开头必须遵守标准的XML开头,用于描述DTD和xml的版本,例如: nzsl@1s  
%J7UP4  
<?xml version="1.0" encoding="ISO-8859-1" ?> .#w6%c@  
w# y2_  
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd"> (Tvcq  
TLD必须以<taglib>来作为它的根元素,<taglib>的子元素如下表: 7+,vTsCd  
-n))*.V  
c:hK$C)T  
<taglib>的子元素 Gt-UJ-RR y  
vNDu9ovs-  
Element 3Qn!y\#  
Description mY-hN|  
Le#spvV3J|  
tlib-version 1|| nR4yK  
Tag库的版本 LR&_2e^[  
m5c&&v6%"b  
jsp-version pbBoy+.>  
Tag库所需要的jsp的版本 +wfVL|.Wq  
/b[2lTC-e  
short-name !{UTD+|=N  
助记符,tag的一个别名(可选) *b|NjwmB  
Te-Amu  
uri mOBACTY^  
用于确定一个唯一的tag库 TwahR:T   
Dd $qQ  
display-name )N !>=  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) zF&=U`v  
+]wuJSxc  
small-icon q9*MNHg }  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) ?u$u?j|N  
L'A)6^d@S  
large-icon Y "jE'  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) .zj0Jy8N  
 HEF?mD3h  
description ^ 4>k%d  
对tag库的描述(可选) -K %5(Eg  
\OwpD,'  
listener v/Pw9j!r;m  
参见下面listener元素 <PD?f/4 /  
WI[:-cv  
tag FY'dJY3O  
参见下面tag 元素 `N8 7 h"  
5 t{ja  
Listener元素 5f7zk  
a:Q[gF8>  
一个tag库可能定义一些类做为它的事件侦听类,这些类在TLD中被称为listener 元素,jsp服务器将会实例化这些侦听类,并且注册它们。Listener元素中有一个叫listener-class的子元素,这个元素的值必须是该侦听类的完整类名。 Z|m`7xeCy  
\=2m7v#E  
Tag元素 Wch~ Yb  
CXaWgxlK:a  
每个tag元素在tag库中都要指出它的名字、类名、脚本变量、tag的属性。其中脚本变量的值可以直接在TLD中定义或通过tag附加信息的类来取得。每个属性描述了这个属性是否可以省略,它的值是否可以通过<%= …%>这样的JSP语法来获得,以及属性的类型。 fw-\|fP  
iLX_T]1  
每一个tag在TLD中对应一个tag元素,下表是tag元素的子元素: p<GR SJIk=  
!PUZWO  
Tag元素的子元素 X&\d)/Y  
F2I 5q C/  
元素名称 Fd$!wBL  
描述 9";sMB}W*  
=?Fkn4t  
name nHOr AD|&  
独一无二的元素名 kBWrqZ6  
](0mjE04<d  
tag-class GHc/Zc"iX  
Tag标签对应的tag处理类 =\kMXB  
{3\R|tZh,`  
tei-class wxQ>ifi9Z  
javax.servlet.jsp.tagext.TagExtraInfo的子类,用于表达脚本变量(可选) %j,iAUE<  
^rAa"p9  
body-content +OaUP*\Dd  
Tag标签body的类型 K?.e|  
U>qHn'M  
display-name ODw`E9  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) Xq#Y*lKVD  
2)0b2QbQ  
small-icon |`rJJFA  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) M4f;/`w  
U.0kR/>Z=  
large-icon !X^Ce)1K  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) &Z("D7.G  
n{5NNV6  
description ,XKCz ]8V  
此tag标签的描述 sH#X0fG  
_=f=fcl  
variable :3ZYJW1  
提供脚本变量的信息(同tei-class)(可选) b'p4wE>  
DT(d@upH  
attribute " {de k  
Tag标签的属性名 #CUz uk&  
o+O}Te  
以下章节介绍对于不同类型的tag,如何具体地实现它们。 [:;# ]?  
n%%7KTqu  
?;ukvD  
简单的tag -.I4-6~  
hlJpElYf  
IzLF'F  
tag处理类 -6~'cm  
v1G"3fy9  
简单的tag处理类必须实现Tag接口的doStartTag和doEndTag方法。当jsp引擎碰到tag标签的开头时,doStartTag被调用,因为简单的tag没有body,所以此方法将返回 SKIP_BODY。当jsp引擎碰到tag标签的结尾时,doEndTag被调用,如果余下的页面还要被计算,那它将返回EVAL_PAGE,否则将会返回SKIP_PAGE。 $9!D\N,}]C  
XVVD 0^ Q  
以下是例子:对于标签 <tt:simple /> ,它的tag处理类实现如下: Z9`TwS@x[  
~W0(1# i  
~eh0[mF^]  
public SimpleTag extends TagSupport #& .]" d  
&p(0K4:  
{ vRQOs0F;  
K|S:{9Q  
public int doStartTag() throws JspException i?@M  
s<QkDERMX  
{ F3U`ueP  
a|j%n  
try{ -b;|q.!  
rVSZ.+n  
pageContext.getOut().print(“Hello.”); `u'bRp  
]c)_&{:V  
}catch(Exception e){ |+,[``d>"  
Td\o9  
throw new JspTagException(“SimpleTag: “ + e.getMessage()); O'*@ Ytn  
afEF]i  
} 1`bl&}6l|E  
I s57F4[}  
return SKIP_BODY; L,[;k  
TbVn6V'  
} < Bg8,;  
AasZuO_I  
public int doEndTag() `RRE(SiKU  
R=j% S!  
{ M" lg%j  
3.Gj4/f  
return EVAL_PAGE; /s:fW+C  
bJ /5|E?  
} _D7]-3uC!  
m#e3%150{  
} LaMLv<)k  
csZ c|kDI  
<W)u{KS#TY  
注意:如果tag标签没有内容的话,那必须定义body-content元素为空,例如 A=5epsB  
q%YV$$c   
<body-content>empty</body-content> R,2P3lv1v@  
bO5k6i  
w(d>HHg  
带属性的tag标签
评价一下你浏览此帖子的感受

精彩

感动

搞笑

开心

愤怒

无聊

灌水
级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
只看该作者 1 发表于: 2007-01-01
tag处理类 ~p0c3*  
K0pac6]  
对于tag标签的每个属性,你必须依照JavaBeans规范来定义其属性,以及get和set方法。以struts的logic:present 标签为例, sM[I4 .A3  
_6@hTen`  
<logic:present parameter=”Clear”> UaG1c%7?X  
3riw1r;Q  
与此相应,此tag处理类应有如下方法和定义: UYP9c}_,4  
_jU5O;  
Ter :sge7  
protected String parameter = null; zvc`3  
zSvgKmNY  
public String getParameter() *u6Y8IL1  
(h-*_a}F4  
{ ,Tagj`@bHc  
oB1>x^  
return this.parameter; gR^>3n'  
 $!@\  
} -Ng'<7  
Flxvhl)L  
public void setParameter(String parameter) 6R;3%-D  
q"qo.TPh|$  
{ E\ 8  
b,TiMf9},h  
this.parameter = parameter; V&]DzjT/  
#L}+H!Myh  
} -5l6&Y   
lfsqC};#\  
HL3XyP7  
注意:如果你的属性名为id,而且你的tag处理类是从TagSupport类继承的,那你就不需要定义它的属性和set和get方法,因为他们早已在TagSupport被定义过了。 /e}#' H   
=QJRMF  
Attribute元素 DaHZ{T8>d  
Pl=]Srw  
对于tag标签的每个属性,你必须定义它是否必须的,它的值是否可以用诸如<%= …%>的表达式来获得,以及它的类型(可选),如果不指定它的类型,那就默认为是java.lang.String类型。如果rtexprvalue元素被定义为true或yes,那么在type元素中就定义了attribute的返回类型。 c?2MBtnu  
J<gJc*Q  
<attribute> h&3YGCl  
ZSy?T  
<name>attr1</name> 9Mp$8-=>7  
g.JN_t5  
<required>true|false|yes|no</required> x"P);su  
?rX]x8iP  
<rtexprvalue>true|false|yes|no</rtexprvalue> HS>f1!  
,6^ znOt  
<type>attribute的返回类型(只用当rtexprvalue为真是才有效)</type> C`jM0Q  
;^Sr"v6r>u  
</attribute> (m[bWdANnW  
M@1r:4CoKH  
如果tag的某个属性不是必须的,那tag处理类会自动提供一个缺省值。 vR6Bn  
k^ F@X  
例如,在logic:present这个tag标签中定义了一个属性叫parameter,但它不是必须的,而且它可以被诸如<%= …%>的表达式来赋值。 5l-mW0,MK  
8N%Bn&   
<tag> _/*U2.xS  
^>y@4qB  
<name>present</name> 2 !" XzdD  
c)md  
<tag-class>org.apache.struts.taglib.logic.PresentTag</tag-class> $/1c= Y@  
f&,{XZ  
<body-content>JSP</body-content> >evS} O6  
R =Ws#'  
Nr<`Z  
mnk"Vr` L  
<attribute> { x0t  
6C4'BCYW(  
<name>parameter</name> +|Hioq* ,t  
; |/leu8  
<required>false</required> "P@>M)-9Z  
XNM a0  
<rtexprvalue>true</rtexprvalue> gkBdR +  
CRve.e8J  
</attribute> 4n1; Bh$  
%ows BO+  
yV3^Qtb!  
ZD#9&q'4<  
</tag> \AUI|M;'  
 8@{OR"Ec  
kPBV6+d~  
属性元素的校验 {K{EOB_u  
Xd E`d.  
r,goRK.  
有关于tag标签的有效值可以从tag库的说明文档中获得,当JSP页面被编译时,jsp引擎会强制性地参照TLD中定义的规则进行检查。 Hd7,ZHj3 ^  
C9DJO:f.2y  
还有一个方法也可以进行属性元素的校验,就是先继承类TagExtraInfo,然后调用它的isValid方法。这个类同时也起到提供tag中定义的脚本变量信息的作用。 H2xeP%;$  
o`zr>  
IsValid方法通过TagData对象来传递属性信息,它包括着tag的所有的属性名-值的信息。由于校验发生在运行时刻,因此这个属性的值将被赋值为TagData.REQUEST_TIME_VALUE。 :!;'J/B@..  
I|-p3g8\  
例如tag标签<tt:twa attr1=”value1” />在TLD中定义如下: ?;YC'bF  
@pI5lh  
<attribute> f=!PllxL:  
CxhY$%C (L  
<name>attr1</name> d8SE,A&  
m\>a,oZH  
<required>true</required> %B 5r"=oO  
Fhz*&JC#  
<rtexprvalue>true</rtexprvalue> l:6,QaT1  
@=]~\[e\  
</attribute> G'zF)0oD  
7J28JK  
n 26Y]7N  
这个定义说明了attr1能在运行期间被赋值。 \? j E#^  
"!>DX1rsi  
以下的isValid方法检查attr1属性的值是否属于Boolean类型。注意由于attr1能在运行刻被赋值,那么isValid方法必须检查tag用户是否对此tag进行了运行时刻赋值。 ]u-]'P  
I]Tsz'T!9  
5 )2:stT73  
Public class TwaTEI extends TagExtraInfo ]W0EVf=,k  
BYW^/B Y)  
{ @''GPL@  
(\"k&O{  
public boolean isValid(Tagdata data) 6ZgU"!|r  
cr?7O;,  
{ to8X=80-3  
&bqT /H18  
Object o = data.getAttribute(“attr1”); }7G8|54t  
FG3UZVUg9  
If(o != null && o != TagData.REQUEST_TIME_VALUE) dw~p?[  
"x941 }  
{ ]Q "p\@\!  
wi8Yl1p]!z  
if( ( (String)o).toLowerCase().equals(“true”) || }~h'FHCC+  
_UE)*l m+  
((String)o).toLowerCase().equals(“false”) ) z|?R/Gf8  
hqk}akXt  
return true; h=kQ$`j6  
1iL 'V-y  
else 0w'j+  
GEjd7s]C  
return false; Sx*oo{Kk%  
P^MOx4  
} ]Ni$.@Hu$  
2M)]!lYy  
else b,P]9$Ut  
~ `>e5OgOJ  
return true; qj0 1]  
'`Bm'Dd  
} :[@ k<8<]  
,U*)2`[  
} s{ V*1$e~  
; )Kh;;e  
&`Y!;@K9W#  
带body的tag xX0-]Y h:  
PqNFyQkl  
<)g8y A  
tag处理类 PCd0 ?c   
KucV3-I  
VHOfaCE  
如果tag标签含有内容,那处理方式会略微有些不同,而且还要视tag处理类是否要与body交互的情况而定。如果要与body交互,那我们认为tag处理类要可能要对body进行操作。 xRu Fuf8  
Mh(]3\  
Tag处理类不与body交互 6m.k;'  
V~GWl1#7  
如果tag处理类不与body交互,tag处理类应该实现Tag接口或从TagSupport中派生,如果body要被计算,那么doStartTag方法应返回 EVAL_BODY_INCLUDE,否则应返回SKIP_BODY。 1%M&CX  
b1pQ`qt  
如果tag处理类要对body反复运算,则它应该实现IterationTag或从TagSupport中派生。如果tag处理类认为body还未计算完的话,那它的doStartTag方法和doAfterBody方法必须返回EVAL_BODY_AGAIN。 CV$],BM  
at!Y3VywG  
Tag处理类与body交互 l ?Y_~Wuw  
L_Q#(in  
如果tag处理类与body交互,那tag处理类应实现BodyTag接口或从BodyTagSupport中派生。这种tag处理类一般要实现doInitBody和doAfterBody方法。 d;Hn#2C  
syx\gz  
Body允许一些方法来读写它的内容。Tag处理类可以调用body内容的getString或getReader方法来从body中提取信息,也可用 writeOut(out) 方法来将body的内容写入到out对象中。其中out对象通过tag处理类的getPreviousOut方法来获得。 G.+l7bnZM  
B) $c|dUV  
如果body的内容需要被计算,那么doStartTag方法必须返回EVAL_BODY_BUFFERED,否则,它将返回 SKIP_BODY。 WWwUwUi  
oRN-xng  
doInitBody 方法 %CZ-r"A  
}}QTHR  
此方法在body内容已经设好,但未被计算之前被调用。你可以根据不同的body内容来制定初始化策略。 G{aT2c  
TUL_TR  
doAfterBody方法 s57N) 0kP  
sGY_{CZ:  
此方法在body内容已被计算后进行调用。 k>}g\a,  
bf_I9Z3m  
和doStartTag方法一样,doAfterBody方法返回一个指示符指示是否要继续计算body,如果要继续计算,则doAfterBody应返回EVAL_BODY_BUFFERED,否则,它应返回SKIP_BODY。 NRnRMY-  
0U66y6  
release 方法 )PkNWj6%y  
-B#yy]8  
tag处理类调用此方法将它的状态重置为初始状态,并释放所有的私有资源。  g]*  
S gMrce<;  
HQ9f ,<  
以下的例子读取body的内容(其中含有一条sql语句),然后将它传递给一个对象,让它进行查询。由于此处body不须重新计算,所以doAfterBody会返回SKIP_BODY。 F Kc;W  
E}CiQUx  
R cY>k  
Public class QueryTag extends BodyTagSupport kH*Pn'  
3`hUo5K  
{ >idBS  
ezhDcI_T  
public int doAfterBody() throws JspTagException [MX;,%;;  
^/wfXm  
{ [#" =yzR<3  
*y`%]Hy<  
BodyContent bc = getBodyContent(); j^`X~gE  
F} J-gZl  
//将body的内容以字符串的格式提取出来 /9Q3iV$I]  
nM=e]qH  
String query = bc.getString(); 1{pmKPu  
"%WgT2)m.  
//清除body z2ms^Y=j  
Ap&)6g   
bc.clearBody(); J MX6yV  
|1Dc!V'?"  
try{ +i `*lBup$  
L~{_!Q  
Statement stmt = connection.createStatement(); LiDvaF:@L!  
dGZntT 2D  
Result result = stmt.executeQuery(query); RhF>T&Q  
-O:_!\uA  
}catch(SQLException e){ hlvt$Jwq  
| sqZ$Mu  
throw new JspTagException(“queryTag: “ + e.getMessage() ); R~L0{` 0  
tc_f;S`k  
return SKIP_BODY; wYeB)1.  
h*0S$p<[1  
} {s,+^7  
f<i7@%  
} Rg29  
F9c`({6k  
RnVtZ#SCh  
body-content元素 O|kKwadC  
"re-@Baw  
u#W5`sl  
由于tag可能会有body,你必须用body-content元素来指定body内容的类型: z `8cOK-  
C>^D*C(  
<body-content>JSP|tagdependent</body-content> 4kp im  
,zcQS-e2  
U IJx*  
如果body的内容是定制的或内部的tag、脚本元素、或HTML广本,则归类为JSP类型。其他的类型,比如上面代码所述的?D?D将sql statement类传给 query tag的这种类型应该标为tagdependent。 5FvOznK^e  
qOCJTOg7  
注意:实际上body-content的值并不影响tag处理类对body内容的处理,它仅仅是被tag编辑工具用来描述此body的内容。 4}v@C|.p  
ofc.zwH  
HCA{pR`  
用tags定义脚本变量 $X`y%*<<v  
x!S;SU  
P sjbR  
tag处理类 O[~x_xeW  
2)iD4G`  
= Je>`{J  
tag处理类负责创建或设置页面中定义的脚本变量,用pageContext.setAttribute(name,value,scope)或pageContext.setAttribute(name,value)方法来实现。一般来说,tag处理类通过脚本变量的名称来获取它,脚本变量的名称一般可用get方法来获得。 R5Yl1   
huFz97?y(  
如果脚本变量的值依赖于tag处理类中的上下文中某一对象,那它可用pageContext.getAttribute(name,scope)方法来找到那个对象。一般的处理过程是tag处理类先找到脚本变量,再对其进行处理,然后用pageContext.setAttribute(name,object)的方法来设置它的新值。 ,a|@d} U  
)9"oL!2h  
对象的生存周期(scope)如下表: suJ_nb  
U0B2WmT~Q  
对象的生存周期表  ~m=EM;  
Hy; Hs#  
名字 uPyVF-i  
可访问范围 E,G<_40  
生存周期 >.9eBz@  
%(m ])  
page Rz <OF^Iy  
当前页面 GrEs1M1]*  
一直有效,除非页面向客户提交响应或重定向到一个新页面 U)jUq_LX  
oT+(W,G  
request #mc!Wt 10  
当前页面或当前页面重定向到的页面 _"f  :`  
一直有效,除非页面向客户提交响应 sLh0&R7   
/9ZcM]X B  
session uZjI?Z.A  
当前页面或在同一浏览器窗口中的页面 0LVE@qEL  
一直有效,除非关闭当前浏览器、超时、网络故障 WnxEu3U  
"X1vZwK8N  
application gy_$#e  
整个web应用程序的所有请求 eMMx8E)B  
一直有效,除非发生网络故障、服务器故障 +H'\3^C-  
H3FW52pjX  
提供关于脚本变量的信息 4I~i)EKy6  
n[k1np$7?6  
以下示例定义了一个名为“book”的脚本变量,用来访问程序中关于书的信息: ?T*";_o,B  
OD9 yxN>P  
<bean:define id=”book” name=”bookDB” property=”bookDetails” type=”database.BookDetails” /> *K!++k!Ixa  
I@Z)<5Zf  
<font color=”red” size=”+2” > x !{   
crmUrF#  
<%= messages.getString(“CartRemoved”) %> CmC0k-%w  
>q( 5ir  
<strong><jsp:getProperty name=”book” property=”title” /></strong> [B/0-(?  
# mT]j""  
</font> jz:gr=* z  
iyM^[/-R6  
当包含此tag的JSP页面被编译时,jsp引擎会自动生成关于此book的同步的代码(同步可以避免几个客户同时访问此book时造成的冲突),要生成同步代码,jsp引擎需要知道此脚本变量的如下信息: bkQ3c-C<  
mN1Ssq"B  
· 脚本变量名称 +uQB rG  
ijZ>:B2:  
· 脚本变量所属的类 *Zkss   
rY70 ^<z  
· 此脚本变量是否引用了一个新的或已存在的对象 vZjZb(jlN  
: }?{@#Z  
· 此脚本变量的有效性 #s"B-sWE  
-CBD|fo[h  
有两种办法可以向jsp引擎提供关于脚本变量的信息:在TLD中定义variable子元素,或用tei-class子元素定义一个额外tag信息类。用variable最简单,但可能降低了一些灵活性。 i^|@"+  
jMU9{Si  
Variable元素 jXIEp01  
p5*lEz|$  
Variable元素有如下子元素: =MSu3<y,  
m6n hC  
· name-given ?D?D 给出的名字,是一个常量 X%4h(7;v  
!Yh}H<w0  
· name-from-attribute?D?D 属性名,在编译时给出的属性名 pCt}66k}  
#)74X% 4(  
name-given或name-from-attribute两者必须选一,但以下子元素是可选的: 0'yyfz  
DX@}!6|T  
· variable-class?D?D变量的类型,缺省为java.lang.String。 FBY ODw  
{+=i?  
· declare?D?D此脚本变量是否引用了一个新对象,缺省为True。 `SOhG?Zo  
LM1b I4  
· scope?D?D脚本变量的范围,缺省为NESTED。下表描述了scope的几种类型: 'j79GC0  
%W;u}`  
脚本变量的有效范围 c^S&F9/U*  
|9s wZ[  
&'O?es|Lb  
有效性 nFXAF!,jj  
方法 epVH.u%  
YNM\pX'  
NESTED 8~5|KO >F  
在tag标签的开始和结束之间 S}gD,7@  
如果tag处理类实现BodyTag接口,则在doInitBody和doAfterBody中调用,否则在doStartTag中调用 Z=9dMND  
.cR*P<3O  
AT_BEGIN 60PYCqWc  
从tag标签的开始一直到页面结束 BX$hAQ(6Q  
如果tag处理类实现BodyTag接口,则在doInitBody、doAfterBody和doEndTag中调用,否则在doStartTag和doEndTag中调用 `Cj,HI_/*  
ryEvmWYu  
AT_END 3 jh|y,  
从tag标签的结束一直到页面结束 ,OB&nN t>  
在doEndTag中调用 Nmf#`+7gCI  
<nA3Sd"QfV  
以struts为例,它的bean:define标签的实现遵循JSP1.1规范,此规范要求使用额外tag信息类来定义脚本变量。Variable元素是JSP1.2规范中加入的。以bean:define标签为例,你可以定义如下variable元素: %FS;>;i?  
l<RfRqjw  
<tag> \Da~p9 T&  
SJ(9rhB5*.  
<variable> {HuLuP 0t  
@,vv\M0)p  
<name-from-attribute>id</name-from-attribute> OK\]*r  
M(S{1|,V  
<variable-class>database.BookDetails</variable-class>  y h-9u  
>4'21,q  
<declare>true</declare> VRhRwdC  
8|<f8Z65!  
<scope>AT_BEGIN</scope> P%!q1`Eke(  
Mcb<[~m  
</variable> \>[gl!B_Rr  
M9g1d7%  
</tag> AI fk"2  
w:R]!e_6\9  
额外tag信息类 V'yxqI?  
yHw!#gWM  
如果要定义一个额外tag信息类,你要继承javax.servlet.jsp.TagExtraInfo类。一个TagExtraInfo类必须实现getVariableInfo方法,此方法返回一个叫VariableInfo的数组类,它包括如下信息: bV7QVu8  
rxkBg0Z`a  
· 变量名 m t.,4  
4`0;^K.  
· 变量所属类名 +-k`x0v  
/O"0L/hc^  
· 此变量是否引用了一个新对象 gT7I9 (x!W  
$y4M#yv  
· 此变量的有效范围 JOHp?3"4  
Bcm=G""  
jsp引擎将一个名为data的参数传给getVariableInfo方法,data中包括tag标签中的所有“属性名?D?D属性值”对。它可以用来向VariableInfo对象提供脚本变量的名字和类名。 %#Q #N,fw  
7eH@n <]Y2  
以struts为例,它在bean:define标签中定义了一个名为DefineTei的额外tag信息类,用来向脚本变量提供信息。由于脚本变量的名称(book)和类名(database.BookDetails)是通过tag标签的属性来传递的,它们一般定义在VariableInfo的构建代码中,并且可用data.getAttributeString方法来得到这些信息。如果要允许book脚本变量能在从tag开始直到整个JSP页面结束的范围内都可用的话,那它的范围应设为AT_BEGIN。如下所示: /2'c>  
~p!QSRu~,b  
Px#4pmz  
public class DefineTei extends TagExtraInfo Sh47c4{  
m[#%/  
{ )XZ,bz*jn  
iy9VruT<x  
public VariableInfo[] getVariableInfo(TagData data) Ko}7$2^  
&@Yoj%%  
{ Es,0'\m&  
%,E7vYjT%  
String type = data.getAttributeString(“type”); fa.f(c  
L%4tw5*N  
If( type == null) C$0 ITw  
.?7So3   
type = “java.lang.Object”; h@/>?Va  
LQ|<3]  
return new VariableInfo[] { Ae3#>[]{  
9 &[\*{  
new VariableInfo(data.getAttributeString(“id”), '.xkn{c  
33S`aJ  
type, ~M(pCSJ[  
a\|X^%2g  
true, B)(w%\M4^  
"URVX1#(r  
VariableInfo.AT_BEGIN) kfIbgya   
&A#90xzF  
}; D`5: JR-{  
5vl2yN  
} EID(M.G  
-kt1t@O  
} ,9+nfj  
*+# k{D,  
T)*l' g'  
注意:关于额外tag信息类的类名必须要在TLD中的tag标签下的tei-class子元素中定义。因此,DefineTei的tei-class中的定义看起来如下: uFa-QG^Y{  
<tei-class> |HT)/UZ|  
org.apache.struts.taglib.bean.DefineTagTei $jDD0<F.#  
</tei-class> ;vZ*,q6  
ug>]U ~0  
E ,Dlaq  
具有协作关系的tag )z|_*||WU^  
R7y-#?  
.|tQ=l@I  
tag通过共享对象来进行协作,JSP技术支持2种方式的对象共享。 iNMLYYq]l  
7E@$}&E  
第一种方法是使用pageContext对象进行对象的共享(可支持JSP页面和tag处理类之间的共享),如果在一个tag处理类中要调用由另一个tag处理类创建的对象,可调用pageContext.getAttribute(name, scope)方法。 W'8J<VBD  
;%lJD"yF  
第二各方式的共享是对于tag之间有嵌套关系而言的,外层的tag所创建的对象对于内层的tag来说是可以共用的。这种形式的共享的好处是减少了可能存在的重名冲突。 HX z iDnj  
r{c5dQ  
要访问一个嵌套tag创建的对象,tag处理类必须先找到此嵌套tag对象,可用TagSupport的静态方法 TagSupport.findAncestorWithClass(from, class)或TagSupport.getParent方法。前者在当不确定此tag是否为嵌套tag对象时使用。一旦它的父类被找到,它就能访问其所有动态或静态创建的对象。静态创建的对象是父类的成员,而动态创建的对象可能是父类的私有对象。诸如此类的对象可以用tag处理类的setValue方法来保存,用getValue方法来获得。 1Z=;Uy\  
zbdOCfA;  
下例阐述了以上两种共享对象的方法。在这个例子当中,一个查询tag检查一个名为connection的属性名是否在doStartTag中被设置。如果connection属性被设置,tag处理类从pageContext中得到这个connection对象。否则,此tag处理类先找到它的父tag处理类,然后从它的父tag处理类中找到connection对象。 UeC 81*XZ  
uV#-8a5!  
</~1p~=hAt  
public class QueryTag extends BodyTagSupport 1j8/4:  
Cf.WO%?P  
{ thR|h+B  
pPU2ar  
private String connectionId; F12S(5Z0%  
6i55Ja  
public int doStartTag() throws JspException 4h[2C6 \+`  
U Ek |8yq  
{ 7UY('Q[  
pyGFDB5_P  
String cid = getConnection(); &FT5w T  
qLU15cOM  
if(cid != null) Ul7,k\q@  
 ||bA  
{ noWRYS%  
wK/}E h\^  
//存在一个connection id,使用它。 8kKRx   
t>fA!K%{  
connection = (Connection) pageContext.getAttribute(cid); aA!@;rR<yU  
8JFnB(3xU  
} OsDp88Bc  
$,!dan<eA  
else |YMzp8Da(  
n/,rn>k7:  
{ \f ~u85  
?^F*"+qI  
ConnectionTag ancestorTag = (ConnectionTag)findAncestorWithClass(this,  'lSnyW{  
~`a#h#  
ConnectionTag.class); h/fb<jIP1  
$u(M 4(}  
if(ancestorTag == null) $NH`Iu9t  
0YgFjd 5  
{ G*kXWEx  
([z<TS#Md  
throw new JspTagException(“一个没有connection属性的查询标签必须被一个connection标记嵌套。”); H"kc^G+(R"  
vUA)#z<  
} w0F:%:/  
Rq~ >h99M  
connection = ancestorTag.getConnection(); n:{-Vvt  
6ba2^3GH  
} 23.y3t_?  
MV:<w3!  
} Z)b)v  
!IQfeo T  
} "oKj~:$  
Vf#oKPP1  
F5om-tzy  
4@ydK  
此查询标签在JSP页面中的调用形式可以从以下2种定义中任选一种: rZwf%}  
4rGO8R  
4OB~h]Vc  
<tt:connection id=”con01” ...> ... </tt:connection> y"%iD`{  
_AsHw  
<tt:query id=”balances” connection=”con01” > kfG65aa>_  
[7ek;d;'t  
SELECT account, balance FROM acct_table h|Teh-@A5  
_ cHV3cz  
where customer_num = <%= request.getCustno() %> Dg];(c+/  
96([V|5K  
</tt:query> 7J </7\  
?3KR(6D  
;NN(CKZ9A  
2*3B~"  
>V ]*mS %K  
<tt:connection ...> } (O D<  
3HDnOl8t  
<x:query id=”balances”> SFXfo1dqH  
[f0oB$  
SELECT account, balance FROM acct_table )e <! =S  
r5fz6"  
where customer_num = <%= request.getCustno() %> eO[Cb]Dy:  
bo?3E +B  
</x:query> ]CtoK%k  
e-duZ o  
</tt:connection> DftGy:Ah3  
0wa!pE"  
Ot8S'cB1,$  
与此同时,在TLD中必须指定connection属性为可选的,定义如下: !<UEq`2  
Z1MJ!{@6  
<tag> ?AM 8*w  
:w&)XI34  
... S &lTKYP  
%I2xK.8=  
<attribute> 2 |kH%  
AcfkY m~  
<name>connection</name> X?k V1  
4q 2=:"z4  
<required>false</required> M}KM]<  
")[Q4H;V  
</attribute> 8bKWIN g_n  
Bafz&#;Q'  
</tag>
描述
快速回复

您目前还是游客,请 登录注册
如果您在写长篇帖子又不马上发表,建议存为草稿
认证码:
验证问题:
3+5=?,请输入中文答案:八 正确答案:八