标准的JSP 标记可以调用JavaBeans组件或者执行客户的请求,这大大降低了JSP开发的复杂度和维护量。JSP技术也允许你自定义taglib,其实换句话说,taglib可以看成是对JSP标记的一种扩展,正如xml是对html的一种扩展一样。taglib通常定义在tag标签库中,这种标签库存放着你自己定义的tag标签。简而言之,如果使用taglib,那么你可以设计自己的JSP标记!
.wtYostv bF +d_t 一般来说,自定义tag标签主要用于操作隐藏对象、处理html提交表单、访问数据库或其它企业级的服务,诸如邮件和目录操作等等。自定义tag标签的使用者一般都是那些对java编程语言非常精通,而且对数据访问和企业级服务访问都非常熟悉的程序员,对于HTML设计者来说,使得他可以不去关注那些较复杂的商业逻辑,而将精力放在网页设计上。同时,它也将库开发者和库使用者进行合理分工,自定义tag标签将那些重复工作进行封装,从而大大提高了生产力,而且可以使得tag库可用于不同的项目中,完美地体现了软件复用的思想。
.ffr2\'* z34+1d 在这篇文章中,我们主要讨论:
li}>xDSQ4 *r6v9 · 什么是自定义tag标签?
ZalL}?E
? J %E0Wd · 怎么使用tag标签?
clIn}wQ X{h[ o 声明要使用的tag库
I7<UC{Ny ;N
_%O o 找到与之对应的tag处理类
9HlM0qE5b M IU B] o tag标签的类型
;;EFiaA owO&[D/ · 自定义tag标签
p\]rxtm 1}CJ& o tag处理类
SNH AL F P>|sCF o tag库描述
~k ]$J|}za 8,B#W#*{ o tag标签示例
G/KTF2wl7 ~BXy)IB6 o 带属性的tag
2nSz0 . @,pn/[ o 带body的tag
H\|H]: CE Jb8%A@Z+ o 定义了脚本变量的tag
Q:Y`^jP "m}N
hoD4 o 具有协作关系的tag
m`@~ZIa?>B ',6d0>4* · 自定义tag标签
Ye[Fu/0 SQJ4}w>i o 一个迭代tag的例子
#*}cc rFto1m o 一个模板tag库
miY=xwK& !Jaj2mS.N o tag处理类到底是怎样被调用的?
(~:ip)v .5#+)] l GGGz7_s
? 什么是自定义的tag?
}&EdA;/o_ *o=( w5
一个自定义的tag标签是用户定义的一种JSP标记。当一个含有自定义的tag标签的JSP页面被jsp引擎编译成servlet时,tag标签被转化成了对一个称为tag处理类的对象进行的操作。于是当JSP页面被jsp引擎转化为servlet后,实际上tag标签被转化成为了对tag处理类的操作。
2j[;M-3 2(Nf$?U@0 自定义tag标签有很多特色,诸如:
;^8X(R ,B,0o*qc{K · 可以在JSP页面中自定义tag标签的属性
BR~+CBH asYUb&Hz88 · 访问JSP页面中的所有对象
_^F%$K6 tLGNYW!K · 可以动态地修改页面输出
wUzMB]w bX+"G}CRP · 彼此这间可以相互通信。你可以先创建一个JavaBeans组件,然后在一个tag中调用此JavaBeans组件,同时可以在另一个tag中调用它。
%D+NrL( XC,by&nY<y · tag允许相互嵌套,可以在一个JSP页面中完成一些复杂的交互。
%lGg}9k' TnPx.mwK\ 4'L.I%#tZ 使用tag标签
<!~NG3KW[> &3YXDNm rmhL|!
Y 本节主要描述怎样在JSP页面中使用tag标签,以及tag标签的不同类型。
ZV~9{E8 d-#yN:}0 要使用tag标签,JSP程序员必须做2件事:
&t74T"(d N<aMUV m · 声明此tag标签的tag库
(w/lZt zUJPINDb · 实现此tag标签
l'"Ici#7Ls xx[l#+:c 声明tag标签所在的tag库
bm(.(0MI K1-y[pS]E 如果要使用tag标签,则应用JSP的taglib指示符来指定其tag库(注意:taglib要在在使用此tag标签之前声明)
bHmn0fZ9 `q?@ Ob& <%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %>
sq}uq![?M ]hY4
MS uri属性定义了唯一的标签库描述(以下简称TLD),它可以是直接是tld文件名或一个独一无二的名字。prefix是用来区别其它TLD中和本TLD中有重名的tag的一种手段。
WNiM&iU W%K=N-kE_ TLD必须以.tld作为扩展名,并且存放在当前应用的WEB-INF目录或其子目录下。你可以通过它的文件名直接引用它,也可以通过别的方式间接地引用它。
?qczMck_ j$khGR! 以下taglib指示符直接引用一个TLD:
f,8PPJ:, c.;<+dYsm* <%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %>
ob7hNo# /SJI ~f+$ 以下的taglib指示符通过一个逻辑名称间接地引用一个TLD:
;)!);q+ 4,7W*mr3( <%@ taglib uri=”/tutorial-template” prefix=”tt” %>
`FIS2sl/ <f@
A\ 如果是间接引用TLD的话,那你必须还要在web.xml中定义此逻辑名称与tld文件之间的映射,具体做法是在web.xml中加入一个名为taglib的元素:
-KiI&Q O[HBw~ <taglib>
7u[$ 7^Y`'~Y^ <taglib-uri>/tutorial-template</taglib-uri>
}j|YX&`p DMd&9EsRG <taglib-location>
pt9fOih[ 8|IlJiJ~v /WEB-INF/tutorial-template.tld
(l:LG"sy\ \Oa11c`6 </taglib-location>
.\|}5J9W {tF)%>\# </taglib>
e&F=w`F\ vA0f4W 8+ Rc`zt7hbJ 实现此tag标签
z6bIv} #|acRZ9
} -o`|A767 为了实现tag标签,你有2种方法来存放tag处理类。一、让tag处理类以.class的方式存放于当前应用的WEB-INF/class子目录下,二、如果tag处理类是以JAR包的形式存在的话,那可以放在当前应用的WEB-INF/lib目录下,如果tag处理类要在多个应用中共享,那么它就应放在jsp服务器上的common/lib目录下,对于tomcat来说,就是tomcat/common/lib目录下。
d{RMX<;G 1IZTo!xi
BPC> tag标签类型
n,%/cUl jg=}l1M" UJrN+RtL 自定义的tag标签遵循XML语法。它有一个开始标记和一个结束标记,有的还有body(即文本节点):
`:EU~4s\ IFF3gh42. <tt:tag>
RJA#cv~f WlnS.P\+E body
)W3kBDD "l
1z@ </tt:tag>
C 4hvk'= e2MjV8Bs QhmOO-Z? 一个不带body的tag标签如下:
Eilo;-El qJEtB;J' <tt:tag />
~DUOL~E `Bv, :i ')~[J$qz 简单的tag标签
^TCfj^FP -n`2>L1 一个没有body和属性的tag标签如下:
.7MLgC; NLO&.Q]# <tt:simple />
MGSD;Lgn 0`"DYJ}d RV, cQ K 带属性的tag标签
OJPi*i 5* c:_dW;MJ0 ;F\sMf{ 自定义标签可以有自己的属性。属性一般在开始标记中定义,语法为 attr=”value”。属性的作用相当于自定义标签的一个参数,它影响着tag处理类的行为。你可以在TLD中详细定义它。
>&uR=Yd >I;J!{ 你可以用一个String常量给一个属性赋值,也可以通过表达式给它赋值,如<%= ...%>。以struts为例,它的logic:present标签就是用的String常量来给属性赋值:
vK8!V7o~h% z]R)Bh <loglic:present parameter = “Clear”>
uZ(,7>0 -Oc 而另一个标签logic:iterate是用表达式来给属性赋值:
NUGiDJ+[ &3bh K5P <logci:iterate collection=”<%= bookDB.getBooks() %>”
}n$I #G}\/ 84M*)cKR~ id=”book” type=”database.BookDetails”>
WOuk>
/ F48W8'un PZO8<d 带body的tag标签
a
#Pr)H o.KE=zp&z 一个自定义标签可以包含其它自定义标签、脚本变量、HTML标记或其它内容。
m[6c{$A/w o9AwW 在下述例子中,此JSP页面使用了struts的logic:present标签,如果些标签定义了parameter=”Clear”的属性,则将清除购物车的内容,然后打印出一条信息:
?/^x)Nm C+Pw <logic:present parameter=”Clear”>
lsRW.h, S]}W+BF3 <% cart.clear(); %>
2U`g[1 `NARJ9M <font color=”#ff0000” size=”+2”><strong>
=1Tn~)^O ;>h:VnV(>( 你选择了清除购物车!
J2Z?}5> 2M3C
5Fu </strong></font>
C?lZu\L uy
oEMT#u </logic:present>
DjQgF=; RS
/*Dp^ =!P$[pN2 到底是用属性还是用body来传递信息?
@1iH4RE* \6K1Z!*; 如上所述,我们既可以通过属性,也可以通过body来传递信息。但一般来说,比较简单的类型,如字符串或简单表达式最好采用属性来传递信息。
L|K^w *\C ,3FG' q2 5r(Y,m"? 定义脚本变量的tag标签
&L4>w.b"N H4JwgQ 所谓脚本变量,是指JSP中可以调用的变量或对象。它可由tag标签产生。以下示例阐述了一个tag标签定义了一个名为tx的由JNDI所定义的事务处理对象。脚本变量可以是ejb对象、事务、数据库连接等等:
yDXW#q IltU6=]"l <tt:lookup id=”tx” type=”UserTransaction” name=”java:comp/UserTransaction” />
W,sPg\G 3 UWg+7RL <% tx.begin(); %>
l. 0|>gj`0 x]<0Kq9K ...
L<H6AzR+ EGJrnz8 s.9_/cFWB 具有协作关系的tag标签
^9A,j}>o- V"R ,omh 自定义tag标签之间可以通过共享对象来实现协作。在下述例子中,标签tag1创建了一个名为obj1的对象,在标签tag2仍可以重复使用obj。
cHk ?$ c$52b4=a <tt:tag1 attr1=”obj1” value1=”value” />
cy!;;bB FG6mh,C! <tt:tag2 attr1=”obj1” />
ipn0WQG #x[3@zP. 在以下这个例子当中,如果外层的tag标签创建了一个对象,那么其内层的所有tag标签都可以使用这个对象。由于这样产生的对象没有一个指定的名字,那么就可以将少重名的冲突。这个例子阐述了一系列协作的嵌套对象。
'?dT<w=Y& u[?M{E/HU <tt:outerTag>
mZ}C)&,m2 [V _\SQV0 <tt:innerTag />
+DA,|~k_ sRDxa5<MD </tt:outerTag>
4&+lc* `/L D:R TwLQ;Q Tag处理类
Vf] ;hm d+158qQOh] 2r>I,TNHl Tag处理类必须实现Tag接口或BodyTag接口,不过现在一般都流行从TagSupport或BodyTagSupport类中继承,这些类或接口都可以在javax.servlet.jsp.tagext包中找到。
)w'GnUqWz M5<cHE 当JSP引擎看到自己的JSP页面中包含有tag标签时,它会调用doStartTag方法来处理tag标签的开头,调用doEndTag方法来处理tag标签的结束。
.[8g6:> %r >Y)@$Vt 下表说明不同类型的tag所需要不同的处理过程:
Y[Kpd[)[v 8$C?j\J|* Tag处理类的方法
mv\S1[<T 9 7Mi{Zz Tag标签类型
1JWo~E' 所调用的方法
^P}c0}^ NG?- dkD 基本标签
bbxo!K
m" doStartTag, doEndTag, release
J\c\Ar: gzeTBlXg 带属性的标签
Lm"zW>v doStartTag, doEndTag, set/getAttribute1...N, release
(YKkJ ' 带内容的标签
WDq~mi doStartTag, doEndTag, release
QTT2P(Pz {axMS yp; 带内容的标签,且内容重复循环
G+zIh}9 doStartTag, doAfterBody, doEndTag, release
l~c# X3E 3KN>t)A# 带内容的标签,且内容与JSP交互
g]Fm%iy doStartTag, doEndTag, release, doInitBody, doAfterBody, release
QDpzIjJj %% A==_b 一个tag处理类可以通过javax.servlet.jsp.PageContext来与JSP交互,通过javax.servlet.jsp.PageContext类,tag处理类可以访问JSP中的request、session和application对像。
*e}1KcJ P2>Y0"bY 如果tag标签是互相嵌套的,那内层的tag处理类可以通过它的parent属性来访问上层的tag处理类。
\YrvH 3~6,fTMz{ 一般情况都将所有的tag处理类打成了JAR的包,以便于发布。
N,~"8YSo %"g; K 3?:?dy(3z Tag库描述(简称TLD)
<`WtP+` v!77dj 6I 85 <%L:EC Tag库是用xml语言描述的,TLD包括了tag库中所有tag标签的描述,它一般用来被jsp服务器用来校验tag的语法正确性,或者被jsp开发者用来开发新的标签。
S1G3xY$0 yOr5kWqX TLD的文件扩展名必须为.tld,而且必须放在当前WEB应用的WEB-INF目录或其子目录中。
>a$b4
pvh ,J ZM%f 一个TLD的内容的开头必须遵守标准的XML开头,用于描述DTD和xml的版本,例如:
2X!!RS>qg I^itlQ <?xml version="1.0" encoding="ISO-8859-1" ?>
BOf)27) IM$I=5ye <!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "
http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd">
T,SCK^ TLD必须以<taglib>来作为它的根元素,<taglib>的子元素如下表:
PuoN<9 # ZKco _ pKWDMB$z <taglib>的子元素
m.DC JDj^7\` Element
$3D#U^7i Description
Bn?MlG;aA AB")aX2%E tlib-version
(3fU2{sm Tag库的版本
9G"-~C"e3 z1`z
k0 jsp-version
)*I%rN8b
Tag库所需要的jsp的版本
19#A7 XbMAcgS short-name
8@J5tFJ&% 助记符,tag的一个别名(可选)
5_~QS rtY4B~_ uri
]/y69ou 用于确定一个唯一的tag库
:MbD=sX k:k!4 display-name
tF=Y3W+L 被可视化工具(诸如Jbuilder)用来显示的名称(可选)
? =a, +KKx\m* small-icon
SF?s^ 被可视化工具(诸如Jbuilder)用来显示的小图标(可选)
oq3{q Ad]oM] large-icon
k}r)I.Lp 被可视化工具(诸如Jbuilder)用来显示的大图标(可选)
9HJA:k*k| 8w]>SEGFs description
g{%2*{;i 对tag库的描述(可选)
_rjLCvv- r]'Q5l4j6" listener
I!uGI 参见下面listener元素
1?5UVv_F n^7m^1to tag
W99Hq1W;r 参见下面tag 元素
<;.->73E Isna
KcLM Listener元素
%zA$+eT Pu7cL 一个tag库可能定义一些类做为它的事件侦听类,这些类在TLD中被称为listener 元素,jsp服务器将会实例化这些侦听类,并且注册它们。Listener元素中有一个叫listener-class的子元素,这个元素的值必须是该侦听类的完整类名。
jXALN LJII7<k Tag元素
8
y+N l&"V ;V"(! 'd 每个tag元素在tag库中都要指出它的名字、类名、脚本变量、tag的属性。其中脚本变量的值可以直接在TLD中定义或通过tag附加信息的类来取得。每个属性描述了这个属性是否可以省略,它的值是否可以通过<%= …%>这样的JSP语法来获得,以及属性的类型。
LwL\CE_6+ b/g"ws_ 每一个tag在TLD中对应一个tag元素,下表是tag元素的子元素:
Jb4A!g5C #m<<]L(o8W Tag元素的子元素
^&-H"jF eg
vgi?y 元素名称
7TN94@kCF 描述
sBfPhBT| L_4ZxsIv name
J)xc mK 独一无二的元素名
~0~f d3| oKP6 tag-class
2AZ)|dM'` Tag标签对应的tag处理类
u/8urxpy =P.m5e< tei-class
YN@4.&RP javax.servlet.jsp.tagext.TagExtraInfo的子类,用于表达脚本变量(可选)
g~AOKHUP z
nc' body-content
h&4f9HhS= Tag标签body的类型
5V{zdS= 0u'qu2mV display-name
7>`VZ? 被可视化工具(诸如Jbuilder)用来显示的名称(可选)
MXj7Z3 u< ,c small-icon
+s'qcC 被可视化工具(诸如Jbuilder)用来显示的小图标(可选)
Q< q&a8~ uM^eoh_ large-icon
Evn=3Tw 被可视化工具(诸如Jbuilder)用来显示的大图标(可选)
CK+GD "Z$ !awfxH0 description
6SIk,Isy8 此tag标签的描述
8C{mV^cn~ =+qtk(p variable
V~uH)IMkh7 提供脚本变量的信息(同tei-class)(可选)
]$>O-- i:ZL0nH- attribute
jB17]OCN Tag标签的属性名
H-sJt: 1.Ximom 以下章节介绍对于不同类型的tag,如何具体地实现它们。
8SGFzb! h WYb\vm=r v{}i`|~J 简单的tag
ZO2$Aan +hIStA x)SW1U3TVx tag处理类
b$f@.L Qw{LD+r( 简单的tag处理类必须实现Tag接口的doStartTag和doEndTag方法。当jsp引擎碰到tag标签的开头时,doStartTag被调用,因为简单的tag没有body,所以此方法将返回 SKIP_BODY。当jsp引擎碰到tag标签的结尾时,doEndTag被调用,如果余下的页面还要被计算,那它将返回EVAL_PAGE,否则将会返回SKIP_PAGE。
bnz2\C9^ ]S6`",+)<f 以下是例子:对于标签 <tt:simple /> ,它的tag处理类实现如下:
dT%$"sj5 DUk&`BSJ &_^t$To public SimpleTag extends TagSupport
W(oJ{R&m{ ?Sq?f? {
<J`",h 3+_
.I{ public int doStartTag() throws JspException
cGhnI& ,{HxX0 {
@,<@y>m7 _JZwd9K try{
W -Yv0n3 g{zvks~it pageContext.getOut().print(“Hello.”);
Vs-])Q?7J ]{r*Z6bs }catch(Exception e){
|=^p`CT xm}9(EJ throw new JspTagException(“SimpleTag: “ + e.getMessage());
b3G4cO;t; iINd*eXb^ }
Ny@CP} I6x return SKIP_BODY;
HWJ(O/N lw4#xH-? }
fWx
%?J CfguL@tR. public int doEndTag()
:esHtkyML d;3/Vr$t= {
6q[|U_3I@ (c X;a/BR return EVAL_PAGE;
k !S0-/h 2nW:|*:/p6 }
O\h*?, ) /Q4TQ\: }
[*<F
d%:B,bck 2NHkK_B1P 注意:如果tag标签没有内容的话,那必须定义body-content元素为空,例如
M^c`j#NQ U{vt9t <body-content>empty</body-content>
g]IRv(gDh la7VeFT }Fd4;
] 带属性的tag标签