サーブレット&JSPの基本|アプリケーションスコープの使い方

全ユーザーで共有するデータを扱う。アプリケーションスコープでWebアプリ全体の共通情報を管理しよう

これまでに、リクエストスコープとセッションスコープを学習しました。

リクエストスコープは、1回のリクエストの中でインスタンスを共有するためのスコープです。サーブレットで作成した処理結果をJSPへ渡すときに利用しました。

セッションスコープは、リクエストをまたいでインスタンスを共有するためのスコープです。入力画面、確認画面、完了画面のように、複数の画面を移動しても同じユーザーの情報を保持したいときに利用しました。

ただし、リクエストスコープもセッションスコープも、基本的にはユーザーごとの処理やデータを扱うためのスコープです。

一方で、Webアプリケーションには、すべてのユーザーで共通して利用したいデータもあります。

たとえば、お知らせ情報、キャンペーン情報、共通の設定情報、アプリケーション全体で共有したいカウント情報などです。

このような、Webアプリケーション全体で共有したいインスタンスを扱うときに使うのがアプリケーションスコープです。

アプリケーションスコープは、1つのWebアプリケーションにつき1つだけ作成されます。そのため、アプリケーションスコープに保存したインスタンスは、そのWebアプリケーション内のすべてのサーブレットクラスやJSPファイルから利用できます。

この記事では、アプリケーションスコープの特徴、Webアプリケーションの開始と終了、ServletContextによる基本操作、JSPでのapplication暗黙オブジェクトの使い方を順番に解説します。

アプリケーションスコープとは

アプリケーションスコープとは、Webアプリケーション全体で共有できるスコープです。

リクエストスコープは1回のリクエストごと、セッションスコープはユーザーごとに用意されました。

それに対して、アプリケーションスコープは1つのWebアプリケーションにつき1つだけ用意されます。

そのため、アプリケーションスコープに保存したインスタンスは、同じWebアプリケーション内のサーブレットクラスやJSPファイルから共通して利用できます。

スコープの大まかな違い

スコープ主な範囲使いどころ
リクエストスコープ1回のリクエスト内サーブレットからJSPへ一時的にデータを渡す
セッションスコープユーザーごとログイン中のユーザー情報などを保持する
アプリケーションスコープWebアプリケーション全体全ユーザーで共有する情報を保持する

アプリケーションスコープは、特定のユーザーだけのものではありません。

同じWebアプリケーションを利用しているすべてのユーザーが、同じアプリケーションスコープを利用します。

すべてのユーザーで共通して使える

アプリケーションスコープの大きな特徴は、全ユーザーで共有できることです。

たとえば、学習サイトに共通のお知らせを表示したい場合を考えます。

青山さんがアクセスしても、山田さんがアクセスしても、同じお知らせ情報を表示したい場合、その情報はユーザーごとに分ける必要がありません。

このような共通情報をアプリケーションスコープに保存しておけば、複数のサーブレットやJSPから同じインスタンスを取り出して利用できます。

アプリケーションスコープに向いている情報

情報の例理由
共通のお知らせすべてのユーザーに同じ内容を表示したい
アプリケーション全体の設定複数の処理で同じ設定を使いたい
共通メッセージさまざまな画面で同じメッセージを表示したい
全体で共有するデータユーザーごとではなくアプリ全体で管理したい

セッションスコープはユーザーごとのスコープです。

アプリケーションスコープは、みんなで共有するスコープです。

この違いを意識すると、どのスコープに何を保存するべきか判断しやすくなります。

図1:アプリケーションスコープの働き

この図から分かること

アプリケーションスコープは、1つのWebアプリケーションにつき1つだけ作成されます。

そのため、同じWebアプリケーションを利用している複数のユーザーが、同じアプリケーションスコープを利用できます。

青山さんのブラウザからアクセスしても、山田さんのブラウザからアクセスしても、同じsiteNoticeインスタンスを取得できます。

