build.gradle 파일 의존성 추가
// Redis
implementation group: 'org.springframework.boot', name: 'spring-boot-starter-data-redis'
// Data Redis (Redis를 DB화하여 사용하는 경우)
compile "org.springframework.boot:spring-boot-starter-data-redis"
compile "redis.clients:jedis:2.9.0"
compile "org.springframework.session:spring-session-data-redis"
application.yml 파일 설정 추가
spring:
redis:
host: 127.0.0.1
port: 6379
redis config 빈 설정
방법 1.
@Configuration
public class RedisConfig {
@Value("${spring.redis.host}")
private String host;
@Value("${spring.redis.port}")
private int port;
@Bean
public JedisConnectionFactory jedisConnectionFactory() {
JedisConnectionFactory jedisConnectionFactory = null;
try {
RedisStandaloneConfiguration conn = new RedisStandaloneConfiguration();
conn.setHostName(host);
conn.setPort(port);
jedisConnectionFactory = new JedisConnectionFactory(conn);
} catch (Exception e) {
e.printStackTrace();
}
return jedisConnectionFactory;
}
@Bean(name="redisTemplate")
public RedisTemplate redisTemplate(JedisConnectionFactory jedisConnectionFactory) {
final RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setDefaultSerializer(new StringRedisSerializer());
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
redisTemplate.setHashValueSerializer(new GenericToStringSerializer<>(Object.class));
redisTemplate.setValueSerializer(new GenericToStringSerializer<>(Object.class));
redisTemplate.setConnectionFactory(jedisConnectionFactory);
return redisTemplate;
}
@Primary
@Bean("cacheManager")
public RedisCacheManager cacheManager() {
RedisCacheManager.RedisCacheManagerBuilder builder = RedisCacheManager.RedisCacheManagerBuilder.fromConnectionFactory(jedisConnectionFactory);
RedisCacheConfiguration configuration = RedisCacheConfiguration.defaultCacheConfig()
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()))
.entryTtl(Duration.ofMinutes(5L)); // 기본 캐시 5분 처리
// 캐시 value에 맞춰 아래 ttl을 적용한다.
Map<String, RedisCacheConfiguration> cacheConfigurations = new HashMap<>();
cacheConfigurations.put("ttl1minute", configuration.entryTtl(Duration.ofMinutes(1L)));
cacheConfigurations.put("ttl5minute", configuration.entryTtl(Duration.ofMinutes(5L)));
cacheConfigurations.put("ttl10minute", configuration.entryTtl(Duration.ofMinutes(10L)));
cacheConfigurations.put("article", configuration.entryTtl(Duration.ofMinutes(10L)));
return builder.cacheDefaults(configuration).withInitialCacheConfigurations(cacheConfigurations).build();
}
}
방법 .2
RedisConfig 빈 등록
@Configuration
@EnableCaching
public class RedisCacheConfig extends CachingConfigurerSupport {
/**
* Cache Key Generator
* 함수명을 캐시 키로 자동 생성해준다.
* @return
*/
@Bean
public KeyGenerator keyGenerator() {
return (o, method, objects) -> {
StringBuilder sb = new StringBuilder();
sb.append(".");
sb.append(o.getClass().getSimpleName());
sb.append(".");
sb.append(method.getName());
sb.append("(");
int index = 0;
for (Object obj : objects) {
if (index > 0) {
sb.append(",");
}
if (o.getClass().isArray()) {
sb.append(Arrays.deepToString((Object[]) obj));
} else {
sb.append(obj.toString());
}
index++;
}
sb.append(")");
return sb.toString();
};
}
/**
* String Redis Serializer
* @return
*/
@Bean
public StringRedisSerializer stringRedisSerializer() {
return new StringRedisSerializer();
}
/**
* Redis Template
* @param redisConnectionFactory
* @return
*/
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactory);
redisTemplate.setKeySerializer(stringRedisSerializer());
return redisTemplate;
}
/**
* Redis CacheManager
* @param redisConnectionFactory
* @return
*/
@Bean
public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(stringRedisSerializer()));
return RedisCacheManager.builder(redisConnectionFactory).cacheDefaults(redisCacheConfiguration)
.withInitialCacheConfigurations(configurationMap())
.build();
}
/**
* Cache Config Map
* @return
*/
private Map<String, RedisCacheConfiguration> configurationMap() {
Map<String, RedisCacheConfiguration> cacheConfigurations = new HashMap<>();
cacheConfigurations.put("cache.day" , createCacheConfiguration("cache.day", (24 * 60 * 60))); // 1일
cacheConfigurations.put("cache.hour" , createCacheConfiguration("cache.hour", (60 * 60))); // 1시간
cacheConfigurations.put("cache.default" , createCacheConfiguration("cache.default", (5 * 60))); // 기본 5분
return cacheConfigurations;
}
/**
* Create Cache Configuration
* @param cacheKey
* @param timeoutInSeconds
* @return
*/
private static RedisCacheConfiguration createCacheConfiguration(String cacheKey, long timeoutInSeconds) {
// SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd");
// String timestamp = format.format(new Timestamp(System.currentTimeMillis()));
return RedisCacheConfiguration.defaultCacheConfig()
.prefixKeysWith(cacheKey)
.entryTtl(Duration.ofSeconds(timeoutInSeconds));
}
}
연동 (Redis Template)
캐시 조회 컨트롤러 생성
@RequiredArgsConstructor
@RestController
@RequestMapping("/caches")
public class CacheController {
private final CacheService cacheService;
@GetMapping("")
public List<String> lists(HttpServletRequest request){
return cacheService.listKey();
}
@GetMapping("/{key}")
public String listsKey(HttpServletRequest request, @PathVariable(name = "key") String key){
return cacheService.getCacheValues(key);
}
@GetMapping("/key}/clear")
public String listsKeyClear(HttpServletRequest request, @PathVariable(name = "key") String key){
cacheService.clear(key);
return "clear";
}
}
캐시 조회 서비스 생성
@RequiredArgsConstructor
@Service
public class CacheService {
private final RedisTemplate<String, Object> redisTemplate;
// 캐시키 제거
public void clear(String key){
redisTemplate.delete(key);
}
// 모든 키를 조회
public List<String> listKey(){
Set<String> keys = redisTemplate.keys("*");
if(keys != null){
List<String> keyList = new ArrayList<>();
keyList.addAll(keys);
return keyList;
}
return new ArrayList<>();
}
// 캐시 키로 조회한 값 조회
public String getCacheValues(String cacheName){
return redisTemplate.opsForValue().get(cacheName).toString();
}
}
캐시 데이터 자동 생성 방법
@RequiredArgsConstructor
@Service
public class AdminIpPermissionService {
private final AdminIpPermissionMapper adminIpPermissionMapper;
/**
* 관리자 허용 IP 리스트 정보 조회
* @param status
* @return
*/
@Cacheable(value = "cache.hour") // 1시간 유지 캐시 설정
public List<AdminIpPermission> getAdminIpPermissionList(String status) {
return adminIpPermissionMapper.getAdminIpPermissionList(status);
}
}
연동 (Redis Data)
repository 생성
public interface RedisNoticeRepository extends CrudRepository<Notice, Long> {
}
entity 생성
@ToString // 테스트용
@Builder
@Getter
@RedisHash("notice")
public class Notice {
@Id
private Long id;
private String content;
public Notice changeContent(String newContent){
this.content = newContent;
return this;
}
}
테스트 코드 작성
@RunWith(SpringRunner.class)
@SpringBootTest
@Transactional
public class RedisNoticeRepositoryTest {
@Autowired
private RedisNoticeRepository redisNoticeRepository;
@Test
public void save(){
Notice notice = Notice.builder().content("test content").build();
redisNoticeRepository.save(notice);
}
@Test
public void selectAll(){
// 출력 테스트
redisNoticeRepository.findAll().forEach(notice ->{
System.out.println(notice.toString());
});
}
@Test
public void selectOne(){
// 키값은 redis-cli에서 직접 확인 필요
Notice notice = redisNoticeRepository.findById().get();
assertEquals("test content", notice.getContent());
}
@Test
public void update(){
// 키값은 redis-cli에서 직접 확인 필요
Notice notice = redisNoticeRepository.findById().get();
notice.changeContent("change content");
redisNoticeRepository.save(notice);
// 키값은 redis-cli에서 직접 확인 필요
Notice updatedNotice = redisNoticeRepository.findById().get();
assertEquals(updatedNotice.getContent(), "change content");
}
}
redis 값 확인 방법
Cacheable TTL 적용 예시
위에 있는 RedisConfig 설정에 선언한 ttl 적용
@RequiredArgsConstructor
@Service
public class MemberRestService {
private final MemberRepository memberRepository;
private final OrdersRepository ordersRepository;
private final ModelMapper modelMapper;
@Cacheable(value = "article")
public List<MemberDto> getAllMembers(){
return memberRepository.findAll()
.stream()
.map(member -> modelMapper.map(member, MemberDto.class))
.collect(Collectors.toList());
}
// article 형태를 가진 모든 키를 제거
@CacheEvict(cacheNames = {"article"}, allEntries = true)
@Transactional
public void updateMember(Long id, int age){
memberRepository.findById(id).ifPresent(member -> member.changeAge(age));
}
public List<OrdersDto> getListOrders(Long id){
return ordersRepository.findByMember_Id(id)
.stream()
.map(orders -> modelMapper.map(orders, OrdersDto.class))
.collect(Collectors.toList());
}
}
'SpringFramework > Spring' 카테고리의 다른 글
jQuery DataTable Paging Model Mapping (0) | 2021.03.09 |
---|---|
Enum 객체 활용 방안 (0) | 2021.03.09 |
ModelMapper 사용 법 (0) | 2020.11.16 |
Swagger2 설정 및 사용 (0) | 2020.11.13 |
class 파일내 DataSource 설정 (0) | 2020.11.11 |