
サーブレット&JSPの基本|アプリケーションスコープを使ったWebアプリ作成
全ユーザーで共有するカウントを保存する。アプリケーションスコープで評価ボタン付きWebアプリを作ろう
アプリケーションスコープは、Webアプリケーション全体で共有できるスコープです。
リクエストスコープは1回のリクエスト内で使うスコープ、セッションスコープはユーザーごとに使うスコープでした。それに対して、アプリケーションスコープは1つのWebアプリケーションにつき1つだけ用意され、すべてのユーザーで共通して利用できます。
この特徴を使うと、サイト全体で共有したい情報を保存できます。
ここでは、教材ページに対する評価ボタン機能を作成します。利用者が役に立ったまたはもう少しをクリックすると、それぞれの人数をカウントし、その結果を画面に表示します。
この評価数は、特定のユーザーだけが使う情報ではありません。サイトを利用するすべてのユーザーで共有したい情報です。そのため、セッションスコープではなく、アプリケーションスコープに保存します。
この記事では、評価情報を持つJavaBeans、評価数を増やすモデル、リクエストを処理するサーブレット、評価結果を表示するJSPを作成しながら、アプリケーションスコープの使い方を確認します。
教材ページ評価ボタン機能で作るもの
今回作成するのは、教材ページに評価ボタンを付けるWebアプリケーションです。
画面には、役に立ったともう少しの2つのリンクを表示します。利用者がどちらかをクリックすると、その評価数が1つ増えます。
画面に表示する内容
| 表示項目 | 内容 |
|---|---|
| ページタイトル | Java入門教材ページへようこそ |
| 評価リンク | 役に立った、もう少し |
| 評価人数 | それぞれのクリック数 |
| 本文 | 教材ページの紹介文 |
最初にアクセスしたときは、評価数がまだ保存されていません。そのため、評価情報を表すインスタンスを新しく作成し、役に立ったともう少しの数を0として表示します。
その後、役に立ったをクリックすると、役に立ったの人数が増えます。もう少しをクリックすると、もう少しの人数が増えます。
図1:教材ページ評価ボタン機能の画面遷移

この図から分かること
教材ページ評価ボタン機能では、最初に教材ページを表示します。
初回表示時は、評価情報がまだアプリケーションスコープに保存されていないため、新しい評価情報を作成します。その後、利用者が役に立ったまたはもう少しをクリックすると、リクエストパラメータactionの値によって、どちらの評価がクリックされたかを判断します。
評価数はアプリケーションスコープに保存されるため、同じWebアプリケーションを利用するすべてのユーザーで共有できます。
作成するファイル
このアプリケーションでは、MVCモデルに合わせて4つのファイルを作成します。
作成するファイル一覧
| ファイル | 種類 | 役割 |
|---|---|---|
| PageFeedback.java | モデル JavaBeans | 役に立ったともう少しの数を持つ |
| PageFeedbackLogic.java | モデル 処理クラス | 評価数を増やす処理を行う |
| LessonIndex.java | コントローラ サーブレット | リクエストを受け取り、評価処理と画面表示を制御する |
| lessonIndex.jsp | ビュー JSP | 教材ページのトップ画面を表示する |
PageFeedback.javaは、教材ページの評価情報を持つJavaBeansです。
PageFeedbackLogic.javaは、役に立ったまたはもう少しの数を増やす処理を担当します。
LessonIndex.javaは、ブラウザからのリクエストを受け取り、アプリケーションスコープから評価情報を取得します。必要に応じて評価数を増やし、JSPへフォワードします。
lessonIndex.jspは、アプリケーションスコープから評価情報を取得し、教材ページとして画面に表示します。
アプリケーションスコープに保存する理由
評価ボタンの人数は、特定のユーザーだけが見る情報ではありません。
すべてのユーザーで共通して見たい情報です。
たとえば、青山さんが役に立ったをクリックして人数が1人になったあと、山田さんが同じ教材ページを開いた場合にも、役に立った 1人と表示されるのが自然です。
このような全ユーザー共通の情報は、アプリケーションスコープに保存します。
評価情報とスコープの関係
| 保存したい情報 | 適したスコープ | 理由 |
|---|---|---|
| 1回の結果表示だけで使う情報 | リクエストスコープ | レスポンス後に残す必要がない |
| ログイン中のユーザー情報 | セッションスコープ | ユーザーごとに分ける必要がある |
| 教材ページ全体の評価数 | アプリケーションスコープ | 全ユーザーで共有したい |
アプリケーションスコープに保存した評価情報は、ブラウザを閉じても、Webアプリケーションが動いている間は残ります。
ただし、サーバを停止したり再起動したりすると、アプリケーションスコープに保存されていたインスタンスは消滅します。
図2:教材ページ評価ボタン機能のしくみ

