@Controller@RequiredArgsConstructor@RequestMapping("/basic/items")publicclassBasicItemController {privatefinalItemRepository itemRepository;/* 생성자 주입으로 빈을 가져온다. 생성자가 하나만 있으면 @Autowired를 생략할 수 있다. 여기서 롬복 @RequiredArgsConstructor까지 쓰면 코드 모두 생략 가능하다. @Autowired public BasicItemController(ItemRepository itemRepository) { this.itemRepository = itemRepository; } */ @GetMappingpublicStringitems(Model model) {List<Item> items =itemRepository.findAll();model.addAttribute("items", items);return"basic/items"; }// 테스트용 데이터 추가 @PostConstructpublicvoidinit() {itemRepository.save(newItem("itemA",10000,10));itemRepository.save(newItem("itemB",20000,20)); }}
@RepositorypublicclassItemRepository {// 실무에서는 멀티 스레드이기 때문에 HashMap 대신 ConcurrentHashMap을 써야 한다.privatestaticfinalMap<Long,Item> store =newHashMap<>();publicstaticlong sequence =0L;publicItemsave(Item item) {item.setId(++sequence);store.put(item.getId(), item);return item; }publicItemfindById(Long id) {returnstore.get(id); }publicList<Item> findAll() {// 컬렉션으로 한 번 감싸서 반환하면 store 자체 값에는 영향을 미치지 않는다.returnnewArrayList<>(store.values()); }// 정석대로라면 프로퍼티에 id를 제외한 즉, 필요한 파라미터만 있는 객체를 따로 사용하는 게 좋다. // 안쓰는 프로퍼티가 있으면 개발자가 헷갈릴 수 있기 때문이다.publicvoidupdate(Long itemId,Item updateParam) {Item findItem =findById(itemId);findItem.setItemName(updateParam.getItemName());findItem.setPrice(updateParam.getPrice());findItem.setQuantity(updateParam.getQuantity()); }publicvoidclearStore() {store.clear(); }}
상품 등록 처리
addItemV1
@Controller@RequiredArgsConstructor@RequestMapping("/basic/items")publicclassBasicItemController {privatefinalItemRepository itemRepository;... @PostMapping("/add")publicStringaddItemV1(@RequestParamString itemName, @RequestParamint price, @RequestParamInteger quantity,Model model) {Item item =newItem();item.setItemName(itemName);item.setPrice(price);item.setQuantity(quantity);itemRepository.save(item);// 새로 저장한 아이템에 대한 새 페이지를 만드는 대신, 템플릿에 값을 넘긴다.model.addAttribute(item);return"basic/item"; }...}
요청 파라미터 데이터를 하나하나 변수로 받는다.
ItemRepository에 저장한 뒤 item을 모델에 담아 뷰에 전달한다.
addItemV2
@Controller@RequiredArgsConstructor@RequestMapping("/basic/items")publicclassBasicItemController {privatefinalItemRepository itemRepository;... @PostMapping("/add")publicStringaddItemV2(@ModelAttribute("item") Item item,Model model) {/* modelAttribute가 item을 V1이랑 똑같이 만들어준다. Item item = new Item(); item.setItemName(itemName); item.setPrice(price); item.setQuantity(quantity); */itemRepository.save(item);/* @ModelAttribute("item")에 지정한 item 이란 이름으로 뷰에도 담아준다. 모델에 들어가는 값이 일치하지 않으면 안된다. 예를 들어 템플릿에 item이라고 되어있는데 @ModelAttribute("item2")라고 하면 실패한다. model.addAttribute(item); */return"basic/item"; }...}
@ModelAttribute가 Item 객체를 생성하고 모델에 넣어주는 일을 대신 해준다.
모델에 데이터를 담을 때는 이름이 필요한데 이때 애너테이션 안에 name 속성을 넣어주면 된다.