标准的JSP 标记可以调用JavaBeans组件或者执行客户的请求,这大大降低了JSP开发的复杂度和维护量。JSP技术也允许你自定义taglib,其实换句话说,taglib可以看成是对JSP标记的一种扩展,正如xml是对html的一种扩展一样。taglib通常定义在tag标签库中,这种标签库存放着你自己定义的tag标签。简而言之,如果使用taglib,那么你可以设计自己的JSP标记!
uQ/h'v (sTuG} 一般来说,自定义tag标签主要用于操作隐藏对象、处理html提交表单、访问数据库或其它企业级的服务,诸如邮件和目录操作等等。自定义tag标签的使用者一般都是那些对java编程语言非常精通,而且对数据访问和企业级服务访问都非常熟悉的程序员,对于HTML设计者来说,使得他可以不去关注那些较复杂的商业逻辑,而将精力放在网页设计上。同时,它也将库开发者和库使用者进行合理分工,自定义tag标签将那些重复工作进行封装,从而大大提高了生产力,而且可以使得tag库可用于不同的项目中,完美地体现了软件复用的思想。
nwmW.(R4 GF$`BGW 在这篇文章中,我们主要讨论:
x#H
3=YD* ;\{`Ci\ · 什么是自定义tag标签?
X+82[Y,mB. :iUF7P1I · 怎么使用tag标签?
k'3Wt*i s'\$t o 声明要使用的tag库
(gXN%rsY >:1P/U o 找到与之对应的tag处理类
RU#F8O 1/Zh^foG o tag标签的类型
se9>.}zZN j
!H^-d}q · 自定义tag标签
S\#1 7.= bC6oqF'# o tag处理类
l"+Jc1\ X SA"8!soY3 o tag库描述
H/fUM ]$b2a&r9 o tag标签示例
*rh,"Zo #&
?g %' o 带属性的tag
mUoIJ3fv_, 5:.{oSy7n o 带body的tag
vbG]mMJ |j~lkzPnV o 定义了脚本变量的tag
B.dT)@Lx0 ('[TLHP o 具有协作关系的tag
vVxD!EL s1j{x&OSq · 自定义tag标签
g(E"4M@t! v|';!p| o 一个迭代tag的例子
^Q}eatEn gl%`qf6:O o 一个模板tag库
B&?sF" Y v6=-g$FG o tag处理类到底是怎样被调用的?
R[B?C;+(O \cJa;WM> PkuTg"; 什么是自定义的tag?
(5Nv8H8| +0l`5."d 一个自定义的tag标签是用户定义的一种JSP标记。当一个含有自定义的tag标签的JSP页面被jsp引擎编译成servlet时,tag标签被转化成了对一个称为tag处理类的对象进行的操作。于是当JSP页面被jsp引擎转化为servlet后,实际上tag标签被转化成为了对tag处理类的操作。
9 ;i\g= Cb;WZ3HR 自定义tag标签有很多特色,诸如:
%;xOB^H^ ~@W*r5/ · 可以在JSP页面中自定义tag标签的属性
p{$p
$/A F>hZ{ · 访问JSP页面中的所有对象
+-?/e-z") yYZxLJ=' · 可以动态地修改页面输出
5@~|*g[ u9qMqeF · 彼此这间可以相互通信。你可以先创建一个JavaBeans组件,然后在一个tag中调用此JavaBeans组件,同时可以在另一个tag中调用它。
Nf41ZT~ ""iaGH+Cxw · tag允许相互嵌套,可以在一个JSP页面中完成一些复杂的交互。
5\fCd| zg)sd1@ K4ZolWbU 使用tag标签
eOT+'[3" J @IS\9O qQ]]~F 本节主要描述怎样在JSP页面中使用tag标签,以及tag标签的不同类型。
]; $] G- C#0Qd% 要使用tag标签,JSP程序员必须做2件事:
5VW|fI iA
}vKQ · 声明此tag标签的tag库
5s{j=.O \*t~==WB · 实现此tag标签
Y"g.IK`V J Yb}Zw; 声明tag标签所在的tag库
O[@q%&_ ~wm;;#_O 如果要使用tag标签,则应用JSP的taglib指示符来指定其tag库(注意:taglib要在在使用此tag标签之前声明)
i yesD bC!`@/ <%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %>
OX]V)QHVZ 5&Ts7& . uri属性定义了唯一的标签库描述(以下简称TLD),它可以是直接是tld文件名或一个独一无二的名字。prefix是用来区别其它TLD中和本TLD中有重名的tag的一种手段。
~Ou1WnmO ,MPB/j^o5! TLD必须以.tld作为扩展名,并且存放在当前应用的WEB-INF目录或其子目录下。你可以通过它的文件名直接引用它,也可以通过别的方式间接地引用它。
o+B:#@9? #]WqM1u 以下taglib指示符直接引用一个TLD:
1 T<+d5[C I{'f|+1 <%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %>
`_ %S HeGYu?& 以下的taglib指示符通过一个逻辑名称间接地引用一个TLD:
6?tlU>A2s QF2q^[>w6 <%@ taglib uri=”/tutorial-template” prefix=”tt” %>
CTa#Q, igL<g 如果是间接引用TLD的话,那你必须还要在web.xml中定义此逻辑名称与tld文件之间的映射,具体做法是在web.xml中加入一个名为taglib的元素:
E>LkJSy= {y= W6uP <taglib>
>4` dy K6JVg$ <taglib-uri>/tutorial-template</taglib-uri>
] ]U<UJ g]~h(mI <taglib-location>
B;6]NCxD YUU-D( /WEB-INF/tutorial-template.tld
G6P)C##ibn Cs3^9m6;d </taglib-location>
y;cUl, :v zdl%iop3e </taglib>
7R.Q
Ql EI~"L$? "^j>tii 实现此tag标签
O) |P,? Xr63?N BAj-akc f 为了实现tag标签,你有2种方法来存放tag处理类。一、让tag处理类以.class的方式存放于当前应用的WEB-INF/class子目录下,二、如果tag处理类是以JAR包的形式存在的话,那可以放在当前应用的WEB-INF/lib目录下,如果tag处理类要在多个应用中共享,那么它就应放在jsp服务器上的common/lib目录下,对于tomcat来说,就是tomcat/common/lib目录下。
k,F"-K+M `A$!]&[~| 6DTTV66 tag标签类型
M,5j5<7 d$ACDX2 }kHdK vZ 自定义的tag标签遵循XML语法。它有一个开始标记和一个结束标记,有的还有body(即文本节点):
*.-.iY.a] P;[OWSR[d <tt:tag>
1F'1>Bu~ -Y#sI3o*R8 body
8M,9kXq{L _ZB\L^j) </tt:tag>
Gl %3XdU %_-zWVJ 9h90huyKF 一个不带body的tag标签如下:
#m{{a]zm^ B5V_e!*5F* <tt:tag />
WF&[HKOy/ JG[o"&Sd thi1kJ`L 简单的tag标签
8(g:HR*; b+-f.!j 一个没有body和属性的tag标签如下:
[H\:pP8t 54;J8XT7 <tt:simple />
0kQPJWF jxaD&4Fs8 X[s8X!# 带属性的tag标签
=h6
sPJ Snly UP~P Pz#7h*;cw. 自定义标签可以有自己的属性。属性一般在开始标记中定义,语法为 attr=”value”。属性的作用相当于自定义标签的一个参数,它影响着tag处理类的行为。你可以在TLD中详细定义它。
9Ya<My 1 2++RkL# 你可以用一个String常量给一个属性赋值,也可以通过表达式给它赋值,如<%= ...%>。以struts为例,它的logic:present标签就是用的String常量来给属性赋值:
%D$,;{ew V-I(WzR9y <loglic:present parameter = “Clear”>
z{"2S=" lU^;Z6f 而另一个标签logic:iterate是用表达式来给属性赋值:
p9U?!L!y r=/;iH?UH <logci:iterate collection=”<%= bookDB.getBooks() %>”
Yb i%od& OJN2z id=”book” type=”database.BookDetails”>
ev0oO+u w@-PqsF X:a`B(@S 带body的tag标签
N..j{FE <}U'V}g 一个自定义标签可以包含其它自定义标签、脚本变量、HTML标记或其它内容。
L9Z;:``p GuZ( &G6* 在下述例子中,此JSP页面使用了struts的logic:present标签,如果些标签定义了parameter=”Clear”的属性,则将清除购物车的内容,然后打印出一条信息:
4H5pr jN-vY<?h] <logic:present parameter=”Clear”>
P7ph}mB etT + <% cart.clear(); %>
X8dR+xd +;g{$da5 <font color=”#ff0000” size=”+2”><strong>
XoLJ L]+? \$aF&r<R 你选择了清除购物车!
9`jcC-;iv k:2QuG^ </strong></font>
C3hv* x^|V af </logic:present>
IEjP<pLe x83
!C}4: Nw& !}#m 到底是用属性还是用body来传递信息?
hmx=
35 9][(Iu]h7 如上所述,我们既可以通过属性,也可以通过body来传递信息。但一般来说,比较简单的类型,如字符串或简单表达式最好采用属性来传递信息。
n,eJ$2!J YSJy` F/m^?{==~* 定义脚本变量的tag标签
-LDCBc" *#%9Rp2| 所谓脚本变量,是指JSP中可以调用的变量或对象。它可由tag标签产生。以下示例阐述了一个tag标签定义了一个名为tx的由JNDI所定义的事务处理对象。脚本变量可以是ejb对象、事务、数据库连接等等:
PkE5|d*, SvN9aD1 <tt:lookup id=”tx” type=”UserTransaction” name=”java:comp/UserTransaction” />
_LAS~x7, HkV1sT <% tx.begin(); %>
IX: 25CEI2 2)#K+O3c ...
8Y0"Cejq ~^u16z, Wk:hFHs3 具有协作关系的tag标签
E_F5(xSA }R3=fbe,\ 自定义tag标签之间可以通过共享对象来实现协作。在下述例子中,标签tag1创建了一个名为obj1的对象,在标签tag2仍可以重复使用obj。
nJRS.xs mS#zraJn5 <tt:tag1 attr1=”obj1” value1=”value” />
ccCzu6 %N;!+
;F_g <tt:tag2 attr1=”obj1” />
Tmh(=
TB' /vY_Y3k# 在以下这个例子当中,如果外层的tag标签创建了一个对象,那么其内层的所有tag标签都可以使用这个对象。由于这样产生的对象没有一个指定的名字,那么就可以将少重名的冲突。这个例子阐述了一系列协作的嵌套对象。
!3mA0-!+ I -Xlx< <tt:outerTag>
6:U$w7P0
e =ji1S}e~p <tt:innerTag />
lPLz@Up~ _|72r}j </tt:outerTag>
A^ _a3$,0 OA:%lC! {T"0DSV Tag处理类
h2ZkCML |/gW_;( d!KsNkk Tag处理类必须实现Tag接口或BodyTag接口,不过现在一般都流行从TagSupport或BodyTagSupport类中继承,这些类或接口都可以在javax.servlet.jsp.tagext包中找到。
f:g,_|JD$ -p-B2?)A 当JSP引擎看到自己的JSP页面中包含有tag标签时,它会调用doStartTag方法来处理tag标签的开头,调用doEndTag方法来处理tag标签的结束。
`X,yM-( rC:?l(8ng3 下表说明不同类型的tag所需要不同的处理过程:
L,d
LE-L TI9UXa:V\ Tag处理类的方法
w ;daC(: hYQ_45Z*? Tag标签类型
*A}cL 所调用的方法
g}laG8 kc7lc|'z 基本标签
mzQ`N}]T: doStartTag, doEndTag, release
b}T6v zkTp`>9R 带属性的标签
|IunpZV doStartTag, doEndTag, set/getAttribute1...N, release
Ngb(F84H? v+jsC`m 带内容的标签
eI1GXQ% doStartTag, doEndTag, release
tb:L\A^: 5XuT={o 带内容的标签,且内容重复循环
LlBN-9p doStartTag, doAfterBody, doEndTag, release
t_ksvWUo g}p;\o
带内容的标签,且内容与JSP交互
pV6d
Id doStartTag, doEndTag, release, doInitBody, doAfterBody, release
J$~<V
IX [1 Ydo` 一个tag处理类可以通过javax.servlet.jsp.PageContext来与JSP交互,通过javax.servlet.jsp.PageContext类,tag处理类可以访问JSP中的request、session和application对像。
[D5t{[i |QV!-LK 如果tag标签是互相嵌套的,那内层的tag处理类可以通过它的parent属性来访问上层的tag处理类。
!*2%"H* 0O k,oW{ 一般情况都将所有的tag处理类打成了JAR的包,以便于发布。
8/z3=O& pfx3C* lpH=2l$>? Tag库描述(简称TLD)
B?$ "\;& D>Gt]s nhG
J Tag库是用xml语言描述的,TLD包括了tag库中所有tag标签的描述,它一般用来被jsp服务器用来校验tag的语法正确性,或者被jsp开发者用来开发新的标签。
j3q~E[Mz\ lTU$0CG TLD的文件扩展名必须为.tld,而且必须放在当前WEB应用的WEB-INF目录或其子目录中。
=8gHS[ /6O??6g 一个TLD的内容的开头必须遵守标准的XML开头,用于描述DTD和xml的版本,例如:
!_2n X0-IRJ[ <?xml version="1.0" encoding="ISO-8859-1" ?>
8q`$y$06Dk v^ d]rSm <!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "
http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd">
&C>/L; TLD必须以<taglib>来作为它的根元素,<taglib>的子元素如下表:
nA?Hxos Y!6/[<r$~k 6Es?
MW= <taglib>的子元素
mAk{"65V nUq<TJ Element
A]L%dFK Description
3:%QB9qc]' !ZDzEP* tlib-version
+.y
.Mp Tag库的版本
Ev!{n /~4"No@ jsp-version
iR$<$P5 Tag库所需要的jsp的版本
kj+#TnF- x\2?ym@ short-name
ND<!4!R^ 助记符,tag的一个别名(可选)
~.%K/=wK @ oJKa"H-jL uri
::n;VY2& 用于确定一个唯一的tag库
.oEmU+ ^$%Z!uz display-name
nN$Y(2ZN 被可视化工具(诸如Jbuilder)用来显示的名称(可选)
E{HY!L[ \,!QJp4 small-icon
mVtXcP4b 被可视化工具(诸如Jbuilder)用来显示的小图标(可选)
%AF5= DoC(Z)o large-icon
vaf&X]p 被可视化工具(诸如Jbuilder)用来显示的大图标(可选)
)'l*Tl A?G IBjs description
b]E|* 对tag库的描述(可选)
?)'~~@NkH 39{{7(hh listener
Qr#1 u 参见下面listener元素
k7tYa;C *%Qn{x tag
s08u @ 参见下面tag 元素
.I3?7 bYe;b><G Listener元素
!~_zm*CqbZ tgL$"chj@x 一个tag库可能定义一些类做为它的事件侦听类,这些类在TLD中被称为listener 元素,jsp服务器将会实例化这些侦听类,并且注册它们。Listener元素中有一个叫listener-class的子元素,这个元素的值必须是该侦听类的完整类名。
y {q*s8NY zU6a'tP Tag元素
jQU"Ved !?
^h;)a 每个tag元素在tag库中都要指出它的名字、类名、脚本变量、tag的属性。其中脚本变量的值可以直接在TLD中定义或通过tag附加信息的类来取得。每个属性描述了这个属性是否可以省略,它的值是否可以通过<%= …%>这样的JSP语法来获得,以及属性的类型。
P?BGBbC JcJmds 每一个tag在TLD中对应一个tag元素,下表是tag元素的子元素:
~_9"3,~o5 (2?G:+C 7 Tag元素的子元素
W:i?t8y\y z}SND9-" 元素名称
PLM _#+R> 描述
xr0haN\p" $o@R^sJ name
\qi|Js*{ 独一无二的元素名
]E3U
J!! UDf9FnG}L tag-class
c= UU" Tag标签对应的tag处理类
8#R?]Uwq f[gqT
yiP tei-class
G0n'KB javax.servlet.jsp.tagext.TagExtraInfo的子类,用于表达脚本变量(可选)
>#+IaKL7 l0*Gb body-content
3CTX -#)vS Tag标签body的类型
4eVI}, (3\Xy display-name
dQy>Nmfy 被可视化工具(诸如Jbuilder)用来显示的名称(可选)
S\y%4}j [fu!AIQs small-icon
- ~O'vLG 被可视化工具(诸如Jbuilder)用来显示的小图标(可选)
v"+k~:t* ryO$6L large-icon
fpM#XFj 被可视化工具(诸如Jbuilder)用来显示的大图标(可选)
~Lfcg* }aB#z<B6 description
nW\(IkX\ 此tag标签的描述
QbYc[8-[ ')+0nPV variable
gG54: 提供脚本变量的信息(同tei-class)(可选)
jc_\'Gr+[ 8:ggECD attribute
mN0=i(H< Tag标签的属性名
3L-^<'~-k; ,xJrXPW 以下章节介绍对于不同类型的tag,如何具体地实现它们。
4yMW^:@ $awi>#[ nbofYI$rd& 简单的tag
9T2xU3UyY \zXlN %Xh fXd' tag处理类
gL$&@NY '(@YK4_M 简单的tag处理类必须实现Tag接口的doStartTag和doEndTag方法。当jsp引擎碰到tag标签的开头时,doStartTag被调用,因为简单的tag没有body,所以此方法将返回 SKIP_BODY。当jsp引擎碰到tag标签的结尾时,doEndTag被调用,如果余下的页面还要被计算,那它将返回EVAL_PAGE,否则将会返回SKIP_PAGE。
ScnY3&rc %@&a7JOL 以下是例子:对于标签 <tt:simple /> ,它的tag处理类实现如下:
#*q2d OVoO6F] { }e^eJ public SimpleTag extends TagSupport
pLoy <v]9lw' {
^<V9'Ut upn8n vy4( public int doStartTag() throws JspException
g: %9jf P1 +"v* {
\Z5+$Ij sB}]yw try{
(4~WWU (iT )jW(6 pageContext.getOut().print(“Hello.”);
jy$@a%FD 4yV].2#rl" }catch(Exception e){
dK?);*w] ft5DU/% throw new JspTagException(“SimpleTag: “ + e.getMessage());
ol!86rky euRss#; }
H~+xB1 [$:,-Q @ return SKIP_BODY;
:F|\Ij0T )y50Mb0+ }
!c8L[/L ;"7/@&M\m public int doEndTag()
T nxKR$Hoh w$Ux?y-L {
xe:' 8J6L 3A0_C?E return EVAL_PAGE;
eqzTQen8q tjzA)/T,4 }
\XH@b6{ )LFD6\z1pl }
p]f&mBO* b :\D\X |$w*RI0C 注意:如果tag标签没有内容的话,那必须定义body-content元素为空,例如
)mD\d|7f E2:D(7(;l <body-content>empty</body-content>
rc~Y=m Z;*`fd?8 _Xh=&(/8@ 带属性的tag标签