标准的JSP 标记可以调用JavaBeans组件或者执行客户的请求,这大大降低了JSP开发的复杂度和维护量。JSP技术也允许你自定义taglib,其实换句话说,taglib可以看成是对JSP标记的一种扩展,正如xml是对html的一种扩展一样。taglib通常定义在tag标签库中,这种标签库存放着你自己定义的tag标签。简而言之,如果使用taglib,那么你可以设计自己的JSP标记!
|yr}g-m $|KbjpQ 一般来说,自定义tag标签主要用于操作隐藏对象、处理html提交表单、访问数据库或其它企业级的服务,诸如邮件和目录操作等等。自定义tag标签的使用者一般都是那些对java编程语言非常精通,而且对数据访问和企业级服务访问都非常熟悉的程序员,对于HTML设计者来说,使得他可以不去关注那些较复杂的商业逻辑,而将精力放在网页设计上。同时,它也将库开发者和库使用者进行合理分工,自定义tag标签将那些重复工作进行封装,从而大大提高了生产力,而且可以使得tag库可用于不同的项目中,完美地体现了软件复用的思想。
(Q&Z/Fe kq+L63fZ 在这篇文章中,我们主要讨论:
HUH=Y; hz!.|U@,{< · 什么是自定义tag标签?
{dDU^7O Q =Z-vTD+ · 怎么使用tag标签?
G"]'`2.m *=rl<?tX o 声明要使用的tag库
@L0.Z1 ). sqhM[u
k o 找到与之对应的tag处理类
^+88z> $P$OWp?b o tag标签的类型
$|AxQQ%f h8Gp>b · 自定义tag标签
"\30YO>\ *5^h>Vk/ o tag处理类
:0/I2: ;TYkJH" o tag库描述
~ ~&M&Fe
k2~j:&p o tag标签示例
WE\V<MGS/ c(fwl`y!x o 带属性的tag
?o2L C.eZcNJG o 带body的tag
b$hQB090 tlE+G@|^ o 定义了脚本变量的tag
]. eGsh2 V<b"jCXI o 具有协作关系的tag
>Gkkr{s9 ` 6PdMvF · 自定义tag标签
MOXDR 9!tRM- o 一个迭代tag的例子
."${.BPn~ <Fi/! o 一个模板tag库
ZDlMkHJ 4q2aVm o tag处理类到底是怎样被调用的?
V}& (fC [Y b1-JnEc 什么是自定义的tag?
=KkHck33 a4?:suX$ 一个自定义的tag标签是用户定义的一种JSP标记。当一个含有自定义的tag标签的JSP页面被jsp引擎编译成servlet时,tag标签被转化成了对一个称为tag处理类的对象进行的操作。于是当JSP页面被jsp引擎转化为servlet后,实际上tag标签被转化成为了对tag处理类的操作。
P:=3;d{v J^U#dYd 自定义tag标签有很多特色,诸如:
*g7dB2{ @#nB]qV:e · 可以在JSP页面中自定义tag标签的属性
h/d&P bx1' · 访问JSP页面中的所有对象
o}<}zTU S>nM&758 · 可以动态地修改页面输出
,`K'qms VK8 5A · 彼此这间可以相互通信。你可以先创建一个JavaBeans组件,然后在一个tag中调用此JavaBeans组件,同时可以在另一个tag中调用它。
e tY9Pq p tMysYT' · tag允许相互嵌套,可以在一个JSP页面中完成一些复杂的交互。
vtmvvv Pl
U!-7 {A{=RPL 使用tag标签
P'[w9'B u>}k+8~ Eg>MG87 本节主要描述怎样在JSP页面中使用tag标签,以及tag标签的不同类型。
7^=O^!sa 0EOpK%{ 要使用tag标签,JSP程序员必须做2件事:
S~hNSw(- -[Q%Vv!8 · 声明此tag标签的tag库
$Ad 5hkz 3eD#[jkAI; · 实现此tag标签
Pn0V{SJOJ% B+ +:7! 声明tag标签所在的tag库
~nw]q<7r /_v@YB!0 如果要使用tag标签,则应用JSP的taglib指示符来指定其tag库(注意:taglib要在在使用此tag标签之前声明)
1qtu,yIf in$Pk$ c <%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %>
X2~>Z^,
U *:wu{3g}M` uri属性定义了唯一的标签库描述(以下简称TLD),它可以是直接是tld文件名或一个独一无二的名字。prefix是用来区别其它TLD中和本TLD中有重名的tag的一种手段。
k? X7h2 zgV{S
Qo TLD必须以.tld作为扩展名,并且存放在当前应用的WEB-INF目录或其子目录下。你可以通过它的文件名直接引用它,也可以通过别的方式间接地引用它。
Drz#D1-2 Z':}ZXy] 以下taglib指示符直接引用一个TLD:
iphe0QE[#} x,pzX( <%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %>
a8''t_Dp Z8Qmj5'[ 以下的taglib指示符通过一个逻辑名称间接地引用一个TLD:
Ry8@U9B6,t l:%4@t` <%@ taglib uri=”/tutorial-template” prefix=”tt” %>
4$C:r&K w`q):yXX 如果是间接引用TLD的话,那你必须还要在web.xml中定义此逻辑名称与tld文件之间的映射,具体做法是在web.xml中加入一个名为taglib的元素:
wjDLsf, d
H]'&&M <taglib>
m
z) O 'Tj9btM*cL <taglib-uri>/tutorial-template</taglib-uri>
&^92z:? ZBi|BD <taglib-location>
%[b~4,c1 crG+BFi /WEB-INF/tutorial-template.tld
"aHA6zTB 4fgA3% </taglib-location>
yc?+L;fN C[z5&
x2 </taglib>
P
>HEV
a va[@XGaC3 `L /\F, 实现此tag标签
>8\EdN59{ uDbz`VpK 9v=5x[fE 为了实现tag标签,你有2种方法来存放tag处理类。一、让tag处理类以.class的方式存放于当前应用的WEB-INF/class子目录下,二、如果tag处理类是以JAR包的形式存在的话,那可以放在当前应用的WEB-INF/lib目录下,如果tag处理类要在多个应用中共享,那么它就应放在jsp服务器上的common/lib目录下,对于tomcat来说,就是tomcat/common/lib目录下。
hKj"Lb9] Tapj7/0` %3!DRz tag标签类型
g4^=Q'j- 4*&_h g)h '#L.w6<B 自定义的tag标签遵循XML语法。它有一个开始标记和一个结束标记,有的还有body(即文本节点):
\L Gj]mb1 V*U{q%p( <tt:tag>
Ey4%N`H-^
bVaydJ* body
gP:mZ7 kdcr*7w </tt:tag>
]lV\D8# PRa#;Wb B@U;[cO& 一个不带body的tag标签如下:
hE@s~~JYd *z&m=G\ <tt:tag />
,'N8Ivt F l@%? )%FRBO] 简单的tag标签
C7:;<<"P _Z'[-rcXWh 一个没有body和属性的tag标签如下:
[<CIh46S. os9X)G <tt:simple />
8K$q6V%# U 51C /A Q4i@y6z 带属性的tag标签
qn=~4rg]R I*hCIy#; jzt$ 自定义标签可以有自己的属性。属性一般在开始标记中定义,语法为 attr=”value”。属性的作用相当于自定义标签的一个参数,它影响着tag处理类的行为。你可以在TLD中详细定义它。
pu3ly&T#a_ :!Ea.v 你可以用一个String常量给一个属性赋值,也可以通过表达式给它赋值,如<%= ...%>。以struts为例,它的logic:present标签就是用的String常量来给属性赋值:
5'*v-l,[ d)d\h`=Z <loglic:present parameter = “Clear”>
{kVhht]X V}_M\Y^^; 而另一个标签logic:iterate是用表达式来给属性赋值:
\-i5b %\<SSp^n <logci:iterate collection=”<%= bookDB.getBooks() %>”
a$-:F$z |:Q`9; id=”book” type=”database.BookDetails”>
+a7J;-| tgz )4u6{-|A 带body的tag标签
AT$eTZ]M pH!e<m 一个自定义标签可以包含其它自定义标签、脚本变量、HTML标记或其它内容。
MOp06 walQo^< 在下述例子中,此JSP页面使用了struts的logic:present标签,如果些标签定义了parameter=”Clear”的属性,则将清除购物车的内容,然后打印出一条信息:
]N<:6+ :jo
!Yi <logic:present parameter=”Clear”>
9OI&De5?=V b8o}bm{s <% cart.clear(); %>
fdk]i/*) H&
L <font color=”#ff0000” size=”+2”><strong>
wd86 y /-J12 O 你选择了清除购物车!
*?dw`j_b > :s(vn Ie^ </strong></font>
<B"M} Y>_P N3 O~_=/v? </logic:present>
>Z-f</v03 p) '.swpJ J)yNp,V 到底是用属性还是用body来传递信息?
ii,/omn: (?[^##03MN 如上所述,我们既可以通过属性,也可以通过body来传递信息。但一般来说,比较简单的类型,如字符串或简单表达式最好采用属性来传递信息。
vuP.V# \l$gcFXb H!uB&qY 定义脚本变量的tag标签
r92C^h0 @-9u;aL 所谓脚本变量,是指JSP中可以调用的变量或对象。它可由tag标签产生。以下示例阐述了一个tag标签定义了一个名为tx的由JNDI所定义的事务处理对象。脚本变量可以是ejb对象、事务、数据库连接等等:
HH`G/(a JrZ"AId2 <tt:lookup id=”tx” type=”UserTransaction” name=”java:comp/UserTransaction” />
>U?U;i L&*/s&>b <% tx.begin(); %>
sA!,)'6 [
QHSCF5 ...
kta`[%KmIZ ,AX7~;hpq ~_|OGp_a 具有协作关系的tag标签
.@7J8FS* YTWlR]Tr6? 自定义tag标签之间可以通过共享对象来实现协作。在下述例子中,标签tag1创建了一个名为obj1的对象,在标签tag2仍可以重复使用obj。
~x}/>-d >'\cNM~nf <tt:tag1 attr1=”obj1” value1=”value” />
&tKr
?l ~D[5AXV`^ <tt:tag2 attr1=”obj1” />
? dD<KCbP, 5yC$G{yV 在以下这个例子当中,如果外层的tag标签创建了一个对象,那么其内层的所有tag标签都可以使用这个对象。由于这样产生的对象没有一个指定的名字,那么就可以将少重名的冲突。这个例子阐述了一系列协作的嵌套对象。
CY{`IZ (+_i^SqK <tt:outerTag>
!4gyrNS UBN^dbP* <tt:innerTag />
/<J&ZoeJB qhNY< </tt:outerTag>
S4qj}`$
Yv d`M]>EDXp zzq7?]D Tag处理类
RfM
uWo: -&3WN!egq ?$:;hGO.<~ Tag处理类必须实现Tag接口或BodyTag接口,不过现在一般都流行从TagSupport或BodyTagSupport类中继承,这些类或接口都可以在javax.servlet.jsp.tagext包中找到。
7F=Xn@ _ EKwA1,Xz 当JSP引擎看到自己的JSP页面中包含有tag标签时,它会调用doStartTag方法来处理tag标签的开头,调用doEndTag方法来处理tag标签的结束。
:
5=E>! X}!r4<;( 下表说明不同类型的tag所需要不同的处理过程:
!sbKJ+V7 s*blZdP Tag处理类的方法
HkgmZw, ^Md]e<WAp Tag标签类型
~[E@P1 所调用的方法
;a]Lxx;- }digw( 基本标签
SHM
?32' doStartTag, doEndTag, release
!`S`%\" D'dE!CAUs 带属性的标签
*TacVp doStartTag, doEndTag, set/getAttribute1...N, release
QEUr+7[ mQVc ZV 带内容的标签
z%
ln} doStartTag, doEndTag, release
ML6V,-KU v&.`^O3W 带内容的标签,且内容重复循环
>O7ITy doStartTag, doAfterBody, doEndTag, release
IYJS>G%* In%K 带内容的标签,且内容与JSP交互
W> ZL[BQ doStartTag, doEndTag, release, doInitBody, doAfterBody, release
ulc m X<6Ro
es2 一个tag处理类可以通过javax.servlet.jsp.PageContext来与JSP交互,通过javax.servlet.jsp.PageContext类,tag处理类可以访问JSP中的request、session和application对像。
co
<ATx <ZF,3~v? 如果tag标签是互相嵌套的,那内层的tag处理类可以通过它的parent属性来访问上层的tag处理类。
F0cde 8|\0\Wd;vu 一般情况都将所有的tag处理类打成了JAR的包,以便于发布。
ct,Iu+HJ NS^(5g caK<;bmu- Tag库描述(简称TLD)
@O~ o_!=-AWV m-{t%[Y Tag库是用xml语言描述的,TLD包括了tag库中所有tag标签的描述,它一般用来被jsp服务器用来校验tag的语法正确性,或者被jsp开发者用来开发新的标签。
'/Y
D$*, j _r?4k TLD的文件扩展名必须为.tld,而且必须放在当前WEB应用的WEB-INF目录或其子目录中。
8XwZJ\5 "X\|!Mxh 一个TLD的内容的开头必须遵守标准的XML开头,用于描述DTD和xml的版本,例如:
f^
q0#+k ) .I6:iB <?xml version="1.0" encoding="ISO-8859-1" ?>
"K.Xo G4| Nk~Xz <!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "
http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd">
$Vu%4kq TLD必须以<taglib>来作为它的根元素,<taglib>的子元素如下表:
]e*Zx;6oi 1KH]l336D" RC[b+J,q <taglib>的子元素
t>W^^'=E +Lq;0tRC Element
VxlK:*t` Description
q T16th[D ."N`X\ tlib-version
x2P}8Idg?A Tag库的版本
me-:A:si /3MTutM|<X jsp-version
t}Z*2=DO Tag库所需要的jsp的版本
HwE1cOT xB&kxW.; short-name
H9c 助记符,tag的一个别名(可选)
}~8/a3 nG0Uv%?{pj uri
c&A;0**K, 用于确定一个唯一的tag库
/EJwO3MW (IAc*V~ display-name
^X&`:f 被可视化工具(诸如Jbuilder)用来显示的名称(可选)
W{0gtT0 =y5~7&9' small-icon
r_sZw@lqJ 被可视化工具(诸如Jbuilder)用来显示的小图标(可选)
X>i`z Ch`nDIne large-icon
hq5=>p 被可视化工具(诸如Jbuilder)用来显示的大图标(可选)
pq
\M;& /0w?"2- description
Yl65|=ne 对tag库的描述(可选)
Bld%d:i b4_"dg~gK listener
<Pg]V:=g' 参见下面listener元素
\ 2Jr(?U (h"Yw tag
oXCZpS 参见下面tag 元素
EYwDv4H,g %-z AV*> Listener元素
8vN} v3HV& 9*?H/iN@p? 一个tag库可能定义一些类做为它的事件侦听类,这些类在TLD中被称为listener 元素,jsp服务器将会实例化这些侦听类,并且注册它们。Listener元素中有一个叫listener-class的子元素,这个元素的值必须是该侦听类的完整类名。
T<p,KqH B{ i5UhxD Tag元素
aL wd#/! A+JM* eB 每个tag元素在tag库中都要指出它的名字、类名、脚本变量、tag的属性。其中脚本变量的值可以直接在TLD中定义或通过tag附加信息的类来取得。每个属性描述了这个属性是否可以省略,它的值是否可以通过<%= …%>这样的JSP语法来获得,以及属性的类型。
\O]1QM94Y rcc.FS 每一个tag在TLD中对应一个tag元素,下表是tag元素的子元素:
!PCw-& =~Ac=j!q Tag元素的子元素
?K<m.+4b*y rUunf'w`e1 元素名称
qXHr[C" 描述
$(2c0S{ 1 /]/3)@wT name
:U5>. ): 独一无二的元素名
^k&T