第06章 Spring Boot・Web

06_web

第06章 Webアプリケーション・Spring Boot(全面改訂版)

この章の読み方: 本文の基本説明、直後の発展解説、例題、演習の順に読んでください。専門用語は初めて出てきた箇所で意味を確認し、コードの予想結果を考えてから実行します。

章末の演習は、それまでの本文の内容を使って解けるように設計しています。

用語の表記: 全10章共通の用語集 と表記を揃えています。

独学演習: 学んだ内容の確認には、第06章の実行予想・段階別ヒント・自己チェックを使ってください。本文の説明を読んだあと、自分で出力を予想してから試します。

00. この章の学び方と完成条件

この章では、最初にデータベースなしで商品一覧を表示し、その後に商品を登録します。最後にMySQLへ保存する方法へ切り替えます。最初から全部を理解しようとする必要はありません。

必ず一つの操作が成功してから次に進み、成功した画面・URL・結果を記録してください。

学習環境はWindows 11、JDK 21、Eclipse、Maven、MySQL 8.4(後半のみ)です。Spring Boot 4.1.1を使用します。

最初のMaven依存ライブラリ取得にはインターネット接続が必要ですが、実行するアプリとMySQLは自分のPC内に置きます。クラウドやGitHubは使いません。

この章の合格条件は、①GETで一覧取得、②POSTで商品登録、③異常値でHTTP 400、④Controller→Service→Repositoryの追跡、⑤メモリー版の再起動によるデータ消失の確認、⑥MySQL版で再起動後も登録データが残ることの確認、⑦付属のテストが成功することです。

MySQL版の確認は実習の後半で行います。

この節の独学チェック:00. この章の学び方と完成条件

確認問題: この章でメモリー版からMySQL版へ進むのはなぜですか。

取り組み方: 解答を見る前に自分の答えを記録してください。

ヒント1

保存先を変える前に、画面からJavaへの流れを追いましょう。

ヒント2

まずHTTPの入口と業務処理がどう分かれるか考えます。

ヒント3

メモリーとDBの違いを学ぶ順序に意味があるか説明してください。

模範解答と理由

HTTPとJava側の役割を先に理解し、その後に保存先の違いと永続化を学ぶためです。

この節の自己採点基準(1点満点)

独立して判定する正答要素

  1. 1点: HTTPとJava側の役割を先に理解し、その後に保存先の違いと永続化を学ぶためです。

満点の正答例: HTTPとJava側の役割を先に理解し、その後に保存先の違いと永続化を学ぶためです。

部分点の判定: 正答要素は1つなので部分点はありません。意味が一致すれば1点、異なれば0点です。

誤答・採点ミスの例: 不十分な解答例:「よく分からないが、そのまま進めればよい」。正答条件「HTTPとJava側の役割を先に理解し、その後に保存先の違いと永続化を学ぶためです」を示していないので0点です。

合格条件:1/1点。 正答の言い換えは認めます。

復習先: この節「00. この章の学び方と完成条件」の本文および直前の例題。誤った採点要素を説明できるまで確認してから再回答します。

01. 前章とのつながり:なぜWebが必要なのか

第05章ではSQLを直接入力して商品を操作しました。しかし、業務システムを使う全員がSQLを覚えるのは現実的ではありません。そこで、利用者に「商品一覧」や「商品登録」という画面を提供し、画面の裏側でJavaが必要な処理を行います。

画面は入力を受け持ち、Javaは処理や入力の確認を受け持ち、MySQLはデータを保存します。これらは別々の役割を持っています。すべてが同じコンピューターで動いていても、この役割分担は変わりません。

この節の独学チェック:01. 前章とのつながり:なぜWebが必要なのか

確認問題: SQLを知らない業務利用者に商品一覧を見せるには、何を提供しますか。

取り組み方: 解答を見る前に自分の答えを記録してください。

ヒント1

利用者がSQLを入力できるとは限りません。

ヒント2

見せる画面とデータを返すAPIは同じものか考えます。

ヒント3

ブラウザ操作→HTTP→Java処理→商品情報の順にたどります。

模範解答と理由

利用者向けにはブラウザで操作するWeb画面を提供する方法があります。画面は必要に応じてHTTPでJavaのAPIを呼び出し、Java側が商品情報を検索して結果を返します。APIそのものは画面ではなく、データを受け渡すための入口です。

この節の自己採点基準(3点満点)

独立して判定する正答要素

  1. 1点: 利用者向けにはブラウザで操作するWeb画面を提供する方法があります。
  2. 1点: 画面は必要に応じてHTTPでJavaのAPIを呼び出し、Java側が商品情報を検索して結果を返します。
  3. 1点: APIそのものは画面ではなく、データを受け渡すための入口です。

満点の正答例: 利用者向けにはブラウザで操作するWeb画面を提供する方法があります。画面は必要に応じてHTTPでJavaのAPIを呼び出し、Java側が商品情報を検索して結果を返します。APIそのものは画面ではなく、データを受け渡すための入口です。

部分点の判定: 部分正答例:「利用者向けにはブラウザで操作するWeb画面を提供する方法があります」。この記述だけなら1点で、残る正答要素は未達です。

誤答・採点ミスの例: 不十分な解答例:「利用者向けにはブラウザで操作するWeb画面を提供する方法があります」。他の必須要素を欠いたまま満点と判定するのは誤りです。

合格条件:3/3点。 正答の言い換えは認めます。

復習先: この節「01. 前章とのつながり:なぜWebが必要なのか」の本文および直前の例題。誤った採点要素を説明できるまで確認してから再回答します。

02. Web通信の登場人物

ブラウザは利用者の代わりに要求を送るクライアントです。Spring Bootで起動したJavaアプリケーションは、組み込みのWebサーバー(教材の構成ではTomcat)を使って要求を受け付けます。

厳密にはJavaアプリケーションとWebサーバーは同じ概念ではありませんが、この実習では同じプロセスで動作します。

localhost は自分が操作しているコンピューターを意味し、8080 は接続先を区別するポート番号です。

http://localhost:8080/api/products の /api/products は、サーバーのどの機能を利用するのかを指定するパスです。

【ブラウザ】 -- HTTPリクエスト --> 【Spring Boot】 -- SQL --> 【MySQL】
【ブラウザ】 <-- HTTPレスポンス -- 【Spring Boot】 <-- 結果 -- 【MySQL】

最初の実習では右端のMySQLを使いません。Spring Bootの内部に保存したデータだけを利用します。これは「通信」と「データ保存」を同時に学んで混乱しないためです。

この節の独学チェック:02. Web通信の登場人物

確認問題: ブラウザと組み込みWebサーバーの役割はどう違いますか。

取り組み方: 解答を見る前に自分の答えを記録してください。

ヒント1

HTTPを送る側と受ける側に分けましょう。

ヒント2

ブラウザでURLを入力してからの通信を考えます。

ヒント3

要求の送信者と、要求を受け付ける入口を明確にしてください。

模範解答と理由

ブラウザはHTTPリクエストを送信し、組み込みWebサーバーはアプリの入口としてHTTPを受け付けます。

この節の自己採点基準(2点満点)

独立して判定する正答要素

  1. 1点: ブラウザはHTTP要求を送るクライアントである。
  2. 1点: 組み込みWebサーバーはHTTP要求を受ける。

満点の正答例: ブラウザはHTTPリクエストを送信し、組み込みWebサーバーはアプリの入口としてHTTPを受け付けます。

