标准的JSP 标记可以调用JavaBeans组件或者执行客户的请求,这大大降低了JSP开发的复杂度和维护量。JSP技术也允许你自定义taglib,其实换句话说,taglib可以看成是对JSP标记的一种扩展,正如xml是对html的一种扩展一样。taglib通常定义在tag标签库中,这种标签库存放着你自己定义的tag标签。简而言之,如果使用taglib,那么你可以设计自己的JSP标记!
mcbvB5U ((OQs. 一般来说,自定义tag标签主要用于操作隐藏对象、处理html提交表单、访问数据库或其它企业级的服务,诸如邮件和目录操作等等。自定义tag标签的使用者一般都是那些对java编程语言非常精通,而且对数据访问和企业级服务访问都非常熟悉的程序员,对于HTML设计者来说,使得他可以不去关注那些较复杂的商业逻辑,而将精力放在网页设计上。同时,它也将库开发者和库使用者进行合理分工,自定义tag标签将那些重复工作进行封装,从而大大提高了生产力,而且可以使得tag库可用于不同的项目中,完美地体现了软件复用的思想。
2:b3+{\f {yFCGCs 在这篇文章中,我们主要讨论:
%@Mv-A6) v;_m1UpuW · 什么是自定义tag标签?
R|4a9G /Wos{}Z0 · 怎么使用tag标签?
5,Rxc= NPc@;g]d" o 声明要使用的tag库
ePF)wl;m #yPQt! o 找到与之对应的tag处理类
ppL*#/jYt r2dU>U*:4 o tag标签的类型
[\|`C4@3a iN\m:m · 自定义tag标签
r:rM~`` ?w/i;pp<, o tag处理类
Jkf%k3H3I* w4I&SLm-b o tag库描述
LTsX{z 7I\qEr57 o tag标签示例
gl.uDO%. @-B)a Z o 带属性的tag
P_7QZ0k/ R
-#40 o 带body的tag
$r3kAM;V: (*6kYkUK o 定义了脚本变量的tag
`LroH>_ ,$4f#) o 具有协作关系的tag
/2s=;tA1 Z+8Q{|Ev · 自定义tag标签
-q&K9ZCl`
ORCG(N o 一个迭代tag的例子
8D]&wBR: Chso]N.1 o 一个模板tag库
A-6><X's6 ^Kbq.4 o tag处理类到底是怎样被调用的?
W%&gvZre. $V/Hr/0 $l
W
7me 什么是自定义的tag?
":I@>t{H* Z=KHsMnB 一个自定义的tag标签是用户定义的一种JSP标记。当一个含有自定义的tag标签的JSP页面被jsp引擎编译成servlet时,tag标签被转化成了对一个称为tag处理类的对象进行的操作。于是当JSP页面被jsp引擎转化为servlet后,实际上tag标签被转化成为了对tag处理类的操作。
jx=5E6(h xU6rZCqE 自定义tag标签有很多特色,诸如:
d~QZcR 4{v?<x8 · 可以在JSP页面中自定义tag标签的属性
Vb57B.I !_P-?u · 访问JSP页面中的所有对象
#{8t
?v l +|K/*VVn` · 可以动态地修改页面输出
v?@=WG <V
b
SEi · 彼此这间可以相互通信。你可以先创建一个JavaBeans组件,然后在一个tag中调用此JavaBeans组件,同时可以在另一个tag中调用它。
.wpp)M.w;H .Ce0yAl~ · tag允许相互嵌套,可以在一个JSP页面中完成一些复杂的交互。
,5XDH6L1 H~1o^
gU &Hj1jM' 使用tag标签
oF(=@UL j6&q6C X #TG7WF5 本节主要描述怎样在JSP页面中使用tag标签,以及tag标签的不同类型。
L> \/%x>Wx kJ_XG;8 要使用tag标签,JSP程序员必须做2件事:
'Szk!,_ @{ CP18~: · 声明此tag标签的tag库
UCBx?9O/0 $/)0iL{0 · 实现此tag标签
<)]j;Tl o4qB0h 声明tag标签所在的tag库
S=zW
wo$ Ly_.%f 如果要使用tag标签,则应用JSP的taglib指示符来指定其tag库(注意:taglib要在在使用此tag标签之前声明)
qDK\MQ! cx_$`H <%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %>
sUl
_W"aQ 95IR.Qfn! uri属性定义了唯一的标签库描述(以下简称TLD),它可以是直接是tld文件名或一个独一无二的名字。prefix是用来区别其它TLD中和本TLD中有重名的tag的一种手段。
C"cBlru8B .4%6_`E TLD必须以.tld作为扩展名,并且存放在当前应用的WEB-INF目录或其子目录下。你可以通过它的文件名直接引用它,也可以通过别的方式间接地引用它。
CubBD+hl* ] vQU(@+I 以下taglib指示符直接引用一个TLD:
d%lwg~@&|5 E]gy5y <%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %>
TjWMdoU$J 8h{;*Wr- 以下的taglib指示符通过一个逻辑名称间接地引用一个TLD:
W5U;{5 SrT=XX, <%@ taglib uri=”/tutorial-template” prefix=”tt” %>
=rzhaU'A' ,AuejMd 如果是间接引用TLD的话,那你必须还要在web.xml中定义此逻辑名称与tld文件之间的映射,具体做法是在web.xml中加入一个名为taglib的元素:
_s~F/G`iT KrqO7 <taglib>
( jtkY_ Rap =& <taglib-uri>/tutorial-template</taglib-uri>
pcO{%]?p r.10b]b <taglib-location>
:}+m[g Vd+5an? /WEB-INF/tutorial-template.tld
VCCG_K9' ;_D5]kl` </taglib-location>
+l@+e_> gH[lpRu|7 </taglib>
U\`yLsKvH` q,fk@GI'2 =G-u "QJ6 实现此tag标签
E|BiK tOVYA\] H\RuYCn2G 为了实现tag标签,你有2种方法来存放tag处理类。一、让tag处理类以.class的方式存放于当前应用的WEB-INF/class子目录下,二、如果tag处理类是以JAR包的形式存在的话,那可以放在当前应用的WEB-INF/lib目录下,如果tag处理类要在多个应用中共享,那么它就应放在jsp服务器上的common/lib目录下,对于tomcat来说,就是tomcat/common/lib目录下。
!k0t
(. X0zE-h6P nk+*M9r|I tag标签类型
xyaU!E* SO}en[()O m9li% p 自定义的tag标签遵循XML语法。它有一个开始标记和一个结束标记,有的还有body(即文本节点):
HHaerc O\[Td <tt:tag>
BGZvgMxLJ /u N3"m5i body
7).zed^ 2apQ4)6#[H </tt:tag>
i'NN pTzfc`~xv ' $5o5\ 一个不带body的tag标签如下:
GcA!I!j/ V[BlT|t <tt:tag />
dD}!E #zv'N Xn:ac^ 简单的tag标签
+H8;*uZ|k, ;WpPdR2 一个没有body和属性的tag标签如下:
!Knv/:+ {1j[RE <tt:simple />
m8ydX6~max lITZ|u ]Zz<9zix 带属性的tag标签
*|Fl&`2 Or[uq,Dm16 7LdNE|IP 自定义标签可以有自己的属性。属性一般在开始标记中定义,语法为 attr=”value”。属性的作用相当于自定义标签的一个参数,它影响着tag处理类的行为。你可以在TLD中详细定义它。
S&m5]h!D Le':b2o 你可以用一个String常量给一个属性赋值,也可以通过表达式给它赋值,如<%= ...%>。以struts为例,它的logic:present标签就是用的String常量来给属性赋值:
g+iV0bbT `%M}
:T <loglic:present parameter = “Clear”>
~*Ir\wE .`Ts'0vVy 而另一个标签logic:iterate是用表达式来给属性赋值:
h8uDs|O9n u:7=Yy
: <logci:iterate collection=”<%= bookDB.getBooks() %>”
_ Oe|ZQ gDJ@s
id=”book” type=”database.BookDetails”>
*tZ#^YG{( vaEAjg*To< k&>l#oH 带body的tag标签
JI}p{yI hT<:)MG)+K 一个自定义标签可以包含其它自定义标签、脚本变量、HTML标记或其它内容。
CJNz J( %1p4K) 在下述例子中,此JSP页面使用了struts的logic:present标签,如果些标签定义了parameter=”Clear”的属性,则将清除购物车的内容,然后打印出一条信息:
|uE_aFQs X@7K#@5 <logic:present parameter=”Clear”>
f3]u-e'b H9Pe,eHs <% cart.clear(); %>
1yIo'i1 .DkDMg1US <font color=”#ff0000” size=”+2”><strong>
L5*,l`lET "yCek 你选择了清除购物车!
A*:(%! |fk,&5s </strong></font>
V6ioQx=K# NR)[,b\v </logic:present>
CQcb !T 6c>tA2G|8 !OJSQB, 到底是用属性还是用body来传递信息?
'k9hzk(* S-:7P.#Q 如上所述,我们既可以通过属性,也可以通过body来传递信息。但一般来说,比较简单的类型,如字符串或简单表达式最好采用属性来传递信息。
7TQh'j S hM}w/4 [+st?;"GF 定义脚本变量的tag标签
s=nE'/q1| |KFWW 所谓脚本变量,是指JSP中可以调用的变量或对象。它可由tag标签产生。以下示例阐述了一个tag标签定义了一个名为tx的由JNDI所定义的事务处理对象。脚本变量可以是ejb对象、事务、数据库连接等等:
\'L6m1UZ% D{,B[5 <tt:lookup id=”tx” type=”UserTransaction” name=”java:comp/UserTransaction” />
" lf_`4 ]41G!'E= <% tx.begin(); %>
uhLg2G^h ^JMSe- ...
:6z0Ep" BVC{Zq6hi Fq5);sX= 具有协作关系的tag标签
*/L;6_ (;T;?v`- 自定义tag标签之间可以通过共享对象来实现协作。在下述例子中,标签tag1创建了一个名为obj1的对象,在标签tag2仍可以重复使用obj。
^IGTGY]s H\3CvFm <tt:tag1 attr1=”obj1” value1=”value” />
m(3bO[u1
1Nk}W!v <tt:tag2 attr1=”obj1” />
(t9qwSS8z ^~5tntb. 在以下这个例子当中,如果外层的tag标签创建了一个对象,那么其内层的所有tag标签都可以使用这个对象。由于这样产生的对象没有一个指定的名字,那么就可以将少重名的冲突。这个例子阐述了一系列协作的嵌套对象。
NoJo-vo* -7">A~c <tt:outerTag>
MQ>vHapr ':!;6v|L <tt:innerTag />
9_ Qm_ ^tuJM: </tt:outerTag>
ANCgch\ {Pg7IYjH V]PTAhc Tag处理类
$XI5fa4Tt pKMf#)qm 7@vcQv
kC Tag处理类必须实现Tag接口或BodyTag接口,不过现在一般都流行从TagSupport或BodyTagSupport类中继承,这些类或接口都可以在javax.servlet.jsp.tagext包中找到。
o0wep&@ w'5~GhnP+ 当JSP引擎看到自己的JSP页面中包含有tag标签时,它会调用doStartTag方法来处理tag标签的开头,调用doEndTag方法来处理tag标签的结束。
xL>0&R =I/J !}. 下表说明不同类型的tag所需要不同的处理过程:
ZF;S}1 ,oP-:q!PC Tag处理类的方法
^%d+nKx9nL Vb 4Qt#o Tag标签类型
EW4XFP4
c 所调用的方法
kQIWDN z PV/{)S 基本标签
KX<RD|= doStartTag, doEndTag, release
jVRd[
X2i<2N*@ 带属性的标签
cp?`\P doStartTag, doEndTag, set/getAttribute1...N, release
f8?K_K;\ <$D)uY K 带内容的标签
FZA8@J|Q4 doStartTag, doEndTag, release
XpH[SRUx de1& 带内容的标签,且内容重复循环
i}<R>]S doStartTag, doAfterBody, doEndTag, release
SsznV}{^ mk4%]t" 带内容的标签,且内容与JSP交互
jd2Fh):q doStartTag, doEndTag, release, doInitBody, doAfterBody, release
m2|0<P@k! !gf&l ^) 一个tag处理类可以通过javax.servlet.jsp.PageContext来与JSP交互,通过javax.servlet.jsp.PageContext类,tag处理类可以访问JSP中的request、session和application对像。
'KQuz)- g\(7z
P 如果tag标签是互相嵌套的,那内层的tag处理类可以通过它的parent属性来访问上层的tag处理类。
wKY6[ vvF RFK
N,oB 一般情况都将所有的tag处理类打成了JAR的包,以便于发布。
\\)-[4uC /2HwK/RZ %k$C Tag库描述(简称TLD)
dIO\ lL
}UGPEf\ J*U(f{Q( Tag库是用xml语言描述的,TLD包括了tag库中所有tag标签的描述,它一般用来被jsp服务器用来校验tag的语法正确性,或者被jsp开发者用来开发新的标签。
74Q?%X g>im2AD+e TLD的文件扩展名必须为.tld,而且必须放在当前WEB应用的WEB-INF目录或其子目录中。
^1cqx]>E Y5MHd>m 一个TLD的内容的开头必须遵守标准的XML开头,用于描述DTD和xml的版本,例如:
m'qMcCE ^m1Rw| <?xml version="1.0" encoding="ISO-8859-1" ?>
\R-u+ci$ZY N M8F <!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "
http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd">
Z@ws,f^e TLD必须以<taglib>来作为它的根元素,<taglib>的子元素如下表:
v8%]^` ' i^IvT s\jLIrG8 <taglib>的子元素
6:EO 7GP?;P Element
<01B\t7 Description
ufR | `P z !H tlib-version
Y*}Sq|y Tag库的版本
H1?1mH K5.C*|w jsp-version
iuHG9 #n Tag库所需要的jsp的版本
;%jt;Xv9 /BIPLDN6 short-name
If&p$pAH? 助记符,tag的一个别名(可选)
C3_*o>8 {9l4 pT3 uri
`\Npu 用于确定一个唯一的tag库
|M
K-~ep 5%>U.X?i display-name
_>`0!mG 被可视化工具(诸如Jbuilder)用来显示的名称(可选)
yQx>h6 ;:!LAe
small-icon
2hpx%H 被可视化工具(诸如Jbuilder)用来显示的小图标(可选)
R*[ACpxr Zka;}UL&Q large-icon
g]ihwm~ 被可视化工具(诸如Jbuilder)用来显示的大图标(可选)
,5\n%J: gEe}xI description
}%1E9u 对tag库的描述(可选)
%d7iQZb> ZbGyl}8ua listener
*"4<&F
S 参见下面listener元素
Yj"UD:p iK#{#ebAoW tag
SA&wW\Ym] 参见下面tag 元素
Ml3F\ fAW HIU@m< Listener元素
[)Ge^yI7 .6"7Xxe]< 一个tag库可能定义一些类做为它的事件侦听类,这些类在TLD中被称为listener 元素,jsp服务器将会实例化这些侦听类,并且注册它们。Listener元素中有一个叫listener-class的子元素,这个元素的值必须是该侦听类的完整类名。
an7N<-? f@}( <# Tag元素
S;c=6@" {l6]O 每个tag元素在tag库中都要指出它的名字、类名、脚本变量、tag的属性。其中脚本变量的值可以直接在TLD中定义或通过tag附加信息的类来取得。每个属性描述了这个属性是否可以省略,它的值是否可以通过<%= …%>这样的JSP语法来获得,以及属性的类型。
W[?B@ sdSZ )5t_tPv 每一个tag在TLD中对应一个tag元素,下表是tag元素的子元素:
Qpc{7#bp xl9l>k6, Tag元素的子元素
lxd<^R3i#^ dg!sRm1iZ: 元素名称
UEe qk"t^ 描述
hB.dqv]^ j;y|Ys)I name
c1<g!Q&E 独一无二的元素名
7/1S5yUr| ?~K2&eo tag-class
P:=ADW c Tag标签对应的tag处理类
B';Ob ]@P*&FRcZ tei-class
DEs?xl]zO javax.servlet.jsp.tagext.TagExtraInfo的子类,用于表达脚本变量(可选)
/{U{smtdFl ` WB|h)Y body-content
l>iU Q&V Tag标签body的类型
@bx2= m\>x_:sE display-name
x -!FS h8q 被可视化工具(诸如Jbuilder)用来显示的名称(可选)
S'O0'5U@ JU@$( small-icon
+ ND9### 被可视化工具(诸如Jbuilder)用来显示的小图标(可选)
.3&m:P8zV ;H=6u large-icon
2ya`2 m 被可视化工具(诸如Jbuilder)用来显示的大图标(可选)
*O5+?J Z! Q.\>+4]1&& description
QD<4(@c5| 此tag标签的描述
ayD\b6Z2. [GuDMl3hC variable
\f
LBw0 提供脚本变量的信息(同tei-class)(可选)
C;5}/J^E 1fy{@j(W attribute
=FbfV*K9 Tag标签的属性名
E;4a(o]{t RFC;1+Jn 以下章节介绍对于不同类型的tag,如何具体地实现它们。
fz&}N`n ;x#>J +QlG A-io-P7qyj 简单的tag
NIfc/% #dft-23 JK(&E{80 tag处理类
$VA4% 9 fh^_=R(/ 简单的tag处理类必须实现Tag接口的doStartTag和doEndTag方法。当jsp引擎碰到tag标签的开头时,doStartTag被调用,因为简单的tag没有body,所以此方法将返回 SKIP_BODY。当jsp引擎碰到tag标签的结尾时,doEndTag被调用,如果余下的页面还要被计算,那它将返回EVAL_PAGE,否则将会返回SKIP_PAGE。
O2G+
' 5dF=DCZ 以下是例子:对于标签 <tt:simple /> ,它的tag处理类实现如下:
K9 q~Vf :tqjm: l 3K8{HY public SimpleTag extends TagSupport
nf4P2<L! IMZKlU3 {
'dzp@-\ L@Z
&v'A public int doStartTag() throws JspException
4.'EEuRw\} + LwoBn>6 {
D$cMPFa2Nt *ls6#j@ try{
bwJi[xF
%\cC]<> pageContext.getOut().print(“Hello.”);
@nP}q!y {Y[D!W2y }catch(Exception e){
DVJc-.x8 VO Qt{v{1| throw new JspTagException(“SimpleTag: “ + e.getMessage());
deoM~r9s .y/b$|d, }
wM)w[ I[UA' ~f return SKIP_BODY;
k%g xY% 0 J[H?nX9 }
Yg[IEy w8
$Qh%J'< public int doEndTag()
=T)2wcXBB 6bNW1]rD {
,[\(U!Z7:% 0UJ`<Bfd return EVAL_PAGE;
[,^dM:E/ (weokP! }
F9\Ot^~ `4bd, }
shT[|@"C !yX<v%>_0 >U<nEnB$? 注意:如果tag标签没有内容的话,那必须定义body-content元素为空,例如
j>xVy]v= | fWyDWU <body-content>empty</body-content>
:dN35Y] a iyYY)roB h50StZ8Yr 带属性的tag标签