このように、アプリケーションスコープはユーザーごとの情報ではなく、Webアプリケーション全体で共有したい情報を扱うためのスコープです。

データベースとアプリケーションスコープの違い

全ユーザーで共有したいデータを扱う場合、一般的にはデータベースを使うことが多くあります。

データベースは、データの保存、検索、更新、保護などに優れています。大量のデータを扱ったり、長期間保存したり、正確に管理したりする場合に向いています。

一方、アプリケーションスコープは、サーバのメモリ上にインスタンスを保存します。そのため、手軽に利用でき、アクセスも高速です。

ただし、データベースのような高度な管理機能や保護機能を備えているわけではありません。

データベースとアプリケーションスコープの比較

比較項目データベースアプリケーションスコープ
保存場所データベース管理システムアプリケーションサーバのメモリ上
データ管理高度な管理ができる手軽にインスタンスを保存できる
データ保護仕組みが整っている自分で管理を考える必要がある
アクセスデータベース接続が必要メモリ上なので扱いやすい
向いている用途永続的に保存したい重要データアプリケーション内で一時的に共有したいデータ

アプリケーションスコープは、データベースの代わりとして何でも保存する場所ではありません。

あくまで、Webアプリケーション全体で共通して利用したいインスタンスを、手軽に扱うためのスコープです。

アプリケーションスコープの有効期間

アプリケーションスコープに保存したインスタンスは、Webアプリケーションが終了するまで利用できます。

リクエストスコープはレスポンスが返るまで、セッションスコープはユーザーのセッションが有効な間、アプリケーションスコープはWebアプリケーションが動いている間です。

保存したインスタンスの寿命

スコープ保存したインスタンスを利用できる期間
リクエストスコープレスポンスが返されるまで
セッションスコープセッションが有効な間
アプリケーションスコープWebアプリケーションが終了するまで

アプリケーションスコープは、3つの中でも特に広い範囲で利用できるスコープです。

ただし、Webアプリケーションが終了すると、アプリケーションスコープに保存していたインスタンスも消滅します。

Webアプリケーションはいつ開始・終了するのか

アプリケーションスコープの有効期間を理解するには、Webアプリケーションがいつ開始され、いつ終了するのかを知っておく必要があります。

Webアプリケーションの開始と終了には、主に次のような場面があります。

Webアプリケーションの開始と終了に関わるもの

場面内容
サーバの起動と停止アプリケーションサーバの起動や停止に合わせてWebアプリケーションも開始、終了する
オートリロード機能ソースコード修正などによりWebアプリケーションが再読み込みされる
管理ツールによる操作管理ツールで特定のWebアプリケーションを開始、終了する

アプリケーションスコープはWebアプリケーションの中に用意されるため、Webアプリケーションが終了すると一緒に消滅します。

サーバを停止したり、再起動したりすると、Webアプリケーションも終了するため、アプリケーションスコープに保存していたインスタンスも利用できなくなります。

サーバの起動と停止

アプリケーションサーバを起動すると、そのサーバ上で動くWebアプリケーションも開始されます。

反対に、アプリケーションサーバを停止すると、その上で動いているWebアプリケーションも終了します。

Eclipseでは、サーバービューからTomcatなどのアプリケーションサーバを起動、停止できます。

また、Eclipseの実行機能でサーブレットクラスを実行したときに、サーバの再起動を促すダイアログが表示されることがあります。

このとき、再起動を選ぶと、サーバの停止と起動が行われます。

サーバ再起動時に起こること

操作起こること
サーバを停止するWebアプリケーションが終了する
サーバを起動するWebアプリケーションが開始する
サーバを再起動するWebアプリケーションが一度終了し、再び開始する
アプリケーションスコープ終了時に保存インスタンスが消滅する

アプリケーションスコープに保存したインスタンスは、サーバの再起動後には残っていません。

