标准的JSP 标记可以调用JavaBeans组件或者执行客户的请求,这大大降低了JSP开发的复杂度和维护量。JSP技术也允许你自定义taglib,其实换句话说,taglib可以看成是对JSP标记的一种扩展,正如xml是对html的一种扩展一样。taglib通常定义在tag标签库中,这种标签库存放着你自己定义的tag标签。简而言之,如果使用taglib,那么你可以设计自己的JSP标记!
4>d[qr*< T&e%/ 一般来说,自定义tag标签主要用于操作隐藏对象、处理html提交表单、访问数据库或其它企业级的服务,诸如邮件和目录操作等等。自定义tag标签的使用者一般都是那些对java编程语言非常精通,而且对数据访问和企业级服务访问都非常熟悉的程序员,对于HTML设计者来说,使得他可以不去关注那些较复杂的商业逻辑,而将精力放在网页设计上。同时,它也将库开发者和库使用者进行合理分工,自定义tag标签将那些重复工作进行封装,从而大大提高了生产力,而且可以使得tag库可用于不同的项目中,完美地体现了软件复用的思想。
DOA[iT";4 !DCVoc]pV 在这篇文章中,我们主要讨论:
LE Jlo%M /Ir 7
DZK · 什么是自定义tag标签?
7YSuB9{M ]lC4+{V · 怎么使用tag标签?
<4S F~i `jt(DKB+J o 声明要使用的tag库
gS0,')w NdaM9a#TZ o 找到与之对应的tag处理类
m}sh I8S +._f.BRmX. o tag标签的类型
$::51#^Wg y0lL Fe~ · 自定义tag标签
Z7ZWf'o aj+zmk~- o tag处理类
I%C]>ZZh y;*My# o tag库描述
AZ]Z,s6 8VKb* o tag标签示例
bK6, saN> an #jZ[ o 带属性的tag
t/_\U=i$ ei(|5h o 带body的tag
R#rh \Gv- sA o 定义了脚本变量的tag
s"gKonwI2 4ZSfz#<[z o 具有协作关系的tag
K4BTk! iFXUKGiV · 自定义tag标签
4d,qXSKty h:eN>yW o 一个迭代tag的例子
w`2_6[,9 &*h`b{] o 一个模板tag库
~r7DEy|+
"`H=AX0 o tag处理类到底是怎样被调用的?
>IR`] Sf#\6X<B |8b$x| B 什么是自定义的tag?
n C\(+K1% =aX1:Z 一个自定义的tag标签是用户定义的一种JSP标记。当一个含有自定义的tag标签的JSP页面被jsp引擎编译成servlet时,tag标签被转化成了对一个称为tag处理类的对象进行的操作。于是当JSP页面被jsp引擎转化为servlet后,实际上tag标签被转化成为了对tag处理类的操作。
OsDp88Bc $,!dan<eA 自定义tag标签有很多特色,诸如:
|YMzp8Da( w`w `q' · 可以在JSP页面中自定义tag标签的属性
\f~u85 K]lb8q}Z~ · 访问JSP页面中的所有对象
_&6juBb
~`a#h# · 可以动态地修改页面输出
Ta!m%=8
}j]<&I} · 彼此这间可以相互通信。你可以先创建一个JavaBeans组件,然后在一个tag中调用此JavaBeans组件,同时可以在另一个tag中调用它。
+^o3}` ]a&x' · tag允许相互嵌套,可以在一个JSP页面中完成一些复杂的交互。
@8T
Vr2uy je$R\7B< C{U[w^X 使用tag标签
O#<|[Dzw bUEt0wRR U:C-\ M 本节主要描述怎样在JSP页面中使用tag标签,以及tag标签的不同类型。
@8}-0c yAZ.L/jyr 要使用tag标签,JSP程序员必须做2件事:
8tG/VE[ e\+~ · 声明此tag标签的tag库
htNL2N @p?b"?QaB · 实现此tag标签
@9
qzn&A Q7OnhGA 声明tag标签所在的tag库
6=aBD_2@ mUe@Dud 如果要使用tag标签,则应用JSP的taglib指示符来指定其tag库(注意:taglib要在在使用此tag标签之前声明)
o%9Ua9|RR H-PW( <%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %>
3tx0y <%5-Pz p uri属性定义了唯一的标签库描述(以下简称TLD),它可以是直接是tld文件名或一个独一无二的名字。prefix是用来区别其它TLD中和本TLD中有重名的tag的一种手段。
`:B kfG 65aa>_ TLD必须以.tld作为扩展名,并且存放在当前应用的WEB-INF目录或其子目录下。你可以通过它的文件名直接引用它,也可以通过别的方式间接地引用它。
j.G.Mx" >8.v.;` 以下taglib指示符直接引用一个TLD:
hA&j?{ UGezo3} <%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %>
H_xQ>~b a`GN@
8 以下的taglib指示符通过一个逻辑名称间接地引用一个TLD:
E:LQ! _tWfb}6;Zb <%@ taglib uri=”/tutorial-template” prefix=”tt” %>
)SlUQ7f> 8/kx 3 如果是间接引用TLD的话,那你必须还要在web.xml中定义此逻辑名称与tld文件之间的映射,具体做法是在web.xml中加入一个名为taglib的元素:
0|*UeM 519:yt <taglib>
qJAv=D 4N0W& Dy <taglib-uri>/tutorial-template</taglib-uri>
;^*+:e HnYFE@Nl:U <taglib-location>
.P0Qs&i #E~WVTOw /WEB-INF/tutorial-template.tld
c=U$$|qHV 6#lC(ko' </taglib-location>
$=S'#^Z cVv4gQD\ </taglib>
R)DNFc: 8 MACbLY CzDR% v x 实现此tag标签
V+@%(x@D_
EY[Q% Bb2r95h}^ 为了实现tag标签,你有2种方法来存放tag处理类。一、让tag处理类以.class的方式存放于当前应用的WEB-INF/class子目录下,二、如果tag处理类是以JAR包的形式存在的话,那可以放在当前应用的WEB-INF/lib目录下,如果tag处理类要在多个应用中共享,那么它就应放在jsp服务器上的common/lib目录下,对于tomcat来说,就是tomcat/common/lib目录下。
dOYm t, o sgS?=8 DRFuvU+e tag标签类型
JCU3\39} 4q2=:"z4 M}KM]< 自定义的tag标签遵循XML语法。它有一个开始标记和一个结束标记,有的还有body(即文本节点):
")[Q4H;V 8bKWIN g_n <tt:tag>
;JD3tM< Gh>fp body
r&l*.C* `__?7"p
)\ </tt:tag>
,VcDvZ7 ^:rNoo ,oi`BOh 一个不带body的tag标签如下:
2
vJ[vsrFv 0qV*d <tt:tag />
$y]||tX ?}lp o; $ O%q;,w{prW 简单的tag标签
J#OE}xASoA Ns(L1'9= 一个没有body和属性的tag标签如下:
Vlxb<$5Nh ,mBKya) <tt:simple />
h/+I-],RF _XO)`D~ Cx3m\
\c 带属性的tag标签
{J6sM$aj ^TCJh^4na K1wN9D{t' 自定义标签可以有自己的属性。属性一般在开始标记中定义,语法为 attr=”value”。属性的作用相当于自定义标签的一个参数,它影响着tag处理类的行为。你可以在TLD中详细定义它。
MnrGD>M@| 6L`+z 你可以用一个String常量给一个属性赋值,也可以通过表达式给它赋值,如<%= ...%>。以struts为例,它的logic:present标签就是用的String常量来给属性赋值:
gp&&
c, \eSk7C <loglic:present parameter = “Clear”>
+` Y ?- Ev|{~U 而另一个标签logic:iterate是用表达式来给属性赋值:
EwBN+v;) tP^mq> <logci:iterate collection=”<%= bookDB.getBooks() %>”
o:Os_NaD {@F["YPxy id=”book” type=”database.BookDetails”>
8iH;GFNJ7' L)nVpqm BnnUUaE 带body的tag标签
i11GW <W[8k-yOV` 一个自定义标签可以包含其它自定义标签、脚本变量、HTML标记或其它内容。
sq6% =(q(? {'Qk>G
s 在下述例子中,此JSP页面使用了struts的logic:present标签,如果些标签定义了parameter=”Clear”的属性,则将清除购物车的内容,然后打印出一条信息:
(l!D=qy MHT,rqG <logic:present parameter=”Clear”>
w5/X{ en#g<on <% cart.clear(); %>
)PoI~km U.j\u>a <font color=”#ff0000” size=”+2”><strong>
S%gO6&^ SlJ/OcAf# 你选择了清除购物车!
j6d"8oH
_ byj mH </strong></font>
V-U
^O45 lX k-86[M </logic:present>
gwB>oi*OE a:%5.!Vd _x|8U'|Ce 到底是用属性还是用body来传递信息?
a4qpnr]0 sluZ-,zE 如上所述,我们既可以通过属性,也可以通过body来传递信息。但一般来说,比较简单的类型,如字符串或简单表达式最好采用属性来传递信息。
_(kwD^x6O{ [
*a>{sO[ 96E7hp !: 定义脚本变量的tag标签
]\mb6Hc Fh4w0u*Q 所谓脚本变量,是指JSP中可以调用的变量或对象。它可由tag标签产生。以下示例阐述了一个tag标签定义了一个名为tx的由JNDI所定义的事务处理对象。脚本变量可以是ejb对象、事务、数据库连接等等:
].T;x| 2?7hUaHX <tt:lookup id=”tx” type=”UserTransaction” name=”java:comp/UserTransaction” />
_M4v1Hr48 Ac(irPrD <% tx.begin(); %>
=|&"/$+s A_*Lo6uII ...
`L[32B9 p1gX4t]%}a y!c7y]9__2 具有协作关系的tag标签
=v`&iL~m y^|3]G3 自定义tag标签之间可以通过共享对象来实现协作。在下述例子中,标签tag1创建了一个名为obj1的对象,在标签tag2仍可以重复使用obj。
JOne&{h]J" hA1hE?c` <tt:tag1 attr1=”obj1” value1=”value” />
vc{]c
} w,#W&>+& <tt:tag2 attr1=”obj1” />
l'lDzB+.* &EJ,k'7$ 在以下这个例子当中,如果外层的tag标签创建了一个对象,那么其内层的所有tag标签都可以使用这个对象。由于这样产生的对象没有一个指定的名字,那么就可以将少重名的冲突。这个例子阐述了一系列协作的嵌套对象。
W9m[>-Ew .lj! ~_ <tt:outerTag>
=ZIFS eV=sDx <tt:innerTag />
b0=AQ/: jL).B& </tt:outerTag>
T:~W.3
i-vJ&}} tsC|R~wW Tag处理类
[_G0kiI}W" VP[!ji9P 5$Q`P',*Ua Tag处理类必须实现Tag接口或BodyTag接口,不过现在一般都流行从TagSupport或BodyTagSupport类中继承,这些类或接口都可以在javax.servlet.jsp.tagext包中找到。
im[gbac 4qcIoO 当JSP引擎看到自己的JSP页面中包含有tag标签时,它会调用doStartTag方法来处理tag标签的开头,调用doEndTag方法来处理tag标签的结束。
%=O!K>^vt< Wq&c,H 下表说明不同类型的tag所需要不同的处理过程:
'xI+kyu 19{?w6G<k Tag处理类的方法
b/}0
&VXo &r%^wfp Tag标签类型
r9'H7J 所调用的方法
92_H!m/ ^X'7>{7Io 基本标签
WWD@rn sVf doStartTag, doEndTag, release
moI<b\G@ _7HJ' 带属性的标签
OiEaVPSI; doStartTag, doEndTag, set/getAttribute1...N, release
`rJ ~*7- J` --O(8Ml 带内容的标签
oOSyOD doStartTag, doEndTag, release
]@T `qR X1qj
l_A 带内容的标签,且内容重复循环
N ^`Efpvg doStartTag, doAfterBody, doEndTag, release
,lYU#Hx* &L`p4AZ 带内容的标签,且内容与JSP交互
_\[JMhd} doStartTag, doEndTag, release, doInitBody, doAfterBody, release
&: 8 &;vk "$;:dfrU 一个tag处理类可以通过javax.servlet.jsp.PageContext来与JSP交互,通过javax.servlet.jsp.PageContext类,tag处理类可以访问JSP中的request、session和application对像。
PH &ms $^ dk>Hj>4 如果tag标签是互相嵌套的,那内层的tag处理类可以通过它的parent属性来访问上层的tag处理类。
/ hdl U.h PC3 一般情况都将所有的tag处理类打成了JAR的包,以便于发布。
!7*/lG \)kAhKtG ~'\u:Imuo Tag库描述(简称TLD)
nW*Oo|p~= zb)SlR ]J]p:Y>NL Tag库是用xml语言描述的,TLD包括了tag库中所有tag标签的描述,它一般用来被jsp服务器用来校验tag的语法正确性,或者被jsp开发者用来开发新的标签。
j=QjvWD 'E8Qi'g TLD的文件扩展名必须为.tld,而且必须放在当前WEB应用的WEB-INF目录或其子目录中。
w.-i !Ls 6x8|v7cMH 一个TLD的内容的开头必须遵守标准的XML开头,用于描述DTD和xml的版本,例如:
wIHz TL d/QM <?xml version="1.0" encoding="ISO-8859-1" ?>
iPYlTV wf$ JuHPt <!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "
http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd">
L<]PK4 TLD必须以<taglib>来作为它的根元素,<taglib>的子元素如下表:
e2ZUl` {g L KR,CPz
&g>+tkC <taglib>的子元素
hG3Lj7)UH nE%qm - Element
V7i`vo3Cc Description
hIr^"kVK ~Nh7C b_ tlib-version
HjR<4;2 Tag库的版本
bvTkSEN Hf|:A(vCx jsp-version
w2AWdO6 Tag库所需要的jsp的版本
@6`@.iZ +c_CYkHJ/ short-name
pz =Wq4l 助记符,tag的一个别名(可选)
xWV7#Z7 7^X_tQf uri
W4a20KM2 用于确定一个唯一的tag库
B6&Mtm1 sg\jC# display-name
t4uxon 被可视化工具(诸如Jbuilder)用来显示的名称(可选)
{u3u%^E;R r{&"]'/X small-icon
"//
8^e%Xo 被可视化工具(诸如Jbuilder)用来显示的小图标(可选)
j` lK} _zwuK1e large-icon
M/;g|J
jM 被可视化工具(诸如Jbuilder)用来显示的大图标(可选)
.1}(Bywm5 ?!Gt.
fb description
7|Y8^T
s 对tag库的描述(可选)
t/(j8w nJC}wh2d# listener
b7mP~]V 参见下面listener元素
vkmR
cX:/ -&tiM
v tag
=p$ Wo 参见下面tag 元素
+R$KEGu~0Y Ne_>%P|I_ Listener元素
Jq)k?WS x|5/#H 一个tag库可能定义一些类做为它的事件侦听类,这些类在TLD中被称为listener 元素,jsp服务器将会实例化这些侦听类,并且注册它们。Listener元素中有一个叫listener-class的子元素,这个元素的值必须是该侦听类的完整类名。
5Px_vtqP Xw5"JE!. Tag元素
i[J', yRDLg
c 每个tag元素在tag库中都要指出它的名字、类名、脚本变量、tag的属性。其中脚本变量的值可以直接在TLD中定义或通过tag附加信息的类来取得。每个属性描述了这个属性是否可以省略,它的值是否可以通过<%= …%>这样的JSP语法来获得,以及属性的类型。
VvKH]>* 1tc9STYR} 每一个tag在TLD中对应一个tag元素,下表是tag元素的子元素:
|JQ05nb Ccmbdw,Z5 Tag元素的子元素
[*v\X %+ \ S R 元素名称
XzsK^E0R 描述
dx}!]_mlZ
)G&OX name
Kfl+8UR5= 独一无二的元素名
=QRZ(2Wq ZS]e}]Zwp tag-class
,55`s#; Tag标签对应的tag处理类
!2}Q9a 9
|Y?#oZ1 tei-class
Mt>DAk javax.servlet.jsp.tagext.TagExtraInfo的子类,用于表达脚本变量(可选)
Fjb[Ev ?9A[;j|a0 body-content
y5}|Y{5 Tag标签body的类型
~gD]JiiA HY:n{=o display-name
9mZ1 a6,x 被可视化工具(诸如Jbuilder)用来显示的名称(可选)
f[D#QC X)+N>8o?N small-icon
^xrR3m*d 被可视化工具(诸如Jbuilder)用来显示的小图标(可选)
i`;I"oY4 duCm+4,. large-icon
{ar}.U 被可视化工具(诸如Jbuilder)用来显示的大图标(可选)
E3qX$|.$/ LtBH4A description
o hCPNm 此tag标签的描述
XijQ)}'C3 .wywO| variable
\N)FUYoHg 提供脚本变量的信息(同tei-class)(可选)
l{4\Wn Va [nrP;
_ attribute
_1~Sj* Tag标签的属性名
-~g3?!+Hb FW4 hqgE@ 以下章节介绍对于不同类型的tag,如何具体地实现它们。
2StpcAlU} kMA>)\ F
7=-k/k 简单的tag
\?ZdUY {mDaK&]Oh `}bUf epMJ tag处理类
6`i' uH#NJoRO 简单的tag处理类必须实现Tag接口的doStartTag和doEndTag方法。当jsp引擎碰到tag标签的开头时,doStartTag被调用,因为简单的tag没有body,所以此方法将返回 SKIP_BODY。当jsp引擎碰到tag标签的结尾时,doEndTag被调用,如果余下的页面还要被计算,那它将返回EVAL_PAGE,否则将会返回SKIP_PAGE。
jn[a23;G) j.K yPWO 以下是例子:对于标签 <tt:simple /> ,它的tag处理类实现如下:
,\M'jV"SK t65!2G"< \ gN) GR public SimpleTag extends TagSupport
|w5#a_adM VF-d^AGt {
h$!qb'| vR,'': public int doStartTag() throws JspException
fjb2-K )UeG2dXx7 {
5^k#fl2 >Et?7@
try{
U6Qeode =cQwR:): pageContext.getOut().print(“Hello.”);
ATU@5,9 <i5^izg }catch(Exception e){
[qz6_WOo aj\'qRrU$ throw new JspTagException(“SimpleTag: “ + e.getMessage());
#[8gH>7 R8E<;^?j }
3Rm$ AYi$LsLhO return SKIP_BODY;
$#!~K2$ YANEdH`d }
IO+z:D{ V6L_aee}CK public int doEndTag()
M$)+Uo2 ~^eAS; {
Wwz>tE PIA&s6U return EVAL_PAGE;
N P"z gR+Z"] }
;?rW`e2 Q*wx6Pu8 }
%bsdC0xM sk5\"jna rk~/^(! 注意:如果tag标签没有内容的话,那必须定义body-content元素为空,例如
oTL "]3`' Q -+jG7vT <body-content>empty</body-content>
yD KX, L=$P fkYQ3d,` 带属性的tag标签