作者 | 桌前明月

来源 | 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 {23    private String name;4    private Integer age;56    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;34    public Long getExpireTime(Long expireTime) {5        expireTime = (expireTime == null || expireTime.longValue() <= 0) ? EXPIRE_MILLISECONDS_DEFAULT_LONG : expireTime;6        return expireTime;7    }89    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@Service2public class JedisCacheService extends JedisCacheServiceSupport  {34    private static Logger logger = LoggerFactory.getLogger(JedisCacheService.class);5678    @Autowired9    private JedisPool jedisPool;1011    /**12     * 获取缓存中的对象13     * @param key14     * @return15     */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    }3031    /**32     *  将对象缓存到Redis中,设置默认过期时间33     * @param key34     * @param value35     */36    public void putObject(String key, Object value) {37        putObject(key,value,null);38    }39    /**40     *  将对象缓存到Redis中,自定义认过期时间41     * @param key42     * @param value43     */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    }555657    /**58     * 序列化59     * @param object60     * @return61     */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    }7980    /**81     * 反序列化82     * @param bytes83     * @return84     */85    public static Object unserialize(byte[] bytes) {86        if (bytes == null) return null;8788        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@SpringBootTest3public class JedisCacheServiceTest {4    private  Logger logger = LoggerFactory.getLogger(JedisCacheService.class);5    @Autowired6    private JedisCacheService jedisCacheService;78    @Test9    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中。

Json 获取对象的具体操作如下:

通过 get(String key) 获取 User 对象的Json串,然后通过 Gson.fromJson(String json, Class<T> classOfT) 将Json串转换成User对象。

通过Json 方式保存和获取对象具体代码如下:

 1@Service2public class JedisJsonCacheService extends JedisCacheServiceSupport {34    private static Logger logger = LoggerFactory.getLogger(JedisJsonCacheService.class);56    @Autowired7    private JedisPool jedisPool;89    /**
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@SpringBootTest3public class JedisJsonCacheServiceTest {45    private Logger logger = LoggerFactory.getLogger(JedisJsonCacheServiceTest.class);6    @Autowired7    private JedisJsonCacheService jedisJsonCacheService;89    @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日,千万流量支持原创作者,更有专属【勋章】等你来挑战

推荐阅读 

☞微信 QQ 小程序因违规被封;微软大破全球最大僵尸网络;VS Code 1.43 发布 | 极客头条

☞官宣!阿里进军 5G,成立 XG 实验室发力新基建

☞前沿技术探秘:知识图谱构建流程及方法

☞留德武汉程序员在疫区:凌晨下载数据,网速影响工作

☞云原生的漏洞与威胁有哪些?云原生安全性如何?这里有你想知道的一切!

☞编程小白模拟简易比特币系统,手把手带你写一波!(附代码) | 博文精选

你点的每一个在看,我认真当成了喜欢

玩转 SpringBoot2.x 之缓存对象 | 原力计划相关推荐

  1. 玩转SpringBoot2.x之缓存对象

    前言 提到Redis 大部分的人首先想到的可能就是缓存,那么在 Java 项目中如何把对象缓存起来呢?这就是本文接下来要介绍的内容:缓存对象.本文通过SpringBoot 项目带你快速了解通过Jedi ...

  2. 获取对象的key_玩转 SpringBoot2.x 之缓存对象

    作者 | 桌前明月 来源 | CSDN博客 头图 | 付费下载自视觉中国 出品 | CSDN(ID:CSDNnews) 前言 提到Redis 大部分的人首先想到的可能就是缓存,那么在 Java 项目中 ...

  3. mybatis mapper.xml 文件共用_MyBatis 缓存原来是这么一回事儿!| 原力计划

    作者 | Lw中责编 | 夕颜出品 | CSDN(ID:CSDNnews) 什么是缓存? 缓存就是存储数据的一个地方(称作:Cache),当程序要读取数据时,会首先从缓存中获取,有则直接返回,否则从其 ...

  4. MyBatis 缓存原来是这么一回事儿!| 原力计划

    作者 | Lw中 责编 | 夕颜 出品 | CSDN(ID:CSDNnews) 什么是缓存? 缓存就是存储数据的一个地方(称作:Cache),当程序要读取数据时,会首先从缓存中获取,有则直接返回,否则 ...

  5. Java 那些最常用的工具类库 | 原力计划

    作者 |  Java 识堂 责编 | 屠敏 出品 | CSDN(ID:CSDNnews) Apache Commons Apache Commons有很多子项目,常用的项目如下: BeanUtils ...

  6. Python2 倒计时,还不快来掌握 Python3 酷炫的新特性? | 原力计划

    作者 | 云爬虫技术研究笔记 责编 | 郭芮 出品 | CSDN 博客 Python3.8已经发布近一个月了,距离Python3.0第一个版本发布也将超过10年了.相信很多人还是依旧在使用Python ...

  7. 面试官:你连 RESTful 都不知道我怎么敢要你?| 原力计划

    作者 | zhanglinblog 责编 | 刘静 出品 | CSDN 博客 面试官:了解RESTful吗? 我:听说过. 面试官:那什么是RESTful? 我:就是用起来很规范,挺好的 面试官:是R ...

  8. 找不到libmmd.dll无法继续执行代码_300 行代码带你秒懂 Java 多线程!| 原力计划...

    作者 | 永远在路上[] 责编 | 胡巍巍 出品 | CSDN博客 线程线程的概念,百度是这样解释的:线程(英语:Thread)是操作系统能够进行运算调度的最小单位.它被包含在进程之中,是进程中的实际 ...

  9. Spring 从入门到入土——AOP 就这么简单!| 原力计划

    作者|  冢狐 责编 | 夕颜 出品 | CSDN博客 什么是AOP? 面向切面编程(Aspect Oriented Programming),通过预编译的方式和运行期动态代理实现程序功能的统一维护的 ...

最新文章

  1. 如何比较浮点数相等_『GCTT 出品』Go 语言中的比较操作符
  2. UVa OJ 120
  3. fscanf和feof的组合使用
  4. 网络营销第一课:市场营销基础(2)
  5. IOS开发之格式化日期时间的使用 编程中常见问题
  6. Programming Assignment 5: Burrows–Wheeler Data Compression
  7. 《ETL原理及应用》学习笔记 ·003【kettle的使用-1】
  8. Flash Builder 找不到Adobe Flash Player或者Flash Builder 找不到debug版本的解决方法
  9. Java Bitwise Operators
  10. 《自己动手写操作系统》第二章——Bochs调试及相关仿真工具的使用方法
  11. 工具学习——在线访问远程服务器的SSH工具
  12. poj2387(Dijkstra)
  13. LVDS的接口电路设计
  14. 如何检测显卡类型和OpenGL版本
  15. RocketMQ中文文档(译)
  16. 新产品、新特性、新生态丨一文回顾openGauss峰会云和恩墨分论坛150分钟的精彩...
  17. shell脚本实践:自动清理文件,以时间方式形成路径的图片或者是Excel、pdf等文件
  18. Go语言开发k8s-04-Service操作
  19. 解决由于权限问题导致YUM安装失败
  20. Hive 常用日期处理-昨天、本月、上月同期、去年同期、月初、月末等

热门文章

  1. BUPT 2012复试机考 2T
  2. IOS 获取系统通讯录中的联系人信息
  3. Android重力感应示例
  4. 输出最长上升子序列 模型(DP)
  5. spinningup 绘制曲线
  6. 【深度学习】【U-net】医学图像(血管)分割实验记录
  7. 下一较大值(一,二)
  8. win10+cuda10.0.130+cudnn7.5.1+tensorflow-gpu 1.13.1+anaconda3+keras+pycharm2018
  9. python的常量变量_Python基础语法-常量与变量
  10. Tensorflow卷积神经网络识别MINST手写数字