2011年12月10日土曜日

Play framework - テンプレートで独自のJavaメソッドを使う

Play! framework Advent Calendar 2011 jp #play_jaの10日目の記事です。

最近、Play!のチュートリアル(yabe)の復習として、簡単な掲示板を作っていました。
書き込まれたURLのリンクくらいは付けたいなーと思い、テンプレートに独自メソッドを追加したいと思ったのですが、これってチュートリアルの範囲外でしたね。

というわけで今回は、HTMLとして出力する文字列中のURLにリンクを張るメソッドを追加してみます。
主にテンプレートに着目した内容となっています。

※ソースコードはplay-1.2.4(最新版)で動作確認しています。

今回紹介するのは、入力値を以下のように編集して出力するだけです。
  1. エスケープする。
  2. URLにリンクを張る。
  3. 改行を<br/>に置換する。
 掲示板に書き込まれる文字列はこんな感じ。

こんにちは、Play!
http://example.com/
<strong>タグ</strong>

入力値をモデルのPost.contentから取得し、ただエスケープして出力する時は、テンプレートの方にこんな感じで書きましたね。

<p>${post.content}</p>

もしくはescape()を明記して

<p>${post.content.escape()}</p>

結果はこんな感じ。

<p>こんにちは、Play!
http://example.com/
&lt;strong&gt;タグ&lt;/strong&gt;</p>

後は、リンクを張るメソッドと改行を<br/>に置換するメソッドを追加します。

 <p>${post.content.escape().toString().urlLink().nl2br().raw()}</p>

urlLink()がこれから追加する独自メソッド。nl2brはplay標準です。最後の.raw()は「エスケープしないで出力する」と明記する意味で付けています。
escape().toString()としているのは、escape()の結果をそのまま受け取れなかったためです。もしかすると別のやり方があるのかも。

最後に、urlLinkメソッドを追加します。
play.templates.JavaExtensionsを継承して、urlLinkメソッドを書くだけです。

package ext;

import play.templates.*;

public class MyExtensions extends JavaExtensions {
    public static String urlLink(String str) {
        return str.replaceAll("(http://|https://){1}[\\w\\.\\-/:]+",
                "<a href='$0'>$0</a>");
    }
}

Play!を開発モードで起動していれば、このクラスも自動的にロードされます。
実行してみます。

<p>こんにちは、Play!<br/><a href='http://example.com/'>http://example.com/</a><br/>&lt;strong&gt;タグ&lt;/strong&gt;</p>

期待する結果が得られました!
長々と書きましたが、要はJavaExtensionsクラスを継承したクラスにメソッドを追加するだけですね。

お読み頂きありがとうございました。

明日、11日目は @katzchang さんです。お楽しみに!

2 件のコメント:

  1. こんにちは。ソース拝見させていただきました。
    結果良さそうですね!

    僭越ながらちょっとだけコメントします。

    public static String urlLink(String str) {
    return str.replaceAll("(http://|https://){1}[\\w\\.\\-/:]+",
    "(置換後の文字列)");
    }

    の箇所はString.replaceAll だと、第一引数の正規表現が毎回Compileされてしまうので、正規表現が固定文字列だったら下のようにCompile済のPatternをfieldに持って使い回すほうがPerformanceがよくなるのでおすすめですよ。

    private static final Pattern URL_PATTERN = Pattern.compile("(http://|https://){1}[\\w\\.\\-/:]+");
    public static String urlLink(String str) {
    return URL_PATTERN.matcher(str).replaceAll("(置換後の文字列)");
    }

    返信削除
  2. >>hagikuratakeshiさん
    こんにちは!
    少し自分の環境ではかってみたら、100万回の実行時間が70%に縮まりました。
    これは良いですね。
    ありがとうございます!

    返信削除