今日の学習時間。
- 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=ビューとして使用
- 三平方の定理を使って直角三角形の斜辺の長さを計算するプログラムを作成
- リクエストパラメータとして
a
とb
を持たせる- この2つの辺の長さから、三平方の定理を使って
c2
を求める Math.sqrt()
で平方根にした数値を斜辺の長さとしてビューに表示- 3辺ともに実数値
- この2つの辺の長さから、三平方の定理を使って
- 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>
- URLにアクセスしてAのページを表示
- Aの3行目で変数
username
を登録
- Aの3行目で変数
- 「次のページへ」のリンクをクリック
- 「こんにちは、ききさん!」と表示される
- Bの3行目を実行することでセッションスコープから
username
を取り出す session_b.jsp
用の変数username
にデータを格納<%= username %>
で「きき」と表示- ※request.getSession().getAttribute()で取り出したデータはObject型なので利用したいオブジェクトの型へキャストする必要がある。この場合は
String
- Bの3行目を実行することでセッションスコープから
- さらに「次のページへ」のリンクをクリック
- 「ログアウトしました」と表示される
- Cの3行目でセッションスコープから変数
username
を削除
- Cの3行目でセッションスコープから変数
- 「前のページへ」のリンクをクリック
- 「こんにちは、nullさん!」と表示される
- セッションスコープの中に
username
が存在しないから
- セッションスコープの中に
アプリケーションスコープを使ってみる。
- アプリケーションが起動して終了するまでの間に有効なデータを置く場所
- Webアプリケーション全般的な設定値を格納するための場所
- ブラウザを終了してもデータが残り続ける
request.getServletContext()
を実行ServletContext
クラスのオブジェクトを取得- その
setAttribute
やgetAttribute
を使用
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("アプリケーションスコープに登録完了");
}
}
/SetAppScopeServlet
にアクセス- サーブレットの23行目で変数
app_name
が登録される
- サーブレットの23行目で変数
- ブラウザを終了し、ブラウザを再び起動
/use_appScope.jsp
にアクセス- JSPの3行目でアプリケーションスコープから
app_name
を取り出す - String型にキャスト
- 変数
app_name
に格納 <%= app_name %>
で「テストアプリケーション」という文字列が表示される
- JSPの3行目でアプリケーションスコープから
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
という名前で利用できるようにする設定
- JSTLのうちのコア機能を
- 13行目
- スクリプト式をJSTLで置き換えたものが
<c:out>
タグ - value属性には表示したいデータを指定
- EL式で
${名前}
という形式で記述 - 変数名のみを
{ }
の中に記述するだけで良い
- EL式で
- スクリプト式をJSTLで置き換えたものが
<p>
タグの3行は全て同じ表示になる。が、HTMLのタグが含まれていると困るデータの中身を表示する際は<c:out>
を利用した方が良い。なぜなら、サニタイジングと呼ばれる「特定の半角記号を無害な形式に変換する(エスケープ)」 セキュリティ対策を自動で施してくれる機能を持っているから。
今日の反省と明日の目標。
スコープは普段使っているWebサイト等でもよく見かける技術なので興味深く学習できました。とはいえ、覚えるのが多くて大変さを感じるようになってきたのも事実です。しかし、どの技術も結局は簡略化するためのものでもあるので、たくさん覚えた方が後から楽になってくるのではないでしょうかね、知らないけど。多分JSTLやEL式も知らなければ、現場で苦労するだろうし。。
難しい部分は出来るだけ頭の中で抽象的に組み立てていきたいところです。頭でガチガチに考えると応用が効かないので。自分だったらこの技術をどう活用するのかシミュレーションを行うことについては今後の学習の中で意識的に取り組んでいきたいですね。