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

サーブレットで保存し、JSPで取り出す。リクエストスコープで処理結果を画面へつなげよう

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

ただし、処理を転送できるだけでは、サーブレットとJSPの連携はまだ完成しません。サーブレットで作成した処理結果を、JSPで表示したい場合には、そのデータを渡す仕組みが必要です。

そこで使うのがリクエストスコープです。

リクエストスコープは、1回のリクエストの中で利用できるスコープです。サーブレットで作成したJavaBeansインスタンスをリクエストスコープに保存し、その後JSPへフォワードすれば、JSP側で同じインスタンスを取り出して表示に使えます。

たとえば、サーブレットでおすすめメニューを決定し、その結果をMenuResultインスタンスとして作成したとします。このMenuResultをリクエストスコープに保存してからmenu-result.jspへフォワードすれば、JSPファイルはリクエストスコープからMenuResultを取得し、メニュー名やコメントを画面に表示できます。

この記事では、リクエストスコープの特徴、setAttributeによる保存、getAttributeによる取得、JSPでの利用方法、そしてキャストや属性名の注意点を順番に解説します。

リクエストスコープとは

リクエストスコープとは、リクエストごとに作られるスコープです。

ブラウザからサーブレットへ1回のリクエストが送られると、そのリクエストの中で利用できる保存領域が用意されます。これがリクエストスコープです。

リクエストスコープに保存したインスタンスは、レスポンスがブラウザへ返されるまで利用できます。

リクエストスコープの特徴

特徴内容
作られるタイミングリクエストごとに作られる
利用できる期間レスポンスが返されるまで
主な使い道サーブレットからJSPへ処理結果を渡す
共有できる相手同じリクエスト内で処理されるサーブレットやJSP

リクエストスコープは、特にフォワードと組み合わせて使う場面が多くあります。

サーブレットで処理結果を作成し、それをリクエストスコープに保存します。その後、JSPへフォワードすると、JSP側で保存されたインスタンスを取り出せます。

リクエストスコープでサーブレットとJSPをつなぐ

サーブレットからJSPへフォワードするだけでは、サーブレットで作成したインスタンスをJSPで自動的に利用できるわけではありません。

そこで、サーブレットは処理結果をリクエストスコープに保存します。

JSPは、フォワードされたあとにリクエストスコープからそのインスタンスを取得し、画面表示に利用します。

リクエストスコープを使った基本の流れ

順番内容
1サーブレットでJavaBeansインスタンスを生成する
2request.setAttributeでリクエストスコープに保存する
3JSPファイルへフォワードする
4JSPでrequest.getAttributeを使って取得する
5取得したインスタンスのプロパティを画面に出力する

この流れを使うことで、サーブレットは処理を担当し、JSPは表示を担当する形にできます。

MVCモデルで考えると、サーブレットがコントローラ、JSPがビューとして動きやすくなります。

図1:リクエストスコープで処理結果をJSPへ渡す流れ

この図から分かること

リクエストスコープを使うと、サーブレットで作成したインスタンスをJSPへ渡せます。

MenuServletは、処理結果としてMenuResultインスタンスを作成します。そのインスタンスをリクエストスコープに保存してからJSPへフォワードすると、menu-result.jspは同じリクエストスコープからMenuResultを取得できます。

このように、リクエストスコープはフォワード元とフォワード先でインスタンスを共有するための保存場所として働きます。

リクエストスコープの正体

リクエストスコープの正体は、HttpServletRequestインスタンスです。

サーブレットのdoGetメソッドやdoPostメソッドには、HttpServletRequest requestが引数として渡されます。このrequestに対してメソッドを使うことで、リクエストスコープを操作できます。

つまり、リクエストスコープを使うということは、HttpServletRequestインスタンスにインスタンスを保存したり、そこから取り出したりすることだと考えられます。

リクエストスコープの操作

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

フォームの値を取得するときにはrequest.getParameterを使いました。

リクエストスコープに保存したインスタンスを取得するときにはrequest.getAttributeを使います。名前が似ているため、使い分けを意識しましょう。

リクエストパラメータとリクエストスコープの違い

requestという同じオブジェクトを使うため、リクエストパラメータとリクエストスコープは混同しやすいところです。

リクエストパラメータは、フォームやURLから送られてきた名前=値のデータです。一方、リクエストスコープは、サーブレット側で作成したインスタンスを保存しておく領域です。

2つの違い

項目リクエストパラメータリクエストスコープ
主な目的ブラウザから送られた値を受け取るサーブレットとJSPでインスタンスを共有する
取得方法request.getParameterrequest.getAttribute
保存方法ブラウザから送られるrequest.setAttributeで保存する
扱う値文字列として取得することが多いJavaBeansなどのインスタンスを扱える

