`
Josh_Persistence
  • 浏览: 1649834 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类

Redis缓存Object,List对象 - Java 对象和List的序列化和反序列化

阅读更多

一、到目前为止(jedis-2.2.0.jar),在Jedis中其实并没有提供这样的API对对象,或者是List对象的直接缓存,即并没有如下类似的API

jedis.set(String key, Object value)

jedis.set(String key, List<M> values)

 

而更多的API是类似于jedis.set(String key, String value)或者jedis.set(String key, String ... value)

 

那如果我们想缓存对象,怎么办呢?

 

二、通过研究Jedis的API,我们发现其提供了这样的API

jedis.set(byte[], byte[]),

 

通过这个API,很显然我们能够实现

jedis.set(String key, Object value)

jedis.set(String key, List<M> values)

 

我们需要关注的就是在cache的时候将Object和List对象转换成字节数组并且需要提供将字节数组转换成对象返回。

 

三、考虑到扩展性,设计了3个类,抽象父类SerializeTranscoder, 子类ListTranscoder和ObjectsTranscoder 以及一个Unit test 类 用于模拟对象,list对象和字节数组的转换,即Serialize和de-searilize的过程。

 

1. SerializeTranscoder

 

 

package com.chuanliu.platform.activity.basic.util.serialize;

import java.io.Closeable;

import org.apache.log4j.Logger;


/**
 * @author Josh Wang(Sheng)
 *
 * @email  josh_wang23@hotmail.com
 */
public abstract class SerializeTranscoder {

	protected static Logger logger = Logger.getLogger(SerializeTranscoder.class);
	
	public abstract byte[] serialize(Object value);
	
	public abstract Object deserialize(byte[] in);
	
	public void close(Closeable closeable) {
		if (closeable != null) {
			try {
				closeable.close();
			} catch (Exception e) {
				 logger.info("Unable to close " + closeable, e); 
			}
		}
	}
}

 

 

2. ListTranscoder

 

package com.chuanliu.platform.activity.basic.util.serialize;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import com.chuanliu.platform.activity.basic.util.LoggerUtils;


/**
 * Case 1.
 * Jedis does not support cache the Object directly, the Objects needed to be 
 * serialized and de-serialized
 * 
 * Case 2.
 * coming very soon...
 * 
 * @author Josh Wang(Sheng)
 *
 * @email  josh_wang23@hotmail.com
 */
public class ListTranscoder<M extends Serializable> extends SerializeTranscoder {
	
	@SuppressWarnings("unchecked")
	public List<M> deserialize(byte[] in) {
		List<M> list = new ArrayList<>();
		ByteArrayInputStream bis = null;
		ObjectInputStream is = null;
		try {
			if (in != null) {
				bis = new ByteArrayInputStream(in);
				is = new ObjectInputStream(bis);
				while (bis.available() > 0) {
                                      // while(true) will throw EOFException
					M m = (M)is.readObject();
					if (m == null) {
						break;
					}
					
					list.add(m);
					
				}
				is.close();
				bis.close();
			}
		} catch (IOException e) {  
            LoggerUtils.error(logger, String.format("Caught IOException decoding %d bytes of data",  
                    in == null ? 0 : in.length) + e);  
        } catch (ClassNotFoundException e) {  
            LoggerUtils.error(logger, String.format("Caught CNFE decoding %d bytes of data",  
                    in == null ? 0 : in.length) + e);  
        }  finally {
			close(is);
			close(bis);
		}
		
		return  list;
	}
	

	@SuppressWarnings("unchecked")
	@Override
	public byte[] serialize(Object value) {
		if (value == null)
			throw new NullPointerException("Can't serialize null");
		
		List<M> values = (List<M>) value;
		
		byte[] results = null;
		ByteArrayOutputStream bos = null;
		ObjectOutputStream os = null;
		
		try {
			bos = new ByteArrayOutputStream();
			os = new ObjectOutputStream(bos);
			for (M m : values) {
				os.writeObject(m);
			}
			
			// os.writeObject(null);
			os.close();
			bos.close();
			results = bos.toByteArray();
		} catch (IOException e) {
			throw new IllegalArgumentException("Non-serializable object", e);
		} finally {
			close(os);
			close(bos);
		}
		
		return results;
	}

	
}

 

3. ObjectsTranscoder

package com.chuanliu.platform.activity.basic.util.serialize;



import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

import com.chuanliu.platform.activity.basic.util.LoggerUtils;

/**
 * Case 1.
 * Jedis does not support cache the Object directly, the Objects needed to be 
 * serialized and de-serialized
 * 
 * Case 2.
 * coming very soon...
 * 
 * @author Josh Wang(Sheng)
 *
 * @email  josh_wang23@hotmail.com
 */
public class ObjectsTranscoder<M extends Serializable> extends SerializeTranscoder {

	
	@SuppressWarnings("unchecked")
	@Override
	public byte[] serialize(Object value) {
		if (value == null) {  
		    throw new NullPointerException("Can't serialize null");  
		}  
        byte[] result = null;  
        ByteArrayOutputStream bos = null;  
        ObjectOutputStream os = null;  
        try {  
            bos = new ByteArrayOutputStream();  
            os = new ObjectOutputStream(bos);
            M m = (M) value;
            os.writeObject(m);  
            os.close();  
            bos.close();  
            result = bos.toByteArray();  
        } catch (IOException e) {  
            throw new IllegalArgumentException("Non-serializable object", e);  
        } finally {  
            close(os);  
            close(bos);  
        }  
        return result;  
	}

	@SuppressWarnings("unchecked")
	@Override
	public M deserialize(byte[] in) {
		M result = null;  
		ByteArrayInputStream bis = null;  
		ObjectInputStream is = null;  
		try {  
	      if (in != null) {  
	          bis = new ByteArrayInputStream(in);  
	          is = new ObjectInputStream(bis);  
	          result = (M) is.readObject();  
	          is.close();  
	          bis.close();  
	      }  
		} catch (IOException e) {  
	      LoggerUtils.error(logger, String.format("Caught IOException decoding %d bytes of data",  
	              in == null ? 0 : in.length) + e);  
		} catch (ClassNotFoundException e) {  
	      LoggerUtils.error(logger, String.format("Caught CNFE decoding %d bytes of data",  
	              in == null ? 0 : in.length) + e);  
		} finally {  
	      close(is);  
	      close(bis);  
		}  
	  return result;  
	}
}

 

4. TestSerializerTranscoder

 

package com.chuanliu.platform.activity.basic.util;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import org.junit.Test;

import com.chuanliu.platform.activity.basic.util.serialize.ListTranscoder;
import com.chuanliu.platform.activity.basic.util.serialize.ObjectsTranscoder;

/**
 * @author Josh Wang(Sheng)
 *
 * @email  josh_wang23@hotmail.com
 */
public class TestSerializerTranscoder implements Serializable {
	
	private static final long serialVersionUID = -1941046831377985500L;

	public TestSerializerTranscoder() {
		
	}

	@Test
	public void testObject() {
		List<TestUser> lists = buildTestData();
		
		TestUser userA = lists.get(0);
		
		ObjectsTranscoder<TestUser> objTranscoder =  new ObjectsTranscoder<>();
		
		byte[] result1 = objTranscoder.serialize(userA);
		
		TestUser userA_userA = objTranscoder.deserialize(result1);
		
		System.out.println(userA_userA.getName() + "\t" + userA_userA.getAge());
	}
	
	@Test
	public void testList() {
		List<TestUser> lists = buildTestData();
		

		ListTranscoder<TestUser> listTranscoder = new ListTranscoder<>();
		
		byte[] result1 = listTranscoder.serialize(lists);
		
		List<TestUser> results = listTranscoder.deserialize(result1);
	
		for (TestUser user : results) {
			System.out.println(user.getName() + "\t" + user.getAge());
		}
		
	}
	
	private static List<TestUser> buildTestData() {
		TestSerializerTranscoder tst = new TestSerializerTranscoder();
		TestUser userA =  tst.new TestUser();
		userA.setName("lily"); 
        userA.setAge(25);
		
        
        TestUser userB = tst.new TestUser();  
        
        
        userB.setName("Josh Wang"); 
		userB.setAge(28);
        
        List<TestUser> list = new ArrayList<TestUser>();  
        list.add(userA);  
        list.add(userB);  
        
        return list;  
    }
	
	class TestUser implements Serializable {
		private static final long serialVersionUID = 1L;

			private String name;
			
			private int age;
			

			public String getName() {
				return name;
			}

			public void setName(String name) {
				this.name = name;
			}

			public int getAge() {
				return age;
			}

			public void setAge(int age) {
				this.age = age;
			}
			
		}
	
	
}

 

四、通过以上几步后,即可使用Jedis的API进行对象的缓存并将从缓存中返回的二进制数组转换成原始的对象或者是List对象了。

 

 

1
0
分享到:
评论
1 楼 wangkaick 2014-07-31  
那还不得慢死

相关推荐

    redis工具类-Java开发

    示例代码展示了如何将 List 和 Map 类型的数据序列化为 JSON 字符串,并将其反序列化回原始的 Java 对象: ```java public static void listToJson() { // 创建 Person 对象列表 List&lt;Person&gt; list = new ...

    java 对Redis的导入和导出

    在Java开发中,Redis作为一个高性能的键值存储系统,常被用作缓存或数据库,其数据操作便捷高效。为了在不同的服务器之间迁移或者备份Redis中的数据,我们需要实现数据的导入与导出功能。本篇将详细介绍如何使用Java...

    redis 增删(obj,list)

    Redis 是一个高性能的键值对数据存储系统,常被用作数据库、缓存和消息中间件。在本项目中,我们关注的是Redis如何处理对象(obj)和列表(list)的增删操作,以及如何结合Spring框架进行集成使用。下面我们将深入...

    Redis集成Spring的Java代码

    在IT行业中,Redis是一款广泛应用的高性能键值存储系统,常被用作缓存和数据库解决方案。集成Redis到Spring框架中可以极大地提升应用的响应速度和数据处理能力。本篇文章将详细探讨如何通过Java代码实现Redis与...

    RedisTemplate-redis-优雅玩法

    在Java中,我们通常需要将对象转换为字节流(序列化)以便存储到Redis中,然后再从字节流恢复为对象(反序列化)。RedisTemplate默认使用JdkSerializationRedisSerializer,但这种方式的性能并不理想。为了提高效率...

    redis基本命令irst-JavaWeb-ma开发笔记

    Redis是一款高性能的键值对数据库,常用于缓存和消息队列等场景。在JavaWeb开发中,Redis的使用非常广泛,能够显著提高应用程序的性能和响应速度。本笔记将探讨Redis的一些基本命令,以及如何在Java环境中进行操作。...

    spring-data-redis-1.6.0.RELEASE.jar + jedis-2.7.2.jar

    在IT行业中,Redis和Jedis是两个非常重要的组件,它们在大数据处理、缓存管理和分布式系统中发挥着关键作用。Spring Data Redis则是Spring框架提供的一套用于操作Redis的高级抽象库,它使得与Redis的数据交互变得...

    Redis缓存,泛型集合与json字符串的相互转换实例

    在本文中,我们将深入探讨Redis缓存的使用,以及如何在Java中处理泛型集合和JSON字符串之间的相互转换。这些技术对于构建高效、可扩展的Web应用程序至关重要,尤其是在处理大量数据时,缓存和数据序列化可以显著提高...

    mybatis plus使用redis作为二级缓存的方法

    接下来,需要定义一个 RedisTemplate 的 Bean,用于将对象序列化到 Redis 中。可以在 Spring Boot 应用程序中添加以下代码: ```java @Bean(value = "redisTemplate") public RedisTemplate, Object&gt; redisTemplate...

    java高级面试篇之redis面试收集总结-62题附答案).docx

    String类型是二进制安全的,这意味着它可以安全地存储任何类型的数据,包括但不限于图片或序列化的对象。 - **最大存储容量**:单个String类型的值最大能存储512MB。 - **常见命令**:get、set、incr、decr、mget等...

    Java-Redisson-ProtoBufCodec:在Redis的缓存过程中实现协议缓冲区编解码器以对数据进行编码和解码

    这将生成`User.java`,其中包含`User`类的序列化和反序列化方法。 现在,我们来创建一个自定义的ProtoBufCodec。Redisson支持自定义的Codec,可以通过实现`org.redisson.codec.Codec`接口来完成。这里我们创建一个...

    spring-redis-maven整合带安装包

    Spring Redis 是一个集成Redis数据库与Spring框架的模块,它提供了对Redis数据存储的全面支持,使得在Java应用中使用Redis变得更加...通过理解和实践上述步骤,你可以轻松地在Java项目中使用Redis进行数据存储和缓存。

    Spring boot redis demo.rar

    确保你的对象类具有合适的getter和setter方法,以便正确序列化和反序列化。 最后,为了测试这个Demo,你可以创建一个Controller,调用上述Service的方法,以实现存取数据的功能,并观察控制台输出或实际的Redis数据...

    spring+redis

    在这个配置中,我们指定了Redis服务器的地址和端口,并配置了序列化器,因为Redis存储的是字节流,需要序列化和反序列化Java对象。这里使用了StringRedisSerializer处理键,以及`GenericJackson2JsonRedisSerializer...

    spring集成redis

    Spring Boot自动配置会为我们创建一个默认的`RedisTemplate`,但通常我们需要自定义序列化方式。以下是如何在配置类中创建`RedisTemplate`的示例: ```java @Configuration public class RedisConfig { @Bean ...

    java 编程 redis手册 c cjson.zip

    在IT行业中,Java编程、Redis缓存技术和C/C++中的cJSON库是三个重要的技术领域。下面将分别详细探讨这三个主题。 首先,Java编程是一种广泛使用的面向对象的编程语言,以其跨平台性、丰富的类库和高效性能而受到...

    java面试笔记整理,包含java,redis,kafka等

    - **保证序列化兼容性:** 如果类的结构发生变化,serialVersionUID保持一致有助于确保反序列化时的兼容性。 #### 四十七、static属性不被序列化的原因 - **static属性属于类而不是对象实例,因此不在序列化过程中...

    Redis 命令参考

    字符串是最基础的键值对类型,可以包含任何数据,如图片或序列化的对象。 - `APPEND` 命令用于在字符串值的末尾追加数据。 - `BITCOUNT` 和 `BITOP` 命令用于对字符串表示的位数组进行操作。 - `DECR`、`DECRBY`、`...

    spring boot - redis-1

    // 可以添加序列化配置,如JdkSerializationRedisSerializer或StringRedisSerializer return template; } ``` 4. **使用RedisTemplate操作数据** `RedisTemplate`提供了丰富的API来进行数据的增删改查操作。...

    Redisdemo.zip

    - Redis 中最基础的数据类型,用于存储单个值,可以是数字、字符串或其他可序列化的值。 - 可以使用 `SET`、`GET`、`INCR`(递增)、`DECR`(递减)等命令进行操作。 4. **映射(Map)/哈希(Hash)**: - 用于...

Global site tag (gtag.js) - Google Analytics