피할 수 없다면 즐기자! 스프링부트 너.. 뭐 돼?
<!DOCTYPE html>
<!--
html 파일에 타임리프를 사용하기 위해선 아래와 같은 선언이 필요하다.
<html xmlns:th="http://www.thymeleaf.org">
-->
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<ul>
<li>상품관리
<ul>
<li>
<a href="/basic/items">상품관리</a>
</li>
</ul>
</li>
</ul>
</body>
</html>
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8">
<link href="./css/bootstrap.min.css"
th: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>
<!-- /basic/items/아이템의ID -->
<a href="item.html"
th:href="@{/basic/items/{itemId}(itemId=${item.id})}"
th:text="${item.id}">1</a>
</td>
<td>
<!-- /basic/items/아이템의ID -->
<a href="item.html"
th:href="@{|/basic/items/${item.id}|}"
th:text="${item.itemName}">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>
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8">
<link href="./css/bootstrap.min.css"
th:href="@{/css/bootstrap.min.css}"
rel="stylesheet">
<style>
.container {
max-width: 560px;
}
</style>
</head>
<body>
<div class="container">
<div class="py-5 text-center">
<h2>상품 상세</h2>
</div>
<!-- 추가 -->
<h2 th:if="${param.status}" th:text="'저장완료!'"></h2>
<div>
<label for="itemId">상품 ID</label>
<input type="text" id="itemId" name="itemId" class="form-control" th:value="${item.id}" value="1" readonly>
</div>
<div>
<label for="itemName">상품명</label>
<input type="text" id="itemName" name="itemName" class="form-control" th:value="${item.itemName}" value="상품A" readonly>
</div>
<div>
<label for="price">가격</label>
<input type="text" id="price" name="price" class="form-control" th:value="${item.price}" value="10000" readonly>
</div>
<div>
<label for="quantity">수량</label>
<input type="text" id="quantity" name="quantity" class="form-control" th:value="${item.quantity}" value="10" readonly>
</div>
<hr class="my-4">
<div>판매 여부</div>
<div>
<div class="form-check">
<input type="checkbox" id="open" th:field="${item.open}"
class="form-check-input" disabled/>
<label for="open" class="form-check-label">판매 오픈</label>
</div>
</div>
<!-- multi checkbox -->
<div>
<div>등록 지역</div>
<div th:each="region : ${regions}" class="form-check form-check-inline">
<input type="checkbox" th:field="${item.regions}" th:value="${region.key}" class="form-check-input" disabled />
<label th:for="${#ids.prev('regions')}" class="form-check-label" th:text="${region.value}">서울</label>
</div>
</div>
<!-- radio button -->
<div>
<div>상품 종류</div>
<div th:each="type : ${itemType}" class="form-check form-check-inline">
<input type="radio" th:field="${item.itemType}" th:value="${type.name()}" class="form-check-input" disabled/>
<label class="form-check-label" th:for="${#ids.prev('itemType')}" th:text="${type.description}"></label>
</div>
</div>
<!-- select box -->
<div>
<div>배송방식</div>
<select class="form-select" th:field="${item.deliveryCode}" disabled>
<option value="">=== 배송 방식 선택 ===</option>
<option th:each="deliveryCode : ${deliveryCodes}"
th:value="${deliveryCode.code}" th:text="${deliveryCode.displayName}">
</option>
</select>
</div>
<hr class="my-4">
<div class="row">
<div class="col">
<!-- /basic/items/아이템Id/edit -->
<button class="w-100 btn btn-primary btn-lg"
onclick="location.href='editForm.html'"
th:onclick="|location.href='@{/basic/items/{itemId}/edit(itemId=${item.id})}'|"
type="button">
상품수정
</button>
</div>
<div class="col">
<button class="w-100 btn btn-secondary btn-lg"
onclick="location.href='items.html'"
th:onclick="|location.href='@{/basic/items}'|"
type="button">
목록으로
</button>
</div>
</div>
</div>
<!-- /container -->
<script th:inline="javascript">
if([[${param.status}]]){
alert("저장완료!");
}
</script>
</body>
</html>
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8">
<link href="./css/bootstrap.min.css"
th:href="@{/css/bootstrap.min.css}"
rel="stylesheet">
<style>
.container {
max-width: 560px;
}
.field-error {
border-color: #dc3545;
color: #dc3545;
}
</style>
</head>
<body>
<div class="container">
<div class="py-5 text-center">
<h2>상품 등록 폼</h2>
</div>
<h4 class="mb-3">상품 입력</h4>
<!-- 같은 url에 전송하고 방법만 달라지는 경우는 url을 생략해도 된다. -->
<form action="item.html" th:object="${item}" th:action method="post">
<div>
<!--
- 타임리프는 스프링의 BindingResult를 활용해서 편리한 오류 표현기능 제공
- field : BindingResult가 제공하는 오류에 접근 할 수 있다.
- th:errorclass : th:field에서 지정한 필드에 오류가 있으면 class를 추가
- th:errors : 해당 필드에 오류가 있는 경우에 태그를 출력한다. th:if의 편의 기능
-->
<label for="itemName">상품명</label>
<!-- th:field를 사용하면 id 와 name, value을 생략할 수 있다. 그러나 label로 묶여있는 경우에는 id속성을 남겨놔야한다. -->
<!-- <input type="text" id="itemName" name="itemName" th:field="${item.itemName}" class="form-control" placeholder="이름을 입력하세요"> -->
<input type="text" id="itemName" th:field="*{itemName}" th:errorclass="field-error" class="form-control" placeholder="이름을 입력하세요">
<div class="field-error" th:errors="*{itemName}">상품명 오류</div>
</div>
<div>
<label for="price">가격</label>
<input type="text" id="price" th:field="*{price}" th:errorclass="field-error" class="form-control" placeholder="가격을 입력하세요">
<div class="field-error" th:errors="*{price}">상품 가격 오류</div>
</div>
<div>
<label for="quantity">수량</label>
<input type="text" id="quantity" th:field="*{quantity}" th:errorclass="field-error" class="form-control" placeholder="수량을 입력하세요">
<div class="field-error" th:errors="*{quantity}">상품 수량 오류</div>
</div>
<hr class="my-4">
<!-- checkbox, thymeleaf -->
<!--
[체크박스]
- 체크박스 체크여부
open=on&_open=on
-> open에 값이 있는 것을 확인하고 사용
-> true 결과값을 출력
-> _open을 무시
_open=on
-> 체크박스를 체크하지 않으면 Spring이 _open만 있는 것을 확인하고 open의 값이 체크되지 않았다고 인식.
-> 이 경우 서버에서 null이 아니라 false인 것을 확인 할 수 있다.
-->
<div>판매 여부</div>
<div>
<div class="form-check">
<input type="checkbox" id="open" th:field="*{open}" class="form-check-input"/>
<label for="open" class="form-check-label">판매 오픈</label>
</div>
</div>
<!-- multi checkbox -->
<div>
<div>등록 지역</div>
<div th:each="region : ${regions}" class="form-check form-check-inline">
<input type="checkbox" th:field="*{regions}" th:value="${region.key}" class="form-check-input" />
<label th:for="${#ids.prev('regions')}" class="form-check-label" th:text="${region.value}">서울</label>
</div>
</div>
<!-- radio button -->
<div>
<div>상품 종류</div>
<div th:each="type : ${itemType}" class="form-check form-check-inline">
<input type="radio" th:field="*{itemType}" th:value="${type.name()}" class="form-check-input" />
<label class="form-check-label" th:for="${#ids.prev('itemType')}" th:text="${type.description}"></label>
</div>
</div>
<!-- select box -->
<div>
<div>배송방식</div>
<select class="form-select" th:field="*{deliveryCode}">
<option value="">=== 배송 방식 선택 ===</option>
<option th:each="deliveryCode : ${deliveryCodes}"
th:value="${deliveryCode.code}" th:text="${deliveryCode.displayName}">
</option>
</select>
</div>
<hr class="my-4">
<div class="row">
<div class="col">
<button class="w-100 btn btn-primary btn-lg" type="submit">
상품등록
</button>
</div>
<div class="col">
<button class="w-100 btn btn-secondary btn-lg"
onclick="location.href='items.html'"
th:onclick="|location.href='@{/basic/items}'|"
type="button">
취소
</button>
</div>
</div>
</form>
</div>
<!-- /container -->
</body>
</html>
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8">
<link href="./css/bootstrap.min.css"
th:href="@{/css/bootstrap.min.css}"
rel="stylesheet">
<style>
.container {
max-width: 560px;
}
</style>
</head>
<body>
<div class="container">
<div class="py-5 text-center">
<h2>상품 수정 폼</h2>
</div>
<form action="item.html" th:object="${item}" th:action method="post">
<div>
<label for="id">상품 ID</label>
<input type="text" id="id" th:field="*{id}" class="form-control" value="1" th:value="${item.id}" readonly>
</div>
<div>
<label for="itemName">상품명</label>
<input type="text" id="itemName" th:field="*{itemName}" class="form-control" value="상품A" th:value="${item.itemName}">
</div>
<div>
<label for="price">가격</label>
<input type="text" id="price" th:field="*{price}" class="form-control" value="10000" th:value="${item.price}">
</div>
<div>
<label for="quantity">수량</label>
<input type="text" id="quantity" th:field="*{quantity}" class="form-control" value="10" th:value="${item.quantity}">
</div>
<hr class="my-4">
<div>판매 여부</div>
<div>
<div class="form-check">
<input type="checkbox" id="open" th:field="*{open}" class="form-check-input"/>
<label for="open" class="form-check-label">판매 오픈</label>
</div>
</div>
<!-- multi checkbox -->
<div>
<div>등록 지역</div>
<div th:each="region : ${regions}" class="form-check form-check-inline">
<input type="checkbox" th:field="*{regions}" th:value="${region.key}" class="form-check-input" />
<label th:for="${#ids.prev('regions')}" class="form-check-label" th:text="${region.value}">서울</label>
</div>
</div>
<!-- radio button -->
<div>
<div>상품 종류</div>
<div th:each="type : ${itemType}" class="form-check form-check-inline">
<input type="radio" th:field="*{itemType}" th:value="${type.name()}" class="form-check-input" />
<label class="form-check-label" th:for="${#ids.prev('itemType')}" th:text="${type.description}"></label>
</div>
</div>
<!-- select box -->
<div>
<div>배송방식</div>
<select class="form-select" th:field="*{deliveryCode}">
<option value="">=== 배송 방식 선택 ===</option>
<option th:each="deliveryCode : ${deliveryCodes}"
th:value="${deliveryCode.code}" th:text="${deliveryCode.displayName}">
</option>
</select>
</div>
<hr class="my-4">
<div class="row">
<div class="col">
<button class="w-100 btn btn-primary btn-lg" type="submit">
저장
</button>
</div>
<div class="col">
<button class="w-100 btn btn-secondary btn-lg"
onclick="location.href='item.html'"
th:onclick="|location.href='@{/basic/items/{itemId}(itemId=${item.id})}'|"
type="button">
취소
</button>
</div>
</div>
</form>
</div>
<!-- /container -->
</body>
</html>
package com.koreait.item.domain.controller;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.StringUtils;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import com.koreait.item.domain.item.DeliveryCode;
import com.koreait.item.domain.item.Item;
import com.koreait.item.domain.item.ItemRepository;
import com.koreait.item.domain.item.ItemType;
import lombok.RequiredArgsConstructor;
@Controller
@RequestMapping("/basic/items")
@RequiredArgsConstructor
// @RequiredArgsConstructor :
// final 이 붙은 멤버변수만 사용해서 생성자를 자동으로 만들어준다.
public class ItemController {
private final ItemRepository itemRepository;
// @Autowired
// 생성자가 1개만 있으면 @Autowired 생략가능
// public ItemController(ItemRepository itemRepository) {
// this.itemRepository = itemRepository;
// }
// @ModelAttribute :
// Controller를 호출할 때(어떤 메서드가 호출이 되던간에)
// model에 자동으로 해당 내용이 담기는게 보장된다.
@ModelAttribute("regions")
public Map<String, String> regions(){
// LinkedHashMap : 순서가 보장되는 hashmap
Map<String, String> regions = new LinkedHashMap<String, String>();
regions.put("SEOUL", "서울");
regions.put("BUSAN", "부산");
regions.put("JEJU", "제주");
// model.addAttribute("regions", regions);
return regions;
}
@ModelAttribute("itemType")
public ItemType[] itemTypes() {
// enum에 있는 값을 배열로 넘겨준다.
return ItemType.values();
}
@ModelAttribute("deliveryCodes")
public List<DeliveryCode> deliveryCodes(){
List<DeliveryCode> deliveryCodes = new ArrayList<DeliveryCode>();
deliveryCodes.add(new DeliveryCode("FAST", "빠른배송"));
deliveryCodes.add(new DeliveryCode("NORMAL", "일반배송"));
deliveryCodes.add(new DeliveryCode("SLOW", "느린배송"));
return deliveryCodes;
}
@GetMapping
public String items(Model model) {
List<Item> items = itemRepository.findAll();
model.addAttribute("items", items);
return "basic/items";
}
// /basic/items/아이템Id
@GetMapping("/{itemId}")
public String item(@PathVariable long itemId, Model model) {
Item item = itemRepository.findById(itemId);
model.addAttribute(item);
return "basic/item";
}
// /basic/items/아이템Id
@GetMapping("/add")
public String addItem(Model model) {
model.addAttribute("item", new Item());
return "basic/addForm";
}
// @PostMapping("/add")
public String save(@RequestParam String itemName,
@RequestParam int price,
@RequestParam Integer quantity,
Model model) {
Item item = new Item();
item.setItemName(itemName);
item.setPrice(quantity);
item.setQuantity(quantity);
itemRepository.save(item);
model.addAttribute("item", item);
return "basic/item";
}
// @PostMapping("/add")
public String saveV2(@ModelAttribute("item") Item item) {
//@ModelAttribute가 해주는 역할
// Item item = new Item();
// item.setItemName(itemName);
// item.setPrice(quantity);
// item.setQuantity(quantity);
itemRepository.save(item);
// model.addAttribute("item", item);
return "basic/item";
}
/*
* @ModelAttribute 에서 name 생략
* -> 생략시 model에 저장되는 name은 클래스명 첫 글자만 소문자로 등록
* Item -> item
*/
// @PostMapping("/add")
public String saveV3(@ModelAttribute Item item) {
itemRepository.save(item);
return "basic/item";
}
// @PostMapping("/add")
public String saveV4(Item item) {
itemRepository.save(item);
return "basic/item";
}
// @PostMapping("/add")
public String saveV5(Item item) {
itemRepository.save(item);
return "redirect:/basic/items/"+ item.getId();
}
/*
* redirect:/basic/items/{itemId}
* -> @PathVariable : {itemId}
* -> 나머지는 파라미터로 처리 : ?status=true
*
* */
// @PostMapping("/add")
public String saveV6(Item item, RedirectAttributes redirectAttributes) {
System.out.println("item.open = " + item.getOpen());
System.out.println("item.regions = " + item.getRegions());
System.out.println("item.itemType = " + item.getItemType());
System.out.println("item.deliveryCode = " + item.getDeliveryCode());
Item saveItem = itemRepository.save(item);
redirectAttributes.addAttribute("itemId", saveItem.getId());
redirectAttributes.addAttribute("status", true);
return "redirect:/basic/items/{itemId}";
}
/*
* BindingResult :
* - Item 객체에 값이 잘 담기지 않을 때 BindingResult 객체에 값이 담긴다.
* - 스프링이 제공하는 검증 오류를 보관하는 객체, 검증 오류가 발생하면 여기에 보관
* - 주의) BindingResult는 검증할 대상 바로 다음에 와야한다. 순서가 중요하다.
* - BindingResult는 Model에 자동으로 포함된다.
*/
// @PostMapping("/add")
public String saveV7(Item item, BindingResult bindingResult, RedirectAttributes redirectAttributes) {
// FieldError : field단위의 error를 처리하는 spring에서 제공해주는 객체
// new FieldError(객체, 에러 발생시 에러메시지를 가져갈 대상, 뱉어낼 에러 메시지)
// StringUtils.hasText(item.getItemName()
// - 값이 있을 경우에는 true, 공백이나 null 들어올 경우에는 false를 반환하게 된다.
if(!StringUtils.hasText(item.getItemName())) {
bindingResult.addError(new FieldError("item", "itemName", "상품이름은 필수입니다!"));
}
/*
* price
* - 조건 : null, 1000원 미만 x, 1000000 초과 x
*
* quantity
* - 조건 : null, 최대 9999 까지만 허용
*/
if(item.getPrice() == null) {
bindingResult.addError(new FieldError("item", "price", "상품 금액은 필수입니다!"));
}else if(item.getPrice() < 1000 || item.getPrice() > 1000000) {
bindingResult.addError(new FieldError("item", "price", "상품 금액은 1000원 이상 100000 미만입니다."));
}
if(item.getQuantity() == null) {
bindingResult.addError(new FieldError("item", "quantity", "상품의 수량은 필수입니다!"));
}else if(item.getQuantity() > 10000) {
bindingResult.addError(new FieldError("item", "quantity", "상품의 수량은 9999개 이하 입니다."));
}
// 검증에 실패하면 다시 입력 폼으로
if(bindingResult.hasErrors()) {
// System.out.println("errors = " + bindingResult);
return "basic/addForm";
}
Item saveItem = itemRepository.save(item);
redirectAttributes.addAttribute("itemId", saveItem.getId());
redirectAttributes.addAttribute("status", true);
return "redirect:/basic/items/{itemId}";
}
// @PostMapping("/add")
public String saveV8(Item item, BindingResult bindingResult, RedirectAttributes redirectAttributes) {
/*
* FieldError param
* - objectName : 오류가 발생한 객체 이름
* - field : 오류 필드
* - rejectedValue : 사용자가 입력한 값(거절된 값)
* - bindingFailure: 타입오류와 같은 바인딩 실패인지를 구분
* - codes : 메시지 코드
* - arguments : 메시지에서 사용하는 인자
* - defaultMessage: 기본 오류 메시지
*/
if(!StringUtils.hasText(item.getItemName())) {
bindingResult.addError(new FieldError("item", "itemName", item.getItemName(), false, null, null, "상품 이름은 필수입니다."));
}
if(item.getPrice() == null || item.getPrice() < 1000 || item.getPrice() > 1000000) {
bindingResult.addError(new FieldError("item", "price", item.getPrice(), false, null, null, "상품 금액은 1000원 이상 100000 미만입니다."));
}
if(item.getQuantity() == null || item.getQuantity() > 10000) {
bindingResult.addError(new FieldError("item", "quantity", item.getQuantity(), false, null, null, "상품의 수량은 9999개 이하 입니다."));
}
if(bindingResult.hasErrors()) {
return "basic/addForm";
}
Item saveItem = itemRepository.save(item);
redirectAttributes.addAttribute("itemId", saveItem.getId());
redirectAttributes.addAttribute("status", true);
return "redirect:/basic/items/{itemId}";
}
@PostMapping("/add")
public String saveV9(Item item, BindingResult bindingResult, RedirectAttributes redirectAttributes) {
if(!StringUtils.hasText(item.getItemName())) {
bindingResult.addError(new FieldError("item", "itemName", item.getItemName(), false,
new String[] {"required.item.itemName", "required.default"}, null, null));
}
if(item.getPrice() == null || item.getPrice() < 1000 || item.getPrice() > 1000000) {
bindingResult.addError(new FieldError("item", "price", item.getPrice(), false,
new String[] {"range.item.price"}, new Object[] {1000, 10000}, null));
}
if(item.getQuantity() == null || item.getQuantity() > 10000) {
bindingResult.addError(new FieldError("item", "quantity", item.getQuantity(), false,
new String[] {"max.item.quantity"}, new Object[] {9999}, null));
}
if(bindingResult.hasErrors()) {
return "basic/addForm";
}
Item saveItem = itemRepository.save(item);
redirectAttributes.addAttribute("itemId", saveItem.getId());
redirectAttributes.addAttribute("status", true);
return "redirect:/basic/items/{itemId}";
}
@GetMapping("/{itemId}/edit")
public String editForm(@PathVariable Long itemId, Model model) {
Item item = itemRepository.findById(itemId);
model.addAttribute("item", item);
return "basic/editForm";
}
@PostMapping("/{itemId}/edit")
public String update(@PathVariable Long itemId, @ModelAttribute Item item) {
itemRepository.update(itemId, item);
// 상세페이지
return "redirect:/basic/items/{itemId}";
}
// 테스트용 데이터 추가
@PostConstruct
public void init() {
// System.out.println("초기화 메서드");
itemRepository.save(new Item("testA", 10000, 10));
itemRepository.save(new Item("testB", 20000, 20));
}
// 종료 메서드
@PreDestroy
public void destroy() {
System.out.println("종료 메서드");
}
}
package com.koreait.item.domain.item;
import java.util.List;
import lombok.Getter;
import lombok.Setter;
@Getter @Setter
public class Item {
private Long id;
private String itemName;
private Integer price;
private Integer quantity;
private Boolean open; // 판매 여부
private List<String> regions; // 등록 지역
private ItemType itemType; // 상품 종류
private String deliveryCode; // 배송 방식
public Item() {
}
public Item(String itemName, Integer price, Integer quantity) {
super();
this.itemName = itemName;
this.price = price;
this.quantity = quantity;
}
}
package com.koreait.item.domain.item;
import lombok.AllArgsConstructor;
import lombok.Data;
@Data
@AllArgsConstructor
public class DeliveryCode {
private String code;
private String displayName;
}
상품 타입을 정리한 java 파일로 enum으로 작성하였다.
package com.koreait.item.domain.item;
public enum ItemType {
BOOK("도서"), FOOD("식품"), ETC("기타");
final private String description;
private ItemType(String description) {
this.description = description;
}
public String getDescription() {
return description;
}
}
메소드 정의 파일
package com.koreait.item.domain.item;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.stereotype.Repository;
@Repository
public class ItemRepository {
// static 사용
private static final Map<Long, Item> store = new HashMap<Long, Item>();
private static long sequence = 0L;
// 저장
public Item save(Item item) {
item.setId(++sequence);
store.put(item.getId(), item);
return item;
}
// id로 찾기
public Item findById(Long Id) {
return store.get(Id);
}
// 전체 찾기
public List<Item> findAll(){
return new ArrayList<Item>(store.values());
}
// 수정
public void update(Long itemId, Item updateParam) {
// item을 먼저 찾는다
Item findItem = findById(itemId);
findItem.setItemName(updateParam.getItemName());
findItem.setPrice(updateParam.getPrice());
findItem.setQuantity(updateParam.getQuantity());
findItem.setOpen(updateParam.getOpen()); // 판매 여부
findItem.setRegions(updateParam.getRegions()); // 배송 지역
findItem.setItemType(updateParam.getItemType()); // 상품 품목
findItem.setDeliveryCode(updateParam.getDeliveryCode()); // 배송 방법
}
}
@GetMapping("/member/{name}")
public String memberFind(@PathVariable("name") String name){
}
@GetMapping("/member/{name}")
public String memberFind(@PathVariable String name){
}
// 여러개
@GetMapping("/member/{id}/{name}")
public String memberFind(@PathVariable("id") String id, @PathVariable("name") String name){
}
@GetMapping("/member/{id}/{name}")
public String memberFind(String id, String name){
}
출처
https://media.giphy.com/media/kyUIknbbDNvID5XzU4/giphy.gif
https://media.giphy.com/media/A6aHBCFqlE0Rq/giphy.gif