Spring boot 중고거래 쇼핑몰 사이트 만들기 프로젝트 4 (상품)

전승재·2023년 7월 28일

상품 Entity

이번엔 상품을 구현한다.
상품 Entity의 구성요소는

  • 상품 이름
  • 상품 가격
  • 상품 설명
  • 상품 고유 Id
  • 구매자에게 보여줄 판매자의 이름
  • 판매자를 식별하기 위한 판매자의 Id
    로 이뤄져있다.
    @Data 어노테이션을 사용하여 getter, setter, constructor를 생성한다.
package com.shopingmall.seungjae.domain;

import jakarta.validation.constraints.NotEmpty;
import lombok.Data;

@Data
public class Item {
    @NotEmpty
    private String itemName;
    @NotEmpty
    private Integer price;
    @NotEmpty
    private String itemDescription;
    private Long itemId;
    @NotEmpty
    private String sellerName;
    @NotEmpty
    private String sellerId;
}

ItemRepository

상품을 저장할 ItemRepository 인터페이스를 생성한다.
ItemRepository는 저장, 조회, 삭제 기능을 가지고 있다.

package com.shopingmall.seungjae.repository;

import com.shopingmall.seungjae.domain.Item;
import org.springframework.stereotype.Repository;

import java.util.List;
import java.util.Optional;

@Repository
public interface ItemRepository {
    Item save(Item item);
    Optional<Item> findByName(String name);

    Item findById(Long Id);
    List<Item> findAll();
    void delete(Long deleteId);
    void clearStore();
}

ItemRepositoryImpl

ItemRepository의 구현체를 생성한다.
저장은 HashMap 임시저장소를 사용해서 저장한다.

package com.shopingmall.seungjae.repository;

import com.shopingmall.seungjae.domain.Item;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Repository;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Optional;

@Repository
@Slf4j
@RequiredArgsConstructor
public class ItemRepositoryImpl implements ItemRepository{

    private static HashMap<Long, Item> itemStore = new HashMap<>();
    private static long sequence = 0L;

    @Override
    public Item findById(Long Id) {
        Item item = itemStore.get(Id);
        return item;
    }
    @Override
    public Item save(Item item) {
        item.setItemId(++sequence);
        itemStore.put(item.getItemId(), item);
        log.info("item save ={}",item);
        return item;
    }

    @Override
    public Optional<Item> findByName(String name) {
        return findAll().stream()
                .filter(
                item -> item.getItemName().equals(name)
        ).findFirst();
    }

    @Override
    public List<Item> findAll() {
        return new ArrayList<>(itemStore.values());
    }

    @Override
    public void delete(Long deleteId) {
        itemStore.remove(deleteId);
    }

    @Override
    public void clearStore() {
        itemStore.clear();
    }
}

ShoppingMallItemController

아이템 컨트롤러를 생성한다.
API는 기본이 /items로 이뤄져있고 명세서는 아래와 같다.

API기능Method권한
/items상품 리스트 출력GETuser
/items/{itemId}상품 상세 페이지 출력GETuser
/items/{itemId}상품 삭제 요청POSTuser {본인의 상품일 경우만}
/items/add상품 추가 페이지 출력GETuser
/items/add상품 추가 요청POSTuser
/items/{itemId}상품 검색GETuser

@GetMapping일때 itemRepository에서 모든 값을 찾아서 Item 리스트에 저장하고 이를 model.addAttribute를 사용하여 랜더링한다.

@GetMapping("/add")일 때 상품추가폼을 리턴하여 사용자에게 보여준다.

@PostMapping("/add")일 때 상품을 추가해야 하는데 상품추가폼에서 사용자가 입력한 내용을 검증을 통해 오류가 없는지를 확인하고 오류가 있다면 다시 추가폼으로 보낸다.
만약 오류가 없다면 저장소에 상품을 저장하고 상품리스트 페이지로 이동한다.

