JavaScriptをサーバで動かす

JavaScriptをHTMLに組み込んでサーバ上で(PHPのように)動かせたらとても良いと思う。そして一番手っ取り早くそれを実現するのはMayaaを使う事だと思う。以下その準備とサンプル。


注意: 手っ取り早くJavaScriptを使うという目的のサンプルなので、S2StrutsなどでMayaaを使う用途としてはあんまり一般的な使い方ではないかも。

準備: Java5とTomcatMayaaをインストール

具体的な手順は以下参照。Mac OS Xの場合は最初から入っているjavaが使える(Java5なので。)


1-2. インストールしよう : Documentation - JavaServer Templates "Mayaa"


インストールと確認作業が終わるとwebappsの下にmayaaというディレクトリが出来ている。その下にJavaScript入りのHTMLファイルを置くとサーバ側で実行してくれるようになる。配置後は特に再起動等も不要。


例: sample.htmlを配置。
配置先: [TOMCATをインストールしたディレクトリ]/webapps/mayaa/sample.html
表示の為のURL: http://localhost:8080/mayaa/sample.html


サーバ側で動かすためにServletエンジンのTomcatJavaのライブラリ(Rhinoなど)を使用しているけど、Javaでプログラムを書く必要は基本的に無い。

サンプル1. 動的な文字列を表示する

HTML上で「${」と「}」で囲った部分がJavaScriptとして評価され、その値が表示される。


以下は、現在のサーバ上での日時を表示するサンプル。

sample_date.html

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html xmlns:m="http://mayaa.seasar.org">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>日付表示サンプル</title>
</head>
<body>
<h1>日付表示サンプル</h1>
現在の日付:${new Date().toLocaleString()}
</body>
</html>

