はじめに
MVCモデルの内、ビューを作成する手順を学習したのでアウトプットします。
Controllerから送信された指示に沿って、ブラウザに提供するためのHTMLを動的に構築するテンプレートを使用できます。
テンプレートエンジンを使う
HTMLのひな形(テンプレート)に変数や繰り返し処理などのプログラムを記述し、画面に出力するためのライブラリをテンプレートエンジンと呼びます。
SpringBootはテンプレートエンジンを使用することでサーバーサイドが用意した変数や処理をHTMLに付与することができるため、使用するアマゾンや楽天などのようなショッピングサイトや商品管理システムなど使用するユーザーに応じて可変する動的なサイトを構築できます
テンプレートエンジンは複数存在する
使用されるテンプレートエンジンは使用する言語により様々存在しますが、Spring Bootで最も一般的に使用されるテンプレートエンジンはThymeleaf(タイムリーフ)
と呼ばれるテンプレートエンジンなので、この記事ではタイムリーフを使った操作方法を紹介しています。
テンプレートを利用するための初期設定
Eclipse(エクリプス)にはThymeleaf(タイムリーフ)が最初から組み込まれているわけではありませんので、新しく追加する必要があります。
Eclipseは依存関係管理のための機能を提供しており、つまり追加機能を紐付けするためのコードを手動で記述する
ことで、ライブラリやモジュールが追加されて使用することができます。以下は、ThymeleafをEclipseプロジェクトで使用可能にするための手順です。
①依存関係の追加(コードを書き足す)
テンプレートエンジンを使用するためには作成したプロジェクトファイルのコードを編集する必要があります。
build.gradleファイル
Springスターター・プロジェクト
で作成したプロジェクトディレクトリの
ルート直下にあります
新しく作成したプロジェクト名がspring_boot_introduction
の場合
/Applications/Eclipse_2023-06.app/Contents/workspace/spring_boot_introduction
build.gradleファイルを編集する
build.gradleというファイルを開くとdependencies
という項目(ブロック)が存在するため以下のコードを追記します
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
/* 追記して上書き保存します */
plugins {
id 'java'
id 'org.springframework.boot' version '2.7.12'
id 'io.spring.dependency-management' version '1.0.15.RELEASE'
}
group = 'com.example'
version = '0.0.1-SNAPSHOT'
java {
sourceCompatibility = '1.8'
}
configurations {
compileOnly {
extendsFrom annotationProcessor
}
}
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
compileOnly 'org.projectlombok:lombok'
developmentOnly 'org.springframework.boot:spring-boot-devtools'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
// 次のように貼り付けする
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
}
tasks.named('test') {
useJUnitPlatform()
}
もしもbuild.gradleファイルが見つからない場合は作成したプロジェクトディレクトリからファイル名build.gradle
を検索してください
編集した依存関係を反映させる
Gradle プロジェクトのリフレッシュ
を実行します
プロジェクトを選択し右クリック→【Gradle】→【Gradle プロジェクトのリフレッシュ】
Gradle(グレイドル)は、ソースコード(人間が書いたコード)を実行可能なソフトウェアに変換するためのツールの一つです(例えば、Javaの場合は.jarファイルや.warファイル)
build.gradleに記述したThymeleaf(タイムリーフ)を使用するための依存関係を示すコードはまだ反映されていないためプロジェクトの設定ファイルをリフレッシュすることで反映させます
どうしてもThymeleafが追加できない場合
新しくプロジェクトを作成する際に、Springスターター・プロジェクト
のウィザードの途中でThymeleafを導入する選択肢が存在するので、選択すれば最初からThymeleafを使用できます
テンプレートを作成する
これから動的なHTMLを作成するために新しいテンプレートを作成します
テンプレートは次の条件に沿って作成します
- 作成場所:
src\main\resources\templates
- ファイル拡張子:
html
- ファイル名:メソッド名とファイル名を同じにする(必須ではなく推奨)
Eclipseで操作する場合、パッケージ・エクスプローラーから作成操作ができます
templates
というディレクトリがあるため右クリックでテンプレートを作成しましょう
テンプレートファイルを編集する
はじめに、Thymeleaf(タイムリーフ)の機能を使用する場合
は、必ずHTMLタグ内でThymeleafの名前空間を定義する必要
があります。以下のようになります。
以下のように名前空間を定義しない場合Thymeleafの特定の属性や構文(th:で始まるもの)を使用しようとするとエラーが発生します。
<!DOCTYPE html>
<!-- htmlタグに名前空間を定義する -->
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>Hello world!!</h1>
</body>
</html>
検索されたURLから表示するテンプレートを設定する
ブラウザから検索されたURLと作成したthmlを紐付けするためには
Controllerのコードを編集し、表示するテンプレートを指定します
package com.example.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("/lesson")
public class LessonController {
@GetMapping("/sample")
// HTMLをレスポンスにする場合は、@ResponseBodyを削除する
// @ResponseBody
public String sample() {
return "index";
}
}
アプリケーションを実行する
プロジェクト内のプログラムを動かすためにはアプリケーションの実行をする必要があります
アプリケーションを実行することによりWebサーバーが起動し、リクエストに応じたプログラムが動くようになります。
今回作成した対象のプロジェクトを右クリックで選択し、
実行
→Spring Boot アプリケーション
を選択します
実行することでコンソールに次の表示が出ていれば起動が完了しています
ポート番号も8080
という番号が表示されています。
Hello World
もしもエラーでHTMLが表示されない場合
サーバーを停止してからもう一度起動し、ブラウザを更新してください
サーバーを停止するボタン
HTMLで変数を使う
Controllerの中で設定された変数や、URLから受け取った引数をテンプレートで扱うにはModel属性に値を保存する必要があります(DBを操作するためのモデルとは異なります)
// Model属性を利用するためのimportを追加します
import org.springframework.ui.Model;
/* 省略 */
// Model型の仮引数を持ちます
public String メソッド名(Model model) {
// 指定した「属性名」をHTML内で変数のように扱います
model.addAttribute("属性名", 値);
/* 後続処理 */
}
Model型の仮引数の名前をmodel
としていますが、仮引数は任意の名前を設定できます
しかし一般的にmodel
とすることで可読性を高めることができます
@Controller
@RequestMapping("/lesson")
public class LessonController {
@GetMapping("/sample")
// Model型の値を必ず仮引数に持つ
public String sample(Model model) {
// 変数を定義する
String text = "今日はいいお天気ですね";
// messageという属性名に、今日はいいお天気ですね という値を追加します
model.addAttribute("message", text);
return "index";
}
}
コントローラーの上部分で宣言するimport文はEclipseでコーディングすると、自動で補完されます
上書き保存する際にも自動で補完されるので、Cmdキー
+sキー
で補完しましょう
テンプレート(HTML)で変数を使う
Thymeleaf(タイムリーフ)ではth:から始まる属性が用意されており、phpのようなプログラム機能を実現することが出来ます。
コントローラーのmodel.addAttribute()によってセットされたModel属性を利用するには通常のHTMLタグの属性にth:text属性を付与します。
<p th:text="${変数名}"></p>
<!DOCTYPE html>
<!--HTMLファイルの中でThymeleafの特定の構文や属性を使用できるようになります。-->
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Hello Spring Boot</title>
</head>
<body>
<!-- Model属性に追加したmessageを出力します -->
<h1 th:text="${message}">ご機嫌いかがですか?</h1>
</body>
</html>
いいお天気ですね
// th属性の値に上書きされる
テンプレートファイルの置き場所
今作成したHTMLのテンプレートはページの数だけファイルが必要になります。
それらのテンプレートは全てtemplatesディレクトリ
に保存することになります
そのためもしもファイル数が100を超える大規模なプロジェクトだった場合、ファイルの管理が困難になるためtemplatesディレクトリ
の下層にさらにディレクトリ
を作成することができます。
product-management-system/
├─ src/
│ ├─ main/
│ │ ├─ java/
│ │ │ ├─ com/
│ │ │ │ ├─ yourcompany/
│ │ │ │ │ ├─ productmanagementsystem/
│ │ │ │ │ │ ├─ controller/
│ │ │ │ │ │ │ ├─ ProductController.java
│ │ │ │ │ │ │ ├─ CategoryController.java
│ │ │ │ │ │ ├─ service/
│ │ │ │ │ │ │ ├─ ProductService.java
│ │ │ │ │ │ │ ├─ CategoryService.java
│ │ │ │ │ │ ├─ repository/
│ │ │ │ │ │ │ ├─ ProductRepository.java
│ │ │ │ │ │ │ ├─ CategoryRepository.java
│ │ │ │ │ │ ├─ model/
│ │ │ │ │ │ │ ├─ Product.java
│ │ │ │ │ │ │ ├─ Category.java
│ │ │ │ │ │ ├─ ProductManagementSystemApplication.java
│ │ ├─ resources/
│ │ │ ├─ templates/
│ │ │ │ ├─ product/
│ │ │ │ │ ├─ list.html
│ │ │ │ │ ├─ detail.html
│ │ │ │ ├─ category/
│ │ │ │ │ ├─ list.html
│ │ │ │ │ ├─ detail.html
│ │ │ ├─ application.properties
│ ├─ test/
│ │ ├─ java/
│ │ │ ├─ com/
│ │ │ │ ├─ yourcompany/
│ │ │ │ │ ├─ productmanagementsystem/
│ │ │ │ │ │ ├─ controller/
│ │ │ │ │ │ │ ├─ ProductControllerTest.java
│ │ │ │ │ │ │ ├─ CategoryControllerTest.java
│ │ │ │ │ │ ├─ service/
│ │ │ │ │ │ │ ├─ ProductServiceTest.java
│ │ │ │ │ │ │ ├─ CategoryServiceTest.java
├─ .gitignore
├─ pom.xml
├─ README.md
ディレクトリを挟んでパスを指定する場合
return "ディレクトリ名/ファイル名";
@Controller
@RequestMapping("/item")
public class ItemController {
@GetMapping("/product")
public String list(Model model) {
return "product/list"; // templates¥product¥list.html を指している
}
@GetMapping("/category")
public String create(Model model) {
return "category/list"; // templates¥category¥list.html を指している
}
}
階層が複数ある場合
次のように階層が複数存在する場合は/
で繋いで記述します
return "list/detail/create/update/delete/file";
product/
├─ list/
│ ├─ detail/
│ │ ├─ create/
│ │ │ ├─ update/
│ │ │ │ ├─ delete/