@GetMapping("/{itemId}")일 때 사용자에게 상품의 상세정보를 보여줘야한다.
따라서 상품의 Id를 @PathVariable을 통해 받고 이를 저장소에서 찾아서 사용자에게 return한다.

@PostMapping("/{itemId}")일 때 사용자가 상품을 삭제하는 행위이다.
상품을 삭제할때의 전제조건이 본인이 상품의 등록자일 경우에 가능하다 이기 때문에 상품의 등록자인지 확인하는 로직을 넣었다.
만약 본인이 등록자이면 저장소에서 상품을 삭제하고 상품리스트로 넘어간다.
등록자가 아닐경우 본인의 제품이 아닐경우 삭제할 수 없다는 오류 메시지와 함께 상품 상세페이지로 return한다.

package com.shopingmall.seungjae.controller.Item;

import com.shopingmall.seungjae.controller.Member.SessionConst;
import com.shopingmall.seungjae.domain.Item;
import com.shopingmall.seungjae.domain.Member;
import com.shopingmall.seungjae.repository.ItemRepository;
import com.shopingmall.seungjae.repository.ItemRepositoryImpl;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.StringUtils;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@Controller
@Slf4j
@RequestMapping("/items")
@RequiredArgsConstructor
public class ShoppingMallItemController {
    ItemRepository itemRepository = new ItemRepositoryImpl();
    @GetMapping
    public String ItemList(Model model) {
        List<Item> items = itemRepository.findAll();
        model.addAttribute("items", items);
        log.info("items ={}",items);
        return "item/itemList";
    }

    @GetMapping("/add")
    public String AddPage(@ModelAttribute Item item,Model model) {
        model.addAttribute("items", item);
        return "item/addItemForm";
    }

    @PostMapping("/add")
    public String AddItem(@ModelAttribute Item item, BindingResult bindingResult, @SessionAttribute(name = SessionConst.LOGIN_MEMBER, required = false) Member loginMember) {
        if (!StringUtils.hasText(item.getItemName())){
            bindingResult.addError(new FieldError("items","itemName", "상품 이름이 올바르지 않습니다."));
        }
        if (item.getPrice()<0){
            bindingResult.addError(new FieldError("items","price", "상품 가격이 올바르지 않습니다."));
        }
        if (!StringUtils.hasText(item.getItemName())){
            bindingResult.addError(new FieldError("items","itemDescription", "상품 설명이 올바르지 않습니다."));
        }
        if (bindingResult.hasErrors()) {
            log.info("상품 추가 오류 발생 bindingResult = {}",bindingResult);
            return "item/addItemForm";
        }
        item.setSellerId(loginMember.getLoginId());
        item.setSellerName(loginMember.getName());
        itemRepository.save(item);
        log.info("item add ={}",item);
        return "redirect:/items";
    }

    @GetMapping("/{itemId}")
    public String ItemInformation(@PathVariable(name = "itemId") Long findItemId, Model model) {
        Item item = itemRepository.findById(findItemId);
        log.info("findItem = {}",item);
        model.addAttribute("item", item);
        return "item/item";
    }

    @PostMapping("/{itemId}")
    public String ItemDelete(@PathVariable(name = "itemId") Long findItemId, Model model,
                             @SessionAttribute(name = SessionConst.LOGIN_MEMBER, required = false) Member loginMember) {
        Item item = itemRepository.findById(findItemId);
        if(loginMember.getLoginId().equals(item.getSellerId())&&loginMember.getName().equals(item.getSellerName())&&loginMember!=null&&item!=null) {
            log.info("deleteItem = {}", item);
            itemRepository.delete(item.getItemId());
            return "redirect:/items";
        }
        else{
            model.addAttribute("item", item);
            model.addAttribute("deleteError","본인의 제품이 아닐경우 삭제하실 수 없습니다.");
            return "item/item";
        }
    }

}

결과



0개의 댓글