この図から分かること
LessonIndex.javaは、教材ページのトップ画面に関するリクエストを処理するコントローラです。
最初に、ServletContextを使ってアプリケーションスコープからPageFeedbackインスタンスを取得します。まだ保存されていない場合は、新しくPageFeedbackインスタンスを作成します。
評価リンクがクリックされた場合は、actionの値を確認します。action=helpfulなら役に立ったの数を増やし、action=notHelpfulならもう少しの数を増やします。
更新されたPageFeedbackインスタンスはアプリケーションスコープに保存され、lessonIndex.jspで取得されて画面に表示されます。
処理全体の流れ
教材ページ評価ボタン機能は、同じLessonIndex.javaにアクセスしながら、actionの値によって動きを変えます。
初回表示の流れ
| 順番 | 内容 |
|---|---|
| 1 | ブラウザからLessonIndexへGETリクエストを送る |
| 2 | LessonIndexのdoGetメソッドが実行される |
| 3 | アプリケーションスコープからPageFeedbackを取得する |
| 4 | 取得結果がnullならPageFeedbackを新しく作成する |
| 5 | アプリケーションスコープにPageFeedbackを保存する |
| 6 | lessonIndex.jspへフォワードする |
| 7 | 教材ページのトップ画面が表示される |
初回アクセス時は、まだアプリケーションスコープに評価情報が保存されていません。
そのため、getAttributeの戻り値はnullになります。この場合は、PageFeedbackインスタンスを新しく作成します。
評価リンクをクリックしたときの流れ
| 順番 | 内容 |
|---|---|
| 1 | 役に立ったまたはもう少しのリンクをクリックする |
| 2 | action付きでLessonIndexへGETリクエストを送る |
| 3 | アプリケーションスコープからPageFeedbackを取得する |
| 4 | actionの値を確認する |
| 5 | PageFeedbackLogicで該当する評価数を増やす |
| 6 | 更新後のPageFeedbackをアプリケーションスコープに保存する |
| 7 | lessonIndex.jspへフォワードする |
| 8 | 更新後の評価数が表示される |
評価情報はアプリケーションスコープに保存されるため、別のユーザーがアクセスした場合でも、更新後の人数が表示されます。
リクエストパラメータactionで評価を判断する
このアプリケーションでは、どの評価リンクがクリックされたかをactionというリクエストパラメータで判断します。
役に立ったをクリックした場合はaction=helpful、もう少しをクリックした場合はaction=notHelpfulを送信します。
LessonIndex.javaでは、request.getParameter("action")でactionの値を取得します。
actionの値と処理
| actionの値 | 判断する内容 | 実行する処理 |
|---|---|---|
| null | 初回表示または通常表示 | 評価数を増やさずに画面を表示する |
| helpful | 役に立ったがクリックされた | 役に立ったの数を1増やす |
| notHelpful | もう少しがクリックされた | もう少しの数を1増やす |
初回表示ではactionを送信しないため、actionの値はnullになります。
この場合、評価処理は行わず、現在の評価数を表示します。
JavaBeansを作成する
まず、教材ページの評価情報を持つJavaBeansを作成します。
PageFeedback.javaには、役に立ったの数と、もう少しの数をフィールドとして用意します。
教材ページ評価に関する情報を持つJavaBeansの例
ファイル名: PageFeedback.java
package model;
import java.io.Serializable;
public class PageFeedback implements Serializable {
private int helpful;
private int notHelpful;
public PageFeedback() {
helpful = 0;
notHelpful = 0;
}
public int getHelpful() {
return helpful;
}
public void setHelpful(int helpful) {
this.helpful = helpful;
}
public int getNotHelpful() {
return notHelpful;
}
public void setNotHelpful(int notHelpful) {
this.notHelpful = notHelpful;
}
}PageFeedback.javaは、modelパッケージに作成します。
このクラスは、教材ページの評価数をまとめて保持するJavaBeansです。
PageFeedback.javaのポイント
PageFeedback.javaでは、helpfulとnotHelpfulという2つのフィールドを用意しています。
PageFeedbackが持つ情報
| フィールド | 内容 |
|---|---|
| helpful | 役に立ったの数 |
| notHelpful | もう少しの数 |
コンストラクタでは、helpfulとnotHelpfulに0を設定しています。
そのため、初めてPageFeedbackインスタンスを作成したときは、どちらの評価数も0から始まります。
アプリケーションスコープに保存するインスタンスとして扱うため、Serializableを実装し、フィールドはprivateにしています。値の取得や設定はgetterとsetterを通して行います。
評価処理を行うモデルを作成する
次に、教材ページ評価に関する処理を行うモデルを作成します。
PageFeedbackLogic.javaでは、役に立ったの数を増やす処理と、もう少しの数を増やす処理を用意します。
教材ページ評価に関する処理を行うモデルの例
ファイル名: PageFeedbackLogic.java
package model;
public class PageFeedbackLogic {
public void helpful(PageFeedback feedback) {
int count = feedback.getHelpful();
feedback.setHelpful(count + 1);
}
public void notHelpful(PageFeedback feedback) {
int count = feedback.getNotHelpful();
feedback.setNotHelpful(count + 1);
}
}PageFeedbackLogic.javaもmodelパッケージに作成します。
このクラスは評価数を増やす処理だけを担当します。画面表示は行いません。また、アプリケーションスコープを直接操作することもありません。
PageFeedbackLogic.javaの役割
PageFeedbackLogic.javaは、PageFeedbackインスタンスを受け取り、評価数を変更します。
処理の内容
| メソッド | 内容 |
|---|---|
| helpful | 役に立ったの数を1増やす |
| notHelpful | もう少しの数を1増やす |
LessonIndex.javaは、actionの値を見て、どちらのメソッドを呼び出すかを判断します。
action=helpfulならhelpfulメソッドを呼び出します。
action=notHelpfulならnotHelpfulメソッドを呼び出します。
PageFeedbackLogicが変更したPageFeedbackインスタンスは、その後アプリケーションスコープに保存され、JSPで表示されます。
コントローラを作成する
次に、教材ページのトップ画面に関するリクエストを処理するサーブレットを作成します。
LessonIndex.javaは、アプリケーションスコープからPageFeedbackインスタンスを取得し、必要に応じて評価数を増やします。
最後に、PageFeedbackをアプリケーションスコープに保存し、lessonIndex.jspへフォワードします。
教材ページのトップ画面に関するリクエストを処理するコントローラの例
ファイル名: LessonIndex.java
package servlet;
import java.io.IOException;
import jakarta.servlet.RequestDispatcher;
import jakarta.servlet.ServletContext;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import model.PageFeedback;
import model.PageFeedbackLogic;
@WebServlet("/LessonIndex")
public class LessonIndex extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
// アプリケーションスコープに保存された教材ページ評価を取得
ServletContext application = this.getServletContext();
PageFeedback pageFeedback =
(PageFeedback) application.getAttribute("pageFeedback");
// 教材ページ評価の初期化
if (pageFeedback == null) {
pageFeedback = new PageFeedback();
}
// リクエストパラメータの取得
request.setCharacterEncoding("UTF-8");
String action = request.getParameter("action");
// 教材ページの評価処理
PageFeedbackLogic pageFeedbackLogic =
new PageFeedbackLogic();
if (action != null && action.equals("helpful")) {
pageFeedbackLogic.helpful(pageFeedback);
} else if (action != null && action.equals("notHelpful")) {
pageFeedbackLogic.notHelpful(pageFeedback);
}
// アプリケーションスコープに教材ページ評価を保存
application.setAttribute("pageFeedback", pageFeedback);
// フォワード
RequestDispatcher dispatcher =
request.getRequestDispatcher(
"WEB-INF/jsp/lessonIndex.jsp");
dispatcher.forward(request, response);
}
}LessonIndex.javaは、servletパッケージに作成します。
URLパターンは/LessonIndexです。ブラウザからhttp://localhost:8080/study/LessonIndexへアクセスすると、doGetメソッドが実行されます。
LessonIndex.javaのポイント
LessonIndex.javaでは、アプリケーションスコープの取得、評価情報の初期化、actionによる評価処理、アプリケーションスコープへの保存、JSPへのフォワードを行っています。
doGetメソッドの主な処理
| 順番 | 内容 |
|---|---|
| 1 | getServletContextでServletContextを取得する |
| 2 | application.getAttributeでPageFeedbackを取得する |
| 3 | PageFeedbackがnullなら新しく作成する |
| 4 | request.getParameterでactionを取得する |
| 5 | actionに応じて評価数を増やす |
| 6 | application.setAttributeでPageFeedbackを保存する |
| 7 | lessonIndex.jspへフォワードする |
アプリケーションスコープを使う場合、最初のアクセスではインスタンスがまだ保存されていないことがあります。
そのため、getAttributeの結果がnullだった場合は、新しいインスタンスを作成する処理が必要です。
初回表示時はgetAttributeがnullになる
初めてLessonIndexにアクセスしたとき、アプリケーションスコープにはまだpageFeedbackが保存されていません。
その状態でapplication.getAttribute("pageFeedback")を実行すると、nullが返されます。
このままJSPで表示しようとすると、PageFeedbackインスタンスが存在しないため、正しく表示できません。
そこで、nullの場合はnew PageFeedbackでインスタンスを作成します。
初回表示時の処理
| 状況 | 処理 |
|---|---|
| pageFeedbackが取得できた | 既存の評価情報を使う |
| pageFeedbackがnull | 新しいPageFeedbackを作成する |
この初期化処理により、初回アクセス時でも役に立った 0人、もう少し 0人として画面を表示できます。
actionの値によって評価処理を分ける
LessonIndex.javaでは、actionの値によって処理を分けています。
初回表示ではactionが送信されないため、actionはnullです。この場合、評価数は増やしません。
役に立ったリンクをクリックした場合は、action=helpfulが送信されます。
もう少しリンクをクリックした場合は、action=notHelpfulが送信されます。
分岐処理
| 条件 | 処理 |
|---|---|
| actionがnull | 評価処理を行わない |
| actionがhelpful | 役に立ったの数を増やす |
| actionがnotHelpful | もう少しの数を増やす |
リクエストパラメータを使うことで、同じLessonIndex.javaのdoGetメソッドでも、通常表示なのか評価ボタンのクリックなのかを判断できます。
アプリケーションスコープに保存し直す
評価数を変更したあと、PageFeedbackインスタンスをアプリケーションスコープへ保存します。
LessonIndex.javaでは、次の処理で保存しています。
application.setAttribute("pageFeedback", pageFeedback);
保存処理の意味
| 指定 | 内容 |
|---|---|
| pageFeedback | 属性名 |
| pageFeedback変数 | 保存するPageFeedbackインスタンス |
同じ属性名で保存すると、アプリケーションスコープ内の値は上書きされます。
今回のように、評価数を更新したあとは、更新後のPageFeedbackインスタンスをアプリケーションスコープへ保存しておきます。
図3:初回表示と評価クリック時の処理分岐

