From d96f7b3cfd215d9a8a69930ee06ccc9d10e22a6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EC=84=9D?= Date: Mon, 19 Aug 2024 02:27:50 +0900 Subject: [PATCH 1/3] =?UTF-8?q?feat=20:=203=EC=9D=BC=EB=82=B4=EC=97=90=20?= =?UTF-8?q?=EB=A7=8C=EB=93=A0=20=ED=86=A0=EB=A1=A0=EC=A4=91=EC=97=90,=20?= =?UTF-8?q?=EA=B0=80=EC=9E=A5=20=EC=A1=B0=ED=9A=8C=EC=88=98=EA=B0=80=20?= =?UTF-8?q?=EB=86=92=EC=9D=80=EA=B1=B8=20=EB=B0=98=ED=99=98=ED=95=98?= =?UTF-8?q?=EB=8F=84=EB=A1=9D=20=ED=95=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../itpick/backend/config/WebConfig.java | 2 +- .../backend/controller/DebateController.java | 8 ++++ .../dto/debate/DebateByKeywordDTO.java | 2 +- .../itpick/backend/model/TrendDebate.java | 28 ++++++++++++++ .../backend/repository/DebateRepository.java | 7 ++++ .../repository/TrendDebateRepository.java | 10 +++++ .../itpick/backend/service/DebateService.java | 37 +++++++++++++++++-- 7 files changed, 89 insertions(+), 5 deletions(-) create mode 100644 src/main/java/store/itpick/backend/model/TrendDebate.java create mode 100644 src/main/java/store/itpick/backend/repository/TrendDebateRepository.java diff --git a/src/main/java/store/itpick/backend/config/WebConfig.java b/src/main/java/store/itpick/backend/config/WebConfig.java index 2649f14..7e639e1 100644 --- a/src/main/java/store/itpick/backend/config/WebConfig.java +++ b/src/main/java/store/itpick/backend/config/WebConfig.java @@ -29,7 +29,7 @@ public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(jwtAuthenticationInterceptor) .order(1) .addPathPatterns("/**") - .excludePathPatterns("/auth/login", "/auth/signup", "/auth/refresh","/auth/emails/**", "/rank/**","/auth/email/check","/auth/nickname/check","/favicon.ico","/keyword/**","/debate/keyword", "/test/**"); + .excludePathPatterns("/auth/login", "/auth/signup", "/auth/refresh","/auth/emails/**", "/rank/**","/auth/email/check","/auth/nickname/check","/favicon.ico","/keyword/**","/debate/keyword", "/test/**","/debate/trend"); //인터셉터 적용 범위 수정 registry.addInterceptor(getJwtInterceptor) .addPathPatterns("/user/email"); diff --git a/src/main/java/store/itpick/backend/controller/DebateController.java b/src/main/java/store/itpick/backend/controller/DebateController.java index a08581b..40665dc 100644 --- a/src/main/java/store/itpick/backend/controller/DebateController.java +++ b/src/main/java/store/itpick/backend/controller/DebateController.java @@ -117,4 +117,12 @@ public BaseResponse deleteDebate(@PreAuthorize long userId, @PathVariable Lon debateService.deleteDebate(debateId,userId); return new BaseResponse<>(null); } + + + @GetMapping("/trend") + public BaseResponse> getTrendDebate(){ + List debateResponse = debateService.updateHotDebate(); + + return new BaseResponse<>(debateResponse); + } } diff --git a/src/main/java/store/itpick/backend/dto/debate/DebateByKeywordDTO.java b/src/main/java/store/itpick/backend/dto/debate/DebateByKeywordDTO.java index 789101d..ee12ab9 100644 --- a/src/main/java/store/itpick/backend/dto/debate/DebateByKeywordDTO.java +++ b/src/main/java/store/itpick/backend/dto/debate/DebateByKeywordDTO.java @@ -10,7 +10,7 @@ @Getter public class DebateByKeywordDTO { String title; - String content; + Long debateId; String mediaUrl; Long hit; Long comment; diff --git a/src/main/java/store/itpick/backend/model/TrendDebate.java b/src/main/java/store/itpick/backend/model/TrendDebate.java new file mode 100644 index 0000000..003422a --- /dev/null +++ b/src/main/java/store/itpick/backend/model/TrendDebate.java @@ -0,0 +1,28 @@ +package store.itpick.backend.model; + + +import jakarta.persistence.*; +import lombok.*; + +import java.sql.Timestamp; + +@Entity +@Table(name = "trend_debate") +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class TrendDebate { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "trend_debate_id") + private Long trendDebateId; + + @OneToOne + @JoinColumn(name = "debate_id", nullable = false) + private Debate debate; + + @Column(name = "update_at", nullable = false) + private Timestamp updateAt; +} diff --git a/src/main/java/store/itpick/backend/repository/DebateRepository.java b/src/main/java/store/itpick/backend/repository/DebateRepository.java index f117f4c..0c192b4 100644 --- a/src/main/java/store/itpick/backend/repository/DebateRepository.java +++ b/src/main/java/store/itpick/backend/repository/DebateRepository.java @@ -1,5 +1,6 @@ package store.itpick.backend.repository; +import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; @@ -8,6 +9,7 @@ import store.itpick.backend.model.Debate; import store.itpick.backend.model.User; +import java.sql.Timestamp; import java.util.List; import java.util.Optional; @@ -38,5 +40,10 @@ public interface DebateRepository extends JpaRepository { Optional getDebateByDebateId(Long debateId); + @Query("SELECT d FROM Debate d " + + "WHERE d.createAt >= :startTime " + + "ORDER BY d.hits DESC") + List findTop3DebatesCreatedInLast3Days(@Param("startTime") Timestamp startTime, Pageable pageable); + } diff --git a/src/main/java/store/itpick/backend/repository/TrendDebateRepository.java b/src/main/java/store/itpick/backend/repository/TrendDebateRepository.java new file mode 100644 index 0000000..d90380c --- /dev/null +++ b/src/main/java/store/itpick/backend/repository/TrendDebateRepository.java @@ -0,0 +1,10 @@ +package store.itpick.backend.repository; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; +import store.itpick.backend.model.TrendDebate; + +@Repository +public interface TrendDebateRepository extends JpaRepository { + void deleteAll(); +} diff --git a/src/main/java/store/itpick/backend/service/DebateService.java b/src/main/java/store/itpick/backend/service/DebateService.java index 987c440..40879a0 100644 --- a/src/main/java/store/itpick/backend/service/DebateService.java +++ b/src/main/java/store/itpick/backend/service/DebateService.java @@ -3,6 +3,7 @@ import jakarta.transaction.Transactional; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.data.domain.PageRequest; import org.springframework.stereotype.Service; import store.itpick.backend.common.exception.DebateException; import store.itpick.backend.common.exception.AuthException; @@ -41,6 +42,7 @@ public class DebateService { private final JwtProvider jwtProvider; private final S3ImageBucketService s3ImageBucketService; private final RecentViewedDebateRepository recentViewedDebateRepository; + private final TrendDebateRepository trendDebateRepository; @Transactional public PostDebateResponse createDebate(PostDebateRequest postDebateRequest, long userId) { @@ -230,11 +232,11 @@ public List GetDebatesByKeyword(Long keywordID, String sort) for (Debate debate : debates) { if(debate.getStatus().equals("active")){ String title= debate.getTitle(); - String content =debate.getContent(); + Long debateId =debate.getDebateId(); String mediaUrl =debate.getImageUrl(); Long hit = debate.getHits(); Long comment = (long) debate.getComment().size(); - debateList.add(new DebateByKeywordDTO(title,content,mediaUrl,hit,comment)); + debateList.add(new DebateByKeywordDTO(title,debateId,mediaUrl,hit,comment)); } } @@ -267,7 +269,7 @@ public List getRecentViewedDebate(long userId){ // Debate를 DTO로 변환 return debates.stream() .filter(debate -> "active".equals(debate.getStatus())) - .map(debate -> new DebateByKeywordDTO(debate.getTitle(), debate.getContent(), debate.getImageUrl(),debate.getHits(), (long) debate.getComment().size())) + .map(debate -> new DebateByKeywordDTO(debate.getTitle(), debate.getDebateId(), debate.getImageUrl(),debate.getHits(), (long) debate.getComment().size())) .collect(Collectors.toList()); } @@ -294,4 +296,33 @@ public void deleteDebate(Long debateId, long userId) { } + @Transactional + public List updateHotDebate() { + // 현재 시간 및 48시간 전 시간 계산 + Timestamp endTime = new Timestamp(System.currentTimeMillis()); + Timestamp startTime = new Timestamp(endTime.getTime() - 3 * 24 * 60 * 60 * 1000); // 3일 전 시간 + PageRequest pageRequest = PageRequest.of(0, 3); // 상위 3개만 가져오기 + + // 기존의 TrendDebate 삭제 + trendDebateRepository.deleteAllInBatch(); + + // 48시간 동안 조회수가 가장 많이 오른 상위 3개의 Debate 조회 + List debateList = debateRepository.findTop3DebatesCreatedInLast3Days(startTime, pageRequest); + List debates = new ArrayList<>(); + + // 새로운 TrendDebate 엔트리 삽입 + for (Debate debate : debateList) { + TrendDebate trendDebate = TrendDebate.builder() + .debate(debate) + .updateAt(endTime) // 업데이트된 시간 저장 + .build(); + + trendDebateRepository.save(trendDebate); + + debates.add(new DebateByKeywordDTO(debate.getTitle(), debate.getDebateId(), debate.getImageUrl(), debate.getHits(), (long) debate.getComment().size())); + } + + return debates; + } + } From bfda473a6d47047ce48da3100424886405be9bcd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EC=84=9D?= Date: Mon, 19 Aug 2024 14:11:42 +0900 Subject: [PATCH 2/3] =?UTF-8?q?feat=20:=20=EB=A7=A4=EC=8B=9C=2030=EB=B6=84?= =?UTF-8?q?=20=EB=A7=88=EB=8B=A4=20=EC=8A=A4=EC=BC=80=EC=A4=84=EB=9F=AC=20?= =?UTF-8?q?=EC=9E=91=EB=8F=99=ED=95=98=EB=8F=84=EB=A1=9D=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../backend/controller/DebateController.java | 2 +- .../itpick/backend/service/DebateService.java | 29 +++++++++++++++++-- .../backend/service/SchedulerService.java | 6 ++++ 3 files changed, 33 insertions(+), 4 deletions(-) diff --git a/src/main/java/store/itpick/backend/controller/DebateController.java b/src/main/java/store/itpick/backend/controller/DebateController.java index 40665dc..61211fd 100644 --- a/src/main/java/store/itpick/backend/controller/DebateController.java +++ b/src/main/java/store/itpick/backend/controller/DebateController.java @@ -121,7 +121,7 @@ public BaseResponse deleteDebate(@PreAuthorize long userId, @PathVariable Lon @GetMapping("/trend") public BaseResponse> getTrendDebate(){ - List debateResponse = debateService.updateHotDebate(); + List debateResponse = debateService.getHotDebate(); return new BaseResponse<>(debateResponse); } diff --git a/src/main/java/store/itpick/backend/service/DebateService.java b/src/main/java/store/itpick/backend/service/DebateService.java index 40879a0..75f4c97 100644 --- a/src/main/java/store/itpick/backend/service/DebateService.java +++ b/src/main/java/store/itpick/backend/service/DebateService.java @@ -297,7 +297,7 @@ public void deleteDebate(Long debateId, long userId) { } @Transactional - public List updateHotDebate() { + public void updateHotDebate() { // 현재 시간 및 48시간 전 시간 계산 Timestamp endTime = new Timestamp(System.currentTimeMillis()); Timestamp startTime = new Timestamp(endTime.getTime() - 3 * 24 * 60 * 60 * 1000); // 3일 전 시간 @@ -308,7 +308,6 @@ public List updateHotDebate() { // 48시간 동안 조회수가 가장 많이 오른 상위 3개의 Debate 조회 List debateList = debateRepository.findTop3DebatesCreatedInLast3Days(startTime, pageRequest); - List debates = new ArrayList<>(); // 새로운 TrendDebate 엔트리 삽입 for (Debate debate : debateList) { @@ -319,9 +318,33 @@ public List updateHotDebate() { trendDebateRepository.save(trendDebate); - debates.add(new DebateByKeywordDTO(debate.getTitle(), debate.getDebateId(), debate.getImageUrl(), debate.getHits(), (long) debate.getComment().size())); } + } + + @Transactional + public List getHotDebate() { + + // TrendDebate 테이블에서 현재 저장된 Debate 3개를 가져옵니다. + List trendDebates = trendDebateRepository.findAll(); + + // DebateByKeywordDTO 리스트 초기화 + List debates = new ArrayList<>(); + + // TrendDebate에 있는 Debate를 DebateByKeywordDTO로 변환하여 리스트에 추가 + for (TrendDebate trendDebate : trendDebates) { + Debate debate = trendDebate.getDebate(); + DebateByKeywordDTO debateDTO = new DebateByKeywordDTO( + debate.getTitle(), + debate.getDebateId(), + debate.getImageUrl(), + debate.getHits(), + (long) debate.getComment().size() + ); + debates.add(debateDTO); + } + + // 최종 리스트 반환 return debates; } diff --git a/src/main/java/store/itpick/backend/service/SchedulerService.java b/src/main/java/store/itpick/backend/service/SchedulerService.java index e296c19..b7e1624 100644 --- a/src/main/java/store/itpick/backend/service/SchedulerService.java +++ b/src/main/java/store/itpick/backend/service/SchedulerService.java @@ -24,6 +24,7 @@ public class SchedulerService { private final SeleniumService seleniumService; private final KeywordService keywordService; + private final DebateService debateService; private final Redis redis; @@ -147,4 +148,9 @@ public void performWeeklyTasks() { log.info("Weekly task completed."); } + @Scheduled(cron = "0 30 * * * *") + public void updateTrendDebate(){ + debateService.updateHotDebate(); + } + } From 1b72591ea93e6892f78708b51f6914a9e2c56c6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EC=84=9D?= Date: Mon, 19 Aug 2024 15:08:44 +0900 Subject: [PATCH 3/3] feat : https://deploy-preview-99--itpick.netlify.app/ --- src/main/java/store/itpick/backend/config/WebConfig.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/store/itpick/backend/config/WebConfig.java b/src/main/java/store/itpick/backend/config/WebConfig.java index 4301a68..1513954 100644 --- a/src/main/java/store/itpick/backend/config/WebConfig.java +++ b/src/main/java/store/itpick/backend/config/WebConfig.java @@ -47,7 +47,7 @@ public void addArgumentResolvers(List resolvers) public void addCorsMappings(CorsRegistry registry) { log.info("CorsMapping이 호출 되었습니다."); registry.addMapping("/**") - .allowedOrigins("http://localhost:3000", "http://localhost:5173", "https://localhost:5173", "https://itpick.netlify.app","https://itpick.vercel.app","https://deploy-preview-85--itpick.netlify.app") + .allowedOrigins("http://localhost:3000", "http://localhost:5173", "https://localhost:5173", "https://itpick.netlify.app","https://itpick.vercel.app","https://deploy-preview-85--itpick.netlify.app","https://deploy-preview-99--itpick.netlify.app") .allowedMethods("GET", "POST", "PUT", "DELETE", "PATCH","OPTIONS") .exposedHeaders("location", "Authorization") .allowedHeaders("Content-Type", "Authorization", "X-Requested-With", "Accept")