2013년 8월 3일 토요일

18. Spring 게시판 프로젝트_전체소스(글리스트,글쓰기,수정,삭제,파일업로드,답변, 댓글, 미리보기AJAX), 스프링 교육, Spring강좌, 오라클자바커뮤니티 스프링강좌

Spring 게시판 구현 1차 버전 최종 본 입니다. 이전 스프링 게시판 강좌 참고하시면 자세한 내용 볼 수 있습니다. 


오라클자바커뮤니티에서 설립한 오엔제이프로그래밍 실무교육센터
(오라클SQL, 튜닝, 힌트,자바프레임워크, 안드로이드, 아이폰, 닷넷 실무전문 강의) 
                                                     

1.     구현된 기능

-       게시판 리스트보기 + 게시물 본문내용 미리 보기 + 게시 글 상세보기 + 커멘트(댓글)기능 + 글쓰기 + 글 수정하기 + 글 삭제하기 + 답변 글


2.  DAO쪽 클래스


[BoardDAO.java]

package onj.board.dao;

import java.util.List;

import onj.board.model.BoardDTO;
import onj.board.model.CommentDTO;

import org.springframework.dao.DataAccessException;


public interface BoardDAO {
       //게시물 리스트 보기
       public List<BoardDTO> boardList() throws DataAccessException;
      
       //게시물 본문 미리보기
       public String preView(String seq) throws DataAccessException;
      
       //게시물 본문 읽기
       public BoardDTO readContent(String seq) throws DataAccessException;
      
       //읽은 글의 조회수 1증가
       public int updateReadCount(String seq) throws DataAccessException;
      
       //Comment저장
       public int insertComment(CommentDTO commentDTO) throws DataAccessException ;
      
       //Comment조회
       public List<CommentDTO> commentList(String seq) throws DataAccessException;
      
       //게시글 입력
       public int insertBoard(BoardDTO board) throws DataAccessException;
      
       // 수정
       public int updateBoard(BoardDTO board) throws DataAccessException;
      
       // 삭제
       public int deleteBoard(String sid , String password) throws DataAccessException;
      
       //답글 달기
       public int replyBoard(BoardDTO board) throws DataAccessException;
}




[SpringBoardDAO.java]

package onj.board.dao;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

import javax.sql.DataSource;

import onj.board.model.BoardDTO;
import onj.board.model.CommentDTO;

import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;


public class SpringBoardDAO implements BoardDAO {
       private JdbcTemplate jdbcTemplate;
      

       public void setDataSource(DataSource dataSource) {
             this.jdbcTemplate = new JdbcTemplate(dataSource);
       }

       // /게시판 전체 리스트 보기(list.html)
       public List<BoardDTO> boardList() throws DataAccessException {
             List<BoardDTO> boardList = null;

             //String sql = "select * from board";
             /*
              * reply : 답변인경우 어느글의 답변인지 상위글 번호
              *         최상위글인 경우 reply 자신의 글번호(seq) 동일, 리스트보기에서 정령시 우선  reply 우선하게 된다.
              * reply_level : 1, 2 답글인지 여부, 하나의 글에  답변이 두개면 두답변은 reply_level 같다.
              *              list.jsp에서 글을 뿌릴 reply_level 따라 들여쓰기를 한다.
              * reply_step : 하나의 아래에 생기는 모든 답변들에 대해 순차적으로 1 증가, reply_level 관계없이
              */
             String sql = " select * from  (select seq, name , passwd, "
                              + "                        title, content, filename, regdate, "
                              + "                        readcount, reply, reply_step, "
                              + "                        reply_level , rownum r "
                              + "                   from board "
                              + "                  order by reply desc , reply_step asc)";        

             boardList = jdbcTemplate.query(sql, new RowMapper() {
                    public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
                           BoardDTO board = new BoardDTO();

                           board.setSeq(rs.getInt("seq"));
                           board.setName(rs.getString("name"));
                           board.setPasswd(rs.getString("passwd"));
                           board.setTitle(rs.getString("title"));
                           board.setContent(rs.getString("content"));
                           board.setFileName(rs.getString("filename"));
                           board.setRegDate(rs.getString("regdate"));
                           board.setReadCount(rs.getInt("readcount"));
                           board.setReply(rs.getInt("reply"));
                           board.setReply_step(rs.getInt("reply_step"));
                           board.setReply_level(rs.getInt("reply_level"));

                           return board;
                    }
             });