この図から分かること
LessonIndex.javaでは、まずアプリケーションスコープからPageFeedbackを取得します。
初回表示ではPageFeedbackが保存されていないため、getAttributeの結果はnullになります。その場合は、新しいPageFeedbackインスタンスを作成します。
次に、actionの値を確認します。action=helpfulなら役に立ったの数を増やし、action=notHelpfulならもう少しの数を増やします。actionがnullなら、評価処理は行わず画面を表示します。
最後に、PageFeedbackをアプリケーションスコープへ保存し、lessonIndex.jspへフォワードします。
教材ページのトップ画面を作成する
最後に、教材ページのトップ画面を表示するJSPを作成します。
lessonIndex.jspでは、アプリケーションスコープからPageFeedbackインスタンスを取得し、評価数を表示します。
また、役に立ったともう少しのリンクには、それぞれactionパラメータを付けます。
教材ページのトップ画面を出力するビューの例
ファイル名: lessonIndex.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" %>
<%@ page import="model.PageFeedback" %>
<%
PageFeedback pageFeedback =
(PageFeedback) application.getAttribute("pageFeedback");
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Java入門教材ページ</title>
</head>
<body>
<h1>Java入門教材ページへようこそ</h1>
<p>
<a href="LessonIndex?action=helpful">役に立った</a>:
<%= pageFeedback.getHelpful() %>人
<a href="LessonIndex?action=notHelpful">もう少し</a>:
<%= pageFeedback.getNotHelpful() %>人
</p>
<h2>このページについて</h2>
<p>このページでは、JavaとWebアプリケーション開発の基礎を学習できます。</p>
</body>
</html>lessonIndex.jspは、src/main/webapp/WEB-INF/jspディレクトリに作成します。
WEB-INF内にあるJSPは、ブラウザから直接リクエストできません。LessonIndex.javaからフォワードして表示します。
lessonIndex.jspのポイント
lessonIndex.jspでは、application暗黙オブジェクトを使って、アプリケーションスコープからPageFeedbackを取得しています。
JSPで確認する点
| 処理 | 内容 |
|---|---|
| page import="model.PageFeedback" | JSPでPageFeedback型を使えるようにする |
| application.getAttribute("pageFeedback") | アプリケーションスコープから評価情報を取得する |
| (PageFeedback) | Object型からPageFeedback型へキャストする |
| getHelpful | 役に立ったの数を表示する |
| getNotHelpful | もう少しの数を表示する |
JSPでは、ServletContextを取得するためにgetServletContextを使う必要はありません。
暗黙オブジェクトapplicationをそのまま使って、アプリケーションスコープを操作できます。
評価リンクでactionを送信する
lessonIndex.jspでは、評価リンクにリクエストパラメータを付けています。
役に立ったリンクでは、LessonIndex?action=helpfulへアクセスします。
もう少しリンクでは、LessonIndex?action=notHelpfulへアクセスします。
評価リンクの対応
| リンク | 送信されるaction | 増える評価 |
|---|---|---|
| 役に立った | helpful | helpfulの数 |
| もう少し | notHelpful | notHelpfulの数 |
リンクをクリックすると、LessonIndexへGETリクエストが送られます。
LessonIndex.javaでは、request.getParameter("action")でactionの値を取得し、どちらの評価数を増やすかを判断します。
実行方法
4つのファイルを作成したら、LessonIndex.javaを実行して動作を確認します。
ブラウザから実行する場合は、次のURLへアクセスします。
または、EclipseでLessonIndex.javaを選択し、サーバーで実行します。
ブラウザの表示例:初回表示時

