본문 바로가기

서버/SprintBoot
[스프링부트(Spring Boot)] Thymeleaf


//Spring Boot + Thymeleaf

- New > Spring Starter Project
~ Name > boot-thymeleaf
  ~ Package > com.test.thymeleaf

~ Spring Boot Version > 2.7.13
 
~ Spring Web
~ Oracle Driver
~ MyBatis Framework
~ Lombok
~ SpringBoot Dev Tools
~ Thymeleaf


// Thymeleaf Standard Expression, 타임리프 표현식

    1. Variable Expression, 변수 표현식
        - ${}
        - 컨트롤러 > 전달된 값 출력

    2. Selection Variable Expression, 선택 변수 표현식
        - *{}
        - 객체/맵 프로퍼티 출력
        - th:object 속성과 같이 사용

    3. Message Expression, 메시지 표현식
        - #{}
        - 스프링 메시지 전용 출력(특수)

    4. Link URL Expression, 링크 주소 표현식
        - @{}
    - 링크의 URL 전용 출력(특수)

    5. Fragment Expression, 조각 표현식
        - ~{}
        - 조각 페이지 삽입(include 지시자 or tiles와 유사한 기능)


- MyBatis + Thyemleaf 설정
    ~ application.properties

# 톰캣 포트 번호
server.port = 8092


# HikariCP settings
spring.datasource.hikari.minimumIdle=5
spring.datasource.hikari.maximumPoolSize=20
spring.datasource.hikari.idleTimeout=30000
spring.datasource.hikari.maxLifetime=2000000
spring.datasource.hikari.connectionTimeout=30000

spring.datasource.driver-class-name=oracle.jdbc.OracleDriver
spring.datasource.url=jdbc:oracle:thin:@localhost:1521:xe
spring.datasource.username=hr
spring.datasource.password=java1234

# Thymeleaf
spring.thymeleaf.enabled=true
spring.thymeleaf.prefix=classpath:/templates/
spring.thymeleaf.suffix=.html

# cache 활성화 > 개발 시에는 false
spring.thymeleaf.cache=false
spring.thymeleaf.encoding=UTF-8

# MyBatis > 패키지 별칭
# mybatis.type-aliases-package=com.test.domain

# MyBatis > 클래스 별칭
mybatis.config-location=classpath:mybatis-config.xml

# 스프링 메시지
spring.messages.basename=messages
spring.messages.encoding=UTF-8

~ "com.test.mapper" > "ThymeleafMapper.java"(I)

package com.test.mapper;

import java.util.List;

import com.test.domain.BoardDTO;

public interface ThymeleafMapper {

	int getNum();

	String getTxt();

	BoardDTO getDTO();

	List<String> getNames();

	List<BoardDTO> getList();

}


    ~ "com.test.domain" > "BoardDTO.java"

package com.test.domain;

import lombok.Data;

@Data
public class BoardDTO {
	
	private String seq;
	private String id;
	private String subject;
	private String content;
	private String regdate;

}


    ~ "com.test.controller" > "ThymeleafController.java"

package com.test.controller;

import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpSession;

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.test.domain.BoardDTO;
import com.test.mapper.ThymeleafMapper;

@Controller
public class ThymeleafController {

	@Autowired
	private ThymeleafMapper mapper;
	
	@GetMapping("/m1")
	public void m1() {
		
		//요청 메소드의 반환값 > void > m1.html (thymeleaf suffix 설정대로 호출)
		System.out.println("m1");
		
	}
	
	//페이지 요청
	//1. 동적 페이지("m2.html") > localhost:8092/m2
	//2. 정적 페이지("m2.html") > localhost:8092/m2.html
	// * 정적 페이지와 동적 페이지 url이 완전히 똑같아서 충돌할 땐 동적 페이지 win
	@GetMapping("/m2")
	public String m2() {
	
		//templates > m2.html
		return "m2";
	}
	
	@GetMapping("/m3")
	public String m3(Model model) {
	
		//단일값 출력
		int num = mapper.getNum();
		String txt = mapper.getTxt();
		BoardDTO dto = mapper.getDTO();
		
		Map<String,String> map = new HashMap<String, String>();
		map.put("dog", "강아지");
		map.put("cat", "고양이");
				
		
		model.addAttribute("num", num);
		model.addAttribute("txt", txt);
		model.addAttribute("now", Calendar.getInstance());
		model.addAttribute("dto", dto);
		model.addAttribute("map", map);
			
		
		return "m3";
	}
	
