태그 th: 으로 사용하며 Controller에서 전송받은 데이터를 받아서 사용 할 수 있다.
View에만 사용이 가능함
pom.xml에 오른쪽 클릭 -> Spring -> Add Start 클릭 -> thymeleaf 선택
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
임시 DB로 메모리에 2MB의 크기를 가진 데이터베이스를 구축하여 테스트용도로 사용함
pom.xml에 오른쪽 클릭 -> Spring -> Add Start 클릭 -> H2 Database 선택
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
application.properties 안에 추가
#h2 DB (메모리안에 임시적으로 사용하는 db)
spring.h2.console.enabled=true
spring.h2.console.path=/h2.console
#jpa 에서 sql을 사용할때마다 log로 콘솔 출력
spring.jpa.show-sql=true
spring.datasource.url=jdbc:h2:mem:testdb
preferences => General => Editors => File Associations
*.html 선택 후 우측 하단의 Add 버튼을 클릭 -> Visual Studio Code 원본파일 선택
-> default를 선택
<!DOCTYPE html>
<html lang="ko" xmlns:th="http://www.thymeleaf.org">
<head th:replace="layouts::헤드"> </head>
<body>
<nav th:replace="layouts:: 네브바"></nav>
<div class="container">
<h1>프로젝트 진행 상황</h1>
<table class="table table-hover">
<thead class="table-dark">
<tr>
<th>프로젝트 이름</th>
<th>현재 진행상태</th>
</tr>
</thead>
<tbody>
<!-- thymeleaf의 반복문-->
<tr th:each="project : ${projectList}">
<td th:text="${project.name}"></td>
<td th:text="${project.stage}"></td>
</tr>
</tbody>
</table>
<h1>직원 현황</h1>
<table class="table table-hover">
<thead class="table-dark">
<tr class="fw-bold">
<th>성</th>
<th>이름</th>
<th>이메일</th>
</tr>
</thead>
<tbody>
<tr th:each="employee : ${employeeList}">
<td th:text="${employee.lastName}"></td>
<td th:text="${employee.firstName}"></td>
<td th:text="${employee.email}"></td>
</tr>
</tbody>
</table>
</div>
</body>
</html>
project 와 employee 데이터를 임시 DB에서 찾아 model 안에 저장
@Controller이기 때문에 return하는 String 타입의 문자가 이동하고자 하는 View파일의 이름과 동일한 파일로 이동
package com.myapp.pma.controllers;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import com.myapp.pma.dao.EmployeeRepository;
import com.myapp.pma.dao.ProjectRepository;
import com.myapp.pma.entities.Employee;
import com.myapp.pma.entities.Project;
@Controller
public class HomeController {
@Autowired
private ProjectRepository projectRepository;
@Autowired
private EmployeeRepository employeeRepository;
@GetMapping("/")
public String displayHome1(Model model) {
List<Project> projectList = projectRepository.findAll();
List<Employee> employeeList = employeeRepository.findAll();
model.addAttribute("projectList", projectList);
model.addAttribute("employeeList", employeeList);
return "main/home";
}
<!DOCTYPE html>
<html lang="en">
<head th:replace="layouts::헤드"> </head>
<body>
<nav th:replace="layouts:: 네브바"></nav>
<div class="container">
<h1>직원 현황</h1>
<a class="btn btn-outline-success my-2" th:href="@{/employees/new}">추가</a>
<table class="table table-hover">
<thead class="table-dark">
<tr class="fw-bold">
<th>성</th>
<th>이름</th>
<th>이메일</th>
</tr>
</thead>
<tbody>
<tr th:each="employee : ${employeeList}">
<td th:text="${employee.lastName}"></td>
<td th:text="${employee.firstName}"></td>
<td th:text="${employee.email}"></td>
</tr>
</tbody>
</table>
</div>
</body>
</html>
<!DOCTYPE html>
<html lang="ko" xmlns:th="http://www.thymeleaf.org">
<head th:replace="layouts::헤드"> </head>
<body>
<nav th:replace="layouts:: 네브바"></nav>
<div class="container">
<form action="/employees/save" method="post" th:object="${employee}">
<div class="row my-2">
<input class="form-control" type="text" placeholder="성" th:field="*{lastName}" />
</div>
<div class="row my-2">
<input class="form-control" type="text" placeholder="이름" th:field="*{firstName}" />
</div>
<div class="row my-2">
<input class="form-control" type="text" placeholder="이메일" th:field="*{email}" />
</div>
<button class="btn btn-secondary" type="submit">새 직원</button>
</form>
</div>
</body>
</html>
메소드를 불러올 Interface를 생성
package com.myapp.pma.dao;
import java.util.List;
import org.springframework.data.repository.CrudRepository;
import com.myapp.pma.entities.Employee;
public interface EmployeeRepository extends CrudRepository<Employee, Long>{
// 자동으로 CRUD 객체 생성
List<Employee> findAll(); // 기존의 findAll() return 타입이 Itreable<Project>에서 변경
}
@Controller이기 때문에 return하는 String 타입의 문자가 이동하고자 하는 View파일의 이름과 동일한 파일로 이동
package com.myapp.pma.controllers;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import com.myapp.pma.dao.EmployeeRepository;
import com.myapp.pma.entities.Employee;
@Controller
@RequestMapping("/employees")
public class EmployeeController {
// Spring에서 repository객체를 처음에 자동생성해서 가지고 있다가
// Autowired는 관련 객체를 필요할 때 자동으로 연결해준다.
@Autowired
private EmployeeRepository employeeRepository;
@GetMapping("/new")
public String displayPrjectForm(Model model) {
Employee e = new Employee();
model.addAttribute("employee", e);
return "employees/new-employee";
}
@PostMapping("/save")
public String createProject(Employee employee) {
employeeRepository.save(employee); // DB에 employee객체를 테이블에 저장
return "redirect:/employees/new"; //post-redirect-get 패턴
}
@GetMapping("/")
public String displayEmployees(Model model) {
List<Employee> employeeList = employeeRepository.findAll();
model.addAttribute("employeeList", employeeList);
return"employees/employees";
}
}
<!DOCTYPE html>
<html lang="en">
<head th:replace="layouts::헤드"> </head>
<body>
<nav th:replace="layouts:: 네브바"></nav>
<div class="container">
<h1>프로젝트 진행 상황</h1>
<a class="btn btn-outline-success my-2" th:href="@{/projects/new}">추가</a>
<table class="table table-hover">
<thead class="table-dark">
<tr>
<th>프로젝트 이름</th>
<th>현재 진행상태</th>
</tr>
</thead>
<tbody>
<!-- thymeleaf의 반복문-->
<tr th:each="project : ${projectList}">
<td th:text="${project.name}"></td>
<td th:text="${project.stage}"></td>
</tr>
</tbody>
</table>
</div>
</body>
</html>
<!DOCTYPE html>
<html lang="ko" xmlns:th="http://www.thymeleaf.org">
<head th:replace="layouts::헤드"> </head>
<body>
<nav th:replace="layouts:: 네브바"></nav>
<div class="container">
<form action="/projects/save" method="post" th:object="${project}">
<div class="row my-2">
<input class="form-control" type="text" placeholder="프로젝트 이름" th:field="*{name}" />
</div>
<div class="row my-2">
<select class="form-select" th:field="*{stage}">
<option th:value="시작전">시작전</option>
<option th:value="진행중">진행중</option>
<option th:value="완료">완료</option>
</select>
</div>
<div class="row my-2">
<textarea class="form-control" placeholder="프로젝트 설명" th:field="*{description}"></textarea>
</div>
<button class="btn btn-secondary" type="submit">새 프로젝트</button>
</form>
</div>
</body>
</html>
메소드를 불러올 Interface를 생성
package com.myapp.pma.dao;
import java.util.List;
import org.springframework.data.repository.CrudRepository;
import com.myapp.pma.entities.Project;
// JPA 에서는 repostiory에 CRUD 가능한 인터페이스 crudRepository를 상속
public interface ProjectRepository extends CrudRepository<Project, Long> {
// crudRepository에 이미 CRUD 코드가 다 만들어져 있어서 사용만 하면 됨. => JPA Hibernate가 구현코드도 다 자동생성
@Override
List<Project> findAll(); // 기존의 findAll() return 타입이 Itreable<Project>에서 변경
}
@Controller이기 때문에 return하는 String 타입의 문자가 이동하고자 하는 View파일의 이름과 동일한 파일로 이동
package com.myapp.pma.controllers;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import com.myapp.pma.dao.ProjectRepository;
import com.myapp.pma.entities.Project;
@Controller
@RequestMapping("/projects")
public class ProjectController {
// Spring에서 repository객체를 처음에 자동생성해서 가지고 있다가
// Autowired는 관련 객체를 필요할 때 자동으로 연결해준다.
@Autowired
private ProjectRepository projectRepository;
@GetMapping("/new")
public String displayPrjectForm(Model model) {
Project p = new Project();
model.addAttribute("project", p);
return "projects/new-project";
}
@PostMapping("/save")
public String createProject(Project project) {
projectRepository.save(project); // DB에 project객체를 테이블에 저장
return "redirect:/projects/new"; //post-redirect-get 패턴
}
@GetMapping("/")
public String displayProjects(Model model) {
List<Project> projectList = projectRepository.findAll();
model.addAttribute(projectList);
return"projects/projects";
}
}