技术开发 频道

精通 Grails: 用 Groovy 服务器页面(GSP)改变视图

  自定义标记库

  虽然标准 Grails 标记很有帮助,但是最终会遇到需要自定义标记的情况。许多资深 Java 开发人员(包括我自己)公开表示,“自定义 TagLib 是合适的架构性解决方案。”,然后却偷偷地编写 scriptlet,以为别人看不到。编写自定义 JSP TagLib 需要的工作太多,所以难以抵抗 scriptlet 的诱惑。scriptlet 并不是正确的方法,但不幸的是,它是一种容易实现的方法。

  Scriptlet 破坏了 HTML 基于标记的范式,将原始代码直接引入视图。错误的并不是代码本身,而是它们缺少封装和重用的潜力。重用 Scriptlet 的惟一方式就是 “复制-粘贴”。这导致 bug、代码膨胀,并严重违背了 DRY 原则。更不用说 Scriptlet 在可测试性方面的匮乏了。

  这就是说,我必须坦白,随着开发期限越来越紧迫,我写的 JSP scriptlet 的比例也相当大。JPS 标准标记库(JSP Standard Tag Library,JSTL)在这方面帮助了我很多,但是编写我自己的自定义 JSP 标记则完全是另一回事。在我用 Java 代码编写自定义 JSP 标记、编译标记,并将大量时间浪费在将标记库描述符(Tag Library Descriptor,TLD)设置为正确的格式和位置时,我已经完全忘记了当初编写这个标记的理由是什么。编写测试来验证我的新 JSP 标记是否正确也同样麻烦 — 只能说我的出发点是好的。

  对比之下,用 Grails 编写自定义 TagLibs 简直就是举手之劳。Grails 框架使得做正确的事(包括编写测试)变得很容易。例如,我经常需要在 Web 页面底部加上标准的版权声明。版权声明应该是这样的: © 2002 - 2008, FakeCo Inc. All Rights Reserved.。问题在于,我希望第二个年份总是当前的年份。清单 6 显示了用 scriptlet 如何完成这个任务:

  清单 6. 用 scriptlet 完成的版权声明

<div id="copyright">
&copy; 2002 - ${Calendar.getInstance().get(Calendar.YEAR)},
    FakeCo Inc. All Rights Reserved.
</div>

  既然知道了如何处理当前年份,那么下面就要创建一个执行同样任务的自定义标记。请输入 grails create-tag-lib Date,这会创建两个文件:grails-app/taglib/DateTagLib.groovy(TagLib)和 grails-app/test/integration/DateTagLibTests.groovy(测试)。将清单 7 中的代码添加到 DateTagLib.groovy:

  清单 7.简单的自定义 Grails 标记

class DateTagLib {
  def thisYear
= {
    out
<< Calendar.getInstance().get(Calendar.YEAR)
  }
}

  清单 7 创建一个 标记。可以看到,年份直接写入输出流。清单 8 显示了新标记的效用:

  清单 8.使用自定义标记的版权声明

<div id="copyright">
&copy; 2002 - <thisYear />, FakeCo Inc. All Rights Reserved.
</div>

  您可能以为这就完成了。非常抱歉,这只完成了一半。

0
相关文章