	@GetMapping("/m4")
	public String m4(Model model) {
		
		int a = 10;
		int b = 3;
		
		model.addAttribute("a", a);
		model.addAttribute("b", b);
				
		return "m4";
	}
	
	@GetMapping("/m5")
	public String m5(Model model) {
		
		model.addAttribute("name", "age");
		model.addAttribute("size", 30);
		model.addAttribute("color", "cornflowerblue");
	
		return "m5";
	}
	
	@GetMapping("/m6")
	public String m6(Model model) {
		
		
		//PCDATA 출력
		String name = mapper.getTxt();
		BoardDTO dto = mapper.getDTO();
		String txt = "안농하세요. <i>홍길동</i>입니다.";
		int num = 100;
		
		List<String> names = mapper.getNames();
		
		model.addAttribute("name", name);
		model.addAttribute("dto", dto);
		model.addAttribute("txt", txt);
		model.addAttribute("num", num);
		model.addAttribute("names", names);
		
		return "m6";
	}

	@GetMapping("/m7")
	public String m7(Model model) {
		
		int num1 = 1234567;
		double num2 = 12345.6789;
		Calendar now = Calendar.getInstance();
		
		model.addAttribute("num1", num1);
		model.addAttribute("num2", num2);
		model.addAttribute("now", now);
	
		return "m7";
	}
	
	@GetMapping("/m8")
	public String m8(Model model) {
		
		int seq = 10;
		String mode = "add";
		
		model.addAttribute("seq", seq);
		model.addAttribute("mode", mode);
	
		return "m8";
	}
	
	@GetMapping("/m9")
	public String m9(Model model) {
		
		int num1 = 100;
		int num2 = 5;
		String mode = "add";
		
		model.addAttribute("num1", num1);
		model.addAttribute("num2", num2);
		model.addAttribute("mode", mode);
	
		return "m9";
	}
	
	@GetMapping("/m10")
	public String m10(Model model) {
		
		List<String> names = mapper.getNames();
		List<BoardDTO> list = mapper.getList();
		
		model.addAttribute("names", names);
		model.addAttribute("list", list);
	
		return "m10";
	}
	
	@GetMapping("/m11")
	public String m11(HttpSession session) {
		
		session.setAttribute("id", "hong");
		
		session.invalidate();
	
		return "m11";
	}
	
	@GetMapping("/m12")
	public String m12() {
	
		return "m12";
	}
    
}


    
~ src/main/resources > templates > "m1.html", "m2.html", "m3.html", "m4.html", "m5.html", "m6.html", "m7.html", "m8.html"

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="stylesheet" href="https://me2.do/5BvBFJ57">
</head>
<body>
	<h1>Thymeleaf</h1>
	
</body>
</html>

 

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="stylesheet" href="https://me2.do/5BvBFJ57">
</head>
<body>
	<h1>Thymeleaf</h1>
	<div>m2.html</div>
</body>
</html>

 

<!DOCTYPE html>
<html xmlns:th="https://thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="stylesheet" href="https://me2.do/5BvBFJ57">
</head>
<body>
	<h1>Thymeleaf <small>단일값 출력</small></h1>
	
	<h2>변수 표현식</h2>
	
	<div>${num}</div>
	 
	<div th:text=${num}>200</div>
	<div th:text="100"></div>
	
	
	<h2>타입별</h2>
	
	<div>숫자: 100</div>
	<div th:text="${num}">숫자: </div>
	
	<div>숫자: <span th:text="${num}"></span></div>
	<div>텍스트: <span th:text="${txt}"></span></div>
	<div>객체: <span th:text="${dto}"></span></div>		
	<div>맵: <span th:text="${map}"></span></div>		
	
	<!--  변수 표현식 -->
	<h2>복합 데이터(객체, 맵) 프로퍼티</h2>
	<div>제목: <span th:text="${dto.getSubject()}"></span></div>
	<div>제목: <span th:text="${dto.subject}"></span></div>
	<div>아이디: <span th:text="${dto.id}"></span></div>
	<div>날짜: <span th:text="${dto.regdate}"></span></div>
	
	<!-- 선택 변수 표현식 -->
	<div th:object = "${dto}">
		<div>제목: <span th:text="*{subject}"></span></div>
		<div>아이디: <span th:text="*{id}"></span></div>
		<div>제목: <span th:text="*{regdate}"></span></div>
	</div>
	
	<hr>
	
	<div th:text="${map.get('dog')}"></div>
	<div th:text="${map.dog}"></div>
	<div th:text="${map.cat}"></div>
	
	
	<div th:object = "${map}">
		<div th:text="*{dog}"></div>
		<div th:text="*{cat}"></div>
	</div>
	
	<hr>
	
	<h2>다국어 지원 <small>스프링 메시지</small></h2>
	
	<div class="message" title="사용 언어" th:text="#{language}"></div>
	
	<div class="message" title="상품">
		<div>상품명: <span th:text="#{item.name}"></span></div>
		<div>색상: <span th:text="#{item.color}"></span></div>
		<div>가격: <span th:text="#{item.price}"></span></div>
	</div>
	
	<div th:text="#{hello('홍길동')}"></div>
	<div th:text="#{hello(#{item.name})}"></div>
	
		
