게시판 리스트에서 게시물의 제목을 클릭하면 해당 게시물의 상세 페이지가 보이도록 하고자 한다.
webapp > board > detail.jsp 파일을 생성하고 상세 페이지가 어떻게 보였으면 하는지 구성을 먼저 잡는다.
게시물 수정과 삭제는 작성자와 로그인 id가 같을 때 가능하도록 <c:if> 태그를 추가했다.
detail.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>자유 게시판</title>
</head>
<body>
<h1>상세 페이지</h1>
<table>
<tr>
<th>제목</th>
<td>${bvo.title }</td>
</tr>
<tr>
<th>작성자</th>
<td>${bvo.writer }</td>
</tr>
<tr>
<th>작성일</th>
<td>${bvo.regdate }</td>
</tr>
<tr>
<th>조회수</th>
<td>${bvo.readcount }</td>
</tr>
<tr>
<th>내용</th>
<td>${bvo.content }</td>
</tr>
<tr>
<th>수정일</th>
<td>${bvo.moddate }</td>
</tr>
</table>
<a href="/brd/register"><button>글쓰기</button></a>
<!-- 만약 로그인id와 작성자가 같다면... -->
<c:if test="${ses.id eq bvo.writer }">
<a href="#"><button>수정</button></a>
<a href="#"><button>삭제</button></a>
</c:if>
<a href="/brd/list"><button>목록</button></a>
</body>
</html>
상세 페이지를 열려면 상세 내용을 보고자하는 게시물의 bno 값을 받아와서 데이터를 뿌려야하는데,
이 값은 게시판 리스트에서 게시물을 클릭했을 때 받아와야한다.
그러므로 list.jsp에서 제목을 눌렀을 때 bno 값을 받아 올 수 있도록 코드를 추가한다.
<a href="/brd/detail?bno=${bvo.bno }">${bvo.title }</a>
list.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>자유게시판</title>
</head>
<body>
<h1>자유게시판</h1>
<!-- ... (기존 코드) -->
<table>
<tr>
<th>No</th>
<th>제목</th>
<th>작성자</th>
<th>작성일</th>
<th>조회수</th>
</tr>
<!-- DB에서 가져온 리스트를 c:forEach를 통해 반복
var="bvo"는 BoardVO 객체를 참조한다. -->
<c:forEach items="${list}" var="bvo">
<tr>
<td>${bvo.bno }</td>
<td><a href="/brd/detail?bno=${bvo.bno }">${bvo.title }</a></td>
<td>${bvo.writer }</td>
<td>${bvo.regdate }</td>
<td>${bvo.readcount }</td>
</tr>
</c:forEach>
</table>
<!-- ...(기존 코드) -->
</body>
</html>
이제 controller로 돌아가 case detail을 추가하고 관련 코드를 작성하고 순차적으로 mapper까지 진행한다.
BoardController.java
package controller;
import java.io.IOException;
import java.util.List;
import javax.servlet.RequestDispatcher;
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 javax.servlet.http.HttpSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import domain.BoardVO;
import domain.MemberVO;
import domain.PagingVO;
import handler.PagingHandler;
import service.BoardService;
import service.BoardServiceImpl;
@WebServlet("/brd/*")
public class BoardController extends HttpServlet {
// ... (기존 코드)
case "detail":
try {
// list.jsp에서 bno 값 가져오기
int bno = Integer.parseInt(request.getParameter("bno"));
log.info(">>> detail check1");
BoardVO bvo = bsv.getDetail(bno);
log.info(">>> bvo >>> {}", bvo);
// detail.jsp에 해당 bno 정보 뿌리기
request.setAttribute("bvo", bvo);
destPage = "/board/detail.jsp";
} catch (Exception e) {
log.info(">>> detail error");
e.printStackTrace();
}
}
// ... (기존 코드)
}
BoardService.interface
package service;
import java.util.List;
import domain.BoardVO;
import domain.PagingVO;
public interface BoardService {
List<BoardVO> getList(PagingVO pgvo);
int getTotal(PagingVO pgvo);
int insert(BoardVO bvo);
BoardVO getDetail(int bno);
}
BoardServiceImpl.java
package service;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import domain.BoardVO;
import domain.PagingVO;
import repository.BoardDAO;
import repository.BoardDAOImpl;
public class BoardServiceImpl implements BoardService {
// ... (기존 코드)
@Override
public BoardVO getDetail(int bno) {
log.info(">>> detail check 2");
return bdao.getDetail(bno);
}
}
BoardDAO.interface
package repository;
import java.util.List;
import domain.BoardVO;
import domain.PagingVO;
public interface BoardDAO {
List<BoardVO> selectList(PagingVO pgvo);
int getTotal(PagingVO pgvo);
int insert(BoardVO bvo);
BoardVO getDetail(int bno);
}
BoardDAOImpl.java
package repository;
import java.util.List;
import org.apache.ibatis.session.SqlSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import domain.BoardVO;
import domain.PagingVO;
import orm.DatabaseBuilder;
public class BoardDAOImpl implements BoardDAO {
// ... (기존 코드)
@Override
public BoardVO getDetail(int bno) {
log.info(">>> detail check3");
return sql.selectOne("BoardMapper.detail", bno);
}
}
boardMapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="BoardMapper">
<!-- ... (기존 코드) -->
<select id="detail" resultType="bvo">
select * from board where bno = #{bno}
</select>
<!-- 예비구문 -->
<!-- ... (기존 코드) -->
</mapper>
상세페이지 화면
상세 페이지 화면뿐 아니라 글쓰기와 목록 버튼도 제대로 작동되는지 확인해야 한다.
상세 페이지에 데이터가 정상적으로 출력되고 이미 구현된 기능이 부여된 버튼들의 작동을 확인했다면
삭제 기능까지 코드를 추가하도록 하자.
controller에 작성하기 전에 detail.jsp에 삭제 버튼의 a태그에 코드를 추가했다.
삭제도 상세 페이지와 마찬가지로 삭제하고자 하는 그 게시물만 지워야 하기 때문에
detail.jsp에서 bno 값을 받아 올 수 있게 해야한다.
<a href="/brd/remove?bno=${bvo.bno }"><button>삭제</button></a>
detail.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>자유 게시판</title>
</head>
<body>
<!-- ... (기존 코드) -->
<a href="/brd/register"><button>글쓰기</button></a>
<!-- 만약 로그인id와 작성자가 같다면... -->
<c:if test="${ses.id eq bvo.writer }">
<a href="#"><button>수정</button></a>
<a href="/brd/remove?bno=${bvo.bno }"><button>삭제</button></a>
</c:if>
<a href="/brd/list"><button>목록</button></a>
</body>
</html>
jsp에 remove로 선언을 해줬기 때문에 controller에 case remove로 코드를 작성하고
순차적으로 mapper까지 진행한다.
BoardController.java
package controller;
import java.io.IOException;
import java.util.List;
import javax.servlet.RequestDispatcher;
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 javax.servlet.http.HttpSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import domain.BoardVO;
import domain.MemberVO;
import domain.PagingVO;
import handler.PagingHandler;
import service.BoardService;
import service.BoardServiceImpl;
@WebServlet("/brd/*")
public class BoardController extends HttpServlet {
// ... (기존 코드)
case "detail":
try {
// list.jsp에서 bno 값 가져오기
int bno = Integer.parseInt(request.getParameter("bno"));
log.info(">>> detail check1");
BoardVO bvo = bsv.getDetail(bno);
log.info(">>> bvo >>> {}", bvo);
// detail.jsp에 해당 bno 정보 뿌리기
request.setAttribute("bvo", bvo);
destPage = "/board/detail.jsp";
} catch (Exception e) {
log.info(">>> detail error");
e.printStackTrace();
}
break;
case "remove":
try {
// detail.jsp에서 bno 값 받아오기
int bno = Integer.parseInt(request.getParameter("bno"));
isOk = bsv.remove(bno);
log.info(">>> remove check1");
log.info(">>> remove >>> " + (isOk > 0 ? "OK" : "FAIL"));
destPage = "list";
} catch (Exception e) {
log.info(">>> remove error");
e.printStackTrace();
}
}
// ... (기존 코드)
}
BoardService.interface
package service;
import java.util.List;
import domain.BoardVO;
import domain.PagingVO;
public interface BoardService {
List<BoardVO> getList(PagingVO pgvo);
int getTotal(PagingVO pgvo);
int insert(BoardVO bvo);
BoardVO getDetail(int bno);
int remove(int bno);
}
BoardServiceImpl.java
package service;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import domain.BoardVO;
import domain.PagingVO;
import repository.BoardDAO;
import repository.BoardDAOImpl;
public class BoardServiceImpl implements BoardService {
// ... (기존 코드)
@Override
public int remove(int bno) {
log.info(">>> remove check 2");
return bdao.delete(bno);
}
}
BoardDAO.interface
package repository;
import java.util.List;
import domain.BoardVO;
import domain.PagingVO;
public interface BoardDAO {
List<BoardVO> selectList(PagingVO pgvo);
int getTotal(PagingVO pgvo);
int insert(BoardVO bvo);
BoardVO getDetail(int bno);
int delete(int bno);
}
BoardDAOImpl.java
package repository;
import java.util.List;
import org.apache.ibatis.session.SqlSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import domain.BoardVO;
import domain.PagingVO;
import orm.DatabaseBuilder;
public class BoardDAOImpl implements BoardDAO {
// ... (기존 코드)
@Override
public BoardVO getDetail(int bno) {
log.info(">>> detail check3");
return sql.selectOne("BoardMapper.detail", bno);
}
@Override
public int delete(int bno) {
log.info(">>> remove check3");
int isOk = sql.delete("BoardMapper.del", bno);
if(isOk > 0) sql.commit();
return isOk;
}
}
boardMapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="BoardMapper">
<!-- ... (기존 코드) -->
<select id="detail" resultType="bvo">
select * from board where bno = #{bno}
</select>
<delete id="del">
delete from board where bno = #{bno}
</delete>
<!-- ... (기존 코드) -->
</mapper>
게시물 삭제 전 화면
게시물 삭제 후 화면
DB에도 게시물이 삭제 되었는지 꼭 확인해야 된다.
DAOImpl에서 commit 명령문을 깜빡하면 화면에서는 지워진 것처럼 보이는데
DB에는 삭제가 안되어서 다시 리스트에 등장하기 때문이다.
삭제만이 아니라 DAOImpl에서 commit을 요하는 insert / delete/ update와 같이
데이터에 변동을 주는 기능을 구현할 때는 DB도 꼭! 반드시! 확인하도록
[JSP/Servlet] 10. 게시글 상세페이지와 삭제
(다음 게시물 예고편)
[JSP/Servlet] 11. 게시글 상세 페이지 - 수정
얼렁뚱땅 주니어 개발자
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!