From 1c15b1c09f91e5e5e18d88854a93a5bfd49cda3e Mon Sep 17 00:00:00 2001 From: donsonioc2010 Date: Wed, 18 Oct 2023 16:54:23 +0900 Subject: [PATCH 1/3] =?UTF-8?q?feat=20:=20=EA=B8=B0=EB=8A=A5=EA=B5=AC?= =?UTF-8?q?=ED=98=84=20#54?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 최근 7일간의 게시물에 대해서 LikeCount가 높은 순으로 게시물 리스트를 가져온다. - QueryString 없을 시 10건만 가져온다. - 특정 BoardId의 게시물만 가져온다. - 메인페이지에서 쓰려고 만들었다. - Mapping추가에 따른 Security 변경 --- .../board/controller/ArticleController.java | 21 ++++++++++++++ .../board/dto/PopularArticleResponse.java | 14 +++++++++ .../board/repository/ArticleRepository.java | 5 +++- .../server/board/service/ArticleService.java | 29 +++++++++++++++++++ .../config/security/SecurityConfig.java | 1 + 5 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 src/main/java/HookKiller/server/board/dto/PopularArticleResponse.java diff --git a/src/main/java/HookKiller/server/board/controller/ArticleController.java b/src/main/java/HookKiller/server/board/controller/ArticleController.java index fd9f061..8fb7385 100644 --- a/src/main/java/HookKiller/server/board/controller/ArticleController.java +++ b/src/main/java/HookKiller/server/board/controller/ArticleController.java @@ -1,6 +1,7 @@ package HookKiller.server.board.controller; import HookKiller.server.board.dto.ArticleRequestDto; +import HookKiller.server.board.dto.PopularArticleResponse; import HookKiller.server.board.dto.PostArticleRequestDto; import HookKiller.server.board.service.ArticleService; import HookKiller.server.board.type.ArticleConstants; @@ -78,4 +79,24 @@ public ResponseEntity deleteArticle(@PathVariable L return ResponseEntity.ok(articleService.deleteArticle(articleId)); } + /** + * 최근 7일간의 추천이 많았던 게시물에 대해서 확인이 가능하다. + * @param boardId 조회를 희망하는 BoardId + * @param page + * @param limit + * @param request + * @return + */ + @GetMapping("/popular/{boardId}") + public ResponseEntity> getPopularArticlesByBoardId( + @PathVariable Long boardId, + @RequestParam(defaultValue = "0", required = false) int page, + @RequestParam(defaultValue = "10", required = false) int limit, + HttpServletRequest request + ) { + return ResponseEntity.ok( + articleService.getPopularArticlesByBoardId(page, limit, boardId, LanguageType.findTypeByRequest(request)) + ); + } + } diff --git a/src/main/java/HookKiller/server/board/dto/PopularArticleResponse.java b/src/main/java/HookKiller/server/board/dto/PopularArticleResponse.java new file mode 100644 index 0000000..01b8851 --- /dev/null +++ b/src/main/java/HookKiller/server/board/dto/PopularArticleResponse.java @@ -0,0 +1,14 @@ +package HookKiller.server.board.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; + +@Getter +@Builder +@AllArgsConstructor +public class PopularArticleResponse { + private Long articleId; + private String title; + +} diff --git a/src/main/java/HookKiller/server/board/repository/ArticleRepository.java b/src/main/java/HookKiller/server/board/repository/ArticleRepository.java index fc0d1c2..06ea4d5 100644 --- a/src/main/java/HookKiller/server/board/repository/ArticleRepository.java +++ b/src/main/java/HookKiller/server/board/repository/ArticleRepository.java @@ -11,6 +11,7 @@ import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; +import java.sql.Timestamp; import java.util.Optional; @@ -20,7 +21,9 @@ public interface ArticleRepository extends JpaRepository { Page
findAllByBoardAndArticleStatusOrderByCreateAtDesc(Board board, ArticleStatus status, Pageable pageable); Page
findAllByCreatedUserOrderByCreateAtDesc(User user, Pageable pageable); - + + Page
findAllByBoardAndCreateAtBetweenOrderByLikeCountDesc(Board board, Timestamp startTimestamp, Timestamp endTimestamp, Pageable pageable); + @Query( value = "select a.id, u.nick_name as nickName, ac.title, ac.content, a.like_count as likeCount " + "from tbl_article a " + diff --git a/src/main/java/HookKiller/server/board/service/ArticleService.java b/src/main/java/HookKiller/server/board/service/ArticleService.java index 88fa440..358e8cf 100644 --- a/src/main/java/HookKiller/server/board/service/ArticleService.java +++ b/src/main/java/HookKiller/server/board/service/ArticleService.java @@ -1,6 +1,7 @@ package HookKiller.server.board.service; import HookKiller.server.board.dto.ArticleRequestDto; +import HookKiller.server.board.dto.PopularArticleResponse; import HookKiller.server.board.dto.PostArticleRequestDto; import HookKiller.server.board.entity.Article; import HookKiller.server.board.entity.ArticleContent; @@ -25,6 +26,10 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.sql.Timestamp; +import java.time.Instant; +import java.time.LocalDateTime; +import java.time.ZoneId; import java.util.ArrayList; import java.util.List; @@ -219,4 +224,28 @@ public CommonBooleanResultResponse deleteArticle(Long articleId) { } return CommonBooleanResultResponse.builder().result(false).message(ArticleConstants.ARTICLE_DELETE_FAIL_RTN_MSG).build(); } + + public List getPopularArticlesByBoardId(int page, int limit, Long boardId, LanguageType language) { + // 현재 시간을 가져와 Timestamp로 변환 + Instant currentInstant = Instant.now(); + Timestamp currentTimestamp = Timestamp.from(currentInstant); + + // 7일 전의 시간을 계산하고 Timestamp로 변환 + LocalDateTime sevenDaysAgo = LocalDateTime.now().minusDays(7); + Instant sevenDaysAgoInstant = sevenDaysAgo.atZone(ZoneId.systemDefault()).toInstant(); + Timestamp sevenDaysAgoTimestamp = Timestamp.from(sevenDaysAgoInstant); + + Board board = boardRepository.findById(boardId).orElseThrow(() -> BoardNotFoundException.EXCEPTION); + + return articleRepository.findAllByBoardAndCreateAtBetweenOrderByLikeCountDesc(board ,sevenDaysAgoTimestamp, currentTimestamp, PageRequest.of(page, limit)) + .stream() + .map(article -> { + ArticleContent content = articleContentRepository.findByArticleAndLanguage(article, language).orElseThrow(() -> ArticleContentNotFoundException.EXCEPTION); + return PopularArticleResponse.builder() + .articleId(article.getId()) + .title(content.getTitle()) + .build(); + }) + .toList(); + } } diff --git a/src/main/java/HookKiller/server/config/security/SecurityConfig.java b/src/main/java/HookKiller/server/config/security/SecurityConfig.java index 140545b..0f6b343 100644 --- a/src/main/java/HookKiller/server/config/security/SecurityConfig.java +++ b/src/main/java/HookKiller/server/config/security/SecurityConfig.java @@ -39,6 +39,7 @@ public class SecurityConfig { "/article/list/{boardId}", "/article/{articleId}", + "/article/popular/{boardId}", "/reply/{articleId}", }); From 4c355d4b5db12333273b4240f83d71aa0016a7b1 Mon Sep 17 00:00:00 2001 From: donsonioc2010 Date: Wed, 18 Oct 2023 16:55:26 +0900 Subject: [PATCH 2/3] =?UTF-8?q?fix=20:=20Feign=20=EC=88=98=EC=A0=95?= =?UTF-8?q?=EC=82=AC=ED=95=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - ObjectMapper Bean에서 낮추고, 내부 메소드에서 불러오는 방향으로 변경 - Spring의 ObjectMapper는 냅두기로... ObjectMapper 변경으로 인한 이슈발생으로 인한 수정 --- .../HookKiller/server/config/feign/FeignCommonConfig.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/main/java/HookKiller/server/config/feign/FeignCommonConfig.java b/src/main/java/HookKiller/server/config/feign/FeignCommonConfig.java index 06c1a60..9daa3cd 100644 --- a/src/main/java/HookKiller/server/config/feign/FeignCommonConfig.java +++ b/src/main/java/HookKiller/server/config/feign/FeignCommonConfig.java @@ -17,11 +17,10 @@ public class FeignCommonConfig { @Bean - public Decoder feignDecoder(ObjectMapper customObjectMapper) { - return new JacksonDecoder(customObjectMapper); + public Decoder feignDecoder() { + return new JacksonDecoder(customObjectMapper()); } - @Bean public ObjectMapper customObjectMapper() { ObjectMapper objectMapper = new ObjectMapper(); objectMapper.registerModule(new JavaTimeModule()); From a985171f89a2217bcb23b769b8cb686d94e9f23f Mon Sep 17 00:00:00 2001 From: donsonioc2010 Date: Wed, 18 Oct 2023 17:17:44 +0900 Subject: [PATCH 3/3] =?UTF-8?q?fix=20:=20=EC=A0=84=EC=B2=B4=EA=B2=8C?= =?UTF-8?q?=EC=8B=9C=EB=AC=BC=EC=9D=B4=20=EC=95=84=EB=8B=8C=20=EA=B3=B5?= =?UTF-8?q?=EA=B0=9C=EB=90=9C=20=EA=B2=8C=EC=8B=9C=EB=AC=BC=EB=A7=8C=20?= =?UTF-8?q?=EA=B0=80=EC=A0=B8=EC=98=A4=EB=8F=84=EB=A1=9D=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../HookKiller/server/board/repository/ArticleRepository.java | 4 +++- .../java/HookKiller/server/board/service/ArticleService.java | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/main/java/HookKiller/server/board/repository/ArticleRepository.java b/src/main/java/HookKiller/server/board/repository/ArticleRepository.java index 06ea4d5..eb06864 100644 --- a/src/main/java/HookKiller/server/board/repository/ArticleRepository.java +++ b/src/main/java/HookKiller/server/board/repository/ArticleRepository.java @@ -22,7 +22,9 @@ public interface ArticleRepository extends JpaRepository { Page
findAllByCreatedUserOrderByCreateAtDesc(User user, Pageable pageable); - Page
findAllByBoardAndCreateAtBetweenOrderByLikeCountDesc(Board board, Timestamp startTimestamp, Timestamp endTimestamp, Pageable pageable); + Page
findAllByBoardAndArticleStatusAndCreateAtBetweenOrderByLikeCountDesc( + Board board, ArticleStatus status, Timestamp startTimestamp, Timestamp endTimestamp, Pageable pageable + ); @Query( value = "select a.id, u.nick_name as nickName, ac.title, ac.content, a.like_count as likeCount " + diff --git a/src/main/java/HookKiller/server/board/service/ArticleService.java b/src/main/java/HookKiller/server/board/service/ArticleService.java index 358e8cf..674095e 100644 --- a/src/main/java/HookKiller/server/board/service/ArticleService.java +++ b/src/main/java/HookKiller/server/board/service/ArticleService.java @@ -237,7 +237,8 @@ public List getPopularArticlesByBoardId(int page, int li Board board = boardRepository.findById(boardId).orElseThrow(() -> BoardNotFoundException.EXCEPTION); - return articleRepository.findAllByBoardAndCreateAtBetweenOrderByLikeCountDesc(board ,sevenDaysAgoTimestamp, currentTimestamp, PageRequest.of(page, limit)) + return articleRepository + .findAllByBoardAndArticleStatusAndCreateAtBetweenOrderByLikeCountDesc(board , PUBLIC, sevenDaysAgoTimestamp, currentTimestamp, PageRequest.of(page, limit)) .stream() .map(article -> { ArticleContent content = articleContentRepository.findByArticleAndLanguage(article, language).orElseThrow(() -> ArticleContentNotFoundException.EXCEPTION);