Skip to content

Commit

Permalink
Merge pull request #203 from shared-solutions/feat#201
Browse files Browse the repository at this point in the history
#201 Feat : RedisRepositoryConfig 템플릿 재정의(Object형), Redis에 Queue로 데이터 저장, 10개까지 조회
  • Loading branch information
ls-rain authored Aug 18, 2024
2 parents 630643a + 3e6ae8d commit 8673f76
Show file tree
Hide file tree
Showing 10 changed files with 139 additions and 11 deletions.
28 changes: 27 additions & 1 deletion src/main/java/friend/spring/config/RedisRepositoryConfig.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
package friend.spring.config;

import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.jsontype.BasicPolymorphicTypeValidator;
import com.fasterxml.jackson.databind.jsontype.PolymorphicTypeValidator;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
Expand All @@ -8,6 +14,7 @@
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.repository.configuration.EnableRedisRepositories;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

@RequiredArgsConstructor
Expand Down Expand Up @@ -38,4 +45,23 @@ public RedisTemplate<String, Object> redisTemplate() {
redisTemplate.setConnectionFactory(redisConnectionFactory());
return redisTemplate;
}
}

@Bean
public RedisTemplate<String, Object> objectRedisTemplate(RedisConnectionFactory redisConnectionFactory){
PolymorphicTypeValidator ptv = BasicPolymorphicTypeValidator
.builder()
.allowIfSubType(Object.class)
.build();
ObjectMapper objectMapper = new ObjectMapper()
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
.activateDefaultTyping(ptv, ObjectMapper.DefaultTyping.NON_FINAL)
.registerModule(new JavaTimeModule())
.disable(SerializationFeature.WRITE_DATE_KEYS_AS_TIMESTAMPS);

RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory());
template.setKeySerializer(new StringRedisSerializer());
template.setValueSerializer(new GenericJackson2JsonRedisSerializer(objectMapper));
return template;
}
}
15 changes: 15 additions & 0 deletions src/main/java/friend/spring/converter/PostConverter.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package friend.spring.converter;

import friend.spring.domain.*;
import friend.spring.domain.Redis.SearchLog;
import friend.spring.domain.enums.PostState;
import friend.spring.domain.enums.PostType;
import friend.spring.domain.enums.PostVoteType;
Expand Down Expand Up @@ -1047,6 +1048,20 @@ public static PostResponseDTO.PostSearchList PostSearchListDTO(Page<Post> postLi
.isEnd(postList.isLast())
.build();
}

public static PostResponseDTO.RecentSearchRes toRecentSearchRes(List<SearchLog> recentSearchLogs){
List<PostResponseDTO.SearchLog> searchLogList = recentSearchLogs.stream().map(PostConverter::toSearchLog).collect(Collectors.toList());
return PostResponseDTO.RecentSearchRes.builder()
.recentSearchList(searchLogList)
.build();
}

public static PostResponseDTO.SearchLog toSearchLog(SearchLog searchLog){
return PostResponseDTO.SearchLog.builder()
.name(searchLog.getName())
.createdAt(searchLog.getCreatedAt())
.build();
}
}


15 changes: 15 additions & 0 deletions src/main/java/friend/spring/domain/Redis/SearchLog.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package friend.spring.domain.Redis;

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

@AllArgsConstructor
@NoArgsConstructor
@Builder
@Getter
public class SearchLog {
private String name;
private String createdAt;
}
7 changes: 4 additions & 3 deletions src/main/java/friend/spring/service/PostQueryService.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
package friend.spring.service;

import friend.spring.domain.Post;
import friend.spring.web.dto.PostRequestDTO;
import friend.spring.web.dto.PostResponseDTO;
import friend.spring.domain.Redis.SearchLog;
import org.springframework.data.domain.Page;

import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Optional;

