✔️타임리프
웹 브라우저의 새로 고침은 마지막에 서버에 전송한 데이터를 다시 전송하게끔 한다.
상품 등록 폼에서 데이터를 입력하고 저장을 선택하면 POST /add
+ 상품 데이터를 서버로 전송한다. 이 상태에서 새로 고침을 하면 마지막에 전송한 POST /add
+ 상품 데이터를 서버로 다시 전송하게 된다. 그래서 내용은 같은데 ID만 다른 상품 데이터가 계속 저장되는 문제가 발생한다.
✔️POST, Redirect GET
웹 브라우저의 새로 고침은 마지막에 서버에 전송한 데이터를 다시 전송하게끔 한다. 새로 고침 문제를 해결하려면 상품 저장 후 뷰 템플릿으로 이동하는 것이 아니라 상품 상세 화면으로 리다이렉트를 호출해주면 된다. 웹 브라우저는 리다이렉트의 영향으로 상품 저장 후에 실제 상품 상세 화면으로 다시 이동한다. 따라서 마지막에 호출한 내용이 상품 상세 화면인 GET /items/{id}
가 되는 것이다.
이런 리다이렉트를 지원하는 속성으로 RedirectAttributes()
이 있다.
상품을 저장하고 상품 상세 화면으로 이동할 수 있도록 RedirectAttributes
를 사용한다.
@Controller
@RequestMapping("/basic/items")
public class BasicItemController {
private final ItemRepository itemRepository;
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";
}
// 상품 상세 조회
@GetMapping("/{itemId}")
public String item(@PathVariable(name = "itemId") Long itemId, Model model) {
Item item = itemRepository.findById(itemId);
model.addAttribute("item", item);
return "basic/item";
}
// 상품 추가 뷰
@GetMapping("/add")
public String addItem() {
return "basic/addForm";
}
// 실질적인 상품 추가가 되도록...
@PostMapping("/add")
public String save(@ModelAttribute(name = "item") Item item, RedirectAttributes redirectAttributes) {
Item savedItem = itemRepository.save(item);
redirectAttributes.addAttribute("itemId", savedItem.getId());
redirectAttributes.addAttribute("status", true);
return "redirect:/basic/items/{itemId}";
}
// 상품 수정 뷰
@GetMapping("/{itemId}/edit")
public String editForm(@PathVariable(name = "itemId") Long itemId, Model model) {
Item item = itemRepository.findById(itemId);
model.addAttribute("item", item);
return "basic/editForm";
}
// 실질적인 상품 수정이 되도록...
// HTML Form의 경우 PATCH를 지원하지 않기 때문에 @PostMapping을 사용
@PostMapping("/{itemId}/edit")
public String edit(@PathVariable(name = "itemId") Long itemId, @ModelAttribute(name = "item") Item item) {
itemRepository.update(itemId, item);
return "redirect:/basic/items/{itemId}";
}
@PostConstruct
public void init() {
itemRepository.save(new Item("itemA", 1000, 1));
itemRepository.save(new Item("itemA", 1000, 2));
}
}