This repository has been archived by the owner on Aug 13, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
#29 게시글 검색시 @Cacheable을 사용하여 RedisCache 적용
- redisTemplate json 형식 받을시 값이 깨지지 않게 직렬화하고 클래스 여러개 사용 가능한 bean 등록 - CategoryDTO builder 적용 - ProductSearchController 검색시 초기 캐싱된 게시글로 조회되게 변경 - 사용하지않는 UserDTO RedisHash 삭제 - ProductSearchMapper selectProducts 인자 ProductDTO -> productStatus 변경 - ProductSearchServiceImpl init함수에서 게시글 최대 2000개 redisTemplate에 push - addRedisKeys, findAllProductsByCacheId 게시글 추가시 캐시 추가하는 함수, 캐싱되어있는 게시글 반환 함수 추가 - RedisKeyFactory redisTemplate 에 key 저장시 종류에따라 key반환하는 클래스 생성
- Loading branch information
Showing
10 changed files
with
172 additions
and
23 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
106 changes: 101 additions & 5 deletions
106
src/main/java/com/market/server/service/Impl/ProductSearchServiceImpl.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,27 +1,123 @@ | ||
package com.market.server.service.Impl; | ||
|
||
import com.fasterxml.jackson.databind.ObjectMapper; | ||
import com.market.server.dto.CategoryDTO; | ||
import com.market.server.dto.ProductDTO; | ||
import com.market.server.mapper.ProductSearchMapper; | ||
import com.market.server.service.ProductSearchService; | ||
import com.market.server.utils.RedisKeyFactory; | ||
import lombok.extern.log4j.Log4j2; | ||
import org.springframework.beans.factory.annotation.Autowired; | ||
import org.springframework.cache.annotation.Cacheable; | ||
import org.springframework.beans.factory.annotation.Value; | ||
import org.springframework.data.redis.core.RedisTemplate; | ||
import org.springframework.stereotype.Service; | ||
import javax.annotation.PostConstruct; | ||
import java.util.List; | ||
import java.util.concurrent.TimeUnit; | ||
import java.util.stream.Collectors; | ||
|
||
@Service | ||
@Log4j2 | ||
public class ProductSearchServiceImpl implements ProductSearchService { | ||
|
||
private final ProductSearchMapper productSearchMapper; | ||
private static final int DEFAULT_SEARCH_CATEGORY_ID = 1; | ||
private static final int DEFAULT_PRODUCT_CACHE_COUNT = 2000; | ||
private static final String DEFAULT_SEARCH_CATEGORY_NAME = CategoryDTO.SortStatus.CATEGORIES.toString(); | ||
public static final String DEFAULT_PRODUCT_CACHE_KEY = "noLogin"; | ||
|
||
@Autowired | ||
private RedisTemplate<String, Object> redisTemplate; | ||
|
||
@Autowired | ||
private ProductSearchMapper productSearchMapper; | ||
private ObjectMapper objectMapper; | ||
|
||
@Value("${expire.products}") | ||
private long productsExpireSecond; | ||
|
||
public ProductSearchServiceImpl(ProductSearchMapper productSearchMapper) | ||
{ | ||
this.productSearchMapper = productSearchMapper; | ||
|
||
} | ||
|
||
// 상위 2000개 게시글을 redisTemplate에 push | ||
@PostConstruct | ||
public void init() { | ||
System.out.println("ProductSearchServiceImpl @PostConstruct init redisTemplate에 push"); | ||
|
||
CategoryDTO categoryDTO = CategoryDTO.builder() | ||
.id(DEFAULT_SEARCH_CATEGORY_ID) | ||
.name(DEFAULT_SEARCH_CATEGORY_NAME) | ||
.sortStatus(CategoryDTO.SortStatus.NEWEST) | ||
.searchCount(DEFAULT_PRODUCT_CACHE_COUNT) | ||
.pagingStartOffset(CategoryDTO.PAGING_OFFSET) | ||
.build(); | ||
|
||
List<ProductDTO> productDTOList = productSearchMapper.selectProducts(ProductDTO.Status.NEW.toString(),categoryDTO); | ||
|
||
for (ProductDTO productDTO : productDTOList) { | ||
|
||
final String key = RedisKeyFactory.generateProductKey(DEFAULT_PRODUCT_CACHE_KEY); | ||
|
||
redisTemplate.watch(key); // 해당 키를 감시한다. 변경되면 로직 취소. | ||
|
||
try { | ||
if (redisTemplate.opsForList().size(key) >= 2000) { | ||
throw new IndexOutOfBoundsException("최상단 중고물품 2O00개 이상 담을 수 없습니다."); | ||
} | ||
|
||
redisTemplate.multi(); | ||
redisTemplate.opsForList().rightPush(key, productDTO); | ||
redisTemplate.expire(key, productsExpireSecond, TimeUnit.SECONDS); | ||
|
||
redisTemplate.exec(); | ||
} catch (Exception e) { | ||
redisTemplate.discard(); // 트랜잭션 종료시 unwatch()가 호출된다 | ||
throw e; | ||
} | ||
} | ||
} | ||
|
||
public void addRedisKeys(ProductDTO productDTO, String userId) { | ||
final String key = RedisKeyFactory.generateProductKey(userId); | ||
|
||
redisTemplate.watch(key); // 해당 키를 감시한다. 변경되면 로직 취소. | ||
|
||
try { | ||
if (redisTemplate.opsForList().size(key) >= 2000) { | ||
throw new IndexOutOfBoundsException("최상단 중고물품 2O00개 이상 담을 수 없습니다."); | ||
} | ||
|
||
redisTemplate.multi(); | ||
redisTemplate.opsForList().rightPush(key, productDTO); | ||
redisTemplate.expire(key, productsExpireSecond, TimeUnit.SECONDS); | ||
redisTemplate.exec(); | ||
|
||
} catch (Exception e) { | ||
redisTemplate.discard(); // 트랜잭션 종료시 unwatch()가 호출된다 | ||
throw e; | ||
} | ||
} | ||
|
||
/** | ||
* 최상단 중고물품들을 조회한다. | ||
* @author topojs8 | ||
* @param useId 고객 아이디 | ||
* @return | ||
*/ | ||
public List<ProductDTO> findAllProductsByCacheId(String useId) { | ||
List<ProductDTO> items = redisTemplate.opsForList() | ||
.range(RedisKeyFactory.generateProductKey(useId), 0, -1) | ||
.stream() | ||
.map(item -> objectMapper.convertValue(item, ProductDTO.class)) | ||
.collect(Collectors.toList()); | ||
return items; | ||
} | ||
|
||
@Cacheable(value="getProducts") | ||
@Override | ||
public List<ProductDTO> getProducts(ProductDTO productDTO, CategoryDTO categoryDTO) { | ||
productDTO.setCategoryId(categoryDTO.getId()); | ||
List<ProductDTO> productDTOList = productSearchMapper.selectProducts(productDTO,categoryDTO); | ||
List<ProductDTO> productDTOList = productSearchMapper.selectProducts(productDTO.getStatus().toString(),categoryDTO); | ||
return productDTOList; | ||
} | ||
} |
18 changes: 18 additions & 0 deletions
18
src/main/java/com/market/server/utils/RedisKeyFactory.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package com.market.server.utils; | ||
|
||
public class RedisKeyFactory { | ||
|
||
public enum Key { | ||
PRODUCT, | ||
} | ||
|
||
// 인스턴스화 방지 | ||
private RedisKeyFactory() {} | ||
|
||
private static String generateKey(String id, Key key) { return id + ":" + key; } | ||
|
||
public static String generateProductKey(String userId) { | ||
return generateKey(userId, Key.PRODUCT); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters