Spring

12.19.(월) Spring Framework(34): 자료실 기능(8)

콜라든포비 2022. 12. 21. 23:00

글 삭제

이제 글을 삭제해보자.

글 보기에서 삭제버튼에 링크를 할당한다. javascript를 이용해서 confirm한 후 페이지를 넘겨줄 것이다.

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!-- attribute : vo -->
<title>${ vo.subject }</title>
<script>
	function dataDel(){
		if(confirm("글을 삭제하시겠습니까?")){
			location.href = "/myapp/data/dataDel/${vo.postno}";
		}
	}
</script>
<div class="container">
	<h1>글 보기</h1>
	<ul>
		<li>글 번호</li>
		<li>${ vo.postno }</li>
		<li>작성자</li>
		<li>${ vo.username }</li>
		<li>등록일</li>
		<li>${ vo.regdate }</li>
		<li>조회수</li>
		<li>${ vo.hitcount }</li>
		<li>제목</li>
		<li>${ vo.subject }</li>
		<li>내용</li>
		<li>${ vo.content }</li>
		<li>첨부파일</li>
		<li>
			<a href="/myapp/upload/${ vo.filename1 }" download>${ vo.filename1 }</a><br>
			<c:if test="${ vo.filename2!=null && vo.filename2!='' }">
				<a href="/myapp/upload/${ vo.filename2 }" download>${ vo.filename2 }</a>
			</c:if>
		</li>
	</ul>
	<div>
		<a href="/myapp/data/dataEdit?postno=${ vo.postno }">수정</a>
		<a href="javascript:dataDel()">삭제</a>
	</div>
</div>

링크의 형태가 약간 다르다. 이렇게 작성했을때 어떻게 parameter로 받을지 알아보자.

컨트롤러 매핑을 해줄때 새로운 어노테이션 @PathVariable을 통해서 받을 수 있다.

// 글 삭제
@GetMapping("/data/dataDel/{postno}")
public ModelAndView dataDel(@PathVariable("postno") int postno) {
	ModelAndView mav = new ModelAndView();
	
	return mav;
}

컨트롤러

우선 삭제가 실패할 것에 대비해서 삭제할 글에 대한 정보를 별도의 DataVO객체에 담아주고,

아이디와 글 고유번호가 일치하는 글에 대해 삭제하도록 Service와 쿼리문을 작성하자.

// 글 삭제
@GetMapping("/data/dataDel/{postno}")
public ModelAndView dataDel(@PathVariable("postno") int postno, HttpSession session) {
	ModelAndView mav = new ModelAndView();
	String username = (String)session.getAttribute("logUsername");
	
	// 삭제할 데이터의 파일명 보관
	DataVO dbVO = service.selectFilename(postno);
	
	return mav;
}

Service

package com.poby.myapp.service;

import java.util.List;

import javax.inject.Inject;

import org.springframework.stereotype.Service;

import com.poby.myapp.dao.DataDAO;
import com.poby.myapp.vo.DataVO;

@Service
public class DataServiceImpl implements DataService {
	@Inject
	DataDAO dao;

	@Override
	public int dataPostOk(DataVO vo) {
		return dao.dataPostOk(vo);
	}

	@Override
	public List<DataVO> dataList() {
		return dao.dataList();
	}

	@Override
	public DataVO dataView(int postno) {
		return dao.dataView(postno);
	}

	@Override
	public DataVO selectFilename(int postno) {
		return dao.selectFilename(postno);
	}

	@Override
	public int dataEdit(DataVO vo) {
		return dao.dataEdit(vo);
	}

	@Override
	public int dataDel(int postno, String username) {
		return dao.dataDel(postno, username);
	}
}

쿼리문 생성

<delete id="dataDel">
	DELETE FROM data_tbl WHERE postno=${param1} AND username=#{param2}
</delete>

컨트롤러 모델&뷰

// 글 삭제
@GetMapping("/data/dataDel/{postno}")
public ModelAndView dataDel(@PathVariable("postno") int postno, HttpSession session) {
	ModelAndView mav = new ModelAndView();
	String username = (String)session.getAttribute("logUsername");
	String path = session.getServletContext().getRealPath("/upload");
	
	// 삭제할 데이터의 파일명 보관
	DataVO dbVO = service.selectFilename(postno);
	
	// 데이터 삭제
	int result = service.dataDel(postno, username);
	
	// 파일 삭제
	if(result>0){	// 삭제 성공 시 글 목록
		File f = new File(path, dbVO.getFilename1());
		f.delete();
		
		if(dbVO.getFilename2()!=null) {
			f = new File(path, dbVO.getFilename2());
			f.delete();
		}
		mav.setViewName("redirect:dataList");
	}else{	// 삭제 실패 시 글 보기
		mav.addObject("postno", postno);
		mav.setViewName("redirect:dataView");
	}

	return mav;
}

※ 400에러 잘못된 요청

글 삭제를 했을때 잘못된 요청이라고 된 에러가 떴다.

원인은 컨트롤러에 매핑된 주소에 의해 redirect의 주소지가 다른 매핑과 달랐기 때문이다.

// 글 삭제
@GetMapping("/data/dataDel/{postno}")
public ModelAndView dataDel(@PathVariable("postno") int postno, HttpSession session) {
	ModelAndView mav = new ModelAndView();
	String username = (String)session.getAttribute("logUsername");
	String path = session.getServletContext().getRealPath("/upload");
	
	// 삭제할 데이터의 파일명 보관
	DataVO dbVO = service.selectFilename(postno);
	
	// 데이터 삭제
	int result = service.dataDel(postno, username);
	
	// 파일 삭제
	if(result>0){	// 삭제 성공 시 글 목록
		File f = new File(path, dbVO.getFilename1());
		f.delete();
		
		if(dbVO.getFilename2()!=null) {
			f = new File(path, dbVO.getFilename2());
			f.delete();
		}
		mav.setViewName("redirect:/data/dataList");
	}else{	// 삭제 실패 시 글 보기
		mav.addObject("postno", postno);
		mav.setViewName("redirect:/data/dataView");
	}
	
	return mav;
}

PathVariable의 형태로 url매핑을 했다보니, redirect가 평소와 다르게 상세 경로까지 설정을 해줘야 작동한다.

삭제도 되고 서버에서도 파일이 제대로 지워진 걸 볼 수 있다.