SpringBoot下用Kyro作為Redis序列化工具
有時候我們需要將Java物件例項存入Redis,常用方法有兩種:
1. 將物件序列化成字串後存入Redis;
2. 將物件序列化成byte陣列後存入Redis;
本章實戰上述第二種方式,並且序列化工具選擇了Kyro,為了便於開發和驗證,將程式碼寫在一個基於SpringBoot的web工程中;
原始碼下載
本章實戰的原始碼可以在github下載,地址和連結資訊如下表所示:
名稱 | 連結 | 備註 |
---|---|---|
git倉庫地址(ssh) | [email protected]:zq2599/blog_demos.git | 該專案原始碼的倉庫地址,ssh協議 |
這個git專案中有多個資料夾,本章原始碼在springboot-redis-kyro-demo資料夾下,如下圖所示:
環境資訊
- JDK:1.8.0_144;
- SpringBoot:1.4.1.RELEASE;
- Kyro:4.0.0;
- Redis:3.2.11;
開發步驟列表
動手前先將整體步驟梳理一下:
1. 準備Reids環境;
2. 建立SpringBoot工程,新增依賴;
3. 在application.properties中配置Redis相關資訊;
4. 建立基於Kyro的序列化介面實現類;
5. 建立Redis配置類;
6. 將存、取、刪除等針對物件的基本操作封裝成一個服務類;
7. 開發一個Controller,對應幾個web介面,用來驗證對Redis的存、取、刪除操作;
8. 啟動工程,通過web請求操作,並在Redis後臺檢查資料;
步驟已經列清楚了,開始實戰吧!
準備Redis環境
如何安裝Reids就不在本章展開了,請自行準備,我這裡為了省事是在Docker上裝的,只需以下一行命令即可(前提是Docker可用):
docker run --name redis -p 6379:6379 -idt redis:3.2.11 redis-server --appendonly yes
建立SpringBoot工程,新增依賴
- spring-boot-starter-parent的版本是1.4.1.RELEASE;
- 基於maven建立SpringBoot工程,需要依賴:spring-boot-starter-web、spring-boot-starter-data-redis;
- 在pom.xml檔案中新增kyro、fastjson依賴,如下:
<!-- kyro相關 -->
<dependency>
<groupId>com.esotericsoftware</groupId>
<artifactId>kryo</artifactId>
<version>4.0.0</version>
</dependency>
<dependency>
<groupId>de.javakaffee</groupId>
<artifactId>kryo-serializers</artifactId>
<version>0.41</version>
</dependency>
<!-- fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.47</version>
</dependency>
在application.properties中配置Redis相關資訊
application.properties中的配置資訊如下,請注意IP地址和埠:
spring.redis.database=0
spring.redis.host=192.168.31.104
spring.redis.port=6379
spring.redis.pool.max-active=2500
spring.redis.pool.max-wait=6000
spring.redis.pool.max-idle=500
spring.redis.pool.min-idle=100
spring.redis.pool.testOnBorrow=true
spring.redis.pool.blockWhenExhausted=true
spring.redis.pool.numTestsPerEvictionRun=3
spring.redis.pool.timeBetweenEvictionRunsMillis=-1
spring.redis.timeout=1000
建立基於Kyro的序列化介面實現類
建立RedisSerializer介面的實現類,後續的序列化和反序列化操作都由該類完成:
public class KryoRedisSerializer<T> implements RedisSerializer<T> {
private static final Logger logger = LoggerFactory.getLogger(KryoRedisSerializer.class);
public static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
private static final ThreadLocal<Kryo> kryos = ThreadLocal.withInitial(Kryo::new);
private Class<T> clazz;
public KryoRedisSerializer(Class<T> clazz) {
super();
this.clazz = clazz;
}
@Override
public byte[] serialize(T t) throws SerializationException {
if (t == null) {
return EMPTY_BYTE_ARRAY;
}
Kryo kryo = kryos.get();
kryo.setReferences(false);
kryo.register(clazz);
try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
Output output = new Output(baos)) {
kryo.writeClassAndObject(output, t);
output.flush();
return baos.toByteArray();
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
return EMPTY_BYTE_ARRAY;
}
@Override
public T deserialize(byte[] bytes) throws SerializationException {
if (bytes == null || bytes.length <= 0) {
return null;
}
Kryo kryo = kryos.get();
kryo.setReferences(false);
kryo.register(clazz);
try (Input input = new Input(bytes)) {
return (T) kryo.readClassAndObject(input);
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
return null;
}
}
上述程式碼有以下三點需要注意:
1. kryos是ThreadLocal物件,由ThreadLocal.withInitial建立,如此一來,每次呼叫kryos.get方法,都能取出當前執行緒對應的Kryo例項,如果沒有會呼叫new方法建立;
2. serialize方法負責將物件例項序列化成byte陣列;
3. deserialize方法複製將byte陣列反序列化成物件例項;
建立Redis配置類
Redis配置類如下,通過setValueSerializer方法將KryoRedisSerializer設定位value的序列化器:
@Configuration
public class RedisConfig {
/**
* redisTemplate 序列化使用的Serializeable, 儲存二進位制位元組碼, 所以自定義序列化類
* @param redisConnectionFactory
* @return
*/
@Bean
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<Object, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
// redis value使用的序列化器
template.setValueSerializer(new KryoRedisSerializer<>(Object.class));
// redis key使用的序列化器
template.setKeySerializer(new StringRedisSerializer());
template.afterPropertiesSet();
return template;
}
}
將存、取、刪除等針對物件的基本操作封裝成一個服務類
本次會用到存、取、刪除等操作,所以做個簡單的封裝,實際使用中,您可以自己定製:
/**
* @Description : 封裝了redis的操作
* @Author : [email protected]
* @Date : 2018-06-10 22:52
*/
@Service
public class RedisClient {
private static final Logger logger = LoggerFactory.getLogger(RedisClient.class);
@Autowired
private RedisTemplate<Object, Object> redisTemplate;
private RedisConnection getConnection() {
return redisTemplate.getConnectionFactory().getConnection();
}
/**
* 釋放連線
* @param redisConnection
*/
private void releaseConnection(RedisConnection redisConnection){
if(null!=redisConnection && null!=redisTemplate){
RedisConnectionFactory redisConnectionFactory = redisTemplate.getConnectionFactory();
if(null!=redisConnectionFactory){
RedisConnectionUtils.releaseConnection(redisConnection, redisConnectionFactory);
}
}
}
/**
* 獲取快取的key
* @param id
* @return
*/
private <T> byte[] getKey(T id) {
RedisSerializer serializer = redisTemplate.getKeySerializer();
return serializer.serialize(id);
}
/**
* 更新快取中的物件,也可以在redis快取中存入新的物件
*
* @param key
* @param t
* @param <T>
*/
public <T> void set(String key, T t) {
byte[] keyBytes = getKey(key);
RedisSerializer serializer = redisTemplate.getValueSerializer();
byte[] val = serializer.serialize(t);
RedisConnection redisConnection = getConnection();
if(null!=redisConnection){
try {
redisConnection.set(keyBytes, val);
}finally {
releaseConnection(redisConnection);
}
}else{
logger.error("1. can not get valid connection");
}
}
/**
* 刪除指定物件
* @param key
* @return
*/
public long del(String key){
RedisConnection redisConnection = getConnection();
long rlt = 0L;
if(null!=redisConnection){
try {
rlt = redisConnection.del(getKey(key));
}finally {
releaseConnection(redisConnection);
}
}else{
logger.error("1. can not get valid connection");
}
return rlt;
}
/**
* 從快取中取物件
*
* @param key
* @param <T>
* @return
*/
public <T> T getObject(String key) {
byte[] keyBytes = getKey(key);
byte[] result = null;
RedisConnection redisConnection = getConnection();
if(null!=redisConnection){
try {
result = redisConnection.get(keyBytes);
}finally {
releaseConnection(redisConnection);
}
}else{
logger.error("2. can not get valid connection");
}
return null!=redisConnection ? (T) redisTemplate.getValueSerializer().deserialize(result) : null;
}
}
以上程式碼有一處需注意:Redis連線物件RedisConnection使用完畢後,一定要記得釋放!
上面用到的Person是個簡單物件,如下:
package com.bolingcavalry.springbootrediskyrodemo.bean;
import java.io.Serializable;
public class Person implements Serializable{
private static final long serialVersionUID = 1L;
private int id;
private String name;
private int age;
public String getName() {
return name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
啟動工程,通過web請求操作,並在Redis後臺檢查資料
現在可以啟動SpringBoot工程進行驗證了:
1. 執行SpringBootApplication;
2. 在瀏覽器輸入http://localhost:8080/add/1/Jerry/11即可新增一條記錄(注意localhost:8080換成您的服務所在地址和埠),如下圖:
3. 用redis-cli命令登入redis,執行命令get person_1,看到內容如下:
[email protected]:/data# redis-cli
127.0.0.1:6379> get person_1
"\x01\x00com.bolingcavalry.springbootrediskyrodemo.bean.Perso\xee\x02\x02Jerr\xf9"
127.0.0.1:6379> get person_1
(nil)
至此,使用Kyro作為redis序列化工具的實戰已經完成,希望能對您的開發提供一些參考;
相關推薦
SpringBoot下用Kyro作為Redis序列化工具
有時候我們需要將Java物件例項存入Redis,常用方法有兩種: 1. 將物件序列化成字串後存入Redis; 2. 將物件序列化成byte陣列後存入Redis; 本章實戰上述第二種方式,並且序列化工具選擇了Kyro,為了便於開發和驗證,將程式碼寫在一個基於
pytorch下可采用visidom作為可視化工具
設置 運行 opts data 不能 文件鏈接 沒有 上網 bsp 2018/9/18更新 感覺tensorboardX插件更好用,已轉用https://github.com/lanpa/tensorboardX 更新:新版visdom0.1.7安裝方式為:conda
自定義redis序列化工具
我們 utils 字節數 pac keys ted ive onu 問題 redis一個優點就是可以將數據寫入到磁盤中。 我們知道寫入磁盤的數據實際上都是以字節(0101這樣的二進制數據)的形式寫入的。 這意味著如果我們要將一個對象寫入磁盤,就必須將這個對象序列化。 jav
Springboot+Redis序列化坑
今天在測試springboot整合redis的時候遇到下面這個坑,百度來百度去發現提示都是ajax的問題,真的是醉了,錯誤提示如下所示,不信大家可以直接複製百度一下答案是什麼(流淚中。。。。),錯誤如下: org.springframework.data.redis.serializer.Seria
SpringBoot Redis序列化配置
Redis配置 #Redis spring.redis.host= spring.redis.port=6379 spring.redis.database=0 # Redis伺服器連線密碼(預設為空) spring.redis.password= # 連線池最大連線數(使用負值表示沒有限制) sp
redis 序列化存入對象
rac ioe tin pan input trace cnblogs bject oid redis 序列化存入對象 //序列化 public static byte [] serialize(Object obj){ ObjectOutpu
redis序列化對象操作
com sql iss stat nts 字符 project esc sage 在項目開發過程中,一些經常用到但又基本不變的對象信息我們可以把它緩存起來,這樣可以減少我們操作msql等數據庫的時間 緩存對象信息最常用的有兩種,一種是將對象信息轉成json形式的字符串緩存起
Redis 序列化方式StringRedisSerializer、FastJsonRedisSerializer和KryoRedisSerializer
out public ack 我們 must instance key) strings initial 當我們的數據存儲到Redis的時候,我們的鍵(key)和值(value)都是通過Spring提供的Serializer序列化到數據庫的。RedisTemplate默認使
Redis-序列化和存儲模式
min 無法 dump hang 兩種模式 行操作 請求 開啟 日誌 Redis中數據存儲模式有2種:cache-only,persistence; ? cache-only即只做為“緩存”服務,不持久數據,數據在服務終止後將消失,此模式下也將不存在“數據恢復”的手段,是一
改變可識別redis序列化方式
bind creat void fast 定義 fault 字體 object autoconf 原來系統所看到的是jdk的默認序列化方式,需要更改設置才可以變為可識別的字體 package com.redisSeri.data.redis; import com.
Spring Data Redis 序列化
mar ext 速度 亦或 access 序列化機制 png 現在 圖片 在Spring中使用的Redis緩存數據,可以通過RedisTemplate直接操作,也可以通過@Cacheable註解實現緩存(可參照另一篇文章的介紹:Spring Cachable Key的定義及
C 下JSON字串的反序列化
分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!  
redis序列化java8 LocalDateTime
org.springframework.data.redis.serializer.SerializationException: Could not read JSON: Can not construct instance of java.time.LocalDateTime: no su
linux下用docker啟動redis叢集
問題起源:我在專案中連線redis叢集連線不上,在伺服器上檢視redis叢集是否啟動。----伺服器虛擬機器用的是docker; 首先用命令:docker ps -a檢視開啟/關閉狀態; 可以看到reids-d1、reids-d2已經redis-s0、redis-s1、redis-s2
mac下安裝redis 和 redis視覺化工具rdm並且連線redis
一、安裝redis 最最最最簡單和推薦的方法就是使用brew命令安裝,前提是你的mac要安裝brew brew install redis 然後就等安裝完畢就好了 二、安裝rdm 直接安裝rdm dmg檔案 https://pan.baidu.com/s/10vpdhw7YfDD7G4y
spring-redis序列化
(一)spring data redis 提供了多種可選擇策略(RedisSerializer) JdkSerializationRedisSerializer:POJO物件的存取場景,使用JDK本身序列化機制,將pojo類通過ObjectInputStream
springboot學習——使用HttpMessageConverter進行http序列化和反序列化
本文轉發自:https://segmentfault.com/a/1190000012658289 物件的序列化/反序列化大家應該都比較熟悉:序列化就是將object轉化為可以傳輸的二進位制,反序列化就是將二進位制轉化為程式內部的物件。序列化/反序列化主要體現在程式I/O這個過程中,包括網路I/
在SpringBoot下用java操作MongoDB資料庫的增刪改查
首先我們需要建立一個SpringBoot工程,在IDEA中有快捷的建立方式。new -> project -> Spring Initializr 根據需要一路next下去即可第二步,給application.properties新增MongoDB配置#Mongo
關於:“無法序列化會話狀態。在“StateServer”或“SQLServer”模式下,ASP.NET 將序列化會話狀態物件,因此不允許使用無法序列化的物件或 MarshalByRef 物件。如果自定義會話狀態儲存在“Custom”模式下執行了類似的序列化
錯誤描述: 無法序列化會話狀態。在“StateServer”或“SQLServer”模式下,ASP.NET 將序列化會話狀態物件,因此不允許使用無法序列化的物件或 MarshalByRef 物件。如果
spring整合redis,序列化物件,以及websocket依賴注入
最近業餘在使用websocket開發一個聊天系統,打算使用redis儲存聊天記錄。 首先匯入spring整合redis的包spring-data-redis-1.6.2.RELEASE.jar, redis java驅動包jedis-2.9.0.ja