68. RestAPI 컨트롤러 요청과 응답

박선규's avatar
Apr 01, 2024
68. RestAPI 컨트롤러 요청과 응답
📌
1.요청은 JSON 으로 통일, 응답도 JSON 으로 통일 2.POST, PUT 요청은 추가된 ROW 혹은 수정된 ROW 를 응답해줘야 한다. 그래야 PK 를 알 수 있다. 인서트 업데이트된 데이터가 있어야 프론트가 알 수 있다. 3. 화면에 필요한 데이터만 전달해야 한다. 그래서 DTO 가 필요하다. → DTO 를 만드는 책임은 서비스가 갖는다. 서비스에서 DTO 를 만들면 커넥션 시간이 줄어든다.
 

1. 요청 BODY 수정

💡
요청 BODY에 @RequestBody 어노테이션 붙이기 Post 와 Put 매핑에 붙인다.
@PutMapping("/api/users/{id}") public String update(@RequestBody UserRequest.UpdateDTO requestDTO){ User sessionUser = (User) session.getAttribute("sessionUser"); User user = userService.회원조회(sessionUser.getId(),requestDTO); session.setAttribute("sessionUser",user); return "redirect:/"; }

2. 응답 BODY 수정

💡
응답은 ReposnseEntity.ok(new ApiUtil()) 를 사용한다.
@RestController public class UserController { private final UserService userService; private final HttpSession session; @PutMapping("/api/users/{id}") //회원 수정은 세션 id 를 받기 때문에 주소에 id가 필요없다. 하지만 프론트 입장에선 필요하다. 또 관리자가 수정을 해야한다면 구분이 필요하다. public ResponseEntity<?> update(@RequestBody @PathVariable Integer id, UserRequest.UpdateDTO requestDTO){ User sessionUser = (User) session.getAttribute("sessionUser"); User newSessionUser = userService.회원조회(sessionUser.getId(),requestDTO); session.setAttribute("sessionUser",newSessionUser); return ResponseEntity.ok(new ApiUtil(newSessionUser)); } }

UserController

package shop.mtcoding.blog.user; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpSession; import lombok.RequiredArgsConstructor; import org.springframework.dao.DataIntegrityViolationException; import org.springframework.dao.EmptyResultDataAccessException; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; import shop.mtcoding.blog._core.errors.exception.Exception400; import shop.mtcoding.blog._core.errors.exception.Exception401; import shop.mtcoding.blog._core.utils.ApiUtil; @RequiredArgsConstructor @RestController public class UserController { private final UserService userService; private final HttpSession session; // TODO: 회원정보 조회 API 필요 -> @GetMapping("/api/users/{id}") @GetMapping("/api/users/{id}") public ResponseEntity<?> userinfo(@PathVariable Integer id){ User user = userService.회원조회(id); return ResponseEntity.ok(new ApiUtil(user)); } @PutMapping("/api/users/{id}") public ResponseEntity<?> update(@PathVariable Integer id, @RequestBody UserRequest.UpdateDTO reqDTO) { User sessionUser = (User) session.getAttribute("sessionUser"); User newSessionUser = userService.회원수정(sessionUser.getId(), reqDTO); session.setAttribute("sessionUser", newSessionUser); return ResponseEntity.ok(new ApiUtil(newSessionUser)); } @PostMapping("/join") public ResponseEntity<?> join(@RequestBody UserRequest.JoinDTO reqDTO) { User user = userService.회원가입(reqDTO); return ResponseEntity.ok(new ApiUtil(user)); } @PostMapping("/login") public ResponseEntity<?> login(@RequestBody UserRequest.LoginDTO reqDTO) { User sessionUser = userService.로그인(reqDTO); session.setAttribute("sessionUser", sessionUser); return ResponseEntity.ok(new ApiUtil(null)); } @GetMapping("/logout") public ResponseEntity<?> logout() { session.invalidate(); return ResponseEntity.ok(new ApiUtil(null)); } }
 

UserService

@Transactional public User 회원가입(UserRequest.JoinDTO reqDTO){ // ssar // 1. 유저네임 중복검사 (서비스 체크) - DB연결이 필요한 것은 Controller에서 작성할 수 없다. Optional<User> userOP = userJPARepository.findByUsername(reqDTO.getUsername()); if(userOP.isPresent()){ throw new Exception400("중복된 유저네임입니다"); } // 2. 회원가입 return userJPARepository.save(reqDTO.toEntity()); }

BoardController

package shop.mtcoding.blog.board; import jakarta.servlet.http.HttpSession; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import shop.mtcoding.blog._core.utils.ApiUtil; import shop.mtcoding.blog.user.User; import java.util.List; @RequiredArgsConstructor // final이 붙은 친구들의 생성자를 만들어줘 @RestController // new BoardController(IoC에서 BoardRepository를 찾아서 주입) -> IoC 컨테이너 등록 public class BoardController { private final BoardService boardService; private final HttpSession session; // TODO: 글목록조회 API 필요 -> @GetMapping("/") @GetMapping("/") public ResponseEntity<?> main(){ List<Board> boardList = boardService.글목록조회(); return ResponseEntity.ok(new ApiUtil(boardList)); } // TODO: 글상세보기 API 필요 -> @GetMapping("/api/boards/{id}/detail") @GetMapping("/api/boards/{id}/detail") public ResponseEntity<?> detail(@PathVariable Integer id){ User sessionUser = (User) session.getAttribute("sessionUser"); Board board = boardService.글상세보기(id, sessionUser); return ResponseEntity.ok(new ApiUtil(board)); } // TODO: 글조회 API 필요 -> @GetMapping("/api/boards/{id}") @GetMapping("/api/boards/{id}") public ResponseEntity<?> findOne(@PathVariable Integer id){ Board board = boardService.글조회(id); return ResponseEntity.ok(new ApiUtil(board)); } @PostMapping("/api/boards") public ResponseEntity<?> save(@RequestBody BoardRequest.SaveDTO reqDTO) { User sessionUser = (User) session.getAttribute("sessionUser"); Board board = boardService.글쓰기(reqDTO, sessionUser); return ResponseEntity.ok(new ApiUtil(board)); } @PutMapping("/api/boards/{id}") public ResponseEntity<?> update(@PathVariable Integer id, @RequestBody BoardRequest.UpdateDTO reqDTO) { User sessionUser = (User) session.getAttribute("sessionUser"); Board board = boardService.글수정(id, sessionUser.getId(), reqDTO); return ResponseEntity.ok(new ApiUtil(board)); } @DeleteMapping("/api/boards/{id}") public ResponseEntity<?> delete(@PathVariable Integer id) { User sessionUser = (User) session.getAttribute("sessionUser"); boardService.글삭제(id, sessionUser.getId()); return ResponseEntity.ok(new ApiUtil(null)); } }
 

BoardService

@Transactional public Board 글수정(int boardId, int sessionUserId, BoardRequest.UpdateDTO reqDTO){ // 1. 조회 및 예외처리 Board board = boardJPARepository.findById(boardId) .orElseThrow(() -> new Exception404("게시글을 찾을 수 없습니다")); // 2. 권한 처리 if(sessionUserId != board.getUser().getId()){ throw new Exception403("게시글을 수정할 권한이 없습니다"); } // 3. 글수정 board.setTitle(reqDTO.getTitle()); board.setContent(reqDTO.getContent()); return board; } // 더티체킹
 
notion image

ReplyController

package shop.mtcoding.blog.reply; import jakarta.servlet.http.HttpSession; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; import shop.mtcoding.blog._core.utils.ApiUtil; import shop.mtcoding.blog.user.User; @RequiredArgsConstructor @RestController public class ReplyController { private final ReplyService replyService; private final HttpSession session; @DeleteMapping("/api/replies/{id}") public ResponseEntity<?> delete(@PathVariable Integer id){ User sessionUser = (User) session.getAttribute("sessionUser"); replyService.댓글삭제(id, sessionUser.getId()); return ResponseEntity.ok(new ApiUtil(null)); } @PostMapping("/api/replies") public ResponseEntity<?> save(@RequestBody ReplyRequest.SaveDTO reqDTO){ User sessionUser = (User) session.getAttribute("sessionUser"); Reply reply = replyService.댓글쓰기(reqDTO, sessionUser); return ResponseEntity.ok(new ApiUtil(reply)); } }
 
 

ReplyService

@Transactional public Reply 댓글쓰기(ReplyRequest.SaveDTO reqDTO, User sessionUser) { Board board = boardJPARepository.findById(reqDTO.getBoardId()) .orElseThrow(() -> new Exception404("없는 게시글에 댓글을 작성할 수 없어요")); Reply reply = reqDTO.toEntity(sessionUser, board); return replyJPARepository.save(reply); }
 
Share article

p4rksk