Spring Bootを使った新人エンジニア向けWebアプリ開発テキスト

第1章:Spring Bootの概要

1.1 Spring Bootとは?

Spring Boot は、Java を使った Web アプリケーション開発を簡単にするフレームワークです。
Spring フレームワークをベースにしており、設定の手間を減らし、シンプルに開発できるのが特徴です。

主な特徴

  • 設定不要で使える:自動設定(Auto Configuration)により、設定ファイルの記述を最小限にできる。
  • 組み込みサーバ:Tomcat などのサーバが最初から組み込まれており、単体で動作可能。
  • 依存関係の管理が簡単:Maven で必要なライブラリを簡単に追加できる。
  • 軽量な開発環境:Spring Boot DevTools を使うと、変更を即時反映できる。

フレームワークとは?

フレームワークとは、ソフトウェア開発を効率化するための基盤となるプログラムの集合体です。共通の機能や構造を提供し、開発者は基本部分を流用しながらアプリケーションを構築できます。代表例にSpringやLaravelなどがあります。

Tomcatとは?

Tomcat(Apache Tomcat)は、Javaで作られたWebアプリケーションを動作させるためのサーブレットコンテナ(Webサーバー機能を持つ実行環境)です。Webブラウザへ動的なページを返す役割を担います。

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                            # 依存関係を管理するファイル

Mavenとは? 依存関係とは?

Mavenは、Apacheが開発したJava向けのビルド管理ツールです。プロジェクトの依存関係管理やビルド、テスト、デプロイを自動化し、統一されたプロジェクト構成を提供します。XML形式のPOMファイルで設定し、再現性の高い開発環境を実現できます。

依存関係とは、ある要素が他の要素に依存している状態を指します。ソフトウェア開発では、プログラムやモジュールが特定のライブラリやコンポーネントに依存することを意味し、適切な管理が求められます。



1.3 EclipseでのSpring Bootプロジェクト作成

Spring Boot のプロジェクトを作成し、実際に起動してみましょう。

(1) Eclipseでプロジェクトを作成
  1. Eclipse を開き、「ファイル」→「新規」→「Spring Bootプロジェクト」を選択
  2. 「Spring Boot バージョン」は 3.1.1 を選択
  3. 「依存関係の追加」で以下を選択
    • Spring Web
    • Thymeleaf
    • Spring Data JDBC
    • MySQL Driver
  4. 「完了」をクリックしてプロジェクトを作成
(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 にアクセスすると、アプリケーションが起動していることを確認できます。

http://localhost:8080とは?

http://localhost:8080 は、ローカル環境で動作するWebアプリケーションにアクセスするためのURL です。

  1. localhost
    • 自分のコンピュータ(ローカルホスト)を指します。
    • 外部のネットワークではなく、開発環境でアプリをテストするときによく使います。
  2. 8080(ポート番号)
    • コンピュータ内で特定のアプリケーション(サーバー)を識別するための番号です。
    • Spring Bootでは、デフォルトで 8080 が使われますが、設定で変更できます。

ハンズオン:Spring Bootの初期プロジェクトを作成し、起動してみよう

【目標】

Spring Boot のプロジェクトを作成し、ブラウザで起動を確認する。

【手順】

  1. Eclipse で Spring Boot プロジェクトを作成する。
  2. SpringKaeruApplication.java を実行し、アプリを起動する。
  3. http://localhost:8080 にアクセスし、エラーページが表示されることを確認する。

→ まだコントローラを作成していないため、エラーになるのが正しい動作です!

【確認ポイント】

  • Eclipse で Spring Boot プロジェクトが作成できたか?
  • main メソッドを実行し、Spring Boot アプリが起動したか?
  • http://localhost:8080 にアクセスし、エラーが表示されたか?

まとめ

  1. Spring Boot は Java の Web アプリ開発を簡単にするフレームワーク。
  2. 設定の手間が少なく、最小限のコードで動作する。
  3. Eclipse で Spring Boot プロジェクトを作成し、実際に起動してみる。

次章では、Spring Boot の基本的な仕組みを理解し、簡単な Web ページを表示する方法を学びます!

第2章:Spring Bootの基本


2.1 Spring Bootのアノテーション

Spring Boot では、コードをシンプルにするために アノテーション を多用します。
本章では、Spring Boot の基本的なアノテーションを理解し、簡単な Web ページを表示する方法を学びます。

アノテーションとは?

アノテーションは、クラスやメソッドに付ける特別な記述で、Springに「このクラスはコントローラー」「このメソッドはGETリクエストを処理」などの指示を与えるものです。

(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 の開発環境が正しく動作しているか確認します。

  1. Eclipse で SpringKaeruApplication.java を実行する
  2. 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

Thymeleafとは?

Thymeleaf(タイムリーフ)は、Javaのテンプレートエンジンの一つで、Spring Bootと組み合わせてよく使われます。HTMLファイルに特殊なタグや属性を埋め込むことで、サーバー側でデータを動的に埋め込んだり、条件分岐や繰り返し処理を行うことができます。

Thymeleaf(タイムリーフ)は、Javaのテンプレートエンジンの一つで、Spring Bootと組み合わせてよく使われます。HTMLファイルに特殊なタグや属性を埋め込むことで、サーバー側でデータを動的に埋め込んだり、条件分岐や繰り返し処理を行うことができます。



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 を表示
    }
}