</body>
</html>

 

<!DOCTYPE html>
<html xmlns:th="https://thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="stylesheet" href="https://me2.do/5BvBFJ57">
</head>
<body>

	<h1>Thymeleaf</h1>
	
	<!-- 
	
		타임리프 연산자
		
		- 산술 연산자 > 동일
		- 비교 연산자 > 동일 + 영문
		- 논리 연산자 > 동일 + 영문
		- 삼항 연산자 > 동일
		- 문자열 연산자 > 동일
	
	-->
	
	<div>10 + 3 = 13</div>
			
	<div><span th:text="${a}"></span> + <span th:text="${b}"></span> = <span th:text="${a + b}"></span></div>		
	
	<div th:text="${a + ' + ' + b + ' = ' + (a + b)}"></div>
	
	<div th:text="${a} + ' + ' + ${b} + ' = ' + ${a + b}"></div>
	
	<div th:text="|홍길동|"></div>
	<div th:text="|${a}|"></div>
	
	<div th:text="|${a} + ${b} = ${a+b}|"></div>
	
	<hr>
	
	<div th:text="${a} + ${b}"></div>
	<div th:text="${a} - ${b}"></div>
	<div th:text="${a} * ${b}"></div>
	<div th:text="${a} / ${b}"></div>
	<div th:text="${a} % ${b}"></div>
	
	<hr>
	
	<div th:text="${a} > ${b}"></div>
	<div th:text="${a} >= ${b}"></div>
	<div th:text="${a} < ${b}"></div>
	<div th:text="${a} <= ${b}"></div>
	<div th:text="${a} == ${b}"></div>
	<div th:text="${a} != ${b}"></div>
	
	<hr>
	
	<div th:text="${a > 5} and ${b < 10}"></div>
	<div th:text="${a > 5} or ${b < 10}"></div>
	
	<hr>
	
	<div th:text="${a > 0} ? '양수' : '음수'"></div>
	
	<hr>
	
	<div th:text="${c} != null ? ${c} : '데이터 없음'"></div>
	<div th:text="${c} ? ${c} : '데이터 없음'"></div>
	<div th:text="${c} ?: '데이터 없음'"></div> <!-- Elvis 연산자 -->
	<div th:text="${c} ?: _">데이터 없음</div> <!-- No-Operation -->
	
</body>
</html>

 

<!DOCTYPE html>
<html xmlns:th="https://thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="stylesheet" href="https://me2.do/5BvBFJ57">
<style>
	
	.one { color: gold; }
	.two { text-decoration: underline; }
	.three { font-size: 3rem; }
	
