[Spring] 댓글 기능 구현 : 백엔드 | ResponseEntity

Jeini·2023년 6월 6일
0

🍃  Spring

목록 보기
30/33
post-thumbnail

💡 댓글 기능 구현 순서

✔️ 1. DB테이블 생성

  • 댓글 기능을 넣을 때는 먼저 DB테이블을 생성해 줘야 한다.

✔️ 2. Mapper XML 작성

  • 중간에 MyBatis 작성 ➡️ Mapper XML

  • 즉, SQL문을 작성해야 한다. ➡️ CRUD 작성

✔️ 3. DTO & DAO 작성 & 테스트

  • 한 레이어마다 테스트를 각각 해야 한다. 한꺼번에 하면 복잡하게 된다.

✔️ 4. Service 작성 & 테스트

✔️ 5. Controller 작성 & 테스트

✔️ 6. 뷰(UI) 작성 & 테스트

  • HTML, CSS, JS, JQuary를 이용해서 view를 만든다.

1~5번까지가 백엔드가 할일이고 6번이 프론트엔드가 하는 일이다. 보통 프로젝트할 때 백엔드와 프론트엔드가 나눠서 작업한다. 댓글에서의 기능은 백엔드에서는 쉬운 편이다. 복잡하지 않기 때문. 오히려 프론트가 더 어렵다.

✏️ 1. DB 테이블 작성


1. cno: 댓글 식별자 번호

  • pk & NotNull & Auto Increment 설정

2. bno: 게시물 번호

  • 게시물에 댓글이 있는 거니까 !
  • NotNull 설정

3. pcno: 대댓글 번호

  • 대댓글이 없을 수도 있으니까 NotNull 처리 ❌

4. comment: 댓글

5. commenter: 댓글 단 user

6. reg_date: 댓글 단 날짜/시간

7. up_date: 업데이트

✏️ 2. Mapper 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="kr.ac.jipark09.dao.CommentMapper">
    <!-- 게시물 번호를 주면 댓글 다 지움-->
    <delete id="deleteAll" parameterType="int">
        DELETE FROM comment
        WHERE bno = #{bno}
    </delete>

    <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">
        SELECT * FROM comment
        WHERE bno = #{bno}
        ORDER BY reg_date ASC, cno ASC
    </select>

    <select id="select" parameterType="int" resultType="CommentDto">
        SELECT * FROM comment
        WHERE cno = #{cno}
    </select>

    <select id="count" parameterType="int" resultType="int">
        SELECT count(*) FROM comment
        WHERE bno = #{bno}
    </select>

    <update id="update" parameterType="CommentDto">
        UPDATE comment
        SET comment = #{comment}, up_date = now()
        WHERE cno = #{cno} AND commenter = #{commenter}
    </update>
</mapper>
  • sql문 CRUD를 작성해 준다.
  • 작성한 다음에는 MySQL Workbench로 잘 돌아가나 테스트 해봐야 한다.

✔️ 확인 체크

✏️ 3. DTO & DAO 작성 & 테스트


✏️ CommentDto

  • 처음 만들었던 Comment 테이블보고 만들면 됨
package kr.ac.jipark09.domain;


import java.util.Date;
import java.util.Objects;

public class CommentDto {
   private Integer cno;
   private Integer bno;
   private Integer pcno;
   private String comment;
   private String commenter;
   private Date reg_date;
   private Date up_date;

   public CommentDto() {}

    public CommentDto(Integer bno, Integer pcno, String comment, String commenter) {
        this.bno = bno;
        this.pcno = pcno;
        this.comment = comment;
        this.commenter = commenter;
    }

    public Integer getCno() {
        return cno;
    }

    public void setCno(Integer cno) {
        this.cno = cno;
    }

    public Integer getBno() {
        return bno;
    }

    public void setBno(Integer bno) {
        this.bno = bno;
    }

    public Integer getPcno() {
        return pcno;
    }

    public void setPcno(Integer pcno) {
        this.pcno = pcno;
    }

    public String getComment() {
        return comment;
    }

    public void setComment(String comment) {
        this.comment = comment;
    }

    public String getCommenter() {
        return commenter;
    }

    public void setCommenter(String commenter) {
        this.commenter = commenter;
    }

    public Date getReg_date() {
        return reg_date;
    }

    public void setReg_date(Date reg_date) {
        this.reg_date = reg_date;
    }

