SPRING

[Spring4] RestController + 댓글기능 restful 서비스 구현

밍디 ٩(ˊ ᗜˋ*)و 2020. 12. 15. 19:31

이번 프로젝트에서 Restful 서비스는 한번 구현해보고싶은데

게시판에 해볼 용기는 도저히 안나서 소심하게 댓글기능에 구현했었다

 

codelib.tistory.com/24

 

@RequestBody와 @ResponseBody 개념

Spring에서 API 구현시 주로 사용되는 @ResquestBody, @ResponseBody 어노테이션의 개념 대해 확실하게 알고 넘어가자. 예를들어 웹페이지에서 json으로 request한 파라미터들을 java에서 받으려면 java object로.

codelib.tistory.com

스프링4에선 @RestController가 새롭게 추가됐다고 해서

이 어노테이션을 사용해 댓글 기능을 ajax로 구현해보았다 와!

 

 

1. Controller


package org.dms.web;

import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpSession;

import org.dms.web.domain.CommentsVO;
import org.dms.web.domain.UserVO;
import org.dms.web.service.BoardService;
import org.dms.web.service.CommentsService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/board")
public class RestCommentController {
	
	@Autowired(required=true)
	private CommentsService commentService;
	private static final Logger logger = LoggerFactory.getLogger(RestCommentController.class);
	
	
	@RequestMapping(value="/{board_id}/comment.read", method=RequestMethod.GET)
	public /*List<CommentsVO>*/ Map<String, Object> readCommentList(@PathVariable("board_id") int board_id) throws Exception{
		logger.info("글번호: " + board_id);
		
		Map<String, Object> map = new HashMap<String, Object>();
		List<CommentsVO> cvo = commentService.readCommentList(board_id);
		int comment_count = commentService.count(board_id);
		
		map.put("comment", cvo);
		map.put("comment_count", comment_count);
		// commentService.readCount(board_id);
		return map;
		//return commentService.readCommentList(board_id);
	}

	 @RequestMapping(value="/comment.insert", method=RequestMethod.POST)
	 public String insertComments(@RequestBody CommentsVO comment) throws Exception {
			logger.info("글내용: " + comment.getComments_content());
			
			SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
		      Calendar cal = Calendar.getInstance();
		      String today = null;
		      today = formatter.format(cal.getTime());
		     Timestamp ts = Timestamp.valueOf(today);
			comment.setComments_upload(ts);
			comment.setComments_content(comment.getComments_content().replace("\r\n", "<br>"));
			commentService.insertComment(comment);
			return "success";
			/*
			try {
				commentService.insertComment(comment);
				return new ResponseEntity<>("ReplyRegisterOK", HttpStatus.OK);
				
			} catch(Exception e) {
				return new ResponseEntity<>("ReplyRegisterFAIL", HttpStatus.BAD_REQUEST);
			}*/
	}
	 @RequestMapping(value="/{board_id}/comment.delete/{comments_id}", method=RequestMethod.DELETE)
	 public String deleteComments(@PathVariable("board_id") int board_id, @PathVariable("comments_id") int comments_id) throws Exception{
		commentService.deleteComment(comments_id);
		return "success";
		 
	 }
	
	
	
	/*@RequestMapping(value="/{board_id}/comment.insert", method=RequestMethod.POST)
	public List<CommentsVO> addComment(@RequestBody CommentsVO comment) throws Exception{
		commentService.insertComment(comment);
		
	}*/

}

 

 

2. board_detail.jsp


<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
<%@ page import="org.dms.web.domain.UserVO"%>
<%	
	String imgURL = "";
	if(request.getAttribute("user") !=null) {
		UserVO user = (UserVO)request.getAttribute("user");
		if(user.getUser_img() == null) {
			imgURL = (String)request.getContextPath() + "/resources/images/user.png";
		} else {
			imgURL = "/getByteImage/" + user.getUser_id();
		}
	}
%>
<!DOCTYPE HTML>
<!--
	Editorial by HTML5 UP
	html5up.net | @ajlkn
	Free for personal and commercial use under the CCA 3.0 license (html5up.net/license)