Getリクエストの復習

GETリクエストは、クライアント(ブラウザなど)がサーバーに情報を要求する際に使用するHTTPリクエストの一種です。例えば、WebサイトのURLにアクセスすると、ブラウザは自動的にGETリクエストを送信します。GETリクエストは主にデータの取得を目的とし、リクエストパラメータをURLに含めることができます(例:/search?q=java)。また、サーバー側では@GetMappingを使用して特定のURLに対応する処理を実装します。フォーム送信や機密情報の送信には不向きです。



(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) アプリを起動し、ブラウザで確認

  1. SpringKaeruApplication.java を実行する
  2. http://localhost:8080/hello にアクセス
  3. 「Hello, Spring Boot!」と表示されることを確認する

ハンズオン:シンプルなHello Worldアプリを作成する

【目標】

Spring Boot を使って、「Hello, Spring Boot!」を表示するWebアプリを作成する。

【手順】

  1. HelloController.java を作成
  2. hello.html を作成
  3. アプリを起動し、ブラウザで動作確認
    • http://localhost:8080/hello にアクセス
    • 「Hello, Spring Boot!」が表示されることを確認

まとめ

  1. @SpringBootApplication はSpring Bootの基本設定をまとめたアノテーション
  2. @Controller はWebリクエストを処理するクラス
  3. @GetMapping でURLと処理を紐づける
  4. Thymeleaf を使って簡単なWebページを作成
  5. 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 を表示
    }
}

Tomcatを起動せずにtemplatesフォルダのhtmlファイルを確認する

Thymeleafを使ったHTMLテンプレートは、通常Spring Bootアプリケーションを起動してサーバー経由で確認しますが、簡易的にHTMLの内容を確認する方法はいくつかあります。

いちばん簡単なのは、EclipseでHTMLファイルを右クリック → 「次で開く」 → 「Webブラウザー」 を選択することです。Thymeleafの特殊な属性(th:text など)は無視されますが、通常のHTMLの構造やCSSの適用を確認する場合には有効です。



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 を表示
    }
}

org.springframework.ui.Modelとは?

org.springframework.ui.Model は、コントローラーからビュー(HTMLなど)にデータを渡すためのインターフェース です。model.addAttribute("キー", 値) を使うことで、テンプレートエンジン(Thymeleaf など)で利用できるデータをセットできます。

例えば、model.addAttribute("message", "こんにちは") とすると、message という変数がビューで使用でき、HTML側で ${message} のように記述すれば表示できます。


