java protostuff實現文件級數據緩存,使用文件緩存對象,java文件級數據緩存

由於業務需要使用文件級別的緩存,特此採用protostuff加上基本的TXT文件操作,來實現基於文件的緩存。

實現以下功能:

文件級別緩存的對象工具類

1、傳入一個對象和緩存時間還有緩存名稱對這個對象進行緩存

2、傳入一個緩存名稱查詢是否存在這個名稱的緩存

3、傳入一個緩存名稱和該類的類型對象獲取對應的緩存

4、傳入一個緩存名稱刪除該名稱的緩存

模塊一:protostuff序列化使用類

package tool;

import io.protostuff.LinkedBuffer;
import io.protostuff.ProtostuffIOUtil;
import io.protostuff.runtime.RuntimeSchema;

/**
 * Created by yy on 2017/9/28.
 * 用與序列化以及反序列化對象的類
 * 1、傳入一個對象,返回該對象序列化後的字節數組
 * 2、傳入字節數組和類的類型對象,獲取這個數據的反序列對象
 */
public class Serialization {
    /**
     * 傳入一個對象,返回這個對象的序列化後的字節數組
     * @param object 需要實例化的對象
     * @param <T> 傳入對象的類型
     * @return 返回對應的字節數組
     * @throws Exception 序列化失敗繼續拋出異常
     */
    public static <T> byte[] sequence(T object) throws Exception{
        //安全判斷,要是傳入的對象爲空返回對應的也是空
        if(object==null){
            return null;
        }
        //獲取對應的類
        Class<T> objectClass = (Class<T>) object.getClass();
        //使用LinkedBuffer分配一塊默認大小的buffer空間;
        LinkedBuffer linkedBuffer = LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE);
        try {
            //生成對應的圖,返回對應的字節數組
            //使用ProtoStuff-runtime生成模式,以便在運行時通過反射進行緩存和使用。
            RuntimeSchema<T> runtimeSchema = RuntimeSchema.createFrom(objectClass);
            return ProtostuffIOUtil.toByteArray(object, runtimeSchema, linkedBuffer);
        } catch (Exception e) {
            //繼續拋出異常
            throw new RuntimeException("對象序列化失敗!",e);
        } finally {
            //關閉Buffer空間
            linkedBuffer.clear();
        }
    }

    /**
     * 根據穿進來的字節數組和具體的類的類型對象,獲取對應反序列的結果對象
     * @param info 序列化完成的字節數組對象
     * @param classInfo 類的類型對象
     * @param <T> 具體要轉換的類類型
     * @return 序列化成功返回序列化前的對象,要是傳入的數據爲空返回空對象
     * @throws Exception 拋出反序列化的異常
     */
    public static <T> T reverse(byte[] info,Class<T> classInfo)throws Exception{
        //安全判斷
        if(info.length==0||classInfo==null){
            return null;
        }
        //根據傳進來的數據反序列具體對象
        try{
            RuntimeSchema<T> runtimeSchema = RuntimeSchema.createFrom(classInfo);
            T object =runtimeSchema.newMessage();
            ProtostuffIOUtil.mergeFrom(info,object,runtimeSchema);
            return object;
        }catch(Exception e){
            throw new RuntimeException("反序列對象失敗!",e);
        }
    }
}

模塊二:MD5加密(用於文件名生成)

package tool;

import java.security.MessageDigest;

/**
 * md5的生成類
 * Created by yy on 2017/10/11.
 */
public class MD5maker {
    public static String make(String value){
        String md5str = "";
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            byte[] input = value.getBytes();
            byte[] buff = md.digest(input);
            md5str = bytesToHex(buff);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return md5str;
    }

    /**
     * 換成16進制
     * @param bytes
     * @return
     */
    private static String bytesToHex(byte[] bytes) {
        StringBuffer md5str = new StringBuffer();
        int digital;
        for (int i = 0; i < bytes.length; i++) {
            digital = bytes[i];
            if (digital < 0) {
                digital += 256;
            }
            if (digital < 16) {
                md5str.append("0");
            }
            md5str.append(Integer.toHexString(digital));
        }
        return md5str.toString().toUpperCase();
    }
}

模塊三:緩存工具類

package tool;

import org.apache.commons.lang3.StringEscapeUtils;

import java.io.*;

/**
 * Created by yy on 2017/9/29.
 * 文件級別緩存的對象工具類
 * 1、傳入一個對象和緩存時間還有緩存名稱對這個對象進行緩存
 * 2、傳入一個名稱查詢是否存在這個名稱的緩存
 * 3、傳入一個名稱和該類的類型對象獲取對應的緩存
 * 4、傳入一個緩存名稱刪除該名稱的緩存
 */
public class CacheBF {
    /**
     * 根據穿進來的名稱和實體緩存對象到文件中
     * @param name 鍵名
     * @param object 需要保存的實體
     * @param time 過期時間秒
     * @param <T> 傳入的實體類型
     * @return 保存成功返回true,失敗返回false
     */
    public static <T> boolean  cache(String name,T object,int time) throws Exception{

        File file=CacheBF.getCacheFile(name);//獲取緩存文件
        FileWriter fw=new FileWriter(file);
        BufferedWriter bw = new BufferedWriter(fw);
        //設置過期時間
        bw.write((System.currentTimeMillis()+(time*1000))+"");
        bw.newLine();
        //設置緩存信息
        bw.write(StringEscapeUtils.escapeJava(new String(Serialization.sequence(object))));//添加轉義
        bw.close();
        fw.close();
        return true;
    }

