JSP 最佳实践:为您的JSP标记创建自定义属性

自定义“Hello, world”
JSP 标记最常见的需求就是能够接受来自某个页面(或者页面作者)的数据,并响应该数据。标记 attributes 允许我们将这种功能性融入到自定义标记中。

举个非常简单的例子,比如典型的“Hello, world”应用程序。很容易想象实现这一 scriptlet 的功能性的自定义标记是什么样子,但是,对这个标记作一点点扩展如何?

在清单 1 中我们可以看到一个 JSP 页面片段,其中有一个典型的“Hello, world!”标记,但是这个标记包括了一个名为 name 的属性。

清单 1. 一个简单的 "Hello, world!" 标记

<p>
    <examples:hello name="Reader" />
</p>

name 属性为页面作者将数据提供给 hello 标记创造了空间,在这个例子中,所提供的数据是一个人的名称,应用程序将把它的消息转播给这个人。实际上,我们已经自定义了“Hello, world” —— 但我们是怎样进行定义的呢?清单 2 显示了用于实现 hello 标记的 Java 代码

清单 2. hello 标记的代码

package com.ibm.examples;

import java.io.IOException;
import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.*;

public class HelloTag extends TagSupport {

    // The "person" to say hello to
    private String name;

    // Accept the attribute data
    public void setName(String name) {
      this.name = name;
    }

    public int doEndTag() {
      try {
	  StringBuffer message = new StringBuffer("Hello, ");
	  message.append(name)
	         .append("!");
	  pageContext.getOut().println(message.toString());
	} catch (IOException ignored) { }
	return EVAL_PAGE;
    }

清单 2 中的代码对于它所做的事情非常简单。我们只是添加了一个 setXXX() 方法,其中 XXX 指的是该属性的名称,但正是由于这一添加,我们便已大大扩展了 hello 标记的功能性。现在,页面作者可以为特定用途设置自定义数据,该数据可以根据需要进行保存、操纵或者激活。doEndTag() 方法允许我们以任何方式使用标记数据。

现在,让讨论更深入一点,看看当我们添加一个属性到 lastModified 标记时会发生什么情况。

扩展 lastModified 标记
我们希望页面作者能够设置他们想要的输出格式(最后修改数据),而不是只有一种显示选择。我们将从后端开始,首先扩展 lastModifiedTag 类, 使其包括一个 java.text.SimpleDateFormat 以用于输出格式化,如清单 3 所示:

清单 3. 在 LastModifiedTag 类中使用 SimpleDateFormat

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 {

    private String format = "MMM d, yyyy";

    public int doEndTag() {
      try {
        HttpServletRequest request =
          (HttpServletRequest)pageContext.getRequest();
        String path = pageContext.getServletContext().getRealPath(
          request.getServletPath());
        File file = new File(path);

        <span class="boldcode">DateFormat formatter = new SimpleDateFormat(format);</span>

        pageContext.getOut().println(
          formatter.format(new Date(file.lastModified())));
      } catch (IOException ignored) { }
      return EVAL_PAGE;
    }
}

在清单 4 中,我们将新的格式化功能添加到 lastModified 标记中,这是通过添加一个属性办到的。注意,format 属性的值与清单 3 中新引入的 format 方法变量是联系在一起的。

清单 4. 处理新属性

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 {

    private String format = "MMM d, yyyy";

    public void setFormat(String format) {
      this.format = format;
    }

    public int doEndTag() {
      try {
        HttpServletRequest request = 
          (HttpServletRequest)pageContext.getRequest();
        String path = pageContext.getServletContext().getRealPath(
          request.getServletPath());
        File file = new File(path);

        DateFormat formatter = new SimpleDateFormat(format);

        pageContext.getOut().println(
          formatter.format(new Date(file.lastModified())));
      } catch (IOException ignored) { }
      return EVAL_PAGE;
    }
}

实现细节
format 属性允许页面作者按照自己的喜好设置日期/时间的输出格式。不过,在使用这个新属性之前,我们必须在 TLD 文件(这个文件应该是 WEB-INF/tlds 目录下的 site-utils.tld)中作一点修改,如清单 5 所示:

清单 5. 修改 TLD

<?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>
      <span class="boldcode"><attribute>
        <name>format</name>
      </attribute></span>
    </tag>
</taglib>

默认值
更新了 TLD 之后,我们应该可以开始使用新属性了,那么让我们来测试一下吧。重新启动 servlet 容器,以确保 servlet 容器接受了新的标记和 TLD 更改,然后连上带有 lastModified 标记的页面。

千真万确,时间戳出现了。但是我们可以看到,输出的格式与之前没什么两样。问题就在于没有添加新的 format 值,因此我们所看到的格式与老格式是一样的。这个小测试展示了为 format 属性添加默认值(在这个例子中,就是您马上要看到的那个格式)的重要性。

为自定义属性添加一个默认值是一种很好的思想,因为这使得页面作者在不想提供他们自己的值时可以省点力气。在某些情况下,页面作者可能会很高兴使用默认值;在其他一些情况下,他们可能需要花点时间来了解新的属性和格式,在这段时间内,暂时使用默认值是很有必要的。不管是 哪种情况,通过为标记添加自定义属性来创建选项,并为执行某种功能的页面提供默认的行为,这样做才是良好的编程习惯。

包装起来
当然,我们做这么多事情并不是漫无目的的!清单 6 显示了 footer.jsp ,这个文件来自原有的那个时间戳实例(参见 “The power of time stamps” ),不过这里为 format 属性提供了一个值:

清单 6. 使用 format 属性

<%@ 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>
          &copy; 2003 
          <a href="mailto:webmaster@newInstance.com">Brett McLaughlin</a><br>
          Last Updated: <site-utils:lastModified 
            <span class="boldcode">format="HH:mm a zz :: MM/dd/yyyy"/></span>
        </div></td>
          <td align="left" valign="top"> </td>
      <td width="141" align="right" valign="top" bgcolor="#330066"> </td>
    </tr>
</table>
<!-- End footer section -->

虽然我们完成了一个良好的开端,但我们还只是简要地描绘了关于处理自定义标记中的属性的一些表面的东西。在下一期的 JSP 最佳实践 中,我们将讨论一些更复杂的场景,这些场景都是您在创建自定义的、可扩展的时间戳标记时可能遇到的——例如错误处理和对不同时区的处理。同时,还将看到为不同类型的功能使用自定义属性的实践,到时候网上见。

参考资料