    public Date getUp_date() {
        return up_date;
    }

    public void setUp_date(Date up_date) {
        this.up_date = up_date;
    }

    @Override
    public String toString() {
        return "CommentDto{" +
                "cno=" + cno +
                ", bno=" + bno +
                ", pcno=" + pcno +
                ", comment='" + comment + '\'' +
                ", commenter='" + commenter + '\'' +
                ", reg_date=" + reg_date +
                ", up_date=" + up_date +
                '}';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        CommentDto that = (CommentDto) o;
        return Objects.equals(cno, that.cno) && Objects.equals(bno, that.bno) && Objects.equals(pcno, that.pcno) && Objects.equals(comment, that.comment) && Objects.equals(commenter, that.commenter);
    }

    @Override
    public int hashCode() {
        return Objects.hash(cno, bno, pcno, comment, commenter);
    }
}

✏️ CommentDaoImpl

  • mapper.xml 보고 매칭하면서 만들면 됨
package kr.ac.jipark09.dao;

import kr.ac.jipark09.domain.CommentDto;
import org.apache.ibatis.session.SqlSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Repository
public class CommentDaoImpl implements CommentDao {
    @Autowired
    private SqlSession session;
    private static String namespace = "kr.ac.jipark09.dao.CommentMapper";

    @Override
    public int deleteAll(Integer bno) {
        return session.delete(namespace + "deleteAll", bno);
    }

    @Override
    public int delete(Integer cno, String commenter) throws Exception {
        Map map = new HashMap();
        map.put("cno", cno);
        map.put("commenter", commenter);
        return session.delete(namespace + "delete", map);
    }

    @Override
    public int insert(CommentDto commentDto) throws Exception {
        return session.insert(namespace + "insert", commentDto);

    }

    @Override
    public List<CommentDto> selectAll(Integer bno) throws Exception {
        return session.selectList(namespace + "selectAll" + bno);
    }

    @Override
    public CommentDto select(Integer cno) throws Exception {
        return session.selectOne(namespace + "select" + cno);
    }

    @Override
    public int count(int bno) throws Exception {
        return session.selectOne(namespace + "count", bno);
    }

    @Override
    public int update(CommentDto commentDto) throws Exception {
        return session.update(namespace + "update" + commentDto);

    }


}

✏️ test

  • 테스트 만들어 주기!

package kr.ac.jipark09.dao;

import kr.ac.jipark09.domain.*;
import org.junit.*;
import org.junit.runner.*;
import org.springframework.beans.factory.annotation.*;
import org.springframework.test.context.*;
import org.springframework.test.context.junit4.*;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

import static org.junit.Assert.*;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"file:src/main/webapp/WEB-INF/spring/root-context.xml"})
public class CommentDaoImplTest {
    @Autowired
    CommentDao commentDao;

    @Test
    @Transactional
    public void count() throws Exception {
        commentDao.deleteAll(1);
        assertTrue(commentDao.count(1) == 0);
    }

    @Test
    @Transactional
    public void delete() throws Exception {
        commentDao.deleteAll(1);
        CommentDto commentDto = new CommentDto(1, 0, "comment", "asdf");
        assertTrue(commentDao.insert(commentDto) == 1);
        assertTrue(commentDao.count(1) == 1);
    }

    @Test
    @Transactional
    public void insert() throws Exception {
        commentDao.deleteAll(1);
        CommentDto commentDto = new CommentDto(1, 0, "comment", "jipark09");
        assertTrue(commentDao.insert(commentDto)==1);
        assertTrue(commentDao.count(1)==1);

        commentDto = new CommentDto(1, 0, "comment", "jipark09");
        assertTrue(commentDao.insert(commentDto)==1);
        assertTrue(commentDao.count(1)==2);
    }

    @Test
    @Transactional
    public void selectAll() throws Exception {
        commentDao.deleteAll(1);
        CommentDto commentDto = new CommentDto(1, 0, "comment", "asdf");
        assertTrue(commentDao.insert(commentDto)==1);
        assertTrue(commentDao.count(1)==1);

        List<CommentDto> list = commentDao.selectAll(1);
        assertTrue(list.size()==1);

        commentDto = new CommentDto(1, 0, "comment", "asdf");
        assertTrue(commentDao.insert(commentDto)==1);
        assertTrue(commentDao.count(1)==2);

        list = commentDao.selectAll(1);
        assertTrue(list.size()==2);
    }

