Spring Boot/구현해보기

게시판 글쓰기 구현

xowoony 2022. 11. 14. 16:17

오늘 배운 내용

@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/

글쓰기 에디터

이런것들을 라이브러리라고 한다.(주소찾기, 글쓰기 등의 특정 기능을 가지고 있는 것)

스프링부트를 프레임워크라고 한다.

 

ckeditor5-35.3.1-awcgi0m1w5ey.zip
0.39MB

압축파일을 풀어서

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();
    }

 

실행결과