JSF2.0の基本的な画面遷移

今日はJSF2.0での基本的な画面遷移方法を書いていきます。

【前提条件】

[環境]

  ・JDK 1.7.0_02
  ・Glassfish 3.1.2

【内容】

JSF2.0ではMVCで言うところのコントローラは
全てManagedBeanというクラスで行います。
ManagedBeanはPOJOで作成します。

@ManagedBean(name = "indexPage")
@RequestScoped
public class IndexPageImpl {

    /** ユーザID */
    private String userId = null;

    /** パスワード */
    private String password = null;

    public String login() {


        System.out.println(userId);
        System.out.println(password);

        return "resultPage.xhtml";
    }

    // アクセサメソッドは省略
}

画面から呼び出されるメソッド名は自由につけることができます。
戻り値は型をStringに、値を画面の遷移先を指定します。

javax.faces.bean.ManagedBeanアノテーションを使用すると
JSF上で自動的に管理してくれるようになります。
name属性にはXHTML上で試用したい場合の名前を指定します。
何もしていない場合はクラス名(先頭は小文字)が自動的に設定されます。

javax.faces.bean.RequestScopedアノテーション
ManagedBeanのスコープをリクエストに指定しています。
そのほかにはApplicationScoped、SessionScoped、ViewScopedがあります。
(この辺はまた別にまとめたいですね)

続いて画面のほうです。
遷移元画面は↓のようにします。
今回、ファイル名は「index.xhtml」とし、
配置場所はWebコンテキストのルートディレクトリ配下にします。

<?xml version="1.0" encoding="Windows-31J" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
      "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:h="http://java.sun.com/jsf/html"> 
    <f:view>
        <h:head>
            <meta http-equiv="Content-Type" content="text/html; charset=Windows-31J" />
            <title>ログイン</title>
        </h:head>
        <h:body>
            <h:form id="loginForm">
                <div id="userIdRow">
                    <span id="userIdLabel">ユーザID</span>
                    <span id="userIdInput">
                        <h:inputText id="userId" value="#{indexPage.userId}" >
                    </span>
                </div>
                <div id="passwordRow">
                    <span id="passwordLabel">パスワード</span>
                    <span id="passwordInput">
                        <h:inputSecret id="password" value="#{indexPage.password}" />
                    </span>
                </div>
                <div>
                    <h:commandButton action="#{indexPage.login}" value="ログイン" />
                </div>
            </h:form>
        </h:body>
    </f:view>
</html>

まずはJSFレンダリングする箇所をタグで囲います。
(なくても動いたような気がしますが、きっちり書きましょう)

タグにはタグの内容を、タグにはタグの内容を書きます。

サブミットする箇所はタグで囲います。
このページの入力項目ではタグを使用しています。
value属性には対応するManagedBeanのプロパティをEL式で指定します。

たとえば、ユーザIDとなっている箇所は「#{indexPage.userId}」と指定しています。
先ほど定義したManagedBeanのIndexPageImplクラスのuserIdに紐付けられます。
EL式の書き方としては「#{(ManagedBean名).(プロパティ名)}になります。

ManagedBean名はManagedBeanアノテーションで指定したvalue属性の値になります。
指定していない場合は自動的に設定された値になります。

サブミットするボタンはタグを使用します。
action属性に実行したいManagedBeanのメソッドを指定します。
こちらもEL式で指定し、「#{(ManagedBean名).(メソッド名)」という形式になります。

続いて遷移先画面です。
遷移先の画面は↓のようになります。
今回、ファイル名は「resultPage.xhtml」とします。
配置場所は「index.html」と同じです。

<?xml version="1.0" encoding="Windows-31J" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:h="http://java.sun.com/jsf/html"> 
    <f:view>
        <h:head>
            <meta http-equiv="Content-Type" content="text/html; charset=Windows-31J" />
            <title>ダーツ ログイン</title>
        </h:head>
        <h:body>
            <h:form id="loginForm">
                <div id="userIdRow">
                    <span id="userIdLabel">ユーザID</span>
                    <span id="userIdInput">
                        <h:outputText id="userId" value="#{indexPage.userId}" label="ユーザID" />
                    </span>
                </div>
                <div id="passwordRow">
                    <span id="passwordLabel">パスワード</span>
                    <span id="passwordInput">
                        <h:outputText id="password" value="#{indexPage.password}"  label="パスワード" />
                    </span>
                </div>
            </h:form>
        </h:body>
    </f:view>
</html>

先ほどとあまり変わりはありません。
ユーザIDとパスワードの入力項目をタグに置き換え、
出力項目として変更しただけです。

以上の三つのファイルを作成し、
Webブラウザでindex.htmlにアクセスします。

そうすると↓のような画面が表示されます。

ユーザ名とパスワードに「test」と入力して
ログインボタンをクリックします。

そうすると↓のような画面が表示されます。
index.xhtmlで入力した内容がresultPage.xhtmlに表示されています。

JSFの基本的な動きは以上になります。

JSFで使えるタグは↓のドキュメントを参考にしてください。
http://docs.oracle.com/cd/E17802_01/j2ee/javaee/javaserverfaces/2.0/docs/pdldocs/facelets/index.html


番外編。
ManagedBeanをCDIで管理する場合。

@Named(value = "indexPage")
@RequestScoped
public class IndexPageImpl {

// 各プロパティ、メソッドは先ほどと同じ

}

ManagedBeanアノテーションではなく、javax.inject.Namedアノテーションを使用します。
value属性はManagedBeanアノテーションと同じです。

RequestScopedアノテーションはjavax.faces.bean.RequestScopedアノテーションではなく、
javax.enterprise.context.RequestScopedアノテーションを使用します。
これで、JSFだけの管理と同様に動きます。

id:ryoasaiさんの↓の記事を参考にさせていただきました。
Java EE6環境でJSF2を使う場合はCDIのBeanを管理Beanとして使う方がよい - 達人プログラマーを目指して

参考どころかほぼコピー・・・