</style>
</head>
<body>

	<h1>Thyemleaf + HTML Attribute</h1>
	
	<!-- 
	
		HTML 속성 조작
		- th:HTML속성명="값"
		- 기존에 동일한 속성이 선언되어 있으면 대체한다.
		- 기존에 동일한 속성이 선언되어 있지 않으면 추가한다.
		
		**대부분 서버에서 전달 받은 값(model)은
			- 직접 표현식은 반드시 th:속성에만 적용이 가능
	
	-->
	
	<input type="text" name="age">
	<input type="text" th:name="age">
	<input type="text" name="${name}">
	<input type="text" th:name="${name}">
	<input type="text" th:name="${name}" th:size="${size}">
	
	<input type="text" th:value="${color}">
	
	<hr>
	
	<div class="one">Box 1</div>
	<div th:class="one">Box 2</div>
	
	<div class="one" th:class="two">Box 3</div>
	
	
	<div class="one" th:attrappend="class=' two'">Box 4</div>
	<div class="one" th:attrprepend="class='two '">Box 5</div>
	
	<div class="one" th:classappend="two">Box 6</div>
	
	<input type="checkbox" name="cb" th:checked="true">
	<input type="checkbox" name="cb" th:checked="false">
	
	<div style="background-color:${color}">Box 7</div>
	<div th:style="'background-color:'+${color}">Box 7</div>
	<div th:style="|background-color:${color}|">Box 7</div>
	
</body>
</html>

 

<!DOCTYPE html>
<html xmlns:th="https://thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="stylesheet" href="https://me2.do/5BvBFJ57">
</head>
<body>

	<h1>Thymeleaf Text</h1>
	
	<!--/*
	
		HTML 콘텐츠 영억 > 데이터 출력
		1. th:text
			- escaped text
			- '<' -> &lt;
			- '>' -> &gt;			
			
		2. th:utext
			- unexcaped text
			- 그대로 출력
			
		인라인 출력
		1. th:inline="text" > 사용 잘 안 함
		2. th:inline="javascript" > 많이 사용(필수)
	
		1. th:inline + [[]] > escaped text	
		2. th:inline + [()] > unescaped text	
	
	*/-->
	
	<div th:text="${txt}"></div>
	<div th:utext="${txt}"></div>
	
	<hr>
	
	<div th:inline="text">[[${name}]]</div>
	<div th:inline="text">[(${name})]</div>
	
	<div th:inline="text">[[${txt}]]</div>
	<div th:inline="text">[(${txt})]</div>
	
	<div th:inline="text">[[${txt}]]</div>
	<div th:inline="text">[(${txt})]</div>
	
	<!--/* 
	<div th:inline="text">[[${a}]] + [[$b}]] = [[${a + b}]]</div>
	*/-->
	
	<div id="label1"></div>
	<div id="label2"></div>
	
<script>

	let name1 = '[[${name}]]';
	let num1 = [[${num}]];
	let names1 = '[[${names}]]';
	let dto1 = '[[${dto}]]';
	
	document.getElementById('label1').textContent = name1;
	
</script>
	
<script th:inline="javascript">

	let name2 = [[${name}]];
	let num2 = [[${num}]];
	let names2 = [[${names}]];
	let dto2 = [[${dto}]];
	
	document.getElementById('label2').textContent = name2;
	
</script>
	
</body>
</html>

 

<!DOCTYPE html>
<html xmlns:th="https://thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="stylesheet" href="https://me2.do/5BvBFJ57">
</head>
<body>

	<h1>Thymeleaf Format</h1>
	
	<!-- 
	
		데이터를 일정한 형식으로 표현하는 도구
		- #numbers
		- #dates
	
	-->
	
	<h2>숫자</h2>
	
	<div th:text="${num1}"></div>
	<div th:text="${#numbers.formatInteger(num1, 10, 'COMMA')}"></div>	
	<div th:text="${#numbers.formatInteger(num1, 10, 'POINT')}"></div>	
	
	<div th:text="${num2}"></div>
	<div th:text="${#numbers.formatDecimal(num2, 3, 'COMMA', 2, 'POINT')}"></div>
	
	
	<h2>날짜</h2>
	
	<!-- <div th:text="${now}"></div> -->
	
	<div th:text="${#dates.year(now)}"></div>
	<div th:text="${#dates.month(now)}"></div>
	<div th:text="${#dates.monthName(now)}"></div>
	<div th:text="${#dates.monthNameShort(now)}"></div>
	<div th:text="${#dates.day(now)}"></div>
	<div th:text="${#dates.hour(now)}"></div>
	<div th:text="${#dates.minute(now)}"></div>
	<div th:text="${#dates.second(now)}"></div>
	<div th:text="${#dates.millisecond(now)}"></div>
	<div th:text="${#dates.dayOfWeek(now)}"></div>
	<div th:text="${#dates.dayOfWeekName(now)}"></div>
	<div th:text="${#dates.dayOfWeekNameShort(now)}"></div>	
	
	<div th:text="${#dates.format(now)}"></div>
	<div th:text="${#dates.format(now, 'yyyy-MM-dd HH:mm:ss')}"></div>
	<div th:text="${#dates.format(now, 'yyyy-MM-dd hh:mm:ss')}"></div>
	<div th:text="${#dates.format(now, 'yyyy-MM-dd aa hh:mm:ss')}"></div>
		
