본문 바로가기
05_Server (04. JSP 프로그래밍 구현)

[2-5] 공지사항서비스 삭제요청

by moca7 2024. 9. 11.

 

 

 

ㅁ 공지사항서비스
- 공지사항서비스_목록조회요청
- 공지사항서비스_작성요청
- 공지사항서비스_수정요청
- 공지사항서비스_삭제요청

 

 

 

 

 

ㅁ 공지사항 목록페이지

 

 
<%@ page import="java.util.List" %>
<%@ page import="com.br.web.notice.model.vo.Notice" %>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
 
<%
  List<Notice> list = (List<Notice>)request.getAttribute("list");
%>
 
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>

  <div class="container p-3">

   <!-- Header, Nav start -->
   <%@ include file="/views/common/header.jsp" %>
   <!-- Header, Nav end -->

   <!-- Section start -->
   <section class="row m-3" style="min-height: 500px">

    <div class="container border p-5 m-4 rounded">

      <h2 class="m-4">공지사항 목록</h2>

      <% if(loginUser != null && loginUser.getStatus().equals("A")) { %>
      <div align="right">
        <a href="<%= contextPath %>/write.no" class="btn btn-secondary btn-sm">등록하기</a>
      </div>
      <% } %>

      <br>
      <table id="notice-list" class="table">
        <thead>
          <tr>
            <th width="100px">번호</th>
            <th width="600px">글제목</th>
            <th width="120px">작성자</th>
            <th>작성일</th>
          </tr>
        </thead>
        <tbody>
          <% if(list.isEmpty()) { %>
          <!-- case1. 조회된 공지글이 없을 경우 -->
          <tr>
            <td colspan="4" style="text-align:center">존재하는 공지사항글이 없습니다.</td>
          </tr>
          <% } else { %>
            <!-- case2. 조회된 공지글이 있을 경우 -->
            <% for(Notice n : list) { %>
            <tr class="board-title" data-toggle="collapse" data-target="#notice<%=n.getNoticeNo()%>">
              <td><%= n.getNoticeNo() %></td>
              <td><%= n.getNoticeTitle() %></td>
              <td><%= n.getNoticeWriter() %></td>
              <td><%= n.getRegistDt() %></td>
            </tr>
            <tr class="board-content collapse" id="notice<%=n.getNoticeNo()%>">
              <td colspan="4">
                <p class="border rounded p-3 w-75 mx-auto" style="min-height: 150px; white-space:pre;"><%= n.getNoticeContent() %></p>
               
                <% if(loginUser != null && loginUser.getUserId().equals(n.getNoticeWriter())) { %>
                <div align="center">
                  <a href="<%= contextPath %>/modify.no?no=<%= n.getNoticeNo() %>" class="btn btn-secondary btn-sm">수정하기</a>
                  <a href="<%= contextPath %>/delete.no?no=<%= n.getNoticeNo() %>" class="btn btn-danger btn-sm">삭제하기</a>
                </div>
               
                <% } %>
              </td>
            </tr>
            <% } %>
          <% } %>

        </tbody>
      </table>
     
     
    </div>

   </section>
   <!-- Section end -->

   <!-- Footer start -->
   <%@ include file="/views/common/footer.jsp" %>
   <!-- Footer end -->

 </div>

</body>
</html>
 

 

 

- 공지사항 목록페이지의 '삭제하기' 버튼을 <button> 태그에서 <a> 태그로 바꾸고,

href 속성에 "<%= contextPath %>/delete.no?no=<%= n.getNoticeNo() %>"을 준다.

- "/delete.no"라는 url mapping 값을 가지는 서블릿 클래스를 호출하면서, 삭제할 게시글의 글번호를 같이 넘긴다.

 

 

 

 

 

 

 

 

 

 

ㅁ /webApp/src/main/java/com/br/web/notice/controller에 NoticeDeleteController.java라는 서블릿 클래스를 만든다.

 

 
package com.br.web.notice.controller;

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.br.web.notice.model.service.NoticeService;


@WebServlet("/delete.no")
public class NoticeDeleteController extends HttpServlet {

    private static final long serialVersionUID = 1L;
       
    public NoticeDeleteController() {
        super();
    }


    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
   
        // 1. 요청
        int noticeNo = Integer.parseInt(request.getParameter("no"));
       