             return boardList;
       }

       // 게시물 본문내용 미리보기(/preView)
       public String preView(String seq) throws DataAccessException {
             String sql = "select * from board where seq = ?";

              String preContent = (String) jdbcTemplate.queryForObject(sql,
                           new Object[] { seq }, new RowMapper() {
                                 public Object mapRow(ResultSet rs, int rowNum)
                                              throws SQLException {
                                        return rs.getString("content");
                                 }
                           });
             return preContent;
       }

       // 게시판 상세보기, 게시글 읽기
       public BoardDTO readContent(String seq) throws DataAccessException {
             String sql = "select * from board where seq = ?";

             BoardDTO boardDTO = (BoardDTO) jdbcTemplate.queryForObject(sql,
                           new Object[] { seq }, new RowMapper() {
                                 public Object mapRow(ResultSet rs, int rowNum)
                                              throws SQLException {
                                        BoardDTO board = new BoardDTO();

                                        board.setSeq(rs.getInt("seq"));
                                        board.setName(rs.getString("name"));
                                        board.setPasswd(rs.getString("passwd"));
                                        board.setTitle(rs.getString("title"));
                                        board.setContent(rs.getString("content"));
                                        board.setFileName(rs.getString("filename"));
                                        board.setRegDate(rs.getString("regdate"));
                                        board.setReadCount(rs.getInt("readcount"));
                                        board.setReply(rs.getInt("reply"));
                                        board.setReply_step(rs.getInt("reply_step"));
                                        board.setReply_level(rs.getInt("reply_level"));

                                        return board;
                                 }
                           });
             // 조회수 1증가
             this.updateReadCount(new Integer(boardDTO.getSeq()).toString());

             return boardDTO;
       }

       // 읽은 글의 조회수를 1증가
       public int updateReadCount(String seq) throws DataAccessException {
             String sql = "update board set readcount = nvl(readcount,0) + 1 where seq = ?";
             Object[] obj = { seq };

             return jdbcTemplate.update(sql, obj);
       }

       // 커맨트 입력
       public int insertComment(CommentDTO commentDTO) throws DataAccessException {
             String sql = "insert into comment_t(seq, name, comm) values (?, ?, ?)";

             Object[] obj = { commentDTO.getSeq(), // 게시글순번
                           commentDTO.getName(), // 작성자
                           commentDTO.getComment() }; // 커맨트

             return jdbcTemplate.update(sql, obj);
       }

       // 커맨트 조회
       public List<CommentDTO> commentList(String seq) throws DataAccessException {
             String sql = "select * from comment_t where seq = ?";

             List<CommentDTO> commentList = jdbcTemplate.query(sql,
                           new Object[] { seq }, new RowMapper() {
                                 public Object mapRow(ResultSet rs, int rowNum)
                                              throws SQLException {
                                        CommentDTO commentDTO = new CommentDTO();
                                        commentDTO.setName(rs.getString("name"));
                                        commentDTO.setComment(rs.getString("comm"));

                                        return commentDTO;
                                 }
                           });
             return commentList;
       }

       // 글쓰기
       public int insertBoard(BoardDTO board) throws DataAccessException {

             String sql = "insert into board values(board_seq.nextval , ? , ? , ? , ? , ? , sysdate , 0 , board_seq.currval , 0 , 0)";

             if (board.getFileName() == null) {
                    Object[] obj = { board.getName(), board.getPasswd(),
                                 board.getTitle(), board.getContent(), "" };
                    return jdbcTemplate.update(sql, obj);
             } else {
                    Object[] obj = { board.getName(), board.getPasswd(),
                                 board.getTitle(), board.getContent(), board.getFileName() };
                    return jdbcTemplate.update(sql, obj);
             }

       }

       // 게시글 수정
       public int updateBoard(BoardDTO board) throws DataAccessException {

             String sql = "update board set  title = ? , content = ? where seq = ?";
             Object[] obj = { board.getTitle(), board.getContent(), board.getSeq() };

             return jdbcTemplate.update(sql, obj);
       }

       // 게시글 삭제
       public int deleteBoard(String seq, String passwd)
                    throws DataAccessException {
             int result = 0;
             String sql = "delete from board where seq = ? and passwd = ?";
             result = jdbcTemplate.update(sql, new Object[] { seq, passwd });

             return result;
       }

       // 답글달기
       public int replyBoard(BoardDTO boardDTO) throws DataAccessException {

             int result = 0;

             String name = boardDTO.getName();
             String passwd = boardDTO.getPasswd();
             String title = boardDTO.getTitle();
             String content = boardDTO.getContent();
             String fileName = boardDTO.getFileName();
             int reply = boardDTO.getReply();
             int reply_step = boardDTO.getReply_step();
             int reply_level = boardDTO.getReply_level();

             //현재 답변을 게시물 보다 높은 스텝의 게시물이 있다면 스텝을 하나씩 상승시킴
             String sql1 = "update board set reply_step = reply_step + 1 "
                               + "where reply = " + reply + " and reply_step > " + reply_step;

             jdbcTemplate.update(sql1);

             String sql2 = "insert into board values(board_seq.nextval , ? , ? , ? , ? , ? , sysdate , 0 , ? , ? , ?)";
            
             // reply_step reply_level 1 증가시킨 내용을 저장
             Object[] obj2 = { name, passwd, title, content, fileName, reply, reply_step + 1, reply_level + 1 };
            
             result = jdbcTemplate.update(sql2, obj2);

             return 0;
       }

}




3.  service 클래스를 만들어 보자.



[BoardService.java]


package onj.board.service;

import java.util.List;
import onj.board.model.BoardDTO;
import onj.board.model.CommentDTO;

/*
 * 게시판에서 구현할 기능을 인터페이스로 정의
 */
public interface BoardService {
       //게시판 리스트 보기
       public List<BoardDTO> boardList();     
      
       //게시물 미리보기
       public String preView(String seq);
      
       //게시판 본문 내용보기, 게시글 읽기
       public BoardDTO readContent(String seq);
      
       //커맨트 입력
       public int insertComment(CommentDTO commentDTO);
      
       //커맨트 조회
       public List<CommentDTO> commentList(String seq);
      
       //게시글 입력
       public int insertBoard(BoardDTO board);
      
       //게시글 수정
       public int updateBoard(BoardDTO board);
      
