作者 | 桌前明月
来源 | CSDN博客
头图 | 付费下载自视觉中国
出品 | CSDN(ID:CSDNnews)
前言
提到Redis 大部分的人首先想到的可能就是缓存,那么在 Java 项目中如何把对象缓存起来呢?这就是本文接下来要介绍的内容:缓存对象。本文通过SpringBoot 项目带你快速了解通过Jedis 把对象缓存到Redis中。
阅读本文需要你了解如何搭建 SpringBoot 项目即可,另外需要了解的是本文SpringBoot 版本是 2.1.0.RELEASE。关于SpringBoot 集成 Jedis 请参考:玩转 SpringBoot 2.x 之 快速集成 Jedis客户端(普通版)
接下来就让我们开始具体的代码案例介绍吧!
代码案例
演示通过将下面的 User 类创建的对象缓存到 Redis 中,具体有2种方式:序列化、Json。User 类具体代码如下:
1public class User implements Serializable { 2 3 private String name; 4 private Integer age; 5 6 public User(String name,Integer age){ 7 this.name = name; 8 this.age = age; 9 } 10 //省略 getter and setter 方法 11}
关于 过期时间处理和返回Jedis 线程操作到线程池操作封装到了 JedisCacheServiceSupport 中,具体代码如下:
1public abstract class JedisCacheServiceSupport { 2 public static final long EXPIRE_MILLISECONDS_DEFAULT_LONG = 3*60*60*1000; 3 4 public Long getExpireTime(Long expireTime) { 5 expireTime = (expireTime == null || expireTime.longValue() <= 0) ? EXPIRE_MILLISECONDS_DEFAULT_LONG : expireTime; 6 return expireTime; 7 } 8 9 public void close(Jedis jedis){ 10 if(jedis != null){ 11 jedis.close(); 12 } 13 } 14}
序列化方式
序列化的方式通过现将对象转换成二进制的流(序列化)后保存到 Redis 中,然后通过key 获取到二进制,在把二进制流转换成对象(反序列化)。
保存对象的具体操作如下:
通过 ObjectOutputStream.writeObject(object) 将User 对象转换成byte 数组,然后通过 psetex(byte[] key, long milliseconds, byte[] value) 将 byte[] 数组存入Redis中。其中
byte[] key:需要将key 转换成byte数组。
long milliseconds:是对象在Redis 中存活的时间,以毫秒为单位。
byte[] value:对象转换成的btye 数组。
获取对象的具体操作如下:
通过 get(byte[] key) 获取 User 对象转换的byte 数组,然后通过 ObjectInputStream.readObject() 将数组转换成User对象。
通过序列化方式保存和获取对象具体代码如下:
1@Service 2public class JedisCacheService extends JedisCacheServiceSupport { 3 4 private static Logger logger = LoggerFactory.getLogger(JedisCacheService.class); 5 6 7 8 @Autowired 9 private JedisPool jedisPool; 10 11 /** 12 * 获取缓存中的对象 13 * @param key 14 * @return 15 */ 16 public Object getObject(String key) { 17 Jedis jedis = null; 18 Object object = null; 19 try { 20 jedis = jedisPool.getResource(); 21 byte[] ObjectByteArray = jedis.get(key.getBytes()); 22 object = unserialize(ObjectByteArray); 23 }catch (Exception e){ 24 e.printStackTrace(); 25 }finally { 26 close(jedis); 27 } 28 return object; 29 } 30 31 /** 32 * 将对象缓存到Redis中,设置默认过期时间 33 * @param key 34 * @param value 35 */ 36 public void putObject(String key, Object value) { 37 putObject(key,value,null); 38 } 39 /** 40 * 将对象缓存到Redis中,自定义认过期时间 41 * @param key 42 * @param value 43 */ 44 public void putObject(String key, Object value, Long expireTime) { 45 Jedis jedis = null; 46 try { 47 jedis = jedisPool.getResource(); 48 jedis.psetex(key.getBytes(),getExpireTime(expireTime),serialize(value)); 49 }catch (Exception e){ 50 e.printStackTrace(); 51 }finally { 52 close(jedis); 53 } 54 } 55 56 57 /** 58 * 序列化 59 * @param object 60 * @return 61 */ 62 public static byte[] serialize(Object object) { 63 ObjectOutputStream oos = null; 64 ByteArrayOutputStream baos = null; 65 try { 66 baos = new ByteArrayOutputStream(); 67 oos = new ObjectOutputStream(baos); 68 oos.writeObject(object); 69 byte[] bytes = baos.toByteArray(); 70 return bytes; 71 } catch (Exception e) { 72 logger.error(e.getMessage(), e); 73 } finally { 74 IOUtil.closeStream(oos); 75 IOUtil.closeStream(baos); 76 } 77 return null; 78 } 79 80 /** 81 * 反序列化 82 * @param bytes 83 * @return 84 */ 85 public static Object unserialize(byte[] bytes) { 86 if (bytes == null) return null; 87 88 ByteArrayInputStream bais = null; 89 ObjectInputStream ois = null; 90 try { 91 bais = new ByteArrayInputStream(bytes); 92 ois = new ObjectInputStream(bais); 93 return ois.readObject(); 94 } catch (Exception e) { 95 logger.error(e.getMessage(), e); 96 } finally { 97 IOUtil.closeStream(bais); 98 IOUtil.closeStream(ois); 99 } 100 return null; 101 } 102}
关闭 输入流和输出流工具类具体代码如下:
1public class IOUtil { 2 public static void closeStream(InputStream inputStream) { 3 if (inputStream != null) { 4 try { 5 inputStream.close(); 6 } catch (IOException e) { 7 e.printStackTrace(); 8 } 9 10 } 11 } 12 13 public static void closeStream(OutputStream outputStream) { 14 if (outputStream != null) { 15 try { 16 outputStream.close(); 17 } catch (IOException e) { 18 e.printStackTrace(); 19 } 20 21 } 22 } 23}
序列化方式演示
测试 JedisCacheService putObject(将对象放入缓存中)、getObject(从缓存中获取对象),具体代码如下:
1@RunWith(SpringRunner.class) 2@SpringBootTest 3public class JedisCacheServiceTest { 4 private Logger logger = LoggerFactory.getLogger(JedisCacheService.class); 5 @Autowired 6 private JedisCacheService jedisCacheService; 7 8 @Test 9 public void putObject() { 10 User user = new User("zhuoqiammingyue",19); 11 jedisCacheService.putObject("user01",user); 12 logger.info("缓存用户成功!"); 13 } 14 15 @Test 16 public void getObject() { 17 User user = (User)jedisCacheService.getObject("user01"); 18 logger.info("User name={},age={}",user.getName(),user.getAge()); 19 } 20}
putObject 日志信息:
12020-02-26 22:08:50.320 INFO 26748 --- [ main] cn.lijunkui.cache.JedisCacheServiceTest : Started JedisCacheServiceTest in 7.157 seconds (JVM running for 9.357) 22020-02-26 22:08:51.144 INFO 26748 --- [ main] cn.lijunkui.cache.JedisCacheService : 缓存用户成功!
getObject 日志信息:
12020-02-26 22:09:57.492 INFO 9612 --- [ main] cn.lijunkui.cache.JedisCacheServiceTest : Started JedisCacheServiceTest in 7.07 seconds (JVM running for 8.902) 22020-02-26 22:09:58.143 INFO 9612 --- [ main] cn.lijunkui.cache.JedisCacheService : User name=zhuoqiammingyue,age=19
Json 方式
Json 的方式是将对象转换成可阅读的Json 串后保存到 Redis 中,然后通过key 获取到Json 串,在把Json 串成对象。对象转成成Json串是通过谷歌的Gson 完成的,所以需要引入Gson的依赖,具体依赖代码如下:
1<dependency> 2 <groupId>com.google.code.gson</groupId> 3 <artifactId>gson</artifactId> 4 <version>2.8.5</version> 5</dependency>
Json 保存对象的具体操作如下:
通过 Gson.toJson(Object src) 将User 对象转换成 Json串,然后通过 psetex(String key, long milliseconds, String value) 将 Json串存入Redis中。
通过 get(String key) 获取 User 对象的Json串,然后通过 Gson.fromJson(String json, Class<T> classOfT) 将Json串转换成User对象。
通过Json 方式保存和获取对象具体代码如下:
1@Service 2public class JedisJsonCacheService extends JedisCacheServiceSupport { 3 4 private static Logger logger = LoggerFactory.getLogger(JedisJsonCacheService.class); 5 6 @Autowired 7 private JedisPool jedisPool; 8 9 /** 10 * 获取缓存中的对象 11 * @param key 12 * @param clazz 13 * @return 14 */ 15 public Object getObject(String key,Class clazz) { 16 Jedis jedis = null; 17 Object object = null; 18 try { 19 jedis = jedisPool.getResource(); 20 String objectJson = jedis.get(key); 21 object = toObjce(objectJson,clazz); 22 }catch (Exception e){ 23 e.printStackTrace(); 24 }finally { 25 close(jedis); 26 } 27 return object; 28 } 29 30 /** 31 * 将对象缓存到Redis中,设置默认过期时间 32 * @param key 33 * @param value 34 */ 35 public void putObject(String key, Object value) { 36 putObject(key, value,null); 37 } 38 39 /** 40 * 将对象缓存到Redis中,自定义认过期时间 41 * @param key 42 * @param value 43 * @param expireTime 44 */ 45 public void putObject(String key, Object value, Long expireTime) { 46 Jedis jedis = null; 47 try { 48 jedis = jedisPool.getResource(); 49 jedis.psetex(key,getExpireTime(expireTime),toJson(value)); 50 }catch (Exception e){ 51 e.printStackTrace(); 52 }finally { 53 close(jedis); 54 } 55 } 56 57 58 59 /** 60 * 将对象转换成Json串 61 * @param value 62 * @return 63 */ 64 private String toJson(Object value) { 65 Gson gson = new Gson(); 66 return gson.toJson(value); 67 } 68 69 /** 70 * 将Json串转换成对象 71 * @param json 72 * @param clazz 73 * @return 74 */ 75 private Object toObjce(String json,Class clazz) { 76 Gson gson = new Gson(); 77 return gson.fromJson(json,clazz); 78 } 79}
序列化方式演示
测试 JedisJsonCacheServiceTest putObject(将对象放入缓存中)、getObject(从缓存中获取对象),具体代码如下:
1@RunWith(SpringRunner.class) 2@SpringBootTest 3public class JedisJsonCacheServiceTest { 4 5 private Logger logger = LoggerFactory.getLogger(JedisJsonCacheServiceTest.class); 6 @Autowired 7 private JedisJsonCacheService jedisJsonCacheService; 8 9 @Test 10 public void putObject() { 11 User user = new User("zhuoqiammingyue2",20); 12 jedisJsonCacheService.putObject("user02",user); 13 logger.info("缓存用户成功!"); 14 } 15 16 @Test 17 public void getObject() { 18 User user = (User)jedisJsonCacheService.getObject("user02",User.class); 19 logger.info("User name={},age={}",user.getName(),user.getAge()); 20 } 21}
putObject 日志信息:
12020-02-27 07:57:16.184 INFO 3692 --- [ main] c.l.cache.JedisJsonCacheServiceTest : Started JedisJsonCacheServiceTest in 7.92 seconds (JVM running for 10.786) 22020-02-27 07:57:16.852 INFO 3692 --- [ main] c.l.cache.JedisJsonCacheServiceTest : 缓存用户成功!
getObject 日志信息:
12020-02-27 07:57:56.359 INFO 27624 --- [ main] c.l.cache.JedisJsonCacheServiceTest : Started JedisJsonCacheServiceTest in 7.364 seconds (JVM running for 9.256) 22020-02-27 07:57:56.824 INFO 27624 --- [ main] c.l.cache.JedisJsonCacheServiceTest : User name=zhuoqiammingyue2,age=20
小结
序列化和Json这2种方式,在实际开发中可以根据你的喜好自行选择。Json 方式使用的是Gson 当然你也可以使用 FastJson ,序列化采用了 Java 原生的序列化和反序列化,同时你也可以切换成效率更高的 Hessian 进行序列化和反序列化。
我本地环境如下:
SpringBoot Version: 2.1.0.RELEASE
Apache Maven Version:3.6.0
Java Version:1.8.0_144
IDEA:IntellJ IDEA
操作过程如出现问题可以在我的GitHub 仓库 springbootexamples 中模块 名为 spring-boot-2.x-redis-jedis-objectcache 项目中进行对比查看
GitHub:https://github.com/zhuoqianmingyue/springbootexamples
原文链接:https://blog.csdn.net/ljk126wy/article/details/104519059
【End】
《原力计划【第二季】- 学习力挑战》正式开始!
即日起至 3月21日,千万流量支持原创作者,更有专属【勋章】等你来挑战
推荐阅读