JavaでCGI

はぁ?いまさら何いっているの?tomcatでしょ?と思っていますね?

ここで紹介するのは本当にJavaCGIを書く方法です。

ただし、Javaコードを実行するためにはVMを起動しなければいけないため、VMを起動するだけのシェルスクリプトを用意します(test.cgi)。

また、System.getProperties() はCGIのために必須な環境変数($QUERY_STRING とか $SCRIPT_NAME とか)を取得できないので、これらはコマンドライン引数で渡してあげる必要があります。

次は、思いっきりはまったんですが、通常ユーザーで実行するときのエンコーディングEUC なのですが、www ユーザーで実行するときはエンコーディングが全く設定されていませんでした。このため VM は英語環境であると勝手に判断し、日本語の出力はすべて化けていました。この対策として $LANG も指定してあげる必要があります。

Javaソースはサーバー上のエンコーディングに合わせて EUC で記述します。Windows 環境ならこの辺はすべて Shift_JIS や MS932 にします。

この方法は以下のような方におすすめです。

Javaは中間コード形式なのでビルドはローカルPCでもできますが、サーバー上にJREが入っていないと実行できませんのであしからず。

test.cgi

#!/bin/sh

export LANG=ja_JP.eucJP

/usr/java/j2sdk1.4.2_08/bin/java \
    -Dcgi.http_cookie="$HTTP_COOKIE" \
    -Dcgi.http_referer="$HTTP_REFERER" \
    -Dcgi.http_user_agent="$HTTP_USER_AGENT" \
    -Dcgi.content_length="$CONTENT_LENGTH" \
    -Dcgi.path_info="$PATH_INFO" \
    -Dcgi.query_string="$QUERY_STRING" \
    -Dcgi.request_method="$REQUEST_METHOD" \
    -Dcgi.script_name="$SCRIPT_NAME" \
    -Dcgi.server_name="$SERVER_NAME" \
    -Dcgi.server_port="$SERVER_PORT" \
    -Dfile.encoding=euc-jp \
  Main

Main.java

import java.util.Properties;
import java.util.Enumeration;

public class Main {
    public static void main(String[] args)
    {
        System.out.println
                 ("Content-Type: text/html;charset=euc-jp\n\n");
        System.out.println("<html lang=\"ja\">");
        System.out.println("<head><title>テスト</title></head>");
        System.out.println("<body>");
        
        System.out.println("<h1>HTTPプロパティ</h1>");
        Properties prop = System.getProperties();
        Enumeration keys = prop.keys();
        while (keys.hasMoreElements()) {
            String key = keys.nextElement().toString();
            String value = prop.getProperty(key);
            if (key.startsWith("cgi.")) {
                System.out.println(key + "=" + value + "<br/>");
            }
        }
        
        System.out.println("<h1>システムプロパティ</h1>");
        prop = System.getProperties();
        keys = prop.keys();
        while (keys.hasMoreElements()) {
            String key = keys.nextElement().toString();
            String value = prop.getProperty(key);
            if (!key.startsWith("cgi.") && !key.startsWith("sun.")) {
                System.out.println(key + "=" + value + "<br/>");
            }
        }
        
        System.out.println("</body></html>");
    }
}

コンパイル&実行

うまく動いたら、ブラウザから test.cgi を叩いてみましょう。

javac Main.java
chmod +x test.cgi
./test.cgi

以下は懸案点です。

  • セッション管理はどうするか
  • DBと毎回コネクションを張ると遅くなる