Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 | 31 |
Tags
- 인접 형제 결합자
- 아두이노
- padding 속성
- 임베디드
- html tag i
- iframe 태그
- RGB
- 전체 선택자
- 일반 형제 결합자
- br 태그
- background-color 속성
- html
- Live Server
- css
- sup태그
- id 선택자
- RGBA
- go live
- Checked 의사 클래스
- 자식결합자
- html 태그
- focus 의사클래스
- height속성
- sub태그
- not 의사클래스
- tag html
- i 태그
- reveal in file explorer
- width속성
- iframe
Archives
- Today
- Total
so woon!
게시판 글쓰기 구현 + DB에 인서트 하기 본문
학습일 : 2022. 11. 17
BbsMapper.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="dev.xowoony.studymemberbbs.mappers.IBbsMapper">
<select id="selectBoardById"
resultType="dev.xowoony.studymemberbbs.entities.bbs.BoardEntity">
SELECT `id` AS `id`,
`text` AS `text`
FROM `study_bbs`.`boards`
WHERE BINARY `id` = #{id}
LIMIT 1
<!--#{id} 에는 notice가 들어가게 된다. notice를 적어줄 경우-->
<!-- abc 같은게 id에 들어왔다 => 없는 게시판일 경우 BbsService 전체가 null이 된다.-->
</select>
<!--게시글(제목, 내용) 작성후 DB에 인서트-->
<insert id="insertArticle"
parameterType="dev.xowoony.studymemberbbs.entities.bbs.ArticleEntity">
INSERT INTO `study_bbs`.`articles` (`user_email`, `board_id`, `title`, `content`, `view`, `written_on`,`modified_on`)
VALUES (#{userEmail}, #{boardId}, #{title}, #{content}, #{view},
IFNULL(#{writtenOn}, DEFAULT(`written_on`)),
IFNULL(#{modifiedOn}, DEFAULT(`modified_on`)));
</insert>
</mapper>
IBbsMapper.java (Interface)
package dev.xowoony.studymemberbbs.mappers;
import dev.xowoony.studymemberbbs.entities.bbs.ArticleEntity;
import dev.xowoony.studymemberbbs.entities.bbs.BoardEntity;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
@Mapper
public interface IBbsMapper {
int insertArticle(ArticleEntity article);
BoardEntity selectBoardById(@Param(value="id") String id);
}
WriteResult.java
package dev.xowoony.studymemberbbs.enums.bbs;
import dev.xowoony.studymemberbbs.interfaces.IResult;
public enum WriteResult implements IResult {
NOT_ALLOWED,
NO_SUCH_BOARD
}
BbsController.java
package dev.xowoony.studymemberbbs.controllers;
import dev.xowoony.studymemberbbs.entities.bbs.ArticleEntity;
import dev.xowoony.studymemberbbs.entities.bbs.BoardEntity;
import dev.xowoony.studymemberbbs.entities.member.UserEntity;
import dev.xowoony.studymemberbbs.enums.CommonResult;
import dev.xowoony.studymemberbbs.enums.bbs.WriteResult;
import dev.xowoony.studymemberbbs.services.BbsService;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
@Controller(value = "dev.xowoony.studymemberbbs.controllers.BbsController")
@RequestMapping(value = "/bbs")
public class BbsController {
public final BbsService bbsService;
// 글쓰기 페이지
@Autowired
public BbsController(BbsService bbsService) {
this.bbsService = bbsService;
}
@RequestMapping(value = "write",
method = RequestMethod.GET,
produces = MediaType.TEXT_HTML_VALUE)
public ModelAndView getWrite(@SessionAttribute(value = "user", required = false) UserEntity user,
@RequestParam(value = "bid", required = false) String bid) {
// required = false => 400 방지
ModelAndView modelAndView;
if (user == null) { // 로그인 확인 (로그인이 안되었을 경우 다시 로그인 페이지로 돌려줌
modelAndView = new ModelAndView("redirect:/member/login"); // ModelAndView 로 redirect 할 수 있다.
} else { // 로그인이 되었을 경우 bbs/write 페이지로 데려다 줌
modelAndView = new ModelAndView("bbs/write");
// BoardEntity board = bid == null ? null : this.bbsService.getBoard(bid); // 참이면 null 반환, 거짓이면 getBoard(bid) 반환
if (bid == null || this.bbsService.getBoard(bid) == null) {
modelAndView.addObject("result", CommonResult.FAILURE.name());
} else {
modelAndView.addObject("result", CommonResult.SUCCESS.name());
modelAndView.addObject("board", this.bbsService.getBoard(bid));
}
}
return modelAndView;
}
// DB에 게시글 내용 insert 하기 (1116)
@RequestMapping(value = "write",
method = RequestMethod.POST, // POST 방식으로 맵핑
produces = MediaType.APPLICATION_JSON_VALUE) // JSON으로 돌려돌려준다.
@ResponseBody
public String postWrite(@SessionAttribute(value = "user", required = false) UserEntity user,
@RequestParam(value = "bid", required = false) String bid,
ArticleEntity article) {
Enum<?> result;
if (user == null) {
result = WriteResult.NOT_ALLOWED;
} else if (bid == null) {
result = WriteResult.NO_SUCH_BOARD;
} else {
article.setUserEmail(user.getEmail());
article.setBoardId(bid);
result = this.bbsService.write(article);
}
JSONObject responseObject = new JSONObject();
responseObject.put("result", result.name().toLowerCase());
return responseObject.toString();
}
}
BbsService.java
package dev.xowoony.studymemberbbs.services;
import dev.xowoony.studymemberbbs.entities.bbs.ArticleEntity;
import dev.xowoony.studymemberbbs.entities.bbs.BoardEntity;
import dev.xowoony.studymemberbbs.enums.CommonResult;
import dev.xowoony.studymemberbbs.interfaces.IResult;
import dev.xowoony.studymemberbbs.mappers.IBbsMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service(value = "dev.xowoony.studymemberbbs.services.BbsService")
public class BbsService {
private final IBbsMapper bbsMapper;
@Autowired
public BbsService(IBbsMapper bbsMapper) {
this.bbsMapper = bbsMapper;
}
public BoardEntity getBoard(String id) {
return this.bbsMapper.selectBoardById(id);
}
public Enum<? extends IResult> write(ArticleEntity article) {
BoardEntity board = this.bbsMapper.selectBoardById(article.getBoardId());
if (board == null) {
return CommonResult.NO_SUCH_BOARD;
}
return this.bbsMapper.insertArticle(article) > 0
? CommonResult.SUCCESS
: CommonResult.FAILURE;
}
}
write.html
<!doctype html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title th:if="${board != null}" th:text="'또치뱅크 - ' + ${board.getText()} + ' 글쓰기'"></title>
<!--<title th:text="${'스터디 -' + board.getText() + '글쓰기'}"></title>-->
<script th:if="${board == null}">
alert('존재하지 않는 게시판입니다.');
if (window.history.length > 1) { // 뒤로가기 할 수 있으면 뒤로 가고
window.history.back(); // 없다면 창을 닫는다.
} else {
window.close();
}
</script>
<th:block th:replace="~{fragments/head :: common}"></th:block>
<link rel="stylesheet" th:href="@{/bbs/resources/stylesheets/write.css}">
<script defer th:src="@{/resources/libraries/ckeditor/ckeditor.js}"></script>
<script defer th:src="@{/bbs/resources/scripts/write.js}"></script>
</head>
<body th:if="${board != null}">
<!--board가 null일때 body가 안뜬다.-->
<th:block th:replace="~{fragments/body :: header}"></th:block>
<th:block th:replace="~{fragments/body :: cover}"></th:block>
<main class="--main main">
<form id="form" class="--content content">
<h1 class="title" th:if="${board!=null}" th:text="'글쓰기 - ' + ${board.getText()}"></h1>
<!--board.getText()가 null 일때 500터짐-->
<input name="bid" type="hidden" th:value="${ board.getId() }">
<table class="table" id="table">
<tbody>
<tr>
<th>제목</th>
<td>
<label class="label">
<span hidden>제목</span>
<input class="--object-input input" maxlength="100" name="title" placeholder="제목을 입력해 주세요." type="text">
</label>
</td>
</tr>
<tr>
<th>내용</th>
<td>
<label class="label">
<span hidden>내용</span>
<textarea name="content" class="--object-input input" placeholder="내용을 입력해 주세요." maxlength="10000"></textarea>
</label>
</td>
</tr>
<tr class="warning-row" rel="warningRow">
<th></th>
<td>
<span class="warning">
<i class="icon fa-solid fa-triangle-exclamation"></i>
<span class="text">제목을 입력해주세요</span>
</span>
</td>
</tr>
<tr>
<th></th>
<td>
<div class="button-container">
<input class="--object-button" name="back" type="button" value="돌아가기">
<input class="--object-button" name="submit" type="submit" value="작성하기">
</div>
</td>
</tr>
</tbody>
</table>
</form>
</main>
<th:block th:replace="~{fragments/body :: footer}"></th:block>
</body>
</html>
write.css
@charset "UTF-8";
body > .main > .content {
margin: 5rem 0;
align-items: stretch;
display: flex;
flex-direction: column;
justify-content: flex-start;
}
body > .main > .content > .title {
font-size: 2rem;
font-weight: 500;
margin-bottom: 2.5rem;
}
/*경고창*/
#form > .table .warning-row {
display: none;
}
#form > .table .warning-row.visible {
display: table-row;
}
#form > .table .warning-row .warning {
background-color: rgb(231, 76, 60);
border-radius: 0.375rem;
color: rgb(255, 255, 255);
font-size: 1rem;
margin-top: 0.25rem;
padding: 1rem 1.25rem;
align-items: center;
display: flex;
flex-direction: row;
justify-content: flex-start;
}
#form > .table .warning-row .warning > .icon {
font-size: 1.5rem;
margin: 0 1.25rem 0 0.25rem;
}
#form > .table .warning-row .warning > .text {
flex: 1;
text-align: justify;
}
#form > .table .button-container {
align-items: stretch;
display: flex;
flex-direction: row;
justify-content: space-between;
margin-top: 0.5rem;
}
#form > .table .button-container > [name="back"] {
background-color: rgb(16, 68, 108);
}
#form > .table .button-container > [name="back"]:hover{
background-color: rgb(130, 170, 204);
}
#form > .table .button-container > [name="back"]:active{
background-color: rgb(44, 62, 80);
}
write.js
const form = window.document.getElementById('form');
const Warning = {
getElementById: () => form.querySelector('[rel="warningRow"]'),
show: (text) => {
const warningRow = Warning.getElementById();
warningRow.querySelector('.text').innerText = text;
warningRow.classList.add('visible');
},
hide: () => Warning.getElementById().classList.remove('visible')
};
let editor; //체인메서드
ClassicEditor
.create(form['content'])
.then( e => editor = e ); // e = 에디터 전체 / 얘가 뱉어낸 e를
form['back'].addEventListener('click', () => window.history.length < 2 ? window.close() : window.history.back());
form.onsubmit = e => {
e.preventDefault();
Warning.hide();
if (form['title'].value === '') {
Warning.show('제목을 입력해 주세요.');
form['title'].focus();
return false;
}
if (editor.getData() === '') {
Warning.show('내용을 입력해 주세요.');
editor.focus();
return false;
}
<!--게시글(제목, 내용) 작성후 DB에 인서트-->
Cover.show('게시글을 작성하고 있어요. 잠시만 기다려주세여.')
const xhr = new XMLHttpRequest();
const formData = new FormData();
formData.append('bid', form['bid'].value);
// formData.append('POST', window.location.href);해도됨
formData.append('title', form['title'].value);
formData.append('content', editor.getData());
xhr.open('POST', './write')
xhr.onreadystatechange = () => {
if (xhr.readyState === XMLHttpRequest.DONE) {
Cover.hide();
if (xhr.status >= 200 && xhr.status < 300) {
const responseObject = JSON.parse(xhr.responseText);
switch (responseObject['result']) {
case 'not_allowed':
Warning.show('게시글 작성권한이 없거나 로그아웃되었ㅅㅂ니다,, 확인후 다시 시도 ㄱ');
break;
case 'success':
//?
break;
default:
Warning.show('알 수 없는 이유로 게시글 작성 못했어요, 다시 시도하세여');
}
} else {
Warning.show('서버와 통신하지 못하였습니다. 잠시 후 다시 시도해 주세요.');
}
}
};
xhr.send(formData);
};
insert 과정
아래와 같이 `study_bbs`.`articles` 테이블에 insert 된다.
그리고 오늘의 과제ㅆ
SUCCESS 일 때
/bbs/read?aid=인덱스
로 이동하도록 조치하기
투 비 컨티뉴.
'Spring Boot > 구현해보기' 카테고리의 다른 글
게시글에 댓글 달기 구현 (5) | 2022.11.27 |
---|---|
게시글 읽기 + DB에 인서트 하기 (0) | 2022.11.21 |
게시판 글쓰기 구현 (0) | 2022.11.14 |
이메일 찾기 구현 (0) | 2022.11.13 |
비밀번호 재설정 구현2 (0) | 2022.11.13 |
Comments