       //게시글 삭제
       public int deleteBoard(String seq , String passwd);
      
       //답글 등록
       public int replyBoard(BoardDTO board); 
            
}



[BoardServiceImpl.java]


package onj.board.service;

import java.util.List;
import onj.board.dao.BoardDAO;
import onj.board.model.BoardDTO;
import onj.board.model.CommentDTO;

public class BoardServiceImpl implements BoardService {
    private BoardDAO boardDAO;
   
    public void setBoardDAO(BoardDAO boardDAO) {
        this.boardDAO = boardDAO;
    }
   
    //게시물 리스트 보기
    public List<BoardDTO> boardList() {
        return boardDAO.boardList();
    }
   
    //게시물 본문 내용 미리보기
    public String preView(String seq) {
        return boardDAO.preView(seq);
    }

    //게시글 읽기
       public BoardDTO readContent(String seq) {
             return boardDAO.readContent(seq);
       }

       //커맨트 입력
       public int insertComment(CommentDTO commentDTO) {
             return boardDAO.insertComment(commentDTO);
       }

       //커맨트 조회
       public List<CommentDTO> commentList(String seq) {
             return boardDAO.commentList(seq);
       }   
      
       //게시글 입력
       public int insertBoard(BoardDTO board) {
             return boardDAO.insertBoard(board);
       }
      
       //게시글 수정
       public int updateBoard(BoardDTO board) {
             return boardDAO.updateBoard(board);
       }
      
       //게시글 삭제
       public int deleteBoard(String seq, String passwd) {
             return boardDAO.deleteBoard(seq, passwd);
       }
      
       //답글 등록
       public int replyBoard(BoardDTO board){
             return boardDAO.replyBoard(board);
       }     
      
}






[BoardServiceHelper.java]


package onj.board.service;

import javax.servlet.ServletContext;

import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

public class BoardServiceHelper {
       public static BoardService getBoardService(ServletContext ctx) {
             WebApplicationContext wac = WebApplicationContextUtils
                                               .getRequiredWebApplicationContext(ctx);
             //boardConfig.xml 정의된 boardService 빈을 리턴
             // 부분은 게시물 미리보기 서블릿(ContentPreview)에서 스프링의 인스턴스를 얻을 이용
             return (BoardService) wac.getBean("boardService");
       }
}






4.     스프링 컨트롤러


[BoardMultiController.java]


package onj.board.controller;

import java.io.PrintWriter;
import java.util.Enumeration;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import onj.board.model.BoardDTO;
import onj.board.model.CommentDTO;
import onj.board.service.BoardService;

import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.multiaction.MultiActionController;

import com.oreilly.servlet.MultipartRequest;
import com.oreilly.servlet.multipart.DefaultFileRenamePolicy;

/*
 * MultiActionController는 비슷하거나 관련있는 로직을 수행하는
 * 다수의 액션을 가지고 있을 때 사용하는 컨트롤러
 * 연관된 요청(Request)를 묶을 때 용이함
 */
public class BoardMultiController extends MultiActionController {
           private BoardService boardService;

           public void setBoardService(BoardService boardService) {
                     this.boardService = boardService;
           }

           // 게시판 리스트 보기, 페이징 기능은 구현 안함
           public ModelAndView list(HttpServletRequest req, HttpServletResponse res)
                                throws Exception {

                     ModelAndView mv = new ModelAndView("list", "list",
                                          boardService.boardList());

                     return mv;
           }

           // 게시글 읽기
           public ModelAndView read(HttpServletRequest req, HttpServletResponse res)
                                throws Exception {
                     String seq = req.getParameter("seq");

                     ModelAndView mav = new ModelAndView("read", "read",
                                          boardService.readContent(seq));
                     // 해당 글의 커맨트도 함께 내려 보내자.
                     mav.addObject("comments", boardService.commentList(seq));
                     return mav;

           }

           // 커맨트쓰기
           public ModelAndView comment(HttpServletRequest req, HttpServletResponse res) {

                     String seq = req.getParameter("seq");

                     CommentDTO commentDTO = new CommentDTO();
                     commentDTO.setSeq(seq);
                     commentDTO.setName(req.getParameter("name"));
                     commentDTO.setComment(req.getParameter("comment"));

                     boardService.insertComment(commentDTO);

                     return new ModelAndView("redirect:/read.html?seq=" + seq);
           }

           // 새글(게시글) 입력
           public ModelAndView write(HttpServletRequest req, HttpServletResponse res)
                                throws Exception {

                     MultipartRequest multi = new MultipartRequest(req,
                                          "c:\\java\\project\\onjboard1\\upload", 5 * 1024 * 1024,
                                          "euc-kr", new DefaultFileRenamePolicy());
                     Enumeration formNames = multi.getFileNames();
                     String formName = (String) formNames.nextElement();
                     String fileName = multi.getFilesystemName(formName);

                     String name = multi.getParameter("name");
                     String passwd = multi.getParameter("passwd");
                     String title = multi.getParameter("title");
                     String content = multi.getParameter("content");

                     BoardDTO board = new BoardDTO(name, passwd, title, content, fileName);

                     boardService.insertBoard(board);

                     return new ModelAndView("redirect:/list.html");
           }