    @Test
    @Transactional
    public void select() throws Exception {
        commentDao.deleteAll(1);
        CommentDto commentDto = new CommentDto(1, 0, "comment", "asdf");
        assertTrue(commentDao.insert(commentDto)==1);
        assertTrue(commentDao.count(1)==1);

        List<CommentDto> list = commentDao.selectAll(1);
        String comment = list.get(0).getComment();
        String commenter = list.get(0).getCommenter();
        assertTrue(comment.equals(commentDto.getComment()));
        assertTrue(commenter.equals(commentDto.getCommenter()));
    }

    @Test
    @Transactional
    public void update() throws Exception {
        commentDao.deleteAll(1);
        CommentDto commentDto = new CommentDto(1, 0, "comment", "asdf");
        assertTrue(commentDao.insert(commentDto)==1);
        assertTrue(commentDao.count(1)==1);

        List<CommentDto> list = commentDao.selectAll(1);
        commentDto.setCno(list.get(0).getCno());
        commentDto.setComment("comment2");
        assertTrue(commentDao.update(commentDto)==1);

        list = commentDao.selectAll(1);
        String comment = list.get(0).getComment();
        String commenter = list.get(0).getCommenter();
        assertTrue(comment.equals(commentDto.getComment()));
        assertTrue(commenter.equals(commentDto.getCommenter()));
    }
}
  • @Transactional 을 붙여서 DB에 영향이 가지 않도록 해 주었다.
    (테스트를 마치면 자동으로 rollback 시켜줌)

✏️ 4. Service 작성 & 테스트


✏️ CommentServiceImpl

package kr.ac.jipark09.service;

import kr.ac.jipark09.dao.BoardDao;
import kr.ac.jipark09.dao.CommentDao;
import kr.ac.jipark09.domain.CommentDto;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@Service
public class CommentServiceImpl implements CommentService {
    private BoardDao boardDao;
    private CommentDao commentDao;

    // @Autowired 없어도 자동으로 알아서 주입해 준다.
    // 생성자가 하나밖에 없을 때 가능하다.
    public CommentServiceImpl(CommentDao commentDao, BoardDao boardDao) {
        this.commentDao = commentDao;
        this.boardDao = boardDao;
    }

    @Override
    public int getCount(Integer bno) throws Exception {
        return commentDao.count(bno);
    }

    @Override
    @Transactional(rollbackFor = Exception.class) // 예외가 발생하면 롤백
    public int remove(Integer cno, Integer bno, String commenter) throws Exception {
        // 게시판의 댓글 갯수 하나 줄음
        int rowCnt = boardDao.updateCommentCnt(-1, bno);
        System.out.println("updateCommentCnt - rowCnt = " + rowCnt);
        // throw new Exception("test") // 예외가 잘 뜨는지 확인

        // 댓글 하나 삭제
        rowCnt = commentDao.delete(cno, commenter);
        System.out.println("rowCnt = " + rowCnt);

        return rowCnt;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int write(CommentDto commentDto) throws Exception {
        boardDao.updateCommentCnt(1, commentDto.getBno());
        return commentDao.insert(commentDto);
    }

    @Override
    public List<CommentDto> getList(Integer bno) throws Exception {
        return commentDao.selectAll(bno);
    }

    @Override
    public CommentDto read(Integer cno) throws Exception{
        return commentDao.select(cno);
    }

    @Override
    public int modify(CommentDto commentDto) throws Exception {
        return commentDao.update(commentDto);
    }
}
  • 댓글이 추가되거나 삭제되면 boardDao에도 영향이 간다. 데이터베이스에서 board테이블을 보면 comment_cnt가 있다.
    ➡️ comment_cnt : 게시물 목록 보여줄 때 댓글이 몇개 달렸는지를 보는 것

  • 댓글이 달렸을 때, comment_cnt를 증가 시켜주고 댓글이 삭제되면 감소시킨다.
    ➡️ BoardDao , CommentDao 두 개다 주입을 받아야 한다.

