taglib简介
因此,这次我们将设计一种新的解决方案。在本期的 JSP最佳实践中,您将学习一些基础知识,主要是关于如何将scriptlet转换成自定义标记,并对其进行设置以便在您的JSP开发项目中使用。
为什么使用taglib?
所谓 标记库(tag library),是指由在JSP页面中使用的标记所组成的库。JSP容器推出时带有一个小型的、默认的标记库。而 自定义标记库是人们为了某种特定的用途或者目的,将一些标记放到一起而形成的一种库。在一个团队中协同工作的开发者们可能会为各自的项目创建一些非常特定化的自定义标记库,同时也会创建一个通用自定义标记库,以供当前使用。
JSP 标记替代了scriptlet,并缓解了由scriptlet所招致的所有令人头痛的事情。例如,您可以看到这样的标记:
|
1
|
<store:shoppingCart id="1097629"/> |
或者这样的标记:
|
1
|
<tools:usageGraph /> |
每个标记都包含了指向一个Java类的引用,但是类中的代码仍然在它该在的地方:在标签之外,一个编译好的类文件之中。
从 scriptlet 到标记
创建一个自定义标记的第一步就是决定您想怎样使用它,如何称呼它,以及它允许使用或者需要什么属性(如果有的话)。对于时间戳标记,我们所需要的很简单:只要一个能够输出一个页面的最后修改数据的简单标记。
因为不需要属性,这个标记看上去就是这个样子:
|
1
|
<site-utils:lastModified /> |
这个标记的名称和前缀是一样的:都是 site-utils 。元素的内容是空的,这意味着该元素中不允许有子元素存在。定义了这个标记之后,接下来的一步就是实现它的行为。
实现行为
实现标记行为的第一步是将scriptlet代码从原先所在的地方移到一个Java类( LastModifiedTag )中,如清单 1 所示:
清单 1. 创建一个时间戳标记
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
package com.newInstance.site.tags;import java.io.File;import java.io.IOException;import java.text.DateFormat;import java.text.SimpleDateFormat;import java.util.Date;import javax.servlet.http.HttpServletRequest;import javax.servlet.jsp.tagext.TagSupport;public class LastModifiedTag extends TagSupport { public int doEndTag() { try { HttpServletRequest request =(HttpServletRequest)pageContext.getRequest(); String path = pageContext.getServletContext().getRealPath( request.getServletPath()); File file = new File(path); DateFormat formatter = DateFormat.getDateInstance( DateFormat.LONG); pageContext.getOut().println( formatter.format(new Date(file.lastModified()))); } catch (IOException ignored) { } return EVAL_PAGE; }} |
这个方法中的代码看上去比较熟悉;实质上,它正是我们在先前用到的相同的时间戳代码。由于不需要用户输入,而且该标记也没有属性或者嵌入的内容,我们惟一需要关心的一个新方法就是 doEndTag()(),在这个方法中该标记可以输出内容(在这个例子中是最后修改数据)到JSP页面。
清单 1 中其他的更改更多地与作为一个JSP标记的代码有关,而与在一个页面内运行的scriptlet没有多大关系。例如,所有的JSP标记都应该扩展JSP类 javax.servlet.jsp.tagext.TagSupport ,这个类为JSP标记提供了基本框架。可能您还注意到 ,该标记返回的 EVAL_PAGE . EVAL_PAGE 是一个预定义的整型常量,它指示容器处理页面的剩下部分。另一种选项就是使用 SKIP_PAGE ,它将中止对页面剩下部分的处理。如果您要将控制转移到另一个页面,例如您要前进(forward)或者重定向(redirect)用户,那么只需要使用 SKIP_PAGE 。剩下来的细节都是与时间戳自身有关的事情。
接下来,编译这个类,并将 LastModifiedTag.class 文件放到一个WEB-INF/classes 目录下,注意要放到正确的路径层次结构中。这个路径应该匹配该标记的包名,包名中的圆点(.)用斜杠(/)代替。在本例中,目录的路径是基路径(WEB-INF/classes)再加上层次结构com/newInstance/site/tags。如果有一个名为 foo.bar.tag.MyTag 的标记,那么它将被放在 WEB-INF/classes/foo/bar/tag中。这种路径层次结构确保了Web容器在任何需要装载该标记的时候都能够找到这个类。
创建TLD
接下来的一步是创建一个 标记库描述符(tag library descriptor ,TLD)文件。TLD向容器和任何要使用该标记库的JSP页面描述您的标记库。清单 2 显示了一个非常标准的TLD,其中只包含了一个标记。当您将更多的标记添加到库中时,TLD文件的长度和复杂性将随之增长。
清单 2. 一个标记库描述符
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
<?xml version="1.0" encoding="ISO-8859-1"?><!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2/EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd"><taglib> <tlib-version>1.0</tlib-version> <jsp-version>1.2</jsp-version> <short-name>site-utils</short-name> <uri>http://www.newInstance.com/taglibs/site-utils</uri> <tag> <name>lastModified</name> <tag-class>com.newInstance.site.tags.LastModifiedTag</tag-class> <body-content>empty</body-content> </tag></taglib> |
TLD 文件顶部的信息应用于整个标记库。在本例中,我提供了一个版本(这对于跟踪某个标记库的JSP创建者拥有哪个版本很有用,尤其是在您需要经常修改标记库的情况下更是如此);该标记库所依赖的JSP版本;一个为该标记库推荐的前缀;以及用于引用这个标记库的URI。注意,我使用了前缀 short-name作为URI的一部分,这样 比较容易将前缀和标记库的URI看成一个整体。
剩下的信息用于一个特定的标记,这些信息用 tag 元素表示。我指定了该标记的名称、用于该标记的类(这个类应该被编译好并放在适当的地方,以便容器能够装载),最后还指定了该标记是否有嵌入的内容。在本例中,标记没有嵌入的内容,因此使用"empty"。
保存这个文件,并将其放到WEB-INF/tlds目录下(您可能需要在您的容器中创建这个目录)。我将这个文件保存为site-utils.tld,并在该标记库的URI(推荐的前缀)和TLD文件本身之间再次创建一个干净的链接。对于这个特定的标记库,要使其可以使用,最后一步要做的是让您的Web应用知道如何连接一个JSP页面中的URI,如何请求使用一个标记库。这可以通过应用的web.xml文件来做。清单 3 显示了一个非常简单的web.xml片段,正是 它为我们的标记库做这样的事情。
清单 3. 将一个URI与一个标记库链接起来
|
1
2
3
4
|
<taglib> <taglib-uri>http://www.newInstance.com/taglibs/site-utils</taglib-uri> <taglib-location>/WEB-INF/tlds/site-utils.tld</taglib-location> </taglib> |
包装起来
如果您已经按照上述步骤执行了,那么现在您应该能够在JSP页面中引用新标记了。清单 4 向我们展示了新改进的footer.jsp,这个文件中现在完全没有scriptlet,也没有指向具有scriptlet的JSP页面的引用。
清单 4. 使用新的标记库
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
<%@ taglib prefix="site-utils" uri="http://www.newInstance.com/taglibs/site-utils" %> </td> <td width="16" align="left" valign="top"> </td> </tr> <!-- End main content --><!-- Begin footer section --> <tr> <td width="91" align="left" valign="top" bgcolor="#330066"> </td> <td align="left" valign="top"> </td> <td class="footer" align="left" valign="top"><div align="center"><br> © 2003 <a href="mailto:webmaster@newInstance.com">Brett McLaughlin</a><br> Last Updated: <site-utils:lastModified /> </div></td> <td align="left" valign="top"> </td> <td width="141" align="right" valign="top" bgcolor="#330066"> </td> </tr></table><!-- End footer section --> |
在前面几期中看了JSTL如何工作(参见“ 利用JSTL更新您的JSP页面”和“ 导入内容到您的Web站点”)之后,接下来该做什么您应该很清楚了:我们通过使用web.xml文件中的URI来引用这个标记库,为之分配一个前缀(来自TLD的 short-name 始终是最好的选择),然后就像使用任何其他JSP标记一样使用这个标记。最终得到的是一个简洁的、更好的JSP页面,这个JSP页面运行起来不比有 scriptlet 的时候差。vv
taglib简介的更多相关文章
- (转载)SPRINGMVC表单标签简介
SpringMVC表单标签简介 在使用SpringMVC的时候我们可以使用Spring封装的一系列表单标签,这些标签都可以访问到ModelMap中的内容.下面将对这些标签一一介绍. 在正式介绍Spri ...
- Struts2标签简介
Struts2标签简介 Struts2标签的优势 标签库简化了用户对标签的使用 结合OGNL使用,对于集合.对象的访问功能非常强大 提供可扩展的主题.模板支持,极大简化了视图页面的编写 不依赖任何表现 ...
- EL表达式简介
EL表达式简介 EL 全名为Expression Language.EL主要作用: 1.获取数据 EL表达式主要用于替换JSP页面中的脚本表达式,以从各种类型的web域 中检索java对象.获取数据. ...
- OGNL简介
OGNL 一:OGNL简介 OGNL的全称是Object Graph Navigation Language即对象导航语音.它是一个开源项目,工作在视图层,用来取代页面中的java脚本.简化数据 ...
- struts2学习(11)struts2验证框架1.验证简介、内置验证
一.Struts2验证简介: 二.struts2内置验证: 下面例子,需求是:为用户注册进行验证: com.cy.model.User.java: package com.cy.model; publ ...
- struts2学习(7)值栈简介与OGNL引入
一.值栈简介: 二.OGNL引入: com.cy.action.HelloAction.java: package com.cy.action; import java.util.Map; impor ...
- 转:SiteMesh简介
OS(OpenSymphony)的SiteMesh是一个用来在JSP中实现页面布局和装饰(layout and decoration)的框架组件,能够帮助网站开发人员较容易实现页面中动态内容和静态装饰 ...
- JSP(1) - JSP简介、原理、语法 - 小易Java笔记
1.JSP简介 (1)JSP的全称是Java Server Pages(运行在服务器端的页面),实际就是Servlet(学习JSP的关键就是时刻联想到Servlet) (2)JSP.Servlet各自 ...
- Spring Security 简介
本文引自:https://blog.csdn.net/xlecho/article/details/80026527 在 Web 应用开发中,安全一直是非常重要的一个方面.安全虽然属于应用的非功能性需 ...
随机推荐
- week5 0.1 安装materializecss
用ATOM打开项目 App是什么呢?就是App.js 我们将不需要的删掉 用一下materialize(类似bootstrap的东西) 官网https://materializecss.com/ 想用 ...
- (转).NET Core 使用 log4net
https://blog.csdn.net/liyazhen2011/article/details/83382221 1.安装log4net 建立.NET Core工程 - 右键 - 管理N ...
- 吴裕雄 21-MySQL 正则表达式
MySQL 正则表达式在前面的章节我们已经了解到MySQL可以通过 LIKE ...% 来进行模糊匹配.MySQL 同样也支持其他正则表达式的匹配, MySQL中使用 REGEXP 操作符来进行正则表 ...
- Kubernetes 本地仓库
1.Kubernetes本地私有仓库 Docker仓库主要用于存放Docker镜像,Docker仓库分为公共仓库和私有仓库,基于registry可以搭建本地私有仓库.使用私有仓库有如下优点: 1)节省 ...
- Java8给出一个时间段,计算该时间范围由哪些日期(天)和月份组成
1. 判断时间段是否合法: 2. 循环判断记录数是否大于0 3. 根据起始时间算出该月的第一天.最后一天和这个月有多少天: 4. 判断起始时间是否是该月第一天,如果是,再判断结束时间与该月最后一天的大 ...
- ssl 的jks 生成工具
https://www.myssl.cn/tools/merge-jks-cert.html 通过key 私钥 ,和公钥pem 生成jks
- float double
float : 单精度浮点数 double : 双精度浮点数 两者的主要区别如下: 01.在内存中占有的字节数不同 单精度浮点数在机内存占4个字节 双精度浮点数在机内存占8个字节 02.有效数字位数不 ...
- vue 高级属性父组件provide向子组件发送数据,子组件通过inject接收数据
以前父组件向子组件中传值是通过props传值,子组件不能更改父组件中的值,但是可以通过从父组件中获取的值定义给自己的data值,这里父组件可以通过provide向子组件传递自己组件中的data值,子组 ...
- Velocity Obstacle
[Velocity Obstacle] Two circular objects A,B, at time t(0), with velocity V(A),V(B). A represent the ...
- 最完整Android Studio插件整理 (转)
转自:http://blog.csdn.net/alpha58/article/details/62881144 现在Android的开发者基本上都使用android Studio进行开发(如果你还在 ...