</body>
</html>

 

<!DOCTYPE html>
<html xmlns:th="https://thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="stylesheet" href="https://me2.do/5BvBFJ57">
</head>
<body>

	<h1>Thymeleaf Links</h1>
	
	<!-- 
	
		Link URL Expressions
		- @{}
		- 링크의 URL 표현
		a. 매개변수 처리 쉽다.
		b. Context Root Path가 자동으로 삽입
	
	-->
	
	<div><a href="/m7">이전 페이지</a></div>		
	<div><a href="/spring/m7">이전 페이지</a></div>	
	<div><a th:href="@{/m7}">이전 페이지</a></div>			
	
	<hr>
	
	<h3>QueryString, 매개변수</h3>	
	<div><a href="/m7?seq=100">이전 페이지</a></div>
	<div><a href="/m7?seq=${seq}">이전 페이지</a></div> <!-- 에러 -->
	<div><a th:href="@{/m7(seq=${seq})}">이전 페이지</a></div>
	
	<div><a href="/m7?seq=100&mode=add">이전 페이지</a></div>
	<div><a th:href="@{/m7(seq=${seq}, mode=${mode})}">이전 페이지</a></div>
	
	<hr>
	
	<!--  
	
		기본 웹(QueryString)
		- /m7?seq=10
		
		REST(Path Variable)
		- /m7/10	
	
	-->
	
	<div><a th:href="@{/m7/{seq}(seq=${seq})}">이전 페이지</a></div>	
	<div><a th:href="@{/m7/{mode}/{seq}(seq=${seq},mode=${mode})}">이전 페이지</a></div>	
	
</body>
</html>

 

<!DOCTYPE html>
<html xmlns:th="https://thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="stylesheet" href="https://me2.do/5BvBFJ57">
</head>
<body>

	<h1>Thymeleaf Conditions</h1>
	
	<!--  	
		1. th:if
		2. th:switch	
	-->
	
	<h2>if</h2>
	
	<div th:if="${num1 > 0}">num1: 양수</div>
	<div th:if="${num1 < 0}">num1: 음수</div>	
	
	<div th:if="${num2 > 0}">num2: 양수</div>
	<div th:if="${num2 < 0}">num2: 음수</div>
	
	<div th:if="${num1 > 0}">
		<span th:text="'양수 ' + ${num1} + '입니다.'"></span>
	</div>	
	
	<div th:if="${num2 > 0}" th:text="'양수 ' + ${num2} + '입니다.'"></div>	
	
	<div th:if="${num2 > 0}" th:text="|양수 ${num2}입니다.|"></div> <!-- 권장 -->
		
	<div th:if="${num2 > 0}">양수 [[${num2}]]입니다.</div> <!-- 비권장 -->
	<div th:unless="${num2 > 0}">음수</div>
	
	<hr>
	
	<h2>switch</h2>
	
	<div th:switch="${mode}">
		<div th:case="add">추가하기</div>
		<div th:case="remove">삭제하기</div>
		<div th:case="*">기타</div>
	</div>
	
		
	
</body>
</html>



   
~ src/main/resources > "com" > "test" > "mapper" > "ThymeleafMapper.xml"

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.test.mapper.ThymeleafMapper">

	<select id="getNum" resultType="Integer">
		select salary from employees where rownum = 1
	</select>
	
	<select id="getTxt" resultType="String">
		select first_name from employees where rownum = 1 
	</select>
	
	<!-- 	
	<select id="getDTO" resultType="BoardDTO">
		select * from tblBoard where rownum = 1
	</select>
	 -->
	 
	<select id="getDTO" resultType="dto">
		select * from tblBoard where rownum = 1
	</select>
	
	<select id="getNames" resultType="String">
		select first_name from employees where rownum &lt;= 10
	</select>
	
	<select id="getList" resultType="dto">
		select * from tblBoard
	</select>

</mapper>

 

