なんでもつくってみようとする・Jythonサーブレット

 Jythonの埋め込み(Embedding)機能を使うと、 JavaのプログラムからPythonのスクリプトが実行できます。 ということは、Javaのプログラムがサーブレットになって、 PythonのスクリプトがHTMLを出力するようになれば、 Jythonサーブレットの出来上がり! 実際、そのようにして、PythonのスクリプトをHTML文書に埋め込んでJSPならぬPSP、 グレート・ザ・Python Server Pagesが作られたこともあります。 (JythonがJPythonと呼ばれていた頃のページ。 今はどうなっているかは調査中です…)
 ここでは、PSPもどきまではいかないまでも、 サーブレットコンテナが動いているWebサーバ上の任意のPythonスクリプトを Jythonで実行してしまう、Jythonサーブレットを作ってみたのでご紹介します。

package oppadmin;

import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
import java.net.URL;

import org.python.util.PythonInterpreter;
import org.python.core.*;

public class SimpleJythonServlet extends HttpServlet {
  protected PythonInterpreter interp;

  public void init(ServletConfig config) throws ServletException {
    super.init(config);
    interp = new PythonInterpreter();
  }

  public void doGet(HttpServletRequest request,
                    HttpServletResponse response)
    throws ServletException, IOException {

    response.setContentType("text/html; charset=Shift_JIS");

    PrintWriter out = response.getWriter();
    // インタープリタの標準出力をJSPのWriterに変更します。
    interp.setOut(out);

    String svPath   = request.getServletPath();
    String realPath = getServletContext().getRealPath(svPath);

    try {
      interp.execfile(realPath);
    } catch (Exception e) {
      System.err.println("エラー:" + e.toString());
      out.println("<h1><font color=\"#700040\">おおっと</font></h1><pre>");
      out.write(e.toString());
      e.printStackTrace(out);
      out.println("</pre>");
    }
    out.close();
  }

  public void doPost(HttpServletRequest request,
                    HttpServletResponse response)
    throws ServletException, IOException {
    doGet(request, response);
  }
}

 ソースコードのファイル名は SimpleJythonServlet.javaです。 冒頭で「package oppadmin」としている部分はもちろん自由に変えてOKです。 ポイントは何点かだけ。 まず、Pythonスクリプトの標準出力をサーブレットの出力ストリームに連結している PythonInterpreter.setOut(Writer) が重要な処理です。 あと、参照されたURL(URI?と呼ぶほうがいいのかナ?) からサーバ上のローカルなファイルパスに変換する ServletContext.getRealPath(String) を使って、Pythonスクリプトのファイルパスを特定しています。

 スクリプトの解釈実行には PythonInterpreter.execfile を使っていますが、これは Jythonがスクリプトを解釈実行するとき、 スクリプトを(Java環境のデフォルトの)エンコーディングを使って読むことを利用しています。 従って、Pythonスクリプトに日本語の文字列を記述するとき、 そのエンコーディングをJava VMのデフォルトのそれに合わせておけば、 特に意識しなくても普通に出力ストリームに正しく出力されます。

 では実際に何かスクリプトを実行してみます。 ここで使用したサーブレットコンテナはJakarta Tomcat 4.0.2です。

  1. TomcatのWebアプリケーションをどこか適当なところに作り、 server.xmlにエディタで書いて登録します。 これはJythonというよりJ2EEの設定の話なので、ここでは省略します。
  2. そのWebアプリケーションディレクトリを $APP と表記し、 パス区切りをUNIX書式で書くことにすると、 $APP/WEB-INF/classes/oppadmin/SimpleJythonServlet.class を置きます。oppadminの部分はパッケージと合わせて下さい。 SimpleJythonServlet.class はもちろん、上のJavaクラスをコンパイルしたものです。
  3. $APP/WEB-INF/web.xml の中で、拡張子「.py」のファイルをSimpleJythonServlet に読ませるための設定を次のようにかきかきします。

    <servlet>
      <servlet-name>JYTHON</servlet-name>
      <servlet-class>oppadmin.SimpleJythonServlet</servlet-class>
    </servlet>
    
    <servlet-mapping>
      <servlet-name>JYTHON</servlet-name>
      <url-pattern>*.py</url-pattern>
    </servlet-mapping>
    

  4. Tomcatを再起動します。

 これで準備はOK。後は上のアプリケーションのコンテキストパスのどこかに、 このようなPythonスクリプトを書きます。

print """
<html><body>
<h1>Hello, Jyvlet World!</h1>
表示しました。<br>
はじめてのあ○む<br>
</body></html>
"""

 このスクリプトを $APP/test/test-jyvlet.py と名づけ、$APPのコンテキストパスを /app とすると、 「http://{サーバのホスト名}/app/test/test-jyvlet.py」 にWebブラウザでアクセスします。 このスクリプトが生成したHTML文書が表示されれば大成功というわけです。

セクションのサブメニューに戻る
(first uploaded 2002/08/06 last updated 2003/01/08)