대충벌레 블로그
article thumbnail
728x90
반응형

MVC 게시판 만들기 위한 테이블 생성 이전 게시판 테이블에서 ip와 답글시 필요한 컬럼을 추가해주었다.

<sql />
create table mvc_board( idx number primary key, name varchar2(30), email varchar2(30), title varchar2(50), content varchar2(2000), password varchar2(20), write_date varchar2(50), hit number(10), ip varchar2(20), ref int, re_step int, re_level int ); drop table mvc_board; create sequence mvc_board_idx increment by 1 start with 1; drop sequence board_num_seq desc table mvc_board; select * from mvc_board;

 

 

 

데이터 베이스 연동을 위한 server.xml 을 수정해준다.

<html />
<GlobalNamingResources> <!-- Editable user database that can also be used by UserDatabaseRealm to authenticate users --> <Resource auth="Container" description="User database that can be updated and saved" factory="org.apache.catalina.users.MemoryUserDatabaseFactory" name="UserDatabase" pathname="conf/tomcat-users.xml" type="org.apache.catalina.UserDatabase"/> <Resource auth="Container" driverClassName="oracle.jdbc.driver.OracleDriver" factory="oracle.jdbc.pool.OracleDataSourceFactory" maxActive="20" maxIdle="10" maxWait="-1" name="jdbc/oracle" password="1234" type="oracle.jdbc.pool.OracleDataSource" url="jdbc:oracle:thin:@localhost:1521:orcl" user="inthegun"/> <!-- 서버에서 제공하는 리소스 : 서버내의 모든곳 사용 가능 --> </GlobalNamingResources>

 

GlobalNamingResources 사이에 Resourec를 추가해줍니다.

 

그리고 server.xml 하단을 보면 Context가 있는데 그 사이에 ResourceLink를 추가해줍니다.

만약 Context가 보이지 않는다면 Run 을 한번하고 확인해보세요

<html />
<Context docBase="MVCboard0107" path="/MVCboard0107" reloadable="true" source="org.eclipse.jst.jee.server:MVCboard0107"> <ResourceLink global="jdbc/oracle" name="jdbc/oracle" type="oracle.jdbc.pool.OracleDataSource"/> </Context>

WEB-INF에 있는 web.xml에서 추가 해주어야합니다.

<html />
<!-- 외부에서 들어오는 경로를 인식하기 위한 서블릿 매핑 작업 --> <!-- 서블릿 설정 --> <servlet> <servlet-name>ControllerAction</servlet-name> <servlet-class>controller.ControllerAction</servlet-class> <init-param> <param-name>propertyConfig</param-name> <param-value>/WEB-INF/Command.properties</param-value> <!-- param-value 경로는 본인의 경로에 맞게 설정 --> </init-param> </servlet> <!-- 서블릿 매핑 servlet name은 위와 같게 한다--> <servlet-mapping> <servlet-name>ControllerAction</servlet-name> <url-pattern>*.do</url-pattern> </servlet-mapping> <!-- 글로벌 자원 참조 --> <resource-ref> <description>Oracle database pool</description> <res-ref-name>jdbc/oracle</res-ref-name> <res-type>oracle.jdbc.pool.OracleDataSource</res-type> <res-auth>Container</res-auth> </resource-ref>

<display-name> 태그 밑에 추가해주면 됩니다.

 

이제 게시판 DTO를 추가해 줍니다.

