お気に入り | 日本語 | ログイン

JSP の使用

Java サーブレット コードから、直接 HTML でユーザー インターフェースを出力することは可能ですが、HTML は複雑になるため維持管理が容易ではありません。このような場合は、テンプレート システムを利用したユーザー インターフェースにすることをおすすめします。別々のファイルとして設計、実装したユーザー インターフェースにプレースホルダを配置し、アプリケーションから提供されたデータを規則に基づいてプレースホルダに挿入します。Java ではさまざまなテンプレート システムを利用できますが、それらはすべて App Engine でも機能します。

このチュートリアルでは、JSP(JavaServer Pages)を使用してゲストブックのユーザー インターフェースを実装します。JSP は、サーブレット標準の一部です。App Engine では、アプリケーションの WAR 内の JSP ファイルが自動的にコンパイルされて URL パスにマップされます。

JSP ファイルの作成

ここまでに作成したゲストブック アプリケーションでは文字列を出力ストリームに書き出していましたが、この文字列を JSP として書き出すこともできます。まずは、JSP のサンプルの最新バージョンを移植してみましょう。

war/ ディレクトリ内に guestbook.jsp という名前のファイルを作成し、そのコンテンツを次のようにします:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page import="com.google.appengine.api.users.User" %>
<%@ page import="com.google.appengine.api.users.UserService" %>
<%@ page import="com.google.appengine.api.users.UserServiceFactory" %>

<html>
  <body>

<%
    UserService userService = UserServiceFactory.getUserService();
    User user = userService.getCurrentUser();
    if (user != null) {
%>
<p>Hello, <%= user.getNickname() %>! (You can
<a href="<%= userService.createLogoutURL(request.getRequestURI()) %>">sign out</a>.)</p>
<%
    } else {
%>
<p>Hello!
<a href="<%= userService.createLoginURL(request.getRequestURI()) %>">Sign in</a>
to include your name with greetings you post.</p>
<%
    }
%>

  </body>
</html>

デフォルトでは、war/ または WEB-INF/ 以外のサブディレクトリ内にある拡張子 .jsp のファイルは、すべて自動的に URL パスにマップされます。URL パスは、その .jsp ファイルまでのパス(ファイル名を含む)です。この JSP は、自動的に URL /guestbook.jsp にマップされます。

ゲストブック アプリケーションでは、このファイルをアプリケーションのホーム ページとし、誰かが URL / にアクセスしたときに表示されるようにします。簡単なのは、web.xml を編集して、guestbook.jsp をそのパスの「welcome」サーブレットとして宣言する方法です。

war/WEB-INF/web.xml で、<welcome-file-list> 内の <welcome-file> 要素を変更します。リストから index.html を削除するのを忘れないようにしてください。静的ファイルは、JSP やサーブレットよりも優先されてしまいます。

    <welcome-file-list>
        <welcome-file>guestbook.jsp</welcome-file>
    </welcome-file-list>

ヒント: Eclipse を使用している場合は、このファイルがエディタの [設計] モードで開かれることがあります。このファイルを XML として編集するには、フレームの最下部で [ソース] タブを選択します。

開発サーバーを停止してからもう一度起動します。次の URL にアクセスします:

アプリケーションによって guestbook.jsp のコンテンツが表示されます。ユーザーがログインしている場合は、ユーザーのニックネームも表示されます。

JSP を初めて読み込むと、開発サーバーによって Java ソース コードに変換され、その Java ソースが Java バイトコードにコンパイルされます。Java ソースとコンパイル済みのクラスは、一時ディレクトリに保存されます。元の JSP ファイルに変更を加えると、JSP が自動的に再生成されてコンパイルされます。

アプリケーションを App Engine にアップロードすると、SDK によってすべての JSP がバイトコードにコンパイルされ、バイトコードだけがアップロードされます。App Engine にアップロードしたアプリケーションは、コンパイル済みの JSP クラスを使用して動作します。

ゲストブックのフォーム

このゲストブック アプリケーションには、ユーザーが新しいグリーティング メッセージを投稿するためのフォームを追加し、その処理方法を指定する必要があります。フォームの HTML は JSP 内に挿入します。フォームは新たな URL /sign に格納し、新たに作成するサーブレット クラス SignGuestbookServlet で処理します。SignGuestbookServlet は、フォームを処理した後に、ユーザーを元の /guestbook.jsp にリダイレクトします。この段階で作成するサーブレットでは、ユーザーが投稿したメッセージをログに書き込むだけにします。

