这是我考WCD的读书笔记,翻译自一个study kit,并没有把所有内容都翻译,但也翻译大部分了,都是一些我觉得比较重要的内容,觉得对理解web开发相当有好处。5月27日就要考了,今天刚好复习到这部分,就先把他放上来。以后章节会陆续上传。
Tag handler: 它是实现了其中一个tag接口的java class.—Tag, IterationTag, BodyTag.
Tag library: 它是一个行为的集合,封装了一些在JSP页中被使用的功能.
Tag library descriptor: 当我们在JSP页面中使用自定义标签的时候,JSP引擎需要知道这些标签的的tag handler class在标签库的位置,以及如何使用他们. 这些meta-information被存储在一个叫做tag library descriptor的文件中.
三种URI:
Absolute URI:例如: http://localhost:8080/taglibs !!!!!!这时自定义的一个URI!!!!!!!!
Root Relative URI: 以”/”开头,它被解释为web应用的文件目录的根目录的相对位置.例如: /taglib1/helloLib
Non-root Relative URI:不以”/”开头,它被解释为当前JSP页面或WEB-INF的相对位置,依赖于它被使用的位置.例如: taglib2/helloLib
如何使用已存在的标签库?
如何实现自定义的标签库?
在标准的JSP语法中这样使用标签库:
<%@ taglib prefix="test" uri="sampleLib.tld" %>
在XML语法中这样使用标签库:
<jsp:root
xmlns:jsp="http://java.sun.com/JSP/Page"
xmlns:test="sampleLib.tld"
version="1.2" >
...JSP PAGE...
</jsp:root>
尽管把所有JSP页和TLD文件保存在同一目录下是最简单的使用taglib的做法,但是由两个不好的地方:安全和适应性.
首先是安全,访问者可以直接访问你的标签库的内容通过键入http://www.someserver.com/sampleLib.tld
当然,我们可以通过限制访问所有TLD文件的权限,但是,更好的做法是我们把TLD文件放在/WEB-INF目录下,使用/WEB-INF/sampleLib.tld访问他们.然而,我们还有适应性的问题.如果我们想改变标签库的版本,比如是sample_2.tld,我们就不得不手动修改所有受影响的JSP页.更甚者,第三方自定义标签库通常被打包成JAR文件。这种情况下,我们怎样才能指定TLD文件的位置呢?
为了避免这个问题,JSP为指明标签库的位置提供了一个清晰的解决方法。JSP容器维护一个我们在taglib directive中使用的URI和实际TLD文件的物理路径之间的映射。取代页面相对路径,我们使用绝对的URI路径:
<%@ taglib prefix="test" uri=http://www.someserver.com/sampleLib
当JSP引擎读到上面的URI时,他会去它内部的映射寻找对应的TLD文件的位置。
因此,这就解决了安全和适应性的问题。实际上的TLD文件可以存储在WEB-INF目录下或者甚至是JAR文件中,对访问者隐藏。如果有一个新的标签库版本发布,我们需要做的只是更新在URI和实际路径中的映射。
在开发标签库的过程中,我们通常是把TLD文件保存在目录下,而不是JAR文件中.这会提高开发和测试的周期.然而,当我们开发完成了,我们会打包handler class 文件和标签库的TLD文件成为一个JAR文件.这个文件被配置到/web-inf/lib目录下.
JSP规范要求,当配置一个JAR文件的时候,TLD文件应该要么直接放在META-INF文件中,要么放在META-IN的子目录下.而且,TLD文件的文件明必须是taglib.tld.因此,JAR文件的结构应该是象这样的:
myPackage/myTagHandler1.class
myPackage/myTagHandler2.class
myPackage/myTagHandler3.class
META-INF/taglib.tld
JSP容器会识别两个位置作为TLD文件的路径,一个是目录,一个是JAR文件.这个路径叫做 TLD资源路径(TLD resource path.).
所有实际上的映射,就是一个URI和TLD文件的位置之间的映射.要么是包含TLD文件的目录,要么是包含TLD文件的JAR文件.这种映射叫taglib map.
三种方法关联URI和TLD文件位置:
1.容器会读取所有出现在部署描述器中用户定义的映射.这叫显映射(explicit mapping)
2.容器会读取所有出现在JAR文件中的taglib.tld文件.由于每个被打进包的TLD文件包含了关于自身URI的信息,JSP容器会自动为这个URI和当前JAR文件的位置创建一个映射.这叫隐映射(implicit mapping).
3.JSP容器会自动装载容器默认的URI.这些URI叫well-known URI. http://java.sun.com/JSP/Page 就是一个well-known URI.
容器自己在它的标签库中提供了所有这些标签的实现实现.这实际上是隐映射的另一种形式.
显映射:
<taglib-uri>这是用户自定义的URI.可以是绝对URI,根相对URI,或是非根相对URI.
<taglib-location>这是TLD资源路径.它的值可以是根相对URI或非根相对URI,它必须指向一个有效的TLD资源路径(注意两个有区别!)
<taglib>
<taglib-uri>
http://www.manning.com/studyKit
</taglib-uri>
<taglib-location>
/myLibs/studyKit.tld
</taglib-location>
</taglib>
<!-- Taglib 2 -->
<taglib>
<taglib-uri>
http://www.manning.com/sampleLib
</taglib-uri>
<taglib-location>
yourLibs/sample.jar
</taglib-location>
</taglib>
当JSP引擎解析JSP文件遇到taglib directive时,他会检查taglib映射,看是否存在taglib directive的URI属性:
1.如果URI属性的值和任何一个<taglib-uir>实体匹配,引擎就会使用对应的<talib-location>的值去定位实际的TLD文件.
<1.如果<tldlib-location>的值是根目录相对URI(root-relative,以/开头),JSP引擎就会认为它的URI位置是相对于web应用的文件根目录的(从应用文件根目录开始找).例如会这样找: <doc-root>/myLibs/studyKit.tld
<2.如果<taglib-location>的值是非根目录相对URI的(not-root relative,不以/开头),JSP引擎会预先考虑/WEB-INF/下的URI,并认为它的位置是相对于web应用根目录的位置(也就是从WEB-INF开始找).例如:会这样找 <doc-root>/WEB-INF/yourLibs/studyKit.tld
2.如果没有匹配的<taglig-uri>实体,有以下三种可能性:
<1.如果uri属性是一个绝对路径,在转化时会报告错误.
<2.如果uri属性是一个根目录相对URI,他会被认为是相对于web应用的根目录的相对位置.
<3.如果uri属性是一个非根目录相对URI,他会被认为是相对于当前的JSP页面的.因此,如果JSP文件<doc-root>/jsp/test.jsp包含了<%@ taglib prefix="test" uri="sample.tld" %>,引擎就会希望在<doc-root>/jsp/sample.tld查找到sample.tld文件.
考虑一个 没有在部署描述器中映射的URI:我们在JSP页中使用<%@ taglib uri="www.manning.com/hello.tld" prefix="a" %>会怎样?
---www.manning.com/hello.tld 这个URI没有包含协议(如http),因此,它不是绝对URI.它不以/开头,因此它不是一个根目录相对URI.他是一个页面相对URI.当没有找到映射后,引擎就会在相对于当前页面的位置查找hello.tld文件.假设当前的JSP的位置是:C:/tomcat/webapps/test.jsp 那么引擎就会在这个位置中查找hello.tld文件:C:/tomcat/webapps/www.maning.com/hello.tld. 如果还找不到,那就报错.
其实,有映射和没有映射是很显然的.有映射的,uri的属性就能是随便什么东西都可以,因为是映射出来的.但是,如果是没有映射的,那么uri的属性就只能是一个tld文件了,因为引擎会真正的从这个uri所指示的位置去寻找tld文件!其中,应该认真区分路径的问题.
不能使用的前缀:jsp,jspx,java,javax,servlet,sun,sunw
4种标签的类型:
空标签(Empty tags):没有内容体. <prefix:tagName></prefix:tagName>或<prefix:tagName/> 相当有用的.
含有属性的标签(Tag with attribute):属性可以是表达式.标签库设计者应该在TLD文件中定义:a.一系列有效的属性名. b.属性是否是强制的. c.值的数据类型. d.属性的值被指明是在转化时使用字符串还是在请求时使用的表达式.
含有JSP代码的标签(Tag with JSP code):
含有嵌套的标签(Tag with nested tags):