開発中にアプリケーションスコープの内容が消えたように見える場合は、サーバが再起動していないかを確認しましょう。

図2:サーバの再起動とアプリケーションスコープの消滅

この図から分かること

アプリケーションスコープは、Webアプリケーションが動いている間だけ利用できます。

サーバを再起動すると、Webアプリケーションは一度終了し、そのあと再び開始されます。この終了のタイミングで、アプリケーションスコープに保存されていたインスタンスは消滅します。

再起動後は、新しいWebアプリケーションとして開始されるため、アプリケーションスコープも新しく用意されます。

オートリロード機能

アプリケーションサーバには、Webアプリケーションを自動的に再読み込みするオートリロード機能があります。

一度実行したサーブレットクラスのソースコードを修正したときに、Webアプリケーションを終了して、もう一度開始するような動きです。

オートリロードが行われると、Webアプリケーションは再読み込みされます。そのため、アプリケーションスコープに保存していたインスタンスも消えることがあります。

Pleiadesに同梱されているApache Tomcatでは、このオートリロード機能がデフォルトで無効になっています。

オートリロードで意識すること

項目内容
目的修正した内容をWebアプリケーションへ反映する
動きWebアプリケーションを再読み込みする
アプリケーションスコープ再読み込みにより内容が消えることがある
Pleiades同梱Tomcatデフォルトではオートリロードが無効

開発中にアプリケーションスコープを使う場合は、サーバの再起動やアプリケーションの再読み込みが起きていないかを意識しましょう。

管理ツールによる開始と終了

アプリケーションサーバには、Webアプリケーションを管理するためのツールが用意されていることがあります。

Apache Tomcatでは、Tomcat Webアプリケーションマネージャを使って、特定のWebアプリケーションを開始したり終了したりできます。

管理ツールでWebアプリケーションを終了すると、そのWebアプリケーションのアプリケーションスコープも終了します。

管理ツールでできること

操作内容
Webアプリケーションの開始指定したWebアプリケーションを起動する
Webアプリケーションの終了指定したWebアプリケーションを停止する
再読み込みWebアプリケーションを終了して再度開始する

アプリケーションスコープは、Webアプリケーションの開始から終了までの間だけ利用できるスコープです。

そのため、管理ツールでWebアプリケーションを終了した場合も、保存していたインスタンスは消滅します。

アプリケーションスコープの正体

アプリケーションスコープの正体は、ServletContextインスタンスです。

リクエストスコープではHttpServletRequestを使いました。

セッションスコープではHttpSessionを使いました。

アプリケーションスコープではServletContextを使います。

スコープと操作に使うインスタンス

スコープ操作に使うインスタンス
リクエストスコープHttpServletRequest
セッションスコープHttpSession
アプリケーションスコープServletContext

サーブレットクラスでServletContextインスタンスを取得するには、getServletContextを使います。

getServletContextは、HttpServletから継承しているメソッドです。

ServletContextを取得する

サーブレットクラスでアプリケーションスコープを利用するには、ServletContextインスタンスを取得します。

取得するときは、次のような形で考えます。

ServletContext application = this.getServletContext();

thisは省略できます。

ServletContextを使うためには、jakarta.servlet.ServletContextをインポートする必要があります。

ServletContext取得のポイント

項目内容
使用するメソッドgetServletContext
取得できるものServletContextインスタンス
変数名の例application
必要なインポートjakarta.servlet.ServletContext
this省略できる

取得したServletContextインスタンスに対して、setAttribute、getAttribute、removeAttributeを使います。

この操作は、リクエストスコープやセッションスコープとよく似ています。

アプリケーションスコープの基本操作

アプリケーションスコープでも、インスタンスの保存、取得、削除にはsetAttribute、getAttribute、removeAttributeを使います。

違うのは、操作する対象がrequestでもsessionでもなく、applicationである点です。

基本操作

