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

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

级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
标准的JSP 标记可以调用JavaBeans组件或者执行客户的请求,这大大降低了JSP开发的复杂度和维护量。JSP技术也允许你自定义taglib,其实换句话说,taglib可以看成是对JSP标记的一种扩展,正如xml是对html的一种扩展一样。taglib通常定义在tag标签库中,这种标签库存放着你自己定义的tag标签。简而言之,如果使用taglib,那么你可以设计自己的JSP标记! (t V T&eO  
Gds(.]_  
一般来说,自定义tag标签主要用于操作隐藏对象、处理html提交表单、访问数据库或其它企业级的服务,诸如邮件和目录操作等等。自定义tag标签的使用者一般都是那些对java编程语言非常精通,而且对数据访问和企业级服务访问都非常熟悉的程序员,对于HTML设计者来说,使得他可以不去关注那些较复杂的商业逻辑,而将精力放在网页设计上。同时,它也将库开发者和库使用者进行合理分工,自定义tag标签将那些重复工作进行封装,从而大大提高了生产力,而且可以使得tag库可用于不同的项目中,完美地体现了软件复用的思想。 R-NM ~gp  
+"BJjxG  
在这篇文章中,我们主要讨论: ]>Z9K@  
o/V T"cT  
· 什么是自定义tag标签? .AO-S)wHR  
zT6nC5E  
· 怎么使用tag标签? gYrB@W; 2  
9@ fSO<  
o 声明要使用的tag库 TB.>?*<n]  
: Bo  
o 找到与之对应的tag处理类 f"j9C% '*  
Q Kr/  
o tag标签的类型 ak| VnNa]  
E' `;  
· 自定义tag标签 fi*b]a\'  
xl,% Z~[  
o tag处理类 L YB @L06a  
R59iuHQ[  
o tag库描述 SZ[?2z  
a$Ud"  
o tag标签示例 .(cpYKFX  
l P=I0A-  
o 带属性的tag p~8O6h@J  
^L d5<  
o 带body的tag x X3I`  
X,3\c:  
o 定义了脚本变量的tag =0EKrG  
[s]$&  
o 具有协作关系的tag H{5,  -x  
d1c+Ii%  
· 自定义tag标签 F5cN F 5  
ey[Z<i1  
o 一个迭代tag的例子 weu+$Kr  
 {p/Yz#  
o 一个模板tag库 tR<#CCtRp'  
rL"]m_FK  
o tag处理类到底是怎样被调用的? }F.k,2  
hO.b?>3NL  
qQDe'f~  
什么是自定义的tag? `!I/6d?A  
Os>&:{D4!  
一个自定义的tag标签是用户定义的一种JSP标记。当一个含有自定义的tag标签的JSP页面被jsp引擎编译成servlet时,tag标签被转化成了对一个称为tag处理类的对象进行的操作。于是当JSP页面被jsp引擎转化为servlet后,实际上tag标签被转化成为了对tag处理类的操作。 J>T98y/))  
z)^.ai,:0  
自定义tag标签有很多特色,诸如: OwNM`xSa|\  
0F- +)S?M[  
· 可以在JSP页面中自定义tag标签的属性 aL&egM*  
V~/@KU8cH  
· 访问JSP页面中的所有对象 sj/k';#g  
r7_%t_O|IL  
· 可以动态地修改页面输出 qvy*; <w  
SODHn9)  
· 彼此这间可以相互通信。你可以先创建一个JavaBeans组件,然后在一个tag中调用此JavaBeans组件,同时可以在另一个tag中调用它。 J`[jub  
)O+Zbn  
· tag允许相互嵌套,可以在一个JSP页面中完成一些复杂的交互。 l(Hz9  
JK!`uG+v  
|+HJ>xA4I  
使用tag标签 hVB(*WA^D  
\ Qx%7 6  
d\3 %5Y  
本节主要描述怎样在JSP页面中使用tag标签,以及tag标签的不同类型。 [+b8 !'|&  
Y{dX[^[  
要使用tag标签,JSP程序员必须做2件事: )XSHKPTQ1  
*^ G,  
· 声明此tag标签的tag库 SOsz=bVx  
2eRk_j]  
· 实现此tag标签 .7Yox1,  
fATVAv  
声明tag标签所在的tag库 ~QUNR?h  
Q -$) H;,  
如果要使用tag标签,则应用JSP的taglib指示符来指定其tag库(注意:taglib要在在使用此tag标签之前声明) |LLpG37_  
-"'+#9{h  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> +U ziO#D  
v8C($<3%  
uri属性定义了唯一的标签库描述(以下简称TLD),它可以是直接是tld文件名或一个独一无二的名字。prefix是用来区别其它TLD中和本TLD中有重名的tag的一种手段。 R%2.N!8v  
58HAl_8W  
TLD必须以.tld作为扩展名,并且存放在当前应用的WEB-INF目录或其子目录下。你可以通过它的文件名直接引用它,也可以通过别的方式间接地引用它。 a"O;DYh  
Q{=r9&&  
以下taglib指示符直接引用一个TLD: G,<d;:  
<"p-0=IgJ  
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %> U&*%KPy`  
2x|F Vp  
以下的taglib指示符通过一个逻辑名称间接地引用一个TLD: 5Zhl@v,L%  
0'A"]6  
<%@ taglib uri=”/tutorial-template” prefix=”tt” %> l+y;>21sTu  
7p!f+\kM  
如果是间接引用TLD的话,那你必须还要在web.xml中定义此逻辑名称与tld文件之间的映射,具体做法是在web.xml中加入一个名为taglib的元素: rZB='(?  
eG2'W  
<taglib> $A,YQH+  
t&x\@p9  
<taglib-uri>/tutorial-template</taglib-uri> U8>4ClJ4  
=Sr<d|\O  
<taglib-location> 7KUf,0D  
s}UJv\*  
/WEB-INF/tutorial-template.tld ct,;V/Dx  
gWjr|m<  
</taglib-location> O.y ?q  
4DL2 A;T  
</taglib> RSB+Saf.8  
W79.Nj2`  
6q`)%"4k  
实现此tag标签 )J+OyR=  
 o4yl3o  
