Spring

부트캠프81일차 spring 소규모프로젝트 (controller , 상품등록,상품업데이트,삭제)

동곤일상 2025. 6. 4. 16:08
반응형

 

 

1) 아이템등록,수정,삭제

1-1) create(상품등록 페이지)

1-2) 상품등록 후

1-3) (목록에서 수정)update

1-4)  아이템삭제 ( delete)

 


 

 

1) 아이템등록,수정,삭제 (controller동작방식 간단하게)

package controller;

@Controller
@RequestMapping("item") // http://localhost:8080/shop1/item
public class ItemController {
	
	@Autowired
	private ShopService service;
	
	//http://localhost:8080/shop1/item/list 요청 시 호출되는메서드
	@RequestMapping("list")
	public ModelAndView list() {
		//ModelAndView : view에 이름과 , 전달데이터를 저장
		ModelAndView mav = new ModelAndView();
		List<Item> itemList = service.itemList();
		mav.addObject("itemList",itemList);
		//mav.setViewName("item/list"); view이름이 null인경우 요청url에서 알아서가져옴
		return mav;
	}
	
	@GetMapping("detail")
	public ModelAndView detail(@RequestParam Integer id) {
		ModelAndView mav = new ModelAndView();
		Item item = service.getItem(id);
		mav.addObject("item",item);
		return mav;
	}
	
	@GetMapping("create") //GET방식
	public ModelAndView create() {
		ModelAndView mav = new ModelAndView();
		mav.addObject(new Item());
		return mav;
	}
	/*
	 * Item item : 파라미터의 이름들과 같은 
	 * 		 item클래스의 setProperty를 이용해 파라미터값 자동 저장
	 */
	@PostMapping("create")//POST방식
	public ModelAndView register(@Valid Item item, BindingResult bresult) {
		System.out.println("@@item : "+item+"@@");
		ModelAndView mav = new ModelAndView();
		return mav;
	}
}

반환되는 view이름이없다면 requestMapping을 이용해서 알아서 가져온다

또한 ModelAndView객체에 addObject를 실행해

view에 전달할 데이터를 저장해놓음

 

1-1) create(상품등록 페이지)

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%><c:catch></c:catch>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<!--파일업로드 , 유효성검증 -->
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>상품등록</title>
</head>
<body>
<%--  enctype="multipart/form-date : POST방식 --%>
<form:form modelAttribute="item" action="create"  enctype="multipart/form-data">
<h2>상품등록</h2>
<table>
<tr><td>상품명</td>
<td><form:input path="name"/></td>
<td><font color="red"><form:errors path="name"/></font></td></tr>

<tr><td>상품가격</td>
	<td><form:input path="price"/></td>
	<td><font color="red"><form:errors path="price"/></font></td></tr>
	
<tr><td>상품이미지</td>	
<td colspan="2"><input type="file" name="picture"></td></tr>

<tr><td>상품설명</td>
	<td><form:textarea path="description" cols="20" rows="5"/></td>
	<td><font color="red"><form:errors path="description"/></font></td></tr>
	
<tr><td colspan="3"><input type="submit" value="상품등록">	
	<input type="button" value="상품목록" onclick="location.href='list'"></td></tr>
</table>
</form:form>
</body>
</html>

여기서 form:errors 라는 이름을 처음볼거다(유효성검증 이라고 봐도 무방함)

path=객체의 get프로퍼티명(파라미터)

 

또한 form태그에서 넘기지않고 form:form태그를 이용해 객체를 post방식으로 넘겨줌

 

 

해당 방식으로 유효성검사를 진행하려면 다음과같이 의존성을 추가해주어야한다

(valid_사용을 위해)

<!--유효성검증-->
		<dependency>
			<groupId>javax.validation</groupId>
			<artifactId>validation-api</artifactId>
			<version>2.0.1.Final</version>
		</dependency>

		<dependency>
			<groupId>org.hibernate.validator</groupId>
			<artifactId>hibernate-validator</artifactId>
			<version>6.1.7.Final</version>
		</dependency>

 

Item객체에 다음과같이 notEmpty ,min ,max 등의 어노테이션 설정

package logic;

@Data //getter,setter,toString, EqualsAndHash
public class Item {
	
	private int id;
	
	@NotEmpty(message="상품명 입력")
	private String name;
	
	@Min(value=10,message="10원 이상 가능합니다")
	@Max(value=100000,message="10만원 이하만 가능합니다")
	private int price;
	
	@NotEmpty(message="상품설명 입력하세요")
	private String description;
	
	private String pictureUrl;
	private MultipartFile picture;

}

 

controller의 register메서드부분

(BidingResult : 유효성검사의결과를 담고있음)


/*@Valid : Item 클래스에 정의된내용으로 입력값 검증
	  		검증결과 =>bresult에 저장*/
