[Spring] 게시판 CRUD 기능 구현: 읽기, 삭제

Jeini·2023년 5월 31일
0

🍃  Spring

목록 보기
25/33
post-thumbnail

💡 기능별 URI 정의


  • uri가 똑같이 /board/write이지만 http메서드를 통해 구별하였다.
  • 수정에서 post방식으로 오면 수정된 게시물을 데이터베이스에 저장한다.

💡 게시물 읽기 기능의 구현


✏️ 제목을 누르면 해당 정보를 보여줌 (읽기)

  1. boardList.jsp에서 제목을 클릭하면 제목에 걸려있는 링크에 따라서 요청이 간다. 게시물 번호가 같이 따라감

  2. BoardController의 read() 가 게시물 번호를 받아서 boardService.read(bno) 를 호출. 그럼 데이터베이스가 게시물을 하나 읽어와서 boardDto에 담아서 다시 Controller로 이동

  3. Controller의 read() 가 board.jsp에게 데이터셋을 읽어온 boardDto를 전달해줌.

  4. board.jsp는 ${boardDto.title} , ${boardDto.content} 를 읽어서 화면에 보여줌

✏️ 목록 버튼 구현

  1. 목록을 누르면 BoardController로 get요청이 감 ➡️ list() 호출

  2. boardService.getPage(map) 호출해서 한 페이지를 갖고 오게 됨

  3. 가져온 페이지를 Controller가 받고 boardService가 담아준 List를 boardList.jsp에 보냄

  • 이때, List만 보내는 것이 아니라, 사용자가 현재 페이지에 있었던 곳으로 보내줘야 한다. 예를 들어, 사용자가 3페이지에 내용을 확인하고 목록버튼을 눌렀으면, 우리는 사용자에게 3페이지의 목록 페이지를 보여줘야 한다.
    ➡️ 애초부터 BoardConroller가 boardList.jsp에게 pagepageSize 의 값을 받아와서 board.jsp에게 값을 보내줘야 한다.

💡 게시물 삭제 기능의 구현


  • 아무나 삭제하게 할 수 없으니까 작성자의 이름이 같아야 삭제하게 만든다.

  • 수정하고 삭제버튼은 보는 사람이 작성자일때만 보여줘야 된다.
    : remove(Interger bno, String id) 이렇게 로그인한 id도 넘겨줘서 writer로 검사해서 맞으면 삭제에 성공하게 만들어준다.

  • 게시물이 삭제된 다음에는 boardList.jsp로 간다. ➡️ redirect:/board/list 로 이동
    ➡️ 하지만 여기에서도 page와 pageSize의 값을 넘겨줘야 한다. 그래야 처음 왔던 페이지로 갈 수 있다.
    : redirect:/board/list?page=..&pageSize=..

✏️ 구현


✔️ BoardController에 read() 추가

package kr.ac.jipark09.Controller;

import kr.ac.jipark09.domain.*;
import kr.ac.jipark09.service.*;
import org.springframework.beans.factory.annotation.*;
import org.springframework.stereotype.*;
import org.springframework.ui.*;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.*;
import java.util.*;

@Controller
@RequestMapping("/board")
public class BoardController {
    @Autowired
    BoardService boardService;

