サーブレット&JSPの基本|リクエストスコープの基本

サーブレットで作ったデータをJSPへ渡す。スコープとJavaBeansで画面表示の連携を整えよう

フォワードを使うと、サーブレットクラスからJSPファイルへ処理を転送できます。

サーブレットでリクエストを受け取り、処理を行い、その結果画面の表示をJSPへ任せる。この流れは、MVCモデルに沿ったWebアプリケーションを作るうえでとても大切です。

しかし、フォワードができるようになっただけでは、サーブレットとJSPの連携はまだ完成していません。

なぜなら、フォワードは処理の転送であり、サーブレットで作成したデータが自動的にJSPへ渡されるわけではないからです。

たとえば、サーブレットでおすすめメニューを決定し、その結果をJSPで表示したいとします。サーブレットからJSPへフォワードするだけでは、JSP側はサーブレットで作成したおすすめメニューのインスタンスをそのまま利用できません。

そこで必要になるのがスコープです。

スコープとは、インスタンスを保存できる領域です。サーブレットクラスで作成したインスタンスをスコープに保存しておけば、フォワード先のJSPファイルでそのインスタンスを取り出して利用できます。

この記事では、スコープとは何か、スコープに保存できるものは何か、そしてスコープへ保存するデータとしてよく使われるJavaBeansについて解説します。

フォワードだけではデータは渡せない

フォワードを使うと、サーブレットクラスからJSPファイルへ処理を移せます。

しかし、処理を移せることと、サーブレットで作ったインスタンスをJSPで使えることは別です。

たとえば、MenuServletでおすすめメニューを決定し、その結果をmenu-result.jspに表示したい場合を考えます。

MenuServletの中で、おすすめメニュー名やコメントを持つインスタンスを作成したとしても、そのインスタンスはMenuServletの中だけで作成されたものです。何もしなければ、menu-result.jspはそのインスタンスを知ることができません。

フォワードだけの場合に起こること

場面内容
サーブレット側おすすめメニュー結果のインスタンスを作成する
フォワードmenu-result.jspへ処理を転送する
JSP側サーブレットで作成したインスタンスをそのまま利用できない

この状態では、JSPファイルでサーブレットの処理結果を表示できません。

サーブレットで作ったデータをJSPへ渡すには、処理をフォワードするだけでなく、データを共有するための仕組みが必要になります。

図1:フォワードだけではインスタンスを共有できない

この図から分かること

フォワードは、サーブレットからJSPへ処理を移すための仕組みです。

しかし、サーブレットで作成したインスタンスが、何もしなくてもJSPで使えるようになるわけではありません。JSPで処理結果を表示するには、サーブレットで作成したインスタンスをどこかに保存し、JSP側で取り出せるようにする必要があります。

その保存場所として使うのがスコープです。スコープを使うことで、サーブレットとJSPの間でインスタンスを共有できるようになります。

スコープとは

スコープとは、インスタンスを保存できる領域のことです。

サーブレットクラスやJSPファイルは、スコープにインスタンスを保存したり、スコープからインスタンスを取得したりできます。

たとえば、MenuServletでおすすめメニュー結果のインスタンスを作成し、それをスコープに保存します。そのあとmenu-result.jspへフォワードすれば、JSP側はスコープからそのインスタンスを取り出して、画面に表示できます。

スコープを使ったデータ連携のイメージ

順番内容
1サーブレットでインスタンスを作成する
2作成したインスタンスをスコープに保存する
3JSPへフォワードする
4JSPでスコープからインスタンスを取得する
5取得したインスタンスの情報を画面に表示する

スコープは、サーブレットとJSPの間に置かれた共有ボックスのようなものです。

サーブレットがそのボックスにデータを入れ、JSPがそのボックスからデータを取り出します。

スコープには4種類ある

スコープには、いくつかの種類があります。

代表的なものは、ページスコープ、リクエストスコープ、セッションスコープ、アプリケーションスコープの4つです。