guestbook.jsp で、次のコード行を終了タグ </body> のすぐ上に挿入します:

  ...

  <form action="/sign" method="post">
    <div><textarea name="content" rows="3" cols="60"></textarea></div>
    <div><input type="submit" value="Post Greeting" /></div>
  </form>

  </body>
</html>

新しいクラス SignGuestbookServlet を、guestbook パッケージ内に作成します(Eclipse を使用していない場合は、SignGuestbookServlet.java というファイルを src/guestbook/ ディレクトリに作成します)。ソース ファイルのコンテンツを次のようにします:

package guestbook;

import java.io.IOException;
import java.util.logging.Logger;
import javax.servlet.http.*;
import com.google.appengine.api.users.User;
import com.google.appengine.api.users.UserService;
import com.google.appengine.api.users.UserServiceFactory;

public class SignGuestbookServlet extends HttpServlet {
    private static final Logger log = Logger.getLogger(SignGuestbookServlet.class.getName());

    public void doPost(HttpServletRequest req, HttpServletResponse resp)
                throws IOException {
        UserService userService = UserServiceFactory.getUserService();
        User user = userService.getCurrentUser();

        String content = req.getParameter("content");
        if (content == null) {
            content = "(No greeting)";
        }
        if (user != null) {
            log.info("Greeting posted by user " + user.getNickname() + ": " + content);
        } else {
            log.info("Greeting posted anonymously: " + content);
        }
        resp.sendRedirect("/intl/ja/guestbook.jsp");
    }
}

SignGuestbookServlet サーブレットを宣言して URL /sign にマップするため、war/WEB-INF/web.xml に次のコード行を追加します:

<web-app xmlns="http://java.sun.com/xml/ns/javaee" version="2.5">
    ...

    <servlet>
        <servlet-name>sign</servlet-name>
        <servlet-class>guestbook.SignGuestbookServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>sign</servlet-name>
        <url-pattern>/sign</url-pattern>
    </servlet-mapping>

    ...
</web-app>

この新しいサーブレットでは、java.util.logging.Logger クラスを使用してメッセージをログに書き込みます。このクラスの動作は、logging.properties ファイルと、アプリケーションの appengine-web.xml ファイル内で設定するシステム プロパティで制御できます。Eclipse を使用している場合は、このファイルのデフォルト バージョン(アプリケーションの src/ に格納されている)と適切なプロパティに基づいてアプリケーションが作成されます。

Eclipse を使用していない場合は、Logger 設定ファイルを手動で設定する必要があります。SDK からサンプル ファイル appengine-java-sdk/config/user/logging.properties をコピーし、アプリケーションの war/WEB-INF/ ディレクトリに格納します。次に、アプリケーションの war/WEB-INF/appengine-web.xml ファイルを次のように編集します:

<appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
    ...

    <system-properties>
        <property name="java.util.logging.config.file" value="WEB-INF/logging.properties"/>
    </system-properties>

</appengine-web-app>

サーブレットは、INFO ログ レベル(log.info())を使用してメッセージをログに書き込みます。デフォルトのログ レベルは WARNING で、その場合 INFO メッセージは出力されません。guestbook パッケージ内のすべてのクラスのログ レベルを変更するには、次のように logging.properties ファイルに guestbook.level のエントリを追加します:

.level = WARNING
guestbook.level = INFO

...

ヒント: App Engine の実行中に java.util.logging.Logger API を使用してメッセージをログに書き込むと、App Engine によってメッセージが記録されます。これらのメッセージは、管理コンソールから参照したり、AppCfg ツールを使用してダウンロードしたりできます。管理コンソールを使用すると、ログ レベル別にメッセージを参照できます。

ビルドし直して再起動し、テストのため http://localhost:8080/ にアクセスします。フォームが表示されます。フォームに任意のテキストを入力して送信します。フォームがアプリケーションに送信され、元の空のフォームにリダイレクトされます。入力したグリーティング データは、サーバーによってコンソールに記録されます。

次のステップ

これで、ユーザーがグリーティングを入力するためのユーザー インターフェースは完成しました。次は、ユーザーが投稿したグリーティング メッセージを記憶しておき、それを他の訪問者に表示する仕組みが必要です。ここでは、App Engine データストアを使用してこの仕組みを実現します。

データストアと JDO の使用 に進みます。