玩轉SpringBoot2.x之緩存對象

前言
提到Redis 大部分的人首先想到的可能就是緩存,那麼在 Java 項目中如何把對象緩存起來呢?這就是本文接下來要介紹的內容:緩存對象。本文經過SpringBoot 項目帶你快速瞭解經過Jedis 把對象緩存到Redis中。 json

閱讀本文須要你瞭解如何搭建 SpringBoot 項目便可,另外須要瞭解的是本文SpringBoot 版本是 2.1.0.RELEASE。關於SpringBoot 集成 Jedis 請參考:玩轉 SpringBoot 2.x 之 快速集成 Jedis客戶端(普通版) 數組

接下來就讓咱們開始具體的代碼案例介紹吧! 緩存

代碼案例
演示經過將下面的 User 類建立的對象緩存到 Redis 中,具體有2種方式:序列化、Json。User 類具體代碼以下: 工具

public class User implements Serializable { 測試

    private String name;
    private Integer age; ui

    public User(String name,Integer age){
        this.name = name;
        this.age = age;
    }
    //省略 getter and setter 方法
} this

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

public abstract class JedisCacheServiceSupport {
    public static final long EXPIRE_MILLISECONDS_DEFAULT_LONG = 3*60*60*1000; 線程

    public Long getExpireTime(Long expireTime) {
        expireTime = (expireTime == null || expireTime.longValue() <= 0) ? EXPIRE_MILLISECONDS_DEFAULT_LONG : expireTime;
        return expireTime;
    } 日誌

    public void close(Jedis jedis){
        if(jedis != null){
            jedis.close();
        }
    }
}

序列化方式
序列化的方式經過現將對象轉換成二進制的流(序列化)後保存到 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對象。

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

@Service
public class JedisCacheService extends JedisCacheServiceSupport  {

    private static Logger logger = LoggerFactory.getLogger(JedisCacheService.class);

    @Autowired
    private JedisPool jedisPool;

    /**
     * 獲取緩存中的對象
     * @param key
     * @return
     */
    public Object getObject(String key) {
        Jedis jedis = null;
        Object object = null;
        try {
            jedis = jedisPool.getResource();
            byte[] ObjectByteArray = jedis.get(key.getBytes());
            object = unserialize(ObjectByteArray);
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            close(jedis);
        }
        return object;
    }

    /**
     *  將對象緩存到Redis中,設置默認過時時間
     * @param key
     * @param value
     */
    public void putObject(String key, Object value) {
        putObject(key,value,null);
    }
    /**
     *  將對象緩存到Redis中,自定義認過時時間
     * @param key
     * @param value
     */
    public void putObject(String key, Object value, Long expireTime) {
        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            jedis.psetex(key.getBytes(),getExpireTime(expireTime),serialize(value));
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            close(jedis);
        }
    }

    /**
     * 序列化
     * @param object
     * @return
     */
    public static byte[] serialize(Object object) {
        ObjectOutputStream oos = null;
        ByteArrayOutputStream baos = null;
        try {
            baos = new ByteArrayOutputStream();
            oos = new ObjectOutputStream(baos);
            oos.writeObject(object);
            byte[] bytes = baos.toByteArray();
            return bytes;
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        } finally {
            IOUtil.closeStream(oos);
            IOUtil.closeStream(baos);
        }
        return null;
    }

    /**
     * 反序列化
     * @param bytes
     * @return
     */
    public static Object unserialize(byte[] bytes) {
        if (bytes == null) return null;

        ByteArrayInputStream bais = null;
        ObjectInputStream ois = null;
        try {
            bais = new ByteArrayInputStream(bytes);
            ois = new ObjectInputStream(bais);
            return ois.readObject();
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        } finally {
            IOUtil.closeStream(bais);
            IOUtil.closeStream(ois);
        }
        return null;
    }
}

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