(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:ifth: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 を使い、商品のリストを画面に表示する。

【手順】

  1. コントローラ (ProductController.java) を作成
  2. テンプレート (products.html) を作成
  3. ブラウザで http://localhost:8080/products にアクセスし、リストが表示されることを確認

まとめ

  1. Thymeleaf は Spring Boot の公式テンプレートエンジン
  2. th:text でテキストを埋め込める
  3. th:each でリストを表示できる
  4. th:if で条件分岐ができる

次章では、コントローラの役割を深掘りしていきます!

第4章:Spring MVCの基本


4.1 Spring MVCとは?

Spring MVC は、Spring フレームワークの一部であり、Webアプリケーションの開発を簡単にするための仕組み です。
従来の Servlet + JSP に比べ、コードの記述量が少なく、整理されたアーキテクチャで開発できる のが特徴です。

Spring MVCの基本構造

Spring MVC では、以下の3つの要素を中心に構成されます。

  1. コントローラ (Controller)
    • ブラウザからのリクエストを受け取り、適切な処理を行う
    • @Controller を使って定義する
  2. モデル (Model)
    • データを管理する
    • @Service@Repository を使って定義する
  3. ビュー (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>

動作確認

  1. http://localhost:8080/form にアクセス
  2. 名前を入力して送信
  3. result.html に入力した名前が表示される

ハンズオン:コントローラを作成してデータを画面に表示する

【目標】

  • コントローラからデータを Thymeleaf に渡して表示する。

【手順】

  1. コントローラ (GreetingController.java) を作成
  2. Thymeleaf (greeting.html) を作成
  3. ブラウザで http://localhost:8080/greeting にアクセス
  4. 「こんにちは、新入社員さん!」と表示されることを確認

まとめ

  • 「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クラスを作成します。

DAOクラスとは?

DAO(Data Access Object)クラスとは、データベースとのやり取りを担当するクラスのことです。DAOの役割は、データの取得・登録・更新・削除(CRUD操作)を一元的に管理し、ビジネスロジックとデータ処理を分離することにあります。

DAOクラスを用いることで、SQL文の記述やJDBCの操作を専用のクラスにまとめられ、コードの可読性や保守性が向上します。また、データベースの変更があった場合でも、DAOクラスを修正するだけで済み、システム全体への影響を最小限に抑えられます。

一般的なDAOクラスには、データベース接続用のメソッド、SQL実行メソッド、エンティティクラスとのデータ変換処理などが含まれます。

src/main/java/com/example/demo/model/CarDao.java

package com.example.demo.model;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;

/**
 * Carテーブルへのアクセスを行うDAOクラス。 (Spring DataのCrudRepository等は使わず、JdbcTemplateで自前実装)
 */
@Repository
public class CarDao {

	private final JdbcTemplate jdbcTemplate;

	@Autowired
	public CarDao(JdbcTemplate jdbcTemplate) {
		this.jdbcTemplate = jdbcTemplate;
	}

	/**
	 * 全件取得
	 */
	public List<Car> getCars() {
		String sql = "SELECT * FROM cars";
		List<Car> list = jdbcTemplate.query(sql, new RowMapper<Car>() {
			@Override
			public Car mapRow(ResultSet rs, int rowNum) throws SQLException {
				Car c = new Car();
				c.setCarId(rs.getInt("car_id"));
				c.setName(rs.getString("name"));
				c.setPrice(rs.getInt("price"));
				c.setDeletedAt(rs.getString("deleted_at"));
				return c;
			}
		});
		return list;
	}
//(中略)


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}">
            <td th:text="${car.carId}">1</td>
            <td th:text="${car.name}">車の名前</td>
            <td th:text="${car.price}">2000000</td>
        </tr>
    </table>
</body>
</html>

(3) アプリを実行して確認

  1. SpringKaeruApplication.java を起動する
  2. http://localhost:8080/cars にアクセス
  3. MySQLのデータが画面に表示されていれば成功!

ハンズオン:データベースから車一覧を取得し、画面に表示する

【目標】

Spring Boot を使い、MySQLのデータを画面に表示する。

【手順】

  1. データベース (MySQL) の作成
  2. application.properties にDB接続設定を追加
  3. エンティティ (Car.java) を作成
  4. DAO (CarDao.java) を作成
  5. コントローラ (CarController.java) を作成
  6. ビュー (car_list.html) を作成
  7. ブラウザで http://localhost:8080/cars にアクセスし、データが表示されることを確認

まとめ

  • 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"; // 登録後に一覧ページへリダイレクト
    }
}