-->
<html>
<head>
<title>CODE SPACE</title>
<meta charset="utf-8" />
<meta name="viewport"
	content="width=device-width, initial-scale=1, user-scalable=no" />
<link rel="stylesheet"
	href="<%=request.getContextPath()%>/resources/css/main.css"
	type="text/css" />
<link rel="stylesheet"
	href="<%=request.getContextPath()%>/resources/css/custom_main.css"
	type="text/css" />
<link rel="stylesheet"
	href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.8.2/css/all.min.css" />
<!-- 이게 Font Awesome 5 Free를 사용하게 해주는거 같아요. 이거덕에 사이드바 모양이 보여요! -->
<!--  <link rel="stylesheet" href="<%=request.getContextPath()%>/resources/css/custom_board.css" /> 우선 주석처리 해봄 -->
<link rel="stylesheet"
	href="<%=request.getContextPath()%>/resources/css/custom_board_detail.css" />

<script>
			function getCommentList(flag){
				
				var contextPath = $('#contextPathHolder').attr('data-contextPath') ? $('#contextPathHolder').attr('data-contextPath') : '';
				var user_id = "${user.user_id}";
				$.ajax({
					url: "/board/" + ${board.board_id}+"/comment.read",
					type: "GET",
					success:function(data){
						var comment = data.comment;
			            var comment_count = data.comment_count;
			            var count = 1;
			           
			            var str = comment_count + "개";
			            $("#comment_count").text(comment_count + "개");
			            
						for(var i=0; i< comment.length; i++) {
					        var idx = comment[i].comments_id;
					        var comment_id = "#comments_" + idx;

					        $("#list").append("<div class='comment_list' id=comments_" + idx + "></div>");
							if(count !=1){
								$(comment_id).append("<div class='comment_dashline'></div>");
							} 
							$(comment_id).append("<div class='comment_image'></div>");

							$(comment_id  + " .comment_image").append("<img src='/getByteImage/"+ comment[i].user_id+"' width='50px' height='50px'>");
							$("#comments_"+ idx).append("<div class='comment_content'></div>");
							$("#comments_"+ idx +  " .comment_content").append("<p class='comment_user'>"+ comment[i].user_id+"</p>");
							$("#comments_"+ idx +  " .comment_content").append("<p class='comment_content' >"+ comment[i].comments_content+"</p>");

							$("#comments_"+ idx).append("<div class='comment_info'></div>");
							$("#comments_"+ idx +  " .comment_info").append("<p class='comment_date'>"+ formatDate(comment[i].comments_upload) +"</p>");
							$("#comments_"+ idx +  " .comment_info").append("<div class='comment_edit'></div>");

							if(comment[i].user_id == user_id){
								$("#comments_"+ idx +  " .comment_edit").append("<a href='#' onclick='comment_edit(" + comment[i].comments_id +")'><img src='"+contextPath+"/resources/images/edit.png'/></a>");
								$("#comments_"+ idx +  " .comment_edit").append("<a href='#' onclick='comment_delete(" + comment[i].comments_id +")'><img src='"+contextPath+"/resources/images/delete.png'/></a>");
							}
							count++;
			
			            	
			            }
						/*var count = 1;
						var comment_id;
						$(data).each(function(){
							var idx = this.comments_id;
							comment_id = "#comments_" + this.comments_id;
							
							$("#list").append("<div class='comment_list' id=comments_" + idx + "></div>");
							if(count !=1){
								$(comment_id).append("<div class='comment_dashline'></div>");
							} 
							$(comment_id).append("<div class='comment_image'></div>");

							$(comment_id  + " .comment_image").append("<img src='/getByteImage/"+ this.user_id+"' width='50px' height='50px'>");
							$("#comments_"+ idx).append("<div class='comment_content'></div>");
							$("#comments_"+ idx +  " .comment_content").append("<p class='comment_user'>"+ this.user_id+"</p>");
							$("#comments_"+ idx +  " .comment_content").append("<p class='comment_content' >"+ this.comments_content+"</p>");

							$("#comments_"+ idx).append("<div class='comment_info'></div>");
							$("#comments_"+ idx +  " .comment_info").append("<p class='comment_date'>"+ formatDate(this.comments_upload) +"</p>");
							$("#comments_"+ idx +  " .comment_info").append("<div class='comment_edit'></div>");

							if(this.user_id == user_id){
								$("#comments_"+ idx +  " .comment_edit").append("<a href='#' onclick='comment_edit(" + this.comments_id +")'><img src='"+contextPath+"/resources/images/edit.png'/></a>");
								$("#comments_"+ idx +  " .comment_edit").append("<a href='#' onclick='comment_delete(" + this.comments_id +")'><img src='"+contextPath+"/resources/images/delete.png'/></a>");
							}
							count++;
							}
						);
							*/
						/*if(flag == 1){
							var offset=$(comment_id).offset();
							$("html body").animate({scrollTop:offset.bottom}, 0);
						}*/
					},
					error:function(){
						alert("error");
					}
				});
			}
			function comment_edit_finish(comments_id){
				var idx = this.comments_id;
				comment_id = "#comments_" + this.comments_id;

				$("#comments_"+ idx +  " .comment_content").append("<p class='comment_content'>"+ this.comments_content+"</p>");
				$("#comments_"+ idx +  " .comment_content").replaceWith(function(){
					 return $('<textarea>',{type : 'text', class: 'input-text'})
					});

				}
			function comment_edit(comments_id){
				var idx = this.comments_id;
				comment_id = "#comments_" + this.comments_id;

				$("#comments_"+ idx +  " .comment_content").append("<p class='comment_content'>"+ this.comments_content+"</p>");
				$('#abc').replaceWith(function(){
					 return $('<textarea>',{type : 'text', class: 'input-text'})
					});

				}
			function comment_delete(comments_id){
				$.ajax({
					url: "/board/" + ${board.board_id}+"/comment.delete/" + comments_id,
					type: "DELETE",
					success:function(data){
						$("#list").empty();
						getCommentList(1);
					},
					error:function(){

					}
				});
				alert("삭제완료")
			}
			
			function resize(obj) {
			  obj.style.height = "1px";
			  obj.style.height = (12+obj.scrollHeight)+"px";
			}
			function comment_register(){
				if($("#comments_content").val() == ""){
						alert("댓글을 작성해주세요");
						return false;
					}

				else{
					var comment = {
							board_id: $("#board_id").val(),
							user_id: $("#user_id").val(),
							comments_content: $("#comments_content").val(),
					}
					$.ajax({
						url: "/board/comment.insert",
						type: "POST",
						data : JSON.stringify(comment),
						contentType: "application/json; charset=utf-8;",

						success : function(result) {
							$("#list").empty();

							$("#comments_content").val('');
							getCommentList(1);
						},
						error : function() {
							alert("fail");
						}
					}
					);
				}
				return true;
			
				}

			function formatDate(date) {
				var d = new Date(date),
				month = '' + (d.getMonth() + 1),
				day = '' + d.getDate(),
				year = d.getFullYear();

				if (month.length < 2) month = '0' + month;
				if (day.length < 2) day = '0' + day;
				return [year, month, day].join('.');

			}
		</script>