    @GetMapping("/read")
    public String read(Integer bno, Model model) {
        try {
            BoardDto boardDto = boardService.read(bno);
            model.addAttribute(boardDto); // 앞글자가 소문자인 애로 key로 담아줌
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "board";
    }

    // 먼저 기본적으로 로그인 체크를 해준다. 누가 게시물을 썼는지 확인을 하기 위해
    @GetMapping("/list")
    public String list(Integer page, Integer pageSize, Model model, HttpServletRequest request) {
        if(!loginCheck(request))
            return "redirect:/login/login?toURL=" + request.getRequestURL();  // 로그인을 안했으면 로그인 화면으로 이동

        if(page == null) {
            page = 1;
        }
        if(pageSize == null) {
            pageSize = 10;
        }

        try {
            // pageHandler 활용
            int totalCnt = boardService.getCount();
            PageHandler pageHandler = new PageHandler(totalCnt, page, pageSize);

            // page, pageSize를 파라미터로 받아서 offset과 pageSize를 map에 저장
            Map map = new HashMap();
            map.put("offset", (page - 1) * pageSize);
            map.put("pageSize", pageSize);

            List<BoardDto> list = boardService.getPage(map);
            model.addAttribute("list", list); // jsp로 보냄
            model.addAttribute("ph", pageHandler); // jsp에서 pageHandler를 가지고 페이지를 나타냄

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
        }


        return "boardList"; // 로그인을 한 상태이면, 게시판 화면으로 이동
    }

    private boolean loginCheck(HttpServletRequest request) {
        // 1. 세션을 얻어서
        HttpSession session = request.getSession();
        // 2. 세션에 id가 있는지 확인, 있으면 true를 반환
        return session.getAttribute("id")!=null;
    }
}

✔️ board.jsp 생성

<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>JTI HomePage</title>
    <link rel="stylesheet" href="<c:url value='/css/menu.css'/>">
</head>
<body>
<div id="menu">
    <ul>
        <li id="logo">JTI</li>
        <li><a href="<c:url value='/'/>">Home</a></li>
        <li><a href="<c:url value='/board/list'/>">Board</a></li>
        <li><a href="<c:url value='/login/login'/>">login</a></li>
        <li><a href="<c:url value='/register/add'/>">Sign in</a></li>
        <li><a href=""><i class="fas fa-search small"></i></a></li>
    </ul>
</div><div style="text-align:center">
    <h2>게시물 읽기</h2>
    <form action="" id="form">
        <input type="text" name="bno" value="${boardDto.bno}" readonly>
        <input type="text" name="title" value="${boardDto.title}" readonly>
        <textarea name="content" id="", cols="30" rows="10" readonly>${boardDto.content}</textarea>
        <button type="button" id="writeBtn" class="btn">등록</button>
        <button type="button" id="modifyBtn" class="btn">수정</button>
        <button type="button" id="removeBtn" class="btn">삭제</button>
        <button type="button" id="listBtn" class="btn">목록</button>
    </form>
</div>
</body>
</html>

  • 틀 완성!

✔️ 링크 걸기: 해당하는 페이지로 넘어가기

✏️ boardList.jsp의 title에 링크를 걸어준다.

 <td><a href="<c:url value='/board/read?bno=${board.bno}&page=${page}&pageSize=${pageSize}'/>">${board.title}</a></td>

✏️ BoardController의 list(), list()에 파라미터 page와 pageSize를 받고 모델에 저장

package kr.ac.jipark09.Controller;

import kr.ac.jipark09.domain.*;
import kr.ac.jipark09.service.*;
import org.springframework.beans.factory.annotation.*;
import org.springframework.stereotype.*;
import org.springframework.ui.*;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.*;
import java.util.*;

@Controller
@RequestMapping("/board")
public class BoardController {
    @Autowired
    BoardService boardService;

    @GetMapping("/read")
    public String read(Integer bno, Integer page, Integer pageSize, Model model) {
        try {
            BoardDto boardDto = boardService.read(bno);
            model.addAttribute(boardDto); // 앞글자가 소문자인 애로 key로 담아줌
            model.addAttribute("page", page);
            model.addAttribute("pageSize", pageSize);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "board";
    }

    // 먼저 기본적으로 로그인 체크를 해준다. 누가 게시물을 썼는지 확인을 하기 위해
    @GetMapping("/list")
    public String list(Integer page, Integer pageSize, Model model, HttpServletRequest request) {
        if(!loginCheck(request))
            return "redirect:/login/login?toURL=" + request.getRequestURL();  // 로그인을 안했으면 로그인 화면으로 이동

        if(page == null) {
            page = 1;
        }
        if(pageSize == null) {
            pageSize = 10;
        }

        try {
            // pageHandler 활용
            int totalCnt = boardService.getCount();
            PageHandler pageHandler = new PageHandler(totalCnt, page, pageSize);

            // page, pageSize를 파라미터로 받아서 offset과 pageSize를 map에 저장
            Map map = new HashMap();
            map.put("offset", (page - 1) * pageSize);
            map.put("pageSize", pageSize);

            List<BoardDto> list = boardService.getPage(map);
            model.addAttribute("list", list); // jsp로 보냄
            model.addAttribute("ph", pageHandler); // jsp에서 pageHandler를 가지고 페이지를 나타냄
            model.addAttribute("page", page);
            model.addAttribute("pageSize", pageSize);
        } catch (Exception e) {
            e.printStackTrace();
        }


        return "boardList"; // 로그인을 한 상태이면, 게시판 화면으로 이동
    }

    private boolean loginCheck(HttpServletRequest request) {
        // 1. 세션을 얻어서
        HttpSession session = request.getSession();
        // 2. 세션에 id가 있는지 확인, 있으면 true를 반환
        return session.getAttribute("id")!=null;
    }
}

✔️ 목록 버튼 구현: 제이쿼리 사용

✏️ jQuery 홈페이지 이동

: https://jquery.com/

