BACKEND/스프링 Spring

spring 게시판 인텔리제이로 Ajax 댓글 기능 구현

꾸준히개발하자 2024. 1. 4. 14:26

상황 - 게시글 상세 페이지에서 댓글을 쓰는 상황

 

댓글 테이블 정의 

create table comment_table(
    id bigint primary key auto_increment,
    commentWriter varchar(50),
    commentContents varchar(200),
    boardId bigint,
    commentCreatedTime datetime default now(),
    constraint fk_comment_table foreign key (boardId) references board_table(id) on delete cascade
);

 

boardId 는 board_table 의 id를 참조한다. 

게시글이 지워지면 댓글도 지워주게 하기 위해서 on delete cascade 를 줬다 

 

detail.jsp 에 댓글 폼을 추가 한다 

 

<div>
    <input type="text" id="commentWriter" placeholder="작성자">
    <input type="text" id="commentContents" placeholder="내용">
    <button id="comment-write-btn" onclick="commentWrite()">댓글작성</button>
</div>


<div id="comment-list">
    <table>
        <tr>
            <th>댓글번호</th>
            <th>작성자</th>
            <th>내용</th>
            <th>작성시간</th>
        </tr>
        <c:forEach items="${commentList}" var="comment">
            <tr>
                <td>${comment.id}</td>
                <td>${comment.commentWriter}</td>
                <td>${comment.commentContents}</td>
                <td>${comment.commentCreatedTime}</td>
            </tr>
        </c:forEach>
    </table>
</div>

 

댓글 작성하면 페이지 로딩 없이 비동기 방식으로 활용한다

비동기 방식으로 Ajax 로 사용할 것이다

폼 테그가 필요없고 사용자 입력을 받는 인풋 테그 2개

작성버튼을 클릭하면 commentWrite 함수를 호출하도록 구성했다

 

작성자와 댓글을 달수있도록 한다.

 

 

AjAX를 사용하기 위해 jQuery 사용하는 라이브러리를 가져온다

<script src="https://code.jquery.com/jquery-3.6.3.min.js" integrity="sha256-pvPw+upLPUjgMXY0G+8O0xUf+/Im1MZjXxxgOcBQBXU=" crossorigin="anonymous"></script>

 

const commentWrite = () => {
        const writer = document.getElementById("commentWriter").value;
        const contents = document.getElementById("commentContents").value;
        const board = '${board.id}';
        
        
        $.ajax({
            type: "post",
            url: "/comment/save",
            data: {
                commentWriter: writer,
                commentContents: contents,
                boardId: board
            },
            dataType: "json",
            success: function(commentList) {
                console.log("작성성공");
                console.log(commentList);
                let output = "<table>";
                output += "<tr><th>댓글번호</th>";
                output += "<th>작성자</th>";
                output += "<th>내용</th>";
                output += "<th>작성시간</th></tr>";
                for(let i in commentList){
                    output += "<tr>";
                    output += "<td>"+commentList[i].id+"</td>";
                    output += "<td>"+commentList[i].commentWriter+"</td>";
                    output += "<td>"+commentList[i].commentContents+"</td>";
                    output += "<td>"+commentList[i].commentCreatedTime+"</td>";
                    output += "</tr>";
                }
                output += "</table>";
                document.getElementById('comment-list').innerHTML = output;
                document.getElementById('commentWriter').value='';
                document.getElementById('commentContents').value='';
            },
            error: function() {
                console.log("실패");
            }
        });

 

댓글 작성을 하면 반드시 어떤 게시글의 작성을 했는지 

게시글의 번호를 모델에 담아서 뿌려주는데

게시글의 아이디 값을 가져올수있다

해당 게시글에 해당 댓글번호는 db에서 만든다

 

Ajax로 controller 로 보내고 

응답 결과에 따라 성공 실패 함수로 응답 받게 된다.

 

 

CommentDTO

package com.codingrecipe.board.dto;

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

import java.sql.Timestamp;

@Getter
@Setter
@ToString
public class CommentDTO {
    private Long id;
    private String commentWriter;
    private String commentContents;
    private Long boardId;
    private Timestamp commentCreatedTime;
}

 

댓글 번호 , 작성자 , 내용 , 해당 게시글에 대한 번호 , 댓글 작성 시간

 

 CommentController

package com.codingrecipe.board.controller;

import com.codingrecipe.board.dto.CommentDTO;
import com.codingrecipe.board.service.CommentService;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.List;

@Controller
@RequiredArgsConstructor
@RequestMapping("/comment")
public class CommentController {
	
    @Autowired
    private final CommentService commentService;

    @PostMapping("/save")
    public @ResponseBody List<CommentDTO> save(@ModelAttribute CommentDTO commentDTO) {
        System.out.println("commentDTO = " + commentDTO);
        commentService.save(commentDTO);
        // 해당 게시글에 작성된 댓글 리스트를 가져옴
        List<CommentDTO> commentDTOList = commentService.findAll(commentDTO.getBoardId());
        return commentDTOList;
    }
}

 

Ajax 응답을 줘야 하기 때문에 @ResponseBody 어노테이션을 적어준다

댓글이 작성되면 DTO가 담긴 리스트를 받아준다 

 

findAll 은 해당 게시글에 작성된 댓글 리스트를 가져온다. 

지금 작성된 게시글에 대한 댓글 리스트를 가져와야 하므로 

매개변수로 게시물 번호가 필요하다 

 

 

 

CommentService

 

package com.codingrecipe.board.service;

import com.codingrecipe.board.dto.CommentDTO;
import com.codingrecipe.board.repository.CommentRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
@RequiredArgsConstructor
public class CommentService {
    private final CommentRepository commentRepository;

    public void save(CommentDTO commentDTO) {
        commentRepository.save(commentDTO);
    }

    public List<CommentDTO> findAll(Long boardId) {
        return commentRepository.findAll(boardId);
    }
}

 

 

CommentRepository

package com.codingrecipe.board.repository;

import com.codingrecipe.board.dto.CommentDTO;
import lombok.RequiredArgsConstructor;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import java.util.List;

@Repository
@RequiredArgsConstructor
public class CommentRepository {
    private final SqlSessionTemplate sql;

    public void save(CommentDTO commentDTO) {
        sql.insert("Comment.save", commentDTO);
    }

    public List<CommentDTO> findAll(Long boardId) {
        return sql.selectList("Comment.findAll", boardId);
    }
}

boardId를 넘겨줘야 해당 게시글에 해당하는 댓글 목록을 가져올 수 있다.  

 

 

CommentMapper 를 등록하기 위해 mybatis-config.xml 에 등록한다 

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <typeAliases>
        <typeAlias type="com.codingrecipe.board.dto.BoardDTO" alias="board"></typeAlias>
        <typeAlias type="com.codingrecipe.board.dto.CommentDTO" alias="comment"></typeAlias>
    </typeAliases>
</configuration>

 

 

CommentMapper.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="Comment">
    <insert id="save" parameterType="comment">
        insert into comment_table(commentWriter, commentContents, boardId)
        values(#{commentWriter}, #{commentContents}, #{boardId})
    </insert>

    <select id="findAll" parameterType="Long" resultType="comment">
        select * from comment_table where boardId=#{boardId} order by id desc
    </select>
</mapper>

 

parameterType 으로 게시물번호 , resultType 으로 댓글 목록 

 

 

작성한 댓글 데이터가 넘어오는것을 확인할 수 있다