标准的JSP 标记可以调用JavaBeans组件或者执行客户的请求,这大大降低了JSP开发的复杂度和维护量。JSP技术也允许你自定义taglib,其实换句话说,taglib可以看成是对JSP标记的一种扩展,正如xml是对html的一种扩展一样。taglib通常定义在tag标签库中,这种标签库存放着你自己定义的tag标签。简而言之,如果使用taglib,那么你可以设计自己的JSP标记!
Eh!%NeO ,h#!!j\j6 一般来说,自定义tag标签主要用于操作隐藏对象、处理html提交表单、访问数据库或其它企业级的服务,诸如邮件和目录操作等等。自定义tag标签的使用者一般都是那些对java编程语言非常精通,而且对数据访问和企业级服务访问都非常熟悉的程序员,对于HTML设计者来说,使得他可以不去关注那些较复杂的商业逻辑,而将精力放在网页设计上。同时,它也将库开发者和库使用者进行合理分工,自定义tag标签将那些重复工作进行封装,从而大大提高了生产力,而且可以使得tag库可用于不同的项目中,完美地体现了软件复用的思想。
yz9`1R2c KfG%#2\G_ 在这篇文章中,我们主要讨论:
_8 vxb bjm`u3
A · 什么是自定义tag标签?
\#LKsQa ,*E%D _ · 怎么使用tag标签?
J}._v\Q7P @tEVgyN o 声明要使用的tag库
E;VB oN [ "sAR<5b o 找到与之对应的tag处理类
thipfS O.&6J/ o tag标签的类型
Q,#M
0 'x+0
yd · 自定义tag标签
C;dA?Es>R sx*1D9s_ o tag处理类
g_0"T}09( tborRi) o tag库描述
n\,TW&3 puZ<cV
e/ o tag标签示例
iL|*g3`-f l2VO=RDiW o 带属性的tag
kgr:85 O3bK>9<K o 带body的tag
`Jm{K*&8Q 4 3]6J]!) o 定义了脚本变量的tag
:e+GtN? e!tgWYN o 具有协作关系的tag
&Eidc . k`oXo% · 自定义tag标签
B|:{.U@ne m9#u.Q* o 一个迭代tag的例子
U|{WtuR v bDw2 o 一个模板tag库
:&?# ~NFH o&(%:| o tag处理类到底是怎样被调用的?
ni2H~{]z
Ic#+*W\ZW /rvXCA)j
什么是自定义的tag?
]3d&S5zU a Q`a>&R0 一个自定义的tag标签是用户定义的一种JSP标记。当一个含有自定义的tag标签的JSP页面被jsp引擎编译成servlet时,tag标签被转化成了对一个称为tag处理类的对象进行的操作。于是当JSP页面被jsp引擎转化为servlet后,实际上tag标签被转化成为了对tag处理类的操作。
(
fdDFb#1 ;Ic3th%u 自定义tag标签有很多特色,诸如:
U?$v1 || &CUkR6 · 可以在JSP页面中自定义tag标签的属性
>x2T' 8^dGI9N
· 访问JSP页面中的所有对象
L'aMXNO YgM6z K~ · 可以动态地修改页面输出
O])/kS` =;Wkg4\5 · 彼此这间可以相互通信。你可以先创建一个JavaBeans组件,然后在一个tag中调用此JavaBeans组件,同时可以在另一个tag中调用它。
PDD` eK}Fj *k+QX · tag允许相互嵌套,可以在一个JSP页面中完成一些复杂的交互。
:\4O9f*5+ })mez[UmZ }ZVNDvGH 使用tag标签
Z:T4Z}4N ZN1QTb GExG1n- 本节主要描述怎样在JSP页面中使用tag标签,以及tag标签的不同类型。
5Qy,Pkje NA/+bgyuT> 要使用tag标签,JSP程序员必须做2件事:
*
+OAc`8 zh/+1 · 声明此tag标签的tag库
Bj@&c> QO#ZQ~ · 实现此tag标签
rBr28_i Y Nq<%i!> 声明tag标签所在的tag库
&v 5yo}s ^f<f&V 如果要使用tag标签,则应用JSP的taglib指示符来指定其tag库(注意:taglib要在在使用此tag标签之前声明)
5)T{iPU%X !Id F6 % <%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %>
6@l:(-(j2A "Ww^?"jQ) uri属性定义了唯一的标签库描述(以下简称TLD),它可以是直接是tld文件名或一个独一无二的名字。prefix是用来区别其它TLD中和本TLD中有重名的tag的一种手段。
zEO
9TuBO Ho\+xX TLD必须以.tld作为扩展名,并且存放在当前应用的WEB-INF目录或其子目录下。你可以通过它的文件名直接引用它,也可以通过别的方式间接地引用它。
//wmJ | KJ9~"v
以下taglib指示符直接引用一个TLD:
,(c="L4[ FfD2
&(-R <%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %>
29av8eW?3 HnY: gu 以下的taglib指示符通过一个逻辑名称间接地引用一个TLD:
3_33@MM X,y$!2QI <%@ taglib uri=”/tutorial-template” prefix=”tt” %>
c#Y9L+O Uj!L:u2b 如果是间接引用TLD的话,那你必须还要在web.xml中定义此逻辑名称与tld文件之间的映射,具体做法是在web.xml中加入一个名为taglib的元素:
4
Qw;r @&EP&
$* <taglib>
<78>6u/W% !2{MWj <taglib-uri>/tutorial-template</taglib-uri>
ImF/RKI~ " xUSIck
<taglib-location>
dDm<'30?*v YDmFR,047 /WEB-INF/tutorial-template.tld
0hNc#x6 B"Fg`s+]U </taglib-location>
-C8awtbC >Zr/U!W*? </taglib>
Pc4sReo' l;|1C[V 0j_!)B 实现此tag标签
0;XnNz3& <?Lj!JGX ~?L. n:wu 为了实现tag标签,你有2种方法来存放tag处理类。一、让tag处理类以.class的方式存放于当前应用的WEB-INF/class子目录下,二、如果tag处理类是以JAR包的形式存在的话,那可以放在当前应用的WEB-INF/lib目录下,如果tag处理类要在多个应用中共享,那么它就应放在jsp服务器上的common/lib目录下,对于tomcat来说,就是tomcat/common/lib目录下。
DH9?~| #vDe/o+= Q7DkhKT tag标签类型
CX1'B0=\r oa9T3gQ? YEZ"BgUnbp 自定义的tag标签遵循XML语法。它有一个开始标记和一个结束标记,有的还有body(即文本节点):
+:Y6O'h. L3kms6ch <tt:tag>
99ZQlX %*s[s0$c body
"arbUX~d gqC:r,a </tt:tag>
`q5*VqIhs u;Z~Px4]v =E,*8O] 一个不带body的tag标签如下:
_Y~+ #Vc 7M$>'PfO <tt:tag />
Fe/*U4xU IzL
yn TnKe"TA|9 简单的tag标签
Z#Zk) ZM)a4h,kcm 一个没有body和属性的tag标签如下:
0#yo\McZ ~Aq UT]l <tt:simple />
:_?>3c}L kj-Sd^ W}Z|v
M$ 带属性的tag标签
s\KV\5\o S&QZ"4jq 5q8bM.k\7N 自定义标签可以有自己的属性。属性一般在开始标记中定义,语法为 attr=”value”。属性的作用相当于自定义标签的一个参数,它影响着tag处理类的行为。你可以在TLD中详细定义它。
].Et&v k@wxN!w; 你可以用一个String常量给一个属性赋值,也可以通过表达式给它赋值,如<%= ...%>。以struts为例,它的logic:present标签就是用的String常量来给属性赋值:
y\@XW*_? 0<P
-` |X <loglic:present parameter = “Clear”>
N:d" {k f-23.]`v 而另一个标签logic:iterate是用表达式来给属性赋值:
J@)6]d/, QGYmQ9m{kL <logci:iterate collection=”<%= bookDB.getBooks() %>”
VvPTL8Z 2} T"|56 id=”book” type=”database.BookDetails”>
-Ol/r=/& aIm\tPbb $Itehy 带body的tag标签
my*/MC^O WJg?R^ 一个自定义标签可以包含其它自定义标签、脚本变量、HTML标记或其它内容。
g@S"!9[;U G_X'd 在下述例子中,此JSP页面使用了struts的logic:present标签,如果些标签定义了parameter=”Clear”的属性,则将清除购物车的内容,然后打印出一条信息:
ci*Z9&eS+ ^c-1wV`/ <logic:present parameter=”Clear”>
v4 c_UFEh<
XLzHm&; <% cart.clear(); %>
~A6QX8a 0_%u(? <font color=”#ff0000” size=”+2”><strong>
BGUP-_& Dpof~o,f 你选择了清除购物车!
T"dEa-O ^Ji5)c </strong></font>
ffSecoX Rr:,'cXGi </logic:present>
//AS44^IS #5'9T:8 !qy/'v4 到底是用属性还是用body来传递信息?
)WBTqML[ :.Np7[~{ 如上所述,我们既可以通过属性,也可以通过body来传递信息。但一般来说,比较简单的类型,如字符串或简单表达式最好采用属性来传递信息。
'KXvn0 ,!Q2^R CM~)\prks 定义脚本变量的tag标签
B'&%EW] CjykM]) 所谓脚本变量,是指JSP中可以调用的变量或对象。它可由tag标签产生。以下示例阐述了一个tag标签定义了一个名为tx的由JNDI所定义的事务处理对象。脚本变量可以是ejb对象、事务、数据库连接等等:
[S*bN!t d7l0;yR&+ <tt:lookup id=”tx” type=”UserTransaction” name=”java:comp/UserTransaction” />
PiM@iS r0hu?3u1? <% tx.begin(); %>
4INO . F7L+bv ...
:,:r {HQ? NPKRX Li% 具有协作关系的tag标签
p+A#t~K [['un\~r~ 自定义tag标签之间可以通过共享对象来实现协作。在下述例子中,标签tag1创建了一个名为obj1的对象,在标签tag2仍可以重复使用obj。
s_VP(Fe@K ;JDxl-~ <tt:tag1 attr1=”obj1” value1=”value” />
MT|}[|_ 9r8*'.K`Z <tt:tag2 attr1=”obj1” />
Q7f\ 5QjT A-4\;[P\ 在以下这个例子当中,如果外层的tag标签创建了一个对象,那么其内层的所有tag标签都可以使用这个对象。由于这样产生的对象没有一个指定的名字,那么就可以将少重名的冲突。这个例子阐述了一系列协作的嵌套对象。
q *-q5FE Li iQ;x <tt:outerTag>
347p2sK> 4WDh8U <tt:innerTag />
nV
GrW#'E 3C2L _ K3 </tt:outerTag>
llI`"a `2UzJ~ .3!=]= Tag处理类
a B%DIH, rT5dv3^MW! 7pmhH%Dn$ Tag处理类必须实现Tag接口或BodyTag接口,不过现在一般都流行从TagSupport或BodyTagSupport类中继承,这些类或接口都可以在javax.servlet.jsp.tagext包中找到。
vBKBMnSd >8HcCG 当JSP引擎看到自己的JSP页面中包含有tag标签时,它会调用doStartTag方法来处理tag标签的开头,调用doEndTag方法来处理tag标签的结束。
-x@mS2 IU/dY`J1 下表说明不同类型的tag所需要不同的处理过程:
vJ }^p} BEN=/
v Tag处理类的方法
hcwKi
WOR~tS Tag标签类型
V%
psaT=)P 所调用的方法
*N<~"D hbzU?_} 基本标签
;#cb%e3 doStartTag, doEndTag, release
ZB<goEg WHMt$W}% 带属性的标签
KK}^E_v doStartTag, doEndTag, set/getAttribute1...N, release
i5q
VQo wjQu3 ,Cj 带内容的标签
hH|3s-o doStartTag, doEndTag, release
j:\MrYt0H 9:IVSD&"Rf 带内容的标签,且内容重复循环
GnkNoaU doStartTag, doAfterBody, doEndTag, release
jL>IX`,+6 8?h-H#h 带内容的标签,且内容与JSP交互
+P81&CaY doStartTag, doEndTag, release, doInitBody, doAfterBody, release
Hh4$Qr;R `(.K|l} 一个tag处理类可以通过javax.servlet.jsp.PageContext来与JSP交互,通过javax.servlet.jsp.PageContext类,tag处理类可以访问JSP中的request、session和application对像。
Y6&w0~?! oaM $< 如果tag标签是互相嵌套的,那内层的tag处理类可以通过它的parent属性来访问上层的tag处理类。
zT*EpIa+LS vc5g4ud 一般情况都将所有的tag处理类打成了JAR的包,以便于发布。
O| ) [j@7 VW$ Hzx_z , 0MDkXb Tag库描述(简称TLD)
IXe[JL: j"9bt GX uL\ B[<: Tag库是用xml语言描述的,TLD包括了tag库中所有tag标签的描述,它一般用来被jsp服务器用来校验tag的语法正确性,或者被jsp开发者用来开发新的标签。
r|:i: ii SBgBZm}% TLD的文件扩展名必须为.tld,而且必须放在当前WEB应用的WEB-INF目录或其子目录中。
3g`uLA X>u D:/^TEib 一个TLD的内容的开头必须遵守标准的XML开头,用于描述DTD和xml的版本,例如:
I|@%|sTW >/Gz*. <?xml version="1.0" encoding="ISO-8859-1" ?>
db'Jl^ M6[&od <!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "
http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd">
&2d^=fih TLD必须以<taglib>来作为它的根元素,<taglib>的子元素如下表:
K}L-$B*i bb`GV |^[]Oy= <taglib>的子元素
# 4L[8(+V yn)K1f^ Element
L
Me{5H Description
z}&?^YU*)` nm_]2z O tlib-version
$0~H~- Tag库的版本
xlZ"F ?4P*,c jsp-version
pQKR Tag库所需要的jsp的版本
yIC8Rl @7e h/|Y, short-name
Ep>3%{V 助记符,tag的一个别名(可选)
s{4|eYR ]v{f!r=} uri
;!v2kVuS] 用于确定一个唯一的tag库
DpI)qg#>V n*D-01vYP display-name
AK]{^Hvz 被可视化工具(诸如Jbuilder)用来显示的名称(可选)
)
wtVFG E LZCrh6* small-icon
3Un
q
9 被可视化工具(诸如Jbuilder)用来显示的小图标(可选)
J\^ZRu_K
<C`qJP- large-icon
^1sX22k 被可视化工具(诸如Jbuilder)用来显示的大图标(可选)
lTBPq?4{ $vlq]6V8 description
PGF=q|j9K 对tag库的描述(可选)
\09eH[ _~ZNX+4 listener
rXPq'k'h#- 参见下面listener元素
w7@fiH{
G?AZ%Yx tag
ze@NqCF 参见下面tag 元素
aVNBF` DK;p6_tT Listener元素
{4SwCN / {7.."@Ob<v 一个tag库可能定义一些类做为它的事件侦听类,这些类在TLD中被称为listener 元素,jsp服务器将会实例化这些侦听类,并且注册它们。Listener元素中有一个叫listener-class的子元素,这个元素的值必须是该侦听类的完整类名。
;[V_w/-u ~8L*N>Y Tag元素
osPJ%I`^ G0Q}
1 每个tag元素在tag库中都要指出它的名字、类名、脚本变量、tag的属性。其中脚本变量的值可以直接在TLD中定义或通过tag附加信息的类来取得。每个属性描述了这个属性是否可以省略,它的值是否可以通过<%= …%>这样的JSP语法来获得,以及属性的类型。
aw&:$twbM :8\!; ! 每一个tag在TLD中对应一个tag元素,下表是tag元素的子元素:
,K'>s<} VJmX@zX9 Tag元素的子元素
YNyaz\L ZG:#r\a 元素名称
|\;oFuCv## 描述
+[Cdd{2 /`McKYIP name
K<TVp;N 独一无二的元素名
eM
Ym@~4 Y /$`vgqs tag-class
g`I`q3EF) Tag标签对应的tag处理类
62GP1qH9 "Ah (EZAR
tei-class
l$N
b1& javax.servlet.jsp.tagext.TagExtraInfo的子类,用于表达脚本变量(可选)
#-*7<wN sLrSi body-content
o!!";q%DX Tag标签body的类型
*5?a%p t\Pn67t display-name
nm5zX, 被可视化工具(诸如Jbuilder)用来显示的名称(可选)
x(pq!+~K c@;$6WSG^ small-icon
ilJeI@ 被可视化工具(诸如Jbuilder)用来显示的小图标(可选)
8|*#r[x Z^5j.d{e$ large-icon
k`FCyO 被可视化工具(诸如Jbuilder)用来显示的大图标(可选)
feU]a5%XZ QFt7L description
4gbi?UAmX 此tag标签的描述
9c9FC BNns#Q8a variable
*W
aL}i(P1 提供脚本变量的信息(同tei-class)(可选)
GO0Spf_Gh kzU;24"K attribute
U'(}emh} Tag标签的属性名
`7_=2C =.NZ{G 以下章节介绍对于不同类型的tag,如何具体地实现它们。
Au3>=x` x}o]R l}odW 简单的tag
|:yQOq| k.=67L Hbwjs?Vq?] tag处理类
q ,6 y{RyS -wv5c 简单的tag处理类必须实现Tag接口的doStartTag和doEndTag方法。当jsp引擎碰到tag标签的开头时,doStartTag被调用,因为简单的tag没有body,所以此方法将返回 SKIP_BODY。当jsp引擎碰到tag标签的结尾时,doEndTag被调用,如果余下的页面还要被计算,那它将返回EVAL_PAGE,否则将会返回SKIP_PAGE。
7.g)_W{7} 2ED^uc:
0S 以下是例子:对于标签 <tt:simple /> ,它的tag处理类实现如下:
gSLwpIK% 5dOA^P@`,M hpp>+= public SimpleTag extends TagSupport
Xb +)@Y4h *%<Ku&C {
YF/@]6j
BM PLL2I public int doStartTag() throws JspException
cfI5KLG~# 6!P];3&o\A {
^@f%A< 0w^\sf%s try{
3S='/^l w}n:_e pageContext.getOut().print(“Hello.”);
@gzm4 3l5rUjRwj }catch(Exception e){
kB_u U !G ]=ar&1}J throw new JspTagException(“SimpleTag: “ + e.getMessage());
gNkx]bm Y^5X> }
c*MSd "a;z return SKIP_BODY;
R7aS{8nn "j|}-a }
b(&~f@%| +LddW0h+=8 public int doEndTag()
#:Z"V8n' K^z-G=|N {
qT]Bl+h2 iw1((&^)" return EVAL_PAGE;
Yc;cf%c1 #k? Rl }
_YF~DU ^pz3L'4n }
T8Sgu6:*R ,])@?TJb@ J]uYXsC 注意:如果tag标签没有内容的话,那必须定义body-content元素为空,例如
9D74/3b* ^aVoH/q*C <body-content>empty</body-content>
'G z>X : mY"DYYR> pKK&+umg 带属性的tag标签