  • 페이지 소스 보기 ㄱㄱ

  • 해당 줄 복사

✏️ board.jsp head에다 붙여넣기

<head>
    <meta charset="UTF-8">
    <title>JTI HomePage</title>
    <link rel="stylesheet" href="<c:url value='/css/menu.css'/>">
    <script src="https://code.jquery.com/jquery-1.11.3.js"></script>
</head>
  • 이렇게 붙여놓으면 해당 jsp에서 제이쿼리를 쓸 수 있게 된다.

  • 하지만 그대로 쓰면 인터넷에서 가져온거라서 느릴 수도 있으니까 Download library 해준다.
    ➡️ 잘 안되가지고 걍 함;;

✏️ board.jsp에 제이쿼리를 활용하여 링크 걸기

<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>JTI HomePage</title>
    <link rel="stylesheet" href="<c:url value='/css/menu.css'/>">
    <script src="https://code.jquery.com/jquery-1.11.3.js"></script>
</head>
<body>
<div id="menu">
    <ul>
        <li id="logo">JTI</li>
        <li><a href="<c:url value='/'/>">Home</a></li>
        <li><a href="<c:url value='/board/list'/>">Board</a></li>
        <li><a href="<c:url value='/login/login'/>">login</a></li>
        <li><a href="<c:url value='/register/add'/>">Sign in</a></li>
        <li><a href=""><i class="fas fa-search small"></i></a></li>
    </ul>
</div><div style="text-align:center">
    <h2>게시물 읽기</h2>
    <form action="" id="form">
        <input type="text" name="bno" value="${boardDto.bno}" readonly>
        <input type="text" name="title" value="${boardDto.title}" readonly>
        <textarea name="content" id="", cols="30" rows="10" readonly>${boardDto.content}</textarea>
        <button type="button" id="writeBtn" class="btn">등록</button>
        <button type="button" id="modifyBtn" class="btn">수정</button>
        <button type="button" id="removeBtn" class="btn">삭제</button>
        <button type="button" id="listBtn" class="btn">목록</button>
    </form>
</div>
<script>
    $(document).ready(function () { // main(): html 문서가 다 준비되었으면 메서드 실행
        // button의 listBtn을 참조하겠다는 의미
        $('#listBtn').on("click", function () { // 클릭하면 어떤 일을 할지 적어줌
            // location: 브라우저 창에 url 주소 치는 영역을 의미함 -> get으로 보냄
            location.href = "<c:url value='/board/list'/>?page=${page}&pageSize=${pageSize}";
        });
    });
</script>
</body>
</html>

scipt.. 상당히 어렵다 ㅜㅜ java에 익숙한 나로써는 ...

  • $(document).ready ➡️ java의 main() 와 비슷.
    : 위에 코드가 준비가 다 되었으면 이 메서드를 실행한다.

