java-beginner.com ブログ

プログラミングを学習するブログ(Javaをメインに)

JSF(JavaServer Faces)で入出力

投稿日:

最終更新日:2018年03月24日

アイキャッチ

こんにちは。「Javaを復習する初心者」です。

今回はJSF(JavaServer Faces)を入力と出力をする簡単な例を作ってみました。

仕様

入力画面と出力画面を作ることにします。以下、今回作るものの大まかな仕様です。


入力画面index.xhtmlでは以下の項目を表示する。

項目 概要
入力欄 姓の入力欄。
入力欄 名の入力欄。
送信ボタン output.xhtmlに遷移する。

遷移先output.xhtmlでは”こんにちは、「[姓][名]」さん。”を出力する。


以上の大まかな仕様を満たす画面を作成しようと思います。

バッキングビーンの作成

index.xhtmlでは2つの入力項目「姓」と「名」があります。これらの値を保持するためのJavaファイルを作成します。

helloというパッケージを作り、そこにHelloクラスを以下のように作りました。

Hello.java

package hello;

import javax.enterprise.context.RequestScoped;
import javax.inject.Named;

@Named
@RequestScoped
public class Hello {

	private String familyName;
	private String firstName;

    public String getFamilyName() {
		return familyName;
	}

	public void setFamilyName(String familyName) {
		this.familyName = familyName;
	}

	public String getFirstName() {
		return firstName;
	}

	public void setFirstName(String firstName) {
		this.firstName = firstName;
	}

	public String next() {
        return "output.xhtml";
    }

}

上記クラスでは、メンバ変数を2つ定義しています。変数familyNameと変数firstNameに入力画面の値を設定しようという想定です。出力にも使います。そのために、ゲッターとセッターを定義しています。xhtmlでこのクラスのメンバ変数を指定するためには、@Namedアノテーションが必要です。このアノテーションを付与すると、クラス名Helloの最初を小文字にしたhelloという記述で、このクラスを指定することが出来ます。@RequestScopedはオブジェクトの生成と破棄のタイミング定義のためのアノテーションです。この場合、リクエストが発生するとオブジェクトが生成され、レスポンスが完了するとオブジェクトが破棄されます。

next()メソッドでは遷移先のファイル名”output.xhtml”をリターンするだけです。画面遷移のためのメソッドです。使い方は入力画面の説明でします。

入力画面index.xhtml

入力画面は以下のように作りました。見栄えは特に気にしてません。

入力画面index.xhtml

<?xml version='1.0' encoding='UTF-8' ?>
<!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:h="http://xmlns.jcp.org/jsf/html">
    <h:head>
        <title>in</title>
    </h:head>
    <h:body>
		<h:form>
			名前を入力してください。<br />
			姓<h:inputText value="#{hello.familyName}"/><br />
			名<h:inputText value="#{hello.firstName}"/><br />
			<h:commandButton value="送信" action="#{hello.next()}" />
		</h:form>
    </h:body>
</html>

htmlタグのxmlnsという属性でタグライブラリを定義しています。接頭辞hでHTML Componentタグを定義しています。HTMLタグに対応するFaceletsタグのようです。細かいことは今回は気にしませんでした。

実際に画面を表示した結果、以下のようにHTMLが出力されました。

XHTMLから生成されたHTML

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"><head id="j_idt2">
        <title>in</title></head><body>
<form id="j_idt5" name="j_idt5" method="post" action="/Hello/faces/index.xhtml;jsessionid=297744a93d240080aef82c7cb0d8" enctype="application/x-www-form-urlencoded">
<input type="hidden" name="j_idt5" value="j_idt5" />

			名前を入力してください。<br />
			姓<input type="text" name="j_idt5:j_idt7" /><br />
			名<input type="text" name="j_idt5:j_idt9" /><br /><input type="submit" name="j_idt5:j_idt11" value="送信" /><input type="hidden" name="javax.faces.ViewState" id="j_id1:javax.faces.ViewState:0" value="-4782337889238561198:-2935324306297524052" autocomplete="off" />
</form></body>
</html>

h:formでhtmlのform要素が生成されました。method属性など自動で設定されるようです。

h:inputText、h:commandButtonでinput要素が生成されました。h:inputTextは文字列入力ボックスを作るために使うようです。h:commandButtonはボタンを作るために使うようです。h:inputTextのvalue属性ではバッキングビーンのメンバ変数を指定します。今回はHelloクラスを作っているので、以下の記述方法になります。

  • #{hello.[メンバ変数]}

画面遷移をするため、h:commandButtonのaction属性にHelloクラスのnext()メソッドを指定しています。この設定によって、ボタン押下時にnext()メソッドが呼び出されます。また、そのメソッドがリターンする文字列が画面遷移先のファイル名になります。

出力画面output.xhtml

出力画面は以下のように作りました。

出力画面output.xhtml

<?xml version='1.0' encoding='UTF-8' ?>
<!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:h="http://xmlns.jcp.org/jsf/html">
    <h:head>
        <title>out</title>
    </h:head>
    <h:body>
			こんにちは、「<h:outputText value="#{hello.familyName}"/><h:outputText value="#{hello.firstName}"/>」さん。
    </h:body>
</html>

h:outputText要素のvalue属性でバッキングビーンのメンバ変数を指定しています。入力画面でユーザーが入力した文字列が出力されることになります。

入力項目を必須にする

上記で作った入力画面で何も入力しなくても画面遷移が出来てしまいます。

JSFでは入力項目を必須にするという設定が出来ます。

h:form要素を次のように書き換えると、各項目に入力必須にすることができ、エラーメッセージを出力することが出来ます。

入力必須に設定

	名前を入力してください。<br />
	姓<h:inputText id="n1" value="#{hello.familyName}" required="true" label="「姓」"/>
	<h:message for="n1"/><br />
	名<h:inputText id="n2" value="#{hello.firstName}" required="true" label="「名」"/>
	<h:message for="n2"/><br />
	<h:commandButton value="送信" action="#{hello.next()}" />

入力必須にするには、h:inputText要素にrequired属性をtrueで記述する必要があります。つまり、「required=”true”」と記述します。これだけで入力必須になるのですが、ボタンを押しても画面遷移が発生しないというだけで、ユーザー側から見たら状況が良く分からないということになります。

エラーメッセージを出力するためにはh:message要素を使います。まず、h:inputText要素にid属性を設定します。これはh:message要素と紐づけるために任意に設定します。また、label属性も設定した方が良いです。メッセージの出力が以下のような形式になるからです。

  • [label属性の値]: 検証エラー: 値が必要です。

最後に、h:message要素にfor属性を設定します。これは対応するh:inputText要素のid属性の値と同じものを設定します。

以上で、任意の項目を入力必須にして対応するエラーメッセージを出力することが出来ます。

エラーメッセージをまとめて表示

h:messages要素を使うとエラーメッセージをまとめて出力することが出来ます。

最後にエラー出力

	名前を入力してください。<br />
	姓<h:inputText value="#{hello.familyName}" required="true" label="「姓」"/><br />
	名<h:inputText value="#{hello.firstName}" required="true" label="「名」"/><br />
	<h:commandButton value="送信" action="#{hello.next()}" />
	<h:messages/>

上記のようにh:messages要素の位置に、すべてのエラーメッセージが出力されます。