ブラウザの表示例:「役に立った」「もう少し」をクリック後

動作確認の流れ
| 操作 | 表示される内容 |
|---|---|
| LessonIndexへアクセスする | 教材ページのトップ画面が表示される |
| 役に立ったをクリックする | 役に立ったの人数が1増える |
| もう少しをクリックする | もう少しの人数が1増える |
| ブラウザを閉じて再度アクセスする | アプリケーションスコープに残っていれば人数が保持される |
アプリケーションスコープの効果として、ブラウザを閉じたあとに再度アクセスしても、評価数が残っていることを確認できます。
これは、評価情報がユーザーごとのセッションスコープではなく、Webアプリケーション全体のアプリケーションスコープに保存されているためです。
サーバを再起動すると評価数は戻る
アプリケーションスコープに保存したインスタンスは、Webアプリケーションが動いている間だけ利用できます。
そのため、サーバを停止したり再起動したりすると、アプリケーションスコープに保存されていたPageFeedbackインスタンスは消滅します。
その後、再びLessonIndexへアクセスすると、pageFeedbackがnullになり、新しいPageFeedbackインスタンスが作成されます。
その結果、役に立ったともう少しの数は0に戻ります。
ブラウザの表示例:サーバ再起動直後

評価数が消えるタイミング
| 操作 | 評価数 |
|---|---|
| ブラウザを閉じる | 基本的には残る |
| 別のブラウザからアクセスする | 同じアプリケーションスコープの値を表示する |
| サーバを停止する | 消える |
| サーバを再起動する | 消える |
| Webアプリケーションが再読み込みされる | 消えることがある |
開発中に評価数が急に0に戻った場合は、サーバが再起動していないか、Webアプリケーションが再読み込みされていないかを確認しましょう。
アプリケーションスコープを使うときの注意
アプリケーションスコープは、すべてのユーザーで共有されます。
今回の評価数のように、全ユーザーで共通して扱いたい情報には向いています。
一方で、ユーザーごとに異なる情報を保存する場所としては向いていません。
アプリケーションスコープに向いている情報と向いていない情報
| 情報 | 向き不向き | 理由 |
|---|---|---|
| 教材ページの評価数 | 向いている | 全ユーザーで共有する情報だから |
| サイト全体のお知らせ | 向いている | すべてのユーザーに同じ内容を表示するから |
| ログイン中のユーザー情報 | 向いていない | ユーザーごとに分ける必要があるから |
| 個人の入力途中データ | 向いていない | 他のユーザーと共有してはいけないから |
アプリケーションスコープは、みんなで使う共有スペースのようなものです。
個人ごとの情報ではなく、Webアプリケーション全体で共通して扱いたい情報を保存します。
確認したいポイント
アプリケーションスコープを使ったWebアプリケーションでは、次の点を確認しましょう。
| 確認項目 | 内容 |
|---|---|
| URLパターン | @WebServlet("/LessonIndex")になっているか |
| 実行URL | http://localhost:8080/study/LessonIndexになっているか |
| JSPの保存場所 | WEB-INF/jspに配置しているか |
| ServletContextの取得 | getServletContextでapplicationを取得しているか |
| 初回表示の判定 | getAttributeの結果がnullならインスタンスを作成しているか |
| 属性名 | pageFeedbackで保存と取得をそろえているか |
| actionの値 | helpfulとnotHelpfulで処理を分けているか |
| 評価処理 | PageFeedbackLogicで人数を増やしているか |
| アプリケーションスコープへの保存 | application.setAttributeで保存しているか |
| JSPでの取得 | application.getAttributeで取得しているか |
アプリケーションスコープを使うと、Webアプリケーション全体で共有する情報を扱えるようになります。
今回の評価ボタン機能では、PageFeedbackインスタンスをアプリケーションスコープに保存することで、すべてのユーザーで共通の評価数を表示できます。
ブラウザを閉じても評価数が残る一方で、サーバの停止や再起動によって消滅する点も、動作確認しながら押さえておきましょう。
