转载

玩转 SpringBoot2.x 之缓存对象 | 原力计划

玩转 SpringBoot2.x 之缓存对象 | 原力计划

玩转 SpringBoot2.x 之缓存对象 | 原力计划

作者 | 桌前明月

来源 | CSDN博客

头图 | 付费下载自视觉中国

出品 | CSDN(ID:CSDNnews)

玩转 SpringBoot2.x 之缓存对象 | 原力计划

前言

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

阅读本文需要你了解如何搭建 SpringBoot 项目即可,另外需要了解的是本文SpringBoot 版本是 2.1.0.RELEASE。关于SpringBoot 集成 Jedis 请参考:玩转 SpringBoot 2.x 之 快速集成 Jedis客户端(普通版)

接下来就让我们开始具体的代码案例介绍吧!

玩转 SpringBoot2.x 之缓存对象 | 原力计划

代码案例

演示通过将下面的 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}

玩转 SpringBoot2.x 之缓存对象 | 原力计划

序列化方式

序列化的方式通过现将对象转换成二进制的流(序列化)后保存到 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}

玩转 SpringBoot2.x 之缓存对象 | 原力计划

序列化方式演示

测试 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

玩转 SpringBoot2.x 之缓存对象 | 原力计划

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@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}

玩转 SpringBoot2.x 之缓存对象 | 原力计划

序列化方式演示

测试 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

玩转 SpringBoot2.x 之缓存对象 | 原力计划

小结

序列化和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日,千万流量支持原创作者,更有专属【勋章】等你来挑战

玩转 SpringBoot2.x 之缓存对象 | 原力计划

推荐阅读 

原文  http://mp.weixin.qq.com/s?__biz=MjM5MjAwODM4MA==&mid=2650740430&idx=3&sn=42da51b7e85edb825da0f4f1df74fa0b
正文到此结束
Loading...