これらは、保存したインスタンスをどの範囲で、どのくらいの期間利用できるかが異なります。

主なスコープの種類

スコープ大まかな特徴
ページスコープ1つのJSPページの中で使う
リクエストスコープ1回のリクエストの中で使う
セッションスコープ同じ利用者の一連の操作で使う
アプリケーションスコープWebアプリケーション全体で使う

この段階で4つの違いをすべて詳しく覚える必要はありません。

まずは、スコープはインスタンスを保存する場所であり、種類によって有効な範囲や期間が異なる、ということを押さえておきましょう。

この章で特に重要になるのは、サーブレットからJSPへデータを渡すときに使うリクエストスコープです。

図2:スコープを経由してサーブレットからJSPへデータを渡す

この図から分かること

スコープを使うと、サーブレットで作成したインスタンスをJSPへ渡せるようになります。

サーブレットは、処理結果を表すインスタンスを作成し、それをスコープに保存します。JSPは、フォワードされたあとにスコープからインスタンスを取得し、画面表示に利用します。

このように、スコープはサーブレットとJSPの間でデータを受け渡すための重要な仕組みです。

スコープに保存できるもの

スコープには何でも保存できるわけではありません。

スコープに保存できるのはインスタンスです。

int型やdouble型などの基本データ型の値は、インスタンスではないため、そのままスコープに保存する対象にはなりません。

スコープに保存できるものとできないもの

種類スコープに保存できるか
インスタンス保存できるString、Integer、MenuResultなど
基本データ型そのままでは保存できないint、double、booleanなど

基本データ型の値をスコープで扱いたい場合は、ラッパークラスを使います。

たとえば、int型の値を扱いたい場合はInteger、double型の値を扱いたい場合はDoubleを使います。

基本データ型とラッパークラスの例

基本データ型対応するラッパークラス
intInteger
doubleDouble
booleanBoolean
longLong

スコープに保存するものはインスタンスだけである、という点をまず覚えておきましょう。

スコープにはJavaBeansを保存する

スコープには一般的なクラスのインスタンスを保存できます。

ただし、Webアプリケーションでは、原則としてJavaBeansと呼ばれるルールに沿ったクラスのインスタンスを保存します。

JavaBeansとは、Javaのクラスを部品として再利用しやすくするためのルール、またはそのルールを守って作られたクラスのことです。

難しく考えすぎる必要はありません。Webアプリケーションで扱う複数の情報を、きちんとした形でまとめるためのお約束を守ったクラス、と考えると分かりやすいです。

たとえば、おすすめメニュー結果を表す場合、メニュー名とコメントを別々の変数として扱うよりも、MenuResultというJavaBeansにまとめておくと扱いやすくなります。

JavaBeansにまとめるメリット

メリット内容
複数の情報をまとめられるメニュー名とコメントなどを1つのインスタンスにできる
JSPへ渡しやすいスコープに1つのインスタンスとして保存できる
再利用しやすい同じデータ構造を別の処理でも使いやすい
役割が分かりやすいデータを表すクラスとして整理できる

JavaBeansは、サーブレットとJSPの間でデータを渡すときの入れ物としてよく使われます。

JavaBeansのルール

スコープに保存する目的でJavaBeansを作る場合、まずは次のルールを押さえておきましょう。

JavaBeansの主なルール

ルール内容
ルール①直列化可能である
ルール②クラスはpublicで、パッケージに所属する
ルール③publicで引数のないコンストラクタを持つ
ルール④フィールドはカプセル化する

直列化可能にするためには、java.io.Serializableインタフェースを実装します。

クラスはpublicにし、package文でパッケージに所属させます。

また、publicで引数のないコンストラクタを用意します。追加で引数を持つコンストラクタを作ってもかまいません。

フィールドはprivateにし、必要に応じてgetterやsetterを用意します。

JavaBeansの例

