Velocity

Velocityについて

コミュニティ

ドキュメント

ツール

比較

日本語訳について

生成?

JSPでの利点として、既存の .jsp ページを速度と効率上の理由からコンパイルして Servletにできることが喧伝されています。 それがどういうことかと言えば、まず .jspページを解析し、 このページの最後に出てくるようなごちゃごちゃしたコードにした上で、 その Servletが、javacやあなたの好きな Java コンパイラ (例えば Jikes) で .class ファイルにコンパイルされて、Servlet エンジンにロードされます。 ふぅ・・・これを説明するだけで頭痛がしてきましたが、いかがですか?

要するに、今のところ、JSP を使うには多段階のプロセスが必要だということです。 JSP の作者は、ユーザがプロセスの存在さえ気がつかないぐらい、 こうしたプロセスのあれこれを裏に隠すのに成功しています。 ユーザは好きなエディタで .jsp ページを編集し、ブラウザを使って、 ページを .class ファイルに変換するプロセスを開始する URI で、 ページを呼び出すだけです。

生成された .jsp テンプレートにはいくつかの根本的な問題があります。 まずは、そのクラス名についてです。つまり、クラスローダーの問題に対処するために、 エンジンは(コンパイルを行うたびに)一意な名前を生成する必要があるということです。 したがって、誰かが .jsp ページを修正するたびに、 新しいファイルがディスクのテンポラリディレクトリに作成されます。 残念なことに、誰かがそれを掃除しない限り、 このディレクトリのサイズは増えつづけることになります。 ひょっとしたらエンジンが代わりに削除してくれるかもしれませんが、そうすると、 削除してはならないファイルを間違って削除してしまうかもしれません。

要するに、編集→変換→コンパイル→ロード→実行という全体のプロセスは、 実際不要ですし、何より設計として良くないということです。 それに対して、Velocity は単にテンプレートをロードし、一度だけ解析し、 何度でも再利用できるように、テンプレートを抽象構文木(AST)表現でメモリに格納します。 プロセスは、単に編集→解析→実行と、単純です。 利点としては、Velocity テンプレートを使うと非常に処理が速くなり、 javacコンパイラとテンポラリディレクトリの間を行ったり来たりする必要がなくなることです。 Velocityでは、テンプレートを変更する際も、既存の蓄積されたテンプレートが、 新たに解析されたバージョンと置き換わるだけです。

テンプレートを使う Velocity のアプローチのもう一つの利点は 実際のテンプレートデータをどこにでも格納できることです。 格納場所としてはデータベースやリモートURIも含まれます。 設定可能なテンプレートローダを使用することにより、 何でもできるテンプレートローダを作成することが可能です。

Turbine がなくても、Velocity でエラー処理を行う方法がいくつかあります。 StrutsとTurbineのようなフレームワークの便利なところは、 エラー処理を適切に行えることです。 しかし、Struts は JSP を基礎に置いているので、 JSP に関する問題をそのまま引き継いでいます。 次の章では、これに関してさらに詳細に説明します。

後述される設計の問題の中でも決定的なのは、 JSP ページは Exception しか捕えられないことです。 もし、JSP ページが OutOfMemoryError といった他の例外を投げたらどうなるでしょうか? ここでの問題は、OutOfMemoryError が (Exception ではなく) Throwable ベースにしているということです。 したがって、JSP ページだけでこの例外を捕えるのは、ずっと難しいです。 将来のバージョンの JSP 仕様・実装では、これに関しては改善される予定です。

この格好のは、 NASA (数10億ドルの機器を天国に送り出しています) の友人が提供してくれたもので、 JSP でのエラー処理の改善がなぜ必要か、ということに関する完璧な例です。

バッファリングはもう一つの大きな問題です。なぜなら、 絶えず出力ストリームに書くのはあまり効率的でないからです。

<%@ page buffer="12kb" %>
<%@ page autoFlush="true" %>

この例では、出力を 12kb だけバッファリングし、ページを autoFlush するように JSP に命令します。Struts と JSP の組み合わせでは、JSP テンプレートで View の部分を提供することによって、MVC (Model-View-Controller) モデルを実装しています。 上記のタグは MVC モデルのどこに属していると思いますか? ご想像の通り、ここ [View] はこれらのタグを使うべきところではありません。

この問題に対する Velocity でのアプローチは、 開発者がテンプレート処理エンジンにストリームを渡すというものです。 ドキュメント生成の途中で例外が投げられたら、例外を捕えて処理できます。また、 バッファリングについてはパーサに対し適切にバッファされたストリームを渡すことで 対応できます。この場合も、エラーが発生したら、 その出力の代わりに別のストリームを使うこともできます。

Tomcat 3.3 m2 で生成された中間コードの例を以下に示します。

package jsp;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.*;

public class helloworld_1 extends org.apache.jasper.runtime.HttpJspBase {

    static {
    }
    public helloworld_1( ) {
    }

    private static boolean _jspx_inited = false;

    public final void _jspx_init() throws org.apache.jasper.JasperException {
    }

    public void _jspService(HttpServletRequest request, HttpServletResponse  response)
        throws java.io.IOException, ServletException {

        JspFactory _jspxFactory = null;
        PageContext pageContext = null;
        HttpSession session = null;
        ServletContext application = null;
        ServletConfig config = null;
        JspWriter out = null;
        Object page = this;
        String  _value = null;
        try {

            if (_jspx_inited == false) {
                _jspx_init();
                _jspx_inited = true;
            }
            _jspxFactory = JspFactory.getDefaultFactory();
            response.setContentType("text/html;charset=8859_1");
            pageContext = _jspxFactory.getPageContext(this, request, response,
			"", true, 8192, true);

            application = pageContext.getServletContext();
            config = pageContext.getServletConfig();
            session = pageContext.getSession();
            out = pageContext.getOut();

            out.write("<html>\r\n<head><title>Hello</title></head>\r\n<body>\r\n<h1>\r\n");
            if (request.getParameter("name") == null) 
              out.write("\r\n          Hello World\r\n");
            else 
              out.write("\r\n          Hello, ");
            request.getParameter("name"); 
              out.write("\r\n</h1>\r\n</body></html>\r\n");

        } catch (Exception ex) {
            if (out != null && out.getBufferSize() != 0)
                out.clearBuffer();
            if (pageContext != null) pageContext.handlePageException(ex);
        } finally {
            if (out instanceof org.apache.jasper.runtime.JspWriterImpl) { 
                ((org.apache.jasper.runtime.JspWriterImpl)out).flushBuffer();
            }
            if (_jspxFactory != null) _jspxFactory.releasePageContext(pageContext);
        }
    }
}

[どちらを選ぶかは] あなたが判断してください。

[ Saying Hello <- 前 | 次 -> エラーの扱い ]



このドキュメントは、 熊坂祐二 、 高橋達男 、 羽生田恒永 が訳しました。
コメントがある場合は、 report@jajakarta.org までお願いします。
オリジナル英文 Copyright © 1999-2005, The Apache Software Foundation