게시판 만들기

1. 게시판 테이블 생성

1) mariadB 게시판 테이블 생성

구문 내용
bno 글번호
title 글제목
content 글 내용
regdate 작성일
updatedate 수정일
readcnt 조회수
ip 작성한곳 아이피
email email
create table springboard(
    bno int primary key,
    title varchar(50) not null, 
    content LONGTEXT,
    regdate date default now(), 
    updatedate date default now(), 
    readcnt int default 0,
    ip varchar(50),
    email varchar(50) references springuser(email) on delete set null);

SELECT  * from springboard;

2. VO

domain 패키지에 board 테이블을 위한 board 클래스 생성

package com.gmail.hi.domain;
import java.util.Date;
import lombok.Data;

@Data
public class Board {
    private int bno;
    private String title;
    private String content;
    private Date regdate;
    private Date updatedate;
    private int readcnt;
    private String ip;
    private String email;
    private String nickname;
    private String dispdate;
}

3. 게시글 작성 처리

home.jsp 파일에서 글쓰기의 링크를 로그인이 된 경우에만 사용할 수 있도록 board/register로 설정

        <div class="box-header with-border">

            <a href="board/register"><h3 class="box-title">게시판 글쓰기</h3></a>
        </div>

header.jsp 파일에서 글쓰기의 링크를 로그인이 된 경우에만 사용할 수 있도록 board/register로 설정

                <li role="presentation"><a href="/board/register">게시물 쓰기 </a></li>

기본패키지에 BoardController 클래스를 생성하고 요청 처리 메소드 생성

package com.gmail.hi;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import com.gmail.hi.domain.Board;

@Controller
@RequestMapping("/board/*")
public class BoardController {
    @RequestMapping(value = "/register", method = RequestMethod.GET)
    public void registerGET(Board board, Model model) {
    }
}

views 디렉토리에 board 디렉토리를 만들고 register.jsp 파일을 생성하고 작성

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@include file="../include/header.jsp"%>
<div class="row">
    <div class="col-lg-12">
        <h1 class="page-header">게시글 작성</h1>
    </div>
    <!-- /.col-lg-12 -->
</div>
<!-- /.row -->
<div class="row">
    <div class="col-lg-12">
        <div class="panel panel-default">
            <div class="panel-heading">게시글 작성</div>
            <!-- /.panel-heading -->
            <div class="panel-body">
                <form role="form" method="post">
                    <div class="form-group">
                        <label>제목</label> <input class="form-control" name='title'>
                    </div>
                    <div class="form-group">
                        <label>내용</label>
                        <textarea class="form-control" rows="3" name='content'></textarea>
                    </div>
                    <div class="form-group">
                        <label>작성자</label> 
                        <input class="form-control" name='writer' value="${user.nickname}" readonly="readonly">
                    </div>
                    <button type="submit" class="btn btn-primary">작성완료</button>
                    <button type="reset" class="btn btn-default">다시작성</button>
                    <input type="button" value="메인으로" class="btn btn-success" onclick="javascript:window.location='/'">
                </form>
            </div>
            <!-- end panel-body -->
        </div>
        <!-- end panel-body -->
    </div>
    <!-- end panel -->
</div>
<%@include file="../include/footer.jsp"%>