           // 게시글 수정
           public ModelAndView update(HttpServletRequest req, HttpServletResponse res)
                                throws Exception {

                     String seq = req.getParameter("seq");
                     String name = req.getParameter("name");
                     String passwd = req.getParameter("passwd");
                     String title = req.getParameter("title");
                     String content = req.getParameter("content");

                     BoardDTO board = new BoardDTO(name, passwd, title, content, "");
                     board.setSeq(Integer.parseInt(seq));

                     boardService.updateBoard(board);

                     return new ModelAndView("redirect:/read.html?seq="
                                          + req.getParameter("seq"));
           }

           // 게시글 삭제
           public ModelAndView delete(HttpServletRequest req, HttpServletResponse res)
                                throws Exception {
                     String seq = req.getParameter("seq");
                     String passwd = req.getParameter("passwd");

                     int result = boardService.deleteBoard(seq, passwd);

                     if (result != 1) {
                                PrintWriter out = res.getWriter();
                                out.println("<script>alert('password not correct');</script>");
                                out.println("<script>history.go(-1);</script>");
                                return null;
                     } else {
                                return new ModelAndView("redirect:/list.html");
                     }
           }

           // 게시물상세보기에서 답변 클릭시 호출되어 답변달 reply.jsp로 연결
           public ModelAndView reply(HttpServletRequest req, HttpServletResponse res) throws Exception {

                     String seq = req.getParameter("seq");

                     // 답변달 게시물 내용을 reply.jsp 넘긴다.
                     ModelAndView mav = new ModelAndView("reply",   //view이름
                                                                      "reply",   //readContent가 넘기는 boardDTO의 이름, reply.jsp에서 사용
                                                                      boardService.readContent(seq));
                    
                     return mav;
           }

           // 답글 저장
           public ModelAndView replyok(HttpServletRequest req, HttpServletResponse res)
                                throws Exception {

                     String seq = req.getParameter("seq");
                     String name = req.getParameter("name");
                     String passwd = req.getParameter("passwd");
                     String title = req.getParameter("title");
                     String content = req.getParameter("content");
                     String fileName = "";
                     String reply = req.getParameter("reply");
                     String reply_step = req.getParameter("reply_step");
                     String reply_level = req.getParameter("reply_level");

                     BoardDTO boardDTO = new BoardDTO(name, passwd, title, content, fileName);

                     boardDTO.setSeq(Integer.parseInt(seq));
                     boardDTO.setReply(Integer.parseInt(reply));
                     boardDTO.setReply_level(Integer.parseInt(reply_level));
                     boardDTO.setReply_step(Integer.parseInt(reply_step));

                     boardService.replyBoard(boardDTO);

                     return new ModelAndView("redirect:/list.html");
           }

}


5.     AJAX에서 이용되는 게시물 미리보기 서블릿

[ContentPreview.java]

package onj.board.ajaxpreview;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import onj.board.service.BoardService;
import onj.board.service.BoardServiceHelper;

//Servlet3.0이상, Tomcat7 이상에서는 애노테이션으로 서블릿 정의가 가능하다.
//@WebServlet(urlPatterns = "/preView")
public class ContentPreview extends HttpServlet {
           protected void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
                     String seq = req.getParameter("seq");
                    
                     req.setCharacterEncoding("utf-8");
                     res.setContentType("text/html; charset=utf-8");
                     res.setHeader("Cache-Control",  "no-cache");
                               
                     BoardService boardService = BoardServiceHelper.getBoardService(getServletContext());
                               
                     PrintWriter out = res.getWriter();  
                     out.println("<pre>" + boardService.preView(seq) + "<pre>");
           }         
}




6.     model 쪽 클래스

[BoardDTO.java]

package onj.board.model;

public class BoardDTO {
       private int seq;
       private String name;
       private String passwd;
       private String title;
       private String content;
       private String fileName;
       private String regdate;
       private int readCount;
       private int reply;
       private int reply_step;
       private int reply_level;
      
       public BoardDTO() {}
      
       public BoardDTO(String name, String passwd, String title, String content, String fileName) {
             this.name = name;
             this.passwd = passwd;
             this.title = title;
             this.content = content;
             this.fileName = fileName;
       }
      
       public BoardDTO(String name, String passwd, String title, String content, String fileName, int readCount) {
             this.name = name;
             this.passwd = passwd;
             this.title = title;
             this.content = content;
             this.fileName = fileName;
             this.readCount = readCount;
       }

       public int getSeq() {
             return seq;
       }

       public void setSeq(int seq) {
             this.seq = seq;
       }

       public String getName() {
             return name;
       }

       public void setName(String name) {
             this.name = name;
       }

       public String getPasswd() {
             return passwd;
       }

       public void setPasswd(String passwd) {
             this.passwd = passwd;
       }

       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 getFileName() {
             return fileName;
       }

       public void setFileName(String fileName) {
             this.fileName = fileName;
       }

       public String getRegdate() {
             return regdate.substring(0, 10);  //2013-07-15 형태
       }

       public void setRegDate(String regdate) {
             this.regdate = regdate;
       }

       public int getReadCount() {
             return readCount;
       }

       public void setReadCount(int readCount) {
             this.readCount = readCount;
       }

       public int getReply() {
             return reply;
       }

       public void setReply(int reply) {
             this.reply = reply;
       }

       public int getReply_step() {
             return reply_step;
       }

       public void setReply_step(int reply_step) {
             this.reply_step = reply_step;
       }

       public int getReply_level() {
             return reply_level;
       }

       public void setReply_level(int reply_level) {
             this.reply_level = reply_level;
       }     
      
}




