5. Controller 작성
에러페이지 진입시 상태 200 정상적이지 않고, 예외발생시 에러페이지 나오도록 ResponseEntity사용
Entity란? 응답 & 요청시 전송할 대상을 말함
성공하면 제대로 나오겠지만, 실패(예외발생)하면 에러500번이 나오야하나 200번 정상 빈화면만나옴.
이를 해결하기 위해 ResponseEntity 객체를 생성하여, 여기에 담아서 응답한다. ResponseEntity<List<CommentDto>>(list, 상태코드) (즉, 상태코드를 추가한 것)
반환타입도 변경
이러면 예외발생시, HttpStatus.BAD_REQUEST
지정된 게시물의 모든 댓글을 가져오는 메서드
댓글 삭제하는 메서드
댓글을 등록하는 메서드
댓글을 수정하는 메서드
6. UI 뷰
SimpleRestController.java
package com.fastcampus.ch4.controller;
import com.fastcampus.ch4.domain.*;
import org.springframework.stereotype.*;
import org.springframework.web.bind.annotation.*;
@Controller
public class SimpleRestController {
@GetMapping("/ajax")
public String ajax() {
return "ajax";
}
@GetMapping("/test")
public String test() {
return "test";
}
@PostMapping("/send")
@ResponseBody
public Person test(@RequestBody Person p) {
System.out.println("p = " + p);
p.setName("ABC");
p.setAge(p.getAge() + 10);
return p;
}
}
CommentController.java
package com.fastcampus.ch4.controller;
import com.fastcampus.ch4.domain.CommentDto;
import com.fastcampus.ch4.service.CommentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpSession;
import javax.xml.stream.events.Comment;
import java.util.List;
// 모든 메서드에 @ResponseBody가 있으니,
@Controller // 각메서드의 @ResponseBody를 생략하고 @Controller -->> RestConroller 로 변경가능
public class CommentController {
@Autowired
CommentService service;
// 댓글을 수정하는 메서드
@PatchMapping("/comments/{cno}") //ex. comments/40
@ResponseBody // 직렬화 ( 객체 --> http text)
public ResponseEntity<String> modify(@PathVariable Integer cno, @RequestBody CommentDto dto, HttpSession session) {
// String commenter = (String) session.getAttribute("id");
String commenter = "asdf"; // 테스트 아이디는 다 asdf라 하드코딩함
dto.setCommenter("asdf");
dto.setCno(cno);
System.out.println("dto = " + dto);
try {
if(service.modify(dto) != 1)
throw new Exception("Modify failed.");
return new ResponseEntity<String>("MOD_OK", HttpStatus.OK);
} catch (Exception e) {
e.printStackTrace();
return new ResponseEntity<String>("MOD_ERR", HttpStatus.BAD_REQUEST);
}
}
// postman 사이트에서 테스트
// {
// "pcno":0,
// "comment":"kkkkkkkkkkkkkk",
// "commenter":"asdf"
// }
// 댓글을 등록하는 메서드
@PostMapping("/comments") //ex. comments?bno=726
@ResponseBody // 직렬화 ( 객체 --> http text)
public ResponseEntity<String> write(@RequestBody CommentDto dto, Integer bno, HttpSession session) {
// ★ dto에 @RequestBody를 붙여줘야함( json -->> 자바객체로 넣기위해 )
// String commenter = (String) session.getAttribute("id");
String commenter = "asdf"; // 테스트 아이디는 다 asdf라 하드코딩함
dto.setCommenter("asdf");
dto.setBno(bno);
System.out.println("dto = " + dto);
try {
if(service.write(dto)!=1)
throw new Exception("Write failed.");
return new ResponseEntity<String>("WRT_OK", HttpStatus.OK);
} catch (Exception e) {
e.printStackTrace();
return new ResponseEntity<String>("WRT_ERR", HttpStatus.BAD_REQUEST);
}
}
// postman 사이트에서 테스트
// {
// "pcno":0,
// "comment":"hi"
// }
// 지정된 댓글을 삭제하는 메서드 // comments/1 이런식으로(쿼리스트링이아니라 URI의 일부라 @PathVariable 필요)
@DeleteMapping("/comments/{cno}")// 즉, comments/1?bno=752 @PathVariable 사용시 이렇게 됨
@ResponseBody // 직렬화 ( 객체 --> http text)
public ResponseEntity<String> remove(@PathVariable Integer cno, Integer bno, HttpSession session) {
// String commenter = (String) session.getAttribute("id");
String commenter = "asdf"; // 테스트 아이디는 다 asdf라 하드코딩함
try {
int rowCnt = service.remove(cno, bno, commenter);
if (rowCnt != 1) {
throw new Exception(("Delete Failed"));
}
return new ResponseEntity<>("Del_OK", HttpStatus.OK);
} catch (Exception e) {
e.printStackTrace();
return new ResponseEntity<>("Del_ERR", HttpStatus.BAD_REQUEST);
}
}
// 지정된 게시물의 모든 댓글을 가져오는 메서드
@RequestMapping("/comments") // comments?bno=1123 이런식으로 // GET방식
@ResponseBody
public ResponseEntity<List<CommentDto>> list(Integer bno){
List<CommentDto> list = null;
try {
list = service.getList(bno);
return new ResponseEntity<List<CommentDto>>(list, HttpStatus.OK) ; // 200
} catch (Exception e) {
e.printStackTrace();
return new ResponseEntity<List<CommentDto>>(HttpStatus.BAD_REQUEST) ; //400
}
// Entity란? 응답 & 요청시 전송할 대상을 말함
// 성공하면 제대로 나오겠지만, 실패(예외발생)하면 에러500번이 나오야하나 200번 정상 빈화면만나옴.
// 이를 해결하기 위해 ResponseEntity 객체를 생성하여, 여기에 담아서 응답한다.
// ResponseEntity<List<CommentDto>>(list, 상태코드) (즉, 상태코드를 추가한 것)
// 반환타입도 변경
// 이러면 예외발생시, HttpStatus.BAD_REQUEST
}
}
test.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
<script src="https://code.jquery.com/jquery-1.11.3.js"></script>
</head>
<body>
<h2>Comment Test</h2>
comment : <input type="text" name="comment"><br>
<button id="sendBtn" type="button">등록</button>
<button id="modBtn" type="button">수정</button>
<h2>Data From Server :</h2>
<div id="commentList"></div>
<script>
let bno = 1000;
// 댓글목록보기
let showList = function(bno){
$.ajax({
type:'GET', //요청 메서드
url:'/ch40/comments?bno='+bno, // 요청 URI
// header: {"content-type":"application/json"}, //요청헤더 // 현재는 보낼데이터 없어 생략
// dataType: 'text', // 전송받을 데이터 타입 // 생략시 기본이 JSON
// data:JSON.stringify(person), // 서버로 전솔할 데이터
success : function (result){
$("#commentList").html(toHtml(result)); // 서버로 응답이 도착하면 호출될 함수
},
error : function(){ alert("error")}
})
}
// ajax 진행흐름
// jsp에서 ajax으로 버튼눌러 요청 -->> uri일치하는 컨트롤러가 받음 (jasckson 데이터바인드에 의해 자바객체로 변환되어서) -->> DB등록 -->> ajax 성공시 출력
// 댓글 등록
$(document).ready(function(){
showList(bno);
$("#sendBtn").click(function(){
let comment = $("input[name=comment]").val();
if (comment.trim() == '') {
alert("댓글을 입력해주세요.");
$("input[name=commet]").focus()
return;
}
$.ajax({
type:'POST', // 요청 메서드
url: '/ch40/comments?bno=' + bno, // 요청 URI. ex. comments?bno=1000
headers : { "content-type": "application/json"}, // 요청 헤더
data : JSON.stringify({bno:bno, comment:comment}), // 서버로 전송할 데이터. stringify()로 직렬화 필요.
success : function(result){
alert(result);
showList(bno);
},
error : function(){ alert("error") } // 에러가 발생했을 때, 호출될 함수
}); // $.ajax()
});
//========================================================================================================
// 댓글 수정하기
$("#commentList").on("click",".modBtn",function() { // commentList클래스의 delBtn에 click이벤트를 넣어줌
// alert("modBTN clicked");
//cno 얻기
let cno = $(this).parent().attr("data-cno");
let comment = $('span.comment', $(this).parent()).text();
// 1. comment의 내용을 inpout에 뿌려주기
$("input[name=comment]").val(comment);
// 2. cno 전달하기
$("#modBtn").attr("data-cno", cno);
})
$("#modBtn").click(function(){
let cno = $(this).attr("data-cno");
let comment = $("input[name=comment]").val();
if (comment.trim() == '') {
alert("댓글을 입력해주세요.");
$("input[name=commet]").focus()
return;
}
$.ajax({
type:'PATCH', // 요청 메서드
url: '/ch40/comments/' + cno, // 요청 URI. ex. comments/70
headers : { "content-type": "application/json"}, // 요청 헤더
data : JSON.stringify({cno:cno, comment:comment}), // 서버로 전송할 데이터. stringify()로 직렬화 필요.
success : function(result){
alert(result);
showList(bno);
},
error : function(){ alert("error") } // 에러가 발생했을 때, 호출될 함수
}); // $.ajax()
});
//========================================================================================================
// 댓글삭제버튼
// $(".delBTN").click(function(){ // 이렇게 걸면안됨. 비동기에 들어있는 버튼이라, 클릭이벤트 발생불가.
$("#commentList").on("click",".delBtn",function(){ // commentList클래스의 delBtn에 click이벤트를 넣어줌
// alert("delBTN clicked")
//cno 얻기
let cno = $(this).parent().attr("data-cno");
let bno = $(this).parent().attr("data-bno");
$.ajax({
type:'DELETE', //요청 메서드
url:'/ch40/comments/' + cno + '?bno=' + bno, // 요청 URI
// header: {"content-type":"application/json"}, //요청헤더 // 현재는 보낼데이터 없어 생략
// dataType: 'text', // 전송받을 데이터 타입 // 생략시 기본이 JSON
// data:JSON.stringify(person), // 서버로 전솔할 데이터
success : function (result){
alert(result);
showList(bno);
},
error : function(){ alert("error")}
}); // ajax
});
});
//========================================================================================================
// 결과값을 배열로 받아서 forEach를통하여 <li> 태그 사용하여 출력에 필요한 함수
let toHtml = function(comments) {
let tmp = "<ul>";
comments.forEach(function (comment) {
tmp += '<li data-cno=' + comment.cno
tmp += ' data-pcno=' + comment.pcno
tmp += ' data-bno=' + comment.bno + '>'
tmp += ' commenter= <span class="commenter">' + comment.commenter + '</span>'
tmp += ' comment= <span class="comment">' + comment.comment + '</span>'
tmp += ' up_date =' + comment.up_date
tmp += '<button class = "modBtn">수정</button>'
tmp += '<button class = "delBtn">삭제</button>'
tmp += '</li>'
});
return tmp + "</ui>";
};
</script>
</body>
</html>
대댓글
test.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
<script src="https://code.jquery.com/jquery-1.11.3.js"></script>
</head>
<body>
<h2>Comment Test</h2>
comment : <input type="text" name="comment"><br>
<button id="sendBtn" type="button">등록</button>
<button id="modBtn" type="button">수정</button>
<h2>Data From Server :</h2>
<div id="commentList"></div>
<div id="replyForm" style="display: none" >
<input type="text" name="replyComment">
<button id="wrtRepBtn" type="button">등록</button>
</div>
<script>
let bno = 1000;
// 댓글목록보기
let showList = function(bno){
$.ajax({
type:'GET', //요청 메서드
url:'/ch40/comments?bno='+bno, // 요청 URI
// header: {"content-type":"application/json"}, //요청헤더 // 현재는 보낼데이터 없어 생략
// dataType: 'text', // 전송받을 데이터 타입 // 생략시 기본이 JSON
// data:JSON.stringify(person), // 서버로 전솔할 데이터
success : function (result){
$("#commentList").html(toHtml(result)); // 서버로 응답이 도착하면 호출될 함수
},
error : function(){ alert("error")}
})
}
// ajax 진행흐름
// jsp에서 ajax으로 버튼눌러 요청 -->> uri일치하는 컨트롤러가 받음 (jasckson 데이터바인드에 의해 자바객체로 변환되어서) -->> DB등록 -->> ajax 성공시 출력
// 댓글 등록
$(document).ready(function() {
showList(bno);
$("#sendBtn").click(function () {
let comment = $("input[name=comment]").val();
if (comment.trim() == '') {
alert("댓글을 입력해주세요.");
$("input[name=commet]").focus()
return;
}
$.ajax({
type: 'POST', // 요청 메서드
url: '/ch40/comments?bno=' + bno, // 요청 URI. ex. comments?bno=1000
headers: {"content-type": "application/json"}, // 요청 헤더
data: JSON.stringify({bno: bno, comment: comment}), // 서버로 전송할 데이터. stringify()로 직렬화 필요.
success: function (result) {
alert(result);
showList(bno);
},
error: function () {
alert("error")
} // 에러가 발생했을 때, 호출될 함수
}); // $.ajax()
});
//========================================================================================================
// 댓글 수정하기
$("#commentList").on("click", ".modBtn", function () { // commentList클래스의 delBtn에 click이벤트를 넣어줌
// alert("modBTN clicked");
//cno 얻기
let cno = $(this).parent().attr("data-cno");
let comment = $('span.comment', $(this).parent()).text();
// 1. comment의 내용을 inpout에 뿌려주기
$("input[name=comment]").val(comment);
// 2. cno 전달하기
$("#modBtn").attr("data-cno", cno);
})
$("#modBtn").click(function () {
let cno = $(this).attr("data-cno");
let comment = $("input[name=comment]").val();
if (comment.trim() == '') {
alert("댓글을 입력해주세요.");
$("input[name=commet]").focus()
return;
}
$.ajax({
type: 'PATCH', // 요청 메서드
url: '/ch40/comments/' + cno, // 요청 URI. ex. comments/70
headers: {"content-type": "application/json"}, // 요청 헤더
data: JSON.stringify({cno: cno, comment: comment}), // 서버로 전송할 데이터. stringify()로 직렬화 필요.
success: function (result) {
alert(result);
showList(bno);
},
error: function () {
alert("error")
} // 에러가 발생했을 때, 호출될 함수
}); // $.ajax()
});
//========================================================================================================
// 댓글삭제버튼
// $(".delBTN").click(function(){ // 이렇게 걸면안됨. 비동기에 들어있는 버튼이라, 클릭이벤트 발생불가.
$("#commentList").on("click", ".delBtn", function () { // commentList클래스의 delBtn에 click이벤트를 넣어줌
// alert("delBTN clicked")
//cno 얻기
let cno = $(this).parent().attr("data-cno");
let bno = $(this).parent().attr("data-bno");
$.ajax({
type: 'DELETE', //요청 메서드
url: '/ch40/comments/' + cno + '?bno=' + bno, // 요청 URI
// header: {"content-type":"application/json"}, //요청헤더 // 현재는 보낼데이터 없어 생략
// dataType: 'text', // 전송받을 데이터 타입 // 생략시 기본이 JSON
// data:JSON.stringify(person), // 서버로 전솔할 데이터
success: function (result) {
alert(result);
showList(bno);
},
error: function () {
alert("error")
}
}); // ajax
});
//========================================================================================================
//========================================================================================================
// <div id="replyForm">
// <input type="text" name="replyComment">
// <button id="wrtRepBtn" type="button">등록</button>
// </div>
// 대댓글 버튼
// $(".delBTN").click(function(){ // 이렇게 걸면안됨. 비동기에 들어있는 버튼이라, 클릭이벤트 발생불가.
$("#commentList").on("click", ".replyBtn", function () { // commentList클래스의 delBtn에 click이벤트를 넣어줌
// 1. 답글을 입력할 replyForm폼을 이동
$("#replyForm").appendTo($(this).parent());
// 2.답글을 입력할 폼을 보여줌
$("#replyForm").css("display","block");
});
$("#wrtRepBtn").click(function () {
// pcno 구하기
let comment = $("input[name=replyComment]").val();
let pcno = $("#replyForm").parent().attr("data-pcno");
if (comment.trim() == '') {
alert("댓글을 입력해주세요.");
$("input[name=replyComment]").focus();
return;
}
$.ajax({
type: 'POST', // 요청 메서드
url: '/ch40/comments?bno=' + bno, // 요청 URI. ex. comments?bno=1000
headers: {"content-type": "application/json"}, // 요청 헤더
data: JSON.stringify({pcno:pcno ,bno: bno, comment: comment}), // 서버로 전송할 데이터. stringify()로 직렬화 필요.
success: function (result) {
alert(result);
showList(bno);
},
error: function () {alert("error")
} // 에러가 발생했을 때, 호출될 함수
}); // $.ajax()
$("#replyForm").css("display","none");
$("input[name=replyComment]").val(''); // 비우기?
$("#replyForm").appendTo("body"); // replyForm을 원래위치로
});
})
//========================================================================================================
// 결과값을 배열로 받아서 forEach를통하여 <li> 태그 사용하여 출력에 필요한 함수
let toHtml = function (comments) {
let tmp = "<ul>";
comments.forEach(function (comment) {
tmp += '<li data-cno=' + comment.cno
tmp += ' data-pcno=' + comment.pcno
tmp += ' data-bno=' + comment.bno + '>'
if(comment.cno != comment.pcno)
tmp += 'ㄴ'
tmp += ' commenter= <span class="commenter">' + comment.commenter + '</span>'
tmp += ' comment= <span class="comment">' + comment.comment + '</span>'
tmp += ' up_date =' + comment.up_date
tmp += '<button class = "modBtn">수정</button>'
tmp += '<button class = "delBtn">삭제</button>'
tmp += '<button class = "replyBtn">답글</button>'
tmp += '</li>'
});
return tmp + "</ui>";
};
</script>
</body>
</html>
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="com.fastcampus.ch4.dao.CommentMapper">
<delete id="deleteAll" parameterType="int">
DELETE FROM comment
WHERE bno = #{bno}
</delete>
<select id="count" parameterType="int" resultType="int">
SELECT count(*) FROM comment
WHERE bno = #{bno}
</select>
<delete id="delete" parameterType="map">
DELETE FROM comment WHERE cno = #{cno} AND commenter = #{commenter}
</delete>
<insert id="insert" parameterType="CommentDto">
INSERT INTO comment
(bno, pcno, comment, commenter, reg_date, up_date)
VALUES
(#{bno}, #{pcno}, #{comment}, #{commenter}, now(), now())
</insert>
<select id="selectAll" parameterType="int" resultType="CommentDto">
-- ifnull(pcno, cno) 하면 pcno가 null이면 cno값이 들어감
SELECT cno, bno, ifnull(pcno, cno)as pcno, comment, commenter, reg_date, up_date
FROM comment
WHERE bno = #{bno}
ORDER BY pcno ASC, cno ASC;
</select>
<select id="select" parameterType="int" resultType="CommentDto">
SELECT cno, bno, pcno, comment, commenter, reg_date, up_date
FROM comment
WHERE cno = #{cno}
</select>
<update id="update" parameterType="CommentDto">
UPDATE comment
SET comment = #{comment}
, up_date = now()
WHERE cno = #{cno} and commenter = #{commenter}
</update>
</mapper>
참고 :
남궁성, 스프링의 정석
'Spring의 정석' 카테고리의 다른 글
SpringMVC 웹사이트(git) 2~3 (0) | 2023.04.03 |
---|---|
SpringMVC 웹사이트(기획) 1 (0) | 2023.04.02 |
게시판만들기 (REST API와 Ajax, 댓글1)9~10 (0) | 2023.04.01 |
게시판만들기 (검색)7~8 (0) | 2023.03.31 |
게시판만들기 (읽기,쓰기, 수정, 삭제)5~6 (0) | 2023.03.30 |