标准的JSP 标记可以调用JavaBeans组件或者执行客户的请求,这大大降低了JSP开发的复杂度和维护量。JSP技术也允许你自定义taglib,其实换句话说,taglib可以看成是对JSP标记的一种扩展,正如xml是对html的一种扩展一样。taglib通常定义在tag标签库中,这种标签库存放着你自己定义的tag标签。简而言之,如果使用taglib,那么你可以设计自己的JSP标记!
}M1sksk5 0y<wvLv2C 一般来说,自定义tag标签主要用于操作隐藏对象、处理html提交表单、访问数据库或其它企业级的服务,诸如邮件和目录操作等等。自定义tag标签的使用者一般都是那些对java编程语言非常精通,而且对数据访问和企业级服务访问都非常熟悉的程序员,对于HTML设计者来说,使得他可以不去关注那些较复杂的商业逻辑,而将精力放在网页设计上。同时,它也将库开发者和库使用者进行合理分工,自定义tag标签将那些重复工作进行封装,从而大大提高了生产力,而且可以使得tag库可用于不同的项目中,完美地体现了软件复用的思想。
Z~A@o""F Z/^ u 在这篇文章中,我们主要讨论:
&a/__c/l USN8N ( · 什么是自定义tag标签?
"NRDNqj( tbnH,* · 怎么使用tag标签?
~gz^Cdh fN"(mW>! o 声明要使用的tag库
Bl9jkq
] tBTTCwNT% o 找到与之对应的tag处理类
{pb>$G:gfx /7!""{1\\ o tag标签的类型
:V2bS 6t/`:OZC: · 自定义tag标签
R<i38/ ~G 8Ld:"Y# o tag处理类
D>Gt]s yr#5k`&\_ o tag库描述
AmwWH7,g G/%iu;7ZCb o tag标签示例
.I}:m%zv %4\OPw& o 带属性的tag
9WJz~SP+vR fYE(n8W3 o 带body的tag
/6O??6g +GsWTEz o 定义了脚本变量的tag
jGrN\D?h B2Xn?i3 l o 具有协作关系的tag
@"T"7c?Cv $+}+zZX5 · 自定义tag标签
FgL,k [ofqGwpDG o 一个迭代tag的例子
nW"q 6<0n *& o 一个模板tag库
;n\= R 5. Y!6/[<r$~k o tag处理类到底是怎样被调用的?
$D31Q[p=+ N_L,]QT? mAk{"65V 什么是自定义的tag?
.qk]$LJF7 <o2r~E0r3 一个自定义的tag标签是用户定义的一种JSP标记。当一个含有自定义的tag标签的JSP页面被jsp引擎编译成servlet时,tag标签被转化成了对一个称为tag处理类的对象进行的操作。于是当JSP页面被jsp引擎转化为servlet后,实际上tag标签被转化成为了对tag处理类的操作。
A]L%dFK ??hJEE 自定义tag标签有很多特色,诸如:
jL)WPq!m+ KJE[+R H+z · 可以在JSP页面中自定义tag标签的属性
IlX$YOf4 %3HVFhl · 访问JSP页面中的所有对象
iTW? W\d '03->7V · 可以动态地修改页面输出
%p&k5:4<"# q9"=mO0J+ · 彼此这间可以相互通信。你可以先创建一个JavaBeans组件,然后在一个tag中调用此JavaBeans组件,同时可以在另一个tag中调用它。
,]}?.g 0J.dG/I% · tag允许相互嵌套,可以在一个JSP页面中完成一些复杂的交互。
zi~5l#I :b[`
v H A}f,),G 使用tag标签
,3I^?5 pf4 ^Bk}e oJKa"H-jL 本节主要描述怎样在JSP页面中使用tag标签,以及tag标签的不同类型。
Vtppuu$ >=iy2~Fz , 要使用tag标签,JSP程序员必须做2件事:
t6c<kIQ:-O v){ .Z^_C · 声明此tag标签的tag库
Nr2 C@FU:0 RFh"&0[ · 实现此tag标签
zo;^m| ?j^=u:< 声明tag标签所在的tag库
]a2W e` E1;@=#t2i 如果要使用tag标签,则应用JSP的taglib指示符来指定其tag库(注意:taglib要在在使用此tag标签之前声明)
q_
=b<.; e6=]m#O9 <%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %>
(wc03,K^ +l^LlqA uri属性定义了唯一的标签库描述(以下简称TLD),它可以是直接是tld文件名或一个独一无二的名字。prefix是用来区别其它TLD中和本TLD中有重名的tag的一种手段。
{b]aC */ G<!W TLD必须以.tld作为扩展名,并且存放在当前应用的WEB-INF目录或其子目录下。你可以通过它的文件名直接引用它,也可以通过别的方式间接地引用它。
|}){}or UN"(5a8. 以下taglib指示符直接引用一个TLD:
s<x1>Q7X~ |%~+2m <%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %>
QrApxiw (h']a! 以下的taglib指示符通过一个逻辑名称间接地引用一个TLD:
IPuA#C 6)pH|d.FR <%@ taglib uri=”/tutorial-template” prefix=”tt” %>
w@2Vts lCW8<g^ 如果是间接引用TLD的话,那你必须还要在web.xml中定义此逻辑名称与tld文件之间的映射,具体做法是在web.xml中加入一个名为taglib的元素:
~}Z\:#U ,(a5 @H$f <taglib>
(BX83) ~f|Z%&l| <taglib-uri>/tutorial-template</taglib-uri>
"i:T+#i({O %hlspI(J <taglib-location>
[nxE)D 0oy-os /WEB-INF/tutorial-template.tld
jClj_E ]0D}T'wM </taglib-location>
[6jbgW~E ch5s<x#CE </taglib>
@1zQce> K}[>T(0E cYNJhGY 实现此tag标签
,?
E&V_5 9>/wUQs!] HG/p$L* 为了实现tag标签,你有2种方法来存放tag处理类。一、让tag处理类以.class的方式存放于当前应用的WEB-INF/class子目录下,二、如果tag处理类是以JAR包的形式存在的话,那可以放在当前应用的WEB-INF/lib目录下,如果tag处理类要在多个应用中共享,那么它就应放在jsp服务器上的common/lib目录下,对于tomcat来说,就是tomcat/common/lib目录下。
=TR,~8Z| w",?
Bef
G
;?qWB, tag标签类型
Ou'?]{ l0*Gb }awzO# 自定义的tag标签遵循XML语法。它有一个开始标记和一个结束标记,有的还有body(即文本节点):
?_\$ 4^6.~6a <tt:tag>
7dihVvL
$ SFH-^ly&D body
DaNW~rd{ =1dI>M>tm </tt:tag>
^s\3/z>b4! ^EVc 95|Z {Hr$wa~ 一个不带body的tag标签如下:
I
PE}gp _eLWQ|6Fx <tt:tag />
ashcvn~z fJjgq)9 n$m"]inX 简单的tag标签
~Lfcg* Ct$82J 一个没有body和属性的tag标签如下:
-6Tk<W
/E wGW <tt:simple />
{>0V[c[~ 33:DH} 5p?!ni9 带属性的tag标签
`n!viW|tB '%v#v 3' Z.Rb~n& 自定义标签可以有自己的属性。属性一般在开始标记中定义,语法为 attr=”value”。属性的作用相当于自定义标签的一个参数,它影响着tag处理类的行为。你可以在TLD中详细定义它。
c*\<,n_ b7C
e%Br 你可以用一个String常量给一个属性赋值,也可以通过表达式给它赋值,如<%= ...%>。以struts为例,它的logic:present标签就是用的String常量来给属性赋值:
9?+9UlJ7K mzL[/B#>M <loglic:present parameter = “Clear”>
I
5ag6l _i}wK?n 而另一个标签logic:iterate是用表达式来给属性赋值:
L{g E'jCC {u7##Vrgt8 <logci:iterate collection=”<%= bookDB.getBooks() %>”
$ &5w\P 4dH}g~[P9 id=”book” type=”database.BookDetails”>
8OWmzY_= ETv9k g oFg5aey4 带body的tag标签
~7q uTp) HU
B|bKy 一个自定义标签可以包含其它自定义标签、脚本变量、HTML标记或其它内容。
(.K\Jg'Y6j \zXlN 在下述例子中,此JSP页面使用了struts的logic:present标签,如果些标签定义了parameter=”Clear”的属性,则将清除购物车的内容,然后打印出一条信息:
#nyv+x; ~#Md"3 <logic:present parameter=”Clear”>
'p)Q68;& =4C}{IL <% cart.clear(); %>
"YFls#4H- h?@G$%2 <font color=”#ff0000” size=”+2”><strong>
;mm!0]V &!7+Yb(1 你选择了清除购物车!
ic6L9>[ Y5A~E#zw </strong></font>
h~HB0^| ~QG?k </logic:present>
L^9HH)Jc >AD=31lq ~M?|Vn 到底是用属性还是用body来传递信息?
O^{1RV3:,T t7#lsd`_ 如上所述,我们既可以通过属性,也可以通过body来传递信息。但一般来说,比较简单的类型,如字符串或简单表达式最好采用属性来传递信息。
.I?@o8'x #/J
'P[z upn8n vy4( 定义脚本变量的tag标签
{sN"(H4$ lpQP"%q 所谓脚本变量,是指JSP中可以调用的变量或对象。它可由tag标签产生。以下示例阐述了一个tag标签定义了一个名为tx的由JNDI所定义的事务处理对象。脚本变量可以是ejb对象、事务、数据库连接等等:
TZ^LA
L'8_ a,'Cyv"> <tt:lookup id=”tx” type=”UserTransaction” name=”java:comp/UserTransaction” />
<2Y0{
8) )&NAs <% tx.begin(); %>
t\U$8l_; 2iXoj&3e ...
#Olg(:\ e]W0xC- ?z` MPdO 具有协作关系的tag标签
:jNYP{Br 4yV].2#rl" 自定义tag标签之间可以通过共享对象来实现协作。在下述例子中,标签tag1创建了一个名为obj1的对象,在标签tag2仍可以重复使用obj。
;cP8 ?U u,i]a#K <tt:tag1 attr1=”obj1” value1=”value” />
f|0lj I{.HO<$7D} <tt:tag2 attr1=”obj1” />
Uf,fX/:! J2Et-Cz 1 在以下这个例子当中,如果外层的tag标签创建了一个对象,那么其内层的所有tag标签都可以使用这个对象。由于这样产生的对象没有一个指定的名字,那么就可以将少重名的冲突。这个例子阐述了一系列协作的嵌套对象。
,j;PRJ kM*T$JqN <tt:outerTag>
=v2%Vs\7k +Takde%~ <tt:innerTag />
#0y<a:}R c c G['7 </tt:outerTag>
Jgx8-\8 w[fDk1H) :uCdq`SaQl Tag处理类
P@ypk^v tbj=~xYf .Oo/y0E^ Tag处理类必须实现Tag接口或BodyTag接口,不过现在一般都流行从TagSupport或BodyTagSupport类中继承,这些类或接口都可以在javax.servlet.jsp.tagext包中找到。
i*tv,f.( 5rN_jC*U 当JSP引擎看到自己的JSP页面中包含有tag标签时,它会调用doStartTag方法来处理tag标签的开头,调用doEndTag方法来处理tag标签的结束。
g,lY ut 0%Q9}l#7 下表说明不同类型的tag所需要不同的处理过程:
8Pmwzpk02 >S&U. Tag处理类的方法
4\Di,PPu ?9?4p@ Tag标签类型
b;vNq 所调用的方法
]S/G\z tjzA)/T,4 基本标签
}OKL
z.5 doStartTag, doEndTag, release
hTS|_5b ]mkJw 3 带属性的标签
r#h {$iW doStartTag, doEndTag, set/getAttribute1...N, release
-ut=8(6& =:K@zlO: 带内容的标签
ofCVbn doStartTag, doEndTag, release
Lo3-X g^lFML|
% 带内容的标签,且内容重复循环
.j 'wQ+_ doStartTag, doAfterBody, doEndTag, release
iz
x[ J%P)%yX 带内容的标签,且内容与JSP交互
|'w^ n doStartTag, doEndTag, release, doInitBody, doAfterBody, release
7>je6*(K G.jQX'%4QG 一个tag处理类可以通过javax.servlet.jsp.PageContext来与JSP交互,通过javax.servlet.jsp.PageContext类,tag处理类可以访问JSP中的request、session和application对像。
t[O+B6 {g=b]yg\o 如果tag标签是互相嵌套的,那内层的tag处理类可以通过它的parent属性来访问上层的tag处理类。
,?=KgG1i z-Hkz 一般情况都将所有的tag处理类打成了JAR的包,以便于发布。
(&Q)EBdm
U1\MA6pXW 9+VF<;Xw Tag库描述(简称TLD)
JLW$+62 Baq ~}B< [}k| Tag库是用xml语言描述的,TLD包括了tag库中所有tag标签的描述,它一般用来被jsp服务器用来校验tag的语法正确性,或者被jsp开发者用来开发新的标签。
&l^n4 x70N8TQ_gK TLD的文件扩展名必须为.tld,而且必须放在当前WEB应用的WEB-INF目录或其子目录中。
-uR{X G. D q6)N*? 一个TLD的内容的开头必须遵守标准的XML开头,用于描述DTD和xml的版本,例如:
NG-`ag`s ]7<m1Lg
<?xml version="1.0" encoding="ISO-8859-1" ?>
N{pa)
/ D0M!"c>\ <!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "
http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd">
GVp TLD必须以<taglib>来作为它的根元素,<taglib>的子元素如下表:
&q>h*w4O q!*MH/R `QLowna <taglib>的子元素
'5WN,Vy8. i+U51t< Element
z\$;' Description
|0w~P
s 59MR|Jt tlib-version
cju@W] ! Tag库的版本
\]a uSO PJwEA jsp-version
3;D?|E]1 Tag库所需要的jsp的版本
a(Sv,@/ d<Dn9,G short-name
N[ Q#R~Hn< 助记符,tag的一个别名(可选)
.HOY q sN@j5p^jc uri
MgP{W=h2 用于确定一个唯一的tag库
0~i q G e[p^p!a display-name
W9jNUZVXE# 被可视化工具(诸如Jbuilder)用来显示的名称(可选)
ORtg>az\% =F[lg?g small-icon
R`3x=q
被可视化工具(诸如Jbuilder)用来显示的小图标(可选)
!h/dZ`# %
&+|==- large-icon
qa;EI ;8 被可视化工具(诸如Jbuilder)用来显示的大图标(可选)
Xa*?<(^` 'Aet{A=9 description
A?sNXhh 对tag库的描述(可选)
hs,5LV)|y FLEg0/m0 listener
6NSO >/E 参见下面listener元素
o@@_J@}# r'PE5xqF tag
SNxz*`@4 参见下面tag 元素
<tU
:U<ea] C &FN#B Listener元素
ZU^Q1}</5 ]nHe$x!2] 一个tag库可能定义一些类做为它的事件侦听类,这些类在TLD中被称为listener 元素,jsp服务器将会实例化这些侦听类,并且注册它们。Listener元素中有一个叫listener-class的子元素,这个元素的值必须是该侦听类的完整类名。
e
mC\i /J8o_EV Tag元素
q4zSS #]A lk~dgky@ 每个tag元素在tag库中都要指出它的名字、类名、脚本变量、tag的属性。其中脚本变量的值可以直接在TLD中定义或通过tag附加信息的类来取得。每个属性描述了这个属性是否可以省略,它的值是否可以通过<%= …%>这样的JSP语法来获得,以及属性的类型。
q"l>`KCG` HMQ'b(a' 每一个tag在TLD中对应一个tag元素,下表是tag元素的子元素:
~Cu lFxu (A|B@a!Y> Tag元素的子元素
jUZ[`f; |y'b217t 元素名称
>]C<j4 描述
FcY$k%;'Q ;]"n?uo name
;\q<zO@x 独一无二的元素名
w0\4Wa L&rO6 tag-class
iF+S%aPd# Tag标签对应的tag处理类
M Yu?&}%^ dvxf lLd @ tei-class
%!D_q~"H javax.servlet.jsp.tagext.TagExtraInfo的子类,用于表达脚本变量(可选)
>Ziy1Dp 6J]~A0vsi} body-content
89ZDOji?O Tag标签body的类型
i"KL;t[1 e ^-3etx display-name
ul}4p{ m[ 被可视化工具(诸如Jbuilder)用来显示的名称(可选)
^Y#@$c tvK rc small-icon
,%.:g65% 被可视化工具(诸如Jbuilder)用来显示的小图标(可选)
d7\k gh ]+FX$+H/A0 large-icon
#fJwC7 4 被可视化工具(诸如Jbuilder)用来显示的大图标(可选)
KgL<}=S +i2YX7Of description
rR3m'[ 此tag标签的描述
o<~-k,{5P m*OLoZVy variable
rn[$x(G 提供脚本变量的信息(同tei-class)(可选)
*C
tsFS~ |:\$n}K attribute
tc!!W9{69 Tag标签的属性名
54;l*}8Hl '[ @F% 以下章节介绍对于不同类型的tag,如何具体地实现它们。
,K`E&hS <tGI]@Nwk ,,zd.9n 简单的tag
z^YeMe J,.j_ii`! WFQ*s4 R( tag处理类
;,()wH xNocGtS 简单的tag处理类必须实现Tag接口的doStartTag和doEndTag方法。当jsp引擎碰到tag标签的开头时,doStartTag被调用,因为简单的tag没有body,所以此方法将返回 SKIP_BODY。当jsp引擎碰到tag标签的结尾时,doEndTag被调用,如果余下的页面还要被计算,那它将返回EVAL_PAGE,否则将会返回SKIP_PAGE。
5+J64_ t*5z1T? 以下是例子:对于标签 <tt:simple /> ,它的tag处理类实现如下:
#IH<HL)t%e (X0`1s Ax :3} public SimpleTag extends TagSupport
4o)(d=q <=#lRZW[z {
X!7cz t Qd9-u)L< public int doStartTag() throws JspException
6@*5!, M9g~lKs' {
"
&_$V@S t$ACQ*O
try{
aslU`#" 5@GD} oAn6 pageContext.getOut().print(“Hello.”);
!5yRWMO9X~
yBJ/>SAcG }catch(Exception e){
+e&m#d pjaiAe!k throw new JspTagException(“SimpleTag: “ + e.getMessage());
Tz+HIUIxF uEc0/a :. }
^aGZJiyJ 3P%w-qT!N return SKIP_BODY;
)Ix-5084 tn(?nQN3 }
D|u^8\'. UIC\CP d public int doEndTag()
+,ZUTG H5 p}Le {
y|&.v< z }FiU[Hs return EVAL_PAGE;
<XkkYI( Z%, \+tRe }
6\NX
5Gh 9~LpO>- }
*u:;:W&5y [
t>}SE oi33{#%t 注意:如果tag标签没有内容的话,那必须定义body-content元素为空,例如
^&f{beU9 *qeic e%E <body-content>empty</body-content>
Zj%B7s1A l044c,AW( BLl%D 带属性的tag标签