フォームから送られた入力値を取得したい場合はgetParameterを使います。

サーブレットで作成したJavaBeansをJSPへ渡したい場合はsetAttributeとgetAttributeを使います。

リクエストスコープにインスタンスを保存する

リクエストスコープにインスタンスを保存するには、request.setAttributeを使います。

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

setAttributeの基本

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

属性名とは、スコープに保存したインスタンスを管理するための名前です。

あとでインスタンスを取得するときには、この属性名を使います。

たとえば、menuResultという属性名でMenuResultインスタンスを保存した場合、JSP側でもmenuResultという属性名を指定して取得します。

保存時の注意点

注意点内容
属性名は大文字と小文字を区別するmenuResultとmenuresultは別名として扱われる
同じ属性名で保存すると上書きされるすでに保存済みのインスタンスは新しい値に置き換わる
第2引数はObject型さまざまなクラスのインスタンスを保存できる

属性名は、サーブレット側とJSP側をつなぐ合言葉のようなものです。名前が少しでも違うと、JSP側で取得できません。

リクエストスコープからインスタンスを取得する

リクエストスコープに保存したインスタンスを取得するには、request.getAttributeを使います。

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

ただし、getAttributeの戻り値はObject型です。そのため、取得したインスタンスを元の型として扱うにはキャストが必要です。

getAttributeの基本

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

たとえば、MenuResult型のインスタンスをmenuResultという属性名で保存した場合、取得時にはMenuResult型にキャストします。

Object型として返ってきたものを、改めてMenuResultとして扱えるようにする、というイメージです。

図2:setAttributeとgetAttributeの対応

この図から分かること

リクエストスコープへ保存するときはrequest.setAttributeを使います。

保存時には、属性名とインスタンスを指定します。あとで取得するときには、同じ属性名をrequest.getAttributeに指定します。

getAttributeの戻り値はObject型なので、取得後に元の型へキャストします。MenuResultとして保存したインスタンスを使いたい場合は、MenuResult型として取り出す必要があります。

サーブレットクラスでリクエストスコープを利用する例

ここでは、サーブレットクラスでMenuResultインスタンスを作成し、リクエストスコープへ保存する例を見てみましょう。

MenuResultは、メニュー名とコメントを持つJavaBeansです。サーブレットで作成したMenuResultをmenuResultという属性名でリクエストスコープに保存し、その後で同じ属性名を使って取得しています。

サーブレットクラスでリクエストスコープを利用する例

ファイル名: MenuScopeServlet.java

package servlet;

import java.io.IOException;

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

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

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

        // リクエストスコープに保存するインスタンスの生成
        MenuResult menuResult = new MenuResult(
                "チキンカレー",
                "午後も集中しやすい定番メニューです");

        // リクエストスコープにインスタンスを保存
        request.setAttribute("menuResult", menuResult);

        // リクエストスコープからインスタンスを取得
        MenuResult result =
                (MenuResult) request.getAttribute("menuResult");
    }
}

この例では、MenuResultインスタンスを生成し、request.setAttributeでリクエストスコープに保存しています。

その後、request.getAttributeで同じインスタンスを取得しています。

実際のWebアプリケーションでは、サーブレットでリクエストスコープに保存したあと、JSPファイルへフォワードし、JSP側で取得して表示する流れになります。

setAttributeのポイント

MenuScopeServlet.javaで特に重要なのは、次の処理です。

request.setAttribute("menuResult", menuResult);

この処理では、menuResultという属性名で、MenuResultインスタンスをリクエストスコープへ保存しています。

setAttributeで指定している内容

指定内容
menuResult属性名
menuResult変数保存するMenuResultインスタンス

第1引数のmenuResultは、リクエストスコープ内でインスタンスを管理するための名前です。

第2引数のmenuResultは、実際に保存するインスタンスです。

同じ名前に見えますが、役割は違います。第1引数は属性名で、第2引数はJavaの変数です。

同じ属性名で保存すると上書きされる

リクエストスコープに同じ属性名でインスタンスを保存した場合、あとから保存したインスタンスで上書きされます。

たとえば、menuResultという属性名で一度インスタンスを保存し、その後もう一度menuResultという属性名で別のインスタンスを保存すると、前のインスタンスは新しいインスタンスに置き換わります。

属性名の扱い

状況結果
異なる属性名で保存するそれぞれ別のインスタンスとして保存される
同じ属性名で保存する後から保存したインスタンスで上書きされる
属性名の大文字小文字が違う別の属性名として扱われる