        int result = new NoticeService().deleteNotice(noticeNo);
 
       
        // 2. 응답
        if(result > 0) { // 성공
 
            request.getSession().setAttribute("alertMsg", "성공적으로 공지사항이 삭제되었습니다.");
            response.sendRedirect(request.getContextPath() + "/list.no");
           
        }else { // 실패
 
            request.setAttribute("msg", "공지사항 삭제 실패");
            request.getRequestDispatcher("/views/common/errorPage.jsp").forward(request, response);
        }
   
    }


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

}

 

 

- 요청시 전달값으로 글번호 하나 있다. 

request.getParameter로 뽑으면 무조건 문자열이기 때문에 int형 변수에 담고 싶으면 무조건 파싱해야한다.

- 이 글번호 하나만 service로 넘긴다.

 

 

 

 

ㅁ NoticeService.java에 deleteNotice() 메소드를 만든다.

 

 
package com.br.web.notice.model.service;

import java.sql.Connection;
import java.util.List;

import com.br.web.notice.model.dao.NoticeDao;
import com.br.web.notice.model.vo.Notice;

import static com.br.web.common.template.JDBCTemplate.getConnection;
import static com.br.web.common.template.JDBCTemplate.close;
import static com.br.web.common.template.JDBCTemplate.commit;
import static com.br.web.common.template.JDBCTemplate.rollback;

public class NoticeService {
   
    private NoticeDao nDao = new NoticeDao();
   
    public List<Notice> selectNoticeList(){
 
        Connection conn = getConnection();
        List<Notice> list = nDao.selectNoticeList(conn);
        close(conn);
        return list;
    }
   
    public int insertNotice(Notice n) {
 
        Connection conn = getConnection();
        int result = nDao.insertNotice(conn, n);
        if(result > 0) {
            commit(conn);
        }else {
            rollback(conn);
        }
        close(conn);
        return result;
    }
   
    public Notice selectNoticeByNo(int noticeNo) {
 
        Connection conn = getConnection();
        Notice n = nDao.selectNoticeByNo(conn, noticeNo);
        close(conn);
        return n;
    }
   
    public int updateNotice(Notice n) {
 
        Connection conn = getConnection();
        int result = nDao.updateNotice(conn, n);
        if(result > 0) {
            commit(conn);
        }else {
            rollback(conn);
        }
        close(conn);
        return result;
    }
   
    public int deleteNotice(int noticeNo) {
 
        Connection conn = getConnection();
        int result = nDao.deleteNotice(conn, noticeNo);
 
        if(result > 0) {
            commit(conn);
        }else {
            rollback(conn);
        }
 
        close(conn);
        return result;
    }
   

}

 

 

 

 

 

 

ㅁ NoticeDao.java에 deleteNotice() 메소드를 만든다.

 

 
package com.br.web.notice.model.dao;

import java.io.FileInputStream;
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

import com.br.web.notice.model.vo.Notice;

import static com.br.web.common.template.JDBCTemplate.close;

public class NoticeDao {
 
   
    private Properties prop = new Properties();
   
