-
Thymeleaf TEMPLATE ENGINESA modern server-side Java template engine for both web and standalone environments. Allows HTML to be correctly displayed in browsers and as static prototypes.
새 프로젝트 생성하기
ex3/src/main/resources/application.properties
# App name
spring.application.name=ex3
# Server port
server.port=8080
# Context path
server.servlet.context-path=/ex3
# Restart WAS
spring.devtools.livereload.enabled=true
# Spring Datasource
spring.datasource.driver-class-name=org.mariadb.jdbc.Driver
spring.datasource.url=jdbc:mariadb://localhost:3306/db7
spring.datasource.username=db7
spring.datasource.password=1234
# JPA
spring.jpa.hibernate.ddl-auto=create
spring.jpa.properties.hibernate.format_sql=true
spring.jpa.show-sql=true
# Thymeleaf
spring.thymeleaf.cache=false
src/main/java/com/example/ex3/controller/SampleController.java
@Controller
@RequestMapping("/sample")
@Log4j2
public class SampleController {
@GetMapping("ex1")
public void ex1(){
log.info("ex1.................");
}
}
src/main/java/com/example/ex3/Ex3Application.java
@SpringBootApplication
public class Ex3Application {
public static void main(String[] args) {
SpringApplication.run(Ex3Application.class, args);
System.out.println("http://localhost:8080/ex3");
}
}
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>static index</h1>
<pre>
thymeleaf 추가하기 전에는 static 폴더가 렌더링 되지만
추가후에는 templates 폴더가 우선적용된다.
그럼에도 불구하고 만약 index.html 파일이 static 과 templates
동시에 있는 경우, 우선은 static에 있는 index가 우선한다.
</pre>
</body>
</html>
<!DOCTYPE html>
<html lang="ko" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>template index</h1>
<!-- 절대 경로 : Context-path 는 향후에 변경가능성 농후 -->
<a href ="/ex3/sample/ex1">/ex3/sample/ex1</a><br>
<!-- 상대 경로 : 나의 위치로부터 경로 설정 변경가능성 존재 -->
<a href ="./sample/ex1">./sample/ex1</a><br>
<!-- Context-relative URL: thymeleaf를 사용,변경에 영향 없음 -->
<a th:href ="@{/sample/ex1}">/sample/ex1</a><br>
</body>
</html>
파일 생성하기
<!DOCTYPE html>
<html lang="ko" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>ex1.html</h1>
</body>
</html>
<!DOCTYPE html>
<html lang="ko" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>ex1.html</h1>
<!-- th:text="${}" ${}에 컨트롤러로 부터 오는 변수,텍스트,숫자 표현가능-->
<h1 th:text="${'ex1.html'}"></h1>
<h4>Thymeleaf의 표현식</h4>
<ul>
<li>변수 ${}</li>
<li>선택변수 *{}</li>
<li>메세지 #{}</li>
<li>link URL @{}</li>
</ul>
</body>
</html>
ex3/src/main/java/com/example/ex3/controller/SampleController.java
package com.example.ex3.controller;
import com.example.ex3.dto.SampleDTO;
import lombok.extern.log4j.Log4j2;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import java.time.LocalDateTime;
//template engine을 사용한 경우 thymeleaf를 적용한다면
//resources 의 templates 폴더의 파일들을 사용해야하고,
//이는 컨트롤러에서 반드시 중재해야만 페이지로 이동가능
//컨트롤러에서 해당 주소에 대한 중재가 없다면 에러발생 404
@Controller
@RequestMapping("/sample")
@Log4j2
public class SampleController {
@GetMapping("/ex1")
public void ex1() {
log.info("ex1...........");
}
@GetMapping("/selection")
public void selection(Model model) {
log.info("selection...........");
SampleDTO sampleDTO = SampleDTO.builder()
.sno(1L)
.first("Park")
.last("JS")
.regTime(LocalDateTime.now())
.build();
model.addAttribute("sampleDTO", sampleDTO);
}
}
ex3/src/main/java/com/example/ex3/dto/SampleDTO.java
package com.example.ex3.dto;
import lombok.Builder;
import lombok.Data;
import java.time.LocalDateTime;
@Builder(toBuilder = true)
@Data
public class SampleDTO {
private Long sno;
private String first;
private String last;
private LocalDateTime regTime;
}
ex3/src/main/resources/templates/sample/selection.html
<!DOCTYPE html>
<html lang="ko" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h3>선택 변수 *{ }</h3>
<xmp>
<div th:object="${sampleDTO}">
<p>
<span>sampleDTO ${}</span><br>
<span th:text="${sampleDTO.getSno()}"></span>
<span th:text="${sampleDTO.getFirst()}"></span>
<span th:text="${sampleDTO.getLast()}"></span>
<span th:text="${sampleDTO.getRegTime()}"></span>
</p>
<p>
<span>sampleDTO *{}</span><br>
<span th:text="*{sno}"></span>
<span th:text="*{first}"></span>
<span th:text="*{last}"></span>
<span th:text="*{regTime}"></span>
</p>
</div>
</xmp>
</body>
</html>
ex3/src/main/resources/templates/sample/ex1.html
<!DOCTYPE html>
<html lang="ko" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>ex1.html</h1>
<!-- th:text="${}" ${}는 컨트롤러부터 오는 변수,텍스트,숫자 표현 -->
<h1 th:text="${'ex1.html'}"></h1>
<h4>Thymeleaf의 표현식</h4>
<ul style="list-style:none;">
<li>변수 또는 값 th:text="${ }"</li>
<li><a th:href="@{/sample/selection}">선택변수 *{ }</a></li>
<li>메세지 #{ }</li>
<li>Link URL th:href="@{}"</li>
</ul>
</body>
</html>
메세지 표현식
ex3/src/main/resources/messages.properties
msg.login.ok=안녕하세요, {0}님 (로그인일시: {1})
src/main/java/com/example/ex3/dto/SampleDTO.java
package com.example.ex3.dto;
import lombok.Builder;
import lombok.Data;
import java.time.LocalDateTime;
@Builder(toBuilder = true)
@Data
public class SampleDTO {
private Long sno;
private String first;
private String last;
private LocalDateTime regTime;
}
src/main/resources/templates/sample/expression.html
<!DOCTYPE html>
<html lang="ko" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h3>선택 변수 *{ }</h3>
<h3>message #{}</h3>
<p th:text=
"#{msg.login.ok(${sampleDTO.getFirst()+' '+sampleDTO.getLast()}, ${sampleDTO.getRegTime()})}"></p>
</body>
</html>
@RequestMapping("/ex2")
public void ex2(Model model){
//void : 요청된 url 이 렌더링된 주소와 같다
log.info("ex2...............");
List<SampleDTO> list = IntStream.rangeClosed(1,20).asLongStream()
.mapToObj(new LongFunction<SampleDTO>() {
@Override
public SampleDTO apply(long i){
SampleDTO dto = SampleDTO.builder()
.sno(i).first("First..."+i)
.last("Last..."+i)
.regTime(LocalDateTime.now()).build();
return dto;
}
}).collect(Collectors.toList());
model.addAttribute("list",list);
}
<ul style="list-style: none;">
<li th:each="dto, state : ${list}}">
<!-- 반복문에는 부가적으로 사용할 수 있는 state 라는 객체가 있다.-->
[[${state.index}]] : [[${dto}]]
</li>
</ul>