操作使用するメソッド
インスタンスを保存するapplication.setAttribute
インスタンスを取得するapplication.getAttribute
インスタンスを削除するapplication.removeAttribute

保存時には属性名とインスタンスを指定します。

取得時には属性名を指定し、Object型で返ってきたインスタンスを元の型へキャストします。

削除時には、削除したいインスタンスの属性名を指定します。

属性名の扱い

アプリケーションスコープでも、属性名は大切です。

属性名は、保存したインスタンスを管理するための名前です。保存するときに指定した属性名を、取得や削除でも使います。

属性名の注意点

注意点内容
大文字と小文字を区別するsiteNoticeとSiteNoticeは別の属性名になる
同じ属性名で保存すると上書きされる後から保存したインスタンスに置き換わる
取得時に一致させる必要がある属性名が違うと取得できない
存在しない属性名を取得するとnullになる保存されていない場合はnullが返る

アプリケーションスコープは全体で共有されるため、属性名が分かりにくいと管理しづらくなります。

何を保存しているのか分かる名前を付けると、あとで確認しやすくなります。

図3:ServletContextでアプリケーションスコープを操作する

この図から分かること

アプリケーションスコープを操作するときは、ServletContextインスタンスを使います。

サーブレットでは、getServletContextでServletContextインスタンスを取得します。その後、application.setAttributeで保存し、application.getAttributeで取得し、application.removeAttributeで削除できます。

JSPでは、暗黙オブジェクトapplicationをそのまま使えます。サーブレットのようにgetServletContextを実行する必要はありません。

サーブレットクラスでアプリケーションスコープを利用する例

ここでは、Webアプリケーション全体で共有するお知らせ情報を、アプリケーションスコープに保存する例を見てみましょう。

その前に、お知らせのタイトルと本文を持つJavaBeansである SiteNotice.java を作成しておきます。

ファイル名: SiteNotice.java

package model;

import java.io.Serializable;

public class SiteNotice implements Serializable {
    private String title;
    private String message;

    public SiteNotice() { }

    public SiteNotice(String title, String message) {
        this.title = title;
        this.message = message;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}

サーブレットクラスでアプリケーションスコープを利用する例

ファイル名: NoticeServlet.java

package servlet;

import java.io.IOException;

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.SiteNotice;

@WebServlet("/NoticeServlet")
public class NoticeServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;

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

        // アプリケーションスコープに保存するインスタンスの生成
        SiteNotice notice = new SiteNotice(
                "学習サイトからのお知らせ",
                "8月分の学習コンテンツを公開しました");

        // ServletContextインスタンスの取得
        ServletContext application = this.getServletContext();

        // アプリケーションスコープにインスタンスを保存
        application.setAttribute("siteNotice", notice);

        // アプリケーションスコープからインスタンスを取得
        SiteNotice savedNotice =
                (SiteNotice) application.getAttribute("siteNotice");

        // アプリケーションスコープからインスタンスを削除
        application.removeAttribute("siteNotice");
    }
}

このサーブレットでは、SiteNoticeインスタンスを作成し、siteNoticeという属性名でアプリケーションスコープに保存しています。

その後、同じ属性名を使って取得し、最後にremoveAttributeで削除しています。

この例は、保存、取得、削除の基本操作を確認するためのものです。

NoticeServlet.javaのポイント

NoticeServlet.javaでは、ServletContextインスタンスを取得してから、アプリケーションスコープを操作しています。

処理の流れ

順番処理内容
1SiteNoticeインスタンスを生成するアプリケーション全体で共有したいお知らせ情報を用意する
2getServletContextを実行するServletContextインスタンスを取得する
3application.setAttributeを実行するsiteNoticeという属性名で保存する
4application.getAttributeを実行するsiteNoticeという属性名で取得する
5application.removeAttributeを実行するsiteNoticeを削除する

アプリケーションスコープは、Webアプリケーション全体で共有されます。

