일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
Tags
- 싱글톤
- 로그인
- Linux
- springboot
- input태그
- 반복문
- security
- 시큐리티 로그아웃
- 시큐리티로그인
- java
- sql
- 시큐리티 로그인
- 2차원배열
- html
- 목록
- Spring boot
- 리눅스
- springSecurity
- 스프링 부트
- programmers
- css
- 소스트리
- gradle
- codingtest
- javascript
- 시큐리티
- 프로그래머스
- 코딩테스트
- StyleSheet
- JAVA11
Archives
- Today
- Total
JAVAIARY
@RestController와 JSON처리 본문
댓글 처리
- 댓글은 게시물의 조회 화면에서 처리
- Ajax를 이용해서 컨트롤러와 JSON 포맷으로 데이터를 교환
- 경로 : '/replies/'
1. JSON & Ajax로 댓글 처리
- 게시물이 로딩된 이후에 화면에서 댓글의 숫자를 클릭하면 해당 게시물에 속한 댓글을 Ajax로 가져와 화면에 출력
- 버튼 클릭 시 새로운 댓글을 입력할 수 있는 모달창 출력, Ajax POST 방식으로 댓글 전송
- 이후에 댓글의 목록을 새로 가져와서 화면상에 조금 전에 추가한 댓글을 볼 수 있도록 함
- 댓글 삭제와 수정은 댓글 등록과 동일하게 특정 댓글을 선택해서 모달창에서 처리
* 자신이 작성한 댓글에 대해서만 수정/삭제가 가능해야 하지만 현재 보안 적용되지 않은 관계로 고려하지 않고 적용
1) ReplyRepository 수정
public interface ReplyRepository extends JpaRepository<Reply, Long> {
// Board 삭제 시 댓글 삭제
@Modifying
@Query("delete from Reply r where r.board.bno = :bno ")
void deleteByBno(Long bno);
//게시물로 댓글 목록 가져오기
List<Reply> getRepliesByBoardOrderByRno(Board board);
}
- 특정 게시글 번호를 통해 댓글 목록 가져오기
test 작성 후 실행
@Test
public void testListByBoard(){
List<Reply> replyList = replyRepository.getRepliesByBoardOrderByRno(
Board.builder().bno(97L).build());
replyList.forEach(reply -> System.out.println(reply));
}
- bno 100번 글의 댓글을 list형태로 저장 및 출력

2. ReplyDTO와 ReplyService/ReplyController
1) ReplyDTO 클래스 추가

@Builder
@AllArgsConstructor
@NoArgsConstructor
@Data
public class ReplyDTO {
private Long rno;
private String text;
private String replyer;
private long bno;
private LocalDateTime regDate, modDate;
}
2) 서비스 계층 처리
- 댓글 등록(register)
- 특정 게시물의 댓글 리스트를 가져오기(getList)
- 댓글 수정(modify)/ 삭제(remove)
- Reply -> DTO (entityToDTO) / DTO -> Reply (dtoToEntity)

package com.example.demo.service;
import com.example.demo.dto.ReplyDTO;
import com.example.demo.entity.Board;
import com.example.demo.entity.Reply;
import java.util.List;
public interface ReplyService {
Long register(ReplyDTO replyDTO); // 댓글 등록
List<ReplyDTO> getList(Long bno); // 특정 게시물의 댓글 목록
void modify(ReplyDTO replyDTO); // 댓글 수정
void remove(Long rno); // 댓글 삭제
//ReplyDTO를 Reply객체로 변환 Board객체의 처리가 수반 됨
default Reply dtoToEntity(ReplyDTO replyDTO) {
Board board = Board.builder().bno(replyDTO.getBno()).build();
Reply reply = Reply.builder()
.rno(replyDTO.getRno())
.text(replyDTO.getText())
.replyer(replyDTO.getReplyer())
.board(board)
.build();
return reply;
}
// Reply 객체를 ReplyDTO로 변환 Board 객체가 필요하지 않으므로 게시물 번호만
default ReplyDTO entityToDTO(Reply reply){
ReplyDTO dto = ReplyDTO.builder()
.rno(reply.getRno())
.text(reply.getText())
.replyer(reply.getReplyer())
.regDate(reply.getRegDate())
.modDate(reply.getModDate())
.build();
return dto;
}
}
@Service
@RequiredArgsConstructor
public class ReplyServiceImpl implements ReplyService {
private final ReplyRepository replyRepository;
@Override
public Long register(ReplyDTO replyDTO) {
Reply reply = dtoToEntity(replyDTO);
replyRepository.save(reply);
return reply.getRno();
}
@Override
public List<ReplyDTO> getList(Long bno) {
List<Reply> result = replyRepository.getRepliesByBoardOrderByRno(Board.builder().bno(bno).build());
return result.stream().map(reply -> entityToDTO(reply)).collect(Collectors.toList());
}
@Override
public void modify(ReplyDTO replyDTO) {
Reply reply = dtoToEntity(replyDTO);
replyRepository.save(reply);
}
@Override
public void remove(Long rno) {
replyRepository.deleteById(rno);
}
}
3) 테스트 작성 및 실행

