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>

 

 

 


참고 :

남궁성, 스프링의 정석

+ Recent posts