고래씌

[JSP] 5-3. 게시판 상세 페이지 수정, 삭제 본문

Server/JSP과 Servlet

[JSP] 5-3. 게시판 상세 페이지 수정, 삭제

고래씌 2023. 12. 12. 16:24

1. 게시판 수정

① 해당 게시판을 클릭하였을 때 게시판 상세 페이지로 이동하였을 때 수정버튼이 보이게되는데(작성자와 사용자가 동일할 경우) 이 버튼을 클릭할 때 현제 게시글의 번호도 서버로 전송될 수 있도록 설정

 

 boardDetailView.jsp

 

☞ b.getBoardNo() => 내가 작성했던 게시글 내용이 보이게 하기 위해서 현재 게시글 번호를 같이 보내야한다!

 

=> 게시판 상세페이지로 이동하였을 때, 수정 버튼을 클릭하였을 때 현재 게시판번호도 같이 서버로 전송될 수 있도록 설정하였다.

 

 

② SQL 쿼리문 생성

☞ 게시판 상세 페이지를 수정할 때 만약 첨부파일이 있었다가 삭제하고 다시 올린다면...?

또한 첨부파일이 없었다가 첨부파일을 넣고 다시 올린다면...?

첨부파일이 있긴한데 등록했던 첨부파일이 아니라 다른 첨부파일로 수정하고 다시 올린다면...?

=> 케이스별로 로직을 다르게 다시 설정해야한다!!!

 

 

■ board-mapper.xml

 

▶ 게시판 수정

 

 

▶ 게시판 첨부파일 수정(이미 첨부파일이 존재하고 있었는데 다른 첨부파일로 수정할 경우)

 

 

▶ SEQ_BNO.CURRVAL 호출되는 부분이 ?로 대체 (첨부파일이 없는데 첨부파일 추가할 경우)

 

=> 똑같은 key 이름이 있으면 안된다!

=> SEQ_BNO.CURRVAL은 NEXTVAL을 가져오는데 수정을 하게 되면 원하는 값을 못가져오니까 ?로 대체함

 

 

③ 서버 전송을 위해 Servlet 작성

■ BoardUpdateController.java

package com.kh.board.controller;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.tomcat.util.http.fileupload.servlet.ServletFileUpload;

import com.kh.board.model.service.BoardService;
import com.kh.board.model.vo.Attachment;
import com.kh.board.model.vo.Board;
import com.kh.board.model.vo.Category;
import com.kh.common.MyFileRenamePolicy;
import com.oreilly.servlet.MultipartRequest;

/**
 * Servlet implementation class BoardUpdateController
 */