public interface PostQueryService {
Expand All @@ -22,6 +22,7 @@ public interface PostQueryService {
Page<Post> getReviewList(Integer page, Integer size, Integer arrange);

Page<Post> getParentPostList(Integer page, Integer size, HttpServletRequest request);
Page<Post> getPostSearch(Integer page, Integer size, String search);
Page<Post> getPostSearch(Long userId,Integer page, Integer size, String search);
List<SearchLog> getRecentSearchLogs(Long userId);

}
30 changes: 29 additions & 1 deletion src/main/java/friend/spring/service/PostQueryServiceImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import friend.spring.apiPayload.code.status.ErrorStatus;
import friend.spring.converter.PostConverter;
import friend.spring.domain.*;
import friend.spring.domain.Redis.SearchLog;
import friend.spring.domain.enums.PostState;
import friend.spring.domain.enums.PostType;
import friend.spring.domain.enums.PostVoteType;
Expand All @@ -14,6 +15,7 @@
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.*;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

Expand All @@ -24,6 +26,8 @@
import java.util.Optional;
import java.util.stream.Collectors;

import static friend.spring.apiPayload.code.status.ErrorStatus.USER_NOT_FOUND;

@Service
@RequiredArgsConstructor
public class PostQueryServiceImpl implements PostQueryService {
Expand All @@ -34,6 +38,7 @@ public class PostQueryServiceImpl implements PostQueryService {
private final Card_VoteRepository cardVoteRepository;
private final CategoryRepository categoryRepository;
private final JwtTokenProvider jwtTokenProvider;
private final RedisTemplate<String, Object> objectRedisTemplate;

@Override
@Transactional
Expand Down Expand Up @@ -145,8 +150,31 @@ public Page<Post> getParentPostList(Integer page, Integer size, HttpServletReque

@Override
@Transactional
public Page<Post> getPostSearch(Integer page, Integer size, String search) {
public Page<Post> getPostSearch(Long userId,Integer page, Integer size, String search) {
Pageable pageable = PageRequest.of(page, size, Sort.by(Sort.Direction.DESC, "createdAt"));
User user = userRepository.findById(userId).orElseThrow(() -> new GeneralException(USER_NOT_FOUND));
String now = LocalDateTime.now().toString();
String key = "CurrentSearch" + user.getId();
SearchLog value = SearchLog.builder()
.name(search)
.createdAt(now)
.build();
Long redisSize = objectRedisTemplate.opsForList().size(key);
if(redisSize == 10){
objectRedisTemplate.opsForList().rightPop(key);
}
objectRedisTemplate.opsForList().leftPush(key, value);
return postRepository.findByKeyWord(search, pageable);
}

public List<SearchLog> getRecentSearchLogs(Long userId) {
User user = userRepository.findById(userId)
.orElseThrow(() -> new GeneralException(USER_NOT_FOUND));

String key = "CurrentSearch" + user.getId();
List<Object> objLogs = objectRedisTemplate.opsForList().
range(key, 0, 10);
List<SearchLog> searchLogs = objLogs.stream().map(i -> (SearchLog) i).collect(Collectors.toList());
return searchLogs;
}
}
2 changes: 2 additions & 0 deletions src/main/java/friend/spring/service/PostService.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import friend.spring.web.dto.CandidateRequestDTO;
import friend.spring.web.dto.PostRequestDTO;
import friend.spring.web.dto.PostResponseDTO;
import friend.spring.web.dto.UserRequestDTO;
import org.springframework.data.domain.Page;

import javax.servlet.http.HttpServletRequest;
Expand Down Expand Up @@ -49,6 +50,7 @@ public interface PostService {

void deleteScrapPost(Long postId, HttpServletRequest request);


PostResponseDTO.ReportResult createReportPost(Long postId, PostRequestDTO.PostReportReq request, HttpServletRequest request2);

}
3 changes: 2 additions & 1 deletion src/main/java/friend/spring/service/PostServiceImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import friend.spring.apiPayload.handler.UserHandler;
import friend.spring.converter.PostConverter;
import friend.spring.domain.*;
import friend.spring.domain.Redis.SearchLog;
import friend.spring.domain.enums.PostState;
import friend.spring.domain.enums.PostType;
import friend.spring.domain.enums.ReportType;
Expand All @@ -17,6 +18,7 @@
import friend.spring.web.dto.*;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.*;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

Expand Down Expand Up @@ -459,7 +461,6 @@ public Post_scrap createScrapPost(Long postId, HttpServletRequest request) {
@Override
public void deleteScrapPost(Long postId, HttpServletRequest request) {
Long userId = jwtTokenProvider.getCurrentUser(request);

Optional<Post> optionalPost = postRepository.findById(postId);
if (optionalPost.isEmpty()) {
this.checkPost(false);
Expand Down
21 changes: 18 additions & 3 deletions src/main/java/friend/spring/web/controller/PostRestController.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import friend.spring.converter.PostConverter;
import friend.spring.domain.Candidate;
import friend.spring.domain.Post;
import friend.spring.domain.Redis.SearchLog;
import friend.spring.repository.PostRepository;
import friend.spring.service.JwtTokenService;
import friend.spring.service.PostQueryService;
Expand All @@ -25,6 +26,7 @@
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.io.IOException;
import java.util.List;

@RestController
@RequiredArgsConstructor
Expand Down Expand Up @@ -334,15 +336,28 @@ public ApiResponse<PostResponseDTO.PostReportRes> createReportPost(
@Parameter(name = "page", description = "query string(RequestParam) - 몇번째 페이지인지 가리키는 page 변수 입니다! (0부터 시작)"),
@Parameter(name = "size", description = "query string(RequestParam) - 몇 개씩 불러올지 개수를 세는 변수입니다. (1 이상 자연수로 설정)"),
@Parameter(name = "atk", description = "RequestHeader - 로그인한 사용자의 accessToken"),
@Parameter(name = "search", description = "query string(RequestParam) - 검색어.")
@Parameter(name = "keyword", description = "query string(RequestParam) - 검색어.")
})
public ApiResponse<PostResponseDTO.PostSearchList> getPostSearch(@RequestParam(name = "page", defaultValue = "0") Integer page,
@RequestParam(name = "size", defaultValue = "15") Integer size,
@RequestParam(name = "search") String search,
@RequestParam(name = "keyword") String keyword,
@RequestHeader("atk") String atk,
HttpServletRequest request2) {
Long userId = jwtTokenService.JwtToId(request2);
Page<Post> postPage = postQueryService.getPostSearch(page, size, search);
Page<Post> postPage = postQueryService.getPostSearch(userId,page, size, keyword);
return ApiResponse.onSuccess(PostConverter.PostSearchListDTO(postPage, userId));
}

@GetMapping("/post/search/recent-log")
@Operation(summary = "최근 검색어 목록 조회 API", description = "최신순으로 검색어 목록을 최대 10개까지 조회합니다.")
@Parameters({
@Parameter(name = "atk", description = "RequestHeader - 로그인한 사용자의 accessToken"),
})
public ApiResponse<PostResponseDTO.RecentSearchRes> getRecentSearch(@RequestHeader("atk") String atk,
HttpServletRequest request){
Long userId = jwtTokenService.JwtToId(request);
List<SearchLog> recentSearchLogs = postQueryService.getRecentSearchLogs(userId);
return ApiResponse.onSuccess(PostConverter.toRecentSearchRes(recentSearchLogs));

}
}
21 changes: 19 additions & 2 deletions src/main/java/friend/spring/web/dto/PostResponseDTO.java
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,15 @@ public static class PostSearchRes{
Boolean isLike;
Boolean isComment;
}


@Builder
@Getter
@NoArgsConstructor
@AllArgsConstructor
public static class RecentSearchRes {
List<SearchLog> recentSearchList;
}

@Builder
@Getter
@NoArgsConstructor
Expand All @@ -199,7 +207,16 @@ public static class PostReportRes {
@Getter
@NoArgsConstructor
@AllArgsConstructor
public static class ReportResult {
public static class SearchLog{
private String name;
private String createdAt;
}

@Builder
@Getter
@NoArgsConstructor
@AllArgsConstructor
public static class ReportResult{
Report report;
Boolean duplicatedReport;
}
Expand Down
8 changes: 8 additions & 0 deletions src/main/java/friend/spring/web/dto/UserRequestDTO.java
Original file line number Diff line number Diff line change
Expand Up @@ -142,4 +142,12 @@ public static class PasswordUpdateReq {
public static class Delete {
private String email;
}
@NoArgsConstructor
@AllArgsConstructor
@Getter
@Setter
public static class SearchReq{
private String name;
private String createdAt;
}
}

0 comments on commit 8673f76

Please sign in to comment.