redis存储对象

redis已经应用相当广泛了,但redis本身并没有直接存储对象的方法,我们可以通过转换对象的方式来存储对象。

大致总结了以下几种方案来存储对象:

方案一:序列化对象为二进制

使用redis的接口:

jedis.get(byte[] key)
jedis.set(byte[] key, byte[] value)

至于序列化方式,我们有很多种选择,比如:Java serialize,Protobuf,或者自己手动序列化都行

public byte[] serialize(Object obj);
public Object unSerialize(byte[] bytes);

方案二:序列化对象为字符串

使用redis的接口:

jedis.get(String key);
jedis.set(String key, String value);

序列化为字符串,我们也有很多选择:Json(Jackson,FastJson),Xml等方式

方案三:转换对象为Map

使用redis的接口:

jedis.hgetAll(String key);
jedis.hmset(String key, Map<String,String> values);

将对象转成一个map:

/**
	 * 将指定的对象数据封装成map
	 * 
	 * @param bean
	 *            对象数据
	 * @return
	 */
	@SuppressWarnings("all")
	public static Map<String, String> warp(AbstractRedisBean bean) {
		Map<String, String> propertyMap = new HashMap<String, String>();
		try {
			PropertyDescriptor[] ps = Introspector.getBeanInfo(bean.getClass())
					.getPropertyDescriptors();
			for (PropertyDescriptor propertyDescriptor : ps) {
				String propertyName = propertyDescriptor.getName();
				if (propertyName != null && !propertyName.equals(CLASS)) {
					Method getter = propertyDescriptor.getReadMethod();
					if (getter != null) {
						RedisBeanField mannota = getter
								.getAnnotation(RedisBeanField.class);
						if (mannota != null && mannota.serialize() == false) {
							continue;
						}
						propertyMap.put(propertyName,
								String.valueOf(getter.invoke(bean, null)));
					}
				}
			}
		} catch (Exception e) {
			logger.error(e);
		}
		return propertyMap;
	}

将map转成java对象:

/**
	 * 将map转成指定的对象
	 * 
	 * @param beanMap
	 *            map数据
	 * @param clazz
	 *            指定的类对象
	 * @return
	 */
	public static <T extends AbstractRedisBean> T reverse(
			Map<String, String> beanMap, Class<T> clazz) {
		T bean = getRedisBean(clazz);
		try {
			PropertyDescriptor[] ps = Introspector.getBeanInfo(clazz)
					.getPropertyDescriptors();
			for (PropertyDescriptor propertyDescriptor : ps) {
				String propertyName = propertyDescriptor.getName();
				if (propertyName != null && !propertyName.equals(CLASS)) {
					Method setter = propertyDescriptor.getWriteMethod();
					String value = beanMap.get(propertyName);
					String type = propertyDescriptor.getPropertyType()
							.getName();
					if (setter != null && value != null
							&& !value.equalsIgnoreCase("null")) {
						Object obj = value(value, type);
						if (obj != null) {
							setter.invoke(bean, obj);
						}
					}
				}
			}
		} catch (Exception e) {
			logger.error(e);
			e.printStackTrace();
		}
		bean.clearChangeMap();
		return bean;
	}

	/**
	 * 将String类型数值转换成指定的类型
	 * 
	 * @param value
	 *            数值
	 * @param type
	 *            指定的类型
	 * @return
	 */
	private static Object value(String value, String type) {
		if (type.equals("boolean")) {
			return Boolean.valueOf(value);
		} else if (type.equals("byte")) {
			return Byte.valueOf(value);
		} else if (type.equals("short")) {
			return Short.valueOf(value);
		} else if (type.equals("float")) {
			return Float.valueOf(value);
		} else if (type.equals("int")) {
			return Integer.valueOf(value);
		} else if (type.equals("java.lang.String")) {
			return value;
		} else if (type.equals("long")) {
			return Long.valueOf(value);
		}
		return null;
	}

这种方式有一个优势:在更新对象的时候不需要更新整个对象,只需要更新需要的字段。

总结:大致总结了三种方案,每种方式都有自己的优势和劣势,根据不同的需求进行选择。