1. 程式人生 > >Redis儲存快取工具類簡單封裝

Redis儲存快取工具類簡單封裝

一、公共實體類

(1)User.java
package cn.xiyou.entity;

import java.io.Serializable;

/**
 * User實體
 * 
 * @author XIOAHU
 *
 */
public class User implements Serializable {
    private static final long serialVersionUID = -5811774997813073219L;

    private String name;
    private Integer age;
    private
Character gender;// 資料型別請忽略,只為測試 public User() { } public User(String name, Integer age, Character gender) { super(); this.name = name; this.age = age; this.gender = gender; } public String getName() { return name; } public void
setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public Character getGender() { return gender; } public void setGender(Character gender) { this
.gender = gender; } @Override public String toString() { return "User [name=" + name + ", age=" + age + ", gender=" + gender + "]"; } }
(2)Person.java
package cn.xiyou.entity;

import java.util.List;

/**
 * Person實體類
 * 
 * @author XIAOHU
 *
 */
public class Person {

    private String name;
    private List<User> uList;

    public Person() {

    }

    public Person(String name, List<User> uList) {
        super();
        this.name = name;
        this.uList = uList;
    }

    public String getName() {
        return name;
    }

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

    public List<User> getuList() {
        return uList;
    }

    public void setuList(List<User> uList) {
        this.uList = uList;
    }

    @Override
    public String toString() {
        return "Person [name=" + name + ", uList=" + uList + "]";
    }

}

二、使用ProtostuffIOUtil提供的序列化機制,封裝Redis儲存工具

  • redis其原生的jedis並沒有實現內部序列化操作,不像memcached內部做了序列化。當高併發時,dk自帶的序列化機制serializable效率比較低,序列化後的檔案大, 故,採用開源社群提供protostuff,它提供的序列化機制效率較高。

  • protostuff把一個物件轉化為二進位制陣列,存入redis中。當獲取時,將得到的二進位制陣列byte[](物件或圖片或文字儲存形式都是二進位制陣列)反序列化得到Object物件。protostuff只需要知道這個物件是什麼class,內部有一個schema描述這個class是什麼結構。並要求該物件為POJO型別,即有getter、setter方法java物件。

(1)工具類:RedisClientUtil.java
package cn.xiyou.utils;

import java.util.List;

import io.protostuff.LinkedBuffer;
import io.protostuff.ProtostuffIOUtil;
import io.protostuff.runtime.RuntimeSchema;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

public class RedisClientUtil {

    /**
     * 連線池
     */
    private static JedisPool pool;

    static {
        pool = new JedisPool("127.0.0.1", 6379);
    }

    /**
     * Redis儲存簡單型別
     * 
     * @param key
     * @param value
     * @return
     */
    public static String set(String key, String value) {
        Jedis jedis = pool.getResource();
        String set = jedis.set(key, value);
        jedis.close();
        return set;
    }

    /**
     * 獲取Redis儲存的簡單型別
     * 
     * @param key
     * @return
     */
    public static String get(String key) {
        Jedis jedis = pool.getResource();
        String value = jedis.get(key);
        jedis.close();
        return value;
    }

    /**
     * ProtostuffIOUtil序列化物件並使用Redis儲存
     * 
     * @param key
     * @param value
     * @param type
     * @return
     */
    public static String setObject(String key, Object value, Class<?> type) {
        Jedis jedis = pool.getResource();
        byte[] byteKey = key.getBytes();
        @SuppressWarnings("unchecked")
        RuntimeSchema<Object> schema = (RuntimeSchema<Object>) RuntimeSchema
                .createFrom(type);
        // 序列化
        byte[] bytes = ProtostuffIOUtil.toByteArray(value, schema,
                LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE));
        String set = jedis.set(byteKey, bytes);
        jedis.close();
        return set;
    }

    /**
     * ProtostuffIOUtil反序列物件並返回Redis中的物件
     * 
     * @param key
     * @param type
     * @return
     */
    @SuppressWarnings("unchecked")
    public static Object getObject(String key, Class<?> type) {
        Jedis jedis = pool.getResource();
        byte[] bytes = jedis.get(key.getBytes());
        RuntimeSchema<Object> schema = (RuntimeSchema<Object>) RuntimeSchema
                .createFrom(type);
        Object result = schema.newMessage();// 建立空物件
        ProtostuffIOUtil.mergeFrom(bytes, result, schema);// 把位元組陣列的資料存入result物件中
        jedis.close();
        return result;
    }

}
(2)測試類:TestRedis.java
package cn.xiyou.test;

