6月22日

投稿者: | 2020年6月22日

fragmentを利用したページにナビゲーションを追加

layout.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>layout.html</title>
<style type="text/css">
header {
  background: #f0f0f0;
  text-align: center;
  padding: 50px;
}

footer {
  background: #e0e0e0;
  text-align: center;
}
</style>
</head>
<body>

<header th:include="header :: header">
仮のヘッダーです
</header>

<nav>
<ul>
<li><a href="/fragment">fragment</a></li>
<li><a href="/mac">mac</a></li>
<li><a href="/windows">windows</a></li>
<li><a href="/linux">linux</a></li>
</ul>
</nav>

<section th:include="${template} :: ${fragment}">
<h1>layout</h1>
<p>本文です。</p>
</section>

<footer th:include="footer :: footer">
仮のフッターです
</footer>

</body>
</html>

switchで分岐

fragmentをそのまま利用して実装してみる。
テンプレート month.html を用意する。

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>季節</title>
</head>
<body>

<div th:fragment="month">
<h1>季節</h1>
<p th:text="${fragment}"></p>

<div th:switch="${season}">
  <p th:case="0" th:text="|${month}月 - Winter|"></p>
  <p th:case="1" th:text="|${month}月 - Spring|"></p>
  <p th:case="2" th:text="|${month}月 - Summer|"></p>
  <p th:case="3" th:text="|${month}月 - Autumn|"></p>
</div>

</div>

</body>
</html>

FragmentController.java に /month/{month} のマッピングを追加する。

package com.example.demo;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

@Controller
public class FragmentController {
	@RequestMapping("/fragment")
	public ModelAndView fragment(ModelAndView mav) {
		mav.addObject("template", "content");
		mav.addObject("fragment", "body1");
		mav.setViewName("layout");
		return mav;
	}

	@RequestMapping("/mac")
	public ModelAndView mac(ModelAndView mav) {
		mav.addObject("template", "content");
		mav.addObject("fragment", "mac");
		mav.setViewName("layout");
		return mav;
	}

	@RequestMapping("/windows")
	public ModelAndView windows(ModelAndView mav) {
		mav.addObject("template", "windows");
		mav.addObject("fragment", "windows");
		mav.setViewName("layout");
		return mav;
	}

	@RequestMapping("/linux")
	public ModelAndView linux(ModelAndView mav) {
		mav.addObject("template", "linux");
		mav.addObject("fragment", "linux");
		mav.setViewName("layout");
		return mav;
	}

	@RequestMapping("/month/{month}")
	public ModelAndView month(@PathVariable int month, ModelAndView mav) {
		mav.addObject("template", "month");
		mav.addObject("fragment", "month");
		mav.addObject("month", month);
		mav.addObject("season", 0);
		mav.setViewName("layout");
		return mav;
	}
}

季節の判定をするために、テスト駆動開発をするのがよさそうなのでやってみる。

FragmentControllerのコードで季節を判定する部分をメソッドにする。

	@RequestMapping("/month/{month}")
	public ModelAndView month(@PathVariable int month, ModelAndView mav) {
		mav.addObject("template", "month");
		mav.addObject("fragment", "month");
		mav.addObject("month", month);
		int season = getSeason(month);
		mav.addObject("season", season);
		mav.setViewName("layout");
		return mav;
	}

まず、FragmentControllerで季節を判定するメソッドを作成する。privateだとテストから見えなくなるので、アクセス制限はパッケージプライベートにしておく。

	int getSeason() {
		return 0;
	}

FragmentController.java を右クリックして[新規]-[その他]を選択。
フィルターに「ju」と入力して「JUnitテストケース」を選択してテストケースを作成する。

package com.example.demo;

import static org.junit.jupiter.api.Assertions.*;

import org.junit.jupiter.api.Test;

class FragmentControllerTest {

	@Test
	void testGetSeason() {
		FragmentController fc = new FragmentController();
		int season = fc.getSeason(1);
		assertEquals(0, season);
	}

}

1月から12月までのテストを書く。

package com.example.demo;

import static org.junit.jupiter.api.Assertions.*;

import org.junit.jupiter.api.Test;

class FragmentControllerTest {

	@Test
	void testGetSeason() {
		FragmentController fc = new FragmentController();
		int season = fc.getSeason(1);
		assertEquals(0, season);
		assertEquals(0, fc.getSeason(2));
		assertEquals(1, fc.getSeason(3));
		assertEquals(1, fc.getSeason(4));
		assertEquals(1, fc.getSeason(5));
		assertEquals(2, fc.getSeason(6));
		assertEquals(2, fc.getSeason(7));
		assertEquals(2, fc.getSeason(8));
		assertEquals(3, fc.getSeason(9));
		assertEquals(3, fc.getSeason(10));
		assertEquals(3, fc.getSeason(11));
		assertEquals(0, fc.getSeason(12));
	}

}

Spring Bootアプリケーションを終了させる方法
「コンソール」タブの「選択されたコンソールの表示」ボタンの右の「▼」をクリックしてXXXApplicationを選択し、をクリックする。

コマンドプロンプトから java.exe を終了させる方法

C:¥User¥hoge> taskkill /im java.exe

正しく季節を返せるように getSeason() を実装する。

	int getSeason(int month) {
		if (month < 3 || month == 12) return 0;
		if (month < 6) return 1;
		if (month < 9) return 2;
		return 3;
	}

次は季節の一覧をループで表示する /seasons ページを作成する。
まずコントローラに新しいマッピングを追加する。

	@RequestMapping("/seasons")
	public ModelAndView seasons(ModelAndView mav) {
		mav.addObject("template", "seasons");
		mav.addObject("fragment", "seasons");
		mav.setViewName("layout");
		return mav;
	}

templates フォルダに seasons.html を作成する。(linux.htmlをseasons.htmlの名前でコピー)
fragmentの名前を「seasons」に変更してSpring Bootを再起動すればアクセスできるようになる。

コントローラで1月から12月までの文字を配列で作成して、テンプレートにわたすようにする。

	@RequestMapping("/seasons")
	public ModelAndView seasons(ModelAndView mav) {
		mav.addObject("template", "seasons");
		mav.addObject("fragment", "seasons");
		String[] s = new String[12];
		for (int i = 1; i <=12; i++) {
			s[i - 1] = i + "月";
		}
		mav.addObject("seasons", s);
		mav.setViewName("layout");
		return mav;
	}

seasons.htmlでは、渡されたString配列でループして1月から12月を表示する。

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>linux.html</title>
</head>
<body>

<div th:fragment="seasons">
<h1>季節</h1>
<div th:each="s:${seasons}">
<p th:text="${s}"></p>
</div>

<p th:text="${fragment}"></p>
</div>

</body>
</html>

「○月は春です。」のような表示を12ヶ月分できるように修正する。

	@RequestMapping("/seasons")
	public ModelAndView seasons(ModelAndView mav) {
		mav.addObject("template", "seasons");
		mav.addObject("fragment", "seasons");
		String[] s = new String[12];
		for (int i = 1; i <=12; i++) {
			s[i - 1] = i + "月は" + getSeasonName(i) + "です。";
		}
		mav.addObject("seasons", s);
		mav.setViewName("layout");
		return mav;
	}

	String getSeasonName(int month) {
		int season = getSeason(month);
		if (season == 0) return "冬";
		if (season == 1) return "春";
		if (season == 2) return "夏";
		return "秋";
	}