これは Mayaa Advent Calendar 2015 の2日目です。昨日は「Mayaaとの出会い」でした。
JSPで書かれたシステムのMayaaへの移行
さて、前回、MayaaはJSPと同じレイヤーで動いているから、JSPでデザインが描かれているシステムは簡単に移行できると書きました。
今回は実例を元に、その様子を解説しようと思います。
何でも良いので、JSPをビューに使っているMVCフレームワークがあるとします。
例えばこれは、SAStrutsのコード例です。
import org.seasar.struts.annotation.Execute;
public class IndexAction {
@Execute(validator = false)
public String index() {
return "index.jsp";
}
}
今から新規にStrutsのコードを書くことはないと思いますが、StrutsライクなMVCフレームワークなら何でも同じようにできると思います。自分の使っているフレームワークに脳内変換してください。
(後日、最近のメジャーなフレームワークとMayaaを連携する例を書きたいと思います。)
MayaaServletをweb.xmlに登録
もし使っているのが、レガシーServletでWeb.xmlを書いているなら、次の設定を書き加えましょう。
<servlet>
<servlet-name>MayaaServlet</servlet-name>
<servlet-class>org.seasar.mayaa.impl.MayaaServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>MayaaServlet</servlet-name>
<url-pattern>*.xhtml</url-pattern>
</servlet-mapping>
<url-pattern>*.xhtml</url-pattern>
という部分は、標準のMayaaの流儀ではないかもしれません。しかし、多くのWebシステムは既にhtmlをマッピングしているのではないでしょうか?私の現場もそうでした。そこで私はxhtmlファイルをMayaaのテンプレートとして設定しました。その結果、テンプレートファイルは正しいxhtml書式で書く文化がチーム内に浸透したため、良い判断だったと思います。
あとは、Java側でフォワードしている部分のJSPの部分を
import org.seasar.struts.annotation.Execute;
public class IndexAction {
@Execute(validator = false)
public String index() {
return "index.xhtml";
}
}
のように書き換えましょう。後はindex.jspの代わりにindex.xhtmlを置くだけです。
この方法の良い所は、JSPとMayaaを同居できることです。移行作業中は、古いJSPのテンプレートも残すことが出来ます。ただし、JSPにMayaa、MayaaにJSPをインクルードすることは出来ませんので、そのあたりはご注意ください。
テンプレートを書く
次にテンプレートを書きましょう。例えばJSPがあったとします。ちなみに、僕はJSPのtaglibが嫌いで、ほとんど使いません。なので、MayaaにもJSPのtaglibをサポートする機能を持っていますが、全然使ったことがありませんので、公式のマニュアルを参照してください(笑)
ちなみに、EL式も使いません。何か文句ありますか?
<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<%@ page import="info.susumuis.sample.ViewHelper" %>
<%@ page import="info.susumuis.sample.SampleBean" %>
<% SampleBean bean = (SampleBean) request.getAttribute("bean"); %>
<html>
<head>
<title ><%= ViewHelper.escape(bean.getTitle()) %> </title>
</head>
<body>
<%= ViewHelper.escape(bean.getMessage()) %>
</body>
</html>
ViewHelper.escapeは、HTMLエスケープをする共通メソッドだと思ってください。
これをMayaaに移植する最も手っ取り早い方法は、JSPを実行した結果のHTMLをいきなり貼り付けてしまうことです。
<html>
<head>
<title >たいとる</title>
</head>
<body>
ハローワールド
</body>
</html>
このままでは文字化けしてしまいますので、metaタグで文字コードを指定します。Mayaaはmetaタグでコンテントタイプを設定しておくと、勝手にヘッダを書き換えてくれますので活用しましょう。
このとき、注意として、HTML5の、<meta charset="">
を使わないことです。使っても良いのですが、text/html;
の部分の情報が抜けてしまうので、以下のように古い書き方を使うことをおすすめします。
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
また、JSP特有の空行は消していきましょう。また、拡張子をxhtmlファイルにしてしまったので、ブラウザでプレビューできるようにxmlns指定を書きます。本当は先頭行に宣言が必要ですがこれはサボっても表示できるようです。(この辺りは、MayaaがContent-Typeを見て最終的に適切な出力に調整してくれます)
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title >たいとる</title>
</head>
<body>
ハローワールド
</body>
</html>
このテンプレートはWebブラウザでそのまま開くことが出来るはずです。
これで、サーバーで実行するのと同じ出力を得ることができますね。
え、動的な部分が固定されてしまっている?その通りです。しかし、Mayaaのページ作りの流儀としてはこれでよいのです。この後の説明を読めば分かります。
動的部分を実装する
元のコードはSampleBeanから、タイトルとメッセージを取得していましたね。Mayaaでは動的な出力を実現するために、m:idというものを使います。
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:m="http://mayaa.seasar.org">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title m:id="TITLE_TAG">たいとる</title>
</head>
<body>
<span m:id="MESSAGE_HERE">ハローワールド</span>
</body>
</html>
htmlタグに名前空間xmlns:m
を追加しています。
m以外を指定しても動きますが、普通はm:に割り当てます。"m:id"は「エム・アイ・ディー」と読みます。Mayaaの世界では非常に多用する単語なので、覚えましょう。
動的にしたいタグにm:idを加えていきます。もともとタグがなかったところはspanタグで補います。
ところで、Mayaaは非常に柔軟ですが、自由に使い過ぎると、デザイナーさんとの連携をスムーズにできません。お互いにある程度ルールを定めるべきです。そこで、僕はm:idは次の4種類に限定しています。
- _HERE
- その場所に文字列を出力する
- _TAG
- そのタグの属性を変化させたり要素を足したりする
- IF_
- そのタグ及びその子要素が特定の条件にもとづいて消える
- LOOP_
- そのタグ及びその子要素を特定の条件に基づいて繰り返す
m:idを発行するときは、出来る限り、HTMLとしてvalidになるように心がけましょう。
例えば、tableタグの中に、divタグを入れたり、titleタグの中にspanタグを入れるのは無しです。そのようなことをすると、Mayaaの良さを喪失してしまうので気をつけてください。
このままページを出力してみましょう。
ローカルでそのままダブルクリックしてブラウザに表示させても、サーバーで実行させても相変わらず表示は同じです。
mayaaファイルを書く
<m:mayaa xmlns:m="http://mayaa.seasar.org">
<m:beforeRender>
var bean = request.bean;
</m:beforeRender>
<!-- タイトルタグです -->
<m:echo m:id="TITLE_TAG">
<m:write value="${bean.getTitle()}" />
</m:echo>
<!-- メッセージを出力します -->
<m:write m:id="MESSAGE_HERE" value="${bean.getMessage()}" />
</m:mayaa>
このようにm:idの動作を記述していきます。実は命名規則を定めたので、これらの書き方はある程度定型化できます。Mayaaはm:idだけ定義しておいて、mayaaファイルに実装していないとログにエラーメッセージを吐くので、エラーメッセージから雛形を出力するマクロを作るのも良いでしょう。僕も過去に作りました。
Mayaaファイルを命名規則から一括作成するEmEditorマクロ
本当は、標準のm:write, m:ifなどは使い勝手が悪いので、自分でプロセッサーを作ることをおすすめします。これについては、後日ご紹介します。
もう一つ、JSPのコードからViewHelper.escapeの記述が消えました。Mayaaでは、出力をエスケープするのがデフォルトの動作です。なので、「必要に応じてエスケープを解除する」というスタイルになります。昨今脆弱性が対策は必須となっていますので、この流儀は大変便利です。
このようにして1ページの移行が完了しました。あとは、全てのページを同じように移行していくことです。
しかし、実際のページはもっと複雑で、難しいことも多いと思います。次回から、個別にハマリポイントとその回避方法を紹介して行こうと思います。