    /**
     * 根據傳進來的文件名,和類的類型獲取緩存的實體類
     * @param name 緩存名稱
     * @param objectClass 需要取得的實體類型
     * @param <T> 旋迴對應實例
     * @return
     * @throws Exception
     */
    public static <T> T get(String name,Class<T> objectClass)throws Exception{

        T vo=null;
        File file=new File(CacheBF.getCacheFileName(name));//獲取緩存文件
        if (file.exists()){//判斷文件是否存在
            FileReader fr=new FileReader(file);
            BufferedReader br=new BufferedReader(fr);
            Long now =System.currentTimeMillis();
            Long time=Long.parseLong(br.readLine());//判斷文件緩存是否過期
            String object=StringEscapeUtils.unescapeJava(br.readLine());//返回程序,反轉義字符
            br.close();
            fr.close();
            if (time>now){
                vo= Serialization.reverse(object.getBytes(),objectClass);
            }else{
                file.delete();//過期刪除文件,刪除前關閉輸出流
            }
        }
        return vo;
    }

    /**
     * 傳入一個緩存名稱,查詢是否存在此緩存
     * @param name 緩存名稱
     * @return 存在並且不過期返回true,否則返回false
     * @throws Exception
     */
    public static boolean check(String name)throws Exception{

        boolean back=false;
        File file=new File(CacheBF.getCacheFileName(name));//獲取緩存文件
        if (file.exists()){
            FileReader fr=new FileReader(file);
            BufferedReader br=new BufferedReader(fr);
            Long now=System.currentTimeMillis();
            Long time=Long.parseLong(br.readLine());//判斷文件緩存是否過期
            br.close();
            fr.close();
            if (time>now){
                back=true;
            }else{
                file.delete();//過期刪除文件
            }
        }
        return back;
    }

    /**
     * 刪除穿進來的緩存名稱的文件
     * @param name 需要刪除的緩存的名稱
     * @throws Exception
     */
    public static void delete(String name)throws Exception{

        File file=new File(CacheBF.getCacheFileName(name));
        if (file.exists()){
            file.delete();
        }

    }
    /**
     * 根據緩存的名稱獲取需要操作的文件對象
     * 1、判斷父類目錄cache是否存在,不存在則創建
     * 2、判斷當前文件是否存在,存在刪除後創建,不存在直接創建
     * 3、文件名MD5加密
     * @param name 需要得到的緩存的名稱
     * @return
     * @throws Exception
     */
    private static File getCacheFile(String name)throws Exception{

        File file=new File(CacheBF.getCacheFileName(name));//獲取操作對象
        //判斷父目錄是否存在
        if (!file.getParentFile().exists()){
            file.getParentFile().mkdir();
        }
        //判斷當前文件是否存在
        if (!file.exists()){
            file.createNewFile();
        }else {
            file.delete();
            file.createNewFile();
        }
        return file;
    }

    /**
     * 傳入緩存名獲取緩存的文件名
     * @param name 緩存名
     * @return
     */
    private static String getCacheFileName(String name){
        name=MD5maker.make(name)+".txt";//獲取文件名
        StringBuffer fileName=new StringBuffer(System.getProperty("user.dir"))
                .append(File.separator).append("src")
                .append(File.separator).append("main")
                .append(File.separator).append("webapp")
                .append(File.separator).append("WEB-INF")
                .append(File.separator).append("cache")
                .append(File.separator).append(name);//獲取文件路徑
        return fileName.toString();
    }
}


模塊四:測試

import tool.CacheBF;
import tool.Serialization;

import java.io.File;

/**
 * Created by yy on 2017/10/11.
 * 文件緩存測試
 */
public class test {
    public static void main(String args[]) {
        Data data= new Data();
        data.setInfo("hello");
        data.setName("world");
        try {
            CacheBF.cache("123",data,100);

            System.out.println("緩存是否存在:"+CacheBF.check("123"));
            Data da=CacheBF.get("123",Data.class);
            System.out.println(da);

            CacheBF.delete("123");
            System.out.println("緩存是否存在:"+CacheBF.check("123"));
            Data dd=CacheBF.get("123",Data.class);
            System.out.println(dd);
        }catch (Exception e){
            e.printStackTrace();
        }


    }
}
//測試使用
class Data{
    private String name;
    private String info;

    public String getName() {
        return name;
    }

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

    public String getInfo() {
        return info;
    }

    public void setInfo(String info) {
        this.info = info;
    }

    @Override
    public String toString() {
        return "Data{" +
                "name='" + name + '\'' +
                ", info='" + info + '\'' +
                '}';
    }
}
模塊五:測試輸出

緩存是否存在:true
Data{name='world', info='hello'}
緩存是否存在:false
null

模塊六:文件內容(A8AE104615CB4E966DDB435F3E575A02.txt)

1508081000098
\n\u0005world\u0012\u0005hello


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章