  • 여기서 인스턴스로 주입을 받는 거 보다 생성자로 주입받는 게 더 나은 이유는,
    인스턴스 변수로 주입을 받으면 하나하나 다 @Autowired를 붙여줘야 한다. 그러면 한개씩 빼트려먹을 확률이 있다. 하지만 생성자로 만들어서 주입받으면 컴파일 할 때 에러가 떠서 주입받지 않았다는 것을 알 수가 있다.

✏️ test

package kr.ac.jipark09.service;

import kr.ac.jipark09.dao.BoardDao;
import kr.ac.jipark09.dao.CommentDao;
import kr.ac.jipark09.domain.BoardDto;
import kr.ac.jipark09.domain.CommentDto;
import org.junit.*;
import org.junit.runner.*;
import org.springframework.beans.factory.annotation.*;
import org.springframework.test.context.*;
import org.springframework.test.context.junit4.*;
import org.springframework.transaction.annotation.Transactional;

import static org.junit.Assert.*;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"file:src/main/webapp/WEB-INF/spring/root-context.xml"})
public class CommentServiceImplTest {
    @Autowired
    CommentService commentService;
    @Autowired
    CommentDao commentDao;
    @Autowired
    BoardDao boardDao;

    @Test
    @Transactional
    public void remove() throws Exception {
        boardDao.deleteAll();

        BoardDto boardDto = new BoardDto("hello", "hello", "asdf");
        assertTrue(boardDao.insert(boardDto) == 1);
        Integer bno = boardDao.selectAll().get(0).getBno();
        System.out.println("bno = " + bno);

        commentDao.deleteAll(bno);
        CommentDto commentDto = new CommentDto(bno,0,"hi","qwer");

        assertTrue(boardDao.select(bno).getComment_cnt() == 0);
        assertTrue(commentService.write(commentDto)==1);
        assertTrue(boardDao.select(bno).getComment_cnt() == 1);

        Integer cno = commentDao.selectAll(bno).get(0).getCno();

        // 일부러 예외를 발생시키고 Tx가 취소되는지 확인해야.
        int rowCnt = commentService.remove(cno, bno, commentDto.getCommenter());
        assertTrue(rowCnt==1);
        assertTrue(boardDao.select(bno).getComment_cnt() == 0);
    }

    @Test
    @Transactional
    public void write() throws  Exception {
        boardDao.deleteAll();

        BoardDto boardDto = new BoardDto("hello", "hello", "asdf");
        assertTrue(boardDao.insert(boardDto) == 1);
        Integer bno = boardDao.selectAll().get(0).getBno();
        System.out.println("bno = " + bno);

        commentDao.deleteAll(bno);
        CommentDto commentDto = new CommentDto(bno,0,"hi","qwer");

        assertTrue(boardDao.select(bno).getComment_cnt() == 0);
        assertTrue(commentService.write(commentDto) == 1);

        Integer cno = commentDao.selectAll(bno).get(0).getCno();
        assertTrue(boardDao.select(bno).getComment_cnt() == 1);
    }
}

✏️ 5. Controller 작성 & 테스트


✔️ RESTful API 설계

✏️ 해당 게시물의 댓글 반환 메서드

package kr.ac.jipark09.Controller;

import kr.ac.jipark09.dao.CommentDao;
import kr.ac.jipark09.domain.CommentDto;
import kr.ac.jipark09.service.CommentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.List;

@Controller
public class CommentController {
    @Autowired
    CommentService commentService;
	
    // 게시물 번호를 받으면 그 게시물에 달린 모든 댓글을 반환하는 메서드
    @RequestMapping("/comments") // comments?bno=1080
    @ResponseBody public List<CommentDto> list(Integer bno) {
        List<CommentDto> list = null;

        try {
             list = commentService.getList(bno);
        } catch (Exception e) {
           e.printStackTrace();
        }
        return list;
    }
}
  • @RequestMapping("/comments")
    : bno의 번호를 받아와야 된다. 이다.게시물 번호를 받으면 그 게시물에 달린 모든 댓글을 반환하는 메서드
    ➡️ comments?bno=1080 get방식으로 받는다고 생각하면 된다.

  • @ResponseBody를 붙여줘야 view이름으로 해석을 하지 않는다.

  • 해당 게시물에 댓글이 없으면 빈 배열이 나온다.

  • 해당 게시물에 댓글이 있으면 JSON 형태의 배열이 나온다.

  • 응답 헤더에 JSON 형태로 간 것을 알 수 있다.

여기서 일부러 예외를 던져도 잘 응답했다는 200번대가 나온다. 예외가 뜨면 서버의 잘못으로 500번대가 떠야되므로 200번으로 처리되면 안된다. 다른 상태코드로 바꿔줄 수 있어야 한다. ➡️ ResponseEntity 객체 생성