ここでは、おすすめメニュー結果を表すMenuResultクラスを作成します。

メニュー名とコメントを持つJavaBeansです。

JavaBeansの例

package model;

import java.io.Serializable;

public class MenuResult implements Serializable {
    private String menuName;
    private String comment;

    public MenuResult() { }

    public MenuResult(String menuName, String comment) {
        this.menuName = menuName;
        this.comment = comment;
    }

    public String getMenuName() {
        return menuName;
    }

    public void setMenuName(String menuName) {
        this.menuName = menuName;
    }

    public String getComment() {
        return comment;
    }

    public void setComment(String comment) {
        this.comment = comment;
    }
}

このMenuResultクラスは、スコープに保存するためのJavaBeansとして利用できます。

メニュー名とコメントという2つの情報を、1つのインスタンスとしてまとめられる点がポイントです。

MenuResult.javaで確認するJavaBeansのルール

MenuResult.javaを、JavaBeansのルールに沿って確認してみましょう。

ルールとの対応

JavaBeansのルールMenuResult.javaでの対応
直列化可能であるimplements Serializableを指定している
publicでパッケージに所属するpackage modelとpublic class MenuResultを指定している
publicで引数のないコンストラクタを持つpublic MenuResult() { }を定義している
フィールドはカプセル化するmenuNameとcommentをprivateにしている
getterとsetterを用意するgetMenuName、setMenuName、getComment、setCommentを定義している

MenuResultは、modelパッケージに所属するpublicなクラスです。

privateなフィールドを持ち、外部から直接フィールドへアクセスできないようにしています。その代わりに、getterやsetterを通して値を読み書きできるようにしています。

直列化可能である

JavaBeansでは、直列化可能であることがルールの1つです。

直列化とは、インスタンスの中に入っているフィールドの値を、バイト列の形に変換できるようにする仕組みです。変換したデータは、ファイルなどに保存したり、あとで元のインスタンスとして復元したりできます。

MenuResult.javaでは、次のようにSerializableを実装しています。

記述意味
import java.io.SerializableSerializableを使えるようにする
implements Serializable直列化可能なクラスにする

JavaBeansを作ったり、スコープに保存したりする段階では、直列化の細かい仕組みを深く理解していなくても問題ありません。

まずは、JavaBeansではSerializableを実装する、と覚えておきましょう。

クラスはpublicでパッケージに所属する

JavaBeansでは、クラスをpublicにし、パッケージに所属させます。

MenuResult.javaでは、先頭に次のようなパッケージ宣言があります。

package model;

これにより、MenuResultクラスはmodelパッケージに所属します。

また、クラス宣言は次のようになっています。

public class MenuResult implements Serializable

publicにすることで、ほかのクラスやJSPから利用できるクラスになります。

パッケージとpublic指定

指定役割
package modelmodelパッケージに所属させる
public class MenuResultほかの場所から利用できるクラスにする

JavaBeansは、Webアプリケーションのいろいろな場所から使われるデータの部品です。そのため、パッケージに入れて整理し、publicなクラスとして作成します。

publicで引数のないコンストラクタを持つ

JavaBeansでは、publicで引数のないコンストラクタを持つ必要があります。

MenuResult.javaでは、次のコンストラクタがそれにあたります。

public MenuResult() { }

このコンストラクタがあることで、引数を指定せずにMenuResultインスタンスを作成できます。

また、MenuResult.javaでは、引数を持つコンストラクタも追加しています。

public MenuResult(String menuName, String comment)

このように、引数なしのコンストラクタを用意したうえで、必要に応じて引数ありのコンストラクタを追加することはできます。

コンストラクタの役割

コンストラクタ役割
public MenuResult() { }引数なしでインスタンスを作成できる
public MenuResult(String menuName, String comment)初期値を指定してインスタンスを作成できる

スコープに保存するJavaBeansとして使う場合は、引数なしのコンストラクタを用意しておくことが大切です。

フィールドはカプセル化する

JavaBeansでは、フィールドをprivateにして、外部から直接アクセスできないようにします。

MenuResult.javaでは、次の2つのフィールドをprivateにしています。

フィールド内容
private String menuNameメニュー名を保持する
private String commentコメントを保持する

privateにしたフィールドは、外部から直接読み書きできません。

そこで、値を読み取るためのgetterと、値を変更するためのsetterを用意します。

getterとsetter

種類役割
getterフィールドの値を呼び出し元へ返す
setter引数で受け取った値をフィールドへ設定する

MenuResult.javaでは、getMenuName、setMenuName、getComment、setCommentを定義しています。

getterとsetterの命名規則

getterとsetterには、基本的な命名規則があります。

getterの命名規則

項目内容
メソッド名getから始める
getの後ろ対象名の先頭を大文字にする
引数なし
戻り値フィールドの値

たとえば、menuNameの値を読み取るgetterはgetMenuNameです。

setterの命名規則

項目内容
メソッド名setから始める
setの後ろ対象名の先頭を大文字にする
引数1つ
戻り値なし

たとえば、menuNameの値を設定するsetterはsetMenuNameです。

Eclipseでは、ソースメニューからgetterおよびsetterの生成を選ぶことで、命名規則に沿ったgetterやsetterを自動生成できます。

JavaBeansのプロパティとは

JavaBeansには、プロパティという考え方があります。

プロパティとは、インスタンスが持つ属性や情報のことです。

たとえば、MenuResultクラスであれば、menuNameやcommentがプロパティになります。

ただし、プロパティはフィールドと完全に同じものではありません。

多くの場合、フィールド名とプロパティ名は一致します。しかし、JavaBeansのプロパティは、フィールドを作っただけで定義されるわけではありません。

プロパティは、getterまたはsetterを作ることで定義されます。

フィールドとプロパティの違い

MenuResultクラスにmenuNameというフィールドがあるとします。

しかし、menuNameというフィールドを作っただけでは、JavaBeansとしてのmenuNameプロパティが定義されたとはいえません。

getMenuNameやsetMenuNameを作ることで、menuNameプロパティが定義されます。

フィールドとプロパティの対応例

public class MenuResult implements Serializable {
    private String menuName;

    public void setMenuName(String menuName) {
        this.menuName = menuName;
    }

    public String getMenuName() {
        return menuName;
    }
}

この例では、private String menuNameがmenuNameフィールドです。

そして、setMenuNameとgetMenuNameを作ることで、menuNameプロパティが定義されます。

フィールドとプロパティの違い

種類定義されるきっかけ
フィールドフィールド変数を宣言する
プロパティgetterまたはsetterを定義する

つまり、フィールドはクラス内の変数として定義されるものです。

プロパティは、getterやsetterの命名規則によって外部から扱える情報として定義されるものです。

図3:フィールドとプロパティの関係

この図から分かること

フィールドとプロパティは似ていますが、定義されるしくみが異なります。

フィールドは、クラスの中で宣言する変数です。一方、プロパティはgetterやsetterによって定義されます。

getMenuNameやsetMenuNameを作ることで、menuNameプロパティが定義されます。プロパティを読み取るときはgetterが使われ、プロパティを変更するときはsetterが使われます。

getterとsetterでプロパティが決まる

getterやsetterのgetまたはsetの後ろに付けた名前が、プロパティ名になります。

たとえば、getMenuNameまたはsetMenuNameを作ると、menuNameプロパティが定義されます。

このとき、getやsetの後ろのMenuNameは、プロパティ名としては先頭が小文字になり、menuNameとして扱われます。

getterやsetterとプロパティの関係

メソッド定義されるプロパティ
getMenuNamemenuName
setMenuNamemenuName
getCommentcomment
setCommentcomment

getterだけを作れば、読み取り可能なプロパティになります。