@WebServlet("/update.bo")
public class BoardUpdateController extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    public BoardUpdateController() {
        super();
    }

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		
		BoardService bService = new BoardService();
		int boardNo = Integer.parseInt(request.getParameter("bno"));  // 강제형변환 String -> int형
		
		// 1) 게시글 정보 조회
		Board b = bService.selectBoard(boardNo);
		
		// 2) 첨부파일 정보 조회
		Attachment at = bService.selectAttachment(boardNo);
		
		// 3) 카테고리목록 조회
		ArrayList<Category> list = bService.selectCategoryList();
		
		request.setAttribute("list", list);
		request.setAttribute("at", at);
		request.setAttribute("b", b);
		
		request.getRequestDispatcher("views/board/boardUpdateForm.jsp").forward(request, response);
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		request.setCharacterEncoding("UTF-8");
		
		if(ServletFileUpload.isMultipartContent(request)) {
			// 전송파일 용량 제한
			int maxSize = 10 * 1024 * 1024; // 10mbyte
			
			// 파일을 저장할 물리적인 경로 알아내기
			String savePath = request.getSession().getServletContext()
					.getRealPath("/resources/board_upfiles/");
					// getServletContext : 웹 전역에 있는 변수를 다룰 수 있는 객체
			
			// 서버에 업로드
			MultipartRequest multi = new MultipartRequest(request, savePath, maxSize, "UTF-8", new MyFileRenamePolicy());
			
			// SQL문 실행시 필요한 변수들 셋팅
			// - BOARD 테이블에 UPDATE시 필요한 변수들
			int boardNo = Integer.parseInt(multi.getParameter("bno"));
			String categoryNo = multi.getParameter("category");
			String boardTitle = multi.getParameter("title");
			String boardContent = multi.getParameter("content");
			
			// Board 객체 값 넣어줌
			Board b = new Board.Builder()
					.boardNo(boardNo)
					.categoryNo(Integer.parseInt(categoryNo))
					.boardTitle(boardTitle)
					.boardContent(boardContent)
					.bulid();
			
			// 첨부파일을 첨부하지않았다면 null 값으로 들어가지만 있다면 if문 이용
			Attachment at = null;
			// 새롭게 전달된 첨부파일이 있을 경우 필요한 값 뽑기
			if(multi.getOriginalFileName("reUpfile") != null) {
				//reUpfile명으로 넘어온 파일명이 null아닐 경우(새롭게 등록할 첨부파일이 있다면)
				
				at = new Attachment();  // 기본생성자 호출
				at.setOriginName(multi.getOriginalFileName("reUpfile"));
				// 원본이름
				at.setChangeName(multi.getFilesystemName("reUpfile"));
				// 수정된 이름
				at.setFilePath("/resources/board_upfiles/");
				
				// 첨부파일이 이미 존재 했을경우(fileNo가 hidden으로 넘어왔음)
				// 우리는 boardUpdateForm.jsp 에서 첨부파일번호(fileNo)를 hidden으로 넘겨주게 설정하였다.
				if(multi.getParameter("originFileNo") != null) {
					// 새로운 첨부파일이 있던 케이스.
					// => update attachment 실행
					// update 하기 위해서는 기존의 파일 고유번호가 필요함
					at.setFileNo(Integer.parseInt(multi.getParameter("originFileNo")));
					
					// 기존의 첨부파일 삭제
					new File(savePath+multi.getParameter("originFileName")).delete();
				}else {
					// 새롭게 첨부파일을 등록하려고 하지만, 기존에는 첨부파일이 없었을 경우
					// => Insert Attachment
					// insert하기 위해서는 현재 게시글 번호가 필요함
					at.setRefBno(boardNo);
				}
			}
			
			// 게시판 작성때와 마찬가지로 하나의 트랜잭션으로 처리할 예정. update는 성공했는데 작성은 실패했다면 
			// 이건 말이 안되니까 하나의 트랜잭션으로 처리해야함
			int result = new BoardService().updateBoard(b, at);
			
			// case1 : 새로 등록할 첨부파일이 없는 경우 => b, null => Board Update
			// case2 : 새로운 첨부파일 O, 기존 첨부파일 O => b, fileno가 담긴 at => Board Update, Attachment Update
			// case3 : 새로운 첨부파일 O, 기존 첨부파일 X => b, refBno가 담긴 at => Board Update, Attachment Insert
			
			// => Board Update는 항상 발생하고, 상황이ㅔ 따라 Attachment가 실행할수고, Update, Insert 할수도 있다.
			
			if(result > 0) {
				// 수정 성공시
				request.getSession().setAttribute("alertMsg", "성공적으로 수정되었습니다.");
				response.sendRedirect("detail.bo?bno="+boardNo); // 게시판 상세페이지 + 게시판번호로 이동
			}else {
				request.setAttribute("errorMsg", "게시글 수정에 실패했습니다..");
				request.getRequestDispatcher("views/common/errorPage.jsp").forward(request, response);
			}
		}
	}

}

 

 

▶ protected void doGet 메소드에서 boardUpdateForm.jps 페이지로 이동하는 코드 작성(현재게시판에서 작성하였던 내용이 그대로 넘어감)

 

▶ protected void doPost 메소드에서 게시판 내용을 수정한 값과 첨부파일 등을 post 방식으로 전송

 

- 첨부파일을 첨부하지않았다면 null 값으로 들어가지만 있다면 if문 이용

Attachment at = null;

 

 