(3) DAOにデータ追加メソッドを作成

JdbcTemplate を使って INSERT 文を実行するメソッドを追加します。

src/main/java/com/example/demo/model/CarDao.java

public int addCar(Car car) {
    String sql = "INSERT INTO cars (name, price) VALUES (?, ?)";
    return jdbcTemplate.update(sql, car.getName(), car.getPrice());
}

(4) 確認

  1. http://localhost:8080/cars/form にアクセス
  2. 車の名前と価格を入力して送信
  3. 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">
        <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) 確認

  1. http://localhost:8080/cars で「編集」リンクをクリック
  2. 車の情報を変更して送信
  3. 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}">
    <td th:text="${car.carId}"></td>
    <td th:text="${car.name}"></td>
    <td th:text="${car.price}"></td>
    <td>
        <a th:href="@{/cars/edit(id=${car.carId})}">編集</a>
        <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) 確認

  1. http://localhost:8080/cars にアクセス
  2. 「削除」ボタンをクリック
  3. データが削除されることを確認

ハンズオン:新しい車を追加・編集・削除できる機能を作成する

【目標】

Spring Boot を使い、MySQLのデータを追加・更新・削除できるようにする。

【手順】

  1. 追加フォーム (car_form.html) を作成
  2. 更新フォーム (car_edit.html) を作成
  3. 一覧ページ (car_list.html) に削除ボタンを追加
  4. DAO (CarDao.java) に追加・更新・削除メソッドを追加
  5. コントローラ (CarController.java) に追加・更新・削除処理を追加
  6. ブラウザで操作し、動作を確認

まとめ

  • INSERT でデータを追加
  • UPDATE でデータを更新
  • DELETE でデータを削除
  • JdbcTemplate を使ってSQLを実行する

次章では、リクエストパラメータとフォーム入力を活用し、検索機能を実装します!

第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) {
    String sql = "SELECT * FROM cars WHERE name LIKE ?";
    String param = "%" + keyword + "%";
    return jdbcTemplate.query(sql, new Object[]{param}, (rs, rowNum) -> 
        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) 動作確認

  1. http://localhost:8080/search にアクセス
  2. 検索フォームに「トヨタ」と入力して送信
  3. 検索結果が一覧表示される

7.4 並べ替え機能を追加

検索結果を昇順・降順で並べ替えられるようにします。

(1) コントローラの修正

並べ替えのパラメータ (order) を追加します。

@GetMapping("/search")
public String search(@RequestParam(name = "query", required = false) String query,
                     @RequestParam(name = "order", required = false, defaultValue = "asc") String order,
                     Model model) {
    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);
    return "search_results";
}

(2) DAOの変更

新しい検索+並べ替えメソッドを追加。

public List<Car> getSortedCars(String sortField, boolean isAscending) {
    String sortOrder = isAscending ? "ASC" : "DESC";
    String sql = "SELECT * FROM cars ORDER BY " + sortField + " " + sortOrder;
    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) {
    String sortOrder = isAscending ? "ASC" : "DESC";
    String sql = "SELECT * FROM cars WHERE name LIKE ? ORDER BY price " + sortOrder;
    String param = "%" + keyword + "%";
    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) 動作確認

  1. http://localhost:8080/search で検索
  2. 「価格の昇順▲」「価格の降順▼」ボタンを押す
  3. 価格順に並べ替えられることを確認

ハンズオン:検索フォームを作成して、検索結果を表示する

【目標】

  • フォームから入力したキーワードでデータを検索する

【手順】

  1. 検索フォーム (search.html) を作成
  2. コントローラ (SearchController.java) を作成
  3. DAO (CarDao.java) に検索メソッドを追加
  4. 検索結果 (search_results.html) を作成
  5. ブラウザで http://localhost:8080/search にアクセス
  6. 検索と並べ替えが動作することを確認