[commentDTO.java]

package onj.board.model;

public class CommentDTO {
       public String seq;       //게시글 번호
       public String name;   //이름
       public String comment;//커맨트
      
       public CommentDTO() {}
      
       public String getSeq() {
             return seq;
       }
       public void setSeq(String seq) {
             this.seq = seq;
       }
       public String getName() {
             return name;
       }
       public void setName(String name) {
             this.name = name;
       }
       public String getComment() {
             return comment;
       }
       public void setComment(String comment) {
             this.comment = comment;
       }
      
}



7.     /jsp/list.jsp

[list.jsp]


<%@ page contentType="text/html; charset=euc-kr" language="java" errorPage="" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>오엔제이 프로그래밍 실무학원</title>
<meta http-equiv="Content-Type" content="text/html; charset=euc-kr">
<style type="text/css">
       #layer1{
             position:absolute;
             padding:5px;
             filter:alpha(opacity=50);
             width:250px; height:150px;
             background-color:white;
             border:2px #000000 dotted;
             visibility:hidden;
       }
</style>
<script language="javascript" type="text/javascript" src="/onjboard1/js/createXMLHttpRequest.js"></script>
<script type="text/javascript">
       var xmlHttp;
       var xmlDoc;
       var message;
      
       function contentprev(seq){
            
             var url = "preView?seq="+seq;  //미리보기 서블릿 호출
             xmlHttp = createXMLHttpRequest();
             xmlHttp.onreadystatechange = handleStateChange;
             xmlHttp.open("get" , url , true);
             xmlHttp.send(null);
       }
      
       function handleStateChange(){
             if(xmlHttp.readyState == 4){
                           if(xmlHttp.status == 200){
                                        xmlDoc = xmlHttp.responseText;
                                        document.getElementById("layer1").innerHTML = xmlDoc;
                           }
             }
       }

       function showlayer(id){   
             if(document.all)
                    document.all[id].style.visibility="visible";
             else if(document.layers)
                    document.layers[id].style.visibility="visible";            
       }
       function hidelayer(id){   
             if(document.all)
                    document.all[id].style.visibility="hidden";
             else if(document.layers)
                    document.layers[id].style.visibility="hidden";      
       }
    function movetip() {
        layer1.style.pixelTop=event.y+document.body.scrollTop+10;
        layer1.style.pixelLeft=event.x+document.body.scrollLeft+10;
    }
    document.onmousemove=movetip;              
</script>
</head>
<body>
<div id="layer1">
             게시물 본문 미리 보기
</div>
<div style="width:500px;">
<div style="float:right;">
<H3>오엔제이 프로그래밍 실무교육센터 스프링 게시판</H3>
<h5> ${list.size()}</h5>
<table width="600" border="1" align="left">
  <tr align="left">
    <td width="10%" align="center">번호</td>
    <td width="40%" align="center">제목</td>
    <td width="20%" align="center">이름</td>
    <td width="20%" align="center">날짜</td>
    <td width="10%" align="center">조회</td>
  </tr>
              <!-- list 가져와서 board 명명 만큼 반복 -->
             <c:forEach var="board" items="${list}">      
  <tr>
    <td align="center">
                    <c:if test="${board.reply_step == 0}">
                                 ${board.seq}
                    </c:if>
                    <c:if test="${board.reply_step != 0}">
                                 &nbsp;
                    </c:if>                   
    </td>
    <td>      <!-- 게시물은 덧글에 따른 번호와 덧글 존재 유무로 정렬됨 -->
                    <c:choose>                
                           <c:when test="${board.reply_step != 0}"><!-- 게시글이 덧글일 경우 -->
                                 <c:forEach var="i" begin="1" end="${board.reply_level}" step="1"><!-- 레벨의 수만큼 글을 뒤로 민다 -->
                                        &nbsp;&nbsp;
                                 </c:forEach>
                                        <a href="read.html?seq=${board.seq}" onmouseover="contentprev('${board.seq}');showlayer('layer1');" onmouseout="hidelayer('layer1');">${board.title}</a>
                                        <!-- 마우스를 올리면 게시물 번호에 따른 showlayer(게시물 미리보기 ) 실행됨 -->
                           </c:when>
                           <c:when test="${board.reply_step == 0}">
                                        <a href="read.html?seq=${board.seq}" onmouseover="contentprev('${board.seq}');showlayer('layer1');" onmouseout="hidelayer('layer1');">${board.title}</a>                    
                           </c:when>
                    </c:choose>
   </td>
    <td align="center">${board.name}</td>
    <td align="center">${board.regdate}</td>
    <td align="center">${board.readCount}</td>
  </tr>
             </c:forEach>

  <tr>
    <td align="center"><input type="button" value="글쓰기" onclick="location.href='/onjboard1/jsp/write.jsp'"></td>
    <td>&nbsp;</td>
    <td>&nbsp;</td>
    <td>&nbsp;</td>
    <td>&nbsp;</td>
  </tr>
</table>
</div>
</div>
</body>
</html>



8.     read.jsp.

[read.jsp]

<%@ page contentType="text/html; charset=euc-kr" language="java" errorPage="" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>게시물 읽기</title>
<meta http-equiv="Content-Type" content="text/html; charset=euc-kr">
<script>
       function write_ok(){
             writeform.submit();
       }
       function update_ok(){
             document.viewform.action = '/onjboard1/update.html';
             document.viewform.submit();
       }
