Spring Boot で書籍の貸出状況確認・貸出申請する Web アプリケーションを作る ( その58 )( セッションに値をセットする・取り出す処理を実装する )
概要
Spring Boot で書籍の貸出状況確認・貸出申請する Web アプリケーションを作る ( その57 )( 気になった点を修正2 ) の続きです。
- 今回の手順で確認できるのは以下の内容です。
- セッションに値をセットする・取り出す処理を実装する。
- 既存の画面に実装する案が思い浮かばなかったので、サンプルの画面を作成することにします。
参照したサイト・書籍
indexnext |previous |TERASOLUNA Server Framework for Java (5.x) Development Guideline 5.1.0.RELEASE documentation - 5.8. セッション管理
http://terasolunaorg.github.io/guideline/5.1.0.RELEASE/ja/ArchitectureInDetail/SessionManagement.html- Web でいろいろ調べましたが、一番分かりやすいのはこのドキュメントだと思います。
目次
- 実装仕様
- feature/106-issue ブランチの作成
- Form クラスの作成
- Thymeleaf テンプレートファイルの作成
- Controller クラスの作成
- 動作確認
- commit、GitHub へ Push、feature/106-issue -> 1.0.x へ Pull Request、1.0.x でマージ、feature/106-issue ブランチを削除
- 感想&次回は。。。
手順
実装仕様
以下の仕様で実装します。
- 入力画面1(「名前」「年齢」を入力できる画面)、入力画面2(「住所」「メールアドレス」を入力できる画面)、確認画面の3画面を用意します。
- 入力画面1、入力画面2で入力されたデータはセッションに保存します。
- セッションに保存する方法には @SessionAttributes アノテーションを使用します。
- 確認画面にはセッションをクリアするボタンを設けます。
画面デザインは以下のものを使用します。
feature/106-issue ブランチの作成
- feature/106-issue ブランチを作成します。
Form クラスの作成
src/main/java/ksbysample/webapp/lending/web の下に sessionsample パッケージを作成します。
src/main/java/ksbysample/webapp/lending/web/sessionsample の下に SessionSampleForm.java を作成します。作成後、リンク先の内容 に変更します。
Thymeleaf テンプレートファイルの作成
src/main/resources/templates の下に sessionsample ディレクトリを作成します。
src/main/resources/templates/sessionsample の下に first.html を作成します。作成後、リンク先の内容 に変更します。
src/main/resources/templates/sessionsample の下に next.html を作成します。作成後、リンク先の内容 に変更します。
src/main/resources/templates/sessionsample の下に confirm.html を作成します。作成後、リンク先の内容 に変更します。
Controller クラスの作成
src/main/java/ksbysample/webapp/lending/web/sessionsample の下に SessionSampleController.java を作成します。作成後、リンク先の内容 に変更します。
/sessionsample 以下の URL はログイン有無の対象外にします。src/main/java/ksbysample/webapp/lending/config の下の WebSecurityConfig.java を リンク先の内容 に変更します。
動作確認
動作確認します。Gradle projects View から bootRun タスクを実行して Tomcat を起動します。
ブラウザを起動して http://localhost:8080/sessionsample にアクセスします。
名前、年齢を入力して「入力その2へ」ボタンをクリックします。
「入力その1へ戻る」ボタンをクリックして入力画面1へ戻ると、入力したデータが表示されることが確認できます。
「入力その2へ」ボタンをクリックして入力画面2へ戻ります。
住所、メールアドレスを入力して「確認画面へ」ボタンをクリックします。
確認画面に遷移すると入力画面1、入力画面2で入力したデータが表示されることが確認できます。
「セッションをクリアする」ボタンをクリックすると入力画面1に戻ります。
「確認画面へ」ボタンをクリックして確認画面へ遷移すると、表示されているデータが消えていることが確認できます。
「入力その2へ戻る」ボタンをクリックして、今度は入力画面2→入力画面1→確認画面の順で入力してみます。
入力画面の順番を変えても、確認画面上に入力したデータが表示されることが確認できます。
Ctrl+F2 を押して Tomcat を停止します。
commit、GitHub へ Push、feature/106-issue -> 1.0.x へ Pull Request、1.0.x でマージ、feature/106-issue ブランチを削除
- commit、GitHub へ Push、feature/106-issue -> 1.0.x へ Pull Request、1.0.x でマージ、feature/106-issue ブランチを削除、をします。
感想&次回は。。。
- 最初は仕組みを理解できていなくて試行錯誤したのですが、分かってしまうとすごく簡単にセッションにデータを入れられて驚きでした。
- 次回は JDK の 8u77 が出ているのでバージョンアップした後、Windows で本番稼働させるためのディレクトリ作成、jar ファイル配置、bat ファイル作成、サービス登録、動作確認へと進む予定です。
ソースコード
SessionSampleForm.java
package ksbysample.webapp.lending.web.sessionsample; import lombok.Data; import java.io.Serializable; @Data public class SessionSampleForm implements Serializable { private static final long serialVersionUID = 1183516008630394266L; private String name; private String age; private String address; private String email; }
- セッションに保存するので Serializable インターフェースを実装します。
first.html
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"/> <meta http-equiv="X-UA-Compatible" content="IE=edge"/> <title>セッションサンプル</title> <!-- Tell the browser to be responsive to screen width --> <meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport"/> <link th:replace="common/head-cssjs"/> <style type="text/css"> <!-- .table { background-color: #ffccff; margin-bottom: 10px; } .has-error .form-control { background-color: #fff5ee; } .form-group { margin-bottom: 0px; } --> </style> </head> <!-- ADD THE CLASS layout-top-nav TO REMOVE THE SIDEBAR. --> <body class="skin-blue layout-top-nav"> <div class="wrapper"> <!-- Main Header --> <div th:replace="common/mainparts :: main-header"></div> <!-- Full Width Column --> <div class="content-wrapper"> <div class="container"> <!-- Content Header (Page header) --> <section class="content-header"> <h1>セッションサンプル(入力その1)</h1> </section> <!-- Main content --> <section class="content"> <div class="row"> <div class="col-xs-12"> <!-- @thymesVar id="sessionSampleForm" type="ksbysample.webapp.lending.web.sessionsample.SessionSampleForm" --> <form id="sessionSampleForm" method="post" action="/sessionsample/confirm" th:action="@{/sessionsample/confirm}" th:object="${sessionSampleForm}"> <table class="table table-bordered"> <colgroup> <col width="20%"/> <col width="80%"/> </colgroup> <tbody> <tr> <th>名前</th> <td> <div class="col-xs-12"> <div class="form-group"> <div class="row"><div class="col-xs-8"> <input type="text" name="name" id="name" class="form-control input-sm" value="" placeholder="氏名を入力してください" th:field="*{name}"/> </div></div> </div> </div> </td> </tr> <tr> <th>年齢</th> <td> <div class="col-xs-12"> <div class="form-group"> <div class="row"><div class="col-xs-3"> <input type="text" name="age" id="age" class="form-control input-sm" value="" placeholder="年齢を入力してください" th:field="*{age}"/> </div></div> </div> </div> </td> </tr> </tbody> </table> <div class="text-center"> <button class="btn bg-blue js-btn-next"><i class="fa fa-hand-o-right"></i> 入力その2へ</button> <button class="btn bg-blue js-btn-confirm"><i class="fa fa-eye"></i> 確認画面へ</button> </div> </form> </div> </div> </section> <!-- /.content --> </div> <!-- /.container --> </div> </div> <!-- ./wrapper --> <script th:replace="common/bottom-js"></script> <script type="text/javascript"> <!-- $(document).ready(function() { $('.js-btn-next').bind('click', function(){ $("#sessionSampleForm").attr("action", "/sessionsample/next"); $('#sessionSampleForm').submit(); return false; }); $('.js-btn-confirm').bind('click', function(){ $('#sessionSampleForm').submit(); return false; }); }); --> </script> </body> </html>
next.html
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"/> <meta http-equiv="X-UA-Compatible" content="IE=edge"/> <title>セッションサンプル</title> <!-- Tell the browser to be responsive to screen width --> <meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport"/> <link th:replace="common/head-cssjs"/> <style type="text/css"> <!-- .table { background-color: #ffccff; margin-bottom: 10px; } .has-error .form-control { background-color: #fff5ee; } .form-group { margin-bottom: 0px; } --> </style> </head> <!-- ADD THE CLASS layout-top-nav TO REMOVE THE SIDEBAR. --> <body class="skin-blue layout-top-nav"> <div class="wrapper"> <!-- Main Header --> <div th:replace="common/mainparts :: main-header"></div> <!-- Full Width Column --> <div class="content-wrapper"> <div class="container"> <!-- Content Header (Page header) --> <section class="content-header"> <h1>セッションサンプル(入力その2)</h1> </section> <!-- Main content --> <section class="content"> <div class="row"> <div class="col-xs-12"> <!-- @thymesVar id="sessionSampleForm" type="ksbysample.webapp.lending.web.sessionsample.SessionSampleForm" --> <form id="sessionSampleForm" method="post" action="/sessionsample/confirm" th:action="@{/sessionsample/confirm}" th:object="${sessionSampleForm}"> <table class="table table-bordered"> <colgroup> <col width="20%"/> <col width="80%"/> </colgroup> <tbody> <tr> <th>住所</th> <td> <div class="col-xs-12"> <div class="form-group"> <div class="row"><div class="col-xs-12"> <input type="text" name="address" id="address" class="form-control input-sm" value="" placeholder="住所を入力してください" th:field="*{address}"/> </div></div> </div> </div> </td> </tr> <tr> <th>メールアドレス</th> <td> <div class="col-xs-12"> <div class="form-group"> <div class="row"><div class="col-xs-8"> <input type="text" name="email" id="email" class="form-control input-sm" value="" placeholder="メールアドレスを入力してください" th:field="*{email}"/> </div></div> </div> </div> </td> </tr> </tbody> </table> <div class="text-center"> <button class="btn bg-blue js-btn-first"><i class="fa fa-hand-o-left"></i> 入力その1へ戻る</button> <button class="btn bg-blue js-btn-confirm"><i class="fa fa-eye"></i> 確認画面へ</button> </div> </form> </div> </div> </section> <!-- /.content --> </div> <!-- /.container --> </div> </div> <!-- ./wrapper --> <script th:replace="common/bottom-js"></script> <script type="text/javascript"> <!-- $(document).ready(function() { $('.js-btn-first').bind('click', function(){ $("#sessionSampleForm").attr("action", "/sessionsample"); $('#sessionSampleForm').submit(); return false; }); $('.js-btn-confirm').bind('click', function(){ $('#sessionSampleForm').submit(); return false; }); }); --> </script> </body> </html>
confirm.html
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"/> <meta http-equiv="X-UA-Compatible" content="IE=edge"/> <title>セッションサンプル</title> <!-- Tell the browser to be responsive to screen width --> <meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport"/> <link th:replace="common/head-cssjs"/> <style type="text/css"> <!-- .table { background-color: #ffccff; margin-bottom: 10px; } .has-error .form-control { background-color: #fff5ee; } .form-group { margin-bottom: 0px; } --> </style> </head> <!-- ADD THE CLASS layout-top-nav TO REMOVE THE SIDEBAR. --> <body class="skin-blue layout-top-nav"> <div class="wrapper"> <!-- Main Header --> <div th:replace="common/mainparts :: main-header"></div> <!-- Full Width Column --> <div class="content-wrapper"> <div class="container"> <!-- Content Header (Page header) --> <section class="content-header"> <h1>セッションサンプル(確認)</h1> </section> <!-- Main content --> <section class="content"> <div class="row"> <div class="col-xs-12"> <!-- @thymesVar id="sessionSampleForm" type="ksbysample.webapp.lending.web.sessionsample.SessionSampleForm" --> <form id="sessionSampleForm" method="post" action="/sessionsample/clear" th:action="@{/sessionsample/clear}" th:object="${sessionSampleForm}"> <table class="table table-bordered"> <colgroup> <col width="20%"/> <col width="80%"/> </colgroup> <tbody> <tr> <th>名前</th> <td th:text="*{name}"></td> </tr> <tr> <th>年齢</th> <td th:text="*{age}"></td> </tr> <tr> <th>住所</th> <td th:text="*{address}"></td> </tr> <tr> <th>メールアドレス</th> <td th:text="*{email}"></td> </tr> </tbody> </table> <div class="text-center"> <button class="btn bg-blue js-btn-first"><i class="fa fa-hand-o-left"></i> 入力その1へ戻る</button> <button class="btn bg-blue js-btn-next"><i class="fa fa-hand-o-left"></i> 入力その2へ戻る</button> <button class="btn bg-blue js-btn-clear"><i class="fa fa-eraser"></i> セッションをクリアする</button> </div> </form> </div> </div> </section> <!-- /.content --> </div> <!-- /.container --> </div> </div> <!-- ./wrapper --> <script th:replace="common/bottom-js"></script> <script type="text/javascript"> <!-- $(document).ready(function () { $('.js-btn-first').bind('click', function () { $("#sessionSampleForm").attr("action", "/sessionsample"); $('#sessionSampleForm').submit(); return false; }); $('.js-btn-next').bind('click', function () { $("#sessionSampleForm").attr("action", "/sessionsample/next"); $('#sessionSampleForm').submit(); return false; }); $('.js-btn-clear').bind('click', function () { $('#sessionSampleForm').submit(); return false; }); }); --> </script> </body> </html>
SessionSampleController.java
package ksbysample.webapp.lending.web.sessionsample; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.SessionAttributes; import org.springframework.web.bind.support.SessionStatus; @Controller @RequestMapping("/sessionsample") @SessionAttributes("sessionSampleForm") public class SessionSampleController { @RequestMapping public String index(SessionSampleForm sessionSampleForm) { return "sessionsample/first"; } @RequestMapping("/next") public String next(SessionSampleForm sessionSampleForm) { return "sessionsample/next"; } @RequestMapping("/confirm") public String confirm(SessionSampleForm sessionSampleForm) { return "sessionsample/confirm"; } @RequestMapping("/clear") public String clear(SessionStatus sessionStatus) { sessionStatus.setComplete(); return "redirect:/sessionsample"; } }
- クラスに @SessionAttributes("sessionSampleForm") アノテーションを付加します。
- セッションをクリアするための clear メソッドでは引数に
SessionStatus sessionStatus
を指定し、メソッド内でsessionStatus.setComplete();
を呼び出します。
WebSecurityConfig.java
@Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() // 認証の対象外にしたいURLがある場合には、以下のような記述を追加します // 複数URLがある場合はantMatchersメソッドにカンマ区切りで対象URLを複数列挙します // .antMatchers("/country/**").permitAll() .antMatchers("/fonts/**").permitAll() .antMatchers("/html/**").permitAll() .antMatchers("/encode").permitAll() .antMatchers("/urllogin").permitAll() .antMatchers("/webapi/**").permitAll() .antMatchers("/springMvcMemo/**").permitAll() .antMatchers("/sessionsample/**").permitAll() .antMatchers("/textareamemo/**").permitAll() .anyRequest().authenticated();
.antMatchers("/sessionsample/**").permitAll()
を追加します。
履歴
2016/03/27
初版発行。