区分 環境情報科目
ディプロマ・ポリシーとの関係

カリキュラム・ポリシーとの関係

カリキュラム全体の中でのこの科目の位置づけ

科目の目的
本科目の目的は、現代のJava Web開発におけるデファクトスタンダードであるSpring Bootフレームワークを用いたWebアプリケーション開発技術を体系的に習得することにあります。単にフレームワークの操作手順を覚えるのではなく、前半でJava Servlet/JSPによる「フレームワークを使わない開発」をあえて経験することで、HTTP通信の仕組みやWebアプリケーションの基本構造を深く理解します。その上で、フレームワークが解決する課題(開発生産性、保守性、セキュリティなど)を実感を伴って学習し、最終的には実務に近いテーマを題材とした実用的なアプリケーションを独力で設計・構築できる実践力を養うことを目的とします。
到達目標
1. Webアプリケーションの動作原理(HTTPリクエスト/レスポンス)を理解し、Servlet/JSPとSpring Frameworkによる開発手法の違いと、フレームワーク導入の意義を論理的に説明できるようになります。
2. Spring Frameworkの中核概念であるDI(依存性の注入)およびJavaConfigによる明示的なBean定義の仕組みを理解し、疎結合で保守性の高いプログラムコードを記述できるようになります。
3. Spring MVC、Thymeleaf、Spring Data JPAなどの周辺技術を適切に組み合わせ、画面表示からデータベース操作、認証・認可(Spring Security)までを含む一連の機能を実装するスキルを習得します。
4. レイヤ化アーキテクチャ(Controller、Service、Repository)に基づいた設計手法を身につけ、実際の業務を想定したお問い合わせ管理システムの構築を通じて、要件定義から実装、そして機能改修までの開発プロセスを完遂できる能力を養います。

科目の概要
本科目は大きく分けて「Web開発の歴史と課題」「Spring Bootの基礎とコア機能」「実践アプリケーション開発」の3つの局面で構成されます。
導入部では、Java ServletとJSPを用いた古典的な開発手法を演習し、コードの複雑化や管理の煩雑さを体験することで、なぜ現代開発にフレームワークが不可欠なのかを学びます。
中盤では、Spring Bootの核心であるDIコンテナとJavaConfigについて、その概念と実装方法を学習した上で、Web表示層を担うSpring MVCとテンプレートエンジンThymeleaf、データアクセス層を担うSpring Data JPAの使い方を段階的に習得します。
終盤では、これまでの学習内容を統合し、あるオンライン販売サイトの「お問い合わせ管理システム」をゼロから構築する総合演習を行います。設計、データベース構築、認証機能の実装、各レイヤの実装、そして機能追加・改修までを通じて、断片的な知識を実践的な技術として定着させます。

科目のキーワード
Java、Spring Framework、Spring Boot、Servlet/JSP、DI(依存性の注入)、JavaConfig、MVCモデル、Thymeleaf、Spring Data JPA、Spring Security、レイヤ化アーキテクチャ
授業の展開方法
本講義は、理論解説とPCを用いたプログラミング演習を交互に行う実践形式で進行します。
前半のServlet/JSPパートでは「課題発見型」のアプローチを取り、不便さを体験することを通じて技術の進化の必然性を学びます。中盤以降は、テキストに沿った講義で新しい概念を理解した後、即座にサンプルコードを用いたハンズオンを行うことで知識の定着を図ります。
また、単なるコーディングだけでなく、IntelliJ IDEA UltimateやH2データベースなどの環境構築や設定、GitHubのタグを用いた教材配布、デバッグ手法についても時間を割き、現場で通用するトラブルシューティング能力の向上を目指します。最終的には一つの完成されたアプリケーションを作成し、達成感と共に確実な技術力を身につけます。

オフィス・アワー
神馬一博:【前期】
Web環境システム概論木曜5限
【後期】
Web環境システム開発Ⅰ(Webアプリケーションの実装)水4限・5限
Web環境システム開発Ⅱ(クライアント再度・プログラミング)木5限
渡辺謙:【前期】
環境データベース概論
環境データベースⅡ
環境プログラミングⅣ(永続化技法)
全科目:木曜5限
【後期】
環境データベースⅠ
環境データベースⅢ
コンピュータ・アーキテクチャ論
全科目:木曜5限
村井浩昭:【前期】
環境プログラミングⅢ(標準API)月曜4限、水曜4限
【後期】
情報リテラシーⅡ(表計算ソフトによるデータ処理)木曜5限

科目コード UC4031
学年・期 2年・後期
科目名 Web環境システム開発Ⅰ(Webアプリケーションの実装)
単位数 6
授業形態 演習
必修・選択 必修
学習時間
前提とする科目
展開科目
関連資格
担当教員名 神馬一博・渡辺謙・村井浩昭
回主題コマシラバス項目内容教材・教具
1 ガイダンス・システムアーキテクチャ史①(メインフレーム→C/S) 科目の中での位置付け 本コマは全45回にわたる本科目の初回であり、フェーズ1(システムアーキテクチャ史とWeb基礎、コマ1〜6)の出発点に位置する。ここでは科目全体の学習目標と5つのフェーズ構成を共有した上で、コンピュータシステムの歴史をメインフレームによる集中処理から説き起こす。次回のコマ2ではクライアント/サーバーモデルからさらにCGI、Servletへと至る発展史を扱うため、本コマで習得する集中処理と分散処理の対比は、以降のアーキテクチャ理解全体の土台となる。単なる歴史知識としてではなく、「なぜ現代のWebシステムがこの形になったのか」を考える視点を養うことが狙いである。
コマ主題細目 ① 授業の全体像と学習目標の共有 ② 集中処理システムとしてのメインフレーム ③ 分散処理の台頭とクライアント/サーバー(C/S)モデル
細目レベル ① 本細目では、まず本科目「Web環境システム開発Ⅰ」の全体像と、受講を通じて到達すべき学習目標を共有する。本科目は全45回で構成され、大きく5つのフェーズに分かれていることを説明する。フェーズ1(コマ1〜6)ではシステムアーキテクチャの歴史とServlet/JSPによる素朴なWeb開発を体験し、フェーズ2(コマ7〜14)でSpring Bootを導入してMVCの基礎を学ぶ。フェーズ3(コマ15〜24)ではDIやJavaConfig、セッション管理、バリデーション、データベース接続、JPAといった中級的な技術を積み上げ、フェーズ4(コマ25〜33)でCRUD機能やページング、Spring Securityを実装し、あるオンライン販売サイトの「お問い合わせ管理システム」を段階的に完成させていく。最後のフェーズ5(コマ34〜45)では、完成したアプリケーションに対して各自が機能追加・改修に取り組む演習を行うことを説明する。
次に、本科目の教育方針として「課題発見型」の姿勢を強調する。フェーズ1ではあえて古い技術であるServletとJSPを直接扱い、その開発上の「手間」を実際に体験してもらう。これは、単にSpring Bootの使い方を知識として教えるのではなく、なぜそのフレームワークが必要とされ、何を解決してくれているのかを身をもって理解してもらうためである。体験し、その不便さに気づき、次の技術への動機を持つという「体験→気づき→動機付け」という流れが、本科目全体を貫く学び方であることを明確に伝える。あわせて、教材は毎回プロジェクトの状態をBefore/After形式で配布し、差分に集中して学習を進める運用であることも紹介する。
さらに、開発環境についてのガイダンスを行う。本科目ではEclipseを使用せず、フェーズ1のServlet開発からフェーズ2以降のSpring Boot開発まで、一貫してIntelliJ IDEA Ultimateを使用する。Jakarta EE関連の機能(Servlet等)はUltimate限定の機能であるため、大学のメールアドレスを用いたJetBrains学生向け無償ライセンスの申請方法を案内し、次回コマ3までに利用可能な状態にしておくよう指示する。
この細目で理解すべき範囲は、本科目の全体構成(5フェーズ・45コマ)と課題発見型の教育方針、および使用する開発環境の準備手順まで。

② 本細目では、コンピュータシステムの歴史における最初期の形態である、メインフレームを中心とした集中処理システムについて解説する。1960年代から1970年代にかけて主流であったこの方式では、非常に高価で強力な演算能力を持つ大型汎用機(メインフレーム)が全ての処理を一手に担い、利用者は「ダム端末」と呼ばれる、それ自体には演算能力を持たない入出力専用の端末を通じてメインフレームに接続していたことを説明する。ダム端末はキー入力の受付と処理結果の表示のみを行い、データの処理や保存といった実質的な計算処理は全てメインフレーム側で実行される。
次に、この集中処理方式の特徴と、その背景にある技術的制約について論じる。当時は演算装置そのものが極めて高価であったため、演算能力を1台のメインフレームに集約し、複数の利用者でその資源を共有する(タイムシェアリングシステム、TSS)ことが経済的に合理的であった。この方式のメリットとして、データやプログラムが1か所(メインフレーム側)に集中して管理されるため、一貫性の維持や保守が比較的容易であった点を挙げる。一方でデメリットとして、メインフレーム自体が単一障害点となること、利用者数の増加に伴う処理能力のスケールアップに限界があること、そして高価な専用機に依存するためコスト面での柔軟性に欠けることを説明する。
この集中処理モデルを理解しておくことは、後述する分散処理やクライアント/サーバーモデルへの移行がなぜ起こったのかを理解する上での比較対象として重要である。あわせて、現代のクラウドコンピューティングにおいても、集中管理という考え方自体は形を変えて残っていることにも軽く触れ、歴史が単純な一方向の進歩ではないことを示唆する。この細目で理解すべき範囲は、メインフレームによる集中処理システムの仕組みと、その利点・欠点を歴史的背景とともに説明できるまで。

③ 本細目では、メインフレームによる集中処理の限界を背景に台頭した、分散処理の考え方とクライアント/サーバー(C/S)モデルについて解説する。1980年代以降、パーソナルコンピュータ(PC)の性能向上と低価格化が進んだことで、末端の利用者側の機器にも一定の演算能力を持たせることが可能になった。この技術的変化を受けて登場したのがC/Sモデルであり、処理を要求する側の「クライアント」と、要求に応じてサービスを提供する側の「サーバー」に役割を分担する設計思想であることを定義する。
次に、C/Sモデルにおける典型的な処理分担のパターンについて説明する。多くの場合、クライアント側のPC上で動作する専用のアプリケーションが画面表示や入力処理、さらには業務ロジックの一部までも担い、サーバー側はデータベースなど共有すべきデータの管理に特化する構成(いわゆる「ファットクライアント」型)が広く採用されたことを紹介する。この方式では、メインフレーム時代に比べて利用者側の応答性が向上し、PCの処理能力を活用した柔軟なアプリケーション開発が可能になった利点がある一方、業務ロジックの変更のたびに全クライアントPCへ新しいアプリケーションを配布・インストールし直す必要が生じるという新たな運用上の課題が生まれたことを指摘する。
この「クライアント側に配布・更新の手間がかかる」という課題こそが、後に登場するWebブラウザを汎用クライアントとして活用する仕組み(CGIやServletに代表されるWebアプリケーション)へと発展していく歴史的な伏線であることを示し、次回のコマ2への橋渡しとする。この細目で理解すべき範囲は、C/Sモデルの基本構造とファットクライアント型の特徴、およびその運用上の課題を説明できるまで。

キーワード ① メインフレーム ② 集中処理 ③ クライアント/サーバーモデル ④ 分散処理 ⑤ ファットクライアント
コマの展開方法 社会人講師 AL ICT PowerPoint・Keynote 教科書
コマ用オリジナル配布資料 コマ用プリント配布資料 その他 該当なし
小テスト 授業時間内に、LMS上において該当コマの小テストを実施する。
復習・予習課題 ◆今回授業の復習
今回の授業で学習した、メインフレームによる集中処理システムと、クライアント/サーバー(C/S)モデルによる分散処理システムの違いを、自分の言葉でノートに整理すること。特に、なぜ集中処理から分散処理へと移行したのか、その技術的・経済的背景(PCの性能向上と低価格化)を説明できるようにしておくこと。また、C/Sモデルにおける「ファットクライアント」という言葉の意味と、その運用上の課題(クライアントソフトの配布・更新の手間)についても振り返っておくこと。

◆次回授業の予習
次回の授業では、C/Sモデルがさらに発展し、Webブラウザを汎用クライアントとして活用するCGI(Common Gateway Interface)という仕組みと、その課題を解決するServletの登場について学習する。そのため、「CGI」という言葉について、インターネットで簡単に検索し、どのような場面で使われる技術なのか概要を把握しておくこと。あわせて、自分が日常的に使っているWebサイトが、裏側でどのようにサーバーと通信しているのか、興味を持って考えてみること。

2 システムアーキテクチャ史②(CGIからServletへ) 科目の中での位置付け 本コマは、フェーズ1の中でコマ1とコマ3を橋渡しする位置にある。前回学習したクライアント/サーバーモデルにおいて、Webブラウザを汎用的なクライアントとして活用するために生まれたCGIの仕組みと、その処理効率上の課題を確認した上で、それを解決する技術として登場したServletの優位性を学ぶ。ここで得られるCGIとServletの対比という視点は、次回コマ3で学ぶHTTPプロトコルの詳細や、コマ4以降で実際にServletを実装していく上での前提知識となる。歴史的な発展の必然性を理解することが本コマの目的である。
コマ主題細目 ① CGI(Common Gateway Interface)の仕組みと課題 ② Servletの登場とその優位性 ③ WebアプリケーションとHTTPプロトコルの基本
細目レベル ① 本細目では、Webサーバーが動的なコンテンツを生成するための初期の標準的な仕組みであるCGI(Common Gateway Interface)について、その動作原理と技術的な課題を解説する。まず、CGIとは、Webサーバーが外部のプログラム(CGIスクリプト。Perlなどで記述されることが多い)を呼び出し、その実行結果をクライアントに返すための規約であることを定義する。具体的な処理の流れとして、クライアントからのリクエストをWebサーバーが受け取ると、Webサーバーは該当するCGIプログラムを新しい別プロセスとしてOS上に起動し、そのプログラムが処理を行った結果(多くの場合HTML)を標準出力経由でWebサーバーに返し、Webサーバーがそれをクライアントへ送信するという一連の流れを説明する。
次に、この仕組みが抱える最大の技術的課題として、リクエストが到着するたびに新しいプロセスを生成するという点を詳しく取り上げる。プロセスの生成(フォーク)はOSにとって比較的重い処理であり、メモリ消費やCPU負荷が大きいため、同時に多数のリクエストが到着するアクセス集中時には、サーバーの処理能力を大きく圧迫し、応答速度の低下やサーバーダウンにつながりやすいという欠点があったことを説明する。また、プロセスごとに状態が独立しているため、リクエスト間でのデータ共有や状態管理も工夫が必要であった点にも触れる。
こうした処理効率上の課題が、後により効率的な仕組み(Servlet)が求められる直接的な動機になったことを示す。この細目で理解すべき範囲は、CGIの基本的な処理の流れと、プロセス生成に起因する性能上の課題を説明できるまで。

② 本細目では、CGIの課題を解決する技術として登場したJavaベースの仕組み、Servletについて、その動作原理とCGIに対する優位性を解説する。まず、Servletとは、Java言語で記述され、Webサーバー(正確にはServletコンテナ、あるいはWebコンテナと呼ばれるソフトウェア。Tomcatなどが代表例)上で動作する小さなプログラムであることを定義する。ServletコンテナはServletの実行環境を提供し、そのライフサイクル(生成・初期化・実行・破棄)を管理する役割を持つことを説明する。
次に、ServletがCGIに対して優れている最大の点として、リクエストごとにプロセスを生成するのではなく、あらかじめメモリ上にロードされたServletインスタンスに対して、リクエストごとにスレッドを割り当てて処理を行う点を詳しく解説する。プロセス生成に比べてスレッド生成・切り替えのコストははるかに小さいため、同時アクセスが多い状況でも効率的に処理を捌けることを説明する。また、Servletインスタンス自体はサーバー起動後も継続してメモリ上に存在し続けるため、データベース接続などの初期化処理を毎回行う必要がなく、処理全体の効率が向上することにも言及する。
さらに、ServletがJavaという言語の特性(プラットフォーム非依存、豊富なライブラリ、オブジェクト指向設計)を活かした標準化されたAPIとして提供されている点も、後のJava EE(現Jakarta EE)における様々な技術の基盤となったことを補足する。この細目で理解すべき範囲は、Servletの動作原理とライフサイクルの概要、およびCGIに対する処理効率上の優位性を説明できるまで。

③ 本細目では、これまで扱ってきたCGIやServletが動作する土台となる、Webアプリケーションの基本構造とHTTPプロトコルの位置づけについて概観する。まず、Webアプリケーションとは、Webブラウザをクライアントとして利用し、ネットワークを介してサーバー上のプログラムと通信することでサービスを提供するアプリケーションの総称であることを確認する。C/Sモデルにおける「クライアント」の役割を、専用のインストール型アプリケーションではなく汎用的なWebブラウザが担うことにより、コマ1で課題として挙げた「クライアントごとの配布・更新の手間」が大幅に軽減される点を、これまでの歴史的な流れと結びつけて説明する。
次に、このクライアントとサーバーの通信を規定する共通のルールがHTTP(HyperText Transfer Protocol)であることを紹介する。HTTPは、クライアントがサーバーに対して「リクエスト」を送信し、サーバーがそれに対して「レスポンス」を返すという、シンプルな1往復のやり取りを基本単位とするプロトコルであることを述べる。この段階では詳細な構造には立ち入らず、Webアプリケーション開発においてHTTPの理解が不可欠な基盤知識であることを認識させるにとどめる。
最後に、次回のコマ3では、このHTTPプロトコルが持つ重要な性質(ステートレス性)や、実際のリクエスト・レスポンスメッセージの中身をブラウザの開発者ツールを用いて具体的に観察していくことを予告し、学習の見通しを示す。この細目で理解すべき範囲は、Webアプリケーションの基本構造と、HTTPがクライアント・サーバー間の通信規約であるという位置づけを理解するまで。

キーワード ① CGI ② プロセス生成 ③ Servlet ④ サーブレットコンテナ ⑤ HTTPプロトコル
コマの展開方法 社会人講師 AL ICT PowerPoint・Keynote 教科書
コマ用オリジナル配布資料 コマ用プリント配布資料 その他 該当なし
小テスト 授業時間内に、LMS上において該当コマの小テストを実施する。
復習・予習課題 ◆今回授業の復習
今回の授業で学習したCGIの処理の流れ(Webサーバーが外部プロセスを起動し、その実行結果を受け取る仕組み)を図に書き出し、リクエストのたびにプロセスが生成されることがなぜ性能上の課題になるのかを、自分の言葉で説明できるようにしておくこと。また、Servletがスレッドベースで動作することでCGIの課題をどのように解決しているのか、両者を対比させた表を作成して整理しておくこと。

◆次回授業の予習
次回の授業では、HTTPプロトコルの役割とステートレス性、およびHTTPリクエスト・レスポンスメッセージの具体的な構造について学習し、あわせてIntelliJ IDEA Ultimateを用いた開発環境の構築を行う。そのため、自分のPCにIntelliJ IDEA Ultimateがインストールされているか、またJetBrains学生ライセンスの申請が完了しているかを事前に確認しておくこと。可能であれば、普段使っているWebブラウザの開発者ツール(F12キーなどで起動)を一度開いてみて、「Network」タブが存在することを確認しておくこと。

3 HTTPの仕組みと開発環境構築 科目の中での位置付け 本コマは、コマ2で概観したHTTPプロトコルについて、その仕組みをより具体的かつ実践的に掘り下げるとともに、以降フェーズ1を通じて使用する開発環境を実際に構築する回である。前半でHTTPのステートレス性やメッセージ構造を学んだ上で、後半ではIntelliJ IDEA Ultimateを用いてServlet開発用のプロジェクトを作成し、Tomcatとの連携を確立する。ここで作成するプロジェクトの器は、次回コマ4以降のHelloServlet実習からコマ6の課題発見型演習まで一貫して使用されるため、本コマでの環境構築が以降のフェーズ1全体の実習を支える土台となる点が重要である。
コマ主題細目 ① HTTPプロトコルの役割とステートレス性 ② HTTPリクエスト・レスポンスメッセージの構造(ブラウザ開発者ツールで確認) ③ IntelliJ IDEA Ultimateでのプロジェクト作成(Jakarta EE/Webアプリケーション)とTomcat連携
細目レベル ① 本細目では、Webアプリケーション開発における最も基礎的な通信規約であるHTTP(HyperText Transfer Protocol)の役割と、その重要な性質であるステートレス性について詳説する。まず、HTTPとは、クライアント(多くの場合Webブラウザ)とサーバーとの間で、テキストベースのメッセージをやり取りするための通信規約であり、クライアントからの「リクエスト」に対してサーバーが「レスポンス」を返すという、1往復の要求・応答型の通信を基本単位とすることを確認する。
次に、HTTPの持つ最も重要な特性の一つである「ステートレス性」について詳しく解説する。ステートレスとは、サーバー側がそれぞれのリクエストを独立したものとして扱い、過去のリクエストの内容や状態を記憶・保持しないという性質であることを定義する。例えば、あるクライアントが1回目のリクエストでログインに成功したとしても、HTTP自体の仕組みだけでは、2回目以降のリクエストがそのクライアントからのものであるとサーバー側は認識できないことを、具体例を交えて説明する。
このステートレス性は、サーバー側の実装をシンプルに保ち、多数のクライアントからのリクエストを処理する上でのスケーラビリティを高めるという設計上のメリットがある一方で、ログイン状態の維持のような「複数リクエストにまたがる状態管理」を実現するには、Cookieやセッションといった別の仕組みを追加する必要があるという課題を生むことを示す。この課題は、コマ5〜6で学ぶセッション管理(HttpSessionオブジェクト)に直接つながる重要な伏線であることを明示する。この細目で理解すべき範囲は、HTTPの基本的な通信モデルと、ステートレス性の定義およびそれがもたらす設計上の課題を説明できるまで。

② 本細目では、HTTP通信において実際にやり取りされるリクエストメッセージとレスポンスメッセージの具体的な構造を、ブラウザの開発者ツールを用いて実際に観察しながら学ぶ。まず、HTTPリクエストメッセージが、リクエストライン(HTTPメソッド、URL、HTTPバージョンから構成される)、リクエストヘッダー(Host、User-Agent、Cookieなど、付加的な情報を示すキーと値の組)、そして必要に応じたリクエストボディ(POSTメソッドで送信するフォームデータなど)という3つの要素から構成されることを説明する。
次に、HTTPレスポンスメッセージについても同様に、ステータスライン(HTTPバージョン、ステータスコード、ステータスメッセージ。200 OKや404 Not Foundなど)、レスポンスヘッダー(Content-Typeなど)、レスポンスボディ(実際に表示されるHTMLなど)から構成されることを解説する。特にステータスコードについては、2xx(成功)、3xx(リダイレクト)、4xx(クライアントエラー)、5xx(サーバーエラー)という大まかな分類を紹介し、代表的なコードの意味を理解させる。
実習として、受講者自身のPCでブラウザの開発者ツール(Networkタブ)を開き、任意のWebサイトへアクセスした際に実際に送受信されているリクエスト・レスポンスメッセージの中身を確認する演習を行う。座学で学んだ抽象的な構造が、実際の通信の中にどのように現れているかを自分の目で確認することで、理解を確実なものにすることを狙いとする。この細目で理解すべき範囲は、HTTPリクエスト・レスポンスメッセージの構成要素と、開発者ツールを用いてそれらを実際に確認する方法まで。

③ 本細目では、以降のフェーズ1における実習(コマ4〜6)で継続して使用する開発環境を、IntelliJ IDEA Ultimateを用いて実際に構築する。まず、IntelliJ IDEA Ultimateの新規プロジェクト作成画面において「Jakarta EE」ジェネレーターを選択し、そこから「Webアプリケーション」テンプレートを選ぶことで、Servletを開発できるプロジェクトの雛形が生成できることを、実際の操作を交えながら説明する。これはEclipseにおける「動的Webプロジェクト」に相当するものであり、Jakarta EE関連の機能はUltimateエディション限定であるため、無料のCommunity Editionでは利用できない点を改めて確認する。
次に、作成したプロジェクトと、実際にServletを実行するためのApplication Server(Tomcat)とを関連付ける設定を行う。IntelliJの「Application Servers」設定画面からTomcatのインストール先を指定し、プロジェクトの実行構成にTomcatを紐づけることで、IDE上から直接Servletアプリケーションを起動・デバッグできるようになることを実演する。
なお、この回で作成するプロジェクトの器(サーバーランタイムとの関連付けなど環境依存の設定を含む)は、コマ6まで継続して使用するものであり、以後のコマでは`src`フォルダ以下のソースコードのみを追加・変更していく運用であることを伝える。また、`.idea`フォルダなどIDE固有の設定ファイルはGit管理の対象外とすることにも触れる。この細目で理解すべき範囲は、IntelliJ IDEA UltimateでJakarta EEのWebアプリケーションプロジェクトを新規作成し、Tomcatと関連付けて実行できる状態にするまで。

キーワード ① HTTP ② ステートレス性 ③ リクエスト/レスポンス ④ IntelliJ IDEA Ultimate ⑤ Tomcat連携
コマの展開方法 社会人講師 AL ICT PowerPoint・Keynote 教科書
コマ用オリジナル配布資料 コマ用プリント配布資料 その他 該当なし
小テスト 授業時間内に、LMS上において該当コマの小テストを実施する。
復習・予習課題 ◆今回授業の復習
今回の授業で学習したHTTPのステートレス性について、なぜこの性質が「ログイン状態を維持できない」という課題につながるのかを、自分の言葉で説明できるようにしておくこと。また、開発者ツールで実際に確認したリクエスト・レスポンスメッセージの構造(リクエストライン、ヘッダー、ボディなど)をノートに図示し、ステータスコードの大まかな分類(2xx〜5xx)を復習しておくこと。IntelliJ上でTomcatと連携したプロジェクトが正しく起動できる状態になっているかも、あわせて確認しておくこと。

◆次回授業の予習
次回の授業では、実際にHelloServletというServletを作成し、doGetメソッドの実装やHTMLフォームを用いたGET/POSTでのデータ送信を実習する。そのため、コマ3で作成したプロジェクトが問題なく起動することを事前に再確認しておくこと。また、HTMLの`<form>`タグについて、`method`属性や`action`属性がどのような役割を持つのか、簡単に調べておくこと。

4 HelloServlet実習とフォーム処理基礎 科目の中での位置付け 本コマは、コマ3で構築した開発環境を用いて、初めて実際にServletのコードを記述し、動作を確認する実習回である。前回学んだHTTPリクエスト・レスポンスの構造を踏まえながら、doGetメソッドの実装とHTMLフォームによるGET/POST送信を体験することで、ブラウザとServletとの間で実際にどのようにデータがやり取りされるのかを体感する。ここで習得するServletの基本的な実装パターンは、次回コマ5・6の課題発見型演習(ログイン機能の実装)において直接活用される前提知識であり、フェーズ1における最初の本格的なハンズオンとして位置づけられる。
コマ主題細目 ① ServletのライフサイクルとdoGetメソッド実装(実習:HelloServlet) ② HTMLフォームの作成とGETメソッドによるデータ送信(実習) ③ POSTメソッドによるデータ送信と処理(実習)
細目レベル ① 本細目では、実際にHelloServletという名称のServletクラスを作成する実習を通じて、Servletのライフサイクルと基本的な実装方法を学ぶ。まず、Servletを作成するには、`HttpServlet`クラスを継承したJavaクラスを定義し、`@WebServlet`アノテーションでそのServletがどのURLパスに対応するかをマッピングすることを説明する。あわせて、Servletコンテナがそのライフサイクルを管理していること(インスタンス生成時の`init`メソッド、リクエストのたびに呼び出される`service`メソッド、そして破棄時の`destroy`メソッド)を、教科書的な説明にとどめず、実際の動作イメージとともに解説する。
次に、GETリクエストを処理するための`doGet`メソッドをオーバーライドする実装を、実際にコーディングしながら進める。`doGet`メソッドは引数として`HttpServletRequest`と`HttpServletResponse`を受け取り、レスポンスに対して`getWriter()`メソッドで取得した`PrintWriter`を用いて、ブラウザに表示するHTMLを直接書き出す実装であることを示す。受講者は実際にIntelliJ上でHelloServletクラスを作成し、ブラウザから該当URLにアクセスして「Hello, Servlet!」といった文字列が表示されることを確認する。
この実習を通じて、これまで概念として学んできたServletが、実際にJavaのコードとしてどのように記述され、Tomcat上で動作するのかを具体的に体感することを狙いとする。この細目で理解すべき範囲は、`@WebServlet`アノテーションによるURLマッピングと、`doGet`メソッドをオーバーライドしてレスポンスを返す基本的なServletの実装方法まで。

② 本細目では、HTMLフォームを用いてクライアントからServletへデータを送信する方法のうち、GETメソッドによる送信を実習を通じて学ぶ。まず、HTMLの`<form>`タグにおいて`method="get"`を指定した場合、フォーム内の各入力項目(`<input>`タグの`name`属性で指定した名前とその値)が、URLの末尾にクエリ文字列(`?name1=value1&name2=value2`の形式)として付加された状態でサーバーに送信されることを説明する。
次に、受講者自身で簡単な入力フォーム(例えば名前を入力するテキストボックス)を含むHTMLファイルを作成し、その`action`属性に送信先のServletのURLを指定する実習を行う。送信されたデータをServlet側で受け取るには、`doGet`メソッド内で`request.getParameter("name1")`のように、HTML側で指定した`name`属性の値をキーとしてパラメータを取得することを示し、実際に取得した値をレスポンスとして画面に表示する処理を実装する。
あわせて、GETメソッドの特性(送信データがURLに含まれるためブラウザの履歴に残る、送信できるデータ量に事実上の制限がある、検索条件の指定など「取得」を目的とした操作に向いている)についても触れ、次に学ぶPOSTメソッドとの対比の材料とする。さらに、日本語などマルチバイト文字を含む値をURLに載せる際にはURLエンコードが行われる点にも軽く触れ、Networkタブでクエリ文字列が実際にどのようにエンコードされて送信されているかを確認させる。この細目で理解すべき範囲は、GETメソッドによるフォーム送信の仕組みと、`request.getParameter`を用いてServlet側でパラメータを取得する方法まで。

③ 本細目では、HTMLフォームの`method="post"`属性を用いたデータ送信と、それをServlet側で処理する`doPost`メソッドの実装を実習する。まず、POSTメソッドではフォームのデータがURLのクエリ文字列としてではなく、HTTPリクエストのボディ部分に格納されて送信される点を、コマ3で学んだHTTPメッセージ構造と結びつけて再確認する。これにより、URLに送信内容が表示されないこと、送信できるデータ量の制限が事実上ないこと、そしてパスワードなど機微な情報の送信や、新規登録・更新のような「サーバー側の状態を変更する」操作に向いていることを説明する。
次に、受講者は先ほど作成したHTMLフォームの`method`属性を`post`に変更し、Servlet側では`doPost`メソッドをオーバーライドして実装する。`doPost`メソッド内でのパラメータ取得方法(`request.getParameter`)自体はGETの場合と同様であることを確認しつつ、なぜHTTPメソッドによって処理を分けて実装する必要があるのか、その設計上の意味を考えさせる。
最後に、GETとPOSTという2つの基本的なデータ送信方法を実際に手を動かして実装した経験を踏まえ、次回以降のログイン機能実装(コマ5・6)では、ユーザー名やパスワードといった機微情報をPOSTメソッドで送信する設計になることを予告し、学習の見通しを与える。この細目で理解すべき範囲は、POSTメソッドによるフォーム送信の仕組みと`doPost`メソッドの実装方法、およびGETとPOSTの使い分けの基準を説明できるまで。

キーワード ① Servlet ② doGetメソッド ③ doPostメソッド ④ HTMLフォーム ⑤ getParameter
コマの展開方法 社会人講師 AL ICT PowerPoint・Keynote 教科書
コマ用オリジナル配布資料 コマ用プリント配布資料 その他 該当なし
小テスト 授業時間内に、LMS上において該当コマの小テストを実施する。
復習・予習課題 ◆今回授業の復習
今回の授業で作成したHelloServletのコードを見直し、`@WebServlet`アノテーションによるURLマッピングと、`doGet`メソッドの役割を自分の言葉で説明できるようにしておくこと。また、GETメソッドとPOSTメソッドでそれぞれ作成したフォームとServletのコードを比較し、送信されるデータの見え方の違い(URLに表示されるか否か)と、使い分けの基準をノートに整理しておくこと。

◆次回授業の予習
次回の授業では、JSPの基本構文(スクリプトレット、式)と、ServletからJSPへのフォワード処理、そしてログイン機能の設計とフォーム画面の作成を行う。そのため、拡張子が`.jsp`のファイルがどのようなものか、HTMLファイルとの違いについて簡単に調べておくこと。また、自分が普段利用しているWebサービスのログイン画面を1つ観察し、どのような入力項目(ユーザー名、パスワードなど)が求められているかを確認しておくこと。

5 課題発見型演習①(ログイン機能実装の準備) 科目の中での位置付け 本コマは、フェーズ1における課題発見型演習の前半にあたり、次回コマ6での「ログイン機能の完成」に向けた準備を行う回である。コマ4までに習得したServletの基本実装を踏まえ、本コマではHTMLと類似した見た目を持つJSPという技術を新たに導入し、ServletからJSPへ処理結果を引き渡すフォワード処理の仕組みを学ぶ。あわせてログイン機能全体の設計とフォーム画面の作成に着手することで、次回のセッション管理・認証処理の実装へと自然につながる流れを作る。フェーズ1の教育的クライマックスであるコマ6の直前の回として、あえて手作業の多い実装を体験させる点が重要である。
コマ主題細目 ① JSPの役割と基本構文(スクリプトレット、式) ② ServletからJSPへのフォワード処理とリクエストスコープ ③ ログイン機能の設計とフォーム画面の作成
細目レベル ① 本細目では、動的なHTML画面を生成するための技術であるJSP(JavaServer Pages)について、その役割と基本的な構文を解説する。まず、JSPとは、拡張子`.jsp`のファイルの中に、通常のHTMLタグとJavaのコードを混在させて記述できる技術であり、実行時にはJSPコンテナによって内部的にServletのソースコードへと変換され、コンパイル・実行される仕組みであることを説明する。この「JSPの正体はServletである」という事実を理解することが、Servletとの関係を把握する上で重要である。
次に、JSPにおける基本的な構文である「スクリプトレット」(`<% ... %>`で囲まれた部分に任意のJavaコードを記述できる)と「式」(`<%= ... %>`で囲まれた部分の評価結果が、その位置にそのまま出力される)について、実際のコード例を交えながら解説する。例えば、リクエストから受け取った値をスクリプトレット内で変数に代入し、式を用いてその変数の値を画面上に表示するといった、簡単な実装を実際に記述させる。
ここで意図的に強調しておきたいのは、スクリプトレットを多用すると、HTMLファイルの中に大量のJavaコードが埋め込まれ、画面のレイアウトを担当する部分とロジックを担当する部分が入り混じり、可読性や保守性が急速に低下していくという点である。この「書きにくさ・読みにくさ」の芽生えを、あえてこの段階で実際に体感してもらうことが、後のフェーズで学ぶMVCモデルの価値を理解する伏線となる。この細目で理解すべき範囲は、JSPの仕組みとスクリプトレット・式という基本構文を用いてJavaのコードをHTML内に埋め込む方法まで。

② 本細目では、Servletでの処理結果を、画面表示を担当するJSPへ引き渡すための「フォワード処理」と、その際にデータを受け渡す仕組みである「リクエストスコープ」について解説する。まず、`RequestDispatcher`インターフェースを用いて、Servlet内から特定のJSPファイルへ処理を転送する`forward`メソッドの使い方を、実際のコード例とともに紹介する。フォワードでは、ブラウザのURLは変化せず、あくまでサーバー内部で処理が転送される点を、ブラウザのURLが変化する「リダイレクト」と対比しながら明確に区別する。
次に、フォワードする際にServlet側で処理したデータをJSP側に渡す方法として、リクエストスコープに値を格納する`request.setAttribute("キー", 値)`メソッドと、JSP側でその値を取り出す`request.getAttribute("キー")`メソッド(あるいはJSP内の式言語による簡略記法)を解説する。このリクエストスコープに格納された値は、1回のリクエスト処理(Servletからフォワードされた先のJSPまで)の間だけ有効であり、リクエストが完了すると破棄される点を強調する。
このフォワード処理とリクエストスコープの仕組みは、次に作成するログイン機能において、Servlet側での認証処理の結果(成功・失敗)をJSP側の表示に反映させるために不可欠な技術であることを説明し、実習へとつなげる。この細目で理解すべき範囲は、`forward`によるServletからJSPへの処理転送の仕組みと、リクエストスコープを用いたデータの受け渡し方法まで。

③ 本細目では、次回コマ6で完成させるログイン機能について、その全体設計を検討した上で、実際にログイン用のフォーム画面を作成する実習を行う。まず、今回実装するログイン機能の仕様として、あらかじめ固定されたユーザー名とパスワードの組み合わせと、フォームから入力された値とを比較し、一致すれば認証成功とするシンプルな方式を採用することを説明する。あわせて、認証に成功した後は、以降のページ(例えばお問い合わせ一覧を表示するページを想定)へのアクセスをログイン済みの利用者に限定する、という全体の処理フローを図で示しながら設計する。
次に、この設計に基づき、ユーザー名とパスワードを入力するための`login.jsp`(またはHTML)ファイルを実際に作成する実習を行う。フォームの`method`属性は`post`とし、`action`属性には次回実装する認証用Servletのパスを指定しておく。入力項目の`name`属性には、Servlet側で`getParameter`により取得しやすいよう、分かりやすい名前(例えば`username`、`password`)を付与することを確認する。
本コマの段階では、あえて認証処理そのもの(HttpSessionへのユーザー情報の格納など)には踏み込まず、画面と全体設計の準備までにとどめる。これにより、次回コマ6において、セッション管理という新しい概念に集中して取り組めるようにする狙いがある。また、ユーザー名やパスワードが未入力のまま送信された場合の扱いなど、細かな例外ケースについても軽く問いかけ、次回以降の実装で考慮すべき観点として意識づけておく。この細目で理解すべき範囲は、ログイン機能全体の処理フロー設計と、ログインフォーム画面の作成まで。

キーワード ① JSP ② スクリプトレット ③ フォワード処理 ④ リクエストスコープ ⑤ ログイン機能設計
コマの展開方法 社会人講師 AL ICT PowerPoint・Keynote 教科書
コマ用オリジナル配布資料 コマ用プリント配布資料 その他 該当なし
小テスト 授業時間内に、LMS上において該当コマの小テストを実施する。
復習・予習課題 ◆今回授業の復習
今回の授業で学習したJSPのスクリプトレット(`<% %>`)と式(`<%= %>`)の違いを、実際に自分で書いたコードを見返しながら整理しておくこと。また、`forward`によるServletからJSPへの処理転送と、`request.setAttribute`/`getAttribute`によるリクエストスコープでのデータ受け渡しの流れを、図に書き出して説明できるようにしておくこと。作成したログインフォーム画面についても、`name`属性の指定に誤りがないか再確認しておくこと。

◆次回授業の予習
次回の授業では、いよいよHttpSessionオブジェクトを用いたセッション管理と、認証Servletの実装によってログイン機能を完成させる。そのため、コマ3で学んだHTTPのステートレス性について改めて振り返り、「なぜ1回のログインだけでは以降のページアクセスがログイン済みと認識されないのか」を自分の言葉で説明できるようにしておくこと。あわせて、Webアプリケーションにおける「セッション」という言葉について、簡単に調べておくこと。

6 課題発見型演習②(ログイン機能実装の完成) 科目の中での位置付け 本コマは、フェーズ1(コマ1〜6)の最終回であり、教育的にも本フェーズの集大成となる回である。前回作成したログインフォームを起点に、HttpSessionオブジェクトを用いたセッション管理と認証Servletの実装によってログイン機能を完成させる。しかしそれ以上に重要なのは、Servlet/JSPによる一連の手作業(フォワード処理、リクエストスコープの管理、セッションチェックの重複記述など)を実際に体験した上で、その「手間」を振り返り、「もっと楽な方法があるはずだ」という気づきを得ることである。この気づきこそが、次回コマ7から始まるフェーズ2・Spring Boot導入への動機付けとなる、本科目全体の設計上の要となっている。
コマ主題細目 ① セッション管理の基礎とHttpSessionオブジェクト ② 認証Servletの実装とセッションへのユーザー情報格納 ③ 課題の振り返りと「もっと楽な方法」への気づき/【コラム】Servletアプリのデプロイ
細目レベル ① 本細目では、コマ3で学んだHTTPのステートレス性という課題を解決する具体的な仕組みとして、セッション管理とHttpSessionオブジェクトについて解説する。まず、セッションとは、ステートレスなHTTP通信の上に、あるクライアントからの一連のリクエストを「同一の利用者からのもの」として関連付けて管理するための仕組みであることを定義する。Servlet/JSPの世界では、この仕組みが`HttpSession`インターフェースとして提供されていることを説明する。
次に、`HttpSession`オブジェクトの具体的な取得方法として、`request.getSession()`メソッドを呼び出すことで、そのクライアント用のセッションオブジェクトを取得(存在しなければ新規作成)できることを示す。取得したセッションオブジェクトに対しては、`setAttribute("キー", 値)`で任意のオブジェクトを格納し、`getAttribute("キー")`で取り出し、`invalidate()`でセッションそのものを破棄(ログアウト処理に相当)できることを、コード例とともに解説する。
あわせて、サーバーが個々のクライアントのセッションを識別する仕組みとして、`JSESSIONID`という値がCookieを通じてクライアントとサーバーの間でやり取りされていることにも簡単に触れ、ブラウザの開発者ツールで実際に確認する。さらに、セッションには既定のタイムアウト時間が設定されており、一定時間操作がないと自動的に破棄されることにも触れ、ログイン状態がいつまでも無条件に保持されるわけではない点を補足する。この細目で理解すべき範囲は、セッションの概念とHttpSessionオブジェクトの取得・格納・破棄という基本操作、およびその背後にあるJSESSIONIDの仕組みまで。

② 本細目では、前回作成したログインフォームからの入力を受け取り、実際に認証処理を行うServletを実装する。まず、`doPost`メソッド内で`request.getParameter`を用いてユーザー名とパスワードを取得し、あらかじめコード内に固定した正しい値と一致するかどうかを比較する処理を実装する。認証に成功した場合は、`request.getSession()`で取得したセッションに`setAttribute("user", ユーザー名)`のようにログイン済みであることを示す情報を格納し、その後お問い合わせ一覧を想定した画面へフォワード(またはリダイレクト)する処理を実装する。認証に失敗した場合は、エラーメッセージとともに再度ログイン画面を表示する分岐処理もあわせて実装する。
次に、ログインが必須となるページ(例えばお問い合わせ一覧を表示するServlet)の`doGet`メソッドの冒頭に、セッションに`user`属性が格納されているかどうかを確認し、格納されていなければログイン画面へ強制的に転送するチェック処理を追加する実習を行う。この確認処理を、ログインが必要な複数のServletそれぞれに個別に記述していく作業を、受講者自身の手で実際に行わせる。
この「ページが増えるたびに同じセッションチェックのコードを1つずつ書き足していく」という作業そのものが、次の細目で振り返る「手間」の具体的な実感として機能することを意識しながら実習を進める。あわせて、ログアウト処理として`session.invalidate()`を呼び出すServletも実装し、ログイン状態の解除を実際に確認する演習も行う。この細目で理解すべき範囲は、認証Servletの実装によるログイン処理の完成と、セッションを用いたアクセス制御の基本パターンまで。

③ 本細目では、まずこれまでフェーズ1(コマ1〜6)を通じて実装してきたServlet/JSPによる一連の開発作業全体を振り返る。ログイン画面ごとに`getParameter`で個別に値を取り出す処理、JSPのスクリプトレットにJavaコードとHTMLが混在してしまう可読性の低さ、ページが増えるたびに同じセッションチェックのコードをコピー&ペーストのように書き足していく非効率さ、そして入力チェック(バリデーション)や画面遷移の制御を全て自前で記述しなければならない負担の大きさを、受講者自身の実装経験に基づいて具体的に洗い出す。これらは全て、共通処理をどこか1か所にまとめて管理する仕組みが存在しないことに起因する課題であることに気づかせる。「もっと楽に、もっと安全に実装する方法があるはずだ」という素朴な疑問こそが、次回コマ7から始まるフェーズ2・Spring Boot導入への最も重要な動機付けとなることを明確に伝える。
続けて【コラム】として、ここまで作成してきたServletアプリケーションのデプロイについて、デモンストレーション中心に簡単に紹介する。IntelliJ IDEA UltimateにはプロジェクトをWARファイル(Web Application Archive)として書き出す機能が用意されており、実際にWARファイルを生成する操作を演示する。生成したWARファイルは、TomcatやTomEEといったアプリケーションサーバーの`webapps`フォルダに配置するだけで、サーバー起動時に自動的にデプロイ(展開・公開)されるという概念を紹介する。ただし、実際の業務現場ではCI/CDパイプラインやコンテナ化など、さらに複雑な手順を経てデプロイが行われることが一般的であることにも一言触れ、今回はあくまで概念とデモの紹介にとどめる。この細目で理解すべき範囲は、フェーズ1で体験したServlet/JSP開発の課題を整理し次のフレームワーク学習への動機として言語化できること、およびWARファイルによるServletアプリケーションのデプロイの概念まで。

キーワード ① HttpSession ② セッションスコープ ③ 認証Servlet ④ WARファイル ⑤ フレームワークの必要性
コマの展開方法 社会人講師 AL ICT PowerPoint・Keynote 教科書
コマ用オリジナル配布資料 コマ用プリント配布資料 その他 該当なし
小テスト 授業時間内に、LMS上において該当コマの小テストを実施する。
復習・予習課題 ◆今回授業の復習
今回の授業で完成させたログイン機能のコード全体を見直し、HttpSessionを用いた認証情報の格納とアクセス制御の流れを、自分の言葉で説明できるようにしておくこと。また、授業内で振り返ったフェーズ1全体の「手間」(スクリプトレットの可読性の低さ、セッションチェックの重複、入力チェックの自前実装など)を箇条書きでノートにまとめ、それぞれがなぜ課題なのかを整理しておくこと。あわせて、WARファイルによるデプロイの概念についても簡単に復習しておくこと。

◆次回授業の予習
次回の授業からはフェーズ2に入り、フェーズ1で体験した課題をSpring Bootがどのように解決するのかを学ぶ。そのため、今回整理した「Servlet/JSP開発の手間」のリストを手元に用意しておき、次回の授業でそれぞれの課題がどのように解決されるのかを照らし合わせながら聞けるようにしておくこと。また、「Spring Boot」というキーワードで簡単に検索し、どのようなフレームワークなのか概要を把握しておくこと。

7 Spring Bootが解決する課題とフレームワークの価値 科目の中での位置付け 本コマは全45回の中で、フェーズ1「システムアーキテクチャ史とServlet/JSP課題発見型演習」(第1〜6回)を終え、フェーズ2「Spring Boot導入とMVC基礎」(第7〜14回)の初回に位置する。フェーズ1ではServlet/JSPによるログイン機能の手作業実装を通じ、設定や配線の煩雑さを体験した。本コマでは、その体験を出発点として「なぜ現代のWeb開発にフレームワークが必要とされるのか」という問いに答え、Spring FrameworkおよびSpring Bootの基本思想を学ぶ。さらに、次回コマ8以降で育てていく統合プロジェクト「お問い合わせ管理システム」の器を、Spring Initializrを用いて生成する回でもあり、フェーズ2〜4の出発点として重要な位置を占める。
コマ主題細目 ① フェーズ1の振り返りとServlet/JSP開発の課題整理 ② Spring FrameworkとSpring Bootの概要 ③ Spring Bootの主要な特徴とSpring Initializrによるプロジェクト作成
細目レベル ① 本細目では、フェーズ1(第1〜6回)で体験したServlet/JSPによるWebアプリケーション開発を振り返り、そこで直面した具体的な課題を整理することで、Spring Bootを学ぶ動機づけを行う。まず、フェーズ1の課題発見型演習において、ログイン機能を実装する過程で何を経験したかを学生自身に言語化させる。具体的には、web.xmlへのServletマッピング記述、HttpServletクラスを継承したクラスの作成、doGetおよびdoPostメソッドのオーバーライド、HttpServletRequestとHttpServletResponseの手動操作、JSPへのフォワード処理とリクエストスコープを用いたデータ受け渡しなど、1つの機能を実現するために多数の定型的な記述(ボイラープレート)が必要であった点を洗い出す。

次に、これらの課題を「設定の煩雑さ」「配線(構成)の手間」「サーバー環境への依存」という3つの観点に整理する。設定の煩雑さとは、XMLファイルへの手作業でのマッピング記述や、サーブレットコンテナの設定に多くの時間を要する点を指す。配線の手間とは、URLとクラスの対応づけ、リクエストパラメータの取得、画面遷移の指定などを、すべて開発者がコードとして明示的に書き下さなければならない点である。サーバー環境への依存とは、開発を始めるためにTomcatなどのアプリケーションサーバーを別途インストールし、IDEと連携させる設定が必要であった点である。これらを黒板やスライドで一覧化し、「同じような記述を毎回繰り返している」という感覚を学生と共有する。

最後に、この課題整理を踏まえ、「もし、これらの定型的な作業をフレームワークが肩代わりしてくれたら、開発者は何に集中できるようになるか」という問いを投げかけ、次の細目であるSpring FrameworkおよびSpring Bootの学習へと接続する。この細目で理解すべき範囲は、フェーズ1で体験したServlet/JSP開発における設定・配線・環境構築の手間を、自分の言葉で3つの観点に整理して説明できるようになるまで。

② 本細目では、Spring FrameworkとSpring Bootという2つの言葉の関係性を整理し、それぞれが解決しようとしている問題領域について解説する。まず、Spring Frameworkとは、Javaによるエンタープライズアプリケーション開発を支援するための、DI(依存性の注入)コンテナを中核とした総合的なフレームワークであることを説明する。Spring Frameworkは、オブジェクト間の結合度を下げるDIコンテナ機能に加え、Web層を担当するSpring MVC、データアクセスを支援するSpring Data、セキュリティを担当するSpring Securityなど、多数のモジュール(プロジェクト)から構成される大きなエコシステムであることを図示しながら説明する。

次に、Spring Bootの位置づけを解説する。Spring Framework自体は非常に高機能である一方、利用する際にはXMLベースの設定ファイルやBean定義を手作業で大量に記述する必要があり、Spring Framework自体もまた「設定が煩雑」という課題を抱えていた時期があったことに触れる。Spring Bootは、このSpring Frameworkの設定作業を大幅に自動化・簡略化するための仕組みであり、Spring Frameworkそのものを置き換えるものではなく、その上に構築された「使いやすくするための層」であることを明確にする。この関係性を、「Spring Frameworkが土台(エンジン)であり、Spring Bootはそのエンジンを簡単に始動できるようにする始動装置である」という比喩を用いて整理する。

最後に、Spring Bootが登場した歴史的経緯にも軽く触れ、Javaのエンタープライズ開発において「設定より規約(Convention over Configuration)」という考え方が重視されるようになった流れの中でSpring Bootが生まれたことを紹介する。これにより、フェーズ1で体験した「手作業による設定・配線」の課題が、Spring Frameworkの機能とSpring Bootの自動化によってどのように解消されるかという見通しを立てさせる。この細目で理解すべき範囲は、Spring FrameworkとSpring Bootの違いと関係性を自分の言葉で説明できるようになるまで。

③ 本細目では、Spring Bootが提供する具体的な特徴を2点解説した上で、実際にSpring Initializrを用いて新規プロジェクトを作成する実習を行う。まず1点目の特徴として「規約優先設定(Convention over Configuration)」を取り上げる。これは、開発者が明示的に設定を行わなくても、フレームワーク側があらかじめ定めた標準的な規約に従っていれば、多くの設定が自動的に行われる考え方である。例えば、application.propertiesという名前のファイルを所定のディレクトリに配置するだけで各種設定が反映される仕組みなどを例に挙げ、フェーズ1のweb.xmlのような明示的な設定記述が大幅に不要になることを説明する。2点目の特徴として「組み込みサーバー(Embedded Server)」を取り上げる。Spring Bootで作成したアプリケーションには、Tomcatなどのサーバーがあらかじめ組み込まれており、開発者が別途サーバーをインストール・設定しなくても、アプリケーション自体を実行するだけでWebサーバーが起動することを説明する。

次に、実習としてSpring Initializr(start.spring.io、またはIntelliJ IDEA Ultimateに統合された新規プロジェクト作成画面)を用いて、本科目で今後段階的に育てていく統合プロジェクト「お問い合わせ管理システム」の器となる新規Spring Bootプロジェクトを作成する。プロジェクトの設定項目として、ビルドツールにGradle、言語にJava、パッケージングにJarを選択し、依存関係(Dependencies)として「Spring Web」「Thymeleaf」「Lombok」の3つをあらかじめチェックしておく。このうちLombokについては、実際にアノテーションを使い始めるのはフェーズ3のJPA導入回(コマ23〜24)であり、本コマの時点では依存関係の追加のみを行うことを明示し、なぜ今チェックしておくのかという理由(依存関係の追加とその機能を使い始めるタイミングを分けて負荷を調整する狙い)についても触れる。

最後に、IntelliJ IDEA Ultimateでプロジェクトを開き、生成されたディレクトリ構成(src/main/java、src/main/resources、build.gradleなど)を確認し、フェーズ1で使用したJakarta EEの「Webアプリケーション」プロジェクトのディレクトリ構成と見比べながら、共通点と相違点を整理する。この細目で理解すべき範囲は、規約優先設定と組み込みサーバーというSpring Bootの2つの特徴を説明でき、Spring Initializrを用いてWeb・Thymeleaf・Lombokの依存関係を持つプロジェクトを新規作成できるようになるまで。

キーワード ① Spring Boot ② Spring Framework ③ 規約優先設定 ④ 組み込みサーバー ⑤ Spring Initializr
コマの展開方法 社会人講師 AL ICT PowerPoint・Keynote 教科書
コマ用オリジナル配布資料 コマ用プリント配布資料 その他 該当なし
小テスト 授業時間内に、LMS上において該当コマの小テストを実施する。
復習・予習課題 ◆今回授業の復習
今回の授業で整理した、フェーズ1のServlet/JSP開発における「設定の煩雑さ」「配線の手間」「サーバー環境への依存」という3つの課題を、自分のノートに改めて書き出し、それぞれがSpring Bootのどのような特徴(規約優先設定・組み込みサーバーなど)によって解消されうるのかを対応づけて整理すること。また、授業内で作成したSpring Bootプロジェクトを自分のIntelliJ IDEA環境で再度開き、build.gradleファイルに記載されたSpring Web・Thymeleaf・Lombokの依存関係の記述を確認しておくこと。

◆次回授業の予習
次回の授業では、実際にSpring MVCのControllerクラスを作成し、ブラウザからのリクエストに対して簡単な文字列を返す「HelloController」を実装する。そのため、テキストの該当箇所を読み、@Controllerおよび@RequestMappingという2つのアノテーションがそれぞれ何のために使われるのか、概要を把握しておくこと。あわせて、フェーズ1で作成したHelloServletのdoGetメソッドの実装内容を見直し、URLに対する処理の書き方がServletとSpring MVCとでどのように異なりそうか、自分なりに予想を立てておくこと。

8 HelloController体験 科目の中での位置付け 本コマは全45回の中で、フェーズ2「Spring Boot導入とMVC基礎」(第7〜14回)の2回目に位置する。前回コマ7でSpring Bootプロジェクトの器を作成し、Spring FrameworkとSpring Bootの概念を学んだことを受け、本コマでは実際に最初のControllerクラスを実装し、動作確認まで行う「Spring Bootで初めて手を動かす」体験の回である。次回コマ9からThymeleafを用いた本格的な画面表示に入るため、その前段としてControllerの基本構造とURLマッピングの仕組みを体得しておく必要がある。フェーズ1のHelloServlet実習(コマ4)との対比を強く意識し、同じ「Hello」を返す処理がどれだけ簡潔に書けるかを実感させることを狙いとする回である。
コマ主題細目 ① Spring MVCにおけるControllerの役割と基本アノテーション ② リクエストマッピングの仕組み(@RequestMapping、@GetMapping) ③ HelloControllerの実装と動作確認
細目レベル ① 本細目では、Spring MVCというアーキテクチャの中でControllerクラスが果たす役割と、それをJavaクラスとして実装するために用いる基本アノテーションについて解説する。まず、Spring MVCがMVC(Model-View-Controller)モデルに基づいたWebアプリケーションのアーキテクチャであることを振り返り、リクエストを受け付けて処理を振り分ける役割を担うのがControllerであることを説明する。Spring MVCでは、クライアントからのすべてのリクエストをまずDispatcherServletと呼ばれる中心的な部品が受け取り、リクエストのURLに応じて適切なControllerクラスのメソッドへと処理を振り分ける仕組みになっていることを図示しながら説明する。フェーズ1で学んだServletが1つのURLに1つのServletクラスを対応させていたのに対し、Spring MVCでは1つのDispatcherServletがすべてのリクエストの窓口となり、その先の振り分けをフレームワークが自動的に行う点が大きな違いであることを強調する。

次に、あるJavaクラスをSpring MVCのControllerとして機能させるために必要な「@Controller」アノテーションについて解説する。クラス定義の直前に「@Controller」を付与することで、そのクラスがSpring MVCのコントローラとして認識され、同時にDIコンテナによって管理されるBean(コンポーネント)として自動的に登録されることを説明する。これは、フェーズ1のHttpServletクラスの継承のように「特定の親クラスを継承する」のではなく、「目印となるアノテーションを付与する」というSpring特有のスタイルであり、この違いに触れることでアノテーションベースの開発スタイルへの理解を促す。

最後に、@Controllerが付与されたクラス内に定義するメソッド(ハンドラメソッドと呼ぶ)が、実際にリクエストを処理する単位になることを説明する。1つのControllerクラスの中に複数のハンドラメソッドを定義でき、それぞれのメソッドが異なるURLに対応づけられる構造は、フェーズ1で1つのURLに1つのdoGetメソッドしか対応できなかった構造と比較して、関連する処理をひとつのクラスにまとめやすいという利点があることを説明する。この細目で理解すべき範囲は、Spring MVCにおけるDispatcherServletとControllerの役割分担、および@Controllerアノテーションの意味とハンドラメソッドの考え方を説明できるようになるまで。

② 本細目では、Controllerクラス内のハンドラメソッドと特定のURLとを対応づける仕組みである、リクエストマッピング用アノテーションについて解説する。まず、「@RequestMapping」アノテーションを取り上げる。@RequestMappingは、クラスレベルとメソッドレベルの両方に付与することができ、value属性(省略可能)にURLのパスを文字列で指定することで、そのパスへのリクエストが来たときに該当するメソッドが呼び出されるようになることを説明する。クラスレベルに付与した場合はそのController内の全メソッドに共通するベースパスとして機能し、メソッドレベルに付与した場合は個々のメソッド固有のパスとして機能するという、2段階でのURL設計が可能であることを図解する。

次に、@RequestMappingをさらに簡潔に書くための派生アノテーションとして「@GetMapping」を紹介する。@GetMappingは、HTTPのGETメソッドによるリクエストのみを受け付ける場合に用いる短縮形であり、「@RequestMapping(method = RequestMethod.GET)」と等価であることを説明する。実務ではGETリクエストを扱う場面が非常に多いため、@GetMappingのように用途を限定した短縮アノテーション(他に@PostMapping等も存在することに触れる)を用いることで、コードの意図がより明確になり可読性が向上するという利点を解説する。

最後に、URLパスの設計方針についても軽く触れる。今後育てていく「お問い合わせ管理システム」において、一覧表示には「/inquiries」のようなリソース名を表す複数形のパスを用いるなど、URLがそのアプリケーションの機能を表す名前になるよう設計することの重要性を説明する。これは、フェーズ1でファイル名やサーブレット名がそのままURLになっていた素朴な設計から一歩進み、URL設計そのものを意識的に行う姿勢を養うことを狙いとしている。この細目で理解すべき範囲は、@RequestMappingの基本的な使い方(クラスレベル・メソッドレベル)と、@GetMappingとの関係、および簡単なURL設計の考え方を習得するまで。

③ 本細目では、これまでの解説を踏まえ、実際にHelloControllerというクラスを作成し、ブラウザからアクセスして動作を確認する実習を行う。まず、IntelliJ IDEA上でsrc/main/java配下に新しいJavaクラス「HelloController」を作成し、クラス宣言の直前に「@Controller」アノテーションを付与する。次に、文字列を返すpublicメソッド(例えばhelloという名前のメソッド)を定義し、そのメソッドに「@GetMapping("/hello")」アノテーションを付与する。このメソッドの戻り値の型をString型とし、"Hello, Spring Boot!"のような固定の文字列を返すよう実装する。

ここで重要な注意点として、@ControllerでマッピングされたメソッドがStringを返す場合、その文字列はそのままブラウザに表示される文章ではなく、後述するView(テンプレートファイル)の名前として解釈される仕組みになっていることに触れる。ただし、本コマの段階ではまだThymeleafによるView遷移を扱わないため、@ResponseBodyアノテーションをメソッドに追加することで、戻り値の文字列をそのままレスポンスのボディとしてブラウザに返す設定にする。この@ResponseBodyの意味づけは簡潔に触れるにとどめ、次回以降View名としての解釈を本格的に扱うことを予告する。

最後に、アプリケーションを起動する。Spring Bootプロジェクトのmainメソッドを持つクラス(アプリケーションクラス)を実行すると、組み込みTomcatサーバーが自動的に起動し、コンソールにポート番号(通常は8080)が表示されることを確認する。その後、ブラウザで「http://localhost:8080/hello」にアクセスし、HelloControllerで定義した文字列が画面に表示されることを確認する。この一連の流れを、フェーズ1のHelloServlet実習(web.xmlへのマッピング記述、Tomcatの個別設定、サーバーへのデプロイ作業)と比較し、記述量と手順の少なさを学生自身に実感させる。この細目で理解すべき範囲は、@Controllerと@GetMappingを用いたHelloControllerクラスを自分で実装し、アプリケーションを起動してブラウザから動作確認を行えるようになるまで。

キーワード ① Controller ② @RequestMapping ③ @GetMapping ④ DispatcherServlet ⑤ 組み込みTomcat
コマの展開方法 社会人講師 AL ICT PowerPoint・Keynote 教科書
コマ用オリジナル配布資料 コマ用プリント配布資料 その他 該当なし
小テスト 授業時間内に、LMS上において該当コマの小テストを実施する。
復習・予習課題 ◆今回授業の復習
今回作成したHelloControllerのコードを見直し、@Controller、@GetMapping、@ResponseBodyという3つのアノテーションがそれぞれ何のために付与されているのかを、自分の言葉でノートに説明を書き出すこと。また、@GetMappingに指定したパスの文字列を変更し(例えば"/hello"を"/greeting"になど)、アプリケーションを再起動してブラウザからのアクセス結果がどう変わるかを実際に試し、URLとメソッドの対応関係を体感的に確認しておくこと。

◆次回授業の予習
次回の授業では、テンプレートエンジンThymeleafを用いて、ControllerからHTML画面(View)へ遷移させる仕組みを学習する。そのため、テキストの該当箇所を読み、テンプレートエンジンとは何か、その概要を把握しておくこと。また、本日のHelloControllerで用いた@ResponseBodyを外した場合に、戻り値の文字列がどのように扱われるのかについて、テキストの記述をもとに予想を立てておくこと。あわせて、次回以降作成していくHTMLファイルの配置先となる「src/main/resources/templates」フォルダの場所をIntelliJ IDEAのプロジェクトビューで確認しておくこと。

9 Thymeleafの基礎とView遷移の仕組み 科目の中での位置付け 本コマは全45回の中で、フェーズ2「Spring Boot導入とMVC基礎」(第7〜14回)の3回目に位置し、シラバス上の「9〜11. ControllerとView(Thymeleaf)【3回】」という一連の3回シリーズの1回目に当たる。前回コマ8でControllerによるリクエスト処理とレスポンス返却の基本を体験したことを踏まえ、本コマではControllerが返す文字列を「レスポンス本体」としてではなく「View名」として扱う本来の使い方に立ち返り、テンプレートエンジンThymeleafを用いたHTML画面表示の仕組みを学ぶ。次回コマ10ではModelを用いた動的なデータ受け渡しへ、コマ11ではThymeleaf構文の応用へと発展していくため、本コマはこの3回シリーズの土台を築く重要な回である。
コマ主題細目 ① テンプレートエンジンの必要性とThymeleafの概要 ② ControllerからViewへの画面遷移の基本構造 ③ 簡単な静的画面をThymeleafで表示する実習
細目レベル ① 本細目では、なぜWebアプリケーション開発においてテンプレートエンジンが必要とされるのかを説明した上で、本科目で採用するThymeleafというテンプレートエンジンの特徴を解説する。まず、フェーズ1のJSP(JavaServer Pages)を振り返る。JSPは、HTMLファイルの中にJavaのコード(スクリプトレット、式など)を直接埋め込むことで動的な画面を生成する仕組みであったが、HTMLとJavaのロジックが1つのファイルに混在するため、画面のデザインを担当する人とロジックを担当する人の作業が分離しづらいという課題があったことを振り返る。

次に、こうした課題を踏まえ、近年のWeb開発では画面の見た目(View)とサーバー側のロジックとをできる限り分離する設計が重視されるようになった経緯を説明し、その代表的な解決策の1つがテンプレートエンジンであることを示す。テンプレートエンジンとは、あらかじめ用意されたテンプレート(雛形となるHTML等)に対して、サーバー側で用意したデータを差し込むことで最終的なHTMLを生成する仕組みである。Spring Bootでは複数のテンプレートエンジンを利用可能であるが、本科目ではThymeleafを採用することを説明する。

最後に、Thymeleafの大きな特徴として「自然なテンプレート(Natural Templates)」という考え方を紹介する。Thymeleafのテンプレートファイルは、th:から始まる独自の属性(th:text、th:eachなど)を通常のHTML要素の属性として追加する形式で記述されるため、ブラウザで直接ファイルを開いてもある程度崩れずに表示できる、静的なHTMLファイルとしての性質を保ったまま動的な処理を組み込めるという利点を説明する。これは、JSPのようにHTMLの構造そのものにJavaのコードが割り込む書き方とは異なるアプローチであることを対比的に示す。この細目で理解すべき範囲は、テンプレートエンジンが必要とされる背景と、Thymeleafが持つ「自然なテンプレート」という特徴を説明できるようになるまで。

② 本細目では、ControllerがどのようにしてThymeleafのテンプレートファイルへと処理を橋渡ししているのか、その基本構造を解説する。まず、前回コマ8で保留にした「Controllerのハンドラメソッドが返す文字列は、@ResponseBodyが付与されていない場合、View名として解釈される」という仕組みを改めて取り上げる。@Controllerが付与されたクラス内のメソッドがStringを返すと、DispatcherServletはその文字列をView(画面)の論理名とみなし、あらかじめ設定された規約に従って対応するテンプレートファイルを探しに行くことを説明する。

次に、Spring Bootの規約優先設定がここでも働いていることを具体的に示す。Spring Bootでは、View名として返された文字列に対して「src/main/resources/templates/」フォルダの下から、その文字列と同じ名前で拡張子が「.html」のファイルを自動的に探索し、それをThymeleafのテンプレートとして処理する規約になっている。例えば、ハンドラメソッドが"hello"という文字列を返せば、「templates/hello.html」というファイルが表示対象になることを、具体的なディレクトリ構造の図とともに説明する。この規約により、開発者はView名とHTMLファイル名を一致させておくだけでよく、ファイルパスをいちいち明示的に指定する必要がないという利点を強調する。

最後に、この一連の流れ(リクエスト受信→Controllerのハンドラメソッド実行→View名の返却→テンプレートファイルの探索→HTMLのレンダリング→レスポンス返却)を、図式化して整理する。フェーズ1のServlet/JSPにおけるフォワード処理(RequestDispatcherを用いた明示的な遷移先指定)と比較し、Spring MVCではView名という文字列を返すだけで遷移が完結する点が大きな簡略化であることを解説する。この細目で理解すべき範囲は、ControllerがView名を返却してからThymeleafのテンプレートファイルが表示されるまでの一連の処理の流れを、規約優先設定の観点も含めて説明できるようになるまで。

③ 本細目では、これまでの解説を踏まえ、実際に簡単な静的画面をThymeleafのテンプレートファイルとして作成し、Controllerと連携させて表示する実習を行う。まず、src/main/resources/templates配下に「hello.html」という名前のHTMLファイルを新規作成する。HTMLファイルの先頭のhtmlタグに「xmlns:th="http://www.thymeleaf.org"」という名前空間の宣言を追加し、このファイルがThymeleafのテンプレートであることを明示する(この宣言自体はIDEの補完機能や後述の動的処理がなければ必須ではないが、th:属性を用いる際の一般的な慣例として紹介する)。画面の中身としては、見出しタグなどを用いて「お問い合わせ管理システム」という固定の文字列を表示するだけの、まだ動的なデータを含まない簡単な静的画面を作成する。

次に、HelloControllerのハンドラメソッドを修正し、これまで文字列をそのまま返していた@ResponseBodyを取り除き、代わりに作成したテンプレートファイルの名前(拡張子を除いた"hello"という文字列)をView名として返すように書き換える。この修正により、Controllerの役割が「レスポンス本体を直接作る」ものから「表示すべきViewを選択する」ものへと変わったことを、コードの変化を通じて実感させる。

最後に、アプリケーションを起動し、ブラウザで「http://localhost:8080/hello」にアクセスして、先ほど作成したHTMLファイルの内容が画面に表示されることを確認する。あわせて、作成したhello.htmlファイルをブラウザで直接開いた場合にも、崩れることなく同じような見た目で表示できることを確認し、Thymeleafの「自然なテンプレート」という特徴を実際に体験させる。この細目で理解すべき範囲は、Thymeleafのテンプレートファイルを新規作成し、Controllerと組み合わせて簡単な静的画面をブラウザに表示できるようになるまで。

キーワード ① Thymeleaf ② テンプレートエンジン ③ View名 ④ 自然なテンプレート ⑤ templatesフォルダ
コマの展開方法 社会人講師 AL ICT PowerPoint・Keynote 教科書
コマ用オリジナル配布資料 コマ用プリント配布資料 その他 該当なし
小テスト 授業時間内に、LMS上において該当コマの小テストを実施する。
復習・予習課題 ◆今回授業の復習
今回作成したhello.htmlとHelloControllerのコードを見直し、Controllerが返す文字列がView名として解釈され、「templates」フォルダ内の同名のHTMLファイルが探索される、という一連の流れを図に描いて説明できるようにしておくこと。また、View名の文字列やHTMLファイル名をわざと一致しない状態に変更し、アプリケーションを起動した際にどのようなエラーが表示されるかを実際に確認しておくこと。

◆次回授業の予習
次回の授業では、Modelオブジェクトを用いてControllerからViewへ動的なデータを受け渡す方法と、その仕組みを使ってお問い合わせのダミーデータ一覧を画面に表示する実装を学習する。そのため、テキストの該当箇所を読み、Modelインターフェースおよびそのaddattributeメソッドの役割について概要を把握しておくこと。また、次回扱う「お問い合わせ(Inquiry)」データの項目(顧客名、メールアドレス、お問い合わせ内容、対応状況、受付日時)を改めて確認し、これらの項目を持つ簡単なJavaクラス(Entity)にどのようなgetter/setterが必要になりそうか、自分なりに考えておくこと。

10 Modelによるデータ受け渡しと一覧表示 科目の中での位置付け 本コマは全45回の中で、フェーズ2の4回目、「9〜11. ControllerとView(Thymeleaf)【3回】」シリーズの2回目に位置する。前回コマ9で静的なHTML画面をThymeleafで表示する基本構造を学んだことを受け、本コマではControllerからViewへ動的なデータを渡すModelオブジェクトを導入し、中核データであるお問い合わせ(Inquiry)のダミーデータをリスト化して一覧表示する実装を行う。ここで作成するInquiryクラスとgetter/setterは、フェーズ3のJPA導入時にLombokへ置き換える前提のため、あえて手書きで用意し、次回コマ11のThymeleaf構文応用につながる土台を築く回である。
コマ主題細目 ① Modelオブジェクトによるデータ受け渡しの仕組み ② お問い合わせEntityとダミーデータの用意 ③ お問い合わせ一覧をThymeleafで表示する実装
細目レベル ① 本細目では、ControllerからViewへ動的なデータを受け渡すための仕組みであるModelオブジェクトについて解説する。まず、前回コマ9で扱った静的画面には、あらかじめ決められた固定の文字列しか表示できないという限界があったことを振り返り、実際のWebアプリケーションでは、データベースや変数に格納された動的なデータを画面に表示する必要があることを説明する。

次に、この動的なデータの受け渡しを担うSpring MVCのModelインターフェースを紹介する。ハンドラメソッドの引数に「Model model」と宣言するだけで、Spring MVCが自動的にModelオブジェクトを生成してメソッドに渡してくれる仕組み(これもDIの一種として簡単に触れる)になっていることを説明する。そして、Modelオブジェクトが持つ「addAttribute」メソッドを用いて、第1引数にView側で参照する際の名前(属性名)を文字列で指定し、第2引数にその名前に対応させたい実際のデータ(オブジェクトやリストなど)を渡すことで、Controller側のデータをView側に受け渡せることを解説する。

最後に、このaddAttributeで登録したデータが、Thymeleafのテンプレート内でどのように参照されるのかという概要(詳細な構文は次の細目・次回コマで扱うことを予告した上で)に軽く触れる。フェーズ1のJSPにおけるrequest.setAttributeによるリクエストスコープへのデータ格納と対比させ、似たような「名前をつけてデータを渡す」という発想がSpring MVCのModelにも受け継がれていることを説明し、既習の知識と新しい仕組みとを結びつける。この細目で理解すべき範囲は、Modelインターフェースの役割と、addAttributeメソッドを用いてControllerからViewへデータを渡す基本的な書き方を説明できるようになるまで。

② 本細目では、本科目で今後育てていく統合プロジェクトの中核データとなる「お問い合わせ(Inquiry)」を表すJavaクラス(Entity)を作成し、あわせて画面表示用のダミーデータを用意する実習を行う。まず、Inquiryクラスに持たせるフィールドを確認する。顧客名(customerName)、メールアドレス(email)、お問い合わせ内容(content)、対応状況(status。未対応・対応中・対応済みの3種類を表す文字列)、受付日時(receivedAt)の5つのフィールドを、それぞれ適切な型(文字列型や日時型)で宣言する。

次に、これらのフィールドに対するgetterおよびsetterメソッドを実装する。本コマの時点ではLombokのアノテーションはまだ使用せず、IntelliJ IDEAのコード生成機能(Generateメニューからgetter/setterを自動生成する機能)を用いるか、あるいは手書きで1つずつ記述する。この段階であえて全フィールド分のgetter/setterを自分の手で生成させることで、フィールド数が増えるとボイラープレートの量も比例して増えていくという感覚を体験させ、フェーズ3でLombokを導入した際にその簡潔さのありがたみを実感できるようにする教育的な意図があることを説明する。

最後に、作成したInquiryクラスを用いて、画面表示確認用のダミーデータを複数件(3〜5件程度)作成する。Controllerクラス内のハンドラメソッドの中で、Inquiryのインスタンスをnewし、setterメソッドを用いて顧客名やメールアドレスなどの値を設定したものを複数用意し、それらをJavaのList<Inquiry>としてまとめる処理を実装する。まだデータベースへの接続は行わないため、このリストはメソッド内のローカル変数として、あるいは処理の起点となる場所に一時的に用意するに留めることを明示する。この細目で理解すべき範囲は、Inquiryクラスの5つのフィールドとgetter/setterを自分で実装でき、確認用のダミーデータをList<Inquiry>として用意できるようになるまで。

③ 本細目では、これまでに用意したお問い合わせのダミーデータをModelに乗せてViewへ渡し、一覧画面として表示する実習を行う。まず、Controllerクラスに一覧表示用のハンドラメソッドを追加し、「@GetMapping("/inquiries")」のようなパスを割り当てる。メソッドの引数にはModelを受け取るようにし、メソッド内で前細目にて用意したList<Inquiry>を生成した後、model.addAttribute("inquiryList", 生成したリスト)のように、任意の属性名(ここでは"inquiryList"とする)を付けてModelに登録する処理を実装する。

次に、View側となるHTMLテンプレートファイル(例えば「inquiry_list.html」)を新規作成し、Controllerから返すView名と一致させる。このHTMLファイル内で、Modelに登録した"inquiryList"というリストの中身を1件ずつ画面上に表示するための構文が必要になるが、本コマではその詳細な構文(th:eachによる繰り返し)は次回コマ11で本格的に扱うことを踏まえ、ごく簡単な形(例えば1件目のデータをth:textで仮に表示してみる、あるいは繰り返し構文の最小限の書き方だけを提示する)にとどめ、「一覧として複数件をどう表示するか」という課題意識を残した状態で授業を終える構成とする。

最後に、アプリケーションを起動し、ブラウザで「/inquiries」にアクセスして、Controllerで用意したダミーデータの内容(少なくとも1件分)が画面に表示されることを確認する。これにより、Modelを介してControllerのデータがViewに届いていることを実際の画面で確認し、次回のThymeleaf構文応用への橋渡しとする。この細目で理解すべき範囲は、Model経由でお問い合わせのダミーデータのリストをViewへ渡し、簡易的な形で画面に表示させる一連の実装ができるようになるまで。

キーワード ① Model ② addAttribute ③ Inquiry ④ getter/setter ⑤ ダミーデータ
コマの展開方法 社会人講師 AL ICT PowerPoint・Keynote 教科書
コマ用オリジナル配布資料 コマ用プリント配布資料 その他 該当なし
小テスト 授業時間内に、LMS上において該当コマの小テストを実施する。
復習・予習課題 ◆今回授業の復習
今回作成したInquiryクラスのフィールドとgetter/setterの実装内容を見直し、自分の手で書いた(またはIDEで自動生成した)コードの行数を数えてみて、フィールドが5つあることでどれだけのコード量になったかを実感として記録しておくこと。また、Controllerのハンドラメソッド内でModelにダミーデータのリストを登録する処理(addAttributeの部分)を、なぜその名前(属性名)にしたのか、Viewからどのように参照されることを意図しているのかを自分の言葉で説明できるようにしておくこと。

◆次回授業の予習
次回の授業では、Thymeleafのth:each属性を用いた繰り返し処理と、th:if属性を用いた条件分岐の書き方を学習し、今回途中までしか実装できなかったお問い合わせ一覧画面を完成させる。そのため、テキストの該当箇所を読み、th:eachがどのようにJavaのList(コレクション)の中身を1件ずつ取り出して繰り返し表示するのか、その基本構文について概要を把握しておくこと。また、対応状況(未対応・対応中・対応済み)に応じて表示を変えるとしたら、どのような場合分けが必要になりそうか、自分なりに考えをまとめておくこと。

11 Thymeleaf構文の応用と一覧画面の完成 科目の中での位置付け 本コマは全45回の中で、フェーズ2「Spring Boot導入とMVC基礎」(第7〜14回)の5回目、「9〜11. ControllerとView(Thymeleaf)【3回】」シリーズの最終回に位置する。前回コマ10でModelを介したダミーデータの受け渡しと簡易的な表示までを実装したことを受け、本コマではThymeleafの繰り返し構文と条件分岐構文を用いて、複数件のお問い合わせデータを一覧として正しく表示し、対応状況に応じた見た目の出し分けまでを実現する。これにより、コマ9〜11の3回シリーズで目指してきた「お問い合わせ一覧画面」が完成し、次回コマ12〜13のフォーム入力機能の実装へとつながる、フェーズ2前半の1つの到達点となる回である。
コマ主題細目 ① Thymeleafの繰り返し構文(th:each) ② Thymeleafの条件分岐構文(th:if)と対応状況に応じた表示の出し分け ③ お問い合わせ一覧画面の完成と動作確認
細目レベル ① 本細目では、Thymeleafが提供する主要な属性のうち、リストや配列の中身を1件ずつ取り出して繰り返し表示するための「th:each」属性について、実装を通じて解説する。まず、前回コマ10で途中までしか実装できなかった一覧画面の課題(複数件のデータを1件ずつ表示する方法が確立していなかった点)を振り返り、その解決策としてth:eachを導入する必然性を確認する。

次に、th:eachの具体的な構文を解説する。HTML要素(多くの場合はテーブルの行を表すtr要素)に「th:each="inquiry : ${inquiryList}"」のように記述することで、Modelに登録した"inquiryList"というリストの要素が1つずつ変数inquiryに代入されながら、その要素の分だけHTML要素が繰り返し生成されることを説明する。この繰り返しの中で、th:text="${inquiry.customerName}"のように、変数名とプロパティ名をドットで連結した式(Thymeleafではこれをオブジェクトナビゲーションと呼ぶ)を用いることで、各Inquiryオブジェクトのgetterメソッド(例えばgetCustomerName)が自動的に呼び出され、その戻り値が画面に表示される仕組みであることを解説する。

最後に、実際にInquiryList一覧画面のHTMLファイルをHTMLのtable要素を用いて構成し直し、テーブルの見出し行(thead)は固定のまま、データ行(tbody内のtr)にth:eachを適用して、顧客名・メールアドレス・お問い合わせ内容・対応状況・受付日時の各列をth:textで表示するよう実装する。この実装により、Controller側で用意したダミーデータの件数がいくつであっても、その件数分の行が自動的に生成されることを確認する。この細目で理解すべき範囲は、th:each属性の構文とオブジェクトナビゲーションの書き方を理解し、リスト内のデータを表形式で繰り返し表示できるようになるまで。

② 本細目では、Thymeleafが提供するもう1つの主要な属性である「th:if」を用いた条件分岐の書き方と、それを応用してお問い合わせの対応状況(未対応・対応中・対応済み)に応じて画面上の表示を出し分ける実装について解説する。まず、th:ifの基本構文を説明する。HTML要素にth:if="条件式"と記述すると、その条件式がtrueと評価された場合にのみそのHTML要素が画面に出力され、falseの場合はその要素自体が丸ごと出力されないという仕組みであることを解説する。あわせて、条件がtrueのときではなくfalseのときに表示したい場合に用いる「th:unless」についても簡単に紹介する。

次に、この条件分岐を対応状況の出し分けに応用する実装を行う。テーブルの対応状況列において、inquiry.statusの値が"未対応"である場合には赤系の警告色、"対応中"である場合には黄系の色、"対応済み"である場合には緑系の色でバッジ状に表示するといった演出を、th:ifを複数並べる形(同じ場所に対して条件が異なる複数のspan要素を用意し、それぞれth:ifで表示条件を分ける)で実装する。この際、Bootstrap 5のbadgeコンポーネント(bg-danger、bg-warning、bg-successなどのクラス)と組み合わせることで、CSSを自分で細かく書かなくても視覚的にわかりやすい一覧画面を作れることに触れ、本科目における画面デザインの方針(Bootstrapの標準コンポーネントを活用する)を実践する。

最後に、th:eachによる繰り返しとth:ifによる条件分岐という2つの構文が、Thymeleafのテンプレート内で組み合わせて使えることを確認する。1つのtr要素に対してth:eachで繰り返しを設定しつつ、その内側の子要素に対してth:ifで条件分岐を設定するという入れ子構造が可能であることを、実際のコードを示しながら解説する。この細目で理解すべき範囲は、th:if(およびth:unless)の構文を理解し、対応状況の値に応じて表示内容や見た目を変える出し分け処理を、th:eachとの組み合わせで実装できるようになるまで。

③ 本細目では、これまでの実装を統合し、お問い合わせ一覧画面を完成させた上で、複数のダミーデータを用いた動作確認を行う。まず、コマ10で用意した3〜5件程度のダミーデータについて、対応状況の値(未対応・対応中・対応済み)がそれぞれ異なるパターンを含むように見直し・追加を行う。これにより、th:ifによる出し分けが実際に機能しているかどうかを、複数のパターンで確認できる状態を整える。

次に、アプリケーションを起動し、ブラウザで「/inquiries」にアクセスして一覧画面を表示する。表示された画面において、ダミーデータの件数分だけテーブルの行が生成されていること、各行に顧客名・メールアドレス・お問い合わせ内容・受付日時が正しく表示されていること、そして対応状況に応じてバッジの色や表示内容が意図した通りに出し分けられていることを、1件ずつ目視で確認する。もし表示が意図通りにならない場合には、th:eachの変数名とth:textの参照名が一致しているか、th:ifの条件式のスペルミスがないかなど、典型的なつまずきポイントを一緒に確認しながらデバッグを行う。

最後に、完成した一覧画面を、フェーズ1で作成したJSPベースの画面や、コマ7〜9で作成してきた簡易的な画面と見比べ、コマ9〜11の3回を通じてどれだけの機能(動的なデータ表示、繰り返し、条件分岐による見た目の出し分け)を、比較的少ない記述量で実現できたかを振り返る。この振り返りを通じて、次回コマ12〜13で扱うフォーム入力機能(データの登録側)への学習意欲につなげる。この細目で理解すべき範囲は、th:eachとth:ifを組み合わせたお問い合わせ一覧画面を最後まで完成させ、複数パターンのデータで正しく動作することを自ら確認できるようになるまで。

キーワード ① th:each ② th:if ③ オブジェクトナビゲーション ④ 対応状況 ⑤ Bootstrap badge
コマの展開方法 社会人講師 AL ICT PowerPoint・Keynote 教科書
コマ用オリジナル配布資料 コマ用プリント配布資料 その他 該当なし
小テスト 授業時間内に、LMS上において該当コマの小テストを実施する。
復習・予習課題 ◆今回授業の復習
今回完成させたお問い合わせ一覧画面のHTMLコードを見直し、th:eachによる繰り返しの範囲(どのHTML要素に付与されているか)と、th:ifによる条件分岐の範囲を、色分けするなどして自分なりに図解しておくこと。また、ダミーデータの対応状況の値を意図的に別の文字列(例えば"未対応"を"未処理"になど)に変更した場合に、バッジの色分けがどのように崩れるかを実際に試し、th:ifの条件式が文字列の完全一致に依存していることを体感的に確認しておくこと。

◆次回授業の予習
次回からの2回(コマ12〜13)では、Thymeleafを用いたフォームの作成と、フォームから送信されたデータをサーバー側で受け取る方法(@RequestParamおよびForm-Backing Bean)について学習し、お問い合わせ登録フォームの画面を作成する。そのため、テキストの該当箇所を読み、th:actionおよびth:objectという2つの属性がフォームの送信先やデータの紐づけにおいてどのような役割を果たすのか、概要を把握しておくこと。また、フェーズ1でHTMLフォームからGETおよびPOSTでデータを送信した際の実装(コマ4)を振り返り、Servletではリクエストパラメータをどのように取得していたかを思い出しておくこと。

12 フォーム作成とリクエストパラメータの個別受信 科目の中での位置付け 本コマは、コマ9〜11で完成させたお問い合わせ一覧のダミーデータ表示画面を土台に、ユーザーからの入力をサーバー側で受け取る仕組みへと学習を進める最初の回である。フェーズ1のServlet/JSPで経験したGET/POST送信とrequest.getParameterによる取得を振り返りつつ、Thymeleafを用いたフォーム部品の記述方法と、Spring MVCが提供する@RequestParamによる個別パラメータ受信を対比しながら学ぶ。あくまで個々のパラメータを一つずつ受け取る素朴な方法にとどめ、次回のForm-Backing Beanによる一括受信への橋渡しとする位置付けである。
コマ主題細目 ① Thymeleafによるフォームの作成(th:action, th:object) ② @RequestParamによるリクエストパラメータの個別受信 ③ GETとPOSTの使い分けの再確認
細目レベル ① 本細目では、お問い合わせ登録画面の骨格となるHTMLフォームを、Thymeleafのテンプレート構文を用いて作成する方法を学ぶ。フェーズ1では純粋なHTMLの<form>タグにactionとmethod属性を静的に記述していたが、Spring MVCと連携するThymeleafではth:action属性を用いることで、Controller側のURLマッピングと整合したパスを動的に、かつコンテキストパスを意識せずに出力できる点を確認する。具体的には、お問い合わせ登録画面(inquiry-form.html)に対し、th:action="@{/inquiry/register}"のように@記法(リンク式)を用いて送信先URLを指定し、method属性にはpostを指定する。

続いて、th:object属性についても導入する。この段階ではまだForm-Backing Beanは扱わないため深入りはしないが、「th:objectを指定すると、そのフォーム内でth:fieldという記法が使えるようになる」という将来像だけを予告的に示し、今回はth:fieldを使わずに素のname属性でinput要素を用意する方針をとる。これは、次回コマ13でForm-Backing Beanを導入した際に、th:fieldへ書き換えることで記述がどれだけ簡潔になるかを実感させるための布石である。顧客名、メールアドレス、お問い合わせ内容の3項目それぞれについて、input要素・textarea要素にname属性(customerName、email、contentなど)を設定し、送信されるリクエストパラメータの名前を明確にしておく。

あわせて、IntelliJのブラウザプレビュー機能やデベロッパーツールのNetworkタブを用いて、実際にフォームを送信した際にどのようなリクエストボディが生成されるかを確認する演習を行う。フォームのname属性とリクエストパラメータ名が一対一で対応していることを、実際の通信内容から裏付けることで、次の細目で学ぶ@RequestParamによる受信処理の理解を確かなものにする。この細目で理解すべき範囲は、th:actionによる送信先URLの動的生成、th:objectの存在と役割の概略、name属性とリクエストパラメータ名の対応関係の確認まで。

② 本細目では、フォームから送信されたリクエストパラメータをController側で受け取るための最も基本的な方法として、@RequestParamアノテーションの使い方を学ぶ。InquiryControllerに新たなハンドラメソッドを追加し、引数に@RequestParam("customerName") String customerNameのように記述することで、リクエストパラメータの値がメソッド引数へ自動的にバインドされる仕組みを確認する。フェーズ1のServletでrequest.getParameter("customerName")と記述し、戻り値がString型であることや、パラメータが存在しない場合の挙動を都度自分でコーディングしていたことと比較し、Spring MVCが型変換や存在チェックの一部を肩代わりしてくれる点の生産性の高さを実感させる。

さらに、@RequestParamの属性であるrequiredとdefaultValueについても解説する。requiredをfalseに設定した場合や、defaultValueで既定値を与えた場合に、パラメータが未送信であってもMissingServletRequestParameterExceptionが発生せず処理が継続する挙動を、実際にパラメータを外したリクエストを送って確認する。これにより、@RequestParamが単なる値の取得だけでなく、入力の有無に応じた振る舞いの制御手段でもあることを理解させる。加えて、複数のパラメータを個別の引数として並べて受け取る場合、メソッドのシグネチャが項目数に比例して肥大化していく問題点にも触れ、次回のForm-Backing Bean導入の必然性を予告する。

受け取ったパラメータについては、この段階ではまだEntityへの変換やDB保存は行わず、Modelにそのまま格納してconfirm.html等の確認的な画面に表示するにとどめる。これは、コマ13で本格的な登録フォームを完成させる前段階として、あくまで「サーバーが値を受け取れていること」を可視化する目的の実装であり、永続化はフェーズ3のコマ21〜22(DB接続)以降に持ち越されることを明確に伝える。この細目で理解すべき範囲は、@RequestParamによるパラメータ受信の基本記法、required/defaultValue属性の役割、および複数パラメータ受信の限界の把握まで。

③ 本細目では、フェーズ1で学んだGETメソッドとPOSTメソッドの違いを、フォーム送信という具体的な文脈の中で再確認し、実務上の使い分けの判断基準を整理する。GETはURLのクエリ文字列にパラメータが付与されるため、ブラウザの履歴やブックマークに残せる、サーバー側の状態を変更しない「安全(safe)」な操作に向いているという特性を、検索フォームやフィルタ条件の指定といった具体例とともに解説する。一方POSTはリクエストボディにパラメータが格納されるため、URLに情報が露出せず、長文のテキストやサーバー側の状態変更を伴う操作(登録・更新・削除)に適していることを、お問い合わせ登録という本演習のユースケースに即して説明する。

お問い合わせ登録フォームがPOSTを採用すべき理由についても、単に「習慣だから」ではなく、お問い合わせ内容という長文データを扱う点、そして最終的にはDBへの新規登録という状態変更を伴う点の2つの観点から論理的に説明できるようにする。あわせて、GETリクエストをブラウザで再読み込みした場合には単に同じ内容が再表示されるだけで安全だが、POSTリクエストの結果画面をそのまま再読み込みすると、ブラウザから「フォームの再送信」の警告が表示され、意図せず二重登録が発生しうるという問題点にも言及する。この二重送信問題は、次回コマ13で学ぶPRG(Post-Redirect-Get)パターンの必要性に直結する重要な伏線である。

最後に、これまで作成してきたお問い合わせ一覧画面(GET)と、今回作成する登録フォーム(POST)を並べて眺め、それぞれのURLマッピングに付与されている@GetMappingと@PostMappingというアノテーションの違いを再確認する。同一のURLパスに対してHTTPメソッドの違いにより異なるハンドラメソッドを対応させられるSpring MVCの設計を理解することで、次回以降のController設計における見通しを良くする。この細目で理解すべき範囲は、GET/POSTそれぞれの特性と適用場面の判断基準、POSTにおける二重送信問題の所在、および@GetMapping/@PostMappingの使い分けまで。

キーワード ① th:action ② @RequestParam ③ リクエストパラメータ ④ GET/POST ⑤ 二重送信問題
コマの展開方法 社会人講師 AL ICT PowerPoint・Keynote 教科書
コマ用オリジナル配布資料 コマ用プリント配布資料 その他 該当なし
小テスト 授業時間内に、LMS上において該当コマの小テストを実施する。
復習・予習課題 ◆今回授業の復習
今回の授業で作成したお問い合わせ登録フォームについて、HTML側のinput要素のname属性と、Controller側の@RequestParamで指定した引数名が正しく対応しているかを、ブラウザの開発者ツール(Networkタブ)で送信内容を確認しながら再点検してください。また、@RequestParamのrequired属性をtrue・falseそれぞれに設定した場合の挙動の違いを、実際にパラメータを外したリクエストを送って自分の手で確認し、どのような場面でどちらを使うべきかをノートに整理してください。あわせて、POSTリクエストの結果画面を再読み込みした際にブラウザがどのような警告を表示するかを実際に確認しておいてください。

◆次回授業の予習
次回の授業では、今回個別に受け取ったリクエストパラメータを、1つのクラス(Form-Backing Bean)でまとめて受け取る方法を学びます。教科書やこれまでの授業で扱ったEntityクラスの構造を見直し、フィールドが増えるとメソッド引数がどれだけ煩雑になるかを想像しておいてください。また、「PRG(Post-Redirect-Get)パターン」という言葉を調べ、なぜPOST処理の直後にリダイレクトを挟む必要があるのか、二重送信という観点から自分なりに仮説を立てておいてください。

13 Form-Backing Beanとお問い合わせ登録フォームの完成 科目の中での位置付け 本コマは、前回コマ12で個別に受信していたリクエストパラメータを、Form-Backing Beanという1つのクラスにまとめて受信する方法へと発展させ、お問い合わせ登録フォームを機能面で完成させる回である。あわせて、POST処理特有の二重送信問題を解決するPRG(Post-Redirect-Get)パターンを導入し、フォーム処理の定石を身につける。ただしこの段階ではDB保存はまだ実装せず、入力内容を確認画面に表示するにとどめ、実際の永続化はフェーズ3のコマ21〜22以降に委ねる位置付けである。
コマ主題細目 ① Form-Backing Beanによるデータの一括受信 ② PRG(Post-Redirect-Get)パターンの重要性 ③ お問い合わせ登録フォームの完成(表示確認まで)
細目レベル ① 本細目では、前回学んだ@RequestParamによる個別受信の限界を踏まえ、フォームの入力項目をまとめて1つのオブジェクトとして受け取るForm-Backing Beanの仕組みを学ぶ。まず、お問い合わせ登録専用のクラスとしてInquiryFormを新規に作成し、customerName、email、contentといったフィールドと、それに対応する手書きのgetter/setterを用意する。この段階ではLombokはまだ導入していないため、IDE(IntelliJ)のコード生成機能を用いてgetter/setterを自動生成し、地道な記述の積み重ねの上にフレームワークの恩恵が成り立っていることを実感させる。

次に、Controllerのハンドラメソッドの引数を、これまでの複数の@RequestParam引数から、InquiryFormを直接受け取る形(例:public String register(InquiryForm form))へと書き換える。Spring MVCのデータバインディング機構により、リクエストパラメータ名とForm-Backing Beanのプロパティ名(setterメソッド名から導出される名前)が一致していれば、フレームワークが自動的に値を各フィールドへ設定してくれる仕組みを、実際にデバッガでフィールドの値を確認しながら検証する。これにより、引数の数が項目数に比例して増えていく問題が解消され、Controllerのシグネチャが常に安定した形に保たれることを理解させる。

あわせて、HTML側のth:objectとth:fieldへの書き換えも行う。前回name属性で個別に指定していたinput要素を、th:object="${inquiryForm}"とth:field="*{customerName}"のような記法に置き換えることで、id属性・name属性・value属性がThymeleafによって自動的に補完される様子を確認し、記述量の削減とタイプミスの防止という2つの利点を体感させる。この細目で理解すべき範囲は、Form-Backing Beanクラスの設計と手書きgetter/setterの用意、Controller引数へのバインディングの仕組み、およびth:object/th:fieldによるHTML側の記法の書き換えまで。

② 本細目では、POSTメソッドによるデータ送信処理の直後に発生しうる「フォームの二重送信問題」を実際に体験し、その解決策としてPRG(Post-Redirect-Get)パターンを導入する。まず、登録処理を実装したハンドラメソッドがreturn "confirm"のようにビュー名を直接返す実装を試作し、その確認画面をブラウザでF5キーにより再読み込みした際に「フォームを再送信しますか」という警告が表示され、再送信を許可すると同じ内容の処理が再実行されてしまう挙動を実際に確認する。この体験を通じて、POST直後にHTMLを直接返すことの危険性を、学生自身の手を動かして実感させる。

続いて、この問題を解決する定石としてPRGパターンの考え方を解説する。POSTリクエストを処理した後、直接ビューを返すのではなく、return "redirect:/inquiry/confirm"のようにredirect:プレフィックスを用いてクライアントに対しリダイレクト指示(HTTPステータス302とLocationヘッダ)を返す。ブラウザはこの指示を受けて自動的にGETリクエストを新たに発行するため、最終的にブラウザの履歴に残るのはGETリクエストとなり、再読み込みしてもPOST処理が再実行されることはない。この一連の流れ(POST受信→処理→リダイレクト→GET受信→画面表示)を図に整理し、なぜ「Post-Redirect-Get」という名前が付けられているのかを名称と処理の対応関係から理解させる。

さらに、リダイレクト先のGETリクエストへ確認したいデータをどう引き継ぐかという課題にも触れる。この段階ではRedirectAttributesの詳細な実装には深入りしないが、「リダイレクトを挟むとリクエストスコープの情報は失われるため、画面間でデータを引き継ぐ工夫が別途必要になる」という課題意識だけを提示し、当面は簡易的にセッションスコープやModel経由での一時的な受け渡しで代替する方針をとる。この細目で理解すべき範囲は、二重送信問題が発生する具体的な条件、redirect:プレフィックスによるリダイレクト実装の方法、およびPRGパターンがなぜ有効なのかという原理の理解まで。

③ 本細目では、これまでの学習内容を総合し、お問い合わせ登録フォームを画面遷移として完成させる実習を行う。具体的には、①一覧画面から登録フォーム画面(inquiry-form.html)へ遷移するリンクの設置、②Form-Backing Beanによるフォーム入力とth:field記法での項目表示、③POSTでの送信を受けたControllerでのバインディング確認、④PRGパターンに則ったリダイレクト処理、⑤リダイレクト先での入力内容確認画面の表示、という一連の流れを実装し、実際にブラウザ上で動作させて確認する。この時点ではデータベースへの保存処理は一切実装せず、あくまで画面表示とデータの受け渡しが正しく機能しているかを確認する範囲にとどめることを、あらためて明確に伝える。

実装にあたっては、確認画面側でInquiryFormの各プロパティをth:text="${inquiryForm.customerName}"のように出力し、入力した内容が正しくサーバーを経由して画面に反映されていることを目視で確認させる。あわせて、対応状況(未対応/対応中/対応済み)については、この段階では新規登録時に自動的に「未対応」を初期値として設定する程度の簡易な扱いにとどめ、ステータス変更のような複雑な業務ロジックには踏み込まない。受付日時についても、java.time.LocalDateTime.now()のような形でControllerまたはFormの初期化時に現在日時を仮設定するにとどめ、厳密な日時管理の議論は行わない。

最後に、コマ9〜11で完成させた一覧表示画面と、今回完成させた登録フォームの確認画面とを見比べ、両者が同じInquiryという題材を異なる切り口(一覧表示と個別入力)で扱っていることを整理する。この整理は、次回コマ14で複数の画面情報をModelでまとめて扱う際の土台となる。この細目で理解すべき範囲は、登録フォームから確認画面までの一連の画面遷移の実装、対応状況・受付日時の仮設定、およびDB保存を伴わない範囲でのデータ受け渡し確認まで。

キーワード ① Form-Backing Bean ② th:field ③ PRG パターン ④ redirect プレフィックス ⑤ 二重送信防止
コマの展開方法 社会人講師 AL ICT PowerPoint・Keynote 教科書
コマ用オリジナル配布資料 コマ用プリント配布資料 その他 該当なし
小テスト 授業時間内に、LMS上において該当コマの小テストを実施する。
復習・予習課題 ◆今回授業の復習
今回実装したお問い合わせ登録フォームについて、フォーム画面から確認画面までのデータの流れ(画面表示→入力→送信→バインディング→リダイレクト→確認画面表示)を、ノートに図解して整理してください。特に、Controller、Form-Backing Bean、Viewの各コンポーネントがどの順番で関わり、データがどのように変換・受け渡しされていくかを明確に記述してください。また、PRGパターンを使わなかった場合にどのようなトラブルが起きるかを、実際にブラウザで再現した二重送信の様子を思い出しながら、自分の言葉で説明できるようにまとめてください。

◆次回授業の予習
次回の授業では、一覧画面や登録フォームで個別に扱ってきた複数のデータ(お問い合わせ件数、対応状況によるフィルタ条件など)を、Modelオブジェクトでまとめて渡す整理を行い、あわせてController全体のリファクタリングに取り組みます。これまで作成してきたInquiryControllerのコードを見返し、1つのメソッドが担っている処理(データ取得・加工・Model格納・ビュー名決定)がどれだけ多岐にわたっているかを確認し、「責務を分ける」とはどういうことかを自分なりに考えておいてください。

14 Modelオブジェクト利用とControllerのリファクタリング 科目の中での位置付け 本コマはフェーズ2(コマ7〜14)の最終回であり、これまで個別に実装してきたお問い合わせ一覧・登録フォームの機能を見直し、複数のデータをModelでまとめて渡す整理と、Controllerの責務を整理するリファクタリングを行う。あわせてフェーズ2全体を振り返り、Spring Bootの基本的なMVC開発パターンが一通り身についたことを確認したうえで、次のフェーズ3で扱うDIとJavaConfigへの橋渡しを行う位置付けである。
コマ主題細目 ① 複数データをModelでまとめて渡す整理 ② Controllerのリファクタリング(責務の整理) ③ フェーズ2の振り返りとフェーズ3への橋渡し
細目レベル ① 本細目では、これまで一覧画面に渡していたお問い合わせのリスト情報に加え、件数や対応状況によるフィルタ条件といった付随的なデータを、Modelオブジェクトを通じてまとめてビューに渡す整理を行う。まず、一覧表示のハンドラメソッドにおいて、model.addAttribute("inquiryList", list)に加え、model.addAttribute("totalCount", list.size())のように件数情報を追加し、Thymeleaf側でth:textを用いて「全○件」といった表示を実現する。さらに、対応状況(未対応/対応中/対応済み)ごとにフィルタ表示を行うための選択肢一覧(例えばenumやListとして用意したステータス候補)もあわせてModelに格納し、フィルタ用のプルダウンやタブをビュー側で構築できるようにする。

この実装を通じて、Modelが単に「1つの一覧データを渡す入れ物」ではなく、「1つの画面表示に必要なあらゆる付随情報を集約する場所」であるという理解を深める。複数のaddAttribute呼び出しが1つのハンドラメソッド内に並ぶようになると、どのキーでどのデータを渡しているかが読み取りにくくなるという課題にも触れ、必要に応じてキー名を定数化する、あるいは複数の関連データをまとめる小さな表示用クラス(ViewModel的な発想)を用意するという設計上の選択肢があることを紹介する。ただし本科目ではこの段階での過度な抽象化は避け、あくまでModelへの複数addAttributeという基本形の徹底を優先する。

また、対応状況によるフィルタ条件自体をどのようにControllerが受け取るかについても触れる。一覧画面のURLに対しクエリパラメータ(例:/inquiry/list?status=未対応)でフィルタ条件を渡す設計とし、@RequestParamで受け取った条件をもとにリストを絞り込んでModelへ格納する、という一連の流れをコマ12で学んだ@RequestParamの知識と結びつけて再確認する。この細目で理解すべき範囲は、Modelへの複数データの格納方法、件数やフィルタ選択肢といった付随情報の渡し方、および@RequestParamと組み合わせたフィルタ条件の受け渡しまで。

② 本細目では、これまで機能追加のたびに肥大化してきたInquiryControllerのコードを見直し、責務を整理するリファクタリングに取り組む。まず、現状のControllerクラスを実際に読み返し、1つのハンドラメソッドの中に「リストの取得」「フィルタ条件による絞り込み」「件数の計算」「Modelへの格納」「ビュー名の決定」といった複数の異なる関心事が混在している状態を確認する。この状態は動作こそ問題なくとも、機能が増えるたびにメソッドが際限なく長くなり、可読性や保守性が低下していくことを、実際のコード行数の推移を振り返りながら実感させる。

次に、リファクタリングの第一歩として、フィルタ条件による絞り込みロジックのような「業務上の判断」を担う処理を、Controllerのメソッドから独立した小さなプライベートメソッドや、単純なヘルパーメソッドへ切り出す作業を行う。この段階ではまだ@ServiceアノテーションによるService層の分離(コマ15〜16で学ぶDIの範囲)には踏み込まないが、「Controllerはリクエストの受付とレスポンスの決定に専念し、データの加工ロジックはできる限り別の場所へ追い出す」という設計思想の芽を植え付けることを目的とする。実際に、絞り込み処理をfilterByStatus(List<Inquiry> list, String status)のようなメソッドへ切り出し、ハンドラメソッド自体が短く見通しの良いものに変わる様子を体験させる。

あわせて、Controllerのメソッド名やURLマッピングの命名についても見直しを行う。一覧表示・登録・確認といった各機能に対応するメソッド名やパスが、一貫した命名規則(動詞+対象、あるいはREST的な発想を意識した命名)に沿っているかを点検し、必要であれば統一的な名称に修正する。これにより、コードを読む人が名前だけでその処理内容を推測できるという、保守性の高いコードの基本を再確認する。この細目で理解すべき範囲は、Controllerに複数の関心事が混在する問題点の把握、加工ロジックの切り出しによる整理の実践、およびメソッド名・URLマッピングの命名の見直しまで。

③ 本細目では、フェーズ2(コマ7〜14)全体を振り返り、Spring Bootを用いたMVC開発の基本パターンがどのように積み上がってきたかを整理する。コマ7〜8でSpring Bootの価値とHelloControllerを体験し、コマ9〜11でThymeleafによる一覧表示とダミーデータの繰り返し・条件分岐表示を学び、コマ12〜13でフォーム入力とForm-Backing Bean、PRGパターンを習得し、そして本コマでModelの整理とControllerのリファクタリングに至るという一連の流れを、実際に完成した画面(一覧・登録フォーム・確認画面)を動かしながら再確認する。この振り返りを通じて、「Controller→Model→View」という基本形が、機能が増えても崩れずに繰り返し適用できる型であることを実感させる。

一方で、今回のリファクタリングで見えてきた限界にも言及する。現状のInquiryのデータはControllerのフィールドやアプリケーション内のList等、メモリ上の簡易な形で保持されているに過ぎず、アプリケーションを再起動すればすべて消えてしまう状態である。また、絞り込みロジックをControllerから切り出したとはいえ、依然としてControllerクラス自身が生成・管理しているに過ぎず、他のControllerから同じロジックを再利用することも難しい。こうした課題を明示的に言語化することで、次のフェーズ3で学ぶDI(依存性注入)とService層の分離が、なぜ必要とされるのかという動機づけを与える。

最後に、次回コマ15〜16で扱うDIとJavaConfigの概要を予告する。Controllerが直接データ操作ロジックを抱えるのではなく、@Serviceアノテーションを付与した専用のクラスにその役割を委譲し、SpringのDIコンテナがそれを自動的に注入する仕組みを学ぶことになる、という展望を示す。あわせて、@ConfigurationクラスによるJavaConfigを用いた明示的なBean定義にも触れることを伝え、フェーズ3が「今回体験した肥大化の問題を、フレームワークの力で解決していく」フェーズであることを印象づける。この細目で理解すべき範囲は、フェーズ2で習得したMVC開発パターンの全体像の総括、現状の実装が抱える限界(永続化・再利用性)の言語化、およびフェーズ3で扱うDI・JavaConfigへの見通しまで。

キーワード ① Model集約 ② addAttribute ③ Controllerの責務分離 ④ リファクタリング ⑤ DIへの橋渡し
コマの展開方法 社会人講師 AL ICT PowerPoint・Keynote 教科書
コマ用オリジナル配布資料 コマ用プリント配布資料 その他 該当なし
小テスト 授業時間内に、LMS上において該当コマの小テストを実施する。
復習・予習課題 ◆今回授業の復習
今回リファクタリングしたInquiryControllerのコードを見直し、リファクタリング前後でハンドラメソッドの行数や読みやすさがどう変化したかを比較して、変更点を箇条書きでまとめてください。また、Modelに格納した「一覧データ」「件数」「フィルタ選択肢」がそれぞれビュー側のどの表示要素に対応しているかを、画面のスクリーンショットとコードを突き合わせて確認しておいてください。あわせて、フェーズ2(コマ7〜14)で完成した一覧画面・登録フォーム・確認画面を通しで操作し、Controller・Model・Viewの役割分担を自分の言葉で説明できるように整理してください。

◆次回授業の予習
次回からフェーズ3に入り、DI(依存性注入)とサービス層の基礎を学びます。今回Controllerから切り出したフィルタ処理のようなロジックが、「もし@Serviceという別クラスに移したら、Controllerからどうやってそのクラスを使えばよいのか」という疑問を持ちながら、DI(Dependency Injection)という言葉が何を意味するのか、事前に簡単に調べておいてください。

15 DI(依存性の注入)の概念とコンテナ 科目の中での位置付け 本コマは「15〜16. DIとサービス層の基礎+JavaConfig」の1回目にあたり、フェーズ2で完成させたお問い合わせ一覧・登録フォームの実装を土台に、Controllerクラスが自らインメモリの`List<Inquiry>`を保持し操作するという密結合な設計の問題点を体験的に理解させることを狙いとする。その解決策として、Spring Frameworkの核心思想であるDI(依存性の注入)とDIコンテナの仕組みを学び、`InquiryService`クラスへとデータ管理ロジックを切り出す演習を行う。次コマのJavaConfigの学習へと接続する、フェーズ3全体の出発点となるコマである。
コマ主題細目 ① 密結合なコードの問題点とDI(依存性の注入)の必要性 ② SpringフレームワークにおけるDIコンテナの役割 ③ @AutowiredによるDIの実践とInquiryServiceへの切り出し演習
細目レベル ① 本細目では、これまでControllerクラス内に直接記述してきたお問い合わせデータの管理ロジックが抱える設計上の問題点を明らかにし、その解決策としてDI(Dependency Injection、依存性の注入)という考え方が必要とされる理由を解説する。まず、フェーズ2までの実装を振り返る。InquiryControllerクラスは、フィールドとしてインメモリの`List<Inquiry>`を直接保持し、一覧表示や(ダミーの)登録処理といったデータ操作までも自らのメソッド内で行っていた。このように、あるクラスが必要とする別のクラス(あるいはデータ構造)を自分自身の内部で直接生成・保持してしまう設計を「密結合」と呼ぶ。

密結合な設計には複数の実務的な問題が存在する。第一に、Controllerがデータ管理という本来の責務(HTTPリクエストの処理とレスポンスの生成)とは異なる関心事まで抱え込むことになり、単一責任の原則に反する。第二に、データ管理ロジックがController内に埋め込まれているため、同じロジックを別のControllerから再利用することができない。第三に、テストの観点からも、Controller単体でテストを行おうとしても、内部に直接埋め込まれたデータ管理ロジックを切り離すことができず、テストが困難になる。第四に、将来的にデータの保存先をインメモリのListからデータベースへ変更する際(本科目では後のフェーズ3中盤でH2データベースへ移行する予定である)、Controller自身のコードを直接書き換える必要が生じ、変更の影響範囲が大きくなってしまう。

これらの問題を解決するのがDIという設計原理である。DIとは、あるオブジェクト(クラス)が必要とする別のオブジェクトを、自分自身では生成せず、外部から「注入」してもらう仕組みを指す。この考え方により、Controllerは「データ管理を行う何らかのオブジェクトが存在する」ということだけを知っていればよく、その実体がどのように生成され、どのように実装されているかを意識する必要がなくなる。これにより、クラス間の結合度が下がり(疎結合)、変更に強く、再利用性・テスト容易性の高い設計が実現される。この細目で理解すべき範囲は、密結合な設計が抱える具体的な問題点(責務の混在、再利用性の欠如、テストの困難さ、変更の影響範囲の大きさ)と、その解決策としてのDIという考え方の基本的な定義を理解するまで。

② 本細目では、Spring Frameworkが提供するDIコンテナ(IoCコンテナ)の役割について、その仕組みと用語を整理しながら詳説する。DIという設計原理そのものは特定のフレームワークに依存する概念ではないが、Spring Frameworkはこれを「DIコンテナ」というインフラストラクチャとして実現している点に大きな特徴がある。DIコンテナとは、アプリケーション内で必要とされるオブジェクト(Springではこれを「Bean」と呼ぶ)の生成・初期化・管理・依存関係の解決までを一手に引き受ける仕組みである。

DIコンテナが行う一連の処理は、しばしば「制御の逆転」(IoC: Inversion of Control)と呼ばれる。通常のプログラミングでは、あるクラスが必要とする別のクラスのインスタンスを、自分自身の中でnewキーワードを用いて生成する。これに対しDIコンテナを用いた設計では、インスタンスの生成とその組み立て(どのBeanをどのBeanに渡すか)という「制御」の主導権が、個々のクラスからDIコンテナ側へと移る。つまり、開発者は「このクラスをBeanとして管理してほしい」という宣言だけを行い、実際の生成・注入のタイミングと手順はSpring側に委ねることになる。

Springがどのクラスをコンテナ管理下のBeanとして認識するかについては、`@Service`や`@Controller`、`@Repository`、`@Component`といった「ステレオタイプアノテーション」をクラスに付与する方法がある。Spring Bootアプリケーションの起動時、これらのアノテーションが付与されたクラスはコンポーネントスキャンによって自動的に検出され、DIコンテナに登録される。本コマではこの自動検出の方式のみを扱い、次コマではこれと対をなす、開発者が明示的にBean定義を行うJavaConfig(`@Configuration`+`@Bean`)の方式を学習する。この細目で理解すべき範囲は、DIコンテナ(IoCコンテナ)の役割、Beanという用語の意味、制御の逆転(IoC)という考え方、およびステレオタイプアノテーションによるコンポーネントスキャンの基本的な仕組みを理解するまで。

③ 本細目では、実際に`@Autowired`アノテーションを用いてDIを実践し、これまでInquiryControllerクラス内に直接記述されていたお問い合わせデータの管理ロジックを、新たに作成する`InquiryService`クラスへと切り出す演習を行う。まず、`@Service`アノテーションを付与した`InquiryService`クラスを新規作成し、フィールドとしてインメモリの`List<Inquiry>`を移動する。一覧表示に必要なデータ取得処理(例えば`findAll()`のようなメソッド)や、これまでダミーとして扱っていた登録処理に相当するメソッドを、このInquiryServiceクラス内に実装として集約する。

次に、InquiryController側の修正を行う。ControllerクラスのフィールドとしてInquiryService型の変数を宣言し、そのフィールドに対して`@Autowired`アノテーションを付与する。これにより、Spring BootアプリケーションのDIコンテナは、起動時にコンポーネントスキャンによって検出済みのInquiryServiceのBeanインスタンスを、このフィールドへ自動的に注入する。Controller側のコードでは、`new InquiryService()`のようなインスタンス生成コードは一切必要とされない点が、DIによって実現される疎結合設計の要である。

演習では、フィールドインジェクション(フィールドに直接`@Autowired`を付与する方式)を用いるが、実務ではコンストラクタインジェクション(コンストラクタの引数として依存先を受け取り、そこに`@Autowired`を付与する、あるいはコンストラクタが1つのみの場合は省略可能な方式)がより推奨される点にも触れ、その理由(不変性の確保、循環参照の早期検出、テストの容易さ)を概説する。実装後は、一覧画面が従来どおり正しく表示されることを確認し、見た目には変化がなくとも内部設計が大きく改善されたことを実感させる。この細目で理解すべき範囲は、`@Service`アノテーションによるInquiryServiceクラスの作成、`@Autowired`によるControllerへの注入という一連の実装手順、およびフィールドインジェクションとコンストラクタインジェクションの違いを理解するまで。

キーワード ① DI(依存性の注入) ② DIコンテナ ③ 疎結合 ④ @Autowired ⑤ ステレオタイプアノテーション
コマの展開方法 社会人講師 AL ICT PowerPoint・Keynote 教科書
コマ用オリジナル配布資料 コマ用プリント配布資料 その他 該当なし
小テスト 授業時間内に、LMS上において該当コマの小テストを実施する。
復習・予習課題 ◆今回授業の復習
今回学んだDIの必要性について、なぜControllerが自らデータを保持する設計が「密結合」と呼ばれ問題視されるのかを、自分の言葉で説明できるように整理すること。あわせて、実際に作成した`InquiryService`クラスと`@Autowired`によるDIの実装コードを見直し、Controller側にnewによるインスタンス生成が一切登場しないことを確認しておくこと。

◆次回授業の予習
次回の授業では、本日学んだステレオタイプアノテーションによる自動検出(コンポーネントスキャン)と対比する形で、`@Configuration`+`@Bean`を用いたJavaConfigによる明示的なBean定義の方法を学習する。そのため、テキストの該当箇所に目を通し、「自動で検出されるBean」と「手動で登録するBean」という2つの方式が存在することの概要を把握しておくこと。

16 JavaConfigによる明示的なBean定義 科目の中での位置付け 本コマは「15〜16」の2回目にあたり、前回学んだ`@Service`等のステレオタイプアノテーションによる自動検出(コンポーネントスキャン)の仕組みを復習したうえで、それと対をなすもう一つのBean定義方式である、JavaConfig(`@Configuration`+`@Bean`)による明示的なBean定義を学習する。JavaConfigは、外部ライブラリのクラスなどアノテーションを付与できないクラスをBean化する場面で不可欠であり、後のフェーズ4で学習するSpring Securityの`SecurityFilterChain`定義にも直結する、必修の基礎知識として位置づけられる。
コマ主題細目 ① ステレオタイプアノテーションによる自動検出の復習 ② @Configuration+@Beanによる明示的なBean定義 ③ 外部ライブラリクラスのBean化と初期データ投入Beanの実装演習
細目レベル ① 本細目では、前回のコマ15で学習した、`@Service`等のステレオタイプアノテーションによるコンポーネントスキャンの仕組みを、対比の観点から改めて整理し直す。前回確認したとおり、`@Component`、`@Service`、`@Controller`、`@Repository`といったアノテーションをクラス定義に付与しておくと、Spring Bootアプリケーションの起動時にクラスパス上が走査され、該当するクラスが自動的にBeanとしてDIコンテナに登録される。この方式は、開発者自身が作成するクラス(InquiryServiceやInquiryControllerなど)に対して非常に簡潔にBean化を行えるという利点がある。

しかし、このコンポーネントスキャンによる自動検出方式には、原理的な制約が存在する。それは、Bean化したいクラスのソースコードに対して、開発者自身が直接アノテーションを付与できることが前提になっているという点である。裏を返せば、Bean化したい対象が、開発者が編集できない外部ライブラリが提供するクラス(jarファイルの中に含まれるクラスなど)である場合、そのクラスの定義自体にアノテーションを追記することは不可能であり、コンポーネントスキャンの対象とすることができない。

また、複数の設定値の組み合わせによって初期状態でデータを投入したい場合や、条件によって異なる実装を切り替えたい場合など、単純にアノテーションを1つ付与するだけでは表現しきれない、やや複雑なBean生成のロジックが必要になる場面も存在する。このような「自動検出方式では対応できない場面」が実務上一定数存在することを踏まえたうえで、次の細目で学ぶJavaConfigという第二のBean定義方式の必要性へと話をつなげる。この細目で理解すべき範囲は、ステレオタイプアノテーションによる自動検出の仕組みと、その方式が抱える原理的な制約(開発者が編集できないクラスには適用できない点)を理解するまで。

② 本細目では、ステレオタイプアノテーションによる自動検出と対をなすもう一つのBean定義方式である、JavaConfigによる明示的なBean定義の書き方を詳説する。JavaConfigとは、Javaのクラスそのものを設定ファイルとして用いる仕組みであり、クラス定義に`@Configuration`アノテーションを付与することで、そのクラスがBean定義を行うための設定クラスであることをSpringに伝える。

設定クラスの内部には、Beanとして登録したいオブジェクトを生成して返す、通常のJavaメソッドを定義する。このメソッドに`@Bean`アノテーションを付与すると、Spring起動時にこのメソッドが実行され、その戻り値のオブジェクトがDIコンテナにBeanとして登録される。つまり、「クラス自体にアノテーションを付与する」ステレオタイプアノテーション方式とは異なり、「Beanを生成するためのメソッドにアノテーションを付与する」という点がJavaConfig方式の最大の特徴である。この違いにより、対象クラスのソースコードを一切変更することなく、任意のクラスのインスタンスをBeanとして登録することが可能になる。

両者の使い分けの原則は次のとおりである。開発者自身が作成する、業務ロジックを担うクラス(Service、Repositoryなど)については、簡潔に記述できるステレオタイプアノテーション方式を用いる。一方、外部ライブラリのクラスや、複雑な初期化ロジックを伴うBean、あるいは環境によって切り替えたいBeanについては、JavaConfigによる明示的な定義を用いる。なお、本科目ではフェーズ4でSpring Securityを導入する際、認証・認可のルールを定義する`SecurityFilterChain`という外部ライブラリ提供のインタフェースの実装を、まさにこのJavaConfig(`@Configuration`+`@Bean`)の形式でBean登録することになる点も予告し、本コマの学習が後のフェーズへ直結することを示す。この細目で理解すべき範囲は、`@Configuration`アノテーションと`@Bean`アノテーションの役割、両者を組み合わせたJavaConfigによるBean定義の基本的な書き方、およびステレオタイプアノテーション方式との使い分けの原則を理解するまで。

③ 本細目では、JavaConfigの具体的な活用場面として、外部ライブラリのクラスをBean化する演習と、アプリケーション起動時に初期データを投入するBeanを登録する演習を行う。まず、外部ライブラリのクラスをBean化する例として、日時のフォーマット処理や乱数生成処理など、開発者が直接アノテーションを付与できない既存のユーティリティクラスを取り上げ、これを`@Configuration`クラス内の`@Bean`メソッドでインスタンス化し、DIコンテナに登録する手順を実演する。この作業を通じて、コンポーネントスキャンでは対応できなかった対象にも、JavaConfigであればBean化の道が開けることを体感させる。

続いて、本科目のプロジェクトに即した実践的な演習として、アプリケーション起動時にお問い合わせデータのサンプル(初期データ)をInquiryServiceが保持するリストへ投入する仕組みを、JavaConfigを用いて実装する。具体的には、`@Configuration`クラス内に`@Bean`メソッドを用意し、Springが提供する`CommandLineRunner`インタフェースの実装(ラムダ式で記述できる)を戻り値として返すことで、アプリケーション起動直後に一度だけ実行される初期化処理を登録する。このメソッド内でInquiryServiceの登録用メソッドを呼び出し、数件のサンプルとなるお問い合わせデータを自動的に投入するようにする。

この演習が完了すると、これまで空の状態から開発者が手動でダミーデータを表示させていた画面が、アプリケーション再起動のたびに自動的に数件のサンプルデータを保持した状態で起動するようになり、開発時の確認作業が効率化される。この細目で理解すべき範囲は、外部ライブラリのクラスをJavaConfigでBean化する具体的な手順と、`CommandLineRunner`を用いた初期データ投入用Beanの登録方法を理解し、実際にInquiryServiceへの初期データ投入を実装できるまで。

キーワード ① JavaConfig ② @Configuration ③ @Bean ④ CommandLineRunner ⑤ コンポーネントスキャン
コマの展開方法 社会人講師 AL ICT PowerPoint・Keynote 教科書
コマ用オリジナル配布資料 コマ用プリント配布資料 その他 該当なし
小テスト 授業時間内に、LMS上において該当コマの小テストを実施する。
復習・予習課題 ◆今回授業の復習
今回作成したJavaConfigの設定クラスを見直し、`@Configuration`と`@Bean`がそれぞれどのような役割を担っているのかを再確認すること。また、ステレオタイプアノテーションによる自動検出とJavaConfigによる明示的な定義について、どのような場面でどちらを使うべきかを、外部ライブラリのクラスや初期データ投入Beanの例を挙げながら自分なりに整理し、他の人に説明できるようにしておくこと。

◆次回授業の予習
次回の授業では、これまでの学習では扱ってこなかった「特定のユーザーだけがログインして使える」という状態管理の仕組みとして、HTTPのステートレス性の問題点とセッション管理の必要性、およびHttpSessionオブジェクトの基本操作について学習する。そのため、テキストの該当箇所を読み、HTTPが「ステートレス」であるとはどういうことか、なぜそれが問題になるのかについて概要を把握しておくこと。

17 セッション管理の基礎とHttpSession 科目の中での位置付け 本コマは「17〜18. セッション管理(ログイン処理)」の1回目にあたり、フェーズ1のServlet/JSP実習で断片的に触れたセッション管理の概念を、Spring Boot環境において体系的に学び直す。HTTPプロトコルが持つステートレス性という根本的な特性を改めて確認したうえで、複数のHTTPリクエストにまたがってユーザーの状態(ログイン中であるか否かなど)を保持するための仕組みであるHttpSessionオブジェクトの使い方を習得する。次コマで実装する手作りログイン処理の設計を先取りして検討する回でもある。
コマ主題細目 ① HTTPのステートレス性とセッション管理の必要性 ② HttpSessionオブジェクトの取得と操作 ③ セッションを用いたログイン処理のフロー設計
細目レベル ① 本細目では、Webアプリケーションにおいてセッション管理という仕組みがなぜ必要とされるのかを、HTTPプロトコルの根本的な特性から解説する。HTTPプロトコルは「ステートレス」なプロトコルである。ステートレスとは、サーバーが個々のHTTPリクエストを完全に独立したものとして扱い、以前のリクエストの内容や状態を一切記憶しないという特性を指す。ブラウザからサーバーへ一覧画面の表示を要求するリクエストと、その直後に登録フォームの表示を要求するリクエストは、サーバー側から見ると互いに何の関連もない、まったく別個のリクエストとして処理される。

この特性は、サーバーの実装をシンプルに保ち、多数のクライアントからのリクエストを効率よくさばくうえでは合理的な設計であるが、一方で実用上大きな課題を生む。例えば、あるユーザーがIDとパスワードを入力してログインに成功した場合、その「ログイン済みである」という状態を、以降の一覧表示リクエストや登録リクエストのたびにサーバー側が覚えていなければ、ユーザーはページを移動するたびに再びログインを要求されてしまうことになる。すなわち、ステートレスなHTTPの上で、疑似的に「状態(ステート)」を維持する仕組みが必要になる。

この課題を解決するのが「セッション管理」である。セッション管理とは、あるクライアント(ブラウザ)が一連の操作を行っている間、そのクライアント固有の情報をサーバー側に保持し続ける仕組みを指す。具体的には、サーバーは各クライアントに対して一意のセッションIDを発行し、それをブラウザにCookieとして保存させる。以降のリクエストでは、ブラウザが自動的にこのセッションIDをサーバーへ送り返すことで、サーバー側は「どのクライアントからのリクエストか」を識別し、そのクライアントに対応する状態(ログイン情報など)をサーバー内のメモリ上で管理し続けることができる。この細目で理解すべき範囲は、HTTPのステートレス性という特性の意味と、それによって生じる課題、およびその解決策としてのセッション管理・セッションID・Cookieの関係性の概要を理解するまで。

② 本細目では、Spring MVCのController内でセッションを操作するための具体的な手段であるHttpSessionオブジェクトの取得方法と、その基本的な操作方法を解説する。HttpSessionは、Jakarta Servlet APIが提供するインタフェースであり、サーバー内でクライアントごとに保持される状態管理領域を表現するオブジェクトである。Spring MVCのControllerメソッド内では、メソッドの引数として`HttpSession session`を宣言するだけで、Spring側が現在のリクエストに対応するHttpSessionオブジェクトを自動的に渡してくれる。

HttpSessionオブジェクトへのデータの格納には`setAttribute(String name, Object value)`メソッドを用いる。第一引数には後で値を取り出す際のキーとなる文字列を、第二引数には保存したい任意のオブジェクトを指定する。例えば、ログインに成功した際に`session.setAttribute("loginUser", "admin")`のように記述することで、「loginUser」というキーに対して文字列「admin」をセッションへ保存できる。逆に、保存された値を取得する際は`getAttribute(String name)`メソッドを用い、`session.getAttribute("loginUser")`のように呼び出すことで、以前に保存した値を取り出すことができる。値が保存されていない場合はnullが返される点に注意が必要である。

さらに、ログアウト処理などセッション自体を破棄したい場面では`invalidate()`メソッドを呼び出す。これにより、そのセッションに紐づいて保存されていたすべての情報が破棄され、以降同じセッションIDでアクセスしても状態が保持されていない状態に戻る。これらの`setAttribute`、`getAttribute`、`invalidate`という3つの基本操作を組み合わせることで、ログイン状態の保存・確認・破棄という一連の流れを実現できることを、簡単なサンプルコードを通じて確認する。この細目で理解すべき範囲は、HttpSessionオブジェクトのControllerメソッドへの取得方法と、`setAttribute`・`getAttribute`・`invalidate`という3つの基本メソッドの役割と使い方を理解するまで。

③ 本細目では、次回のコマ18で実装する具体的なログイン処理の実装に先立ち、セッションを用いたログイン処理全体のフローを設計レベルで整理する。まず、ログイン処理に関わる画面とControllerの構成要素を洗い出す。具体的には、(1)ID・パスワードの入力を受け付けるログイン画面、(2)入力されたID・パスワードを検証し、正しければセッションにログイン状態を保存したうえで一覧画面へリダイレクトする認証処理を行うController、(3)ログイン状態を必須とする一覧画面自体、(4)ログイン状態を解除するログアウト処理、という4つの要素が必要になる。

次に、これらの要素間の処理の流れを、リクエストとレスポンスの往復として時系列に整理する。ユーザーがログイン画面にアクセスするとGETリクエストが送られ、ログイン用のフォームが表示される。ユーザーがIDとパスワードを入力して送信するとPOSTリクエストが送られ、Controller側でその値を検証する。検証に成功した場合はHttpSessionへログイン済みであることを示す情報(ユーザー名など)を保存し、一覧画面へリダイレクトする(PRGパターンの適用)。検証に失敗した場合は、エラーメッセージとともに再びログイン画面を表示する。

さらに、一覧画面を表示するControllerメソッドの冒頭で、HttpSessionに「ログイン済み」を示す情報が保存されているかどうかを確認し、保存されていなければログイン画面へリダイレクトする、という「ログインガード」の処理が必要になることを設計段階で明確にする。この一連の設計を図式化しながら整理することで、次回の実装がスムーズに進むよう準備する。この細目で理解すべき範囲は、ログイン画面・認証処理・ログイン必須の一覧画面・ログアウト処理という4つの構成要素と、それらの間をセッションがどのようにつなぐかという処理フロー全体の設計を理解するまで。

キーワード ① ステートレス ② セッション管理 ③ HttpSession ④ setAttribute/getAttribute ⑤ PRGパターン
コマの展開方法 社会人講師 AL ICT PowerPoint・Keynote 教科書
コマ用オリジナル配布資料 コマ用プリント配布資料 その他 該当なし
小テスト 授業時間内に、LMS上において該当コマの小テストを実施する。
復習・予習課題 ◆今回授業の復習
今回学んだHTTPのステートレス性とセッション管理の関係について、なぜHTTPだけでは「ログイン状態」を維持できないのかを、CookieとセッションIDの関係も含めて自分の言葉で説明できるように整理すること。あわせて、HttpSessionの`setAttribute`・`getAttribute`・`invalidate`という3つのメソッドの役割を、簡単なサンプルコードを見ながら再確認し、それぞれがログイン処理のどの場面で使われるのかを対応づけておくこと。

◆次回授業の予習
次回の授業では、今回設計したログイン処理のフローを実際にコードとして実装し、固定のID・パスワードによる手作りログイン機能と、お問い合わせ一覧のログイン必須化を完成させる。そのため、今回整理したログイン画面・認証処理・一覧画面・ログアウト処理という4つの構成要素の関係を、もう一度自分の手で図に書き出して確認しておくこと。

18 ログイン処理の実装完成 科目の中での位置付け 本コマは「17〜18」の2回目にあたり、前回設計したセッションを用いたログイン処理のフローを、実際にコードとして実装し完成させる回である。固定のID・パスワードを用いた手作りのログイン機能を実装し、これまで誰でも閲覧できていたお問い合わせ一覧画面をログイン必須の画面へと変更する。本コマで実装する「素朴な手作りログイン」は、フェーズ4でSpring Securityへ置き換える際の比較対象となり、フレームワークが自動化してくれる処理の価値を実感するための重要な布石となる。
コマ主題細目 ① 固定ID/パスワードによる手作りログインの実装 ② ログイン状態の確認とログアウト処理 ③ お問い合わせ一覧のログイン必須化
細目レベル ① 本細目では、前回設計したフローに基づき、固定のID・パスワードを用いた手作りのログイン機能を実装する。まず、ログイン画面用のControllerメソッドを作成する。GETリクエストでアクセスした場合には、単純にログイン用のThymeleafテンプレート(IDとパスワードの入力欄を持つフォーム)を表示するだけのメソッドを用意する。フォームの`th:action`には認証処理を行うURLを指定し、送信方式はPOSTとする。

次に、認証処理を行うControllerメソッドを実装する。このメソッドは`@RequestParam`または専用のForm-Backing Beanを用いて、入力されたIDとパスワードの値を受け取る。本科目では学習を単純化するため、データベースに問い合わせるのではなく、あらかじめControllerクラス内で固定値として定義しておいたID(例えば「admin」)とパスワード(例えば「password」)の文字列と、受け取った入力値をif文で比較する、という素朴な実装を採用する。

比較の結果が一致した場合には、認証成功と判断し、HttpSessionに対して`session.setAttribute("loginUser", id)`のようにログイン中であることを示す情報を保存したうえで、お問い合わせ一覧画面のURLへリダイレクトする。一致しなかった場合には、認証失敗と判断し、Modelにエラーメッセージ(「IDまたはパスワードが正しくありません」等)を格納したうえで、再びログイン画面を表示する。この際、単にreturnでログイン画面のテンプレート名を返すのか、リダイレクトを用いるのかという設計判断についても、PRGパターンの観点から補足する。この細目で理解すべき範囲は、固定ID・パスワードとの比較による認証処理の実装方法と、認証成功時にHttpSessionへログイン情報を保存する処理を、実際にコードとして書けるようになるまで。

② 本細目では、ログイン処理の完成に不可欠な、ログイン状態の確認処理とログアウト処理の実装を扱う。まず、画面上部などに「現在ログイン中のユーザー名」を表示したり、ログイン中かどうかによって表示するリンクを切り替えたりする場面を想定し、Controller側でHttpSessionから`getAttribute("loginUser")`を呼び出し、その戻り値がnullでなければログイン中であると判定するロジックを実装する。この判定結果をModelへ格納し、Thymeleafテンプレート側で`th:if`を用いて表示を出し分ける。

次に、ログアウト処理を実装する。ログアウト用のURLに対応するControllerメソッドを新たに用意し、そのメソッド内でHttpSessionの`invalidate()`メソッドを呼び出す。これにより、それまでセッションに保存されていたログイン情報(`loginUser`の値を含むすべての情報)が破棄される。処理の最後には、ログイン画面またはトップページへリダイレクトし、ログアウトが完了したことをユーザーに示す。

あわせて、`invalidate()`を呼び出した直後に同じHttpSessionオブジェクトに対して操作を行おうとすると例外が発生する点や、ログアウト後に再度保護された画面へアクセスしようとした場合には、次の細目で実装するログインガードによって再びログイン画面へ誘導される必要がある点にも触れ、ログイン・ログアウトという一連のライフサイクルが正しく閉じるように設計されていることを確認する。この細目で理解すべき範囲は、HttpSessionからログイン状態を確認する判定ロジックの実装方法と、`invalidate()`メソッドを用いたログアウト処理の実装方法を理解するまで。

③ 本細目では、これまで実装してきたログイン・ログアウトの仕組みを活用し、これまで誰でも閲覧可能であったお問い合わせ一覧画面を、ログイン済みのユーザーでなければ閲覧できないよう変更する実装を行う。具体的には、一覧画面を表示するControllerメソッドの冒頭に、HttpSessionから`getAttribute("loginUser")`を取得し、その値がnullである場合(すなわち未ログインである場合)には、一覧画面の表示処理を実行せずにログイン画面へリダイレクトする、という「ログインガード」の処理を追加する。

このガード処理により、URLを直接入力するなどして一覧画面へ直接アクセスを試みたとしても、ログインしていなければ強制的にログイン画面へ差し戻されるようになる。実装後は、ブラウザのシークレットウィンドウ等を利用してログインしていない状態から一覧画面のURLへ直接アクセスし、正しくログイン画面へリダイレクトされることを確認する演習を行う。また、正しいIDとパスワードでログインした後は、問題なく一覧画面が表示され、登録フォームへのアクセスも可能になることをあわせて確認する。

最後に、本コマで実装した「Controllerメソッドの冒頭に毎回同じガード処理を書く」という方式には、対象となる画面が増えるたびに同じコードを繰り返し書かなければならないという保守上の課題が残ることを指摘する。この課題こそが、フェーズ4で学習するSpring Securityが「認可(アクセス制御)」の機能として一括して解決してくれる領域であることを予告し、手作り実装の限界とフレームワーク導入の意義を対比させる。この細目で理解すべき範囲は、Controllerメソッドの冒頭でHttpSessionを確認するログインガードの実装方法と、それを一覧画面へ適用してログイン必須化を実現する具体的な手順を理解するまで。

キーワード ① 手作りログイン ② 固定ID/パスワード認証 ③ ログインガード ④ invalidate ⑤ 認可(アクセス制御)
コマの展開方法 社会人講師 AL ICT PowerPoint・Keynote 教科書
コマ用オリジナル配布資料 コマ用プリント配布資料 その他 該当なし
小テスト 授業時間内に、LMS上において該当コマの小テストを実施する。
復習・予習課題 ◆今回授業の復習
今回実装した手作りのログイン機能について、認証処理・ログイン状態の確認・ログアウト処理・ログインガードという4つのコードそれぞれがHttpSessionのどのメソッドを使っているのかを見直し、対応関係を整理しておくこと。あわせて、ログインしていない状態で一覧画面のURLへ直接アクセスした場合の挙動と、正しくログインした場合の挙動の両方を、実際に自分の手で再現して確認しておくこと。

◆次回授業の予習
次回の授業では、サーバーサイドバリデーションの重要性と、Spring Validationを用いた入力チェックの実装方法について学習する。そのため、これまでのお問い合わせ登録フォームで、顧客名やお問い合わせ内容を空欄のまま送信した場合や、極端に長い文字列を送信した場合にどのような結果になるかを実際に試し、現状のフォームには入力チェックの仕組みが一切存在しないことを確認しておくこと。

19 バリデーションの基礎とサーバーサイドチェック 科目の中での位置付け 本コマは「19〜20. バリデーションとエラーメッセージ」の1回目にあたり、これまで実装してきたお問い合わせ登録フォームに対して、入力内容の妥当性を検証するサーバーサイドバリデーションの仕組みを導入する。なぜクライアントサイドのチェックだけでは不十分なのかという原理的な理由を確認したうえで、Spring Validation(Bean Validation)を用いた必須チェックや文字数制限といった単項目チェックの実装方法を習得し、顧客名やお問い合わせ内容のフィールドへ実際に適用する演習を行う。
コマ主題細目 ① サーバーサイドバリデーションの重要性と種類 ② Spring Validationによる単項目チェックの実装 ③ 顧客名・お問い合わせ内容へのバリデーション適用演習
細目レベル ① 本細目では、Webアプリケーション開発においてサーバーサイドでの入力値検証(バリデーション)がなぜ不可欠であるのかを、その理由と種類の両面から解説する。まず、入力チェックにはクライアントサイド(ブラウザ側、JavaScriptやHTML5のrequired属性など)で行うものと、サーバーサイド(アプリケーションサーバー側)で行うものの2種類が存在することを整理する。クライアントサイドのチェックは、ユーザーへ即座にフィードバックを返せる、サーバーへの通信を減らせるといった利点がある一方で、ブラウザの開発者ツールを用いてJavaScriptを無効化したり、あるいはcurlコマンドやAPIツールを用いてブラウザを経由せず直接HTTPリクエストを送信したりすることで、容易に迂回することが可能である。

すなわち、クライアントサイドのチェックはあくまで「ユーザー体験の向上」のための仕組みであり、「不正なデータがシステムに保存されることを防ぐ」というセキュリティ・データ品質の観点からは、まったく信頼することができない。悪意の有無に関わらず、意図しない形式のデータや空のデータがサーバーへ送信される可能性を、サーバー側は常に想定しておかなければならない。この原則を踏まえ、本科目では「サーバーサイドバリデーションこそが本質的に必要な検証である」という立場を明確にする。

バリデーションの種類としては、大きく「単項目チェック」と「相関項目チェック」の2つに分類できることを紹介する。単項目チェックとは、1つの入力項目単体の妥当性(必須入力であるか、文字数が範囲内か、形式が正しいかなど)を検証するものであり、本コマではこちらを扱う。一方、複数の項目間の整合性(パスワードと確認用パスワードの一致など)を検証する相関項目チェックについては、本科目のInquiryエンティティの構造上は必要性が低いため、概念のみの紹介にとどめる。この細目で理解すべき範囲は、クライアントサイドチェックが容易に迂回可能であるためサーバーサイドバリデーションが不可欠であるという理由、および単項目チェックと相関項目チェックという分類の違いを理解するまで。

② 本細目では、Spring Bootが提供するSpring Validation(内部的にはBean Validation/Hibernate Validatorという標準仕様を利用する)を用いて、単項目チェックを実装する具体的な方法を解説する。Spring Validationの基本的な考え方は、バリデーションのルールをForm-Backing Beanクラスのフィールドに対してアノテーションとして宣言的に記述する、というものである。これにより、Controller側のメソッド内にif文の羅列としてチェックロジックを書く必要がなくなり、コードの見通しが大幅に改善される。

代表的なアノテーションとして、必須入力を検査する`@NotBlank`(文字列がnullでも空文字でも空白文字のみでもないことを検証する)、文字数の範囲を検査する`@Size(min = 数値, max = 数値)`などを紹介する。これらのアノテーションを、お問い合わせ登録用のForm-Backing Beanクラスの各フィールド(顧客名、お問い合わせ内容など)に付与することで、そのフィールドに課したい制約を宣言する。

これらのアノテーションを実際に機能させるためには、Controllerのメソッド引数においてForm-Backing Beanの型の直前に`@Validated`(または`@Valid`)アノテーションを付与する必要がある。このアノテーションが付与されると、Spring MVCはリクエストパラメータをFormオブジェクトへバインドする際に、あわせて各フィールドに付与されたバリデーションアノテーションのルールを自動的に検証してくれるようになる。この検証結果は、次のコマで詳しく扱うBindingResultオブジェクトへ格納される。本コマの段階では、まず`@NotBlank`と`@Size`という2つの基本的なアノテーションの意味と書き方を確実に習得することに主眼を置く。この細目で理解すべき範囲は、`@NotBlank`・`@Size`という代表的なバリデーションアノテーションの意味と書き方、およびそれらを機能させるために`@Validated`(`@Valid`)をControllerメソッドに付与する必要があることを理解するまで。

③ 本細目では、これまで学んだバリデーションアノテーションを、実際にお問い合わせ登録フォームのForm-Backing Beanクラスへ適用する演習を行う。まず、顧客名フィールドに対して`@NotBlank(message = "顧客名を入力してください")`のようにメッセージ付きで必須チェックを付与し、あわせて`@Size(max = 50)`のように文字数の上限を設定する。ここでのポイントは、messageオプションを用いることで、バリデーション違反時に表示したい文言をアノテーション自体に定義できるという点である。

次に、お問い合わせ内容フィールドに対しても同様に`@NotBlank`を付与し、長文が想定されるフィールドであることを踏まえて`@Size(max = 500)`のように、顧客名よりも大きな上限値を設定する。この作業を通じて、フィールドごとの性質(短い文字列か長い文章かなど)に応じて、適切な制約値をどのように設計すべきかという実践的な観点にも触れる。

なお、本コマの段階ではControllerメソッドに`@Validated`を付与し、Formオブジェクトの直後にBindingResultオブジェクトを引数として受け取るところまでは実装するが、検証結果に応じてエラー画面を表示し分ける具体的な処理(BindingResultの中身を実際に判定してエラーメッセージを画面に表示する処理)は次コマで扱うことを明示する。本コマではまず、`@NotBlank`や`@Size`を付与したフィールドに対して不正な値(空欄や上限を超える長さの文字列)を送信した際に、BindingResultオブジェクトの内部にエラー情報が正しく格納されること自体を、デバッガやログ出力を用いて確認するにとどめる。この細目で理解すべき範囲は、顧客名・お問い合わせ内容のフィールドへ`@NotBlank`・`@Size`を実際に付与できること、およびBindingResultにエラー情報が格納される仕組みの存在を確認できるまで。

キーワード ① サーバーサイドバリデーション ② Bean Validation ③ @NotBlank ④ @Size ⑤ BindingResult
コマの展開方法 社会人講師 AL ICT PowerPoint・Keynote 教科書
コマ用オリジナル配布資料 コマ用プリント配布資料 その他 該当なし
小テスト 授業時間内に、LMS上において該当コマの小テストを実施する。
復習・予習課題 ◆今回授業の復習
今回学んだ「クライアントサイドのチェックは迂回可能であり、サーバーサイドバリデーションこそが本質的に必要である」という原則を、具体的にどのような方法で迂回できるのかという例とあわせて説明できるように整理すること。あわせて、顧客名・お問い合わせ内容フィールドへ付与した`@NotBlank`・`@Size`アノテーションの記述を見直しておくこと。

◆次回授業の予習
次回の授業では、今回途中まで扱ったBindingResultオブジェクトを実際に使いこなし、バリデーションエラー発生時に入力画面へエラーメッセージとともに再表示する処理を完成させる。あわせてメールアドレスの形式チェックを行う`@Email`アノテーションも学習する。そのため、これまでのお問い合わせ登録フォームにメールアドレス欄がどのように実装されているかを見直しておくこと。

20 エラーハンドリングとメールアドレスのバリデーション 科目の中での位置付け 本コマは「19〜20」の2回目にあたり、前回実装した`@NotBlank`・`@Size`によるバリデーションの検証結果を、実際にユーザーへ分かりやすく提示するためのエラーハンドリングの仕組みを完成させる。BindingResultオブジェクトを用いてエラーの有無を判定し、エラーが存在する場合には入力内容を保持したまま入力画面へ再表示する処理を実装するとともに、メールアドレスの形式チェックを行う`@Email`アノテーションを導入する。本コマの完成をもって、フェーズ3前半(DI・セッション・バリデーション)の一区切りとなる。
コマ主題細目 ① BindingResultオブジェクトによるエラーハンドリング ② エラー発生時の入力画面への再表示処理 ③ @Emailアノテーションによるメールアドレスの形式チェック
細目レベル ① 本細目では、前回のコマ19で導入した`@Validated`アノテーションによるバリデーションの検証結果を実際に受け取り、エラーの有無を判定するためのBindingResultオブジェクトについて詳説する。BindingResultは、Spring MVCがリクエストパラメータをForm-Backing Beanへバインドする過程、およびアノテーションによるバリデーションを実行した結果を格納するオブジェクトである。Controllerメソッドの引数において、`@Validated`を付与したForm-Backing Beanの直後の引数として`BindingResult`型を宣言することで、Spring側がこのオブジェクトを自動的に渡してくれる。

このBindingResultの引数の位置には重要な制約がある。必ず`@Validated`(または`@Valid`)を付与したFormオブジェクトの直後の引数として宣言しなければならない。もしFormオブジェクトとBindingResultの間に別の引数を挟んでしまったり、そもそもBindingResultを引数に含めなかったりすると、バリデーションエラーが発生した際にSpringはエラー情報を格納する先が見つからず、例外(BindException等)をスローしてしまう。この仕様上の制約を、実際にコードの引数の並び順を確認しながら理解させる。

BindingResultオブジェクトが提供する代表的なメソッドとして、エラーが1件でも存在するかどうかを真偽値で返す`hasErrors()`メソッドを紹介する。Controllerメソッド内でこのメソッドを呼び出し、trueが返された場合には、バリデーションに違反した入力が存在したことを意味するため、後続の登録処理(データの保存)を実行せず、入力画面へ処理を差し戻すという分岐処理を実装する。この`hasErrors()`による分岐が、バリデーション機能全体の要となる仕組みである。この細目で理解すべき範囲は、BindingResultオブジェクトの役割と、Controllerメソッドの引数における宣言位置の制約、および`hasErrors()`メソッドによるエラー有無の判定方法を理解するまで。

② 本細目では、`hasErrors()`によってバリデーションエラーが検出された場合に、ユーザーへエラー内容を提示しながら入力画面へ処理を差し戻す、再表示処理の実装方法を解説する。まず、Controllerメソッドにおいて`hasErrors()`がtrueを返した場合の分岐処理として、登録用のThymeleafテンプレート名をそのままreturnする(リダイレクトを行わない)という実装を行う。この際、リダイレクトを用いずreturnで直接テンプレート名を返す理由は、Formオブジェクトが保持しているユーザーの入力値と、BindingResultが保持しているエラー情報の両方を、そのままModelを介さずにThymeleaf側へ引き継ぐ必要があるためである。

次に、Thymeleaf側での表示方法を実装する。Thymeleafは、Spring MVCのBindingResultと連携するための専用の属性群を提供しており、代表的なものが`th:errors`である。各入力項目に対応するHTML要素の近くに`<span th:if="${#fields.hasErrors('customerName')}" th:errors="*{customerName}"></span>`のような記述を追加することで、該当フィールドにエラーが存在する場合にのみ、アノテーションのmessageオプションで指定したエラーメッセージが自動的に表示されるようになる。

さらに、入力画面を再表示する際には、エラーとなった項目だけでなく、ユーザーがそれまでに入力していた他の項目の値(顧客名やお問い合わせ内容など)もそのまま画面上に保持されている必要がある。これは、Form-Backing Beanが`th:object`を通じて画面全体にバインドされているため、Controller側で特別な処理を追加しなくても自動的に実現される点を確認する。この一連の実装により、ユーザーは入力し直す手間を最小限に抑えながら、どの項目にどのような不備があったのかを画面上で直接確認できるようになる。この細目で理解すべき範囲は、バリデーションエラー発生時にreturnでテンプレート名を返す再表示処理の実装方法と、`th:errors`属性を用いたエラーメッセージの画面表示方法を理解するまで。

③ 本細目では、Bean Validationが提供する形式チェック用アノテーションの代表例として、`@Email`アノテーションを取り上げ、お問い合わせフォームのメールアドレス項目へ適用する演習を行う。これまで学んだ`@NotBlank`や`@Size`が「値の有無」や「文字数」という比較的単純な条件を検証するものであったのに対し、`@Email`はより高度な検証、すなわち入力された文字列が電子メールアドレスとして妥当な形式(アットマークやドメイン部分の構造など)になっているかどうかを、正規表現に基づいて自動的に判定してくれる点に特徴がある。

実装の手順としては、Form-Backing Beanクラスのメールアドレスフィールドに対して`@Email(message = "メールアドレスの形式が正しくありません")`を付与する。あわせて、メールアドレスは通常必須項目であることが多いため、`@NotBlank`とあわせて複数のアノテーションを1つのフィールドに同時に付与できることも確認する。複数のアノテーションを付与した場合、いずれか一方でも条件に違反すれば、その項目に対応するエラーがBindingResultへ格納される。

演習では、実際に「メールアドレスを空欄のまま送信した場合」と「アットマークを含まない不正な形式の文字列を入力した場合」の2パターンを試し、それぞれ`@NotBlank`と`@Email`のどちらのアノテーションによるエラーメッセージが、`th:errors`を通じて画面に表示されるかを確認する。この確認作業を通じて、複数のバリデーションルールが1つのフィールドに対して独立して機能していることを体感的に理解させる。本コマの完成をもって、お問い合わせ登録フォームは「必須チェック」「文字数制限」「形式チェック」という3種類の基本的なサーバーサイドバリデーションを備えた状態となる。この細目で理解すべき範囲は、`@Email`アノテーションの役割と書き方、複数のバリデーションアノテーションを1つのフィールドに併用する方法、および実際にメールアドレス項目へ適用して動作を確認できるまで。

キーワード ① BindingResult ② hasErrors ③ th:errors ④ @Email ⑤ 入力画面への再表示
コマの展開方法 社会人講師 AL ICT PowerPoint・Keynote 教科書
コマ用オリジナル配布資料 コマ用プリント配布資料 その他 該当なし
小テスト 授業時間内に、LMS上において該当コマの小テストを実施する。
復習・予習課題 ◆今回授業の復習
今回完成させたバリデーション機能について、`hasErrors()`による分岐からreturnによる再表示、`th:errors`によるエラーメッセージの表示までの一連の流れを、コードを見ながら順を追って説明できるように整理すること。あわせて、メールアドレス欄に様々な不正な入力(空欄、アットマークなし等)を試し、`@NotBlank`と`@Email`のどちらのアノテーションによるエラーが表示されるのかを、実際に確認しておくこと。

◆次回授業の予習
次回の授業では、これまでインメモリの`List`で管理してきたお問い合わせデータを、実際のデータベースであるH2に永続化する仕組みを学習する。そのため、データベース接続の基本的な役割と、これまで学んできたインメモリでのデータ管理との違いについて、テキストの該当箇所を読んで概要を把握しておくこと。

21 データベース接続の概要とH2の導入 科目の中での位置付け これまでの授業では、お問い合わせデータをServiceクラス内のList<Inquiry>というインメモリの領域に保持してきた。しかしこの方式では、アプリケーションを再起動するたびに登録済みのデータがすべて消えてしまうという致命的な制約がある。実務のWebアプリケーションでは、顧客からの問い合わせのような重要な情報を恒久的に保存する必要があり、そのためにはデータベースとの連携が不可欠である。本コマでは、これまで学習してきたバリデーション済みのInquiryデータを実際にデータベースへ保存していくための第一歩として、データベース接続の基本概念とJDBCの役割、そして開発初期段階で扱いやすいインメモリデータベースH2の導入方法を学習する。
コマ主題細目 ① データベース接続の概要とJDBCの役割 ② インメモリデータベースH2の導入と設定 ③ JdbcTemplateによるデータ操作の簡素化の概要
細目レベル ① 本細目では、JavaアプリケーションからDBMSへ接続する仕組みの全体像と、その中核を担うJDBC(Java Database Connectivity)の役割について解説する。まず、これまでServiceクラスの中でList<Inquiry>というJavaのコレクションにデータを保持してきた実装を振り返り、この方式の限界を整理する。アプリケーションプロセスが終了すればメモリ上のデータは失われるため、対応状況を「対応済み」に変更した記録も、再起動すれば元の状態に戻ってしまう。この問題を解決するには、アプリケーションの外部に存在し、電源が落ちても内容を保持し続けるデータベース管理システム(DBMS)にデータを永続化する必要がある。

続いて、JavaプログラムからDBMSへアクセスするための標準APIであるJDBCの位置づけを学習する。JDBCは、MySQLやPostgreSQL、H2といった種類の異なるDBMSに対して、統一されたインターフェースでアクセスするための仕組みを提供する。具体的には、DriverManagerクラスを通じてDBMSへの接続(Connection)を確立し、Statementオブジェクトを介してSQL文を送信し、実行結果をResultSetオブジェクトとして受け取るという一連の流れが、JDBCの基本的な処理パターンである。各DBMSベンダーが提供するJDBCドライバをクラスパスに追加することで、アプリケーション側のコードを大きく変更することなく、接続先のDBMSを切り替えられる点もJDBCの重要な特徴である。

さらに、Spring Bootにおけるデータベース接続設定の基本にも触れる。application.propertiesファイルに接続先URL、ユーザー名、パスワードといった情報を記述するだけで、Spring Bootが自動的にDataSourceをBeanとして構成してくれる仕組みを概観し、次の細目で導入するH2データベースへの接続準備につなげる。この細目で理解すべき範囲は、インメモリList方式の限界、JDBCの役割と基本的な処理の流れ、およびSpring BootにおけるDataSource自動構成の概要まで。

② 本細目では、開発・学習用途に適したインメモリデータベースH2の導入方法と、Spring Bootプロジェクトへの設定手順について詳説する。H2は、Javaで実装された軽量なリレーショナルデータベースであり、別途DBMSサーバーをインストール・起動する手間がなく、アプリケーションと同じJVMプロセス内で動作するインメモリモードを持つ点が最大の特徴である。本格的な本番運用にはPostgreSQLやMySQLのような永続型DBMSが用いられるが、学習段階では環境構築の負担を最小限に抑えつつSQLとJDBCの基本を体験できるH2が最適である。

導入手順としては、まずpom.xmlにH2のJDBCドライバに対する依存関係(com.h2database:h2)を追加する。IntelliJ IDEAでSpring Initializrからプロジェクトを作成した場合は、依存関係の選択画面でH2 Databaseにチェックを入れるだけでよい。次に、application.propertiesにspring.datasource.urlとしてjdbc:h2:mem:testdbのような形式のURLを記述し、インメモリモードでデータベースを起動するよう設定する。あわせてspring.h2.console.enabled=trueを設定することで、ブラウザから直接SQLを実行できるH2コンソール(/h2-console)を有効化できる。

さらに、テーブル定義用のSQLファイルであるschema.sqlをsrc/main/resources直下に配置することで、アプリケーション起動時に自動的にお問い合わせ情報を格納するinquiryテーブルが作成される仕組みを学ぶ。顧客名、メールアドレス、お問い合わせ内容、対応状況、受付日時といった各カラムをこのschema.sqlで定義し、これまでInquiryクラスのフィールドとして扱ってきた項目とテーブルのカラムとの対応関係を確認する。この細目で理解すべき範囲は、H2の特徴とインメモリモードの意味、pom.xmlおよびapplication.propertiesへの設定追加、およびschema.sqlによるテーブル定義まで。

③ 本細目では、Spring FrameworkがJDBCの定型処理を大幅に簡略化するために提供するJdbcTemplateクラスの概要について学習する。素のJDBCを直接利用する場合、Connectionの取得、PreparedStatementの生成、SQL実行、ResultSetからのデータ取り出し、そして例外処理やリソースのクローズ処理まで、すべてを開発者自身が記述しなければならない。特にtry-with-resources文やfinally句によるConnection・Statement・ResultSetの確実なクローズ処理は記述量が多く、閉じ忘れによるリソースリークという不具合の温床にもなりやすい。

JdbcTemplateは、こうした定型的でエラーの起きやすい処理をSpring Framework側があらかじめ実装しておくことで、開発者がSQL文とパラメータ、そして結果の変換方法(RowMapper)だけを記述すればよい設計になっている。具体的には、queryForObjectメソッドで1件のデータを取得したり、queryメソッドで複数件のデータをList形式で取得したりする際に、ResultSetから各カラムの値を取り出しJavaオブジェクトへ詰め替える処理をRowMapperというインターフェースの実装として分離できる。この仕組みにより、SQLの実行結果とJavaオブジェクトとのマッピングという本質的な処理に集中できるようになる。

Spring Bootのプロジェクトでは、H2などのJDBCドライバをクラスパスに追加し、DataSourceの自動構成が行われていれば、JdbcTemplateのインスタンスはSpring Bean(DIコンテナが管理する部品)として自動的に用意される。そのため、これまでコマ15〜16で学習した@Autowiredによるフィールドインジェクションやコンストラクタインジェクションと同じ要領で、RepositoryクラスにJdbcTemplateを注入して利用できる。次回のコマ22では、この概要を踏まえ、実際にINSERT文とSELECT文をJdbcTemplateで実行し、お問い合わせデータの永続化を実装していく。この細目で理解すべき範囲は、素のJDBCの課題、JdbcTemplateが担う役割とRowMapperの位置づけ、およびDIによるJdbcTemplateの利用方法まで。

キーワード ① JDBC ② H2データベース ③ DataSource ④ JdbcTemplate ⑤ schema.sql
コマの展開方法 社会人講師 AL ICT PowerPoint・Keynote 教科書
コマ用オリジナル配布資料 コマ用プリント配布資料 その他 該当なし
小テスト 授業時間内に、LMS上において該当コマの小テストを実施する。
復習・予習課題 ◆今回授業の復習
今回学習したJDBCの基本的な処理の流れ(Connection取得→SQL実行→ResultSet取得→クローズ)を、これまでインメモリのListで実装してきたInquiryデータの保存処理と比較し、両者の違いをノートに整理してください。また、自分のプロジェクトのpom.xmlにH2の依存関係が追加されていること、application.propertiesにspring.datasource.urlとspring.h2.console.enabled=trueが設定されていることを確認し、実際にH2コンソールへアクセスして、schema.sqlで作成したinquiryテーブルの構造(カラム名・型)を確認してください。

◆次回授業の予習
次回のコマ22では、JdbcTemplateを用いて実際にINSERT文とSELECT文を実行し、お問い合わせデータをH2データベースに永続化する実装を行います。これまでService層で扱ってきたList<Inquiry>への追加・取得の処理が、データベースへの保存・検索の処理にどのように置き換わるのか、事前にコード上のどこを変更する必要がありそうか予想してきてください。

22 JdbcTemplateによるデータ永続化 科目の中での位置付け 前回のコマ21では、JDBCの役割とH2データベースの導入、そしてJdbcTemplateが定型処理を簡略化する仕組みの概要を学習した。本コマでは、その理解を踏まえて実際にJdbcTemplateのメソッドを用いたSQL実行のコードを記述し、これまでインメモリのListとして保持してきたお問い合わせデータの管理方式を、H2データベースへの永続化に置き換える実装演習を行う。INSERT文とSELECT文をそれぞれJdbcTemplateのupdateメソッドとqueryメソッドで実行する方法を習得し、アプリケーションを再起動してもデータが失われないことを実際に確認することで、データベース永続化の意義を体感する。
コマ主題細目 ① INSERT文・SELECT文の実行(JdbcTemplateの具体的なメソッド) ② インメモリのListを廃止し、H2+JdbcTemplateでお問い合わせデータを永続化する実装 ③ アプリケーション再起動後もデータが消えないことの確認
細目レベル ① 本細目では、JdbcTemplateクラスが提供する具体的なメソッドを用いて、SQL文の実行方法を実践的に学習する。データを新規登録するINSERT文の実行には、JdbcTemplateのupdateメソッドを使用する。updateメソッドの第一引数にはプレースホルダ(?)を含んだSQL文字列を、第二引数以降には可変長引数としてプレースホルダに対応する値を渡す。たとえば、顧客名・メールアドレス・お問い合わせ内容・対応状況・受付日時をinquiryテーブルへ挿入する場合、"INSERT INTO inquiry (customer_name, email, content, status, received_at) VALUES (?, ?, ?, ?, ?)"というSQL文とともに、Inquiryオブジェクトの各フィールドの値を順番に渡す。プレースホルダを用いることで、SQL文中に値を直接文字列結合する場合に比べてSQLインジェクションのリスクを避けられる点も重要な学習ポイントである。

一方、データを取得するSELECT文の実行には、戻り値の件数に応じてqueryメソッドとqueryForObjectメソッドを使い分ける。一覧画面のようにお問い合わせデータを複数件取得する場合はqueryメソッドを用い、第二引数にRowMapperを渡すことでResultSetの各行をInquiryオブジェクトへ変換したList<Inquiry>を受け取る。RowMapperは、ResultSetとその行番号(rowNum)を引数に取り、rs.getString("customer_name")やrs.getTimestamp("received_at")といったメソッドで各カラムの値を取得し、Inquiryオブジェクトを組み立てて返すラムダ式またはインターフェース実装として記述する。IDを指定して1件だけ取得する場合にはqueryForObjectメソッドを用い、該当データが存在しない場合の例外処理(EmptyResultDataAccessException)についても触れる。

これらのメソッドをRepositoryクラス(例:InquiryJdbcRepository)にまとめ、Service層からはこのRepositoryのメソッドを呼び出すだけでデータベース操作が完結するように設計する。この構成により、Controller・Service層のコードはデータの保存先がインメモリのListであってもデータベースであっても変更を受けにくくなる。この細目で理解すべき範囲は、updateメソッドによるINSERT実行、query・queryForObjectメソッドによるSELECT実行、およびRowMapperによる結果の変換方法まで。

② 本細目では、これまでService層のフィールドとして保持してきたList<Inquiry>を廃止し、データの保存先を完全にH2データベースへ置き換える実装演習を行う。まず、これまでList<Inquiry>に対してaddメソッドやgetメソッドを呼び出す形で実装されていたInquiryServiceクラスのコードを確認し、その内部実装をInquiryJdbcRepositoryクラスへの委譲に書き換える。ServiceクラスにInquiryJdbcRepositoryをDI(コンストラクタインジェクション)で注入し、たとえばregisterメソッドの内部で行っていたlist.add(inquiry)という処理を、repository.insert(inquiry)という呼び出しに置き換える。

同様に、一覧を取得するfindAllメソッドについても、これまでlistをそのまま返していた処理を、repository.findAll()としてJdbcTemplateのqueryメソッドを呼び出す処理に置き換える。この際、Controller層のコードは一切変更する必要がない点に注目させたい。Controllerは常にInquiryServiceのメソッドを呼び出しているだけであり、Serviceの内部実装がListからデータベースアクセスに変わっても、Controllerから見えるインターフェースは変化しないためである。これは、コマ15〜16で学習したService層への責務分離が、実装の差し替えに対する柔軟性という形で効果を発揮する具体例である。

実装が完了したら、実際にアプリケーションを起動し、お問い合わせフォームから複数件のデータを登録し、一覧画面に正しく表示されることを確認する。あわせてH2コンソールを開き、inquiryテーブルに実際にレコードが格納されていることをSELECT文で直接確認する作業も行う。この細目で理解すべき範囲は、Service層におけるList操作からRepository呼び出しへの置き換え方法、コンストラクタインジェクションによるRepositoryの注入、およびController層への影響がないことの確認まで。

③ 本細目では、今回の実装によってお問い合わせデータの永続化がどこまで達成されたのかを、実際にアプリケーションを再起動して検証する。まず、アプリケーションを起動した状態でお問い合わせフォームから新規データを2〜3件登録し、一覧画面に反映されることを確認する。次に、IntelliJ IDEAの実行を一旦停止し、再度アプリケーションを起動し直す。この状態で一覧画面へアクセスし、先ほど登録したデータが引き続き表示されることを確認できれば、インメモリのListからH2データベースへの置き換えが正しく機能していることの証左となる。

ここで重要なのは、現時点のH2の設定がインメモリモード(jdbc:h2:mem:testdb)である場合、アプリケーションプロセス自体を終了させるとH2のデータも失われるという点である。したがってこの確認作業で示せるのは、あくまで「アプリケーションの実行を継続したまま画面遷移や再読み込みを行ってもデータが消えない」という永続化の効果であり、コンテナやマシン自体の再起動を跨いだ永続化を望む場合は、H2をファイルモード(jdbc:h2:file:)やPostgreSQL等の永続型DBMSへ切り替える必要があることにも触れる。この違いを正しく理解することが、次のフェーズでの本格的なDB設計にもつながる。

最後に、フェーズ3全体を通じて積み上げてきた「素朴な実装から段階的に整備していく」という学習の流れを振り返る。コマ15〜16でService層に切り出し、コマ18〜19でセッションによるログイン制御を加え、コマ20〜21でバリデーションを整備し、そして今回JDBCによるデータ永続化を実現したことで、お問い合わせ管理システムはインメモリの試作段階から、実務的なWebアプリケーションの土台へと着実に近づいている。この細目で理解すべき範囲は、再起動確認の具体的な手順、インメモリモードとファイルモードの違い、およびフェーズ3を通じた実装の積み上げの全体像まで。

キーワード ① INSERT文 ② SELECT文 ③ RowMapper ④ Repositoryクラス ⑤ データ永続化
コマの展開方法 社会人講師 AL ICT PowerPoint・Keynote 教科書
コマ用オリジナル配布資料 コマ用プリント配布資料 その他 該当なし
小テスト 授業時間内に、LMS上において該当コマの小テストを実施する。
復習・予習課題 ◆今回授業の復習
今回実装したInquiryJdbcRepositoryクラスのコードを見直し、insertメソッド内のINSERT文とプレースホルダの対応関係、およびfindAllメソッド内のRowMapperがResultSetの各カラムをInquiryオブジェクトのどのフィールドに対応させているかを、コメントを付けながら整理してください。また、実際にアプリケーションを再起動してデータが保持されていることを確認した手順を振り返り、なぜインメモリのList方式では実現できなかった動作なのかを自分の言葉で説明できるようにしてください。

◆次回授業の予習
次回のコマ23では、今回自分たちの手で書いたJDBCのコードを踏まえたうえで、O/Rマッパーおよびspring Data JPAという、これをさらに簡略化する仕組みを学習します。今回SQL文やRowMapperを自分で記述した経験を思い出しながら、「この定型作業をフレームワークが自動化してくれるとしたら、どの部分が省略できそうか」を予想してきてください。

23 Repositoryパターンの基礎とJPAの概念 科目の中での位置付け コマ21〜22では、JdbcTemplateを用いて自らSQL文とRowMapperを記述し、お問い合わせデータをH2データベースへ永続化する仕組みを実装した。この経験を通じて、INSERT文やSELECT文、ResultSetからのオブジェクト変換といった定型作業がいかに繰り返し発生するかを体感できたはずである。本コマでは、こうした定型作業をさらに自動化するO/Rマッパーの考え方と、その代表的な実装であるJPA(Java Persistence API)の概念、そしてSpring Data JPAが提供するJpaRepositoryインターフェースの基本を学習する。次回のコマ24で行う実際の置き換え作業に向けた理論的な土台を固める回である。
コマ主題細目 ① O/RマッパーとRepositoryパターンの概念 ② JPA(Java Persistence API)とEntityのマッピングの仕組み ③ JpaRepositoryインターフェースの基本
細目レベル ① 本細目では、リレーショナルデータベースのテーブルとJavaのオブジェクトとの間に存在する構造的なギャップと、それを埋めるO/Rマッパー(Object-Relational Mapper)の役割について学習する。前回までの実装で扱ったinquiryテーブルの各行(レコード)と、Inquiryクラスのインスタンスは、概念的には同じ情報を表しているにもかかわらず、テーブルの行は列と値の集合、オブジェクトはフィールドとメソッドの集合という異なる形式で表現される。この違いを「インピーダンスミスマッチ」と呼び、JdbcTemplateのRowMapperで行っていた変換処理は、まさにこのミスマッチを人手で解消する作業であったことを振り返る。

O/Rマッパーは、この変換作業をフレームワーク側で自動化する仕組みである。テーブルの各カラムとJavaクラスの各フィールドとの対応関係(マッピング)をあらかじめ設定しておけば、SQL文やResultSetの操作をほとんど意識することなく、オブジェクトを保存・取得できるようになる。あわせて、データアクセスのロジックをRepositoryという専用のクラス(またはインターフェース)に集約するRepositoryパターンについても解説する。Repositoryパターンでは、Service層は「データをどこにどう保存するか」というデータベース固有の詳細を知る必要がなく、Repositoryが提供する抽象化されたメソッド(save、findByIdなど)を呼び出すだけでよいという設計上の利点がある。

前回コマ22で作成したInquiryJdbcRepositoryクラスも、このRepositoryパターンの一形態であったことを確認し、次の細目以降で学ぶJPAとJpaRepositoryが、このパターンをさらに洗練させ、インターフェースの宣言だけで実装コードの記述すら不要にする仕組みであることへの橋渡しとする。この細目で理解すべき範囲は、インピーダンスミスマッチの概念、O/Rマッパーが解決する課題、およびRepositoryパターンの設計思想まで。

② 本細目では、JavaにおけるO/Rマッピングの標準仕様であるJPA(Java Persistence API)の概念と、そのマッピングの仕組みについて学習する。JPAはあくまで「仕様(インターフェースの集合)」であり、実際の処理を行う実装はHibernateなどのJPAプロバイダが担う。Spring Bootでspring-boot-starter-data-jpaという依存関係を追加すると、標準の実装としてHibernateが組み込まれ、開発者はJPAが定めたアノテーションを用いるだけでO/Rマッピングの恩恵を受けられるようになる。

JPAによるマッピングの中心となるのが@Entityアノテーションである。これまでのInquiryクラスに@Entityを付与し、対応するテーブル名を明示する@Table(name = "inquiry")、主キーを示す@Id、主キーの自動採番方法を指定する@GeneratedValueといったアノテーションを追加することで、Javaクラスとデータベーステーブルとの対応関係を宣言的に記述できる。各フィールドについても、カラム名を明示したい場合は@Columnアノテーションを用いる。これらのアノテーションにより、これまでschema.sqlで手動定義していたテーブル構造とInquiryクラスの対応関係が、Javaのコード側から一元的に管理できるようになる点が大きな特徴である。

また、JPAの内部でエンティティのライフサイクル(永続化状態の管理)を担うEntityManagerという仕組みにも軽く触れ、Spring Data JPAがこのEntityManagerをさらに抽象化し、開発者がほとんど意識せずに済むよう設計されていることを説明する。この細目で理解すべき範囲は、JPAとHibernateの関係、@Entity・@Id・@GeneratedValue・@Columnといった主要アノテーションの役割、およびEntityManagerの位置づけまで。

③ 本細目では、Spring Data JPAが提供するJpaRepositoryインターフェースの基本的な使い方について学習する。JpaRepositoryは、Spring Data JPAが用意する汎用的なリポジトリインターフェースであり、開発者は「public interface InquiryRepository extends JpaRepository<Inquiry, Long>」のように、対象のEntityクラスと主キーの型を型パラメータとして指定したインターフェースを宣言するだけでよい。驚くべきことに、このインターフェースにはメソッドの実装を一切記述する必要がない。

これは、Spring Data JPAがアプリケーション起動時にこのインターフェースを検出し、実行時に自動的に実装クラスを生成してDIコンテナへBeanとして登録する仕組みによるものである。JpaRepositoryを継承するだけで、save(保存・更新)、findById(主キーによる1件取得)、findAll(全件取得)、deleteById(削除)といった基本的なCRUD操作のメソッド群が、実装コードなしにそのまま利用可能になる。前回コマ22で自分たちの手でinsertメソッドやfindAllメソッドを実装したことを踏まえると、この「インターフェースを書くだけで実装が手に入る」という体験がいかに大きな省力化であるかを実感しやすい。

さらに、findByステータスのような命名規則に従ったメソッド(例:List<Inquiry> findByStatus(String status))をインターフェースに宣言するだけで、Spring Data JPAがメソッド名を解析してSQLに相当する処理を自動生成する「クエリメソッド」の仕組みについても概要を紹介する。次回のコマ24では、これらのJpaRepositoryの機能を実際にプロジェクトへ組み込み、これまでのJDBCベタ書きの実装を置き換えていく。この細目で理解すべき範囲は、JpaRepositoryインターフェースの宣言方法、標準で利用可能なCRUDメソッドの種類、およびクエリメソッドの基本的な考え方まで。

キーワード ① O/Rマッパー ② インピーダンスミスマッチ ③ Entity ④ JPA ⑤ JpaRepository
コマの展開方法 社会人講師 AL ICT PowerPoint・Keynote 教科書
コマ用オリジナル配布資料 コマ用プリント配布資料 その他 該当なし
小テスト 授業時間内に、LMS上において該当コマの小テストを実施する。
復習・予習課題 ◆今回授業の復習
今回学習したO/Rマッパーの考え方について、前回コマ22で自分が実装したRowMapperのコードを見直し、「どの部分がインピーダンスミスマッチの解消にあたる作業だったか」を具体的に書き出してください。また、@Entity、@Id、@GeneratedValue、@Columnという4つのアノテーションについて、それぞれがInquiryクラスとinquiryテーブルのどの要素に対応するのかを、図やノートに整理して説明できるようにしてください。

◆次回授業の予習
次回のコマ24では、今回学んだJpaRepositoryを実際のプロジェクトへ導入し、これまでJDBCで自作していたInquiryJdbcRepositoryをJpaRepositoryへ置き換える演習を行います。あわせてLombokによる@Data等のアノテーションでEntityクラスのコンストラクタ・getter/setterを自動生成する方法も学びます。JPAのEntityにgetter/setterが必須である理由を、前回のマッピングの仕組みから予想してきてください。

24 JDBCからJPAへの置き換えとLombok導入 科目の中での位置付け 前回コマ23では、O/RマッパーとJPAの概念、そしてJpaRepositoryインターフェースの基本を理論面から学習した。本コマでは、いよいよ実際のプロジェクトにおいて、コマ21〜22で自作したJDBCベタ書きのInquiryJdbcRepositoryを、Spring Data JPAのJpaRepositoryへ置き換える演習を行う。あわせて、Entityクラスのボイラープレートを削減するLombokの本格導入も行い、フレームワークによる開発効率化を体感する。本コマはフェーズ3(コマ15〜24)の最終回でもあり、これまでの学習内容を振り返りながら、次のフェーズ4で取り組む本格的なCRUD実装への橋渡しとする位置づけを持つ。
コマ主題細目 ① JpaRepositoryを用いたCRUD操作の実践 ② Lombokの導入(@Data @NoArgsConstructor @AllArgsConstructor) ③ フェーズ3の振り返りとフェーズ4への橋渡し
細目レベル ① 本細目では、コマ21〜22で作成したInquiryJdbcRepositoryクラスを、JpaRepositoryを継承したInquiryRepositoryインターフェースへ実際に置き換える演習を行う。まず、Inquiryクラスに@Entity、@Table、@Id、@GeneratedValueといったアノテーションを付与し、前回学習したマッピングの仕組みに従ってEntityクラスとして整備する。次に、「public interface InquiryRepository extends JpaRepository<Inquiry, Long>」というインターフェースを新規に作成し、これまでInquiryJdbcRepositoryが提供していたinsertメソッドやfindAllメソッドを、JpaRepositoryが標準で提供するsaveメソッドやfindAllメソッドに置き換えていく。

この置き換え作業を通じて、InquiryServiceクラスの内部で呼び出していたrepository.insert(inquiry)という処理がrepository.save(inquiry)に、repository.findAll()という処理がそのままJpaRepositoryのfindAll()に変わるだけで、これまで自分たちで記述していたSQL文・PreparedStatementへのパラメータ設定・RowMapperによる変換処理が、コードとしては一切不要になることを確認する。実際にコードの行数を比較し、JDBCベタ書きの実装が数十行を要していた処理が、JpaRepositoryではインターフェースの宣言のみ(実質1行)で完結する様子を目の当たりにすることで、フレームワークが提供する抽象化の価値を体感できる。

あわせて、対応状況で絞り込む処理を想定し、findByStatusのようなクエリメソッドを実際にInquiryRepositoryへ追加してみる演習も行い、コマ23で学んだ命名規則による自動SQL生成の仕組みを実践レベルで確認する。この細目で理解すべき範囲は、EntityクラスへのJPAアノテーション付与、JpaRepositoryインターフェースの作成、およびJDBC実装からJpaRepository呼び出しへの置き換え手順まで。

② 本細目では、Entityクラスのボイラープレートコードを大幅に削減するLombokの本格的な導入について学習する。Lombok自体はコマ7のSpring Initializrの時点で依存関係にチェック済みであったが、これまで意図的に本格利用は見送ってきた。今回JPAの@Entityクラスとして整備したInquiryクラスは、仕様上、引数なしコンストラクタ(JPAがEntityをインスタンス化する際に必要)、全フィールドを引数に取るコンストラクタ、そして全フィールドに対するgetter・setterのフルセットが必要になり、フィールドが5つあるだけでも数十行のコードが発生する。ここでようやくLombokのインパクトが最も伝わりやすい場面が訪れる。

具体的には、Inquiryクラスに@Data、@NoArgsConstructor、@AllArgsConstructorという3つのアノテーションを付与するだけで、これまで手書きしていた全フィールドのgetter・setter、引数なしコンストラクタ、全フィールドを引数に取るコンストラクタ、さらにはtoString・equals・hashCodeメソッドまでもが、コンパイル時に自動生成されるようになる。@Dataはgetter・setter・toString・equals・hashCodeをまとめて生成するアノテーションであり、@NoArgsConstructorと@AllArgsConstructorをあわせて付与することで、JPAが要求するコンストラクタのフルセットも同時に満たせる。

実際にこれらのアノテーションを付与した後、これまで手書きまたはIDEの自動生成機能で作成していたgetter・setterのコードをすべて削除し、それでもコンパイルが通り、アプリケーションが問題なく動作することを確認する。この作業を通じて、コマ9〜13の頃に手書きで経験したgetter・setterの記述量を思い出しながら、Lombokがその作業をどれほど省力化するかを実感を伴って理解できる。この細目で理解すべき範囲は、Lombok導入の必然性(JPAが要求するボイラープレートの増加)、@Data・@NoArgsConstructor・@AllArgsConstructorそれぞれの役割、および導入後のコード削減効果まで。

③ 本細目では、コマ15から本コマ24までのフェーズ3全体を振り返り、お問い合わせ管理システムがどのように発展してきたかを整理する。フェーズ3の冒頭では、Controllerに直接書かれていた処理をServiceクラスへ切り出すDIの基礎とJavaConfigによるBean定義を学び、続いてセッションを用いた手作りのログイン機能によってアプリケーションに認証という概念を導入した。さらにバリデーションの実装によって、不正な入力データがそもそもEntityへ届かない仕組みを整え、そして今回のコマ21〜24にかけて、インメモリのListから始まったデータ保持の方式を、JDBCによる自作の永続化処理を経て、最終的にJpaRepositoryによる宣言的な実装へと発展させた。

この一連の流れは、「まず素朴な方法で仕組みを自分の手で実装し、その大変さを体感したうえで、フレームワークがそれをどう解決してくれるのかを学ぶ」という、本科目全体を貫く教育方針の集大成である。特にJDBC(コマ21〜22)からJPA(コマ23〜24)への置き換えは、SQL文やRowMapperを自分で書く作業がインターフェースの宣言だけに置き換わるという、フェーズ3の中でも最もフレームワークの価値を実感しやすい体験であったはずである。

フェーズ4(コマ25以降)では、ここまで整えてきたJpaRepositoryとLombok対応済みのEntityを土台として、登録・検索・更新・削除という本格的なCRUD機能一式を実装していく。これまでは一覧表示と新規登録が中心であったが、次回以降は編集画面への遷移、更新処理の実装、削除確認画面の追加など、実務的なWebアプリケーションとして求められる操作を一通り揃えていくことになる。この細目で理解すべき範囲は、フェーズ3を通じた実装の発展の流れ、JDBCからJPAへの置き換えが持つ教育上の意味、およびフェーズ4で取り組むCRUD実装の全体像まで。

キーワード ① JpaRepository ② Lombok ③ @Data ④ ボイラープレート ⑤ CRUD実装
コマの展開方法 社会人講師 AL ICT PowerPoint・Keynote 教科書
コマ用オリジナル配布資料 コマ用プリント配布資料 その他 該当なし
小テスト 授業時間内に、LMS上において該当コマの小テストを実施する。
復習・予習課題 ◆今回授業の復習
今回の置き換え作業によって、InquiryJdbcRepositoryクラスの内部で記述していたSQL文・PreparedStatementへのパラメータ設定・RowMapperによる変換処理が、JpaRepositoryのどのメソッド呼び出しに対応するのかを一つずつ表にまとめてください。また、Inquiryクラスに@Data、@NoArgsConstructor、@AllArgsConstructorを付与する前後でコードの行数がどれだけ変化したかを実際に数え、Lombokによる削減効果を数値で確認してください。

◆次回授業の予習
フェーズ4では、いよいよお問い合わせ管理システムの本格的なCRUD機能(登録・検索・更新・削除)を作り込んでいきます。次回のコマ25〜26では、これまで整備したJpaRepositoryとEntityを土台に、お問い合わせの登録機能と検索機能を実装します。更新や削除の際にはどのようにデータを特定すればよいか、主キーであるIDの役割を意識しながら予習してきてください。

25 CRUDアプリケーション全体設計とエンティティ・リポジトリ 科目の中での位置付け フェーズ4の初回である本コマから、フェーズ3までに整えたJPA・ログイン・バリデーションという土台の上に、本格的なCRUD(Create・Read・Update・Delete)アプリケーションを構築していく。次回と合わせた2回構成の1回目にあたる今回は、実装に先立ってCRUDアプリケーション全体のアーキテクチャを設計し、Inquiryエンティティとリポジトリ(JpaRepository)の整備、および対応状況などの検索条件の設計方針を確認する。全体像を俯瞰してから着手することで、以降のController・Service実装が迷いなく進められるようにする。
コマ主題細目 ① CRUDアプリケーション全体設計の考え方 ② Inquiryエンティティとリポジトリ(JpaRepository)の整備 ③ 検索条件(対応状況など)の設計
細目レベル ① 本細目では、これから2コマかけて実装するCRUDアプリケーション全体の設計方針を確認する。これまでの授業では一覧表示や登録フォームの表示など、個別の画面を単発で作成してきたが、実務でのアプリケーション開発では、一覧・詳細・登録・更新・削除という一連の操作が互いに連携し、1つのEntityに対する統一的な操作群として提供される。本コマではまず、お問い合わせ管理システムにおいてどのようなURL設計・画面遷移が必要になるかを整理する。具体的には、一覧兼検索画面(/inquiries)、登録画面(/inquiries/new)、登録処理(POST /inquiries)、更新画面(/inquiries/{id}/edit)、更新処理(POST /inquiries/{id})、削除処理(POST /inquiries/{id}/delete)といった、RESTfulな設計を意識したURLパターンを一覧表に整理し、それぞれがどのControllerメソッドに対応するかを対応付ける。また、これまで学んだController・Service・Repositoryの3層構造を、CRUD全体を通してどのように使い分けるかを改めて確認する。Controllerはリクエストの受付とレスポンスの決定に専念し、業務ロジックの詳細やトランザクション制御はServiceに委譲し、データベースとのやり取りはRepositoryに一任するという役割分担を、具体的なメソッドシグネチャを例に説明する。たとえば一覧表示であればInquiryController#list()がInquiryService#findAll()を呼び出し、登録であればInquiryController#create()がバリデーション済みのFormをServiceへ渡してEntity保存を依頼する、といった具体的な呼び出しの流れを図示しながら説明する。さらに、フェーズ2〜3で学んだPRGパターンやForm-Backing Beanの考え方もCRUD全体を貫く共通ルールとして機能することを確認し、登録・更新という「状態を変更する処理」では必ずリダイレクトを経由して画面を再表示する設計にする方針を、次回以降の実装に向けて明示しておく。この設計を先に固めておくことで、次回以降の実装がどの層にどのコードを書くべきかで迷わずに進められるようになる。この細目で理解すべき範囲は、CRUDアプリケーションに必要なURL設計とController・Service・Repositoryの役割分担、およびPRGパターンをCRUD全体に適用する方針まで。
② 本細目では、お問い合わせ管理システムの中心となるInquiryエンティティと、そのデータアクセスを担うリポジトリを整備する。フェーズ3のコマ23〜24で作成したInquiryエンティティを見直し、CRUD実装に必要なフィールドが揃っているかを確認する。具体的には、@Entityと@Idを付与した主キー(id、@GeneratedValueによる自動採番)に加え、顧客名(customerName)、メールアドレス(email)、お問い合わせ内容(content)、対応状況(status)、受付日時(receivedAt)の各フィールドを持つクラスとし、@Data、@NoArgsConstructor、@AllArgsConstructorといったLombokのアノテーションを付与してボイラープレートコードを削減する。対応状況については、単純な文字列ではなく「未対応」「対応中」「対応済み」を表すenum型(StatusなどのInner Enum)として定義し、@Enumeratedアノテーションでデータベースへの保存方法(EnumType.STRING推奨)を指定する設計を紹介する。文字列ではなくenumを採用する理由として、「みたいほう」や「たいおうちゅう」のような誤字混入を型レベルで防止できる点、および画面側でswitch式やThymeleafのth:switchと組み合わせて表示を分岐しやすくなる点を挙げ、対応状況というドメイン知識をコードとして表現することの意義を説明する。続いてInquiryRepositoryインターフェースを取り上げ、JpaRepository(Inquiryクラス、主キー型Long)を継承するだけで、save、findById、findAll、deleteByIdといった基本的なCRUDメソッドがフレームワークによって自動実装される仕組みを、フェーズ3で学んだJPAの復習を交えながら再確認する。あわせて、@Repositoryアノテーションを個別に付与する必要がなく、JpaRepositoryを継承したインターフェースはSpring Data JPAによって自動的にBean登録される点も、DIコンテナの仕組みと関連付けて解説する。この細目で理解すべき範囲は、Inquiryエンティティのフィールド設計とenumによる対応状況の表現、およびJpaRepositoryの継承によるCRUDメソッド自動生成の仕組みまで。
③ 本細目では、次回実装する検索機能に備えて、対応状況による絞り込み検索の設計を行う。まず、検索機能がなぜ必要かを、お問い合わせ件数が増えていくシステムの運用イメージから説明する。「未対応のお問い合わせだけを一覧表示したい」という業務上の要求に応えるため、対応状況をキーとした検索条件を設計する。実装方法としては、JpaRepositoryのメソッド名からクエリを自動生成する仕組みを活用し、findByStatusというメソッドをInquiryRepositoryに宣言するだけで、「WHERE status = ?」に相当するSQLがSpring Data JPAによって自動生成されることを説明する。このメソッド名解析の仕組みは、フィールド名とキーワード(By、And、OrderByなど)を組み合わせるだけでSQLを書かずに条件検索ができるという、JPAならではの生産性の高さを実感できる好例であるため、findByCustomerNameContainingのような部分一致検索への発展例も軽く紹介し、今後の拡張の可能性についてイメージを持たせる。また、「すべて」を選んだ場合には絞り込みを行わずfindAllを呼び出す必要があるため、検索条件が未指定(null)の場合と指定された場合とで呼び分けるController側の分岐ロジックについても、疑似コードを交えて設計方針を示す。あわせて、検索フォームの入力値を受け取るためのSearchFormクラス(statusフィールドを持つ簡易なForm-Backing Bean)を用意する方針も確認し、次回のControllerメソッド実装にそのまま接続できるようにしておく。さらに、検索条件をURLのクエリパラメータ(例:/inquiries?status=未対応)として渡す設計とすることで、検索結果画面をブックマークしたり再読み込みしたりしても条件が保持されるという、GETリクエストならではの利点についても触れておく。この細目で理解すべき範囲は、findByStatusによるメソッド名からのクエリ自動生成の仕組みと、検索条件の有無によるController側の分岐設計、およびSearchFormによる検索条件の受け渡し方針まで。
キーワード ① JpaRepository ② エンティティ設計 ③ enum型 ④ メソッド名クエリ ⑤ URL設計
コマの展開方法 社会人講師 AL ICT PowerPoint・Keynote 教科書
コマ用オリジナル配布資料 コマ用プリント配布資料 その他 該当なし
小テスト 授業時間内に、LMS上において該当コマの小テストを実施する。
復習・予習課題 ◆今回授業の復習
本日整理したお問い合わせ管理システムのURL設計表(一覧・登録・更新・削除の各URLとHTTPメソッド、対応するControllerメソッド名)を、自分のノートまたはテキストエディタに書き出して整理してください。あわせて、InquiryエンティティにLombokの各アノテーションを付与し、対応状況をenumとして定義し直したうえで、InquiryRepositoryがJpaRepositoryを継承した状態になっていることをIDE上で確認しておいてください。

◆次回授業の予習
次回は、本日設計したURLと検索条件をもとに、実際に登録機能と検索機能をControllerに実装します。フェーズ3で学んだ@Valid・BindingResultによるバリデーションの流れ(コマ19〜20)を軽く見直しておくと、登録処理へのバリデーション統合がスムーズに理解できます。また、本日整理した検索用URL(/inquiries?status=対応中 のようなクエリパラメータ付きURL)の形式を、ブラウザのアドレスバーに実際に打ち込むとどう見えるか、頭の中でイメージしておいてください。

26 登録機能・検索機能の実装 科目の中での位置付け 前回設計したURL構成とInquiryエンティティ・リポジトリを土台に、本コマでは「25〜26. CRUDアプリ実装①(登録・検索)」の2回目として、お問い合わせの登録機能と検索機能を実際にコードとして実装する。登録処理では、フェーズ3で学んだ@Valid・BindingResultによるバリデーションをそのまま統合し、検索処理では、対応状況によるフィルタ検索をInquiryRepositoryのメソッドを用いて実現する。実装後は必ずブラウザで動作確認を行い、登録データが一覧に反映されること、検索条件によって表示件数が変化することを自分の目で確かめる。
コマ主題細目 ① お問い合わせの登録機能の実装(バリデーション統合) ② 検索機能の実装(対応状況によるフィルタ検索) ③ 動作確認
細目レベル ① 本細目では、お問い合わせ登録画面から送信されたデータを受け取り、データベースに保存するまでの一連の処理を実装する。まず、InquiryFormクラス(顧客名・メールアドレス・お問い合わせ内容の各フィールドを持つForm-Backing Bean)に対して、フェーズ3のコマ19〜20で学んだ@NotBlank、@Size、@Emailといったアノテーションを付与し、入力チェックのルールを定義する。続いてInquiryController#create()メソッドを実装し、引数に@Validated InquiryForm form, BindingResult resultを受け取る形とする。メソッド内ではまずresult.hasErrors()を判定し、エラーがあれば登録画面テンプレートへフォワードして再入力を促し、エラーがなければInquiryHelperクラス(もしくはServiceメソッド内)でFormからEntityへの変換を行う。この変換処理では、受付日時にLocalDateTime.now()を設定し、対応状況の初期値をStatus.未対応で固定するといった、画面から入力させない項目をサーバー側で補完するロジックを実装する。生成したInquiryエンティティをInquiryService#register()に渡し、Service内部でInquiryRepository#save()を呼び出して永続化する。保存が完了したら、RedirectAttributesを用いてフラッシュメッセージ「お問い合わせを登録しました」をセットし、一覧画面へリダイレクトする、というPRGパターンに沿った処理の流れを完成させる。なお、対応状況やidのように画面から送信されるべきでない項目を、念のためFormクラスに含めない設計とすることで、悪意ある入力によって意図しない値が上書きされるリスクをあらかじめ排除しておく点にも触れる。この細目で理解すべき範囲は、InquiryFormへのバリデーションアノテーション付与、@Validatedによるバリデーション実行とBindingResultによるエラー判定、およびForm→Entity変換を経てRepositoryに保存するまでの一連の登録処理の実装まで。
② 本細目では、前回設計したfindByStatusメソッドを活用し、対応状況による絞り込み検索を一覧画面に組み込む。まずInquiryController#list()メソッドのシグネチャを見直し、@RequestParam(required = false) String statusとして検索条件を受け取れるようにする。requiredをfalseに設定することで、検索条件を指定せずに/inquiriesへアクセスした場合にもエラーとならず、全件を表示する挙動を実現できる点を確認する。メソッド内部では、statusがnullまたは空文字であればInquiryRepository#findAll()を、値が指定されていればStatus.valueOf(status)でenumに変換したうえでInquiryRepository#findByStatus()を呼び出すという分岐を実装する。取得したInquiryのリストと、選択中の検索条件をModelに追加し、一覧画面テンプレートに引き渡す。画面側では、Bootstrapのform-selectコンポーネントを用いた検索用ドロップダウンを配置し、「すべて」「未対応」「対応中」「対応済み」の各選択肢をth:eachまたは直接記述で用意し、選択済みの値をth:selectedで反映させることで、検索後も選択状態が画面に残るユーザー体験を作る。検索フォームの送信方法はGETメソッドとし、検索条件がURLのクエリパラメータとして残る設計であることを、実際にブラウザのアドレスバーを見せながら確認する。また、検索処理はデータを変更しないGETリクエストとして実装することが原則であり、POSTリクエストで実装してしまうと再読み込みのたびに二重送信の確認ダイアログが出るなど、ユーザー体験上の不都合が生じる点にも注意を促す。この細目で理解すべき範囲は、@RequestParamによる任意パラメータの受け取り方、条件の有無によるRepositoryメソッドの呼び分け、およびBootstrapのform-selectを用いた検索フォームの実装まで。
③ 本細目では、実装した登録機能と検索機能を実際に動かし、意図した通りに動作するかを確認する手順を学ぶ。まず登録機能について、正常系(すべての項目を正しく入力した場合)と異常系(必須項目を空欄にした場合、メールアドレスの形式が誤っている場合)の両方を試し、正常系では一覧画面へリダイレクトされフラッシュメッセージが表示されること、異常系では登録画面が再表示されエラーメッセージが該当項目のそばに表示されることをそれぞれ確認する。特に、フォワードとリダイレクトの違いを、ブラウザのアドレスバーのURLが変化するかどうかで見分ける方法を復習し、PRGパターンが正しく機能しているかをその場で判断できるようにする。続いて検索機能については、あらかじめ複数の対応状況を持つお問い合わせデータを登録しておき、「未対応」「対応中」「対応済み」それぞれの条件で検索した際に、件数と表示内容が正しく絞り込まれているかをデータベースの中身(H2コンソールなど)と突き合わせて検証する。また、「すべて」を選択した場合に全件が表示されることも忘れずに確認する。動作確認の過程でエラーが発生した場合は、コンソールログのスタックトレースを上から読み、どのクラスのどの行で例外が発生しているかを特定するデバッグの基本手順も、このタイミングで改めて習慣づける。さらに、対応状況の文字列をStatus.valueOf()でenumに変換する処理は、想定外の文字列が渡されるとIllegalArgumentExceptionを送出する点にも触れ、検索ドロップダウンの選択肢とenumの値を必ず一致させておく必要があることを、実際に不正な値を試して例外を発生させながら体験させる。この細目で理解すべき範囲は、登録機能における正常系・異常系それぞれの動作確認方法と、検索機能における条件別の絞り込み結果の検証方法まで。
キーワード ① バリデーション統合 ② PRGパターン ③ RequestParam ④ findByStatus ⑤ 動作確認
コマの展開方法 社会人講師 AL ICT PowerPoint・Keynote 教科書
コマ用オリジナル配布資料 コマ用プリント配布資料 その他 該当なし
小テスト 授業時間内に、LMS上において該当コマの小テストを実施する。
復習・予習課題 ◆今回授業の復習
本日実装した登録処理のコードを見返し、Controller・Form・Helper(またはService)・Repositoryのそれぞれで、どのクラスがどの責務を担っているかをノートに書き出して整理してください。また、検索フォームで対応状況を切り替えながら、URLのクエリパラメータがどう変化するかを実際に確認し、@RequestParamとの対応関係を自分の言葉で説明できるようにしておいてください。

◆次回授業の予習
次回は、本日作成した一覧・検索画面から編集画面へ遷移し、お問い合わせの更新機能を実装します。特に対応状況を「未対応」から「対応中」へ変更するといった業務上の操作をイメージしながら、既存データを編集画面に表示するにはどのような情報(idなど)をURLやフォームに含める必要があるか、事前に考えておいてください。あわせて、フェーズ2で学んだ@PathVariableの使い方(コマ12〜13)を軽く復習しておくと、編集画面のURL設計(/inquiries/{id}/edit)への理解がスムーズになります。

27 更新機能の実装 科目の中での位置付け 「27〜28. CRUDアプリ実装②(更新・削除)」の1回目にあたる本コマでは、お問い合わせの更新機能を実装する。登録機能とは異なり、更新機能では既存データを編集画面にあらかじめ表示し、変更された内容だけを反映するという、「表示」と「更新」の2段階の処理が必要になる点が大きな違いである。対応状況を「未対応」から「対応中」へ変更するといった、実務を意識した操作を題材に、編集画面への遷移、更新処理の実装、そしてPRGパターンの適用までを一貫して学ぶ。登録機能で身につけたForm・Helper・Repositoryという構成をそのまま流用できることを確認しながら実装を進め、CRUDの各機能が独立した実装ではなく、共通の設計パターンの上に成り立っていることを実感してもらう。
コマ主題細目 ① 編集画面への遷移とデータの初期表示 ② 更新処理の実装(対応状況の変更などを想定) ③ PRGパターンの適用
細目レベル ① 本細目では、一覧画面から編集画面へ遷移し、既存のお問い合わせデータをフォームにあらかじめ表示する処理を実装する。まず一覧画面テンプレートに、各行へ「編集」ボタン(Bootstrapのbtn btn-outline-primaryなど)を配置し、th:hrefで@{/inquiries/{id}/edit(id=${inquiry.id})}のようなリンクを生成する。続いてInquiryController側にGETマッピングの#edit(@PathVariable Long id, Model model)メソッドを実装し、InquiryService#findById(id)を呼び出して対象のInquiryエンティティを取得する。ここで、指定されたidのデータが存在しない場合の考慮も忘れてはならない。Optional型で返却されるfindByIdの結果に対し、orElseThrowでカスタム例外(InquiryNotFoundExceptionなど)を送出する設計を示し、存在しないIDへのアクセスという異常系にも備える姿勢を養う。取得したEntityは、そのままModelに渡すのではなく、登録時と対称的にInquiryHelperでEntityからInquiryFormへ変換したうえでModelに追加する。この変換を経由することで、登録画面と編集画面が同じInquiryFormおよび同じHTMLテンプレートを共有できるようになり、次回のコマ29で扱うテンプレート共通化の効果を最大限に活かせる設計になる。画面側では、th:valueやth:fieldを用いて各入力欄に既存データを初期表示し、対応状況についてはth:selectedを用いたセレクトボックスとして表示することで、現在の状態が一目で分かるようにする。この細目で理解すべき範囲は、@PathVariableによるidの受け取りとfindByIdによるデータ取得、Optionalを用いた存在チェック、およびEntityからFormへの変換を経た編集画面への初期データ表示まで。
② 本細目では、編集画面から送信された内容をもとに、既存のお問い合わせデータを更新する処理を実装する。InquiryController#update(@PathVariable Long id, @Validated InquiryForm form, BindingResult result)メソッドを実装し、登録処理と同様にresult.hasErrors()でバリデーションエラーを判定したうえで、エラーがある場合は編集画面を再表示し、エラーがなければ更新処理へ進む。ここで重要となるのが、更新対象のEntityをデータベースから再取得し、フォームから送られてきた値で必要なフィールドだけを上書きするという手順である。受付日時のように更新時に変更してはならない項目と、対応状況や内容のように更新の対象となる項目を明確に区別し、InquiryHelper内のupdateEntityメソッドなどで「idと受付日時は元の値を維持し、それ以外をFormの値で上書きする」というロジックを実装する。特に対応状況について、管理画面上でセレクトボックスから「対応中」を選んで保存すると、データベース上のstatusカラムがStatus.対応中に更新されることを、実際にH2コンソールで確認しながら学ぶ。更新後のEntityはInquiryRepository#save()に渡すが、このsaveメソッドは、IDが未設定であれば新規insertとして、IDが既存であればupdateとして動作するというJPAの重要な仕様も、このタイミングで改めて解説する。また、更新処理においても登録処理と同様に@Validatedによるバリデーションが機能することを確認し、「メールアドレスを空欄にして更新を試みるとエラーになる」といった具体例で、バリデーションが登録・更新の両方で一貫して働くことを体験させる。この細目で理解すべき範囲は、更新対象Entityの再取得と部分的な上書きロジックの実装、同一のsaveメソッドがinsertとupdateの両方に対応するJPAの仕様、および更新処理へのバリデーション統合まで。
③ 本細目では、更新処理においてもPRGパターン(Post-Redirect-Get)を一貫して適用する重要性を、登録処理との共通点・相違点を比較しながら再確認する。更新処理が正常に完了した場合、InquiryController#update()メソッドの最後ではreturn "redirect:/inquiries"のように、更新結果画面を直接returnするのではなく、必ず一覧画面へのリダイレクトを行う設計とする。この際、RedirectAttributesのaddFlashAttributeを用いて「お問い合わせ情報を更新しました」というフラッシュメッセージをセットし、遷移後の一覧画面にBootstrapのalert alert-successコンポーネントで表示する実装をあわせて行う。PRGパターンを適用しない場合に発生する不具合として、更新完了画面をブラウザの再読み込みボタンで再表示すると、同じ更新リクエストが二重に送信されてしまう問題を、実際に手を動かして再現し体験させる。この体験を通じて、「データを変更する処理の直後は必ずリダイレクトする」というルールが、単なる作法ではなく実害を防ぐための設計原則であることを実感させる。また、バリデーションエラーによって編集画面を再表示する場合には、リダイレクトではなくフォワード(return "inquiry/edit"など)を用いる点も、登録処理のコマ26で学んだ内容と対比しながら再確認し、「正常終了はリダイレクト、エラー時はフォワード」という使い分けを定着させる。あわせて、リダイレクト先のURLを固定文字列で記述するのではなく、Thymeleafのth:href同様にコード上でも一箇所に集約しておくと、将来URL構成を変更する際の修正箇所を最小限に抑えられるという保守性の観点にも触れておく。この細目で理解すべき範囲は、更新完了時のリダイレクトとフラッシュメッセージの実装、PRGパターンを適用しない場合の二重送信問題、および正常終了とエラー時とでリダイレクト・フォワードを使い分ける設計原則まで。
キーワード ① 編集画面遷移 ② PathVariable ③ Optional ④ 部分更新 ⑤ PRGパターン
コマの展開方法 社会人講師 AL ICT PowerPoint・Keynote 教科書
コマ用オリジナル配布資料 コマ用プリント配布資料 その他 該当なし
小テスト 授業時間内に、LMS上において該当コマの小テストを実施する。
復習・予習課題 ◆今回授業の復習
本日実装した更新処理について、編集画面表示(GET)から更新実行(POST)、そして一覧画面へのリダイレクトまでの一連のデータフローを、図に描いて整理してください。特に、どの時点でEntityがデータベースから取得され、どの時点でFormの値によって上書きされ、どの時点でsaveされるのかを、矢印を使って順を追って書き出すと理解が深まります。

◆次回授業の予習
次回は、お問い合わせデータの削除機能を実装します。削除は一度実行すると元に戻せない操作であるため、実務のシステムでは「本当に削除してよいか」を確認する画面を挟むのが一般的です。普段利用しているWebサービスで、データを削除しようとしたときにどのような確認画面やダイアログが表示されるか、身近な例を1つ思い出しておいてください。あわせて、本日の編集画面遷移で使った@PathVariableとfindByIdの組み合わせは、削除確認画面への遷移でもほぼ同じ形で再利用できるため、今回のコードを見返して構造を頭に入れておくと次回の理解が早まります。

28 削除機能の実装とバリデーション統合 科目の中での位置付け 「27〜28. CRUDアプリ実装②(更新・削除)」の2回目となる本コマでは、お問い合わせの削除機能を実装し、登録・検索・更新・削除というCRUD一式の実装をひとまず完成させる。削除は取り消しのきかない操作であるため、確認画面を挟んでからデータベースの操作を実行する設計とし、UI/UX上の配慮についても学ぶ。さらにコマ25から積み上げてきたCRUD全体を振り返り、バリデーションが登録・更新の各処理で一貫して機能していることを最終確認し、フェーズ4後半のテンプレート共通化・ページング・Security実装へとつなげる。
コマ主題細目 ① 削除機能の実装(確認画面→削除処理) ② 削除確認のUI/UX上の工夫 ③ CRUD全体を通したバリデーションとの統合確認
細目レベル ① 本細目では、お問い合わせデータを安全に削除するための一連の処理を実装する。まず一覧画面に「削除」ボタンを配置し、編集機能と同様に@{/inquiries/{id}/delete(id=${inquiry.id})}へのリンクを生成するが、ここでは即座に削除を実行するのではなく、いったん削除確認画面(GETマッピングの#confirmDelete()メソッド)を経由する設計とする。確認画面では、編集画面と同様にfindByIdで対象のInquiryを取得し、顧客名やお問い合わせ内容といった主要な情報を読み取り専用の形でModelに渡して画面に表示することで、「今から何を削除しようとしているのか」をユーザーが目視で確認できるようにする。確認画面上の「削除する」ボタンを押すと、InquiryController#delete(@PathVariable Long id)メソッドへPOSTリクエストが送信され、内部でInquiryService#delete(id)を呼び出し、さらにその中でInquiryRepository#deleteById(id)を実行して物理削除を行う。存在しないidが指定された場合には、JpaRepositoryのdeleteByIdがEmptyResultDataAccessExceptionを送出することがあるため、try-catchで補足するか、事前にexistsById()で存在確認を行うといった防御的な実装についても紹介する。削除処理はデータベースへの変更操作であるため、確認画面からの遷移だけでなくGETリクエストによる誤った削除実行を防ぐために、削除実行そのものは必ずPOST(またはフォーム経由)で行うという原則を徹底する。この細目で理解すべき範囲は、確認画面を経由した削除フローの設計、deleteByIdによる物理削除の実装、および存在しないidへの削除リクエストに対する防御的な実装まで。
② 本細目では、削除確認画面をより使いやすく、誤操作を防ぎやすい画面にするためのUI/UX上の工夫を、Bootstrap 5の標準コンポーネントを使って実現する方法を学ぶ。まず、削除確認画面全体をcardコンポーネントで囲み、card-header部分に「以下のお問い合わせを削除します」という見出しを、card-body部分に対象データの詳細を表形式(tableコンポーネント)で表示する構成とする。削除ボタンについては、通常のボタンと視覚的に区別できるようbtn btn-dangerクラスを付与し、誤って押しても後戻りできる「キャンセル」ボタン(一覧画面へのth:hrefリンク、btn btn-secondary)を隣に並べて配置することで、ユーザーが削除の是非を落ち着いて判断できるレイアウトにする。さらに発展的な工夫として、確認画面へ遷移せずJavaScriptのconfirm()関数を用いて一覧画面上でダイアログ表示のみを行う簡易な方式と、本コマで実装するサーバーサイドの確認画面方式との違いを比較し、後者の方が削除対象の詳細を正確に提示できる、画面遷移の履歴が残るためユーザーの操作をログとして追いやすいといった利点を持つことを説明する。こうした細部の配慮が、システム全体の「本格的なアプリケーションらしさ」を作り出すことを、実際の画面を見せながら実感してもらう。あわせて、削除完了後の一覧画面にもRedirectAttributesを用いたフラッシュメッセージを表示し、「お問い合わせを削除しました」という結果がひと目で分かるようにすることで、登録・更新と同様のフィードバック設計を削除処理にも一貫して適用する重要性を確認する。この細目で理解すべき範囲は、Bootstrapのcard・table・btn-dangerを用いた削除確認画面のレイアウト実装と、確認画面方式とconfirm()方式のUI/UX上の違いまで。
③ 本細目では、コマ25から本コマまでの4回にわたって構築してきたCRUD一式について、特にバリデーションが各機能でどのように一貫して機能しているかを総復習の形で確認する。登録処理(コマ26)ではInquiryFormに付与した@NotBlank・@Size・@Emailが新規入力時のチェックとして機能し、更新処理(コマ27)では同じFormクラスと同じバリデーションルールが編集時にも適用されることを、実際に更新画面で不正な値を入力してエラーが表示されることを再現しながら確認する。一方で削除処理には入力フォームが存在しないため、バリデーションの対象とはならない点も明確に整理し、「バリデーションは入力を伴う登録・更新に対して働く仕組みである」という理解を定着させる。また、CRUD全体を俯瞰して、Controller・Form・Helper・Service・Repositoryという各層が登録・検索・更新・削除のそれぞれでどのように連携しているかを、一枚の構成図としてまとめる作業を行う。この図式化を通じて、次回のコマ29で学ぶテンプレート共通化やフェーズ4後半のページング・Security機能が、このCRUD基盤の上にどのように積み重なっていくのかを見通せるようにしておく。さらに、現時点でのCRUDアプリケーションがすでに、一覧・検索・登録・更新・削除という業務システムに必要な基本操作を一通り備えていることを確認し、フェーズ4後半では画面の見た目や利便性(テンプレート共通化、ページング)、そして安全性(Spring Security)を高めていく段階に入ることを見通しとして共有する。この細目で理解すべき範囲は、登録・更新処理におけるバリデーションの一貫した適用の確認、削除処理がバリデーション対象外である理由、およびCRUD全体のController・Form・Helper・Service・Repositoryの連携構成の整理まで。
キーワード ① 削除確認画面 ② deleteById ③ UI/UX ④ Bootstrapカード ⑤ CRUD統合
コマの展開方法 社会人講師 AL ICT PowerPoint・Keynote 教科書
コマ用オリジナル配布資料 コマ用プリント配布資料 その他 該当なし
小テスト 授業時間内に、LMS上において該当コマの小テストを実施する。
復習・予習課題 ◆今回授業の復習
本日完成させたCRUD一式(登録・検索・更新・削除)を、実際に一連の操作として通して動かしてみてください。新規のお問い合わせを登録し、対応状況で検索し、対応状況を更新し、最後に削除するという一連の流れをブラウザ上で実行し、各画面でBootstrapのどのコンポーネントが使われているかをあわせて確認しておいてください。

◆次回授業の予習
次回は、これまで個別に作成してきた各画面のヘッダー部分を共通化し、Bootstrapのnavbarコンポーネントを使った統一感のあるナビゲーションバーを全画面に適用します。現状の一覧・登録・編集・削除確認の各画面を見比べて、見出しやリンクなど、共通化できそうな部分がどこにあるか、事前に見比べておいてください。また、普段よく利用するWebサイトのヘッダー部分(ロゴ、メニュー項目、ログインボタンなど)がどのページでも同じ配置になっていることを意識して観察しておくと、次回学ぶテンプレート共通化のメリットがより実感しやすくなります。

29 Thymeleaf応用:テンプレート共通化とBootstrap導入 科目の中での位置付け コマ25〜28でCRUD一式が完成した現時点のアプリケーションは、機能面ではひとまず完結しているが、各画面のヘッダー部分がテンプレートごとに個別に記述されており、画面数が増えるほど修正の手間とデザインの不統一が生じやすい状態にある。本コマでは、Thymeleafのフラグメント機能とレイアウト機能を用いてヘッダー・フッターを共通部品化するとともに、Bootstrap 5をCDN経由で読み込み、navbarコンポーネントによる共通ナビゲーションバーをth:replace/th:insertで全画面に適用し、統一感のある「本格的なアプリケーションらしい」画面デザインを完成させる。
コマ主題細目 ① フラグメントによる共通部品化(ヘッダー・フッター)とレイアウト機能の活用 ② Bootstrap 5のCDN読み込みとnavbarコンポーネントを用いた共通ヘッダー/ナビゲーションバーの実装(th:replace/th:insert) ③ 全画面への適用と統一感のある画面デザインの完成
細目レベル ① 本細目では、Thymeleafが提供するフラグメント機能を用いて、複数のHTMLファイルに重複して記述されているヘッダー・フッター部分を1箇所に集約する方法を学ぶ。まず、fragments/layout.htmlのような共通部品専用のテンプレートファイルを新規に作成し、th:fragment="header"属性を付与したhtml要素またはdiv要素の中に、これまで各画面に個別記述していたヘッダー部分のマークアップを移す。同様にフッター部分もth:fragment="footer"として切り出す。続いて、一覧・登録・編集・削除確認といった各画面のテンプレートから、th:replace="~{fragments/layout :: header}"という記法で共通ヘッダーを読み込む方法を実装し、th:insertとth:replaceの違い(挿入先タグを残すか、フラグメント側のタグで置き換えるか)を、実際のHTML出力結果を見比べながら確認する。さらに発展的な内容として、Thymeleaf Layout Dialectのような、ページ全体の骨格(レイアウト)を1つのテンプレートで定義し、各画面はコンテンツ部分だけを差し込むレイアウト機能の考え方にも触れ、フラグメントによる部品単位の共通化と、レイアウトによるページ全体構造の共通化という2つのアプローチの違いを整理する。この共通化によって、たとえばナビゲーションメニューに新しい項目を1つ追加したい場合でも、修正箇所がfragments/layout.htmlの1ファイルだけで済むようになる保守性の向上を、実際にコード行数を比較しながら実感させる。この細目で理解すべき範囲は、th:fragmentによる共通部品の定義方法、th:replaceとth:insertによる読み込みとその違い、およびフラグメントによる共通化がもたらす保守性向上の具体的な効果まで。
② 本細目では、これまで素朴なHTML・CSSで作成してきた画面に、Bootstrap 5を導入して見た目を大きく整える。まず、Bootstrap公式が提供するCDNのlinkタグ(CSS)とscriptタグ(JavaScript Bundle)を、先ほど作成したfragments/layout.htmlのhead部分およびbody末尾に追記し、CDN経由での読み込みであればビルド設定を変更する必要がなく、タグを1箇所追加するだけで全画面にBootstrapが適用される手軽さを確認する。続いて、Bootstrapのnavbarコンポーネントを用いて、共通ヘッダーを本格的なナビゲーションバーとして作り直す。navbar、navbar-expand-lg、navbar-light、bg-light等のクラスを組み合わせたnav要素の中に、アプリケーション名を表示するnavbar-brand、一覧画面・登録画面へのリンクを並べるnav-itemの並び、そしてハンバーガーメニュー(navbar-toggler)による狭い画面幅でのレスポンシブ対応までを、CSSを自作することなくクラス名の指定だけで実現できることを体験する。作成したnavbarをth:fragment="header"として先ほどのfragments/layout.htmlに組み込み、各画面からth:replace="~{fragments/layout :: header}"で呼び出す構成に更新することで、細目1で学んだフラグメント機能とBootstrapのコンポーネントを組み合わせた実装を完成させる。現在表示中のページに対応するnavリンクにactiveクラスを付与し、いま自分がどの画面を見ているかを視覚的に分かりやすくする工夫についても紹介する。この細目で理解すべき範囲は、BootstrapのCDN読み込み方法、navbarコンポーネントの主要クラスの組み合わせ方、およびth:replace/th:insertを用いた共通navbarフラグメントの実装方法まで。
③ 本細目では、細目1・細目2で作成した共通ヘッダー(navbar)とフッターを、一覧・検索、登録、編集、削除確認というCRUDの全画面に漏れなく適用し、アプリケーション全体の見た目を統一する仕上げの作業を行う。各画面テンプレートを1つずつ開き、これまで個別記述されていたheader相当のマークアップをth:replaceの記述に置き換えていく作業を通じて、共通化前と共通化後とでコード量がどれだけ削減されるかを実際に確認する。あわせて、これまでBootstrapを部分的にしか使っていなかったcard・table・alert・form-selectといった各コンポーネントについても、全画面で一貫したクラス指定になっているかを見直し、フォントサイズや余白(padding、marginに相当するBootstrapユーティリティクラス)の細部を揃えることで、画面ごとにばらつきのあった見た目を統一する。この作業を通じて、「CSSを自作しなくても、Bootstrapの標準コンポーネントを正しく組み合わせるだけで、実務レベルの見た目に近づけられる」という実感を持たせることが本コマ最大のねらいである。最後に、完成したアプリケーションを一覧画面から順に操作し、ナビゲーションバーを使って各画面を行き来しても常に同じヘッダーが表示され続けることを確認し、フェーズ4後半(ページング、Spring Security)に向けて画面デザインの土台が完成したことを共有する。この細目で理解すべき範囲は、共通ヘッダー・フッターのCRUD全画面への適用手順、Bootstrapコンポーネントのクラス指定を全画面で統一する調整、および共通化とBootstrap導入によって得られる保守性・デザイン統一の効果まで。
キーワード ① Thymeleafフラグメント ② th:replace ③ th:insert ④ Bootstrap 5 ⑤ navbar
コマの展開方法 社会人講師 AL ICT PowerPoint・Keynote 教科書
コマ用オリジナル配布資料 コマ用プリント配布資料 その他 該当なし
小テスト 授業時間内に、LMS上において該当コマの小テストを実施する。
復習・予習課題 ◆今回授業の復習
本日共通化したfragments/layout.htmlの内容を見返し、th:fragmentで定義した部分と、各画面からth:replaceで呼び出している部分がどのように対応しているかを、矢印でつないだ図にして整理してください。また、Bootstrapのnavbarに使われている主要なクラス名(navbar、navbar-brand、nav-item、navbar-togglerなど)を一覧にまとめ、それぞれがどの見た目を担当しているかをブラウザの開発者ツールで要素を確認しながら復習しておいてください。

◆次回授業の予習
次回は、フォーム処理の応用として、複数入力項目やチェックボックスの扱いを学びます。本日整えたお問い合わせ管理システムの入力フォームを見返し、もし対応状況以外にも「複数のタグを選択させる」ような項目を追加するとしたら、画面上でどのような部品(チェックボックスやラジオボタンなど)が適切そうか、簡単にイメージしておいてください。

30 フォーム処理応用と対応状況の一括更新 科目の中での位置付け これまでの実習では、一覧画面から1件ずつお問い合わせの対応状況を編集する構成であった。しかし実務のお問い合わせ管理システムでは、複数件をまとめて「対応中」や「対応済み」に変更したいという要望が頻繁に発生する。本コマでは、この一括更新のニーズに応えるため、一覧画面にチェックボックスを追加し、選択された複数のInquiryエンティティの対応状況を1回の操作でまとめて更新する機能を実装する。単一パラメータの受け渡しに慣れてきた学生にとって、複数チェックボックスの値を配列として受け取る処理は新たなつまずきポイントとなるため、丁寧に段階を追って解説する。
コマ主題細目 ① 複数チェックボックスの送信と受信処理 ② 対応状況の一括更新処理の実装 ③ 実務における一括処理の位置づけ
細目レベル ① 本細目では、一覧画面上で複数のお問い合わせを同時に選択するためのチェックボックスの実装と、それをControllerが受け取る仕組みについて解説する。これまでのフォーム処理では、th:objectで単一のFormクラスとフィールドを1対1に対応させる形が中心であったが、一覧画面のように行数が可変する場面では、同じname属性を持つ複数のinput要素をどう扱うかという新しい課題に直面する。

具体的には、Thymeleafのth:eachで一覧を描画する際、各行のチェックボックスにtype="checkbox" name="selectedIds" th:value="${inquiry.id}"という属性を持つinput要素を用意し、共通のname属性を与える。ブラウザは同じname属性を持つ複数のチェック済み要素を送信するため、Controller側では単一の値ではなく、Long型を要素とするListとしてselectedIdsという配列的な形でパラメータを受け取る必要がある。Spring MVCは@RequestParamやForm-Backing BeanのフィールドをLong型のList宣言にするだけで、複数の値を自動的にコレクションへ変換してくれる点を確認し、これまで単一の文字列や数値でしか受け渡ししてこなかったパラメータの扱いが、コレクション型に拡張されることを体感させる。

また、1件もチェックしないまま一括更新ボタンが押された場合や、全件選択・全件解除を切り替えるチェックボックス(いわゆる「すべて選択」チェックボックス)をJavaScriptで補助的に実装するケースにも簡単に触れ、実務のシステムでよく見られるUIパターンであることを紹介する。この細目で理解すべき範囲は、同一name属性による複数チェックボックスの送信の仕組みと、Controller側でList型として受信する方法まで。

② 本細目では、細目1で受け取った複数のID一覧をもとに、対応状況を一括で変更する更新処理をServiceおよびRepository層に実装する方法を解説する。まず一覧画面に、対応状況を選択するためのプルダウン(未対応/対応中/対応済み)と「一括更新」ボタンを追加し、選択されたIDのリストと、変更後の対応状況の値をまとめてControllerへ送信するフォームを構成する。

Controllerでは、受け取ったLong型のListであるselectedIdsと変更後のステータス文字列を、InquiryServiceの新規メソッド(例えばbulkUpdateStatusのようなメソッド名)に渡す。Service層では、IDのリストをループ処理し、それぞれのInquiryエンティティをJpaRepositoryのfindByIdで取得したうえで対応状況フィールドを書き換え、saveメソッドで保存し直すという処理を実装する。件数が多い場合はループ内で都度saveを呼び出すことの効率面の課題にも触れ、将来的にはRepositoryのsaveAllメソッドやJPQLの一括UPDATE文(@Modifying+@Query)といった選択肢があることも紹介し、今回の演習では理解のしやすさを優先してシンプルなループ処理を採用する方針を明確にする。

更新後は、これまでと同様にPRG(Post-Redirect-Get)パターンに従って一覧画面へリダイレクトし、フラッシュメッセージで「〇件のお問い合わせを更新しました」といった結果を表示する。この細目で理解すべき範囲は、複数IDを対象としたループ処理による対応状況の一括更新の実装方法と、その結果を一覧画面へ反映するまでの一連の流れまで。

③ 本細目では、本コマで実装した一括更新機能が、実際の業務システムにおいてどのような場面で活用されているかを整理し、単なる操作の効率化以上の意味を持つことを理解させる。例えば、ECサイトの受注管理システムでは複数の注文をまとめて「発送済み」に変更する機能、勤怠管理システムでは複数の申請をまとめて承認する機能、メールソフトでは複数のメールをまとめて既読にする、あるいは迷惑メールフォルダへ移動する機能など、業務系システムのほぼすべてに一括処理の仕組みが組み込まれている。

これらに共通するのは、「大量のデータを1件ずつ処理していては業務が回らない」という現場の切実な要望であり、システム開発者はこうした要望を見越して、一覧画面には検索・並び替えに加えて一括操作の導線を用意しておくことが多い。本コマのお問い合わせ管理システムも、実際の運用では1日に数十件以上のお問い合わせが寄せられることを想定すれば、対応状況の一括更新は決して些末な機能ではなく、担当者の日々の業務負荷を大きく左右する重要な機能であることを説明する。

さらに、一括処理は件数が増えるほど価値が高まる一方で、対象範囲を誤って選択したまま実行してしまった場合の被害も大きくなるという二面性を持つことに注意を促す。実務のシステムでは、一括更新の対象件数を確認ダイアログで明示したり、実行後に取り消し(アンドゥ)できる仕組みを用意したりするなど、操作ミスを前提とした設計上の工夫が施されていることが多い。

あわせて、一括処理を実装する際に注意すべき点として、意図しない範囲まで一括で変更してしまう操作ミスのリスクや、更新前に確認画面を挟むべきかどうかといったUI設計上の判断についても言及し、単に「実装できればよい」のではなく、利用者の立場に立った機能設計の視点を養う。この細目で理解すべき範囲は、一括処理が実務システムで果たす役割の具体例と、機能設計時に配慮すべき操作ミス防止の観点まで。

キーワード ① 一括更新 ② チェックボックス ③ 複数パラメータ受信 ④ PRGパターン ⑤ 業務システム設計
コマの展開方法 社会人講師 AL ICT PowerPoint・Keynote 教科書
コマ用オリジナル配布資料 コマ用プリント配布資料 その他 該当なし
小テスト 授業時間内に、LMS上において該当コマの小テストを実施する。
復習・予習課題 ◆今回授業の復習
今回学習した複数チェックボックスの送信・受信の仕組みについて、なぜ同じname属性を複数個並べるとController側でList型として受け取れるのか、HTTPリクエストの生データ(フォームデータ)のレベルで説明できるようにしておくこと。また、対応状況の一括更新処理をServiceクラスに実装した際のループ処理の流れを、自分の言葉でノートに整理し直しておくこと。可能であれば、演習で作成した一括更新機能に対して、0件選択時や全件選択時など、境界値のケースで正しく動作するかを自分で確認しておくとよい。

◆次回授業の予習
次回はページングとソートを扱う。お問い合わせ件数が数百件、数千件に増えた場合、一覧画面に全件を表示し続けることがなぜ問題になるのかを事前に考えておくこと。また、SpringのPageableという言葉を聞いたことがあれば、それがどのような役割を持つオブジェクトなのか、公式ドキュメントやWeb検索で軽く調べておくと、次回の理解がスムーズになる。

31 ページングとソート 科目の中での位置付け 件数が数百件・数千件規模に増えたお問い合わせ一覧を、これまでのように全件まとめて画面に表示し続けることは、表示速度やデータベースへの負荷、そして担当者にとっての見やすさの観点から現実的ではない。本コマでは、Spring Data JPAが標準で提供するPageableという仕組みを用いて、一覧画面に「ページ分割(ページング)」の機能を導入する。あわせて、受付日時順や対応状況順など、複数の観点で一覧を並び替える「ソート」機能も実装し、実務のシステムで当たり前に備わっているこれらの機能が、Spring Bootではごくわずかなコードで実現できることを、教員によるデモンストレーションを中心に体感させる。
コマ主題細目 ① Pageableオブジェクトによるページング処理 ② Sortを用いた並び替え機能の実装 ③ 教員デモによる一覧画面の完成確認
細目レベル ① 本細目では、Spring Data JPAが提供するPageableインターフェースを用いて、一覧データをページ単位で取得する仕組みについて解説する。これまでJpaRepositoryのfindAllメソッドは、条件に合致する全件をInquiry型のListとしてまとめて返す形で利用してきた。JpaRepositoryはこのfindAllメソッドに対して、引数にPageableを渡すオーバーロードを標準で用意しており、これを利用するだけで戻り値の型がInquiry型のPageに変わり、指定したページ番号・1ページあたりの件数に応じたデータのみを取得できるようになることを確認する。

具体的には、Controller側でPageRequest.of(ページ番号, 1ページの件数)という静的メソッドを用いてPageableオブジェクトを生成し、これをrepository.findAll(pageable)のように渡す。戻り値のPageオブジェクトは、そのページの内容(getContent)だけでなく、総件数(getTotalElements)や総ページ数(getTotalPages)、次のページが存在するかどうか(hasNext)といった情報も同時に保持しており、これらをModelに渡すことでThymeleaf側にページ送りのUI(Bootstrapのpaginationコンポーネント)を実装できることを示す。

また、URLのクエリパラメータ(例えば?page=2)としてページ番号を受け取り、@RequestParamで取得してPageRequestに反映する流れも合わせて確認する。この細目で理解すべき範囲は、PageableインターフェースとPageの役割、およびfindAllメソッドにPageableを渡すことで一覧データをページ単位に分割取得する方法まで。

② 本細目では、一覧に表示するお問い合わせを、受付日時順や対応状況順など任意の項目で並び替えるソート機能の実装方法について解説する。Spring Data JPAでは、org.springframework.data.domain.Sortクラスを用いることで、SQLのORDER BY句に相当する並び替え条件をJavaのコードとして表現できる。Sort.by("receivedAt").descending()のように記述すれば受付日時の降順に、Sort.by("status")と記述すれば対応状況の昇順に並び替えられることを、実際にデモコードを動かしながら確認する。

さらに、このSortオブジェクトは単独でfindAllメソッドに渡すこともできるが、細目1で扱ったPageableと組み合わせて使うことが実務ではより一般的である。PageRequest.of(ページ番号, 件数, sort)のようにPageRequestの第三引数にSortを渡すことで、「並び替えたうえでページ分割する」という一覧画面としてごく自然な要求を、1行のコードで実現できることを示す。一覧画面のテーブルヘッダー(受付日時、対応状況など)をリンクにし、クリックすると並び替え条件を切り替えて再表示するというUIパターンも紹介し、昇順・降順をトグルさせる工夫についても触れる。

本コマは教員デモを中心とした展開とし、学生には主要なコードの動作結果を確認させながら、Pageable・Sortという2つのオブジェクトがどのように連携しているかを理解させることに重点を置く。この細目で理解すべき範囲は、Sortクラスによる並び替え条件の指定方法と、PageableとSortを組み合わせて一覧を取得する方法まで。

③ 本細目では、これまでの細目で解説したPageableとSortを実際に組み込んだ一覧画面を、教員によるデモンストレーションを通じて完成形として確認する。デモでは、あらかじめ大量(数十件〜百件程度)のサンプルお問い合わせデータをJavaConfigやCommandLineRunnerで投入したうえで、ページ送りリンクをクリックしてデータが正しく切り替わること、テーブルヘッダーをクリックすると受付日時順・対応状況順に並び替えが行われることを、ブラウザの画面上で順に見せていく。

このコマは実装量に対して教員デモの比重を高くしている理由についても説明する。ページングとソートの実装自体はPageableとSortというオブジェクトの使い方を覚えれば比較的短いコードで実現できる一方、Bootstrapのpaginationコンポーネントを用いた画面側の実装や、現在のページ番号・並び替え条件をURLパラメータとして一貫して引き回す処理は、細部の配慮点が多く、初学者が一からすべて手を動かすには時間がかかりすぎるためである。そのため本コマでは、コアとなるPageable・Sortの概念とAPIの使い方を学生自身が理解することを最優先とし、画面側の細かな実装は教員がデモで見せる形にとどめる。

あわせて、次のコマから始まるSpring Securityへの置き換えに向けて、これまで完成させてきたCRUD・一括更新・ページング・ソートを含む一覧画面全体が、フェーズ4の集大成であることを振り返り、フェーズ4後半への橋渡しとする。この細目で理解すべき範囲は、Pageable・Sortを組み込んだ一覧画面がどのように動作するかを理解し、実装の詳細よりも概念とAPIの使い方を優先して押さえることまで。

キーワード ① Pageable ② Pageオブジェクト ③ Sortクラス ④ ページネーション ⑤ 教員デモ
コマの展開方法 社会人講師 AL ICT PowerPoint・Keynote 教科書
コマ用オリジナル配布資料 コマ用プリント配布資料 その他 該当なし
小テスト 授業時間内に、LMS上において該当コマの小テストを実施する。
復習・予習課題 ◆今回授業の復習
今回のデモで確認したPageableとSortの役割について、findAllメソッドの戻り値がListからInquiry型のPageに変わることで何が変わったのか、そのPageが保持している情報(総件数、総ページ数など)にはどのようなものがあったかを、配布資料やデモコードを見返しながら整理しておくこと。余裕があれば、自分の手元の演習環境でPageRequestの引数(ページ番号・件数・Sort)を変えて動作を確認してみるとよい。

◆次回授業の予習
次回からはいよいよSpring Securityの導入に入る。これまでコマ17〜18で自作したHttpSessionによるログイン処理のコードを見返し、固定ID・パスワードの照合やセッションへの保存・確認をどのように自分たちで実装したかを思い出しておくこと。また、「認証」と「認可」という2つの言葉の意味の違いについても、事前に調べておくと次回の理解が深まる。

32 Spring Securityの概要と導入 科目の中での位置付け フェーズ3のコマ17〜18で、学生はHttpSessionを直接操作する手作りのログイン処理を実装し、固定ID・パスワードの照合からセッションへの保存、ログイン状態の確認までを自らのコードで実現した。本コマからの2回(コマ32〜33)では、この手作りの認証処理を、Spring Bootアプリケーションにおける事実上標準の認証・認可フレームワークであるSpring Securityへと置き換えていく。1回目にあたる本コマでは、まずSpring Securityがなぜ必要とされるのか、手作り実装のどこに限界があったのかを整理したうえで、依存関係の追加とSecurityFilterChainの雛形作成という最小構成の導入を行い、次回のカスタマイズにつなげる土台を作る。
コマ主題細目 ① Spring Securityの概要と必要性 ② 依存関係の追加とSecurityFilterChainの雛形作成 ③ ログインフォームのカスタマイズに向けた準備
細目レベル ① 本細目では、Spring Securityというフレームワークが果たす役割と、それを導入する必要性について解説する。まず、コマ17〜18で実装した手作りのログイン処理を振り返り、そこで学生自身が実装しなければならなかった処理を棚卸しする。具体的には、パスワードを平文のままソースコードやデータベースに保持していたこと、ログインしていないユーザーが特定のURLへ直接アクセスした場合の制御を各Controllerメソッドの冒頭に自分で書いていたこと、ログアウト処理やセッションのタイムアウトといった細かな挙動も一つ一つ自作していたことなどを確認する。

これらは学習目的としては手を動かして理解する意義が大きいが、実務でそのまま採用するには、パスワードの安全な保存(ハッシュ化)、CSRF(クロスサイトリクエストフォージェリ)対策、URLごとのアクセス制御の一元管理、認証失敗時の適切な挙動など、考慮すべき事項が非常に多く、車輪の再発明にはリスクが伴う。Spring Securityは、これらの認証・認可に関する定番の実装パターンをフレームワークとして提供しており、Spring Bootと組み合わせることで依存関係を追加するだけの最小構成から段階的に機能を積み上げられる設計になっていることを説明する。

あわせて、「認証(Authentication)」と「認可(Authorization)」という2つの概念の違いについても整理する。認証は「このユーザーは誰であるか」を確認する処理であり、認可は「このユーザーに何を許可するか」を判断する処理である。手作り実装では両者を明確に区別せずif文で済ませていた部分が多いが、Spring Securityではこの2つの概念がAPI設計上も明確に分離されていることに触れる。この細目で理解すべき範囲は、手作りログイン実装の限界と、Spring Securityが解決する認証・認可という2つの概念の違いまで。

② 本細目では、実際にSpring Securityをプロジェクトへ導入する最初の一歩として、依存関係の追加と、認証・認可の設定を記述する中心的なクラスであるSecurityFilterChainの雛形作成を行う。まず、build.gradle(またはpom.xml)にspring-boot-starter-securityを追加する。この依存関係を追加してアプリケーションを再起動するだけで、それまで自由にアクセスできていた全画面がSpring Securityによって保護され、デフォルトのログイン画面が表示されるようになる点を実演し、フレームワークが提供する「まず安全側に倒す」という設計思想を体感させる。

続いて、この自動生成されたデフォルトの挙動をアプリケーションの要件に合わせてカスタマイズするために、@Configurationアノテーションを付与したSecurityConfigクラスを作成し、その中にSecurityFilterChainという型のBeanを定義する。ここでコマ15〜16で学習した「@Configuration+@Beanによる明示的なBean定義(JavaConfig)」の知識が、まさにこの場面で実際に活用されることを強調する。JavaConfigは抽象的な学習事項ではなく、Spring Securityのような大規模なフレームワークの設定を行う際に必ず登場する実践的な技術であることを、学生に実感させる重要な接続点である。

SecurityFilterChainのBeanメソッド内では、HttpSecurityオブジェクトに対してauthorizeHttpRequestsメソッドを用いてURLごとのアクセス制御ルールを記述していく雛形(例えば、特定のパスは認証不要とし、それ以外は認証必須とする最小構成)を作成する。この細目で理解すべき範囲は、spring-boot-starter-securityの追加による挙動の変化と、SecurityFilterChainをBeanとして定義する基本構成、およびJavaConfigの知識がここで活用される点まで。

③ 本細目では、次回のコマ33で行うログインフォームのカスタマイズに向けて、Spring Securityが標準で提供するデフォルトのログイン画面の仕組みと、それをカスタマイズするための準備を整理する。SecurityFilterChainの設定において、formLoginメソッドを呼び出すことで、Spring Securityはあらかじめ用意されたシンプルなログイン画面を自動的に表示する。まずはこのデフォルト画面でログインが行えることを確認し、フォーム認証という仕組みが最小限の設定で動作することを体感する。

次に、このデフォルト画面を、これまでコマ17〜18やBootstrapによる共通デザインで作り込んできた画面の雰囲気に合わせてカスタマイズするための準備として、formLoginメソッドにloginPageメソッドを連ねることで、自作のThymeleafテンプレート(例えばlogin.html)をログイン画面として指定できることを紹介する。あわせて、カスタムログイン画面を指定した場合には、そのページ自体は誰でもアクセスできるように認可設定側でも除外しておく必要があるという、初学者がつまずきやすいポイントについても触れておく。

本細目はあくまで次回の演習に向けた準備・見通しの共有であり、実際のカスタムログイン画面の作成とスタイリング、および手作りセッション認証からの置き換え作業そのものは次回コマ33で行うことを明示し、コマ32とコマ33の役割分担を学生に明確に伝える。この細目で理解すべき範囲は、formLoginメソッドとloginPageメソッドによるログイン画面カスタマイズの基本的な仕組みと、カスタム画面自体へのアクセス許可設定が必要になる点まで。

キーワード ① Spring Security ② 認証と認可 ③ SecurityFilterChain ④ spring-boot-starter-security ⑤ JavaConfig
コマの展開方法 社会人講師 AL ICT PowerPoint・Keynote 教科書
コマ用オリジナル配布資料 コマ用プリント配布資料 その他 該当なし
小テスト 授業時間内に、LMS上において該当コマの小テストを実施する。
復習・予習課題 ◆今回授業の復習
今回整理した「認証」と「認可」の違いについて、自分の言葉で説明できるかどうかを確認しておくこと。また、spring-boot-starter-securityを追加しただけでデフォルトのログイン画面が表示されるようになった仕組みと、SecurityFilterChainのBeanとしてどのような設定を行ったかを、演習コードとノートを見比べながら復習しておくこと。特に、コマ15〜16のJavaConfigの知識がSecurityConfigクラスの中でどのように使われていたかを、意識して振り返っておくとよい。

◆次回授業の予習
次回は、本コマで準備したログインフォームのカスタマイズを完成させ、コマ17〜18で自作した手作りのセッション認証をSpring Securityへ実際に置き換える演習を行う。手元にあるこれまでのログイン処理のコード(HttpSessionを使った部分)を見返し、どの処理がSpring Securityの機能に置き換わりそうかを自分なりに予想しておくこと。

33 Spring Securityへの置き換えとデプロイ 科目の中での位置付け 本コマは、コマ32で準備したSpring Securityの基本設定を土台に、ログインフォームのカスタマイズを完成させたうえで、コマ17〜18から使い続けてきた手作りのHttpSessionによるセッション認証を、実際にSpring Securityへ置き換える演習を行う。素朴な実装からフレームワークによる実装へと置き換える体験は、本科目がDB接続(JDBC→JPA)でも繰り返してきた学びの型であり、本コマでその最終回を迎える。さらに授業の最後には【コラム】として、ここまで作り上げてきたSpring Bootアプリケーションを無料PaaSのRenderを用いて実際にインターネット上へ公開するデモを行い、フェーズ4の締めくくりとする。
コマ主題細目 ① カスタムログイン画面の完成 ② 手作りセッション認証からSpring Securityへの置き換え ③ 【コラム】Renderを用いたSpring Bootアプリのデプロイ
細目レベル ① 本細目では、コマ32で準備した仕組みを用いて、Bootstrapによる共通デザインに沿ったオリジナルのログイン画面を完成させる。まず、これまでの一覧画面や登録画面と同じヘッダー・ナビゲーションバーの構成を踏襲したlogin.htmlをThymeleafテンプレートとして作成し、SecurityFilterChainのformLoginメソッドにloginPageメソッドで指定する。フォーム自体は、th:actionに/loginを指定し、ユーザー名とパスワードの入力欄をname="username"、name="password"という、Spring Securityが標準で認識するname属性で用意するだけで、認証処理自体を自分でコーディングする必要がない点を確認する。

次に、ログインに失敗した場合のエラーメッセージ表示を実装する。Spring Securityはログイン失敗時に/login?errorというクエリパラメータを付与してログイン画面へリダイレクトする仕様になっているため、Thymeleaf側でth:ifを用いてこのerrorパラメータの有無を判定し、Bootstrapのalertコンポーネントで「ユーザー名またはパスワードが正しくありません」といったメッセージを表示する処理を追加する。あわせて、ログアウト時のリダイレクト先や、ログアウト成功時のメッセージ表示についても、logoutメソッドの設定とあわせて確認する。

これらの作業を通じて、コマ17〜18で自分たちがゼロから実装していたエラーメッセージ表示やログアウト処理の多くが、Spring Securityでは設定とテンプレート側の少しの記述だけで実現できることを実感させる。この細目で理解すべき範囲は、カスタムログイン画面のテンプレート作成方法と、ログイン失敗時のエラー表示・ログアウト処理の実装方法まで。

② 本細目では、コマ17〜18で実装した手作りのHttpSessionによる認証処理を取り除き、Spring Securityによる認証・認可へ完全に置き換える演習を行う。まず、各ControllerメソッドやInterceptorの冒頭に書かれていた、session.getAttributeでログイン状態を確認しリダイレクトさせる自作の判定コードをすべて削除する。これらの判定処理は、SecurityFilterChainのauthorizeHttpRequestsメソッドで宣言的に記述したアクセス制御ルール(例えば/inquiries/**は認証必須、/loginや静的リソースは許可)に一元化されるため、Controller側のコードが大きくシンプルになることを確認する。

次に、ログイン処理そのもの(入力されたIDとパスワードを固定値と比較する処理)や、ログイン成功時にHttpSessionへ属性を保存する自作コードについても削除する。これらはSpring Securityの内部で、UsernamePasswordAuthenticationFilterなどのフィルタ機構によって自動的に処理されるようになる。今回の演習では、まずはインメモリのユーザー定義(InMemoryUserDetailsManagerや、SecurityFilterChainの設定内でユーザー名・パスワードを定義する簡易な方法)を用いて認証情報を用意し、DBに保存されたユーザー情報を参照するUserDetailsServiceの自作実装は将来の発展課題として位置づける。

置き換え作業が完了したら、実際にログイン・ログアウト・未ログイン状態での保護されたURLへのアクセス制限が、以前の手作り実装と同様に機能することを一つずつ動作確認する。この一連の作業を通じて、手作りの実装がフレームワークの機能とどのように対応しているかを具体的に対応づけながら理解させる。この細目で理解すべき範囲は、手作りのセッション認証コードを削除し、Spring Securityの宣言的なアクセス制御・認証フィルタへ置き換える一連の演習手順まで。

③ 本細目はコラムとして、ここまで作り上げてきたSpring Bootアプリケーションを、実際にインターネット上へ公開する手順を教員によるデモンストレーションを中心に紹介する。デプロイ先として、無料で利用できるPaaS(Platform as a Service)であるRenderを取り上げる。近年はRailwayが従量課金中心の料金体系へ移行し、長らく定番であったHerokuも無料プランを廃止したため、無料でSpring Bootアプリを公開できる現実的な選択肢としてRenderが挙げられることを説明する。

Renderの無料枠では、Web Serviceを月750時間まで無料で稼働させられる一方、15分間アクセスがないとアプリケーションがスリープ状態になり、次にアクセスした際に再起動のための遅延が発生するという制約があることに触れる。デプロイの流れとしては、①これまでGitで管理してきたソースコードをGitHubリポジトリへpushし、②Renderの管理画面でそのリポジトリをWeb Serviceとして接続し、③Renderが自動的にビルド・デプロイを行った結果発行されるURLへ実際にアクセスして、これまで手元のlocalhostでしか確認できなかったアプリケーションが世界中からアクセス可能になっていることを確認する、という3ステップで進める。GitHubリポジトリと連携させておけば、以後はpushするだけで自動的に再ビルド・再デプロイされる継続的デプロイの仕組みも簡単に紹介する。

あわせて、現在のアプリケーションが使用しているH2はインメモリデータベースであるため、Renderのコンテナが再起動するとそれまで登録したお問い合わせデータがすべて消えてしまうという限界にも言及する。本番運用を行うのであればPostgreSQLなど永続化されたデータベースサービスと接続する必要があり、これはフェーズ5以降の発展的な検討課題となることを示す。このコラムはデモ中心の紹介としハンズオンは最小限にとどめ、学生には「自分たちが作ったアプリケーションがインターネット上で実際に動く」という体験を持ち帰ってもらうことを主眼とする。この細目で理解すべき範囲は、Renderへのデプロイ手順(GitHubへのpush→Web Service接続→公開URLへのアクセス確認)の3ステップと、H2のインメモリ特性による本番運用上の限界まで。

キーワード ① Spring Security置き換え ② UserDetailsService ③ 宣言的アクセス制御 ④ PaaSデプロイ ⑤ Render
コマの展開方法 社会人講師 AL ICT PowerPoint・Keynote 教科書
コマ用オリジナル配布資料 コマ用プリント配布資料 その他 該当なし
小テスト 授業時間内に、LMS上において該当コマの小テストを実施する。
復習・予習課題 ◆今回授業の復習
今回完成させたカスタムログイン画面と、手作りのセッション認証からSpring Securityへの置き換え作業について、コマ17〜18で自作していたコードのどの部分が、Spring Securityのどの機能に対応していたのかを一つずつ整理し直しておくこと。また、コラムで紹介したRenderへのデプロイ手順(GitHubへのpush、Web Serviceとしての接続、公開URLへのアクセス確認)の流れを、自分の言葉で説明できるようにしておくとよい。

◆次回授業の予習
次回からはフェーズ5に入り、これまで33回かけて完成させたお問い合わせ管理システムをベースに、各自が機能追加・改修に取り組む個人演習が始まる。まずは自分がこれまで作ってきたアプリケーション全体のコードを見返し、どの機能に自信があり、どの部分の理解が曖昧なままになっているかを自己点検しておくこと。あわせて、対応状況によるソートやカテゴリ分類、CSV出力など、興味のある改修テーマがあれば考えておくとよい。

34 機能追加・改修演習ガイダンスと要件整理 科目の中での位置付け 本コマは、フェーズ1からフェーズ4まで一貫して積み上げてきたお問い合わせ管理システムの開発を踏まえ、フェーズ5「機能追加・改修演習」の出発点となる回である。ここからはチーム演習ではなく、各自に配布された作業コピーを用いた個人演習が中心となるため、まず既存システムの全体像を俯瞰的に振り返るとともに、今後取り組む個人演習のお題一覧とその難易度の考え方を共有する。あわせて、完成済みのアプリケーションに新たな機能を付け加える際に欠かせない「要件整理」の視点、すなわち既存の設計・実装のどこまでに影響が及ぶのかを見極める考え方を身につけることに重点を置く。
コマ主題細目 ① フェーズ4完成時点のお問い合わせ管理システム全体像の振り返り ② 個人演習の進め方とお題一覧の共有 ③ 機能追加・改修における要件整理の考え方
細目レベル ① 本細目では、フェーズ1からフェーズ4を通じて段階的に構築してきたお問い合わせ管理システムの全体構成を、レイヤーごとに整理しながら振り返る。まず、Controller・Service・Repositoryという3層構造を採用したMVCアーキテクチャの全体像を再確認し、それぞれの層がどのような責務を担っているかを整理する。ControllerはHTTPリクエストの受付とレスポンス(Thymeleafによる画面遷移)を担当し、Serviceはビジネスロジックとトランザクション境界を担い、Repositoryは`JpaRepository`を介したデータベースアクセスを担当するという役割分担を、実際のクラス名(InquiryController、InquiryService、InquiryRepository)とともに確認する。

続いて、Entityクラス`Inquiry`が持つフィールド(顧客名、メールアドレス、お問い合わせ内容、対応状況、受付日時)と、Lombokの`@Data`等のアノテーションによるボイラープレート削減の効果を振り返る。あわせて、Thymeleafを用いた一覧・詳細・登録・編集・削除の各画面がどのようにForm-Backing BeanとBindingResultを介したバリデーション、PRG(Post-Redirect-Get)パターンと連携しているかを整理する。

さらに、Spring Securityによるログイン認証・認可の仕組み、Bootstrap 5による画面デザインの統一、Renderへのデプロイによって実際にインターネット上で稼働している状態にあることを確認し、「完成したアプリケーション」に対して機能追加・改修を行うというフェーズ5の前提条件を学生自身の言葉で説明できる状態を目指す。この細目で理解すべき範囲は、既存システムの3層構造とInquiryエンティティの構成、CRUD・認証・デプロイまでの全体像まで。

② 本細目では、フェーズ5における個人演習の具体的な進め方を説明する。まず、コマ33完成時点のプロジェクトを教員がGitHubのTemplate repository機能、またはZIPアーカイブとして配布し、各受講者がそれぞれ独立した作業コピーを持つ状態からスタートすることを確認する。以後の演習はチームではなく個人単位で進め、教員は各自の進捗を巡回しながら助言を行うデモ中心の関わり方に切り替わる点を強調する。

続いて、今回提示する個人演習のお題一覧を紹介する。優先度ソート機能の追加(初級〜中級)、問い合わせ種別によるカテゴリ分類機能の追加(中級)、CSV出力機能の追加(中級〜上級)という3つのお題を、コマ35以降で順に2コマずつ、あるいは1〜2コマ単位で扱っていく計画であることを共有する。あわせて、余力のある受講者向けの上級者向け任意チャレンジ課題として、AOPによるログ出力・処理時間計測のリファクタリングが用意されていることにも触れ、必須課題と発展課題の位置づけの違いを明確にする。

お題の難易度は、既存のEntity構造をそのまま使えるか(優先度ソート)、Entityへのフィールド追加やDBスキーマ変更を伴うか(カテゴリ分類)、新しい技術要素(ファイル入出力)を必要とするか(CSV出力)という観点で段階的に設計されていることを説明し、各自が自分のペースで着実に取り組めるよう見通しを持たせる。

また、教員デモが果たす役割についても補足する。個人演習が中心とはいえ、要所要所で教員が実装例を画面共有しながら解説するデモを挟むことで、実装に迷った際の参考となる「型」を示す方針であることを伝え、完全な自習ではなく適度な伴走があることを安心材料として共有する。

この細目で理解すべき範囲は、作業コピーの配布方法と個人演習への移行の意味、3つのお題の概要と難易度設定の考え方まで。

③ 本細目では、既存の完成したアプリケーションに新たな機能を追加・改修する際に不可欠な「要件整理」の考え方を扱う。ゼロから新規にアプリケーションを設計する場面とは異なり、機能追加・改修では既存の設計・実装との整合性を保ちながら変更を加える必要があるため、まず「何を実現したいのか」という要求を明確にし、次に「その実現のためにシステムのどの部分(Entity、Repository、Service、Controller、View)に手を加える必要があるか」という影響範囲を洗い出す手順を丁寧に説明する。

具体的には、優先度ソート機能を例に、Entityのフィールド構成は変更せずにRepositoryのクエリメソッドやServiceのロジックだけで実現できるのか、あるいはカテゴリ分類機能のようにEntityへのフィールド追加とDBスキーマの変更を伴うのかを見極める視点を提示する。また、既存の画面(一覧・詳細・登録・編集)や既存のテストケース、既存のバリデーションルールに副作用を及ぼさないかを確認する「影響範囲分析」の重要性にも言及し、実務における改修作業の進め方の基本型を体験的に理解させる。

最後に、要件整理の結果を簡単なメモや箇条書きとして自分自身のために書き出しておく習慣を持つことを推奨し、次回以降の個人演習に着手する前の準備として位置づける。

あわせて、要件整理を怠った場合に起こりがちな失敗例(実装を始めてから既存の画面が壊れることに気づく、対応範囲を絞り込まずに手を広げすぎて完成しない等)を具体的に紹介し、最初に整理の時間を取ることの投資対効果を実感させる。個人演習という自走的な取り組みだからこそ、こうした地道な準備が完成度を左右することを強調する。

この細目で理解すべき範囲は、要件整理の基本手順と影響範囲分析の考え方、既存設計への副作用を確認する視点まで。

キーワード ① 要件整理 ② 影響範囲分析 ③ 個人演習 ④ 作業コピー ⑤ レイヤードアーキテクチャ
コマの展開方法 社会人講師 AL ICT PowerPoint・Keynote 教科書
コマ用オリジナル配布資料 コマ用プリント配布資料 その他 該当なし
小テスト 授業時間内に、LMS上において該当コマの小テストを実施する。
復習・予習課題 ◆今回授業の復習
今回振り返ったお問い合わせ管理システムの全体構成(Controller・Service・Repositoryの3層構造とInquiryエンティティの各フィールド)について、自分の作業コピーのソースコードを実際に開いて確認し、どのクラスがどの役割を担っているかを自分の言葉で説明できるようにしておくこと。あわせて、提示された3つの個人演習のお題(優先度ソート、カテゴリ分類、CSV出力)のうち、それぞれがInquiryエンティティのどのフィールドに関係する機能なのかを整理しておくこと。

◆次回授業の予習
次回からは個人演習①「優先度ソート機能の追加」に着手する。対応状況(未対応/対応中/対応済み)や受付日時といった既存のフィールドを使って、どのような順序で問い合わせを並べ替えれば業務上便利かを自分なりに考え、優先度付けの条件をメモしておくこと。

35 優先度ソート機能の設計 科目の中での位置付け 本コマからコマ36にかけての2コマは、フェーズ5個人演習①「対応状況・受付日時による優先度ソート機能の追加」に取り組む1回目である。初級〜中級のお題として位置づけられており、既存のInquiryエンティティのフィールド構成を変更せずに実現できる範囲であるため、機能追加演習の入門として最初に扱う。本コマでは実装に着手する前段階として、ソート機能の要件定義とSpring Data JPAにおけるソートクエリの実装方法、画面側での表示設計を扱い、次回コマ36での実装完成につなげる。
コマ主題細目 ① ソート機能の要件定義(複数条件による優先度付け) ② Spring Data JPAにおけるソートクエリの実装方法 ③ 画面側でのソート結果表示の設計
細目レベル ① 本細目では、優先度ソート機能を実装する前段階として、「何を基準に、どのような順序で並べ替えるのか」という要件を自分自身の手で定義する演習を行う。お問い合わせ管理システムでは、対応状況が「未対応」の問い合わせを先頭に表示し、同じ対応状況の中では受付日時が古いものを優先して表示する、といった複数条件による優先度付けが業務上有用であることを、実際のコールセンターや窓口業務を例に説明する。

続いて、単一条件によるソート(例えば受付日時のみで並べ替える)と、複数条件を組み合わせた優先度ソート(対応状況を第一キー、受付日時を第二キーとする)の違いを整理し、後者を実現するためには「対応状況ごとの並び順(未対応→対応中→対応済み)」をどのように数値やEnum、あるいは文字列の比較順として表現するかという設計上の論点があることを示す。

さらに、要件定義の演習として、受講者自身に「どのような並び順が業務上望ましいか」を考えさせ、優先度の定義(第一条件・第二条件・昇順/降順)を明文化させる。この作業を通じて、実装に入る前に仕様を言語化する重要性を体感させる。

あわせて、優先度という概念そのものが業務要件によって変わりうることにも触れる。例えば「対応済みの問い合わせは表示順の末尾でよいが、未対応と対応中のどちらを優先すべきか」といった判断は、業務ルール次第で異なりうることを示し、要件定義とは唯一の正解を探す作業ではなく、システムを使う現場の事情に即して自分なりの根拠を持って条件を決める作業であることを理解させる。

この細目で理解すべき範囲は、複数条件による優先度付けの考え方と、対応状況・受付日時を用いた優先度の定義方法まで。

② 本細目では、Spring Data JPAが提供するソート機能の実装方法を扱う。まず、`JpaRepository`が標準で継承している`findAll(Sort sort)`メソッドを用いて、呼び出し側から動的にソート条件を指定する方法を確認する。`Sort.by(Sort.Direction.ASC, "receivedAt")`のように、フィールド名と昇順・降順を指定するだけでSQLのORDER BY句が自動生成される仕組みを、実際のコード例とともに解説する。

次に、複数条件によるソートを実現する`Sort.by(...).and(Sort.by(...))`の記法や、`OrderBy`命名規則を用いたリポジトリメソッド(例:`findAllByOrderByStatusAscReceivedAtAsc`)による静的なソートクエリの定義方法を扱う。両者の違い、すなわち「呼び出し側で条件を切り替えたい場合はSortオブジェクトを使う」「固定の並び順でよい場合はOrderBy命名規則メソッドが簡潔である」という使い分けの指針を示す。

あわせて、対応状況(未対応/対応中/対応済み)を優先度順に並べる際に、文字列の辞書順とは異なる独自の順序を実現するにはEnum型の`ordinal()`を利用する方法や、DB上のカラムに順序を表す数値を持たせる設計上の選択肢があることにも触れる。

また、既に対応状況ごとにグループ化された一覧を作りたい場合には、単純なソートだけでなくグルーピング表示という選択肢もあることに触れ、今回の演習ではまずソートによる並び替えを基本形とすることを確認する。余力のある受講者には、グルーピング表示への発展を自由課題として提示する。

この細目で理解すべき範囲は、`Sort`オブジェクトとOrderBy命名規則メソッドによるソートクエリの実装方法、両者の使い分けの考え方まで。

③ 本細目では、Service層・Controller層で取得したソート済みのお問い合わせ一覧を、Thymeleafを用いた画面側にどのように反映するかを設計する。まず、Controllerが`InquiryService`から受け取ったソート済みの`List<Inquiry>`をModelに格納し、一覧画面(th:each)でそのまま順序通りに表示すれば、追加の画面側ロジックなしにソート結果が反映される仕組みを確認する。

続いて、ユーザーが並び替え条件を選択できるようにするための画面設計の考え方を扱う。例えば、一覧画面の上部にプルダウンやボタンを配置し、選択された条件をクエリパラメータ(`?sort=status`など)としてControllerに渡し、Controller側でどの`Sort`条件を適用するかを分岐させる、という基本的な設計方針を示す。この際、画面遷移のたびにソート条件が失われないよう、選択中の条件を画面上に表示する、あるいはURLに含めておくといった配慮の必要性にも触れる。

さらに、対応状況を色分けしたBootstrapのバッジやラベルで表示し、優先度の高い問い合わせが視覚的にも把握しやすいデザインにする工夫を紹介し、次回コマ36での具体的なUI実装につなげる。

また、一覧画面の件数が多い場合には、コマ31で学んだページングとの組み合わせが必要になる点にも触れ、ソート条件とページング条件を同時に扱う際にURLのクエリパラメータがどのように構成されるかについても概要を示し、次回の実装作業で迷わないよう見通しを持たせる。

この細目で理解すべき範囲は、ソート済み一覧のModelへの受け渡しと画面表示の基本、並び替え条件を切り替えるための画面設計の考え方まで。

キーワード ① Sortオブジェクト ② OrderBy命名規則 ③ 優先度付け ④ 複数条件ソート ⑤ Enum型ordinal
コマの展開方法 社会人講師 AL ICT PowerPoint・Keynote 教科書
コマ用オリジナル配布資料 コマ用プリント配布資料 その他 該当なし
小テスト 授業時間内に、LMS上において該当コマの小テストを実施する。
復習・予習課題 ◆今回授業の復習
今回学習した`Sort`オブジェクトとOrderBy命名規則メソッドの違いについて、自分の言葉で説明できるようにしておくこと。また、対応状況・受付日時を用いた優先度の定義(どちらを第一条件にするか、対応状況内の並び順をどう表現するか)を、自分の作業コピーのInquiryエンティティに即して具体的にメモしておくこと。時間があれば、実際に`findAllByOrderBy〜`という形式のメソッド名を自分で組み立ててみて、命名規則の感覚を身につけておくこと。

◆次回授業の予習
次回コマ36では、今回設計したソート条件を実際に画面に組み込み、並び替え条件を切り替えられるUIを実装して演習①を完成させる。今回定義した優先度の条件(第一条件・第二条件)を確認し、それを選択するためのUI(プルダウンやボタンなど)としてどのような見た目・操作性が使いやすいか、簡単にイメージを持っておくこと。

36 優先度ソート機能の実装完成 科目の中での位置付け 本コマは、フェーズ5個人演習①「対応状況・受付日時による優先度ソート機能の追加」の2回目であり、前回コマ35で設計したソート要件とSpring Data JPAによるソートクエリを、実際に動作するアプリケーションとして完成させる回である。個人演習として各自のペースで実装を進めながら、教員は巡回とデモを通じて助言を行う。実装が完成した後は、自分の手で動作確認とデバッグを行い、演習を振り返った上で、次の個人演習②「カテゴリ分類機能の追加」への橋渡しを行う。
コマ主題細目 ① ソート条件切り替えUIの実装 ② 実装結果の動作確認とデバッグ ③ 演習の振り返りと次の演習テーマへの橋渡し
細目レベル ① 本細目では、前回コマ35で設計したソート条件を、実際に画面上で切り替えられるUIとして実装する演習を行う。まず、一覧画面にBootstrapのボタングループやドロップダウンを配置し、「対応状況優先」「受付日時が古い順」といった選択肢をリンクとして用意する。それぞれのリンクにクエリパラメータ(例:`/inquiries?sort=priority`)を付与し、Controllerの`@GetMapping`メソッドの`@RequestParam`でこのパラメータを受け取る実装を進める。

続いて、Controller内で受け取ったパラメータの値に応じて、`InquiryService`に渡す`Sort`条件を分岐させる実装を行う。例えば、パラメータが`priority`であれば対応状況・受付日時の複合ソートを適用し、`newest`であれば受付日時の降順のみを適用する、といった条件分岐をswitch文やif文で実装し、Serviceのメソッドに引数として`Sort`オブジェクトを渡す設計にリファクタリングする。

さらに、現在選択されているソート条件を画面上に視覚的に表示する(選択中のボタンをactive状態にする等)ことで、ユーザーが今どの順序で表示されているかを把握しやすくする工夫を、Thymeleafの条件分岐(th:classappend等)を用いて実装する。

また、実装を進める中で、ソート条件を追加するたびにControllerのコードが複雑化していく懸念にも触れ、条件の種類が増えた場合には、条件名と`Sort`オブジェクトの対応表をMapとして持たせる、あるいはEnum型に`Sort`を返すメソッドを持たせるといったリファクタリングの方向性があることを紹介し、コードの見通しを保つ工夫の重要性を伝える。

この細目で理解すべき範囲は、クエリパラメータを用いたソート条件の受け渡しと、Controller内での条件分岐によるSort適用の実装方法まで。

② 本細目では、実装したソート機能が意図通りに動作しているかを、自分の手で確認しデバッグする演習を行う。まず、複数件のダミーデータ(対応状況・受付日時の異なるお問い合わせ)を用意し、各ソート条件を選択した際に一覧の並び順が期待通りに変化するかを目視で確認する手順を説明する。

次に、意図した順序にならない場合の典型的な原因(Sortの`Direction`指定の誤り、複合ソートにおけるキーの順序の取り違え、Enum型の`ordinal()`が意図した順序になっていない等)を挙げ、IntelliJ IDEAのデバッガでブレークポイントを設置し、Controllerに渡されたパラメータの値やServiceに渡される`Sort`オブジェクトの中身を実際に確認しながら原因を特定する進め方を実演する。

あわせて、境界値(対応状況が全件同じ場合、受付日時が同一の場合等)における挙動も確認し、単純な動作確認だけでなくエッジケースにも目を向ける姿勢を養う。個人演習であるため、受講者ごとに実装の細部やつまずくポイントが異なることを踏まえ、教員は巡回しながら個別に助言を行う。

さらに、動作確認の記録を簡単なチェックリストとして残しておくことも推奨する。「対応状況優先で並べた場合に未対応が先頭に来るか」「受付日時順で並べた場合に古い順になっているか」といった確認項目をあらかじめリストアップしておくことで、実装を変更するたびに同じ観点で再確認でき、デグレード(機能の後退)を防ぐ習慣を身につけさせる。

この細目で理解すべき範囲は、ソート機能の動作確認の基本手順と、デバッガを用いた原因特定の進め方まで。

③ 本細目では、個人演習①として取り組んだ優先度ソート機能の実装を振り返り、次の個人演習②「問い合わせ種別によるカテゴリ分類機能の追加」への橋渡しを行う。まず、今回の演習を通じて体験した「要件定義→実装方法の選定(SortオブジェクトかOrderBy命名規則メソッドか)→画面への組み込み→動作確認」という一連の流れが、実務における小規模な機能追加の典型的な進め方であることを確認する。

続いて、既存のEntity構造を変更せずに実現できた今回の演習に対し、次回から取り組むカテゴリ分類機能では、Inquiryエンティティへの新しいフィールドの追加とデータベーススキーマの変更を伴う、より難易度の高い改修になることを予告する。これにより、「フィールドを追加しない改修」と「フィールドを追加する改修」とでは、影響範囲の見極め方や作業手順がどのように変わってくるのかという視点を持たせる。

最後に、早く完成した受講者には、ソート条件の選択肢を増やす、あるいはページングと組み合わせるといった発展的な工夫を試すよう促し、個人の理解度に応じた自走的な取り組みを後押しする。

また、教員は巡回の中で、受講者ごとに異なる実装アプローチ(switch文かif文か、Controllerで分岐するかServiceに分岐ロジックを持たせるか等)を見て回り、後半でいくつかの実装例を簡単に紹介することで、個人演習であっても多様な設計判断があることに気づかせる機会とする。

あわせて、こうした振り返りをコマ34で作成した要件整理のメモと突き合わせ、実際に実装してみて初めて気づいた点や、当初の想定とは異なった部分がなかったかを確認することも勧める。要件整理と実装結果を照らし合わせる習慣は、次回以降のより難易度の高い演習にも活きる基礎的な姿勢である。

この細目で理解すべき範囲は、個人演習①の一連の流れの振り返りと、個人演習②で新たに扱うEntity変更を伴う改修の見通しまで。

キーワード ① ソート条件切り替え ② RequestParam ③ デバッグ ④ エッジケース ⑤ 動作確認
コマの展開方法 社会人講師 AL ICT PowerPoint・Keynote 教科書
コマ用オリジナル配布資料 コマ用プリント配布資料 その他 該当なし
小テスト 授業時間内に、LMS上において該当コマの小テストを実施する。
復習・予習課題 ◆今回授業の復習
今回完成させたソート条件切り替え機能について、自分の作業コピーで複数のソート条件を実際に切り替えながら、意図した順序で一覧が表示されることを再確認しておくこと。デバッグの際に確認したControllerのパラメータ受け取りとServiceへのSortオブジェクトの受け渡しの流れを、自分のコードを見ながら説明できるようにしておくこと。

◆次回授業の予習
次回からは個人演習②「問い合わせ種別によるカテゴリ分類機能の追加」に着手する。自分が管理しているお問い合わせ管理システムにおいて、問い合わせ内容をどのような種別(例:製品について、配送について、返品について等)に分類すると業務上便利かを考え、カテゴリの候補をいくつか挙げてメモしておくこと。あわせて、Java言語のEnum型についてこれまで学んだ内容を軽く復習しておくこと。

37 カテゴリ分類機能の設計 科目の中での位置付け 本コマからコマ38にかけての2コマは、フェーズ5個人演習②「問い合わせ種別によるカテゴリ分類機能の追加」に取り組む1回目である。前回までの優先度ソート機能が既存のフィールド構成を変更しない改修であったのに対し、本演習ではInquiryエンティティへの新しいフィールドの追加とデータベーススキーマの変更を伴う、より本格的な改修に取り組む。本コマでは実装に入る前段階として、カテゴリの要件定義とEntity設計への影響、Enum型を用いたカテゴリ表現の方法、既存DBスキーマへのカラム追加の考え方を扱う。
コマ主題細目 ① 問い合わせ種別(カテゴリ)の要件定義とEntity設計への影響 ② Enum型を用いたカテゴリ表現の実装方法 ③ 既存DBスキーマへのカラム追加(マイグレーションの考え方)
細目レベル ① 本細目では、カテゴリ分類機能を実装する前段階として、「問い合わせ内容をどのような種別に分類するか」という要件を自分自身で定義する演習を行う。実際のオンライン販売サイトを想定し、「製品について」「配送について」「返品・交換について」「支払いについて」「その他」といったカテゴリ候補を挙げ、業務上どのような分類が窓口対応の効率化に役立つかを考えさせる。

続いて、このカテゴリという新しい概念をInquiryエンティティにどのように反映するかを検討する。既存のフィールド(顧客名、メールアドレス、お問い合わせ内容、対応状況、受付日時)に加えて「カテゴリ」という新しいフィールドを追加する必要があること、そしてこの追加が単にEntityクラスにフィールドを1つ増やすだけでなく、データベースのテーブル定義、登録フォームの入力項目、一覧・詳細画面の表示項目、検索・絞り込み機能といった複数のレイヤーに影響が及ぶことを整理する。

コマ34で扱った「影響範囲分析」の考え方を実際に適用する場面として本演習を位置づけ、Entity・Repository・Service・Controller・Viewのどこに、どのような変更が必要になるかを受講者自身にリストアップさせる。

また、要件定義の段階で、カテゴリという分類が対応状況とは独立した軸であることも整理する。対応状況は「今どこまで処理が進んでいるか」を表す時間的な軸であるのに対し、カテゴリは「何についての問い合わせか」という内容面の軸であり、両者を組み合わせることで、例えば「未対応の配送に関する問い合わせ」のように、より具体的な絞り込みが可能になることを示す。

この細目で理解すべき範囲は、カテゴリの要件定義の考え方と、Entityへのフィールド追加が及ぼす影響範囲の整理まで。

② 本細目では、カテゴリのような「あらかじめ決まった選択肢の中から1つを選ぶ」データを表現するためのJavaのEnum型の活用方法を扱う。対応状況(未対応/対応中/対応済み)ではこれまで文字列や簡易な区分で表現してきたが、カテゴリについてはEnum型を用いることで、コード上の可読性と安全性を高める実装方法を新たに学ぶ。

具体的には、`public enum InquiryCategory { PRODUCT, SHIPPING, RETURN, PAYMENT, OTHER }`のようなEnum型を定義し、Inquiryエンティティのフィールドとして`@Enumerated(EnumType.STRING)`アノテーションとともに保持させる方法を解説する。`EnumType.STRING`を用いることで、データベース上には数値ではなく文字列としてカテゴリ名が保存され、後からEnumの定義順を変更してもデータの整合性が崩れないという実務上の利点にも触れる。

あわせて、Enum型に日本語の表示名(例:「製品について」)を持たせるためのフィールドとコンストラクタ、getterを追加する実装パターンや、Thymeleaf側でEnumの値をプルダウン(selectタグ)の選択肢として展開する方法(`th:each`でEnumの全要素を列挙する)についても具体的なコード例とともに紹介する。

さらに、カテゴリの選択肢が将来増える可能性(例えば新しい製品ラインの追加に伴う分類の追加)についても触れ、Enum型に選択肢を追加する場合の変更箇所(Enum定義、画面のプルダウン表示、必要であれば初期データ)を整理しておくことで、拡張性を意識した設計の考え方にも触れる。

この細目で理解すべき範囲は、Enum型によるカテゴリ表現の定義方法と、`@Enumerated(EnumType.STRING)`によるEntityへの組み込み方まで。

③ 本細目では、既存のInquiryテーブルに新しいカラム(カテゴリ)を追加する際の考え方を扱う。まず、これまでのフェーズ3〜4で構築してきたH2データベースが、Spring Data JPAの設定(`spring.jpa.hibernate.ddl-auto`)によってアプリケーション起動時にテーブル定義を自動生成・更新する仕組みになっていることを振り返り、Entityにフィールドを追加するだけで対応するカラムが自動的にテーブルに追加される仕組みを確認する。

続いて、この自動更新の仕組みが開発中の学習環境では便利である一方、実務における本番データベースでは既存データを保持したままカラムを追加する必要があり、FlywayやLiquibaseといったマイグレーションツールを用いて`ALTER TABLE`文をバージョン管理する手法が一般的であることを、コラム的に紹介する。今回の演習ではH2のインメモリデータベースを使用しているため本格的なマイグレーション管理は扱わないが、「実務ではスキーマ変更にも慎重な手順が必要である」という基礎的な考え方には触れておく。

また、カラム追加に伴い、既存のダミーデータや初期データ投入用のJavaConfig(あるいはdata.sql)にもカテゴリの初期値を設定する必要があることを確認し、既存の動作を壊さないための配慮点として整理する。

さらに、Entityへのフィールド追加という変更が、これまでのフェーズ2〜4で積み上げてきたバリデーションやテスト的な確認作業(画面操作による動作確認)にも影響しうることを整理する。既存の登録・編集フォームがカテゴリという新しい項目を必須項目とするか任意項目とするかによって、既存のバリデーションルールへの追加が必要になる可能性があることにも触れ、次回コマ38の実装作業に向けた準備を整えさせる。

この細目で理解すべき範囲は、`ddl-auto`によるスキーマ自動更新の仕組みと、実務におけるマイグレーション管理の基礎的な考え方まで。

キーワード ① カテゴリ分類 ② Enum型 ③ EnumType.STRING ④ スキーマ変更 ⑤ ddl-auto
コマの展開方法 社会人講師 AL ICT PowerPoint・Keynote 教科書
コマ用オリジナル配布資料 コマ用プリント配布資料 その他 該当なし
小テスト 授業時間内に、LMS上において該当コマの小テストを実施する。
復習・予習課題 ◆今回授業の復習
今回検討したカテゴリ候補(製品について、配送について等)と、それをEnum型として表現する方法(`@Enumerated(EnumType.STRING)`の役割)について、自分の言葉で説明できるようにしておくこと。あわせて、Entityへのフィールド追加がEntity・DB・フォーム・画面のどこに影響するかを整理したメモを見返し、次回の実装で何を作る必要があるかを具体的にイメージしておくこと。

◆次回授業の予習
次回コマ38では、今回設計したEnum型のカテゴリを実際にEntityに組み込み、カテゴリによる絞り込み検索機能と画面(登録フォーム・一覧・詳細)への表示を実装して演習②を完成させる。自分が定義したカテゴリの選択肢を確認し、登録フォームでどのようにカテゴリを選択させる見た目(プルダウンやラジオボタン等)が使いやすいか、簡単にイメージしておくこと。

38 カテゴリ分類機能の実装完成 科目の中での位置付け 本コマは、フェーズ5個人演習②「問い合わせ種別によるカテゴリ分類機能の追加」の2回目であり、前回コマ37で設計したEnum型によるカテゴリ表現とEntityへのフィールド追加を、実際に動作するアプリケーションとして完成させる回である。カテゴリによる絞り込み検索機能の実装と、登録フォーム・一覧・詳細画面へのカテゴリ表示への反映を個人演習として進め、最後に演習全体を振り返る。次回コマ39からは個人演習③「CSV出力機能の追加」へと進む。
コマ主題細目 ① カテゴリによる絞り込み検索機能の実装 ② 画面(登録フォーム・一覧・詳細)へのカテゴリ表示の反映 ③ 演習の振り返り
細目レベル ① 本細目では、前回コマ37で定義したカテゴリのEnum型とEntityへのフィールド追加を踏まえ、カテゴリによる絞り込み検索機能を実装する演習を行う。まず、Spring Data JPAのリポジトリメソッドとして、`List<Inquiry> findByCategory(InquiryCategory category)`のようなクエリメソッド命名規則を用いた実装方法を確認し、コマ25〜26で扱った検索機能の考え方をカテゴリという新しい条件に応用する。

続いて、対応状況による絞り込みとカテゴリによる絞り込みを組み合わせたい場合には、`findByCategoryAndStatus`のようにクエリメソッド名を連結する方法や、条件が増えるにつれてメソッド名が長くなる場合には`Specification`やJPQLを用いた動的クエリへの発展的な選択肢があることにも触れ、まずはシンプルなクエリメソッドで実現する方針を確認する。

さらに、一覧画面にカテゴリを選択するためのプルダウンを配置し、選択されたカテゴリをクエリパラメータとしてControllerに渡し、Controller内で該当するリポジトリメソッドを呼び出すという、コマ35〜36のソート機能実装で経験した「画面からのパラメータ受け取り→Controllerでの分岐→Serviceへの委譲」という実装パターンを再利用しながら実装を進めることを促す。

また、絞り込み検索の実装が完了した段階で、対応状況・カテゴリという2つの軸のどちらを主軸にした画面構成にするかという、ユーザビリティ上の判断にも触れる。両方の条件を同時にプルダウンで選べるようにするか、まずはカテゴリのみのシンプルな絞り込みから着手するかは、個人演習として各自の完成度目標に応じて選択してよいことを伝える。

この細目で理解すべき範囲は、カテゴリを条件とするクエリメソッドの実装方法と、画面からの絞り込み条件の受け渡しの実装パターンまで。

② 本細目では、カテゴリという新しい情報を、登録フォーム・一覧画面・詳細画面のそれぞれにどのように反映させるかを実装する演習を行う。まず登録フォーム(Form-Backing Bean)にカテゴリのフィールドを追加し、Thymeleafの`th:field`と`select`タグを用いて、Enum型の全要素をプルダウンの選択肢として動的に展開する実装を行う。これにより、フォーム送信時にカテゴリの選択値がBindingを通じてFormオブジェクトに格納される流れを確認する。

続いて、一覧画面のテーブルにカテゴリの列を追加し、Bootstrapのバッジコンポーネントを用いてカテゴリごとに異なる色を付けるなど、視認性を高める表示の工夫を行う。詳細画面についても同様に、カテゴリの表示名(Enumに保持させた日本語表示名)を表示する実装を加える。

これらの実装を通じて、Entityへのフィールド追加という1つの変更が、Form・Controller・複数のView(登録・一覧・詳細)という広い範囲に波及することを実感させ、コマ34・コマ37で学んだ「影響範囲分析」の視点が実際の実装作業でどのように活きるかを体験させる。個人演習として各自のアプリケーションに合わせた表示デザインの工夫も推奨する。

また、詳細画面や一覧画面でカテゴリを表示する際に、Enum型の英語の定数名(PRODUCT等)をそのまま表示してしまうと利用者にとって分かりにくくなる点にも注意を促す。表示名を保持するgetterメソッドを必ず経由して画面に渡すという実装上のルールを徹底させ、内部的な実装(Enumの定数名)と利用者向けの表示(日本語名)を分離して考える設計上の基本姿勢を身につけさせる。

この細目で理解すべき範囲は、登録フォーム・一覧・詳細の各画面へのカテゴリ表示の実装方法と、Entity変更が複数画面に波及する実感まで。

③ 本細目では、個人演習②として取り組んだカテゴリ分類機能の実装を振り返る。まず、優先度ソート機能(個人演習①)とカテゴリ分類機能(個人演習②)を比較し、前者が既存のEntity構造を変更しない改修であったのに対し、後者はEntityへのフィールド追加とDBスキーマの変更、Enum型の導入という、より広い範囲に影響が及ぶ改修であったことを整理する。この難易度の違いを踏まえ、実務における機能追加の規模感や工数の見積もりにもつながる感覚を養う。

続いて、受講者ごとに実装したカテゴリの分類方法や画面デザインの工夫を教員がデモ的に紹介し、同じ要件に対しても実装のアプローチやUIの見せ方に個人差が生まれることを確認し合う。これにより、個人演習であっても他者の実装から学ぶ機会を作る。

最後に、次回コマ39から取り組む個人演習③「CSV出力機能の追加」が、これまでの画面表示中心の機能とは異なり、ファイル入出力という新しい技術要素を扱う中級〜上級のお題であることを予告し、「Webアプリケーションからファイルをダウンロードさせる」という新しいテーマへの関心を高める。

また、演習を通じて生じた疑問点や、実装中に詰まった箇所についても簡単に共有する時間を設け、同じお題に取り組んだ受講者同士で解決の糸口を得られるようにする。個人演習であっても、つまずきの経験や解決方法を共有し合うことが理解の定着につながることを強調し、次回以降の演習にも同様の姿勢で臨むよう促す。

この細目で理解すべき範囲は、個人演習①と②の難易度・影響範囲の違いの整理と、個人演習③で新たに扱うファイル入出力というテーマへの見通しまで。

キーワード ① 絞り込み検索 ② クエリメソッド ③ カテゴリ表示 ④ 影響範囲 ⑤ バッジ表示
コマの展開方法 社会人講師 AL ICT PowerPoint・Keynote 教科書
コマ用オリジナル配布資料 コマ用プリント配布資料 その他 該当なし
小テスト 授業時間内に、LMS上において該当コマの小テストを実施する。
復習・予習課題 ◆今回授業の復習
今回完成させたカテゴリによる絞り込み検索機能と、登録フォーム・一覧・詳細画面へのカテゴリ表示について、自分の作業コピーで一通り操作し、正しく動作することを再確認しておくこと。優先度ソート機能とカテゴリ分類機能とで、影響が及んだ範囲(クラスや画面)がどのように異なっていたかを自分の実装を見ながら整理しておくこと。

個人演習②を通じて、Entityへのフィールド追加が複数レイヤーに波及する感覚を実際のコード変更箇所を見ながら振り返り、影響範囲分析の考え方を自分の言葉で説明できるようにしておくこと。

◆次回授業の予習
次回からは個人演習③「CSV出力機能の追加」に着手する。自分が管理しているお問い合わせ管理システムのデータを、CSVファイルとして出力できると業務上どのような場面で役立つかを考えておくこと。あわせて、これまでの授業で学んだJavaのファイル入出力(I/O)に関する既存の知識があれば軽く振り返っておくこと。

39 CSV出力機能の設計と基礎 科目の中での位置付け 本コマは、フェーズ5個人演習③「CSV出力機能の追加」の1回目である。これまでの2つの個人演習が画面表示や検索条件の追加であったのに対し、本演習ではWebアプリケーションからファイルを生成しダウンロードさせるという、中級〜上級に位置づけられる新しいテーマに取り組む。本コマでは実装に入る前段階として、CSV出力機能の利用シーンを想定した要件定義、Javaにおけるファイル入出力の基礎、HTTPレスポンスとしてCSVファイルをダウンロードさせる仕組みの概要を扱う。
コマ主題細目 ① CSV出力機能の要件定義(利用シーンの想定) ② Javaにおけるファイル入出力の基礎(OutputStream・Writer) ③ HTTPレスポンスとしてのCSVダウンロードの仕組み
細目レベル ① 本細目では、CSV出力機能を実装する前段階として、「どのような場面でこの機能が使われるのか」という利用シーンを想定した要件定義を行う。オンライン販売サイトの窓口担当者が、1日の終わりにその日受け付けたお問い合わせの一覧を日次レポートとしてExcelやスプレッドシートに取り込み、上長への報告や社内の情報共有に用いる場面を具体例として提示し、CSV形式で出力できることの業務上の価値を説明する。

続いて、CSV出力の対象範囲をどう設計するかという論点を扱う。すべてのお問い合わせを出力する単純な実装から始め、余力があれば、これまでの演習で実装したカテゴリや対応状況による絞り込み検索の結果だけをCSV出力する、受付日時の範囲(当日分のみ等)を指定して出力するといった発展的な要件も考えられることを示し、個人演習として自分がどこまでの機能を目指すかを自分で設計させる。

あわせて、CSVファイルに含める列(顧客名、メールアドレス、お問い合わせ内容、対応状況、カテゴリ、受付日時)の並び順や、ヘッダー行の要否についても、実際にExcelで開いた際の見やすさを意識して検討させる。

さらに、CSV出力機能を業務要件として捉える際に、「誰が」「いつ」「何のために」使うのかという利用者視点を明確にすることの重要性にも触れる。窓口担当者が日々の業務報告のために使うのか、管理者が月次の集計のために使うのかによって、出力すべき期間や項目の粒度が変わりうることを示し、要件定義の基本姿勢を再確認する。

また、要件定義の演習の一環として、CSV出力用のURL(エンドポイント)をどのように設計するかについても軽く考えさせる。一覧画面のボタンから遷移させる形にするのか、URLを直接入力してダウンロードさせる形にするのかといった利用者の操作導線も含めて検討することで、機能単体ではなく画面全体の使い勝手を意識した設計につなげる。

この細目で理解すべき範囲は、CSV出力機能の利用シーンの想定と、出力対象・出力項目の設計の考え方まで。

② 本細目では、CSV出力機能の実装に必要となるJavaのファイル入出力(I/O)の基礎を扱う。これまでの授業では、Web上のデータはEntity・Repository・Thymeleafのテンプレートを介して画面に表示されるという流れのみを扱ってきたが、CSV出力ではアプリケーション自身が「ファイルの中身となる文字列(テキストデータ)」を組み立てて出力するという、これまでとは異なる処理が必要になることを確認する。

具体的には、`java.io.OutputStream`が「バイト単位でデータを出力先へ書き出す」ための基本的な仕組みであることを確認した上で、文字コードを意識しながらテキストを書き出すための`OutputStreamWriter`や`PrintWriter`、`BufferedWriter`といったラッパークラスの役割を解説する。CSV形式ではカンマ区切り・改行区切りという単純なテキスト構造で表現できるため、`Inquiry`のリストを1件ずつループしながら、各フィールドの値をカンマで連結し改行を挟んで書き出していく処理の骨格をコード例とともに示す。

あわせて、フィールドの値自体にカンマや改行、ダブルクォートが含まれる場合にCSVとして正しく解釈されなくなる問題(エスケープ処理の必要性)にも軽く触れ、実務レベルのCSV出力では既存のライブラリを活用する選択肢があることも紹介する。

あわせて、try-with-resources構文を用いてストリームを確実にクローズする重要性にも触れる。ファイルやストリームを扱う処理では、例外発生時にもリソースが確実に解放されるようにする実装習慣が必要であることを説明し、これまでのDB接続処理(JDBC)で学んだリソース管理の考え方がファイル入出力にも共通することを確認する。

この細目で理解すべき範囲は、`OutputStream`・`Writer`系クラスの役割とCSV形式のテキストを組み立てる基本的な処理の流れまで。

③ 本細目では、Spring MVCのControllerからCSVファイルをHTTPレスポンスとしてブラウザにダウンロードさせる仕組みの概要を扱う。これまでのControllerメソッドはThymeleafのテンプレート名を返す、あるいはリダイレクト先を返すという実装が中心であったが、ファイルダウンロードでは`HttpServletResponse`を直接操作し、レスポンスヘッダーとレスポンスボディの両方を自分でコントロールする必要があることを説明する。

具体的には、レスポンスの`Content-Type`ヘッダーに`text/csv`を設定すること、`Content-Disposition`ヘッダーに`attachment; filename=...`を設定することでブラウザに「ファイルとして保存する」動作をさせられること、そして`response.getOutputStream()`または`response.getWriter()`から取得したストリームに対して、細目2で扱ったCSVの文字列を書き出す、という一連の流れを概要として提示する。

あわせて、日本語を含むCSVファイルをExcelで正しく開けるようにするための文字コード(Shift_JISやUTF-8にBOMを付与する等)の実務上の注意点にも軽く触れ、次回コマ40以降で実際にController・Serviceのコードとして実装していく際の見通しを持たせる。この細目で理解すべき範囲は、`Content-Type`・`Content-Disposition`ヘッダーの役割と、HTTPレスポンスとしてCSVを出力する処理の全体像まで。

キーワード ① CSV出力 ② OutputStream ③ Content-Disposition ④ ファイル入出力 ⑤ 日次レポート
コマの展開方法 社会人講師 AL ICT PowerPoint・Keynote 教科書
コマ用オリジナル配布資料 コマ用プリント配布資料 その他 該当なし
小テスト 授業時間内に、LMS上において該当コマの小テストを実施する。
復習・予習課題 ◆今回授業の復習
今回学習したOutputStream・Writer系クラスの役割と、HTTPレスポンスとしてCSVをダウンロードさせる仕組み(Content-Type、Content-Dispositionヘッダーの役割)について、自分の言葉で説明できるようにしておくこと。あわせて、自分が出力したいCSVの項目(顧客名、メールアドレス、対応状況、カテゴリ、受付日時等)とその並び順を、実際にメモとして書き出しておくこと。

また、try-with-resources構文の役割についても簡単に振り返り、ファイル入出力においてリソースを確実に解放することの重要性を自分の言葉で説明できるようにしておくこと。

◆次回授業の予習
次回はCSV出力機能の実装を進めていく回となる。今回整理したCSVの出力項目・出力範囲の設計メモを見返し、ControllerにどのようなURL(例:`/inquiries/export`)でアクセスすればCSVがダウンロードされるようにしたいか、具体的なイメージを持っておくこと。

40 CSV出力機能の実装完成 科目の中での位置付け 本コマは、前回のコマ39でCSV出力機能の設計と基礎を学んだことを受け、「個人演習③」の2回目としてその実装を完成させる回である。HttpServletResponseを直接操作してブラウザにファイルをダウンロードさせるという、Spring MVCの標準的なMVCパターンとは一線を画す処理形態を実際に手を動かして完成させ、あわせて日本語データを扱う上で避けて通れない文字コードの問題(Shift_JISとUTF-8、Excelでの文字化け)への対処を学ぶ。単に「動くコード」を書くだけでなく、実際の利用者がExcelで開いたときに困らない品質まで踏み込んで完成させることを到達目標とし、最後に演習全体を振り返ることで、設計から実装までの一連の開発サイクルを体験として定着させる。
コマ主題細目 ① HttpServletResponseによるCSVファイルダウンロード処理の実装 ② 文字コード(Shift_JIS/UTF-8)とExcelでの文字化け対策 ③ CSV出力演習の振り返りとレビュー
細目レベル ① 本細目では、前回のコマ39で設計したCSV出力の方針に基づき、実際にInquiryの一覧データをCSV形式の文字列へ変換し、HttpServletResponseを通じてブラウザにファイルとしてダウンロードさせる処理を完成させる。これまでThymeleafによるHTML画面の表示を前提としてきたSpring MVCのControllerとは異なり、CSV出力用のハンドラメソッドではreturn文でビュー名を返すのではなく、レスポンスオブジェクトに対して直接バイト列を書き込むという、いわば「Viewを経由しない」処理形態を扱う点にまず注意を促す。具体的には、Controllerのメソッド引数にHttpServletResponse responseを受け取り、response.setContentType("text/csv")によりコンテンツタイプを指定した上で、response.getOutputStream()またはresponse.getWriter()を通じてCSVの各行を書き込んでいく。

続いて、ブラウザにダウンロードダイアログを表示させるための重要な設定として、Content-Dispositionヘッダの付与を実装する。response.setHeader("Content-Disposition", "attachment; filename=inquiries.csv")のように指定することで、ブラウザはレスポンスを画面表示ではなくファイル保存の対象として扱うようになる。あわせて、日本語を含むファイル名を指定する場合にはURLエンコードが必要になる場面があることにも触れ、実際にファイル名に日本語を含めた場合の挙動を確認する演習を行う。

さらに、Inquiryのリストを1行ずつCSVの形式(カンマ区切り)に変換するロジックをService側に実装する。この際、お問い合わせ内容のようなフリーテキストの中にカンマや改行、ダブルクォートが含まれていた場合にCSVの列がずれてしまう問題にも言及し、値をダブルクォートで囲む、あるいは値の中のダブルクォートをエスケープするといった基本的な対処方針を、実際のサンプルデータを用いて確認する。この細目で理解すべき範囲は、HttpServletResponseへの直接書き込みによるCSV出力の実装方法、Content-Dispositionヘッダによるダウンロード指定、およびCSV形式変換時の特殊文字(カンマ・改行・ダブルクォート)への配慮まで。

② 本細目では、CSV出力において日本語環境特有の注意点となる文字コードの扱いと、Excelで開いた際の文字化け対策について学ぶ。まず、Windows版のExcelは既定でCSVファイルをShift_JIS(正確にはWindows-31J)として解釈する仕様になっており、Java側でUTF-8のままCSVを出力すると、Excelで開いた瞬間に日本語の顧客名やお問い合わせ内容が文字化けを起こす現象を、実際に手元の環境で再現して確認する。この体験を通じて、「サーバー側で正しく処理できているデータが、クライアント側のソフトウェアの既定の解釈によって崩れて見える」という、文字コード問題特有のわかりにくさを実感させる。

対策の一つ目として、出力する文字コードをShift_JISに明示的に変換する方法を扱う。response.getOutputStream()に対し、new OutputStreamWriter(response.getOutputStream(), "Shift_JIS")のように文字コードを指定してPrintWriterを生成し、CSVの内容をShift_JISのバイト列として書き出す。この方法はExcelとの相性が最も良い一方で、Shift_JISで表現できない文字(一部の環境依存文字や絵文字など)が含まれる場合には文字化けや例外が発生しうるという限界にも触れる。

対策の二つ目として、UTF-8を維持したままExcelに正しく認識させる方法であるBOM(Byte Order Mark)の付与を扱う。UTF-8のバイト列の先頭にBOM(0xEF, 0xBB, 0xBF)を書き込んでおくことで、Excelがそのファイルを「UTF-8で書かれている」と認識し、文字化けせずに開けるようになる仕組みを、実際にBOMを付与したファイルと付与しないファイルを見比べながら確認する。両アプローチの長所・短所(Shift_JISは他ソフトとの互換性、UTF-8+BOMは表現可能な文字の広さ)を整理し、本演習ではどちらか一方を選択して実装を完成させる。この細目で理解すべき範囲は、Excelの既定の文字コード解釈による文字化けの発生メカニズム、Shift_JISへの明示的な変換による対策、およびBOM付与によるUTF-8のExcel対応という2つの代表的な解決手段の理解まで。

③ 本細目では、コマ39〜40の2回にわたって取り組んだCSV出力機能の演習全体を振り返り、設計段階での検討事項が実装段階でどのように具体化されたかを整理する。前回のコマ39で検討した「どの項目を出力するか」「ヘッダ行を付けるか」といった設計上の判断が、今回のHttpServletResponseへの書き込み処理やCSVの行生成ロジックにそのまま反映されていることを、設計時のメモと完成したコードを突き合わせながら確認する。この振り返りにより、設計と実装が地続きのプロセスであることをあらためて意識させる。

あわせて、実装を通じて発生したつまずきのポイント(文字化け、Content-Dispositionの指定漏れ、CSVの列ずれなど)を学生同士で共有し、教員がよくある誤りとその原因をデモを交えて解説する。特に文字コードの問題は、動作確認をブラウザ上のHTML表示だけで済ませてしまうと気づきにくく、実際にファイルをダウンロードしてExcelで開くところまで確認して初めて発覚するという性質があるため、「動いているように見える」ことと「正しく動いている」ことの違いを意識した検証の重要性を強調する。

最後に、本演習で扱わなかった発展的な論点(大量データを扱う際のストリーミング出力、出力対象列をユーザーが選択できるようにする設計、CSV以外の形式であるExcelファイル(.xlsx)への直接出力など)を紹介し、余力のある学生が次の学習ステップとして自主的に取り組めるよう視野を広げておく。この細目で理解すべき範囲は、設計から実装までの一連の開発プロセスの振り返り、CSV出力実装における典型的なつまずきとその対処、および発展的な論点の所在の把握まで。

キーワード ① HttpServletResponse ② Content-Disposition ③ 文字コード変換 ④ BOM ⑤ CSVエスケープ
コマの展開方法 社会人講師 AL ICT PowerPoint・Keynote 教科書
コマ用オリジナル配布資料 コマ用プリント配布資料 その他 該当なし
小テスト 授業時間内に、LMS上において該当コマの小テストを実施する。
復習・予習課題 ◆今回授業の復習
今回完成させたCSV出力機能について、実際にダウンロードしたファイルをExcelで開き、日本語の顧客名やお問い合わせ内容が文字化けせずに正しく表示されることを必ず確認してください。もし文字化けが発生する場合は、文字コードの指定箇所(OutputStreamWriterの生成部分やBOMの付与処理)を見直し、原因を自分の手で特定してください。また、お問い合わせ内容にカンマや改行を含むデータをあえて登録し、CSVの列がずれずに正しく出力されるかもあわせて確認しておいてください。

◆次回授業の予習
次回の授業では、これまで画面(HTML)を返してきたお問い合わせ管理システムの一部機能を、JSON形式のデータとして返すREST APIへと作り替える設計を学びます。「REST API」という言葉と、これまで作ってきたMVC(画面遷移型)のアプリケーションとの違いについて、簡単に調べておいてください。あわせて、ブラウザ以外のクライアント(スマートフォンアプリなど)がサーバーとどのようにデータをやり取りするのか、想像を巡らせておくと理解がスムーズになります。

41 REST API化の設計 科目の中での位置付け 本コマは、フェーズ5における「個人演習④【2コマ】」の1回目であり、これまでThymeleafによる画面表示を前提としてきたお問い合わせ管理システムの一部機能を、JSON形式でデータをやり取りするREST APIとして設計し直す、上級者向けのお題である。画面遷移を伴うMVCパターンと、データそのものをやり取りするREST APIという2つの設計思想の違いを対比的に理解し、@RestControllerや@RequestBody/@ResponseBodyといった新たなアノテーションの役割を学んだ上で、次回コマ42での実装完成に備えて対象機能とAPI仕様を具体的に設計することを目的とする。
コマ主題細目 ① REST APIの概念とMVC(画面遷移型)との違い ② @RestControllerと@RequestBody/@ResponseBodyの役割 ③ お問い合わせ管理システムのAPI化対象機能とエンドポイント設計
細目レベル ① 本細目では、これまで一貫して採用してきたMVC(Model-View-Controller)パターンによる画面遷移型のアプリケーションと対比しながら、REST(Representational State Transfer)の考え方に基づくAPIとはどのようなものかを解説する。これまでのControllerは、Thymeleafのテンプレートエンジンと連携してHTML文書そのものを生成し、ブラウザに画面として表示させることを最終的な出力としてきた。ユーザーはリンクやフォームを操作するたびに新しい画面(HTML全体)を受け取り、ブラウザがそれを解釈して表示するという流れであった。

これに対しREST APIは、HTML文書ではなくJSON(あるいはXML)のようなデータそのものをレスポンスとして返す点が本質的に異なる。クライアント(ブラウザのJavaScript、スマートフォンアプリ、あるいは別のサーバーなど)は、受け取ったデータを自分自身の都合に合わせて自由に加工・表示できるようになり、画面の見た目とデータの提供元を分離できるという利点が生まれる。この「画面とデータを分離する」という発想の転換こそが、REST API化の学習における最大のポイントであることを強調する。あわせて、URLに対する操作の意味をHTTPメソッド(GET=取得、POST=作成、PUT/PATCH=更新、DELETE=削除)に対応させるというRESTの基本原則にも触れ、これまで学んできた@GetMapping/@PostMappingの知識が、REST API設計においてより体系的な意味を持つようになることを示す。

最後に、なぜ本科目の集大成であるフェーズ5でREST API化を上級者向けのお題として位置づけているのかについても説明する。画面ベースのCRUDアプリケーションが完成した今だからこそ、「同じ機能を別の見せ方(データ提供)で実現するとどう変わるか」という比較を通じて、Webアプリケーション開発における設計の自由度と、フロントエンドとバックエンドを分離する現代的なアーキテクチャへの入り口を体感できることを伝える。この細目で理解すべき範囲は、MVCパターンとREST APIという2つの設計思想の違い、REST APIがデータそのものを返すことの意味、およびHTTPメソッドと操作の対応関係という基本原則の理解まで。

② 本細目では、Spring MVCにおいてREST APIを実装するための中心的なアノテーションである@RestControllerと、そのリクエスト・レスポンスにおけるデータ変換を担う@RequestBody・@ResponseBodyの役割を学ぶ。まず、これまで用いてきた@Controllerアノテーションは、ハンドラメソッドの戻り値の文字列を「ビュー名」として解釈し、対応するThymeleafテンプレートを探して画面を生成する仕組みであったことを振り返る。これに対し@RestControllerは、実質的に@Controllerと@ResponseBodyを組み合わせたアノテーションであり、ハンドラメソッドの戻り値をビュー名としてではなく、レスポンスボディそのもの(多くの場合JSON)として直接クライアントに返す点が本質的に異なることを対比的に説明する。

具体的には、@RestControllerを付与したControllerのメソッドがList<Inquiry>のようなJavaオブジェクトをそのまま返すと、Spring Bootに組み込まれているJacksonというライブラリが自動的にそのオブジェクトをJSON文字列へ変換し、Content-Typeをapplication/jsonに設定した上でレスポンスとして送信してくれる仕組みを解説する。この「オブジェクトを返すだけでJSONに変換される」という挙動の裏側でHttpMessageConverterという仕組みが働いていることにも軽く触れ、フレームワークがどのような処理を肩代わりしてくれているのかを意識させる。

さらに、クライアントからJSON形式のデータを受け取る場面で用いる@RequestBodyについても解説する。POSTやPUTリクエストのボディに含まれるJSONデータを、@RequestBody InquiryForm formのようにメソッド引数へ指定することで、Jacksonが自動的にJSON文字列をJavaオブジェクトへ変換(デシリアライズ)してくれる。これは、これまでフォームのパラメータをForm-Backing Beanで受け取っていた仕組みと構造的には似ているが、データの送信元がHTMLフォームではなくJSON文字列である点が異なることを整理する。この細目で理解すべき範囲は、@RestControllerと@Controllerの違い、オブジェクトが自動的にJSONへ変換される仕組み(HttpMessageConverter)の概略、および@RequestBodyによるJSONデータの受信方法まで。

③ 本細目では、お問い合わせ管理システムのどの機能をREST API化の対象とするかを検討し、具体的なエンドポイント設計を行う演習に取り組む。まず、既存のCRUD機能(一覧取得・登録・更新・削除)の中から、次回コマ42で確実に実装を完成させられる範囲として、まずは「お問い合わせ一覧をJSON形式で取得するAPI」を必須の対象として設定する。あわせて、余力に応じて個別のお問い合わせをID指定で取得するAPI、新規登録を行うAPIなど、難易度に応じた発展課題も選択肢として提示する。

エンドポイント設計にあたっては、RESTの慣習に沿ったURL設計(例:一覧取得はGET /api/inquiries、個別取得はGET /api/inquiries/{id})を紹介し、これまでの画面用URL(例:/inquiry/list)とは別の名前空間(/api配下)を用いることで、画面用のControllerとAPI用のControllerを明確に分離するという設計判断を解説する。この分離により、既存の画面機能に影響を与えることなく、並行してAPIを開発できるという実務上の利点にも触れる。

最後に、各自が今回の授業内で、対象とするエンドポイントのURL・HTTPメソッド・レスポンスとして返すデータ項目(顧客名、メールアドレス、対応状況など全項目を返すか、一部に絞るか)を簡単な設計メモとして書き出す演習を行う。この設計メモは次回コマ42での実装作業の指針となるため、教員がデモを交えながら各自の設計内容を確認し、実装可能な粒度に調整する助言を行う。この細目で理解すべき範囲は、API化対象機能の選定における考え方、REST的なURL設計の慣習と画面用URLとの分離方針、および実装前の設計メモとしてのエンドポイント仕様の書き出しまで。

キーワード ① REST API ② @RestController ③ @RequestBody ④ HttpMessageConverter ⑤ エンドポイント設計
コマの展開方法 社会人講師 AL ICT PowerPoint・Keynote 教科書
コマ用オリジナル配布資料 コマ用プリント配布資料 その他 該当なし
小テスト 授業時間内に、LMS上において該当コマの小テストを実施する。
復習・予習課題 ◆今回授業の復習
今回学んだMVCパターンとREST APIの違いについて、これまで作成してきたお問い合わせ一覧画面(HTML)と、これから作るお問い合わせ一覧API(JSON)が同じInquiryのデータを扱っていながら何が異なるのかを、自分の言葉でノートに整理してください。また、今回設計したエンドポイント(URL・HTTPメソッド・返すデータ項目)を、次回の実装にそのまま使える程度まで具体的に書き出しておいてください。

◆次回授業の予習
次回の授業では、今回設計したエンドポイントをもとに、実際にJSON形式でお問い合わせ一覧を返すAPIを実装し、ブラウザやcurlコマンドを使って動作確認を行います。curlコマンドについて簡単に調べ、GETリクエストをコマンドラインから送信する基本的な書式を確認しておいてください。また、ブラウザで直接JSON形式のレスポンスを表示した場合にどのような見た目になるかも、余裕があれば予想しておいてください。

42 REST API化の実装完成 科目の中での位置付け 本コマは、前回コマ41で設計したエンドポイント仕様に基づき、「個人演習④」の2回目としてお問い合わせ一覧取得APIなどのREST API実装を完成させる回である。@RestControllerと@RequestBody/@ResponseBodyの知識を実際のコードに落とし込み、ブラウザやcurlコマンドを用いた動作確認まで一通り経験することで、REST API開発の一連の流れを体験する。あわせて、コマ35から本コマまで続いたフェーズ5前半の個人演習全体を振り返り、各自が取り組んだ機能追加・改修の内容を共有し合うことで、多様な実装アプローチに触れる機会とする。
コマ主題細目 ① JSON形式でのレスポンス実装(お問い合わせ一覧取得APIなど) ② 動作確認(ブラウザ・curl等でのAPI呼び出し) ③ フェーズ5個人演習(コマ35〜42)全体の振り返り
細目レベル ① 本細目では、前回コマ41で設計したエンドポイント仕様に基づき、実際にJSON形式でお問い合わせ一覧を返すAPIを実装する。まず、画面用のInquiryControllerとは別に、REST API専用のInquiryApiControllerのような新しいクラスを作成し、クラス全体に@RestControllerを付与する。@RequestMapping("/api/inquiries")のようにクラスレベルで共通のパスを指定した上で、@GetMappingを付与したメソッド内でInquiryServiceから一覧データを取得し、List<Inquiry>をそのままreturn文で返す実装を行う。この時点で、これまで意識してきた「ビュー名を返す」という発想から、「データそのものを返す」という発想へ切り替わっていることを、コードを書きながら実感させる。

続いて、返却するデータの形をどこまで既存のInquiryエンティティに依存させるかという設計判断についても扱う。Entityをそのまま返すと、JPAの内部的な情報が意図せずJSONに含まれてしまう場合があることに触れ、必要に応じてAPIレスポンス専用の簡易なDTO(データ転送用クラス)を用意し、外部に公開してよい項目だけを選んで詰め替えるという発展的な設計手法も紹介する。ただし本科目ではEntityを直接返す簡易な実装を基本形とし、DTOの導入はあくまで余力のある学生向けの発展的選択肢として位置づける。

さらに、個別のお問い合わせをID指定で取得するAPI(GET /api/inquiries/{id})に挑戦する学生に向けては、@PathVariableを用いたパス変数の受け取り方や、該当するIDが存在しない場合にどのようなレスポンス(404 Not Foundなど)を返すべきかという設計判断についても、教員が個別に助言する形で対応する。この細目で理解すべき範囲は、@RestControllerを用いた一覧取得APIの基本実装、EntityをそのままJSONとして返す場合の注意点とDTOという発展的選択肢の存在、および個別取得APIにおけるパス変数と存在しないデータへの対応まで。

② 本細目では、実装が完成したREST APIが実際に正しく動作しているかを、複数の方法で確認する演習を行う。まず最も手軽な確認方法として、Webブラウザのアドレスバーに直接APIのURL(例:http://localhost:8080/api/inquiries)を入力し、GETリクエストを送信した結果としてJSON形式のレスポンスがそのまま画面に表示されることを確認する。この際、ブラウザによってはJSON整形表示機能が働き、階層構造が見やすく表示されることにも触れ、開発時の動作確認においてブラウザが手軽なツールとして活用できることを実感させる。

次に、より実務的な確認方法としてcurlコマンドを用いたAPI呼び出しを演習する。ターミナルからcurl http://localhost:8080/api/inquiriesのようなコマンドを実行し、レスポンスとして返るJSON文字列をそのまま確認する。あわせて、curlに-iオプションを付与することでレスポンスヘッダ(Content-Type: application/jsonなど)もあわせて確認し、ブラウザが自動的に処理してくれていた情報が実際にはどのような形でやり取りされているのかを、生のHTTP通信のレベルで理解させる。POSTでの登録APIに挑戦した学生には、curl -X POST -H "Content-Type: application/json" -d '{...}' ...のような形でJSONデータを送信する方法もあわせて紹介する。

最後に、意図的に存在しないIDを指定してAPIを呼び出す、あるいは不正な形式のJSONを送信するといった異常系のテストも行い、実装したAPIがエラー時にどのような挙動を示すかを確認する。この確認を通じて、正常系だけでなく異常系の挙動まで含めて動作確認することの重要性を、REST API開発の基本姿勢として身につけさせる。この細目で理解すべき範囲は、ブラウザによるGET APIの簡易確認方法、curlコマンドを用いたレスポンス・レスポンスヘッダの確認方法、および異常系を含めた動作確認の重要性の理解まで。

③ 本細目では、コマ35からコマ42まで続いたフェーズ5前半の個人演習(対応状況によるソート、カテゴリ分類、CSV出力、REST API化など、難易度別に用意されたお題)について、各自が取り組んだ内容を振り返り、共有する時間を設ける。個人演習であるため学生ごとに選択したお題や実装の完成度は異なるが、全員が共通して「完成したCRUDアプリケーションに対し、既存のコードを壊さずに新しい機能を安全に追加する」という実務的な作業を経験してきたことを、あらためて言語化して確認する。

振り返りにあたっては、各自が実装の過程でつまずいた点、うまくいった工夫、参考にした技術情報などを簡単に共有し合う時間を設け、教員が代表的な実装例をデモとして紹介する。特にREST API化に挑戦した学生の実装については、画面ベースの実装との対比が明確になるため、クラス全体で見比べる価値が高い題材として扱う。この共有を通じて、同じ題材であっても取り組み方や設計判断に多様性があることを実感し、自分とは異なるアプローチから新たな学びを得る機会とする。

最後に、フェーズ5前半で得られた経験(設計から実装、動作確認までの一連の開発サイクルを自走した経験)が、次に控えるAOPの発展課題や、フェーズ5後半の総復習・総まとめにどうつながっていくかを見通す。特に、機能追加のたびにController/Serviceに似たようなコードが増えていく感覚を持った学生がいれば、それこそが次回コマ43で扱うAOPというテーマへの絶好の導入になることを予告する。この細目で理解すべき範囲は、フェーズ5前半の個人演習全体を通じて何を経験してきたかの言語化、多様な実装アプローチからの相互学習、およびAOP発展課題への導入としての位置づけの理解まで。

キーワード ① JSON変換 ② curl ③ @PathVariable ④ DTO ⑤ 異常系確認
コマの展開方法 社会人講師 AL ICT PowerPoint・Keynote 教科書
コマ用オリジナル配布資料 コマ用プリント配布資料 その他 該当なし
小テスト 授業時間内に、LMS上において該当コマの小テストを実施する。
復習・予習課題 ◆今回授業の復習
今回完成させたREST APIについて、ブラウザとcurlコマンドの両方から実際にアクセスし、同じデータが異なる見た目・情報量で確認できることを比較しながら整理してください。あわせて、意図的に存在しないIDを指定するなどの異常系のテストを自分の実装に対して行い、想定通りの挙動になっているかを確認しておいてください。フェーズ5前半で自分が取り組んだ演習内容についても、どのような設計判断を行ったかを簡単に振り返っておいてください。

◆次回授業の予習
次回の授業では、上級者向けの任意チャレンジ課題として、AOP(アスペクト指向プログラミング)によるリファクタリングを扱います。まず、ログ出力や処理時間計測のようなコードを、複数のControllerやServiceのメソッドに手作業でコピー&ペーストして実装するとどのような問題が起きそうか、想像を巡らせておいてください。「同じようなコードがあちこちに散らばる」ことの不便さを、自分がこれまで書いてきたコードに照らして考えておくと、次回の学習がより実感を伴ったものになります。

43 【発展課題】AOPによるリファクタリング 科目の中での位置付け 本コマは、フェーズ5における上級者向けの任意チャレンジ課題として、AOP(アスペクト指向プログラミング)の概念とその実践的な価値を体験する回である。成績評価の対象には含めず、余力のある学生が発展的に取り組むコラム的な位置づけとする。まず既存のControllerやServiceのメソッドにログ出力・処理時間計測のコードを手作業でコピー&ペーストして実装し、重複コードが増えていく痛みをあえて体験させたうえで、@Aspect+@Aroundを用いてその共通処理を1つのクラスへ集約するリファクタリングを行う。余力があれば、これまで当然のように使ってきた@Transactionalも同じ仕組みで動いていることへの種明かしにも到達する。
コマ主題細目 ① ログ出力・処理時間計測コードの手動コピペ実装と重複コードの痛み ② AOP(アスペクト指向プログラミング)の概念と@Aspect・@Around ③ 横断的関心事の集約と@Transactionalへの種明かし
細目レベル ① 本細目では、まずAOPのありがたみを体感するための前段階として、あえて素朴な方法でログ出力と処理時間計測の機能を実装する演習を行う。具体的には、InquiryControllerやInquiryServiceの複数のメソッドの冒頭と末尾に、System.out.println等を用いてメソッド名や引数の内容をログとして出力するコード、およびSystem.currentTimeMillis()を用いて処理開始時刻と終了時刻を記録し、その差分から処理時間を計算して出力するコードを、1つ1つのメソッドに対して手作業でコピー&ペーストしながら実装していく。

この作業を3つ、4つのメソッドに対して繰り返すうちに、学生自身が「同じようなコードを何度も書いている」という違和感を強く持つよう、教員は意図的にある程度の数のメソッドへの実装を課題として課す。単なる説明としてではなく、実際に手を動かして重複コードを書く体験そのものが、この細目の核心である。コピー&ペーストを繰り返す過程で、変数名の統一忘れやログ出力形式の微妙なばらつきといった、人手による重複実装につきものの品質のばらつきにも直面させる。

さらに、この状態のまま新しいメソッドが追加されるたびに同じログ出力・計測コードを書き足していく未来を想像させ、「本来のビジネスロジック(お問い合わせの検索・登録などの本質的な処理)と、ログ出力や計測処理という付随的な関心事が、コードの中で分かちがたく混在してしまっている」という問題点を言語化する。この状態を指して「関心事が横断的に散らばっている」と表現できることを予告し、次の細目で学ぶAOPがこの問題に対する解決策として提示されることへの期待感を持たせる。この細目で理解すべき範囲は、ログ出力・処理時間計測コードを複数メソッドへ手作業で実装する体験、その過程で生じる重複コードとその品質のばらつきの実感、および関心事の混在という問題点の言語化まで。

② 本細目では、前の細目で体験した重複コードの問題を解決する手段として、AOP(アスペクト指向プログラミング:Aspect Oriented Programming)の考え方を導入する。AOPとは、ログ出力や処理時間計測、あるいはトランザクション管理のように、アプリケーションの多くの箇所に共通して現れるが本質的なビジネスロジックとは異なる関心事(横断的関心事)を、1か所にまとめて定義し、必要な箇所へ後から織り込む(weaveする)というプログラミングパラダイムである。この定義だけでは抽象的でわかりにくいため、直前の細目で実際に重複させたログ出力コードを念頭に置きながら説明することで、具体的なイメージと結びつけて理解させる。

Spring AOPにおける実践的な実装方法として、@Aspectアノテーションを付与したクラス(例:LoggingAspect)を新規に作成し、その中に@Aroundアノテーションを付与したメソッド(アドバイスと呼ばれる)を定義する。@Aroundには、どのメソッドに対して処理を織り込むかを指定するポイントカット式(例:execution(* com.example.inquiry.controller..*(..))のような記法)を指定し、対象となるメソッド群を一括で捕捉できることを解説する。アドバイスメソッドの内部では、ProceedingJoinPointという引数を通じて、本来呼び出されるはずだったメソッド(joinPoint.proceed())の前後に、ログ出力や処理時間計測のコードを1か所だけ記述すればよいことを、実際にコードを書きながら確認する。

このAOPによる実装が完成すると、これまで各メソッドに個別に埋め込んでいたログ出力・計測コードをすべて削除しても、実行時には同じログや計測結果が出力され続けるという、いわば「魔法のような」体験をする。この体験こそが、AOPの価値を実感として理解させる最大のポイントであり、ポイントカット式1つで対象範囲を柔軟に増減できる利便性もあわせて確認する。この細目で理解すべき範囲は、AOPの基本概念(横断的関心事の分離と織り込み)、@Aspect・@Aroundを用いた実装の基本記法、およびポイントカット式による対象メソッドの指定方法まで。

③ 本細目では、前細目で完成させたAOPによるリファクタリングの成果を整理するとともに、余力のある学生に向けてさらに発展的な内容を紹介する。まず、リファクタリング前後のコード量とメソッドの見通しの良さを比較し、ビジネスロジックそのものを表すコードから、ログ出力・計測処理という付随的な関心事が完全に分離されたことを確認する。この分離により、今後ログ出力の形式を変更したい場合や、計測対象のメソッドを追加・削除したい場合にも、LoggingAspectクラス1か所を修正するだけで済むようになるという保守性の向上を、具体的な変更シナリオを想定しながら実感させる。

続いて、余力のある学生に向けて、「実はこの科目でこれまで当然のように使ってきた@Transactionalアノテーションも、同じAOPの仕組みによって実現されている」という種明かしを行う。@Transactionalが付与されたメソッドの呼び出し時に、Spring FrameworkがCGLIBやJDKダイナミックプロキシを用いて対象クラスのプロキシを生成し、そのプロキシがメソッド呼び出しの前後でトランザクションの開始・コミット・ロールバックといった処理を織り込んでいるという内部構造を、今回自作したLoggingAspectと対比しながら解説する。これにより、これまでブラックボックスとして扱ってきたアノテーションの内部で、実は今回学んだのと同じ仕組みが動いていたという発見的な理解を促す。

最後に、本課題があくまで上級者向けの任意チャレンジであり、成績評価の対象には含まれないことをあらためて確認した上で、AOPやプロキシベースの仕組みは実務のフレームワーク開発やライブラリ設計においても重要な考え方であることを伝え、興味を持った学生がさらに自主的に学習を深められるよう参考文献や発展的なキーワード(動的プロキシ、Spring AOPとAspectJの違いなど)を紹介する。この細目で理解すべき範囲は、AOPによるリファクタリングの効果の整理、@Transactionalが同じAOPの仕組みで実現されているという発展的理解、および本課題が任意の発展学習であるという位置づけの再確認まで。

キーワード ① AOP ② @Aspect ③ @Around ④ 横断的関心事 ⑤ 動的プロキシ
コマの展開方法 社会人講師 AL ICT PowerPoint・Keynote 教科書
コマ用オリジナル配布資料 コマ用プリント配布資料 その他 該当なし
小テスト 授業時間内に、LMS上において該当コマの小テストを実施する。
復習・予習課題 ◆今回授業の復習
今回体験した「ログ出力コードを手作業で複数メソッドにコピー&ペーストする作業」と、「@Aspect・@Aroundで1か所に集約する作業」のそれぞれについて、コード量や修正のしやすさがどう変化したかを具体的に比較し、ノートに整理してください。余力があれば、ポイントカット式の指定範囲を変更し、対象となるメソッドの範囲を意図的に増減させて、AOPの柔軟性を自分の手で確認しておいてください。本課題は成績評価の対象外ですが、時間の許す限り取り組んでおくことを推奨します。

◆次回授業の予習
次回の授業では、フェーズ1のシステムアーキテクチャ史からフェーズ4のSpring Boot MVCまでの全体像を、あらためて総復習します。これまでの授業で使ってきた資料やノートを見返し、特にフェーズ1で体験したServlet/JSP開発の「不便さ」と、フェーズ2以降でSpring Bootがそれをどう解決してきたかについて、自分の言葉で説明できるかどうかを一度確認しておいてください。

44 総復習:アーキテクチャ史からSpring Bootまでの全体像 科目の中での位置付け 本コマは、フェーズ5の締めくくりに向けた総復習として、全45回の授業内容のうち特にフェーズ1のシステムアーキテクチャ史とServlet/JSP開発の体験、そしてフェーズ2〜4で積み上げてきたSpring Boot MVC開発の技術要素を、あらためて俯瞰的に整理する回である。個別の技術トピックを断片的に振り返るのではなく、「なぜその技術が必要とされたのか」という歴史的・技術的な必然性の連鎖として全体像を再構成することに主眼を置き、次回コマ45の総まとめ(理解度確認・今後の学習)への橋渡しとする位置付けである。
コマ主題細目 ① システムアーキテクチャ史(メインフレーム→C/S、CGI→Servlet)の振り返り ② Servlet/JSP開発の課題とSpring Bootによる解決の対比 ③ DI・JavaConfig・MVC・JPA・Securityなど技術要素の関連づけ整理
細目レベル ① 本細目では、フェーズ1のコマ1〜2で学んだシステムアーキテクチャの歴史的変遷を、あらためて時系列に沿って振り返る。集中処理を前提としたメインフレームの時代から、処理をクライアントとサーバーに分散させるクライアント/サーバー(C/S)モデルへの移行、そしてインターネットの普及に伴いWebブラウザをクライアントとするWebアプリケーションが主流となっていく流れを、当時それぞれの方式が解決しようとした課題(集中処理の限界、クライアント側の管理コスト、配布の手間など)と対応づけながら再確認する。

続いて、Web上での動的なコンテンツ生成の出発点であるCGI(Common Gateway Interface)の仕組みと、リクエストのたびにプロセスを新規起動するというCGIの性能上の課題、そしてその課題を解決する形で登場したServletが、Webサーバーのプロセス内でリクエストを処理し続けられる(プロセス起動のオーバーヘッドがない)という優位性を持っていたことを、コマ2で学んだ内容に立ち返って整理する。この振り返りにおいては、単に「CGIは遅く、Servletは速い」という結果の暗記にとどまらず、「なぜ遅かったのか(プロセス起動のコスト)」「なぜ速くなったのか(プロセスの使い回し)」という技術的な理由の理解を確認することに重点を置く。

最後に、この歴史的変遷全体を通じて一貫している「新しい技術は、それ以前の技術が抱えていた具体的な課題を解決するために登場する」という技術発展の基本的なパターンを言語化し、この見方がこの後のServletからSpring Bootへの移行の理解にもそのまま応用できることを予告する。この細目で理解すべき範囲は、メインフレームからC/Sモデルへの変遷とその背景にある課題、CGIの仕組みと性能上の課題、およびServletがCGIの課題をどのように解決したかという技術的な理由の理解まで。

② 本細目では、フェーズ1のコマ3〜6で実際に手を動かして体験したServlet/JSP開発の「不便さ」と、フェーズ2以降で導入したSpring Bootがそれらの課題をどのように解決してきたかを、1つずつ対比しながら整理する。まず、ServletでdoGetメソッド内にHTMLタグを文字列として直接書き出していた不便さ(画面デザインとロジックが強く結合し、可読性・保守性が著しく低い)を振り返り、これに対しSpring Boot導入後はThymeleafというテンプレートエンジンがController(ロジック)とView(画面)を明確に分離してくれたことを、実際に両方のコードを見比べながら確認する。

次に、フェーズ1のコマ5〜6で体験した手作りのHttpSessionによるログイン処理(セッションへのユーザー情報の格納、ログイン状態の判定を各Servletで個別に実装する煩雑さ)を振り返り、フェーズ3のコマ17〜18(セッション管理)、そしてフェーズ4のコマ32〜33で導入したSpring Securityが、認証・認可という共通の関心事をフレームワークレベルで一元的に扱えるようにしてくれたことを対比する。あわせて、Servlet単体のプロジェクト構成における設定ファイルの煩雑さと、Spring Bootの「規約優先設定(Convention over Configuration)」や組み込みサーバーによって、開発者が本質的なビジネスロジックに集中できるようになったという生産性の変化についても、コマ7で学んだ内容に立ち返って再確認する。

このように個々の技術要素を対比的に並べ直す作業を通じて、Spring Bootという1つのフレームワークが、単発の便利機能の寄せ集めではなく、「Servlet/JSP時代に開発者が繰り返し直面してきた具体的な痛みを、体系的に解決するために設計されたもの」であるという理解に到達させる。この細目で理解すべき範囲は、画面とロジックの分離・認証処理の一元化・設定の簡素化という3つの観点からのServlet/JSPとSpring Bootの対比、およびSpring Bootが体系的な課題解決として設計されているという理解まで。

③ 本細目では、フェーズ2〜4で個別に学習してきたDI、JavaConfig、MVC、JPA、Spring Securityといった技術要素が、実は互いにどのように関連し合いながら1つのお問い合わせ管理システムを支えているのかを、俯瞰的に整理する。まず、DI(依存性注入)がSpring Frameworkの中核をなす仕組みであり、@Serviceや@Repositoryといったステレオタイプアノテーションによる自動検出、あるいはJavaConfigによる明示的なBean定義によってDIコンテナにBeanとして登録された各コンポーネントが、Controllerへ@Autowiredを通じて注入されるという基本構造を、実際のInquiryControllerのコードを例に再確認する。

次に、MVCパターンにおけるController・Service・Repository(JPA)という3層構造が、DIによって疎結合に組み合わされていることを整理する。JpaRepositoryを実装したInquiryRepositoryがDIコンテナに登録され、InquiryServiceに注入され、さらにInquiryServiceがInquiryControllerに注入されるという一連の依存関係の連鎖を図解し、各層が互いの実装詳細を意識せずに協調動作できる設計になっていることを確認する。あわせて、Spring Securityの認証処理もまた、SecurityFilterChainというBeanをJavaConfigで定義し、DIコンテナに登録することで機能する仕組みになっており、フェーズ3で学んだJavaConfigの知識がフェーズ4のセキュリティ実装に直結していたことを、あらためて明示的に結びつける。

最後に、これら技術要素の関連図を学生自身に描かせる演習を行い、DI・JavaConfig・MVC・JPA・Securityという個々の単語の暗記ではなく、「Spring Bootというフレームワーク全体が、DIコンテナを中心とした一貫した設計思想のもとに統合されている」という構造的な理解に到達しているかを確認する。この細目で理解すべき範囲は、DIを中心としたController・Service・Repositoryの依存関係の連鎖、JavaConfigがSecurity設定にも活用されていることの理解、およびSpring Boot全体がDIコンテナを軸に統合された設計であることの俯瞰的理解まで。

キーワード ① アーキテクチャ史 ② Servlet/JSPの課題 ③ DIコンテナ ④ 技術要素の関連づけ ⑤ 俯瞰的理解
コマの展開方法 社会人講師 AL ICT PowerPoint・Keynote 教科書
コマ用オリジナル配布資料 コマ用プリント配布資料 その他 該当なし
小テスト 授業時間内に、LMS上において該当コマの小テストを実施する。
復習・予習課題 ◆今回授業の復習
今回の授業で整理した「メインフレーム→C/S→CGI→Servlet→Spring Boot」という技術の変遷を、自分なりの年表または図として白紙にまとめ直してください。それぞれの技術が「何を解決するために登場したのか」を一言で説明できるかを自己確認し、説明できない箇所があれば教科書や過去の授業資料に立ち返って確認しておいてください。また、DI・JavaConfig・MVC・JPA・Securityの関連図についても、今回の授業で描いた図を見返し、自分の言葉で人に説明できる状態に仕上げておいてください。

◆次回授業の予習
次回はいよいよ本科目最終回であり、全体の理解度確認と質疑応答、そして今後の学習の方向性についての総まとめを行います。これまでの授業を振り返り、特に理解があいまいなまま残っている技術トピックがあれば、質問としてまとめておいてください。また、完成したお問い合わせ管理システムについて、自分が加えた機能追加・改修の内容を簡潔に説明できるよう、成果を整理しておいてください。

45 総まとめ:理解度確認と今後の学習 科目の中での位置付け 本コマは全45回にわたる本科目の最終回であり、これまで積み上げてきた学習内容全体の理解度を質疑応答を通じて確認するとともに、フェーズ5を通じて各自が機能追加・改修を加えてきたお問い合わせ管理システムの完成形を発表・確認し、科目全体を締めくくる回である。単なる知識の総復習にとどまらず、Web環境システム開発という分野における今後の学習の方向性(発展的な技術領域、実務との接続)についても具体的な助言を行い、学生が本科目修了後も自律的に学び続けられるような視座を提供することを目的とする。
コマ主題細目 ① 科目全体の理解度確認(質疑応答と総括的な振り返り) ② 完成したお問い合わせ管理システムの成果確認・デモ ③ 今後の学習の方向性(発展的技術領域と実務との接続)
細目レベル ① 本細目では、全45回の授業を通じて学んできた内容について、質疑応答形式を中心に理解度を確認する時間を設ける。事前にコマ44の予習として各自にまとめさせた「理解があいまいな技術トピック」に関する質問を1つずつ取り上げ、教員が回答するとともに、必要に応じて該当するコマの内容に立ち返りながら短く再解説を行う。個々の質問への回答にとどまらず、その質問が科目全体のどの技術要素とつながっているかを都度示すことで、最後まで断片的な知識の寄せ集めではなく、体系だった理解として着地させることを意識する。

あわせて、フェーズごとの学習内容を教員側から短く総括する時間も設ける。フェーズ1でシステムアーキテクチャ史とServlet/JSPの課題を体験し、フェーズ2でSpring Bootによる基本的なMVC開発を習得し、フェーズ3でDI・JavaConfig・セッション・バリデーション・DB接続・JPAという中級的な技術を積み上げ、フェーズ4でCRUD・Thymeleaf応用・ページング・Securityを実装し、フェーズ5で機能追加・改修演習を通じてそれらを実践的に使いこなす経験を積んだという、45回全体の学習ストーリーをあらためて言語化して共有する。

最後に、簡単な確認問題や口頭での質問を通じて、各自が自分自身の理解度を客観的に把握できる機会を設ける。理解が不十分な箇所を「わからないまま終わらせない」ことを重視し、授業時間内で解消しきれない質問については、個別の質問対応やオフィスアワー等でのフォローアップにつなげる案内を行う。この細目で理解すべき範囲は、質疑応答を通じた個々の疑問点の解消とその科目全体への位置づけの理解、フェーズ1〜5の学習ストーリー全体の総括、および自分自身の理解度を客観的に把握し不明点を解消する姿勢の獲得まで。

② 本細目では、フェーズ5(コマ34〜43)を通じて各自が機能追加・改修に取り組んできたお問い合わせ管理システムの完成形を発表し、成果を確認し合う時間を設ける。個人演習であったため、対応状況によるソート、カテゴリ分類、CSV出力、REST API化、AOPによる発展課題など、学生ごとに取り組んだお題や到達度は異なっているが、全員が共通してコマ33完成時点のCRUDアプリケーションという同じ土台から出発し、そこに自分なりの付加価値を積み上げてきたという事実を、実際の画面やコードを見せ合いながら確認する。

発表にあたっては、単に完成した機能を動かして見せるだけでなく、実装にあたってどのような設計判断を行ったか、どこでつまずき、どのように解決したかというプロセスについても簡潔に共有させる。これにより、結果としての完成度だけでなく、開発の過程で発揮した問題解決の姿勢そのものが評価に値することを、あらためて学生に伝える。教員は各発表に対して、実務的な観点からの講評(コードの読みやすさ、エラー処理の丁寧さ、UIの使いやすさなど)を短く行い、今後の学習・開発における着眼点を示す。

最後に、コマ7のSpring Initializrによるプロジェクト作成から始まり、この最終回に至るまでのアプリケーションの成長の軌跡を、初期のダミーデータ表示画面のスクリーンショットと現在の完成画面を並べて振り返り、45回という長い学習期間を経て1つの本格的なWebアプリケーションを自らの手で完成させたという達成感を、クラス全体で共有する時間とする。この細目で理解すべき範囲は、フェーズ5で各自が取り組んだ機能追加・改修の成果の発表と相互確認、実装プロセスにおける設計判断・問題解決の共有、および科目全体を通じたアプリケーション成長の軌跡の総括的な確認まで。

③ 本細目では、本科目の修了をもって学習が完結するのではなく、ここから先どのような方向へ学習を発展させていけるかについて、具体的な助言を行う。まず技術的な発展方向として、本科目では扱わなかったトピック(Spring Bootにおけるより高度なテスト(JUnit・Mockitoを用いた単体テスト・結合テスト)、フロントエンドとバックエンドを分離したSPA(Single Page Application)構成とReact/Vue等のフレームワークとの連携、Dockerによるコンテナ化、マイクロサービスアーキテクチャなど)を、本科目で習得した知識を土台にどのように接続していけるかを、それぞれ簡単な位置づけとともに紹介する。

次に、実務との接続という観点から、本科目で経験した「画面ベースのCRUDアプリケーション開発」「REST API化」「AOPのような設計パターン」が、実際の企業におけるWebシステム開発の現場でどのように活用されているかを、一般的な事例を交えて説明する。特に、フェーズ5で経験した「既存の完成したアプリケーションに対して機能追加・改修を行う」という作業形態そのものが、実務におけるシステム開発・保守業務の縮図であったことを振り返り、ゼロから作る経験と同じくらい、既存コードを理解して安全に改修する経験の価値が高いことを強調する。

最後に、今後の学習を進める上での具体的な取り組み方(公式ドキュメントの読み方、個人でのポートフォリオ開発の勧め、コミュニティやオープンソースへの参加といった選択肢)について助言し、本科目で得た「フレームワークが何を解決してくれているのかを理解した上で使う」という姿勢が、今後どの技術を学ぶ場合にも通用する普遍的な学び方であることを伝えて、全45回にわたる本科目を締めくくる。この細目で理解すべき範囲は、本科目の先にある発展的な技術領域の見取り図、実務における開発・保守業務との接続の理解、および今後の自律的な学習の進め方に関する具体的な指針の獲得まで。

キーワード ① 理解度確認 ② 成果発表 ③ 開発の軌跡 ④ 発展的技術領域 ⑤ 実務との接続
コマの展開方法 社会人講師 AL ICT PowerPoint・Keynote 教科書
コマ用オリジナル配布資料 コマ用プリント配布資料 その他 該当なし
小テスト 授業時間内に、LMS上において該当コマの小テストを実施する。
復習・予習課題 ◆今回授業の復習
本科目全45回を通じて学んだ内容を、フェーズ1(アーキテクチャ史とServlet/JSP)からフェーズ5(機能追加・改修演習)まで通しで振り返り、自分が最も成長を実感した技術トピックと、今後さらに深めていきたい技術トピックをそれぞれ1つずつ言語化してみてください。完成したお問い合わせ管理システムのコードとスクリーンショットは、今後のポートフォリオや就職活動の際にも活用できる貴重な成果物として、必ず手元に保管しておいてください。

◆本科目の総括と今後の学習に向けて
本科目は、メインフレームからクライアント/サーバー、CGIからServlet、そしてSpring Bootへと至るシステムアーキテクチャの歴史的必然性を体験的に理解した上で、Spring Bootを用いた実践的なWebアプリケーション開発の力を身につけることを目標として構成されてきた。全45回を通じて完成させたお問い合わせ管理システムは、単なる演習課題ではなく、DI・MVC・JPA・Security・REST APIといった現代的なWeb開発技術が有機的に組み合わさった、実務に通用する土台である。今後は、本科目で得た「なぜその技術が必要とされるのかを理解した上で使う」という姿勢を軸に、テスト技法、フロントエンド連携、クラウド・コンテナ技術など、より広い技術領域への学習を自律的に発展させていくことを期待する。

履修判定指標
履修指標履修指標の水準キーワード配点関連回
第1部:Web開発の歴史と課題(Java Servlet/JSP)

履修指標:
フレームワーク以前の技術であるServletとJSPを用いた開発を体験し、HTTPプロトコルの仕組みやWebアプリの基本構造を理解する。手動での実装がいかに煩雑であるかを体感し、フレームワークが必要とされる背景と動機を明確にする。
【★☆☆初級】
- HTTPのリクエストとレスポンスの基本的な流れを説明できる
- IntelliJ IDEA UltimateとTomcatを用いたJava Web開発環境を構築し、動作確認ができる
- Servletを作成し、ブラウザ上に単純な文字列を表示できる

【★★☆中級】
- GETメソッドとPOSTメソッドの違いを理解し、フォーム処理を実装できる
- JSPを用いてHTMLとJavaコードを分離し、Servletから画面へ遷移できる
- リクエストスコープを利用して、画面間でデータの受け渡しができる

【★★★上級】
- セッション管理(HttpSession)を用いて、ログイン状態の維持を実装できる
- ServletとJSPのみで開発する場合のコードの可読性や保守性の課題を具体的に指摘できる
- MVCモデルの原型となる処理の流れを、フレームワークなしで構築できる
HTTPプロトコル、Servlet、JSP、GET/POSTメソッド、セッション管理 10 1, 2, 3, 4, 5, 6
第2部:Spring Boot導入とMVC基礎

履修指標:
現代のJava開発におけるデファクトスタンダードであるSpring Bootの概要と、Spring MVCによる基本的な画面表示・フォーム処理の実装手法を習得する。フェーズ1で体験したServlet/JSP開発の課題を踏まえ、フレームワークがそれをどのように解決するのかを実感する。
【★☆☆初級】
- Spring FrameworkおよびSpring Bootの役割と利点を説明できる
- Spring Initializrを用いてプロジェクトを作成できる
- Controllerクラスを作成し、特定のURLに対するリクエストを処理できる

【★★☆中級】
- Thymeleafを用いて、Modelに格納されたデータを画面に表示できる
- Thymeleafの制御構文(繰り返しや条件分岐)を用いて、動的な画面構成を作成できる
- @RequestParamやForm-Backing Beanを用いて、フォームから送信されたデータを取得できる

【★★★上級】
- PRG(Post-Redirect-Get)パターンの必要性を理解し、実装できる
- 複数のデータをModelを用いて整理し、Controllerを適切にリファクタリングできる
- MVCモデルにおけるModel、View、Controllerの役割分担を自分の言葉で説明できる
Spring Boot、Spring MVC、Thymeleaf、Model、Form-Backing Bean 15 7, 8, 9, 10, 11, 12, 13, 14
第3部:Spring Frameworkのコア機能とデータ永続化

履修指標:
Spring Frameworkの根幹をなすDI(依存性の注入)とJavaConfigによるBean定義の仕組みを理解し、セッション管理によるログイン処理、サーバーサイドバリデーション、そしてJDBCからSpring Data JPAへと至るデータベース連携技術を段階的に習得する。
【★☆☆初級】
- DIコンテナの役割を理解し、アノテーションを用いてBean定義ができる
- コンポーネントスキャンの仕組みにより、クラスが自動検出される流れを理解している
- HttpSessionオブジェクトを用いた基本的なセッション管理の仕組みを説明できる

【★★☆中級】
- @Autowiredアノテーションを用いて、必要なインスタンスを適切に注入できる
- JavaConfigを用いて、コンポーネントスキャンでは検出できないBeanを明示的に定義できる
- Spring Validationを用いて、入力データの単項目チェックとエラーメッセージの表示を実装できる

【★★★上級】
- 固定ID/パスワードによるログイン処理を実装し、認証が必要な画面へのアクセス制御ができる
- JdbcTemplateおよびSpring Data JPAを用いて、データベースへの永続化処理を実装できる
- 生のJDBCコードをJpaRepositoryに置き換え、Lombokを用いてEntityのボイラープレートを削減できる
DI(依存性の注入)、JavaConfig、セッション管理、Bean Validation、Spring Data JPA 20 15, 16, 17, 18, 19, 20, 21, 22, 23, 24
第4部:CRUDアプリケーション開発とセキュリティ

履修指標:
これまでに学習した知識を統合し、お問い合わせ管理システムの登録・検索・更新・削除(CRUD)機能を実装する。あわせて、共通レイアウトの部品化、ページング、そしてSpring Securityによる認証・認可の実装を通じて、実務水準の画面設計とセキュリティ対策の基礎を習得する。
【★☆☆初級】
- アプリケーションの要件に基づき、必要なEntityとRepositoryを作成できる
- お問い合わせの一覧表示および検索機能を実装できる
- Bootstrap 5のコンポーネントを用いて、統一感のある画面デザインを適用できる

【★★☆中級】
- お問い合わせの登録・更新・削除といったCRUD機能をすべて実装し、正常に動作させることができる
- Thymeleafのフラグメント機能を用いて、共通ヘッダーなどの部品を複数画面で再利用できる
- Pageableオブジェクトを用いて、一覧表示にページングとソート機能を実装できる

【★★★上級】
- 対応状況の一括更新など、複数入力やチェックボックスを伴うフォーム処理を実装できる
- Spring Securityを導入し、手作りのセッション認証を置き換えて認証・認可機能を実装できる
- 完成したアプリケーションをRenderなどのPaaS上に実際にデプロイし、公開できる
CRUD、Bootstrap、ページング、Spring Security、デプロイ 25 25, 26, 27, 28, 29, 30, 31, 32, 33
第5部:機能追加・改修演習と総括

履修指標:
フェーズ4までに完成したお問い合わせ管理システムを題材に、個人演習として機能追加・改修に取り組み、要件整理から設計、実装までを自律的に遂行する能力を養う。あわせて、科目全体で学習した技術要素を総復習し、体系的な理解として統合する。
【★☆☆初級】
- 既存のアプリケーションのコードを読み解き、機能追加に必要な変更範囲を特定できる
- ソート機能やカテゴリ分類など、比較的小規模な機能追加を設計・実装できる
- 科目全体で学習したアーキテクチャ史からSpring Bootまでの技術変遷を説明できる

【★★☆中級】
- Entityへのフィールド追加やEnum型の活用など、既存設計への影響を考慮した改修ができる
- CSV出力など、ファイル入出力を伴う機能を設計・実装できる
- 学習した各技術要素(DI、MVC、JPA、Securityなど)の関連性を体系的に整理できる

【★★★上級】
- REST APIとしての機能提供など、既存のMVCアーキテクチャを拡張する設計ができる
- 任意課題として、AOPを用いた重複コードのリファクタリングに取り組むことができる
- 完成したアプリケーション全体を見直し、保守性や可読性の観点から自律的に改善提案ができる
機能追加・改修、REST API、CSV出力、AOP、リファクタリング 30 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45
第6部:実践アプリケーション開発(ToDoアプリ)

履修指標:
これまでに学習した知識を統合し、ToDo管理アプリケーションの設計から実装までを行う。レイヤ化アーキテクチャに基づいた開発プロセスを実践し、実務に近い形でのアプリケーション構築能力を養う。
【★☆☆初級】
- アプリケーションの要件に基づき、必要なデータベースのテーブルを作成できる
- プロジェクトのパッケージ構成を適切に行い、各レイヤのクラスを配置できる
- ToDoの一覧表示および詳細表示機能を実装できる

【★★☆中級】
- Service層にビジネスロジックを集約し、ControllerやRepositoryと適切に連携させることができる
- ToDoの新規登録、更新、削除といったCRUD機能をすべて実装し、正常に動作させることができる
- 完了・未完了の状態管理など、アプリ固有のロジックを正しく実装できる

【★★★上級】
- 例外処理(Exception Handling)を実装し、予期せぬエラー発生時に適切なエラー画面へ遷移できる
- 検索機能やページネーションなど、ユーザビリティを考慮した機能拡張ができる
- 作成したアプリケーション全体のコードを見直し、保守性や可読性の観点からリファクタリングができる
レイヤ化アーキテクチャ、要件定義、Service層、Repository層、例外処理 20 30, 31, 32, 33, 34, 35, 36, 37, 38, 39
評価方法
評価基準 評語
    学習目標をほぼ完全に達成している・・・・・・・・・・・・・ S (100~90点)
    学習目標を相応に達成している・・・・・・・・・・・・・・・ A (89~80点)
    学習目標を相応に達成しているが不十分な点がある・・・・・・ B (79~70点)
    学習目標の最低限は満たしている・・・・・・・・・・・・・・ C (69~60点)
    学習目標の最低限を満たしていない・・・・・・・・・・・・・ D (60点未満)
教科書
参考文献
実験・実習・教材費