글쓰기
1. 게시판 CRUD를 구현하기 위해 BoardVO 클래스를 작성 & board 테이블 생성
package board.vo;
import lombok.Data;
@Data
public class BoardVo {
private int boardIdx; // 게시글 번호
private String title; // 제목
private String contents; // 내용
private int hitCnt; // 조회수
private String username; // 작성자 id
private String nickname; // 작성자 닉네임
private String createdDateTime; // 작성일
private String updaterId; // 수정자
private String updatedDateTime; // 수정일
private int replyCount; // 댓글 갯수
private String deletedYn; // 삭제 여부
}
CREATE TABLE board
(
`board_idx` int(10) NOT NULL AUTO_INCREMENT COMMENT '게시글 번호',
`title` varchar(300) NOT NULL COMMENT '제목',
`contents` text NOT NULL COMMENT '내용',
`hit_cnt` smallint(10) NOT NULL DEFAULT 0 COMMENT '조회수',
`created_datetime` datetime NOT NULL COMMENT '작성 일자',
`username` varchar(50) NOT NULL COMMENT '작성 회원 id',
`updated_datetime` datetime NULL COMMENT '수정 일자',
`updater_id` varchar(50) NULL COMMENT '수정 회원 id',
`deleted_yn` char(1) NOT NULL DEFAULT 'N' COMMENT '삭제 여부',
`reply_count` int NULL DEFAULT 0 COMMENT '댓글 갯수',
PRIMARY KEY (board_idx)
);
-- Foreign Key 설정 SQL - board(creator_id) -> user(username)
ALTER TABLE board
ADD CONSTRAINT user_board_fk FOREIGN KEY (username)
REFERENCES user (username) ON DELETE RESTRICT ON UPDATE RESTRICT;
UserVO와 마찬가지로 getter, setter, toString 등의 메서드를 자동으로 생성해주는 롬복 라이브러리를 사용했다.
게시글 번호(board_idx): MariaDB의 AUTO_INCREMENT 기능을 사용하여 자동으로 1씩 증가되도록 하였고,
조회수(hit_cnt): 기본값은 0으로 하고, 게시글을 클릭할 때마다 1씩 증가하도록 할 것이다.
작성 일자(created_datetime): datetime 형식으로 SQL문 작성 시 now() 함수를 이용해 추가해줄 것이다.
작성 회원(username): 작성 회원의 id로, SQL문을 통해 DB에 insert 시켜줄 것이다.
수정자(updater_id)와 수정일(updated_datetime)은 추가하고싶지 않다면 추가하지 않아도 문제가 없다.
댓글 갯수(reply_count): 게시판에 달린 댓글의 갯수를 카운트하기 위해 추가했고, 이 댓글의 갯수는 게시글 목록 페이지에서 보여줄 것이다.
롬복을 사용하기 위해 IntelliJ -> Settings -> Plugins에서 lombok을 설치해주었다.
2. BoardController 작성
게시판 기능은 기본적으로 네 가지 기능을 떠올릴 수 있다.
- 글쓰기(Create)
- 글읽기(Read)
- 글수정(Update)
- 글삭제(Delete)
글쓰기를 담당하는 컨트롤러는 다음과 같다.
package board.controller;
import board.vo.BoardVo;
import board.service.BoardService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Map;
@Controller
public class BoardController {
@Autowired
private BoardService boardService;
@RequestMapping("/board/boardWrite") // 글 작성 페이지
public String boardWrite() {
return "/board/boardWrite";
}
@RequestMapping("/board/insertBoard") // 글 작성 로직
public String insertBoard(BoardVo boardVo, @RequestParam String username, @RequestParam String nickname) throws Exception {
boardVo.setUsername(username);
boardVo.setNickname(nickname);
boardService.insertBoard(boardVo);
return "redirect:/board";
}
- /board/boardWrite로 받은 요청을 /board/boardWrite.jsp(글쓰기 페이지)로 반환해준다.
- 이후에 boardWrite.jsp에서 글을 작성하면 /board/insertBoard로 요청하여 게시글 정보와 작성자의 정보를 DB에 insert한 후 게시글 목록으로 이동하도록 한다.
3. BoardService, BoardServiceImpl, BoardMapper 작성
BoardService.java
package board.service;
import board.vo.BoardVo;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Map;
@Service
public interface BoardService {
void insertBoard(BoardVo boardVo) throws Exception;
}
BoardServiceImpl.java
package board.service;
import board.vo.BoardVo;
import board.mapper.BoardMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Service
public class BoardServiceImpl implements BoardService {
@Autowired
private BoardMapper boardMapper;
@Override
public void insertBoard(BoardVo boardVo) throws Exception { // 글쓰기
boardMapper.insertBoard(boardVo);
}
}
BoardMapper.java
package board.mapper;
import board.vo.BoardVo;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
import java.util.Map;
@Mapper
public interface BoardMapper {
void insertBoard(BoardVo boardVo) throws Exception;
}
4. /board/boardWrite.jsp 생성
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ include file="../layout/header.jsp"%>
<c:if test="${signIn == null}"><c:redirect url="http://staffriends.duckdns.org/user/needLogin"/></c:if>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>글쓰기</title>
<style>
.ck-editor__editable { height: 1000px; }
.ck-content { font-size: 12px; }
.cke_chrome {max-width: 90%; height: auto; margin: auto; }
.textarea {width: 100%; border: none; resize: none; height: 3.1rem;}
</style>
</head>
<body class="center-div">
<div class="container justify-content-center">
<h2 style="text-align: center; margin-top: 30px; margin-bottom: 70px; font-family: KakaoBold;">글쓰기</h2>
<form id="frm" name="frm" method="post">
<table style="margin-left:auto;margin-right:auto;">
<tr>
<td>
<textarea class="textarea" id="title" name="title" placeholder="제목을 입력해주세요." style="font-size: 30px"></textarea>
<hr style="margin-top: 0;"/>
</td>
</tr>
<tr>
<td colspan="2">
<textarea class="form-control" id="contents" name="contents"></textarea>
<script>
writeEditor();
</script>
</td>
</tr>
<input type="hidden" value="${signIn.username}" name="username" id="username">
<input type="hidden" value="${signIn.nickname}" name="nickname" id="nickname">
</table>
</form>
<h5 style="text-align: center"><button class="btn btn-success" id="save" style="margin-top: 20px; margin-bottom: 20px;">글 작성 완료</button></h5>
<script>
insertBoard();
</script>
</div>
</body>
<%@ include file="../layout/footer.jsp"%>
</html>
hidden 값으로 username과 nickname 값을 넘겨주고, 컨트롤러에서는 이 두 값을 받아 setUsername과 setNickname 메서드로 값을 지정한 뒤 DB에 insert 한다.
글쓰기 페이지에는 CKEditor4를 적용했으며, CKEditor4는 아래 링크에서 다운로드하거나 CDN 링크를 얻을 수 있다.
https://ckeditor.com/ckeditor-4/download/
4. js/board.js 작성
function insertBoard() {
document.getElementById("save").onclick = function(event) {
let frm = document.getElementById("frm");
frm.action = "/board/insertBoard";
frm.submit();
alert('글 작성이 완료되었습니다.');
}
}
function writeEditor() {
CKEDITOR.replace('contents', {
filebrowserUploadUrl: '/fileUpload',
height: '500px'
});
}
- save라는 id를 가진 버튼이 클릭되는 순간 frm 이라는 id를 가진 폼을 /board/insertBoard URL로 전송하고 글 작성이 완료되었다는 알림창을 띄운다.
- ckeditor의 contents라는 id를 가진 요소(게시글 내용이 들어가는 필드)에 파일 업로드 기능을 추가하여 사진을 업로드할 수 있도록 하였고, height로 높이 지정을 해주었다.
5. sql-board.xml 작성
<?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.mapper.BoardMapper">
<insert id="insertBoard" parameterType="board.vo.BoardVo">
<![CDATA[
INSERT INTO board
(
title,
contents,
created_datetime,
username,
nickname
)
VALUES
(
#{title},
#{contents},
now(),
#{username},
#{nickname}
)
]]>
</insert>
</mapper>
프로젝트 전체 코드 Github 주소
https://github.com/sungwoo-jo/Staffriends-Project
'프로젝트 > Staffriends 프로젝트' 카테고리의 다른 글
[Staffriends 프로젝트] (1) 회원 CRUD 구현하기 - 3. 회원 정보 수정 (0) | 2023.05.22 |
---|---|
[Staffriends 프로젝트] (1) 회원 CRUD 구현하기 - 2. 로그인 (0) | 2023.05.22 |
[Staffriends 프로젝트] (1) 회원 CRUD 구현하기 - 1. 회원가입 (0) | 2023.05.22 |