玩轉 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 類具體代碼如下:

<code> 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}
/<code>

關於 過期時間處理和返回Jedis 線程操作到線程池操作封裝到了 JedisCacheServiceSupport 中,具體代碼如下:

<code> 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 == || expireTime.longValue <= 0) ? EXPIRE_MILLISECONDS_DEFAULT_LONG : expireTime;
6 return expireTime;
7 }
8
9 public void close(Jedis jedis){
10 if(jedis != ){
11 jedis.close;
12 }
13 }
14}
/<code>
玩转 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對象。

通過序列化方式保存和獲取對象具體代碼如下:

<code> 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 = ;
18 Object object = ;
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,);
38 }
39 /**
40 * 將對象緩存到Redis中,自定義認過期時間
41 * @param key
42 * @param value
43 */
44 public void putObject(String key, Object value, Long expireTime) {
45 Jedis jedis = ;
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 = ;
64 ByteArrayOutputStream baos = ;
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 ;
78 }
79
80 /**
81 * 反序列化
82 * @param bytes
83 * @return
84 */
85 public static Object unserialize(byte[] bytes) {
86 if (bytes == ) return ;
87
88 ByteArrayInputStream bais = ;
89 ObjectInputStream ois = ;
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 ;
101 }
102}
/<code>

關閉 輸入流和輸出流工具類具體代碼如下:

<code> 1public class IOUtil {
2 public static void closeStream(InputStream inputStream) {
3 if (inputStream != ) {
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 != ) {
15 try {
16 outputStream.close;
17 } catch (IOException e) {
18 e.printStackTrace;
19 }
20
21 }
22 }
23}
/<code>
玩转 SpringBoot2.x 之缓存对象 | 原力计划

序列化方式演示

測試 JedisCacheService putObject(將對象放入緩存中)、getObject(從緩存中獲取對象),具體代碼如下:

<code> 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}
/<code>

putObject 日誌信息:

<code>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 : 緩存用戶成功!
/<code>

getObject 日誌信息:

<code>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
/<code>
玩转 SpringBoot2.x 之缓存对象 | 原力计划

Json 方式

Json 的方式是將對象轉換成可閱讀的Json 串後保存到 Redis 中,然後通過key 獲取到Json 串,在把Json 串成對象。對象轉成成Json串是通過谷歌的Gson 完成的,所以需要引入Gson的依賴,具體依賴代碼如下:

<code>1<dependency>
2 <groupid>com.google.code.gson/<groupid>
3 <artifactid>gson/<artifactid>
4 <version>2.8.5/<version>
5/<dependency>
/<code>

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 classOfT) 將Json串轉換成User對象。

通過Json 方式保存和獲取對象具體代碼如下:

<code> 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 = ;
17 Object object = ;
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,);
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 = ;
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}
/<code>
玩转 SpringBoot2.x 之缓存对象 | 原力计划

序列化方式演示

測試 JedisJsonCacheServiceTest putObject(將對象放入緩存中)、getObject(從緩存中獲取對象),具體代碼如下:

<code> 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}
/<code>

putObject 日誌信息:

<code>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 : 緩存用戶成功!
/<code>

getObject 日誌信息:

<code>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
/<code>
玩转 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


分享到:


相關文章: