Servlet における Bean クラスとは Part 1

Java

Java Servlet を使って Web アプリケーションや Web サイトを作成するにあたって、サーバー側で処理したデータを JSP でページに表示するという一連の流れがあります。

このとき、基本的には request.getAttribute / setAttribute を使ってリクエストにデータを持たせて JSP に渡し、それを表示するというソースコードを書くことが多いと思います。

ですが、 JSP に渡す必要があるデータの数が多いとき、何度も setAttribute して getAttribute するのは大変で、スパゲッティコードが生まれやすくなってしまいます。

このような問題を軽減し、JSP へのデータの受け渡しを簡潔にする役割を果たすのが Java Servlet における Bean クラスです。

スポンサーリンク

Bean クラスを使う場合と使わない場合を比較する

まずは普通にいろいろ渡すソースコードを書いてみます。

Bean を使わずにデータを格納していく

protected void doGet(HttpServletRequest request,
		HttpServletResponse response) throws ServletException, IOException {

	// キャラクターのデータ
 	int charaId1 = 1;
 	int charaId2 = 2;
 	int charaId3 = 3;

	String name1 = "タロー";
	String name2 = "ジロー";
	String name3 = "ハナコ";

	String job1 = "勇者";
	String job2 = "魔法使い";
	String job3 = "僧侶";

	int level1 = 33;
	int level2 = 31;
	int level3 = 32;


	request.setAttribute("charaId1", charaId1);
	request.setAttribute("charaId2", charaId2);
	request.setAttribute("charaId3", charaId3);

	request.setAttribute("name1", name1);
	request.setAttribute("name2", name2);
	request.setAttribute("name3", name3);

	request.setAttribute("job1", job1);
	request.setAttribute("job2", job2);
	request.setAttribute("job3", job3);

	request.setAttribute("level1", level1);
	request.setAttribute("level2", level2);
	request.setAttribute("level3", level3);


	ServletContext context = this.getServletContext();

	// フォワード先を指定
	RequestDispatcher dispatcher = context
			.getRequestDispatcher("/partyMember.jsp");

	// フォワード処理
	dispatcher.forward(request, response);
}

doGet メソッド以外の行は省略しています。

ファンタジー系の RPG ゲームにありそうなキャラクターのデータを、JSP へフォワードで転送する処理です。

パーティメンバーの1番目、2番目、3番目、という意味で数字が振ってありますが、パッと見自分以外の誰かが見てもわかってもらえないかもしれません。正直自分で見てても嫌になるくらいごちゃごちゃしているソースコードです。

これは一応以下のように配列化することである程度きれいにまとめることができます。

// キャラクターのデータ
int charaId[] = {1,2,3};
String name[] = {"タロー","ジロー","ハナコ"};
String job[] = {"勇者","魔法使い","僧侶"};
int level[] = {33,31,32};

// とりあえず キャラ2のデータだけセットしてフォワードします
request.setAttribute("charaId", charaId[1]);
request.setAttribute("name", name[1]);
request.setAttribute("job", job[1]);
request.setAttribute("level", level[1]);

配列は int 型と String 型をごちゃまぜにできないから、こんな感じになっちゃったけど、結構スッキリした! いやぁよかったよかった。

と言いたいところなのですが、これは運用する上で使いやすいデータと言えるのでしょうか。

仕方なく別々にしたとはいえ、考えてみれば「キャラの名前一覧」「キャラのレベル一覧」などというようなデータが、頻繁に必要になるとは思えません。

Bean を使ってデータを格納する

可能であれば「キャラ1のデータ」「キャラ2のデータ」とまとめておきたいものです。

しかし、型の縛りを無視することはできません。ぐぬぬ…と困っているそんなとき。役に立つのが Bean クラスです。

Bean クラスは一言でいうと自作した倉庫のようなものです。データを格納するために作るクラスということになります。

配列の int や String のような型に縛られるのは困る! それならば自分で型を作ってしまえばいい、という認識で運用するのがいいでしょう。

Bean クラスを作る上でのルール

Bean クラスには以下のルールや通例があります。

  • クラス名の末尾には Bean とつける
  • Serializable クラスをインターフェイスにして、serialVersionUID という名前の private な 定数を宣言する
  • 引数なしのコンストラクタを実装する
  • 変数はすべて private にし、取り出しなどをするための専用メソッドを実装する(getter と setter)

試しに CharacterBean を作成してみます。

import java.io.Serializable;

