BackEnd/spring

간단한 Web페이지 프로젝트(2)-상품 목록(타임리프)

연향동큰손 2024. 7. 5. 14:46

<BasicItemController>

package hello.itemservice.web.basic;

import hello.itemservice.domain.item.Item;
import hello.itemservice.domain.item.ItemRepository;
import jakarta.annotation.PostConstruct;
import lombok.RequiredArgsConstructor;
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.RequestMapping;

import java.util.List;

@Controller
@RequestMapping("/basic/items")
@RequiredArgsConstructor
public class BasicItemController {

    private final ItemRepository itemRepository;

//    //@Autowired 생성자가 하나 이므로 생략
//    public BasicItemController(ItemRepository itemRepository) {
//        this.itemRepository = itemRepository;
//    }
    @GetMapping
    public String items(Model model){
        List<Item> items = itemRepository.findAll();
        model.addAttribute("items",items);
        return "basic/items";
    }

    @PostConstruct
    public void init(){
        itemRepository.save(new Item("itemA",10000,10));
        itemRepository.save(new Item("itemB",20000,20));
    }
}

 

컨트롤러는 itemRepository에서 모든 상품을 조회한 다음에 모델에 담는다. 

그 후 뷰 템플릿을 호출한다.

 

@PostContruct란?

의존성 주입이 완료된 후에 실행되어야 하는 method에 사용

이 클래스에서는 테스트 용 데이터를 추가하는 목적으로 사용

 

@RequiredArgsConstructor란?

final이 붙은 멤버변수만 사용해서 생성자를 자동으로 만들어준다.

 

** 생성자가 딱 1개만 있으면 스프링이 해당 생성자에 @Autowired로 의존관계를 주입해준다. 이 때문에 final 키워드를 빼면 안된다.

 

 

items.html을 뷰 템플릿 영역으로 복사하고 수정

<!DOCTYPE HTML>
<html  xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="utf-8">
    <link  th:href="@{/css/bootstrap.min.css}"
            href="../css/bootstrap.min.css" rel="stylesheet">

</head>
<body>

<div class="container" style="max-width: 600px">
    <div class="py-5 text-center">
        <h2>상품 목록</h2>
    </div>
    <div class="row">
        <div class="col">
            <button class="btn btn-primary float-end"
                    onclick="location.href='addForm.html'"
                    th:onclick="|location.href='@{/basic/items/add}'|"
                    type="button">상품 등록
            </button>
        </div>
    </div>
    <hr class="my-4">
    <div>
        <table class="table">
            <thead>
            <tr>
                <th>ID</th>
                <th>상품명</th>
                <th>가격</th>
                <th>수량</th>
            </tr>
            </thead>
            <tbody>
            <tr th:each = "item : ${items}">
                <td><a href="item.html" th:href="@{/basic/items/{itemId}(itemId=${item.id})}" th:text="${item.id}">회원id</a></td>
                <td><a href="item.html" th:href="@{|/basic/items/${item.id}|}" th:text="${item.itemName}">상품명</a></td>
                <td th:text="${item.price}">10000</td>
                <td th:text="${item.quantity}">10</td>
            </tr>
            </tbody>
        </table>
    </div>
</div> <!-- /container -->
</body>
</html>

 

 

타임리프 사용 선언

<html  xmlns:th="http://www.thymeleaf.org">

 

 

타임리프 뷰 템플릿을 거치게 되면 원래 값을 th:xxx 값으로 변경한다. 만약 값이 없다면 새로 생성한다.

**** th:xxx 가 붙은 부분은 서버사이드에서 랜더링 되고, 기존 것을 대체한다.

단. HTML을 파일로 직접 열었을 때, th:xxx가 있어도 웹 브라우저는 th:속성을 알지 못하므로 무시한다.

 

<link  th:href="@{/css/bootstrap.min.css}"
        href="../css/bootstrap.min.css" rel="stylesheet">

 

 

 

 

타임리프의 URL 링크 표현식 --> @{...}

th:href="@{/css/bootstrap.min.css}"

 

 

리터럴 대체 ==> |...|

 

 

반복 출력 ==> th:each

<tr th:each = "item : ${items}">
    <td><a href="item.html" th:href="@{/basic/items/{itemId}(itemId=${item.id})}" th:text="${item.id}">회원id</a></td>
    <td><a href="item.html" th:href="@{|/basic/items/${item.id}|}" th:text="${item.itemName}">상품명</a></td>
    <td th:text="${item.price}">10000</td>
    <td th:text="${item.quantity}">10</td>
</tr>

 

th: each문을 통해 모델에 포함된 item 컬렉션 데이터가 item 변수에 하나씩 포함되고, 반복문 안에서 item 변수를 사용할 수 있다.

 

 

 

 

변수 표현식 ==> ${...}

<td th:text="${item.price}">10000</td>

모델에 포함된 값이나 타임리프 변수로 선언한 값을 조회할 수 있다.

 

 

 

내용 변경 ==> th:text

<td th:text="${item.price}">10000</td>

내용의 값을 th:text 의 값으로 변경한다.

여기서는 10000을 ${item.price} 의 값으로 변경한다.