diff --git a/README.md b/README.md index 268357e..aa56785 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,3 @@ # REST API using Spring Boot - ## task 5 + ## task 6 diff --git a/docker-compose.yml b/docker-compose.yml index af423c8..a4336e3 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -10,6 +10,7 @@ services: - SPRING_PROFILES_ACTIVE=${PROFILE:-postgres} depends_on: - postgres + - redis postgres: image: postgres:15.0-alpine @@ -23,6 +24,12 @@ services: - "5432:5432" volumes: - pgdata:/var/lib/postgresql/data + redis: + image: redis:7-alpine + container_name: redis + ports: + - "6379:6379" + restart: always volumes: pgdata: diff --git a/pom.xml b/pom.xml index cb2b369..18cdb52 100644 --- a/pom.xml +++ b/pom.xml @@ -21,8 +21,19 @@ org.springframework.boot spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-data-redis + + + + + org.springframework.boot + spring-boot-starter-cache + - + com.fasterxml.jackson.datatype jackson-datatype-jsr310 diff --git a/src/main/java/task/TaskApplication.java b/src/main/java/task/TaskApplication.java index 5b859de..dd846a9 100644 --- a/src/main/java/task/TaskApplication.java +++ b/src/main/java/task/TaskApplication.java @@ -2,8 +2,10 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cache.annotation.EnableCaching; @SpringBootApplication +@EnableCaching public class TaskApplication { public static void main(String[] args) { diff --git a/src/main/java/task/config/RedisConfig.java b/src/main/java/task/config/RedisConfig.java new file mode 100644 index 0000000..194e742 --- /dev/null +++ b/src/main/java/task/config/RedisConfig.java @@ -0,0 +1,50 @@ +package task.config; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.JsonTypeInfo; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import org.springframework.cache.annotation.EnableCaching; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.cache.RedisCacheConfiguration; +import org.springframework.data.redis.cache.RedisCacheManager; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.RedisSerializationContext; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +import java.text.SimpleDateFormat; +import java.time.Duration; + +@Configuration +@EnableCaching +public class RedisConfig { + + @Bean + public RedisCacheManager cacheManager(RedisConnectionFactory connectionFactory) { + + // Настраиваем ObjectMapper, чтобы поддерживал LocalDateTime + ObjectMapper objectMapper = new ObjectMapper(); + objectMapper.registerModule(new JavaTimeModule()); // поддержка LocalDateTime + objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); + objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")); + + + GenericJackson2JsonRedisSerializer serializer = + new GenericJackson2JsonRedisSerializer(objectMapper); + + RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig() + .entryTtl(Duration.ofMinutes(10)) + .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer())) + .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(serializer)) + .disableCachingNullValues(); + return RedisCacheManager.builder(connectionFactory) + .cacheDefaults(config) + .build(); + } +} \ No newline at end of file diff --git a/src/main/java/task/service/impl/TaskServiceImpl.java b/src/main/java/task/service/impl/TaskServiceImpl.java index 6a5ae72..25f5ca6 100644 --- a/src/main/java/task/service/impl/TaskServiceImpl.java +++ b/src/main/java/task/service/impl/TaskServiceImpl.java @@ -5,7 +5,10 @@ import java.util.stream.Collectors; import lombok.AllArgsConstructor; +import org.springframework.cache.annotation.Caching; import org.springframework.stereotype.Service; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; import task.model.Notification; import task.model.Task; @@ -19,22 +22,35 @@ public class TaskServiceImpl implements TaskService { private final TaskRepository taskRepository; @Override + @Cacheable(value = "tasks", key = "'all'") public List getAllTasks() { return taskRepository.findByIsDeleteFalse(); } @Override - public List getUserTasks(Long userId) { + @Cacheable(value = "tasks", key = "'user:' + #userId") + public List getUserTasks(Long userId) { return taskRepository.findByUserIdAndIsDeleteFalse(userId); } @Override + @Cacheable(value = "tasks", key = "'pending user:' + #userId") public List getUserTasksPending(Long userId) { return taskRepository.findByUserIdAndIsCompleteFalseAndIsDeleteFalse(userId); } @Override + @Caching(evict = { + @CacheEvict(value = "tasks", key = "'all'"), + @CacheEvict(value = "tasks", key = "'user:' + #task.userId"), + @CacheEvict(value = "tasks", key = "'pending user:' + #task.userId") + }) public Task createTask(Task task) { return taskRepository.save(task); } @Override + @Caching(evict = { + @CacheEvict(value = "tasks", key = "'all'"), + @CacheEvict(value = "tasks", key = "'user:' + #task.userId"), + @CacheEvict(value = "tasks", key = "'pending user:' + #task.userId") + }) public void deleteTask(Long taskId) { taskRepository.markAsDeleted(taskId); } diff --git a/src/main/resources/application-postgres.properties b/src/main/resources/application-postgres.properties index 8b61e2f..181d6c3 100644 --- a/src/main/resources/application-postgres.properties +++ b/src/main/resources/application-postgres.properties @@ -14,4 +14,12 @@ spring.flyway.enabled=true spring.flyway.locations=classpath:db/migration spring.flyway.baseline-on-migrate=true +# Cache Redis +spring.cache.type=redis +spring.data.redis.host=redis +spring.data.redis.port=6379 +spring.data.redis.timeout=60000 + + +