そのため、保存したインスタンスは、同じWebアプリケーション内のほかのサーブレットやJSPからも取得できます。

setAttributeで保存する

アプリケーションスコープにインスタンスを保存するときは、application.setAttributeを使います。

保存時には、属性名と保存するインスタンスを指定します。

setAttributeの指定

引数内容
第1引数属性名をString型で指定する
第2引数保存するインスタンスを指定する

第1引数には、アプリケーションスコープ内で管理する名前を指定します。

第2引数には、保存したいインスタンスを指定します。

第2引数はObject型として扱われるため、さまざまなクラスのインスタンスを保存できます。

getAttributeで取得する

アプリケーションスコープに保存したインスタンスを取得するときは、application.getAttributeを使います。

getAttributeには、取得したいインスタンスの属性名を指定します。

戻り値はObject型です。そのため、元の型として使うにはキャストが必要です。

getAttributeの指定

項目内容
引数取得したいインスタンスの属性名
戻り値Object型
必要な処理元の型へのキャスト
属性名が存在しない場合nullが返る

NoticeServlet.javaでは、siteNoticeという属性名で取得し、SiteNotice型にキャストしています。

Object型として返ってきたインスタンスを、SiteNoticeとして扱えるようにしているわけです。

removeAttributeで削除する

アプリケーションスコープに保存したインスタンスを削除するときは、application.removeAttributeを使います。

removeAttributeには、削除したいインスタンスの属性名を指定します。

removeAttributeの指定

項目内容
使用するメソッドapplication.removeAttribute
引数削除するインスタンスの属性名
削除されるもの指定した属性名で保存されているインスタンス

アプリケーションスコープは、Webアプリケーション全体で共有されるため、不要なインスタンスを残し続けると、思わぬところで使われる可能性があります。

使い終わったインスタンスや、不要になった共通情報は、必要に応じてremoveAttributeで削除します。

JSPファイルでアプリケーションスコープを利用する

JSPファイルでも、アプリケーションスコープを利用できます。

サーブレットでは、getServletContextでServletContextインスタンスを取得しました。

一方、JSPでは、暗黙オブジェクトapplicationがあらかじめ用意されています。

そのため、JSPではgetServletContextを使わずに、application.getAttributeでアプリケーションスコープからインスタンスを取得できます。

サーブレットとJSPでの違い

場所アプリケーションスコープの使い方
サーブレットgetServletContextでServletContextを取得して使う
JSP暗黙オブジェクトapplicationをそのまま使う

JSPでJavaBeansの型を使う場合は、pageディレクティブで対象のクラスをインポートします。

JSPファイルでアプリケーションスコープから取得して表示する例

ここでは、アプリケーションスコープに保存されたSiteNoticeインスタンスをJSPで取得し、お知らせのタイトルと本文を表示します。

SiteNotice型をJSPで使うため、pageディレクティブでmodel.SiteNoticeをインポートします。

JSPファイルでアプリケーションスコープを利用する例

ファイル名: notice.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" %>
<%@ page import="model.SiteNotice" %>
<%
    // アプリケーションスコープからインスタンスを取得
    SiteNotice notice =
            (SiteNotice) application.getAttribute("siteNotice");
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>学習サイトからのお知らせ</title>
</head>
<body>
<h1><%= notice.getTitle() %></h1>
<p><%= notice.getMessage() %></p>
</body>
</html>

このJSPでは、application.getAttribute("siteNotice")を使って、アプリケーションスコープからSiteNoticeインスタンスを取得しています。

getAttributeの戻り値はObject型なので、SiteNotice型へキャストしています。

その後、getTitleとgetMessageを使って、SiteNoticeインスタンスが持つプロパティの値を画面へ出力しています。

notice.jspのポイント

notice.jspでは、暗黙オブジェクトapplicationを使って、アプリケーションスコープからインスタンスを取得しています。

JSPで確認する点

