前言
提到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 進行序列化和反序列化。