リンクの動的設定(th:href, th:src)を完全ガイド!初心者でもわかる基本的な使い方
新人
「Spring MVCでHTML内のリンクや画像のURLを動的に設定する方法ってありますか?」
先輩
「Thymeleafでは、th:hrefとth:srcを使えば、簡単にリンクや画像のパスを動的に設定できるんだ。」
新人
「それってどうやって使うんですか?具体的な例が知りたいです!」
先輩
「じゃあ、基本から順番に見ていこう!」
1. リンクの動的設定とは?
リンクの動的設定とは、HTML内でリンク先のURLや画像のパスをサーバーサイドのデータに基づいて変更できる仕組みです。例えば、商品詳細ページへのリンクやユーザープロフィール画像など、ユーザーや商品ごとに異なるリンクや画像を表示する場合に役立ちます。Spring MVCとThymeleafを組み合わせることで、これを簡単に実現できます。
2. th:hrefとは何か?
th:hrefは、Thymeleafでリンク(<a>タグ)のhref属性を動的に設定するための属性です。Spring MVCから渡されたモデルデータを利用してリンク先を変更できます。
【コントローラの作成】
@Controller
public class ProductController {
@GetMapping("/products")
public String showProducts(Model model) {
List<String> productIds = List.of("101", "102", "103");
model.addAttribute("productIds", productIds);
return "product-list";
}
}
【HTMLファイル(product-list.html)の作成】
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>商品一覧</title>
</head>
<body>
<h2>商品一覧</h2>
<ul>
<li th:each="id : ${productIds}">
<a th:href="@{'/product/' + ${id}}" th:text="'商品ID: ' + ${id}"></a>
</li>
</ul>
</body>
</html>
上記コードでは、th:eachで商品IDのリストをループし、各商品へのリンクをth:hrefで動的に設定しています。クリックすると/product/101や/product/102などの商品詳細ページへ遷移します。
3. th:srcとは何か?
th:srcは、Thymeleafで画像(<img>タグ)のsrc属性を動的に設定するための属性です。ユーザーのプロフィール画像や商品画像のパスを動的に指定する際に利用されます。
【コントローラの作成】
@Controller
public class UserController {
@GetMapping("/users")
public String showUsers(Model model) {
Map<String, String> users = Map.of(
"田中太郎", "/images/tanaka.png",
"山田花子", "/images/yamada.png",
"佐藤次郎", "/images/sato.png"
);
model.addAttribute("users", users);
return "user-list";
}
}
【HTMLファイル(user-list.html)の作成】
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>ユーザー一覧</title>
</head>
<body>
<h2>ユーザーとプロフィール画像</h2>
<ul>
<li th:each="user : ${users}">
<p th:text="${user.key}"></p>
<img th:src="@{${user.value}}" alt="プロフィール画像" width="100">
</li>
</ul>
</body>
</html>
この例では、usersマップのキー(ユーザー名)と値(画像パス)をループで表示しています。th:srcを使うことで、ユーザーごとに異なる画像を簡単に表示できます。
4. th:hrefを使った基本的なリンクの動的設定の実例
th:hrefは、Thymeleafでリンク先のURLを動的に設定する際に使用されます。これにより、HTML内のリンクがサーバーから渡されたデータに基づいて変更されるため、コードの再利用性が向上します。例えば、ユーザー一覧ページから各ユーザーの詳細ページへのリンクを作成する場合に便利です。
【コントローラの作成】
@Controller
public class UserController {
@GetMapping("/users")
public String showUsers(Model model) {
List<User> users = List.of(
new User(1, "田中太郎"),
new User(2, "山田花子"),
new User(3, "佐藤次郎")
);
model.addAttribute("users", users);
return "user-list";
}
}
【HTMLファイル(user-list.html)の作成】
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>ユーザー一覧</title>
</head>
<body>
<h2>ユーザー一覧</h2>
<ul>
<li th:each="user : ${users}">
<a th:href="@{'/user/' + ${user.id}}" th:text="${user.name}"></a>
</li>
</ul>
</body>
</html>
上記の例では、各ユーザーの名前がリンクとして表示され、クリックすると/user/1や/user/2などの詳細ページに遷移します。これにより、リンク先のURLが動的に生成され、メンテナンスが容易になります。
5. th:srcを使った画像やスクリプトの動的読み込み方法
th:srcは、画像やスクリプトのパスを動的に設定するための属性です。ユーザーごとのプロフィール画像や商品画像を表示する際に特に有用です。
【コントローラの作成】
@Controller
public class ProfileController {
@GetMapping("/profiles")
public String showProfiles(Model model) {
Map<String, String> profiles = Map.of(
"田中太郎", "/images/tanaka.png",
"山田花子", "/images/yamada.png",
"佐藤次郎", "/images/sato.png"
);
model.addAttribute("profiles", profiles);
return "profile-list";
}
}
【HTMLファイル(profile-list.html)の作成】
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>プロフィール一覧</title>
</head>
<body>
<h2>ユーザープロフィール画像</h2>
<ul>
<li th:each="entry : ${profiles}">
<p th:text="${entry.key}"></p>
<img th:src="@{${entry.value}}" alt="プロフィール画像" width="120">
</li>
</ul>
</body>
</html>
このコードでは、ユーザー名と対応する画像が表示されます。th:srcを使うことで、各ユーザーに対応する画像を簡単に動的に読み込むことが可能です。
6. th:hrefとth:srcの併用と実用的な使い方
th:hrefとth:srcを組み合わせることで、画像付きのリンクを動的に生成できます。例えば、ユーザーの名前をクリックすると詳細ページに遷移し、同時にプロフィール画像を表示することが可能です。
【コントローラの作成】
@Controller
public class UserProfileController {
@GetMapping("/user-profiles")
public String showUserProfiles(Model model) {
List<UserProfile> profiles = List.of(
new UserProfile(1, "田中太郎", "/images/tanaka.png"),
new UserProfile(2, "山田花子", "/images/yamada.png"),
new UserProfile(3, "佐藤次郎", "/images/sato.png")
);
model.addAttribute("profiles", profiles);
return "user-profile-list";
}
}
【HTMLファイル(user-profile-list.html)の作成】
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>ユーザープロフィール</title>
</head>
<body>
<h2>ユーザープロフィール一覧</h2>
<ul>
<li th:each="profile : ${profiles}">
<a th:href="@{'/user/' + ${profile.id}}">
<img th:src="@{${profile.imagePath}}" alt="プロフィール画像" width="80">
<span th:text="${profile.name}"></span>
</a>
</li>
</ul>
</body>
</html>
この例では、ユーザー名と画像がリンクになっており、クリックするとユーザー詳細ページへ移動します。th:hrefとth:srcを併用することで、視認性が高く、ユーザーフレンドリーなインターフェースを実現できます。
7. th:hrefとth:srcを使う際のよくあるエラーとその対処法
th:hrefやth:srcを使う際、初心者がよく遭遇するエラーとその解決方法を解説します。リンクの動的設定や画像の読み込みで正しく表示されない場合、パスの指定方法やモデルデータの受け渡しに原因があることが多いです。
【エラー1: パスが正しく解決されない】
th:hrefやth:srcでURLが正しく生成されない場合、パスの指定方法に問題があることがあります。特に、"@{}"の書き方に注意が必要です。
<!-- 誤った例 -->
<a th:href="/user/${user.id}">リンク</a>
<!-- 正しい例 -->
<a th:href="@{'/user/' + ${user.id}}">リンク</a>
誤った例ではth:hrefに直接変数を埋め込んでいますが、@{}構文でURLを生成する必要があります。
【エラー2: 画像が表示されない】
画像の表示に問題がある場合、静的リソースの配置場所が間違っている可能性があります。Spring Bootでは、src/main/resources/static以下に画像を配置してください。
<!-- 誤った例 -->
<img th:src="/images/profile.png" alt="プロフィール画像">
<!-- 正しい例 -->
<img th:src="@{/images/profile.png}" alt="プロフィール画像">
正しい例では@{}構文を使用して画像のURLを正しく解決しています。
8. th:hrefとth:srcのベストプラクティスと注意点
th:hrefとth:srcを使用する際のベストプラクティスを紹介します。正しい使い方を知ることで、保守性が向上し、エラーも減少します。
【ベストプラクティス1: 絶対パスではなく相対パスを使用する】
リンクや画像のパスは、できるだけ相対パスで指定しましょう。これにより、環境に依存しないコードが書けます。
<!-- 悪い例 -->
<a th:href="http://example.com/user/1">ユーザー詳細</a>
<!-- 良い例 -->
<a th:href="@{'/user/' + ${user.id}}">ユーザー詳細</a>
【ベストプラクティス2: モデルデータがnullの場合を考慮する】
モデルデータがnullの場合、リンクや画像が正しく生成されません。必ずnullチェックを行いましょう。
<p th:if="${user != null}">
<a th:href="@{'/user/' + ${user.id}}">詳細</a>
</p>
<p th:unless="${user != null}">ユーザー情報が見つかりません。</p>
【注意点】
- 変数のスコープ: モデルに属性が追加されているか確認。
- パスの書き方:
@{}内でスラッシュの有無に注意。 - 静的リソースの配置: 正しいフォルダ(
staticやpublic)に配置。
9. 実践!リンクと画像を動的に表示する簡単なアプリの作成例
ここでは、ユーザー一覧ページで各ユーザーのプロフィール画像と詳細ページへのリンクを表示するアプリケーションを作成します。
【コントローラの作成】
@Controller
public class UserController {
@GetMapping("/users")
public String showUsers(Model model) {
List<User> users = List.of(
new User(1, "田中太郎", "/images/tanaka.png"),
new User(2, "山田花子", "/images/yamada.png"),
new User(3, "佐藤次郎", "/images/sato.png")
);
model.addAttribute("users", users);
return "user-list";
}
}
【HTMLファイル(user-list.html)の作成】
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>ユーザー一覧</title>
</head>
<body>
<h2>ユーザープロフィールとリンク</h2>
<ul>
<li th:each="user : ${users}">
<a th:href="@{'/user/' + ${user.id}}">
<img th:src="@{${user.profileImagePath}}" alt="プロフィール画像" width="80">
<span th:text="${user.name}"></span>
</a>
</li>
</ul>
</body>
</html>
このアプリでは、各ユーザーの名前と画像がリンクとして表示され、クリックするとユーザー詳細ページへ遷移します。画像とリンクを動的に設定することで、ユーザー情報の管理が容易になります。
まとめ
本記事では、th:hrefとth:srcの基本から実践的な使い方、よくあるエラーとその解決方法、さらにはベストプラクティスまでを初心者にもわかりやすく丁寧に解説しました。
th:hrefを使えば、動的なリンクを簡単に生成でき、商品ページやユーザー詳細ページなど、個別のURLを自動で生成することができます。また、th:srcを使うことで、画像やスクリプトファイルの読み込みを動的に制御でき、ユーザーごとのプロフィール画像や商品画像の表示など、柔軟なUI設計が可能になります。
エラーの原因としては@{}の記法ミスや、静的リソースの配置場所の誤りが多いため、今回紹介した例や構文に従えば、こうしたトラブルも未然に防げるでしょう。
実際にリンクと画像を組み合わせた動的表示も紹介し、ユーザー体験の向上に役立つ設計が簡単に実現できることを実感していただけたと思います。
最後に、相対パスの使用やnullチェックなどのベストプラクティスを守ることで、より保守性の高いアプリケーションが構築できます。
以下に、基本的なサンプルコードを再掲しますので、実際に自分のプロジェクトで使いながら理解を深めていきましょう。
【動的リンク+画像表示のサンプルHTML】
<ul>
<li th:each="user : ${users}">
<a th:href="@{'/user/' + ${user.id}}">
<img th:src="@{${user.profileImagePath}}" alt="プロフィール画像" width="80">
<span th:text="${user.name}"></span>
</a>
</li>
</ul>
【エラーパターンと改善例(th:hrefの誤用)】
<!-- 誤り -->
<a th:href="/user/${user.id}">リンク</a>
<!-- 正しい -->
<a th:href="@{'/user/' + ${user.id}}">リンク</a>
新人
「th:hrefとth:srcって、リンクと画像の設定を動的にできる便利な機能なんですね!」
先輩
「そうそう。Spring MVCとThymeleafを組み合わせると、テンプレート側で動的にURLや画像のパスを指定できるから、開発がかなり効率的になるよ。」
新人
「特に@{}の使い方を間違えやすいので気をつけたいです。th:hrefやth:srcの記述ルールもちゃんと理解しておかないとですね。」
先輩
「その通り。あと、モデルがnullのときの挙動も考慮しておくのが大事。UIが崩れないようにth:ifやth:unlessでチェックする習慣をつけるといいよ。」
新人
「ありがとうございます!これでユーザーごとのページや画像をスマートに表示できる気がします!」
先輩
「あとは実際にコードを書いて試すのみだね。慣れてきたらth:actionなんかも使ってフォーム処理も動的にすると、さらにThymeleafの活用が広がるよ。」