</script>
</head>

<body>
<div style="width:600px;">
<div style="float:enter;">

<table width="600" height="420" border="1" align="center">
  <tr height="20"><h2>오엔제이프로그래밍실무교육센터 게시판</h2></tr>
  <form name="viewform" method="post">
  <input type="hidden" name="seq" value="${read.seq}">
  <input type="hidden" name="reply" value="${read.reply}">
  <input type="hidden" name="reply_step" value="${read.reply_step}">
  <input type="hidden" name="reply_level" value="${read.reply_level}">
  <tr>
    <td width="100">* 이름</td>
    <td width="500">: <input name="name" type="text" value="${read.name}" size="50" readonly>
      </td>
  </tr>
  <tr>
    <td>* 제목</td>
    <td>:
    <input name="title" type="text" value="${read.title}" size="50" ></td>
  </tr>
  <tr align="center">
    <td colspan="2"><textarea name="content" cols="80" rows="12" >${read.content}</textarea></td>
  </tr>
  <tr>
    <td>* 파일</td>
    <td>:
                    <c:choose>
                           <c:when test="${read.fileName != null}">
                                 ${read.fileName}                                    
                           </c:when>
                           <c:when test="${read.fileName == null}">
                                 파일 없음
                           </c:when>
                    </c:choose>
       </td>
  </tr>
  <tr>
    <td>&nbsp;</td>
    <td><input name="button" type="button" onClick="location.href='/onjboard1/reply.html?seq=${read.seq}'" value="답변">
|
  <input name="button" type="button" onClick="update_ok()" value="수정">
<input name="button" type="button" onClick="location.href='/onjboard1/jsp/delete.jsp?seq=${read.seq}'" value="삭제">
|
<input name="button" type="button" onClick="location.href='/onjboard1/list.html'" value="목록"></td>
  </tr>
  </form>
  <tr>
    <td height="99" colspan="2">
    <!-- BoardMultiController comment() 메소드 호출 -->
    <form method="post" action="comment.html">
           <table border="1">
             <tr>          
               <td>이름 : </td>
               <td><input type="text" name="name"></td>
               <td>코멘트:</td>
               <td><input type="text" name="comment"></td>
               <td><input type="submit" name="Button" value="쓰기"></td>
             </tr>
           </table>
           <input type="hidden" name="seq" value="${read.seq}">
    </form>
            <!--  달려있는 커맨트 보기 -->
              <table width="789" border="1">
                  <c:forEach var="comment" items="${comments}">
                               <tr>
                              <td width="42" align="center">*</td>
                              <td width="86">${comment.name}</td>
                              <td width="639">${comment.comment}</td>
                            </tr>
                        </c:forEach>
             </table>
      </td>
    </tr>
   
</table>
<br><br>
<table><tr><td><tr><b>http://www.onjprogramming.co.kr</tr></td></tr></table>


</div>
</div>
</body>
</html>



9.     /jsp/reply.jsp 작성.

[reply.jsp]

<%@ page contentType="text/html; charset=euc-kr" language="java" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>답변 달기</title>
<meta http-equiv="Content-Type" content="text/html; charset=euc-kr">
<script>
       function write_ok(){
             if(document.form.name.value == ""){
                           alert("이름을 입력하세요.");
                           document.form.name.focus();
                           return false;
             }
             if(document.form.title.value == ""){
                           alert("제목을 입력하세요.");
                           document.form.title.focus();
                           return false;
             }
             if(document.form.content.value == ""){
                           alert("내용을 입력하세요.");
                           document.form.content.focus();
                           return false;
             }           
             if(document.form.passwd.value == ""){
                           alert("비밀번호를  입력하세요.");
                           document.form.passwd.focus();
                           return false;
             }     
       form.submit();
       }
</script>
</head>
<body>
<div style="width:600px;">
<form method="post" name="form" action="/onjboard1/replyok.html">
<table><tr><td><h2>오엔제이프로그래밍실무교육센터 게시판(답글달기)</h2><tr><td></table>
<table width="600" height="277" border="1" align="center">
  <tr>
    <td width="120">* 이름</td>
    <td width="480">: <input name="name" type="text" size="50"></td>
  </tr>
  <tr>
    <td>* 제목</td>
    <td>:
    <input name="title" type="text" value="Re: ${reply.title}" size="50"></td>
  </tr>
  <tr align="center">
    <td colspan="2"><textarea name="content" cols="80" rows="10">${reply.content}</textarea></td>
  </tr>
  <tr>
    <td>* 비밀번호</td>
    <td>:
      <input type="password" name="passwd"></td>
  </tr>
  <tr>
    <td>&nbsp;</td>
    <td><input type="button" value="답변" onclick="write_ok();"> |
        <input type="button" value="취소" onclick="history.back();"></td>
  </tr>
</table>
<input type="hidden" name="seq" value="${reply.seq}">
<input type="hidden" name="reply" value="${reply.reply}">
<input type="hidden" name="reply_step" value="${reply.reply_step}">
<input type="hidden" name="reply_level" value="${reply.reply_level}">
</form>
</div>
<br><br>
<table><tr><td><tr><b>http://www.onjprogramming.co.kr</tr></td></tr></table>
</body>
</html>


10.   /jsp/delete.jsp 작성.

[delete.jsp]