public class CharacterBean implements Serializable {
    private static final long serialVersionUID = 1L;

    // private な変数
    // (倉庫に入れておきたいデータ)
    private int charaId;
    private String name;
    private String job;
    private int level;

	// 引数のないコンストラクタ
	CharacterBean(){}

	public void setCharaId(int charaId) {
		this.charaId = charaId;
	}

	public void setName(String name) {
		this.name = name;
	}

	public void setJob(String job) {
		this.job = job;
	}

	public void setLevel(int level) {
		this.level = level;
	}

	public int getCharaId() {
		return charaId;
	}

	public String getName() {
		return name;
	}

	public String getJob() {
		return job;
	}

	public int getLevel() {
		return level;
	};

}

クラスの実態はというと、set○○、get○○というメソッドだけが決まった法則で実装されただけのものです。

さて、Bean クラスは倉庫だと表現しました。CharacterBean はなにか特別なものが入っているわけでもない倉庫ではありますが、倉庫に鍵をかけずにほっぽりだしておくのはちょっと問題がありますよね。

そこでアクセス修飾子を private にし、外部からの変数への直接アクセスはできなくしてしまいます。これが倉庫にたとえると鍵の役割になります。

ではこの変数への書き換えや取り出しはどうやっておこなうのか。この疑問を解消するのが getter / setter メソッドです。

// データの書き込み
bean.setName("ジロー");

// データの取り出し
String name = bean.getName();

getter / setter メソッドは、private な変数にアクセスするためのメソッドということで「アクセサメソッド」とも呼ばれます。

// CharacterBean の使い方
CharacterBean bean = new CharacterBean();

// データの書き込み
bean.setCharaId(2);
bean.setName("ジロー");
bean.setJob("魔法使い");
bean.setLevel(31);
		
// この時点で、bean という変数の中にキャラ一人のデータがまるまる入ったことになります。

// データの取り出し
int charaId = bean.getCharaId();
String name = bean.getName();
String job = bean.getJob();
int level = bean.getLevel();

この getter と setter が Bean クラスという倉庫の番人というわけです。倉庫からなにかを取り出すには getter さんを通さなければものを取り出すことはできませんし、なにかを運び入れるには setter さんを通さなければ運び入れることはできません。

Bean クラスを実際に使ってみる

今度は Bean クラスを Servlet でうまい具合に使ってみようと思います。

Servlet における Bean クラスの扱い方

protected void doGet(HttpServletRequest request,
		HttpServletResponse response) throws ServletException, IOException {

	CharacterBean bean = new CharacterBean();

	// データの書き込み
	bean.setCharaId(2);
	bean.setName("ジロー");
	bean.setJob("魔法使い");
	bean.setLevel(31);

	request.setAttribute("bean", bean);

	ServletContext context = this.getServletContext();

	// フォワード先を指定
	RequestDispatcher dispatcher = context
				.getRequestDispatcher("/partyMember.jsp");

	// フォワード処理
	dispatcher.forward(request, response);
}

上は Servlet 側のソースコードです。

request.setAttribute("bean", bean);

先ほどは id と name と job と level をそれぞれ別々に setAttribute しなければならなかったのに対し、今度は bean というひとまとまりにしてリクエストに乗せることができています。

ものを詰め込んだ倉庫ごと運んでしまおうという魂胆です。すっきりしていていいですね!

次にこれを JSP 側で取り出してみます。

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>

<%@ page import="hello.CharacterBean" %>
<%
// bean をリクエストデータから取得
CharacterBean bean = (CharacterBean)request.getAttribute("bean");
%>

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>パーティメンバー</title>
</head>
<body>

	<table>
		<tbody>
			<tr>
				<th>キャラID</th>
				<th>キャラ名</th>
				<th>職業</th>
				<th>レベル</th>
			</tr>
			<tr>
				<td><%=bean.getCharaId() %></td>
				<td><%=bean.getName() %></td>
				<td><%=bean.getJob() %></td>
				<td><%=bean.getLevel() %></td>
			</tr>
		</tbody>
	</table>


</body>
</html>

ソースコードは上の通り。

<%@ page import="hello.CharacterBean" %>

この記述は自作した Bean クラスを JSP で使うための記述です。

今回は hello というパッケージ名でパッケージを作成しているので、 hello.CharacterBean になっています。実際に使うときは自分のパッケージ名に合わせてください。

実行してみるとこんな感じになりました。

長くなったので区切ります。

コメント

タイトルとURLをコピーしました