出力結果:(http://localhost:8080/mayaa/sample_date.html)

日付表示サンプル

現在の日付:2007/12/16 15:29:37 JST

サンプル2. 繰り返し結果を表示する

繰り返し処理を行うサンプル。繰り返し処理にはforプロセッサを使用する。(リストの中身を繰り返し処理するforeachプロセッサもある。)


HTML中に<span m:inject="m:for" m:init="${ スクリプト1 }" m:test="${ スクリプト2 }" m:after="${ スクリプト3 }">〜</span>と記述すると、「${」と「}」で囲った部分がJavaScriptとして実行され、実行結果に従って〜の部分が繰り返し表示される。(スクリプト1: 開始時に実行、スクリプト2: ループ毎に最初に実行され、真ならループ継続、スクリプト3: ループ毎に最後に実行される。)


以下は、1~10までの二乗数を表示するサンプル。


sample_for.html

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html xmlns:m="http://mayaa.seasar.org">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>繰り返しサンプル</title>
</head>
<body>
<h1>繰り返しサンプル</h1>
<span m:inject="m:for" m:init="${ var i = 1; }" m:test="${ i &lt;= 10 }" m:after="${ i += 1 }" >
    ${i}^2 = ${i*i}<br>
</span>
</body>
</html>

出力結果:(http://localhost:8080/mayaa/sample_for.html)

繰り返しサンプル

1^2 = 1
2^2 = 4
3^2 = 9
4^2 = 16
5^2 = 25
6^2 = 36
7^2 = 49
8^2 = 64
9^2 = 81
10^2 = 100

m:forのm:initでvarで宣言した変数iを繰り返しの内部で使用している。スクリプト中の「&<>"'」などはエスケープする必要がある("i <= 10" → "i &lt;= 10")

サンプル3. URLパラメータの値を取得する

リクエストの値を取得するには、定義済みオブジェクトparamを使用する。JavaScript内で「param.パラメータ名」と記述すれば、URLパラメータやformで渡した値を取得出来る。


条件によって表示を切り替えたい時は、ifプロセッサを使用する。HTML中に<span m:inject="m:if" m:test="${ スクリプト }">〜</span>と記述すると、「${」と「}」で囲った部分がJavaScriptとして評価され、条件が満たされる場合に<span>タグの内部が表示される。


以下は、名前を入力すると挨拶するサンプル。

sample_param.html

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html xmlns:m="http://mayaa.seasar.org">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>パラメータサンプル</title>
</head>
<body>
<h1>パラメータ表示サンプル</h1>
<span m:inject="m:if" m:test="${param.yourname != null}">
   こんにちは、${param.yourname}さん
</span>
<span m:inject="m:if" m:test="${param.yourname == null}">
   <form action="/mayaa/sample_param.html" method="POST">
   名前を入力してください: <input type="text" name="yourname">
   </form>
</span>
</body>
</html>

出力結果:(http://localhost:8080/mayaa/sample_param.html)

パラメータ表示サンプル

名前を入力してください: [      ]

テラゾーと入力

パラメータ表示サンプル

こんにちは、テラゾーさん

GETだと文字化けする場合についての対処は後述

サンプル4. Javaのクラスを利用する

JavaScript内からJavaのクラスを利用出来る。Javaのクラスパッケージ名の前にPackages.を付けることでアクセスできるようになる。


以下は、RSSのfeed URLを指定するとサーバサイドで内容を取得して表示するサンプル
sample_java.html

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html xmlns:m="http://mayaa.seasar.org">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Java実行サンプル</title>
</head>
<body>
<h1>Java実行サンプル</h1>
<span m:inject="m:if" m:test="${param.url != null}">

${
       var dbfactory = Packages.javax.xml.parsers.DocumentBuilderFactory.newInstance();
       var builder = dbfactory.newDocumentBuilder();
       var doc = builder.parse(param.url);
       var XPathAPI = Packages.com.sun.org.apache.xpath.internal.XPathAPI;
       var items = XPathAPI.selectNodeList(doc, '/RDF/item');
}
     ${items.getLength()}件取得<br>
     <table border="1"> 
        <tr>
         <th>タイトル</th>
         <th>内容</th>
    </tr>
     <span m:inject="m:for" m:init="${ var i = 0, c = items.getLength(); }"
                 m:test="${ i &lt; c }" m:after="${ i += 1 }" >
${
   var item = items.item(i);
   var titleNode = XPathAPI.selectSingleNode(item, 'title/text()');
   var title = titleNode != null ? titleNode.getNodeValue() : '';
   var linkNode = XPathAPI.selectSingleNode(item, 'link/text()');
   var link = linkNode != null ? linkNode.getNodeValue() : '';
   var descNode = XPathAPI.selectSingleNode(item, 'description/text()');
   var desc = descNode != null ? descNode.getNodeValue() : '';
}
         <tr>
              <td><a href="${link}">${title}</a></td>
              <td>${desc}</td>
          </tr>
     </span>
     </table>
</span>
<span m:inject="m:if" m:test="${param.url == null}">
   <form action="/mayaa/sample_java.html" method="POST">
   URLを入力してください: <input type="text" name="url">
   </form>
</span>
</body>
</html>

出力結果:(http://localhost:8080/mayaa/sample_java.html)

Java実行サンプル

URLを入力してください: [      ]

http://b.hatena.ne.jp/entrylist?mode=rss&sort=hot&threshold=2を入力

Java実行サンプル

30件取得
........

GETで文字化けする場合のworkaround

GETだと文字化けするのはServletの仕様です。回避するにはTomcatの設定ファイルを変更する。conf/server.xmlのConnector定義にuseBodyEncodingForURI="true"を追加する。(cf: google:useBodyEncodingForURI)

テンプレートの置き場所を変えたい場合

webapps/mayaa/WEB-INFの下にclasses/META-INF/というディレクトリを作成し、以下の設定ファイルを配置

[TOMCATをインストールしたディレクトリ]/webapps/mayaa/WEB-INF/classes/META-INF/org.seasar.mayaa.source.PageSourceFactory

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE factory
    PUBLIC "-//The Seasar Foundation//DTD Mayaa Factory 1.0//EN"
    "http://mayaa.seasar.org/dtd/mayaa-factory_1_0.dtd">
<factory>
    <parameter name="absolutePath" value="/Users/terazzo/Labs/mayaa/html/"/>
</factory>

上は所定のディレクトリの他に、"/Users/terazzo/Labs/mayaa/html/"の下も検索対象に含めるという例。複数記述する事も可能。

テンプレートの文字コードを変えたい場合

例:Shift_JISに変更


HTMLファイルのエンコードおよび内部のMETAタグのContent-Typeのcharsetを変える。


それだけだと入力値が化ける場合、webapps/mayaa/WEB-INFの下にclasses/META-INF/というディレクトリを作成し、以下の設定ファイルを配置


[TOMCATをインストールしたディレクトリ]/webapps/mayaa/WEB-INF/classes/META-INF/org.seasar.mayaa.provider.ServiceProvider

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE provider
    PUBLIC "-//The Seasar Foundation//DTD Mayaa Provider 1.0//EN"
    "http://mayaa.seasar.org/dtd/mayaa-provider_1_0.dtd">
<provider>
    <engine>
        <parameter name="requestCharacterEncoding" value="Shift_JIS"/>
    </engine>
</provider>