<%@ page contentType="text/html; charset=euc-kr" language="java" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>오엔제이프로그래밍실무교육센터 게시물 삭제</title>
<meta http-equiv="Content-Type" content="text/html; charset=euc-kr">
<script>
       function del_ok(){
             if(document.delform.passwd.value == ""){
                           alert("비밀번호를  입력하세요.");
                           document.delform.passwd.focus();
                           return false;
             }     
            
             delform.submit();
       }
</script>
</head>

<body>
<form method="post" name="delform" action="/onjboard1/delete.html">
<table border="1" align="center">
       <tr>
             <td>비밀번호</td>
             <td><input type="text" name="passwd"></td>
         <td><input type="button" value="확인" onclick="del_ok();">
           <input name="button" type="button" value="취소" onclick="history.back();"></td>           
       </tr>       
</table>
<table align="center"><tr><td><a href="/onjboard1/list.html">목록보기</a></td></tr></table>
<input type="hidden" name="seq" value="${param.seq}">
</form>
</body>
</html>



11.   /jsp/write.jsp 작성.

[write.jsp]

<%@ page contentType="text/html; charset=euc-kr" language="java" errorPage="" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>게시물 쓰기</title>
<meta http-equiv="Content-Type" content="text/html; charset=euc-kr">
<script language="javascript" type="text/javascript">
       function form_check(){
             if(document.form.name.value == ""){
                           alert("이름을 입력하세요.");
                           document.form.name.focus();
                           return false;
             }
             if(document.form.title.value == ""){
                           alert("제목을 입력하세요.");
                           document.form.title.focus();
                           return false;
             }
             if(document.form.content.value == ""){
                           alert("내용을 입력하세요.");
                           document.form.content.focus();
                           return false;
             }           
             if(document.form.passwd.value == ""){
                           alert("비밀번호를  입력하세요.");
                           document.form.passwd.focus();
                           return false;
             }
      
       document.form.submit();
       }

function addFileForm(){

  var tb1 = document.getElementById("file_table");
  if(9 >= tb1.rows.length) {
   var idx = getObj().parentElement.rowIndex + 1;
   var trow= tb1.insertRow(idx);
   var uploadOBJ="<input name='attatch' type='file' class='TEXT_FORM' id='f_id'><a OnClick='javascript:addFileForm();'>&nbsp;추가</a>&nbsp;&nbsp;<a OnClick='javascript:deleteRow();'>삭제</a>&nbsp;";
   trow.insertCell(0).innerHTML = uploadOBJ;
  } else {
   alert("문서파일은 10 이상 접수할   없습니다.");
   return;
  }
 }

 function getObj()
 {
     var obj = event.srcElement
     while (obj.tagName !='TD') //TD 나올때까지의 Object추출
     {
         obj = obj.parentElement
     }
     return obj
 }

 function deleteRow(){
  var tb1 = document.getElementById("file_table");

  var idx = getObj().parentElement.rowIndex;

  if(tb1.rows.length-1 !=0){
   var tRow = tb1.deleteRow(idx);
  }else{
    document.getElementById('f_id').select();
       document.selection.clear();
  }
 }
</script>

</head>

<body>
<H3>오엔제이 프로그래밍 실무교육센터 스프링 게시판 글쓰기</H3>
<div style="width:600px;">
<div style="float:right;">
<!--  /write.html 요천의 경우 컨트롤로의 write 메소드가 실행되도록 매핑되어있다 -->
<form name="form" method="post" action="/onjboard1/write.html" enctype="multipart/form-data">
<table width="580" height="277" border="1" align="center">
  <tr>
    <td width="100">* </td>
    <td width="580">: <input name="name" type="text" size="50">
      </td>
  </tr>
  <tr>
    <td>* </td>
    <td>:
    <input name="title" type="text" size="50"></td>
  </tr>
  <tr align="center">
    <td colspan="2"><textarea name="content" cols="80" rows="10"></textarea></td>
  </tr>
  <tr>
    <td>*   :</td>
    <td><table id="file_table">
                           <tr>
                                     <td>
                                                 <input name="attatch" type="file" class="TEXT_FORM" id="f_id"><a OnClick="javascript:addFileForm();">&nbsp;추가</a>&nbsp;&nbsp;<a OnClick="javascript:deleteRow();">삭제</a>
                                     </td>
                       </tr>
               </table>
    </td>
  </tr>
  <tr>
    <td>* 비밀번호</td>
    <td>:
      <input type="password" name="passwd"></td>
  </tr>
  <tr>
    <td>&nbsp;</td>
    <td><input type="button" name="Submit" value="쓰기" onclick="form_check();">
      <input type="button" name="Submit2" value="취소" onclick="history.back();"></td>
  </tr>
</table>
</div>
</div>
</form>
</body>
</html>


12.   /js/createXMLHttpRequest.js.

[createXMLHttpRequest.js]

             function createXMLHttpRequest(){
                    var xmlHttp;
                    if(window.ActiveXObject){
                                 try{
                                              xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
                                 } catch(e){
                                        try{
                                              xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
                                        } catch(e1){
                                              xmlHttp = null;
                                        }
                                 }
                    } else if(window.XMLHttpRequest){
                           try{
                                        xmlHttp = new XMLHttpRequest();
                           } catch(e){
                                        xmlHttp = null;
                           }
                    }
                          
                    if(xmlHttp == null) errorMessage();
                    return xmlHttp;
             }
      
             function errorMessage(){
                    alert("지원할 없는 브라우저입니다.");
             }