</head>
<body class="is-preload">
	<!-- Wrapper -->
	<div id="wrapper">

		<!-- Main -->
		<div id="main">
			<jsp:include page="header.jsp" flush="true">
				<jsp:param name="imgURL" value="<%=imgURL%>" />
			</jsp:include> 
			<div class="inner">
				<section>
					<div class="title_header">
						<div class="header_problemid">
							<c:if test="${board.problem_id > 0}">
								<a href="/problem/${problem.problem_id}"><span
									id="problem_id">${problem.problem_id}.
										${problem.problem_title}</span></a>
							</c:if>

						</div>
						<div class="board_info">
							<a href="insert"><img
								src="<%=request.getContextPath()%>/resources/images/write.png">글쓰기</a>
							<a href="/board" style="vertical-align: middle"><img
								src="<%=request.getContextPath()%>/resources/images/board_list.png"
								style="vertical-align: middle">목록</a>
						</div>

					</div>
					<div class="title_box">
						<span>${board.board_title}</span> <span id="info_id">${board.user_id}</span>
					</div>
					<div></div>
					<div class="content">
						<p id="board_upload"><fmt:formatDate pattern="yyyy.MM.dd HH:mm:ss" value="${board.board_upload}"/></p>

						<div class="content_box">
							<p>${board.board_content}<br>
						</div>

						<div class="info_box">
							<div class="comment_count">
								<img
									src="<%=request.getContextPath()%>/resources/images/comment.png"><span id="comment_count"></span>
							</div>
							<div class="board_info">

								<c:if test="${user.user_id == board.user_id}">
									<a href="edit?id=${board.board_id}" style="color: black"><img
										src="<%=request.getContextPath()%>/resources/images/edit.png"></a>
									<a onclick="return alert('정말로 삭제하시겠습니까?')"
										href="delete?board_id=${board.board_id}" ><img
										src="<%=request.getContextPath()%>/resources/images/delete.png">삭제</a>
								</c:if>

							</div>

						</div>

					</div>



					<div id="list">
						<!--
									<%int i = 0; %>
									<c:forEach var="comments" items="${comments}">
										<div class="comment_list">
											<%if(i!=0){ %>
												<div class="comment_dashline"></div>
											<% } %>
											<div class="comment_image">
												<img src="/getByteImage/${comments.user_id}" width="50px" height="50px">
											</div>
											
											<div class="comment_content">
												<p class="comment_user">${comments.user_id}
												<p class="comment_content"> ${comments.comments_content}
											</div>
											
											<div class="comment_info">
												<p class="comment_date">${comments.comments_upload} <br>
												<div class="comment_edit">
													<c:if test="${user.user_id == comments.user_id}">
														<a href="#"><img src="<%=request.getContextPath()%>/resources/images/edit.png"></a>
														<a href="#"><img src="<%=request.getContextPath()%>/resources/images/delete.png"></a>
													</c:if>	
												</div>
											</div>
												<% i++; %>
										</div>
										

									</c:forEach>

									-->
					</div>
					<div class="comment_typing">
						<input type="hidden" id="board_id" value="${board.board_id}" /> <input
							type="hidden" id="user_id" value="${user.user_id}" />
						<textarea id="comments_content" name="comments_content"
							onkeydown="resize(this)" onkeyup="resize(this)"></textarea>
						<div class="comment_typing_button">
							<input id="comment_typing_button" type="image"
								src="<%=request.getContextPath()%>/resources/images/submit.png"
								class="submit-button" onclick="comment_register()">
						</div>
					</div>
					
				</section>m

			</div>
		</div>

		<!-- Sidebar -->

	</div>

	<!-- Scripts -->

	<script
		src="${pageContext.request.contextPath}/resources/js/jquery.min.js"></script>
	<script
		src="${pageContext.request.contextPath}/resources/js/browser.min.js"></script>
	<script
		src="${pageContext.request.contextPath}/resources/js/breakpoints.min.js"></script>
	<script src="${pageContext.request.contextPath}/resources/js/util.js"></script>
	<script src="${pageContext.request.contextPath}/resources/js/main.js"></script>
	<script>
				/* 가장 먼저 실행되는 함수입니다*/
				$(function(){
				 	//alert("hello");
				 	getCommentList(0);
				});
				/*$('#comment_typing_button').on('click', function(){
			        var form = {
			                comments_content: "jamong",
			                user_id: ""
			        }
			        $.ajax({
			            url: "/board/comment.insert",
			            type: "POST",
			            data: JSON.stringify(form),
			            contentType: "application/json; charset=utf-8;",
			            dataType: "json",
			            success: function(data){
			            	alert("restController err");
			            },
			            error: function(){
			                alert("restController err");
			            }
			        });
			    });*/
			</script>
</body>
</html>