部分点の判定: 部分正答例:「ブラウザはHTTP要求を送るクライアントである」。この記述だけなら1点で、残る正答要素は未達です。

誤答・採点ミスの例: 不十分な解答例:「ブラウザはHTTP要求を送るクライアントである」。他の必須要素を欠いたまま満点と判定するのは誤りです。

合格条件:2/2点。 正答の言い換えは認めます。

復習先: この節「02. Web通信の登場人物」の本文および直前の例題。誤った採点要素を説明できるまで確認してから再回答します。

図解:クライアント・サーバー

クライアント・サーバー

図の読み方:ブラウザが要求を送り、サーバーが応答を返します。

03. HTTPリクエストとレスポンスを読む

HTTPはクライアントとサーバーの通信手順です。リクエストにはメソッド(どの操作をしたいか)、URL(どこを使うか)、ヘッダー(データの形式など)、必要に応じて本文(送りたいデータ)が含まれます。

サーバーからのレスポンスにはステータスコード(結果の種類)、ヘッダー、本文が含まれます。

商品一覧では GET /api/products、商品登録では POST /api/products を使います。GETはデータの取得、POSTは新しいデータの作成によく利用されます。

成功時の200は取得成功、201は登録成功を表し、400は利用者が送ったデータに問題があること、404は指定したパスが見つからないこと、500はサーバー内部の処理でエラーが起きたことを表します。

ここで示した200・201・400・404・500は代表例であり、同じ操作でもAPI仕様によって別の成功ステータスやエラーステータスを使う場合があります。

POST /api/products HTTP/1.1
Content-Type: application/json

{"name":"消しゴム","price":90}
HTTP/1.1 201 Created
Content-Type: application/json

{"id":3,"name":"消しゴム","price":90}

上記は読み方を説明するための通信例です。IDは登録件数によって変わります。実際の通信では他にもヘッダーが付きます。

この節の独学チェック:03. HTTPリクエストとレスポンスを読む

確認問題: GET /productsに対するHTTP 200と404はどう違いますか。

取り組み方: 解答を見る前に自分の答えを記録してください。

ヒント1

200と404の先頭数字だけでなく意味を考えましょう。

ヒント2

URLパスが存在しない場合に何が返るか想像します。

ヒント3

リクエスト成功と対象リソースの不存在を区別します。

模範解答と理由

200はHTTPリクエストの成功を示し、404は指定したURLに対応するリソースが見つからないことを示します。404は商品データの不存在だけでなく、パスやマッピングの誤りでも起こり得ます。

この節の自己採点基準(2点満点)

独立して判定する正答要素

  1. 1点: HTTP 200は要求成功を示す。
  2. 1点: HTTP 404は指定URLのリソースが見つからないことを示す。

満点の正答例: 200はHTTPリクエストの成功を示し、404は指定したURLに対応するリソースが見つからないことを示します。404は商品データの不存在だけでなく、パスやマッピングの誤りでも起こり得ます。

部分点の判定: 部分正答例:「HTTP 200は要求成功を示す」。この記述だけなら1点で、残る正答要素は未達です。

誤答・採点ミスの例: 不十分な解答例:「HTTP 200は要求成功を示す」。他の必須要素を欠いたまま満点と判定するのは誤りです。

合格条件:2/2点。 正答の言い換えは認めます。

復習先: この節「03. HTTPリクエストとレスポンスを読む」の本文および直前の例題。誤った採点要素を説明できるまで確認してから再回答します。

図解:HTTPの往復

HTTPの往復

図の読み方:HTTPはメソッド・URL・ステータス・本文などで通信を表します。

04. HTMLとJSONを区別する

HTMLは画面の構造を記述するための言語です。見出しに<h1>、入力欄に<input>などを使います。JSONはデータを表すための形式です。{"name":"ノート","price":180}はJSONの例です。

キーに対して値が関連付けられています。複数の商品を並べる場合は角括弧[]を使います。JavaのProductをJSONとして返すための変換はSpring Bootのライブラリが担当します。

この章では、/ がHTMLの画面を返し、/api/products がJSONを返します。URLごとに結果が違うのは不具合ではありません。

この節の独学チェック:04. HTMLとJSONを区別する

確認問題: HTMLとJSONのどちらが画面の構造を表しますか。

取り組み方: 解答を見る前に自分の答えを記録してください。

ヒント1

ブラウザがタグを画面に配置する働きを考えます。

ヒント2

商品データをキーと値で表す形式も思い出しましょう。

ヒント3

画面の構造そのものを記述する形式を選んでください。

模範解答と理由

HTMLは画面の要素や構造を記述します。JSONは主にデータを表現します。

この節の自己採点基準(2点満点)

独立して判定する正答要素

  1. 1点: HTMLは画面の要素や構造を記述します。
  2. 1点: JSONは主にデータを表現します。

満点の正答例: HTMLは画面の要素や構造を記述します。JSONは主にデータを表現します。

部分点の判定: 部分正答例:「HTMLは画面の要素や構造を記述します」。この記述だけなら1点で、残る正答要素は未達です。

誤答・採点ミスの例: 不十分な解答例:「HTMLは画面の要素や構造を記述します」。他の必須要素を欠いたまま満点と判定するのは誤りです。

合格条件:2/2点。 正答の言い換えは認めます。

復習先: この節「04. HTMLとJSONを区別する」の本文および直前の例題。誤った採点要素を説明できるまで確認してから再回答します。

05. MavenプロジェクトをEclipseに取り込む

  1. 配布物の examples/06_web/product-web フォルダーを C:\java-training\product-web など自分の作業用フォルダーへコピーします。pom.xml がコピー先直下にあることを確認してください。
  2. Eclipseを起動してワークスペースを開き、メニューの File → Import... をクリックします。
  3. Maven → Existing Maven Projects を選び Next を押します。
  4. Root Directory でコピーした product-web を選択します。プロジェクト一覧にpom.xmlが検出されたことを確認し Finish を押します。
  5. EclipseのProject Explorerに src/main/java、src/main/resources、pom.xml が見えたら読み込み成功です。依存ライブラリのダウンロードが終わるまで赤いエラーが消えないことがあります。
  6. pom.xml を開き、Javaバージョンが21、Spring Bootが4.1.1になっていることを確認してください。

失敗した場合:pom.xmlが見つからなければ選択した階層が違います。Maven → Update Project... を実行しても失敗する場合、Eclipseからネット接続できるかを確認します。

java -versionとEclipseのInstalled JREsも確認してください。

この節の独学チェック:05. MavenプロジェクトをEclipseに取り込む

確認問題: EclipseでMavenプロジェクトを取り込むとき、何を選びますか。

取り組み方: 解答を見る前に自分の答えを記録してください。

ヒント1

プロジェクトのルートにあるファイルを確認します。

ヒント2

外部依存関係をどのファイルで管理しているでしょうか。

ヒント3

Eclipseの取り込み機能で既存Mavenプロジェクトを探します。

模範解答と理由

pom.xmlを含む既存Mavenプロジェクトを選びます。通常の単一Javaファイルとして扱いません。

この節の自己採点基準(1点満点)

独立して判定する正答要素

  1. 1点: pom.xmlを含む既存Mavenプロジェクトを選択すると答える。

満点の正答例: pom.xmlを含む既存Mavenプロジェクトを選びます。通常の単一Javaファイルとして扱いません。

部分点の判定: 正答要素は1つなので部分点はありません。意味が一致すれば1点、異なれば0点です。

