Merge pull request #10729 from hkhan/BAEL-4868-spring-cache-redis-backend
[BAEL-4868] Use Redis as cache store
This commit is contained in:
commit
c3aa009bb6
2
pom.xml
2
pom.xml
|
@ -623,6 +623,7 @@
|
||||||
<module>spring-boot-rest-2</module>
|
<module>spring-boot-rest-2</module>
|
||||||
|
|
||||||
<module>spring-caching</module>
|
<module>spring-caching</module>
|
||||||
|
<module>spring-caching-2</module>
|
||||||
|
|
||||||
<module>spring-cloud</module>
|
<module>spring-cloud</module>
|
||||||
<module>spring-cloud-bus</module>
|
<module>spring-cloud-bus</module>
|
||||||
|
@ -1079,6 +1080,7 @@
|
||||||
<module>spring-boot-rest-2</module>
|
<module>spring-boot-rest-2</module>
|
||||||
|
|
||||||
<module>spring-caching</module>
|
<module>spring-caching</module>
|
||||||
|
<module>spring-caching-2</module>
|
||||||
|
|
||||||
<module>spring-cloud</module>
|
<module>spring-cloud</module>
|
||||||
<module>spring-cloud-bus</module>
|
<module>spring-cloud-bus</module>
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
### Relevant articles:
|
|
@ -0,0 +1,66 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<artifactId>spring-caching-2</artifactId>
|
||||||
|
<version>0.1-SNAPSHOT</version>
|
||||||
|
<name>spring-caching-2</name>
|
||||||
|
<packaging>war</packaging>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>com.baeldung</groupId>
|
||||||
|
<artifactId>parent-boot-2</artifactId>
|
||||||
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
|
<relativePath>../parent-boot-2</relativePath>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<embedded.redis.version>0.7.3</embedded.redis.version>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.data</groupId>
|
||||||
|
<artifactId>spring-data-commons</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.h2database</groupId>
|
||||||
|
<artifactId>h2</artifactId>
|
||||||
|
<scope>runtime</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-cache</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-data-redis</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>it.ozimov</groupId>
|
||||||
|
<artifactId>embedded-redis</artifactId>
|
||||||
|
<version>${embedded.redis.version}</version>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>org.slf4j</groupId>
|
||||||
|
<artifactId>slf4j-simple</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</project>
|
|
@ -0,0 +1,33 @@
|
||||||
|
package com.baeldung.caching.redis;
|
||||||
|
|
||||||
|
import org.springframework.boot.autoconfigure.cache.RedisCacheManagerBuilderCustomizer;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.data.redis.cache.RedisCacheConfiguration;
|
||||||
|
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
|
||||||
|
|
||||||
|
import java.time.Duration;
|
||||||
|
|
||||||
|
import static org.springframework.data.redis.serializer.RedisSerializationContext.SerializationPair;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class CacheConfig {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public RedisCacheManagerBuilderCustomizer redisCacheManagerBuilderCustomizer() {
|
||||||
|
return (builder) -> builder
|
||||||
|
.withCacheConfiguration("itemCache",
|
||||||
|
RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofMinutes(10)))
|
||||||
|
.withCacheConfiguration("customerCache",
|
||||||
|
RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofMinutes(5)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public RedisCacheConfiguration cacheConfiguration() {
|
||||||
|
return RedisCacheConfiguration.defaultCacheConfig()
|
||||||
|
.entryTtl(Duration.ofMinutes(60))
|
||||||
|
.disableCachingNullValues()
|
||||||
|
.serializeValuesWith(SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
package com.baeldung.caching.redis;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@Entity
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class Item implements Serializable {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
String id;
|
||||||
|
|
||||||
|
String description;
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
package com.baeldung.caching.redis;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class ItemController {
|
||||||
|
|
||||||
|
private final ItemService itemService;
|
||||||
|
|
||||||
|
@GetMapping("/item/{id}")
|
||||||
|
public Item getItemById(@PathVariable String id) {
|
||||||
|
return itemService.getItemForId(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
package com.baeldung.caching.redis;
|
||||||
|
|
||||||
|
import org.springframework.data.repository.CrudRepository;
|
||||||
|
|
||||||
|
public interface ItemRepository extends CrudRepository<Item, String> {
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
package com.baeldung.caching.redis;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import org.springframework.cache.annotation.Cacheable;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class ItemService {
|
||||||
|
|
||||||
|
private final ItemRepository itemRepository;
|
||||||
|
|
||||||
|
@Cacheable(value = "itemCache")
|
||||||
|
public Item getItemForId(String id) {
|
||||||
|
return itemRepository.findById(id)
|
||||||
|
.orElseThrow(RuntimeException::new);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
package com.baeldung.caching.redis;
|
||||||
|
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
import org.springframework.cache.annotation.EnableCaching;
|
||||||
|
|
||||||
|
@SpringBootApplication
|
||||||
|
@EnableCaching
|
||||||
|
public class RedisCacheApplication {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
SpringApplication.run(RedisCacheApplication.class, args);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
spring.datasource.url=jdbc:h2:mem:testdb;DB_CLOSE_ON_EXIT=FALSE
|
||||||
|
spring.datasource.driverClassName=org.h2.Driver
|
||||||
|
spring.datasource.username=sa
|
||||||
|
spring.datasource.password=
|
||||||
|
|
||||||
|
# Enabling H2 Console
|
||||||
|
spring.h2.console.enabled=true
|
||||||
|
spring.h2.console.path=/h2
|
||||||
|
|
||||||
|
# Connection details
|
||||||
|
#spring.redis.host=localhost
|
||||||
|
#spring.redis.port=6379
|
|
@ -0,0 +1 @@
|
||||||
|
INSERT INTO ITEM VALUES('abc','ITEM1');
|
|
@ -0,0 +1,84 @@
|
||||||
|
package com.baeldung.caching.redis;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
|
||||||
|
import org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration;
|
||||||
|
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
|
||||||
|
import org.springframework.boot.test.context.TestConfiguration;
|
||||||
|
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||||
|
import org.springframework.cache.CacheManager;
|
||||||
|
import org.springframework.cache.annotation.EnableCaching;
|
||||||
|
import org.springframework.context.annotation.Import;
|
||||||
|
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||||
|
import redis.embedded.RedisServer;
|
||||||
|
|
||||||
|
import javax.annotation.PostConstruct;
|
||||||
|
import javax.annotation.PreDestroy;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.mockito.BDDMockito.given;
|
||||||
|
import static org.mockito.Mockito.times;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
|
||||||
|
@Import({ CacheConfig.class, ItemService.class })
|
||||||
|
@ExtendWith(SpringExtension.class)
|
||||||
|
@ImportAutoConfiguration(classes = { CacheAutoConfiguration.class, RedisAutoConfiguration.class })
|
||||||
|
@EnableCaching
|
||||||
|
class ItemServiceCachingIntegrationTest {
|
||||||
|
|
||||||
|
private static final String AN_ID = "id-1";
|
||||||
|
private static final String A_DESCRIPTION = "an item";
|
||||||
|
|
||||||
|
@MockBean
|
||||||
|
private ItemRepository mockItemRepository;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ItemService itemService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private CacheManager cacheManager;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void givenRedisCaching_whenFindItemById_thenItemReturnedFromCache() {
|
||||||
|
Item anItem = new Item(AN_ID, A_DESCRIPTION);
|
||||||
|
given(mockItemRepository.findById(AN_ID))
|
||||||
|
.willReturn(Optional.of(anItem));
|
||||||
|
|
||||||
|
Item itemCacheMiss = itemService.getItemForId(AN_ID);
|
||||||
|
Item itemCacheHit = itemService.getItemForId(AN_ID);
|
||||||
|
|
||||||
|
assertThat(itemCacheMiss).isEqualTo(anItem);
|
||||||
|
assertThat(itemCacheHit).isEqualTo(anItem);
|
||||||
|
|
||||||
|
verify(mockItemRepository, times(1)).findById(AN_ID);
|
||||||
|
assertThat(itemFromCache()).isEqualTo(anItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Object itemFromCache() {
|
||||||
|
return cacheManager.getCache("itemCache").get(AN_ID).get();
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestConfiguration
|
||||||
|
static class EmbeddedRedisConfiguration {
|
||||||
|
|
||||||
|
private final RedisServer redisServer;
|
||||||
|
|
||||||
|
public EmbeddedRedisConfiguration() {
|
||||||
|
this.redisServer = new RedisServer();
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostConstruct
|
||||||
|
public void startRedis() {
|
||||||
|
redisServer.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
@PreDestroy
|
||||||
|
public void stopRedis() {
|
||||||
|
this.redisServer.stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<configuration>
|
||||||
|
<include resource="org/springframework/boot/logging/logback/base.xml" />
|
||||||
|
<logger name="org.springframework" level="OFF"/>
|
||||||
|
</configuration>
|
Loading…
Reference in New Issue