属性名は、JSP側で取得するときにも使います。

そのため、名前を分かりやすくし、保存側と取得側で必ず一致させることが大切です。

getAttributeのポイント

リクエストスコープからインスタンスを取得するには、request.getAttributeを使います。

MenuScopeServlet.javaでは、次のように取得しています。

MenuResult result = (MenuResult) request.getAttribute("menuResult");

この処理では、menuResultという属性名で保存されているインスタンスを取得し、MenuResult型にキャストしています。

getAttributeで指定している内容

指定内容
menuResult取得するインスタンスの属性名
MenuResult取得後に扱いたい型
result取得したインスタンスを代入する変数

getAttributeはObject型を返します。

そのため、MenuResultとして扱うには、MenuResult型へのキャストが必要です。

キャストを忘れると、MenuResultのgetMenuNameやgetCommentのようなメソッドをそのまま使えません。

キャストが必要な理由

request.getAttributeの戻り値はObject型です。

Object型は、Javaのさまざまなインスタンスを表せる大きな型です。リクエストスコープにはさまざまなクラスのインスタンスを保存できるため、getAttributeは具体的な型ではなくObject型で返します。

しかし、プログラムの中でMenuResultとして使いたい場合は、Object型のままでは不便です。

そこで、次のようにキャストしてMenuResult型として受け取ります。

MenuResult result = (MenuResult) request.getAttribute("menuResult");

キャストのイメージ

状態内容
getAttribute直後Object型として返される
キャスト後MenuResult型として扱える
キャスト後にできることgetMenuNameやgetCommentを呼び出せる

キャストは、あいまいなObject型として返ってきたインスタンスを、元の型として扱い直すための処理です。

属性名が存在しない場合はnullになる

request.getAttributeに指定した属性名のインスタンスが保存されていない場合、戻り値はnullになります。

たとえば、サーブレット側でmenuResultという属性名で保存しているのに、JSP側でmenuresultと指定した場合、属性名が一致しません。

menuResultとmenuresultは大文字小文字が違うため、別の属性名として扱われます。

nullになりやすい原因

原因内容
属性名のスペルミスmenuResultとmenuResltなど
大文字小文字の違いmenuResultとmenuresultなど
setAttributeを実行していないそもそも保存されていない
フォワードしていない同じリクエスト内でJSPに渡っていない
リダイレクトしている新しいリクエストになり、リクエストスコープを引き継げない

リクエストスコープから値が取得できないときは、まず属性名が一致しているかを確認しましょう。

JSPファイルでリクエストスコープを利用する

JSPファイルでは、暗黙オブジェクトであるrequestを使ってリクエストスコープを操作できます。

サーブレットクラスでは、doGetやdoPostの引数としてHttpServletRequest requestを受け取りました。

JSPファイルでは、requestは暗黙オブジェクトとしてあらかじめ用意されています。そのため、自分で宣言しなくてもrequest.getAttributeを使えます。

JSPで利用するときの流れ

順番内容
1サーブレットでMenuResultをリクエストスコープに保存する
2JSPへフォワードする
3JSPでrequest.getAttributeを使って取得する
4MenuResult型にキャストする
5getterを使ってプロパティの値を表示する

JSPは、リクエストスコープに保存されたJavaBeansを取り出し、そのプロパティを画面に表示する役割を持つことが多くなります。

JSPファイルでリクエストスコープから取得して表示する例

ここでは、リクエストスコープに保存されたMenuResultインスタンスを取得し、メニュー名とコメントを表示するJSPファイルを作成します。

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

JSPファイルでリクエストスコープを利用する例

ファイル名: menu-result.jsp

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

<%
    // リクエストスコープからインスタンスを取得
    MenuResult result =
            (MenuResult) request.getAttribute("menuResult");
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>おすすめメニュー結果</title>
</head>
<body>
<p>本日のおすすめメニューは「<%= result.getMenuName() %>」です。</p>
<p><%= result.getComment() %></p>
</body>
</html>

このJSPファイルでは、request.getAttribute("menuResult")を使って、リクエストスコープからMenuResultインスタンスを取得しています。

取得したインスタンスはObject型で返されるため、MenuResult型にキャストしています。

その後、result.getMenuNameとresult.getCommentを使って、MenuResultが持っているプロパティの値を画面に出力しています。

JSPでインポートが必要になる理由

menu-result.jspでは、MenuResult型を使っています。

JSPファイルの中でMenuResult型を使用するには、そのクラスをインポートする必要があります。

そのため、pageディレクティブでmodel.MenuResultをインポートしています。

インポートの役割

