WEB JAVA SPRING/PROJECT
3.상품 등록하기
sshhhh
2023. 9. 12. 16:59
@ManyToOne : itemimg의 입장에서 하나의 item에 여러개의 사진 가능
@JoinColumn(name = "item_id") //fk
1.ItemImg 엔티티
package com.shop.entity;
import lombok.Getter;
import lombok.Setter;
import javax.persistence.*;
/**
* 상품 이미지 엔티티
*/
@Entity
@Getter @Setter
@Table(name = "item_img")
public class ItemImg {
@Id
@Column(name="item_img_id")
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String imgName; //이미지 파일명
private String oriImgName; //원본 이미지 파일명
private String imgUrl; //이미지 조회 경로
private String repimgYn; //대표 이미지 여부
@ManyToOne(fetch = FetchType.LAZY) //itemimg의 입장에서 하나의 item에 여러개의 사진 가능
@JoinColumn(name = "item_id") //fk
private Item item;
//이미지 정보 업데이트
public void updateItemImg(String oriImgName, String imgName, String imgUrl){
this.oriImgName = oriImgName;
this.imgName = imgName;
this.imgUrl = imgUrl;
}
}
2.ItemImgDto
/**
*상품 저장 후 상품 이미지에 대한 데이터 전달
*/
package com.shop.dto;
import com.shop.entity.ItemImg;
import lombok.Getter;
import lombok.Setter;
import org.modelmapper.ModelMapper;
@Getter @Setter
public class ItemImgDto {
private Long id;
private String imgName;
private String oriImgName;
private String imgUrl;
private String repImgYn; //대표상품
private static ModelMapper modelMapper = new ModelMapper(); //멤버 변수로 modelMapper를 추가
public static ItemImgDto of(ItemImg itemImg) {
return modelMapper.map(itemImg,ItemImgDto.class);
}
}
3.ItemImgFormDto
/**
* 상품 데이터 정보 전달
*/
package com.shop.dto;
import com.shop.constant.ItemSellStatus;
import com.shop.entity.Item;
import lombok.Getter;
import lombok.Setter;
import org.modelmapper.ModelMapper;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.util.ArrayList;
import java.util.List;
@Getter @Setter
public class ItemFormDto {
private Long id;
@NotBlank(message = "상품명은 필수 입력 값입니다.")
private String itemNm;
@NotNull(message = "가격은 필수 입력 값입니다.")
private Integer price;
@NotBlank(message = "상품 상세는 필수 입력 값입니다.")
private String itemDetail;
@NotNull(message = "재고는 필수 입력 값입니다.")
private Integer stockNumber;
private ItemSellStatus itemSellStatus; // SELL, SOLD_OUT
private List<ItemImgDto> itemImgDtoList = new ArrayList<>(); //상품 저장 후 수정할때 상품 이미지 정보 저장
private List<Long> itemImgIds = new ArrayList<>(); //상품의 이미지 아이디 저장 (상품 등록 시 이미지x ,수정시 이미지o)
private static ModelMapper modelMapper = new ModelMapper();
//modelMapper를 이용하여 엔티티 객체와 DTO객체 간의 데이터를 복사하여 복사한 객체를 반환
public Item createItem(){
return modelMapper.map(this, Item.class);
}
public static ItemFormDto of(Item item){
return modelMapper.map(item,ItemFormDto.class);
}
}
4.ItemController
/**
* 상품 등록 페이지로 이동
*/
@Controller
@RequiredArgsConstructor
public class ItemController {
private final ItemService itemService;
//상품 등록 페이지
@GetMapping(value = "/admin/item/new")
public String itemForm(Model model) {
model.addAttribute("itemFormDto", new ItemFormDto());
return "item/itemForm";
}
5.itemForm.html
script 부분
html
6.WebMvcConfigurer
/**
* 업로드한 이미지 파일을 읽어올 경로 설정
*/
package com.shop.config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Value("${uploadPath}") //properties에 설정한 uploadPath 프로퍼티 값 읽어옴
String uploadPath;
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/images/**") //uploadPath에 설정한 폴더를 기준으로 파일 읽어옴
.addResourceLocations(uploadPath); //로컬 컴퓨터에 저장된 파일을 읽어올 root 경로 설정
}
}
7.FileService
/**
* 파일처리 (등록,삭제)
*/
package com.shop.service;
import lombok.extern.java.Log;
import org.springframework.stereotype.Service;
import java.io.File;
import java.io.FileOutputStream;
import java.util.UUID;
/**
* 파일 처리
*/
@Service
@Log
public class FileService {
//파일 업로드
public String uploadFile(String uploadPath, String originalFileName, byte[] fileData) throws Exception{
UUID uuid = UUID.randomUUID(); //Universally Unique Identifier 서로 다른 개체 구별하기위해 이름을 부여할 때 사용(파일명 중복 해결)
String extension = originalFileName.substring(originalFileName.lastIndexOf("."));
String savedFileName = uuid.toString() + extension; // + 확장자 =저장될 파일 이름
String fileUploadFullUrl = uploadPath + "/" + savedFileName;
FileOutputStream fos = new FileOutputStream(fileUploadFullUrl); //FileOutputStream클래스는 바이트 단위의 출력을 내보내는 클래스, 생성자로 파일이 저장될 위치와 파일의 이름을 넘겨 파일 출력 스트림 만든다.
fos.write(fileData); //fileData를 파일 출력 스트림에 입력
fos.close();
return savedFileName; //업로드된 파일 이름 반환
}
//삭제
public void deleteFile(String filePath) throws Exception{
File deleteFile = new File(filePath); //파일이 저장된 경로를 이용해 파일 객체 생성
if(deleteFile.exists()) {
deleteFile.delete();
log.info("파일을 삭제하였습니다.");
} else {
log.info("파일이 존재하지 않습니다.");
}
}
}
8.ItemImgRepository
/**
* 상품 이미지 정보를 저장
*/
package com.shop.repository;
import com.shop.entity.ItemImg;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.List;
public interface ItemImgRepository extends JpaRepository<ItemImg,Long> {
/*
이미지가 잘 저장됐는지 테스트 코드 작성 위해...
매개변수로 넘겨준 상품id를 가지며, 상품 이미지 아이디를 오름차순으로 가져옴
*/
List<ItemImg> findByItemIdOrderByIdAsc(Long itemId);
}
9.ItemImgService
/**
* 상품 이미지 업로드, 상품 이미지 정보 저장
*/
@Service
@RequiredArgsConstructor
@Transactional
public class ItemImgService {
@Value("${itemImgLocation}") //properties파일에 등록한 itemImgLocation 값을 불러온다.
private String itemImgLocation;
private final ItemImgRepository itemImgRepository;
private final FileService fileService;
public void saveItemImg(ItemImg itemImg, MultipartFile itemImgFile) throws Exception {
String oriImgName = itemImgFile.getOriginalFilename();
String imgName = "";
String imgUrl = "";
//파일 업로드
if (!StringUtils.isEmpty(oriImgName)) {
//imgName:실제로컬에 저장된 상품 이미지 파일 이름, oriImgName: 업로드했던 상품 이미지파일 원래 이름
imgName = fileService.uploadFile(itemImgLocation, oriImgName,
itemImgFile.getBytes());
imgUrl = "/images/item/" + imgName; //업로드 결과 로컬에 저장된 상품 이미지 파일 불러오는 경로
}
//상품 이미지 정보 저장
itemImg.updateItemImg(oriImgName, imgName, imgUrl);
itemImgRepository.save(itemImg);
}
}
10.ItemService
/**
* 상품 등록
*/
@Service
@Transactional
@RequiredArgsConstructor
public class ItemService {
private final ItemRepository itemRepository;
private final ItemImgService itemImgService;
private final ItemImgRepository itemImgRepository;
public Long saveItem(ItemFormDto itemFormDto, List<MultipartFile> itemImgFileList) throws Exception{
//상품 등록
Item item = itemFormDto.createItem();//상품 등록 폼으로부터 입력받은 데이터를 이용해 item객체 생성
itemRepository.save(item); //상품 데이터 저장
//이미지 등록
for(int i=0;i<itemImgFileList.size();i++){
ItemImg itemImg = new ItemImg();
itemImg.setItem(item);
if(i == 0) //첫번째 이미지일 경우
itemImg.setRepimgYn("Y"); //대표 상품 이미지 여부를 Y로 세팅
else
itemImg.setRepimgYn("N");
itemImgService.saveItemImg(itemImg, itemImgFileList.get(i)); //상품 이미지 정보 저장
}
return item.getId();
}
11.ItemController
//상품 등록하는 url
@PostMapping(value = "/admin/item/new")
public String itemNew(@Valid ItemFormDto itemFormDto, BindingResult bindingResult,
Model model, @RequestParam("itemImgFile") List<MultipartFile> itemImgFileList) {
/*- 검증하려는 객체 앞에 @Vaild 선언하고, bindingResult 객체 추가 후 검사후 결과 담는다.
bindingResult.hasErrors()를 호출하여 에러가 있는지 검사
- @RequestParam("가져올 데이터의 이름") [데이터타입] [가져온데이터를 담을 변수]
*/
//상품 등록시 필수 값이 없다면 다시 상품 등록 페이지로 전환
if (bindingResult.hasErrors()) {
return "item/itemForm";
}
if (itemImgFileList.get(0).isEmpty() && itemFormDto.getId() == null) {
model.addAttribute("errorMessage", "첫번째 상품 이미지는 필수 입력 값 입니다.");
return "item/itemForm";
}
try {
itemService.saveItem(itemFormDto, itemImgFileList);
} catch (Exception e) {
model.addAttribute("errorMessage", "상품 등록 중 에러가 발생하였습니다.");
return "item/itemForm";
}
return "redirect:/"; //정상 등록 시 메인
}
이미지 등록하기 힘들다.