setterだけを作れば、変更可能なプロパティになります。

getterとsetterの両方を作れば、読み取りも変更もできるプロパティになります。

フィールド名とプロパティ名が一致しない場合

多くの場合、フィールド名とプロパティ名は同じになります。

しかし、厳密にはフィールド名とプロパティ名は別に考えます。

次の例では、フィールド名は price ですが、getterとsetterの名前から、costプロパティが定義されます。

フィールド名とプロパティ名が異なる例

private int price;

public void setCost(int cost) {
    this.price = cost;
}

public int getCost() {
    return price;
}

この例では、フィールド名はpriceです。

しかし、メソッド名がsetCostとgetCostなので、JavaBeansのプロパティ名はcostになります。

つまり、プロパティ名はフィールド名から自動的に決まるのではなく、getterやsetterの名前から決まります。

boolean型のgetterはisから始める

getterは通常getから始めます。

ただし、戻り値の型がbooleanの場合は、isから始めることがあります。

たとえば、年齢が18歳以上かどうかを表すプロパティを作る場合、isAdultというgetterを定義できます。

boolean型のgetterの例

private int age;

public boolean isAdult() {
    return age >= 18;
}

この例では、isAdultによってadultプロパティが定義されます。

戻り値がbooleanの場合、isから始まるgetterによって、真偽値を表すプロパティを作れます。

boolean型getterの対応

メソッド定義されるプロパティ
isAdultadult

プロパティ名はAdultではなく、先頭を小文字にしたadultです。

JavaBeansは複数の情報をまとめるために使う

WebアプリケーションにおけるJavaBeansの大きな役割は、関連する複数の情報をひとまとめにして保持することです。

たとえば、MenuResultクラスでは、メニュー名とコメントを1つのインスタンスにまとめています。

MenuResultが保持する情報

プロパティ内容
menuNameおすすめメニュー名
commentメニューに関するコメント

サーブレットクラスでは、処理結果としてMenuResultインスタンスを作成します。

そして、そのMenuResultインスタンスをスコープに保存します。

JSPファイルでは、スコープからMenuResultインスタンスを取り出し、menuNameやcommentを使って画面を表示します。

サーブレットとJSPのデータ連携にJavaBeansを使う

サーブレットからJSPへ複数の情報を渡したい場合、個別の値をバラバラに扱うよりも、JavaBeansにまとめると整理しやすくなります。

たとえば、おすすめメニュー名、コメント、価格、提供時間などを扱う場合、それぞれを別々に管理するよりも、MenuResultのようなJavaBeansにまとめておくほうが分かりやすくなります。

JavaBeansを使った連携のイメージ

担当処理内容
サーブレットMenuResultインスタンスを作成する
スコープMenuResultインスタンスを保存する
JSPMenuResultインスタンスを取得して表示する

このように、JavaBeansはサーブレットとJSPの間で処理結果を受け渡すための入れ物として使われます。

最初に押さえたいポイント

リクエストスコープを本格的に使う前に、まずは次の考え方を押さえておきましょう。

ポイント内容
フォワードだけではデータは自動で渡らない処理は移せるが、インスタンスの共有には別の仕組みが必要
スコープはインスタンスを保存する領域サーブレットやJSPが保存、取得できる
スコープに保存できるのはインスタンス基本データ型はそのまま保存する対象ではない
JavaBeansを保存するのが基本複数の情報をまとめて扱いやすい
JavaBeansにはルールがあるSerializable、public、引数なしコンストラクタ、カプセル化など
プロパティはgetterやsetterで定義されるフィールドを作るだけではプロパティとはいえない

サーブレットで処理を行い、JSPで結果を表示するには、処理だけでなくデータの受け渡しも必要です。

スコープとJavaBeansは、そのデータ連携を行うための土台になります。まずは、サーブレットで作ったインスタンスをスコープに保存し、JSPがそれを取り出して使う、という大きな流れを理解しておきましょう。