Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feat/6] 게시글 API 구현 #18

Merged
merged 9 commits into from
Jul 4, 2024
2 changes: 2 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.0.2' // swagger
implementation 'org.springframework.boot:spring-boot-starter-validation' // validation
implementation 'com.github.gavlyukovskiy:p6spy-spring-boot-starter:1.9.0' // 쿼리문에 들어가는 파라미터 로그로 보여주기

compileOnly 'org.projectlombok:lombok'
runtimeOnly 'com.mysql:mysql-connector-j'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,15 @@ public enum ErrorStatus implements BaseErrorCode {
ARTICLE_NOT_FOUND(HttpStatus.NOT_FOUND, "ARTICLE4001", "게시글이 없습니다."),

// 테스트
TEMP_EXCEPTION(HttpStatus.BAD_REQUEST, "TEMP4001", "이거는 테스트");
TEMP_EXCEPTION(HttpStatus.BAD_REQUEST, "TEMP4001", "이거는 테스트"),

// DREAM
DREAM_NOT_FOUND(HttpStatus.NOT_FOUND, "DREAM4001", "해당 꿈 기록을 찾을 수 없습니다."),

// DREAM
POST_NOT_FOUND(HttpStatus.NOT_FOUND, "POST4001", "해당 게시글을 찾을 수 없습니다.")

;



Expand Down
66 changes: 66 additions & 0 deletions src/main/java/com/umc/dream/controller/PostRestController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package com.umc.dream.controller;


import com.umc.dream.apiPayload.ApiResponse;
import com.umc.dream.converter.PostConverter;
import com.umc.dream.domain.Comment;
import com.umc.dream.domain.Post;
import com.umc.dream.dto.PostRequestDTO;
import com.umc.dream.dto.PostResponseDTO;
import com.umc.dream.service.PostCommandService;
import com.umc.dream.service.PostQueryService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.web.bind.annotation.*;

@RestController
@RequiredArgsConstructor
@RequestMapping("/posts")
public class PostRestController {

private final PostCommandService postCommandService;
private final PostQueryService postQueryService;

@PostMapping("/community")
@Operation(summary = "커뮤니티 게시글 등록 API",description = "친구, 전문가와 공유하는 게시글이 아닌 커뮤니티에 전체 공유되는 게시글을 저장하는 API 입니다")
public ApiResponse<PostResponseDTO.CreateCommunityPostDTO> createCommunityPost(@RequestBody @Valid PostRequestDTO.CreateCommunityDTO request) {
Post savedCommunityPost = postCommandService.createCommunityPost(request);
return ApiResponse.onSuccess(PostConverter.toCreateCommunityPostResultDTO(savedCommunityPost));
}

@GetMapping("/community")
@Operation(summary = "커뮤니티 게시글 전체 조회 API", description = "query string으로 page를 받고, 한 페이지당 게시물 10개 입니다. 페이지는 0부터 입력해주세요.")
@Parameters({
@Parameter(name = "page", description = "페이지 번호, 0이 1 페이지 입니다."),
})
public ApiResponse<PostResponseDTO.PostPreviewListDTO> getCommunityPostList(@RequestParam(name = "page") Integer page) {
Page<Post> communityPostList = postQueryService.getCommunityPostList(page);
return ApiResponse.onSuccess(PostConverter.toPostPreviewListDTO(communityPostList));
}

@GetMapping("/{postId}")
@Operation(summary = "특정 게시글 상세 조회 API", description = "postId를 받아 게시글의 세부 내용과 댓글을 조회합니다.")
public ApiResponse<PostResponseDTO.PostDetailDTO> getPostDetail(@PathVariable Long postId) {
Post postDetail = postQueryService.getPostDetail(postId);
return ApiResponse.onSuccess(PostConverter.toPostDetailDTO(postDetail));
}

@PostMapping("/{postId}/comments")
@Operation(summary = "게시글 댓글 작성 API", description = "게시글의 id, 작성자의 id, 댓글 내용을 받아 댓글을 생성하는 API입니다.")
public ApiResponse<PostResponseDTO.CreateCommentDTO> createComment(@PathVariable Long postId, @RequestBody @Valid PostRequestDTO.CreateCommentDTO dto) {
Comment newComment = postCommandService.createComment(postId, dto);
return ApiResponse.onSuccess(PostConverter.toCreateCommentResponseDTO(newComment));
}

@DeleteMapping("/{postId}")
@Operation(summary = "게시글 삭제 API", description = "게시글의 id를 받아 게시글을 삭제하는 API입니다.")
public ApiResponse deletePost(@PathVariable Long postId) {
postCommandService.deletePost(postId);
return ApiResponse.onSuccess("게시글 삭제 성공!");
}

}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.umc.dream;
package com.umc.dream.controller;

import io.swagger.v3.oas.annotations.Operation;
import org.springframework.web.bind.annotation.GetMapping;
Expand Down
101 changes: 101 additions & 0 deletions src/main/java/com/umc/dream/converter/PostConverter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
package com.umc.dream.converter;

import com.umc.dream.domain.Comment;
import com.umc.dream.domain.Dream;
import com.umc.dream.domain.Post;
import com.umc.dream.domain.User;
import com.umc.dream.dto.PostRequestDTO;
import com.umc.dream.dto.PostResponseDTO;
import org.springframework.data.domain.Page;

import java.time.LocalDate;
import java.util.List;
import java.util.stream.Collectors;

public class PostConverter {

public static PostResponseDTO.CreateCommunityPostDTO toCreateCommunityPostResultDTO(Post post) {
return PostResponseDTO.CreateCommunityPostDTO
.builder()
.postId(post.getId())
.createdAt(post.getCreatedDate())
.build();
}

public static Post toPost(PostRequestDTO.CreateCommunityDTO request, User user, Dream dream) {
return Post.builder()
.writer(user)
.dream(dream)
.title(request.getTitle())
.content(request.getContent())
.type(request.getType())
.build();
}

public static PostResponseDTO.PostPreviewDTO toPostPreviewDTO(Post post) {
return PostResponseDTO.PostPreviewDTO
.builder()
.postId(post.getId())
.title(post.getTitle())
.content(post.getContent()) // 미리보기이므로 한 15자로 제한
.writer(post.getWriter().getName())
.createdAt(LocalDate.from(post.getCreatedDate()))
.build();
}

public static PostResponseDTO.PostPreviewListDTO toPostPreviewListDTO(Page<Post> communityPostList) {
List<PostResponseDTO.PostPreviewDTO> communityPostDTOList = communityPostList.stream()
.map(PostConverter::toPostPreviewDTO)
.collect(Collectors.toList());

return PostResponseDTO.PostPreviewListDTO.builder()
.isLast(communityPostList.isLast())
.isFirst(communityPostList.isFirst())
.totalPage(communityPostList.getTotalPages())
.totalElements(communityPostList.getTotalElements())
.listSize(communityPostDTOList.size())
.communityPostDTOList(communityPostDTOList)
.build();
}

public static PostResponseDTO.CommentDetailDTO toCommentDetailDTO(Comment comment) {
return PostResponseDTO.CommentDetailDTO
.builder()
.commentId(comment.getId())
.writer(comment.getUser().getName())
.content(comment.getReply())
.build();
}

public static PostResponseDTO.PostDetailDTO toPostDetailDTO(Post post) {

List<PostResponseDTO.CommentDetailDTO> commentDetailDTOList = post.getCommentList().stream()
.map(PostConverter::toCommentDetailDTO)
.collect(Collectors.toList());

return PostResponseDTO.PostDetailDTO
.builder()
.postId(post.getId())
.writer(post.getWriter().getName())
.title(post.getTitle())
.content(post.getContent())
.createdAt(LocalDate.from(post.getCreatedDate()))
.commentDetailDTOList(commentDetailDTOList)
.build();
}

public static Comment toComment(PostRequestDTO.CreateCommentDTO dto, User user, Post post) {
return Comment.builder()
.post(post)
.user(user)
.reply(dto.getReply())
.build();
}

public static PostResponseDTO.CreateCommentDTO toCreateCommentResponseDTO(Comment comment) {
return PostResponseDTO.CreateCommentDTO.builder()
.commentId(comment.getId())
.createdAt(comment.getCreatedDate())
.build();
}
}
1 change: 1 addition & 0 deletions src/main/java/com/umc/dream/domain/People.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.umc.dream.domain.common.BaseEntity;
import jakarta.persistence.*;

import lombok.*;

@Entity
Expand Down
31 changes: 31 additions & 0 deletions src/main/java/com/umc/dream/dto/PostRequestDTO.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.umc.dream.dto;

import com.umc.dream.domain.enums.Type;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.Getter;

public class PostRequestDTO {

@Getter
public static class CreateCommunityDTO {
@NotNull(message = "작성자의 pk를 입력해주세요.")
private Long userId;
private Long dreamId;
@NotBlank(message = "글의 제목은 필수입니다.")
private String title;
@NotBlank(message = "글의 내용은 필수입니다.")
private String content;
@NotBlank(message = "게시글의 유형은 필수입니다.")
private Type type;

}

@Getter
public static class CreateCommentDTO {
@NotNull(message = "작성자의 pk를 입력해주세요.")
private Long writerId;
@NotBlank(message = "댓글 내용은 필수입니다.")
private String reply;
}
}
79 changes: 79 additions & 0 deletions src/main/java/com/umc/dream/dto/PostResponseDTO.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package com.umc.dream.dto;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;

public class PostResponseDTO {

@Builder
@Getter
@NoArgsConstructor
@AllArgsConstructor
public static class CreateCommunityPostDTO {
Long postId;
LocalDateTime createdAt;
}

@Builder
@Getter
@NoArgsConstructor
@AllArgsConstructor
public static class CreateCommentDTO {
Long commentId;
LocalDateTime createdAt;
}

@Builder
@Getter
@NoArgsConstructor
@AllArgsConstructor
public static class PostPreviewListDTO {
List<PostPreviewDTO> communityPostDTOList;
Integer listSize;
Integer totalPage;
Long totalElements;
Boolean isFirst;
Boolean isLast;
}

@Builder
@Getter
@NoArgsConstructor
@AllArgsConstructor
public static class PostPreviewDTO {
Long postId;
String writer;
String title;
String content;
LocalDate createdAt;
}

@Builder
@Getter
@NoArgsConstructor
@AllArgsConstructor
public static class PostDetailDTO {
Long postId;
String writer;
String title;
String content;
LocalDate createdAt;
List<CommentDetailDTO> commentDetailDTOList;
}

@Builder
@Getter
@NoArgsConstructor
@AllArgsConstructor
public static class CommentDetailDTO {
private Long commentId;
private String writer;
private String content;
}
}
7 changes: 7 additions & 0 deletions src/main/java/com/umc/dream/repository/CommentRepository.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.umc.dream.repository;

import com.umc.dream.domain.Comment;
import org.springframework.data.jpa.repository.JpaRepository;

public interface CommentRepository extends JpaRepository<Comment, Long> {
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.umc.dream.repository;

import com.umc.dream.domain.Dream;

import com.umc.dream.domain.User;
import org.springframework.data.jpa.repository.JpaRepository;

Expand Down
7 changes: 7 additions & 0 deletions src/main/java/com/umc/dream/repository/PostRepository.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,17 @@

import com.umc.dream.domain.Post;
import com.umc.dream.domain.enums.Type;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.jpa.repository.Query;

import java.util.List;

public interface PostRepository extends JpaRepository<Post, Long> {
List<Post> findAllByWriterIdAndType(Long userId, Type type);

@Query("select p from Post p join fetch p.writer where p.type = :type")
Page<Post> findAllByTypeJoinFetch(Type type, PageRequest pageRequest);
}
11 changes: 11 additions & 0 deletions src/main/java/com/umc/dream/service/PostCommandService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.umc.dream.service;

import com.umc.dream.domain.Comment;
import com.umc.dream.domain.Post;
import com.umc.dream.dto.PostRequestDTO;

public interface PostCommandService {
Post createCommunityPost(PostRequestDTO.CreateCommunityDTO request);
Comment createComment(Long postId, PostRequestDTO.CreateCommentDTO request);
void deletePost(Long postId);
}
Loading
Loading