import java.util.ArrayList;
import java.util.List;

import cn.xiyou.entity.Person;
import cn.xiyou.entity.User;
import cn.xiyou.utils.RedisClientUtil;

public class TestRedis {

    public static void main(String[] args) {

        /**
         * 測試儲存簡單型別(String key : String value)
         */
        RedisClientUtil.set("name", "zhang");
        String name = RedisClientUtil.get("name");
        System.out.println(name);// 輸出:zhang
        RedisClientUtil.set("age", "12");
        String age = RedisClientUtil.get("age");
        if (age != null) {
            System.out.println(Integer.parseInt(age));// 輸出:12
        }

        /**
         * 測試儲存簡單JavaBean
         */
        User u = new User("xiao", 18, '男');
        RedisClientUtil.setObject("user", u, User.class);
        User user1 = (User) RedisClientUtil.getObject("user", User.class);
        System.out.println(user1);
        // 輸出:User [name=xiao, age=18, gender=男]

        /**
         * 存取List集合
         * (以下測試失敗)不能直接儲存List集合,無法識別List儲存的具體的儲存型別
         */
        /*
        User u3 = new User("cai", 20, '女');
        ArrayList<User> aList = new ArrayList<User>();
        aList.add(u3);
        RedisClientUtil.setObject("aList", aList, ArrayList.class);
        @SuppressWarnings("unchecked")
        ArrayList<User> list2 = (ArrayList<User>) RedisClientUtil.getObject(
                "aList", ArrayList.class);
        System.out.println(list2.get(0));// 報異常:java.lang.ArrayIndexOutOfBoundsException:0
        for (Iterator<User> it = list2.iterator(); it.hasNext();) {
            User user = it.next();// 報異常:java.util.ConcurrentModificationException
            System.out.println(user);
        }
        */

        /**
         * 存取List集合
         * 【第一種】建議將List集合封裝成複雜JavaBean,即可。
         */
        User u2 = new User("cai", 20, '女');
        ArrayList<User> uList = new ArrayList<User>();
        uList.add(u2);
        Person p = new Person("哈哈", uList);
        RedisClientUtil.setObject("p", p, Person.class);
        Person pp = (Person) RedisClientUtil.getObject("p", Person.class);
        System.out.println(pp);
        // 輸出:Person [name=哈哈, uList=[User [name=cai, age=20, gender=女]]]

        /**
         * 儲存List集合
         * 【第二種】使用fastjson將其轉換為String儲存,取時再轉換成list即可。
         */
        User u5 = new User("cai", 20, '女');
        User u6 = new User("xiao", 18, '男');
        ArrayList<User> list2 = new ArrayList<User>();
        list2.add(u5);
        list2.add(u6);
        RedisClientUtil.set("list2", JSON.toJSONString(list2));
        String jsonStr = RedisClientUtil.get("list2");
        List<User> resultList = JSON.parseArray(jsonStr, User.class);
        System.out.println("====");
        System.out.println(resultList);
        //輸出:[User [name=cai, age=20, gender=女], User [name=xiao, age=18, gender=男]]

    }

}

三、使用JDK提供的序列化機制,封裝Redis儲存工具

(1)序列化工具類:JDKSerializeUtil.java
package cn.xiyou.utils;

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

/**
 * 封裝JDK提供的序列化
 * 
 * @author XIAOHU
 * 
 */
public class JDKSerializeUtil {

    /**
     * 單個物件序列化
     * 
     * @param object
     * @return
     */
    public static byte[] serialize(Object object) {
        if (object == null) {
            return null;
        }
        ObjectOutputStream oos = null;
        ByteArrayOutputStream baos = null;
        byte[] bytes = null;
        try {
            baos = new ByteArrayOutputStream();
            oos = new ObjectOutputStream(baos);
            oos.writeObject(object);
            bytes = baos.toByteArray();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            close(oos);
            close(baos);
        }
        return bytes;
    }