<java />
package board; public class BoardDTO { private int idx; private String name; private String email; private String title; private String content; private String password; private String write_date; private int hit; private String ip; private int ref; private int re_step; private int re_level; public int getRef() { return ref; } public void setRef(int ref) { this.ref = ref; } public int getRe_step() { return re_step; } public void setRe_step(int re_step) { this.re_step = re_step; } public int getRe_level() { return re_level; } public void setRe_level(int re_level) { this.re_level = re_level; } public int getIdx() { return idx; } public void setIdx(int idx) { this.idx = idx; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getContent() { return content; } public void setContent(String content) { this.content = content; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getWrite_date() { return write_date; } public void setWrite_date(String write_date) { this.write_date = write_date; } public int getHit() { return hit; } public void setHit(int hit) { this.hit = hit; } public String getIp() { return ip; } public void setIp(String ip) { this.ip = ip; } }

 

다음은 DAO를 추가해줍니다.

<java />
package board; 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 javax.naming.Context; import javax.naming.InitialContext; import javax.sql.DataSource; public class BoardDAO { private static BoardDAO instance = new BoardDAO(); // 싱글톤 public static BoardDAO getInstance() { return instance; } public BoardDAO() { // 생성자입니다 // TODO Auto-generated constructor stub } // 연동객체 public Connection getConnection() throws Exception{ Context initCtx = new InitialContext(); Context envCtx = (Context)initCtx.lookup("java:comp/env"); DataSource ds = (DataSource)envCtx.lookup("jdbc/oracle"); return ds.getConnection(); }

그리고 위에 web.xml에서 정한 경로를 설정해주도록 합니다.

Command.properties를 생성하고 경로를 설정합니다.

<html />
# 웹 경로 = 컨트롤러 class #/MVCboard0107/writeForm.do=action.WriteFormAction /MVCboard0107/write.do=action.WriteFormAction /MVCboard0107/write_ok.do=action.WriteProAction /MVCboard0107/list.do=action.ListAction

맨앞 MVCboard0107은 프로젝트명/write.do 실행할 경로 = 패키지.클래스명

#은 주석입니다.

write.do 글쓰기 폼 / write_ok.do  글쓰기 처리 / list.do 리스트 보기

 

그다음으로 CommandAction을 추가해줍니다.

<java />
package action; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; // 요청 파라미터로 명령어를 전달하는 방식 public interface CommandAction { public String requestPro(HttpServletRequest req , HttpServletResponse res) throws Throwable; }

 

그리고 컨트롤러 액션을 추가해줍니다.

 

<java />
package controller; import java.io.FileInputStream; import java.io.IOException; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Properties; import javax.servlet.RequestDispatcher; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import action.CommandAction; // 서블릿 public class ControllerAction extends HttpServlet { private Map commandMap = new HashMap(); // 명령어하고 명령어 처리클래스를 K,V 저장 @Override public void init(ServletConfig config) throws ServletException { String path = config.getServletContext().getRealPath("/"); // 실제경로 String props=config.getInitParameter("propertyConfig"); //web.xml에서 리턴합니다 Properties pr=new Properties(); FileInputStream f=null; try { f = new FileInputStream(path+props); pr.load(f); } catch (IOException e) { // TODO: handle exception throw new ServletException(e); }finally { if(f!=null) try {f.close();} catch(IOException ex) {} } Iterator keyIter = pr.keySet().iterator(); while(keyIter.hasNext()) { String command=(String) keyIter.next(); String className=pr.getProperty(command); try { Class commandClass=Class.forName(className); //동적으로 로드 Object commandInstance = commandClass.newInstance(); commandMap.put(command, commandInstance); } catch (ClassNotFoundException e) { // TODO: handle exception throw new ServletException(e); }catch(InstantiationException e) { throw new ServletException(e); }catch(IllegalAccessException e) { throw new ServletException(e); } } } @Override //get방식 서비스 메소드 protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { execute(req,resp); } @Override //post방식 서비스 메서드 protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO Auto-generated method stub execute(req,resp); } //추가 메소드 //사용자의 요청을 분석해서 해당 작업을 처리 private void execute(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException{ String view =null; CommandAction com=null; try { String command = request.getRequestURI(); com=(CommandAction) commandMap.get(command); //경로확인 view=com.requestPro(request, response); } catch (Throwable e) { throw new ServletException(e); // TODO: handle exception } RequestDispatcher dispatcher = request.getRequestDispatcher(view); dispatcher.forward(request, response); } }

 

글 입력 폼을 처리하기위해 WriteFormAction 클래스를 추가해줍니다.

<java />
package action; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class WriteFormAction implements CommandAction { @Override public String requestPro(HttpServletRequest req, HttpServletResponse resp) throws Throwable { // 글 입력 폼을 처리 첫 게시글과 답글을 구분 int idx=0,ref=1,re_step=0,re_level=0; try { if(req.getParameter("idx")!= null) { // 답글이다? idx = Integer.parseInt(req.getParameter("idx")); ref=Integer.parseInt(req.getParameter("ref")); re_step=Integer.parseInt(req.getParameter("re_step")); re_level=Integer.parseInt(req.getParameter("re_level")); } } catch (Exception e) { // TODO: handle exception } // 뷰에서 사용할 속성 request 영역에 저장해서 리턴 req.setAttribute("idx", new Integer(idx)); req.setAttribute("ref", new Integer(ref)); req.setAttribute("re_step", new Integer(re_step)); req.setAttribute("re_level", new Integer(re_level)); return "write.jsp"; // 해당하는뷰 } // 글 입력 폼을 처리 }

 

이제 글쓰기폼을 생성해줍니다.

<html />
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%-- <%@ include file="" %> 인클루드 파일 있을시 --%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>글쓰기</title> <script type="text/javascript"> function writeBoard(){ if(document.write.name.value==""){ alert("이름 입력"); document.writeform.name.focus(); return false; } /* 추가 ~ */ } </script> </head> <body> <center> 게시판 글쓰기 </center> <form name="boardform" method="post" action="/MVCboard0107/write_ok.do" onsubmit="return writeBoard()"> <input type="hidden" name="idx" value="${idx }"> <%--request영역 idx --%> <input type="hidden" name="ref" value="${ref }"> <input type="hidden" name="re_step" value="${re_step }"> <input type="hidden" name="re_level" value="${re_level }"> <table width="600" border="1" align="center"> <tr><td width="20%"> 이름 </td> <td><input type="text" name="name" size="15"></td> </tr> <tr><td> 이메일 </td> <td><input type="text" name="email" size="30"></td> </tr> <tr><td> 제목 </td> <td> <c:if test="${idx ==0 }"> <!-- 첫글[새글] --> <input type="text" name="title" size="50"></td> </tr> </c:if> <c:if test="${idx != 0 }"> <!-- 답글 --> <input type="text" name="title" value="[답글]"></td> </c:if> <tr><td> 내용 </td> <td><textarea name="content" rows="10" cols="40"></textarea></td> </tr> <tr><td> 비밀번호 </td> <td><input type="password" name="password" size="20"></td> </tr> <tr> <td colspan="2" align="center"> <input type="submit" value="글쓰기"> &nbsp;&nbsp; <input type="reset" value="다시쓰기"></td> </tr> <tr> <td align="center"><input type='button' value='리스트' onclick="window.location='/MVCboard0107/list.do'"> </td> </tr> </table> </form> </body> </html>

글쓰기 폼은 이전 게시판했을때와 유사합니다.

경로는 당연히 write.jsp가 아니라 write.do로 해야 올바르게 작동합니다.

이제 글 입력을 하기위한 DAO를 추가해줍니다.

 

<java />
// 글 입력 public void insert(BoardDTO boardDTO) throws Exception{ Connection c = null; PreparedStatement p = null; ResultSet r = null; int idx=boardDTO.getIdx(); //글번호 int ref=boardDTO.getRef(); //그룹번호 int re_step=boardDTO.getRe_step(); // 그룹 내부안의 순서 int re_level=boardDTO.getRe_level(); // 응답 깊이 int number=0; String sql =""; try { c=getConnection(); p=c.prepareStatement("select max(idx) from mvc_board"); r=p.executeQuery(); if(r.next()) { number= r.getInt(1)+1; }else { number=1; } if(idx!=0) { // 답글이야? sql="UPDATE mvc_board SET re_step=re_step+1 WHERE ref=? and re_step > ?"; p=c.prepareStatement(sql); p.setInt(1, ref); p.setInt(2, re_step); re_step=re_step+1; re_level=re_level+1; p.executeUpdate(); }else { ref=number; re_step=0; re_level=0; } // 쿼리 sql="INSERT INTO mvc_board(idx,name,email,title,content,password,write_date, ip,ref,re_step,re_level)"+ " values ( mvc_board_idx.nextval, ? , ? , ? , ? , ? , to_char(sysdate,'yyyy-mm-dd'), ? , ? , ? , ?) "; p=c.prepareStatement(sql); p.setString(1, boardDTO.getName()); p.setString(2, boardDTO.getEmail()); p.setString(3, boardDTO.getTitle()); p.setString(4, boardDTO.getContent()); p.setString(5, boardDTO.getPassword()); p.setString(6, boardDTO.getIp()); p.setInt(7, ref); p.setInt(8, re_step); p.setInt(9, re_level); p.executeUpdate(); } catch (Exception e) { // TODO: handle exception e.printStackTrace(); }finally { if(r !=null) try {r.close();} catch (Exception e2) {} if(p !=null) try {p.close();} catch(SQLException e) {} if(c !=null) try {c.close();} catch(SQLException e3) {} } }// insert

글 입력 처리를 위한 WriteProAction 클래스를 생성해줍니다.

<java />
package action; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import board.BoardDAO; import board.BoardDTO; // 입력된 글을 처리한다. public class WriteProAction implements CommandAction { @Override public String requestPro(HttpServletRequest req, HttpServletResponse res) throws Throwable { req.setCharacterEncoding("utf-8"); // 인코딩 BoardDTO boardDTO = new BoardDTO(); // 빈 boardDTO.setIdx(Integer.parseInt(req.getParameter("idx"))); boardDTO.setName(req.getParameter("name")); boardDTO.setEmail(req.getParameter("email")); boardDTO.setTitle(req.getParameter("title")); boardDTO.setContent(req.getParameter("content")); boardDTO.setPassword(req.getParameter("password")); boardDTO.setWrite_date(req.getParameter("write_date")); boardDTO.setIp(req.getRemoteAddr()); // IP boardDTO.setRef(Integer.parseInt(req.getParameter("ref"))); boardDTO.setRe_step(Integer.parseInt(req.getParameter("re_step"))); boardDTO.setRe_level(Integer.parseInt(req.getParameter("re_level"))); BoardDAO boardDAO = BoardDAO.getInstance(); // DB를 처리 boardDAO.insert(boardDTO); return "write_ok.jsp"; } }

 

글 입력 처리를 위한 write_ok.jsp를 생성해줍니다.

간단하게 자동으로 리스트 이동하는 페이지 입니다.

<html />
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <meta http-equiv="refresh" content="2;url=/MVCboard0107/list.do"> <title>Insert title here</title> </head> <body> 글이 정상적으로 입력됨 . 2초뒤 리스트로 이동함 </body> </html>

 

이제 글 갯수를 구하는것과 리스트를 구하는 DAO를 추가해줍니다.

<java />
// 글 갯수 구하기 public int getBoardCount() throws Exception{ Connection c = null; PreparedStatement p = null; ResultSet r = null; int count =0; String sql=""; try { c=getConnection(); sql = "select count(*) from mvc_board"; p=c.prepareStatement(sql); r=p.executeQuery(); if(r.next()) { count = r.getInt(1); } } catch (Exception e) { // TODO: handle exception e.printStackTrace(); }finally { if(r !=null) try {r.close();} catch (Exception e2) {} if(p !=null) try {p.close();} catch(SQLException e) {} if(c !=null) try {c.close();} catch(SQLException e3) {} } return count; }// getBoardCount() 글 갯수

 

글 목록 

오라클의 ROWNUM을 활용해서 게시판 페이징을 처리해봅시다,.

<java />
// 글목록 public List getArticles(int start,int end) throws Exception{ Connection c=null; PreparedStatement p=null; ResultSet r=null; List articleList=null; try { c=getConnection(); p=c.prepareStatement( "select a.* "+ "from ("+ "select ROWNUM as RNUM, b.* "+ "from ("+ "select * "+ "from mvc_board "+ "order by ref desc, re_step asc "+ ") b"+ ") a"+ " where a.RNUM >= ?" + " and a.RNUM <= ?"); p.setInt(1, start); p.setInt(2, end); //System.out.println(sql); r=p.executeQuery(); if(r.next()) { articleList=new ArrayList(end); do { BoardDTO article = new BoardDTO(); article.setIdx(r.getInt("idx")); article.setName(r.getString("name")); article.setEmail(r.getString("email")); article.setTitle(r.getString("title")); article.setPassword(r.getString("password")); article.setWrite_date(r.getString("write_date")); article.setHit(r.getInt("hit")); article.setRef(r.getInt("ref")); article.setRe_step(r.getInt("re_step")); article.setRe_level(r.getInt("re_level")); article.setContent(r.getString("content")); article.setIp(r.getString("ip")); articleList.add(article); }while(r.next()); } } catch (Exception e) { // TODO: handle exception e.printStackTrace(); }finally { if(r !=null) try {r.close();} catch (Exception e2) {} if(p !=null) try {p.close();} catch(SQLException e) {} if(c !=null) try {c.close();} catch(SQLException e3) {} } return articleList; }//getArticles(int start,int end)

 

ListAction 클래스를 생성해 줍시다 .

<java />
package action; import java.util.Collections; import java.util.List; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import board.BoardDAO; // 글 목록 public class ListAction implements CommandAction { @Override public String requestPro(HttpServletRequest req, HttpServletResponse res) throws Throwable { String pageNum = req.getParameter("pageNum"); // 페이지 번호 if(pageNum == null) { pageNum ="1"; } int pageSize=10; // 한페이지의 글의 개수 int currentPage = Integer.parseInt(pageNum); int startRow = (currentPage -1 ) * pageSize +1 ; // 한 페이지의 시작글 번호 int endRow = currentPage * pageSize;// 한페이지의 마지막 글 번호 int count=0; int number=0; List articleList =null; BoardDAO dbPro=BoardDAO.getInstance(); //DB연동 count =dbPro.getBoardCount(); //전체 글의 수 if(count >0) { articleList=dbPro.getArticles(startRow, endRow);//현재 페이지에 해당하는 글 목록 }else { articleList=Collections.EMPTY_LIST; } number=count-(currentPage-1)*pageSize; //글목록에 표시할 글번호 //해당뷰에서 사용할 속성 req.setAttribute("currentPage", new Integer(currentPage)); req.setAttribute("startRow", new Integer(startRow)); req.setAttribute("endRow", new Integer(endRow)); req.setAttribute("count", new Integer(count)); req.setAttribute("pageSize", new Integer(pageSize)); req.setAttribute("number", new Integer(number)); req.setAttribute("articleList", articleList); return "list.jsp";//해당뷰 } }

 

이제 리스트를 띄우기 위한 jsp를 추가해줍시다 

<html />
<%@ 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> </script> <meta charset="UTF-8"> <title>게시글 리스트</title> </head> <body> <table border ="0" align="center"> <tr> <td align='left'> [게시글 수 : ${count} ]</td> <td align='center'> <font style='bold'>게시글 리스트 </font></td> <td align='right'> [<a href='/MVCboard0107/write.do'>글쓰기</a>]</td> </tr> </table> <!-- 상단 테이블 --><br> <c:if test="${count == 0 }"> <table width="700" border="1" cellpadding="0" cellspacing="0"> <tr> <td align="center"> 게시판에 저장된 글이 없습니다. </td> </tr> </table> </c:if> <c:if test="${count > 0 }"> <table width="600" align="center" border="1"> <tr> <td width="10%">&nbsp;번호</td> <td width="20%">&nbsp;제목</td> <td width="15%">&nbsp;이름</td> <td width="30%">&nbsp;일자</td> <td width="15%">&nbsp;IP</td> <td>&nbsp;조회수</td> </tr> <c:forEach var="article" items="${articleList }"> <tr height="30"> <td align="center" width="50"> <c:out value="${number}"/> <c:set var="number" value="${number-1 }"/> </td> <td width="250"> <c:if test="${article.re_level > 0 }"> <%-- <img src="images/level.gif" width="${5 * article.re_level }" height="16"> <img src="images/re.gif"> --%> </c:if> <c:if test="${article.re_level == 0 }"> <%-- <img src="images/level.gif" width="${5 * article.re_level }" height="16"> --%> </c:if> <a href="/MVCboard0107/content.do?idx=${article.idx }&pageNum=${currentPage}">${article.title }</a> <c:if test="${article.hit >=20 }"> <!-- <img src="images/hot.gif" border="0" height="16"> --> </c:if> </td> <td align="center" width="100"> ${article.name } </td> <td align="center" width="150" >${article.write_date } </td> <td align="center" width="50">${article.ip }</td> <td align="center" width="100">${article.hit }</td> </tr> </c:forEach> </table> </c:if> <c:if test="${count >0 }"> <c:set var="pageCount" value="${ count/pageSize +(count % pageSize == 0 ? 0 : 1)}"/> <c:set var="startPage" value="${ currentPage / pageSize+1 }"/> <c:set var="endPage" value="${startPage+10 }"/> <c:if test="${endPage > pageCount }"> <c:set var="endPage" value="${pageCount }"/> </c:if> <c:if test="${startPage>10 }"> <a href="/Mvcboard0107/list.do?pageNum=${startPage-10 }">[이전]</a> </c:if> <c:forEach var="i" begin="${startPage }" end="${endPage }"> <a href="/Mvcboard0107/list.do?pageNum=${i}">[${i}]</a> </c:forEach> <c:if test="${endPage<pageCount }"> <a href="/Mvcboard0107/list.do?pageNum=${startPage+10 }">[다음]</a> </c:if> </c:if> <br> <!-- 검색 폼 --> <div align="center"> <form action='search.jsp' method="post" name="searchform"> <select name='type'> <option value=name>이름</option> <option value=title selected="selected">제목</option> <option value=content>내용</option> </select> <input type="text" name="search" size="20"> <input type="button" value='찾기' onclick='send(this.form);'> </form> </div> </body> </html>

 

글 보는것과 수정 삭제는 응용해서 하면 쉽게 다가올겁니다.

만약 시간이 된다면 따로 추가해보겟습니다 . 

궁금하신점은 댓글로 남겨주세요.

 

아 추가로 IP 부분은 그대로 넣을시 IPv6로 나올수 있습니다.

Run Configurations 에서 Arguments탭에서 

 

-Djava.net.preferIPv4Stack=true

위의 속성을 추가해주어야합니다. 

반응형
profile

대충벌레 블로그

@대충벌레

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!