mappers 디렉토리에 springboard 테이블에 대한 SQL을 작성하는 board.xml 파일을 만들고 삽입을 위한 sql을 추가

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="board">
    <insert id="register" parameterType="Board">
        insert into springboard(bno, title, content, ip, email)
        values(boardseq.nextval, #{title}, #{content}, #{ip}, #{email})
    </insert>
</mapper>

image-20200326204423611

Unknown column 'boardseq.nextval' in 'field list'

MYSQL은 sequence 기능이 없기에 Mysql 문법으로 수정해줬다.

덕분에 DB 테이블도 수정해줌 - 이미 만들어진거라 추가했다 AUTO_INCREMENT

ALTER TABLE springboard MODIFY bno INT NOT NULL AUTO_INCREMENT;
  • board.xml 파일에 sql 구문 수정
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="board">
    <insert id="register" parameterType="Board">
        insert into springboard(bno, title, content, ip, email)
        select case count(*) when 0 then 1 else max(bno) + 1 end, #{title}, #{content}, #{ip}, #{email} from springboard
    </insert>
</mapper>

이 방법은 데이타베이스에 초기에 seq값을 안 들어가있을 경우 즉. seq가 0일 때도 무리없이 실행시킬수 있기 때문에 테스트하기에 가장 좋습니다. 출처: https://hunit.tistory.com/201 [Ara Blog]

dao 패키지에 BoardDao 클래스를 추가하고 게시글을 삽입하는 메소드 구현

package com.gmail.hi.dao;

import org.apache.ibatis.session.SqlSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import com.gmail.hi.domain.Board;

@Repository
public class BoardDao {
    @Autowired
    private SqlSession sqlSession;

    public void register(Board vo) {
        sqlSession.insert("board.register", vo);
    }
}

기본 패키지에 BoardService 인터페이스를 만들고 게시글 삽입을 위한 메소드 선언

package com.gmail.hi;

import javax.servlet.http.HttpServletRequest;

public interface BoardService {
    public void register(HttpServletRequest request);
}

service 패키지에 BoardServiceImpl 클래스를 만들고 메소드구현

package com.gmail.hi.service;

import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.gmail.hi.BoardService;
import com.gmail.hi.dao.BoardDao;
import com.gmail.hi.domain.Board;
import com.gmail.hi.domain.User;

@Service
public class BoardServiceImpl implements BoardService {

    @Autowired
    private BoardDao boardDao;

    @Override
    public void register(HttpServletRequest request) {
        // 매개변수가 request일 때는 파라미터를 읽습니다.
        String title = request.getParameter("title");
        String content = request.getParameter("content");
        User user = (User) request.getSession().getAttribute("user");
        String email = user.getEmail();
        if (title.length() == 0) {
            title = "무제";
        }
        if (content.length() == 0) {
            content = "냉무";
        }
        // 필요한 데이터를 생성
        String ip = request.getRemoteAddr();
        Board vo = new Board();
        vo.setTitle(title);
        vo.setContent(content);
        vo.setEmail(email);
        vo.setIp(ip);
        // DAO의 메소드를 호출
        boardDao.register(vo);
    }
}

BoardController 클래스에 삽입 처리를 위한 Service 클래스를 주입

    @Autowired
    private BoardService boardService;

BoardController 클래스에 삽입 처리를 위한 메소드를 작성

    @RequestMapping(value = "/register", method = RequestMethod.POST)
    public String registPOST(HttpServletRequest request, RedirectAttributes rttr) {
        boardService.register(request);
        rttr.addFlashAttribute("msg", "게시글 작성에 성공하셨습니다.");
        return "redirect:/board/list";
    }

4. 전체 목록 보기

home.jsp 파일에 전체 목록 보기 링크를 추가

        <div class="box-header with-border">

            <a href="board/list"><h3 class="box-title">게시판 목록보기</h3></a>
        </div>

header.jsp 파일의 목록보기 경로도 변경

<li role="presentation"><a href="/board/list">목록보기 </a></li>

board.xml 파일에 전체 목록 보기를 위한 sql을 추가

    <!-- 전체 목록을 가져오는 sql -->
    <select id="list" resultType="Board">
        select bno, title, nickname, regdate, readcnt, u.email
        from springuser u, springboard b
        where u.email = b.email
        order by updatedate desc
    </select>

BoardDao 클래스 전체 목록 보기를 위한 메소드 구현

    public List<Board> list() {
        return sqlSession.selectList("board.list");
        }

BoardService 인터페이스에 전체 목록 보기 처리를 위한 메소드 선언

    public List<Board> list();

BoardServiceImpl 클래스에 전체 목록 보기 처리를 위한 메소드 구현

  • Date today = new Date(cal.getTimeInMilles());
  • 이 구문은.. Date 자료형이라 substring() 으로 자를 수가 없다.
  • 과감하게 구문 빼고 SimpleDateFormat 으로 변경
    @Override
    public List<Board> list() {
        List<Board> list = boardDao.list();
        Calendar cal = Calendar.getInstance();
        // Date today = new Date(cal.getTimeInMillis());
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
        String strDate = sdf.format(cal.getTime());


        for (Board vo : list) {
            if (strDate.toString().equals(vo.getRegdate().substring(0, 10))) {
                vo.setDispdate(vo.getRegdate().substring(11));
            } else {
                vo.setDispdate(vo.getRegdate().substring(0, 10));
            }
        }
        return list;
    }

domain 패키지에 board 클래스에서 Date 자료형을 String으로 변경하였다.

package com.gmail.hi.domain;
import java.util.Date;
import lombok.Data;

@Data
public class Board {
    private int bno;
    private String title;
    private String content;
    private String regdate;
    private String updatedate;
    private int readcnt;
    private String ip;
    private String email;
    private String nickname;
    private String dispdate;
}

BoardController에 전체목록보기 요청을 처리하는 메소드를 작성

    @RequestMapping(value = "/list", method = RequestMethod.GET)
    public void list(Model model) {
        List<Board> list = boardService.list();
        model.addAttribute("list", list);
    }

board 디렉토리에 list.jsp 파일을 생성하고 작성

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@include file="../include/header.jsp"%>
<div class="box">
    <div class="box-header with-border">
        <c:if test="${msg == null}">
            <h3 class="box-title">게시판 목록보기</h3>
        </c:if>
        <c:if test="${msg != null}">
            <h3 class="box-title">${msg}</h3>
        </c:if>
    </div>
    <div class="box-body">
        <table class="table table-bordered table-hover">
            <tr>
                <th width="11%">글번호</th>
                <th width="46%">제목</th>
                <th width="16%">작성자</th>
                <th width="16%">작성일</th>
                <th width="11%">조회수</th>
            </tr>
            <c:forEach var="vo" items="${list }">
                <tr>
                    <td align="right">${vo.bno}&nbsp;</td>
                    <td>&nbsp; ${vo.title}</td>
                    <td>&nbsp;${vo.nickname}</td>
                    <td>&nbsp; ${vo.dispdate}</td>
                    <td align="right"><span class="badge bg-blue">
                            ${vo.readcnt}</span>&nbsp;</td>
                </tr>
            </c:forEach>
        </table>
    </div>
    <div class="box-footer">
        <div class="text-center">
            <button id='mainBtn' class="btn-primary">메인으로</button>
        </div>
        <script>
            document.getElementById('mainBtn').addEventListener("click",
                    function(event) {
                        location.href = "../";
                    });
        </script>
    </div>
</div>
<%@include file="../include/footer.jsp"%>

5. 상세보기

list.jsp 파일의 제목을 출력하는 부분에 링크를 추가

<a href="detail/${vo.bno}">${vo.title}</a>

            <c:forEach var="vo" items="${list }">
                <tr>
                    <td align="right">${vo.bno}&nbsp;</td>
                    <td>&nbsp; <a href="detail/${vo.bno}">${vo.title}</a></td>
                    <td>&nbsp;${vo.nickname}</td>
                    <td>&nbsp; ${vo.dispdate}</td>
                    <td align="right"><span class="badge bg-blue">
                            ${vo.readcnt}</span>&nbsp;</td>
                </tr>
            </c:forEach>

board.xml 파일에 상세 보기를 위한 sql을 추가

    <!-- 글번호를 가지고 하나의 데이터를 가져오는 sql -->
    <select id="detail" resultType="Board"
        parameterType="java.lang.Integer">
        select bno, title, content, u.email, ip, nickname, regdate, updatedate,
        readcnt
        from springuser u, springboard b
        where u.email = b.email and bno = #{bno}
    </select>

    <!-- 글번호를 가지고 조회수를 1증가시키는 sql -->
    <update id="updateReadcnt" parameterType="java.lang.Integer">
        update springboard
        set readcnt = readcnt + 1
        where bno = #{bno}
    </update>

BoardDao 클래스 상세 보기를 위한 메소드 구현

    public Board detail(int bno) {
        return sqlSession.selectOne("board.detail", bno);
    }

    public void updateReadcnt(int bno) {
        sqlSession.update("board.updateReadcnt", bno);
    }

BoardService 인터페이스에 상세 보기 처리를 위한 메소드 선언

//글번호를 가지고 하나의 게시글을 가져오는 메소드
public Board detail(int bno);

BoardServiceImpl 클래스에 상세 보기 처리를 위한 메소드 구현

@Override
public Board detail(int bno){
    boardDao.updateReadcnt(bno);
    return boardDao.detail(bno);
}

BoardController의 상세보기 처리 요청의 메소드를 추가

    @RequestMapping(value = "/detail/{bno}", method = RequestMethod.GET)
    public String detail(@PathVariable("bno") int bno, Model model) {
        model.addAttribute("vo", boardService.detail(bno));
        return "board/detail";
    }

board 디렉토리에 detail.jsp 파일을 추가하고 작성

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ include file="../include/header.jsp"%>
<section class="content">
    <div class="box">
        <div class="box-header">
            <h3 class="box-title">상세보기</h3>
        </div>
        <div class="box-body">
            <div class="form-group">
                <label>제목</label> <input type="text" name="title"
                    class="form-control" value="${vo.title}" readonly="readonly" />
            </div>
            <div class="form-group">
                <label>내용</label>
                <textarea name="content" rows="5" readonly="readonly"
                    class="form-control">${vo.content}</textarea>
            </div>
            <div class="form-group">
                <label>작성자</label> <input type="text" class="form-control"
                    value="${vo.nickname}" readonly="readonly" />
            </div>
        </div>
        <div class="box-footer">
            <button class="btn btn-success" id="mainbtn">메인</button>
            <c:if test="${user.email == vo.email}">
                <button class="btn btn-warning" id="updatebtn">수정</button>
                <button class="btn btn-danger" id="deletebtn">삭제</button>
            </c:if>
            <button class="btn btn-primary" id="listbtn">목록</button>
        </div>
    </div>
</section>
<%@ include file="../include/footer.jsp"%>
<script>
    //메인 버튼을 눌렀을 때 처리
    document.getElementById("mainbtn").addEventListener("click", function() {
        location.href = "/";
    });
    //목록 버튼을 눌렀을 때 처리
    document.getElementById("listbtn").addEventListener("click", function() {
        location.href = "/board/list";
    });
    <c:if test = "${user.email == vo.email}">
    //삭제 버튼을 눌렀을 때 처리
    document.getElementById("deletebtn").addEventListener("click", function() {
        location.href = "/board/delete/${vo.bno}";
    });
    //수정 버튼을 눌렀을 때 처리
    document.getElementById("updatebtn").addEventListener("click", function() {
        location.href = "/board/update/${vo.bno}";
    });
    </c:if>
</script>

6. 게시글 수정

BoardService 인터페이스에 게시글 수정 보기 처리를 위한 메소드 선언

    public Board updateView(int bno);

BoardServiceImpl 클래스에 게시글 수정 보기 처리를 위한 메소드 구현

@Override
public Board updateView(int bno) {
return boardDao.detail(bno);
}

BoardController에 게시글 수정 보기 처리 요청의 메소드를 추가

    @RequestMapping(value = "/update/{bno}", method = RequestMethod.GET)
    public String update(@PathVariable("bno") int bno, Model model) {
        model.addAttribute("vo", boardService.updateView(bno));
        return "board/update";
    }

board 디렉토리에 update.jsp 파일을 작성

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ include file="../include/header.jsp"%>
<section class="center">
    <div class="box box-primary">
        <div class="box-header">
            <h3 class="box-title">게시물 수정</h3>
        </div>
        <form role="form" id="updateForm" action="/board/update" method="post">
            <!-- 글번호를 넘겨주기 위해서 숨김 객체로 생성 -->
            <input type="hidden" name="bno" value="${vo.bno}" />
            <div class="box-body">
                <div class="form-group">
                    <label>제목</label> <input type="text" name="title"
                        class="form-control" value="${vo.title}" />
                </div>
                <div class="form-group">
                    <label>내용</label>
                    <textarea name="content" class="form-control" placeholder="내용 입력"
                        rows="5">${vo.content}</textarea>
                </div>
                <div class="form-group">
                    <label>작성자</label> <input type="text" class="form-control"
                        value="${vo.nickname}" readonly="readonly" />
                </div>
            </div>
        </form>
        <div class="box-footer">
            <button class="btn btn-success" id="updatebtn">수정완료</button>
            <button class="btn btn-warning" id="mainbtn">메인으로</button>
            <button class="btn btn-primary" id="listbtn">목록보기</button>
        </div>
    </div>
</section>
<%@ include file="../include/footer.jsp"%>
<script>
    //메인 버튼을 눌렀을 때 처리
    document.getElementById("mainbtn").addEventListener("click", function() {
        location.href = "/";
    });
    //목록 버튼을 눌렀을 때 처리
    document.getElementById("listbtn").addEventListener("click", function() {
        location.href = "/board/list";
    });
    //수정 완료 버튼을 눌렀을 때 처리
    document.getElementById("updatebtn").addEventListener("click", function() {
        document.getElementById("updateForm").submit();
    });
</script>

board.xml 파일에 게시글 수정을 위한 sql을 추가

    <!-- 게시글을 수정하는 sql -->
    <update id="update" parameterType="Board">
        update springboard
        set title=#{title}, content=#{content},
        ip=#{ip}, updatedate=now()
        where bno = #{bno}
    </update>

BoardDao 클래스에 게시글 수정을 위한 메소드 구현

    public void update(Board vo) {
        sqlSession.update("board.update", vo);
    }

BoardService 인터페이스에 게시글 수정 처리를 위한 메소드 선언

    public void update(HttpServletRequest request);

BoardServiceImpl 클래스에 게시글 수정 처리를 위한 메소드 구현

    @Override
    public void update(HttpServletRequest request) {
        // 매개변수가 request일 때는 파라미터를 읽습니다.
        int bno = Integer.parseInt(request.getParameter("bno"));
        String title = request.getParameter("title");
        String content = request.getParameter("content");
        if (title.length() == 0) {
            title = "무제";
        }
        if (content.length() == 0) {
            content = "냉무";
        }
        // 필요한 데이터를 생성
        String ip = request.getRemoteAddr();
        Board vo = new Board();
        vo.setBno(bno);
        vo.setTitle(title);
        vo.setContent(content);
        vo.setIp(ip);
        boardDao.update(vo);
    }

BoardController에 게시글 수정 처리 요청의 메소드를 추가

@RequestMapping(value = "/update", method = RequestMethod.POST)
public String update(HttpServletRequest request, RedirectAttributes rttr) {
    boardService.update(request);
    rttr.addFlashAttribute("msg", "게시글 수정에 성공하셨습니다.");
    return "redirect:list";
}

7. 게시글 삭제

detail.jsp 파일에 삭제 UI를 위한 jquery 링크 및 대화상자 내용을 추가


<c:if test="${user.email == vo.email}">
    <link rel="stylesheet"
        href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
    <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
    <div id="dialog-confirm" title="삭제?" style="display: none;">
        <p>정말로 삭제하시겠습니까?</p>
    </div>
</c:if>

detail.jsp 파일에 삭제 버튼을 눌렀을 때 호출되는 스크립트 코드를 수정

    //삭제 버튼을 눌렀을 때 처리
    document.getElementById("deletebtn").addEventListener("click", function() {
        $("#dialog-confirm").dialog({
            resizable : false,
            height : "auto",
            width : 400,
            modal : true,
            buttons : {
                "삭제" : function() {
                    $(this).dialog("close");
                    location.href = "/board/delete/${vo.bno}";
                },
                "취소" : function() {
                    $(this).dialog("close");
                }
            }
        });
    });

board.xml 파일에 게시글 삭제를 위한 sql을 추가

    <!-- 글번호를 가지고 게시글을 삭제하는 sql -->
    <delete id="delete" parameterType="java.lang.Integer">
        delete from springboard
        where bno = #{bno}
    </delete>

BoardDao 클래스 게시글 삭제를 위한 메소드 구현

    public void delete(int bno) {
        sqlSession.delete("board.delete", bno);
    }

BoardService 인터페이스에 게시글 삭제 처리를 위한 메소드 선언

//글번호를 가지고 게시글을 삭제하는 메소드
public void delete(int bno);

BoardServiceImpl 클래스에 게시글 삭제 처리를 위한 메소드 구현

@Override
public void delete(int bno) {
    boardDao.delete(bno);
}

BoardController에 게시글 삭제 처리 요청의 메소드를 추가

    @RequestMapping(value = "/delete/{bno}", method = RequestMethod.GET)
    public String delete(@PathVariable("bno") int bno, RedirectAttributes rttr) {
        boardService.delete(bno);
        rttr.addFlashAttribute("msg", "게시글 삭제에 성공하셨습니다.");
        return "redirect:/board/list";
    }

results matching ""

    No results matching ""