상품목록 컨트롤러 → 상품 목록 뷰 → 상품 등록 → 상품 저장 컨트롤러 → 상품 상세 뷰 ←상품상세 컨트롤러
[상품 도메인]
<1. item - 상품 객체>
@Data
@Getter @Setter
public class Item {
private Long id;
private String itemName;
private Integer price;
private Integer quantity;
public Item() {
}
public Item(String itemName, Integer price, Integer quantity) {
this.itemName = itemName;
this.price = price;
this.quantity = quantity;
}
}
<2. ItemRepository - 상품 저장소>
@Repository
public class ItemRepository {
private static final Map<Long, Item> store = new HashMap<>(); //static 사용
private static long sequence = 0L; //static 사용
public Item save(Item item) {
item.setId(++sequence);
store.put(item.getId(), item);
return item;
}
public Item findById(Long id) {
return store.get(id);
}
public List<Item> findAll() {
return new ArrayList<>(store.values()); //감싸서 넣으면 값을 넣어도 store에도 변함없음
}
public void update(Long itemId, Item updateParam) {
Item findItem = findById(itemId); //item 찾기
findItem.setItemName(updateParam.getItemName());
findItem.setPrice(updateParam.getPrice());
findItem.setQuantity(updateParam.getQuantity());
}
public void clearStore() {
store.clear(); //hashmap다 날려
}
}
<3. ItemRepositoryTest - 상품 저장소 테스트>
public class ItemRepositoryTest {
ItemRepository itemRepository = new ItemRepository();
@AfterEach
void afterEach() {
itemRepository.clearStore();
}
@Test
void save() {
//given
Item item = new Item("itemA", 10000, 10);
//when
Item savedItem = itemRepository.save(item);
//then
Item findItem = itemRepository.findById(item.getId());
assertThat(findItem).isEqualTo(savedItem);
}
@Test
void findAll() {
//given
Item item1 = new Item("item1", 10000, 10);
Item item2 = new Item("item2", 20000, 20);
itemRepository.save(item1);
itemRepository.save(item2);
//when
List<Item> result = itemRepository.findAll();
//then
assertThat(result.size()).isEqualTo(2);
assertThat(result).contains(item1, item2);
}
@Test
void updateItem() {
//given
Item item = new Item("item1", 10000, 10);
Item savedItem = itemRepository.save(item);
Long itemId = savedItem.getId();
//when
Item updateParam = new Item("item2", 20000, 30);
itemRepository.update(itemId, updateParam);
Item findItem = itemRepository.findById(itemId);
//then
assertThat(findItem.getItemName()).isEqualTo(updateParam.getItemName());
assertThat(findItem.getPrice()).isEqualTo(updateParam.getPrice());
assertThat(findItem.getQuantity()).isEqualTo(updateParam.getQuantity());
}
}
<4. BasicItemController>
@Controller
@RequestMapping("/basic/items")
@RequiredArgsConstructor //생성자 자동 생성
public class BasicItemController {
private final 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 Long itemId, Model model) {
Item item = itemRepository.findById(itemId);
model.addAttribute("item", item);
return "basic/item";
}
@GetMapping("/add")
public String addForm() {
return "basic/addForm";
}
//@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";
}
//@ModelAttribute 사용 - model객체 만들어 주고 model에 넣어주기까지
@PostMapping("/add")
public String addItemV2(@ModelAttribute("item") Item item, Model model) {
itemRepository.save(item);
//model.addAttribute("item", item); //자동 추가, 생략 가능
return "basic/item";
}
/**
* ModelAttribute name 생략 가능
* model.addAttribute(item); 자동 추가, 생략 가능
* 생략시 model에 저장되는 name은 클래스명 첫글자만 소문자로 등록 Item -> item
*/
//@PostMapping("/add")
public String addItemV3(@ModelAttribute Item item) {
itemRepository.save(item);
return "basic/item";
}
/**
* ModelAttribute 자체 생략 가능
* model.addAttribute(item) 자동 추가
*/
//@PostMapping("/add")
public String addItemV4(Item item) {
itemRepository.save(item);
return "basic/item";
}
/**
* PRG - Post/Redirect/Get
*/
//@PostMapping("/add")
public String addItemV5(Item item) {
itemRepository.save(item);
return "redirect:/basic/items/" + item.getId();
}
/**
* 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}";
}
@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 edit(@PathVariable Long itemId, @ModelAttribute Item item) {
itemRepository.update(itemId, item);
return "redirect:/basic/items/{itemId}";
}
/**
* 테스트용 데이터 추가
*/
@PostConstruct
public void init() {
itemRepository.save(new Item("testA", 10000, 10));
itemRepository.save(new Item("testB", 20000, 20));
}
}
[POST 등록 후 새로 고침]
상품 등록 폼에서 데이터를 입력하고 저장을 선택하면 POST /add + 상품 데이터를 서버로 전송한다. 이 상태에서 새로 고침을 또 선택하면 마지막에 전송한 POST /add + 상품 데이터를 서버로 다시 전송
그래서 POST, Redirect GET!
2.저장하고 리다이렉트를 하면 웹브라우저입장에서는 새로 요청하는 거. 그래서 상품 상세 다시요청해
여기서 다시 새로고침하면 상품 상세를 다시 요청하게됨
[RedirectAttributes] - 파라미터가있으면 저장됐다는거 보여주게끔
저장됐다는게 쿼리파라미터로 넘어가->뷰 템플릿 메시지 추가 resources/templates/basic/item.html
'Spring 강의 > springMVC' 카테고리의 다른 글
springMVC 활용 - (8) HTTP응답 (0) | 2022.05.12 |
---|---|
springMVC 활용 - (7) 스프링 기능 (0) | 2022.05.11 |
springMVC 활용 - (6) MVC프레임워크 구조 (0) | 2022.05.11 |
springMVC 활용 - (5) mvc 프레임워크 만들기 (0) | 2022.04.13 |
springMVC 활용 - (4) 회원관리 웹 애플리케이션 (0) | 2022.03.26 |