目次
- 1
- 2 🎯 この記事で実現すること
- 3 📱 完成イメージ
- 4 入力画面
- 5 一覧画面
- 6 🗂 ファイル構成
- 7 🛠 実装手順
- 8 Step 1: Studentモデルクラスを拡張
- 9 Step 2: StudentControllerを作成
- 10 Step 3: 入力フォーム画面を作成
- 11 Step 4: 一覧表示画面を作成
- 12 🔍 動作確認手順
- 13 💡 技術解説
- 14 MVCパターンの実装
- 15 Spring Bootの重要な機能
- 16 Thymeleafの便利な機能
- 17 🚀 さらなる機能拡張
- 18 1. データベース連携
- 19 2. 合格判定機能
- 20 3. バリデーション機能
- 21 4. 削除・編集機能
- 22 📝 まとめ
🎯 この記事で実現すること
名前と点数を入力フォームで送信し、それを一覧テーブルに追加表示する本格的なWebアプリケーションを作成します。前回の「表示だけ」から一歩進んで、ユーザーが実際にデータを入力できる動的なアプリに挑戦しましょう!
📱 完成イメージ
入力画面
1 2 3 4 |
<span>学生情報を入力 </span><span>名前: [太郎 ] </span><span>点数: [85 ] </span><span> [追加ボタン]</span> |
一覧画面
名前 | 点数 |
---|---|
太郎 | 85 |
花子 | 92 |
次郎 | 78 |
[新しい学生を登録] ← リンクで入力画面に戻る
🗂 ファイル構成
今回作成するファイルは以下の4つです:
ファイル名 | 役割 |
---|---|
Student.java |
名前と点数を持つモデルクラス |
StudentController.java |
入力フォームと一覧を処理するコントローラ |
student_form.html |
入力画面(フォーム) |
student_list.html |
一覧表示画面(テーブル形式) |
🛠 実装手順
Step 1: Studentモデルクラスを拡張
前回からsetterを追加します。フォームからデータを受け取るために必要です。
ファイル: src/main/java/com/example/demo/model/Student.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
<span><span class="token">package</span> <span class="token">com</span><span class="token">.</span><span class="token">example</span><span class="token">.</span><span class="token">demo</span><span class="token">.</span><span class="token">model</span><span class="token">;</span> </span><span> </span><span><span class="token">public</span> <span class="token">class</span> <span class="token">Student</span> <span class="token">{</span> </span><span> <span class="token">private</span> <span class="token">String</span> name<span class="token">;</span> </span><span> <span class="token">private</span> <span class="token">int</span> score<span class="token">;</span> </span><span> </span><span> <span class="token">public</span> <span class="token">Student</span><span class="token">(</span><span class="token">)</span> <span class="token">{</span><span class="token">}</span> <span class="token">// フォーム用の空コンストラクタ</span> </span><span> </span><span> <span class="token">public</span> <span class="token">Student</span><span class="token">(</span><span class="token">String</span> name<span class="token">,</span> <span class="token">int</span> score<span class="token">)</span> <span class="token">{</span> </span><span> <span class="token">this</span><span class="token">.</span>name <span class="token">=</span> name<span class="token">;</span> </span><span> <span class="token">this</span><span class="token">.</span>score <span class="token">=</span> score<span class="token">;</span> </span><span> <span class="token">}</span> </span><span> </span><span> <span class="token">// getter(表示用)</span> </span><span> <span class="token">public</span> <span class="token">String</span> <span class="token">getName</span><span class="token">(</span><span class="token">)</span> <span class="token">{</span> </span><span> <span class="token">return</span> name<span class="token">;</span> </span><span> <span class="token">}</span> </span><span> </span><span> <span class="token">public</span> <span class="token">int</span> <span class="token">getScore</span><span class="token">(</span><span class="token">)</span> <span class="token">{</span> </span><span> <span class="token">return</span> score<span class="token">;</span> </span><span> <span class="token">}</span> </span><span> </span><span> <span class="token">// setter(フォーム受け取り用)</span> </span><span> <span class="token">public</span> <span class="token">void</span> <span class="token">setName</span><span class="token">(</span><span class="token">String</span> name<span class="token">)</span> <span class="token">{</span> </span><span> <span class="token">this</span><span class="token">.</span>name <span class="token">=</span> name<span class="token">;</span> </span><span> <span class="token">}</span> </span><span> </span><span> <span class="token">public</span> <span class="token">void</span> <span class="token">setScore</span><span class="token">(</span><span class="token">int</span> score<span class="token">)</span> <span class="token">{</span> </span><span> <span class="token">this</span><span class="token">.</span>score <span class="token">=</span> score<span class="token">;</span> </span><span> <span class="token">}</span> </span><span><span class="token">}</span></span> |
重要ポイント:
public Student() {}
– 空のコンストラクタが必要setName()
,setScore()
– フォームから値を設定するため
Step 2: StudentControllerを作成
3つの処理(フォーム表示・送信処理・一覧表示)をまとめて管理します。
ファイル: src/main/java/com/example/demo/controller/StudentController.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
<span><span class="token">package</span> <span class="token">com</span><span class="token">.</span><span class="token">example</span><span class="token">.</span><span class="token">demo</span><span class="token">.</span><span class="token">controller</span><span class="token">;</span> </span><span> </span><span><span class="token">import</span> <span class="token">com</span><span class="token">.</span><span class="token">example</span><span class="token">.</span><span class="token">demo</span><span class="token">.</span><span class="token">model</span><span class="token">.</span><span class="token">Student</span><span class="token">;</span> </span><span><span class="token">import</span> <span class="token">org</span><span class="token">.</span><span class="token">springframework</span><span class="token">.</span><span class="token">stereotype</span><span class="token">.</span><span class="token">Controller</span><span class="token">;</span> </span><span><span class="token">import</span> <span class="token">org</span><span class="token">.</span><span class="token">springframework</span><span class="token">.</span><span class="token">ui</span><span class="token">.</span><span class="token">Model</span><span class="token">;</span> </span><span><span class="token">import</span> <span class="token">org</span><span class="token">.</span><span class="token">springframework</span><span class="token">.</span><span class="token">web</span><span class="token">.</span><span class="token">bind</span><span class="token">.</span><span class="token">annotation</span><span class="token">.</span><span class="token">*</span><span class="token">;</span> </span><span> </span><span><span class="token">import</span> <span class="token">java</span><span class="token">.</span><span class="token">util</span><span class="token">.</span><span class="token">ArrayList</span><span class="token">;</span> </span><span><span class="token">import</span> <span class="token">java</span><span class="token">.</span><span class="token">util</span><span class="token">.</span><span class="token">List</span><span class="token">;</span> </span><span> </span><span><span class="token annotation">@Controller</span> </span><span><span class="token">public</span> <span class="token">class</span> <span class="token">StudentController</span> <span class="token">{</span> </span><span> </span><span> <span class="token">// メモリ上でデータを保持(今回は簡単のため)</span> </span><span> <span class="token">private</span> <span class="token">List</span><span class="token generics"><</span><span class="token generics">Student</span><span class="token generics">></span> studentList <span class="token">=</span> <span class="token">new</span> <span class="token">ArrayList</span><span class="token generics"><</span><span class="token generics">></span><span class="token">(</span><span class="token">)</span><span class="token">;</span> </span><span> </span><span> <span class="token">// フォーム表示</span> </span><span> <span class="token annotation">@GetMapping</span><span class="token">(</span><span class="token">"/student/form"</span><span class="token">)</span> </span><span> <span class="token">public</span> <span class="token">String</span> <span class="token">showForm</span><span class="token">(</span><span class="token">Model</span> model<span class="token">)</span> <span class="token">{</span> </span><span> model<span class="token">.</span><span class="token">addAttribute</span><span class="token">(</span><span class="token">"student"</span><span class="token">,</span> <span class="token">new</span> <span class="token">Student</span><span class="token">(</span><span class="token">)</span><span class="token">)</span><span class="token">;</span> </span><span> <span class="token">return</span> <span class="token">"student_form"</span><span class="token">;</span> </span><span> <span class="token">}</span> </span><span> </span><span> <span class="token">// フォーム送信処理</span> </span><span> <span class="token annotation">@PostMapping</span><span class="token">(</span><span class="token">"/student/submit"</span><span class="token">)</span> </span><span> <span class="token">public</span> <span class="token">String</span> <span class="token">submitForm</span><span class="token">(</span><span class="token annotation">@ModelAttribute</span> <span class="token">Student</span> student<span class="token">)</span> <span class="token">{</span> </span><span> studentList<span class="token">.</span><span class="token">add</span><span class="token">(</span>student<span class="token">)</span><span class="token">;</span> </span><span> <span class="token">return</span> <span class="token">"redirect:/student/list"</span><span class="token">;</span> </span><span> <span class="token">}</span> </span><span> </span><span> <span class="token">// 一覧表示</span> </span><span> <span class="token annotation">@GetMapping</span><span class="token">(</span><span class="token">"/student/list"</span><span class="token">)</span> </span><span> <span class="token">public</span> <span class="token">String</span> <span class="token">showList</span><span class="token">(</span><span class="token">Model</span> model<span class="token">)</span> <span class="token">{</span> </span><span> model<span class="token">.</span><span class="token">addAttribute</span><span class="token">(</span><span class="token">"studentList"</span><span class="token">,</span> studentList<span class="token">)</span><span class="token">;</span> </span><span> <span class="token">return</span> <span class="token">"student_list"</span><span class="token">;</span> </span><span> <span class="token">}</span> </span><span><span class="token">}</span></span> |
処理の流れ:
- GET
/student/form
→ 入力フォーム画面を表示 - POST
/student/submit
→ 送信されたデータをリストに追加 - GET
/student/list
→ 登録済みデータを一覧表示
Step 3: 入力フォーム画面を作成
ファイル: src/main/resources/templates/student_form.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
<span><span class="token"><!</span><span class="token doctype-tag">DOCTYPE</span><span class="token"> </span><span class="token name">html</span><span class="token">></span> </span><span><span class="token"><</span><span class="token">html</span><span class="token"> </span><span class="token">lang</span><span class="token">=</span><span class="token">"</span><span class="token">ja</span><span class="token">"</span><span class="token"> </span><span class="token">xmlns:</span><span class="token">th</span><span class="token">=</span><span class="token">"</span><span class="token">http://www.thymeleaf.org</span><span class="token">"</span><span class="token">></span> </span><span><span class="token"><</span><span class="token">head</span><span class="token">></span> </span><span> <span class="token"><</span><span class="token">meta</span><span class="token"> </span><span class="token">charset</span><span class="token">=</span><span class="token">"</span><span class="token">UTF-8</span><span class="token">"</span><span class="token">></span> </span><span> <span class="token"><</span><span class="token">title</span><span class="token">></span>学生情報入力<span class="token"></</span><span class="token">title</span><span class="token">></span> </span><span> <span class="token"><</span><span class="token">style</span><span class="token">></span><span class="token style language-css"> </span></span><span><span class="token style language-css"> </span><span class="token style language-css">body</span><span class="token style language-css"> </span><span class="token style language-css">{</span><span class="token style language-css"> </span></span><span><span class="token style language-css"> </span><span class="token style language-css">font-family</span><span class="token style language-css">:</span><span class="token style language-css"> Arial</span><span class="token style language-css">,</span><span class="token style language-css"> sans-serif</span><span class="token style language-css">;</span><span class="token style language-css"> </span></span><span><span class="token style language-css"> </span><span class="token style language-css">max-width</span><span class="token style language-css">:</span><span class="token style language-css"> </span><span class="token style language-css">600</span><span class="token style language-css unit">px</span><span class="token style language-css">;</span><span class="token style language-css"> </span></span><span><span class="token style language-css"> </span><span class="token style language-css">margin</span><span class="token style language-css">:</span><span class="token style language-css"> </span><span class="token style language-css">50</span><span class="token style language-css unit">px</span><span class="token style language-css"> auto</span><span class="token style language-css">;</span><span class="token style language-css"> </span></span><span><span class="token style language-css"> </span><span class="token style language-css">padding</span><span class="token style language-css">:</span><span class="token style language-css"> </span><span class="token style language-css">20</span><span class="token style language-css unit">px</span><span class="token style language-css">;</span><span class="token style language-css"> </span></span><span><span class="token style language-css"> </span><span class="token style language-css">}</span><span class="token style language-css"> </span></span><span><span class="token style language-css"> </span><span class="token style language-css class">.form-group</span><span class="token style language-css"> </span><span class="token style language-css">{</span><span class="token style language-css"> </span></span><span><span class="token style language-css"> </span><span class="token style language-css">margin-bottom</span><span class="token style language-css">:</span><span class="token style language-css"> </span><span class="token style language-css">15</span><span class="token style language-css unit">px</span><span class="token style language-css">;</span><span class="token style language-css"> </span></span><span><span class="token style language-css"> </span><span class="token style language-css">}</span><span class="token style language-css"> </span></span><span><span class="token style language-css"> </span><span class="token style language-css">label</span><span class="token style language-css"> </span><span class="token style language-css">{</span><span class="token style language-css"> </span></span><span><span class="token style language-css"> </span><span class="token style language-css">display</span><span class="token style language-css">:</span><span class="token style language-css"> inline-block</span><span class="token style language-css">;</span><span class="token style language-css"> </span></span><span><span class="token style language-css"> </span><span class="token style language-css">width</span><span class="token style language-css">:</span><span class="token style language-css"> </span><span class="token style language-css">80</span><span class="token style language-css unit">px</span><span class="token style language-css">;</span><span class="token style language-css"> </span></span><span><span class="token style language-css"> </span><span class="token style language-css">font-weight</span><span class="token style language-css">:</span><span class="token style language-css"> bold</span><span class="token style language-css">;</span><span class="token style language-css"> </span></span><span><span class="token style language-css"> </span><span class="token style language-css">}</span><span class="token style language-css"> </span></span><span><span class="token style language-css"> </span><span class="token style language-css">input</span><span class="token style language-css attribute">[</span><span class="token style language-css attribute">type</span><span class="token style language-css attribute">=</span><span class="token style language-css attribute">"text"</span><span class="token style language-css attribute">]</span><span class="token style language-css">,</span><span class="token style language-css"> input</span><span class="token style language-css attribute">[</span><span class="token style language-css attribute">type</span><span class="token style language-css attribute">=</span><span class="token style language-css attribute">"number"</span><span class="token style language-css attribute">]</span><span class="token style language-css"> </span><span class="token style language-css">{</span><span class="token style language-css"> </span></span><span><span class="token style language-css"> </span><span class="token style language-css">width</span><span class="token style language-css">:</span><span class="token style language-css"> </span><span class="token style language-css">200</span><span class="token style language-css unit">px</span><span class="token style language-css">;</span><span class="token style language-css"> </span></span><span><span class="token style language-css"> </span><span class="token style language-css">padding</span><span class="token style language-css">:</span><span class="token style language-css"> </span><span class="token style language-css">8</span><span class="token style language-css unit">px</span><span class="token style language-css">;</span><span class="token style language-css"> </span></span><span><span class="token style language-css"> </span><span class="token style language-css">border</span><span class="token style language-css">:</span><span class="token style language-css"> </span><span class="token style language-css">1</span><span class="token style language-css unit">px</span><span class="token style language-css"> solid </span><span class="token style language-css hexcode color">#ddd</span><span class="token style language-css">;</span><span class="token style language-css"> </span></span><span><span class="token style language-css"> </span><span class="token style language-css">border-radius</span><span class="token style language-css">:</span><span class="token style language-css"> </span><span class="token style language-css">4</span><span class="token style language-css unit">px</span><span class="token style language-css">;</span><span class="token style language-css"> </span></span><span><span class="token style language-css"> </span><span class="token style language-css">}</span><span class="token style language-css"> </span></span><span><span class="token style language-css"> </span><span class="token style language-css">button</span><span class="token style language-css"> </span><span class="token style language-css">{</span><span class="token style language-css"> </span></span><span><span class="token style language-css"> </span><span class="token style language-css">background-color</span><span class="token style language-css">:</span><span class="token style language-css"> </span><span class="token style language-css hexcode color">#007bff</span><span class="token style language-css">;</span><span class="token style language-css"> </span></span><span><span class="token style language-css"> </span><span class="token style language-css">color</span><span class="token style language-css">:</span><span class="token style language-css"> </span><span class="token style language-css color">white</span><span class="token style language-css">;</span><span class="token style language-css"> </span></span><span><span class="token style language-css"> </span><span class="token style language-css">padding</span><span class="token style language-css">:</span><span class="token style language-css"> </span><span class="token style language-css">10</span><span class="token style language-css unit">px</span><span class="token style language-css"> </span><span class="token style language-css">20</span><span class="token style language-css unit">px</span><span class="token style language-css">;</span><span class="token style language-css"> </span></span><span><span class="token style language-css"> </span><span class="token style language-css">border</span><span class="token style language-css">:</span><span class="token style language-css"> none</span><span class="token style language-css">;</span><span class="token style language-css"> </span></span><span><span class="token style language-css"> </span><span class="token style language-css">border-radius</span><span class="token style language-css">:</span><span class="token style language-css"> </span><span class="token style language-css">4</span><span class="token style language-css unit">px</span><span class="token style language-css">;</span><span class="token style language-css"> </span></span><span><span class="token style language-css"> </span><span class="token style language-css">cursor</span><span class="token style language-css">:</span><span class="token style language-css"> pointer</span><span class="token style language-css">;</span><span class="token style language-css"> </span></span><span><span class="token style language-css"> </span><span class="token style language-css">}</span><span class="token style language-css"> </span></span><span><span class="token style language-css"> </span><span class="token style language-css">button</span><span class="token style language-css pseudo-class">:hover</span><span class="token style language-css"> </span><span class="token style language-css">{</span><span class="token style language-css"> </span></span><span><span class="token style language-css"> </span><span class="token style language-css">background-color</span><span class="token style language-css">:</span><span class="token style language-css"> </span><span class="token style language-css hexcode color">#0056b3</span><span class="token style language-css">;</span><span class="token style language-css"> </span></span><span><span class="token style language-css"> </span><span class="token style language-css">}</span><span class="token style language-css"> </span></span><span><span class="token style language-css"> </span><span class="token"></</span><span class="token">style</span><span class="token">></span> </span><span><span class="token"></</span><span class="token">head</span><span class="token">></span> </span><span><span class="token"><</span><span class="token">body</span><span class="token">></span> </span><span> <span class="token"><</span><span class="token">h1</span><span class="token">></span>📝 学生情報を入力<span class="token"></</span><span class="token">h1</span><span class="token">></span> </span><span> </span><span> <span class="token"><</span><span class="token">form</span><span class="token"> </span><span class="token">th:</span><span class="token">action</span><span class="token">=</span><span class="token">"</span><span class="token">@{/student/submit}</span><span class="token">"</span><span class="token"> </span><span class="token">th:</span><span class="token">object</span><span class="token">=</span><span class="token">"</span><span class="token">${student}</span><span class="token">"</span><span class="token"> </span><span class="token">method</span><span class="token">=</span><span class="token">"</span><span class="token">post</span><span class="token">"</span><span class="token">></span> </span><span> <span class="token"><</span><span class="token">div</span><span class="token"> </span><span class="token">class</span><span class="token">=</span><span class="token">"</span><span class="token">form-group</span><span class="token">"</span><span class="token">></span> </span><span> <span class="token"><</span><span class="token">label</span><span class="token"> </span><span class="token">for</span><span class="token">=</span><span class="token">"</span><span class="token">name</span><span class="token">"</span><span class="token">></span>名前:<span class="token"></</span><span class="token">label</span><span class="token">></span> </span><span> <span class="token"><</span><span class="token">input</span><span class="token"> </span><span class="token">type</span><span class="token">=</span><span class="token">"</span><span class="token">text</span><span class="token">"</span><span class="token"> </span><span class="token">th:</span><span class="token">field</span><span class="token">=</span><span class="token">"</span><span class="token">*{name}</span><span class="token">"</span><span class="token"> </span><span class="token">id</span><span class="token">=</span><span class="token">"</span><span class="token">name</span><span class="token">"</span><span class="token"> </span><span class="token">required</span><span class="token"> </span><span class="token">/></span> </span><span> <span class="token"></</span><span class="token">div</span><span class="token">></span> </span><span> </span><span> <span class="token"><</span><span class="token">div</span><span class="token"> </span><span class="token">class</span><span class="token">=</span><span class="token">"</span><span class="token">form-group</span><span class="token">"</span><span class="token">></span> </span><span> <span class="token"><</span><span class="token">label</span><span class="token"> </span><span class="token">for</span><span class="token">=</span><span class="token">"</span><span class="token">score</span><span class="token">"</span><span class="token">></span>点数:<span class="token"></</span><span class="token">label</span><span class="token">></span> </span><span> <span class="token"><</span><span class="token">input</span><span class="token"> </span><span class="token">type</span><span class="token">=</span><span class="token">"</span><span class="token">number</span><span class="token">"</span><span class="token"> </span><span class="token">th:</span><span class="token">field</span><span class="token">=</span><span class="token">"</span><span class="token">*{score}</span><span class="token">"</span><span class="token"> </span><span class="token">id</span><span class="token">=</span><span class="token">"</span><span class="token">score</span><span class="token">"</span><span class="token"> </span><span class="token">min</span><span class="token">=</span><span class="token">"</span><span class="token">0</span><span class="token">"</span><span class="token"> </span><span class="token">max</span><span class="token">=</span><span class="token">"</span><span class="token">100</span><span class="token">"</span><span class="token"> </span><span class="token">required</span><span class="token"> </span><span class="token">/></span> </span><span> <span class="token"></</span><span class="token">div</span><span class="token">></span> </span><span> </span><span> <span class="token"><</span><span class="token">button</span><span class="token"> </span><span class="token">type</span><span class="token">=</span><span class="token">"</span><span class="token">submit</span><span class="token">"</span><span class="token">></span>📊 一覧に追加<span class="token"></</span><span class="token">button</span><span class="token">></span> </span><span> <span class="token"></</span><span class="token">form</span><span class="token">></span> </span><span><span class="token"></</span><span class="token">body</span><span class="token">></span> </span><span><span class="token"></</span><span class="token">html</span><span class="token">></span></span> |
フォームの技術ポイント:
th:action="@{/student/submit}"
– 送信先URLth:object="${student}"
– バインドするオブジェクトth:field="*{name}"
– Studentクラスのnameフィールドと連携required
– 必須入力チェック
Step 4: 一覧表示画面を作成
ファイル: src/main/resources/templates/student_list.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
<span><span class="token"><!</span><span class="token doctype-tag">DOCTYPE</span><span class="token"> </span><span class="token name">html</span><span class="token">></span> </span><span><span class="token"><</span><span class="token">html</span><span class="token"> </span><span class="token">lang</span><span class="token">=</span><span class="token">"</span><span class="token">ja</span><span class="token">"</span><span class="token"> </span><span class="token">xmlns:</span><span class="token">th</span><span class="token">=</span><span class="token">"</span><span class="token">http://www.thymeleaf.org</span><span class="token">"</span><span class="token">></span> </span><span><span class="token"><</span><span class="token">head</span><span class="token">></span> </span><span> <span class="token"><</span><span class="token">meta</span><span class="token"> </span><span class="token">charset</span><span class="token">=</span><span class="token">"</span><span class="token">UTF-8</span><span class="token">"</span><span class="token">></span> </span><span> <span class="token"><</span><span class="token">title</span><span class="token">></span>学生一覧<span class="token"></</span><span class="token">title</span><span class="token">></span> </span><span> <span class="token"><</span><span class="token">style</span><span class="token">></span><span class="token style language-css"> </span></span><span><span class="token style language-css"> </span><span class="token style language-css">body</span><span class="token style language-css"> </span><span class="token style language-css">{</span><span class="token style language-css"> </span></span><span><span class="token style language-css"> </span><span class="token style language-css">font-family</span><span class="token style language-css">:</span><span class="token style language-css"> Arial</span><span class="token style language-css">,</span><span class="token style language-css"> sans-serif</span><span class="token style language-css">;</span><span class="token style language-css"> </span></span><span><span class="token style language-css"> </span><span class="token style language-css">max-width</span><span class="token style language-css">:</span><span class="token style language-css"> </span><span class="token style language-css">800</span><span class="token style language-css unit">px</span><span class="token style language-css">;</span><span class="token style language-css"> </span></span><span><span class="token style language-css"> </span><span class="token style language-css">margin</span><span class="token style language-css">:</span><span class="token style language-css"> </span><span class="token style language-css">50</span><span class="token style language-css unit">px</span><span class="token style language-css"> auto</span><span class="token style language-css">;</span><span class="token style language-css"> </span></span><span><span class="token style language-css"> </span><span class="token style language-css">padding</span><span class="token style language-css">:</span><span class="token style language-css"> </span><span class="token style language-css">20</span><span class="token style language-css unit">px</span><span class="token style language-css">;</span><span class="token style language-css"> </span></span><span><span class="token style language-css"> </span><span class="token style language-css">}</span><span class="token style language-css"> </span></span><span><span class="token style language-css"> </span><span class="token style language-css">table</span><span class="token style language-css"> </span><span class="token style language-css">{</span><span class="token style language-css"> </span></span><span><span class="token style language-css"> </span><span class="token style language-css">width</span><span class="token style language-css">:</span><span class="token style language-css"> </span><span class="token style language-css">100</span><span class="token style language-css unit">%</span><span class="token style language-css">;</span><span class="token style language-css"> </span></span><span><span class="token style language-css"> </span><span class="token style language-css">border-collapse</span><span class="token style language-css">:</span><span class="token style language-css"> collapse</span><span class="token style language-css">;</span><span class="token style language-css"> </span></span><span><span class="token style language-css"> </span><span class="token style language-css">margin</span><span class="token style language-css">:</span><span class="token style language-css"> </span><span class="token style language-css">20</span><span class="token style language-css unit">px</span><span class="token style language-css"> </span><span class="token style language-css">0</span><span class="token style language-css">;</span><span class="token style language-css"> </span></span><span><span class="token style language-css"> </span><span class="token style language-css">}</span><span class="token style language-css"> </span></span><span><span class="token style language-css"> </span><span class="token style language-css">th</span><span class="token style language-css">,</span><span class="token style language-css"> td</span><span class="token style language-css"> </span><span class="token style language-css">{</span><span class="token style language-css"> </span></span><span><span class="token style language-css"> </span><span class="token style language-css">border</span><span class="token style language-css">:</span><span class="token style language-css"> </span><span class="token style language-css">1</span><span class="token style language-css unit">px</span><span class="token style language-css"> solid </span><span class="token style language-css hexcode color">#ddd</span><span class="token style language-css">;</span><span class="token style language-css"> </span></span><span><span class="token style language-css"> </span><span class="token style language-css">padding</span><span class="token style language-css">:</span><span class="token style language-css"> </span><span class="token style language-css">12</span><span class="token style language-css unit">px</span><span class="token style language-css">;</span><span class="token style language-css"> </span></span><span><span class="token style language-css"> </span><span class="token style language-css">text-align</span><span class="token style language-css">:</span><span class="token style language-css"> center</span><span class="token style language-css">;</span><span class="token style language-css"> </span></span><span><span class="token style language-css"> </span><span class="token style language-css">}</span><span class="token style language-css"> </span></span><span><span class="token style language-css"> </span><span class="token style language-css">th</span><span class="token style language-css"> </span><span class="token style language-css">{</span><span class="token style language-css"> </span></span><span><span class="token style language-css"> </span><span class="token style language-css">background-color</span><span class="token style language-css">:</span><span class="token style language-css"> </span><span class="token style language-css hexcode color">#f8f9fa</span><span class="token style language-css">;</span><span class="token style language-css"> </span></span><span><span class="token style language-css"> </span><span class="token style language-css">font-weight</span><span class="token style language-css">:</span><span class="token style language-css"> bold</span><span class="token style language-css">;</span><span class="token style language-css"> </span></span><span><span class="token style language-css"> </span><span class="token style language-css">}</span><span class="token style language-css"> </span></span><span><span class="token style language-css"> </span><span class="token style language-css">tr</span><span class="token style language-css pseudo-class">:nth-child</span><span class="token style language-css">(</span><span class="token style language-css n-th">even</span><span class="token style language-css">)</span><span class="token style language-css"> </span><span class="token style language-css">{</span><span class="token style language-css"> </span></span><span><span class="token style language-css"> </span><span class="token style language-css">background-color</span><span class="token style language-css">:</span><span class="token style language-css"> </span><span class="token style language-css hexcode color">#f2f2f2</span><span class="token style language-css">;</span><span class="token style language-css"> </span></span><span><span class="token style language-css"> </span><span class="token style language-css">}</span><span class="token style language-css"> </span></span><span><span class="token style language-css"> </span><span class="token style language-css class">.add-link</span><span class="token style language-css"> </span><span class="token style language-css">{</span><span class="token style language-css"> </span></span><span><span class="token style language-css"> </span><span class="token style language-css">display</span><span class="token style language-css">:</span><span class="token style language-css"> inline-block</span><span class="token style language-css">;</span><span class="token style language-css"> </span></span><span><span class="token style language-css"> </span><span class="token style language-css">background-color</span><span class="token style language-css">:</span><span class="token style language-css"> </span><span class="token style language-css hexcode color">#28a745</span><span class="token style language-css">;</span><span class="token style language-css"> </span></span><span><span class="token style language-css"> </span><span class="token style language-css">color</span><span class="token style language-css">:</span><span class="token style language-css"> </span><span class="token style language-css color">white</span><span class="token style language-css">;</span><span class="token style language-css"> </span></span><span><span class="token style language-css"> </span><span class="token style language-css">padding</span><span class="token style language-css">:</span><span class="token style language-css"> </span><span class="token style language-css">10</span><span class="token style language-css unit">px</span><span class="token style language-css"> </span><span class="token style language-css">20</span><span class="token style language-css unit">px</span><span class="token style language-css">;</span><span class="token style language-css"> </span></span><span><span class="token style language-css"> </span><span class="token style language-css">text-decoration</span><span class="token style language-css">:</span><span class="token style language-css"> none</span><span class="token style language-css">;</span><span class="token style language-css"> </span></span><span><span class="token style language-css"> </span><span class="token style language-css">border-radius</span><span class="token style language-css">:</span><span class="token style language-css"> </span><span class="token style language-css">4</span><span class="token style language-css unit">px</span><span class="token style language-css">;</span><span class="token style language-css"> </span></span><span><span class="token style language-css"> </span><span class="token style language-css">margin-top</span><span class="token style language-css">:</span><span class="token style language-css"> </span><span class="token style language-css">20</span><span class="token style language-css unit">px</span><span class="token style language-css">;</span><span class="token style language-css"> </span></span><span><span class="token style language-css"> </span><span class="token style language-css">}</span><span class="token style language-css"> </span></span><span><span class="token style language-css"> </span><span class="token style language-css class">.add-link</span><span class="token style language-css pseudo-class">:hover</span><span class="token style language-css"> </span><span class="token style language-css">{</span><span class="token style language-css"> </span></span><span><span class="token style language-css"> </span><span class="token style language-css">background-color</span><span class="token style language-css">:</span><span class="token style language-css"> </span><span class="token style language-css hexcode color">#218838</span><span class="token style language-css">;</span><span class="token style language-css"> </span></span><span><span class="token style language-css"> </span><span class="token style language-css">}</span><span class="token style language-css"> </span></span><span><span class="token style language-css"> </span><span class="token style language-css class">.empty-message</span><span class="token style language-css"> </span><span class="token style language-css">{</span><span class="token style language-css"> </span></span><span><span class="token style language-css"> </span><span class="token style language-css">text-align</span><span class="token style language-css">:</span><span class="token style language-css"> center</span><span class="token style language-css">;</span><span class="token style language-css"> </span></span><span><span class="token style language-css"> </span><span class="token style language-css">color</span><span class="token style language-css">:</span><span class="token style language-css"> </span><span class="token style language-css hexcode color">#666</span><span class="token style language-css">;</span><span class="token style language-css"> </span></span><span><span class="token style language-css"> </span><span class="token style language-css">font-style</span><span class="token style language-css">:</span><span class="token style language-css"> italic</span><span class="token style language-css">;</span><span class="token style language-css"> </span></span><span><span class="token style language-css"> </span><span class="token style language-css">padding</span><span class="token style language-css">:</span><span class="token style language-css"> </span><span class="token style language-css">20</span><span class="token style language-css unit">px</span><span class="token style language-css">;</span><span class="token style language-css"> </span></span><span><span class="token style language-css"> </span><span class="token style language-css">}</span><span class="token style language-css"> </span></span><span><span class="token style language-css"> </span><span class="token"></</span><span class="token">style</span><span class="token">></span> </span><span><span class="token"></</span><span class="token">head</span><span class="token">></span> </span><span><span class="token"><</span><span class="token">body</span><span class="token">></span> </span><span> <span class="token"><</span><span class="token">h1</span><span class="token">></span>📊 登録された学生一覧<span class="token"></</span><span class="token">h1</span><span class="token">></span> </span><span> </span><span> <span class="token"><</span><span class="token">div</span><span class="token"> </span><span class="token">th:</span><span class="token">if</span><span class="token">=</span><span class="token">"</span><span class="token">${#lists.isEmpty(studentList)}</span><span class="token">"</span><span class="token"> </span><span class="token">class</span><span class="token">=</span><span class="token">"</span><span class="token">empty-message</span><span class="token">"</span><span class="token">></span> </span><span> まだ学生が登録されていません。 </span><span> <span class="token"></</span><span class="token">div</span><span class="token">></span> </span><span> </span><span> <span class="token"><</span><span class="token">table</span><span class="token"> </span><span class="token">th:</span><span class="token">unless</span><span class="token">=</span><span class="token">"</span><span class="token">${#lists.isEmpty(studentList)}</span><span class="token">"</span><span class="token">></span> </span><span> <span class="token"><</span><span class="token">tr</span><span class="token">></span> </span><span> <span class="token"><</span><span class="token">th</span><span class="token">></span>名前<span class="token"></</span><span class="token">th</span><span class="token">></span> </span><span> <span class="token"><</span><span class="token">th</span><span class="token">></span>点数<span class="token"></</span><span class="token">th</span><span class="token">></span> </span><span> <span class="token"></</span><span class="token">tr</span><span class="token">></span> </span><span> <span class="token"><</span><span class="token">tr</span><span class="token"> </span><span class="token">th:</span><span class="token">each</span><span class="token">=</span><span class="token">"</span><span class="token">student, stat : ${studentList}</span><span class="token">"</span><span class="token">></span> </span><span> <span class="token"><</span><span class="token">td</span><span class="token"> </span><span class="token">th:</span><span class="token">text</span><span class="token">=</span><span class="token">"</span><span class="token">${student.name}</span><span class="token">"</span><span class="token">></span>名前<span class="token"></</span><span class="token">td</span><span class="token">></span> </span><span> <span class="token"><</span><span class="token">td</span><span class="token"> </span><span class="token">th:</span><span class="token">text</span><span class="token">=</span><span class="token">"</span><span class="token">${student.score}</span><span class="token">"</span><span class="token">></span>点数<span class="token"></</span><span class="token">td</span><span class="token">></span> </span><span> <span class="token"></</span><span class="token">tr</span><span class="token">></span> </span><span> <span class="token"></</span><span class="token">table</span><span class="token">></span> </span><span> </span><span> <span class="token"><</span><span class="token">a</span><span class="token"> </span><span class="token">th:</span><span class="token">href</span><span class="token">=</span><span class="token">"</span><span class="token">@{/student/form}</span><span class="token">"</span><span class="token"> </span><span class="token">class</span><span class="token">=</span><span class="token">"</span><span class="token">add-link</span><span class="token">"</span><span class="token">></span>➕ 新しい学生を登録<span class="token"></</span><span class="token">a</span><span class="token">></span> </span><span><span class="token"></</span><span class="token">body</span><span class="token">></span> </span><span><span class="token"></</span><span class="token">html</span><span class="token">></span></span> |
表示の技術ポイント:
th:if="${#lists.isEmpty(studentList)}"
– リストが空の場合の表示th:unless
– 条件の逆(リストが空でない場合)th:each="student, stat : ${studentList}"
– 繰り返し表示th:href="@{/student/form}"
– フォーム画面へのリンク
🔍 動作確認手順
- Spring Bootアプリケーションを起動
- ブラウザで
http://localhost:8080/student/form
にアクセス - 名前(例:太郎)と点数(例:85)を入力
- 「一覧に追加」ボタンをクリック
- 一覧画面に遷移し、入力したデータが表示される
- 「新しい学生を登録」リンクで再びフォーム画面に戻れる
💡 技術解説
MVCパターンの実装
- Model(Student): データ構造を定義
- View(HTML): ユーザーインターフェース
- Controller(StudentController): 処理ロジックとデータの橋渡し
Spring Bootの重要な機能
アノテーション | 役割 |
---|---|
@Controller |
このクラスがコントローラーであることを宣言 |
@GetMapping |
HTTP GETリクエストを処理 |
@PostMapping |
HTTP POSTリクエストを処理 |
@ModelAttribute |
フォームデータを自動でオブジェクトに変換 |
Thymeleafの便利な機能
属性 | 説明 |
---|---|
th:action |
フォーム送信先URL |
th:object |
バインドするオブジェクト |
th:field |
フォーム要素とオブジェクトのフィールドを連携 |
th:each |
リスト要素の繰り返し表示 |
th:if/unless |
条件分岐表示 |
🚀 さらなる機能拡張
この基本形ができたら、以下の機能に挑戦してみましょう:
1. データベース連携
1 2 3 4 5 6 7 8 |
<span><span class="token">// H2データベースやMySQLでデータを永続化</span> </span><span><span class="token annotation">@Entity</span> </span><span><span class="token">public</span> <span class="token">class</span> <span class="token">Student</span> <span class="token">{</span> </span><span> <span class="token annotation">@Id</span> </span><span> <span class="token annotation">@GeneratedValue</span><span class="token">(</span>strategy <span class="token">=</span> <span class="token">GenerationType</span><span class="token">.</span>IDENTITY<span class="token">)</span> </span><span> <span class="token">private</span> <span class="token">Long</span> id<span class="token">;</span> </span><span> <span class="token">// ...</span> </span><span><span class="token">}</span></span> |
2. 合格判定機能
1 2 3 4 5 |
<span><span class="token"><!-- 点数に応じて色分け表示 --></span> </span><span><span class="token"><</span><span class="token">td</span><span class="token"> </span><span class="token">th:</span><span class="token">text</span><span class="token">=</span><span class="token">"</span><span class="token">${student.score}</span><span class="token">"</span><span class="token"> </span></span><span><span class="token"> </span><span class="token">th:</span><span class="token">class</span><span class="token">=</span><span class="token">"</span><span class="token">${student.score >= 80} ? </span><span class="token">'</span><span class="token">pass</span><span class="token">'</span><span class="token"> : </span><span class="token">'</span><span class="token">fail</span><span class="token">'</span><span class="token">"</span><span class="token">></span> </span><span> 点数 </span><span><span class="token"></</span><span class="token">td</span><span class="token">></span></span> |
3. バリデーション機能
1 2 3 4 5 6 7 |
<span><span class="token">// 入力値チェック</span> </span><span><span class="token annotation">@NotBlank</span><span class="token">(</span>message <span class="token">=</span> <span class="token">"名前は必須です"</span><span class="token">)</span> </span><span><span class="token">private</span> <span class="token">String</span> name<span class="token">;</span> </span><span> </span><span><span class="token annotation">@Min</span><span class="token">(</span>value <span class="token">=</span> <span class="token">0</span><span class="token">,</span> message <span class="token">=</span> <span class="token">"点数は0以上で入力してください"</span><span class="token">)</span> </span><span><span class="token annotation">@Max</span><span class="token">(</span>value <span class="token">=</span> <span class="token">100</span><span class="token">,</span> message <span class="token">=</span> <span class="token">"点数は100以下で入力してください"</span><span class="token">)</span> </span><span><span class="token">private</span> <span class="token">int</span> score<span class="token">;</span></span> |
4. 削除・編集機能
- 各行に「編集」「削除」ボタンを追加
- RESTful URLパターンの実装
📝 まとめ
この記事では、Spring Boot + Thymeleafを使って完全な CRUD(Create, Read)操作の基礎を実装しました。
習得した技術スキル:
- フォームデータの送受信
- MVCアーキテクチャの実装
- Thymeleafテンプレートエンジンの活用
- RESTfulなURL設計の基礎
実用的なポイント:
- ユーザー入力の受け取り方法
- データの一時保存と表示
- 画面間の遷移制御
このチュートリアルをマスターすれば、多くのWebアプリケーションの基本パターンが理解できます。次はデータベース連携や高度な機能に挑戦して、より実用的なアプリケーションを作ってみましょう!
次回予告: 「Spring Boot + H2データベースで永続化機能を実装しよう!」
コメントを残す