@SpringBootTest
public class ReplyServiceTests {
@Autowired
private ReplyService service;
@Test
public void testGetList(){
Long bno = 100l; // 데이터베이스에 존재하는 번호
List<ReplyDTO> replyDTOList = service.getList(bno);
replyDTOList.forEach(replyDTO -> System.out.println(replyDTO));
}
}


- 댓글 리스트가 정상적으로 불러와지는지 확인
4) 컨트롤러 작성
- Controller를 통해 조회화면에서 Ajax로 댓글 표시
- 댓글 데이터를 JSON으로 생성할 것이므로 @RestController 어노테이션 사용
@RestController
@RequestMapping("/replies/")
@Log4j2
@RequiredArgsConstructor
public class ReplyController {
private final ReplyService replyService; // 자동주입을 위해 final;
@GetMapping(value = "/board/{bno}", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<List<ReplyDTO>> getListByBoard(@PathVariable("bno") Long bno){
log.info("bno " + bno);
return new ResponseEntity<>(replyService.getList(bno), HttpStatus.OK);
}
- 게시글 번호에 해당하는 댓글 가져오는 메서드
- ResponseEntity 객체를 이용하여 HTTP의 상태 코드 함께 전달 가능
- @PathVariable 어노테이션을 통해 URL 에서 { }로 동적변수 처리 가능

- 웹에서 게시글 번호에 해당하는 댓글 가져오는 것 확인
2. 조회 화면에서 처리
- 해당 게시물의 댓글 수 파악
- 댓글 수 클릭 시 Ajax로 데이터 처리
1) read.html
<div>
<div class="mt-4">
<h5><span class="badge badge-secondary replyCount">Reply Count[[${dto.replyCount}]]</span></h5>
</div>
</div>
<div class = "list-group" replyList>
</div>
- 최하단에 댓글이 출력될 div 작성
- Reply Count 버튼을 클릭했을 때 실행될 이벤트는 JavaScript로 작성
<scipt th:inline="javascript">
$(document).ready(function(){
var bno = [[${dto.bno}]];
var listGroup = $(".replyList"){
$.getJSON('/replies/board/'+bno, function(arr){
console.log(arr);
}) //end getJSON
}) //end click
</scipt>


- Reply Count 뱃지 클릭시 콘솔에 댓글 정보 출력
2) 댓글 조회기능 분리
- 실제 웹 화면에 댓글을 띄울 수 있도록 스크립트 수정
$(document).ready(function(){
var bno = [[${dto.bno}]];
var listGroup = $(".replyList"); // 댓글이 추가될 영역
// 날짜 처리를 위한 함수
function formatTime(str){
var date = new Date(str);
return date.getFullYear() + '/' +
(date.getMonth() + 1) + '/' +
date.getDate() + ' ' +
date.getHours() + ':' +
date.getMinutes();
}
// 특정한 게시글의 댓글을 처리하는 함수
function loadJSONData() {
$.getJSON('/replies/board/'+bno, function(arr){
console.log(arr);
var str = "";
$('.replyCount').html(" Reply Count " + arr.length);
$.each(arr, function(idx, reply){
console.log(reply);
str += ' <div class="card-body" data-rno="' + reply.rno + '"><b>' + reply.rno + '</b>';
str += ' <h5 class="card-title">' + reply.text + '</h5>';
str += ' <h6 class="card-subtitle mb-2 text-muted">' + reply.replyer + '</h6>';
str += ' <p class="card-text">' + formatTime(reply.regDate) + '</p>';
str += ' </div>';
})
listGroup.html(str);
}); // end getJSON
}
$(".replyCount").click(function(){
loadJSONData();
$.getJSON('/replies/board/'+bno, function(arr){
console.log(arr);
}) // end getJSON
}) // end click
});

2) 댓글 추가 모달창
- 댓글 쓰기 버튼을 누르면 모달창을 띄우는 방식
- 모달창 html과 모달을 띄우는 javaScript 추가
<!-- 모달 시작 -->
<div class="modal" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Modal title</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<div class="form-group">
<input class="form-control" type="text" name="replyText" placeholder="Reply Text...">
</div>
<div class="form-group">
<input class="form-control" type="text" name="replyer" placeholder="Replyer">
<input type="hidden" name="rno" >
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-danger replyRemove">Remove</button>
<button type="button" class="btn btn-warning replyModify">Modify</button>
<button type="button" class="btn btn-primary replySave">Save</button>
<button type="button" class="btn btn-outline-secondary replyClose" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
<!-- 모달 끝 -->
//모달 창
var modal = $('.modal');
$(".addReply").click(function () {
modal.modal('show');
//댓글 입력하는 부분 초기화 시키기
$('input[name="replyText"]').val('');
$('input[name="replyer"]').val('');
$(".modal-footer .btn").hide(); //모달 내의 모든 버튼을 안 보이도록
$(".replySave, .replyClose").show(); //필요한 버튼들만 보이도록
});