処理内容
page import="model.SiteNotice"JSPでSiteNotice型を使えるようにする
application.getAttribute("siteNotice")アプリケーションスコープからインスタンスを取得する
(SiteNotice)Object型からSiteNotice型へキャストする
getTitleお知らせタイトルを取得する
getMessageお知らせ本文を取得する

JSPでアプリケーションスコープを利用するときも、保存時と取得時の属性名を一致させることが大切です。

NoticeServlet.javaでsiteNoticeという属性名で保存している場合、notice.jspでもsiteNoticeという属性名で取得します。

application暗黙オブジェクト

JSPでは、applicationという暗黙オブジェクトが用意されています。

このapplicationは、アプリケーションスコープを操作するためのオブジェクトです。

サーブレットで取得したServletContextインスタンスと同じように、setAttribute、getAttribute、removeAttributeを使えます。

applicationでできること

操作使用例
保存application.setAttribute
取得application.getAttribute
削除application.removeAttribute

サーブレットではgetServletContextを使ってServletContextを取得しますが、JSPではapplicationをそのまま使えます。

暗黙オブジェクトが違うだけで、保存、取得、削除の考え方は、リクエストスコープやセッションスコープとよく似ています。

3つのスコープの操作を比べる

リクエストスコープ、セッションスコープ、アプリケーションスコープは、操作方法が似ています。

いずれもsetAttribute、getAttribute、removeAttributeを使います。

ただし、操作する対象と保存される範囲が違います。

スコープごとの操作対象

スコープ操作する対象保存取得削除
リクエストスコープrequestrequest.setAttributerequest.getAttributerequest.removeAttribute
セッションスコープsessionsession.setAttributesession.getAttributesession.removeAttribute
アプリケーションスコープapplicationapplication.setAttributeapplication.getAttributeapplication.removeAttribute

どのスコープを使う場合でも、属性名を指定して保存し、同じ属性名で取得します。

getAttributeの戻り値はObject型なので、必要な型へキャストします。

この共通点を押さえておくと、新しいスコープを学んでも混乱しにくくなります。

アプリケーションスコープを使うときの注意

アプリケーションスコープは、Webアプリケーション全体で共有されます。

そのため、ユーザーごとに異なる情報を保存する場所としては向いていません。

たとえば、ログイン中のユーザー情報をアプリケーションスコープに保存してしまうと、すべてのユーザーで同じ情報を共有することになってしまいます。

アプリケーションスコープに向かない情報

情報向かない理由
ログイン中のユーザー情報ユーザーごとに分ける必要がある
個人の入力途中データ他のユーザーと共有してはいけない
個人のカート情報利用者ごとに内容が異なる

ユーザーごとの情報はセッションスコープを使います。

1回のリクエスト内だけで使う処理結果はリクエストスコープを使います。

全ユーザーで共通して使いたい情報だけを、アプリケーションスコープに保存します。

アプリケーションスコープで確認したいこと

アプリケーションスコープを使うときは、次の点を確認しましょう。

確認項目内容
共有したい情報か全ユーザーで使う情報かを確認する
ServletContextを取得しているかサーブレットではgetServletContextを使う
必要なインポートがあるかjakarta.servlet.ServletContextをインポートする
属性名は一致しているか保存、取得、削除で同じ属性名を使う
キャストしているかgetAttributeの戻り値はObject型
JSPではapplicationを使っているか暗黙オブジェクトapplicationを利用する
Webアプリケーションの終了を意識しているか終了すると保存インスタンスは消滅する
ユーザーごとの情報を保存していないか個人情報はセッションスコープなどを使う

アプリケーションスコープは、Webアプリケーション全体で共通利用する情報を扱うためのスコープです。

保存、取得、削除の方法はほかのスコープとよく似ていますが、保存範囲が非常に広い点が特徴です。

ユーザーごとの情報ではなく、全体で共有したい情報を扱うときに利用しましょう。