标准的JSP 标记可以调用JavaBeans组件或者执行客户的请求,这大大降低了JSP开发的复杂度和维护量。JSP技术也允许你自定义taglib,其实换句话说,taglib可以看成是对JSP标记的一种扩展,正如xml是对html的一种扩展一样。taglib通常定义在tag标签库中,这种标签库存放着你自己定义的tag标签。简而言之,如果使用taglib,那么你可以设计自己的JSP标记!
b'J'F;zh> M%1}/!J3 一般来说,自定义tag标签主要用于操作隐藏对象、处理html提交表单、访问数据库或其它企业级的服务,诸如邮件和目录操作等等。自定义tag标签的使用者一般都是那些对java编程语言非常精通,而且对数据访问和企业级服务访问都非常熟悉的程序员,对于HTML设计者来说,使得他可以不去关注那些较复杂的商业逻辑,而将精力放在网页设计上。同时,它也将库开发者和库使用者进行合理分工,自定义tag标签将那些重复工作进行封装,从而大大提高了生产力,而且可以使得tag库可用于不同的项目中,完美地体现了软件复用的思想。
dYSr4pb A/s>PhxV 在这篇文章中,我们主要讨论:
M7+nW ; e% Ul2R'"FB · 什么是自定义tag标签?
+|bmT AgV G`q · 怎么使用tag标签?
>y.%xK R&|mdY8 o 声明要使用的tag库
t<~ $ D|rFu o 找到与之对应的tag处理类
dY@WI[yog uwa~-xX6 o tag标签的类型
vJ\pR~? N` aF{3[ · 自定义tag标签
a;QMAd! T^T[$26 o tag处理类
Y|8:;u' (4'$y`Z o tag库描述
P`#Z9 HM4 M&NB/ o tag标签示例
<@}I0 f8M$45A' o 带属性的tag
'|S%aMLZ) w=j o 带body的tag
Mu{;vf|j Nc+,&R13m o 定义了脚本变量的tag
PUo/J~ v Q -MQ9' o 具有协作关系的tag
X>NhZ5\
1WY/6[ · 自定义tag标签
sXi=70o }-~X4u# o 一个迭代tag的例子
y]J89
WcHgBbNe o 一个模板tag库
0{dz5gUde #ggf' QIHp o tag处理类到底是怎样被调用的?
N@O8\oQG p"l3e9&'j 3l3+A+n 什么是自定义的tag?
YyTSyP4 9uRFnzJVx 一个自定义的tag标签是用户定义的一种JSP标记。当一个含有自定义的tag标签的JSP页面被jsp引擎编译成servlet时,tag标签被转化成了对一个称为tag处理类的对象进行的操作。于是当JSP页面被jsp引擎转化为servlet后,实际上tag标签被转化成为了对tag处理类的操作。
BT)X8>ct D[_| *9BC 自定义tag标签有很多特色,诸如:
wD68tG$ A|L 8P · 可以在JSP页面中自定义tag标签的属性
slg ]#Dy z "+Mrew · 访问JSP页面中的所有对象
Q3|T':l4 GP&vLt51 · 可以动态地修改页面输出
t5'V6nv Nluv/?< · 彼此这间可以相互通信。你可以先创建一个JavaBeans组件,然后在一个tag中调用此JavaBeans组件,同时可以在另一个tag中调用它。
Pcu#lWC$ {e+-vl · tag允许相互嵌套,可以在一个JSP页面中完成一些复杂的交互。
v2H#=E4cZ# TF 'U uiJS8(Cb 使用tag标签
g.'yZvaP OCZ[D{i9@ x9x E& 本节主要描述怎样在JSP页面中使用tag标签,以及tag标签的不同类型。
ZO4*sIw%
5aln>1x>hn 要使用tag标签,JSP程序员必须做2件事:
%^1cyk ,WvY$_#xW% · 声明此tag标签的tag库
K_2|_MLlZ EL8NZ%:v: · 实现此tag标签
E<C&Cjz:H U Z|HJ8_ 声明tag标签所在的tag库
_U{zMVr W
D
T]! 如果要使用tag标签,则应用JSP的taglib指示符来指定其tag库(注意:taglib要在在使用此tag标签之前声明)
>.'<J] hSFn8mpXT <%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %>
ax{ ;:fW Qb)C[5a} uri属性定义了唯一的标签库描述(以下简称TLD),它可以是直接是tld文件名或一个独一无二的名字。prefix是用来区别其它TLD中和本TLD中有重名的tag的一种手段。
?0YCpn x.3J[=z=> TLD必须以.tld作为扩展名,并且存放在当前应用的WEB-INF目录或其子目录下。你可以通过它的文件名直接引用它,也可以通过别的方式间接地引用它。
lu#LCG-. wE@'ap# 以下taglib指示符直接引用一个TLD:
)(tM/r4`c& uu}x@T@ <%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %>
'=1KVE^Fk [@Q_(LQ-U 以下的taglib指示符通过一个逻辑名称间接地引用一个TLD:
-
/(s#D /v/C<] <%@ taglib uri=”/tutorial-template” prefix=”tt” %>
-T&.kYqnb$ e.@uhB. 如果是间接引用TLD的话,那你必须还要在web.xml中定义此逻辑名称与tld文件之间的映射,具体做法是在web.xml中加入一个名为taglib的元素:
=e gW 8}fu,$$5 <taglib>
{X[ HCfJd #
eCjn <taglib-uri>/tutorial-template</taglib-uri>
g8w2Vz2/ ?V}j`r8|\4 <taglib-location>
_UT$,0u_i -s|}Rh?Y /WEB-INF/tutorial-template.tld
&Ch#-CUE/ jL^](J> </taglib-location>
FL8g5I '0\@Mc U] </taglib>
t=u
Qb= 4'6`Ll|iq b8%C*r7 实现此tag标签
WBN w~|DO] ^-rfvc sf]s",t~J 为了实现tag标签,你有2种方法来存放tag处理类。一、让tag处理类以.class的方式存放于当前应用的WEB-INF/class子目录下,二、如果tag处理类是以JAR包的形式存在的话,那可以放在当前应用的WEB-INF/lib目录下,如果tag处理类要在多个应用中共享,那么它就应放在jsp服务器上的common/lib目录下,对于tomcat来说,就是tomcat/common/lib目录下。
\EKU*5\Hp> 549jWG ?Q-h n:F) tag标签类型
Kh4$ wwn +<}0|Xl& m!W3Cwz\& 自定义的tag标签遵循XML语法。它有一个开始标记和一个结束标记,有的还有body(即文本节点):
hUD7_arKF
zfc3)7 <tt:tag>
?UK|>9y}Z 7C$
5 body
k51Eyy50( fx@j?*Qb </tt:tag>
+8v9flh @&]#uRl|[ m85WA
#
` 一个不带body的tag标签如下:
?x+Z)`w_ =)E,8L <tt:tag />
f8SL3+v xGU(n_Y l3Lyea: 简单的tag标签
S a4W` kN%MP6? J 一个没有body和属性的tag标签如下:
}g3+{\x8 2_ :n <tt:simple />
P\]B< r}0\}~'?c ?H_LX;r 带属性的tag标签
>yXN,5d[ 2P]L9'N{Y <H0R&l\ 自定义标签可以有自己的属性。属性一般在开始标记中定义,语法为 attr=”value”。属性的作用相当于自定义标签的一个参数,它影响着tag处理类的行为。你可以在TLD中详细定义它。
OiAJ[L =1P6Vk 你可以用一个String常量给一个属性赋值,也可以通过表达式给它赋值,如<%= ...%>。以struts为例,它的logic:present标签就是用的String常量来给属性赋值:
?KITC;\\ R(-<BtM!- <loglic:present parameter = “Clear”>
}BiiE%a Ja SI^go 而另一个标签logic:iterate是用表达式来给属性赋值:
dJv!Dts')C 'S2bp4G <logci:iterate collection=”<%= bookDB.getBooks() %>”
FSRm| $''9K id=”book” type=”database.BookDetails”>
{CR 5K9 16L]=&@ sP-^~ pp 带body的tag标签
@]qBF]6 XxDaz1 一个自定义标签可以包含其它自定义标签、脚本变量、HTML标记或其它内容。
_:+
KMR O:{U^K:* 在下述例子中,此JSP页面使用了struts的logic:present标签,如果些标签定义了parameter=”Clear”的属性,则将清除购物车的内容,然后打印出一条信息:
pGSai& Yk42(!
<logic:present parameter=”Clear”>
mKT>,M p-%|P]& <% cart.clear(); %>
A<\JQ A/7X9ir <font color=”#ff0000” size=”+2”><strong>
H33i*][H Ne$"g[uFU 你选择了清除购物车!
yQ3OL# >|6iR%"f# </strong></font>
ork=`}; % aUsOB-RV </logic:present>
k<RZKw Qc H'MJ{r0, lCF`*DM# 到底是用属性还是用body来传递信息?
`xiCm': Cda!Mk: 如上所述,我们既可以通过属性,也可以通过body来传递信息。但一般来说,比较简单的类型,如字符串或简单表达式最好采用属性来传递信息。
);*YQmdx' `MEYd U1 EZ.!rh~+ 定义脚本变量的tag标签
&20P,8@ :L_BG)dM 所谓脚本变量,是指JSP中可以调用的变量或对象。它可由tag标签产生。以下示例阐述了一个tag标签定义了一个名为tx的由JNDI所定义的事务处理对象。脚本变量可以是ejb对象、事务、数据库连接等等:
px SX#S6I _/S?# <tt:lookup id=”tx” type=”UserTransaction” name=”java:comp/UserTransaction” />
XE3'`D! ,Rx{yf]k <% tx.begin(); %>
dq IlD!
eZr&x~]
-w ...
=<@\,xN>C
_SACqamo5s JlKM+UE: 具有协作关系的tag标签
AF43$6KZP$ ubu?S%` 自定义tag标签之间可以通过共享对象来实现协作。在下述例子中,标签tag1创建了一个名为obj1的对象,在标签tag2仍可以重复使用obj。
/%4_-C pm 5j0{p$'9 <tt:tag1 attr1=”obj1” value1=”value” />
N~g:Wf! BZb]SoAL <tt:tag2 attr1=”obj1” />
{k5X*W f'q 28lVf 在以下这个例子当中,如果外层的tag标签创建了一个对象,那么其内层的所有tag标签都可以使用这个对象。由于这样产生的对象没有一个指定的名字,那么就可以将少重名的冲突。这个例子阐述了一系列协作的嵌套对象。
[+w3J#K CSV;+,Vv <tt:outerTag>
+,50qN:%[ mp~{W <tt:innerTag />
`.#@@5e Qp2I[Ioz3 </tt:outerTag>
9_fePS|Z4 ]NhS=3*i+ aS|wpm)K>8 Tag处理类
^). ) D;Gq)]O OzT#1T1'c Tag处理类必须实现Tag接口或BodyTag接口,不过现在一般都流行从TagSupport或BodyTagSupport类中继承,这些类或接口都可以在javax.servlet.jsp.tagext包中找到。
CzV(cSS9- {FN;'Uc 当JSP引擎看到自己的JSP页面中包含有tag标签时,它会调用doStartTag方法来处理tag标签的开头,调用doEndTag方法来处理tag标签的结束。
Jti(b*~ :Vg}V"QR 下表说明不同类型的tag所需要不同的处理过程:
d bS
+ /D_+{dtE Tag处理类的方法
0W`LVue _{jP;W Tag标签类型
i#X!#vyc 所调用的方法
^MD;"A< 8hA^`Y 基本标签
`(0LK%w doStartTag, doEndTag, release
bXYA5wG BIf^~jAER% 带属性的标签
"Lh doStartTag, doEndTag, set/getAttribute1...N, release
PN$
.X"D8 m}$+Hdk+7 带内容的标签
tvX>{-M doStartTag, doEndTag, release
Fv?=Z-wk [oc~iDx%W 带内容的标签,且内容重复循环
<B /5J:o< doStartTag, doAfterBody, doEndTag, release
XE}H 3/2 }<MR`h1 带内容的标签,且内容与JSP交互
+:6Ii9GN doStartTag, doEndTag, release, doInitBody, doAfterBody, release
Lt#'W 5j"1z1_& 一个tag处理类可以通过javax.servlet.jsp.PageContext来与JSP交互,通过javax.servlet.jsp.PageContext类,tag处理类可以访问JSP中的request、session和application对像。
SbsouGD,{ 'mdM q=VI 如果tag标签是互相嵌套的,那内层的tag处理类可以通过它的parent属性来访问上层的tag处理类。
.BO< RA a[t :| 一般情况都将所有的tag处理类打成了JAR的包,以便于发布。
kqvow3u 7:h!Wj-a] ,J mbqOV?! Tag库描述(简称TLD)
J
NC n,P5o_^: iy\KzoB Tag库是用xml语言描述的,TLD包括了tag库中所有tag标签的描述,它一般用来被jsp服务器用来校验tag的语法正确性,或者被jsp开发者用来开发新的标签。
:9l51oE7 /T0nLp`gi TLD的文件扩展名必须为.tld,而且必须放在当前WEB应用的WEB-INF目录或其子目录中。
K#K\-TR|$ #>@z
2K7 一个TLD的内容的开头必须遵守标准的XML开头,用于描述DTD和xml的版本,例如:
v_PdOp[
k %'L;FPxB <?xml version="1.0" encoding="ISO-8859-1" ?>
AF4?IH =A[5=
k> <!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "
http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd">
tPHS98y TLD必须以<taglib>来作为它的根元素,<taglib>的子元素如下表:
1'6cGpZY +c206. o%M<-l"!/ <taglib>的子元素
yy2Ie #
Oup^ o@ Element
,D80/2U^ Description
`PI(%N XeUC0K[D tlib-version
TUp%FJXA| Tag库的版本
3Rl,GWK ned2lC&'d> jsp-version
t~K%.|'0 Tag库所需要的jsp的版本
#~?kYCtC) Q"J-tP! short-name
:ipoD%@ 助记符,tag的一个别名(可选)
a0Oe:]mo\ -E&e1u,Mi uri
0?bA$y 用于确定一个唯一的tag库
9w;?- 5b#QYu display-name
us)*2`?6t 被可视化工具(诸如Jbuilder)用来显示的名称(可选)
,[48Mspp H!IDV}dn small-icon
i4Z4xTn 被可视化工具(诸如Jbuilder)用来显示的小图标(可选)
/k:$l9C[ 83]PA<R large-icon
'bW5Fr>W 被可视化工具(诸如Jbuilder)用来显示的大图标(可选)
b_$1f> qFRdg V>8 description
1H4fJ3- 对tag库的描述(可选)
y@vj;3: 2%rLoL$Y2+ listener
&hZwZgV+3 参见下面listener元素
B(HT.%r^A p5]_}I`+2 tag
BQgoVnQo_c 参见下面tag 元素
{_ V0 "/x_>ui1F Listener元素
LZ~`29qw( ~o15#Pfn/ 一个tag库可能定义一些类做为它的事件侦听类,这些类在TLD中被称为listener 元素,jsp服务器将会实例化这些侦听类,并且注册它们。Listener元素中有一个叫listener-class的子元素,这个元素的值必须是该侦听类的完整类名。
SHdL/1~t b#Kq[} Tag元素
L&w.j0fq =_=*OEgO] 每个tag元素在tag库中都要指出它的名字、类名、脚本变量、tag的属性。其中脚本变量的值可以直接在TLD中定义或通过tag附加信息的类来取得。每个属性描述了这个属性是否可以省略,它的值是否可以通过<%= …%>这样的JSP语法来获得,以及属性的类型。
yFIIX=NC /Ic[N& 每一个tag在TLD中对应一个tag元素,下表是tag元素的子元素:
EO"C8z'al p6 xPheD Tag元素的子元素
?F$6;N6x BD;H
元素名称
/NBTvTI 描述
H 30OUrD W3pQ? name
#V 43= 独一无二的元素名
h_
!>yK Q .RO tag-class
d!{7r7ob\ Tag标签对应的tag处理类
:\}U9QfCw k
'zat3#f tei-class
,-#GX{! javax.servlet.jsp.tagext.TagExtraInfo的子类,用于表达脚本变量(可选)
Up ?=m^
C B}BQd body-content
sk X]8 Tag标签body的类型
BnEdv8\,&s m/${8 display-name
6}&^=^- 被可视化工具(诸如Jbuilder)用来显示的名称(可选)
i2F(GH?p[ aw$Y`6,S small-icon
xks?y.wA 被可视化工具(诸如Jbuilder)用来显示的小图标(可选)
|4SW[>WT: VuWib+fT large-icon
fGu!M9qN4 被可视化工具(诸如Jbuilder)用来显示的大图标(可选)
f$D@*33ft !=zx description
*6*-WV6 此tag标签的描述
QUP|FIpZ _PB@kH# variable
h`?k.{})M 提供脚本变量的信息(同tei-class)(可选)
!$kR ;Q"/ M<oA<#IW attribute
xdF guV8 Tag标签的属性名
,{<Fz% {\We72! 以下章节介绍对于不同类型的tag,如何具体地实现它们。
6Y?`=kAp Ml`vx %8D?$v"#Z 简单的tag
T\3 [F%? sc xLB; ?y_awoBd1 tag处理类
ba&o;BLUy BlaJl[P iv 简单的tag处理类必须实现Tag接口的doStartTag和doEndTag方法。当jsp引擎碰到tag标签的开头时,doStartTag被调用,因为简单的tag没有body,所以此方法将返回 SKIP_BODY。当jsp引擎碰到tag标签的结尾时,doEndTag被调用,如果余下的页面还要被计算,那它将返回EVAL_PAGE,否则将会返回SKIP_PAGE。
B7 c[4 .Ty,_3+{#p 以下是例子:对于标签 <tt:simple /> ,它的tag处理类实现如下:
Vipp /WV FzhT$7Gw (T;9us0 public SimpleTag extends TagSupport
VK4/82@5 B)a@fmp"a {
NV~vuC Zz")`hUG public int doStartTag() throws JspException
tp+=0k2i <IH*\q:7 {
)0|):g pTET%)3 try{
Wm>b3: BTs0o&}e pageContext.getOut().print(“Hello.”);
"_)|8|gN #JS`e_3Rr }catch(Exception e){
b`]M|C [5 *<dHqK`?C throw new JspTagException(“SimpleTag: “ + e.getMessage());
u+DX$#-n!] ysth{[<5F3 }
5&(3A|P2 \3j)>u,r return SKIP_BODY;
3Uo]>BG #Q+R%p[D }
0BXs&i-TP5 ?pKN'` public int doEndTag()
DPeVKyjU {rfte'4;= {
Y- ~;E3( u_Zm1*'?B return EVAL_PAGE;
g< )72-h lPp6
pVr }
f!!P ^2JPyyZa }
#S*pD?VZ d5'
)6 AA.Ys89V 注意:如果tag标签没有内容的话,那必须定义body-content元素为空,例如
x\]z j! SJ[AiHR <body-content>empty</body-content>
}{=8&gA0 /&QQ p3 x_|>n<Z 带属性的tag标签