본문 바로가기
Spring/스프링 MVC

[스프링 MVC 1편] 7 - (4) 상품 등록, 수정, Redirect

by Poorm 푸름 2023. 12. 4.

 *  스프링 입문 = window, 스프링 MVC 1편 = Mac 으로 진행합니다

 *  섹션7 부터는 자바 17 버전으로 진행합니다

 *  진도 : 섹션7 - (7) ~ (11)

 *          : 자바 클래스명,         : 코드,         : 단축키

 

 

1. 상품 등록

1) 컨트롤러 추가
[ java/hello/itemservice/web/basic/BasicItemController ]

@GetMapping("/add")
public String addForm(){
    return "basic/addForm";
}

@PostMapping ("/add")
public String save(@ModelAttribute("item") Item item){
    itemRepository.save(item);
    return "basic/item";
}

 

url 경로는 같으나 방식을 다르게 함으로서 Get 타입은 등록하는 창, Post 타입은 등록 완료

 

더보기

< 변경 과정 _ 포스트 6-(3) 참고 >

 

1단계_@RequestParam 사용

 @PostMapping("/add")
  public String addItemV1(@RequestParam String itemName,
                          @RequestParam int price,
                          @RequestParam Integer quantity,
                          Model model) {
      Item item = new Item();
      item.setItemName(itemName);
      item.setPrice(price);
      item.setQuantity(quantity);
      itemRepository.save(item);
      model.addAttribute("item", item);
      return "basic/item";
  }
  • 요청파라미터 조회 (request.getParameter()와 같은 기능)
  • model 객체 생성
  • item 객체 생성
  • itemRepository에 저장
  • 저장된 item을 모델에 담아서 뷰에 전달

 

2단계_@ModelAttribute 사용

@PostMapping("/add")
  public String addItemV2(@ModelAttribute("item") Item item, Model model) {
      itemRepository.save(item); 
      return "basic/item";
  }
  • @ModelAttribute
    • Item 객체 자동 생성 가능
    • model 객체 생성 / 모델에 item 넣어주는 model.addAtribute 기능 수행 가능

 

3단계_@ModelAttribute 사용

 @PostMapping("/add")
  public String addItemV3(Item item) {
      itemRepository.save(item);
      return "basic/item";
  }
  • @ModelAttribute("name")에서 이름 생략 가능
  • 클래스명(=Item)에 따라서 앞글자만 소문자로 바꿔(=item) 이름 자동으로 만들어준다 
  • @ModelAttribute 전체 생략 가능

 

 

2) 뷰 화면 타임리프로 만들기

 

- [resources/templates/basic/addForm]에서 타임리프 영역 수정하기 (강의 참고)

<form action="item.html" th:action method="post">

 

url이 같아서 th:action에 별도의 경로 추가 없이 진행하고 방식만 달리해서 전송한다

( = action에 값이 없으면 현재 URL에 데이터 전송 )

 

th:onclick="|location.href='@{/basic/items}'|"

 

취소를 누르면 원래 목록으로 돌아갈 수 있게 설정

 

 

2. 상품 수정


1) 컨트롤러 추가
[ java/hello/itemservice/web/basic/BasicItemController ]

@GetMapping("/{itemId}/edit")
    public String editForm(@PathVariable("itemId") Long itemId, Model model) {
        Item item = itemRepository.findById(itemId);
        model.addAttribute("item", item);
        return "basic/editForm";
    }

    @PostMapping ("/{itemId}/edit")
    public String edit(@PathVariable("itemId") Long itemId, @ModelAttribute Item item) {
        itemRepository.update(itemId, item);
        return "redirect:/basic/items/{itemId}";
    }

 

url 경로는 같으나 방식을 다르게 함으로서 Get 타입은 수정하는 창, Post 타입은 수정 완료 

상품 수정은 마지막에 뷰 템플릿을 호출하는 대신에 상품 상세 화면으로 이동하도록 리다이렉트를 호출한다
(@PathVariable 의 값은 redirect 에도 사용 가능)

 

 

2) 뷰 화면 타임리프로 만들기

 

- [resources/templates/basic/editForm]에서 타임리프 영역 수정하기 (강의 참고)

<form action="item.html" th:action method="post">

 

url이 같아서 th:action에 별도의 경로 추가 없이 진행하고 방식만 달리해서 전송한다

( = action에 값이 없으면 현재 URL에 데이터 전송 )

 

th:onclick="|location.href='@{/basic/items/{itemId}(itemId=${item.id})}'|"

 

취소를 누르면 이전 상품상세 페이지로 돌아갈 수 있게 설정

 

th:value="${item.id}"
th:value="${item.itemName}"
th:value="${item.price}"
th:value="${item.quantity}"
  • 모델에 있는 item 정보를 획득하고 프로퍼티 접근법으로 출력

 

 

3. Redirect를 사용하는 이유 (PRG)

 

< 동작과정 >

 

사용자가 상품 등록 버튼을 누른다 → 상품 등록화면을 보여준다 (Get)

사용자가 정보를 입력하고 상품 저장을 누른다 → 상품 데이터를 서버로 전송하고 저장된 화면(상품 상세)을 보여준다 (Post)

이때 새로고침 버튼을 누른다면 마지막에 전송한 데이터를 서버로 보내게 된다

즉 아이디만 다르고 같은 정보가 계속해서 저장된다

 

< 리다이렉트를 사용하면 >

 

사용자가 상품 등록 버튼을 누른다 → 상품 등록화면을 보여준다 (Get)

사용자가 정보를 입력하고 상품 저장을 누른다  리다이렉트로 URI 바꾼 다음 저장된 화면(상품 상세)을 보여준다 (Post)

이렇게 되면 마지막 데이터는 상품저장이 아닌 상품 상세가 되므로 새로고침 문제를 해결할 수 있다

 

1) 컨트롤러 수정
[ java/hello/itemservice/web/basic/BasicItemController ]

@PostMapping ("/add")
public String save(@ModelAttribute("item") Item item){
    itemRepository.save(item);
    return "redirect:/basic/items/" + item.getId();
}

 

 

 

4. RedirectAttributes

상품등록 할 때 저장완료라는 글을 출력하고 싶다 어떻게 해야할까

 

1) 컨트롤러 수정
[ java/hello/itemservice/web/basic/BasicItemController ]

@PostMapping("/add")
public String save(Item item, RedirectAttributes redirectAttributes) {
    Item savedItem = itemRepository.save(item);
    redirectAttributes.addAttribute("itemId", savedItem.getId());
    redirectAttributes.addAttribute("status", true);
    return "redirect:/basic/items/{itemId}";
}

반환값이 items이니까 찾아가보면 items 클래스에서 List<item> 사용 → item 클래스 찾아가기 → 해당 클래스 뷰 찾아가기 → basic/item.html에서 조건 코드 추가하기

 

 

2) 뷰 화면 수정하기

- [resources/templates/basic/item]에서 타임리프 영역 수정하기 (강의 참고)

 

<h2 th:if="${param.status}" th:text="저장완료"></h2>

 

파라미터값 조건이 참이면 출력하기

 

실행해보면 다음과 같은 리다이렉트 결과가 나온다

http://localhost:8080/basic/items/3?status=true