はじめに
Eclipse で Spring Boot + Thymeleaf . (その2)の続き。
そのほかのThymeleaf の機能を使用してみます。
ループと、引数付きのLayoutを使用します。
開発環境
Windows 10 Pro 1709(16299.192)
Eclipse pleiades-4.7.3
java 1.8.0_162
spring-boot-2.0.2.RELEASE
thymeleaf-3.0.9.RELEASE
ファイル構造
pom.xml 自動生成のまま
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>MyApp</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>MyApp</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
MyAppApplication.java 自動生成のまま
MyAppApplication.java
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class MyAppApplication {
public static void main(String[] args) {
SpringApplication.run(MyAppApplication.class, args);
}
}
EmployeeBean.java
EmployeeBean.java
package com.example.demo;
import lombok.Data;
@Data
public class EmployeeBean {
private String id = "";
private String name = "";
private String email = "";
}
EmployeeListFrom.java
EmployeeListFrom.java
package com.example.demo;
import java.util.List;
import lombok.Data;
@Data
public class EmployeeListForm {
private List<EmployeeBean> employees;
}
EmployeeFrom.java
EmployeeFrom.java
package com.example.demo;
import lombok.Data;
@Data
public class EmployeeForm {
private EmployeeBean employee;
}
EmployeeController.java
EmployeeController.java
package com.example.demo;
import java.util.ArrayList;
import java.util.List;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.servlet.ModelAndView;
@Controller
public class EmployeeController {
@GetMapping("/list")
public ModelAndView list(ModelAndView mav) {
EmployeeListForm form = new EmployeeListForm();
List<EmployeeBean> list = new ArrayList<EmployeeBean>();
EmployeeBean bean = new EmployeeBean();
bean.setId("1");
bean.setName("Ken");
bean.setEmail("ken@mail.coml");
list.add(bean);
bean = new EmployeeBean();
bean.setId("2");
bean.setName("Hanako");
bean.setEmail("hanako@mail.coml");
list.add(bean);
form.setEmployees(list);
mav.addObject("employeeListForm", form);
EmployeeForm employeeForm = new EmployeeForm();
employeeForm.setEmployee(bean);
mav.addObject("employeeForm", employeeForm);
mav.setViewName("contents/employeeList");
return mav;
}
@PostMapping("/detail")
public ModelAndView list(@ModelAttribute EmployeeForm employeeForm, ModelAndView mav) {
mav.addObject("employeeForm", employeeForm);
mav.setViewName("contents/employee");
return mav;
}
}
application.properties
application.properties
spring.datasource.url=jdbc:postgresql://localhost:5432/postgres
spring.datasource.username=postgres
spring.datasource.password=admin
spring.datasource.driverClassName=org.postgresql.Driver
# disable driver's feature detection
spring.jpa.properties.hibernate.temp.use_jdbc_metadata_defaults = false
# without detection you have to set the dialect by hand
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect
common/base.html
common/base.html
<head th:fragment="common_header(title,links)">
<!-- 各ページのタイトル -->
<title th:replace="${title}">The demo application</title>
<!-- 共通ファイル -->
<!-- 各ページ固有で読み込むリンク -->
<th:block th:replace="${links}" />
</head>
common/header.html
common/header.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>header</title>
</head>
<body>
<div th:fragment="common_header" th:remove="tag">
<h1>
<a th:href="@{/}" style="background: #e5eCf9;">Staff Management System</a>
</h1>
</div>
</body>
</html>
common/footer.html
common/footer.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>footer</title>
</head>
<body>
<div th:fragment="common_footer" th:remove="tag">
<p style="text-align: center; background: #e5eCf9;">Copyright © 20XX CompanyName</p>
</div>
</body>
</html>
contents/employeeList.html
contents/employeeList.html
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html xmlns:th="http://www.thymeleaf.org">
<head th:replace="common/base :: common_header(~{::title},~{::link})"> <!-- 追加 -->
<title>従業員一覧</title>
<link rel="stylesheet" th:href="@{/css/mycss.css}">
</head>
<body>
<div th:replace="common/header :: common_header"></div> <!-- 追加 -->
<h1>Hello, Spring Boot!</h1>
<div th:object="${employeeListForm}">
<table>
<caption>
<strong>従業員検索</strong>
</caption>
<thead>
<tr>
<th>ID</th>
<th>NAME</th>
<th>EMAIL</th>
</tr>
</thead>
<tbody>
<tr th:each="emp : *{employees}">
<td th:text="${emp.id}"></td>
<td th:text="${emp.name}"></td>
<td th:text="${emp.email}"></td>
</tr>
</tbody>
</table>
</div>
<form th:action="@{/detail}" th:object="${employeeForm.employee}" method="post">
<p>Id: <input required type="text" th:field="*{id}" />
<em th:if="${#fields.hasErrors('id')}" th:errors="*{id}">Name Error</em></p>
<p>Name: <input required type="text" th:field="*{name}" />
<em th:if="${#fields.hasErrors('name')}" th:errors="*{name}">Name Error</em></p>
<p>Email: <input required type="email" th:field="*{email}" />
<em th:if="${#fields.hasErrors('email')}" th:errors="*{email}">Email Error</em></p>
<p><input type="submit" value="Submit" /></p>
</form>
<div th:replace="common/footer :: common_footer"></div> <!-- 追加 -->
</body>
</html>
contents/employee.html
contents/employee.html
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html xmlns:th="http://www.thymeleaf.org">
<head th:replace="common/base :: common_header(~{::title},~{::link})"> <!-- 追加 -->
<title>従業員詳細</title>
<link rel="stylesheet" th:href="@{/css/mycss.css}">
</head>
<body>
<div th:replace="common/header :: common_header"></div> <!-- 追加 -->
<h1>Hello, Spring Boot!</h1>
<form th:action="@{/detail}" th:object="${employeeForm.employee}" method="post">
<p>Id: <input required type="text" th:field="*{id}" />
<em th:if="${#fields.hasErrors('id')}" th:errors="*{id}">Name Error</em></p>
<p>Name: <input required type="text" th:field="*{name}" />
<em th:if="${#fields.hasErrors('name')}" th:errors="*{name}">Name Error</em></p>
<p>Email: <input required type="email" th:field="*{email}" />
<em th:if="${#fields.hasErrors('email')}" th:errors="*{email}">Email Error</em></p>
<p><input type="submit" value="Submit" /></p>
</form>
<div th:replace="common/footer :: common_footer"></div> <!-- 追加 -->
</body>
</html>