게시판 프로젝트 맛보기 : https://pabeba.tistory.com/173
프로젝트 진행 과정을 보여드렸고 이제는 맛보기에서 말한 방법으로 직접 프로그램을 제작하면서 게시판을 만들어보려고 합니다.
데이터베이스나 UML 등은 미리 만들어 놓았으니 이제는 코드를 작성해보려고 합니다. 위의 글을 읽고 오시면 더 이해가 잘 되실 겁니다.
그리고 기본적인 세팅 같은 것은 앞서 작성한 글들에 있으니까 확인해 보시면 더욱 이해가 잘 되실 겁니다.
1. 게시판 리스트 정보 확인
회원과 비회원 모두 리스트 정보를 볼 수 있습니다. 또한 게시판의 첫 모습이 게시글들의 리스트이기 때문에 이 기능부터 제작해 보겠습니다.
테이블은 이렇게 제작하였으니
구현의 순서
1. sql 작성을 통해 데이터 CRUD 테스트
2. 테스트 케이스를 작성하여 DAO 메서드 및 함수 실행 진행
3. Controller를 생성하여 request 응답
-> View와 Controller 생성
1. SQL 제작
먼저 리스트를 불러올 sql 문을 제작해 볼까요?
SELECT b.no, b.title, m.name, to_char(time_posted,'YYYY.MM.DD') AS time_posted , b.hits
FROM board b
INNER JOIN community_member m ON b.id=m.id
ORDER BY b.no DESC
JOIN 문을 이용하여 역순으로 게시글들을 불러오는 문장입니다.
2. Test Case 제작
public class TestUnitFindPostList {
public static void main(String[] args) {
try {
ArrayList<PostVO> list = BoardDAO.getInstance().findPostList();
for(PostVO pvo:list)
System.out.println(pvo);
} catch (Exception e) {
e.printStackTrace();
}
}
}
public ArrayList<PostVO> findPostList() throws SQLException {
Connection con=null;
PreparedStatement pstmt=null;
ResultSet rs=null;
ArrayList<PostVO> list=new ArrayList<>();
try {
con=dataSource.getConnection();// dbcp 로부터 컨넥션을 빌려온다
StringBuilder sql=new StringBuilder();
sql.append("SELECT b.no, b.title, m.name, to_char(time_posted,'YYYY.MM.DD') AS time_posted , b.hits ");
sql.append("FROM board b ");
sql.append("INNER JOIN community_member m ON b.id=m.id ");
sql.append("ORDER BY b.no DESC ");
pstmt=con.prepareStatement(sql.toString());
rs=pstmt.executeQuery();
while(rs.next()) {
PostVO pvo=new PostVO();
pvo.setNo(rs.getLong("no"));
pvo.setTitle(rs.getString("title"));
MemberVO mvo=new MemberVO();
mvo.setName(rs.getString("name"));
pvo.setMemberVO(mvo);
pvo.setTimePosted(rs.getString("time_posted"));
pvo.setHits(rs.getLong("hits"));
list.add(pvo);
}
}finally {
closeAll(rs, pstmt, con);//컨넥션을 database connection pool에 반납한다
}
return list;
}
1. ArrayList를 받아오는 findPostList 메서드를 제작합니다.
2. 위에서 작성한 sql 문을 이용하여 preparedStatement를 만들고 실행합니다.
3. ArrayList에 PostVO를 담아서 보내줍니다.
4. 받은 List의 값이 잘 나오는지 확인하면 테스트는 끝이 납니다.
위의 내용이 잘 나오게 된다면 그 이후에는 Controller를 만들면서 http 통신을 직접 해봅니다.
3. Controller 제작
public class FindPostListController implements Controller {
@Override
public String handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
request.setAttribute("list", BoardDAO.getInstance().findPostList());
request.setAttribute("url", "board/list.jsp");
return "layout.jsp";
}
}
리스트를 보여주는 컨트롤러에 대한 설명을 하겠습니다.
Layout 관련 글 : https://pabeba.tistory.com/174
1. 요청에 list를 담아서 보내줍니다.
2. 요청에 url을 담아서 보내줍니다.
3. layout.jsp로 이동을 하게 해서 board/list.jsp 파일을 실행하게 해 줍니다.
아래는 url에 담은 jsp파일입니다.
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<table class="table table-boarderd table-hover boardlist">
<thead>
<tr style="background-color: #ccffee">
<th>번호</th>
<th class="title">제목</th>
<th>작성자</th>
<th>작성일</th>
<th>조회</th>
</tr>
</thead>
<tbody>
<c:forEach items="${list}" var="post">
<tr>
<td>${post.no}</td>
<td>
<c:choose>
<c:when test="${sessionScope.mvo==null}">
${post.title}
</c:when>
<c:otherwise>
<a href="FindPostByNo.do?no=${post.no}">${post.title}</a>
</c:otherwise>
</c:choose>
</td>
<td>${post.memberVO.name}</td>
<td>${post.timePosted}</td>
<td>${post.hits}</td>
</tr>
</c:forEach>
</tbody>
</table>
잘 작성해 보면 이런 식으로 리스트가 나오게 됩니다.
다음은 글을 보기 위해서 로그인을 해야 하는데, header에 로그인을 만들면서 로그인을 할 수 있게 만들어 봅니다.
2. 로그인
1. SQL 제작
SELECT name FROM community_member WHERE id=? AND password=?
아이디 비밀번호 둘 다 맞아야 값을 가져올 수 있습니다.
2. Test Case 제작
public class TestMemberLogin {
public static void main(String[] args) {
try {
String id="java";
String password="a2";
MemberVO mvo=MemberDAO.getInstance().login(id,password);
if(mvo==null)
System.out.println("로그인 실패");
else
System.out.println("로그인 성공:"+mvo);
}catch (Exception e) {
e.printStackTrace();
}
}
}
public MemberVO login(String id, String password) throws SQLException {
Connection con=null;
PreparedStatement pstmt=null;
ResultSet rs=null;
MemberVO mvo=null;
try {
con=dataSource.getConnection();
String sql="SELECT name FROM community_member WHERE id=? AND password=?";
pstmt=con.prepareStatement(sql);
pstmt.setString(1, id);
pstmt.setString(2, password);
rs=pstmt.executeQuery();
if(rs.next())
mvo=new MemberVO(id, password, rs.getString(1));
}finally {
closeAll(rs, pstmt, con);
}
return mvo;
}
1. MemberDAO에 로그인 메서드를 제작합니다.
2. 테스트해 보고 Controller를 제작합니다.
3. Controller 제작
public class LoginController implements Controller {
@Override
public String handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
//System.out.println(request.getMethod());
if(request.getMethod().equals("POST")==false)
throw new ServletException("POST METHOD 방식만 로그인 가능합니다");
String id=request.getParameter("id");
String password=request.getParameter("password");
MemberVO mvo=MemberDAO.getInstance().login(id, password);
if(mvo==null) {
return "redirect:member/login-fail.jsp";
}else {
HttpSession session=request.getSession();
session.setAttribute("mvo", mvo);
//조회수 증가 방지를 위해 조회한 커뮤니티 게시글번호를 저장할 리스트를 세션에 저장한다
session.setAttribute("communityBoardNoList", new ArrayList<Long>());
return "redirect:FindPostList.do";
}
}
}
1. Post 요청이 아니면 에러를 발생시킵니다.
2. id, password 값을 받아와 로그인 메서드를 실행합니다.
3. mvo의 값이 없으면 로그인 실패 jsp 파일로 이동하고, 아니면 session에 mvo를 잘 담아서 게시물 리스트 페이지로 이동합니다.
4. 로그인이 잘 되면 header에 홈 글쓰기 사용자의 이름이 나타나게 됩니다.
header.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<c:choose>
<c:when test="${sessionScope.mvo==null}">
<form action="${pageContext.request.contextPath}/Login.do" method="post">
<input type="text" name="id" placeholder="아이디" required="required" size="12">
<input type="password" name="password" placeholder="패스워드" required="required" size="12">
<button type="submit">로그인</button>
</form>
</c:when>
<c:otherwise>
<a href="${pageContext.request.contextPath}/FindPostList.do">홈</a>
<!-- <a href="WritePostFormController.do">글쓰기</a> -->
<a href="${pageContext.request.contextPath}/WritePostForm.do">글쓰기</a>
${sessionScope.mvo.name}님
<a href="javascript:logout()">로그아웃</a>
<form method="post" action="${pageContext.request.contextPath}/Logout.do" id="logoutForm"></form>
<script>
function logout() {
if(confirm("로그아웃 하시겠습니까?")){
document.getElementById("logoutForm").submit();
}
}
</script>
</c:otherwise>
</c:choose>
세션이 있으면 로그인 폼이 나타나고 세션이 없으면 홈, 글쓰기, 로그아웃 버튼이 생성됩니다.
또한 세션이 생기기 때문에 리스트를 클릭하면 상세페이지로 갈 수 있게 되었습니다. (물론 아직 상세페이지는 만들지 않았지만요.)
3. 로그아웃
로그아웃 기능은 따로 데이터베이스에 접근하지 않기 때문에 controller만 제작하면 됩니다.
public class LogoutController implements Controller{
@Override
public String handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
if(request.getMethod().equals("POST")==false)
throw new ServletException("로그아웃 서비스는 POST방식만 가능합니다");
HttpSession session=request.getSession(false);
if(session!=null)
session.invalidate();
return "redirect:FindPostList.do";
}
}
1. 로그아웃기능은 세션을 찾아서 세션이 있으면 invalidate 메서드를 이용해서 세션을 없애면 됩니다.
2. 없앤 후에는 다시 게시물 리스트페이지로 이동시킵니다.
다음 시간에는 리스트페이지에서 글을 누르면 상세페이지를 볼 수 있게 상세페이지 관련 내용 작성도 해보고 게시물 수정, 삭제도 알아보겠습니다.
소감
최근에 프로젝트를 하느라 조금은 바빠서 블로그를 자주 작성하지 못하고 있습니다. 더 좋은 자료를 올려드리고 싶은데 제가 하는 프로젝트는 아직 아기 프로젝트라 지금까지 배운 것을 써먹는 것이라 무엇을 올릴지 고민하다가 지금 프로젝트의 발판인 게시판 만들기를 업로드하게 되었습니다. 잘 봐주시길 바랍니다.
그리고 최근에 말과 관련해서 좋은 글이 있어서 남기고 갑니다.
타인의 나쁜 점을 말한다는 것은 언제나 자기 자신에게 손해를 가지고 온다는 사실을 기억하라.
명심하고 또 명심해야겠습니다. 이렇게 행동하면 적을 만들지 않을 수 있고, 괜한 에너지를 빼앗기지 않아서 좋다고 생각합니다.
저 말을 거꾸로 생각하면 '타인의 좋은 점을 말하고 다니면 언젠가는 자기 자신에게 이익을 가지고 온다'가 될 것입니다.
존중받고 존경받고 싶으면 타인을 존경하고 존중하는 자세를 가져야겠습니다.
'코딩 개발 > Java' 카테고리의 다른 글
게시판 만들기 3 (게시글 수정, 게시글 삭제) (0) | 2023.06.28 |
---|---|
게시판 만들기 2 (게시물 상세 페이지, 게시물 작성) (0) | 2023.06.27 |
Pagination (페이지 매기기) (0) | 2023.06.21 |
JSTL - Layout으로 import 하기(header, section, nav, aside, footer) (2) | 2023.06.17 |
게시판 만들기 (프로젝트 맛보기) (6) | 2023.06.17 |