<!DOCTYPE html>
<html xmlns:th="https://thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="stylesheet" href="https://me2.do/5BvBFJ57">
</head>
<body>

	<h1>Thymeleaf Iterations</h1>
	
	<h2>each</h2>
	
	<ul>
		<li th:each="name : ${names}" th:text="${name}">이름</li>
	</ul>
	
	<ul>
		<li th:each="name : ${names}"><span th:text="${name}"></span></li>
	</ul>
	
	<ul th:each="name: ${names}">
		<li th:text="${name}"></li>
	</ul>
	
	<hr>
	
	<ul>
		<li th:each="dto : ${list}" th:text="|${dto.subject}(${dto.id})|"></li>
	</ul>
	
	<ul>
		<li th:each="dto : ${list}" th:object="${dto}" th:text="*{subject}"></li>
	</ul>
	
	<hr>
	
	<table>
		<tr>
			<th>번호</th>
			<th>아이디</th>
			<th>제목</th>
			<th>index</th>
			<th>count</th>
			<th>size</th>
			<th>even</th>
			<th>odd</th>
			<th>first</th>
			<th>last</th>
		</tr>
		<tr th:each="dto, status : ${list}">
			<td th:text="${dto.seq}"></td>
			<td th:text="${dto.id}"></td>
			<td th:text="${subject}"></td>
			<td th:text="${status.index}"></td>
			<td th:text="${status.count}"></td>
			<td th:text="${status.size}"></td>
			<td th:text="${status.even}"></td>
			<td th:text="${status.odd}"></td>
			<td th:text="${status.first}"></td>
			<td th:text="${status.last}"></td>
		</tr>
	</table>
	
</body>
</html>

 

<!DOCTYPE html>
<html xmlns:th="https://thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="stylesheet" href="https://me2.do/5BvBFJ57">
</head>
<body>
	
	<h1>Thymeleaf Expression Basic Objects</h1>
	
	<!--/*
	
		${#request}
		${#response}
		${#locale}
		${#session}
		${#servletContext}
	
	*/-->
	
	<div th:text="${#request}"></div>
	<div th:text="${#response}"></div>
	<div th:text="${#locale}"></div>
	<div th:text="${#session}"></div>
	<div th:text="${#servletContext}"></div>
	
	<hr>
	
	<div th:if="${session.id != null}">
		인증: <span th:text="${session.id}">아이디</span>
	</div>
	
	<div th:unless="${session.id != null}">미인증</div>
	
</body>
</html>

 

<!DOCTYPE html>
<html xmlns:th="https://thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="stylesheet" href="https://me2.do/5BvBFJ57">
</head>
<body>

	<h1>Thymeleaf Fragment</h1>
	
	<h2>insert</h2>
	<div th:insert="~{inc/sub.html}"></div>
	
	<h2>replace</h2>
	<div th:replace="~{inc/sub.html}"></div>
	
	<hr>
	
	<!-- 확장자 생략 가능 -->
	<div th:insert="~{inc/sub}"></div>
	
	<!-- ~{} 생략 가능, but 비권장 -->		
	<div th:insert="inc/sub"></div>
	
	<hr>	
	
	<div th:insert="~{inc/sub2.html :: part}"></div>
	
	<hr>	
	
	<div th:insert="~{inc/sub2.html :: part2}"></div>
	
	<hr>	
	
	<div th:insert="~{inc/sub2.html :: owner('아무개', '010-1111-2222')}"></div>
	
	<div th:insert="~{inc/sub2.html :: owner('테스트', '010-3333-4444')}"></div>
	
</body>
</html>


    
~ templates > "inc" > "sub.html", "sub2.html"

<div>조각 페이지</div>

 

<!DOCTYPE html>
<html xmlns:th="https://thymeleaf.org">
<body>

	<div th:fragment="part">조각 페이지2</div>
	
	<div th:fragment="part2">조각 페이지3</div>
	
	<div th:fragment="owner(name,tel)">
		<div>소유주: <span th:text="${name}"></span></div>
		<div>연락처: <span th:text="${tel}"></span></div>
	</div>
	
</body>
</html>


    
~ boot-thymeleaf > "mybatis-config.xml"

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0/EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">

<configuration>
	<typeAliases>
		<typeAlias type="com.test.domain.BoardDTO" alias="dto"/>
	</typeAliases>
</configuration>