From 997f9da57a8de372b24135760fa804c0076b4a09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=EC=9E=AC=EC=9A=B1?= Date: Fri, 21 Feb 2025 05:45:47 +0900 Subject: [PATCH 01/15] feat --- .../_1/_1/controller/ArticleController.java | 42 +++++++++++++++ .../backed/task/_1/_1/domain/Article.java | 17 ++++++ .../class4/backed/task/_1/_1/domain/README.md | 2 - .../global/annotation/task/info/TaskInfo.java | 9 +--- .../task/_1/_1/global/config/WebConfig.java | 17 ++++++ .../_1/_1/global/entity/BaseIdxEntity.java | 2 +- .../_1/_1/repository/ArticleRepository.java | 9 ++++ .../task/_1/_1/service/ArticleService.java | 53 +++++++++++++++++++ src/main/resources/application.yml | 10 ++-- 9 files changed, 145 insertions(+), 16 deletions(-) create mode 100644 src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/controller/ArticleController.java create mode 100644 src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/domain/Article.java delete mode 100644 src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/domain/README.md create mode 100644 src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/global/config/WebConfig.java create mode 100644 src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/repository/ArticleRepository.java create mode 100644 src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/service/ArticleService.java diff --git a/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/controller/ArticleController.java b/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/controller/ArticleController.java new file mode 100644 index 0000000..65afed4 --- /dev/null +++ b/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/controller/ArticleController.java @@ -0,0 +1,42 @@ +package com.gsm._8th.class4.backed.task._1._1.controller; + +import com.gsm._8th.class4.backed.task._1._1.domain.Article; +import com.gsm._8th.class4.backed.task._1._1.service.ArticleService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@RequestMapping("/articles") +public class ArticleController { + + @Autowired + private ArticleService articleService; + + @GetMapping + public ResponseEntity> getAllArticles() { + return articleService.getAllArticles(); + } + + @GetMapping("/{articleId}") + public ResponseEntity
getArticleById(@PathVariable Long articleId) { + return articleService.getArticleById(articleId); + } + + @PostMapping + public ResponseEntity
createArticle(@RequestBody Article article) { + return articleService.createArticle(article); + } + + @PatchMapping("/{articleId}") + public ResponseEntity
updateArticle(@PathVariable Long articleId, @RequestBody Article articleDetails) { + return articleService.updateArticle(articleId, articleDetails); + } + + @DeleteMapping("/{articleId}") + public ResponseEntity deleteArticle(@PathVariable Long articleId) { + return articleService.deleteArticle(articleId); + } +} \ No newline at end of file diff --git a/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/domain/Article.java b/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/domain/Article.java new file mode 100644 index 0000000..4909266 --- /dev/null +++ b/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/domain/Article.java @@ -0,0 +1,17 @@ +package com.gsm._8th.class4.backed.task._1._1.domain; + +import com.gsm._8th.class4.backed.task._1._1.global.entity.BaseIdxEntity; + +import jakarta.persistence.Entity; +import jakarta.persistence.Table; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@Entity +@Table(name = "articles") +public class Article extends BaseIdxEntity { + private String title; + private String content; +} \ No newline at end of file diff --git a/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/domain/README.md b/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/domain/README.md deleted file mode 100644 index 589add4..0000000 --- a/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/domain/README.md +++ /dev/null @@ -1,2 +0,0 @@ -여기서부터 작업을 시작해주시면 됩니다! -Entity의 경우에는 API 명세서를 참고하셔서 필요한 요소들을 모두 적용해주세요! \ No newline at end of file diff --git a/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/global/annotation/task/info/TaskInfo.java b/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/global/annotation/task/info/TaskInfo.java index c68daf8..8a8e8f3 100644 --- a/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/global/annotation/task/info/TaskInfo.java +++ b/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/global/annotation/task/info/TaskInfo.java @@ -4,16 +4,9 @@ import jdk.jfr.Name; import org.springframework.stereotype.Component; -import java.lang.annotation.Retention; +import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; -/** - * 과제 정보를 출력하는 클래스에 적용되는 어노테이션 - * - * @Componset 어노테이션을 사용하여 빈으로 등록된 클래스에 적용 - * @Slf4j 어노테이션을 사용하여 로깅을 위한 Logger 객체를 생성 - * 어노테이션은 런타임에도 유지되어야 하므로 @Retention 어노테이션을 사용하여 런타임에도 유지되도록 함 - */ @Name("TaskInfo") @Retention(RetentionPolicy.RUNTIME) @Component diff --git a/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/global/config/WebConfig.java b/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/global/config/WebConfig.java new file mode 100644 index 0000000..9edbebf --- /dev/null +++ b/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/global/config/WebConfig.java @@ -0,0 +1,17 @@ +package com.gsm._8th.class4.backed.task._1._1.global.config; + +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.CorsRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +@Configuration +public class WebConfig implements WebMvcConfigurer { + + @Override + public void addCorsMappings(CorsRegistry registry) { + registry.addMapping("/**") + .allowedOrigins("*") + .allowedMethods("*") + .allowedHeaders("*"); + } +} \ No newline at end of file diff --git a/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/global/entity/BaseIdxEntity.java b/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/global/entity/BaseIdxEntity.java index 72bf006..0b286af 100644 --- a/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/global/entity/BaseIdxEntity.java +++ b/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/global/entity/BaseIdxEntity.java @@ -7,7 +7,7 @@ @Getter @MappedSuperclass -abstract class BaseIdxEntity { +public abstract class BaseIdxEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "idx", nullable = false, updatable = false, insertable = false, unique = true) diff --git a/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/repository/ArticleRepository.java b/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/repository/ArticleRepository.java new file mode 100644 index 0000000..16b55d9 --- /dev/null +++ b/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/repository/ArticleRepository.java @@ -0,0 +1,9 @@ +package com.gsm._8th.class4.backed.task._1._1.repository; + +import com.gsm._8th.class4.backed.task._1._1.domain.Article; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface ArticleRepository extends JpaRepository { +} \ No newline at end of file diff --git a/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/service/ArticleService.java b/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/service/ArticleService.java new file mode 100644 index 0000000..da85388 --- /dev/null +++ b/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/service/ArticleService.java @@ -0,0 +1,53 @@ +package com.gsm._8th.class4.backed.task._1._1.service; + +import com.gsm._8th.class4.backed.task._1._1.domain.Article; +import com.gsm._8th.class4.backed.task._1._1.repository.ArticleRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Optional; + +@Service +public class ArticleService { + + @Autowired + private ArticleRepository articleRepository; + + public ResponseEntity> getAllArticles() { + List
articles = articleRepository.findAll(); + return ResponseEntity.ok(articles); + } + + public ResponseEntity
getArticleById(Long id) { + Optional
article = articleRepository.findById(id); + return article.map(ResponseEntity::ok) + .orElseGet(() -> ResponseEntity.notFound().build()); + } + + public ResponseEntity
createArticle(Article article) { + Article savedArticle = articleRepository.save(article); + return ResponseEntity.ok(savedArticle); + } + + public ResponseEntity
updateArticle(Long id, Article articleDetails) { + return articleRepository.findById(id) + .map(existingArticle -> { + existingArticle.setTitle(articleDetails.getTitle()); + existingArticle.setContent(articleDetails.getContent()); + Article updatedArticle = articleRepository.save(existingArticle); + return ResponseEntity.ok(updatedArticle); + }) + .orElseGet(() -> ResponseEntity.notFound().build()); + } + + public ResponseEntity deleteArticle(Long id) { + return articleRepository.findById(id) + .map(article -> { + articleRepository.delete(article); + return ResponseEntity.noContent().build(); + }) + .orElseGet(() -> ResponseEntity.notFound().build()); + } +} \ No newline at end of file diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 743a92a..b127227 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -3,13 +3,13 @@ spring: name: task.1-1 datasource: driver-class-name: com.mysql.cj.jdbc.Driver - url: jdbc:mysql://${RDB_HOST:localhost}:${RDB_PORT:3306}/${RDB_NAME:task_1_1} - username: ${RDB_USER:root} - password: ${RDB_PASSWORD:123456} + url: jdbc:mysql://localhost:3306/task_1_1 + username: root + password: 1234 jpa: hibernate: - ddl-auto: ${DDL_AUTO:update} + ddl-auto: update show-sql: true properties: hibernate: - dialect: org.hibernate.dialect.MySQL8Dialect \ No newline at end of file + dialect: org.hibernate.dialect.MySQL8Dialect From 95a635747b0bc6f3682672171203aeee802bdd12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=EC=9E=AC=EC=9A=B1?= Date: Sat, 22 Feb 2025 04:18:42 +0900 Subject: [PATCH 02/15] =?UTF-8?q?refector:=20Autowired=20=EB=8C=80?= =?UTF-8?q?=EC=8B=A0=20=EC=83=9D=EC=84=B1=EC=9E=90=20=EC=A3=BC=EC=9E=85?= =?UTF-8?q?=EC=9D=84=20=EC=82=AC=EC=9A=A9=ED=95=98=EB=8F=84=EB=A1=9D=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD=ED=96=88=EC=8A=B5=EB=8B=88=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../backed/task/_1/_1/controller/ArticleController.java | 8 +++++--- .../task/_1/_1/global/annotation/task/info/TaskInfo.java | 1 - .../class4/backed/task/_1/_1/service/ArticleService.java | 8 +++++--- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/controller/ArticleController.java b/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/controller/ArticleController.java index 65afed4..b150729 100644 --- a/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/controller/ArticleController.java +++ b/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/controller/ArticleController.java @@ -2,7 +2,6 @@ import com.gsm._8th.class4.backed.task._1._1.domain.Article; import com.gsm._8th.class4.backed.task._1._1.service.ArticleService; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; @@ -12,8 +11,11 @@ @RequestMapping("/articles") public class ArticleController { - @Autowired - private ArticleService articleService; + private final ArticleService articleService; + + public ArticleController(ArticleService articleService) { + this.articleService = articleService; + } @GetMapping public ResponseEntity> getAllArticles() { diff --git a/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/global/annotation/task/info/TaskInfo.java b/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/global/annotation/task/info/TaskInfo.java index 8a8e8f3..0381495 100644 --- a/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/global/annotation/task/info/TaskInfo.java +++ b/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/global/annotation/task/info/TaskInfo.java @@ -1,6 +1,5 @@ package com.gsm._8th.class4.backed.task._1._1.global.annotation.task.info; -import jakarta.annotation.PostConstruct; import jdk.jfr.Name; import org.springframework.stereotype.Component; diff --git a/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/service/ArticleService.java b/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/service/ArticleService.java index da85388..435ba45 100644 --- a/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/service/ArticleService.java +++ b/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/service/ArticleService.java @@ -2,7 +2,6 @@ import com.gsm._8th.class4.backed.task._1._1.domain.Article; import com.gsm._8th.class4.backed.task._1._1.repository.ArticleRepository; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; @@ -12,8 +11,11 @@ @Service public class ArticleService { - @Autowired - private ArticleRepository articleRepository; + private final ArticleRepository articleRepository; + + public ArticleService(ArticleRepository articleRepository) { + this.articleRepository = articleRepository; + } public ResponseEntity> getAllArticles() { List
articles = articleRepository.findAll(); From c492febd71a78fd86dd89b867132de18a7a0f891 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=EC=9E=AC=EC=9A=B1?= Date: Sat, 22 Feb 2025 04:22:49 +0900 Subject: [PATCH 03/15] =?UTF-8?q?refector:=20service=20layer=EC=97=90?= =?UTF-8?q?=EC=84=9C=20responseentitiy=EB=A5=BC=20=EC=A0=9C=EA=B1=B0?= =?UTF-8?q?=ED=95=98=EA=B3=A0=20contorler=EC=97=90=EC=84=9C=20=EC=B2=98?= =?UTF-8?q?=EB=A6=AC=ED=95=98=EB=8F=84=EB=A1=9D=20=ED=96=88=EC=8A=B5?= =?UTF-8?q?=EB=8B=88=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../_1/_1/controller/ArticleController.java | 17 +++++++--- .../task/_1/_1/service/ArticleService.java | 31 +++++++------------ 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/controller/ArticleController.java b/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/controller/ArticleController.java index b150729..146889b 100644 --- a/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/controller/ArticleController.java +++ b/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/controller/ArticleController.java @@ -19,26 +19,33 @@ public ArticleController(ArticleService articleService) { @GetMapping public ResponseEntity> getAllArticles() { - return articleService.getAllArticles(); + List
articles = articleService.getAllArticles(); + return ResponseEntity.ok(articles); } @GetMapping("/{articleId}") public ResponseEntity
getArticleById(@PathVariable Long articleId) { - return articleService.getArticleById(articleId); + return articleService.getArticleById(articleId) + .map(ResponseEntity::ok) + .orElseGet(() -> ResponseEntity.notFound().build()); } @PostMapping public ResponseEntity
createArticle(@RequestBody Article article) { - return articleService.createArticle(article); + Article createdArticle = articleService.createArticle(article); + return ResponseEntity.ok(createdArticle); } @PatchMapping("/{articleId}") public ResponseEntity
updateArticle(@PathVariable Long articleId, @RequestBody Article articleDetails) { - return articleService.updateArticle(articleId, articleDetails); + return articleService.updateArticle(articleId, articleDetails) + .map(ResponseEntity::ok) + .orElseGet(() -> ResponseEntity.notFound().build()); } @DeleteMapping("/{articleId}") public ResponseEntity deleteArticle(@PathVariable Long articleId) { - return articleService.deleteArticle(articleId); + boolean deleted = articleService.deleteArticle(articleId); + return deleted ? ResponseEntity.noContent().build() : ResponseEntity.notFound().build(); } } \ No newline at end of file diff --git a/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/service/ArticleService.java b/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/service/ArticleService.java index 435ba45..0cc2cbc 100644 --- a/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/service/ArticleService.java +++ b/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/service/ArticleService.java @@ -2,7 +2,6 @@ import com.gsm._8th.class4.backed.task._1._1.domain.Article; import com.gsm._8th.class4.backed.task._1._1.repository.ArticleRepository; -import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import java.util.List; @@ -17,39 +16,33 @@ public ArticleService(ArticleRepository articleRepository) { this.articleRepository = articleRepository; } - public ResponseEntity> getAllArticles() { - List
articles = articleRepository.findAll(); - return ResponseEntity.ok(articles); + public List
getAllArticles() { + return articleRepository.findAll(); } - public ResponseEntity
getArticleById(Long id) { - Optional
article = articleRepository.findById(id); - return article.map(ResponseEntity::ok) - .orElseGet(() -> ResponseEntity.notFound().build()); + public Optional
getArticleById(Long id) { + return articleRepository.findById(id); } - public ResponseEntity
createArticle(Article article) { - Article savedArticle = articleRepository.save(article); - return ResponseEntity.ok(savedArticle); + public Article createArticle(Article article) { + return articleRepository.save(article); } - public ResponseEntity
updateArticle(Long id, Article articleDetails) { + public Optional
updateArticle(Long id, Article articleDetails) { return articleRepository.findById(id) .map(existingArticle -> { existingArticle.setTitle(articleDetails.getTitle()); existingArticle.setContent(articleDetails.getContent()); - Article updatedArticle = articleRepository.save(existingArticle); - return ResponseEntity.ok(updatedArticle); - }) - .orElseGet(() -> ResponseEntity.notFound().build()); + return articleRepository.save(existingArticle); + }); } - public ResponseEntity deleteArticle(Long id) { + public boolean deleteArticle(Long id) { return articleRepository.findById(id) .map(article -> { articleRepository.delete(article); - return ResponseEntity.noContent().build(); + return true; }) - .orElseGet(() -> ResponseEntity.notFound().build()); + .orElse(false); } } \ No newline at end of file From 6ea9a4dcab0234380423192bfb6d4d53caeaca2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=EC=9E=AC=EC=9A=B1?= Date: Sat, 22 Feb 2025 04:24:22 +0900 Subject: [PATCH 04/15] =?UTF-8?q?perf:=20getAllArticles=EC=97=90=20?= =?UTF-8?q?=EC=BA=90=EC=8B=B1=EC=9D=84=20=EC=A0=81=EC=9A=A9=ED=95=98?= =?UTF-8?q?=EC=98=80=EC=8A=B5=EB=8B=88=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../backed/task/_1/_1/service/ArticleService.java | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/service/ArticleService.java b/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/service/ArticleService.java index 0cc2cbc..22b258c 100644 --- a/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/service/ArticleService.java +++ b/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/service/ArticleService.java @@ -3,6 +3,7 @@ import com.gsm._8th.class4.backed.task._1._1.domain.Article; import com.gsm._8th.class4.backed.task._1._1.repository.ArticleRepository; import org.springframework.stereotype.Service; +import org.springframework.cache.annotation.Cacheable; import java.util.List; import java.util.Optional; @@ -16,6 +17,7 @@ public ArticleService(ArticleRepository articleRepository) { this.articleRepository = articleRepository; } + @Cacheable("articles") public List
getAllArticles() { return articleRepository.findAll(); } @@ -38,11 +40,8 @@ public Optional
updateArticle(Long id, Article articleDetails) { } public boolean deleteArticle(Long id) { - return articleRepository.findById(id) - .map(article -> { - articleRepository.delete(article); - return true; - }) - .orElse(false); + Optional
article = articleRepository.findById(id); + article.ifPresent(articleRepository::delete); + return article.isPresent(); } } \ No newline at end of file From 22f68152179dd59b782c0584f19efda64c0734c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=EC=9E=AC=EC=9A=B1?= Date: Sat, 22 Feb 2025 04:28:16 +0900 Subject: [PATCH 05/15] =?UTF-8?q?perf:=20ArticleService=EC=99=80=20Article?= =?UTF-8?q?Controller=EC=97=90=20=EB=B9=84=EB=8F=99=EA=B8=B0=20=EC=B2=98?= =?UTF-8?q?=EB=A6=AC=20=EB=A1=9C=EC=A7=81=EC=9D=84=20=EC=B6=94=EA=B0=80?= =?UTF-8?q?=ED=95=98=EC=98=80=EC=8A=B5=EB=8B=88=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../_1/_1/controller/ArticleController.java | 29 +++++++++---------- .../task/_1/_1/service/ArticleService.java | 29 ++++++++++++------- 2 files changed, 32 insertions(+), 26 deletions(-) diff --git a/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/controller/ArticleController.java b/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/controller/ArticleController.java index 146889b..4206223 100644 --- a/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/controller/ArticleController.java +++ b/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/controller/ArticleController.java @@ -6,6 +6,7 @@ import org.springframework.web.bind.annotation.*; import java.util.List; +import java.util.concurrent.CompletableFuture; @RestController @RequestMapping("/articles") @@ -18,34 +19,32 @@ public ArticleController(ArticleService articleService) { } @GetMapping - public ResponseEntity> getAllArticles() { - List
articles = articleService.getAllArticles(); - return ResponseEntity.ok(articles); + public CompletableFuture>> getAllArticles() { + return articleService.getAllArticles().thenApply(ResponseEntity::ok); } @GetMapping("/{articleId}") - public ResponseEntity
getArticleById(@PathVariable Long articleId) { + public CompletableFuture> getArticleById(@PathVariable Long articleId) { return articleService.getArticleById(articleId) - .map(ResponseEntity::ok) - .orElseGet(() -> ResponseEntity.notFound().build()); + .thenApply(article -> article.map(ResponseEntity::ok) + .orElseGet(() -> ResponseEntity.notFound().build())); } @PostMapping - public ResponseEntity
createArticle(@RequestBody Article article) { - Article createdArticle = articleService.createArticle(article); - return ResponseEntity.ok(createdArticle); + public CompletableFuture> createArticle(@RequestBody Article article) { + return articleService.createArticle(article).thenApply(ResponseEntity::ok); } @PatchMapping("/{articleId}") - public ResponseEntity
updateArticle(@PathVariable Long articleId, @RequestBody Article articleDetails) { + public CompletableFuture> updateArticle(@PathVariable Long articleId, @RequestBody Article articleDetails) { return articleService.updateArticle(articleId, articleDetails) - .map(ResponseEntity::ok) - .orElseGet(() -> ResponseEntity.notFound().build()); + .thenApply(article -> article.map(ResponseEntity::ok) + .orElseGet(() -> ResponseEntity.notFound().build())); } @DeleteMapping("/{articleId}") - public ResponseEntity deleteArticle(@PathVariable Long articleId) { - boolean deleted = articleService.deleteArticle(articleId); - return deleted ? ResponseEntity.noContent().build() : ResponseEntity.notFound().build(); + public CompletableFuture> deleteArticle(@PathVariable Long articleId) { + return articleService.deleteArticle(articleId) + .thenApply(deleted -> deleted ? ResponseEntity.noContent().build() : ResponseEntity.notFound().build()); } } \ No newline at end of file diff --git a/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/service/ArticleService.java b/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/service/ArticleService.java index 22b258c..bcc100f 100644 --- a/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/service/ArticleService.java +++ b/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/service/ArticleService.java @@ -4,6 +4,8 @@ import com.gsm._8th.class4.backed.task._1._1.repository.ArticleRepository; import org.springframework.stereotype.Service; import org.springframework.cache.annotation.Cacheable; +import org.springframework.scheduling.annotation.Async; +import java.util.concurrent.CompletableFuture; import java.util.List; import java.util.Optional; @@ -17,31 +19,36 @@ public ArticleService(ArticleRepository articleRepository) { this.articleRepository = articleRepository; } + @Async @Cacheable("articles") - public List
getAllArticles() { - return articleRepository.findAll(); + public CompletableFuture> getAllArticles() { + return CompletableFuture.completedFuture(articleRepository.findAll()); } - public Optional
getArticleById(Long id) { - return articleRepository.findById(id); + @Async + public CompletableFuture> getArticleById(Long id) { + return CompletableFuture.completedFuture(articleRepository.findById(id)); } - public Article createArticle(Article article) { - return articleRepository.save(article); + @Async + public CompletableFuture
createArticle(Article article) { + return CompletableFuture.completedFuture(articleRepository.save(article)); } - public Optional
updateArticle(Long id, Article articleDetails) { - return articleRepository.findById(id) + @Async + public CompletableFuture> updateArticle(Long id, Article articleDetails) { + return CompletableFuture.completedFuture(articleRepository.findById(id) .map(existingArticle -> { existingArticle.setTitle(articleDetails.getTitle()); existingArticle.setContent(articleDetails.getContent()); return articleRepository.save(existingArticle); - }); + })); } - public boolean deleteArticle(Long id) { + @Async + public CompletableFuture deleteArticle(Long id) { Optional
article = articleRepository.findById(id); article.ifPresent(articleRepository::delete); - return article.isPresent(); + return CompletableFuture.completedFuture(article.isPresent()); } } \ No newline at end of file From 2693c8febcacbd70b72aff63a6f2276e35abe7ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=EC=9E=AC=EC=9A=B1?= Date: Sat, 22 Feb 2025 04:35:33 +0900 Subject: [PATCH 06/15] =?UTF-8?q?Refector:=20javax.validation=20=EB=9D=BC?= =?UTF-8?q?=EC=9D=B4=EB=B8=8C=EB=9F=AC=EB=A6=AC=EB=A5=BC=20=EC=82=AC?= =?UTF-8?q?=EC=9A=A9=ED=95=98=EC=97=AC=20=EC=9E=85=EB=A0=A5=EA=B0=92=20?= =?UTF-8?q?=EA=B2=80=EC=A6=9D=EC=9D=84=20=ED=95=98=EC=98=80=EC=8A=B5?= =?UTF-8?q?=EB=8B=88=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 3 +++ .../backed/task/_1/_1/service/ArticleService.java | 12 +++++++----- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/build.gradle b/build.gradle index 34ece7c..bc54260 100644 --- a/build.gradle +++ b/build.gradle @@ -31,6 +31,9 @@ dependencies { annotationProcessor 'org.projectlombok:lombok' testImplementation 'org.springframework.boot:spring-boot-starter-test' testRuntimeOnly 'org.junit.platform:junit-platform-launcher' + implementation 'javax.validation:validation-api:2.0.1.Final' + implementation 'org.hibernate.validator:hibernate-validator:6.0.13.Final' + implementation 'org.glassfish:javax.el:3.0.0' } tasks.named('test') { diff --git a/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/service/ArticleService.java b/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/service/ArticleService.java index bcc100f..b9aa906 100644 --- a/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/service/ArticleService.java +++ b/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/service/ArticleService.java @@ -8,7 +8,9 @@ import java.util.concurrent.CompletableFuture; import java.util.List; -import java.util.Optional; +import java.util.Optional; +import javax.validation.Valid; +import javax.validation.constraints.NotNull; @Service public class ArticleService { @@ -26,17 +28,17 @@ public CompletableFuture> getAllArticles() { } @Async - public CompletableFuture> getArticleById(Long id) { + public CompletableFuture> getArticleById(@NotNull Long id) { return CompletableFuture.completedFuture(articleRepository.findById(id)); } @Async - public CompletableFuture
createArticle(Article article) { + public CompletableFuture
createArticle(@Valid Article article) { return CompletableFuture.completedFuture(articleRepository.save(article)); } @Async - public CompletableFuture> updateArticle(Long id, Article articleDetails) { + public CompletableFuture> updateArticle(@NotNull Long id, @Valid Article articleDetails) { return CompletableFuture.completedFuture(articleRepository.findById(id) .map(existingArticle -> { existingArticle.setTitle(articleDetails.getTitle()); @@ -46,7 +48,7 @@ public CompletableFuture> updateArticle(Long id, Article artic } @Async - public CompletableFuture deleteArticle(Long id) { + public CompletableFuture deleteArticle(@NotNull Long id) { Optional
article = articleRepository.findById(id); article.ifPresent(articleRepository::delete); return CompletableFuture.completedFuture(article.isPresent()); From e9038a3fe211bfed3da2a95dae247f446805c044 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=EC=9E=AC=EC=9A=B1?= Date: Sat, 22 Feb 2025 04:42:30 +0900 Subject: [PATCH 07/15] =?UTF-8?q?feat:=20@controlleradvice=EB=A5=BC=20?= =?UTF-8?q?=ED=86=B5=ED=95=B4=20=EC=A0=84=EC=97=AD=20=EC=98=88=EC=99=B8=20?= =?UTF-8?q?=EC=B2=98=EB=A6=AC=20=ED=81=B4=EB=9E=98=EC=8A=A4=EB=A5=BC=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=ED=96=88=EC=8A=B5=EB=8B=88=EB=8B=A4.=20?= =?UTF-8?q?=EB=98=90=ED=95=9C=20=EC=B5=9C=EC=A0=81=ED=99=94=EB=A5=BC=20?= =?UTF-8?q?=EC=9C=84=ED=95=B4=20=EC=9E=84=EC=9D=98=EB=A1=9C=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=ED=95=9C=20=EB=B9=84=EB=8F=99=EA=B8=B0=20=EB=A9=94?= =?UTF-8?q?=EC=84=9C=EB=93=9C=EC=97=90=EB=8F=84=20exceptionally=EB=A5=BC?= =?UTF-8?q?=20=EC=9D=B4=EC=9A=A9=ED=95=98=EC=97=AC=20=EC=98=88=EC=99=B8?= =?UTF-8?q?=EB=A5=BC=20=EC=B2=98=EB=A6=AC=ED=96=88=EC=8A=B5=EB=8B=88?= =?UTF-8?q?=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../_1/_1/global/GlobalExceptionHandler.java | 16 +++++++++ .../task/_1/_1/service/ArticleService.java | 33 ++++++++++++++----- 2 files changed, 41 insertions(+), 8 deletions(-) create mode 100644 src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/global/GlobalExceptionHandler.java diff --git a/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/global/GlobalExceptionHandler.java b/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/global/GlobalExceptionHandler.java new file mode 100644 index 0000000..e0728a0 --- /dev/null +++ b/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/global/GlobalExceptionHandler.java @@ -0,0 +1,16 @@ +package com.gsm._8th.class4.backed.task._1._1.global; + +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; + +@ControllerAdvice +public class GlobalExceptionHandler { + + @ExceptionHandler(Exception.class) + public ResponseEntity handleException(Exception e) { + return new ResponseEntity<>(e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); + } + +} \ No newline at end of file diff --git a/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/service/ArticleService.java b/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/service/ArticleService.java index b9aa906..5739785 100644 --- a/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/service/ArticleService.java +++ b/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/service/ArticleService.java @@ -24,33 +24,50 @@ public ArticleService(ArticleRepository articleRepository) { @Async @Cacheable("articles") public CompletableFuture> getAllArticles() { - return CompletableFuture.completedFuture(articleRepository.findAll()); + return CompletableFuture.supplyAsync(() -> articleRepository.findAll()) + .exceptionally(ex -> { + return List.of(); + }); } @Async public CompletableFuture> getArticleById(@NotNull Long id) { - return CompletableFuture.completedFuture(articleRepository.findById(id)); + return CompletableFuture.supplyAsync(() -> articleRepository.findById(id)) + .exceptionally(ex -> { + return Optional.empty(); + }); } @Async public CompletableFuture
createArticle(@Valid Article article) { - return CompletableFuture.completedFuture(articleRepository.save(article)); + return CompletableFuture.supplyAsync(() -> articleRepository.save(article)) + .exceptionally(ex -> { + return null; + }); } @Async public CompletableFuture> updateArticle(@NotNull Long id, @Valid Article articleDetails) { - return CompletableFuture.completedFuture(articleRepository.findById(id) + return CompletableFuture.supplyAsync(() -> articleRepository.findById(id) .map(existingArticle -> { existingArticle.setTitle(articleDetails.getTitle()); existingArticle.setContent(articleDetails.getContent()); return articleRepository.save(existingArticle); - })); + })) + .exceptionally(ex -> { + return Optional.empty(); + }); } @Async public CompletableFuture deleteArticle(@NotNull Long id) { - Optional
article = articleRepository.findById(id); - article.ifPresent(articleRepository::delete); - return CompletableFuture.completedFuture(article.isPresent()); + return CompletableFuture.supplyAsync(() -> { + Optional
article = articleRepository.findById(id); + article.ifPresent(articleRepository::delete); + return article.isPresent(); + }) + .exceptionally(ex -> { + return false; + }); } } \ No newline at end of file From 492e11ebbf204b0777379a6c23deb4dd39278796 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=EC=9E=AC=EC=9A=B1?= Date: Sat, 22 Feb 2025 05:40:11 +0900 Subject: [PATCH 08/15] =?UTF-8?q?Refector:=20ArticleServiceImpl=20?= =?UTF-8?q?=ED=81=B4=EB=9E=98=EC=8A=A4=EA=B0=80=20ArticleService=20?= =?UTF-8?q?=EC=9D=B8=ED=84=B0=ED=8E=98=EC=9D=B4=EC=8A=A4=EB=A5=BC=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84=ED=95=98=EB=8F=84=EB=A1=9D=20=ED=96=88?= =?UTF-8?q?=EC=8A=B5=EB=8B=88=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../task/_1/_1/service/ArticleService.java | 70 ++--------------- .../_1/service/impl/ArticleServiceImpl.java | 75 +++++++++++++++++++ 2 files changed, 83 insertions(+), 62 deletions(-) create mode 100644 src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/service/impl/ArticleServiceImpl.java diff --git a/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/service/ArticleService.java b/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/service/ArticleService.java index 5739785..74e4d83 100644 --- a/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/service/ArticleService.java +++ b/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/service/ArticleService.java @@ -1,73 +1,19 @@ package com.gsm._8th.class4.backed.task._1._1.service; import com.gsm._8th.class4.backed.task._1._1.domain.Article; -import com.gsm._8th.class4.backed.task._1._1.repository.ArticleRepository; -import org.springframework.stereotype.Service; -import org.springframework.cache.annotation.Cacheable; -import org.springframework.scheduling.annotation.Async; -import java.util.concurrent.CompletableFuture; - import java.util.List; -import java.util.Optional; -import javax.validation.Valid; -import javax.validation.constraints.NotNull; - -@Service -public class ArticleService { - - private final ArticleRepository articleRepository; +import java.util.Optional; +import java.util.concurrent.CompletableFuture; - public ArticleService(ArticleRepository articleRepository) { - this.articleRepository = articleRepository; - } +public interface ArticleService { - @Async - @Cacheable("articles") - public CompletableFuture> getAllArticles() { - return CompletableFuture.supplyAsync(() -> articleRepository.findAll()) - .exceptionally(ex -> { - return List.of(); - }); - } + CompletableFuture> getAllArticles(); - @Async - public CompletableFuture> getArticleById(@NotNull Long id) { - return CompletableFuture.supplyAsync(() -> articleRepository.findById(id)) - .exceptionally(ex -> { - return Optional.empty(); - }); - } + CompletableFuture> getArticleById(Long id); - @Async - public CompletableFuture
createArticle(@Valid Article article) { - return CompletableFuture.supplyAsync(() -> articleRepository.save(article)) - .exceptionally(ex -> { - return null; - }); - } + CompletableFuture
createArticle(Article article); - @Async - public CompletableFuture> updateArticle(@NotNull Long id, @Valid Article articleDetails) { - return CompletableFuture.supplyAsync(() -> articleRepository.findById(id) - .map(existingArticle -> { - existingArticle.setTitle(articleDetails.getTitle()); - existingArticle.setContent(articleDetails.getContent()); - return articleRepository.save(existingArticle); - })) - .exceptionally(ex -> { - return Optional.empty(); - }); - } + CompletableFuture> updateArticle(Long id, Article articleDetails); - @Async - public CompletableFuture deleteArticle(@NotNull Long id) { - return CompletableFuture.supplyAsync(() -> { - Optional
article = articleRepository.findById(id); - article.ifPresent(articleRepository::delete); - return article.isPresent(); - }) - .exceptionally(ex -> { - return false; - }); - } + CompletableFuture deleteArticle(Long id); } \ No newline at end of file diff --git a/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/service/impl/ArticleServiceImpl.java b/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/service/impl/ArticleServiceImpl.java new file mode 100644 index 0000000..fdffd86 --- /dev/null +++ b/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/service/impl/ArticleServiceImpl.java @@ -0,0 +1,75 @@ +package com.gsm._8th.class4.backed.task._1._1.service.impl; + +import com.gsm._8th.class4.backed.task._1._1.domain.Article; +import com.gsm._8th.class4.backed.task._1._1.repository.ArticleRepository; +import com.gsm._8th.class4.backed.task._1._1.service.ArticleService; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Optional; +import java.util.concurrent.CompletableFuture; + +@Service +public class ArticleServiceImpl implements ArticleService { + + private final ArticleRepository articleRepository; + + public ArticleServiceImpl(ArticleRepository articleRepository) { + this.articleRepository = articleRepository; + } + + @Override + @Async + public CompletableFuture> getAllArticles() { + return CompletableFuture.supplyAsync(() -> articleRepository.findAll()) + .exceptionally(ex -> { + return List.of(); + }); + } + + @Override + @Async + public CompletableFuture> getArticleById(Long id) { + return CompletableFuture.supplyAsync(() -> articleRepository.findById(id)) + .exceptionally(ex -> { + return Optional.empty(); + }); + } + + @Override + @Async + public CompletableFuture
createArticle(Article article) { + return CompletableFuture.supplyAsync(() -> articleRepository.save(article)) + .exceptionally(ex -> { + return null; + }); + } + + @Override + @Async + public CompletableFuture> updateArticle(Long id, Article articleDetails) { + return CompletableFuture.supplyAsync(() -> articleRepository.findById(id) + .map(existingArticle -> { + existingArticle.setTitle(articleDetails.getTitle()); + existingArticle.setContent(articleDetails.getContent()); + return articleRepository.save(existingArticle); + })) + .exceptionally(ex -> { + return Optional.empty(); + }); + } + + @Override + @Async + public CompletableFuture deleteArticle(Long id) { + return CompletableFuture.supplyAsync(() -> { + Optional
article = articleRepository.findById(id); + article.ifPresent(articleRepository::delete); + return article.isPresent(); + }) + .exceptionally(ex -> { + return false; + }); + } +} \ No newline at end of file From e637cad0f03d9e0fc92c096821dd51e6cebb8c0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=EC=9E=AC=EC=9A=B1?= Date: Sat, 22 Feb 2025 05:44:00 +0900 Subject: [PATCH 09/15] =?UTF-8?q?refector:=20=EB=B6=84=EB=A6=AC..=3F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../_1/service/impl/CreateArticleService.java | 50 +++++++++++++++++ .../_1/service/impl/DeleteArticleService.java | 54 ++++++++++++++++++ .../service/impl/GetAllArticlesService.java | 50 +++++++++++++++++ .../service/impl/GetArticleByIdService.java | 50 +++++++++++++++++ .../_1/service/impl/UpdateArticleService.java | 55 +++++++++++++++++++ 5 files changed, 259 insertions(+) create mode 100644 src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/service/impl/CreateArticleService.java create mode 100644 src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/service/impl/DeleteArticleService.java create mode 100644 src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/service/impl/GetAllArticlesService.java create mode 100644 src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/service/impl/GetArticleByIdService.java create mode 100644 src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/service/impl/UpdateArticleService.java diff --git a/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/service/impl/CreateArticleService.java b/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/service/impl/CreateArticleService.java new file mode 100644 index 0000000..aae170a --- /dev/null +++ b/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/service/impl/CreateArticleService.java @@ -0,0 +1,50 @@ +package com.gsm._8th.class4.backed.task._1._1.service.impl; + +import com.gsm._8th.class4.backed.task._1._1.domain.Article; +import com.gsm._8th.class4.backed.task._1._1.repository.ArticleRepository; +import com.gsm._8th.class4.backed.task._1._1.service.ArticleService; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Service; + +import java.util.concurrent.CompletableFuture; +import java.util.List; +import java.util.Optional; + +@Service +public class CreateArticleService implements ArticleService { + + private final ArticleRepository articleRepository; + + public CreateArticleService(ArticleRepository articleRepository) { + this.articleRepository = articleRepository; + } + + @Override + @Async + public CompletableFuture
createArticle(Article article) { + return CompletableFuture.supplyAsync(() -> articleRepository.save(article)) + .exceptionally(ex -> { + return null; + }); + } + + @Override + public CompletableFuture> getAllArticles() { + throw new UnsupportedOperationException(); + } + + @Override + public CompletableFuture> getArticleById(Long id) { + throw new UnsupportedOperationException(); + } + + @Override + public CompletableFuture> updateArticle(Long id, Article articleDetails) { + throw new UnsupportedOperationException(); + } + + @Override + public CompletableFuture deleteArticle(Long id) { + throw new UnsupportedOperationException(); + } +} \ No newline at end of file diff --git a/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/service/impl/DeleteArticleService.java b/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/service/impl/DeleteArticleService.java new file mode 100644 index 0000000..0b18cf7 --- /dev/null +++ b/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/service/impl/DeleteArticleService.java @@ -0,0 +1,54 @@ +package com.gsm._8th.class4.backed.task._1._1.service.impl; + +import com.gsm._8th.class4.backed.task._1._1.domain.Article; +import com.gsm._8th.class4.backed.task._1._1.repository.ArticleRepository; +import com.gsm._8th.class4.backed.task._1._1.service.ArticleService; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Service; + +import java.util.concurrent.CompletableFuture; +import java.util.List; +import java.util.Optional; + +@Service +public class DeleteArticleService implements ArticleService { + + private final ArticleRepository articleRepository; + + public DeleteArticleService(ArticleRepository articleRepository) { + this.articleRepository = articleRepository; + } + + @Override + @Async + public CompletableFuture deleteArticle(Long id) { + return CompletableFuture.supplyAsync(() -> { + Optional
article = articleRepository.findById(id); + article.ifPresent(articleRepository::delete); + return article.isPresent(); + }) + .exceptionally(ex -> { + return false; + }); + } + + @Override + public CompletableFuture> getAllArticles() { + throw new UnsupportedOperationException(); + } + + @Override + public CompletableFuture> getArticleById(Long id) { + throw new UnsupportedOperationException(); + } + + @Override + public CompletableFuture
createArticle(Article article) { + throw new UnsupportedOperationException(); + } + + @Override + public CompletableFuture> updateArticle(Long id, Article articleDetails) { + throw new UnsupportedOperationException(); + } +} \ No newline at end of file diff --git a/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/service/impl/GetAllArticlesService.java b/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/service/impl/GetAllArticlesService.java new file mode 100644 index 0000000..225022d --- /dev/null +++ b/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/service/impl/GetAllArticlesService.java @@ -0,0 +1,50 @@ +package com.gsm._8th.class4.backed.task._1._1.service.impl; + +import com.gsm._8th.class4.backed.task._1._1.domain.Article; +import com.gsm._8th.class4.backed.task._1._1.repository.ArticleRepository; +import com.gsm._8th.class4.backed.task._1._1.service.ArticleService; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.concurrent.CompletableFuture; +import java.util.Optional; + +@Service +public class GetAllArticlesService implements ArticleService { + + private final ArticleRepository articleRepository; + + public GetAllArticlesService(ArticleRepository articleRepository) { + this.articleRepository = articleRepository; + } + + @Override + @Async + public CompletableFuture> getAllArticles() { + return CompletableFuture.supplyAsync(() -> articleRepository.findAll()) + .exceptionally(ex -> { + return List.of(); + }); + } + + @Override + public CompletableFuture> getArticleById(Long id) { + throw new UnsupportedOperationException(); + } + + @Override + public CompletableFuture
createArticle(Article article) { + throw new UnsupportedOperationException(); + } + + @Override + public CompletableFuture> updateArticle(Long id, Article articleDetails) { + throw new UnsupportedOperationException(); + } + + @Override + public CompletableFuture deleteArticle(Long id) { + throw new UnsupportedOperationException(); + } +} \ No newline at end of file diff --git a/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/service/impl/GetArticleByIdService.java b/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/service/impl/GetArticleByIdService.java new file mode 100644 index 0000000..579576d --- /dev/null +++ b/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/service/impl/GetArticleByIdService.java @@ -0,0 +1,50 @@ +package com.gsm._8th.class4.backed.task._1._1.service.impl; + +import com.gsm._8th.class4.backed.task._1._1.domain.Article; +import com.gsm._8th.class4.backed.task._1._1.repository.ArticleRepository; +import com.gsm._8th.class4.backed.task._1._1.service.ArticleService; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Service; + +import java.util.Optional; +import java.util.concurrent.CompletableFuture; +import java.util.List; + +@Service +public class GetArticleByIdService implements ArticleService { + + private final ArticleRepository articleRepository; + + public GetArticleByIdService(ArticleRepository articleRepository) { + this.articleRepository = articleRepository; + } + + @Override + @Async + public CompletableFuture> getArticleById(Long id) { + return CompletableFuture.supplyAsync(() -> articleRepository.findById(id)) + .exceptionally(ex -> { + return Optional.empty(); + }); + } + + @Override + public CompletableFuture> getAllArticles() { + throw new UnsupportedOperationException(); + } + + @Override + public CompletableFuture
createArticle(Article article) { + throw new UnsupportedOperationException(); + } + + @Override + public CompletableFuture> updateArticle(Long id, Article articleDetails) { + throw new UnsupportedOperationException(); + } + + @Override + public CompletableFuture deleteArticle(Long id) { + throw new UnsupportedOperationException(); + } +} \ No newline at end of file diff --git a/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/service/impl/UpdateArticleService.java b/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/service/impl/UpdateArticleService.java new file mode 100644 index 0000000..0d589d5 --- /dev/null +++ b/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/service/impl/UpdateArticleService.java @@ -0,0 +1,55 @@ +package com.gsm._8th.class4.backed.task._1._1.service.impl; + +import com.gsm._8th.class4.backed.task._1._1.domain.Article; +import com.gsm._8th.class4.backed.task._1._1.repository.ArticleRepository; +import com.gsm._8th.class4.backed.task._1._1.service.ArticleService; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Service; + +import java.util.Optional; +import java.util.concurrent.CompletableFuture; +import java.util.List; + +@Service +public class UpdateArticleService implements ArticleService { + + private final ArticleRepository articleRepository; + + public UpdateArticleService(ArticleRepository articleRepository) { + this.articleRepository = articleRepository; + } + + @Override + @Async + public CompletableFuture> updateArticle(Long id, Article articleDetails) { + return CompletableFuture.supplyAsync(() -> articleRepository.findById(id) + .map(existingArticle -> { + existingArticle.setTitle(articleDetails.getTitle()); + existingArticle.setContent(articleDetails.getContent()); + return articleRepository.save(existingArticle); + })) + .exceptionally(ex -> { + return Optional.empty(); + }); + } + + @Override + public CompletableFuture> getAllArticles() { + throw new UnsupportedOperationException(); + } + + @Override + public CompletableFuture> getArticleById(Long id) { + throw new UnsupportedOperationException(); + } + + @Override + public CompletableFuture
createArticle(Article article) { + throw new UnsupportedOperationException(); + } + + @Override + public CompletableFuture deleteArticle(Long id) { + throw new UnsupportedOperationException(); + } +} \ No newline at end of file From c78214fb230788ee47d701994c5c6d8b48eca804 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=EC=9E=AC=EC=9A=B1?= Date: Sat, 22 Feb 2025 05:52:26 +0900 Subject: [PATCH 10/15] =?UTF-8?q?refector:=20=EC=9D=B4=EA=B2=8C=EB=A7=9E?= =?UTF-8?q?=EB=82=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../backed/task/_1/_1/domain/Article.java | 19 ++++++++++--- .../backed/task/_1/_1/domain/ArticleDTO.java | 27 +++++++++++++++++++ .../task/_1/_1/domain/ArticleMapper.java | 14 ++++++++++ 3 files changed, 57 insertions(+), 3 deletions(-) create mode 100644 src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/domain/ArticleDTO.java create mode 100644 src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/domain/ArticleMapper.java diff --git a/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/domain/Article.java b/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/domain/Article.java index 4909266..861918a 100644 --- a/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/domain/Article.java +++ b/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/domain/Article.java @@ -4,14 +4,27 @@ import jakarta.persistence.Entity; import jakarta.persistence.Table; +import lombok.AccessLevel; +import lombok.Builder; import lombok.Getter; -import lombok.Setter; +import lombok.NoArgsConstructor; @Getter -@Setter +@NoArgsConstructor(access = AccessLevel.PROTECTED) @Entity @Table(name = "articles") public class Article extends BaseIdxEntity { private String title; private String content; -} \ No newline at end of file + + @Builder + public Article(String title, String content) { + this.title = title; + this.content = content; + } + + public void update(String title, String content) { + this.title = title; + this.content = content; + } +} \ No newline at end of file diff --git a/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/domain/ArticleDTO.java b/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/domain/ArticleDTO.java new file mode 100644 index 0000000..9c1fb2d --- /dev/null +++ b/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/domain/ArticleDTO.java @@ -0,0 +1,27 @@ +package com.gsm._8th.class4.backed.task._1._1.domain; + +public class ArticleDTO { + private String title; + private String content; + + public ArticleDTO(String title, String content) { + this.title = title; + this.content = content; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getContent() { + return content; + } + + public void setContent(String content) { + this.content = content; + } +} \ No newline at end of file diff --git a/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/domain/ArticleMapper.java b/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/domain/ArticleMapper.java new file mode 100644 index 0000000..11621d5 --- /dev/null +++ b/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/domain/ArticleMapper.java @@ -0,0 +1,14 @@ +package com.gsm._8th.class4.backed.task._1._1.domain; + +public class ArticleMapper { + public static ArticleDTO toDTO(Article article) { + return new ArticleDTO(article.getTitle(), article.getContent()); + } + + public static Article toEntity(ArticleDTO articleDTO) { + return Article.builder() + .title(articleDTO.getTitle()) + .content(articleDTO.getContent()) + .build(); + } +} \ No newline at end of file From f212afbe598bcfc1db949909c5a5b23fc71ab9c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=EC=9E=AC=EC=9A=B1?= Date: Sat, 22 Feb 2025 06:26:22 +0900 Subject: [PATCH 11/15] =?UTF-8?q?refector:=20=EC=9D=B4=EA=B2=8C=EB=A7=9E?= =?UTF-8?q?=EB=82=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 1 + .../_1/_1/controller/ArticleController.java | 29 +++++++++++++--- .../backed/task/_1/_1/domain/Article.java | 8 +++++ .../task/_1/_1/dto/ArticleRequestDTO.java | 33 +++++++++++++++++++ 4 files changed, 67 insertions(+), 4 deletions(-) create mode 100644 src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/dto/ArticleRequestDTO.java diff --git a/build.gradle b/build.gradle index bc54260..dba4f5c 100644 --- a/build.gradle +++ b/build.gradle @@ -34,6 +34,7 @@ dependencies { implementation 'javax.validation:validation-api:2.0.1.Final' implementation 'org.hibernate.validator:hibernate-validator:6.0.13.Final' implementation 'org.glassfish:javax.el:3.0.0' + implementation 'org.springframework.boot:spring-boot-starter-validation' } tasks.named('test') { diff --git a/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/controller/ArticleController.java b/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/controller/ArticleController.java index 4206223..bb8ffc8 100644 --- a/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/controller/ArticleController.java +++ b/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/controller/ArticleController.java @@ -1,7 +1,9 @@ package com.gsm._8th.class4.backed.task._1._1.controller; import com.gsm._8th.class4.backed.task._1._1.domain.Article; +import com.gsm._8th.class4.backed.task._1._1.dto.ArticleRequestDTO; import com.gsm._8th.class4.backed.task._1._1.service.ArticleService; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; @@ -14,7 +16,7 @@ public class ArticleController { private final ArticleService articleService; - public ArticleController(ArticleService articleService) { + public ArticleController(@Qualifier("articleServiceImpl") ArticleService articleService) { this.articleService = articleService; } @@ -31,14 +33,18 @@ public CompletableFuture> getArticleById(@PathVariable L } @PostMapping - public CompletableFuture> createArticle(@RequestBody Article article) { + public CompletableFuture> createArticle(@RequestBody ArticleRequestDTO articleDTO) { + validateArticleDTO(articleDTO); + Article article = articleDTO.toEntity(); return articleService.createArticle(article).thenApply(ResponseEntity::ok); } @PatchMapping("/{articleId}") - public CompletableFuture> updateArticle(@PathVariable Long articleId, @RequestBody Article articleDetails) { + public CompletableFuture> updateArticle(@PathVariable Long articleId, @RequestBody ArticleRequestDTO articleDTO) { + validateArticleDTO(articleDTO); + Article articleDetails = articleDTO.toEntity(); return articleService.updateArticle(articleId, articleDetails) - .thenApply(article -> article.map(ResponseEntity::ok) + .thenApply(updatedArticle -> updatedArticle.map(ResponseEntity::ok) .orElseGet(() -> ResponseEntity.notFound().build())); } @@ -47,4 +53,19 @@ public CompletableFuture> deleteArticle(@PathVariable Long return articleService.deleteArticle(articleId) .thenApply(deleted -> deleted ? ResponseEntity.noContent().build() : ResponseEntity.notFound().build()); } + + private void validateArticleDTO(ArticleRequestDTO articleDTO) { + if (articleDTO.getTitle() == null || articleDTO.getTitle().isBlank()) { + throw new IllegalArgumentException("Title에 뭐라도 써주세요..."); + } + if (articleDTO.getTitle().length() > 100) { + throw new IllegalArgumentException("Title은 100자를 넘을 수 없습니다."); + } + if (articleDTO.getContent() == null || articleDTO.getContent().isBlank()) { + throw new IllegalArgumentException("Content에 뭐라도 써주세요..."); + } + if (articleDTO.getContent().length() > 1000) { + throw new IllegalArgumentException("Content는 1000자를 넘을 수 없습니다."); + } + } } \ No newline at end of file diff --git a/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/domain/Article.java b/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/domain/Article.java index 861918a..b597dde 100644 --- a/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/domain/Article.java +++ b/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/domain/Article.java @@ -27,4 +27,12 @@ public void update(String title, String content) { this.title = title; this.content = content; } + + public void setTitle(String title) { + this.title = title; + } + + public void setContent(String content) { + this.content = content; + } } \ No newline at end of file diff --git a/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/dto/ArticleRequestDTO.java b/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/dto/ArticleRequestDTO.java new file mode 100644 index 0000000..3d7ae38 --- /dev/null +++ b/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/dto/ArticleRequestDTO.java @@ -0,0 +1,33 @@ +package com.gsm._8th.class4.backed.task._1._1.dto; + +import com.gsm._8th.class4.backed.task._1._1.domain.Article; + +public class ArticleRequestDTO { + + private String title; + + private String content; + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getContent() { + return content; + } + + public void setContent(String content) { + this.content = content; + } + + public Article toEntity() { + return Article.builder() + .title(this.title) + .content(this.content) + .build(); + } +} \ No newline at end of file From fcc415282d661e050a9d7a6ca497e52b522da7f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=EC=9E=AC=EC=9A=B1?= Date: Sat, 22 Feb 2025 10:27:39 +0900 Subject: [PATCH 12/15] =?UTF-8?q?Refector:=20setter=20pattern=EC=9D=84=20?= =?UTF-8?q?=EA=B3=BC=EA=B0=90=ED=9E=88=20=EC=A0=9C=EA=B1=B0=ED=95=98?= =?UTF-8?q?=EC=97=AC=20article=20entity=EC=9D=98=20state=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD=EC=9D=84=20=EC=BA=A1=EC=8A=90=ED=99=94=ED=95=98?= =?UTF-8?q?=EC=98=80=EC=8A=B5=EB=8B=88=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../gsm/_8th/class4/backed/task/_1/_1/domain/Article.java | 8 -------- .../task/_1/_1/service/impl/ArticleServiceImpl.java | 3 +-- .../task/_1/_1/service/impl/UpdateArticleService.java | 3 +-- 3 files changed, 2 insertions(+), 12 deletions(-) diff --git a/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/domain/Article.java b/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/domain/Article.java index b597dde..861918a 100644 --- a/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/domain/Article.java +++ b/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/domain/Article.java @@ -27,12 +27,4 @@ public void update(String title, String content) { this.title = title; this.content = content; } - - public void setTitle(String title) { - this.title = title; - } - - public void setContent(String content) { - this.content = content; - } } \ No newline at end of file diff --git a/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/service/impl/ArticleServiceImpl.java b/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/service/impl/ArticleServiceImpl.java index fdffd86..5af6dc6 100644 --- a/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/service/impl/ArticleServiceImpl.java +++ b/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/service/impl/ArticleServiceImpl.java @@ -51,8 +51,7 @@ public CompletableFuture
createArticle(Article article) { public CompletableFuture> updateArticle(Long id, Article articleDetails) { return CompletableFuture.supplyAsync(() -> articleRepository.findById(id) .map(existingArticle -> { - existingArticle.setTitle(articleDetails.getTitle()); - existingArticle.setContent(articleDetails.getContent()); + existingArticle.update(articleDetails.getTitle(), articleDetails.getContent()); return articleRepository.save(existingArticle); })) .exceptionally(ex -> { diff --git a/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/service/impl/UpdateArticleService.java b/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/service/impl/UpdateArticleService.java index 0d589d5..6bf4ec7 100644 --- a/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/service/impl/UpdateArticleService.java +++ b/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/service/impl/UpdateArticleService.java @@ -24,8 +24,7 @@ public UpdateArticleService(ArticleRepository articleRepository) { public CompletableFuture> updateArticle(Long id, Article articleDetails) { return CompletableFuture.supplyAsync(() -> articleRepository.findById(id) .map(existingArticle -> { - existingArticle.setTitle(articleDetails.getTitle()); - existingArticle.setContent(articleDetails.getContent()); + existingArticle.update(articleDetails.getTitle(), articleDetails.getContent()); return articleRepository.save(existingArticle); })) .exceptionally(ex -> { From 7da4863155811f6d6b9487c40a94aafdf2d07d1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=EC=9E=AC=EC=9A=B1?= Date: Sat, 22 Feb 2025 10:30:16 +0900 Subject: [PATCH 13/15] =?UTF-8?q?Refector:=20=EA=B1=8D=20=EC=A7=80?= =?UTF-8?q?=EC=9A=B8=EA=B2=8C=20=E3=85=8B=E3=85=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../backed/task/_1/_1/domain/ArticleDTO.java | 31 ++++++------------- 1 file changed, 9 insertions(+), 22 deletions(-) diff --git a/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/domain/ArticleDTO.java b/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/domain/ArticleDTO.java index 9c1fb2d..e8e80d2 100644 --- a/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/domain/ArticleDTO.java +++ b/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/domain/ArticleDTO.java @@ -1,27 +1,14 @@ package com.gsm._8th.class4.backed.task._1._1.domain; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.AllArgsConstructor; + +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor public class ArticleDTO { private String title; private String content; - - public ArticleDTO(String title, String content) { - this.title = title; - this.content = content; - } - - public String getTitle() { - return title; - } - - public void setTitle(String title) { - this.title = title; - } - - public String getContent() { - return content; - } - - public void setContent(String content) { - this.content = content; - } -} \ No newline at end of file +} \ No newline at end of file From 2834d52aa0d3d83416cdcc45a5ca93c83a2bd51c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=EC=9E=AC=EC=9A=B1?= Date: Sat, 22 Feb 2025 10:48:01 +0900 Subject: [PATCH 14/15] =?UTF-8?q?Refector:=20=EC=98=88=EC=99=B8=20?= =?UTF-8?q?=EC=B2=98=EB=A6=AC=20=EB=A1=9C=EC=A7=81=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../task/_1/_1/service/ArticleService.java | 2 +- .../_1/service/impl/ArticleServiceImpl.java | 21 +++++------------ .../task/_1/_1/util/ExceptionHandlerUtil.java | 23 +++++++++++++++++++ 3 files changed, 30 insertions(+), 16 deletions(-) create mode 100644 src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/util/ExceptionHandlerUtil.java diff --git a/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/service/ArticleService.java b/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/service/ArticleService.java index 74e4d83..e8beeb3 100644 --- a/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/service/ArticleService.java +++ b/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/service/ArticleService.java @@ -16,4 +16,4 @@ public interface ArticleService { CompletableFuture> updateArticle(Long id, Article articleDetails); CompletableFuture deleteArticle(Long id); -} \ No newline at end of file +} diff --git a/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/service/impl/ArticleServiceImpl.java b/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/service/impl/ArticleServiceImpl.java index 5af6dc6..59a6571 100644 --- a/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/service/impl/ArticleServiceImpl.java +++ b/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/service/impl/ArticleServiceImpl.java @@ -3,6 +3,7 @@ import com.gsm._8th.class4.backed.task._1._1.domain.Article; import com.gsm._8th.class4.backed.task._1._1.repository.ArticleRepository; import com.gsm._8th.class4.backed.task._1._1.service.ArticleService; +import com.gsm._8th.class4.backed.task._1._1.util.ExceptionHandlerUtil; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; @@ -23,27 +24,21 @@ public ArticleServiceImpl(ArticleRepository articleRepository) { @Async public CompletableFuture> getAllArticles() { return CompletableFuture.supplyAsync(() -> articleRepository.findAll()) - .exceptionally(ex -> { - return List.of(); - }); + .exceptionally(ex -> ExceptionHandlerUtil.handleListException(ex)); } @Override @Async public CompletableFuture> getArticleById(Long id) { return CompletableFuture.supplyAsync(() -> articleRepository.findById(id)) - .exceptionally(ex -> { - return Optional.empty(); - }); + .exceptionally(ex -> ExceptionHandlerUtil.handleOptionalException(ex)); } @Override @Async public CompletableFuture
createArticle(Article article) { return CompletableFuture.supplyAsync(() -> articleRepository.save(article)) - .exceptionally(ex -> { - return null; - }); + .exceptionally(ex -> ExceptionHandlerUtil.handleException(ex, null)); } @Override @@ -54,9 +49,7 @@ public CompletableFuture> updateArticle(Long id, Article artic existingArticle.update(articleDetails.getTitle(), articleDetails.getContent()); return articleRepository.save(existingArticle); })) - .exceptionally(ex -> { - return Optional.empty(); - }); + .exceptionally(ex -> ExceptionHandlerUtil.handleOptionalException(ex)); } @Override @@ -67,8 +60,6 @@ public CompletableFuture deleteArticle(Long id) { article.ifPresent(articleRepository::delete); return article.isPresent(); }) - .exceptionally(ex -> { - return false; - }); + .exceptionally(ex -> ExceptionHandlerUtil.handleBooleanException(ex)); } } \ No newline at end of file diff --git a/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/util/ExceptionHandlerUtil.java b/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/util/ExceptionHandlerUtil.java new file mode 100644 index 0000000..824102f --- /dev/null +++ b/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/util/ExceptionHandlerUtil.java @@ -0,0 +1,23 @@ +package com.gsm._8th.class4.backed.task._1._1.util; + +import java.util.List; +import java.util.Optional; + +public class ExceptionHandlerUtil { + + public static T handleException(Throwable ex, T defaultValue) { + return defaultValue; + } + + public static Optional handleOptionalException(Throwable ex) { + return Optional.empty(); + } + + public static List handleListException(Throwable ex) { + return List.of(); + } + + public static Boolean handleBooleanException(Throwable ex) { + return false; + } +} \ No newline at end of file From 1e100e96b32e226db77487d230b414d93d965d00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=EC=9E=AC=EC=9A=B1?= Date: Sat, 22 Feb 2025 10:53:56 +0900 Subject: [PATCH 15/15] refector: remove Boilerplate code --- .../backed/task/_1/_1/controller/ArticleController.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/controller/ArticleController.java b/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/controller/ArticleController.java index bb8ffc8..efdafc5 100644 --- a/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/controller/ArticleController.java +++ b/src/main/java/com/gsm/_8th/class4/backed/task/_1/_1/controller/ArticleController.java @@ -3,6 +3,7 @@ import com.gsm._8th.class4.backed.task._1._1.domain.Article; import com.gsm._8th.class4.backed.task._1._1.dto.ArticleRequestDTO; import com.gsm._8th.class4.backed.task._1._1.service.ArticleService; +import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; @@ -12,14 +13,12 @@ @RestController @RequestMapping("/articles") +@RequiredArgsConstructor public class ArticleController { + @Qualifier("articleServiceImpl") private final ArticleService articleService; - public ArticleController(@Qualifier("articleServiceImpl") ArticleService articleService) { - this.articleService = articleService; - } - @GetMapping public CompletableFuture>> getAllArticles() { return articleService.getAllArticles().thenApply(ResponseEntity::ok);