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}">
</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"><!-- 레벨의
수만큼
글을
뒤로
민다 -->
</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> </td>
<td> </td>
<td> </td>
<td> </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> </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> </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();'> 추가</a> <a
OnClick='javascript:deleteRow();'>삭제</a> ";
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();"> 추가</a> <a OnClick="javascript:deleteRow();">삭제</a>
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td>* 비밀번호</td>
<td>:
<input type="password" name="passwd"></td>
</tr>
<tr>
<td> </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"?>
<web-app id="WebApp_ID" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<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
댓글 없음:
댓글 쓰기