まとめ

  • @RequestParam を使うと、URLのクエリパラメータを取得できる
  • LIKE を使うと、部分一致検索ができる
  • ORDER BY を使って、昇順・降順の並べ替えができる
  • JdbcTemplate を使って、データベースと連携できる

次章では、セッションと認証の仕組みを学び、ログイン機能を実装します!

第8章:セッションと認証


8.1 セッションとは?

Webアプリケーションでは、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
public class UserDao {

    private final JdbcTemplate jdbcTemplate;

    @Autowired
    public UserDao(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }

    public User findByLoginId(String loginId) {
        String sql = "SELECT * FROM login_user WHERE login_id = ?";
        return jdbcTemplate.queryForObject(sql, new Object[]{loginId}, new RowMapper<User>() {
            @Override
            public User mapRow(ResultSet rs, int rowNum) throws SQLException {
                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;

@Controller
public class LoginController {

    private final UserDao userDao;

    @Autowired
    public LoginController(UserDao userDao) {
        this.userDao = userDao;
    }

    @GetMapping("/login")
    public String showLoginForm() {
        return "login";
    }

    @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";
    }

    @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 {

    @GetMapping("/mypage")
    public String myPage(HttpSession session, Model model) {
        User loginUser = (User) session.getAttribute("loginUser");
        if (loginUser == null) {
            return "redirect:/login";
        }
        model.addAttribute("loginUser", loginUser);
        return "mypage";
    }
}

8.3 ログイン機能の動作確認

【目標】

ログインフォームからユーザーが認証できるようにする。

【手順】

  1. http://localhost:8080/login にアクセス
  2. ログインIDとパスワードを入力
  3. 「ログイン」ボタンを押す
  4. マイページ (http://localhost:8080/mypage) にリダイレクトされる
  5. 「ログアウト」ボタンを押すと、ログアウトして /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) 動作確認

  1. http://localhost:8080/cars にアクセス
  2. 購入ボタンを押す
  3. データベースの 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) 動作確認

  1. http://localhost:8080/cars で車を購入
  2. http://localhost:8080/mypage にアクセス
  3. 購入履歴が表示されることを確認

9.5 ハンズオン:完成した販売管理アプリを動かしてみる

【目標】

  • ログイン → 車の購入 → 購入履歴を確認する の一連の流れを実装する。

【手順】

  1. sales テーブルを作成
  2. DAO (SaleDao.java) を作成
  3. 購入処理 (SaleController.java) を実装
  4. 購入履歴の表示 (MyPageController.java) を実装
  5. ブラウザで購入し、購入履歴が正しく表示されることを確認

まとめ

  • 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) {
    String sql = "INSERT INTO login_user (login_id, password) VALUES (?, ?)";
    BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
    String hashedPassword = encoder.encode(password);
    return jdbcTemplate.update(sql, loginId, hashedPassword);
}

(c) ログイン時にハッシュ化されたパスワードを比較

LoginController.java

@PostMapping("/login")
public String login(@RequestParam String loginId, @RequestParam String password, HttpSession session, Model model) {
    try {
        User user = userDao.findByLoginId(loginId);
        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 動作確認

【目標】

全体の動作を統合し、本番環境に近い形でアプリケーションを動作させる

【手順】

  1. ログインしていない状態で /cars にアクセスし、リダイレクトされるか確認
  2. パスワードのハッシュ化が適用されているか確認
  3. メニューが正しく表示され、ナビゲーションできるか確認
  4. エラー発生時に error.html が表示されるか確認

まとめ

  • ログインしていないユーザーを /login にリダイレクト
  • パスワードを BCryptPasswordEncoder でハッシュ化
  • メニューを追加して UI を改善
  • @ControllerAdvice を使い、エラー処理を統一

🎉 おめでとうございます! 本書のゴールである Spring Boot を使ったWebアプリケーションの完成 です! 🚀
このアプリをベースに、機能を拡張していくことで、さらに実践的なスキルを磨けます!

セイ・コンサルティング・グループの新人エンジニア研修のメニューへのリンク

投稿者プロフィール

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