- 새롭게 전달된 첨부파일이 있을 경우 필요한 값 뽑기

if(multi.getOriginalFileName("reUpfile") != null) {   
//reUpfile명으로 넘어온 파일명이 null아닐 경우(새롭게 등록할 첨부파일이 있다면)
// boardUpdateForm.jsp 에서 우리는 첨부파일을 재등록할 때 name=reUpfile로 지정하였었다.

     at = new Attachment();  // 기본생성자 호출
     at.setOriginName(multi.getOriginalFileName("reUpfile"));
     // 원본이름
     at.setChangeName(multi.getFilesystemName("reUpfile"));
     // 수정된 이름
     at.setFilePath("/resources/board_upfiles/");
     // 경로 지정
 
   // 첨부파일이 이미 존재 했을경우(fileNo가 hidden으로 넘어왔음)
   // 우리는 boardUpdateForm.jsp 에서 첨부파일번호(fileNo)를 hidden으로 넘겨주게 설정하였었다.
   if(multi.getParameter("originFileNo") != null) {
        // 새로운 첨부파일이 있던 케이스.
        // => update attachment 실행
       // update 하기 위해서는 기존의 파일 고유번호가 필요함
       at.setFileNo(Integer.parseInt(multi.getParameter("originFileNo")));

       // 기존의 첨부파일 삭제
       new File(savePath+multi.getParameter("originFileName")).delete();
   }else {
       // 새롭게 첨부파일을 등록하려고 하지만, 기존에는 첨부파일이 없었을 경우
       // => Insert Attachment
       // insert하기 위해서는 현재 게시글 번호가 필요함
       at.setRefBno(boardNo);
   }
}

 

 

▶ 게시판 작성때와 마찬가지로 하나의 트랜잭션으로 처리할 예정. update는 성공했는데 작성은 실패했다면 이건 말이 안되니까 하나의 트랜잭션으로 처리해야함

 

case1 : 새로 등록할 첨부파일이 없는 경우 => b, null => Board Update
case2 : 새로운 첨부파일 O, 기존 첨부파일 O => b, fileno가 담긴 at => Board Update, Attachment Update
case3 : 새로운 첨부파일 O, 기존 첨부파일 X => b, refBno가 담긴 at => Board Update, Attachment Insert

=> Board Update는 항상 발생하고, 상황이ㅔ 따라 Attachment가 실행할수고, Update, Insert 할수도 있다.

 

☞ BoardService().updateBoard(b, at); 에서 case별 처리

int result = new BoardService().updateBoard(b, at);

 

 

 

④ 게시판 수정 폼으로 이동하도록 html 생성(boardUpdateForm.jsp)

■ boardUpdateForm.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" import="java.util.ArrayList, com.kh.board.model.vo.*"%>
<%
	ArrayList<Category> list = (ArrayList<Category>) request.getAttribute("list");
	Board b = (Board) request.getAttribute("b");
	Attachment at = (Attachment) request.getAttribute("at");
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<style>
#enroll-form>table{border:1px solid white;}
#enroll-form input, #enroll-form textarea{
	width:100%;
	box-sizing:border-box;
}
</style>
</head>
<body>
	<%@ include file="../common/menubar.jsp" %>
	
	<div class="outer">
		<br>
		<h2 align="center">일반게시판 수정</h2>
		
		<form action="<%= contextPath %>/update.bo" id="enroll-form" method="post"
		enctype="multipart/form-data">

			<!-- 게시글번호 -> input type hidden으로 넘길 예정 -->
			<input type="hidden" name="bno" value="<%= b.getBoardNo() %>">
			<table align="center">
				<tr>
					<th width="100">카테고리</th>
					<td width="500">
						<select name="category">
								<% for(Category c : list) { %>
								<option value="<%= c.getCategoryNo() %>" 
									<%if(b.getCategoryName().equals(c.getCategoryName())) { %>
										<%-- 사용자가 지정한 카테고리(board타입 객체의 카테고리)와 카테고리 리스트의 카테고리가 같다면 --%>
										selected
									<% } %>
								><%= c.getCategoryName() %></option>
								<% } %>
						</select>
					</td>
				</tr>
				<tr>
					<th>제목</th>
					<td><input type="text" name="title" required value="<%= b.getBoardTitle() %>"></td>
																<!-- 사용자가 입력한 게시판 제목 가져옴 -->
				</tr>
				<tr>
					<th>내용</th>
					<td>
						<textarea name="content" rows="10" required><%=b.getBoardContent() %></textarea>
					</td>
				</tr>
				<tr>
					<th>첨부파일</th>
					<td>
						<% if(at != null) { %>
							<%= at.getOriginName() %>
							<input type="hidden" name="originFileNo" value="<%= at.getFileNo() %>">
							<input type="hidden" name="originFIleName" value="<%= at.getChangeName() %>">
						<% } %>
						<input type="file" name="reUpfile">  <!-- reUpfile : 재등록 -->
					</td>
				</tr>
			</table>
			
			<br>
			
			<div align="center">
				<button type="submit">수정</button>
			</div>
			
		</form>
	</div>