q6sb;?I  
为了实现tag标签,你有2种方法来存放tag处理类。一、让tag处理类以.class的方式存放于当前应用的WEB-INF/class子目录下,二、如果tag处理类是以JAR包的形式存在的话,那可以放在当前应用的WEB-INF/lib目录下,如果tag处理类要在多个应用中共享,那么它就应放在jsp服务器上的common/lib目录下,对于tomcat来说,就是tomcat/common/lib目录下。 F+BCzsm7$  
O+< +yQl  
pih 0ME}z  
tag标签类型 c}),yQ|!:  
]^wr+9zd  
p NQ7uy  
自定义的tag标签遵循XML语法。它有一个开始标记和一个结束标记,有的还有body(即文本节点): ?0sTx6x@  
tfm3IX  
<tt:tag> X6t9*|C  
X+u1p?  
body NZ8X@|N  
"dOQ)<;  
</tt:tag> -nUK%a"(D  
P&[&Dj  
(IjM  
一个不带body的tag标签如下: 1!U:M8T|  
X6w+L?A  
<tt:tag /> .tHc*Eh  
HSU?4=Q  
`0_ Y| 4KB  
简单的tag标签 a ^juZ  
h|Qb:zEP,  
一个没有body和属性的tag标签如下: z_KCG2=5  
l:/x &=w  
<tt:simple /> Ets6tM`  
z"7X.*]  
8D?$@!-  
带属性的tag标签 Bzt:9hr6BO  
6r@>n_6LY  
*D[yA  
自定义标签可以有自己的属性。属性一般在开始标记中定义,语法为 attr=”value”。属性的作用相当于自定义标签的一个参数,它影响着tag处理类的行为。你可以在TLD中详细定义它。 Q 9f5}  
_.]mES|  
你可以用一个String常量给一个属性赋值,也可以通过表达式给它赋值,如<%= ...%>。以struts为例,它的logic:present标签就是用的String常量来给属性赋值: >/}p{Tj  
Fe: ~M?]  
<loglic:present parameter = “Clear”> eMV8`&c'  
IBu\Sh-  
而另一个标签logic:iterate是用表达式来给属性赋值: C v*K.T  
SG0PQ  
<logci:iterate collection=”<%= bookDB.getBooks() %>” ]Z=al`-  
-lv(@7o~  
id=”book” type=”database.BookDetails”> ~>0H k}Hv  
bBo>Y7%  
Tj<B;f!u  
带body的tag标签 bNm]h.  
x7i<dg&  
一个自定义标签可以包含其它自定义标签、脚本变量、HTML标记或其它内容。 DYgB_Iak  
W|n$H`;R  
在下述例子中,此JSP页面使用了struts的logic:present标签,如果些标签定义了parameter=”Clear”的属性,则将清除购物车的内容,然后打印出一条信息: ;<b7kepR  
ouFKqRs;  
<logic:present parameter=”Clear”> sD{Wc%5  
&u6n5-!v  
<% cart.clear(); %> oaILh  
/<k 5"C% z  
<font color=”#ff0000” size=”+2”><strong> VTyj<6Y  
IQ-l%x[fue  
你选择了清除购物车! EymSrZw  
7 &%#bMnw  
</strong></font> 9!Xp+<  
e0Gs|c+6  
</logic:present> S}]B|Q  
t6\--lk_  
-F3~X R  
到底是用属性还是用body来传递信息? mV4gw'.;7  
YH^@8   
如上所述,我们既可以通过属性,也可以通过body来传递信息。但一般来说,比较简单的类型,如字符串或简单表达式最好采用属性来传递信息。 Y(?SE< 4R  
\l 8_aj  
oEFo7X`t  
定义脚本变量的tag标签 aX |(%1r  
W5:fY>7  
所谓脚本变量,是指JSP中可以调用的变量或对象。它可由tag标签产生。以下示例阐述了一个tag标签定义了一个名为tx的由JNDI所定义的事务处理对象。脚本变量可以是ejb对象、事务、数据库连接等等: @qx$b~%  
Ss\?SEq  
<tt:lookup id=”tx” type=”UserTransaction” name=”java:comp/UserTransaction” /> qZ@d:u  
5tZ0zr  
<% tx.begin(); %> m!P<# |V  
.j**>&7L  
... mh SknyqT  
{{gt>"D,  
UTN[! 0[  
具有协作关系的tag标签 ~3f|-%Z  
[cl+AV "  
自定义tag标签之间可以通过共享对象来实现协作。在下述例子中,标签tag1创建了一个名为obj1的对象,在标签tag2仍可以重复使用obj。 Ip)u6We>I  
Yw5-:w0f  
<tt:tag1 attr1=”obj1” value1=”value” /> 7^LCP*  
A:yql`&s  
<tt:tag2 attr1=”obj1” /> +o"CMI  
yaWY>sB  
在以下这个例子当中,如果外层的tag标签创建了一个对象,那么其内层的所有tag标签都可以使用这个对象。由于这样产生的对象没有一个指定的名字,那么就可以将少重名的冲突。这个例子阐述了一系列协作的嵌套对象。 5 ddfdIp  
7-~)/7L  
<tt:outerTag> IA]wO%c  
C+5X8  
<tt:innerTag /> O/d]2<V  
KtH^k&z.f  
</tt:outerTag> nLv~)IQ}:  
u%I%4 gM  
E'(nJ  
Tag处理类 6 v~nEw  
7n+,!oJ  
`<| <1,  
Tag处理类必须实现Tag接口或BodyTag接口,不过现在一般都流行从TagSupport或BodyTagSupport类中继承,这些类或接口都可以在javax.servlet.jsp.tagext包中找到。 o8hE.pf&  
*vEj\  
当JSP引擎看到自己的JSP页面中包含有tag标签时,它会调用doStartTag方法来处理tag标签的开头,调用doEndTag方法来处理tag标签的结束。 T{"Ur :p  
&1&OXm$  
下表说明不同类型的tag所需要不同的处理过程: U,61 3G  
v2p0EOS  
Tag处理类的方法 [C<K~  
r)K5<[\r  
Tag标签类型 {&B_b|g*fW  
所调用的方法 MuP>#Vk  
=l${p*ABQ  
基本标签 rXE0jTf:a  
doStartTag, doEndTag, release 3/yt  
Y Q.Xl_  
带属性的标签 4>vO9q  
doStartTag, doEndTag, set/getAttribute1...N, release *n7=m=%)  
1EC;t1.7  
带内容的标签 ]j6K3  
doStartTag, doEndTag, release y,ub*-:  
#=33TvprR2  
带内容的标签,且内容重复循环 vTK8t:JQ~  
doStartTag, doAfterBody, doEndTag, release | B*B>P#  
|O oczYf  
带内容的标签,且内容与JSP交互 B7|%N=S%/  
doStartTag, doEndTag, release, doInitBody, doAfterBody, release ?CC.xE  
G e]NA]<  
一个tag处理类可以通过javax.servlet.jsp.PageContext来与JSP交互,通过javax.servlet.jsp.PageContext类,tag处理类可以访问JSP中的request、session和application对像。 ^,AE;Z T7  
<*dcl2xS  
如果tag标签是互相嵌套的,那内层的tag处理类可以通过它的parent属性来访问上层的tag处理类。 kD%MFT4  
?~t5>PEonv  
一般情况都将所有的tag处理类打成了JAR的包,以便于发布。 \=im{(0h  
7iwck.*  
j%-Ems*H  
Tag库描述(简称TLD) vcp{Gf|^  
H@$K /  
<HN+pi  
Tag库是用xml语言描述的,TLD包括了tag库中所有tag标签的描述,它一般用来被jsp服务器用来校验tag的语法正确性,或者被jsp开发者用来开发新的标签。 t&=bW<6  
HQ" trV  
TLD的文件扩展名必须为.tld,而且必须放在当前WEB应用的WEB-INF目录或其子目录中。 YlGUd~$`"+  
bPP@  
一个TLD的内容的开头必须遵守标准的XML开头,用于描述DTD和xml的版本,例如: I *sT*;U  
Us'JMZ~  
<?xml version="1.0" encoding="ISO-8859-1" ?> CrL9|78  
U]vUa^nG  
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd"> t=@d`s:R2  
TLD必须以<taglib>来作为它的根元素,<taglib>的子元素如下表: 3C%|src  
t,8?Tf+i  
*GBV[D[G,  
<taglib>的子元素 %aK[Yvo6  
]GY8f3~|{  
Element p}1gac_c  
Description <Z3C&BM  
iv6G9e{cx  
tlib-version -bOtF%  
Tag库的版本 )^s> 21  
lqL5V"2Y  
jsp-version I5l%X{u"N  
Tag库所需要的jsp的版本 iBbaHU*V  
*K$a;2WjzG  
short-name U!o  
助记符,tag的一个别名(可选) Sq_.RU  
OhCdBO  
uri sGtxqnX:J  
用于确定一个唯一的tag库 U+B"$yBR  
*v K~t|z  
display-name f['lY1#V1  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) ?#:']q  
Ezew@*(  
small-icon <|Lz#iV37  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) RxJbQs$Ph  
KNQj U-A  
large-icon yy8BkG(  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) zNKB'hsK  
r^C(|Vx  
description WR#h~N 9c  
对tag库的描述(可选) %u&Vt"6m=  
2(3Q#3V  
listener ,z#D[5  
参见下面listener元素 O^-QqCZE  
+,)k@OI  
tag E8sM`2z5  
参见下面tag 元素 Ar/P%$Zfq  
Y1sK sdV  
Listener元素 n5A|Zjk;  
R-Lpgi<a"  
一个tag库可能定义一些类做为它的事件侦听类,这些类在TLD中被称为listener 元素,jsp服务器将会实例化这些侦听类,并且注册它们。Listener元素中有一个叫listener-class的子元素,这个元素的值必须是该侦听类的完整类名。 Zh;}Q(w  
1/:vFX  
Tag元素 l }^ziY!  
B\rY\  
每个tag元素在tag库中都要指出它的名字、类名、脚本变量、tag的属性。其中脚本变量的值可以直接在TLD中定义或通过tag附加信息的类来取得。每个属性描述了这个属性是否可以省略,它的值是否可以通过<%= …%>这样的JSP语法来获得,以及属性的类型。 !] uB4  
CUpRtE8@[_  
每一个tag在TLD中对应一个tag元素,下表是tag元素的子元素: Sft vN-  
Z.@n7G  
Tag元素的子元素 p2b~k[  
[O_5`X9|  
元素名称 ['\R4H!x  
描述 EmUn&p%hI  
-wC}JVVcK  
name !L9|iC:8  
独一无二的元素名 P(8Yz W  
<eSg%6z  
tag-class =d5;F`m  
Tag标签对应的tag处理类 RXAE jzf   
=2GKv7q$x,  
tei-class yxpv;v:)=  
javax.servlet.jsp.tagext.TagExtraInfo的子类,用于表达脚本变量(可选) {e2ZW]  
4>L* 7i  
body-content BWYv.&=(  
Tag标签body的类型 )^qXjF  
*(r9c(xa  
display-name 7)#JrpTj%  
被可视化工具(诸如Jbuilder)用来显示的名称(可选) Il@K8?H@  
xh#_K@8  
small-icon ynMYf  
被可视化工具(诸如Jbuilder)用来显示的小图标(可选) R{A$|Ipaq  
mpwh=  
large-icon 6j {ynt  
被可视化工具(诸如Jbuilder)用来显示的大图标(可选) ^hZ0"c  
AdDR<IW  
description Ei]Sks V>*  
此tag标签的描述 I'{Ctc  
Vtj*O'0  
variable E,?IIRg&  
提供脚本变量的信息(同tei-class)(可选) z)*{bz]  
~0-)S@  
attribute 'Tqusr>lPY  
Tag标签的属性名 NF |[j=?  
c%b|+4 }x  
以下章节介绍对于不同类型的tag,如何具体地实现它们。 dly -mPmP  
X_ Lt{mf  
4<1V  
简单的tag kl1Q:  
jYAm}_?No  
>HwVP.~HN  
tag处理类 17l?li  
ircL/:  
简单的tag处理类必须实现Tag接口的doStartTag和doEndTag方法。当jsp引擎碰到tag标签的开头时,doStartTag被调用,因为简单的tag没有body,所以此方法将返回 SKIP_BODY。当jsp引擎碰到tag标签的结尾时,doEndTag被调用,如果余下的页面还要被计算,那它将返回EVAL_PAGE,否则将会返回SKIP_PAGE。 .@;5"  
@m`H~]AU  
以下是例子:对于标签 <tt:simple /> ,它的tag处理类实现如下: e9:pS WA-n  
>^#Liwm  
8VG~n?y  
public SimpleTag extends TagSupport L* 6<h  
w0sy@OF  
{ ]1GyEr:  
 rB(Q)N  
public int doStartTag() throws JspException {s6#h#U  
VpbJe@*D  
{ x=W s)&H_Y  
4V]xVma  
try{ Ha ZV7  
SZtSUt(ss  
pageContext.getOut().print(“Hello.”); !](Mt?e  
dR,a0+!  
}catch(Exception e){ "<&o ;x<  
 8QKu  
throw new JspTagException(“SimpleTag: “ + e.getMessage()); 91a);d  
SZ4@GK  
} f::^zAV  
[CV0sYEA  
return SKIP_BODY; 67Tu8I/r  
I(j{D>v  
} [%Dh0hOg  
 _ qQ  
public int doEndTag() v )2yR~J  
O7&OCo|b%>  
{ Tn3C0  
K6~')9 Q  
return EVAL_PAGE; #=m:>Q?%z  
bgInIe  
} xw1,Wbu]  
Mcd K!V  
} t[b(erO'  
9(KffnE^  
K TE*Du  
注意:如果tag标签没有内容的话,那必须定义body-content元素为空,例如 -/7@ A  
wmP[\^c%$j  
<body-content>empty</body-content> H3JDA^5  
8L@@UUjr  
AMK3I`=8WO  
带属性的tag标签
评价一下你浏览此帖子的感受

精彩

感动

搞笑

开心

愤怒

无聊

灌水
级别: 终身会员
发帖
3743
铜板
8
人品值
493
贡献值
9
交易币
0
好评度
3746
信誉值
0
金币
0
所在楼道
只看该作者 1 发表于: 2007-01-01
tag处理类 @oMl^UYM=  
W5 RZsS]  
对于tag标签的每个属性,你必须依照JavaBeans规范来定义其属性,以及get和set方法。以struts的logic:present 标签为例, J\I`#  
"9H#pj -  
<logic:present parameter=”Clear”> kr]_?B(r  
 qJj5_  
与此相应,此tag处理类应有如下方法和定义: -]MZP:s  
UWBR5  
Cz4l  
protected String parameter = null; Y3luU&'  
! AL?bW  
public String getParameter() LS1}j WU!  
PF;`mdi-,  
{ ?eR^\-e  
,<CzS,(  
return this.parameter; $D#eD.  
u O~MT7~[X  
} <$'FTv  
/vFdhh  
public void setParameter(String parameter) 9t0NO-a  
&eX^ll  
{ hKp-"  
/57)y_ \  
this.parameter = parameter; Y<`uq'V  
I!,FxOM|$  
}  jQ?6I1o  
c5tCw3$t  
/ CVhvK  
注意:如果你的属性名为id,而且你的tag处理类是从TagSupport类继承的,那你就不需要定义它的属性和set和get方法,因为他们早已在TagSupport被定义过了。 Ps7Bt(/  
C&KH.h/N  
Attribute元素 D& #ph%U,P  
XhJbBVS|  
对于tag标签的每个属性,你必须定义它是否必须的,它的值是否可以用诸如<%= …%>的表达式来获得,以及它的类型(可选),如果不指定它的类型,那就默认为是java.lang.String类型。如果rtexprvalue元素被定义为true或yes,那么在type元素中就定义了attribute的返回类型。 ^0&   
:+\B|*T2.L  
<attribute> GbZqLZ0  
q%GlS=o "  
<name>attr1</name> FOd)zU*L2  
!XS ;&s7[*  
<required>true|false|yes|no</required> |Orp:e!  
Q+'QJ7fw'|  
<rtexprvalue>true|false|yes|no</rtexprvalue> 'I roQ M  
3)+}2  
<type>attribute的返回类型(只用当rtexprvalue为真是才有效)</type> D>Dch0{H,:  
r%~/y  
</attribute> ^< O=<tN\  
sKI{AHJ?X  
如果tag的某个属性不是必须的,那tag处理类会自动提供一个缺省值。 E%6}p++  
v9s /!<j  
例如,在logic:present这个tag标签中定义了一个属性叫parameter,但它不是必须的,而且它可以被诸如<%= …%>的表达式来赋值。 !Wz%Hy:ZK  
[1{uK&$e  
<tag> 0(!D1G{ul  
Ks@  
<name>present</name> 8P= z"y  
nv^nq]4'Dq  
<tag-class>org.apache.struts.taglib.logic.PresentTag</tag-class> t1)Qa(#]  
L<**J\=7M  
<body-content>JSP</body-content> 1FiFP5  
8Yq_6  
3jB5F0^r1  
J2W:Q  
<attribute> t)Mi,ljY[  
MxO0#  
<name>parameter</name> {@c)!% 2$  
b-rgiR$cg  
<required>false</required> m:,S1V_jl  
pIy+3&\e;  
<rtexprvalue>true</rtexprvalue> eS/4gM7%  
fYuz39#*  
</attribute>  k_;+z  
S0 AaJty  
#sK:q&/G`  
b]X c5Dp{  
</tag> 1 \_S1ZS  
11s*C #  
U!rhj&n  
属性元素的校验 7LM?<lp]  
6ZCSCBW  
ySLa4DQf  
有关于tag标签的有效值可以从tag库的说明文档中获得,当JSP页面被编译时,jsp引擎会强制性地参照TLD中定义的规则进行检查。 t`6R)'  
Ne)H*DT  
还有一个方法也可以进行属性元素的校验,就是先继承类TagExtraInfo,然后调用它的isValid方法。这个类同时也起到提供tag中定义的脚本变量信息的作用。 J~3+j6?%  
yrnIQu*Uu  
IsValid方法通过TagData对象来传递属性信息,它包括着tag的所有的属性名-值的信息。由于校验发生在运行时刻,因此这个属性的值将被赋值为TagData.REQUEST_TIME_VALUE。 #R<ErX)F  
0Y8Si^T  
例如tag标签<tt:twa attr1=”value1” />在TLD中定义如下: #G;0yB:76  
f?OFMac  
<attribute> 3(De> gs$  
+O 2H":$  
<name>attr1</name> u&HLdSHe  
$d]3ek/  
<required>true</required> #@QZ  
^Gc#D:zU  
<rtexprvalue>true</rtexprvalue> FaOfe]F  
y my/`%  
</attribute> SL9]$MmJn  
Q{ibH=^  
nwOT%@nw  
这个定义说明了attr1能在运行期间被赋值。 /T53"+7:0  
0:Ow$  
以下的isValid方法检查attr1属性的值是否属于Boolean类型。注意由于attr1能在运行刻被赋值,那么isValid方法必须检查tag用户是否对此tag进行了运行时刻赋值。 a9hK8e  
LZirw'  
:`~;~gW<  
Public class TwaTEI extends TagExtraInfo  \^$g%a  
i/j DwA  
{ K'6dlwn).  
oDtgB O<  
public boolean isValid(Tagdata data) %|&WcpQR  
2 1b  
{ ?U\@?@  
W$g<nhLK  
Object o = data.getAttribute(“attr1”); K\w:'%>-  
jA&ZO>4  
If(o != null && o != TagData.REQUEST_TIME_VALUE) j06q3N"  
Qy>n]->%  
{ $e bx  
eI%{/>  
if( ( (String)o).toLowerCase().equals(“true”) || gLyXe,Jp  
>5rb4  
((String)o).toLowerCase().equals(“false”) ) s4RqY*VK  
'<}N`PS#N  
return true; ws!pp\F  
8F?6Aq1B  
else op\'T;xIu  
) =KD   
return false; {yo<19kV@  
O;bnyB$  
} L_TM]0D>7  
ZCP r`H  
else rb"J{^  
8`QbUQ6  
return true; g4Y1*`}2f  
P2U^%_~  
} WOw( -  
fVb~j;  
} {5%u G2g  
36 &ghx  
'T!^H  
带body的tag t)!(s,;T  
qK_jgj=w  
>s 5i  
tag处理类 {`-f<>N3  
v[++"=< o8  
"s$$M\)T  
如果tag标签含有内容,那处理方式会略微有些不同,而且还要视tag处理类是否要与body交互的情况而定。如果要与body交互,那我们认为tag处理类要可能要对body进行操作。 K~1u R:DR  
';>]7oT`  
Tag处理类不与body交互 -2o_ L?  
, QB]y|:  
如果tag处理类不与body交互,tag处理类应该实现Tag接口或从TagSupport中派生,如果body要被计算,那么doStartTag方法应返回 EVAL_BODY_INCLUDE,否则应返回SKIP_BODY。 y.iA]Ikz  
U*p;N,SjQ  
如果tag处理类要对body反复运算,则它应该实现IterationTag或从TagSupport中派生。如果tag处理类认为body还未计算完的话,那它的doStartTag方法和doAfterBody方法必须返回EVAL_BODY_AGAIN。 r]sN I[  
&nKb<o  
Tag处理类与body交互 xF/u('A  
{5GXN!f  
如果tag处理类与body交互,那tag处理类应实现BodyTag接口或从BodyTagSupport中派生。这种tag处理类一般要实现doInitBody和doAfterBody方法。 4p}?QR>tZ  
zs=[C+Z\  
Body允许一些方法来读写它的内容。Tag处理类可以调用body内容的getString或getReader方法来从body中提取信息,也可用 writeOut(out) 方法来将body的内容写入到out对象中。其中out对象通过tag处理类的getPreviousOut方法来获得。 TJ_<21a  
sz"N,-<Ig  
如果body的内容需要被计算,那么doStartTag方法必须返回EVAL_BODY_BUFFERED,否则,它将返回 SKIP_BODY。 d~0k}|>  
JZ l"k  
doInitBody 方法 #YiphR&  
l;~b:[r  
此方法在body内容已经设好,但未被计算之前被调用。你可以根据不同的body内容来制定初始化策略。 )z" .lw  
Wb1?>q  
doAfterBody方法 A$7j B4  
|E}-j;(  
此方法在body内容已被计算后进行调用。 hw @)W  
6E)emFkQ  
和doStartTag方法一样,doAfterBody方法返回一个指示符指示是否要继续计算body,如果要继续计算,则doAfterBody应返回EVAL_BODY_BUFFERED,否则,它应返回SKIP_BODY。 qh]D=i  
6zZT5 Kn  
release 方法 6T9?C|q  
I2&R+~ktR  
tag处理类调用此方法将它的状态重置为初始状态,并释放所有的私有资源。 ]B2%\}c  
# n_gry!5  
O>KrTK-AV  
以下的例子读取body的内容(其中含有一条sql语句),然后将它传递给一个对象,让它进行查询。由于此处body不须重新计算,所以doAfterBody会返回SKIP_BODY。 kMz*10$gn  
1(diG&  
+I <^w)  
Public class QueryTag extends BodyTagSupport ['%$vnS5S  
)w_hbU_Pb&  
{ RSTA!?K/.  
?!Wh ^su-  
public int doAfterBody() throws JspTagException <K:L.c!  
* YR>u @  
{ H "; !A=0  
N hY`_?)  
BodyContent bc = getBodyContent(); G'<Ie@$6l  
EJid@  
//将body的内容以字符串的格式提取出来 N f^6t1se  
h`@z61UI  
String query = bc.getString(); e#<A\?  
8=-/0y9,  
//清除body s}93nv*ez  
;uhpo  
bc.clearBody(); B;A< pNT  
+v)+ k  
try{ e` eh;@9p  
3-T"[tCe  
Statement stmt = connection.createStatement(); }? :T*CJ  
,GY K3+}Z  
Result result = stmt.executeQuery(query); <"z9(t(V\%  
2~ y<l  
}catch(SQLException e){ f~R`RBZ]9  
Fp(-&,L0fc  
throw new JspTagException(“queryTag: “ + e.getMessage() ); WX&0;Kr  
S rom@c  
return SKIP_BODY; 3>#io^35  
eAK=ylF;  
} w?JM;'<AYQ  
) :st-I!o  
} ~(-df>  
R/\qDY,@  
qM(@wFg  
body-content元素 Rebo.6rG  
mNPz%B  
c{{RP6o/j=  
由于tag可能会有body,你必须用body-content元素来指定body内容的类型: A(1WQUu j  
S^7u`-  
<body-content>JSP|tagdependent</body-content>  bE%*ZB  
&9 khIJI n  
:+v4,=fHy  
如果body的内容是定制的或内部的tag、脚本元素、或HTML广本,则归类为JSP类型。其他的类型,比如上面代码所述的?D?D将sql statement类传给 query tag的这种类型应该标为tagdependent。 R,8460e7  
gJJBRn{MI  
注意:实际上body-content的值并不影响tag处理类对body内容的处理,它仅仅是被tag编辑工具用来描述此body的内容。 D"<>! ]@(a  
v9GfudTZR  
DoFF<LXBt  
用tags定义脚本变量 {S"!c.  
suFO~/lRno  
uX8G<7O^  
tag处理类 PcEE@W9  
UJ^-T+fut  
1v'|%B;O  
tag处理类负责创建或设置页面中定义的脚本变量,用pageContext.setAttribute(name,value,scope)或pageContext.setAttribute(name,value)方法来实现。一般来说,tag处理类通过脚本变量的名称来获取它,脚本变量的名称一般可用get方法来获得。 h9cx~/7,_)  
L YMb)=u]  
如果脚本变量的值依赖于tag处理类中的上下文中某一对象,那它可用pageContext.getAttribute(name,scope)方法来找到那个对象。一般的处理过程是tag处理类先找到脚本变量,再对其进行处理,然后用pageContext.setAttribute(name,object)的方法来设置它的新值。 zC WN,K`  
MmW]U24s  
对象的生存周期(scope)如下表: %5Zhq>  
c{\x< AwO  
对象的生存周期表 d$PQb9Q+f  
@WuG8G  
名字 znNv;-q  
可访问范围 hEfFMi=a`  
生存周期 HC RmW'  
?dQ#%06mn  
page gjPbhY=C[  
当前页面 S,GM!YZg  
一直有效,除非页面向客户提交响应或重定向到一个新页面 FK,Jk04on  
0Rz",Mu>  
request F=V_ACU  
当前页面或当前页面重定向到的页面 #QKgY7  
一直有效,除非页面向客户提交响应 l/6(V:  
zF_aJ+i:~  
session &` weW  
当前页面或在同一浏览器窗口中的页面 .!Q?TSQ+{!  
一直有效,除非关闭当前浏览器、超时、网络故障 {3N5Fi7S  
3.?B')  
application 3.D|xE]g  
整个web应用程序的所有请求 9I*i/fa  
一直有效,除非发生网络故障、服务器故障 =>Dw ,+"  
0 rilg  
提供关于脚本变量的信息 ~MZ.988:<  
=d1i<iw?-  
以下示例定义了一个名为“book”的脚本变量,用来访问程序中关于书的信息: k4BiH5\hA  
d>jRw  
<bean:define id=”book” name=”bookDB” property=”bookDetails” type=”database.BookDetails” /> hG>3y\!#  
|3uE"\nfA  
<font color=”red” size=”+2” > XFcIBWS  
Fhbp,CX4p  
<%= messages.getString(“CartRemoved”) %> 0?\d%J!"S  
Iw;J7[hJ&$  
<strong><jsp:getProperty name=”book” property=”title” /></strong> mx")cGGQ  
QTuj v<|  
</font> H_+!.  
>Wr  
当包含此tag的JSP页面被编译时,jsp引擎会自动生成关于此book的同步的代码(同步可以避免几个客户同时访问此book时造成的冲突),要生成同步代码,jsp引擎需要知道此脚本变量的如下信息: ,?>:Cdz4  
#>(h!lT_  
· 脚本变量名称 XCku[?Ix  
2ZZF hj  
· 脚本变量所属的类 pk:2>sx/  
G ~|Z (}H  
· 此脚本变量是否引用了一个新的或已存在的对象 <P)0Yu  
a>/jW-?  
· 此脚本变量的有效性 *<T,Fyc|  
sXm,y$ \m  
有两种办法可以向jsp引擎提供关于脚本变量的信息:在TLD中定义variable子元素,或用tei-class子元素定义一个额外tag信息类。用variable最简单,但可能降低了一些灵活性。 eWwI@ASaA  
U0t~H{-H  
Variable元素 B:QAG  
R'{BkC}.  
Variable元素有如下子元素: UXN!iU)  
)a'c_ 2[  
· name-given ?D?D 给出的名字,是一个常量 $l!+SLK  
Ah <6m5+  
· name-from-attribute?D?D 属性名,在编译时给出的属性名 U,)@+?U+h  
]>\!}\R<  
name-given或name-from-attribute两者必须选一,但以下子元素是可选的: =/]d\JSp  
YQk<1./}I  
· variable-class?D?D变量的类型,缺省为java.lang.String。 }^Kye23  
7Yrp#u1!  
· declare?D?D此脚本变量是否引用了一个新对象,缺省为True。 v5!G/TZ1  
p 6FPdt)  
· scope?D?D脚本变量的范围,缺省为NESTED。下表描述了scope的几种类型: rxJWU JMxK  
msiftP.  
脚本变量的有效范围 LV X01ox$  
" O,TL *$  
A(>kp=~  
有效性 ~Q)137u]P  
方法 V=g<3R&  
MGzuQrl{H  
NESTED M&5;Qeoiv  
在tag标签的开始和结束之间 A&~<qgBTp  
如果tag处理类实现BodyTag接口,则在doInitBody和doAfterBody中调用,否则在doStartTag中调用 ^7l^ /GSO  
ZHku3)V=o  
AT_BEGIN G~\ SI.  
从tag标签的开始一直到页面结束 ,`lVB#|  
如果tag处理类实现BodyTag接口,则在doInitBody、doAfterBody和doEndTag中调用,否则在doStartTag和doEndTag中调用 :jp4 !0w  
^?3e?Q?  
AT_END :U7m@3czU  
从tag标签的结束一直到页面结束 4vk^=  
在doEndTag中调用 }m6j6uAR6)  
u*NU MT2  
以struts为例,它的bean:define标签的实现遵循JSP1.1规范,此规范要求使用额外tag信息类来定义脚本变量。Variable元素是JSP1.2规范中加入的。以bean:define标签为例,你可以定义如下variable元素: 1li1&  
-bHfo%"^TT  
<tag> E'g2<k  
J0hY~B~X  
<variable> *?#t (Y[  
 j`9+pI  
<name-from-attribute>id</name-from-attribute> L8FLHT+R-  
/}Z0\ ,  
<variable-class>database.BookDetails</variable-class> /{~cUB,Um  
(HUGgX"=  
<declare>true</declare> zmxrz[  
n./onv  
<scope>AT_BEGIN</scope> cQaEh1n  
vh~:{akR  
</variable> XVfp* `  
p?X`f#  
</tag> MpV6Vbp  
A~!3svJW  
额外tag信息类  jJjD)  
Us ]Uy|j  
如果要定义一个额外tag信息类,你要继承javax.servlet.jsp.TagExtraInfo类。一个TagExtraInfo类必须实现getVariableInfo方法,此方法返回一个叫VariableInfo的数组类,它包括如下信息: o >=YoG  
7x%0 ^~/n  
· 变量名 EuAJ.n  
Xjal6e)[  
· 变量所属类名 bm{L6D E  
6' M"-9?G  
· 此变量是否引用了一个新对象 }xl @:Qo  
od- 0wJN-m  
· 此变量的有效范围 ql%>)k /x  
T#1>pED  
jsp引擎将一个名为data的参数传给getVariableInfo方法,data中包括tag标签中的所有“属性名?D?D属性值”对。它可以用来向VariableInfo对象提供脚本变量的名字和类名。 T~k5` ~\(  
~67L  
以struts为例,它在bean:define标签中定义了一个名为DefineTei的额外tag信息类,用来向脚本变量提供信息。由于脚本变量的名称(book)和类名(database.BookDetails)是通过tag标签的属性来传递的,它们一般定义在VariableInfo的构建代码中,并且可用data.getAttributeString方法来得到这些信息。如果要允许book脚本变量能在从tag开始直到整个JSP页面结束的范围内都可用的话,那它的范围应设为AT_BEGIN。如下所示: 5@+8*Fdk  
W`C&$v#  
4ifWNL^)  
public class DefineTei extends TagExtraInfo >s E5zj|V  
Kl[WscR  
{ m6bI<C3^5  
K%<Z"2!+  
public VariableInfo[] getVariableInfo(TagData data) 3ySP*J5  
|5}{4k~9J  
{ .Lrdw3(  
'|e5cW6z  
String type = data.getAttributeString(“type”); Ms*;?qtrR  
!U$ %Jz  
If( type == null) 'M\ou}P  
" [=Ee[/  
type = “java.lang.Object”; GA6)O-^G  
:~ 3/  
return new VariableInfo[] { %ma1LN[  
#Dx$KPD  
new VariableInfo(data.getAttributeString(“id”), uU`zbh}]L.  
Rww"Z=F  
type, 5:f}bW*  
$Q|66/S^  
true, 3Gt'<E|"  
YTq>K/  
VariableInfo.AT_BEGIN) muQ7sJ9 r  
K}O~tff  
}; 4qjY,QJ  
<;x+ ?j  
} ;W#G<M&n'  
MC3XGnT#5  
} l\5qa_{z  
_y`'T;~OY  
_'Q}Y nEv  
注意:关于额外tag信息类的类名必须要在TLD中的tag标签下的tei-class子元素中定义。因此,DefineTei的tei-class中的定义看起来如下: ^zqz$G#  
<tei-class> lN1T\  
org.apache.struts.taglib.bean.DefineTagTei z@VY s  
</tei-class> D6_16PJE  
~@R=]l"  
wmY6&^?uS  
具有协作关系的tag GVY_u@6   
Jx_ OT C  
2N(c&Dzkh`  
tag通过共享对象来进行协作,JSP技术支持2种方式的对象共享。 ~v9\4O  
vK#xA+W  
第一种方法是使用pageContext对象进行对象的共享(可支持JSP页面和tag处理类之间的共享),如果在一个tag处理类中要调用由另一个tag处理类创建的对象,可调用pageContext.getAttribute(name, scope)方法。 z -(dT  
1h]Dc(Oc#=  
第二各方式的共享是对于tag之间有嵌套关系而言的,外层的tag所创建的对象对于内层的tag来说是可以共用的。这种形式的共享的好处是减少了可能存在的重名冲突。 L<QqQ"`  
!e.@Xk.P6  
要访问一个嵌套tag创建的对象,tag处理类必须先找到此嵌套tag对象,可用TagSupport的静态方法 TagSupport.findAncestorWithClass(from, class)或TagSupport.getParent方法。前者在当不确定此tag是否为嵌套tag对象时使用。一旦它的父类被找到,它就能访问其所有动态或静态创建的对象。静态创建的对象是父类的成员,而动态创建的对象可能是父类的私有对象。诸如此类的对象可以用tag处理类的setValue方法来保存,用getValue方法来获得。 ;wDcYs  
61T"K  
下例阐述了以上两种共享对象的方法。在这个例子当中,一个查询tag检查一个名为connection的属性名是否在doStartTag中被设置。如果connection属性被设置,tag处理类从pageContext中得到这个connection对象。否则,此tag处理类先找到它的父tag处理类,然后从它的父tag处理类中找到connection对象。 0_qqBL.4  
^#exs Xy  
i/oaKpPN  
public class QueryTag extends BodyTagSupport Z\i@Qa+r  
tb&{[|O^  
{ PWLMux  
8!me$k&  
private String connectionId; ~b8U#'KD  
l[Ng8[R  
public int doStartTag() throws JspException Tp[ub(/;7  
Hc^b}A y7  
{ ^"l>;.w  
]_|qv1K6  
String cid = getConnection(); H <F6o-*  
O>|Q Zd  
if(cid != null) ;2)@NH  
?K I_>{  
{ zWB>;Z}  
0l^-[jK)  
//存在一个connection id,使用它。 WK /Byd.Z  
}I,]"0b  
connection = (Connection) pageContext.getAttribute(cid); ./[%%"  
|CY.Y,  
} XL g6?Nu  
1/6G&RB  
else n/S1Hae`  
[)# ,~L3  
{ 8>6+]]O  
W84JB3p  
ConnectionTag ancestorTag = (ConnectionTag)findAncestorWithClass(this,  yYp!s  
*hAq]VC})  
ConnectionTag.class); vDv:3qN7(  
+<|6y46  
if(ancestorTag == null) sR +=<u1  
MY4cMMjp~  
{ -+#\WB{AI  
pDCQ?VW  
throw new JspTagException(“一个没有connection属性的查询标签必须被一个connection标记嵌套。”); jzdK''CHi  
:JxShF:M  
} rrwBsa3  
"S_t%m&R  
connection = ancestorTag.getConnection(); Qg<_te)\  
)(_}60  
} a5:YP  
+0;6.PK  
} [- a2<E  
loLQ@?E  
} MHpPb{ ^  
(@p E  
M0S}-eXc5  
(w-z~#<  
此查询标签在JSP页面中的调用形式可以从以下2种定义中任选一种: o(u&n3Q'  
4=%Uv^M  
(UA a  
<tt:connection id=”con01” ...> ... </tt:connection> m3+MRy 5  
~kD/dXt  
<tt:query id=”balances” connection=”con01” > u-qg9qXJb  
-shS?kV  
SELECT account, balance FROM acct_table *[wy- fu  
l|/h4BJ'  
where customer_num = <%= request.getCustno() %> &<_*yl p  
)~rf x  
</tt:query> `kpX}cKK}  
(vB aem9  
1j`-lD  
%FDi7Rx  
-}/u?3^-  
<tt:connection ...> >8"oO[U5>  
w-C ~ Ik  
<x:query id=”balances”> &BY%<h0c  
(CJiCtAsl`  
SELECT account, balance FROM acct_table `TYQ^Zm  
.0:BgM  
where customer_num = <%= request.getCustno() %> 6iV jAxR  
Hzcy '  
</x:query> [ >O4hifq  
Z3g6 ?2w6  
</tt:connection> X,C&nqVFm8  
5Q#;4  
gbsRf&4h  
与此同时,在TLD中必须指定connection属性为可选的,定义如下: %0fF_OU  
6}='/d-[  
<tag> Sf);j0G,D  
QM\v ruTB  
... %<lfe<;^t  
jV]'/X<  
<attribute> kTb.I;S  
|5 _bFB+&  
<name>connection</name> H%t/-'U?  
!C * %,Ak  
<required>false</required> P~Q5d&1SO  
Gtd!Y x  
</attribute> vA2@Db}  
gh=s#DQsFw  
</tag>
描述
快速回复

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