【原】Spring整合Redis(第二篇)—SDR环境搭建具体步骤
【环境参数】
Spring版本:4.2.6.RELEASE
Spring-Data-Redis版本:1.7.2.RELEASE
Redis版本:redis-2.4.5-win32-win64
【简要说明】
搭建Spring与Reids的环境时,重点在于在Spring容器中配置RedisTemplate和ConnectionFactory,以及封装RedisTemplate组件。
【具体步骤】
0、配置pom.xml文件
1 <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"> 2 <modelVersion>4.0.0</modelVersion> 3 <groupId>com.zjrodger</groupId> 4 <artifactId>Spring-Redis</artifactId> 5 <version>0.0.1-SNAPSHOT</version> 6 <packaging>war</packaging> 7 8 <!-- 定义依赖的版本 --> 9 <properties> 10 <spring.version>4.2.6.RELEASE</spring.version> 11 </properties> 12 13 <dependencies> 14 <!-- Spring Core --> 15 <dependency> 16 <groupId>org.springframework</groupId> 17 <artifactId>spring-core</artifactId> 18 <version>${spring.version}</version> 19 </dependency> 20 <dependency> 21 <groupId>org.springframework</groupId> 22 <artifactId>spring-beans</artifactId> 23 <version>${spring.version}</version> 24 </dependency> 25 <dependency> 26 <groupId>org.springframework</groupId> 27 <artifactId>spring-context</artifactId> 28 <version>${spring.version}</version> 29 </dependency> 30 <dependency> 31 <groupId>org.springframework</groupId> 32 <artifactId>spring-context-support</artifactId> 33 <version>${spring.version}</version> 34 </dependency> 35 <dependency> 36 <groupId>org.springframework</groupId> 37 <artifactId>spring-expression</artifactId> 38 <version>${spring.version}</version> 39 </dependency> 40 41 <!-- Spring Transaction --> 42 <dependency> 43 <groupId>org.springframework</groupId> 44 <artifactId>spring-tx</artifactId> 45 <version>${spring.version}</version> 46 </dependency> 47 48 <!-- Spring AOP --> 49 <dependency> 50 <groupId>org.springframework</groupId> 51 <artifactId>spring-aop</artifactId> 52 <version>${spring.version}</version> 53 </dependency> 54 <dependency> 55 <groupId>org.springframework</groupId> 56 <artifactId>spring-aspects</artifactId> 57 <version>${spring.version}</version> 58 </dependency> 59 <dependency> 60 <groupId>aopalliance</groupId> 61 <artifactId>aopalliance</artifactId> 62 <version>1.0</version> 63 </dependency> 64 65 <!-- JUnit相关jar包 --> 66 <dependency> 67 <groupId>org.springframework</groupId> 68 <artifactId>spring-test</artifactId> 69 <version>${spring.version}</version> 70 </dependency> 71 72 <!-- Spring-Date-Redis相关 --> 73 <dependency> 74 <groupId>org.springframework.data</groupId> 75 <artifactId>spring-data-redis</artifactId> 76 <version>1.7.2.RELEASE</version> 77 </dependency> 78 <dependency> 79 <groupId>redis.clients</groupId> 80 <artifactId>jedis</artifactId> 81 <version>2.7.3</version> 82 </dependency> 83 84 </dependencies> 85 86 </project>
1、配置redis.properties属性文件
# 连接redis服务的ip redis.host=127.0.0.1 # 连接redis服务的端口 redis.port=6379 # 连接redis服务的超时时间(单位:秒) redis.timeout=10 # 连接redis服务的密码 #redis.password=zjrodger # 连接redis服务的数据库 redis.database=2 # 最大连接数 redis.maxTotal=5000 # 最大空闲连接数 redis.maxIdle=100 # 最大等待时间:单位(毫秒) redis.maxWait=10000 # 最小空闲连接数 redis.minIdle=10 # 在borrow一个jedis实例时,是否提前进行alidate操作;如果为true,则得到的jedis实例均是可用的。 redis.testOnBorrow=true # 在return给pool时,是否提前进行validate操作。 redis.testOnReturn=true # 如果为true,表示有一个idle object evitor线程对idle object进行扫描,如果validate失败,此object会被从pool中drop掉;这一项只有在timeBetweenEvictionRunsMillis大于0时才有意义。 redis.testWhileIdle=false
2、在Spring容器中配置RedisTemplate和ConnectionFactory
在Spring容器中配置RedisTemplate和RedisConnectionFactory的实现类,即JedisConnectionFactory
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" 4 xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop" 5 xmlns:p="http://www.springframework.org/schema/p" xmlns:mvc="http://www.springframework.org/schema/mvc" 6 xmlns:task="http://www.springframework.org/schema/task" 7 xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd 8 http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd 9 http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd 10 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd 11 http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd 12 http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"> 13 14 <!-- Spring 扫包 --> 15 <context:component-scan base-package="com.zjrodger"/> 16 17 <!-- 读取配置文件 --> 18 <context:property-placeholder location="classpath:properties/*.properties"/> 19 20 <!-- jedis 配置 --> 21 <bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig" > 22 <property name="maxIdle" value="${redis.maxIdle}" /> 23 <property name="maxWaitMillis" value="${redis.maxWait}" /> 24 <property name="testOnBorrow" value="${redis.testOnBorrow}" /> 25 </bean > 26 27 <!-- redis服务器中心 --> 28 <bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory" > 29 <property name="poolConfig" ref="poolConfig" /> 30 <property name="port" value="${redis.port}" /> 31 <property name="hostName" value="${redis.host}" /> 32 <property name="timeout" value="${redis.timeout}" /> 33 <property name="database" value="${redis.database}" /> 34 <!-- <property name="password" value="${redis.password}"></property> --> 35 </bean > 36 37 <!-- redisTemplate配置 --> 38 <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate" > 39 <property name="connectionFactory" ref="jedisConnectionFactory" /> 40 </bean> 41 </beans>
3、封装RedisTemplate组件。
1 @Component( value ="redisTemplateFactory" ) 2 public class RedisTemplateFactory { 3 4 @Autowired 5 private RedisTemplate<String, Object> redisTemplate; 6 7 @SuppressWarnings("rawtypes") 8 public RedisTemplate getLocalRedisTemplate(){ 9 redisTemplate.setKeySerializer(redisTemplate.getStringSerializer()); 10 return this.redisTemplate; 11 } 12 }
4、准备测试数据:实体类、Dao接口和其实现类。
(1)封装User实体类
1 public class User implements Serializable { 2 private String userId; 3 private String username; 4 private String password; 5 ... 省略 setter()和getter()方法.. 6 }
(2)封装IUserDao接口
1 public interface IUserDao { 2 /** 新增 */ 3 boolean add(User user); 4 5 /** 批量新增 使用pipeline方式 */ 6 boolean add(List<User> list); 7 8 /**删除*/ 9 void delete(String key); 10 11 /**删除多个*/ 12 void delete(List<String> keys); 13 14 /**修改*/ 15 boolean update(User user) throws Exception; 16 17 /**通过key获取*/ 18 User get(String keyId); 19 20 boolean opsForList(String key, User user); 21 22 boolean getListValueByIndex(String key, int index); 23 }
(3)实现IUserDao接口
1 @Component( value = "userDao") 2 public class UserDaoImpl implements IUserDao { 3 4 @Autowired 5 public RedisTemplateFactory redisTemplateFactory; 6 7 @SuppressWarnings("unchecked") 8 @Override 9 public boolean add(User user) { 10 RedisTemplate<String, Object> localRedisTemplate = redisTemplateFactory.getLocalRedisTemplate(); 11 ValueOperations<String, Object> opsForValue = localRedisTemplate.opsForValue(); 12 opsForValue.set(user.getUserId(), user); 13 return true; 14 } 15 16 @SuppressWarnings("unchecked") 17 @Override 18 public boolean add(List<User> list) { 19 RedisTemplate<String, Object> localRedisTemplate = redisTemplateFactory.getLocalRedisTemplate(); 20 ValueOperations<String, Object> opsForValue = localRedisTemplate.opsForValue(); 21 for(User user: list){ 22 opsForValue.set(user.getUserId(), user); 23 } 24 return true; 25 } 26 27 @SuppressWarnings("unchecked") 28 @Override 29 public void delete(String key) { 30 RedisTemplate<String, Object> localRedisTemplate = redisTemplateFactory.getLocalRedisTemplate(); 31 ValueOperations<String, Object> opsForValue = localRedisTemplate.opsForValue(); 32 opsForValue.getOperations().delete(key); 33 } 34 35 @SuppressWarnings("unused") 36 @Override 37 public void delete(List<String> keys) { 38 RedisTemplate<String, Object> localRedisTemplate = redisTemplateFactory.getLocalRedisTemplate(); 39 ValueOperations<String, Object> opsForValue = localRedisTemplate.opsForValue(); 40 RedisOperations<String, Object> operations = opsForValue.getOperations(); 41 for(String key : keys){ 42 operations.delete(key); 43 } 44 } 45 46 @Override 47 public boolean update(User user) throws Exception { 48 if( null == user.getUserId()){ 49 throw new Exception("该用户的Key不存在"); 50 } 51 RedisTemplate<String, Object> localRedisTemplate = redisTemplateFactory.getLocalRedisTemplate(); 52 ValueOperations<String, Object> opsForValue = localRedisTemplate.opsForValue(); 53 opsForValue.set(user.getUserId(), user); 54 return true; 55 } 56 57 @Override 58 public User get(String keyId) { 59 RedisTemplate<String, Object> localRedisTemplate = redisTemplateFactory.getLocalRedisTemplate(); 60 ValueOperations<String, Object> opsForValue = localRedisTemplate.opsForValue(); 61 return (User)opsForValue.get(keyId); 62 } 63 64 @Override 65 public boolean opsForList(String key, User user) { 66 RedisTemplate<String, Object> localRedisTemplate = redisTemplateFactory.getLocalRedisTemplate(); 67 ListOperations<String, Object> opsForList = localRedisTemplate.opsForList(); 68 opsForList.rightPush(key, user); 69 return true; 70 } 71 72 @Override 73 public boolean getListValueByIndex(String key, int index) { 74 RedisTemplate<String, Object> localRedisTemplate = redisTemplateFactory.getLocalRedisTemplate(); 75 ListOperations<String, Object> opsForList = localRedisTemplate.opsForList(); 76 User user = (User) opsForList.index(key, index); 77 System.out.println(user); 78 return true; 79 } 80 }
5、测试:以OpsForXX()方式,对User的增删改查操作(推荐)。
此种方式是推荐的操作Redis的方式。
1 @RunWith(SpringJUnit4ClassRunner.class) 2 @ContextConfiguration(locations = { "classpath:applicationContext.xml" }) 3 public class SpringTestCase { 4 5 @Autowired 6 private IUserDao userDao; 7 8 private static final Integer COUNTER = 10; 9 10 // 测试添加单个User 11 @Test 12 public void testAddUser(){ 13 for(int i=1; i<=COUNTER; i++){ 14 User user = new User("mykey000"+i, "zjroger000"+i, "password000"+i); 15 if( userDao.add(user) ){ 16 System.out.println("用户zjrodger"+i+"添加成功。"); 17 }else{ 18 System.out.println("用户zjrodger"+i+"添加失败。"); 19 } 20 } 21 } 22 23 // 测试按照Key-Value方式添加User 24 @Test 25 public void testAddUserList(){ 26 List<User> userList = new ArrayList<>(); 27 for(int i=1; i<=COUNTER; i++){ 28 User user = new User("mykey000"+i, "zjroger000"+i, "password000"+i); 29 userList.add(user); 30 } 31 if( userDao.add(userList) ){ 32 System.out.println("用户列表添加成功。"); 33 }else{ 34 System.out.println("用户列表添加成功。"); 35 } 36 } 37 38 // 通过OpsForList方式添加User 39 @Test 40 public void testOpsForList(){ 41 String myListKey = "key:myListKey01"; 42 List<User> userList = new ArrayList<>(); 43 for(int i=1; i<=COUNTER; i++){ 44 User user = new User("myUserList0"+i, "myUserList0"+i, "myUserList0"+i); 45 userDao.opsForList(myListKey, user); 46 } 47 } 48 49 @Test 50 public void testgetListValueByIndex(){ 51 String myListKey = "key:myListKey01"; 52 int index = 0; 53 userDao.getListValueByIndex(myListKey, index); 54 } 55 56 // 测试删除User 57 @Test 58 public void testDelete(){ 59 // 单个删除 60 // String key = "mykey0002"; 61 // userDao.delete(key); 62 63 // 多个删除 64 List<String> keys = new ArrayList<>(); 65 keys.add("mykey0001"); 66 keys.add("mykey0002"); 67 keys.add("mykey0003"); 68 userDao.delete(keys); 69 70 } 71 72 // 测试获取User 73 @Test 74 public void testGetUser(){ 75 User user = userDao.get("mykey0001"); 76 System.out.println(user.toString()); 77 // 多条查询 78 // for(int i=1; i<=COUNTER; i++){ 79 // User user = userDao.get("mykey0"+i); 80 // System.out.println(user.toString()); 81 // } 82 } 83 84 // 测试更新User 85 @Test 86 public void testUpdateUser(){ 87 String mykey01 = "mykey0001"; 88 User user = userDao.get(mykey01); 89 System.out.println("原来的用户:"+user.toString()); 90 user.setUsername("ttttt"); 91 92 try { 93 boolean result = userDao.update(user); 94 System.out.println("数据更新完毕。"); 95 System.out.println(user.toString()); 96 } catch (Exception e) { 97 e.printStackTrace(); 98 } 99 }
6、测试:以RedisCallback()方式,对User的增删改查操作。
1 public class UserDaoImpl implements IUserDao { 2 3 @Autowired 4 private RedisTemplateFactory redisTemplateFactory; 5 6 /** 7 * 添加一个User对象 8 */ 9 @SuppressWarnings("unchecked") 10 @Override 11 public boolean add(User user) { 12 13 final RedisTemplate redisTemplate = redisTemplateFactory.getLocalRedisTemplate(); 14 15 boolean result = (boolean) redisTemplate.execute(new RedisCallback(){ 16 17 @SuppressWarnings("rawtypes") 18 @Override 19 public Boolean doInRedis(RedisConnection connection) 20 throws DataAccessException { 21 22 RedisSerializer stringSerializer = redisTemplate.getStringSerializer(); 23 RedisSerializer<User> valueSerializer = redisTemplate.getValueSerializer(); 24 byte[] key = stringSerializer.serialize(user.getUserId()); 25 byte[] value = valueSerializer.serialize(user); 26 return connection.setNX(key, value); 27 } 28 }); 29 return result; 30 } 31 32 /** 添加一个User的List对象*/ 33 @SuppressWarnings("unchecked") 34 @Override 35 public boolean add(List<User> list) { 36 37 final RedisTemplate redisTemplate = redisTemplateFactory.getLocalRedisTemplate(); 38 39 return (boolean) redisTemplate.execute(new RedisCallback(){ 40 41 @SuppressWarnings("rawtypes") 42 @Override 43 public Boolean doInRedis(RedisConnection connection) 44 throws DataAccessException { 45 46 RedisSerializer keySerializer = redisTemplate.getKeySerializer(); 47 RedisSerializer<User> valueSerializer = redisTemplate.getValueSerializer(); 48 for(User user : list){ 49 byte[] key = keySerializer.serialize(user.getUserId()); 50 byte[] value = valueSerializer.serialize(user); 51 connection.setNX(key, value); 52 } 53 return true; 54 } 55 }, 56 false, 57 true); 58 } 59 }