본문 바로가기
스프링

타임리프

by moonstal 2022. 6. 16.

타임리프

  • 순수 HTML 그대로 유지,뷰 템플릿 사용=> 네츄럴 템플릿
    <html xmlns:th="http://www.thymeleaf.org">

텍스트

    model.addAttribute("data", "Hello Spring!");
    <span th:text="${data}">
    <li>[[${data}]]</li> //직접
  • 기본적으로 이스케이프 제공: th:text, [[...]]
  • 이스케이프x: th:utext, [(...)]

변수 - SpringEL

    model.addAttribute("user", userA);
    model.addAttribute("users", list);
    model.addAttribute("userMap", map);

    th:text="${user.username}"
    th:text="${users[0].username}"
    th:text="${userMap['userA'].username}"

    //지역변수
    th:with="first=${users[0]}"
    th:text="${first.username}"

기본 객체

  • 기본 객체: ${#request},${#response},${#session},${#servletContext},${#locale}
  • 편의 객체
    session.setAttribute("sessionData", "Hello Session");
    ${session.sessionData}

    @Component("helloBean")
    ${@helloBean.hello('Spring!')}

    ${param.paramData}

유틸리티 객체와 날짜

    model.addAttribute("localDateTime", LocalDateTime.now());
    th:text="${#temporals.format(localDateTime, 'yyyy-MM-dd HH:mm:ss')}"
    th:text="${#temporals.day(localDateTime)}"

URL 링크

  • 단순 URL: th:href="@{/hello}"
  • 쿼리 파라미터: th:href="@{/hello(param1=${param1}, param2=${param2})}"
  • 경로 변수: {param1}(param1=${param1})

리터럴

  • 고정된 값
  • 문자열 공백 ''로 감싸기
    <span th:text="'hello world!'"></span>

    //리터럴 대체
    model.addAttribute("data", "Spring!");
    <span th:text="|hello ${data}|"></span>

연산

    th:text="10 + 2"
    th:text="1 gt 10"

    <span th:text="${nullData}?: '데이터가 없습니다.'"></span></li>
    <span th:text="${nullData}?: _">데이터가 없습니다.</span></li>
    //타임리프가 실행되지 않는 것 처럼 동작

속성 값 설정

  • 속성추가
th:attrappend="class='large'" 앞
th:attrprepend="class='large'" 뒤
th:classappend="large"
th:checked="true"

반복

    model.addAttribute("users", list);
    <tr th:each="user : ${users}">
    <td th:text="${user.username}">username</td>
    <td th:text="${user.age}">0</td>
    </tr>

    // 상태확인(userStat 생략가능)
    <tr th:each="user, userStat : ${users}">
    <span th:text="${userStat.index}"></span>

조건부 평가

    //참인경우 출력
    <span th:text="'미성년자'" th:if="${user.age lt 20}"></span>
    <span th:text="'미성년자'" th:unless="${user.age ge 20}"></span>

    <td th:switch="${user.age}">
    <span th:case="10">10살</span>
    <span th:case="20">20살</span>
    <span th:case="*">기타</span>
    </td>

블록

  • <th:block th:each="user : ${users}">
  • 애매한 경우

자바스크립트 인라인

  • 타입 변환, 이스케이브, 객체 json 변환
    //each
    <script th:inline="javascript">
        [# th:each="user, stat : ${users}"]
            var user[[${stat.count}]] = [[${user}]];
        [/]
    </script>

템플릿 조각

    <footer th:fragment="copyParam (param1)">
       <p th:text="${param1}"></p>
    </footer>

    ->다른 파일에 합쳐짐

    //합칠 조각의 위치::조각 이름(파라미터)
    <div th:replace="~{template/fragment/footer :: copyParam ('데이터1')}"></div>

    //단순표현
    <div th:replace="template/fragment/footer :: copy"></div>

템플릿 레이아웃

    //베이스
    <head th:fragment="common_header(title,links)">
        <title th:replace="${title}">레이아웃 타이틀</title>
        ~~~공통부분~~~
        <th:block th:replace="${links}" />
    </head>

    //메인
    <head th:replace="template/layout/base :: common_header(~{::title},~{::link})">
    <title>메인 타이틀</title>
    <link rel="stylesheet" th:href="@{/css/bootstrap.min.css}">

    -> 컨트롤러는 메인을 호출 메인에서 베이스로 바꿀 부분만 넘겨서 가져와

타임리프 - 스프링 통합과 폼

입력 폼 처리

    model.addAttribute("item", new Item());
    th:object="${item}"
    th:field="*{itemName}"//선택 변수 식 ->${item.itemName}
    ->field가 id="itemName" name="itemName" th:value="*{itemName}" 만들어줌

체크박스 -단일

    <input type="checkbox" id="open" name="open" class="form-check-input">
    <input type="hidden" name="_open" value="on"/> //체크 해제 인식

    //타임리프 hidden 자동생성
    <input type="checkbox" id="open" th:field="*{open}" class="form-check-input">

체크박스 -멀티

  • 컨트롤러에 있는 별도의 메서드에 적용: @ModelAttribute("regions")
    th:each="region : ${regions}" //map
    type="checkbox" th:field="*{regions}" th:value="${region.key}"
    th:for="${#ids.prev('regions')}" th:text="${region.value}"

라디오 버튼

    @ModelAttribute("itemTypes")
    th:each="type : ${itemTypes}" //ENUM-배열
    type="radio" th:field="*{itemType}" th:value="${type.name()}"
    th:for="${#ids.prev('itemType')}" th:text="${type.description}"
  • 히든 필드 사용할 필요 없음

셀렉트 박스

    @ModelAttribute("deliveryCodes")
    <select th:field="*{deliveryCode}" class="form-select"> //객체 "${item.deliveryCode}"
        <option value="">==배송 방식 선택==</option>
        <option th:each="deliveryCode : ${deliveryCodes}" th:value="${deliveryCode.code}"
                th:text="${deliveryCode.displayName}">FAST</option>
    </select>

메시지, 국제화

  • messages.properties(기본) / messages_en.properties
  • item.itemName=상품명 {0} / item.itemName=Item Name {0}
  • th:text="#{item.itemName(${item.itemName})}"
  • ResourceBundleMessageSource 빈 등록
      setBasenames("messages", "errors");
      setDefaultEncoding("utf-8");
  • 스프링 부트 MessageSource자동 등록
  • spring.messages.basename=messages
  • {0}:매개변수 ms.getMessage("item.itemName", new Object[]{"안녕"}, null);->상품명 안녕
  • 국제화 파일 선택 ms.getMessage("item.itemName", null, Locale.ENGLISH)->Item Name

링크

 

스프링 MVC 2편 - 백엔드 웹 개발 활용 기술 - 인프런 | 강의

웹 애플리케이션 개발에 필요한 모든 웹 기술을 기초부터 이해하고, 완성할 수 있습니다. MVC 2편에서는 MVC 1편의 핵심 원리와 구조 위에 실무 웹 개발에 필요한 모든 활용 기술들을 학습할 수 있

www.inflearn.com

 

'스프링' 카테고리의 다른 글

로그인  (0) 2022.06.18
검증  (0) 2022.06.17
[스프링] 스프링 MVC  (0) 2022.06.09
[스프링] MVC 프레임워크  (0) 2022.06.09
[스프링] 서블릿, JSP, MVC 패턴  (0) 2022.06.09