学習19日目: JSPへ値を送るためのスコープについて。

今日の学習時間。

  • Day:19
  • Today:7h
  • Total:111h

学習内容について。

別のサーブレットにリダイレクトさせる。

package test;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

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

    /**
     * @see HttpServlet#HttpServlet()
     */
    public BeforeRedirectServlet() {
        super();
        // TODO Auto-generated constructor stub
    }

    /**
     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.sendRedirect("/first_webapp/VCServlet");
    }

    /**
     * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // TODO Auto-generated method stub
        doGet(request, response);
    }

}

doGetメソッドのみ変更

doGetメソッド
  • sendRedirect
    • あるサーブレットから別のサーブレットに自動でリダイレクトさせる
  • response.sendRedirect(“/first_webapp/VCServlet”);
    • first_webapp内にあるVCServletへ遷移

 リクエスト・パラメータを受け取る方法。

ブラウザからリクエストされた際に送られてくる情報(パラメータ)をサーブレットで受け取る方法。下記コードはGET通信のサンプル。

package test;

import java.io.IOException;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

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

    /**
     * @see HttpServlet#HttpServlet()
     */
    public GetServlet() {
        super();
        // TODO Auto-generated constructor stub
    }

    /**
     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setCharacterEncoding("UTF-8");

        String q = request.getParameter("q");

        request.setAttribute("q", q);

        RequestDispatcher rd = request.getRequestDispatcher("/WEB-INF/get_result.jsp");
        rd.forward(request, response);
    }

}
doGetメソッド
  • /GetServlet?q=abcというURLの場合
    • abcというデータが格納された変数qをパラメータとして受け取る
  • request.setCharacterEncoding("UTF-8");
    • 文字化けを防止
  • request.getParameter()
    • パラメータを取得
    • 引数にはパラメータの名前(変数名)を文字列として指定
    • 取得した値はすべてString型のデータとなる
      • 値を数値として扱いたい場合は数値への変換処理が必要
  • request.setAttribute("q", q);
    • ビューにデータを送るための命令
  • 最後に、/WEB-INF/get_result.jspへのフォワードを行う
リクエストスコープ
  • スコープ
    • JavaのWebアプリケーションで使用するデータを置いておく場所
    • 上記のGetServletではリクエストスコープを使用
  • リクエストスコープ
    • 有効期限は1回のページ遷移のみ(ひとつのリクエストに対するレスポンスの画面)
    • 基本的にサーブレットからJSPへ値を送る場合に使われる
    • request.setAttribute("q", q);
      • 変数qの内容を、同じqという変数名でJSPの中で扱えるよう、リクエストスコープに格納
    • ①:request.setAttribute()でデータをリクエストスコープに置く
    • ②:JSPからrequest.getAttribute()を実行。リクエストスコープからデータを取り出す
  • 暗黙のオブジェクト
    • 宣言不要のオブジェクト
    • 上記のrequestオブジェクトも含む
    • 他はImplicit Objects
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<% request.setCharacterEncoding("UTF-8"); %>
<!DOCTYPE html>
<html lang="ja">
    <head>
        <meta charset="UTF-8">
        <title>クエリパラメータのテスト</title>
    </head>
    <body>
        <p>送信パラメータ:<%= request.getAttribute("q") %></p>
    </body>
</html>
  • 上記コードはrequest.setAttribute()でデータを送られたJSP
  • request.setCharacterEncoding("UTF-8");
    • 文字化け防止のために追記
  • 動作確認
    • 下記URLにアクセス
    • 末尾のパラメータを変更したら内容もそれに応じて変わることを確認
http://localhost:8090/first_webapp/GetServlet?q=abc

練習問題を解いてみる。

条件
  • サーブレット=コントローラ、JSP=ビューとして使用
  • 三平方の定理を使って直角三角形の斜辺の長さを計算するプログラムを作成
  • リクエストパラメータとしてabを持たせる
    • この2つの辺の長さから、三平方の定理を使ってc2を求める
    • Math.sqrt()で平方根にした数値を斜辺の長さとしてビューに表示
    • 3辺ともに実数値
  • String型から実数値への変換はDouble.parseDouble()を使用
  • 回答例は下記
http://localhost:8080/first_webapp/PythagorasServlet?a=3.0&b=4.0にアクセス

直角をはさむ2辺の長さが 3.0 と 4.0 のとき、 斜辺の長さは 5.0 になります。
package test;

import java.io.IOException;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

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

    /**
     * @see HttpServlet#HttpServlet()
     */
    public PythagorasServlet() {
        super();
        // TODO Auto-generated constructor stub
    }

    /**
     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        request.setCharacterEncoding("UTF-8");

        double a = Double.parseDouble(request.getParameter("a"));
        double b = Double.parseDouble(request.getParameter("b"));

        double c = Math.sqrt(a * a + b * b);

        request.setAttribute("a", a);
        request.setAttribute("b", b);
        request.setAttribute("c", c);

        RequestDispatcher rd = request.getRequestDispatcher("/WEB-INF/calc_c.jsp");
        rd.forward(request, response);
    }

}

リクエストパラメータ a, b を受け取って整数値に変換するところは悩んだ。単純に()内に入れられるのになるほどと思った。

セッションスコープを使ってみる。

  • ユーザがWebアプリケーションを利用している間(セッションが有効な間)、いつでも利用できるデータを置いておく場所のこと
    • 意図的にデータを消去、ブラウザを終了、もしくはセッションの有効期限が切れるまで有効
    • サイトへのログインに関連した処理で利用
  • setAttribute()getAttribute()を使用
    • request.getSession().setAttribute()
    • request.getSession().getAttribute()
  • 意図的にセッションスコープのデータを消去する場合
    • request.getSession().removeAttribute()
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<% request.setCharacterEncoding("UTF-8"); %>
<% request.getSession().setAttribute("username", "きき"); %>
<!DOCTYPE html>
<html lang="ja">
    <head>
        <meta charset="UTF-8">
        <title>セッションスコープのテスト</title>
    </head>
    <body>
        <h1>ログインしました</h1>
        <p><a href="session_b.jsp">次のページへ</a></p>
    </body>
</html>
  1. URLにアクセスしてAのページを表示
    1. Aの3行目で変数usernameを登録
  2. 「次のページへ」のリンクをクリック
  3. 「こんにちは、ききさん!」と表示される
    1. Bの3行目を実行することでセッションスコープからusernameを取り出す
    2. session_b.jsp用の変数usernameにデータを格納
    3. <%= username %>で「きき」と表示
    4. ※request.getSession().getAttribute()で取り出したデータはObject型なので利用したいオブジェクトの型へキャストする必要がある。この場合はString
  4. さらに「次のページへ」のリンクをクリック
  5. 「ログアウトしました」と表示される
    1. Cの3行目でセッションスコープから変数usernameを削除
  6. 「前のページへ」のリンクをクリック
  7. 「こんにちは、nullさん!」と表示される
    1. セッションスコープの中にusernameが存在しないから

アプリケーションスコープを使ってみる。

  • アプリケーションが起動して終了するまでの間に有効なデータを置く場所
  • Webアプリケーション全般的な設定値を格納するための場所
    • ブラウザを終了してもデータが残り続ける
  • request.getServletContext()を実行
    • ServletContextクラスのオブジェクトを取得
    • そのsetAttributegetAttributeを使用
package test;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

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


    public SetAppScopeServlet() {
        super();
    }


    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.getServletContext().setAttribute("app_name", "テストアプリケーション");

        response.setContentType("text/html; charset=UTF-8");
        PrintWriter out = response.getWriter();
        out.println("アプリケーションスコープに登録完了");
    }
}
  1. /SetAppScopeServletにアクセス
    1. サーブレットの23行目で変数app_nameが登録される
  2. ブラウザを終了し、ブラウザを再び起動
  3. /use_appScope.jspにアクセス
    1. JSPの3行目でアプリケーションスコープからapp_nameを取り出す
    2. String型にキャスト
    3. 変数app_nameに格納
    4. <%= app_name %>で「テストアプリケーション」という文字列が表示される

 JSTLとEL式を使ってみる。

MavenとJSPの設定を行う。

STEP
プロジェクト上で右クリック→構成→「Mavenプロジェクトへ変換」。

グループIdはデフォルト状態から変更する。

STEP
pom.xmlが作成されるので開く。
STEP
「依存関係」に下記の情報を追加。
1つ目のJSTL
  • グループId:org.apache.taglibs
  • アーティファクトId:taglibs-standard-impl
  • バージョン:1.2.5
2つ目のJSTL
  • グループId:javax.servlet.jsp.jstl
  • アーティファクトId:javax.servlet.jsp.jstl-api
  • バージョン:1.2.1

入力が完了したらpom.xmlを保存。

STEP
JSPファイルを変更。
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<% request.setCharacterEncoding("UTF-8"); %>
<!DOCTYPE html>
<html lang="ja">
    <head>
        <meta charset="UTF-8">
        <title>クエリパラメータのテスト</title>
    </head>
    <body>
        <p>送信パラメータ:<%= request.getAttribute("q") %></p>
        <p>送信パラメータ:${q}</p>
        <p>送信パラメータ:<c:out value="${q}" /></p>
    </body>
</html>
  • 2行目
    • JSTLのうちのコア機能をcという名前で利用できるようにする設定
  • 13行目
    • スクリプト式をJSTLで置き換えたものが<c:out>タグ
    • value属性には表示したいデータを指定
      • EL式で${名前}という形式で記述
      • 変数名のみを{ }の中に記述するだけで良い

<p>タグの3行は全て同じ表示になる。が、HTMLのタグが含まれていると困るデータの中身を表示する際は<c:out>を利用した方が良い。なぜなら、サニタイジングと呼ばれる「特定の半角記号を無害な形式に変換する(エスケープ)」 セキュリティ対策を自動で施してくれる機能を持っているから。

今日の反省と明日の目標。

スコープは普段使っているWebサイト等でもよく見かける技術なので興味深く学習できました。とはいえ、覚えるのが多くて大変さを感じるようになってきたのも事実です。しかし、どの技術も結局は簡略化するためのものでもあるので、たくさん覚えた方が後から楽になってくるのではないでしょうかね、知らないけど。多分JSTLやEL式も知らなければ、現場で苦労するだろうし。。

難しい部分は出来るだけ頭の中で抽象的に組み立てていきたいところです。頭でガチガチに考えると応用が効かないので。自分だったらこの技術をどう活用するのかシミュレーションを行うことについては今後の学習の中で意識的に取り組んでいきたいですね。

閉じる