📎 ResponseEntity

✔️ HttpEntity를 상속받는, 결과 데이터와 HTTP 상태 코드를 직접 제어할 수 있는 클래스

✏️ 사용예시

package kr.ac.jipark09.Controller;

import kr.ac.jipark09.dao.CommentDao;
import kr.ac.jipark09.domain.CommentDto;
import kr.ac.jipark09.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.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.List;

@Controller
public class CommentController {
    @Autowired
    CommentService commentService;

    // 게시물 번호를 받으면 그 게시물에 달린 모든 댓글을 반환하는 메서드
    @RequestMapping("/comments") // comments?bno=1080
    @ResponseBody public ResponseEntity<List<CommentDto>> list(Integer bno) {
        List<CommentDto> list = null;

        try {
             list = commentService.getList(bno);
             return new ResponseEntity<List<CommentDto>>(list, HttpStatus.OK); // 200
        } catch (Exception e) {
           e.printStackTrace();
           // 사용자가 잘못 요청해서 에러나니까 400번대를 날린다.
           return new ResponseEntity<List<CommentDto>>(HttpStatus.BAD_REQUEST); // 400
        }
    }
}
  • list는 Entity이다. 이 Entity에다가 상태코드를 추가했을 뿐이다. 원래는 Entity만 보낸 것을 내가 설정해 준 상태코드도 같이 보냈다고 생각하면 된다.
    ➡️ 그 다음은 Spring이 알아서 처리해줌

❗️ Entity
: 응답 또는 요청할 때 전송할 대상

✏️ 삭제 메서드

 	@DeleteMapping("/comments/{cno}") // comments/1?bno=1 <-- 삭제할 댓글 번호
    @ResponseBody
    public ResponseEntity<String> remove(HttpSession session, @PathVariable Integer cno, Integer bno) {
        String commenter = "jipark09";
//                (String)session.getAttribute("id");
        try {
            int rowCnt = commentService.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);
        }
    }
  • 맵핑된 url의 일부({cno})를 읽어올 때는 @PathVariable을 붙여줘야 한다.

  • 뒤에 쿼리스트링(comments/?bno)이 있는 것은 그냥 파라미터에 쓰면 되는데, {cno} 는 쿼리스트링이 아니라, REST 형식으로 설계된 url의 일부이다.
    값을 가져올 때는 {} 로 감싸주고 그 값 앞에다가 @PathVariable 을 붙여줘야 한다. 브라우저에서 1(cno)을 보내면 해당 1이 cno 로 들어가게 된다.

잘 실행된 것을 확인!

✏️ 댓글 등록 메서드

 	// 댓글 저장하는 메서드
    @ResponseBody
    @PostMapping("/comments") // comments?bno=1 POST
    public ResponseEntity<String> write(@RequestBody CommentDto dto, Integer bno, HttpSession session) {
//        String commenter = (String) session.getAttribute("id");
        String commenter = "jipark09";
        dto.setCommenter(commenter);
        dto.setBno(bno);
        System.out.println("dto=" + dto);

        try {
            int result = commentService.write(dto);

            if(result != 1) {
                throw new Exception("Write Failed");
            }

            return new ResponseEntity<>("WRT_OK", HttpStatus.OK);
        } catch (Exception e) {
            e.printStackTrace();
            return new ResponseEntity<>("WRT_ERR", HttpStatus.BAD_REQUEST);
        }
    }
  • 입력한 내용을 받아와야 되니까 CommentDto를 받아온다.

  • 글쓰기니까 POST로 받는다.

  • CommentDto를 넘겨줘야 하는데 Stringfy() 된 JSON으로 Controller에 줘야 한다. 그래야 톰캣이 그 데이터를 Java 객체로 변환해서 파라미터에 넣어준다.

  • 받은 데이터에 @RequestBody 를 붙여줘야 JSON으로 온 객체를 Java객체로 변환해서 넣어줄 수 있다.

  • 요청할 때, 헤더에다가 Content-Type을 지정해 줘야 한다.
    : 내가 보내는 데이터가 JSON이야! 라는 것을 알려줘야 한다. 그렇지 않으면 웹 서버가 받았을 때 보낸 것이 어떤 것인지 모르기 때문에 해석하지 못한다.

