1) SpringBoot
1-1) Ajax 예제5
1-1-1) 댓글 작성 / 댓글 목록 출력 / 댓글 수정 / 댓글 삭제
1) SpringBoot
1-1) Ajax 예제5
1-1-1) 댓글 작성 / 댓글 목록 출력 / 댓글 수정 / 댓글 삭제
(1) [src/main/resources] - [templates] 안에 home.html 파일 생성 후 아래와 같이 작성
<!DOCTYPE html>
<html xmlns:th="http://thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>test_ajax</title>
</head>
<body>
<h1>[ Ajax 예제 ]</h1>
<p>
<a href="ajax1">Ajax 테스트 페이지 1</a>
</p>
<p>
<a href="ajax2">Ajax 테스트 페이지 2</a>
</p>
<p>
<a href="like">추천 테스트</a>
</p>
<p>
<a href="idDuplicate">ID 중복확인 테스트</a>
</p>
<p>
<a href="comment/main">댓글 달기 테스트</a>
</p>
</body>
</html>
(2) [src/main/resources] - [templates] 안에 comment.html 파일 생성 후 아래와 같이 작성
<!DOCTYPE html>
<html lang="ko" xmlns:th="http://thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>test_ajax</title>
<style>
#comment {
width: 350px;
}
thead tr {
background-color: #cccccc;
}
tbody tr:nth-child(odd) {
background-color: #dddddd;
}
th {
width: 80px;
}
th.w300 {
width: 300px;
}
</style>
<script src="/js/jquery-3.7.1.min.js"></script>
<script>
$(document).ready(function() {
//댓글 작성 버튼 클릭 이벤트
$("#inputButton").click(inputButtonClick);
//목록 가져오기 호출
list();
});
// 댓글 저장
function inputButtonClick() {
// 입력한 이름과 글내용 입력하기
// 서버로 전달
let name = $('#name').val();
let comment = $('#comment').val();
$.ajax({
url: 'write',
type: 'post',
data: {name: name, comment: comment},
success: function() {
$('#name').val('');
$('#comment').val('');
list();
},
error: function(e) {
alert("저장 실패");
}
});
}
// 목록 출력
function list() {
// ajax() 함수로 DB의 댓글목록을 가져와서 반복문으로 출력
$.ajax({
url: 'list',
type: 'get',
dataType: 'json',
success: function(list) {
console.log(list);
$('#commentList').empty();
$(list).each(function(i, ob) {
let html = `
<tr>
<td class="numTd">${ob.num}</td>
<td>${ob.name}</td>
<td class="commentTd">${ob.comment}</td>
<td><button class="deleteButton" data-num="${ob.num}">삭제</button></td>
<td><button class="updateButton">수정</button></td>
</tr>
`;
$('#commentList').append(html);
});
//삭제 버튼 클릭 이벤트
$('.deleteButton').click(deleteButtonClick);
//수정 버튼 클릭 이벤트
$('.updateButton').click(updateButtonClick);
},
error: function() {
alert('목록 조회 실패');
}
});
}
//삭제
function deleteButtonClick(e) {
let num = $(this).data('num');
$.ajax({
url: 'delete',
type: 'post',
data : {num : num},
success: function(data) {
list();
},
error: function() {
alert('삭제 실패');
}
});
}
//수정
function updateButtonClick() {
// 클릭한 버튼이 속한 행(tr) 찾기
let tr = $(this).closest('tr');
// 같은 행의 class명이 commentTd인 td의 텍스트
let commentText = tr.find('.commentTd').text();
// 같은 행의 class명이 numTd인 td의 텍스트
let numText = tr.find('.numTd').text();
// 텍스트를 입력 대화상자에 보여주고 수정하도록 함
// prompt() : alert() 함수에 입력창이 추가된 함수
let newCommentText = prompt('수정할 내용을 입력하세요', commentText);
// 확인 버튼을 누르면 서버로 전송하여 저장
if (newCommentText != null && newCommentText != '') {
$.ajax({
url: 'update',
type: 'post',
data: {num: numText, comment: newCommentText},
success: function() {
list();
},
error: function(e) {
alert('수정 실패');
}
});
}
}
</script>
</head>
<body>
<h1>[ 댓글 달기 테스트 ]</h1>
<!-- 댓글쓰기 폼 -->
<div>
<input type="text" id="name" placeholder="작성자명을 입력하세요.">
<input type="text" id="comment" placeholder="댓글 내용을 입력하세요.">
<button id="inputButton">저장</button>
</div>
<br>
<table>
<thead>
<tr>
<th>번호</th>
<th>작성자</th>
<th class="w300">내용</th>
<th></th>
<th></th>
</tr>
</thead>
<tbody id="commentList">
<!-- 댓글 내용 출력 영역 -->
</tbody>
</table>
</body>
</html>
(3) [src/main/java] - [net.datasa.test_ajax_my.domain.entity] 안에 CommentEntity.java 파일 생성 후 아래와 같이 작성
package net.datasa.test_ajax_my.domain.entity;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* comment entity
* */
@Builder
@Data
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(name="ajax_comment")
public class CommentEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name="num")
private Integer num;
@Column(name="name", length = 30, nullable = false)
private String name;
@Column(name="comment", length = 1000, nullable = false)
private String comment;
}
(4) [src/main/java] - [net.datasa.test_ajax_my.repository] 안에 CommentRepository.java 파일 생성 후 아래와 같이 작성
package net.datasa.test_ajax_my.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import net.datasa.test_ajax_my.domain.entity.CommentEntity;
public interface CommentRepository extends JpaRepository<CommentEntity, Integer> {
}
(5) [src/main/java] - [net.datasa.test_ajax_my.domain.dto] 안에 CommentDTO.java 파일 생성 후 아래와 같이 작성
package net.datasa.test_ajax_my.domain.dto;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Builder
@Data
@NoArgsConstructor
@AllArgsConstructor
public class CommentDTO {
int num;
String name;
String comment;
}
(6) [src/main/java] - [net.datasa.test_ajax_my.controller] 안에 CommentController.java 파일 생성 후 아래와 같이 작성
package net.datasa.test_ajax_my.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@RequiredArgsConstructor
@RequestMapping("comment")
@Controller
public class CommentController {
/**
* 댓글 테스트 페이지로 이동
* @return HTML 파일경로
* */
@GetMapping("main")
public String main() {
return "comment";
}
}
(7) [src/main/java] - [net.datasa.test_ajax_my.controller] 안에 CommentRestController.java 파일 생성 후 아래와 같이 작성
package net.datasa.test_ajax_my.controller;
import java.util.List;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.datasa.test_ajax_my.domain.dto.CommentDTO;
import net.datasa.test_ajax_my.service.CommentService;
@Slf4j
@RequiredArgsConstructor
@RequestMapping("comment")
// @RestController : 이 annotation은 주석을 붙인 대상이 controller이면서 여기에 전부 "@ResponseBody"를 붙인다는 의미이다.
@RestController
public class CommentRestController {
private final CommentService commentService;
@PostMapping("write")
public void write(CommentDTO dto) {
log.debug("전달된 입력값 : {}", dto);
commentService.writeSave(dto);
}
@GetMapping("list")
public List<CommentDTO> list() {
List<CommentDTO> commentList = commentService.getList();
log.debug("받아올 객체배열 : {}", commentList);
return commentList;
}
@PostMapping("delete")
public void delete(@RequestParam("num") Integer num) {
log.debug("삭제할 댓글 번호 : {}", num);
commentService.delete(num);
}
@PostMapping("update")
public void update(CommentDTO dto) {
log.debug("수정할 댓글 정보 : {}", dto);
commentService.update(dto);
}
}
(8) [src/main/java] - [net.datasa.test_ajax_my.service] 안에 CommentService.java 파일 생성 후 아래와 같이 작성
package net.datasa.test_ajax_my.service;
import java.util.ArrayList;
import java.util.List;
import org.springframework.stereotype.Service;
import jakarta.persistence.EntityNotFoundException;
import jakarta.transaction.Transactional;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.datasa.test_ajax_my.domain.dto.CommentDTO;
import net.datasa.test_ajax_my.domain.entity.CommentEntity;
import net.datasa.test_ajax_my.repository.CommentRepository;
/**
* comment service
* */
@Slf4j
@RequiredArgsConstructor
@Service
@Transactional
public class CommentService {
private final CommentRepository commentRepository;
public void writeSave(CommentDTO dto) {
CommentEntity entity = CommentEntity.builder()
// DTO로 전달받은 값들을 Entity에 세팅
.name(dto.getName())
.comment(dto.getComment())
.build();
// DB에 저장
commentRepository.save(entity);
}
public List<CommentDTO> getList() {
List<CommentEntity> entityList = commentRepository.findAll();
List<CommentDTO> dtoList = new ArrayList<>();
for (CommentEntity entity : entityList) {
CommentDTO dto = new CommentDTO();
dto.setNum(entity.getNum());
dto.setName(entity.getName());
dto.setComment(entity.getComment());
dtoList.add(dto);
}
return dtoList;
}
public void delete(int num) {
commentRepository.deleteById(num);
}
public void update(CommentDTO dto) {
CommentEntity entity = commentRepository.findById(dto.getNum())
.orElseThrow(() -> new EntityNotFoundException("수정할 댓글이 없습니다."));
entity.setComment(dto.getComment());
}
}
(9) 결과 화면
첫 접속 화면
"댓글 달기 테스트" 화면
- "작성자"와 "댓글 내용"의 Input Box에 값을 입력한 뒤 "저장" 버튼을 누르면 DB에 저장되며, 아래 댓글 목록에 새로 입력한 내용이 추가됨
- "삭제" 또는 "수정" 버튼을 누를 경우, 페이지 이동 없이 댓글 목록 상 해당 라인의 댓글이 삭제되거나 수정됨
- "수정"의 경우, 현재 "prompt() 함수"를 사용하여 입력값을 받아 그 내용으로 댓글 내용을 수정할 수 있도록 설정해 놓음(단, 디자인을 고려했을 때 "prompt() 함수"보다는 "모달"을 사용할 것을 권장함)
- 특정 댓글(작성자 : 이일우)을 삭제한 화면 : "삭제" 버튼을 누를 시 해당 라인의 댓글이 바로 목록과 DB 상에서 삭제됨
- 특정 댓글(작성자 : 홍길동)을 수정한 화면 : "수정" 버튼을 누를 시 "prompt" 창이 열리며 수정할 내용을 입력받아 그 입력값으로 해당 라인의 댓글 내용을 목록과 DB 상에서 바로 수정 반영함