    public NoticeDao() {
 
        try {
            prop.loadFromXML(new FileInputStream(NoticeDao.class.getResource("/db/mappers/notice-mapper.xml").getPath()));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
 
   
    public List<Notice> selectNoticeList(Connection conn){

        // select => ResultSet (여러행, 여러Notice객체) => List<Notice>
        List<Notice> list = new ArrayList<>();
        PreparedStatement pstmt = null;
        ResultSet rset = null;
        String sql = prop.getProperty("selectNoticeList");
       
        try {
            pstmt = conn.prepareStatement(sql);
            rset = pstmt.executeQuery();
           
            while(rset.next()) {
                list.add(new Notice(rset.getInt("notice_no")
                                  , rset.getString("notice_title")
                                  , rset.getString("notice_content")
                                  , rset.getString("user_id")
                                  , rset.getDate("regist_date")));
            }
           
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            close(rset);
            close(pstmt);
        }
       
        return list;
       
    }
 
   
    public int insertNotice(Connection conn, Notice n) {

        // insert => 처리된 행수
        int result = 0;
        PreparedStatement pstmt = null;
        String sql = prop.getProperty("insertNotice");
       
        try {
            pstmt = conn.prepareStatement(sql);
            pstmt.setString(1, n.getNoticeTitle());
            pstmt.setString(2, n.getNoticeContent());
            pstmt.setString(3, n.getNoticeWriter());
           
            result = pstmt.executeUpdate();
           
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            close(pstmt);
        }
       
        return result;
       
    }
 
   
    public Notice selectNoticeByNo(Connection conn, int noticeNo) {

        // select => ResultSet (한행, 한개의 공지사항) => Notice
        Notice n = null;
        PreparedStatement pstmt = null;
        ResultSet rset = null;
        String sql = prop.getProperty("selectNoticeByNo");
       
        try {
            pstmt = conn.prepareStatement(sql);
            pstmt.setInt(1, noticeNo);
           
            rset = pstmt.executeQuery();
           
            if(rset.next()) {
                n = new Notice();
                n.setNoticeNo(rset.getInt("notice_no"));
                n.setNoticeTitle(rset.getString("notice_title"));
                n.setNoticeContent(rset.getString("notice_content"));
            }
           
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            close(rset);
            close(pstmt);
        }
       
        return n;
       
    }
 
   
    public int updateNotice(Connection conn, Notice n) {

        // update => 처리된 행수
        int result = 0;
        PreparedStatement pstmt = null;
        String sql = prop.getProperty("updateNotice");
       
        try {
            pstmt = conn.prepareStatement(sql);
            pstmt.setString(1, n.getNoticeTitle());
            pstmt.setString(2, n.getNoticeContent());
            pstmt.setInt(3, n.getNoticeNo());
           
            result = pstmt.executeUpdate();
           
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            close(pstmt);
        }
       
        return result;
    }
 
   
    public int deleteNotice(Connection conn, int noticeNo) {
       
        // update => 처리된 행수
        int result = 0;
        PreparedStatement pstmt = null;
 
        String sql = prop.getProperty("deleteNotice");
       
        try {
            pstmt = conn.prepareStatement(sql);
            pstmt.setInt(1, noticeNo);
            result = pstmt.executeUpdate();
           
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            close(pstmt);
        }
       
        return result;
    }
   

}

 

 

- 실제 쿼리는 update지만 기능을 따서 deleteNotice라고 메소드명을 지었다.

- executeUpdate()와 executeQuery() 메소드를 실행만한다고 끝이 아니고 result에 담아야 한다.

db에만 반영되고 처리된 행 수인 return은 안된다.

 

 

 

 

 

 

- notice-mapper.xml에 쿼리를 작성해놨다.

삭제 요청시 delete문이 아닌 update문으로 STATUS 컬럼의 값을 'Y'에서 'N'으로만 바꾼다.

- 조회 요청시 STATUS 컬럼의 값이 'Y'인 데이터만 가져온다.

 

 

 

 

 /webApp/src/main/java/com/br/web/notice/controller의 NoticeDeleteController.java로 돌아온다.

 

 

 

 
package com.br.web.notice.controller;

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.br.web.notice.model.service.NoticeService;


@WebServlet("/delete.no")
public class NoticeDeleteController extends HttpServlet {

    private static final long serialVersionUID = 1L;
       
    public NoticeDeleteController() {
        super();
    }


    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
   
        // 1. 요청
        int noticeNo = Integer.parseInt(request.getParameter("no"));
       
        int result = new NoticeService().deleteNotice(noticeNo);
 
 
       
        // 2. 응답
        if(result > 0) { // 성공
 
            request.getSession().setAttribute("alertMsg", "성공적으로 공지사항이 삭제되었습니다.");
            response.sendRedirect(request.getContextPath() + "/list.no");
           
        }else { // 실패
 
            request.setAttribute("msg", "공지사항 삭제 실패");
            request.getRequestDispatcher("/views/common/errorPage.jsp").forward(request, response);
        }
   
    }


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

}

 

 

 

- 실패 시에는 에러페이지로 이동하고 "공지사항 삭제 실패"라는 문자열을 request에 "msg"라는 key 값으로 담는다.

 

- 성공 시에는 응답페이지가 공지사항 목록페이지다.

이 목록페이지에는 내가 삭제 요청한 글이 보여져서는 안된다.

목록페이지를 갈 때는 db로부터 갱신된 데이터가 조회돼서 화면에 보여져야 한다.

- 그런데 여기서 직접 조회해서 forward로 이동하지 않고, 그걸 해주는 "/list.no"라는 url mapping 값을 가지는 서블릿 클래스를 재요청(redirect)한다.

 

 

 

ㅁ 서버 재시작, 브라우저 새로고침, 관리자로 로그인 후 공지사항 목록페이지에서 본인이 쓴 공지사항 게시글을 삭제할 수 있다.