KoreaIt Academy/Spring Boot
[Spring Boot] JS모듈화(Ajax, callback)를 통한 REST Controller와의 통신
728x90
반응형
댓글 RestController
package com.example.board.controller;
import com.example.board.beans.vo.Criteria;
import com.example.board.beans.vo.ReplyVO;
import com.example.board.services.ReplyService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.io.UnsupportedEncodingException;
import java.util.List;
@RestController
@Slf4j
@RequiredArgsConstructor
@RequestMapping("/replies/*")
public class ReplyController {
private final ReplyService replyService;
// 댓글 등록
// 브라우저에서 JSON타입으로 데이터를 전송하고 서버에서는 댓글의 처리 결과에 따라 문자열로 결과를 리턴한다.
// consumes : Ajax를 통해 전달받은 데이터의 타입
// produces : Ajax의 success:function(result)에 있는 result로 전달할 데이터 타입
// @ResponseBody : @Controller에서 REST API를 구현하기 위해서 사용된다.
// 문자열을 전달할 때 한글이 깨지지 않게 하기 위해서는 text/plain; charset=utf-8을 작성한다.
// ResponseEntity : 서버의 상태 코드, 응답 메세지 등을 담을 수 있는 타입이다.
@PostMapping(value="/new", consumes="application/json", produces = "text/plain; charset= utf-8")
public ResponseEntity<String> create(@RequestBody ReplyVO replyVO) throws UnsupportedEncodingException{
int replyCount = replyService.register(replyVO);
log.info("ReplyVO : "+ replyVO);
log.info("REPLY INSERT COUNT : "+ replyCount);
return replyCount==1?
new ResponseEntity<>(new String("댓글등록 완료".getBytes(),"utf-8"), HttpStatus.OK) :
new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
}
// 스프링 부트는 ResponseEntity를 무조건 써야하나 자동으로 바꿔줌 List->ResponseEntity
// 게시글 댓글 전체 조회
@GetMapping("pages/{bno}/{page}")
public List<ReplyVO> getList(@PathVariable("bno") Long bno, @PathVariable("page") int page){
log.info("getList/.................");
Criteria criteria = new Criteria(page,10);
log.info(criteria.toString());
return replyService.getList(bno, criteria);
}
// 댓글 조회
// URI에 댓글 번호만 작성한다.
// 전달받은 rno를 JSON으로 리턴한다.
@GetMapping("{rno}")
public ReplyVO get(@PathVariable("rno") Long rno){
log.info("get......................");
return replyService.get(rno);
}
// 댓글 수정
// PUT : 자원의 전체 수정, 자원 내 모든 필드를 전달해야 함, 일부만 전달할 경우 오류
// PATCH : 자원의 일부 수정, 수정할 필드만 전송(자동 주입이 아닌 부분만 수정하는 쿼리문에서 사용)
// PATCH가 PUT을 담고 있기 때문에 전체를 전달 받아서 전체를 수정하는 상황, 전체 중 부분만 수정하는 상황 모두 PATCH를 사용하는 것이 좋다.
@RequestMapping(method={RequestMethod.PUT, RequestMethod.PATCH}, value="{rno}" ,
consumes = "application/json", produces = "text/plain; charset=utf-8")
public ResponseEntity<String> modify(@RequestBody ReplyVO replyVO, @PathVariable("rno") Long rno) throws UnsupportedEncodingException{
replyVO.setRno(rno);
return replyService.modify(replyVO) == 1 ? new ResponseEntity<>(new String("댓글 수정성공".getBytes(),"utf-8"),HttpStatus.OK) :
new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
}
// 댓글 삭제
// URI로 댓글 번호를 전달 받은 후 성공 시 댓글 삭제 성공 전달
@DeleteMapping(value = "{rno}" , produces = "text/plain; charset=utf-8")
public ResponseEntity<String> remove(@PathVariable("rno") Long rno) throws UnsupportedEncodingException{
return replyService.remove(rno) == 1 ? new ResponseEntity<>(new String("댓글 삭제 성공".getBytes(),"utf-8"),HttpStatus.OK) :
new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
}
}
js 모듈화
//Ajax모듈화-> 사용부의 코드가 깔끔해 집니다.
/*
함수들을 하나의 모듈처럼 묶음으로 구성하는 것을 의미
화면 내에서 Javascript 처리를 하다 보면 이벤트 처리와 DOM, Ajax 처리 등 복잡하게 섞여서 유지보수가 힘들다.
따라서 javascript를 하나의 모듈처럼 구성하여 사용한다.
*/
console.log("Reply Module.....");
//일회성으로 사용되는 함수
let replyService = (function () {
//callback, error는 외부에서 전달받을 함수이다.
//함수의 파라미터 개수를 일치시킬 필요가 없기 때문에
//사용시 callback이나 error와 같은 파라미터는 상황에 따라 작성한다.
//댓글 등록
function add(replyInfo, callback, error) {
console.log("add reply................");
$.ajax({
url: "/replies/new",
type: "post",
data: JSON.stringify(replyInfo),// 전달할 JSON데이터에서 문자열 처리가 필요한 것들(key, dateType)을 자동으로 처리해준다.
contentType: "application/json; charset=utf-8",
// dataType: 생략가능 자동으로 됨
success: function (result, status, xhr) {
if (callback) {
//외부에서 전달받은 값이 있다면 결과를 해당 함수의 매개변수로 전달하여 사용한다.
callback(result);
}
},
error: function (xhr, status, err) {
if (error) {
error(err);
}
}
});
}
//댓글 삭제
function remove(rno, callback, error) {
console.log("remove reply........");
$.ajax({
url: "/replies/" + rno,
type: "delete",
data: rno,
success: function (result) {
if (callback) {
callback(result);
}
},
error: function (xhr, status, err) {
if (error) {
error(err);
}
}
}
);
}
//댓글 수정
function modify(replyInfo, callback, error) {
console.log("MODIFY reply........");
$.ajax({
url: "/replies/" + replyInfo.rno,
type: "patch",
data: JSON.stringify(replyInfo),
contentType: "application/json; charset=utf-8",
success: function (result) {
if (callback) {
callback(result);
}
},
error: function (xhr, status, err) {
if (error) {
error(err);
}
}
});
}
//댓글 목록
function getList(params, callback, error) {
console.log("list...........");
// let date = x | y : x가 없으면 y
let page = params.page || 1;
// get방식으로 요청 후 JSON으로 응답
// $.getJSON(url, callback).fail(callback)
//리턴값을 json으로 바꿔줌
$.getJSON(
"/replies/pages/" + params.bno + "/" + page,
function (list) {
if (callback) {
callback(list);
}
}
).fail(function (xhr, status, err) {
if (error) {
error(err);
}
});
}
// 댓글 하나 조회
function get(rno, callback, error) {
$.get(
"/replies/" + rno,
function (replyInfo) {
if (callback) {
callback(replyInfo);
}
}
).fail(function (xhr, status, err) {
if (error) {
error(err);
}
});
}
return {add: add, remove: remove, modify: modify, getList: getList}
// 외부에서는 replyService.add(객체, 콜백)형식으로 사용하며,
// Ajax 호출이 감춰져 있기 떄문에 사용부의 코드가 더 깔끔해진다.
})();
사용부(html)
//이벤트 위임
//작성된 HTML에는 이벤트 처리가 가능하지만,
//DOM에서 새롭게 추가되는 HTML에는 이벤트가 반영되지 않는다.
//따라서 미리 작성해놓은 HTML에 이벤트를 반영한 후,
//해당 자식 태그를 선택하여 이벤트 위임을 진행해야 한다.
$("div.paging").on("click", "a.changePage", function(e){
e.preventDefault();
pageNum = parseInt($(this).attr("href"));
showList(pageNum);
});
function showList(page){
replyService.getList({bno:bno, page:page || 1},
function(replyCnt, list){
if(list == null || list.length == 0){
replyUL.html("댓글이 없습니다.");
return;
}
let str = "";
for(let i=0, len=list.length; i<len; i++){
str += "<li style='display: block' data-rno='" + list[i].rno + "'>"
str += "<strong>" + list[i].replier + "</strong>"
str += "<div>"
str += "<p class='reply" + list[i].rno +"'>" + list[i].reply + "</p>"
str += "<p><strong class='date'>" + replyService.displayTime(list[i].replyDate);
if(list[i].replyDate != list[i].updateDate){
str += "<br>수정된 날짜 " + replyService.displayTime(list[i].updateDate);
}
str += "</strong></p></div>"
str += "<div style='text-align: right'><a class='modify' href='" + list[i].rno + "'>수정</a>"
str += "<a class='finish' style='display: none' href='" + list[i].rno + "'>수정완료</a>"
str += " <a class='remove' href='" + list[i].rno + "'>삭제</a>"
str += "</div></li>"
str += "<div class='line'></div>"
}
replyUL.html(str);
showReplyPage(replyCnt);
}
);
}
let check = false;
$(".replies").on("click", "a.modify", function(e){
e.preventDefault();
let rnoValue = $(this).attr("href");
$("p.reply" + rnoValue).html("<textarea class='" + rnoValue + "'>" + $("p.reply" + rnoValue).text() + "</textarea>")
$(this).hide();
let arFinish = $(".finish");
for(let i=0; i<arFinish.length; i++){
if($(arFinish[i]).attr("href") == rnoValue){
$(arFinish[i]).show();
check = true;
break;
}
}
});
$(".replies").on("click", "a.finish", function(e){
e.preventDefault();
let rnoValue = $(this).attr("href");
let newReply = $("." + rnoValue).val();
if(newReply == ""){return;}
replyService.update({rno:rnoValue, reply:newReply},
function(result){
alert(result);
check = false;
showList(pageNum);
}
)
})
728x90
반응형
'KoreaIt Academy > Spring Boot' 카테고리의 다른 글
[Spring Boot] REST 방식 - ResponseEntity을 사용한 댓글 수정(PUT, PATCH) , 삭제(DELETE) (0) | 2021.10.14 |
---|---|
[Spring Boot] @Controller와 @RestController의 차이, REST 방식 사용법(Ajax) - 댓글 등록, 조회 (0) | 2021.10.14 |
[Spring Boot] 단일 검색, 다중 검색 처리, MyBatis의 동적 태그 (0) | 2021.10.13 |
[Spring Boot] UriComponentsBuilder - 파라미터 연결(페이지 유지) (0) | 2021.10.13 |
[Spring Boot] 페이징 처리 - Criteria, PageDTO (2) | 2021.10.13 |
댓글