誤答・採点ミスの例: 不十分な解答例:「よく分からないが、そのまま進めればよい」。正答条件「pom.xmlを含む既存Mavenプロジェクトを選択すると答える」を示していないので0点です。

合格条件:1/1点。 正答の言い換えは認めます。

復習先: この節「05. MavenプロジェクトをEclipseに取り込む」の本文および直前の例題。誤った採点要素を説明できるまで確認してから再回答します。

06. 起動し、最初のAPIを呼ぶ

  1. src/main/java/training/web/ProductWebApplication.javaを開きます。
  2. ファイルを右クリックして Run As → Java Application を選びます。
  3. EclipseのConsoleにStarted ProductWebApplicationのような表示が出たら、起動に成功しています。
  4. ブラウザのアドレス欄へhttp://localhost:8080/api/helloを入力します。{"message":"JavaのWeb開発へようこそ"}というJSONが表示されます。
  5. 次にhttp://localhost:8080/api/productsへアクセスすると、初期データのノートとペンがJSONで返ります。
  6. http://localhost:8080/では、HTMLの一覧と商品登録フォームが表示されます。

理由:main()からSpringApplication.run()を呼ぶことで、SpringがJavaのクラスを調べてWebサーバーを起動します。ブラウザは同じPCの8080番ポートに接続します。

アプリを停止すると接続できなくなります。

この節の独学チェック:06. 起動し、最初のAPIを呼ぶ

確認問題: localhostと8080と/productsは、それぞれ何を指しますか。

取り組み方: 解答を見る前に自分の答えを記録してください。

ヒント1

URLを3つの部分に区切ってください。

ヒント2

ネットワークの宛先・ポート・要求対象の順です。

ヒント3

localhost:8080/products をそれぞれの役割に対応付けます。

模範解答と理由

localhostは同じPC、8080は接続先ポート、/productsは要求するパスです。

この節の自己採点基準(3点満点)

独立して判定する正答要素

  1. 1点: localhostは同じPCを指すホスト名である。
  2. 1点: 8080は通信先のポート番号である。
  3. 1点: /productsはHTTPリクエストのパスである。

満点の正答例: localhostは同じPC、8080は接続先ポート、/productsは要求するパスです。

部分点の判定: 部分正答例:「localhostは同じPCを指すホスト名である」。この記述だけなら1点で、残る正答要素は未達です。

誤答・採点ミスの例: 不十分な解答例:「localhostは同じPCを指すホスト名である」。他の必須要素を欠いたまま満点と判定するのは誤りです。

合格条件:3/3点。 正答の言い換えは認めます。

復習先: この節「06. 起動し、最初のAPIを呼ぶ」の本文および直前の例題。誤った採点要素を説明できるまで確認してから再回答します。

07. Javaコードを行ごとに読む:起動クラス

@SpringBootApplication
public class ProductWebApplication {
    public static void main(String[] args) {
        SpringApplication.run(ProductWebApplication.class, args);
    }
}

@SpringBootApplicationはSpring Bootアプリの入口であり、設定の自動構成やコンポーネントの検出を有効にします。

classはクラスの宣言、mainはJavaプログラムの入口、String[] argsは起動時の引数を受け取る配列です。

SpringApplication.runはSpringの管理機構を開始し、組み込みWebサーバーを動かします。ProductWebApplication.classは開始地点のクラス情報を渡す指定です。

クラスファイルの実際のpackage文とimport文も必ず確認してください。

理解を深める:アノテーションはフレームワークへ設定を伝える手掛かりになる

@RestController はHTTPリクエストを扱うクラスとしてSpringに認識させ、戻り値をHTTPレスポンスに利用する役割を持ちます。@GetMapping はGETとURLパスの対応付けです。

クラスを置けばどこでも自動検出されるわけではなく、起動クラスのパッケージ位置とコンポーネントスキャンの範囲も関係します。疑問があれば「Springが何を見つけ、いつ呼び出すのか」を分けて考えます。

この節の独学チェック:07. Javaコードを行ごとに読む:起動クラス

確認問題: @SpringBootApplicationを持つ起動クラスは何をしますか。

取り組み方: 解答を見る前に自分の答えを記録してください。

ヒント1

Spring Boot起動クラスの注釈に注目します。

ヒント2

mainメソッドとSpringApplication.runの流れを追います。

ヒント3

アプリ起動とコンポーネント設定の開始点を考えます。

模範解答と理由

Spring Bootアプリケーションを起動し、設定や対象コンポーネントの検出を開始します。

この節の自己採点基準(1点満点)

独立して判定する正答要素

  1. 1点: Spring Bootアプリケーションを起動し、設定や対象コンポーネントの検出を開始します。

満点の正答例: Spring Bootアプリケーションを起動し、設定や対象コンポーネントの検出を開始します。

部分点の判定: 正答要素は1つなので部分点はありません。意味が一致すれば1点、異なれば0点です。

誤答・採点ミスの例: 不十分な解答例:「よく分からないが、そのまま進めればよい」。正答条件「Spring Bootアプリケーションを起動し、設定や対象コンポーネントの検出を開始します」を示していないので0点です。

合格条件:1/1点。 正答の言い換えは認めます。

復習先: この節「07. Javaコードを行ごとに読む:起動クラス」の本文および直前の例題。誤った採点要素を説明できるまで確認してから再回答します。

08. Controllerを行ごとに追跡する

HelloController.javaを開いて、次の要点とファイルを見比べます。

@RestController
public class HelloController {
    @GetMapping("/api/hello")
    public Map<String, String> hello() {
        return Map.of("message", "JavaのWeb開発へようこそ");
    }
}

@RestControllerはHTTP要求を受けて結果を返すクラスであることをSpringに知らせます。@GetMappingは、GETで指定したパスにアクセスされた際に下のメソッドを実行する対応付けです。

publicは外部から使えること、Map<String,String>は文字列のキーと文字列の値の組を表します。Map.ofはそのデータを作る命令です。SpringがこのMapをJSONに変換して返します。

確認実習:文字列の「ようこそ」を「学習中です」に変更して一度アプリを停止・再起動し、ブラウザを更新します。変更した文字列が表示されれば、編集→コンパイル→実行→HTTPという一連の流れを体験できました。

実習後は元の文に戻します。

この節の独学チェック:08. Controllerを行ごとに追跡する

確認問題: @GetMapping("/products")を持つメソッドはいつ呼び出されますか。

取り組み方: 解答を見る前に自分の答えを記録してください。

ヒント1

HTTPメソッドとURLの組み合わせを確認します。

ヒント2

GETとPOSTで同じパスでも処理が異なります。

ヒント3

指定された注釈に対応するリクエストを一つ示してください。

模範解答と理由

対応するGET /productsへのHTTPリクエストを受けたときです。

この節の自己採点基準(1点満点)

独立して判定する正答要素

  1. 1点: 対応するGET /productsへのHTTPリクエストを受けたときです。

満点の正答例: 対応するGET /productsへのHTTPリクエストを受けたときです。

部分点の判定: 正答要素は1つなので部分点はありません。意味が一致すれば1点、異なれば0点です。

誤答・採点ミスの例: 不十分な解答例:「よく分からないが、そのまま進めればよい」。正答条件「対応するGET /productsへのHTTPリクエストを受けたときです」を示していないので0点です。

合格条件:1/1点。 正答の言い換えは認めます。

復習先: この節「08. Controllerを行ごとに追跡する」の本文および直前の例題。誤った採点要素を説明できるまで確認してから再回答します。

