From 3a905caf9386ad3d08edda35c37e5d03330a8bd1 Mon Sep 17 00:00:00 2001 From: tmddus2 Date: Tue, 4 Jun 2024 22:53:53 +0900 Subject: [PATCH 01/11] =?UTF-8?q?chore:=20gradle-wrapper.properties=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- blog/gradle/wrapper/gradle-wrapper.properties | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 blog/gradle/wrapper/gradle-wrapper.properties diff --git a/blog/gradle/wrapper/gradle-wrapper.properties b/blog/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..b82aa23 --- /dev/null +++ b/blog/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,7 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip +networkTimeout=10000 +validateDistributionUrl=true +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists From 6931a84cb285b1de38fa62f7817d50c244945fb3 Mon Sep 17 00:00:00 2001 From: seoyeon0201 Date: Thu, 6 Jun 2024 18:30:15 +0900 Subject: [PATCH 02/11] =?UTF-8?q?feat:=20=EA=B2=8C=EC=8B=9C=EA=B8=80=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../blog/posts/controller/PostController.java | 10 +++++++++- .../cloudclub/blog/posts/entity/Post.java | 20 +++++++++++-------- .../blog/posts/service/PostService.java | 13 ++++++++++-- 3 files changed, 32 insertions(+), 11 deletions(-) diff --git a/blog/src/main/java/cloudclub/blog/posts/controller/PostController.java b/blog/src/main/java/cloudclub/blog/posts/controller/PostController.java index ac00b56..1bf960a 100644 --- a/blog/src/main/java/cloudclub/blog/posts/controller/PostController.java +++ b/blog/src/main/java/cloudclub/blog/posts/controller/PostController.java @@ -1,7 +1,9 @@ package cloudclub.blog.posts.controller; +import cloudclub.blog.posts.dto.PostDto; import cloudclub.blog.posts.dto.PostRequestsDto; import cloudclub.blog.posts.config.ResultMessage; +import cloudclub.blog.posts.entity.Post; import cloudclub.blog.posts.service.PostService; import lombok.RequiredArgsConstructor; import org.apache.coyote.Response; @@ -27,7 +29,13 @@ public ResponseEntity getPost(@RequestParam Long postId, @Request @GetMapping("/MyBlog.io/@{userId}/{slug}") public ResponseEntity getPost(@PathVariable Long userId, @PathVariable String slug) { - return postService.getPostByUrl(userId, slug); + return postService.getPostDtoByUrl(userId, slug); + } + + @DeleteMapping("/MyBlog.io/@{userId}/{slug}") + public void deletePost(@PathVariable Long userId, @PathVariable String slug) { + Post post = postService.getPostByUrl(userId, slug); + postService.deletePost(post.getId()); } } diff --git a/blog/src/main/java/cloudclub/blog/posts/entity/Post.java b/blog/src/main/java/cloudclub/blog/posts/entity/Post.java index 32b6642..0a598e3 100644 --- a/blog/src/main/java/cloudclub/blog/posts/entity/Post.java +++ b/blog/src/main/java/cloudclub/blog/posts/entity/Post.java @@ -2,10 +2,12 @@ import com.fasterxml.jackson.annotation.JsonManagedReference; import jakarta.persistence.*; +import jakarta.persistence.CascadeType; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; +import org.hibernate.annotations.*; import org.springframework.web.ErrorResponse; import java.time.LocalDateTime; @@ -14,6 +16,8 @@ @Getter @NoArgsConstructor @Entity +@SQLDelete(sql = "UPDATE post SET del_yn=true WHERE id = ?") +@SQLRestriction("del_yn = false") public class Post extends BaseEntity{ @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @@ -41,6 +45,12 @@ public class Post extends BaseEntity{ @Column(name = "ogDescription") private String ogDescription; + @Column(name = "view_count") + private Long viewCount; + + @Column(name = "del_yn") + private Boolean delYn; + @OneToMany(mappedBy = "post", cascade = CascadeType.ALL, orphanRemoval = true) @JsonManagedReference private List postHashtags; @@ -51,15 +61,9 @@ public Post(String title, String contents, Long userId, String url) { this.contents = contents; this.userId = userId; this.url = url; + this.viewCount = 0L; + this.delYn = false; } -// //여기 아래로는 사용 X -// @Column(name = "view_count") -// private Long viewCount; -// -// @Column(name = "del_yn") -// private String delYn; - - } diff --git a/blog/src/main/java/cloudclub/blog/posts/service/PostService.java b/blog/src/main/java/cloudclub/blog/posts/service/PostService.java index 0134dfc..13d30ee 100644 --- a/blog/src/main/java/cloudclub/blog/posts/service/PostService.java +++ b/blog/src/main/java/cloudclub/blog/posts/service/PostService.java @@ -118,7 +118,7 @@ public ResponseEntity getPost(Long postId, Long userId) { /* slug로 불러오기 */ - public ResponseEntity getPostByUrl(Long userId, String slug) { + public ResponseEntity getPostDtoByUrl(Long userId, String slug) { String url = "MyBlog.io/@"+userId+"/"+slug; Post post = postRepository.findByUrl(url).orElseThrow(() -> new CustomException("Post Not Found", "413")); @@ -132,7 +132,6 @@ public ResponseEntity getPostByUrl(Long userId, String slug) { .contents(post.getContents()) .tagNames(listTagName) .build(); - //response ResultMessage message = new ResultMessage(); HttpHeaders headers = new HttpHeaders(); @@ -145,4 +144,14 @@ public ResponseEntity getPostByUrl(Long userId, String slug) { return new ResponseEntity<>(message, headers, HttpStatus.OK); } + public Post getPostByUrl(Long userId, String slug) { + String url = "MyBlog.io/@"+userId+"/"+slug; + Post post = postRepository.findByUrl(url).orElseThrow(() -> new CustomException("Post Not Found", "413")); + return post; + } + + public void deletePost(Long postId) { + postRepository.deleteById(postId); + } + } From cb2edf60dee1e6a9c0c50a4f35062bd7439f8e16 Mon Sep 17 00:00:00 2001 From: seoyeon0201 Date: Thu, 6 Jun 2024 19:07:04 +0900 Subject: [PATCH 03/11] =?UTF-8?q?refactor:=20=EA=B2=8C=EC=8B=9C=EA=B8=80?= =?UTF-8?q?=20=EC=82=AD=EC=A0=9C=20=EA=B8=B0=EB=8A=A5=20=EC=BD=94=EB=93=9C?= =?UTF-8?q?=20=EB=A6=AC=ED=8C=A9=ED=86=A0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../blog/posts/controller/PostController.java | 8 ++++---- .../java/cloudclub/blog/posts/service/PostService.java | 10 ++++------ 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/blog/src/main/java/cloudclub/blog/posts/controller/PostController.java b/blog/src/main/java/cloudclub/blog/posts/controller/PostController.java index 1bf960a..2a7ab31 100644 --- a/blog/src/main/java/cloudclub/blog/posts/controller/PostController.java +++ b/blog/src/main/java/cloudclub/blog/posts/controller/PostController.java @@ -32,10 +32,10 @@ public ResponseEntity getPost(@PathVariable Long userId, @PathVar return postService.getPostDtoByUrl(userId, slug); } - @DeleteMapping("/MyBlog.io/@{userId}/{slug}") - public void deletePost(@PathVariable Long userId, @PathVariable String slug) { - Post post = postService.getPostByUrl(userId, slug); - postService.deletePost(post.getId()); + @DeleteMapping("/v1/post") + public void deletePost(@PathVariable Long postId) { + postService.deletePost(postId); } + } diff --git a/blog/src/main/java/cloudclub/blog/posts/service/PostService.java b/blog/src/main/java/cloudclub/blog/posts/service/PostService.java index 13d30ee..6de1ee4 100644 --- a/blog/src/main/java/cloudclub/blog/posts/service/PostService.java +++ b/blog/src/main/java/cloudclub/blog/posts/service/PostService.java @@ -144,14 +144,12 @@ public ResponseEntity getPostDtoByUrl(Long userId, String slug) { return new ResponseEntity<>(message, headers, HttpStatus.OK); } - public Post getPostByUrl(Long userId, String slug) { - String url = "MyBlog.io/@"+userId+"/"+slug; - Post post = postRepository.findByUrl(url).orElseThrow(() -> new CustomException("Post Not Found", "413")); - return post; - } - + /* + 게시글 삭제: delYn = True로 변경 + */ public void deletePost(Long postId) { postRepository.deleteById(postId); } + } From cb4999e5d7ab5fae5552fb7ce16e9f61f1afadac Mon Sep 17 00:00:00 2001 From: seoyeon0201 Date: Sat, 8 Jun 2024 17:18:44 +0900 Subject: [PATCH 04/11] =?UTF-8?q?feat:=20=EA=B2=8C=EC=8B=9C=EA=B8=80=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../blog/posts/controller/PostController.java | 5 ++- .../blog/posts/entity/BaseEntity.java | 1 + .../cloudclub/blog/posts/entity/Hashtag.java | 2 + .../cloudclub/blog/posts/entity/Post.java | 12 ++++-- .../blog/posts/service/HashtagService.java | 3 ++ .../blog/posts/service/PostService.java | 40 +++++++++++++++++++ 6 files changed, 58 insertions(+), 5 deletions(-) diff --git a/blog/src/main/java/cloudclub/blog/posts/controller/PostController.java b/blog/src/main/java/cloudclub/blog/posts/controller/PostController.java index 2a7ab31..d00a9b6 100644 --- a/blog/src/main/java/cloudclub/blog/posts/controller/PostController.java +++ b/blog/src/main/java/cloudclub/blog/posts/controller/PostController.java @@ -37,5 +37,8 @@ public void deletePost(@PathVariable Long postId) { postService.deletePost(postId); } - + @PatchMapping("/v1/post") + public ResponseEntity updatePost(@RequestParam Long postId, @RequestBody PostRequestsDto requestsDto) throws Exception { + return postService.update(postId, requestsDto); + } } diff --git a/blog/src/main/java/cloudclub/blog/posts/entity/BaseEntity.java b/blog/src/main/java/cloudclub/blog/posts/entity/BaseEntity.java index b48d18e..c0d4e05 100644 --- a/blog/src/main/java/cloudclub/blog/posts/entity/BaseEntity.java +++ b/blog/src/main/java/cloudclub/blog/posts/entity/BaseEntity.java @@ -4,6 +4,7 @@ import jakarta.persistence.*; import lombok.Getter; import lombok.NoArgsConstructor; +import lombok.Setter; import lombok.experimental.SuperBuilder; import org.springframework.data.annotation.CreatedDate; import org.springframework.data.annotation.LastModifiedDate; diff --git a/blog/src/main/java/cloudclub/blog/posts/entity/Hashtag.java b/blog/src/main/java/cloudclub/blog/posts/entity/Hashtag.java index 3f33e27..29bded8 100644 --- a/blog/src/main/java/cloudclub/blog/posts/entity/Hashtag.java +++ b/blog/src/main/java/cloudclub/blog/posts/entity/Hashtag.java @@ -25,4 +25,6 @@ public Hashtag(String tagName) { this.tagName = tagName; } + + } diff --git a/blog/src/main/java/cloudclub/blog/posts/entity/Post.java b/blog/src/main/java/cloudclub/blog/posts/entity/Post.java index 0a598e3..2904288 100644 --- a/blog/src/main/java/cloudclub/blog/posts/entity/Post.java +++ b/blog/src/main/java/cloudclub/blog/posts/entity/Post.java @@ -3,10 +3,7 @@ import com.fasterxml.jackson.annotation.JsonManagedReference; import jakarta.persistence.*; import jakarta.persistence.CascadeType; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; +import lombok.*; import org.hibernate.annotations.*; import org.springframework.web.ErrorResponse; @@ -65,5 +62,12 @@ public Post(String title, String contents, Long userId, String url) { this.delYn = false; } + public void updatePostTitle(String title) { + this.title = title; + } + + public void updatePostContents(String contents) { + this.contents = contents; + } } diff --git a/blog/src/main/java/cloudclub/blog/posts/service/HashtagService.java b/blog/src/main/java/cloudclub/blog/posts/service/HashtagService.java index a27aad8..d879460 100644 --- a/blog/src/main/java/cloudclub/blog/posts/service/HashtagService.java +++ b/blog/src/main/java/cloudclub/blog/posts/service/HashtagService.java @@ -1,5 +1,6 @@ package cloudclub.blog.posts.service; +import cloudclub.blog.posts.config.CustomException; import cloudclub.blog.posts.entity.Hashtag; import cloudclub.blog.posts.repository.HashtagRepository; import lombok.RequiredArgsConstructor; @@ -19,9 +20,11 @@ public Optional findByTagName(String tagName) { } public Hashtag save(String tagName) { + return hashtagRepository.save( Hashtag.builder() .tagName(tagName) .build()); } + } diff --git a/blog/src/main/java/cloudclub/blog/posts/service/PostService.java b/blog/src/main/java/cloudclub/blog/posts/service/PostService.java index 6de1ee4..de59017 100644 --- a/blog/src/main/java/cloudclub/blog/posts/service/PostService.java +++ b/blog/src/main/java/cloudclub/blog/posts/service/PostService.java @@ -6,6 +6,7 @@ import cloudclub.blog.posts.dto.PostRequestsDto; import cloudclub.blog.posts.config.ResultMessage; import cloudclub.blog.posts.dto.PostResponseDto; +import cloudclub.blog.posts.entity.Hashtag; import cloudclub.blog.posts.entity.Post; import cloudclub.blog.posts.entity.PostHashtag; import cloudclub.blog.posts.repository.PostHashtagRepository; @@ -34,6 +35,7 @@ public class PostService { private final PostHashtagService postHashtagService; private final PostRepository postRepository; private final HashtagRepository hashtagRepository; + private final HashtagService hashtagService; private final PostHashtagRepository postHashtagRepository; /* @@ -151,5 +153,43 @@ public void deletePost(Long postId) { postRepository.deleteById(postId); } + /* + 게시글 수정 + */ + public ResponseEntity update(Long postId, PostRequestsDto postRequestsDto) throws Exception { + Post post = postRepository.findById(postId).orElseThrow(() -> new CustomException("Post Not Found", "413")); + + if (postRequestsDto.title() != null) { + post.updatePostTitle(postRequestsDto.title()); + } + + if (postRequestsDto.contents() != null) { + post.updatePostContents(postRequestsDto.contents()); + } + postRepository.save(post); + + //해시태그 처리. 기존 해시태그 제거. 해시태그 cnt가 0인 경우 해당 hashtag 삭제 + if (postRequestsDto.tagNames().size() != 0) { + List postHashtags = postHashtagRepository.findByPost(post); + postHashtags.stream() + .forEach(postHashtag -> + postHashtagRepository.delete(postHashtag)); + + } + + //새로운 해시 태그 저장: postHashtag, hashtag + postHashtagService.saveHashtag(post, postRequestsDto.tagNames()); + + + //response + ResultMessage message = new ResultMessage(); + HttpHeaders headers = new HttpHeaders(); + + message.setStatus(StatusEnum.OK); + message.setData(postRequestsDto); + message.setMessage("Post Patch"); + + return new ResponseEntity<>(message, headers, HttpStatus.OK); + } } From 5ad79365c509b3352349c221b4eb1baf2ebd2a13 Mon Sep 17 00:00:00 2001 From: seoyeon0201 Date: Sat, 8 Jun 2024 18:38:02 +0900 Subject: [PATCH 05/11] =?UTF-8?q?feat:=20=EA=B2=8C=EC=8B=9C=EA=B8=80=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20=EC=8B=9C=20Hashtag=20=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/cloudclub/blog/posts/entity/Hashtag.java | 7 +++++++ .../blog/posts/service/HashtagService.java | 13 +++++++++++++ .../blog/posts/service/PostHashtagService.java | 4 ++++ .../cloudclub/blog/posts/service/PostService.java | 7 +++++-- 4 files changed, 29 insertions(+), 2 deletions(-) diff --git a/blog/src/main/java/cloudclub/blog/posts/entity/Hashtag.java b/blog/src/main/java/cloudclub/blog/posts/entity/Hashtag.java index 29bded8..20a726d 100644 --- a/blog/src/main/java/cloudclub/blog/posts/entity/Hashtag.java +++ b/blog/src/main/java/cloudclub/blog/posts/entity/Hashtag.java @@ -15,6 +15,7 @@ public class Hashtag extends BaseEntity { private String tagName; + private int cnt = 0; @OneToMany(mappedBy = "hashtag", cascade = CascadeType.ALL, orphanRemoval = true) @JsonManagedReference @@ -25,6 +26,12 @@ public Hashtag(String tagName) { this.tagName = tagName; } + public void increaseCnt() { + this.cnt += 1; + } + public void decreaseCnt() { + this.cnt -= 1; + } } diff --git a/blog/src/main/java/cloudclub/blog/posts/service/HashtagService.java b/blog/src/main/java/cloudclub/blog/posts/service/HashtagService.java index d879460..1800245 100644 --- a/blog/src/main/java/cloudclub/blog/posts/service/HashtagService.java +++ b/blog/src/main/java/cloudclub/blog/posts/service/HashtagService.java @@ -27,4 +27,17 @@ public Hashtag save(String tagName) { .build()); } + public void checkHashtag(Hashtag hashtag) { + int cnt = hashtag.getCnt(); + if (cnt == 0) { + hashtagRepository.delete(hashtag); + } + } + + public void removeHashtag(Hashtag hashtag) { + hashtag.decreaseCnt(); + hashtagRepository.save(hashtag); + checkHashtag(hashtag); + } + } diff --git a/blog/src/main/java/cloudclub/blog/posts/service/PostHashtagService.java b/blog/src/main/java/cloudclub/blog/posts/service/PostHashtagService.java index c47eb8e..4a790cc 100644 --- a/blog/src/main/java/cloudclub/blog/posts/service/PostHashtagService.java +++ b/blog/src/main/java/cloudclub/blog/posts/service/PostHashtagService.java @@ -3,6 +3,7 @@ import cloudclub.blog.posts.entity.Hashtag; import cloudclub.blog.posts.entity.Post; import cloudclub.blog.posts.entity.PostHashtag; +import cloudclub.blog.posts.repository.HashtagRepository; import cloudclub.blog.posts.repository.PostHashtagRepository; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -16,6 +17,7 @@ public class PostHashtagService { private final HashtagService hashtagService; private final PostHashtagRepository postHashtagRepository; + private final HashtagRepository hashtagRepository; public void saveHashtag(Post post, List tagNames) { //tag가 없는 경우 @@ -31,6 +33,8 @@ public void saveHashtag(Post post, List tagNames) { //hashtag와 post를 연결하는 DB table에 저장 private Long mapHashtagToPost(Post post, Hashtag hashtag) { + hashtag.increaseCnt(); + hashtagRepository.save(hashtag); return postHashtagRepository.save(new PostHashtag(post, hashtag)).getId(); } diff --git a/blog/src/main/java/cloudclub/blog/posts/service/PostService.java b/blog/src/main/java/cloudclub/blog/posts/service/PostService.java index de59017..f80d306 100644 --- a/blog/src/main/java/cloudclub/blog/posts/service/PostService.java +++ b/blog/src/main/java/cloudclub/blog/posts/service/PostService.java @@ -168,13 +168,16 @@ public ResponseEntity update(Long postId, PostRequestsDto postReq } postRepository.save(post); - //해시태그 처리. 기존 해시태그 제거. 해시태그 cnt가 0인 경우 해당 hashtag 삭제 + //해시태그 처리. 기존 해시태그 제거 if (postRequestsDto.tagNames().size() != 0) { List postHashtags = postHashtagRepository.findByPost(post); postHashtags.stream() .forEach(postHashtag -> - postHashtagRepository.delete(postHashtag)); + {postHashtagRepository.delete(postHashtag); + Hashtag hashtag = postHashtag.getHashtag(); + hashtagService.removeHashtag(hashtag); + }); } //새로운 해시 태그 저장: postHashtag, hashtag From 14eaf9b042fe05a37fc7d72e011c380ea64c52d1 Mon Sep 17 00:00:00 2001 From: seoyeon0201 Date: Sat, 8 Jun 2024 18:46:47 +0900 Subject: [PATCH 06/11] =?UTF-8?q?refactor:=20=EA=B2=8C=EC=8B=9C=EA=B8=80?= =?UTF-8?q?=20=EC=82=AD=EC=A0=9C=20=EC=BD=94=EB=93=9C=20=EB=A6=AC=ED=8C=A9?= =?UTF-8?q?=ED=86=A0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/cloudclub/blog/posts/controller/PostController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blog/src/main/java/cloudclub/blog/posts/controller/PostController.java b/blog/src/main/java/cloudclub/blog/posts/controller/PostController.java index d00a9b6..d490ace 100644 --- a/blog/src/main/java/cloudclub/blog/posts/controller/PostController.java +++ b/blog/src/main/java/cloudclub/blog/posts/controller/PostController.java @@ -32,7 +32,7 @@ public ResponseEntity getPost(@PathVariable Long userId, @PathVar return postService.getPostDtoByUrl(userId, slug); } - @DeleteMapping("/v1/post") + @DeleteMapping("/v1/post/{postId}") public void deletePost(@PathVariable Long postId) { postService.deletePost(postId); } From 7e5108a62f6123fe0ea126b2b34cdc787c3797af Mon Sep 17 00:00:00 2001 From: seoyeon0201 Date: Sat, 8 Jun 2024 18:51:07 +0900 Subject: [PATCH 07/11] =?UTF-8?q?refactor:=20=EA=B2=8C=EC=8B=9C=EA=B8=80?= =?UTF-8?q?=20=EC=82=AD=EC=A0=9C=20=EC=BD=94=EB=93=9C=20=EB=A6=AC=ED=8C=A9?= =?UTF-8?q?=ED=86=A0=EB=A7=81-URI=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/cloudclub/blog/posts/controller/PostController.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/blog/src/main/java/cloudclub/blog/posts/controller/PostController.java b/blog/src/main/java/cloudclub/blog/posts/controller/PostController.java index d490ace..4af46f2 100644 --- a/blog/src/main/java/cloudclub/blog/posts/controller/PostController.java +++ b/blog/src/main/java/cloudclub/blog/posts/controller/PostController.java @@ -32,8 +32,8 @@ public ResponseEntity getPost(@PathVariable Long userId, @PathVar return postService.getPostDtoByUrl(userId, slug); } - @DeleteMapping("/v1/post/{postId}") - public void deletePost(@PathVariable Long postId) { + @DeleteMapping("/v1/post") + public void deletePost(@RequestParam Long postId) { postService.deletePost(postId); } From 58b61f2fd44e2a9740ceca29b765b6788597e53f Mon Sep 17 00:00:00 2001 From: JIAH-LEA Date: Sat, 8 Jun 2024 23:56:17 +0900 Subject: [PATCH 08/11] =?UTF-8?q?feat:=EA=B3=B5=ED=86=B5=20response=20?= =?UTF-8?q?=EA=B3=B5=ED=86=B5=20=EC=9D=91=EB=8B=B5=20=ED=8F=AC=EB=A7=B7=20?= =?UTF-8?q?=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/enums/SuccessResponseStatus.java | 21 ++++ .../blog/common/model/ResponseDto.java | 20 +++ .../blog/common/model/ResponsePagingDto.java | 19 +++ .../blog/common/util/ResponseUtil.java | 118 ++++++++++++++++++ 4 files changed, 178 insertions(+) create mode 100644 blog/src/main/java/cloudclub/blog/common/enums/SuccessResponseStatus.java create mode 100644 blog/src/main/java/cloudclub/blog/common/model/ResponseDto.java create mode 100644 blog/src/main/java/cloudclub/blog/common/model/ResponsePagingDto.java create mode 100644 blog/src/main/java/cloudclub/blog/common/util/ResponseUtil.java diff --git a/blog/src/main/java/cloudclub/blog/common/enums/SuccessResponseStatus.java b/blog/src/main/java/cloudclub/blog/common/enums/SuccessResponseStatus.java new file mode 100644 index 0000000..fab07fa --- /dev/null +++ b/blog/src/main/java/cloudclub/blog/common/enums/SuccessResponseStatus.java @@ -0,0 +1,21 @@ +package cloudclub.blog.common.enums; + +import org.springframework.http.HttpStatus; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public enum SuccessResponseStatus { + + // S1XX : Server response success + SUCCESS(HttpStatus.OK ,"S101", "요청이 성공하였습니다."), + REDIRECT(HttpStatus.FOUND, "S102", "지정된 URL로 이동합니다."); + // S2XX : something + + private HttpStatus httpStatus; + private String statusCode; + private String message; + +} diff --git a/blog/src/main/java/cloudclub/blog/common/model/ResponseDto.java b/blog/src/main/java/cloudclub/blog/common/model/ResponseDto.java new file mode 100644 index 0000000..28bb656 --- /dev/null +++ b/blog/src/main/java/cloudclub/blog/common/model/ResponseDto.java @@ -0,0 +1,20 @@ +package cloudclub.blog.common.model; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ResponseDto { + + private boolean successOrNot; + private String statusCode; + private String message; + private T data; + +} + diff --git a/blog/src/main/java/cloudclub/blog/common/model/ResponsePagingDto.java b/blog/src/main/java/cloudclub/blog/common/model/ResponsePagingDto.java new file mode 100644 index 0000000..b2b1edd --- /dev/null +++ b/blog/src/main/java/cloudclub/blog/common/model/ResponsePagingDto.java @@ -0,0 +1,19 @@ +package cloudclub.blog.common.model; + +import java.net.http.HttpResponse; + +import lombok.Builder; + +@Builder +public class ResponsePagingDto { + private String statusCode; + + private String message; + + private Long page; + + private Integer size; + + private T data; + +} \ No newline at end of file diff --git a/blog/src/main/java/cloudclub/blog/common/util/ResponseUtil.java b/blog/src/main/java/cloudclub/blog/common/util/ResponseUtil.java new file mode 100644 index 0000000..ba00b58 --- /dev/null +++ b/blog/src/main/java/cloudclub/blog/common/util/ResponseUtil.java @@ -0,0 +1,118 @@ +package cloudclub.blog.common.util; + +import cloudclub.blog.common.enums.SuccessResponseStatus; +import cloudclub.blog.common.model.ResponseDto; +import cloudclub.blog.common.model.ResponsePagingDto; +import lombok.experimental.UtilityClass; + +import org.springframework.data.domain.Pageable; +import org.springframework.http.HttpHeaders; +import org.springframework.http.ResponseEntity; + +@UtilityClass +public class ResponseUtil { + + public static ResponseEntity> createSuccessResponse() { + ResponseDto dto = ResponseDto.builder() + .successOrNot(true) + .statusCode(SuccessResponseStatus.SUCCESS.getStatusCode()) + .message(SuccessResponseStatus.SUCCESS.getMessage()) + .data(null) + .build(); + return new ResponseEntity<>(dto, SuccessResponseStatus.SUCCESS.getHttpStatus()); + } + + public static ResponseEntity> createSuccessResponse(HttpHeaders httpHeaders) { + ResponseDto dto = ResponseDto.builder() + .successOrNot(true) + .statusCode(SuccessResponseStatus.SUCCESS.getStatusCode()) + .message(SuccessResponseStatus.SUCCESS.getMessage()) + .data(null) + .build(); + return new ResponseEntity<>(dto, httpHeaders, SuccessResponseStatus.SUCCESS.getHttpStatus()); + } + + public static ResponseEntity> createSuccessResponse(T data) { + ResponseDto dto = ResponseDto.builder() + .successOrNot(true) + .statusCode(SuccessResponseStatus.SUCCESS.getStatusCode()) + .message(SuccessResponseStatus.SUCCESS.getMessage()) + .data(data) + .build(); + return new ResponseEntity<>(dto, SuccessResponseStatus.SUCCESS.getHttpStatus()); + } + + public static ResponseEntity> createSuccessResponse(T data, HttpHeaders httpHeaders) { + ResponseDto dto = ResponseDto.builder() + .successOrNot(true) + .statusCode(SuccessResponseStatus.SUCCESS.getStatusCode()) + .message(SuccessResponseStatus.SUCCESS.getMessage()) + .data(data) + .build(); + return new ResponseEntity<>(dto, httpHeaders, SuccessResponseStatus.SUCCESS.getHttpStatus()); + } + + public static ResponseEntity> createSuccessResponse(SuccessResponseStatus status) { + ResponseDto dto = ResponseDto.builder() + .successOrNot(true) + .statusCode(status.getStatusCode()) + .message(status.getMessage()) + .data(null) + .build(); + return new ResponseEntity<>(dto, status.getHttpStatus()); + } + + public static ResponseEntity> createSuccessResponse(SuccessResponseStatus status, HttpHeaders httpHeaders) { + ResponseDto dto = ResponseDto.builder() + .successOrNot(true) + .statusCode(status.getStatusCode()) + .message(status.getMessage()) + .data(null) + .build(); + return new ResponseEntity<>(dto, httpHeaders, status.getHttpStatus()); + } + + public static ResponseEntity> createSuccessResponse(SuccessResponseStatus status, T data) { + ResponseDto dto = ResponseDto.builder() + .successOrNot(true) + .statusCode(status.getStatusCode()) + .message(status.getMessage()) + .data(data) + .build(); + return new ResponseEntity<>(dto, status.getHttpStatus()); + } + + public static ResponseEntity> createSuccessResponse(SuccessResponseStatus status, T data, HttpHeaders httpHeaders) { + ResponseDto dto = ResponseDto.builder() + .successOrNot(true) + .statusCode(status.getStatusCode()) + .message(status.getMessage()) + .data(data) + .build(); + return new ResponseEntity<>(dto, httpHeaders, status.getHttpStatus()); + } + + + + public static ResponseEntity> createSuccessResponse(T data, Pageable pageable) { + ResponsePagingDto dto = ResponsePagingDto.builder() + .statusCode(SuccessResponseStatus.SUCCESS.getStatusCode()) + .message(SuccessResponseStatus.SUCCESS.getMessage()) + .data(data) + .page(pageable.getOffset()) + .size(pageable.getPageSize()) + .build(); + return new ResponseEntity<>(dto, SuccessResponseStatus.SUCCESS.getHttpStatus()); + } + + public static ResponseEntity> createSuccessResponse(T data, HttpHeaders httpHeaders, Pageable pageable) { + ResponsePagingDto dto = ResponsePagingDto.builder() + .statusCode(SuccessResponseStatus.SUCCESS.getStatusCode()) + .message(SuccessResponseStatus.SUCCESS.getMessage()) + .data(data) + .page(pageable.getOffset()) + .size(pageable.getPageSize()) + .build(); + return new ResponseEntity<>(dto, httpHeaders, SuccessResponseStatus.SUCCESS.getHttpStatus()); + } +} From ec5178d37ee1003c789aedf62799c471b7834018 Mon Sep 17 00:00:00 2001 From: JIAH-LEA Date: Sat, 8 Jun 2024 23:57:04 +0900 Subject: [PATCH 09/11] =?UTF-8?q?feat:=EA=B3=B5=ED=86=B5=20Exception=20?= =?UTF-8?q?=EA=B3=B5=ED=86=B5=20=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../blog/common/enums/FailResponseStatus.java | 31 +++++++++++++++ .../exception/GlobalExceptionHandler.java | 38 +++++++++++++++++++ .../common/exception/RestApiException.java | 18 +++++++++ 3 files changed, 87 insertions(+) create mode 100644 blog/src/main/java/cloudclub/blog/common/enums/FailResponseStatus.java create mode 100644 blog/src/main/java/cloudclub/blog/common/exception/GlobalExceptionHandler.java create mode 100644 blog/src/main/java/cloudclub/blog/common/exception/RestApiException.java diff --git a/blog/src/main/java/cloudclub/blog/common/enums/FailResponseStatus.java b/blog/src/main/java/cloudclub/blog/common/enums/FailResponseStatus.java new file mode 100644 index 0000000..1abf92f --- /dev/null +++ b/blog/src/main/java/cloudclub/blog/common/enums/FailResponseStatus.java @@ -0,0 +1,31 @@ +package cloudclub.blog.common.enums; + +import org.springframework.http.HttpStatus; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public enum FailResponseStatus { + + // example + // HttpStatus 관련 논의 필요 + BAD_REQUEST("BAD_REQUEST", "E400", HttpStatus.BAD_REQUEST, "잘못된 요청입니다."), + INVALID_PARAM_ERROR("INVALID_PARAM_ERROR", "E401", HttpStatus.BAD_REQUEST, "파라미터가 유효하지 않습니다."), + INTERNAL_SERVER_ERROR("INTERNAL_SERVER_ERROR", + "E500", + HttpStatus.INTERNAL_SERVER_ERROR, + "내부 서버 오류입니다."); + + private final String statusName; + private final String statusCode; + private final HttpStatus httpStatusCode; + private final String message; + + + @Override + public String toString() { + return message; + } +} diff --git a/blog/src/main/java/cloudclub/blog/common/exception/GlobalExceptionHandler.java b/blog/src/main/java/cloudclub/blog/common/exception/GlobalExceptionHandler.java new file mode 100644 index 0000000..0af30ae --- /dev/null +++ b/blog/src/main/java/cloudclub/blog/common/exception/GlobalExceptionHandler.java @@ -0,0 +1,38 @@ +package cloudclub.blog.common.exception; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +import cloudclub.blog.common.enums.FailResponseStatus; +import cloudclub.blog.common.model.ResponseDto; + +@RestControllerAdvice +public class GlobalExceptionHandler { + @ExceptionHandler(RestApiException.class) + public ResponseEntity> handleCustomException(final RestApiException e) { + final FailResponseStatus errorCode = e.getFailResponseStatus(); + e.printStackTrace(); + ResponseDto dto = ResponseDto.builder() + .successOrNot(false) + .statusCode(errorCode.getStatusCode().toString()) + .message(errorCode.getMessage()) + .data(null) + .build(); + return new ResponseEntity<>(dto, errorCode.getHttpStatusCode()); + } + + @ExceptionHandler({Exception.class}) + public ResponseEntity> handleAllException(final Exception ex) { + final FailResponseStatus errorCode = FailResponseStatus.INTERNAL_SERVER_ERROR; + ex.printStackTrace(); + ResponseDto dto = ResponseDto.builder() + .successOrNot(false) + .statusCode(errorCode.getStatusCode().toString()) + .message(errorCode.getMessage()) + .data(null) + .build(); + return new ResponseEntity<>(dto, errorCode.getHttpStatusCode()); + } + +} \ No newline at end of file diff --git a/blog/src/main/java/cloudclub/blog/common/exception/RestApiException.java b/blog/src/main/java/cloudclub/blog/common/exception/RestApiException.java new file mode 100644 index 0000000..467d3b3 --- /dev/null +++ b/blog/src/main/java/cloudclub/blog/common/exception/RestApiException.java @@ -0,0 +1,18 @@ +package cloudclub.blog.common.exception; + +import cloudclub.blog.common.enums.FailResponseStatus; +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +public class RestApiException extends RuntimeException { + + private FailResponseStatus failResponseStatus; + + public RestApiException(FailResponseStatus e) { + super(e.getMessage()); + this.failResponseStatus = e; + } + +} \ No newline at end of file From 00a3e6aec1551850f706352efbe509aa994e3e9b Mon Sep 17 00:00:00 2001 From: Yuri JI <45191069+ur2e@users.noreply.github.com> Date: Sun, 9 Jun 2024 17:22:13 +0900 Subject: [PATCH 10/11] =?UTF-8?q?chore:=20application.properties=20?= =?UTF-8?q?=ED=99=95=EC=9E=A5=EC=9E=90=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- blog/src/main/resources/application.properties | 4 ---- blog/src/main/resources/application.yaml | 9 +++++++++ 2 files changed, 9 insertions(+), 4 deletions(-) delete mode 100644 blog/src/main/resources/application.properties create mode 100644 blog/src/main/resources/application.yaml diff --git a/blog/src/main/resources/application.properties b/blog/src/main/resources/application.properties deleted file mode 100644 index 71890bf..0000000 --- a/blog/src/main/resources/application.properties +++ /dev/null @@ -1,4 +0,0 @@ -spring.application.name=blog -spring.h2.console.enabled=true -spring.datasource.url= jdbc:h2:mem:testdb -#spring.jpa.show-sql=true \ No newline at end of file diff --git a/blog/src/main/resources/application.yaml b/blog/src/main/resources/application.yaml new file mode 100644 index 0000000..9daa858 --- /dev/null +++ b/blog/src/main/resources/application.yaml @@ -0,0 +1,9 @@ +spring: + h2: + console: + enabled: true + datasource: + driver-class-name: org.h2.Driver + url: jdbc:h2:mem:testdb + application: + name: blog From 8821131553cbdd5ab887b62239837f5c603ff798 Mon Sep 17 00:00:00 2001 From: hong-geon-ui Date: Sat, 15 Jun 2024 14:25:53 +0900 Subject: [PATCH 11/11] =?UTF-8?q?Add:=20[#17]=20=EB=A1=9C=EA=B7=B8=20?= =?UTF-8?q?=EC=B6=94=EC=A0=81=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cloudclub/blog/common/log/BlogLogger.java | 53 +++++++++++++++++++ .../blog/common/log/LoggerConfig.java | 16 ++++++ 2 files changed, 69 insertions(+) create mode 100644 blog/src/main/java/cloudclub/blog/common/log/BlogLogger.java create mode 100644 blog/src/main/java/cloudclub/blog/common/log/LoggerConfig.java diff --git a/blog/src/main/java/cloudclub/blog/common/log/BlogLogger.java b/blog/src/main/java/cloudclub/blog/common/log/BlogLogger.java new file mode 100644 index 0000000..61777d5 --- /dev/null +++ b/blog/src/main/java/cloudclub/blog/common/log/BlogLogger.java @@ -0,0 +1,53 @@ +package cloudclub.blog.common.log; + +import jakarta.servlet.http.HttpServletRequest; +import lombok.extern.slf4j.Slf4j; +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.annotation.After; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Before; +import org.aspectj.lang.annotation.Pointcut; +import org.aspectj.lang.reflect.MethodSignature; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import java.lang.reflect.Method; + +@Aspect +@Slf4j +public class BlogLogger { + + @Pointcut("execution(* cloudclub.blog.*.*(..))") + private void publicTarget(){ + } + + + @Before("publicTarget()") + public void beforeController(JoinPoint joinPoint) { + MethodSignature signature = (MethodSignature) joinPoint.getSignature(); + Method method = signature.getMethod(); + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest(); + String requestId = request.getRequestId(); + String className = joinPoint.getTarget().getClass().getSimpleName(); + log.info("[{}] #BEFORE >> {}.{}()", requestId, className, method.getName()); + Object[] args = joinPoint.getArgs(); + for(Object arg : args) { + if(arg != null) { + log.info(" type = {}", arg.getClass().getSimpleName()); + log.info(" value = {}", arg); + } + } + } + + @After("publicTarget()") + public void afterController(JoinPoint joinPoint) { + MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature(); + Method method = methodSignature.getMethod(); + + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest(); + String requestId = request.getRequestId(); + String className = joinPoint.getTarget().getClass().getSimpleName(); + log.info("[{}] #After >> {}.{}()", requestId, className, method.getName()); + } + +} diff --git a/blog/src/main/java/cloudclub/blog/common/log/LoggerConfig.java b/blog/src/main/java/cloudclub/blog/common/log/LoggerConfig.java new file mode 100644 index 0000000..9e49848 --- /dev/null +++ b/blog/src/main/java/cloudclub/blog/common/log/LoggerConfig.java @@ -0,0 +1,16 @@ +package cloudclub.blog.common.log; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.EnableAspectJAutoProxy; + +@Configuration +@EnableAspectJAutoProxy +public class LoggerConfig { + + @Bean + public BlogLogger blogLogger() { + return new BlogLogger(); + } + +}