标准的JSP 标记可以调用JavaBeans组件或者执行客户的请求,这大大降低了JSP开发的复杂度和维护量。JSP技术也允许你自定义taglib,其实换句话说,taglib可以看成是对JSP标记的一种扩展,正如xml是对html的一种扩展一样。taglib通常定义在tag标签库中,这种标签库存放着你自己定义的tag标签。简而言之,如果使用taglib,那么你可以设计自己的JSP标记!
iZmcI;?u mpyt5#f 一般来说,自定义tag标签主要用于操作隐藏对象、处理html提交表单、访问数据库或其它企业级的服务,诸如邮件和目录操作等等。自定义tag标签的使用者一般都是那些对java编程语言非常精通,而且对数据访问和企业级服务访问都非常熟悉的程序员,对于HTML设计者来说,使得他可以不去关注那些较复杂的商业逻辑,而将精力放在网页设计上。同时,它也将库开发者和库使用者进行合理分工,自定义tag标签将那些重复工作进行封装,从而大大提高了生产力,而且可以使得tag库可用于不同的项目中,完美地体现了软件复用的思想。
h[ ZN+M i8p6Xht 在这篇文章中,我们主要讨论:
jXJyc'm7 6BlXLQ,8q · 什么是自定义tag标签?
JF]JOI6.e sOY:e/_F · 怎么使用tag标签?
+@UV?"d pH;%ELZ o 声明要使用的tag库
hH.G#-JO ~*7]r`6\@ o 找到与之对应的tag处理类
GgU/!@ g(g& TO o tag标签的类型
crCJrN= \8tsDG(1 ' · 自定义tag标签
H,J8M{ l;U?Z'n o tag处理类
tPvpJX6kP "@kaHIf[ o tag库描述
f$( e\++ 6!o1XQr=Z o tag标签示例
hTkyz
la jPeYmv] o 带属性的tag
<@}9Bid!o al0L&z\ o 带body的tag
XW9!p.*.U ,4rPg]r@ o 定义了脚本变量的tag
}Jw,>} ]n~V!hl?A o 具有协作关系的tag
a*;b^Ze`v ?2a $*( · 自定义tag标签
/reX{Y u2I Cl o 一个迭代tag的例子
BUFv|z+H =a!=2VN9y o 一个模板tag库
& kIFcd@ :&Nbw o tag处理类到底是怎样被调用的?
9uY'E'm* 9Flb|G% H]s.=.Ki 什么是自定义的tag?
6@o*xK7L POW>~Tof1 一个自定义的tag标签是用户定义的一种JSP标记。当一个含有自定义的tag标签的JSP页面被jsp引擎编译成servlet时,tag标签被转化成了对一个称为tag处理类的对象进行的操作。于是当JSP页面被jsp引擎转化为servlet后,实际上tag标签被转化成为了对tag处理类的操作。
:N@^?q{b dx]>(e@(t{ 自定义tag标签有很多特色,诸如:
!k%#R4*> d-m7}2c · 可以在JSP页面中自定义tag标签的属性
Cw%{G'O Ru XC(qcq · 访问JSP页面中的所有对象
0V]s:S ;4a{$Lw~^9 · 可以动态地修改页面输出
!wNO8;( l2d{ 73h · 彼此这间可以相互通信。你可以先创建一个JavaBeans组件,然后在一个tag中调用此JavaBeans组件,同时可以在另一个tag中调用它。
ToQ"Iy? u-TUuP · tag允许相互嵌套,可以在一个JSP页面中完成一些复杂的交互。
wzaV;ac4K ,Q,^3*HX9} Q?T]MUY(L 使用tag标签
hph4 `{T &zhAh1m 8fb'yjIC 本节主要描述怎样在JSP页面中使用tag标签,以及tag标签的不同类型。
>7r!~+B"9' ,[Fb[#Qqb 要使用tag标签,JSP程序员必须做2件事:
l,:F Q&&@v4L · 声明此tag标签的tag库
t5zKW _J7 %SI'BJ · 实现此tag标签
4YHY7J z2c6T.1M 声明tag标签所在的tag库
DJir { \F zL it 如果要使用tag标签,则应用JSP的taglib指示符来指定其tag库(注意:taglib要在在使用此tag标签之前声明)
&zs$x?/ 9l,oP? <%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %>
y]imZ4{/ _U0f=m uri属性定义了唯一的标签库描述(以下简称TLD),它可以是直接是tld文件名或一个独一无二的名字。prefix是用来区别其它TLD中和本TLD中有重名的tag的一种手段。
t
Pf40`@ k8Xm n6X TLD必须以.tld作为扩展名,并且存放在当前应用的WEB-INF目录或其子目录下。你可以通过它的文件名直接引用它,也可以通过别的方式间接地引用它。
sGb{9.WK _|]x2xb) 以下taglib指示符直接引用一个TLD:
9cgUT@a ca}2TT&t <%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %>
/> Nt[o[r fV:83|eQ 以下的taglib指示符通过一个逻辑名称间接地引用一个TLD:
b\ PgVBf9 zVD:#d%b <%@ taglib uri=”/tutorial-template” prefix=”tt” %>
nie% eC&U ]d`VT)~vje 如果是间接引用TLD的话,那你必须还要在web.xml中定义此逻辑名称与tld文件之间的映射,具体做法是在web.xml中加入一个名为taglib的元素:
bfO=;S]b! |' . <taglib>
BD-AI vj*%Q(E6Pt <taglib-uri>/tutorial-template</taglib-uri>
.KC++\{HE o.\oA6P_ <taglib-location>
4sM.C9W iOdpM{~* /WEB-INF/tutorial-template.tld
kR9-8I{J 7Qsgys#/= </taglib-location>
xCKRxF f X)#=c|5 </taglib>
6r_)sHf *j-aXN/ $ &/b~k3{M_ 实现此tag标签
(ik\|y% A }`"6aM Kg$Mx 为了实现tag标签,你有2种方法来存放tag处理类。一、让tag处理类以.class的方式存放于当前应用的WEB-INF/class子目录下,二、如果tag处理类是以JAR包的形式存在的话,那可以放在当前应用的WEB-INF/lib目录下,如果tag处理类要在多个应用中共享,那么它就应放在jsp服务器上的common/lib目录下,对于tomcat来说,就是tomcat/common/lib目录下。
o14cwb G\?YK.Y> p:%loDk tag标签类型
8Eq7Sa 9/;P->wy X7wKy(g 自定义的tag标签遵循XML语法。它有一个开始标记和一个结束标记,有的还有body(即文本节点):
:Yks|VJ1 g1o8._f. <tt:tag>
bF(f*u M[uA@ body
:aQt;C6Z> V>
bCKtf& </tt:tag>
7)k\{&+P )ANmIwmC# BUR*n;V` 一个不带body的tag标签如下:
X76e&~ iIogx8[ <tt:tag />
k'"%.7$U! %#}Z y
9mFE?J 简单的tag标签
B]$GSEB &M'*6A 一个没有body和属性的tag标签如下:
`g})|Gx m_l[MG\ <tt:simple />
4H-'Dr=G `#gie$B{ 'eX ' 带属性的tag标签
-GgA&dh (M
~e?s f`/x"@~H5 自定义标签可以有自己的属性。属性一般在开始标记中定义,语法为 attr=”value”。属性的作用相当于自定义标签的一个参数,它影响着tag处理类的行为。你可以在TLD中详细定义它。
uH-)y,2& BCcjK6' 你可以用一个String常量给一个属性赋值,也可以通过表达式给它赋值,如<%= ...%>。以struts为例,它的logic:present标签就是用的String常量来给属性赋值:
h=%_Ao<x VQ{fne< <loglic:present parameter = “Clear”>
+'@Dz9:> l$'wD hN* 而另一个标签logic:iterate是用表达式来给属性赋值:
EyLu O-5 FEVlZ<PW3I <logci:iterate collection=”<%= bookDB.getBooks() %>”
Wr5V`sM {>%&(
id=”book” type=”database.BookDetails”>
~WN:DXn Ydy9 W,-g=6, 带body的tag标签
$a%MOKr uOGw9O-d9 一个自定义标签可以包含其它自定义标签、脚本变量、HTML标记或其它内容。
8Bg;Kh6B *~H Sy8s 在下述例子中,此JSP页面使用了struts的logic:present标签,如果些标签定义了parameter=”Clear”的属性,则将清除购物车的内容,然后打印出一条信息:
5P$4 =z91 pXK^Y'2C! <logic:present parameter=”Clear”>
&yol_%C vI)LB)Q <% cart.clear(); %>
27<
Enq] Q1l '7N <font color=”#ff0000” size=”+2”><strong>
c{LO6dNg\z |B2+{@R 你选择了清除购物车!
Z*2Vpnqh\ TvQo? </strong></font>
qcGK2Qx ff1c/c/ </logic:present>
',4iFuY K!]/(V(} *r% c 到底是用属性还是用body来传递信息?
6B
?twh) ivz5H(b 如上所述,我们既可以通过属性,也可以通过body来传递信息。但一般来说,比较简单的类型,如字符串或简单表达式最好采用属性来传递信息。
-[DOe?T "v4B5:bmqW 5Zva: 定义脚本变量的tag标签
.eP.& g|Fn7]G 所谓脚本变量,是指JSP中可以调用的变量或对象。它可由tag标签产生。以下示例阐述了一个tag标签定义了一个名为tx的由JNDI所定义的事务处理对象。脚本变量可以是ejb对象、事务、数据库连接等等:
Dl8;$~ E`k@{*Hn& <tt:lookup id=”tx” type=”UserTransaction” name=”java:comp/UserTransaction” />
qWKAM@ ]P2"[y <% tx.begin(); %>
$"&{aa BFJnV.0M! ...
[R7Y}k:9U s&!a '-/xyAzS 具有协作关系的tag标签
-8rjgB~."/ xpx\=iAe 自定义tag标签之间可以通过共享对象来实现协作。在下述例子中,标签tag1创建了一个名为obj1的对象,在标签tag2仍可以重复使用obj。
A6iq[b] Nl(3Xqov <tt:tag1 attr1=”obj1” value1=”value” />
fe#\TNeQJ[ D+7Rz_= <tt:tag2 attr1=”obj1” />
q=qcm`ce Mzw X>3x 在以下这个例子当中,如果外层的tag标签创建了一个对象,那么其内层的所有tag标签都可以使用这个对象。由于这样产生的对象没有一个指定的名字,那么就可以将少重名的冲突。这个例子阐述了一系列协作的嵌套对象。
H ?y,ie#u ?#YE`] <tt:outerTag>
CoAvSw Km6YP!i <tt:innerTag />
.Twk {p R#8L\1l </tt:outerTag>
oD1/{dRzj Vr1<^Ib e2W".+B1 Tag处理类
^4Ah_U 9Ly]DZ;L qH 6>!=00 Tag处理类必须实现Tag接口或BodyTag接口,不过现在一般都流行从TagSupport或BodyTagSupport类中继承,这些类或接口都可以在javax.servlet.jsp.tagext包中找到。
L4|`;WP Z@@K[$ 当JSP引擎看到自己的JSP页面中包含有tag标签时,它会调用doStartTag方法来处理tag标签的开头,调用doEndTag方法来处理tag标签的结束。
usL*
x9i f[^Aw(o 下表说明不同类型的tag所需要不同的处理过程:
84 pFc;< =+MPFhvg! Tag处理类的方法
.JiziFJ@mj M6-&R=78K Tag标签类型
x`IEU*z# 所调用的方法
([LSsZ]sj 4u47D$= 基本标签
["e3Ez doStartTag, doEndTag, release
U\<?z Dw 7y@Pa&^8 带属性的标签
B=A [ymm doStartTag, doEndTag, set/getAttribute1...N, release
JyOo1E. c+nq] xOs' 带内容的标签
kO*$"w#X[p doStartTag, doEndTag, release
TLe~y1dwY= T+k{W6 带内容的标签,且内容重复循环
M8b;d}XL doStartTag, doAfterBody, doEndTag, release
dIBE!4 V[ >:!X.TG$ 带内容的标签,且内容与JSP交互
y(pks$ doStartTag, doEndTag, release, doInitBody, doAfterBody, release
&wE%<"aRAl o\pVp bB 一个tag处理类可以通过javax.servlet.jsp.PageContext来与JSP交互,通过javax.servlet.jsp.PageContext类,tag处理类可以访问JSP中的request、session和application对像。
2nIw7>.}f Jh[UtYb5 如果tag标签是互相嵌套的,那内层的tag处理类可以通过它的parent属性来访问上层的tag处理类。
GMl;7?RA - kwXvYu\ 一般情况都将所有的tag处理类打成了JAR的包,以便于发布。
_ T):G6C8 -rli(RR)| SHo$9+ Tag库描述(简称TLD)
/&+tf* !pdb'*,n Jrpx}2'9:a Tag库是用xml语言描述的,TLD包括了tag库中所有tag标签的描述,它一般用来被jsp服务器用来校验tag的语法正确性,或者被jsp开发者用来开发新的标签。
25[I=ZdS MsGM5(r:b TLD的文件扩展名必须为.tld,而且必须放在当前WEB应用的WEB-INF目录或其子目录中。
C"T;Qp~B Nyj( 0W 一个TLD的内容的开头必须遵守标准的XML开头,用于描述DTD和xml的版本,例如:
,1CIBFY !XCm>]R <?xml version="1.0" encoding="ISO-8859-1" ?>
xZwLlY hUMf"=q+ <!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "
http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd">
%pd ,%pg TLD必须以<taglib>来作为它的根元素,<taglib>的子元素如下表:
Z>W g*sZy) 4 bH^":i( pF Rg?- <taglib>的子元素
y)!5R 3b $LFYoovX Element
ssxzC4m Description
y6,/:qm 9!}8UALD tlib-version
$!yW_HTx Tag库的版本
1@1U/ss1 =i*;VFc jsp-version
0dhaAq`k Tag库所需要的jsp的版本
usCt#eZK aV|hCN~ short-name
LS*y 助记符,tag的一个别名(可选)
(l-ab2' UsQ+`\| uri
;J2z p*| 用于确定一个唯一的tag库
5}]"OXQ 9"A`sGZ display-name
=~H<Z LE+ 被可视化工具(诸如Jbuilder)用来显示的名称(可选)
kep/+J-u OAkZKG| small-icon
~h85BF5 被可视化工具(诸如Jbuilder)用来显示的小图标(可选)
lP@Ki5 78# v large-icon
R$TB1w9] 被可视化工具(诸如Jbuilder)用来显示的大图标(可选)
QpA/SmJ 71gT.E description
E!l!OtFL 对tag库的描述(可选)
$5<#n@
$#S&QHyEe listener
b+6\JE^Mz 参见下面listener元素
A
'5,LfTu DYxCQ
D tag
[@b&? b~K 参见下面tag 元素
v+`N*\J_ pDIVZC Listener元素
u TK,& k+C zj 一个tag库可能定义一些类做为它的事件侦听类,这些类在TLD中被称为listener 元素,jsp服务器将会实例化这些侦听类,并且注册它们。Listener元素中有一个叫listener-class的子元素,这个元素的值必须是该侦听类的完整类名。
8b-Q F
2Mmz %S'd Tag元素
YSh+pr 5$&%re!{Z 每个tag元素在tag库中都要指出它的名字、类名、脚本变量、tag的属性。其中脚本变量的值可以直接在TLD中定义或通过tag附加信息的类来取得。每个属性描述了这个属性是否可以省略,它的值是否可以通过<%= …%>这样的JSP语法来获得,以及属性的类型。
G]i/nB
s<_)$} 每一个tag在TLD中对应一个tag元素,下表是tag元素的子元素:
}O^zl# F,MO@&ue" Tag元素的子元素
^T$|J;I ahOM CZF| 元素名称
,Pjew% 描述
*q".-u!D[ <|+Ex name
$yYO_ZBiy 独一无二的元素名
db6b-Y{ lfz2~Si5A tag-class
K4;'/cS Tag标签对应的tag处理类
I}6\Sv= t&CJ%XP tei-class
gy0haW javax.servlet.jsp.tagext.TagExtraInfo的子类,用于表达脚本变量(可选)
Vz)`nmO}5\ YWe"zz body-content
GlT7b/JCG Tag标签body的类型
Uo>]sNP~ 2hkRd>)&5 display-name
4V==7p
x( 被可视化工具(诸如Jbuilder)用来显示的名称(可选)
6qaQ[XTxf x`mN U small-icon
{{MRELipW 被可视化工具(诸如Jbuilder)用来显示的小图标(可选)
DRgTe&+ ul2")HL]; large-icon
CS-uNG6 被可视化工具(诸如Jbuilder)用来显示的大图标(可选)
ayD}r#7 }mdAM6 description
,Bo>E: u 此tag标签的描述
H77" .CU5}Tv- variable
mkF" 提供脚本变量的信息(同tei-class)(可选)
?5cI' M8Z2Pg\0 attribute
"WK{ >T Tag标签的属性名
o=?C&f{ 5HO9+i 以下章节介绍对于不同类型的tag,如何具体地实现它们。
h!ZV8yMc >W`4aA yA(K=?sq 简单的tag
kO{s^_qR^c /)(#{i* ;Tc`}2 tag处理类
xs:n\N ;R?I4}O#R8 简单的tag处理类必须实现Tag接口的doStartTag和doEndTag方法。当jsp引擎碰到tag标签的开头时,doStartTag被调用,因为简单的tag没有body,所以此方法将返回 SKIP_BODY。当jsp引擎碰到tag标签的结尾时,doEndTag被调用,如果余下的页面还要被计算,那它将返回EVAL_PAGE,否则将会返回SKIP_PAGE。
%V{7DA&C uYil ?H{kH 以下是例子:对于标签 <tt:simple /> ,它的tag处理类实现如下:
nwaxz>; ]=";IN:SU GBFtr public SimpleTag extends TagSupport
[7S} g dW~*e2nq {
i35=Y~P- H&
Ca`B public int doStartTag() throws JspException
:!b'Vk 5<j%EQN|D {
LLXVNO@e+ P2'DD 3 try{
!0C^TCuG e0@Y#7N62 pageContext.getOut().print(“Hello.”);
Ej>g.vp8I ,NVsn }catch(Exception e){
e `,ds~ F^LZeF[#t throw new JspTagException(“SimpleTag: “ + e.getMessage());
FMkzrs c#]q^L\x }
P7MeX(Tay
$g+[yb7@ return SKIP_BODY;
q)vplV1A '@CR\5 @ }
^:* 1d
\ | j a- public int doEndTag()
jSuL5|Gui {aC!~qR {
`zt_7MD adi[-L# return EVAL_PAGE;
FEW_bP/4 A7`1-# }
NDAw{[.% $aPfGZ<i }
UNi`P9D]3 JA_BKA zC:wNz@zK 注意:如果tag标签没有内容的话,那必须定义body-content元素为空,例如
Io|Aj j$Je6zq0x <body-content>empty</body-content>
n?urE-_ JiU9CeD3 IMl!,(6; 带属性的tag标签