</body>
</html>

 

 

▶ BoardUpdateController에서 값을 넣어놓은 Board 객체와 Attachment 객체의 값을 가져옴 (b, at)

 

 

▶ 게시글 번호 input type hidden으로 넘김

 

 

▶ 카테고리 선택이 작성했었던 게시판에서 선택했던 카테고리가 그대로 넘어오도록 설정

 

 

▶ 작성했었던 게시판의 제목과 내용, 첨부파일 번호, 이름을 가져옴

 

 

▶ 첨부파일 재등록(name = reUpfile) 로 설정  => BoardUpdateController.java 에서 다시 업로드하는 파일이 있다면..?

 

 

 

⑤ BoardService.java 에서 Connection 객체 생성 후, 첨부파일 case별 처리

■ BoardService.java

 

 

⑥ SQL 쿼리문 실행

■ BoardDao.java

 

▶ 게시판 수정

 

 

▶ 첨부파일 수정할 때(첨부파일 있었던 경우)

 

 

▶ 첨부파일 추가할 때(첨부파일이 없었던 경우)

 


2. 게시글 삭제

 

■ boardDetailView.java

 

 

■ board-mapper.xml 에서 SQL 쿼리 생성

 

 

■ BoardDeleteController.java

package com.kh.board.controller;

import java.io.File;
import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.kh.board.model.service.BoardService;
import com.kh.board.model.vo.Attachment;
import com.kh.board.model.vo.Board;

/**
 * Servlet implementation class BoardDeleteController
 */
@WebServlet("/delete.bo")
public class BoardDeleteController extends HttpServlet {
	private static final long serialVersionUID = 1L;

    public BoardDeleteController() {
        super();
    }


	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		BoardService bService = new BoardService();
		
		// 삭제 성공시 list 페이지로 이동
		int boardNo = Integer.parseInt(request.getParameter("bno"));
		
		Attachment at = new BoardService().selectAttachment(boardNo);
		
		
		// 게시글 정보 조회
		int result = new BoardService().deleteBoard(boardNo);
		
		if(result > 0) {
			
			// 첨부파일이 있다면
			if(at != null) {
				// 파일을 저장했던 물리적인 경로 알아내기
				String savePath = request.getSession().getServletContext()
									.getRealPath("/"+at.getFilePath());
				// board_upfiles 폴더내의 파일 삭제
				new File(savePath+at.getChangeName()).delete();
			}
			request.getSession().setAttribute("alertMsg", "게시글 삭제 성공");
			response.sendRedirect(request.getContextPath()+"/list.bo");
		}else {
			request.setAttribute("errorMsg", "게시글 삭제 실패");
			request.getRequestDispatcher("views/common/errorPage.jsp").forward(request, response);
		}
	}


	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doGet(request, response);
	}

}

 

 

 

■ BoardService.java

 

 

 

■ BoardDao.java

▶ 게시판 삭제 메소드

 

▶ 첨부파일 삭제 메소드