  • 还是JSP技术的初学者吗?那么请参见由 Brett McLaughlin 撰写的 JSP最佳实践 系列前面的几期

  • 您或许还想研究一下对遵从JSP规范的IDE的使用。那么下面有一些选择:

  • Noel Bergman 的 “JSP taglibs:设计带来更好的可用性”(developerWorks, 2001年12月)介绍了自定义标记库工具,这种工具允许创建JSTL

  • Jeff Wilson 的 “利用自定义标记控制您的 JSP 页面”(developerWorks, 2002年1月)是关于自定义标记库通信的入门读物。

  • 使用 JSP 和 JDBC 技术的动态的基于 Web 的数据访问”(developerWorks, 2001年9月) 演示了对于访问和操纵JSP页面中内容必不可少的一些技术。

  • Mark Kolb的 “JSTL 初级读物” (developerWorks, 2003年2月至5月)对 JSP 标准标记库(JSP Standard Tag Library)作了完整的介绍。

  • 要获得对JSP技术的指导性的介绍,请参见 Noel Bergman 的教程“JaveServer Pages 技术简介”(developerWorks, 2001年8月)。

  • 要获得JSP技术的细节,您最好的选择是阅读 JSP 规范说明书

  • Hans Bergsten 的JavaServer Pages (O'Reilly & Associates, 2002)是学习 JSP 技术时不可或缺的资料。

  • 参见developerWorks Java 技术教程页面 以获得完整的免费教程清单。

  • developerWorks Java 技术专区 您可以找到大量关于 Java 编程各个方面的文章(包括更多关于JSP技术的文章)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值