13.   /WEB-INF/action-servlet.xml

[action-servlet.xml]


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
<beans>

       <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
             destroy-method="close">
             <property name="driverClassName">
                    <value>oracle.jdbc.driver.OracleDriver</value>
             </property>
             <property name="url">
                    <value>jdbc:oracle:thin:@127.0.0.1:1521:onj</value>
             </property>
             <property name="username">
                    <value>scott</value>
             </property>
             <property name="password">
                    <value>tiger</value>
             </property>
       </bean>

       <!-- 넘어오는 URL 따라 컨트롤러에서 실행될 메소드 매핑 -->
       <!-- PropertiesMethodNameResolver prop key 넘어오는 url 대해 실행할 컨트롤러의 메소드
             정의 -->
       <bean id="userControllerMethodNameResolver"
              class="org.springframework.web.servlet.mvc.multiaction.PropertiesMethodNameResolver">
             <property name="mappings">
                    <props>
                           <!-- list.html 요청이 오면 컨트롤러의 list 메소드 실행 -->
                           <prop key="/list.html">list</prop>
                          
                           <!-- read.html 요청이 오면 컨트롤러의 read 메소드 실행 -->
                           <prop key="/read.html">read</prop>
                          
                           <!-- comment.html 요청이 오면 컨트롤러의 comment 메소드 실행 -->
                           <prop key="/comment.html">comment</prop>
                          
                           <!-- write.html 요청이 오면 컨트롤러의 write 메소드 실행 -->
                           <prop key="/write.html">write</prop>
                          
                           <!-- update.html 요청이 오면 컨트롤러의 update 메소드 실행 -->
                           <prop key="/update.html">update</prop>                                  
                          
                           <!-- delete.html 요청이 오면 컨트롤러의 delete 메소드 실행 -->
                           <prop key="/delete.html">delete</prop>
                          
                           <!-- reply.html 요청이 오면 컨트롤러의 reply 메소드 실행 -->
                           <prop key="/reply.html">reply</prop>
                          
                           <!-- replyok.html 요청이 오면 컨트롤러의 replyok 메소드 실행 -->
                           <prop key="/replyok.html">replyok</prop>
                    </props>
             </property>
       </bean>

       <!-- 리졸버 -->
       <bean id="viewResolver"
             class="org.springframework.web.servlet.view.InternalResourceViewResolver">
             <property name="prefix">
                    <value>/jsp/</value>
             </property>
             <property name="suffix">
                    <value>.jsp</value>
             </property>
       </bean>

       <!-- 컨트롤러 매핑 -->
       <bean name="/list.html /read.html /comment.html /write.html
                   /update.html /delete.html /reply.html /replyok.html"
            class="onj.board.controller.BoardMultiController">
             <property name="methodNameResolver">
                    <ref local="userControllerMethodNameResolver" />
             </property>
             <property name="boardService">
                    <ref bean="boardService" />
             </property>
       </bean>
      
</beans>



14.   /WEB-INF/boardConfig.xml

[boardConfig.xml]

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
<beans>
       <bean id="boardDAO"  class="onj.board.dao.SpringBoardDAO">
             <property name="dataSource">
                    <ref bean="dataSource"/>
             </property>
       </bean>

       <bean id="boardService" class="onj.board.service.BoardServiceImpl">
             <property name="boardDAO">
                    <ref bean="boardDAO"/>
             </property>
       </bean>
</beans>    




15.   /WEB-INF/web.xml

[web.xml]

<?xml version="1.0" encoding="UTF-8"?>
       <display-name>OnJSpringBoard1.0, 오엔제이프로그래밍실무교육센터</display-name>
      
       <filter>
             <filter-name>encodingFilter</filter-name>
             <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
             <init-param>
                    <param-name>encoding</param-name>
                    <param-value>EUC-KR</param-value>
             </init-param>
       </filter>

       <filter-mapping>
             <filter-name>encodingFilter</filter-name>
             <url-pattern>/*</url-pattern>
       </filter-mapping>
      
       <!--  ContextLoaderListener 설정 -->
       <listener>
               <listener-class>
                           org.springframework.web.context.ContextLoaderListener
               </listener-class>
        </listener>
      
       <!--  ContextLoaderListener 설정 파일 -->
       <context-param>
             <param-name>contextConfigLocation</param-name>
                    <param-value>
                           /WEB-INF/boardConfig.xml,
                           /WEB-INF/action-servlet.xml
                    </param-value>
       </context-param>

       <!-- 디스패처 서블릿 정의 설정 -->
       <servlet>
             <servlet-name>action</servlet-name>
             <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
             <load-on-startup>1</load-on-startup>
       </servlet>
      
       <servlet-mapping>
             <servlet-name>action</servlet-name>
             <url-pattern>*.html</url-pattern>
       </servlet-mapping>
      

       <!--  게시물 미리 보기 기능을 위한 ajax 처리용 서블릿 정의 -->
       <servlet>
             <servlet-name>preView</servlet-name>
             <servlet-class>onj.board.ajaxpreview.ContentPreview</servlet-class>
       </servlet>  

       <servlet-mapping>
             <servlet-name>preView</servlet-name>
             <url-pattern>/preView</url-pattern>
       </servlet-mapping>

</web-app>





























[출처]오라클자바커뮤니티



www.oraclejavacommunity.co.kr

댓글 없음:

댓글 쓰기