标准的JSP 标记可以调用JavaBeans组件或者执行客户的请求,这大大降低了JSP开发的复杂度和维护量。JSP技术也允许你自定义taglib,其实换句话说,taglib可以看成是对JSP标记的一种扩展,正如xml是对html的一种扩展一样。taglib通常定义在tag标签库中,这种标签库存放着你自己定义的tag标签。简而言之,如果使用taglib,那么你可以设计自己的JSP标记!
4MCj*ok< g#G ]}8C 一般来说,自定义tag标签主要用于操作隐藏对象、处理html提交表单、访问数据库或其它企业级的服务,诸如邮件和目录操作等等。自定义tag标签的使用者一般都是那些对java编程语言非常精通,而且对数据访问和企业级服务访问都非常熟悉的程序员,对于HTML设计者来说,使得他可以不去关注那些较复杂的商业逻辑,而将精力放在网页设计上。同时,它也将库开发者和库使用者进行合理分工,自定义tag标签将那些重复工作进行封装,从而大大提高了生产力,而且可以使得tag库可用于不同的项目中,完美地体现了软件复用的思想。
^3QJv{)Q {9cjitl 在这篇文章中,我们主要讨论:
zT>BC}~.b uSH_=^yTQ · 什么是自定义tag标签?
(N9g6V S.?DR3XLc · 怎么使用tag标签?
%{?9#)) )kYDN_W o 声明要使用的tag库
%Y9CZRY9 vX&W;& o 找到与之对应的tag处理类
/*t H$\6* 8/lgM'Eux o tag标签的类型
}q,d JE {W=5
J7 · 自定义tag标签
z:&/O&? -Q|]C{r o tag处理类
~"8r=8| X, }(MW o tag库描述
Q!r` G Zb:Z,O(vn o tag标签示例
D[Q/:_2l 2G_]Y8 o 带属性的tag
MHA_b^7? \p^'[B(O77 o 带body的tag
UtRwZ(09 iV!V!0- @ o 定义了脚本变量的tag
B`)bo}h b,>>E^wd! o 具有协作关系的tag
3u<
ntx >< 2q*wYuc · 自定义tag标签
bHQ) :W Ko|gH]B' o 一个迭代tag的例子
pm[+xM9PB @gw8r[ o 一个模板tag库
]Qe"S>,?` e%IbME]x o tag处理类到底是怎样被调用的?
jsP+,brO cM]ZYi e$&n)>% 什么是自定义的tag?
5<P6PHdY )jh~jU? c@ 一个自定义的tag标签是用户定义的一种JSP标记。当一个含有自定义的tag标签的JSP页面被jsp引擎编译成servlet时,tag标签被转化成了对一个称为tag处理类的对象进行的操作。于是当JSP页面被jsp引擎转化为servlet后,实际上tag标签被转化成为了对tag处理类的操作。
e\!Aoky Kq(JHB+ 自定义tag标签有很多特色,诸如:
by\Sq} FrE#l.)?! · 可以在JSP页面中自定义tag标签的属性
!'B=']. \u;`Lf · 访问JSP页面中的所有对象
3rR1/\ ` $q0fTz · 可以动态地修改页面输出
qqys`. 9_ZGb"(Lj · 彼此这间可以相互通信。你可以先创建一个JavaBeans组件,然后在一个tag中调用此JavaBeans组件,同时可以在另一个tag中调用它。
YPA$38 $VF$Ok> · tag允许相互嵌套,可以在一个JSP页面中完成一些复杂的交互。
1-E utq v:n[H]K| +,TrJg 使用tag标签
RE1M4UV. 0E)M6
jJ <(H<*Xf9 本节主要描述怎样在JSP页面中使用tag标签,以及tag标签的不同类型。
0%)T]SDS k=&n>P 要使用tag标签,JSP程序员必须做2件事:
}7_$[r'_oI E()%IC/R · 声明此tag标签的tag库
Ys|SacWC ?Cx=!k. · 实现此tag标签
M+b?qw 7
D{% 声明tag标签所在的tag库
B:Awy/XMi +O.qYX 如果要使用tag标签,则应用JSP的taglib指示符来指定其tag库(注意:taglib要在在使用此tag标签之前声明)
A6 `a cIcu=U <%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %>
Ul}<@d9: B 6;wKL?snO uri属性定义了唯一的标签库描述(以下简称TLD),它可以是直接是tld文件名或一个独一无二的名字。prefix是用来区别其它TLD中和本TLD中有重名的tag的一种手段。
S#<y_w% JoZSp"R TLD必须以.tld作为扩展名,并且存放在当前应用的WEB-INF目录或其子目录下。你可以通过它的文件名直接引用它,也可以通过别的方式间接地引用它。
;lfv.-u:< :Gew8G 以下taglib指示符直接引用一个TLD:
#%w)w R3 >8b%*f8R <%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %>
) TRUx O%haaL\ 以下的taglib指示符通过一个逻辑名称间接地引用一个TLD:
&gUa^5'# 6Nt/>[ <%@ taglib uri=”/tutorial-template” prefix=”tt” %>
*||Q_tlz TKgN31 ` 如果是间接引用TLD的话,那你必须还要在web.xml中定义此逻辑名称与tld文件之间的映射,具体做法是在web.xml中加入一个名为taglib的元素:
qw>vu7/z "h|kf%
W <taglib>
\A)Pcc}7 ` U-vXP <taglib-uri>/tutorial-template</taglib-uri>
m]H]0T `5rfO6; <taglib-location>
[HL>Lp&A? xW2?\em /WEB-INF/tutorial-template.tld
'+3C2! 6 N:Ps8Hg </taglib-location>
Zo
}^"u X(\L1N </taglib>
e
m0 hTxb !~vx|_$# <0 qhc$M 实现此tag标签
H6Bw3I[ lJdYR'/Wd j;
R20xf 0 为了实现tag标签,你有2种方法来存放tag处理类。一、让tag处理类以.class的方式存放于当前应用的WEB-INF/class子目录下,二、如果tag处理类是以JAR包的形式存在的话,那可以放在当前应用的WEB-INF/lib目录下,如果tag处理类要在多个应用中共享,那么它就应放在jsp服务器上的common/lib目录下,对于tomcat来说,就是tomcat/common/lib目录下。
^@{"a 1
-C~C]& Ob}XeN(L3 tag标签类型
L
u'<4 R B*w]yL( ),[@NK&= 自定义的tag标签遵循XML语法。它有一个开始标记和一个结束标记,有的还有body(即文本节点):
`xx3JQv[ &]shBvzl^ <tt:tag>
(E,Ibz2G:e 7upWM~H^ body
yz5! >|EB :@eHV=|+> </tt:tag>
) xKW +r9neS.l "z;R"sv\ 一个不带body的tag标签如下:
~"<^4h |lZp5MOc <tt:tag />
~sPXkLqK
o)]O EU04U 简单的tag标签
#TC}paIpj |\/\FK]?] 一个没有body和属性的tag标签如下:
=8%*Rrj^ 1N:~5S}s> <tt:simple />
i]L=M
5^C rHk,OC WiZTE(NM` 带属性的tag标签
.l5-i@=W . UH'U\M 8n-Xt7z 自定义标签可以有自己的属性。属性一般在开始标记中定义,语法为 attr=”value”。属性的作用相当于自定义标签的一个参数,它影响着tag处理类的行为。你可以在TLD中详细定义它。
f-ceDn Dln1 R[ 你可以用一个String常量给一个属性赋值,也可以通过表达式给它赋值,如<%= ...%>。以struts为例,它的logic:present标签就是用的String常量来给属性赋值:
9%"`9j~H> 1uCF9P
ai <loglic:present parameter = “Clear”>
>tx[UF@P@ SM2N3"\ 而另一个标签logic:iterate是用表达式来给属性赋值:
r4DHALu#) qvK/} <logci:iterate collection=”<%= bookDB.getBooks() %>”
<;O^3_' (DS"*4ty id=”book” type=”database.BookDetails”>
SbzJeaZv o4J@M{xb_ g_N^Y 带body的tag标签
Jj5VBI!Ok
S~E@A.7 一个自定义标签可以包含其它自定义标签、脚本变量、HTML标记或其它内容。
{
0&l*@c& Cb`, N 在下述例子中,此JSP页面使用了struts的logic:present标签,如果些标签定义了parameter=”Clear”的属性,则将清除购物车的内容,然后打印出一条信息:
~G-W|> 9 wbQ$>G9 <logic:present parameter=”Clear”>
0fn*;f8{XJ MGxkqy? <% cart.clear(); %>
OP" _I!t )fxn bBz{ <font color=”#ff0000” size=”+2”><strong>
>cg)NqD nk7>iK!i 你选择了清除购物车!
9V[}#(f$ gIusp917 </strong></font>
0@{0#W3R @rDBK] V </logic:present>
*|<~IQg wfpl]d! LHXR7Fjc 到底是用属性还是用body来传递信息?
&5${k' C"B'Dj 如上所述,我们既可以通过属性,也可以通过body来传递信息。但一般来说,比较简单的类型,如字符串或简单表达式最好采用属性来传递信息。
,UNk]vd R=&-nC5e 8iOHav4 定义脚本变量的tag标签
u'Q82l&Y gx',K1T 所谓脚本变量,是指JSP中可以调用的变量或对象。它可由tag标签产生。以下示例阐述了一个tag标签定义了一个名为tx的由JNDI所定义的事务处理对象。脚本变量可以是ejb对象、事务、数据库连接等等:
TI/RJF b &vt)7[ <tt:lookup id=”tx” type=”UserTransaction” name=”java:comp/UserTransaction” />
o3GkTn O G5K?Q+n
<% tx.begin(); %>
"bF52lLu QKB+mjMH#x ...
K/ &` 9==4T$nM[ L jTSu9I> 具有协作关系的tag标签
l U4 I* |+::sL\r 自定义tag标签之间可以通过共享对象来实现协作。在下述例子中,标签tag1创建了一个名为obj1的对象,在标签tag2仍可以重复使用obj。
qNP)oU92 N6\rjYx+7 <tt:tag1 attr1=”obj1” value1=”value” />
hf0(!C* jC>#`gD <tt:tag2 attr1=”obj1” />
i*m;kWu, e&U$;sS` 在以下这个例子当中,如果外层的tag标签创建了一个对象,那么其内层的所有tag标签都可以使用这个对象。由于这样产生的对象没有一个指定的名字,那么就可以将少重名的冲突。这个例子阐述了一系列协作的嵌套对象。
R@s7s%y= ipg`8*My <tt:outerTag>
EU%v
|] cz/cY:o) <tt:innerTag />
b1jDbiH& k ,+,,W </tt:outerTag>
PnInsf%; ,Xfu?Yan =~Qg(=U0U Tag处理类
z rG VPuR4p. CfP-oFHoQ Tag处理类必须实现Tag接口或BodyTag接口,不过现在一般都流行从TagSupport或BodyTagSupport类中继承,这些类或接口都可以在javax.servlet.jsp.tagext包中找到。
3S]QIZ1 =_z o 当JSP引擎看到自己的JSP页面中包含有tag标签时,它会调用doStartTag方法来处理tag标签的开头,调用doEndTag方法来处理tag标签的结束。
fCF.P"{W" X&LJ"ahK 下表说明不同类型的tag所需要不同的处理过程:
v[{7\Hha -3v\ c~ Tag处理类的方法
5N%d Les K:$mEB[c< Tag标签类型
#jG?{j3;? 所调用的方法
?kQY ^pU v
@0G^z| 基本标签
n8=Dzv0 doStartTag, doEndTag, release
jll:Rh(b ,>7dIJqzw 带属性的标签
"0[`U(/ doStartTag, doEndTag, set/getAttribute1...N, release
a^@.C5 AG9DJ{T 带内容的标签
)UF'y{K} doStartTag, doEndTag, release
8h@L_*Kr ]k^?= 带内容的标签,且内容重复循环
%<a3[TQd`\ doStartTag, doAfterBody, doEndTag, release
B ;E"VS0 9X=<uS 带内容的标签,且内容与JSP交互
`y^\c#k doStartTag, doEndTag, release, doInitBody, doAfterBody, release
amC)t8L? Nc{&AV8Y_v 一个tag处理类可以通过javax.servlet.jsp.PageContext来与JSP交互,通过javax.servlet.jsp.PageContext类,tag处理类可以访问JSP中的request、session和application对像。
fxoEK}TM 0E!-G= v 如果tag标签是互相嵌套的,那内层的tag处理类可以通过它的parent属性来访问上层的tag处理类。
`'<$N<! {}ADsh@7d' 一般情况都将所有的tag处理类打成了JAR的包,以便于发布。
WQ[nK5# '@hUmrl =FV(m
S Tag库描述(简称TLD)
tlUh8os 7<MEM NYX d94k Tag库是用xml语言描述的,TLD包括了tag库中所有tag标签的描述,它一般用来被jsp服务器用来校验tag的语法正确性,或者被jsp开发者用来开发新的标签。
_.V5-iN "``>ii TLD的文件扩展名必须为.tld,而且必须放在当前WEB应用的WEB-INF目录或其子目录中。
;<Hk Cd ."^\1N(.n 一个TLD的内容的开头必须遵守标准的XML开头,用于描述DTD和xml的版本,例如:
|C z7_Rn )1M2}11uS <?xml version="1.0" encoding="ISO-8859-1" ?>
,3T"fT-( Uoe;=P@ <!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "
http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd">
P658
XKE TLD必须以<taglib>来作为它的根元素,<taglib>的子元素如下表:
-sKtT 9o *nJ,|T ou~$XZ7oi <taglib>的子元素
>4Tk#+%Jj DGb1_2ZQ Element
tJ K58m$ Description
lW-h
@ I8)D tlib-version
u%z'.#r; a Tag库的版本
(XmmbAbVom b/
\EN) jsp-version
;#9?3Os Tag库所需要的jsp的版本
QJ(%rvn3 =LV-n short-name
U!r8}@ 助记符,tag的一个别名(可选)
XK3O,XM Sv /P:r
_ uri
K'J_AMBL 用于确定一个唯一的tag库
I@6+AU~,6 ZwLr>?0$
p display-name
?rQ .nN 被可视化工具(诸如Jbuilder)用来显示的名称(可选)
tB~#;:g ,m?V3xvq small-icon
Z+y'w#MZL 被可视化工具(诸如Jbuilder)用来显示的小图标(可选)
%|}*xMQ '#3FEo large-icon
Y=G`~2Pr= 被可视化工具(诸如Jbuilder)用来显示的大图标(可选)
x
cAs}y} `b8nz 7 description
W g7
eY'FE 对tag库的描述(可选)
&(Fm@ksh\ p@f
#fs listener
}RadbJ{q= 参见下面listener元素
Lg!E K=0xR*ll5 tag
4sQm"XgE 参见下面tag 元素
'=Zm[P, ?<3 d
Fb Listener元素
9AhA"+? m=@xZw< 一个tag库可能定义一些类做为它的事件侦听类,这些类在TLD中被称为listener 元素,jsp服务器将会实例化这些侦听类,并且注册它们。Listener元素中有一个叫listener-class的子元素,这个元素的值必须是该侦听类的完整类名。
"Ux(nt i@?|vu Tag元素
n5UUoBv /fb}]e]N 每个tag元素在tag库中都要指出它的名字、类名、脚本变量、tag的属性。其中脚本变量的值可以直接在TLD中定义或通过tag附加信息的类来取得。每个属性描述了这个属性是否可以省略,它的值是否可以通过<%= …%>这样的JSP语法来获得,以及属性的类型。
mJ<`/p?: P:.jb!ZU 每一个tag在TLD中对应一个tag元素,下表是tag元素的子元素:
Ya\:C] dGOFSH Tag元素的子元素
tmS2%1o ( `bb1gz 元素名称
$%DoLpE> 描述
N ~=PecQ 0*5Jq#5 name
NN'pBUR 独一无二的元素名
CqC
)H7A $eI
cCLF tag-class
81y<Uz 6 Tag标签对应的tag处理类
0{
mm%@o :s_.K'4?a tei-class
: H;S"D javax.servlet.jsp.tagext.TagExtraInfo的子类,用于表达脚本变量(可选)
iE"]S ) ;y\/7E body-content
)u{]rb[ Tag标签body的类型
|=YK2}; vi^YtA display-name
_";w*lg} 被可视化工具(诸如Jbuilder)用来显示的名称(可选)
rrRv 7J&Q 5?` 4qSUz small-icon
V?
tH/P 被可视化工具(诸如Jbuilder)用来显示的小图标(可选)
LJ@(jO{z +`Q]p "G large-icon
]vf0 f,F 被可视化工具(诸如Jbuilder)用来显示的大图标(可选)
R_/;U&R :$u[1&6 description
6~0kb_td 此tag标签的描述
cKkH*0B5 ~L<"]V+B variable
d'MZ%.# 提供脚本变量的信息(同tei-class)(可选)
QObVJg,GD 02[m{a- attribute
Q?1.GuF Tag标签的属性名
a_}C*+D \K\eq>@6 以下章节介绍对于不同类型的tag,如何具体地实现它们。
R7(XDX=[s &PV%=/-J
N#9N ^#1 简单的tag
a+lNXlh= %$zak@3%' ;5X~"#%U_ tag处理类
AFL'Ox]0 ]>[TF'pIAx 简单的tag处理类必须实现Tag接口的doStartTag和doEndTag方法。当jsp引擎碰到tag标签的开头时,doStartTag被调用,因为简单的tag没有body,所以此方法将返回 SKIP_BODY。当jsp引擎碰到tag标签的结尾时,doEndTag被调用,如果余下的页面还要被计算,那它将返回EVAL_PAGE,否则将会返回SKIP_PAGE。
0'F/z%SMj C)i8XX 以下是例子:对于标签 <tt:simple /> ,它的tag处理类实现如下:
=dNE1rdzNa D>{`I' J#Y0R"fo public SimpleTag extends TagSupport
$*X?]? DjK7_'7(L {
:l]qTCmY n.9k5r@ public int doStartTag() throws JspException
g`'!Vgd?M[ Brs6RkRf {
jq]5Y^e 5SUO`4L try{
'6NrL;
RICm$, pageContext.getOut().print(“Hello.”);
M.dX;iM< ^g(qPtQ }catch(Exception e){
o%j?}J7y C1_0 9Vc throw new JspTagException(“SimpleTag: “ + e.getMessage());
[7PC\ fWA#n }
>F7HKwg}Z H%l-@::+$ return SKIP_BODY;
d:>^]5cE& U5j4iz' }
FYFlh^} >%`SXB&9 public int doEndTag()
.
U6(>6- y7h^_D+Ce {
_/Ve~(
" BJ3<"D{.*4 return EVAL_PAGE;
X(E`cH
| #]1jvB }
|)>+&
xk u=L Dfn }
\41/84BA .9ZK@xM&? `,~'T [ 注意:如果tag标签没有内容的话,那必须定义body-content元素为空,例如
+`"Tn`O |) ~-Wy <body-content>empty</body-content>
>G!=lLyR ^bPpcm= 2jhJXM=~ 带属性的tag标签