  • $('#listBtn').on("click", function () ..
    : 클릭하면 어떤 일을 할지 적어줌 (javascript의 onclick 메서드)

  • location
    : 브라우저 창에 url 주소 치는 영역을 의미. 그냥 홈페이지 url에 주소 친거랑 똑같음
    ➡️ get으로 보냄

✔️ 삭제 기능 넣기

✏️ BoardController에 remove 메서드 생성

	@PostMapping("/remove")
    public String remove(Integer bno, Integer page, Integer pageSize, Model model, HttpSession session) {
        String writer = (String) session.getAttribute("id");
        try {
            boardService.remove(bno, writer);
        } catch (Exception e) {
            e.printStackTrace();
        }

        model.addAttribute("page", page);
        model.addAttribute("pageSize", pageSize);
        //redirect:/board/list?page=..&pageSize=.. 와 마찬가지

        return "redirect:/board/list";
    }

✏️ Board.jsp script 제이쿼리 메서드 삭제 추가

<script>
    $(document).ready(function () { // main(): html 문서가 다 준비되었으면 메서드 실행
        // button의 listBtn을 참조하겠다는 의미
        $('#listBtn').on("click", function () { // 클릭하면 어떤 일을 할지 적어줌
            // location: 브라우저 창에 url 주소 치는 영역을 의미함 -> get으로 보냄
            location.href = "<c:url value='/board/list'/>?page=${page}&pageSize=${pageSize}";
        });

        $('#removeBtn').on("click", function () {
            if(!confirm("정말로 삭제하시겠습니까?")) {
               	return; // yes가 아니면 빠져나감
            }
            // post로 처리해야 함
            let form = $('#form'); // id가 form인 애를 넣어서 변수로 담음
            form.attr("action", "<c:url value='/board/remove'/>?page=${page}&pageSize=${pageSize}"); // form의 action 설정
            form.attr("method", "post");
            form.submit();
        });
    });

</script>
  • 삭제에서는 post로 보내줘야 하기 때문에 form 설정을 바꿈

  • 정말로 삭제하시겠습니까? 추가

✔️ 삭제되면 잘 삭제 되었다고 메세지 추가 + 작성자가 아닌 사람이 삭제할 시 메세지 + 새로고침했을 때 메세지 반복적으로 안 뜨게 하기

✏️ BoardController remove 수정

	@PostMapping("/remove")
    public String remove(Integer bno, Integer page, Integer pageSize, Model model, HttpSession session, RedirectAttributes rettr) {
        String writer = (String) session.getAttribute("id");
        try {
            model.addAttribute("page", page);
            model.addAttribute("pageSize", pageSize);
            //redirect:/board/list?page=..&pageSize=.. 와 마찬가지

            int rowcount = boardService.remove(bno, writer);
            // 잘 삭제 되었으면 delect ok 메세지 보냄
            if(rowcount == 1) {
                rettr.addFlashAttribute("msg", "delect ok!");
                return "redirect:/board/list";

            } else {
                rettr.addFlashAttribute("msg", "Writer does not match.");
                return "redirect:/board/list";
            }
        } catch (Exception e) {
            e.printStackTrace();
            rettr.addFlashAttribute("msg", "delect Error!");
        }
        
        return "redirect:/index";
    }
  • RedirectAtrributes.addFlashAttribute("msg", String)
    : 메시지가 한번만 나옴. 일회성이라서 한번 쓰고 없어진다.
    : session을 잠깐 저장했다가 쓰고 바로 지워버림. session에 부담가지 않는다.

✏️ BoardList.jsp 수정

<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>JTI HomePage</title>
    <link rel="stylesheet" href="<c:url value='/css/menu.css'/>">
</head>
<body>
<div id="menu">
    <ul>
        <li id="logo">JTI</li>
        <li><a href="<c:url value='/'/>">Home</a></li>
        <li><a href="<c:url value='/board/list'/>">Board</a></li>
        <li><a href="<c:url value='/login/login'/>">login</a></li>
        <li><a href="<c:url value='/register/add'/>">Sign in</a></li>
        <li><a href=""><i class="fas fa-search small"></i></a></li>
    </ul>
</div>
<script>
    let msg = "${msg}"
    if(msg == "delect ok!") {
        alert("성공적으로 삭제되었습니다.");
    } else if(msg == "Writer does not match.") {
        alert("작성자만 삭제 가능합니다.")
    }
</script>
<div style="text-align:center">
    <table border="1">
        <tr>
            <th>번호</th>
            <th>제목</th>
            <th>이름</th>
            <th>등록일</th>
            <th>조회수</th>
        </tr>
        <c:forEach var="boardDto" items="${list}">
        <tr>
            <td>${boardDto.bno}</td>
            <td><a href="<c:url value='/board/read?bno=${boardDto.bno}&page=${page}&pageSize=${pageSize}'/>">${boardDto.title}</a></td>
            <td>${boardDto.writer}</td>
            <td>${boardDto.reg_date}</td>
            <td>${boardDto.view_cnt}</td>
        </tr>
        </c:forEach>
    </table>
    <br>
    <div>
        <c:if test="${ph.showPrev}">
            <a href="<c:url value='/board/list?page=${ph.beginPage - 1}&pageSize=${ph.pageSize}'/>">&lt;</a>
        </c:if>
        <c:forEach var="i" begin="${ph.beginPage}" end="${ph.endPage}">
            <a href="<c:url value='/board/list?page=${i}&pageSize=${ph.pageSize}'/>">${i}</a>
        </c:forEach>
        <c:if test="${ph.showNext}">
            <a href="<c:url value='/board/list?page=${ph.endPage + 1}&pageSize=${ph.pageSize}'/>">&gt;</a>
        </c:if>
    </div>
</div>
</body>
</html>

Reference
: https://fastcampus.co.kr/dev_academy_nks

profile
Fill in my own colorful colors🎨

0개의 댓글