게시글 단건 조회 - Get
- postId로 findById
- RequestBody - null
@GetMapping("/{postId}")
public ResponseEntity<SuccessResponse<?>> getPostById(
@PathVariable Long postId) {
// 서비스 계층에 위임
PostDetailRes postDetailRes = postService.getById(postId);
// 반환
return ResponseEntity
.status(HttpStatus.OK)
.body(SuccessResponse.ok(postDetailRes));
}
(1) URL이 /api/post/{postId}이므로, Mapping
(2) findById로 찾은 값을 PostDetailRes에 그대로 저장
(3) 그 값을 그대로 반환 (상태나 반환이 성공적으로 이루어짐)
// API 명세상, data를 전부 반환해야 할 때 사용할 Record
public record PostDetailRes(
Long id,
String title,
String content,
String username,
String password,
PostState state,
LocalDateTime createdAt,
LocalDateTime updatedAt
) {
}
@Override
public PostDetailRes getById(Long postId) {
// 1. postId에 해당하는 Post - DB에서 조회
Post post = postRepository.findById(postId)
// 404 - postId에
.orElseThrow(PostNotFoundException::new);
// 2. PostDetailRes 반환
return new PostDetailRes(
post.getId(),
post.getTitle(),
post.getContent(),
post.getUsername(),
post.getPassword(),
post.getState(),
post.getCreatedAt(),
post.getUpdatedAt()
);
}
게시글 전체 조회 - Get
- findAll로 전체를 조회한다.
- stream 같은 반복문으로 전체 게시글을 List화
@GetMapping
public ResponseEntity<SuccessResponse<?>> getAllPosts() {
// 서비스 로직
PostSummaryRes postSummaryRes = postService.getAll();
// 반환
return ResponseEntity
.status(HttpStatus.OK)
.body(SuccessResponse.ok(postSummaryRes));
}
ResponseEntity - 클라이언트 요청에 의해 서브되는 데이터(= 응답 데이터)
SuccessResponse - API 명세서 형식을 따르는 상태코드 등의 정보 포함 (개발자가 직접 짜야 하는 것 같다.)
// 배려해주셔서 for문으로 작성하셨다. stream 사용법 숙지 요망
public record PostSummaryRes(
List<PostSummary> postSummaryList
) {
public record PostSummary(
Long id,
String title,
String username,
LocalDateTime createdAt
) {
}
}
@Override
public PostSummaryRes getAll() {
// 1. DB 에서 모든 Post 조회 (postRepository)
List<Post> posts = postRepository.findAll();
// 2. posts -> PostSummaryRes 변환
List<PostSummary> postSummaryList = new ArrayList<>();
for(Post post : posts) {
PostSummary postSummary = new PostSummary(
post.getId(),
post.getTitle(),
post.getUsername(),
post.getCreatedAt()
);
postSummaryList.add(postSummary);
}
// 3. 반환
return new PostSummaryRes(postSummaryList);
}
게시글 수정 - Put
- 비밀번호가 일치해야 수정할 수 있다.
- 제목과 내용만 수정한다.
@PutMapping("/{postId}")
public ResponseEntity<SuccessResponse<?>> modifyPost(
@PathVariable Long postId,
@RequestBody ModifyPostReq modifyPostReq
) {
// 서비스
PostDetailRes postDetailRes = postService.modifyOne(postId, modifyPostReq);
// 반환
return ResponseEntity
.status(HttpStatus.OK)
.body(SuccessResponse.ok(postDetailRes));
}
@Getter
@NoArgsConstructor
public class ModifyPostReq {
private String title;
private String content;
private String password;
}
@Transactional
@Override
public PostDetailRes modifyOne(Long postId, ModifyPostReq modifyPostReq) {
// 1. DB 에서 postId로 Post 찾기
Post foundPost = postRepository.findById(postId)
// 404 - 게시글 없음
.orElseThrow(PostNotFoundException::new);
// 2. 비밀번호 검증
// 403 - 비밀번호 불일치
if(!foundPost.getPassword().equals(modifyPostReq.getPassword())) {
throw new InvalidPasswordException();
}
// 3. post 수정
foundPost.modify(modifyPostReq.getTitle(), modifyPostReq.getContent());
// PostDetailRes 반환
return new PostDetailRes(
foundPost.getId(),
foundPost.getTitle(),
foundPost.getContent(),
foundPost.getUsername(),
foundPost.getPassword(),
foundPost.getState(),
foundPost.getCreatedAt(),
foundPost.getUpdatedAt()
);
}
게시글 삭제 - Delete
- findById에 의해 delete 되어야 함
@DeleteMapping("/{postId}")
public ResponseEntity<SuccessResponse<?>> deletePost(
@PathVariable Long postId,
@RequestBody DeletePostReq deletePostReq) {
// 서비스 로직
postService.deleteOne(postId, deletePostReq);
// 반환
return ResponseEntity
.status(HttpStatus.OK)
.body(SuccessResponse.empty());
}
@Transactional
@Override
public void deleteOne(Long postId, DeletePostReq deletePostReq) {
// 1. 게시글 존재 확인
Post post = postRepository.findById(postId)
// 404 - 게시글 존재하지 않음
.orElseThrow(PostNotFoundException::new);
// 2. 비밀번호 검증
if(!post.getPassword().equals(deletePostReq.getPassword())) {
// 403 - 비밀번호 불일치
throw new InvalidPasswordException();
}
// 3. 삭제
postRepository.delete(post);
}
save, add, delete 같은 명령어를 쓸 수 있다.
귯귯