09. Controller、Service、Repositoryの関係

長いプログラムを一つのクラスに書くと、通信方法の変更が商品計算に影響しやすくなります。そこで役割を分けます。

ControllerはURLと受信データを扱い、Serviceは商品に関する業務ルールを扱い、Repositoryはデータの読み書きを担当します。

HTTP GET /api/products
        |
        v
ProductController.list()
        |
        v
ProductService.list()
        |
        v
ProductRepository.findAll()
        |
        +--> MemoryProductRepository (最初はこちら)
        |
        +--> JdbcProductRepository   (MySQL学習時はこちら)

ProductRepositoryはインターフェースです。具体的に保存する方法はMemoryProductRepositoryとJdbcProductRepositoryの二つが持っています。

ControllerやServiceは保存先の種類を気にせず利用できます。

理解を深める:一つのクラスにすべての処理を書くと何が問題になるか

HTTPの受け付け、入力チェック、在庫計算、MySQLへの保存をControllerにすべて記述することも技術的には可能です。

しかし、Web画面を変更しただけで業務ロジックを触ったり、データベースなしでは計算のテストができなくなったりします。

そこで責務を分けます。ControllerはHTTPの受け口、Serviceは業務上の判断、Repositoryは保存先とのやり取りです。

この分離によって、例えばデータの保存先をメモリーからMySQLへ切り替える場合に、HTTPの入口や業務ルールへの影響を抑えやすくなります。ただし小さな教材で過剰にクラスを増やす必要はなく、変更理由を説明できる範囲に留めます。

POST /products  {"name":"ペン","price":120}
     ↓
Controller : JSONを受け取りHTTP応答へ変換する
     ↓
Service    : 名前・価格の業務ルールを検査する
     ↓
Repository : 商品データを保存する
     ↓
Controller : 201 Createdなどの応答を返す

理解を深める:なぜControllerに全部書かないのか

HTTPから受けた商品登録の入力検証、価格の判定、SQLの実行を一つのControllerに書くことも技術的には可能です。しかし画面からの登録に加えてバッチ処理からも商品を登録すると、同じ業務ルールが別の場所へ重複しがちです。

そこで Controllerは通信の入口、Serviceは業務ルール、Repositoryは保存・検索に分けます。単純なアプリではクラス数が増えますが、変更の影響範囲を把握しやすい利点があります。

POST /api/products
   ↓ HTTP入力を受け付ける
ProductController
   ↓ 商品を登録してほしいと依頼する
ProductService
   ↓ 保存を依頼する
ProductRepository
   ↓
メモリー/MySQL

この線を逆にしないことが重要です。RepositoryがControllerの画面表示方式を知っていると、保存方法を変えるだけで通信処理まで影響を受けます。

この節の独学チェック:09. Controller、Service、Repositoryの関係

確認問題: Controllerに商品価格の計算やDB操作を全て書くと何が困りますか。

取り組み方: 解答を見る前に自分の答えを記録してください。

ヒント1

ControllerへSQLまで書いた状態を想像します。

ヒント2

表示方法が変わったときの影響箇所を考えましょう。

ヒント3

通信・業務判断・永続化の責務を分離するメリットを説明します。

模範解答と理由

HTTP処理と業務処理・保存処理が密結合になり、変更やテストが難しくなります。

この節の自己採点基準(1点満点)

独立して判定する正答要素

  1. 1点: HTTP処理と業務処理・保存処理が密結合になり、変更やテストが難しくなります。

満点の正答例: HTTP処理と業務処理・保存処理が密結合になり、変更やテストが難しくなります。

部分点の判定: 正答要素は1つなので部分点はありません。意味が一致すれば1点、異なれば0点です。

誤答・採点ミスの例: 不十分な解答例:「よく分からないが、そのまま進めればよい」。正答条件「HTTP処理と業務処理・保存処理が密結合になり、変更やテストが難しくなります」を示していないので0点です。

合格条件:1/1点。 正答の言い換えは認めます。

復習先: この節「09. Controller、Service、Repositoryの関係」の本文および直前の例題。誤った採点要素を説明できるまで確認してから再回答します。

図解:Spring Bootのレイヤー

Spring Bootのレイヤー

図の読み方:Controllerは受付、Serviceは業務処理、Repositoryは永続化を担当します。

10. BeanとDI(依存性注入)を理解する

BeanはSpringが生成し、管理するオブジェクトのことです。

@Serviceが付いたProductService、@Repositoryが付いたRepository、@RestControllerが付いたControllerなどをSpringが検出します。

**DI(Dependency Injection、依存性注入)**は、クラスが必要とする相手のオブジェクトをSpring側で渡す仕組みです。

private final ProductService service;
public ProductController(ProductService service) {
    this.service = service;
}

最初の行はServiceを保持するためのフィールドです。finalはこのフィールドを後から別のServiceに代入し直せないことを表します。

コンストラクタの引数を通じてSpringがServiceを渡すため、Controllerの中でnew ProductService(...)を記述する必要はありません。この形式をコンストラクタ注入と呼びます。

Repositoryの選択には@ConditionalOnPropertyを利用しています。

training.storage=memoryならメモリー版、training.storage=mysqlならMySQL版だけをBeanにします。

2種類のRepositoryが同時にBeanになると候補が重複する可能性があるため、この設定を使っています。

理解を深める:DIが必要になる前の困りごと

Serviceが new MySQLProductRepository() を直接実行すると、ServiceはMySQLという保存方式に強く結び付きます。テスト時だけメモリー版に差し替える作業が難しくなります。

**依存性注入(DI)**は、必要なRepositoryをServiceの外側から渡す考え方です。SpringではBeanという管理対象のオブジェクトを用意し、コンストラクタを通じて依存先を渡せます。

class ProductService {
    private final ProductRepository repository;
    ProductService(ProductRepository repository) {
        this.repository = repository;
    }
}

この例はDIの考え方を示す短い断片です。ProductRepository は教材中で定義したインターフェースなどを想定しています。実際にSpringへ登録するには @Service などの適切な設定が必要です。

アノテーションを書くだけで何でも自動登録されるわけではありません。 パッケージ走査やBean定義の対象になっていることが条件です。

理解を深める:DIはなぜ必要なのか

Serviceがコンストラクタ内で new MysqlProductRepository() を直接作ると、保存先をメモリー版へ切り替えたいときにServiceを修正しなければなりません。

代わりに「商品を保存できるもの」を外から渡せば、Serviceはどの具体的な保存方式かを意識せずに済みます。これが依存性注入(DI)の基本です。

Springでは管理対象のオブジェクトをBeanと呼び、@Service 等を付けたクラスを読み取って生成し、コンストラクタ引数に必要なBeanを渡す仕組みがあります。

ただし、候補が複数あるとどれを使うか決める設定が必要です。

この節の独学チェック:10. BeanとDI(依存性注入)を理解する

確認問題: コンストラクタ注入でServiceを受け取る利点は何ですか。

取り組み方: 解答を見る前に自分の答えを記録してください。

ヒント1

newでServiceを直接作る場合と比較します。

ヒント2

Serviceを外からコンストラクタに渡す形を確認します。

ヒント3

テスト時に別の実装を差し込む場面を想像してください。

模範解答と理由

Springが管理する依存オブジェクトを外部から渡せるため、生成責務を分離して差し替え・テストしやすくなります。

この節の自己採点基準(1点満点)

