Railsのcontent_forをJSPで実装してみた


2011年 03月 14日

SAStrutsで複雑なレイアウトのHTMLを組み立てるときtiles:insert、tiles:putを利用していました。しかし次の問題点からtiles:putの利用を取りやめてしまいました。

  1. tiles:putにはaddが存在しない。
  2. tiles:putでキャプチャした文字列は、2段目以降のテンプレートで参照できない。

そこでこれらの問題を解決するために、Railsのcontent_forに似せたカスタムタグライブラリtags-captureを作りました。

依存関係

pom.xmlにリポジトリを設定します。

<repository>
  <id>troter.jp</id>
  <name>troter.jp release repository</name>
  <url>http://troter.jp/maven2/release</url>
</repository>

依存関係は次の通りです。

<dependency>
  <groupId>jp.troter</groupId>
  <artifactId>tags-capture</artifactId>
  <version>1.0.0</version>
</dependency>

taglibディレクティブで宣言します

<%@taglib prefix="capture" uri="http://troter.jp/tags-capture"%>

利用方法

<%@page contentType="text/html;charset=UTF-8" pageEncoding="UTF-8" trimDirectiveWhitespaces="true" %>
<%@taglib prefix="capture" uri="http://troter.jp/tags-capture"%>

<%-- 基本的な例  --%>
<capture:contentFor name="title" value="TIM Labs" />

<%-- value属性だけで無くbodyでも指定できます。 --%>
<capture:contentFor name="javascript">
  alert("middle");
</capture:contentFor>

<%--
 | 同じ名前で複数キャプチャした場合は連結されます。
 |%-->
<%-- 通常は末尾に追加されます --%>
<capture:contentFor name="javascript">
  alert("last");
</capture:contentFor>

<%-- addFirst属性をtrueにすると先頭に追加されます --%>
<capture:contentFor name="javascript" addFirst="true">
  alert("first");
</capture:contentFor>

<%-- 同じ文字列は追加されません --%>
<capture:contentFor name="javascript">
  alert("first");
</capture:contentFor>

<%-- duplicate属性をtrueにすると追加できます --%>
<capture:contentFor name="javascript" duplicate="true">
  alert("last");
</capture:contentFor>

<%-- キャプチャした文字列はcapture:yieldで出力できます。 --%>
<html>
<head>
  <title><capture:yield name="title" /></title>
  <script type="text/javascript">
    <capture:yield name="javascript" />
  </script>
</head>
<body>
 <p> alert </p>
</body>
</html>

この例では次のようなHTMLが出力されます。

<html>
<head>
  <title>TIM Labs</title>
  <script type="text/javascript">

  alert("first");

  alert("middle");

  alert("last");

  alert("last");
</script>
</head>
<body>
 <p> alert </p>
</body>
</html>

実装

capture:contentForタグのname属性に_contentForというプレフィックスをつけてリクエストスコープに保存しているだけです。

利点

  • リクエストスコープに保存する簡単実装のためtilesの2段目移行のテンプレートでもキャプチャした文字列が参照できます。
  • content_forを使えばタグファイル内のJSPと密接に絡んだJavascriptをタグファイル内に記述する事も可能になります。
  • JSPを直接利用する(テンプレートエンジンを利用しない)開発ではそれなりに便利に使えると思います。

欠点

  • 結構何でもできるため、利用するケースを制限しないとひどい事になったりします。
  • キャプチャのリセットをサポートしていません。