    /**
     * 單個物件反序列化
     * 
     * @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) {
            e.printStackTrace();
        } finally {
            close(bais);
            close(ois);
        }
        return null;
    }

    /**
     * 序列化 list 集合
     * 
     * @param list
     * @return
     */
    public static byte[] serializeList(List<?> list) {
        if (list == null || list.size() == 0) {
            return null;
        }
        ObjectOutputStream oos = null;
        ByteArrayOutputStream baos = null;
        byte[] bytes = null;
        try {
            baos = new ByteArrayOutputStream();
            oos = new ObjectOutputStream(baos);
            for (Object obj : list) {
                oos.writeObject(obj);
            }
            bytes = baos.toByteArray();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            close(oos);
            close(baos);
        }
        return bytes;
    }

    /**
     * 反序列化 list 集合
     * @param bytes
     * @return
     */
    public static List<?> unserializeList(byte[] bytes) {
        if (bytes == null) {
            return null;
        }
        List<Object> list = new ArrayList<Object>();
        ByteArrayInputStream bais = null;
        ObjectInputStream ois = null;
        try {
            // 反序列化
            bais = new ByteArrayInputStream(bytes);
            ois = new ObjectInputStream(bais);
            while (bais.available() > 0) {
                Object obj = (Object) ois.readObject();
                if (obj == null) {
                    break;
                }
                list.add(obj);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            close(bais);
            close(ois);
        }
        return list;
    }

    /**
     * 關閉io流物件
     * 
     * @param closeable 可用來關閉的資料的來源或目的地
     */
    public static void close(Closeable closeable) {
        if (closeable != null) {
            try {
                closeable.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

}
(2)Redis工具類:RedisClientUtil.java
package cn.xiyou.utils;

import java.util.List;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

public class RedisClientUtil {

    /**
     * 連線池
     */
    private static JedisPool pool;

    static {
        pool = new JedisPool("127.0.0.1", 6379);
    }

    /**
     * JDk序列物件並存儲List集合
     * 
     * @param key
     * @param list
     */
    public static void setList(String key, List<?> list) {
        Jedis jedis = pool.getResource();
        try {
            if (list == null || list.size() == 0) {// 如果list為空,則設定一個空串""
                jedis.set(key.getBytes(), "".getBytes());
            } else {
                jedis.set(key.getBytes(), JDKSerializeUtil.serializeList(list));
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            jedis.close();
        }
    }

    /**
     * JDK反序列物件並獲取List集合
     * 
     * @param key
     * @return
     */
    public static List<?> getList(String key) {
        Jedis jedis = pool.getResource();
        if (jedis == null || !jedis.exists(key)) {
            return null;
        }
        byte[] data = jedis.get(key.getBytes());
        jedis.close();
        return JDKSerializeUtil.unserializeList(data);
    }

}
(3)測試類:TestRedis.java
package cn.xiyou.test;

import java.util.ArrayList;
import java.util.List;

import cn.xiyou.entity.Person;
import cn.xiyou.entity.User;
import cn.xiyou.utils.RedisClientUtil;

public class TestRedis {

    public static void main(String[] args) {

        /**
         * 使用jdk提供的序列化,測試Redis儲存List集合
         */
        User u4 = new User("cai", 20, '女');
        ArrayList<User> list = new ArrayList<User>();
        list.add(u4);
        RedisClientUtil.setList("ulist", list);
        @SuppressWarnings("unchecked")
        List<User> list111 = (List<User>) RedisClientUtil.getList("ulist");
        System.out.println(list111);
        // 輸出:[User [name=cai, age=20, gender=女]]

    }

}

四、所用jar包列表

commons-pool2-2.3.jar
jedis-2.7.0.jar
protostuff-api-1.4.4.jar
protostuff-collectionschema-1.4.4.jar
protostuff-core-1.4.4.jar
protostuff-runtime-1.4.4.jar
fastjson-1.2.47.jar