✏️ 댓글 수정 메서드

	@PatchMapping("/comments/{cno}") // 수정할 댓글 번호를 적어준다.
    @ResponseBody
    public ResponseEntity<String> modify(@PathVariable Integer cno, @RequestBody CommentDto dto) {
//        String commenter = (String) session.getAttribute("id");
        String commenter = "jipark09";
        dto.setCommenter(commenter);
        dto.setCno(cno);

        try {
            int result = commentService.modify(dto);

            if(result != 1) {
                throw new Exception("Modiry Failed!");
            }
            return new ResponseEntity<String>("MOD_OK", HttpStatus.OK);

        } catch (Exception e) {
            e.printStackTrace();
            return new ResponseEntity<String>("MOD_ERR", HttpStatus.BAD_REQUEST);
        }
    }

❗️ Controller 총 정리

package kr.ac.jipark09.Controller;

import kr.ac.jipark09.domain.CommentDto;
import kr.ac.jipark09.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 java.util.List;

@RestController // = @Controller + @ResponseBody
public class CommentController {
    @Autowired
    CommentService commentService;

    // 게시물 번호를 받으면 그 게시물에 달린 모든 댓글을 반환하는 메서드
    @RequestMapping("/comments") // comments?bno=1080
    public ResponseEntity<List<CommentDto>> list(Integer bno) {
        List<CommentDto> list = null;

        try {
             list = commentService.getList(bno);
             return new ResponseEntity<List<CommentDto>>(list, HttpStatus.OK); // 200
        } catch (Exception e) {
           e.printStackTrace();
           // 사용자가 잘못 요청해서 에러나니까 400번대를 날린다.
           return new ResponseEntity<List<CommentDto>>(HttpStatus.BAD_REQUEST); // 400
        }
    }

    // 댓글 삭제하는 메서드
    // 맵핑된 url(cno)을 읽어올 때는 @PathVariable을 붙여줘야 한다.
    @DeleteMapping("/comments/{cno}") // comments/1?bno=1 <-- 삭제할 댓글 번호
    public ResponseEntity<String> remove(HttpSession session, @PathVariable Integer cno, Integer bno) {
        String commenter = "jipark09";
//                (String)session.getAttribute("id");
        try {
            int rowCnt = commentService.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);
        }
    }

    // 댓글 저장하는 메서드
    @PostMapping("/comments") // comments?bno=1 POST
    public ResponseEntity<String> write(@RequestBody CommentDto dto, Integer bno, HttpSession session) {
//        String commenter = (String) session.getAttribute("id");
        String commenter = "jipark09";
        dto.setCommenter(commenter);
        dto.setBno(bno);
        System.out.println("dto=" + dto);

        try {
            int result = commentService.write(dto);

            if(result != 1) {
                throw new Exception("Write Failed");
            }

            return new ResponseEntity<>("WRT_OK", HttpStatus.OK);
        } catch (Exception e) {
            e.printStackTrace();
            return new ResponseEntity<>("WRT_ERR", HttpStatus.BAD_REQUEST);
        }
    }

    // 댓글을 수정하는 메서드
    @PatchMapping("/comments/{cno}") // 수정할 댓글 번호를 적어준다.
    public ResponseEntity<String> modify(@PathVariable Integer cno, @RequestBody CommentDto dto) {
//        String commenter = (String) session.getAttribute("id");
        String commenter = "jipark09";
        dto.setCommenter(commenter);
        dto.setCno(cno);

        try {
            int result = commentService.modify(dto);

            if(result != 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);
        }
    }
}
  • @ResponseBody를 class에 달아주면 메서드에 일일이 안붙여줘도 된다.
    @ResponseBody대신, class에 @RestController을 달아줘도 된다.

  • ⭐️ @RestController = @Controller + @ResponseBody

✏️ @RestController

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Controller
@ResponseBody
public @interface RestController {

	/**
	 * The value may indicate a suggestion for a logical component name,
	 * to be turned into a Spring bean in case of an autodetected component.
	 * @return the suggested component name, if any (or empty String otherwise)
	 * @since 4.0.1
	 */
	@AliasFor(annotation = Controller.class)
	String value() default "";

}
  • @Controller와 @ResponseBody가 합쳐져 있는 것을 볼 수 있다.

Reference
: https://fastcampus.co.kr/dev_academy_nks

profile
Fill in my own colorful colors🎨

0개의 댓글