独立して判定する正答要素

  1. 1点: Springが管理する依存オブジェクトを外部から渡せるため、生成責務を分離して差し替え・テストしやすくなります。

満点の正答例: Springが管理する依存オブジェクトを外部から渡せるため、生成責務を分離して差し替え・テストしやすくなります。

部分点の判定: 正答要素は1つなので部分点はありません。意味が一致すれば1点、異なれば0点です。

誤答・採点ミスの例: 不十分な解答例:「よく分からないが、そのまま進めればよい」。正答条件「Springが管理する依存オブジェクトを外部から渡せるため、生成責務を分離して差し替え・テストしやすくなります」を示していないので0点です。

合格条件:1/1点。 正答の言い換えは認めます。

復習先: この節「10. BeanとDI(依存性注入)を理解する」の本文および直前の例題。誤った採点要素を説明できるまで確認してから再回答します。

図解:依存性注入(DI)

依存性注入(DI)

図の読み方:DIでは必要なオブジェクトを外部から受け取り、依存関係を組み替えやすくします。

11. GETとPOSTで実際に通信する

PowerShellを開き、アプリを起動したまま次を一行ずつ実行してください。

Invoke-RestMethod -Method Get -Uri 'http://localhost:8080/api/products'
$body = @{ name = '消しゴム'; price = 90 } | ConvertTo-Json
Invoke-RestMethod -Method Post -Uri 'http://localhost:8080/api/products' -ContentType 'application/json; charset=utf-8' -Body ([System.Text.Encoding]::UTF8.GetBytes($body))
Invoke-RestMethod -Method Get -Uri 'http://localhost:8080/api/products'

1行目は一覧取得です。2行目は送信する商品情報をJSONに変換して変数へ入れます。3行目は商品をPOSTで登録します。

Windows PowerShellの文字コード差による文字化けを避けるため、JSONをUTF-8のバイト列へ変換しています。4行目で商品が増えたことを確認します。

POST成功時は201が返り、商品IDは現在の登録状況で変化します。

正常系と異常系:price=0は成功、price=-1は400、商品名が空なら400になるはずです。4xx応答はPowerShellではエラー表示されることがありますが、サーバーが不正入力を拒否した証拠です。

再起動するとメモリー版の登録内容は初期状態へ戻ります。

理解を深める:HTTPの責任と業務の責任を分ける

価格が負のとき「無効な商品」とする判断は業務ルールです。それを利用者に 400 Bad Request として伝える形式はWebの責任です。

ServiceがHTTPレスポンスを直接組み立てると、別の用途(たとえばバッチ処理)でServiceを再利用しにくくなります。全例外を一律500にするのではなく、入力不備と予期しないサーバー障害を区別します。

この節の独学チェック:11. GETとPOSTで実際に通信する

確認問題: GETとPOSTは商品一覧と商品登録のどちらに使いますか。

取り組み方: 解答を見る前に自分の答えを記録してください。

ヒント1

情報の取得と新規作成の違いを考えます。

ヒント2

一覧表示と商品登録に同じHTTPメソッドが適切でしょうか。

ヒント3

登録データをリクエストのどこへ入れるかも確認します。

模範解答と理由

通常、取得はGET、登録はPOSTです。POSTではリクエスト本文を使うことがあります。

この節の自己採点基準(2点満点)

独立して判定する正答要素

  1. 1点: 商品一覧の取得にはGETを使用する。
  2. 1点: 商品の登録にはPOSTを使用する。

満点の正答例: 通常、取得はGET、登録はPOSTです。POSTではリクエスト本文を使うことがあります。

部分点の判定: 部分正答例:「商品一覧の取得にはGETを使用する」。この記述だけなら1点で、残る正答要素は未達です。

誤答・採点ミスの例: 不十分な解答例:「商品一覧の取得にはGETを使用する」。他の必須要素を欠いたまま満点と判定するのは誤りです。

合格条件:2/2点。 正答の言い換えは認めます。

復習先: この節「11. GETとPOSTで実際に通信する」の本文および直前の例題。誤った採点要素を説明できるまで確認してから再回答します。

12. 入力値を検証する理由

ブラウザの入力欄に最小値を設定しても、PowerShellなど別の通信手段から負の値を送れます。そのため、必ずJava側で入力を確認します。

ProductController.createがJSONをProductRequestとして受け取り、必要な項目があるかを確認します。

ProductService.registerが商品名の空文字・100文字超過・負の金額を検査し、不正ならIllegalArgumentExceptionを投げます。

Controllerでその例外をHTTP 400へ変換します。

演習:nameを空文字、priceを負の数、priceを文字列へ変え、それぞれのHTTP結果を確認してください。予期しない500が返った場合は、入力エラーを適切に400へ変換できていない可能性があります。

理解を深める:HTTPステータスはなぜ使い分けるか

要求が成功したのか、入力値が間違っていたのか、対象が見つからないのかを、受け手が機械的に判断できるようにするためです。典型例として検索成功は200、作成成功は201、入力不備は400、見つからない場合は404を使います。

ただし、API仕様に応じて選ぶ必要があります。例外が出たからといって必ず500を返す設計は、利用者の入力ミスとサーバー障害を混同させます。

この節の独学チェック:12. 入力値を検証する理由

確認問題: 商品価格が負数なら入力時にどうするべきですか。

取り組み方: 解答を見る前に自分の答えを記録してください。

ヒント1

価格-1の商品が保存されると何が困るでしょうか。

ヒント2

入力の妥当性を業務処理の前に判断します。

ヒント3

HTTP応答で利用者に不正入力を知らせる方法を考えます。

模範解答と理由

仕様に従い不正な値として拒否し、理由がわかる4xx系の応答を返します。

この節の自己採点基準(1点満点)

独立して判定する正答要素

  1. 1点: 仕様に従い不正な値として拒否し、理由がわかる4xx系の応答を返します。

満点の正答例: 仕様に従い不正な値として拒否し、理由がわかる4xx系の応答を返します。

部分点の判定: 正答要素は1つなので部分点はありません。意味が一致すれば1点、異なれば0点です。

誤答・採点ミスの例: 不十分な解答例:「よく分からないが、そのまま進めればよい」。正答条件「仕様に従い不正な値として拒否し、理由がわかる4xx系の応答を返します」を示していないので0点です。

合格条件:1/1点。 正答の言い換えは認めます。

復習先: この節「12. 入力値を検証する理由」の本文および直前の例題。誤った採点要素を説明できるまで確認してから再回答します。

13. 画面HTMLとJavaScriptの接続

src/main/resources/static/index.htmlをブラウザから開くと、商品一覧と登録フォームが表示されます。

JavaScriptのfetch('/api/products')がGET通信を送り、取得したJSONから一覧を生成しています。登録ボタンを押すとJavaScriptがPOST /api/productsを呼び出します。

Chrome、Edge、FirefoxのいずれかでF12を押し、**Network(ネットワーク)**を開きます。次に画面を再読み込みするとGETが見えます。商品を登録するとPOSTが見えます。

クリックした要求のURL・Method・Status・Responseを確認してください。画面の表示が変わる理由と、通信結果が対応していることが分かります。

この節の独学チェック:13. 画面HTMLとJavaScriptの接続

確認問題: HTML上のボタン操作から商品APIを呼ぶとき何が必要ですか。

取り組み方: 解答を見る前に自分の答えを記録してください。

ヒント1

HTMLだけでは外部APIの応答は画面へ反映されません。

ヒント2

ボタンを押してからHTTP通信が起きる手順を追いましょう。

