最近项目中用到Redis,上网查了很多示例,发现或多或少都有问题。踩过很多坑,终于在Spring Boot中成功实现了Redis存储。记录如下,方便别人,也方便自己。
Redis(REmote DIctionary Server) 是一个由Salvatore Sanfilippo写的key-value存储系统。Redis是一个开源的使用ANSI C语言编写、遵守BSD协议、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。它通常被称为数据结构服务器,因为值(value)可以是 字符串(String), 哈希(Map), 列表(list), 集合(sets) 和 有序集合(sorted sets)等类型。
至于在服务器上如何搭建Redis存储系统,本文就不在赘述,网上相关教程很多,请自行Google。如果要实现Redis可远程连接,需要注意一下几点:
pom.xml文件中依赖如下
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
可以利用配置文件进行设置,也可以直接通过注释配置。配置文件application.yml如下:
spring: # REDIS (RedisProperties) redis: # Redis服务器地址 host: 192.168.1.197 # Redis服务器连接端口 port: 6379 pool: # 连接池中的最大空闲连接 max-idle: 8 # 连接池中的最小空闲连接 min-idle: 0 # 连接池最大连接数(使用负值表示没有限制) max-active: 8 # 连接池最大阻塞等待时间(使用负值表示没有限制) max-wait: -1 # 连接超时时间(毫秒) timeout: 0 # Redis数据库索引(默认为0) database: 0 # Redis服务器连接密码(默认为空) password: your-password
package com.ygingko.utest.config; import com.ygingko.utest.config.redis.RedisObjectSerializer; import com.ygingko.utest.entity.dto.UserDTO; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.PropertySource; import org.springframework.data.redis.connection.jedis.JedisConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.serializer.StringRedisSerializer; import redis.clients.jedis.JedisPoolConfig; @Configuration @PropertySource("classpath:application.yml") public class RedisConfig{ @Value("${spring.redis.host}") private String host; @Value("${spring.redis.port}") private int port; @Value("${spring.redis.password}") private String password; @Value("${spring.redis.database}") private int database; @Value("${spring.redis.timeout}") private int timeout; @Value("${spring.redis.pool.max-active}") private int maxActive; @Value("${spring.redis.pool.max-idle}") private int maxIdle; @Value("${spring.redis.pool.min-idle}") private int minIdle; @Value("${spring.redis.pool.max-wait}") private long maxWait; @Bean JedisConnectionFactoryjedisConnectionFactory(){ JedisConnectionFactory factory = new JedisConnectionFactory(); factory.setHostName(host); factory.setPort(port); factory.setPassword(password); factory.setDatabase(database); factory.setTimeout(timeout); JedisPoolConfig jedisPoolConfig = new JedisPoolConfig(); jedisPoolConfig.setMaxTotal(maxActive); jedisPoolConfig.setMaxIdle(maxIdle); jedisPoolConfig.setMinIdle(minIdle); jedisPoolConfig.setMaxWaitMillis(maxWait); factory.setPoolConfig(jedisPoolConfig); return factory; } @Bean public RedisTemplate<String, UserDTO> redisTemplate(){ RedisTemplate<String, UserDTO> template = new RedisTemplate<>(); template.setConnectionFactory(jedisConnectionFactory()); template.setKeySerializer(new StringRedisSerializer()); template.setValueSerializer(new RedisObjectSerializer()); return template; } }
package com.ygingko.utest.config.redis; import org.springframework.core.convert.converter.Converter; import org.springframework.core.serializer.support.DeserializingConverter; import org.springframework.core.serializer.support.SerializingConverter; import org.springframework.data.redis.serializer.RedisSerializer; import org.springframework.data.redis.serializer.SerializationException; public class RedisObjectSerializerimplements RedisSerializer{ private Converter<Object, byte[]> serializer = new SerializingConverter(); private Converter<byte[], Object> deserializer = new DeserializingConverter(); private static final byte[] EMPTY_ARRAY = new byte[0]; @Override public byte[] serialize(Object o) throws SerializationException { if (o == null) { return EMPTY_ARRAY; } try { return serializer.convert(o); } catch (Exception e) { return EMPTY_ARRAY; } } @Override public Object deserialize(byte[] bytes)throws SerializationException { if (isEmpty(bytes)) { return null; } try { return deserializer.convert(bytes); } catch (Exception e) { throw new SerializationException("Cannot deserialize ", e); } } private boolean isEmpty(byte[] data){ return (data == null || data.length == 0); } }
存储对象必须实现Serializable接口,有固定的serialVersionUID。如下:
package com.ygingko.utest.entity.dto; import com.alibaba.fastjson.JSON; import java.io.Serializable; public class UserDTOimplements Serializable{ private static final long serialVersionUID = 4044555734385804034L; private Integer uid; private String name; private String password; private Integer level; public Integer getUid(){ return uid; } public void setUid(Integer uid){ this.uid = uid; } public String getName(){ return name; } public void setName(String name){ this.name = name; } public String getPassword(){ return password; } public void setPassword(String password){ this.password = password; } public Integer getLevel(){ return level; } public void setLevel(Integer level){ this.level = level; } @Override public String toString(){ return JSON.toJSONString(this); } }
package com.ygingko.utest; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.test.context.junit4.SpringRunner; import redis.clients.jedis.Jedis; import java.util.ArrayList; import java.util.List; @RunWith(SpringRunner.class) @SpringBootTest public class UtestApplicationTests{ @Autowired private RedisTemplate<String, UserDTO> redisTemplate; @Test public void testRedis()throws Exception { UserDTO userBean = new UserDTO(); userBean.setUid(1001); userBean.setName("huang"); userBean.setLevel(1); redisTemplate.opsForValue().set("token", userBean); System.out.println(redisTemplate.opsForValue().get("token")); } @Test public void contextLoads(){ Jedis jedis = new Jedis("192.168.1.197", 6379); System.out.println("****************" + jedis.ping()); } }