public class IOUtil {
    public static void closeStream(InputStream inputStream) {
        if (inputStream != null) {
            try {
                inputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
    }

    public static void closeStream(OutputStream outputStream) {
        if (outputStream != null) {
            try {
                outputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
    }
}

序列化方式演示
測試 JedisCacheService putObject(將對象放入緩存中)、getObject(從緩存中獲取對象),具體代碼以下:

@RunWith(SpringRunner.class)
@SpringBootTest
public class JedisCacheServiceTest {
    private  Logger logger = LoggerFactory.getLogger(JedisCacheService.class);
    @Autowired
    private JedisCacheService jedisCacheService;

    @Test
    public void putObject() {
        User user = new User("zhuoqiammingyue",19);
        jedisCacheService.putObject("user01",user);
        logger.info("緩存用戶成功!");
    }

    @Test
    public void getObject() {
        User user = (User)jedisCacheService.getObject("user01");
        logger.info("User name={},age={}",user.getName(),user.getAge());
    }
}

putObject 日誌信息:

2020-02-26 22:08:50.320  INFO 26748 --- [           main] cn.lijunkui.cache.JedisCacheServiceTest  : Started JedisCacheServiceTest in 7.157 seconds (JVM running for 9.357)
2020-02-26 22:08:51.144  INFO 26748 --- [           main] cn.lijunkui.cache.JedisCacheService      : 緩存用戶成功!

getObject 日誌信息:

2020-02-26 22:09:57.492  INFO 9612 --- [           main] cn.lijunkui.cache.JedisCacheServiceTest  : Started JedisCacheServiceTest in 7.07 seconds (JVM running for 8.902)
2020-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的依賴,具體依賴代碼以下:

<dependency>
        <groupId>com.google.code.gson</groupId>
        <artifactId>gson</artifactId>
        <version>2.8.5</version>
</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 方式保存和獲取對象具體代碼以下:

@Service
public class JedisJsonCacheService extends JedisCacheServiceSupport {

    private static Logger logger = LoggerFactory.getLogger(JedisJsonCacheService.class);

    @Autowired
    private JedisPool jedisPool;

    /**
     * 獲取緩存中的對象
     * @param key
     * @param clazz
     * @return
     */
    public Object getObject(String key,Class clazz) {
        Jedis jedis = null;
        Object object = null;
        try {
            jedis = jedisPool.getResource();
            String objectJson = jedis.get(key);
             object = toObjce(objectJson,clazz);
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            close(jedis);
        }
        return object;
    }

    /**
     * 將對象緩存到Redis中,設置默認過時時間
     * @param key
     * @param value
     */
    public void putObject(String key, Object value) {
        putObject(key, value,null);
    }

    /**
     * 將對象緩存到Redis中,自定義認過時時間
     * @param key
     * @param value
     * @param expireTime
     */
    public void putObject(String key, Object value, Long expireTime) {
        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            jedis.psetex(key,getExpireTime(expireTime),toJson(value));
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            close(jedis);
        }
    }

    /**
     * 將對象轉換成Json串
     * @param value
     * @return
     */
    private String toJson(Object value) {
        Gson gson = new Gson();
        return gson.toJson(value);
    }

    /**
     * 將Json串轉換成對象
     * @param json
     * @param clazz
     * @return
     */
    private Object  toObjce(String json,Class clazz) {
        Gson gson = new Gson();
        return gson.fromJson(json,clazz);
    }
}

序列化方式演示
測試 JedisJsonCacheServiceTest putObject(將對象放入緩存中)、getObject(從緩存中獲取對象),具體代碼以下:

@RunWith(SpringRunner.class)
@SpringBootTest
public class JedisJsonCacheServiceTest {

    private Logger logger = LoggerFactory.getLogger(JedisJsonCacheServiceTest.class);
    @Autowired
    private JedisJsonCacheService jedisJsonCacheService;

    @Test
    public void putObject() {
        User user = new User("zhuoqiammingyue2",20);
        jedisJsonCacheService.putObject("user02",user);
        logger.info("緩存用戶成功!");
    }

    @Test
    public void getObject() {
        User user = (User)jedisJsonCacheService.getObject("user02",User.class);
        logger.info("User name={},age={}",user.getName(),user.getAge());
    }
}

putObject 日誌信息:

2020-02-27 07:57:16.184  INFO 3692 --- [           main] c.l.cache.JedisJsonCacheServiceTest      : Started JedisJsonCacheServiceTest in 7.92 seconds (JVM running for 10.786)
2020-02-27 07:57:16.852  INFO 3692 --- [           main] c.l.cache.JedisJsonCacheServiceTest      : 緩存用戶成功!
1
2
getObject 日誌信息:

2020-02-27 07:57:56.359  INFO 27624 --- [           main] c.l.cache.JedisJsonCacheServiceTest      : Started JedisJsonCacheServiceTest in 7.364 seconds (JVM running for 9.256) 2020-02-27 07:57:56.824  INFO 27624 --- [           main] c.l.cache.JedisJsonCacheServiceTest      : User name=zhuoqiammingyue2,age=20 1 2 小結 序列化和Json這2種方式,在實際開發中能夠根據你的喜愛自行選擇。Json 方式使用的是Gson 固然你也能夠使用 FastJson ,序列化採用了 Java 原生的序列化和反序列化,同時你也能夠切換成效率更高的 Hessian 進行序列化和反序列化。

相關文章
相關標籤/搜索