ヒント3

応答データを受けた後、画面のどこを更新するか考えます。

模範解答と理由

JavaScript等でHTTPリクエストを送り、レスポンスを受けて画面に反映します。

この節の自己採点基準(1点満点)

独立して判定する正答要素

  1. 1点: JavaScript等でHTTPリクエストを送り、レスポンスを受けて画面に反映します。

満点の正答例: JavaScript等でHTTPリクエストを送り、レスポンスを受けて画面に反映します。

部分点の判定: 正答要素は1つなので部分点はありません。意味が一致すれば1点、異なれば0点です。

誤答・採点ミスの例: 不十分な解答例:「よく分からないが、そのまま進めればよい」。正答条件「JavaScript等でHTTPリクエストを送り、レスポンスを受けて画面に反映します」を示していないので0点です。

合格条件:1/1点。 正答の言い換えは認めます。

復習先: この節「13. 画面HTMLとJavaScriptの接続」の本文および直前の例題。誤った採点要素を説明できるまで確認してから再回答します。

図解:画面からAPIを利用

画面からAPIを利用

図の読み方:fetchで非同期にAPIを呼び出し、応答を使って画面を更新します。

14. MySQLへ保存する準備

ここからは第05章で導入したMySQLを使います。最初にSQLファイルを実行するのは一度だけです。 二度実行すると初期商品のノートとペンが重複するため、再実行前にテーブルの状態を確認してください。

第05章のtraining_dbを壊さないよう、第06章専用のtraining_web_dbを使用します。 価格は整数円(INT)、商品IDはBIGINTです。

第05章のproductsと型が異なるため、同じDBをそのまま使わないでください。

  1. MySQLのコマンドラインクライアントを開き、管理用アカウントでログインします。
  2. product-web/sql/01_schema.sqlをSQLとして実行します。MySQLクライアントなら SOURCE C:/java-training/product-web/sql/01_schema.sql; と入力できます。パスは実際のコピー先へ変えてください。Windowsではパス区切りに / を使えます。
  3. USE training_web_db; SELECT * FROM products;を実行し、初期商品2件が表示されることを確認します。
  4. 以下のSQLで学習用ユーザーを作ります。例にあるパスワード文字列をそのまま使わず、自分で長い値に置き換えてください。
CREATE USER IF NOT EXISTS 'training_web_user'@'localhost' IDENTIFIED BY 'ここを独自の強いパスワードに変更';
GRANT SELECT, INSERT ON training_web_db.* TO 'training_web_user'@'localhost';

すでに同名ユーザーがある場合、CREATE USER IF NOT EXISTSは既存パスワードを変えません。ユーザーの状態が分からない場合、むやみに設定を変更する前に指導者へ確認してください。

実習ではDELETEやUPDATE権限を与えていません。

理解を深める:なぜ最初にメモリー版を作るのか

HTTP通信とDB保存を同時に学ぶと、失敗時に通信の問題かSQLの問題かを切り分けづらくなります。最初はDBなしでGET・POSTとHTTPステータスを理解し、その後RepositoryをMySQL版に切り替えます。

分かっている部分を増やしてから新しい要素を加えるのが学習設計上の理由です。

この節の独学チェック:14. MySQLへ保存する準備

確認問題: メモリー保存とMySQL保存の大きな違いは何ですか。

取り組み方: 解答を見る前に自分の答えを記録してください。

ヒント1

アプリを停止してから起動し直す場面を想像します。

ヒント2

プロセス内のコレクションとDBの保存領域を比べます。

ヒント3

登録した値が再起動後も見えるかを判定材料にします。

模範解答と理由

メモリー上のデータはアプリ終了で通常消えますが、DBへコミットしたデータは再起動後も保持されます。

この節の自己採点基準(2点満点)

独立して判定する正答要素

  1. 1点: メモリー上のデータはプロセス終了時に通常失われる。
  2. 1点: DBに確定したデータは再起動後も保持される。

満点の正答例: メモリー上のデータはアプリ終了で通常消えますが、DBへコミットしたデータは再起動後も保持されます。

部分点の判定: 部分正答例:「メモリー上のデータはプロセス終了時に通常失われる」。この記述だけなら1点で、残る正答要素は未達です。

誤答・採点ミスの例: 不十分な解答例:「メモリー上のデータはプロセス終了時に通常失われる」。他の必須要素を欠いたまま満点と判定するのは誤りです。

合格条件:2/2点。 正答の言い換えは認めます。

復習先: この節「14. MySQLへ保存する準備」の本文および直前の例題。誤った採点要素を説明できるまで確認してから再回答します。

15. MySQLモードの起動と接続確認

Windows PowerShellで次を実行します。YOUR_PASSWORDを先ほど決めたパスワードに置き換えてください。環境変数の設定はこのPowerShellのプロセスだけに反映されます。

パスワードを共有したり、コマンド履歴を提出したりしないでください。

$env:DB_USERNAME = 'training_web_user'
$env:DB_PASSWORD = 'YOUR_PASSWORD'
cd C:\java-training\product-web
mvn spring-boot:run '-Dspring-boot.run.profiles=mysql'

Mavenが見つからない場合は、第01章のMaven設定を確認してください。同時にEclipseから起動しているアプリは停止してください。8080番ポートが重複すると起動できません。

DB接続に成功したらhttp://localhost:8080/api/productsにアクセスし、初期商品2件が表示されます。

次に前節のPowerShellのPOSTを実行し、商品を登録してください。アプリをCtrl+Cで止めて再度起動しても商品が残っていればDBへの永続化に成功です。

MySQL側でSELECT * FROM training_web_db.products;も確認してください。

EclipseからMySQLモードで起動する場合は、Run ConfigurationsのEnvironmentにDB_USERNAMEとDB_PASSWORDを指定し、Program argumentsに--spring.profiles.active=mysqlを入力します。

通常の起動設定へ秘密情報を埋め込んで共有しないでください。

この節の独学チェック:15. MySQLモードの起動と接続確認

確認問題: MySQL版で接続できないとき、HTTPを疑う前に何を確認しますか。

取り組み方: 解答を見る前に自分の答えを記録してください。

ヒント1

画面以前に、アプリからDBへの通信を確かめます。

ヒント2

MySQLサービスと接続URL・資格情報を分けて調べます。

ヒント3

接続先のDB名が存在するかも忘れず確認します。

模範解答と理由

DBサービス、接続先、ポート、ユーザー、パスワードと対象DBの存在を確認します。

この節の自己採点基準(3点満点)

独立して判定する正答要素

  1. 1点: MySQLサーバーが起動しているか確認する。
  2. 1点: 接続先・ポート・DB名が正しいか確認する。
  3. 1点: ユーザー名・パスワードを確認する。

満点の正答例: DBサービス、接続先、ポート、ユーザー、パスワードと対象DBの存在を確認します。

部分点の判定: 部分正答例:「MySQLサーバーが起動しているか確認する」。この記述だけなら1点で、残る正答要素は未達です。

誤答・採点ミスの例: 不十分な解答例:「MySQLサーバーが起動しているか確認する」。他の必須要素を欠いたまま満点と判定するのは誤りです。

合格条件:3/3点。 正答の言い換えは認めます。

復習先: この節「15. MySQLモードの起動と接続確認」の本文および直前の例題。誤った採点要素を説明できるまで確認してから再回答します。

16. RepositoryのJDBCコードを読む

