게시판 글쓰기 구현
오늘 배운 내용
@SessionAttribute [Variable] : 어떠한 값을 세션 저장소로 부터 불러온다.
value : 불러올 값의 쌍에 대한 키(이름)이다. HttpSession 타입의 객체에 setAttribute(n, v) 메서드 호출시 적었던 이름(n) 과 같아야 한다.
required : 세션에서 불러올 값이 필수인가에 대한 여부이다. 기본값은 true이다.
이 값이 true 일때 세션에서 해당 변수를 불러올 수 없다면 400 (Bad Request) 오류가 발생한다.
Bbs로 새로 생성
BbsControllor.java
package dev.xowoony.studymemberbbs.controllers;
import dev.xowoony.studymemberbbs.entities.member.UserEntity;
import dev.xowoony.studymemberbbs.services.MemberService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.SessionAttribute;
import org.springframework.web.servlet.ModelAndView;
@Controller(value = "dev.xowoony.studymemberbbs.controllers.BbsController")
@RequestMapping(value = "/bbs")
public class BbsController {
public final MemberService memberService;
@Autowired
public BbsController(MemberService memberService) {
this.memberService = memberService;
}
@RequestMapping(value = "write",
method = RequestMethod.GET,
produces = MediaType.TEXT_HTML_VALUE)
public ModelAndView getWrite(@SessionAttribute(value = "user", required = false) UserEntity user) {
// required = false => 400 방지
ModelAndView modelAndView;
if (user == null) { // 로그인 확인 (로그인이 안되었을 경우 다시 로그인 페이지로 돌려줌
modelAndView = new ModelAndView("redirect:/member/login");
} else { // 로그인이 되었을 경우 bbs/write 페이지로 데려다 줌
modelAndView = new ModelAndView("bbs/write");
}
return modelAndView;
}
}
MemberService.java
원래 쓰던 애 그대로
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>스터디 - 글쓰기</title>
<th:block th:replace="~{fragments/head :: common}"></th:block>
<link rel="stylesheet" th:href="@{/bbs/resources/stylesheets/write.css}">
<script defer th:src="@{/bbs/resources/scripts/write.js}"></script>
</head>
<body>
<th:block th:replace="~{fragments/body :: header}"></th:block>
<th:block th:replace="~{fragments/body :: cover}"></th:block>
<main class="--main main">
글쓰기 페이지임!
</main>
<th:block th:replace="~{fragments/body :: footer}"></th:block>
</body>
</html>
body.html
session.user == null 일 경우 로그인과 회원가입이 뜨게 하고
session.user != null 일 경우 로그아웃과 마이페이지가 뜨게 한다.
<ul class="--menu">
<li class="--item" th:if="${session.user == null}">
<a class="--link" th:href="@{/member/login}">로그인</a>
</li>
<li class="--item" th:if="${session.user == null}">
<a class="--link" th:href="@{/member/register}">회원가입</a>
</li>
<li class="--item" th:if="${session.user != null}">
<a class="--link" th:href="@{/member/logout}">로그아웃</a>
</li>
<li class="--item" th:if="${session.user != null}">
<a class="--link" th:href="@{/member/my}">마이페이지</a>
</li>
</ul>
결과
1. 로그인을 하고 왔을 경우
글쓰기 페이지가 로그인 상태가 되었기 때문에
화면 우측 상단에 로그아웃과 마이페이지 버튼이 등장
글쓰기 페이지가 정상적으로 나타나게 됨.
2. 로그인을 하지 않은 상태로 주소창에 bbs/write 로 접속했을 경우
redirect로 인해 로그인 페이지로 바로 돌려줘버림.
11/15
https://ckeditor.com/ckeditor-5/online-builder/
이런것들을 라이브러리라고 한다.(주소찾기, 글쓰기 등의 특정 기능을 가지고 있는 것)
스프링부트를 프레임워크라고 한다.
압축파일을 풀어서
build 디렉토리 안
ckeditor.js.map 를
옆 경로로와 같이 지정해주면
아래와 같이
글쓰기 폼이 적용되어
아래와 같은 결과가 나타난다.
게시판 유저(DB)
-게시글
-댓글
문제
BoardEntity BbsService.getBoard(String id)
- 단순히 컨트롤러와 매퍼의 연결고리 역할을 함
BoardEntity IBbsmapper.selectBoardById(@Param(value="id") String id)
- 전달 받은 문자열 객체 `id`가 가진 값을 `study_bbs`.`boards` 테이블의 `id`열 값을 가지는 레코드에 대한 엔티티 객체를 반환함.
- '.../write?bid=x' 주소로 접근하였을 때 페이지 로드 시에 바로 게시판 유무에 대한 대응하여야 하므로 XHR을 사용하지 않음.
즉, BbsController의 getWrite(...) 메서드를 활용하여야 함.
`study_bbs`.`boards`
테이블 CREATE
CREATE SCHEMA `study_bbs`;
CREATE TABLE `study_bbs`.`boards`
(
`id` VARCHAR(10) NOT NULL,
`text` VARCHAR(100) NOT NULL,
CONSTRAINT PRIMARY KEY (`id`)
);
BbsMapper.xml
SELECT 해주기
<?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
</select>
</mapper>
IBbsMapper.java (Interface)
xml에서 select 했던 내용 사용하기
1. IBbsMapper 에서 인터페이스 생성
2. @param 을 통해 불러온다 ( @param(value="id") String id )
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 {
BoardEntity selectBoardById(@Param(value="id") String id);
}
BbsService.java
DB에서 selectBoardById의 id 값 select 했던 것을 boardEntity를 이용해 반환
package dev.xowoony.studymemberbbs.services;
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.interfaces.IResult;
import dev.xowoony.studymemberbbs.mappers.IBbsMapper;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@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) {
BoardEntity boardEntity = this.bbsMapper.selectBoardById(id);
return boardEntity;
}
}
BbsController.java
package dev.xowoony.studymemberbbs.controllers;
import dev.xowoony.studymemberbbs.entities.bbs.BoardEntity;
import dev.xowoony.studymemberbbs.entities.member.UserEntity;
import dev.xowoony.studymemberbbs.enums.CommonResult;
import dev.xowoony.studymemberbbs.services.BbsService;
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;
}
}
required = false
400 에러 방지의 역할.
@SessionAttribute의 역할
MemberController의 session 에 setAttribute("user", user) 했던 부분을 참고하게 된다.
user == null 의 경우(로그인이 안된 경우) => redirect를 통해 login 페이지로 데려다 주게 되고,
user != null 의 경우 (로그인이 된 경우) => bbs/write 페이지로 데려다 주게 된다.
참고 ↓
MemberController
@RequestMapping(value = "login",
method = RequestMethod.POST,
produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public String postLogin(HttpSession session, UserEntity user) {
Enum<?> result = this.memberService.login(user);
if(result == CommonResult.SUCCESS) {
session.setAttribute("user", user); // 해당 요소에 user 이름의 user 값을 가지는 HTML 속성을 추가한다.
System.out.println("이메일/비밀번호 맞음.");
} else {
System.out.println("이메일/비밀번호 틀림.");
}
JSONObject responseObject = new JSONObject();
responseObject.put("result", result.name().toLowerCase());
return responseObject.toString();
}
실행결과