标准的JSP 标记可以调用JavaBeans组件或者执行客户的请求,这大大降低了JSP开发的复杂度和维护量。JSP技术也允许你自定义taglib,其实换句话说,taglib可以看成是对JSP标记的一种扩展,正如xml是对html的一种扩展一样。taglib通常定义在tag标签库中,这种标签库存放着你自己定义的tag标签。简而言之,如果使用taglib,那么你可以设计自己的JSP标记!
"Y- WY,H $P%cdJ T0 一般来说,自定义tag标签主要用于操作隐藏对象、处理html提交表单、访问数据库或其它企业级的服务,诸如邮件和目录操作等等。自定义tag标签的使用者一般都是那些对java编程语言非常精通,而且对数据访问和企业级服务访问都非常熟悉的程序员,对于HTML设计者来说,使得他可以不去关注那些较复杂的商业逻辑,而将精力放在网页设计上。同时,它也将库开发者和库使用者进行合理分工,自定义tag标签将那些重复工作进行封装,从而大大提高了生产力,而且可以使得tag库可用于不同的项目中,完美地体现了软件复用的思想。
)1HWD]>4 b&LAk-}[ 在这篇文章中,我们主要讨论:
A&WC})H5 d/~g3n>| · 什么是自定义tag标签?
\[*q~95$v .|s,':hA · 怎么使用tag标签?
&CN(PZv +PKsiUJ| o 声明要使用的tag库
fz2}M:u S3E5^n\\ o 找到与之对应的tag处理类
dB0
UZirb mF jM6pmo o tag标签的类型
lNWP9?X ;_E|I=%'E · 自定义tag标签
X:g#&e_ ~<_WYSzS o tag处理类
r`h".=oD jh`[Y7RJO o tag库描述
;ny 9q ={N1j<%fh o tag标签示例
{ w sT ?A*!rW:l; o 带属性的tag
Qh-:P`CN ?#z<<FR o 带body的tag
[+xsX*+ W7!iYxO o 定义了脚本变量的tag
n+YUG c/v|e&q o 具有协作关系的tag
uKvdL
" 2+~gZxHq · 自定义tag标签
{P_7AM cF8 X o 一个迭代tag的例子
zR]!g|;f x-%RRm<V o 一个模板tag库
(}.MB3`#C (K84J*; o tag处理类到底是怎样被调用的?
N@}h 4K?
\5(b e3~{l~Rb 什么是自定义的tag?
c%gL3kOT &);P|v`8 一个自定义的tag标签是用户定义的一种JSP标记。当一个含有自定义的tag标签的JSP页面被jsp引擎编译成servlet时,tag标签被转化成了对一个称为tag处理类的对象进行的操作。于是当JSP页面被jsp引擎转化为servlet后,实际上tag标签被转化成为了对tag处理类的操作。
6o(IL-0]c ?# _{h 自定义tag标签有很多特色,诸如:
=y)K er *L$_80 · 可以在JSP页面中自定义tag标签的属性
$j<KXR NX.5u8Pf · 访问JSP页面中的所有对象
*pv<ZF0> y1Z>{SDiq · 可以动态地修改页面输出
ov;^ev,( c1jRj=\ · 彼此这间可以相互通信。你可以先创建一个JavaBeans组件,然后在一个tag中调用此JavaBeans组件,同时可以在另一个tag中调用它。
2.b,8wT/ -C3 [:g · tag允许相互嵌套,可以在一个JSP页面中完成一些复杂的交互。
0gaHYqkA>} @p
WN5VL )Se$N6u- 使用tag标签
hd~#I<8;2 <p*k-mfr ]77f`<q<}! 本节主要描述怎样在JSP页面中使用tag标签,以及tag标签的不同类型。
:/$WeAg liH#=C8l*% 要使用tag标签,JSP程序员必须做2件事:
9 i/
( t&J A1|q · 声明此tag标签的tag库
f pq|mY 2%`=
LGQC · 实现此tag标签
W&%,XwkQ dgoAaS2M 声明tag标签所在的tag库
4YikC .O5V;&, 如果要使用tag标签,则应用JSP的taglib指示符来指定其tag库(注意:taglib要在在使用此tag标签之前声明)
1Z @sh>X| '6&o:t <%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %>
/[\g8U{5B} }P.Z}n;Uj uri属性定义了唯一的标签库描述(以下简称TLD),它可以是直接是tld文件名或一个独一无二的名字。prefix是用来区别其它TLD中和本TLD中有重名的tag的一种手段。
V@#oQi* rlY0UA, TLD必须以.tld作为扩展名,并且存放在当前应用的WEB-INF目录或其子目录下。你可以通过它的文件名直接引用它,也可以通过别的方式间接地引用它。
%\T,=9tD\ B\)Te9k' 以下taglib指示符直接引用一个TLD:
4d PTrBQ? _Tor9Tj <%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %>
kodd7 AD Xi[]8o 以下的taglib指示符通过一个逻辑名称间接地引用一个TLD:
O=RS</01! 0r1GGEW`s <%@ taglib uri=”/tutorial-template” prefix=”tt” %>
89 (qU FrXP"U}Y 如果是间接引用TLD的话,那你必须还要在web.xml中定义此逻辑名称与tld文件之间的映射,具体做法是在web.xml中加入一个名为taglib的元素:
Z}uY%] |zpy!X 3 <taglib>
Qa )+Tv In96H` <taglib-uri>/tutorial-template</taglib-uri>
=N\; ?eF( wPjq
B{!Q <taglib-location>
KxX [8 P7XZ|Td4* /WEB-INF/tutorial-template.tld
m]>zdP+ o&E8<e </taglib-location>
9Sxr9FLW~ e>Z&0lV: </taglib>
@NRN#~S,_] Y|fD)zG_ 018SFle 实现此tag标签
-|#{V.G3' v7
*L3Ol
^rVHaI 为了实现tag标签,你有2种方法来存放tag处理类。一、让tag处理类以.class的方式存放于当前应用的WEB-INF/class子目录下,二、如果tag处理类是以JAR包的形式存在的话,那可以放在当前应用的WEB-INF/lib目录下,如果tag处理类要在多个应用中共享,那么它就应放在jsp服务器上的common/lib目录下,对于tomcat来说,就是tomcat/common/lib目录下。
0@-4.IHl fe/;U=te zY_J7,0g tag标签类型
8O'bCBhv y%i9 b&gDd Gc`PO 自定义的tag标签遵循XML语法。它有一个开始标记和一个结束标记,有的还有body(即文本节点):
:C} I6v= &<98nT <tt:tag>
Jq&Hz$L| >^jBE'' body
T(?w}i ]i.N'O<p </tt:tag>
?uSoJM`wa! {wz)^A
sy wBXa;. 一个不带body的tag标签如下:
hi!A9T3%}M s`bGW1#io <tt:tag />
+Pl)E5W!=` TUnAsE/J& bQautRW 简单的tag标签
I2$DlEke Ow/,pC >V 一个没有body和属性的tag标签如下:
W:RjWn @< KBB)xez8 <tt:simple />
M/p9 I
gp x*vD^1"'P $UH:r 带属性的tag标签
Z8$BgP %Z_O\zRqy) z;1dMQ,# 自定义标签可以有自己的属性。属性一般在开始标记中定义,语法为 attr=”value”。属性的作用相当于自定义标签的一个参数,它影响着tag处理类的行为。你可以在TLD中详细定义它。
'M~`IN` QGuqV8 y0 你可以用一个String常量给一个属性赋值,也可以通过表达式给它赋值,如<%= ...%>。以struts为例,它的logic:present标签就是用的String常量来给属性赋值:
e' l9 -n 9&W <loglic:present parameter = “Clear”>
%@vF% D ;> 7y}\ 而另一个标签logic:iterate是用表达式来给属性赋值:
m~
ah!QM 6AJk6W^Z <logci:iterate collection=”<%= bookDB.getBooks() %>”
wI|h9q1U .b]sQ' id=”book” type=”database.BookDetails”>
JI.=y5I .gg0rTf=- i4|R0>b 带body的tag标签
GFdbwn5B fG'~@'P~ 一个自定义标签可以包含其它自定义标签、脚本变量、HTML标记或其它内容。
({j8|{)+ l9f_NJHo 在下述例子中,此JSP页面使用了struts的logic:present标签,如果些标签定义了parameter=”Clear”的属性,则将清除购物车的内容,然后打印出一条信息:
Wz'!stcp hEB5=~A_ <logic:present parameter=”Clear”>
G*N[t w 5bt>MoKxv <% cart.clear(); %>
~wDXjn"U& N 5*Qnb8 <font color=”#ff0000” size=”+2”><strong>
,kJ7c;:i I*N"_uKU 你选择了清除购物车!
kC. !cPd |qMG@ </strong></font>
5c]:/9& *Mhirz%iD </logic:present>
+ kMj|()>\ V,rc&97 Vq+7 /+2" 到底是用属性还是用body来传递信息?
5\pS8<RJ; o>8~rtl 如上所述,我们既可以通过属性,也可以通过body来传递信息。但一般来说,比较简单的类型,如字符串或简单表达式最好采用属性来传递信息。
.+1I>L T]wI) 62HA[cr&) 定义脚本变量的tag标签
YAc:QVT87 X\Bl?
F
所谓脚本变量,是指JSP中可以调用的变量或对象。它可由tag标签产生。以下示例阐述了一个tag标签定义了一个名为tx的由JNDI所定义的事务处理对象。脚本变量可以是ejb对象、事务、数据库连接等等:
jcqUY+T$ aPelt` <tt:lookup id=”tx” type=”UserTransaction” name=”java:comp/UserTransaction” />
>}* W$i <u\Hy0g <% tx.begin(); %>
xJ$uoy3+ ,A{Bx`o? ...
A8&@Vxdz 8S#$'2sT O z0-cM8t 具有协作关系的tag标签
Sn*s@RE\s ,pD sU @ 自定义tag标签之间可以通过共享对象来实现协作。在下述例子中,标签tag1创建了一个名为obj1的对象,在标签tag2仍可以重复使用obj。
eV*QUjS~
!tTv$L> <tt:tag1 attr1=”obj1” value1=”value” />
r[!~~yu/o }3: mn <tt:tag2 attr1=”obj1” />
5&s6(?,Eu m
.(ja 在以下这个例子当中,如果外层的tag标签创建了一个对象,那么其内层的所有tag标签都可以使用这个对象。由于这样产生的对象没有一个指定的名字,那么就可以将少重名的冲突。这个例子阐述了一系列协作的嵌套对象。
1TQ?Fxj s@{82}f~ <tt:outerTag>
4JK6<Pk /FN:yCf <tt:innerTag />
n'mrLZw I]eeV+U8W </tt:outerTag>
i[KXkjr G{: B'08 c)#7T<>*' Tag处理类
@FIL4sb :'bZ:J>f j:cu;6| Tag处理类必须实现Tag接口或BodyTag接口,不过现在一般都流行从TagSupport或BodyTagSupport类中继承,这些类或接口都可以在javax.servlet.jsp.tagext包中找到。
2B$dT=G 6ZIPe~` 当JSP引擎看到自己的JSP页面中包含有tag标签时,它会调用doStartTag方法来处理tag标签的开头,调用doEndTag方法来处理tag标签的结束。
I+
|uyc D
1.59mHsD 下表说明不同类型的tag所需要不同的处理过程:
ZOfv\(iJ; UUfM7gq Tag处理类的方法
y<6Sl6l* OT\D;Z"__I Tag标签类型
75;RAKGi 所调用的方法
XcoX8R%U oA5Qk3b: 基本标签
.<QKQ% - doStartTag, doEndTag, release
GImPPF |5(un# 带属性的标签
>e!J(4.- doStartTag, doEndTag, set/getAttribute1...N, release
O83J[YuzjN <y?+xZM]#| 带内容的标签
#"6l+} doStartTag, doEndTag, release
TFb7P/g 6%p6BK6 带内容的标签,且内容重复循环
QswPga(- doStartTag, doAfterBody, doEndTag, release
BywEoS (+v':KH3_ 带内容的标签,且内容与JSP交互
$DH/ doStartTag, doEndTag, release, doInitBody, doAfterBody, release
Ch?yk^cY CX/[L)|Ru 一个tag处理类可以通过javax.servlet.jsp.PageContext来与JSP交互,通过javax.servlet.jsp.PageContext类,tag处理类可以访问JSP中的request、session和application对像。
EB&hgz&_ 4'D^>z!c 如果tag标签是互相嵌套的,那内层的tag处理类可以通过它的parent属性来访问上层的tag处理类。
2n>mISy+ ;s,1/ kA 一般情况都将所有的tag处理类打成了JAR的包,以便于发布。
P\ P=1NM pm+E)z6Yo I*U7YqDC9 Tag库描述(简称TLD)
\68bXY. JUw|nUnl? 4?@5JpC9VA Tag库是用xml语言描述的,TLD包括了tag库中所有tag标签的描述,它一般用来被jsp服务器用来校验tag的语法正确性,或者被jsp开发者用来开发新的标签。
o]p$
w[5 A?HDY_u TLD的文件扩展名必须为.tld,而且必须放在当前WEB应用的WEB-INF目录或其子目录中。
"d/54PKWx e?(4lD)d 一个TLD的内容的开头必须遵守标准的XML开头,用于描述DTD和xml的版本,例如:
|b@`ykD Z5rL.a& <?xml version="1.0" encoding="ISO-8859-1" ?>
~Fvz&dO wIRU!lIF9 <!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "
http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd">
G:+D1J] TLD必须以<taglib>来作为它的根元素,<taglib>的子元素如下表:
_@\-`>J w`boQ_Ir zfUj%N <taglib>的子元素
) 5`^@zx |LIcq0Z Element
]p(es,[ Description
1 h(n}u G@rh/b<$ tlib-version
D {E,XOi Tag库的版本
uAYDX<Ja9 O:V.;q2]U jsp-version
:p<:0W2! Tag库所需要的jsp的版本
}}Q h_( l-IA Q!d short-name
[Ketg 助记符,tag的一个别名(可选)
#?M[Q: C]ho7qC uri
Q Wm
g#2 ' 用于确定一个唯一的tag库
J'#o6Ud (8S+-k? display-name
<vg|8-,#m 被可视化工具(诸如Jbuilder)用来显示的名称(可选)
~EDO< O>3 ak}ke small-icon
F9_X^#%L 被可视化工具(诸如Jbuilder)用来显示的小图标(可选)
'&AeOn H-&
ktQWK3 large-icon
S ="\ S 被可视化工具(诸如Jbuilder)用来显示的大图标(可选)
:d<F7`k
H !9zs>T&9a\ description
/#x0?d{5 对tag库的描述(可选)
r_^]5C\ QSYKYgxC listener
YTe8C9eO 参见下面listener元素
}z-)!8vF !q+
%]k?x tag
]x_14$rk 参见下面tag 元素
BYI13jMH+Y 8
=3#S'n Listener元素
dr=KoAIxy r)w]~)8 一个tag库可能定义一些类做为它的事件侦听类,这些类在TLD中被称为listener 元素,jsp服务器将会实例化这些侦听类,并且注册它们。Listener元素中有一个叫listener-class的子元素,这个元素的值必须是该侦听类的完整类名。
:=`N2D ]waCYrG<sY Tag元素
|msQ rYyEs
I#qo 每个tag元素在tag库中都要指出它的名字、类名、脚本变量、tag的属性。其中脚本变量的值可以直接在TLD中定义或通过tag附加信息的类来取得。每个属性描述了这个属性是否可以省略,它的值是否可以通过<%= …%>这样的JSP语法来获得,以及属性的类型。
P-N+ SP|Dz,o 每一个tag在TLD中对应一个tag元素,下表是tag元素的子元素:
40LAG wGpw+O Tag元素的子元素
O;;vz+ j f;W>:`' 元素名称
=Rf!i78c5 描述
4d]T` 75H5{#) name
}~Y#N 独一无二的元素名
'q*/P&x5 9fb"R"(M tag-class
HuL9' M Tag标签对应的tag处理类
~ @s$ ,OO0*% tei-class
6n.C!,Zmn javax.servlet.jsp.tagext.TagExtraInfo的子类,用于表达脚本变量(可选)
N5GQ2V T$xY]hqr body-content
y$pT5X G Tag标签body的类型
[hXU$Y>"0 D\GP+Ota display-name
L
sMS`o6 被可视化工具(诸如Jbuilder)用来显示的名称(可选)
@GR|co I'RhA\` small-icon
yu62$d 被可视化工具(诸如Jbuilder)用来显示的小图标(可选)
k*xgF[T
8 5eSmyj-W large-icon
yn5yQ; 被可视化工具(诸如Jbuilder)用来显示的大图标(可选)
xyTjK.N 1QH5<)Oa description
DJhCe==$v 此tag标签的描述
> jvi7 /7<l`RSr variable
+-OqO3R 提供脚本变量的信息(同tei-class)(可选)
U.QjB0; 9ozUg,+Z|J attribute
7[W!Nx Tag标签的属性名
JB= L\E} K%A:W 以下章节介绍对于不同类型的tag,如何具体地实现它们。
QR($KW( GoNX\^A BI-xo}KI 简单的tag
@'EU\Y\l Ey!+rq} lf\]^yM # tag处理类
Rc H",*U !bG%@{W T 简单的tag处理类必须实现Tag接口的doStartTag和doEndTag方法。当jsp引擎碰到tag标签的开头时,doStartTag被调用,因为简单的tag没有body,所以此方法将返回 SKIP_BODY。当jsp引擎碰到tag标签的结尾时,doEndTag被调用,如果余下的页面还要被计算,那它将返回EVAL_PAGE,否则将会返回SKIP_PAGE。
bytAdS$3 |,89zTk' 以下是例子:对于标签 <tt:simple /> ,它的tag处理类实现如下:
r4h4A w { ,9W|$2=F ^?H3:CS public SimpleTag extends TagSupport
d&QB?yLd 0XBv8fg {
195m0'zda fE;<)tU
public int doStartTag() throws JspException
{WJ+6!v ~P85Or {
pAo5c4y!4 hX~d1.]Y try{
6WQT,@? }Zue?!KQ pageContext.getOut().print(“Hello.”);
r9Wk7?w) Oozt&* F }catch(Exception e){
J?~El& *1fq :-- throw new JspTagException(“SimpleTag: “ + e.getMessage());
i[_WO2 c-L1 Bkw }
x4PA~R =Vv"\p8 return SKIP_BODY;
A&OU;j] 90oG+T4 }
>weY_%a _h2axXFhT public int doEndTag()
dMw0Aw,2]8 9@LL_r`?< {
ykv,>nSXLL >TT4;p h return EVAL_PAGE;
_H9.AI 3,2|8Q,((! }
K]{Y >w 60B6~@]P }
Nv@SpV' B zmmE2~* a7+w)]r 注意:如果tag标签没有内容的话,那必须定义body-content元素为空,例如
UMN3.-4K# 88]V6Rm9[* <body-content>empty</body-content>
C:+-T+m[ !e5!8z >YwvM=b"V 带属性的tag标签