将 scriptlet 转换成自定义标记以获得更好的 JSP 代码
Scriptlet 对于快而杂( fast-and-dirty)的编码来说是一种不错的选择, 但是从长远来看, 您需要为您的 JSP 页面选择一种不那么杂乱的解决方案。在本 期的 JSP 最佳实践 中,Brett McLaughlin 向您展示了如何将 scriptlet 转化成 JSP 自定义标记, 然后将其用于 您的 JSP 开发中。 在 JSP 最佳实践的上一期,您学习了一种基于 scriptlet 的技术,这种技术被用来将上次 修改的时间戳添加到 JavaServer Page(JSP)文件 中。不幸的是,比起它所提供的短期利 益,scriptlet 会将更多的长期复杂性引入到您的页面中来。这些 scriptlet 会用 Java 代 码将各种类型 的
HTML 混杂在一起, 从而使得
程序的调试和设计极其错综复杂。 scriptlet 不能重用, 这常常导致开发者不得不在 JSP 页面之间进行复制-粘贴操 作, 进而导致同一段 代码出现多个版本。而且,scriptlet 还加大了错误处理的难度,因为 JSP 没有提供干净利 落的方式来
报告脚本错误。
因此,这次我们将
设计一种新的解决
方案。在本期的 JSP 最佳实践中,您将
学习一些基础知 识, 主要是关于如何将 scriptlet 转换成自定义标记, 并对其进行设置以便在您的 JSP 开发 项目中使用。
为什么使用 taglib? 所 谓标记库(tag library),是指由在 JSP 页面中使用的标记所组成的库。JSP 容器推出 时带有一个小型的、 默认的标记库。 而自定义标记库是人们 为了某种特定的用途或者目的, 将一些标记放到一起而形成的一种库。 在一个团队中协同工作的开发者们可能会为各自的项 目创建一些非常特定化的自定义标记库, 同时也会创建一个通用自定义标记库,以供当前 使用。
JSP 标记替代了 scriptlet,并缓解了由 scriptlet 所招致的所有令人头痛的事情。例如, 您可以看到这样的标记:
或者这样的标记:
每个标记都包含了指向一个
Java 类的引用,但是类中的代码仍然在它该在的地方:在标签 之外,一个编译好的类文件之中。
从 scriptlet 到标记 创建一个自定义标记的第一步就是决定您想怎样使用它, 如何称呼它, 以及它允许使用或者 需要什么属性(如果有的话)。对于时间戳标记,我们所需要的很简单:只要一个能够输出 一个页面的最后修改数据的简单标记。
因为不需要属性,这个标记看上去就是这个样子:
这个标记的名称和前缀是一样的:都是 site-utils。元素的内容是空的,这意味着该元素 中不允许有子元素存在。定义了这个标记之后,接下来的一步就是实现它的行为。
实现行为 实现标记行为的第一步是将 scr
iptlet 代码从原先所在的地方移到一个 Java 类 (LastModifiedTag)中,如清单 1 所示:
清单 1. 创建一个时间戳标记
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; }
}
这 个方法中的代码看上去比较熟悉; 实质上, 它正是我们在先前用到的相同的时间戳代码。 由于不需要用户输入,而且该标记也没有属性或者嵌入的内容,我们惟一需 要关心的一