JdbcProductRepository.javaを開きます。JdbcTemplateはSpring JDBCが提供する、SQLを実行して結果をJavaへ変換する処理を助けるクラスです。

findAll()はSELECTを実行し、結果の1行をProductへ変換します。insert()はINSERTを実行し、新しく発行されたAUTO_INCREMENTのIDを取得します。

SQL文の?はプレースホルダーであり、setStringとsetIntで値を渡します。文字列をそのままSQL文へ結合しないため、SQLインジェクションの防止にも役立ちます。

PreparedStatementは第05章で学習した仕組みを引き継いでいます。

PowerShell POST → ProductController.create
→ ProductService.register(入力を確認)
→ JdbcProductRepository.insert(SQLを実行)
→ MySQL productsテーブル
→ 発行された商品IDと商品情報をJSONで返す

注意:MySQL接続エラーは通常、アプリ側の500系エラーやコンソール上の例外として見えます。接続URL、MySQL稼働状況、ユーザー権限、パスワード、テーブル作成状況を順番に調べます。

この節の独学チェック:16. RepositoryのJDBCコードを読む

確認問題: RepositoryのJDBCコードでSQLの値を文字列連結しない理由は何ですか。

取り組み方: 解答を見る前に自分の答えを記録してください。

ヒント1

SQL文字列と入力値を別にするAPIを探してください。

ヒント2

SQL文の構造へ外部入力が混入した場合を考えます。

ヒント3

JDBCのパラメータ設定が防ぐ問題を説明してください。

模範解答と理由

PreparedStatementで値を安全に設定し、SQLインジェクションを避けるためです。

この節の自己採点基準(1点満点)

独立して判定する正答要素

  1. 1点: PreparedStatementで値を安全に設定し、SQLインジェクションを避けるためです。

満点の正答例: PreparedStatementで値を安全に設定し、SQLインジェクションを避けるためです。

部分点の判定: 正答要素は1つなので部分点はありません。意味が一致すれば1点、異なれば0点です。

誤答・採点ミスの例: 不十分な解答例:「よく分からないが、そのまま進めればよい」。正答条件「PreparedStatementで値を安全に設定し、SQLインジェクションを避けるためです」を示していないので0点です。

合格条件:1/1点。 正答の言い換えは認めます。

復習先: この節「16. RepositoryのJDBCコードを読む」の本文および直前の例題。誤った採点要素を説明できるまで確認してから再回答します。

17. Mavenのテストを実行する

プロジェクトのフォルダーでPowerShellを開き、以下を実行します。

mvn clean test

このテストはProductServiceTestを実行します。商品を正常に登録できること、負の価格と空欄の商品名を拒否できることを確認します。BUILD SUCCESSが表示されれば成功です。

MySQLなしでも実行できるよう、メモリー版のRepositoryを直接使うテストになっています。

テスト失敗時は、最初のFAILURE・ERRORを確認して入力値と期待結果を照合します。Could not resolve dependenciesはテストの失敗ではなくMavenライブラリ取得の失敗です。

java -version、mvn -versionの出力とネットワーク接続を確認します。

この節の独学チェック:17. Mavenのテストを実行する

確認問題: mvn testとmvn packageは何が違いますか。

取り組み方: 解答を見る前に自分の答えを記録してください。

ヒント1

Mavenのライフサイクル順序を見ましょう。

ヒント2

testより後にpackageがあることに注目します。

ヒント3

生成される成果物の有無と、テストの実行範囲を比べます。

模範解答と理由

mvn testはテストまでを実行し、mvn packageはパッケージ生成まで実行します。標準ライフサイクルではテストも含まれます。

この節の自己採点基準(2点満点)

独立して判定する正答要素

  1. 1点: mvn testはテストまでを実行し、mvn packageはパッケージ生成まで実行します。
  2. 1点: 標準ライフサイクルではテストも含まれます。

満点の正答例: mvn testはテストまでを実行し、mvn packageはパッケージ生成まで実行します。標準ライフサイクルではテストも含まれます。

部分点の判定: 部分正答例:「mvn testはテストまでを実行し、mvn packageはパッケージ生成まで実行します」。この記述だけなら1点で、残る正答要素は未達です。

誤答・採点ミスの例: 不十分な解答例:「mvn testはテストまでを実行し、mvn packageはパッケージ生成まで実行します」。他の必須要素を欠いたまま満点と判定するのは誤りです。

合格条件:2/2点。 正答の言い換えは認めます。

復習先: この節「17. Mavenのテストを実行する」の本文および直前の例題。誤った採点要素を説明できるまで確認してから再回答します。

18. よくあるエラーの切り分け

症状 最初に確認すること 改善の例
Connection refused Spring Bootが起動しているか Eclipse Consoleの起動ログを読む
HTTP 404 パス・HTTPメソッド /api/productsの綴りを確認する
HTTP 400 POSTのJSON、名前、価格 nameは文字列、priceは整数にする
HTTP 500 サーバーログ・DB設定 接続URL、権限、SQLテーブルを調べる
Port 8080 already in use 二重起動の有無 片方のJavaアプリを停止する
Access denied for user DBユーザーとパスワード MySQLユーザーの権限を確認する
Table ... doesn't exist 使用DB、SQLの実行 USE training_web_db; SHOW TABLES;
No qualifying bean training.storageの設定 memory/mysqlの表記を確認する
Maven依存関係エラー インターネット・プロキシ Eclipse Maven Update Projectも確認

パスワードをエラーログや提出物に含めないでください。困った場合は、秘密情報を伏せてエラーの最初の行と再現手順を指導者へ伝えます。

この節の独学チェック:18. よくあるエラーの切り分け

確認問題: 404と500が出た場合、最初に確認する場所はどう違いますか。

取り組み方: 解答を見る前に自分の答えを記録してください。

ヒント1

404と500の発生段階は同じでしょうか。

ヒント2

URL対応が見つからない場合と処理中の例外を比べます。

ヒント3

Controllerのマッピングとアプリの例外ログを使い分けます。

模範解答と理由

404はURLとControllerのマッピング、500はアプリの例外ログなど内部処理を確認します。

この節の自己採点基準(2点満点)

独立して判定する正答要素

  1. 1点: 404ならURL・ルーティング・対象リソースを確認する。
  2. 1点: 500ならアプリ例外ログなどサーバー内部を確認する。

満点の正答例: 404はURLとControllerのマッピング、500はアプリの例外ログなど内部処理を確認します。

部分点の判定: 部分正答例:「404ならURL・ルーティング・対象リソースを確認する」。この記述だけなら1点で、残る正答要素は未達です。

誤答・採点ミスの例: 不十分な解答例:「404ならURL・ルーティング・対象リソースを確認する」。他の必須要素を欠いたまま満点と判定するのは誤りです。

合格条件:2/2点。 正答の言い換えは認めます。

復習先: この節「18. よくあるエラーの切り分け」の本文および直前の例題。誤った採点要素を説明できるまで確認してから再回答します。

19. 段階別演習と提出物

演習1:写経・再現。GETの結果を読み、初期データを表示します。HTTPステータスとJSONを記録してください。

演習2:一部変更。ノートの価格を180円から200円に変更し、再起動後にGET結果が変わることを確認します。その後元に戻します。

演習3:入力チェック。POSTで0円、-1円、空の名前を送り、結果と理由を記録します。

演習4:DBへ切り替える。MySQLモードに変更して商品を登録します。Javaアプリを再起動し商品が残ることを確認します。

