여기에서 스프링 부트 프로젝트를 준비한다.
스프링 부트 3버전 이상 사용시 주의점
1. JAVA 17이상
2. 패키지 명 javax -> jakarta
3. H2 DB 2.1.214 버전 이상
타임리프를 사용하려면 다음 선언을 하면 된다.
<html xmlns:th="http://www.thymeleaf.org">
• 간단한 표현:
◦ 변수 표현식: ${...}
◦ 선택 변수 표현식: *{...}
◦ 메시지 표현식: #{...}
◦ 링크 URL 표현식: @{...}
◦ 조각 표현식: ~{...}
• 리터럴
◦ 텍스트: 'one text', 'Another one!',…
◦ 숫자: 0, 34, 3.0, 12.3,…
◦ 불린: true, false
◦ 널: null
◦ 리터럴 토큰: one, sometext, main,…
• 문자 연산:
◦ 문자 합치기: +
◦ 리터럴 대체: |The name is ${name}|
• 산술 연산:
◦ Binary operators: +, -, *, /, %
◦ Minus sign (unary operator): -
• 불린 연산:
◦ Binary operators: and, or
◦ Boolean negation (unary operator): !, not
• 비교와 동등:
◦ 비교: >, <, >=, <= (gt, lt, ge, le)
◦ 동등 연산: ==, != (eq, ne)
• 조건 연산:
◦ If-then: (if) ? (then)
◦ If-then-else: (if) ? (then) : (else)
◦ Default: (value) ?: (defaultvalue)
• 특별한 토큰:
◦ No-Operation: _
너무 많은 기능이 있으므로
관리자 페이지 직접 구현 아니라면 이런 기능이 이런 이름으로 있다. 하고 넘어가자.
타임리프는 HTML 태그 속성에 기능을 정의 한다.
데이터를 출력(렌더링?) 할 때는 th:text
와 [[...]]
를 사용한다.
<div class="content"><span th:text="${data}" /></div>
<!-- 태그가 아닌 HTML 컨텐츠에서 직접 출력시 -->
<div class="content">컨텐츠 내용은 [[${data}]] 입니다</div>
가끔 게시판을 이용하다보면 태그 속성을 넘겨받는다. 이를 그대로 출력하면 다음과 같다
@GetMapping("/text-basic")
public String textBasic(Model model) {
model.addAttribute("data", "Hello <b>Spring!</b>");
return "basic/text-basic";
}
// html
[[...]] = Hello <b>Spring</b>
HTML 문서는 <, >
과 같은 특수 문자를 기분으로 하기에 <
과 같은 문자를 태그의 시작으로 본다. 따라서 <
를 태그가 아닌 문자
로 표현 할 방법이 필요한다. 이를 HTML 엔티티라고 한다. HTML에서 사용하는 특수 문자를 HTML 엔티티로 변경하는 것을 이스케이프라고한다.
<
--> <
>
--> >
Thymeleaf에서는 이스케이프를 사용하지 않을 수 있게 -다음 두 방법을 제공한다.
th:text
--> th:utext
[[...]]
--> [(...)]
변수 표현식 : ${...}
- Object
<li><span th:text="${user.username}"></span></li>
- List
<li><span th:text="${users[0].username}"></span></li>
- Map
<li><span th:text="${userMap['userA'].username}"></span></li>
스프링부트 3부터 사라짐
java.util 객체를 다음과 같이 사용 가능
<!-- temporals는 java 8 util 객체 -->
<span th:text="${#temporals.format(localDateTime, 'yyyy-MM-dd HH:mm:ss')}"></
span>
@GetMapping("/link")
public String link(Model model) {
model.addAttribute("param1", "data1");
model.addAttribute("param2", "data2");
return "basic/link";
}
단순 url
<a th:href="@{/hello}"/>
쿼리 파라미터
<a th:href="@{/hello(param1=${param1}, param2=${param2})}"/>
경로 변수 (Path Variables)
<a th:href="@{/hello/{param1}/{param2}(param1=${param1}, param2=${param2})}"/>
경로 + 쿼리 파라미터
<a th:href="@{/hello/{param1}(param1=${param1}, param2=${param2})}"/>
리터럴이란 소스 코드 상 고정 된 값
String a = "Hello"
int a = 10 * 20
'(작은 따옴표)
감싸야 한다.<span th:text="hello">
<span th:text="hello world!"></span>
<span th:text="'hello ' + ${data}">
<span th:text="|hello ${data}|">
속성 설정
<input type="text" name="mock" th:name="userA" />
속성 추가
th:attrappend : 속성 값의 뒤에 값을 추가한다.
<input type="text" class="text" th:attrappend="class='large'" />
th:attrprepend : 속성 값의 앞에 값을 추가한다.
<input type="text" class="text" th:attrpreppend="class='large'" />
th:classappend : class 속성에 자연스럽게 추가한다
<input type="text" class="text" th:classappend="class='large'" />
checkbox에서 사용 가능한 th:checked="false" 기능 (checked 예약어 우회)
<input type="checkbox" name="active" th:checked="false" />
th:each
<tr th:each="user : ${users}">
<td th:text="${user.username}">username</td>
<td th:text="${user.age}">0</td>
</tr>
반복의 두번째 파라미터(Stat)
stat
<div th:each="user, userStat : ${users}">
<span th:text="{userStat.index}"/>
...
</div>
반복 상태 유지 기능
index : 0부터 시작하는 값
count : 1부터 시작하는 값
size : 전체 사이즈
even , odd : 홀수, 짝수 여부( boolean )
first , last :처음, 마지막 여부( boolean )
current : 현재 객체
if
, unless(if 반대)
타임리프는 해당 조건이 맞지 않으면 태그 자체를 렌더링하지 않는다.
만약 다음 조건이 false 인 경우 <span>...<span>
부분 자체가 렌더링 되지 않고 사라진다.
<span th:text="'미성년자'" th:if="${user.age lt 20}"></span>
html 주석: 타임리프가 렌더해도 아래가 출력 된다.
<!--
<span th:text="${data}">html data</span>
-->
타임리프 파서 주석: 타임리프가 렌더하면 출력 안된다.
<!--/* [[${data}]] */-->
<!--/*-->
<span th:text="${data}">html data</span>
<!--*/-->
타임리프 프로토타입 주석
<!--/*/
<span th:text="${data}">html data</span>
/*/-->
HTML 생으로 열면 주석처리, 타임리프 렌더링하면 그 때서야 보임
<th:block>
유일한 타임리프 고유 태그
아래와 같이 빈 태그 없이 반복문 이용 가능
<th:block th:each="user : ${users}">
...
</th:block>
<script th:inline="javascript">