공부한것들을 정리하는 블로그 입니다.
8. MVC Model2 아키텍처로 게시판 개발 본문
프로젝트 별첨 https://drsggg.tistory.com/236
이번 실습8에서는, 기존에 실습7까지 작성했던 프로젝트(7. MVC Model1 아키텍처로 게시판)의 소스 및 구조를
MVC Model2 아키텍처 게시판으로 변경해보도록 하겠습니다.
기존 실습에서 진행했던 Model 1 아키텍처는 시스템의 규모가 크고 기능이 복잡한 엔터프라이즈 시스템에 적합하지 않습니다.
Model 1 아키텍처가 엔터프라이즈 시스템에 적합하지 않은 이유는 자바 로직과 화면 디자인이 통합되어 유지보수가 어렵기 때문입니다. JSP파일에 자바 로직과 화면 디자인이 통합되어 있기 때문에, 자바 개발자와 디자이너 모두 어려움을 느낄 수 있습니다.
이러한 문제를 해결하기 위해 고안된 웹 개발 모델이 Model 2 아키텍처, 즉 MVC 아키텍처입니다.
가장 큰 특징은 Controller의 등장이며 Controller는 서블릿 클래스를 중심으로 구현합니다. 기존에 JSP가 담당했던 Controller 로직이 별도의 Controller 기능의 서블릿으로 옮겨졌기 때문에 유지보수하기 보다 나아졌습니다.
MVC 프레임워크가 제공하는 Controller(서블릿)과 그 기능을 사용하기에 앞서, 직접 구현해보면서 이해해보는 과정을 실습8에서 진행해보도록 하겠습니다. (프레임워크가 제공하는 기능은 실습9 이후부터 할 예정)
Controller 구현하기
1. DispatcherServlet.java 추가
2. 서블릿 생성 및 등록 : web.xml
3. 실행 : 로그인/로그아웃, 게시글 조회/상세조회, 게시글 입력/수정/삭제
1. DispatcherServlet.java 추가
- DispatcherServlet 경로
DispatcherServlet.java
- 로그인, 로그아웃 기능 : /login.do, /logout.do
- 글 목록 조회 기능 : /getBoardList.do
- 글 상세 조회 기능 : /getBoard.do
- 글 입력 조회 기능 : /insertBoard.do
- 글 수정 조회 기능 : /updateBoard.do
- 글 삭제 조회 기능 : /deleteBoard.do
* 글 목록 조회 기능( /getBoardList.do) 과 글 상세 조회 기능(/getBoard.do) 은 응답시 'do'가 아니라 'jsp' 로 redirect 해야함 ex) response.sendRedirect("getBoard.jsp");
package com.springbook.view.controller;
import java.io.IOException;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import com.springbook.biz.board.BoardVO;
import com.springbook.biz.board.impl.BoardDAO;
import com.springbook.biz.paging.PagingVO;
import com.springbook.biz.user.UserVO;
import com.springbook.biz.user.impl.UserDAO;
/**
* Servlet implementation class DispatcherServlet
*/
public class DispatcherServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public DispatcherServlet() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
process(request, response);
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 한글깨짐방지
request.setCharacterEncoding("UTF-8");
process(request, response);
}
private void process(HttpServletRequest request, HttpServletResponse response) throws IOException {
String uri = request.getRequestURI();
String path = uri.substring(uri.lastIndexOf("/"));
System.out.println("path=[" + path + "]");
if(path.equals("/login.do")) {
System.out.println("로그인 처리");
HttpSession session = request.getSession();
String id = request.getParameter("id");
String password = request.getParameter("password");
UserVO vo = new UserVO();
vo.setId(id);
vo.setPassword(password);
UserDAO userDAO = new UserDAO();
UserVO user = userDAO.getUser(vo);
if(user != null) {
session.setAttribute("id", id);
response.sendRedirect("getBoardList.do");
} else {
response.sendRedirect("login.jsp");
}
} else if(path.equals("/logout.do")) {
System.out.println("로그아웃 처리");
HttpSession session = request.getSession();
session.invalidate();
response.sendRedirect("login.jsp");
} else if(path.equals("/insertBoard.do")) {
System.out.println("글 등록 처리");
String title = request.getParameter("title");
String writer = request.getParameter("writer");
String content = request.getParameter("content");
BoardVO vo = new BoardVO();
vo.setTitle(title);
vo.setWriter(writer);
vo.setContent(content);
BoardDAO boardDAO = new BoardDAO();
boardDAO.insertBoard(vo);
response.sendRedirect("getBoardList.do");
} else if(path.equals("/updateBoard.do")) {
System.out.println("글 수정 처리");
String title = request.getParameter("title");
String writer = request.getParameter("writer");
String content = request.getParameter("content");
String seq = request.getParameter("seq");
BoardVO vo = new BoardVO();
vo.setSeq(Integer.parseInt(seq));
vo.setTitle(title);
vo.setWriter(writer);
vo.setContent(content);
BoardDAO boardDAO = new BoardDAO();
boardDAO.updateBoard(vo);
response.sendRedirect("getBoardList.do");
} else if(path.equals("/deleteBoard.do")) {
System.out.println("글 삭제 처리");
String seq = request.getParameter("seq");
BoardVO vo = new BoardVO();
vo.setSeq(Integer.parseInt(seq));
BoardDAO boardDAO = new BoardDAO();
boardDAO.deleteBoard(vo);
response.sendRedirect("getBoardList.do");
} else if(path.equals("/getBoard.do")) {
System.out.println("글 상세 조회 처리");
HttpSession session = request.getSession();
// 글 목록 -> 글 상세 : 글번호(seq)
String seq = request.getParameter("seq");
// 페이징처리
BoardVO board = paging(request, session, seq);
session.setAttribute("board", board);
response.sendRedirect("getBoard.jsp");
} else if(path.equals("/getBoardList.do")) {
System.out.println("글 목록 검색 처리");
HttpSession session = request.getSession();
// 사용자 이름 설정
String id = (String)session.getAttribute("id");
// 페이징처리
List<BoardVO> boardList = paging(request, session);
session.setAttribute("boardList", boardList);
session.setAttribute("id", id);
if (session.getAttribute("searchCondition") != null && session.getAttribute("searchKeyword") != null ) {
String search = "&searchCondition="+session.getAttribute("searchCondition")+"&searchKeyword="+session.getAttribute("searchKeyword");
session.setAttribute("search", search);
response.sendRedirect("getBoardList.jsp?"+search);
} else {
response.sendRedirect("getBoardList.jsp");
}
}
}
protected BoardVO paging(HttpServletRequest request, HttpSession session, String seq) {
// 저장된 쿠키 불러오기
Cookie[] cookieFromRequest = request.getCookies();
String cookieValue = null;
for(int i = 0 ; i<cookieFromRequest.length; i++) {
// 요청정보로부터 쿠키를 가져온다.
cookieValue = cookieFromRequest[0].getValue(); // 테스트라서 추가 데이터나 보안사항은 고려하지 않으므로 1번째 쿠키만 가져옴
}
// 쿠키 세션 입력
if (session.getAttribute(seq+":cookie") == null) {
session.setAttribute(seq+":cookie", seq + ":" + cookieValue);
} else {
session.setAttribute(seq+":cookie ex", session.getAttribute(seq+":cookie"));
if (!session.getAttribute(seq+":cookie").equals(seq + ":" + cookieValue)) {
session.setAttribute(seq+":cookie", seq + ":" + cookieValue);
}
}
BoardVO vo = new BoardVO();
vo.setSeq(Integer.parseInt(seq));
BoardDAO boardDAO = new BoardDAO();
// 글 상세 조회
BoardVO board = boardDAO.getBoard(vo);
// 조회수 카운트
if (!session.getAttribute(seq+":cookie").equals(session.getAttribute(seq+":cookie ex"))) {
boardDAO.updateBoardCnt(vo);
// 가시적으로 조회수 1 추가해줌
board.setCnt(board.getCnt() + 1);
}
return board;
}
protected List<BoardVO> paging(HttpServletRequest request, HttpSession session) {
// 임의의 상수 설정
String searchCondition = request.getParameter("searchCondition");
String searchKeyword = request.getParameter("searchKeyword");
//========= get board list with paging ===========
BoardVO vo = new BoardVO();
BoardDAO boardDAO = new BoardDAO();
// 게시글 검색 설정
vo.setSearchCondition(searchCondition);
vo.setSearchKeyword(searchKeyword);
// 페이징 처리 된 데이터 조회
int boardListcnt = boardDAO.getBoardCnt(vo);
//========= paging ===========
PagingVO pagingVO = new PagingVO();
// 현재 페이지 체크 및 설정
// 첫 페이지면 1이 설정, 아니라면 해당 페이지 넘버가 설정됨
int currentPage = 1;
//System.out.println("request.param page = " + request.getParameter("page") );
if (request.getParameter("page") != null) {
currentPage = Integer.parseInt(request.getParameter("page"));
}
pagingVO.setCurrentPage(currentPage);
// 전체 페이지 설정
// sql rownum 설정하기 이전의 count 필요
pagingVO.setTotalCount( boardListcnt );
//========= pagination ===========
pagingVO.setEndPage( ((int) Math.ceil(pagingVO.getCurrentPage() / (double) pagingVO.getDisplayPage())) * pagingVO.getDisplayPage() ); //Math.ceil : 소수점 이하를 올림한다
pagingVO.setBeginPage( pagingVO.getEndPage() - (pagingVO.getDisplayPage() - 1) );
pagingVO.setTotalPage( (int) Math.ceil(pagingVO.getTotalCount() / (double) pagingVO.getDisplayRow()) );
if (pagingVO.getEndPage() > pagingVO.getTotalPage()) {
pagingVO.setEndPage(pagingVO.getTotalPage());
}
//========= get board list with paging ===========
// 페이징 처리 된 데이터 조회
List<BoardVO> boardList;
boardList = boardDAO.getBoardListWithPaging(currentPage, vo);
session.setAttribute("searchCondition", searchCondition);
session.setAttribute("searchKeyword", searchKeyword);
session.setAttribute("pagingVO", pagingVO);
return boardList;
}
}
2. 서블릿 생성 및 등록 : web.xml
web.xml
3. 실행 : 로그인/로그아웃, 게시글 조회/상세조회, 게시글 입력/수정/삭제
tomcat 실행 후 웹페이지 방문시 error 발생 : Could not open ServletContext resource [/WEB-INF/action-servlet.xml]
index.jsp
error 발생 : Could not open ServletContext resource [/WEB-INF/action-servlet.xml]
원인은 간단합니다. servlet의 정의 또는 mapping이 잘못되었다는 이야기죠.
아래처럼 작성하면 MVC 프레임워크가 제공하는 Controller(Servlet)을 사용하겠다는 거고 이 경우 Servlet 경로의 디폴트가 /WEB-INF/action-servlet.xml 인데, 경로에 해당 파일이 존재하지 않기에 발생 한 오류입니다.
<servlet>
<servlet-name>action</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
위의 코드를 아래처럼 수정해주시면 됩니다
init-param 부분은 MVC 프레임워크가 제공하는 Servlet 경로의 디폴트를 사용자가 명시해주겠다는 의미입니다. 편의를 돕기위해 주석처리 한 후 코드를 추가하였을 뿐 사용은 하지 않습니다(실습9 이후에 사용예정)
<servlet>
<servlet-name>action</servlet-name>
<!-- <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> -->
<servlet-class>com.springbook.view.controller.DispatcherServlet</servlet-class>
<!-- <init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/config/presentation-layer.xml</param-value>
</init-param> -->
</servlet>
<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
아래와같이 정상출력 확인 가능합니다
로그인/로그아웃, 게시글 조회/상세조회, 게시글 입력/수정/삭제 기능도 Model 1 에서 Model 2로 수정하겠습니다.
login.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
String errMsg = (String)session.getAttribute("errMsg");
if(errMsg == null) errMsg = "";
session.invalidate();
%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>로그인</title>
</head>
<body>
<center>
<h1>로그인</h1>
<hr>
<!-- <form action="login_proc.jsp" method="post"> -->
<form action="login.do" method="post">
<table border="1" cellpadding="0" cellspacing="0">
<tr>
<td bgcolor="orange">아이디</td>
<td>
<input type="text" name="id" value="user1">
</td>
</tr>
<tr>
<td bgcolor="orange">비밀번호</td>
<td>
<input type="password" name="password" value="user1">
</td>
</tr>
<tr>
<td colspan="2" align="center">
<input type="submit" value="로그인">
</td>
</tr>
</table>
</form>
<hr>
<div id="errMsg" style="color:red"><%=errMsg %></div>
</center>
</body>
</html>
getBoardList.jsp
<%@ page import="java.io.Console"%>
<%@ page import="java.util.List"%>
<%@ page import="com.springbook.biz.board.impl.BoardDAO"%>
<%@ page import="com.springbook.biz.board.BoardVO"%>
<%@ page import="com.springbook.biz.user.UserVO"%>
<%@ page import="com.springbook.biz.paging.PagingVO"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
<%
String id = (String)session.getAttribute("id");
String searchCondition = (String)request.getParameter("searchCondition");
String searchKeyword = (String)request.getParameter("searchKeyword");
String search = (String)session.getAttribute("search");
// 임의의 상수 설정
String action = "/biz/getBoardList.do";
//게시글 출력
List<BoardVO> boardList = (List)session.getAttribute("boardList");
// 페이징처리
PagingVO pagingVO = (PagingVO)session.getAttribute("pagingVO");
%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>글 목록</title>
<style type="text/css">
body {
text-align: center;
}
#paging {
font-size: 22pt;
}
</style>
</head>
<body>
<center>
<h1>글 목록</h1>
<%-- <h3><%=id%>님 환영합니다....<a href="logout_proc.jsp">log out</a> --%>
<h3><%=id%>님 환영합니다....<a href="logout.do">log out</a>
</h3>
<!-- 검색 시작 -->
<!-- <form action="getBoardList.jsp" method="get"> -->
<form action="getBoardList.do" method="get">
<table border="1" cellpadding="0" cellspacing="0" width="700">
<tr>
<td align="right"><select id="searchCondition"
name="searchCondition">
<option value="TITLE">제목</option>
<option value="CONTENT">내용</option>
</select> <input id="searchKeyword" name="searchKeyword" type="text">
<input type="submit" value="검색 "></td>
</tr>
</table>
</form>
<!-- 검색 종료 -->
<!-- 전체 게시글 수 -->
<div>
전체 게시글 수 : <%=pagingVO.getTotalCount() %>
</div>
<table border="1" cellpadding="0" cellspacing="0" width="700">
<tr>
<th bgcolor="orange" width="100">번호</th>
<th bgcolor="orange" width="200">제목</th>
<th bgcolor="orange" width="150">작성자</th>
<th bgcolor="orange" width="150">등록일</th>
<th bgcolor="orange" width="100">조회수</th>
</tr>
<%
for (BoardVO board : boardList) {
%>
<tr>
<td><%=board.getSeq()%></td>
<%-- <td align="left"><a href="getBoard.jsp?seq=<%=board.getSeq()%>"> --%>
<td align="left">
<a href="getBoard.do?seq=<%=board.getSeq()%>">
<%=board.getTitle()%>
</a>
</td>
<td><%=board.getWriter()%></td>
<td><%=board.getRegDate()%></td>
<td><%=board.getCnt()%></td>
</tr>
<%
}
%>
</table>
<br>
<!-- 여기부터 페이징처리 -->
<div id="pagination">
<!-- 변수 매핑 -->
<c:set var="page" value="<%=pagingVO.getCurrentPage() %>" />
<c:set var="beginPage" value="<%=pagingVO.getBeginPage() %>" />
<c:set var="endPage" value="<%=pagingVO.getEndPage() %>" />
<c:set var="totalPage" value="<%=pagingVO.getTotalPage() %>" />
<c:set var="displayPage" value="<%=pagingVO.getDisplayPage() %>" />
<c:set var="searchKeyword" value="<%=searchKeyword %>" />
<c:set var="search" value="<%=search %>" />
<c:set var="action" value="<%=action %>" />
<!-- 처음으로 -->
<c:if test="${ searchKeyword == null }">
<a href="${ action }?page=1">
<span>«</span>
</a>
</c:if>
<c:if test="${ searchKeyword != null }">
<a href="${ action }?page=1${ search }">
<span>«</span>
</a>
</c:if>
<!-- 이전버튼 -->
<c:if test="${ page <= 1 }">
<span>이전</span>
</c:if>
<c:if test="${ page > 1 }">
<c:if test="${ searchKeyword == null }">
<a href="${ action }?page=${ page - 1 }">이전</a>
</c:if>
<c:if test="${ searchKeyword != null }">
<a href="${ action }?page=${ page - 1 }${ search }">이전</a>
</c:if>
</c:if>
<!-- 넘버링버튼 for문 -->
<c:forEach var="item" varStatus="status" begin="${ beginPage }" end="${ endPage }" step="1">
<c:if test="${ page == item }">
${ item }
</c:if>
<c:if test="${ page != item }">
<c:if test="${ searchKeyword == null }">
<a href="${ action }?page=${ item }">${ item }</a>
</c:if>
<c:if test="${ searchKeyword != null }">
<a href="${ action }?page=${ item }${ search }">${ item }</a>
</c:if>
</c:if>
</c:forEach>
<!-- 다음버튼 -->
<c:if test="${ page >= totalPage }">
<span>다음</span>
</c:if>
<c:if test="${ page < totalPage }">
<c:if test="${ searchKeyword == null }">
<a href="${ action }?page=${ page + 1 }">다음</a>
</c:if>
<c:if test="${ searchKeyword != null }">
<a href="${ action }?page=${ page + 1 }${ search }">다음</a>
</c:if>
</c:if>
<!-- 끝으로 -->
<c:if test="${ searchKeyword == null }">
<a href="${ action }?page=${ totalPage }">
<span>»</span>
</a>
</c:if>
<c:if test="${ searchKeyword != null }">
<a href="${ action }?page=${ totalPage }${ search }">
<span>»</span>
</a>
</c:if>
</div>
<br> <a href="insertBoard.jsp">새 글 등록</a>
</center>
</body>
</html>
getBoard.jsp
<%@ page import="com.springbook.biz.board.BoardVO" %>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
BoardVO board = (BoardVO)session.getAttribute("board");
%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>글 상세</title>
</head>
<body>
<center>
<h1>글 상세</h1>
<!-- <a href="logout_proc.jsp">log out</a> -->
<a href="logout.do">log out</a>
<hr>
<!-- <form action="updateBoard_proc.jsp" method="post"> -->
<form action="updateBoard.do" method="post">
<table border="1" cellpadding="0" cellspacing="0">
<tr>
<td bgcolor="orange" width="70">제목</td>
<td align="left">
<input name="title" type="text" value="<%= board.getTitle() %>">
</td>
</tr>
<tr>
<td bgcolor="orange">작성자</td>
<td align="left"><%= board.getWriter() %></td>
</tr>
<tr>
<td bgcolor="orange">내용</td>
<td align="left">
<textarea name="content" cols="40" rows="10"><%= board.getContent() %></textarea>
</td>
</tr>
<tr>
<td bgcolor="orange">등록일</td>
<td align="left"><%= board.getRegDate() %></td>
</tr>
<tr>
<td bgcolor="orange">조회수</td>
<td align="left"><%= board.getCnt() %></td>
</tr>
<tr>
<td colspan="2" align="center">
<input type="submit" value="글 수정" />
</td>
</tr>
</table>
<input name="seq" type="hidden" value="<%= board.getSeq() %>" />
</form>
<hr>
<!-- <a href="insertBoard.jsp">글 등록</a> -->
<%-- <a href="deleteBoard_proc.jsp?seq=<%= board.getSeq() %>">글 삭제</a> --%>
<!-- <a href="getBoardList.jsp">글 목록</a> -->
<a href="insertBoard.do">글 등록</a>
<a href="deleteBoard.do?seq=<%= board.getSeq() %>">글 삭제</a>
<a href="getBoardList.do">글 목록</a>
</center>
</body>
</html>
insertBoard.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>새 글 등록</title>
</head>
<body>
<center>
<h1>글 등록</h1>
<a href="logout.do">log out</a>
<hr>
<!-- <form action="insertBoard_proc.jsp" method="post"> -->
<form action="insertBoard.do" method="post">
<table border="1" cellpadding="0" cellspacing="0">
<tr>
<td bgcolor="orange" width="70">제목</td>
<td align="left">
<input name="title" type="text">
</td>
</tr>
<tr>
<td bgcolor="orange">작성자</td>
<td align="left">
<input name="writer" size="10" />
</td>
</tr>
<tr>
<td bgcolor="orange">내용</td>
<td align="left">
<textarea name="content" cols="40" rows="10"></textarea>
</td>
</tr>
<tr>
<td colspan="2" align="center">
<input type="submit" value="새 글 등록" />
</td>
</tr>
</table>
</form>
<hr>
<a href="getBoardList.do">글 목록 가기</a>
</center>
</body>
</html>
게시판 화면 디자인이 기존 실습7과 동일하기 때문에 사진캡처는 생략하겠습니다.
다음글에서 뵙겠습니다.
'(2019) 사이드 프로젝트 > BoardWeb(게시판-MVC1,MVC2,스프링MVC)' 카테고리의 다른 글
7-8. 글 등록, 수정, 삭제 구현 : insertBoard.jsp, insertBoard_proc.jsp, updateBoard_proc.jsp, deleteBoard_proc.jsp (0) | 2019.07.12 |
---|---|
7-7. 실습 중간점검 , 프로젝트 별첨 (0) | 2019.07.05 |
7-6. 페이징처리(paging, pagination) : BoardDAO.java, BoardList2.jsp, PagingVO.java (2) | 2019.07.04 |
7-5. 실습 중간점검 , 프로젝트 별첨 (0) | 2019.06.28 |
7-4. 글 조회수 카운트, session을 이용한 조회수 중복 방지 처리(jsp) : BoardDAO.java, getBoard.jsp (0) | 2019.06.28 |
7-3. 글 상세 조회 : getBoard.jsp (0) | 2019.06.24 |
7-2. 글 목록 조회, 글 검색 기능 : getBoardList.jsp, BoardDAO.java (0) | 2019.06.24 |
7-1. 로그인, 로그아웃, 로그인 검증 및 실패 후처리 : login.jsp, login_proc.jsp, logout_proc.jsp (3) | 2019.06.24 |