상품등록과 같은 POST 요청을 보내고 나서 Redirect 처리를 안해주면 새로고침 시 POST 요청이 또 나갈 수 있다.
왜냐하면 새로고침은 마지막 요청을 다시 보내기 때문이다.
이 문제를 어떻게 해결할까?
상품 저장 후에 뷰 템플릿으로 이동하는 것이 아니라, 상품 상세 화면으로 리다이렉트를 호출해주면 된다.
@PostMapping("/add")
public String addItemV5(Item item) {
itemRepository.save(item);
return "redirect:/basic/items/" + item.getId();
}
이렇게, POST 요청 후에 Redirect로 GET 요청을 보내는 것이 PRG 패턴이다.
하지만 위 코드에서도 문제가 있다.
URL을 인코딩 하지 않고 사용하는것은 위험할 수 있다.
그래서 RedirectAttributes를 사용해야 한다.
RedirectAttributes
코드를 먼저 보겠다.
@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}";
}
컨트롤러에서 RedirectAttributes redirectAttributes 로 매개변수를 받아온다.
redirectAttributes.addAttribute("itemId", savedItem.getId()); 는 PathVariable을 지정할 수 있고
redirectAttributes.addAttribute("status", true); 이것과 같이 값을 지정하지 않은 것들은 쿼리파라미터로 넘어가게된다. (ex. /basic/items/1?status=true)
추가로 URL 인코딩까지 자동으로 해준다.
추가 요구사항
상품등록이 성공했으면 "저장되었습니다"라는 메세지를 보여달라는 요구사항이 추가되었다.
사실 위에서 status를 true로 쿼리파라미터로 보낸 이유가 있다.
RedirectAttributes와 타임리프의 param을 이용해서 해결할 수 있다.
<h2 th:if="${param.status}" th:text="'저장 완료'"></h2>
타임리프에서는 RedirectAttributes의 쿼리파라미터를 param으로 그냥 읽어낼 수 있다.
그래서 th:if="${param.status}" 는 th:if=true 와 같고, true 이므로 th:text="'저장 완료'" 가 실행된다.
'Web > MVC' 카테고리의 다른 글
[Servlet 구현하기] Controller Scanner와 JSON View (3) | 2022.09.29 |
---|---|
[Servlet 구현하기] 어노테이션 기반 MVC 프레임워크 구현 (5) | 2022.09.19 |
EP8. Thymeleaf 타임리프 (0) | 2021.04.01 |
EP7. HTTP 응답 데이터 처리 (0) | 2021.03.30 |
EP6. HTTP 요청 데이터 처리 (0) | 2021.03.29 |