@PostMapping("create")
	//valid : 유효성검사
	//BindingResult : error를 담고있는 객체
	public ModelAndView register(@Valid Item item, BindingResult bresult,
			HttpServletRequest request) {
		ModelAndView mav = new ModelAndView();
		if(bresult.getErrorCount() > 0) { //입력값 검증 오류발생 시 
			return mav;
		}
		//정상인경우
		service.itemCreate(item,request);
		mav.setViewName("redirect:list");
		return mav;
	}

 

1-2) 상품등록 후

 

ShopService의

itemCreate(DB에 item저장)

uploadFileCreate(사진등록담당)

public void itemCreate(Item item, HttpServletRequest request) {
		
		//업로드파일이 존재 시 
		if(item.getPicture() != null && !item.getPicture().isEmpty()) {
			//프로젝트의 img폴더 하위에 저장
			String path =request.getServletContext().getRealPath("/")+"img/";
			uploadFileCreate(item.getPicture(),path);
			item.setPictureUrl(item.getPicture().getOriginalFilename());
		}
		
		int maxid = itemDao.maxId();
		item.setId(maxid+1); //현재 최대 id에 +1을 해준다.
		itemDao.insert(item);
	}

	
	private void uploadFileCreate(MultipartFile picture, String path) {
		String orgFile = picture.getOriginalFilename();//업로드된 파일명
		File f = new File(path);
		if(!f.exists()) {
			f.mkdirs();
		}
		
		try {
			//transferTo 메서드를 호출하여 업로드된 파일을 지정된 경로에 저장
			picture.transferTo(new File(path+orgFile));
		}
		catch(Exception e) {
			e.printStackTrace();
		}
	}

 

ItemDao(mapper에게 쿼리문을 받아옴)

public int maxId() {
		return template.getMapper(cls).maxId();
	}

	public void insert(Item item) {
		template.getMapper(cls).insert(item);
		
	}

 

쿼리문(itemMapper)은 다음과같이 작성했다

@Insert("insert into item values(#{id},#{name},#{price},#{description},#{pictureUrl})")
	public void insert(Item item);

	
	@Select("select ifnull(max(id),0) from item")
	public int maxId();


1-3) (목록에서 수정)update

 

이번엔 JSP(view)까지는 보여주지않으려한다.

로직의 흐름정도만 설명하겠음

 

1) 컨트롤러에서 유효성검사를 끝냈다면

2)service에 itemUpdate(item,request)를 호출함

 

service의 itemUpdate 메서드

(파일을 업로드하고 업데이트문을 실행함)

public void itemUpdate(Item item, HttpServletRequest request) {
		//업로드파일이 존재 시 
		if(item.getPicture() != null && !item.getPicture().isEmpty()) {
			//프로젝트의 img폴더 하위에 저장
			String path =request.getServletContext().getRealPath("/")+"img/";
			uploadFileCreate(item.getPicture(),path);//폴더에업로드
			item.setPictureUrl(item.getPicture().getOriginalFilename());
		}
		
		itemDao.update(item);

	}

쿼리는 뭐  다음과같이 구성되어있는 간단한 update문임

@Update("update item set name=#{name},"

+ " price=#{price},description=#{description},pictureUrl=#{pictureUrl}"

+ " where id=#{id}")

public void update(Item item);

 


1-4) 아이템삭제 ( delete)

getMapping을 이용해 delete에 접근하기전에 id를 이용해

item객체를 받아서 모든정보들을 출력해줄거임

 

delete.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>상품 삭제 전 확인</title>
</head>
<body>
<h2>상품 삭제 전 확인</h2>
<table>
<tr>
<td><img src="../img/${item.pictureUrl}"></td>
<td><table>
<tr><td>상품명</td><td>${item.name}</td></tr>
<tr><td>가격</td><td>${item.price}</td></tr>
<tr><td>상품설명</td><td>${item.description}</td></tr>
<tr><td colspan="2">
<form action="delete" method="post">
	<input type="hidden" name="id" value="${item.id}">
	<input type="submit"  value="상품 삭제">
	<input type="button" value="상품목록" onclick="location.href='list'">
</form>
</table>
</td>
</tr>
</table>

</body>
</html>

 

폼이넘어가는곳 postMapping

 

@PostMapping("delete")
	public ModelAndView postDelete(@RequestParam Integer id) {
		ModelAndView mav = new ModelAndView();
		service.deleteItem(id);
		mav.setViewName("redirect:list"); //list 재요청
		return mav;
	}

 

service와 dao는 그냥 deleteItem메서드를 호출하는 용도로만 사용되므로 간단하다(생략)

 

쿼리(mapper)

@Delete("delete from item where id=#{id}")

public void deleteItem(Integer id);