3) 댓글 등록 처리
$(".replySave").click(function(){
var reply = {
bno: bno,
text: $('input[name="replyText"]').val(),
replyer: $('input[name="replyer"]').val()
}
console.log(reply);
$.ajax({
url: 'replies/',
method: 'post',
data: JSON.stringify(reply),
contentType: 'application/json; charset = utf-8',
dataType : 'json',
success : function(data){
console.log(data);
var newRno = parseInt(data);
alert(newRno +"번 댓글이 등록되었습니다.")
modal.modal('hide');
loadJSONData();
}
})
})

ReplyController 작성
@PostMapping("")
public ResponseEntity<Long> register(@RequestBody ReplyDTO replyDTO){
log.info(replyDTO);
Long rno = replyService.register(replyDTO);
return new ResponseEntity<>(rno, HttpStatus.OK);
}
- save 버튼 클릭시 작동하도록 작성
- Ajax를 이용해서 POST 방식으로 처리
- @RequestBody 어노테이션을 사용해 JSON으로 들어오는 데이터를 자동으로 해당 타입의 객체로 매핑해 줌


- save 버튼 클릭시 확인창이 뜨고 모달 닫힘
4) 댓글 삭제 처리
- 특정 댓글을 클릭하면 댓글 삭제할 수 있도록 모달창 출력
// 댓글 클릭
$('.replyList').on("click", ".card-body", function(){
var rno = $(this).data("rno");
$("input[name='replyText']").val( $(this).find('.card-title').html());
$("input[name='replyer']").val( $(this).find('.card-subtitle').html());
$("input[name='rno']").val(rno);
$(".modal-footer .btn").hide();
$(".replyRemove, .replyModify, .replyClose").show();
modal.modal('show');
});
// 댓글 삭제
$(".replyRemove").on("click", function(){
var rno = $("input[name='rno']").val(); //모달 창에 보이는 댓글 번호 hidden처리되어 있음
$.ajax({
url: '/replies/' + rno,
method: 'delete',
success: function(result){
console.log("result: " + result);
if(result ==='success'){
alert("댓글이 삭제되었습니다");
modal.modal('hide');
loadJSONData();
}
}
})
});
@DeleteMapping("/{rno}")
public ResponseEntity<String> remove(@PathVariable("rno") Long rno){
log.info("RNO: " + rno);
replyService.remove(rno);
return new ResponseEntity<>("success", HttpStatus.OK);
}
- 댓글 번호(rno)로 삭제하고 문자열을 결과로 전달


5) 댓글 수정 처리
// 댓글 수정
$(".replyModify").click(function() {
var rno = $("input[name='rno']").val();
var reply = {
rno: rno,
bno: bno,
text: $('input[name="replyText"]').val(),
replyer: $('input[name="replyer"]').val()
}
console.log(reply);
$.ajax({
url: '/replies/' + rno,
method: 'put',
data: JSON.stringify(reply),
contentType: 'application/json; charset=utf-8',
success: function(result){
console.log("RESULT: " + result);
if(result ==='success'){
alert("댓글이 수정되었습니다");
modal.modal('hide');
loadJSONData();
}
}
});
});
@PutMapping("/{rno}")
public ResponseEntity<String> modify(@RequestBody ReplyDTO replyDTO){
log.info(replyDTO);
replyService.modify(replyDTO);
return new ResponseEntity<>("success", HttpStatus.OK);
}



- 댓글 수정되는 것 확인
'Project > 2023.02~ ) Study toy 프로젝트' 카테고리의 다른 글
M : N (다대다) 관계의 설계와 구현 (0) | 2023.04.03 |
---|---|
자잘한 이슈 고치기! (0) | 2023.03.13 |
JPQL로 검색하기 (0) | 2023.03.13 |
컨트롤러와 화면 처리 (0) | 2023.03.06 |
프로젝트 적용하기(Board) (0) | 2023.03.06 |