Spring Bootを使った新人エンジニア向けWebアプリ開発テキスト
第1章:Spring Bootの概要
1.1 Spring Bootとは?
Spring Boot は、Java を使った Web アプリケーション開発を簡単にするフレームワークです。
Spring フレームワークをベースにしており、設定の手間を減らし、シンプルに開発できるのが特徴です。
主な特徴
- 設定不要で使える:自動設定(Auto Configuration)により、設定ファイルの記述を最小限にできる。
- 組み込みサーバ:Tomcat などのサーバが最初から組み込まれており、単体で動作可能。
- 依存関係の管理が簡単:Maven で必要なライブラリを簡単に追加できる。
- 軽量な開発環境:Spring Boot DevTools を使うと、変更を即時反映できる。
1.2 依存関係の確認とプロジェクト構成
Spring Boot のプロジェクトでは、Maven を使って必要なライブラリを管理します。
今回のプロジェクトでは、以下の依存関係を使用します。
<dependencies>
<!-- Webアプリに必要 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Thymeleafテンプレートエンジン -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!-- Spring JDBC -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jdbc</artifactId>
</dependency>
<!-- MySQLドライバ -->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
</dependencies>
プロジェクト構成
SpringBootSample/
├── src/main/java/com/example/demo/
│ ├── SpringKaeruApplication.java # 起動クラス
│ ├── controller/ # コントローラ層
│ │ ├── CarController.java
│ ├── model/ # データベースアクセス層
│ │ ├── Car.java
│ │ ├── CarDao.java
│ ├── service/ # ビジネスロジック層(今回はなし)
├── src/main/resources/
│ ├── application.properties # 設定ファイル
│ ├── templates/ # Thymeleafテンプレート
│ │ ├── kaeru.html
├── pom.xml # 依存関係を管理するファイル
1.3 EclipseでのSpring Bootプロジェクト作成
Spring Boot のプロジェクトを作成し、実際に起動してみましょう。
(1) Eclipseでプロジェクトを作成
- Eclipse を開き、「ファイル」→「新規」→「Spring Bootプロジェクト」を選択
- 「Spring Boot バージョン」は
3.1.1
を選択 - 「依存関係の追加」で以下を選択
- Spring Web
- Thymeleaf
- Spring Data JDBC
- MySQL Driver
- 「完了」をクリックしてプロジェクトを作成
(2) プロジェクトの起動
Eclipse の「SpringBootSampleApplication.java」を開き、main
メソッドを実行します。
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* 新入社員のみなさんへ
*
* このクラスは、Spring Bootアプリケーションのエントリーポイント(起動クラス)になります。
*
* 【ポイント】 1. @SpringBootApplication - Spring Bootにおけるアプリケーションの自動設定(Auto
* Configuration)を有効にするアノテーションです。
*
* 2. mainメソッド - Javaの実行クラスはmainメソッドを持ちます。Spring Bootアプリケーションも同様にここが起点となり、
* アプリケーションを起動します。 - SpringApplication.run(SpringKaeruApplication.class, args)
* と呼び出すことで 内部的にTomcatなどのサーバが起動し、Webアプリケーションとして動作を開始します。
*
* 3. アプリケーション名 - クラス名「SpringKaeruApplication」という部分はプロジェクトごとに自由に設定できます。
* ただし、慣例として「(プロジェクト名)Application」という形式が多く使われます。
*
* 4. 基本の流れ - mainメソッドが呼び出される → SpringApplication.run(...) が実行される →
* Springフレームワークによる自動設定やコンポーネントの読み込み → アプリケーション起動
*
@SpringBootApplication
public class SpringKaeruApplication {
/**
* Javaプログラムの実行を開始するmainメソッドです。
* SpringApplication.run(...)によってSpringアプリケーションを起動します。
*
* @param args プログラム実行時に渡される引数(今回は特に使用しない想定)
*/
public static void main(String[] args) {
SpringApplication.run(SpringKaeruApplication.class, args);
}
}
ブラウザで http://localhost:8080
にアクセスすると、アプリケーションが起動していることを確認できます。
ハンズオン:Spring Bootの初期プロジェクトを作成し、起動してみよう
【目標】
Spring Boot のプロジェクトを作成し、ブラウザで起動を確認する。
【手順】
- Eclipse で Spring Boot プロジェクトを作成する。
SpringKaeruApplication.java
を実行し、アプリを起動する。http://localhost:8080
にアクセスし、エラーページが表示されることを確認する。
→ まだコントローラを作成していないため、エラーになるのが正しい動作です!
【確認ポイント】
- Eclipse で Spring Boot プロジェクトが作成できたか?
main
メソッドを実行し、Spring Boot アプリが起動したか?http://localhost:8080
にアクセスし、エラーが表示されたか?
まとめ
- Spring Boot は Java の Web アプリ開発を簡単にするフレームワーク。
- 設定の手間が少なく、最小限のコードで動作する。
- Eclipse で Spring Boot プロジェクトを作成し、実際に起動してみる。
次章では、Spring Boot の基本的な仕組みを理解し、簡単な Web ページを表示する方法を学びます!
第2章:Spring Bootの基本
2.1 Spring Bootのアノテーション
Spring Boot では、コードをシンプルにするために アノテーション を多用します。
本章では、Spring Boot の基本的なアノテーションを理解し、簡単な Web ページを表示する方法を学びます。
(1) @SpringBootApplication
Spring Boot アプリケーションの起動クラスに付けるアノテーションです。
このアノテーションをつけることで、Spring Bootの自動設定 (Auto Configuration) やコンポーネントスキャンが有効になります。
@SpringBootApplication
public class SpringKaeruApplication {
public static void main(String[] args) {
SpringApplication.run(SpringKaeruApplication.class, args);
}
}
@SpringBootApplication の内部の動作
- @Configuration: 設定クラスとして認識される
- @EnableAutoConfiguration: 自動設定を有効にする
- @ComponentScan: 指定したパッケージ以下のクラスを自動的に登録する
(2) @Controller
コントローラ (Controller) を表すアノテーションです。
このクラスは、ブラウザからのリクエストを受け取り、適切な処理を実行して画面にデータを渡す役割 を持ちます。
// コントローラーとして動作することを示すアノテーション
@Controller
public class HelloController {
// HTTPのGETリクエストで「/hello」にアクセスしたときに、このメソッドが呼び出される
@GetMapping("/hello")
public String hello() {
// 「hello」というビュー名を返す
// src/main/resources/templates/hello.html を表示する仕組み
return "hello";
}
}
@GetMapping("/hello")
によって、http://localhost:8080/hello
にアクセスするとhello.html
を表示する。
(3) @GetMapping
@GetMapping
は、HTTPのGETリクエストを受け付けるメソッド を定義するアノテーションです。
例えば、以下のように使います。
@Controller
public class HelloController {
// HTTP GETリクエストのマッピングを指定するアノテーション
// "/" へアクセスがあった場合にこのメソッドが呼び出される
@GetMapping("/")
public String index() {
// "index" という文字列を返すことで、
// src/main/resources/templates/index.html のテンプレートを表示する
return "index";
}
}
@GetMapping("/")
は、ブラウザからの「/」リクエスト (http://localhost:8080/) を処理 します。
2.2 アプリケーションの起動と開発環境の確認
Spring Boot の開発環境が正しく動作しているか確認します。
- Eclipse で
SpringKaeruApplication.java
を実行する http://localhost:8080/hello
にアクセスし、「エラーページ」が表示されることを確認する- エラーページになるのが正しい動作!
hello.html
をまだ作成していないため、テンプレートが見つからないエラーが出る
2.3 application.properties の基本設定
プロパティとは、アプリケーションの設定情報を管理する仕組みです。Spring Boot では、src/main/resources/application.properties
に設定を書いて、アプリの挙動を変更できます。
(1) ポート番号の変更
デフォルトでは 8080
ですが、変更したい場合は以下を追加します。
server.port=8081
これで、http://localhost:8081/
にアクセスするとアプリが動作します。
(2) Thymeleaf のキャッシュ無効化
Thymeleaf のテンプレートを編集するたびに、アプリを再起動しなくても変更を反映する設定です。ただし、Javaコードの変更には影響せず、Javaを修正した場合は アプリケーションの再起動が必要になります。開発環境では有効にしておくと効率が上がりますが、本番環境ではパフォーマンスのために true にしておくのが一般的です。
spring.thymeleaf.cache=false
2.4 簡単なWebページを表示する
Spring Boot を使って、簡単な Web ページを表示してみます。
(1) コントローラを作成
src/main/java/com/example/demo/controller/HelloController.java
を作成し、以下のコードを記述します。
package com.example.demo.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class HelloController {
@GetMapping("/hello")
public String hello() {
return "hello"; // hello.html を表示
}
}
(2) Thymeleaf のテンプレートを作成
src/main/resources/templates/hello.html
を作成し、以下の内容を記述します。
<!DOCTYPE html>
<html lang="ja" xmlns:th="http://www.thymeleaf.org">
<!--
xmlns:th="http://www.thymeleaf.org" は、Thymeleafテンプレートエンジンの名前空間を指定しています。
このあとでThymeleafの `th:*` 属性(例: th:text, th:if など)を使用できるようになることを学びます。
-->
<head>
<meta charset="UTF-8">
<title>Hello Spring Boot</title>
</head>
<body>
<h1>Hello, Spring Boot!</h1>
</body>
</html>
(3) アプリを起動し、ブラウザで確認
SpringKaeruApplication.java
を実行するhttp://localhost:8080/hello
にアクセス- 「Hello, Spring Boot!」と表示されることを確認する
ハンズオン:シンプルなHello Worldアプリを作成する
【目標】
Spring Boot を使って、「Hello, Spring Boot!」を表示するWebアプリを作成する。
【手順】
HelloController.java
を作成hello.html
を作成- アプリを起動し、ブラウザで動作確認
http://localhost:8080/hello
にアクセス- 「Hello, Spring Boot!」が表示されることを確認
まとめ
- @SpringBootApplication はSpring Bootの基本設定をまとめたアノテーション
- @Controller はWebリクエストを処理するクラス
- @GetMapping でURLと処理を紐づける
- Thymeleaf を使って簡単なWebページを作成
- application.properties でアプリの設定を変更できる
次章では、Thymeleaf の基本を学び、動的なデータを表示する方法を学習します!
第3章:Thymeleafによる画面表示
3.1 Thymeleafとは?
Thymeleaf(タイムリーフ)は、Spring Boot の公式テンプレートエンジンです。
HTMLファイルの中に動的なデータを埋め込むことができ、JavaとHTMLを直感的に組み合わせられるのが特徴です。
Thymeleafの特徴
- 通常のHTMLとして表示可能(開発中でもブラウザで確認しやすい)
- Spring Bootと統合が簡単(特別な設定なしで使用できる)
- シンプルな構文でJavaオブジェクトを埋め込める
- セキュリティ対策がデフォルトで有効(XSS対策など)
3.2 HTMLテンプレートの作成
Spring Boot のテンプレートは src/main/resources/templates/
に配置します。
まず、以下のようなシンプルなHTMLを作成します。
(1) テンプレートの作成
src/main/resources/templates/welcome.html
を作成し、以下のコードを記述します。
<!DOCTYPE html>
<html lang="ja" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Welcome</title>
</head>
<body>
<h1 th:text="${message}">Hello, Thymeleaf!</h1>
</body>
</html>
(2) コントローラの作成
src/main/java/com/example/demo/controller/WelcomeController.java
を作成し、以下のコードを記述します。
package com.example.demo.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class WelcomeController {
@GetMapping("/welcome")
public String welcome(Model model) {
model.addAttribute("message", "Spring Bootへようこそ!");
return "welcome"; // welcome.html を表示
}
}
3.3 Thymeleafの基本構文
Thymeleaf では、HTML内で th:*
という特別な属性を使って動的なデータを埋め込むことができます。
構文 | 例 | 説明 |
---|---|---|
th:text | <p th:text="${message}"> | テキストを埋め込む |
th:if / th:unless | <p th:if="${isLoggedIn}"> | 条件分岐 |
th:each | <li th:each="item : ${items}"> | ループ処理 |
th:href | <a th:href="@{/home}">Home</a> | リンクの生成 |
th:action | <form th:action="@{/submit}"> | フォームの送信先 |
th:value | <input th:value="${username}"> | 入力値の設定 |
3.4 ループ処理(一覧表示)
データのリストを表示する場合、th:each
を使います。
(1) コントローラでデータを準備
src/main/java/com/example/demo/controller/ProductController.java
を作成します。
package com.example.demo.controller;
import java.util.Arrays;
import java.util.List;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class ProductController {
@GetMapping("/products")
public String products(Model model) {
// 商品リストを作成(固定のデータを用意)
List<String> productList = Arrays.asList("車A", "車B", "車C");
// Modelオブジェクトを使ってデータをView(HTML)に渡す
// "products" というキーで productList を Thymeleaf などのテンプレートエンジンに提供
return "products"; // products.html を表示
}
}
(2) Thymeleafでリストを表示
src/main/resources/templates/products.html
を作成し、以下のコードを記述します。
<!DOCTYPE html>
<html lang="ja" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>商品一覧</title>
</head>
<body>
<h1>商品一覧</h1>
<ul>
<!--
th:each="product : ${products}" の解説:
- "products" はコントローラー側でModelに追加されたリスト。
- "th:each" は Thymeleaf の繰り返し処理を行う属性。
- "product" という変数に、リスト "products" の各要素が順番に入る。
- リストの要素数だけ <li> 要素が生成される。
-->
<!--
th:text="${product}" の解説:
- "${product}" は、th:each でセットされた各要素。
- <li> 内のテキストがリストの各アイテムに置き換えられる。
- 例えば、"車A", "車B", "車C" が products に含まれている場合、
それぞれの <li> 要素に "車A", "車B", "車C" が表示される。
-->
<li th:each="product : ${products}" th:text="${product}">商品名</li>
</ul>
</body>
</html>
ブラウザで http://localhost:8080/products
にアクセスすると、以下のように表示されます。
商品一覧
- 車A
- 車B
- 車C
3.5 条件分岐
Thymeleafでは、th:if
や th:unless
を使って条件分岐ができます。
(1) コントローラの作成
src/main/java/com/example/demo/controller/DiscountController.java
を作成します。
package com.example.demo.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class DiscountController {
@GetMapping("/discount")
public String discount(Model model) {
model.addAttribute("isDiscount", true);
return "discount";
}
}
(2) Thymeleafで条件分岐
src/main/resources/templates/discount.html
を作成し、以下のコードを記述します。
<!DOCTYPE html>
<html lang="ja" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>セール情報</title>
</head>
<body>
<h1>セール情報</h1>
<!--
th:if は、Thymeleaf の条件分岐を行う属性。
${isDiscount} の値が true(または null 以外の値)ならば、この <p> 要素が表示される。
例えば、Controller で model.addAttribute("isDiscount", true) と設定すると、
「今だけ特別割引中!」というテキストが表示される。
-->
<p th:if="${isDiscount}">今だけ特別割引中!</p>
<!--
th:unless は th:if の逆の意味を持ち、${isDiscount} の値が false(または null)ならば、この <p> 要素が表示される。
例えば、Controller で model.addAttribute("isDiscount", false) または値を設定しない場合、
「現在セールは行っていません。」が表示される。
-->
<p th:unless="${isDiscount}">現在セールは行っていません。</p>
</body>
</html>
ブラウザで http://localhost:8080/discount
にアクセスすると、以下のように表示されます。
セール情報
今だけ特別割引中!
3.6 ユーザー入力の受け取り
Spring Boot + Thymeleaf では、フォームを使ってユーザー入力を受け取ることもできます。
(1) フォームを表示
src/main/resources/templates/input.html
を作成します。
<!DOCTYPE html>
<html lang="ja" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>ユーザー入力</title>
</head>
<body>
<h1>名前を入力してください</h1>
<form th:action="@{/greet}" method="get">
<!--
th:action は Thymeleaf の属性で、フォームの送信先 URL を指定します。
"@{/greet}" は Spring Boot のコントローラのエンドポイント "/greet" にマッピングされます。
例えば、`@GetMapping("/greet")` のようなメソッドが Spring のコントローラに定義されていれば、
フォームを送信した際に、そのメソッドが処理を行います。
-->
<input type="text" name="name">
<button type="submit">送信</button>
</form>
</body>
</html>
(2) 入力を処理
src/main/java/com/example/demo/controller/GreetController.java
を作成します。
package com.example.demo.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
@Controller
public class GreetController {
@GetMapping("/greet")
public String greet(@RequestParam String name, Model model) {
// クライアントからのリクエストパラメータ "name" を受け取る
// 例えば "/greet?name=Taro" のようなリクエストが来ると、name には "Taro" が格納される
model.addAttribute("name", name);
return "greet";
}
}
(3) 画面に表示
src/main/resources/templates/greet.html
を作成します。
<!DOCTYPE html>
<html lang="ja" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>挨拶</title>
</head>
<body>
<h1>こんにちは、<span th:text="${name}">ゲスト</span>さん!</h1>
</body>
</html>
ハンズオン:Thymeleafを使って商品一覧を表示する
【目標】
Thymeleaf を使い、商品のリストを画面に表示する。
【手順】
- コントローラ (
ProductController.java
) を作成 - テンプレート (
products.html
) を作成 - ブラウザで
http://localhost:8080/products
にアクセスし、リストが表示されることを確認
まとめ
- Thymeleaf は Spring Boot の公式テンプレートエンジン
th:text
でテキストを埋め込めるth:each
でリストを表示できるth:if
で条件分岐ができる
次章では、コントローラの役割を深掘りしていきます!
第4章:Spring MVCの基本
4.1 Spring MVCとは?
Spring MVC は、Spring フレームワークの一部であり、Webアプリケーションの開発を簡単にするための仕組み です。
従来の Servlet + JSP に比べ、コードの記述量が少なく、整理されたアーキテクチャで開発できる のが特徴です。
Spring MVCの基本構造
Spring MVC では、以下の3つの要素を中心に構成されます。
- コントローラ (Controller)
- ブラウザからのリクエストを受け取り、適切な処理を行う
@Controller
を使って定義する
- モデル (Model)
- データを管理する
@Service
や@Repository
を使って定義する
- ビュー (View)
- 画面を表示する(Thymeleafなど)
src/main/resources/templates/
にHTMLを配置する
4.2 @Controllerと@GetMappingの使い方
コントローラを使ってWebページを制御します。
(1) @Controller の基本
@Controller
は、リクエストを受け取るクラスに付けます。
package com.example.demo.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class HomeController {
@GetMapping("/") // http://localhost:8080/ にアクセスしたときの処理
public String index() {
return "index"; // index.html を表示
}
}
解説
@Controller
を付けることで、このクラスがWebリクエストを処理することを宣言。@GetMapping("/")
により、http://localhost:8080/
にアクセスするとindex.html
を表示。
4.3 Modelを使ってデータを画面に渡す
Model
を使ってコントローラから画面(HTML)にデータを渡します。
(1) コントローラでデータを渡す
package com.example.demo.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class GreetingController {
@GetMapping("/greeting")
public String greeting(Model model) {
model.addAttribute("name", "新入社員");
return "greeting"; // greeting.html を表示
}
}
(2) Thymeleafでデータを表示
src/main/resources/templates/greeting.html
を作成し、以下のコードを記述。
<!DOCTYPE html>
<html lang="ja" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>挨拶</title>
</head>
<body>
<h1>こんにちは、<span th:text="${name}">ゲスト</span>さん!</h1>
</body>
</html>
結果
http://localhost:8080/greeting
にアクセスすると、
「こんにちは、新入社員さん!」 と表示される。
4.4 URLパラメータを受け取る
URLのパラメータを受け取ることも可能です。
(1) @RequestParam を使う
@RequestParam
を使うと、URLのパラメータを取得できます。
package com.example.demo.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
@Controller
public class WelcomeController {
@GetMapping("/welcome")
public String welcome(
// クエリパラメータ "name" を受け取るための @RequestParam アノテーション
@RequestParam(
name = "name", // クエリパラメータのキーを指定(例: /welcome?name=太郎)
required = false, // パラメータが省略されてもエラーにならないようにする
defaultValue = "ゲスト" // パラメータが渡されなかった場合のデフォルト値
) String name,
Model model // ビューにデータを渡すための Model オブジェクト
) {
model.addAttribute("name", name);
return "welcome";
}
}
(2) HTMLで表示
src/main/resources/templates/welcome.html
を作成。
<!DOCTYPE html>
<html lang="ja" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Welcome</title>
</head>
<body>
<h1>ようこそ、<span th:text="${name}">ゲスト</span> さん!</h1>
</body>
</html>
動作確認
http://localhost:8080/welcome?name=田中
- 「ようこそ、田中さん!」 と表示される。
4.5 フォーム入力の受け取り
フォームを使ってデータを入力し、処理することができます。
(1) フォームを作成
src/main/resources/templates/form.html
を作成。
<!DOCTYPE html>
<html lang="ja" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>入力フォーム</title>
</head>
<body>
<h1>名前を入力してください</h1>
<form th:action="@{/submit}" method="post">
<!-- th:action="@{/submit}" は、Thymeleaf の構文を使用してフォームの送信先 URL を指定します。
@{} の中にパスを書き、サーバー側のエンドポイント(/submit)にデータを送信します。
例えば、Spring Boot では @PostMapping("/submit") で処理することが一般的です。 -->
<!-- method="post" は、HTTP メソッドの指定です。
データを送信する際に GET ではなく POST を使用することで、
URL にデータを含めず、安全に送信できます。 -->
<input type="text" name="name">
<button type="submit">送信</button>
</form>
</body>
</html>
(2) コントローラでフォームのデータを受け取る
package com.example.demo.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
@Controller
public class FormController {
@PostMapping("/submit")
public String submit(@RequestParam String name, Model model) {
model.addAttribute("name", name);
return "result";
}
}
(3) 結果を表示
src/main/resources/templates/result.html
を作成。
<!DOCTYPE html>
<html lang="ja" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>結果</title>
</head>
<body>
<h1>こんにちは、<span th:text="${name}">ゲスト</span> さん!</h1>
</body>
</html>
動作確認
http://localhost:8080/form
にアクセス- 名前を入力して送信
result.html
に入力した名前が表示される
ハンズオン:コントローラを作成してデータを画面に表示する
【目標】
- コントローラからデータを Thymeleaf に渡して表示する。
【手順】
- コントローラ (
GreetingController.java
) を作成 - Thymeleaf (
greeting.html
) を作成 - ブラウザで
http://localhost:8080/greeting
にアクセス - 「こんにちは、新入社員さん!」と表示されることを確認
まとめ
- 「Controller → Model → View」 で構成される。
@Controller
を使うと、リクエストを処理できる。@GetMapping
でページを表示する。Model
を使ってコントローラからビューにデータを渡せる。@RequestParam
を使うと、URLのパラメータを受け取れる。- フォームを使うことで、ユーザー入力を受け取れる。
次章では、Spring Bootとデータベースを連携し、MySQLからデータを取得・表示する方法を学びます!
第5章:データベース接続 (JDBC)
5.1 Spring BootとMySQLの接続
Spring Bootでは、JDBCを使ってMySQLと簡単に連携できます。
本章では、Spring BootからMySQLのデータを取得し、画面に表示する方法 を学びます。
(1) MySQLの準備
すでにMySQLでデータベースとテーブルを作成済みですのでcarsテーブルを使っていきます。
(2) application.properties
の設定
Spring BootがMySQLと接続できるように、以下の設定を追加します。
src/main/resources/application.properties
# MySQL接続情報
spring.datasource.url=jdbc:mysql://localhost:3306/sip_a?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Tokyo
spring.datasource.username=newuser
spring.datasource.password=0
# JDBCドライバ
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
# SQLログを出力
logging.level.org.springframework.jdbc.core=DEBUG
5.2 JDBCテンプレートの使い方
Spring Bootには JdbcTemplate
という便利なライブラリがあり、SQLをシンプルに記述できます。
(1) Carエンティティの作成
src/main/java/com/example/demo/model/Car.java
を作成し、以下のコードを記述します。
package com.example.demo.model;
import java.io.Serializable;
/**
* Carエンティティ
*/
public class Car implements Serializable {
private int carId;
private String name;
private int price;
/**
* 論理削除された日時 (nullの場合は未削除)
*/
private String deletedAt;
public Car() {
}
public Car(int carId, String name, int price, String deletedAt) {
this.carId = carId;
this.name = name;
this.price = price;
this.deletedAt = deletedAt;
}
public int getCarId() {
return carId;
}
public void setCarId(int carId) {
this.carId = carId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
public String getDeletedAt() {
return deletedAt;
}
public void setDeletedAt(String deletedAt) {
this.deletedAt = deletedAt;
}
@Override
public String toString() {
return "Car{" + "carId=" + carId + ", name='" + name + '\'' + ", price=" + price + ", deletedAt='" + deletedAt
+ '\'' + '}';
}
}
(2) DAO(データアクセスオブジェクト)を作成
JdbcTemplate
を使って、データベースからデータを取得するDAOクラスを作成します。
src/main/java/com/example/demo/model/CarDao.java
// @Repository はこのクラスがデータアクセス(DAO)を担当することを示すSpringのアノテーション。
// Springがこのクラスを自動的にBeanとして管理し、例外をSpringのDataAccessExceptionに変換する。
@Repository
public class CarDao {
// JdbcTemplate はSpringが提供するデータベース操作を簡単に行うためのクラス。
// SQLの実行や結果のマッピングを簡潔に記述できる。
private final JdbcTemplate jdbcTemplate;
// @Autowired を付けることで、Springがこのクラスのコンストラクタに
// 必要なBean(JdbcTemplate)を自動的に注入(DI)する。
@Autowired
public CarDao(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
/**
* 全件取得
*/
public List<Car> getCars() {
// 実行するSQL文
String sql = "SELECT * FROM cars";
// jdbcTemplate.query() はSQLを実行し、結果をオブジェクトのリストに変換するメソッド。
// 第2引数に RowMapper を指定することで、SQLの結果セットをCarオブジェクトにマッピングできる。
List<Car> list = jdbcTemplate.query(sql, new RowMapper<Car>() {
@Override
public Car mapRow(ResultSet rs, int rowNum) throws SQLException {
// Carオブジェクトを作成し、ResultSetから値を取り出してセットする。
Car c = new Car();
c.setCarId(rs.getInt("car_id")); // car_id カラムの値を取得し、セット
c.setName(rs.getString("name")); // name カラムの値を取得し、セット
c.setPrice(rs.getInt("price")); // price カラムの値を取得し、セット
c.setDeletedAt(rs.getString("deleted_at")); // deleted_at カラムの値を取得し、セット
return c; // マッピングされたCarオブジェクトを返す
}
});
return list; // 取得したCarオブジェクトのリストを返す
}
}
//(中略)
5.3 データ取得の基本 (SELECT文)
Spring Bootのコントローラを作成し、データベースから取得したデータを画面に表示してみます。
(1) コントローラの作成
src/main/java/com/example/demo/controller/CarController.java
package com.example.demo.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import com.example.demo.model.Car;
import com.example.demo.model.CarDao;
@Controller
public class CarController {
private final CarDao carDao;
@Autowired
public CarController(CarDao carDao) {
this.carDao = carDao;
}
@GetMapping("/cars")
public String listCars(Model model) {
List<Car> cars = carDao.getCars();
model.addAttribute("cars", cars);
return "car_list"; // car_list.html を表示
}
}
(2) Thymeleafでデータを表示
src/main/resources/templates/car_list.html
を作成します。
<!DOCTYPE html>
<html lang="ja" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>車一覧</title>
</head>
<body>
<h1>車一覧</h1>
<table border="1">
<tr>
<th>ID</th>
<th>名前</th>
<th>価格</th>
</tr>
<tr th:each="car : ${cars}">
<!-- `th:text` は Thymeleaf の属性で、サーバー側で car.carId の値に置き換えられる -->
<!-- もし car.carId の値が存在しない場合(このファイルを単体で実行したときなど)、"1" が表示される -->
<td th:text="${car.carId}">1</td>
<!-- 同様にcar.name の値がない場合、"車の名前" が表示される -->
<td th:text="${car.name}">車の名前</td>
<!-- 同様にcar.price の値がない場合、"2000000"(価格の例)が表示される -->
<td th:text="${car.price}">2000000</td>
</tr>
</table>
</body>
</html>
(3) アプリを実行して確認
SpringKaeruApplication.java
を起動するhttp://localhost:8080/cars
にアクセス- MySQLのデータが画面に表示されていれば成功!
ハンズオン:データベースから車一覧を取得し、画面に表示する
【目標】
Spring Boot を使い、MySQLのデータを画面に表示する。
【手順】
- データベース (MySQL) の作成
application.properties
にDB接続設定を追加- エンティティ (
Customer.java
) を作成 - DAO (
CustomerDao.java
) を作成 - コントローラ (
CustomerController.java
) を作成 - ビュー (
customer_list.html
) を作成 - ブラウザで
http://localhost:8080/customers
にアクセスし、データが表示されることを確認
まとめ
- Spring Boot では
JdbcTemplate
を使って MySQLと簡単に接続できる - DAOパターンを使って、データアクセスを分離する
- @Repository を使ってデータベースアクセスクラスを定義する
- @Autowired を使ってコンポーネントを自動的に注入できる
- Thymeleaf を使ってデータを動的に表示する
次章では、データの追加・更新・削除を行い、より本格的なデータ操作を学びます!
第6章:データの追加・更新・削除
6.1 データの追加(INSERT)
データベースに新しいデータを追加するには、SQLの INSERT
文を使います。
Spring Bootでは、JdbcTemplate
を使って簡単にデータを追加できます。
(1) フォームを作成
新しい車を登録するためのフォームを作成します。
src/main/resources/templates/car_form.html
<!DOCTYPE html>
<html lang="ja" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>車の追加</title>
</head>
<body>
<h1>新しい車を追加</h1>
<form th:action="@{/cars/add}" method="post">
<label>車の名前:</label>
<input type="text" name="name" required>
<br>
<label>価格:</label>
<input type="number" name="price" required>
<br>
<button type="submit">追加</button>
</form>
</body>
</html>
(2) コントローラの追加
フォームのデータを受け取って、データベースに登録します。
src/main/java/com/example/demo/controller/CarController.java
package com.example.demo.controller;
import com.example.demo.model.Car;
import com.example.demo.model.CarDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import java.util.List;
@Controller
public class CarController {
private final CarDao carDao;
@Autowired
public CarController(CarDao carDao) {
this.carDao = carDao;
}
@GetMapping("/cars")
public String listCars(Model model) {
List<Car> cars = carDao.getCars();
model.addAttribute("cars", cars);
return "car_list"; // car_list.html を表示
}
@GetMapping("/cars/form")
public String carForm() {
return "car_form"; // car_form.html を表示
}
@PostMapping("/cars/add")
public String addCar(@RequestParam String name, @RequestParam int price) {
carDao.addCar(new Car(0, name, price));
return "redirect:/cars"; // 登録後に一覧ページへリダイレクト
// リダイレクトを使用する理由:
// 1. PRG (Post/Redirect/Get) パターンを適用することで、
// フォームの再送信による二重登録を防ぐ。
// 2. ユーザーが「更新」ボタンを押しても、再度POSTリクエストが送信されることがない。
// 3. 処理が完了した後、明示的に一覧ページへ遷移させることで、
// ユーザーに最新のデータを表示できる。
}
}
(3) DAOにデータ追加メソッドを作成
JdbcTemplate
を使って INSERT
文を実行するメソッドを追加します。
src/main/java/com/example/demo/model/CarDao.java
public int addCar(Car car) {
// SQL文を定義。`?` はプレースホルダ(後から値を埋め込む)
String sql = "INSERT INTO cars (name, price) VALUES (?, ?)";
// updateメソッドの引数
// 第1引数: 実行するSQL文(プレースホルダを含む)
// 第2引数: プレースホルダの1つ目の値(carのname)
// 第3引数: プレースホルダの2つ目の値(carのprice)
return jdbcTemplate.update(sql, car.getName(), car.getPrice());
}
(4) 確認
http://localhost:8080/cars/form
にアクセス- 車の名前と価格を入力して送信
http://localhost:8080/cars
でデータが追加されていることを確認
6.2 データの更新(UPDATE)
データを更新するには、SQLの UPDATE
文を使います。
(1) フォームの作成
編集用のフォームを作成します。
src/main/resources/templates/car_edit.html
<!DOCTYPE html>
<html lang="ja" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>車の編集</title>
</head>
<body>
<h1>車の編集</h1>
<form th:action="@{/cars/update}" method="post">
<!--
th:value 属性は、Thymeleaf の式を使用して HTML 要素の value 属性に値を設定するためのものです。
ここでは、car オブジェクトの carId プロパティの値を hidden フィールドに設定しています。
ユーザーには表示されませんが、フォーム送信時に carId の値がサーバーへ送信されます。
-->
<input type="hidden" name="carId" th:value="${car.carId}">
<label>車の名前:</label>
<input type="text" name="name" th:value="${car.name}" required>
<br>
<label>価格:</label>
<input type="number" name="price" th:value="${car.price}" required>
<br>
<button type="submit">更新</button>
</form>
</body>
</html>
(2) コントローラの追加
更新処理のためのコントローラを追加します。
src/main/java/com/example/demo/controller/CarController.java
@GetMapping("/cars/edit")
public String editCar(@RequestParam int id, Model model) {
Car car = carDao.getCar(id);
model.addAttribute("car", car);
return "car_edit";
}
@PostMapping("/cars/update")
public String updateCar(@RequestParam int carId, @RequestParam String name, @RequestParam int price) {
carDao.updateCar(new Car(carId, name, price));
return "redirect:/cars";
}
(3) DAOに更新メソッドを追加
src/main/java/com/example/demo/model/CarDao.java
public int updateCar(Car car) {
String sql = "UPDATE cars SET name=?, price=? WHERE car_id=?";
return jdbcTemplate.update(sql, car.getName(), car.getPrice(), car.getCarId());
}
(4) 確認
http://localhost:8080/cars
で「編集」リンクをクリック- 車の情報を変更して送信
http://localhost:8080/cars
でデータが更新されたことを確認
6.3 データの削除(DELETE)
データを削除するには、SQLの DELETE
文を使います。
(1) 削除ボタンを追加
car_list.html
に削除ボタンを追加します。
src/main/resources/templates/car_list.html
<tr th:each="car : ${cars}"> <!-- carsリストの各要素をcarとしてループ処理 -->
<td th:text="${car.carId}"></td> <!-- carのcarIdを表示 -->
<td th:text="${car.name}"></td> <!-- carのnameを表示 -->
<td th:text="${car.price}"></td> <!-- carのpriceを表示 -->
<td>
<!-- 編集リンク: car.carIdをURLのクエリパラメータとして渡し、編集ページへ遷移 -->
<a th:href="@{/cars/edit(id=${car.carId})}">編集</a>
<!-- 削除リンク: car.carIdをURLのクエリパラメータとして渡し、削除処理を実行 -->
<!-- onclick属性でJavaScriptのconfirm関数を使用し、ユーザーに削除の確認を促す -->
<a th:href="@{/cars/delete(id=${car.carId})}" onclick="return confirm('削除しますか?')">削除</a>
</td>
</tr>
(2) コントローラの追加
削除処理のためのメソッドを追加します。
src/main/java/com/example/demo/controller/CarController.java
@GetMapping("/cars/delete")
public String deleteCar(@RequestParam int id) {
carDao.deleteCar(id);
return "redirect:/cars";
}
(3) DAOに削除メソッドを追加
src/main/java/com/example/demo/model/CarDao.java
public int deleteCar(int carId) {
String sql = "DELETE FROM cars WHERE car_id=?";
return jdbcTemplate.update(sql, carId);
}
(4) 確認
http://localhost:8080/cars
にアクセス- 「削除」ボタンをクリック
- データが削除されることを確認
ハンズオン:新しい顧客を追加・編集・削除できる機能を作成する
【目標】
Spring Boot を使い、MySQLのデータを追加・更新・削除できるようにする。
【手順】
- 追加フォーム (
customer_form.html
) を作成 - 更新フォーム (
customer_edit.html
) を作成 - 一覧ページ (
customer_list.html
) に削除ボタンを追加 - DAO (
CustomerDao.java
) に追加・更新・削除メソッドを追加 - コントローラ (
CustomerController.java
) に追加・更新・削除処理を追加 - ブラウザで操作し、動作を確認
まとめ
JdbcTemplate
は、Spring Framework の org.springframework.jdbc.core.JdbcTemplate
クラスで提供される JDBC 操作のための便利な API です。ここでは、主要なメソッドを用途ごとにまとめます。
1. データの取得(SELECT)
メソッド | 説明 |
---|---|
query(String sql, RowMapper<T> rowMapper) | SQL を実行し、RowMapper を使用して結果をオブジェクトに変換する |
query(String sql, Object[] args, RowMapper<T> rowMapper) | プレースホルダー付き SQL を実行し、結果を RowMapper で処理する |
queryForObject(String sql, Class<T> requiredType) | 単一の結果を取得し、指定した型 (Integer など) で返す |
queryForObject(String sql, Object[] args, Class<T> requiredType) | プレースホルダー付き SQL で単一の値を取得する |
queryForMap(String sql) | クエリの結果を Map<String, Object> で取得する(1行のみ) |
queryForList(String sql, Class<T> elementType) | クエリの結果を List<T> で取得する |
2. データの追加・更新・削除(INSERT / UPDATE / DELETE)
メソッド | 説明 |
---|---|
update(String sql) | SQL を実行し、変更された行数を返す |
update(String sql, Object... args) | プレースホルダー付き SQL を実行し、変更された行数を返す |
3. データの挿入とキーの取得(INSERT)
メソッド | 説明 |
---|---|
update(PreparedStatementCreator psc, KeyHolder kh) | 挿入時に自動生成されたキーを KeyHolder で取得する |
次章では、リクエストパラメータとフォーム入力を活用し、検索機能を実装します!
JUnitによるテスト
Spring Bootプロジェクトでは、テストのために JUnit を標準で利用することが多いです。spring-boot-starter-test
という依存関係を追加すると、JUnitやMockitoなど、テストに必要なライブラリがまとめて導入されます。
1. 依存関係の追加
pom.xml
の <dependencies>
内に以下を追記することで、JUnit環境が整います。(初期プロジェクト作成時に「Spring Boot Starter Test」を選ぶと自動的に含まれます。)
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope> <!-- テスト時のみ有効 -->
</dependency>
2. テストクラスの配置
Mavenプロジェクトの構造では、src/test/java
にテスト用のクラスを作成します。
例えば、CarDaoTest.java
というクラスを作り、DAOのメソッドが正しく動作するかを確認するテストを書きます。
SpringBootSample/
├── src/main/java/com/example/demo/ # 本番コード
│ └── model/CarDao.java
└── src/test/java/com/example/demo/ # テストコード
└── model/CarDaoTest.java
3. JUnitテストの基本例
以下は、JUnit 5 (Jupiter) を使ったテストの簡単な例です。
package com.example.demo.model;
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
/**
* CarDaoのメソッドをテストする例
*/
@SpringBootTest
class CarDaoTest {
@Autowired
private CarDao carDao;
@Test
void testGetCars() {
// 例:全件取得が0件以上であることを検証
assertFalse(carDao.getCars().isEmpty(), "車の一覧が空でないこと");
}
@Test
void testAddCar() {
// 例:新しいCarを追加し、戻り値が1(1行追加)であることを検証
Car newCar = new Car(0, "TestCar", 999999, null);
int result = carDao.addCar(newCar);
assertEquals(1, result, "INSERTが成功した場合は1が返るはず");
}
}
@SpringBootTest
Spring Bootアプリケーションのコンテキストを読み込み、DI(依存性注入)を有効にしてテストできるアノテーションです。@Autowired
で DAO や Service を注入できます。@Test
JUnit 5 (JUnit Jupiter) におけるテストメソッドであることを示すアノテーションです。
メソッド名は自由ですが、testSomething()
という形にすると分かりやすいです。assertXXX(...)
系メソッド
JUnitで用意されているアサーション(検証)メソッドです。assertFalse(条件, "メッセージ")
: 条件がfalseであることを期待assertEquals(期待値, 実際の値, "メッセージ")
: 値が等しいことを期待
4. テストの実行
Eclipse などのIDE上で、テストクラス(例: CarDaoTest.java
)を右クリックし、「JUnitテストを実行」を選択するとテストが走ります。
また、Mavenを使ってコマンドラインから実行する場合は、以下のように mvn test
を実行します。
bashコピーするmvn clean test
- 成功時: すべてのテストメソッドが問題なく通れば、
BUILD SUCCESS
と表示されます。 - 失敗時: どのテストが失敗したか、どのアサーションで引っかかったかが表示されます。
5. JUnitのメリット
- バグの早期発見:リファクタリングや機能追加時にテストを実行し、既存機能が壊れていないか確認できる。
- ドキュメントとして機能:テストコードが動作仕様の一部として機能する。
- 開発効率の向上:テストによって安心感を得られるため、新機能の追加や既存コードの修正がしやすくなる。
6. まとめ
JUnit の assertXXX(...) 系メソッドを よく使われるものに限定して まとめた表を作成しました。
メソッド | 説明 | 使用例 |
---|---|---|
assertEquals(expected, actual) | 期待値と実際の値が等しいことを検証する | assertEquals(5, result); |
assertNotEquals(unexpected, actual) | 期待しない値と実際の値が異なることを検証する | assertNotEquals(0, count); |
assertTrue(condition) | 条件が true であることを検証する | assertTrue(result > 0); |
assertFalse(condition) | 条件が false であることを検証する | assertFalse(list.isEmpty()); |
assertNull(actual) | オブジェクトが null であることを検証する | assertNull(user); |
assertNotNull(actual) | オブジェクトが null でない ことを検証する | assertNotNull(product); |
assertSame(expected, actual) | 同じオブジェクト であることを検証する | assertSame(obj1, obj2); |
assertNotSame(unexpected, actual) | 異なるオブジェクト であることを検証する | assertNotSame(newObj1, newObj2); |
assertArrayEquals(expected, actual) | 配列の内容が等しい ことを検証する | assertArrayEquals(new int[]{1,2,3}, actualArray); |
assertThrows(expectedType, executable) | 例外が発生することを検証する | assertThrows(IllegalArgumentException.class, () -> methodCall()); |
補足
assertEquals
とassertNotEquals
は、数値・文字列・オブジェクトの比較によく使われます。assertTrue
/assertFalse
は、条件式の検証に便利です。assertNull
/assertNotNull
は、値が 適切にセットされているかどうか を確認する際に有効です。assertSame
/assertNotSame
は、参照が同じかどうか をテストします(==
の動作)。assertArrayEquals
は、配列の中身が同じかどうかを確認するために使います。assertThrows
は、例外の発生を確認する ための重要なメソッドで、エラーハンドリングのテストでよく使われます。
JUnit 5 では、これらのメソッドは org.junit.jupiter.api.Assertions
に含まれています。import static org.junit.jupiter.api.Assertions.*;
を記述すると、メソッド名だけで呼び出せるようになります。
第7章:リクエストパラメータとフォーム入力
7.1 リクエストパラメータとは?
リクエストパラメータとは、URLやフォームを通じて送信されるデータ のことです。
Spring Bootでは、@RequestParam
を使って簡単に取得できます。
例: クエリパラメータ
http://localhost:8080/search?query=トヨタ
このURLでは、query
に "トヨタ"
という値が渡されています。
7.2 @RequestParam でパラメータを取得
@RequestParam
を使うと、URLからパラメータを取得できます。
(1) コントローラの作成
src/main/java/com/example/demo/controller/SearchController.java
package com.example.demo.controller;
import com.example.demo.model.Car;
import com.example.demo.model.CarDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import java.util.List;
@Controller
public class SearchController {
private final CarDao carDao;
@Autowired
public SearchController(CarDao carDao) {
this.carDao = carDao;
}
@GetMapping("/search")
public String search(@RequestParam(name = "query", required = false) String query, Model model) {
List<Car> cars;
if (query == null || query.isEmpty()) {
cars = carDao.getCars(); // 何も入力されていない場合は全件取得
} else {
cars = carDao.searchCars(query);
}
model.addAttribute("cars", cars);
return "search_results"; // search_results.html を表示
}
}
(2) DAOに検索メソッドを追加
LIKE
を使った部分一致検索を行います。
src/main/java/com/example/demo/model/CarDao.java
public List<Car> searchCars(String keyword) {
// SQLクエリを定義: carsテーブルからnameカラムがキーワードを含むレコードを取得
String sql = "SELECT * FROM cars WHERE name LIKE ?";
// 検索キーワードを部分一致検索用に加工
String param = "%" + keyword + "%";
// jdbcTemplateを使用してクエリを実行し、結果をCarオブジェクトのリストに変換
return jdbcTemplate.query(
sql,
new Object[]{param}, // プレースホルダにバインドする値
(rs, rowNum) ->
// ResultSetの各行をCarオブジェクトにマッピング
new Car(rs.getInt("car_id"), rs.getString("name"), rs.getInt("price"))
);
}
7.3 Thymeleafで検索フォームを作成
(1) 検索フォーム
src/main/resources/templates/search.html
<!DOCTYPE html>
<html lang="ja" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>検索</title>
</head>
<body>
<h1>車を検索</h1>
<form th:action="@{/search}" method="get">
<input type="text" name="query" placeholder="車の名前を入力">
<button type="submit">検索</button>
</form>
</body>
</html>
(2) 検索結果の表示
src/main/resources/templates/search_results.html
<!DOCTYPE html>
<html lang="ja" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>検索結果</title>
</head>
<body>
<h1>検索結果</h1>
<table border="1">
<tr>
<th>ID</th>
<th>名前</th>
<th>価格</th>
</tr>
<tr th:each="car : ${cars}">
<td th:text="${car.carId}"></td>
<td th:text="${car.name}"></td>
<td th:text="${car.price}"></td>
</tr>
</table>
</body>
</html>
(3) 動作確認
http://localhost:8080/search
にアクセス- 検索フォームに「車」と入力して送信
- 検索結果が一覧表示される
7.4 並べ替え機能を追加
検索結果を昇順・降順で並べ替えられるようにします。
(1) コントローラの修正
並べ替えのパラメータ (order
) を追加します。
@GetMapping("/search")
public String search(
// クエリパラメータ "query" を受け取る(指定がなくてもOK)
@RequestParam(name = "query", required = false) String query,
// クエリパラメータ "order" を受け取る(指定がない場合はデフォルト値 "asc")
@RequestParam(name = "order", required = false, defaultValue = "asc") String order,
// Viewにデータを渡すためのModelオブジェクト
Model model) {
// "order" パラメータが "desc" の場合は降順、それ以外は昇順
boolean isAscending = !order.equals("desc");
List<Car> cars; // 検索結果のリストを格納する変数
if (query == null || query.isEmpty()) {
// クエリが指定されていない場合は、全ての車を価格順でソートして取得
cars = carDao.getSortedCars("price", isAscending);
} else {
// クエリが指定されている場合は、検索結果を指定の順序で取得
cars = carDao.searchAndSortCars(query, isAscending);
}
// 取得した車のリストをモデルに追加し、ビューに渡す
model.addAttribute("cars", cars);
// 入力された検索クエリもモデルに追加(ビューで再表示できるようにするため)
model.addAttribute("query", query);
// "search_results" テンプレート(HTML)をレンダリングする
return "search_results";
}
(2) DAOの変更
新しい検索+並べ替えメソッドを追加。
public List<Car> getSortedCars(String sortField, boolean isAscending) {
// ソート順を決定(昇順: "ASC", 降順: "DESC")
String sortOrder = isAscending ? "ASC" : "DESC";
// SQLクエリを動的に生成(ソートするカラム名を外部から受け取る)
// 【注意】文字列連結によるSQLクエリの生成はSQLインジェクションのリスクがある
String sql = "SELECT * FROM cars ORDER BY " + sortField + " " + sortOrder;
// クエリを実行し、結果をCarオブジェクトのリストにマッピング
return jdbcTemplate.query(sql, (rs, rowNum) ->
new Car(rs.getInt("car_id"), rs.getString("name"), rs.getInt("price"))
);
}
public List<Car> searchAndSortCars(String keyword, boolean isAscending) {
// ソート順を決定(昇順: "ASC", 降順: "DESC")
String sortOrder = isAscending ? "ASC" : "DESC";
// 検索条件(nameに部分一致するデータを取得)
// SQLクエリの?プレースホルダーを使用することでSQLインジェクションを防ぐ
String sql = "SELECT * FROM cars WHERE name LIKE ? ORDER BY price " + sortOrder;
// LIKE検索用のパラメータを設定(部分一致検索のために%を付与)
String param = "%" + keyword + "%";
// クエリを実行し、結果をCarオブジェクトのリストにマッピング
return jdbcTemplate.query(sql, new Object[]{param}, (rs, rowNum) ->
new Car(rs.getInt("car_id"), rs.getString("name"), rs.getInt("price"))
);
}
(3) 並べ替えボタンの追加
search_results.html
に並べ替えボタンを追加
<p>並べ替え:</p>
<form th:action="@{/search}" method="get">
<input type="hidden" name="query" th:value="${query}">
<button type="submit" name="order" value="asc">価格の昇順▲</button>
<button type="submit" name="order" value="desc">価格の降順▼</button>
</form>
(4) 動作確認
http://localhost:8080/search
で検索- 「価格の昇順▲」「価格の降順▼」ボタンを押す
- 価格順に並べ替えられることを確認
ハンズオン:検索フォームを作成して、検索結果を表示する
【目標】
- フォームから入力したキーワードで顧客データを検索する
【手順】
- 検索フォーム (
search.html
) を作成 - コントローラ (
SearchController.java
) を作成 - DAO (
CustomerDao.java
) に検索メソッドを追加 - 検索結果 (
search_results.html
) を作成 - ブラウザで
http://localhost:8080/search
にアクセス - 検索と並べ替えが動作することを確認
まとめ
@RequestParam
を使うと、URLのクエリパラメータを取得できるLIKE
を使うと、部分一致検索ができるORDER BY
を使って、昇順・降順の並べ替えができるJdbcTemplate
を使って、データベースと連携できる
次章では、セッションと認証の仕組みを学び、ログイン機能を実装します!
第8章:セッションと認証
8.1 セッションとは?
Webアプリケーションやネットワークの分野で「セッション」という言葉は、ある特定の時間内にクライアント(ユーザーのブラウザなど)とサーバーがやり取りを行う一連の通信のことを指します。セッションは、一回の接続やリクエスト単体ではなく、ログイン状態の維持や複数の操作の関連付けを可能にする仕組みとして重要です。
例えば、ECサイトでユーザーがログインし、カートに商品を追加して決済を行うまでの流れは、同じセッション内で処理される必要があります。このため、サーバーは「セッションID」という識別子を発行し、ブラウザのクッキーやURLパラメータなどを使って管理します。
HTTPは本来「ステートレス(状態を保持しない)」なプロトコルのため、通常のリクエストは毎回新しい接続として扱われます。しかし、セッションを利用することで、サーバー側がユーザーごとの状態を一時的に保持し、利便性を向上させることができます。
Spring Boot では、HttpSession
を使ってセッション管理 ができます。
8.2 ログイン機能の実装
(1) テーブルの作成
まず、ログインユーザーを管理する login_user
テーブルを作成します。
CREATE TABLE login_user (
id INT AUTO_INCREMENT PRIMARY KEY,
login_id VARCHAR(45) NOT NULL UNIQUE,
password VARCHAR(100) NOT NULL
);
INSERT INTO login_user (login_id, password) VALUES
('user1', 'password1'),
('admin', 'adminpass');
(2) ユーザーモデルの作成
src/main/java/com/example/demo/model/User.java
package com.example.demo.model;
import java.io.Serializable;
public class User implements Serializable {
private int id;
private String loginId;
private String password;
public User() {}
public User(int id, String loginId, String password) {
this.id = id;
this.loginId = loginId;
this.password = password;
}
public int getId() { return id; }
public void setId(int id) { this.id = id; }
public String getLoginId() { return loginId; }
public void setLoginId(String loginId) { this.loginId = loginId; }
public String getPassword() { return password; }
public void setPassword(String password) { this.password = password; }
}
(3) DAOの作成
ユーザー情報を取得するDAOを作成します。
src/main/java/com/example/demo/model/UserDao.java
package com.example.demo.model;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;
import java.sql.ResultSet;
import java.sql.SQLException;
// @Repository アノテーションを付けることで、このクラスがデータアクセス層 (DAO) のコンポーネントであることを示す。
// Spring によって Bean として管理され、DI (依存性注入) の対象になる。
@Repository
public class UserDao {
private final JdbcTemplate jdbcTemplate;
// @Autowired により、Spring の DI コンテナが JdbcTemplate のインスタンスを自動的に注入する。
// JdbcTemplate はデータベースへの問い合わせを簡潔に記述できるようにする Spring の便利なクラス。
@Autowired
public UserDao(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
// 指定された loginId をもとに、login_user テーブルからユーザー情報を取得する。
public User findByLoginId(String loginId) {
// プレースホルダー (?) を使って SQL インジェクションを防ぐ。
String sql = "SELECT * FROM login_user WHERE login_id = ?";
// queryForObject メソッドを使って、1件のデータを取得。
// 第3引数には、RowMapper を指定し、ResultSet から User オブジェクトを生成する。
return jdbcTemplate.queryForObject(sql, new Object[]{loginId}, new RowMapper<User>() {
@Override
public User mapRow(ResultSet rs, int rowNum) throws SQLException {
// ResultSet からデータを取得し、User インスタンスを生成して返す。
return new User(rs.getInt("id"), rs.getString("login_id"), rs.getString("password"));
}
});
}
}
(4) ログインフォームの作成
ユーザーがログインするためのフォームを作成します。
src/main/resources/templates/login.html
<!DOCTYPE html>
<html lang="ja" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>ログイン</title>
</head>
<body>
<h1>ログイン</h1>
<form th:action="@{/login}" method="post">
<label>ログインID:</label>
<input type="text" name="loginId" required>
<br>
<label>パスワード:</label>
<input type="password" name="password" required>
<br>
<button type="submit">ログイン</button>
</form>
<p th:if="${error}" style="color:red;">ログインIDまたはパスワードが違います。</p>
</body>
</html>
(5) ログイン処理
セッションを使って、ログイン状態を管理します。
src/main/java/com/example/demo/controller/LoginController.java
package com.example.demo.controller;
import com.example.demo.model.User;
import com.example.demo.model.UserDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import jakarta.servlet.http.HttpSession;
/**
* ユーザーのログイン機能を提供するコントローラークラス。
* Spring MVC の @Controller アノテーションを使用して、リクエストのハンドリングを行う。
*/
@Controller
public class LoginController {
private final UserDao userDao;
/**
* @Autowired を使用して、UserDao のインスタンスを DI(依存性注入)する。
* DI により、UserDao のインスタンス管理を Spring に任せることができる。
*/
@Autowired
public LoginController(UserDao userDao) {
this.userDao = userDao;
}
/**
* ログイン画面を表示する。
* GETリクエスト "login" に対応。
* @return ログイン画面のビュー名 "login" を返す。
*/
@GetMapping("/login")
public String showLoginForm() {
return "login";
}
/**
* ログイン処理を行う。
* POSTリクエスト "login" に対応。
*
* @param loginId ユーザーが入力したログインID
* @param password ユーザーが入力したパスワード
* @param session ログイン情報をセッションに保存するための HttpSession
* @param model ログイン失敗時にエラーメッセージを表示するための Model
* @return ログイン成功時はマイページへリダイレクト、失敗時はログイン画面を再表示。
*/
@PostMapping("/login")
public String login(@RequestParam String loginId, @RequestParam String password, HttpSession session, Model model) {
try {
// ユーザー情報をデータベースから取得
User user = userDao.findByLoginId(loginId);
// 取得したユーザー情報があり、かつパスワードが一致する場合
if (user != null && user.getPassword().equals(password)) {
// セッションにユーザー情報を保存し、マイページにリダイレクト
session.setAttribute("loginUser", user);
return "redirect:/mypage";
}
} catch (Exception e) {
// データベースエラーなどの例外が発生した場合の処理
// (ここでは特に何もしないが、ログにエラーメッセージを出すとよい)
}
// ログイン失敗時、エラーフラグを設定し、再びログイン画面を表示
model.addAttribute("error", true);
return "login";
}
/**
* ログアウト処理を行う。
* GETリクエスト "logout" に対応。
* @param session 現在のセッションを無効化する。
* @return ログアウト後はログイン画面へリダイレクト。
*/
@GetMapping("/logout")
public String logout(HttpSession session) {
session.invalidate(); // セッションを破棄してログアウト処理を実行
return "redirect:/login";
}
}
(6) マイページの作成
ログイン後のページを作成し、セッション情報を表示します。
src/main/resources/templates/mypage.html
<!DOCTYPE html>
<html lang="ja" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>マイページ</title>
</head>
<body>
<h1>マイページ</h1>
<p>ようこそ、<span th:text="${loginUser.loginId}">ゲスト</span> さん!</p>
<a href="/logout">ログアウト</a>
</body>
</html>
(7) マイページのコントローラ
src/main/java/com/example/demo/controller/MyPageController.java
package com.example.demo.controller;
import com.example.demo.model.User;
import jakarta.servlet.http.HttpSession;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
/**
* ユーザーのマイページを表示するコントローラー
*/
@Controller
public class MyPageController {
/**
* マイページを表示する処理
*
* @param session HTTPセッション。ログインユーザー情報を取得するために使用。
* @param model ビューにデータを渡すためのオブジェクト。
* @return マイページのテンプレート名。未ログインの場合はログインページへリダイレクト。
*/
@GetMapping("/mypage") // "/mypage" にアクセスした際にこのメソッドが実行される
public String myPage(HttpSession session, Model model) {
// セッションからログインユーザー情報を取得
User loginUser = (User) session.getAttribute("loginUser");
// ログインユーザーが存在しない場合、ログインページへリダイレクト
if (loginUser == null) {
return "redirect:/login";
}
// ログインユーザー情報をビューに渡す
model.addAttribute("loginUser", loginUser);
// "mypage" テンプレートを表示
return "mypage";
}
}
8.3 ログイン機能の動作確認
【目標】
ログインフォームからユーザーが認証できるようにする。
【手順】
http://localhost:8080/login
にアクセス- ログインIDとパスワードを入力
- 「ログイン」ボタンを押す
- マイページ (
http://localhost:8080/mypage
) にリダイレクトされる - 「ログアウト」ボタンを押すと、ログアウトして
/login
に戻る
まとめ
HttpSession
を使って ログイン状態を管理 する@RequestParam
で フォームの入力を取得 する@PostMapping
を使って ログイン処理を実装 する- ログイン後の画面 (
mypage.html
) を作成し、セッション情報を表示
次章では、簡易的な販売管理システムを作成し、アプリケーションの統合を行います!
第9章:簡易的な販売管理システムの作成
9.1 アプリの仕様設計
この章では、Spring Boot を使って簡易的な販売管理システムを作成 します。
システムの機能
✅ ログイン機能(前章で実装済み)
✅ 車の一覧表示(第5章で実装済み)
✅ 車の購入機能(新規追加)
✅ 購入履歴の表示機能(新規追加)
9.2 データベースの設計
(1) sales テーブルの作成
車の購入履歴を管理する sales
テーブルを作成します。
CREATE TABLE sales (
sale_id INT AUTO_INCREMENT PRIMARY KEY,
car_id INT NOT NULL,
customer_id INT NOT NULL,
saleDateTime TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (car_id) REFERENCES cars(car_id),
FOREIGN KEY (customer_id) REFERENCES login_user(id)
);
9.3 車の購入機能の実装
(1) DAOの作成
JdbcTemplate
を使って、車の購入データを登録します。
src/main/java/com/example/demo/model/SaleDao.java
package com.example.demo.model;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
@Repository
public class SaleDao {
private final JdbcTemplate jdbcTemplate;
@Autowired
public SaleDao(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
public int addSale(int carId, int customerId) {
String sql = "INSERT INTO sales (car_id, customer_id) VALUES (?, ?)";
return jdbcTemplate.update(sql, carId, customerId);
}
}
(2) コントローラの作成
車を購入すると、sales
テーブルにデータが追加されるようにします。
src/main/java/com/example/demo/controller/SaleController.java
package com.example.demo.controller;
import com.example.demo.model.SaleDao;
import com.example.demo.model.User;
import jakarta.servlet.http.HttpSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
@Controller
public class SaleController {
private final SaleDao saleDao;
@Autowired
public SaleController(SaleDao saleDao) {
this.saleDao = saleDao;
}
@GetMapping("/purchase")
public String purchase(@RequestParam int carId, HttpSession session) {
User loginUser = (User) session.getAttribute("loginUser");
if (loginUser == null) {
return "redirect:/login";
}
saleDao.addSale(carId, loginUser.getId());
return "redirect:/mypage";
}
}
(3) 購入ボタンの追加
購入ボタンを car_list.html
に追加します。
src/main/resources/templates/car_list.html
<tr th:each="car : ${cars}">
<td th:text="${car.carId}"></td>
<td th:text="${car.name}"></td>
<td th:text="${car.price}"></td>
<td>
<a th:href="@{/purchase(carId=${car.carId})}">購入</a>
</td>
</tr>
(4) 動作確認
http://localhost:8080/cars
にアクセス- 購入ボタンを押す
- データベースの
sales
テーブルにデータが登録されているか確認
9.4 購入履歴の表示
(1) DAOの作成
sales
テーブルから購入履歴を取得します。
src/main/java/com/example/demo/model/SaleDao.java
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import org.springframework.jdbc.core.RowMapper;
public List<String> getSalesByUserId(int customerId) {
String sql = "SELECT c.name FROM sales s INNER JOIN cars c ON s.car_id = c.car_id WHERE s.customer_id = ?";
return jdbcTemplate.query(sql, new Object[]{customerId}, new RowMapper<String>() {
@Override
public String mapRow(ResultSet rs, int rowNum) throws SQLException {
return rs.getString("name");
}
});
}
(2) コントローラの作成
src/main/java/com/example/demo/controller/MyPageController.java
package com.example.demo.controller;
import com.example.demo.model.SaleDao;
import com.example.demo.model.User;
import jakarta.servlet.http.HttpSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import java.util.List;
@Controller
public class MyPageController {
private final SaleDao saleDao;
@Autowired
public MyPageController(SaleDao saleDao) {
this.saleDao = saleDao;
}
@GetMapping("/mypage")
public String myPage(HttpSession session, Model model) {
User loginUser = (User) session.getAttribute("loginUser");
if (loginUser == null) {
return "redirect:/login";
}
List<String> sales = saleDao.getSalesByUserId(loginUser.getId());
model.addAttribute("loginUser", loginUser);
model.addAttribute("sales", sales);
return "mypage";
}
}
(3) マイページの修正
src/main/resources/templates/mypage.html
<!DOCTYPE html>
<html lang="ja" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>マイページ</title>
</head>
<body>
<h1>マイページ</h1>
<p>ようこそ、<span th:text="${loginUser.loginId}">ゲスト</span> さん!</p>
<h2>購入履歴</h2>
<ul>
<li th:each="sale : ${sales}" th:text="${sale}"></li>
</ul>
<a href="/logout">ログアウト</a>
</body>
</html>
(4) 動作確認
http://localhost:8080/cars
で車を購入http://localhost:8080/mypage
にアクセス- 購入履歴が表示されることを確認
9.5 ハンズオン:完成した販売管理アプリを動かしてみる
【目標】
- ログイン → 車の購入 → 購入履歴を確認する の一連の流れを実装する。
【手順】
sales
テーブルを作成- DAO (
SaleDao.java
) を作成 - 購入処理 (
SaleController.java
) を実装 - 購入履歴の表示 (
MyPageController.java
) を実装 - ブラウザで購入し、購入履歴が正しく表示されることを確認
まとめ
INSERT
を使って 購入データを登録INNER JOIN
を使って 購入履歴を取得HttpSession
を使って ログイン状態を管理- Thymeleaf を使って 購入履歴を表示
🚀 おめでとうございます! 簡易的な販売管理システムが完成しました!
次章では、全体の統合とアプリの改善点をまとめます。
第10章:アプリケーションの統合と改善
10.1 アプリケーションの全体構成
これまでの章で実装した機能を統合し、販売管理システムとして完成させます。
各機能を整理し、アプリケーションの構成を振り返ります。
✅ 実装した機能
機能 | 概要 |
---|---|
ログイン機能 | ユーザー認証を行い、セッション管理をする |
車の一覧表示 | MySQL の cars テーブルからデータを取得して表示 |
車の検索機能 | LIKE を使用して検索 |
車の並べ替え | 価格の昇順・降順にソート |
車の購入機能 | 購入したデータを sales テーブルに登録 |
購入履歴の表示 | ユーザーごとの購入履歴を sales テーブルから取得 |
🔧 改善ポイント
- ログインしていないユーザーのアクセス制限
- セキュリティの強化(パスワードのハッシュ化)
- UI の整理(メニューの追加)
- 例外処理の追加(エラーハンドリング)
10.2 ログインしていないユーザーのアクセス制限
現在の状態では、ログインしなくても /cars
や /mypage
にアクセスできます。
これを制限するために、ログインしていない場合は /login
にリダイレクトするように修正します。
(1) アクセス制限を追加
各コントローラで、ログイン状態をチェックし、未ログインの場合はリダイレクトします。
src/main/java/com/example/demo/controller/MyPageController.java
@GetMapping("/mypage")
public String myPage(HttpSession session, Model model) {
User loginUser = (User) session.getAttribute("loginUser");
if (loginUser == null) {
return "redirect:/login";
}
List<String> sales = saleDao.getSalesByUserId(loginUser.getId());
model.addAttribute("loginUser", loginUser);
model.addAttribute("sales", sales);
return "mypage";
}
src/main/java/com/example/demo/controller/CarController.java
@GetMapping("/cars")
public String listCars(HttpSession session, Model model) {
if (session.getAttribute("loginUser") == null) {
return "redirect:/login";
}
List<Car> cars = carDao.getCars();
model.addAttribute("cars", cars);
return "car_list";
}
10.3 セキュリティの強化(パスワードのハッシュ化)
現在はプレーンテキストのパスワードをデータベースに保存していますが、
セキュリティの観点から、ハッシュ化 して保存するように変更します。
(1) パスワードのハッシュ化
Spring Security の BCryptPasswordEncoder
を使ってパスワードを暗号化します。
(a) 依存関係を追加
pom.xml
に以下の依存関係を追加。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
(b) パスワードをハッシュ化
UserDao
にパスワードをハッシュ化して保存する処理を追加します。
src/main/java/com/example/demo/model/UserDao.java
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
public int registerUser(String loginId, String password) {
// ユーザー情報をデータベースに登録するためのSQL文
String sql = "INSERT INTO login_user (login_id, password) VALUES (?, ?)";
// BCryptPasswordEncoder を使用してパスワードをハッシュ化
// ハッシュ化することで、データベースに生のパスワードを保存せずに済み、セキュリティを強化できる
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
String hashedPassword = encoder.encode(password); // パスワードをハッシュ化
// SQL を実行してユーザー情報をデータベースに保存
// loginId はそのまま、password はハッシュ化したものを保存する
return jdbcTemplate.update(sql, loginId, hashedPassword);
}
(c) ログイン時にハッシュ化されたパスワードを比較
LoginController.java
@PostMapping("/login") // HTTP POSTリクエストを受け付けるエンドポイント(ログイン処理)
public String login(
@RequestParam String loginId, // リクエストパラメータから loginId を取得
@RequestParam String password, // リクエストパラメータから password を取得
HttpSession session, // セッション管理のための HttpSession オブジェクト
Model model) { // View にデータを渡すための Model オブジェクト
try {
// ユーザー情報をDBから検索
User user = userDao.findByLoginId(loginId);
// パスワードのハッシュ化・検証のための BCryptPasswordEncoder を作成
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
// ユーザーが存在し、パスワードが一致する場合
if (user != null && encoder.matches(password, user.getPassword())) {
// セッションにログインユーザー情報を保存
session.setAttribute("loginUser", user);
// マイページへリダイレクト
return "redirect:/mypage";
}
} catch (Exception e) {
// 例外処理:通常はログを出力するべき(ここでは省略)
// 例外が発生してもログイン失敗として処理を継続
}
// ログイン失敗時にエラーフラグを設定し、ログイン画面に戻す
model.addAttribute("error", true);
return "login";
}
10.4 メニューの追加
アプリのナビゲーションを改善するため、メニューを追加 します。
(1) メニューを作成
src/main/resources/templates/menu.html
<!DOCTYPE html>
<html lang="ja" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>メニュー</title>
</head>
<body>
<h1>メニュー</h1>
<ul>
<li><a href="/mypage">マイページ</a></li>
<li><a href="/cars">車一覧</a></li>
<li><a href="/search">車の検索</a></li>
<li><a href="/logout">ログアウト</a></li>
</ul>
</body>
</html>
(2) 各ページにメニューを組み込み
各ページの先頭に以下のコードを追加します。
<div th:replace="menu :: *"></div>
10.5 例外処理の追加
データベース接続エラーや存在しないデータを取得したときのために、エラーハンドリングを追加します。
(1) グローバルエラーハンドリング
Spring Boot の @ControllerAdvice
を使い、アプリ全体のエラーをキャッチします。このコードは決まり文句なので詳細な解説は割愛します。
src/main/java/com/example/demo/exception/GlobalExceptionHandler.java
package com.example.demo.exception;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
public String handleException(Exception e, Model model) {
model.addAttribute("errorMessage", "エラーが発生しました: " + e.getMessage());
return "error";
}
}
(2) エラーページの作成
src/main/resources/templates/error.html
<!DOCTYPE html>
<html lang="ja" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>エラー</title>
</head>
<body>
<h1>エラーが発生しました</h1>
<p th:text="${errorMessage}"></p>
<a href="/">トップページへ戻る</a>
</body>
</html>
10.6 動作確認
【目標】
全体の動作を統合し、本番環境に近い形でアプリケーションを動作させる。
【手順】
- ログインしていない状態で
/cars
にアクセスし、リダイレクトされるか確認 - パスワードのハッシュ化が適用されているか確認
- メニューが正しく表示され、ナビゲーションできるか確認
- エラー発生時に
error.html
が表示されるか確認
まとめ
- ログインしていないユーザーを
/login
にリダイレクト - パスワードを
BCryptPasswordEncoder
でハッシュ化 - メニューを追加して UI を改善
@ControllerAdvice
を使い、エラー処理を統一
おめでとうございます! 本書のゴールである Spring Boot を使ったWebアプリケーションの完成 です!
当社の新人研修では、このアプリをベースに、機能を拡張していくことで、さらに実践的なスキルを磨きましょう!
セイ・コンサルティング・グループの新人エンジニア研修のメニューへのリンク
投稿者プロフィール

- 代表取締役
-
セイ・コンサルティング・グループ株式会社代表取締役。
岐阜県出身。
2000年創業、2004年会社設立。
IT企業向け人材育成研修歴業界歴20年以上。
すべての無駄を省いた費用対効果の高い「筋肉質」な研修を提供します!
この記事に間違い等ありましたらぜひお知らせください。