演習5:自力改修。商品のstock(在庫数)を追加します。Product、Repository、SQL、API入力、HTML表示、テストにどの変更が必要かを最初に書き出してから実装してください。

stock=0は許可し、stock=-1は拒否します。テーブル変更はバックアップをとった学習用DBで行います。

提出物は exercises/06_web/assignment.md に記録します。正解は一つのソースコードだけでなく、実行した結果と、その結果になった理由まで含みます。

この節の独学チェック:19. 段階別演習と提出物

確認問題: 商品登録APIの演習で最低限確認する正常系・異常系を挙げてください。

取り組み方: 解答を見る前に自分の答えを記録してください。

ヒント1

正常な商品と不正な商品をそれぞれ考えましょう。

ヒント2

商品名が空の場合、価格が負の場合を分けます。

ヒント3

登録成功と二種類の拒否が確かめられるか確認します。

模範解答と理由

正常な商品が登録できることと、空の商品名や負の価格など不正値が拒否されることです。

この節の自己採点基準(3点満点)

独立して判定する正答要素

  1. 1点: 正常な商品登録ができることを確認する。
  2. 1点: 空の商品名を拒否することを確認する。
  3. 1点: 負の価格を拒否することを確認する。

満点の正答例: 正常な商品が登録できることと、空の商品名や負の価格など不正値が拒否されることです。

部分点の判定: 部分正答例:「正常な商品登録ができることを確認する」。この記述だけなら1点で、残る正答要素は未達です。

誤答・採点ミスの例: 不十分な解答例:「正常な商品登録ができることを確認する」。他の必須要素を欠いたまま満点と判定するのは誤りです。

合格条件:3/3点。 正答の言い換えは認めます。

復習先: この節「19. 段階別演習と提出物」の本文および直前の例題。誤った採点要素を説明できるまで確認してから再回答します。

20. 理解度チェックと次章の準備

  1. localhostと8080は何を表していますか。
  2. GETとPOSTの違いを、商品管理の例で説明してください。
  3. HTTPの200、201、400、404、500の使い分けは何ですか。
  4. Controller・Service・Repositoryは何を担当しますか。
  5. Spring BeanとDIはなぜ便利ですか。
  6. メモリー版で再起動すると追加商品が消える理由は何ですか。
  7. MySQL版の再起動後に商品が残る理由は何ですか。
  8. 入力チェックをHTMLだけに任せてはいけない理由は何ですか。
  9. SQLを直接文字列結合することの問題は何ですか。
  10. 例外が出たとき、画面・HTTP・ログのどこを見るべきですか。

理解できなかった設問は章の該当箇所へ戻ってください。第07章では、ここで作ったアプリに対してテストの種類を増やし、エラー処理やログの設計を学習します。

理解を深める:ここまでに確認しておきたいこと

  1. ControllerにSQLを書く構造の何が困りますか。
  2. Repositoryをメモリー版へ切り替えるときDIはどう役立ちますか。
  3. 入力が不正なPOSTに201を返してはいけない理由を説明してください。

この節の独学チェック:20. 理解度チェックと次章の準備

確認問題: 第07章へ進む前に、この章で説明できるべき処理の順は何ですか。

取り組み方: 解答を見る前に自分の答えを記録してください。

ヒント1

リクエストを受けてから応答を返すまでの流れを描きます。

ヒント2

Controller・Service・Repositoryの担当箇所を特定します。

ヒント3

保存先から値を受け取り応答になるまで順に追います。

模範解答と理由

HTTP要求→Controller→Service→Repository→保存先→レスポンスの順を説明できることです。

この節の自己採点基準(3点満点)

独立して判定する正答要素

  1. 1点: HTTP要求がControllerに届く。
  2. 1点: Serviceが業務処理を担当する。
  3. 1点: Repositoryが保存先を扱い、処理結果がHTTP応答になる。

満点の正答例: HTTP要求→Controller→Service→Repository→保存先→レスポンスの順を説明できることです。

部分点の判定: 部分正答例:「HTTP要求がControllerに届く」。この記述だけなら1点で、残る正答要素は未達です。

誤答・採点ミスの例: 不十分な解答例:「HTTP要求がControllerに届く」。他の必須要素を欠いたまま満点と判定するのは誤りです。

合格条件:3/3点。 正答の言い換えは認めます。

復習先: この節「20. 理解度チェックと次章の準備」の本文および直前の例題。誤った採点要素を説明できるまで確認してから再回答します。

21. 自動確認スクリプトで動作を再確認する

付属するexamples/06_web/product-web/verification/README.mdを開いてください。Windows PowerShellから一覧取得・商品登録・不正入力の拒否をまとめて確認できます。

MySQLモードでは再起動後の永続化も確認できます。スクリプトの作成と、その環境での動作確認は別の作業です。現時点では実機検証済みとはみなしません。

学習内容を振り返るための操作確認

この節は、本文の例題や演習が実行できないときに戻るための案内です。最初にファイルの場所と作業中のツールを確認し、コマンドを貼り付ける前に現在のフォルダーを確認してください。

実行する場所と順序

教材ルートから examples/06_web/product-web をEclipseのExisting Maven Projectsで取り込みます。まずメモリーモードで起動し、MySQLモードへは動作確認後に切り替えます。

成功・失敗の判断

ブラウザのGETとPowerShellのPOSTの両方を実行し、HTTPステータスとJSON本文を記録します。

途中で止まったとき

接続拒否はアプリ未起動、404はURLや経路、400は入力、500はサーバー処理の問題を疑い、起動ログを併せて確認します。

作業記録の書き方

  1. 利用環境(OS、Java、必要なツールのバージョン)を記録します。
  2. 実際に操作したフォルダー、実行コマンド、入力内容を記録します。
  3. 期待した結果と実際の結果を別々に書きます。失敗時にはエラーメッセージの全文を保管します。
  4. 修正を加えた場合は変更箇所を記録し、同じ手順で再確認します。
  5. 成功を確認できていなければ「未確認」と記載し、成功と推測して次へ進まないでください。

実際の入力、実行結果、原因の説明、演習の提出物がそろって初めて章の学習を完了とします。

この節の独学チェック:21. 自動確認スクリプトで動作を再確認する

確認問題: 自動確認スクリプトが失敗してもAPIが壊れていると断定できますか。

取り組み方: 解答を見る前に自分の答えを記録してください。

ヒント1

スクリプトにも実行環境と事前条件があります。

ヒント2

APIサーバーが停止している場合を考えてください。

ヒント3

テストデータやPowerShellのエラーとAPI不具合を切り分けます。

模範解答と理由

できません。サーバー未起動、接続先、テストデータ状態、PowerShell側エラーなども切り分けます。

この節の自己採点基準(1点満点)

独立して判定する正答要素

  1. 1点: サーバー未起動、接続先、テストデータ状態、PowerShell側エラーなども切り分けます。

満点の正答例: できません。サーバー未起動、接続先、テストデータ状態、PowerShell側エラーなども切り分けます。

部分点の判定: 正答要素は1つなので部分点はありません。意味が一致すれば1点、異なれば0点です。

誤答・採点ミスの例: 不十分な解答例:「よく分からないが、そのまま進めればよい」。正答条件「サーバー未起動、接続先、テストデータ状態、PowerShell側エラーなども切り分けます」を示していないので0点です。

合格条件:1/1点。 正答の言い換えは認めます。

復習先: この節「21. 自動確認スクリプトで動作を再確認する」の本文および直前の例題。誤った採点要素を説明できるまで確認してから再回答します。