项目地址:
https://github.com/CarrowZhu/springredis
项目简介:
基于spring-data-redis的注解实现redis缓存操作
requirement
JDK6
Spring4
原理&实现
1)AOP
2)实现参考自Spring的Cache注解
区别:
1)支持TTL
2)支持Hash
配置说明
XML配置文件
xsi:schemaLocation="http://www.siyuan.com/schema/springredis
http://www.siyuan.com/schema/springredis/springredis.xsd"
<springRedis:annotation-driven />
属性说明
redisTemplate:Advice中将使用的redisTemplate,默认为"redisTemplate"
order:Advice的执行顺序,默认优先级最高(Ordered.HIGHEST_PRECEDENCE)
exceptionHandler:beanId,操作异常处理器,必须实现接口com.siyuan.springredis.interceptor.SpringRedisExceptionHandler,默认为com.siyuan.springredis.interceptor.LoggerExceptionHandler
注解
1)@SpringRedisConfig:Class级别配置
属性说明
value:等同于redisTemplate
redisTemplate:(String)Advice中将使用的redisTemplate
2)@SpringRedisValueCache:方法级别,操作的数据类型为String
对应操作流程:读cache,hit返回,miss -> 获取数据 -> cache
属性说明
value:等同于key
redisTemplate:(String)Advice中将使用的redisTemplate
condition:(String)支持SpringEL,缓存操作条件
timeout:(long)TTL,<=0表示永不过期,默认为0
timeUnit:(TimeUnit)TTL单位,默认为TimeUnit.MILLISECONDS
key:(String)支持SpringEL,缓存对应的key值,必须提供
refreshTTL:(boolean)缓存命中时是否刷新TTL,默认为false
3)@SpringRedisValueEvict :方法级别,操作的数据类型为String
对应的流程:清除缓存
属性说明
value:等同于key
redisTemplate:(String)Advice中将使用的redisTemplate
condition:(String)支持SpringEL,缓存操作条件
key:(String)支持SpringEL,缓存对应的key值,必须提供
4)@SpringRedisHashCache:方法级别,操作的数据类型为Hash
对应操作流程:与 @SpringRedisValueCache 类似
属性说明
value:等同于key
redisTemplate:(String)Advice中将使用的redisTemplate
condition:(String)支持SpringEL,缓存操作条件
timeout:(long)TTL,<=0表示永不过期,默认为0
timeUnit:(TimeUnit)TTL单位,默认为TimeUnit.MILLISECONDS
key:(String)支持SpringEL,缓存对应的key值,必须提供
refreshTTL:(boolean)缓存命中时是否刷新TTL,默认为false
hashKey:(String)支持SpringEL,缓存对应的hashKey值,必须提供
5)@SpringRedisHashEvict :方法级别,操作的数据类型为Hash
对应的流程:与 @SpringRedisValueEvict 类似
属性说明
value:等同于key
redisTemplate:(String)Advice中将使用的redisTemplate
condition:(String)支持SpringEL,缓存操作条件
key:(String)支持SpringEL,缓存对应的key值,必须提供
hashKey:(String)支持SpringEL,缓存对应的hashKey值,必须提供
SpringEL
Name > Location > Example
methodName > root object > #root.methodName
method > root object > #root.method.name
target > root object > #root.target
targetClass > root object > #root.targetClass
args > root object > #root.args[0]
argument name > evaluation context > #name (编译时必须保留方法名信息)
result > evaluation context > #result
示例
1)ApplicationContext-SpringRedis.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:springRedis="http://www.siyuan.com/schema/springredis" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.siyuan.com/schema/springredis http://www.siyuan.com/schema/springredis/springredis.xsd"> <springRedis:annotation-driven /> <context:component-scan base-package="com.siyuan.springredis" /> <bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory" /> <bean id="stringRedisSerializer" class="org.springframework.data.redis.serializer.StringRedisSerializer"/> <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate" p:connection-factory-ref="jedisConnectionFactory" p:key-serializer-ref="stringRedisSerializer"> <property name="defaultSerializer"> <bean class="org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer" /> </property> </bean> <bean id="studentRedisTemplate" class="org.springframework.data.redis.core.RedisTemplate" p:connection-factory-ref="jedisConnectionFactory" p:key-serializer-ref="stringRedisSerializer" p:hash-key-serializer-ref="stringRedisSerializer"> <property name="defaultSerializer"> <bean class="org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer"> <constructor-arg index="0" value="#{T(com.siyuan.springredis.Student)}" /> </bean> </property> </bean> </beans>
2)Student.java
package com.siyuan.springredis; public class Student { private Long id; private String name; public Student() { } public Student(Long id, String name) { this.id = id; this.name = name; } public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((id == null) ? 0 : id.hashCode()); result = prime * result + ((name == null) ? 0 : name.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Student other = (Student) obj; if (id == null) { if (other.id != null) return false; } else if (!id.equals(other.id)) return false; if (name == null) { if (other.name != null) return false; } else if (!name.equals(other.name)) return false; return true; } @Override public String toString() { return "Student [id=" + id + ", name=" + name + "]"; } }
3)StudentDAO.java
package com.siyuan.springredis; public interface StudentDAO { Student getById(long id); void updateStudent(Student student); }
4)StudentService.java
package com.siyuan.springredis; import java.util.concurrent.TimeUnit; import org.springframework.stereotype.Service; import com.siyuan.springredis.annotation.SpringRedisConfig; import com.siyuan.springredis.annotation.SpringRedisHashCache; import com.siyuan.springredis.annotation.SpringRedisHashEvict; import com.siyuan.springredis.annotation.SpringRedisValueCache; import com.siyuan.springredis.annotation.SpringRedisValueEvict; @Service("studentService") @SpringRedisConfig("studentRedisTemplate") public class StudentService { private StudentDAO studentDAO; @SpringRedisValueCache(key = "'student:' + #id", condition = "#id > 100", timeout = 60, timeUnit = TimeUnit.MINUTES, refreshTTL = true) public Student getById(long id) { return studentDAO.getById(id); } @SpringRedisValueEvict(key = "'student:' + #student.id", condition = "#student.id > 100") public void updateStudent(Student student) { studentDAO.updateStudent(student); } @SpringRedisHashCache(key = "'students'", hashKey = "#id.toString()", condition = "#id > 100", timeout = 60, timeUnit = TimeUnit.MINUTES, refreshTTL = true) public Student getById2(long id) { return studentDAO.getById(id); } @SpringRedisHashEvict(key = "'students'", hashKey = "#student.id.toString()", condition = "#student.id > 100") public void updateStudent2(Student student) { studentDAO.updateStudent(student); } public StudentDAO getStudentDAO() { return studentDAO; } public void setStudentDAO(StudentDAO studentDAO) { this.studentDAO = studentDAO; } }
5)StudentServiceTest.java
package com.siyuan.springredis.test; import org.junit.After; import static org.junit.Assert.*; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import static org.mockito.Mockito.*; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import com.siyuan.springredis.Student; import com.siyuan.springredis.StudentDAO; import com.siyuan.springredis.StudentService; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = "/ApplicationContext-SpringRedis.xml") public class StudentServiceTest { @Autowired @Qualifier("studentRedisTemplate") private RedisTemplate<String, Student> redisTemplate; @Autowired private StudentService service; private StudentDAO studentDAO; private StudentDAO mock; @Before public void setUp() { redisTemplate.delete("student:123"); redisTemplate.delete("student:100"); redisTemplate.delete("students"); studentDAO = service.getStudentDAO(); mock = mock(StudentDAO.class); service.setStudentDAO(mock); } @Test public void testGetById() { when(mock.getById(123L)).thenReturn(new Student(123L, "name:123")); // no cache Student stu = service.getById(123L); assertArrayEquals(new Object[] { new Student(123L, "name:123") }, new Object[] { stu }); // cache stu = service.getById(123L); assertArrayEquals(new Object[] { new Student(123L, "name:123") }, new Object[] { stu }); verify(mock, times(1)).getById(123L); when(mock.getById(100L)).thenReturn(new Student(100L, "name:100")); // no cache stu = service.getById(100L); assertArrayEquals(new Object[] { new Student(100L, "name:100") }, new Object[] { stu }); // no cache stu = service.getById(100L); assertArrayEquals(new Object[] { new Student(100L, "name:100") }, new Object[] { stu }); verify(mock, times(2)).getById(100L); } @Test public void testUpdateStudent() { // evict Student stu = new Student(123L, "name:123"); redisTemplate.opsForValue().set("student:123", stu); service.updateStudent(stu); assertNull(redisTemplate.opsForValue().get("student:123")); // do not evict stu = new Student(100L, "name:100"); redisTemplate.opsForValue().set("student:100", stu); service.updateStudent(stu); assertNotNull(redisTemplate.opsForValue().get("student:100")); } @Test public void testGetById2() { when(mock.getById(123L)).thenReturn(new Student(123L, "name:123")); // no cache Student stu = service.getById2(123L); assertArrayEquals(new Object[] { new Student(123L, "name:123") }, new Object[] { stu }); // cache stu = service.getById2(123L); assertArrayEquals(new Object[] { new Student(123L, "name:123") }, new Object[] { stu }); verify(mock, times(1)).getById(123L); when(mock.getById(100L)).thenReturn(new Student(100L, "name:100")); // no cache stu = service.getById2(100L); assertArrayEquals(new Object[] { new Student(100L, "name:100") }, new Object[] { stu }); // no cache stu = service.getById2(100L); assertArrayEquals(new Object[] { new Student(100L, "name:100") }, new Object[] { stu }); verify(mock, times(2)).getById(100L); } @Test public void testUpdateStudent2() { // evict Student stu = new Student(123L, "name:123"); redisTemplate.opsForHash().put("students", "123", stu); service.updateStudent2(stu); assertNull(redisTemplate.opsForHash().get("students", "123")); // do not evict stu = new Student(100L, "name:100"); redisTemplate.opsForHash().put("students", "100", stu); service.updateStudent2(stu); assertNotNull(redisTemplate.opsForHash().get("students", "100")); } @After public void clear() { service.setStudentDAO(studentDAO); } }
相关推荐
Redis是一款开源的、高性能的键值对数据库,而Spring是Java领域广泛使用的框架,提供了一整套的企业级应用开发工具。将Spring与Redis结合,可以方便地在应用程序中利用Redis的强大功能。 一、Spring Data Redis概述...
Spring Redis是Spring Data项目的一部分,它提供了对Redis数据存储的高级抽象,支持多种操作模式,如Jedis和Lettuce客户端。通过Spring Redis,开发者可以轻松地将缓存功能引入到Spring应用程序中。 二、Redis基础...
Spring Data Redis项目简化了在Spring应用中使用Redis的过程。首先,你需要在项目中添加Spring Data Redis的依赖,通常在Maven或Gradle的配置文件中进行: ```xml <!-- Maven 示例 --> <groupId>org.spring...
8. **Spring Boot样例项目分析**:`spring-boot-sample-Redis`可能包含了一个简单的Spring Boot应用,演示了如何配置Redis,以及如何使用RedisTemplate进行数据操作。通过阅读源代码,你可以深入理解如何在实际项目...
Spring Data Redis是一个强大的Java库,它是Spring Data项目的一部分,旨在简化与Redis内存数据存储的集成。Redis是一个开源的、高性能的键值数据存储系统,常用于数据库、缓存和消息中间件。Spring Data Redis提供...
在Java开发领域,Spring框架与Redis的集成是常见的数据存储和缓存解决方案。Spring提供了对多种数据源的支持,...通过上述步骤,你已经具备了使用Spring与Redis集成的基础,可以根据项目需求进行更深入的定制和优化。
本项目结合了Spring、SpringMVC、MyBatis、Dubbo、Redis和Netty等技术,构建了一个完整的分布式服务系统。 1. **Spring框架**:Spring是Java企业级应用的核心框架,提供了依赖注入(DI)和面向切面编程(AOP)等...
这个"spring+redis整合"项目展示了如何利用Spring框架和Redis数据库来实现一个高效的、高可用的登录系统,其中会话(Session)由Redis进行管理,同时支持通过Nginx进行负载均衡。以下是关于这一主题的详细知识讲解。...
1. **添加依赖**:在项目中引入Spring Data Redis和Redis客户端库(如Jedis或Lettuce)的依赖。在Maven项目中,可以在pom.xml文件中添加对应的dependency。 2. **配置Redis**:在Spring的配置文件(如...
- "SpringRedis"这个文件夹可能包含了一个完整的Spring Boot项目,其中包括了`pom.xml`配置文件、`application.properties`或`application.yml`配置文件,以及相关的Java源代码。 - 源代码中可能会有Redis配置类、...
"liugh-openResources"这个文件名可能指的是一个开源项目或资源库,其中包含了与Java Web相关的各种组件、文档、示例代码和配置文件。这个压缩包可能包含了一个完整的Web项目实例,或者是一些用于教学或参考的开源...
基于netty, spring boot, redis等开源项目开发来的物联网框架, 支持udp, tcp底层协议和http, mqtt, modbus等上层协议. 支持对设备同步和异步的调用操作. 主要向开发人员开放了一套统一、简洁的用于操作设备的Api接口...
2. **添加依赖**:在Spring项目中,需要在Maven或Gradle的配置文件中引入Redis的相关依赖。如果是Maven,可以在`pom.xml`中添加以下依赖: ```xml <groupId>org.springframework.boot <artifactId>spring-boot-...
在IT行业中,Spring框架是Java领域最常用的轻量级开源框架之一,而Redis则是一种高性能的内存数据存储系统,常用于缓存、消息队列等场景。MySQL则是世界上最流行的开源关系型数据库。将Spring、Redis和MySQL整合在...
首先,我们需要在项目中引入Spring对Redis支持的相关依赖。在Maven项目中,可以在pom.xml文件中添加如下依赖: ```xml <groupId>org.springframework.boot <artifactId>spring-boot-starter-data-redis ``` 接...
首先,Spring Data Redis是Spring Data项目的一部分,该项目致力于简化各种数据存储的访问,包括关系型数据库、NoSQL存储以及缓存系统如Redis。通过Spring Data Redis,你可以使用Java或Groovy API来方便地执行Redis...
【标题】"dubbo spring mybatis redis" 涵盖了四个关键的开源技术,它们在企业级应用开发中扮演着重要角色。Dubbo 是一个高性能、轻量级的 Java RPC 框架,用于构建分布式服务。Spring 是一个广泛使用的 Java 应用...
4. **Redis**:Redis是一个开源的内存数据结构存储系统,支持多种数据类型如字符串、哈希、列表、集合和有序集合。在Java应用中,我们可以使用Jedis或者Lettuce等客户端库与Redis通信。在SSH框架中,Redis常用于缓存...
2. **配置 Redis**:在 Spring Boot 项目中,可以在 `application.properties` 或 `application.yml` 文件中配置 Redis 连接信息,如主机名、端口、密码等: ```properties spring.redis.host=localhost spring....
通过这个开源项目,开发者不仅可以学习到Spring和Redis结合实现消息队列的具体步骤,还可以借鉴其中的设计思想和最佳实践,进一步提升自己的分布式系统设计能力。对于需要在Spring应用中引入消息队列的开发者来说,...