[Spring] 스프링 MVC 1편 7) 스프링 MVC 웹 페이지 만들기(2)
Session 7 스프링 MVC 웹 페이지 만들기
7. 상품 등록 폼
1) 속성 변경 th:action
th:action
상품 등록 폼의 URL과 실제 상품 등록 처리하는 URL을 똑같이 맞추고 HTTP 메서드로 두 기능 구분, 하나의 URL로 등록 폼과 등록 처리를 깔끔하게 처리 가능
상품 등록 폼 Get - /basic/items/add
상품 등록 처리 POST - /basic/items/add
8. 상품 등록 처리 - @ModelAttribute
1) @ModelAttribute
@ModelAttribute 이용해 한번에 처리
@PostMapping("/add")
public String addItemV2(@ModelAttribute("item") Item item, Model model) {
itemRepository.save(item);
//model.addAttribute("item", item); //자동 추가, 생략 가능
return "basic/item";
}
2) 요청 파라미터 처리
@ModelAttribute는 Item 객체를 생성하고 요청 파라미터 값을 프로퍼티 접근법으로 입력
3) Model 추가
모델에 @ModelAttribute로 지정한 객체를 자동으로 넣어줌
모델에 데이터를 담을 때 @ModelAttribute에 지정한 name 속성을 사용
4) @ModelAttribute 이름 생략
이름 생략하면 모델에 저장될 때 클래스명 사용
클래스의 첫 글자만 소문자로 변경해 등록 Item → item
5) @ModelAttribute 전체 생략
@PostMapping("/add")
public String addItemV4(Item item) {
itemRepository.save(item);
return "basic/item";
}
@ModelAttribute 자체도 생략 가능, 대상 객체는 모델에 자동 등록된다
9. 상품 수정
1) 리다이렉트
@PostMapping("/{itemId}/edit")
public String edit(@PathVariable Long itemId, @ModelAttribute Item item){
itemRepository.update(itemId, item);
return "redirect:/basic/items/{itemId}";
}
상품 수정 후 뷰 템플릿을 호출하는 대신 상세 화면으로 이동 → 리다이렉트 호출
10. PRG Post/Redirect/Get
1) 중복 등록
상품 등록을 완료하고 웹 브라우저의 새로고침 버튼을 클릭해 보면 중복 등록되는 버그가 있다.
웹 브라우저의 새로고침은 마지막에 서버에 전송한 데이터를 다시 전송
상품 등록 폼에서 데이터를 입력하고 저장을 선택하면 POST /add + 상품 데이터를 서버로 전송, 새로고침 하면 다시 전송
2) 중복 해결 PRG
상품 등록 후 뷰 템플릿으로 이동하는 것이 아니라 상품 상세 화면으로 리다이렉트 호출해 주면 된다.
새로 고침을 해도 상품 상세 화면으로 이동하게 되므로 새로 고침 문제를 해결할 수 있다.
이런 문제 해결 방식을 PRG라 한다.
@PostMapping("/add")
public String addItemV5(Item item) {
itemRepository.save(item);
return "redirect:/basic/items/" + item.getId();
}
item.getId()처럼 URL에 변수를 더해서 사용하는 것은 URL 인코딩이 안되기 때문에 위험 → redirectAttribute 사용
11. RedirectAttributes
1) RedirectAttribute
고객 입장에서는 상품 등록이 제대로 된것인지 애매함 → 저장되었습니다. 메시지 요구사항 추가
@PostMapping("/add")
public String addItemV6(Item item, RedirectAttributes redirectAttributes) {
Item savedItem = itemRepository.save(item);
redirectAttributes.addAttribute("itemId", savedItem.getId());
redirectAttributes.addAttribute("status", true);
return "redirect:/basic/items/{itemId}";
}
RedirectAttribute를 사용하면 URL 인코딩도 해주고 pathVariable, 쿼리 파라미터까지 처리해 준다.
pathVariable 바인딩 : {itemId}
나머지 쿼리 파라미터 처리 : ?status= rue
리다이렉트 할 때 status = true 추가
뷰 템플릿에서 이 값이 있으면 저장되었습니다 메시지 출력
<h2 th:if="${param.status}"th:text="'저장 완료!'"></h2>
th:if 해당 조건이 참이면 실행
${param.atatus} : 타임리프에서 쿼리 파라미터를 편리하게 조회하는 기능, 컨트롤러 모델에 직접 담고 값을 꺼내야 하지만 쿼리 파라미터는 자주 사용해서 타임리프에서 직접 지원
으아아 피곤하다 mvc도 완강...⭐️