記述役割
page import="model.MenuResult"JSP内でMenuResult型を使えるようにする

MenuResultのようなJavaBeansクラスは、modelパッケージに所属しています。

パッケージに所属しているクラスをJSPで使う場合は、importで読み込む必要があります。

反対に、パッケージに入っていないクラスはインポートできません。スコープに保存してJSPで利用するJavaBeansを作成するときは、modelパッケージなどに入れておくことを忘れないようにしましょう。

図3:JSPでリクエストスコープからJavaBeansを取得する

この図から分かること

JSPファイルでは、暗黙オブジェクトrequestを使ってリクエストスコープからインスタンスを取得できます。

取得したインスタンスはObject型として返されるため、MenuResult型にキャストします。その後、getterを使ってmenuNameやcommentの値を取り出し、HTML内に出力します。

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

JSPはJavaBeansのプロパティを出力するビュー

MVCモデルでは、JSPファイルは画面表示を担当するビューとして使うことが多くなります。

サーブレットは処理を行い、処理結果をJavaBeansとしてリクエストスコープに保存します。

JSPは、そのJavaBeansをリクエストスコープから取り出し、プロパティの値を画面に出力します。

MVCモデルでの役割

担当役割
サーブレット処理結果を作成し、リクエストスコープに保存する
リクエストスコープサーブレットとJSPの間でインスタンスを共有する
JSPJavaBeansを取得し、プロパティの値を画面に表示する

menu-result.jspでは、MenuResultのgetMenuNameとgetCommentを呼び出して、メニュー名とコメントを表示しています。

このように、JSPはリクエストスコープに保存されているJavaBeansのプロパティを出力する役割を担当します。

保存側と取得側で属性名を一致させる

リクエストスコープを使うときに特に重要なのは、保存側と取得側で属性名を一致させることです。

サーブレット側でmenuResultという属性名で保存した場合、JSP側でもmenuResultという属性名で取得します。

属性名の対応

サーブレット側JSP側
request.setAttribute("menuResult", menuResult)request.getAttribute("menuResult")

属性名が違うと、JSP側では保存されたインスタンスを見つけられません。

また、属性名は大文字と小文字を区別します。menuResultとMenuResultは別の属性名として扱われます。

属性名は、短すぎず、何を保存しているのか分かる名前にすると、あとで確認しやすくなります。

リクエストスコープはレスポンスまで利用できる

リクエストスコープに保存したインスタンスは、レスポンスが返されるまで利用できます。

サーブレットで保存し、JSPへフォワードし、JSPが結果画面を作成してブラウザへ返すまでが、同じリクエストの中で行われます。

その間であれば、リクエストスコープに保存したインスタンスを取得できます。

利用できる範囲

状況リクエストスコープを利用できるか
サーブレットからJSPへフォワードする利用できる
同じリクエスト内で処理が続く利用できる
レスポンスが返された後利用できない
リダイレクトして別リクエストになる引き継げない

リクエストスコープは、長く保存しておくための場所ではありません。

あくまで、1回のリクエストの中でサーブレットからJSPへデータを渡すための領域として使います。

リダイレクトではリクエストスコープを引き継げない

リクエストスコープは、1回のリクエストの中で利用できるスコープです。

そのため、リダイレクトを使うとリクエストスコープは引き継がれません。

リダイレクトでは、ブラウザがリダイレクト先へ新しくリクエストし直します。つまり、最初のリクエストとは別のリクエストになります。

その結果、最初のリクエストで保存したリクエストスコープのインスタンスは、リダイレクト先では取得できません。

フォワードとリダイレクトでの違い

転送方法リクエストスコープ
フォワード引き継げる
リダイレクト引き継げない

リクエストスコープに保存したインスタンスをJSPで表示したい場合は、基本的にフォワードを使います。

リクエストスコープ利用時の確認ポイント

リクエストスコープを使うときは、次の点を確認しましょう。

確認項目内容
保存するものJavaBeansなどのインスタンスになっているか
保存方法request.setAttributeを使っているか
属性名保存側と取得側で一致しているか
取得方法request.getAttributeを使っているか
キャスト取得後に元の型へキャストしているか
importJSPで使うJavaBeansのクラスをインポートしているか
転送方法JSPへフォワードしているか
null確認属性名の間違いや保存忘れがないか

リクエストスコープは、サーブレットとJSPを連携させるための基本的な仕組みです。

サーブレットで処理結果を作る、リクエストスコープに保存する、JSPへフォワードする、JSPで取得して表示する。この流れをしっかり押さえると、MVCモデルに沿ったWebアプリケーションの作り方が理解しやすくなります。