对mongodb document 转换bytes类java代码的实现

文章目录

  • 前言
  • 一、为什么要将Document转换为bytes
  • 二、工具类实现
    • 1.引入库
    • 2 document系列化bytes
    • 3.bytes反序列化document
    • 4 定义类型DataType
    • 5 开发环境

前言

         最近在设计一个针对mongodb数据操作的客户端,以配合自己设计的DB接点一同使用。

一、为什么要将Document转换为bytes?

        在实际开发中,开发一个针对mongodb的一个客户端,该客户端与DB接点进程(自己开发的进程)进行通讯,为了让开发客户端操作数据库与直接操作DB进程操作一样的便利性,选择直接操作document,就好比redis客户端一样,如:jedis等

        但是发现一个问题,虽然document可以直接转换string类型,但是相对比较耗费流量,并且不能跨语言使用,所以设计一个document序列化和反序列转换为bytes的工具就是我的目的

二、工具类实现

1.引入库:

dependencies {
    
     //打印异常库(可以不添加)
    implementation group: 'org.apache.commons', name: 'commons-lang3', version: '3.12.0'

    //MongoDB 依赖库
    implementation group: 'org.mongodb', name: 'mongodb-driver-core', version: '3.11.0'
    implementation group: 'org.mongodb', name: 'bson', version: '3.11.0'
    implementation group: 'org.mongodb', name: 'mongodb-driver', version: '3.11.0'
}

 以下代码使用了lombok插件,具体插件安装请自行安装,不作叙述,引用 log4j2日志库

2.bytes序列化转换为document

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.bson.Document;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;


@Slf4j

public class DocumentInputStream {

    ByteArrayInputStream mInput = null;
    DataInputStream mData = null;

    public DocumentInputStream(byte[] data) {
        this.mInput = new ByteArrayInputStream(data);
        this.mData = new DataInputStream(this.mInput);
    }

    private DocumentInputStream() {
    }

    public Document dataToDocument() {
        Document doc = new Document();

        try {
            byte type = this.mData.readByte();
            if (type != DataType.IS_DOCUMENT_HEAD) {
                throw new IllegalArgumentException(" data head is not IS_DOCUMENT_HEAD");
            }

            byte valueType = this.mData.readByte();
            if (valueType == DataType.IS_EMPTY_DOCUMENT) {
                this.mData.readByte();
                return new Document();
            }

            for(; valueType != DataType.IS_DOCUMENT_END && !this.isEnd(); valueType = this.mData.readByte()) {
                String key = this.readSmallString();
                if (DataType.IS_BYTE == valueType) {
                    doc.put(key, this.mData.readByte());
                } else if (DataType.IS_SHORT == valueType) {
                    doc.put(key, this.mData.readShort());
                } else if (DataType.IS_INT == valueType) {
                    doc.put(key, this.mData.readInt());
                } else if (DataType.IS_FLOAT == valueType) {
                    doc.put(key, this.mData.readFloat());
                } else if (DataType.IS_DOUBLE == valueType) {
                    doc.put(key, this.mData.readDouble());
                } else if (DataType.IS_LONG == valueType) {
                    doc.put(key, this.mData.readLong());
                } else if (DataType.IS_STRING == valueType) {
                    doc.put(key, this.readShortString());
                } else if (DataType.IS_BYTES == valueType) {
                    doc.put(key, this.readBytes());
                } else if (DataType.IS_BOOLEAN == valueType) {
                    doc.put(key, this.mData.readBoolean());
                } else if (DataType.IS_LIST == valueType) {
                    doc.put(key, this.readList());
                } else if (DataType.IS_DOCUMENT == valueType) {
                    doc.put(key, this.dataToDocument());
                }
                else
                {
                    throw new IOException(" An error occurred,please check the document key="+key);
                }
            }
        } catch (IOException e) {
            log.error(ExceptionUtils.getStackTrace(e));
        }

        return doc;
    }

    @SuppressWarnings("unchecked")
    List readList() throws IOException {
        int nCount = this.mData.readInt();
        if (nCount == 0) {
            return new ArrayList();
        } else {
            byte type = this.mData.readByte();
            if (DataType.IS_NO_SUPPORT == type) {
                return new ArrayList();
            } else {
                List l = new ArrayList();

                for(int i = 0; i < nCount; ++i) {
                    if (DataType.IS_BYTE == type) {
                        l.add(this.mData.readByte());
                    } else if (DataType.IS_SHORT == type) {
                        l.add(this.mData.readShort());
                    } else if (DataType.IS_INT == type) {
                        l.add(this.mData.readInt());
                    } else if (DataType.IS_FLOAT == type) {
                        l.add(this.mData.readFloat());
                    } else if (DataType.IS_DOUBLE == type) {
                        l.add(this.mData.readDouble());
                    } else if (DataType.IS_LONG == type) {
                        l.add(this.mData.readLong());
                    } else if (DataType.IS_STRING == type) {
                        l.add(this.readShortString());
                    } else if (DataType.IS_BYTES == type) {
                        l.add(this.readBytes());
                    } else if (DataType.IS_BOOLEAN == type) {
                        l.add(this.mData.readBoolean());

                    } else if (DataType.IS_LIST == type) {
                        l.add(this.readList());
                    }else if (DataType.IS_DOCUMENT == type) {
                        l.add(this.dataToDocument());
                    }

                }

                return l;
            }
        }
    }

    public boolean isEnd() {
        try {
            return this.mData.available() <= 0;
        } catch (IOException e) {
            log.error(ExceptionUtils.getStackTrace(e));
            return false;
        }
    }

    String readString(int nLen) throws IOException {
        byte[] data = new byte[nLen];
        this.mData.read(data);
        String outData = new String(data);
        return outData;
    }

    String readShortString() throws IOException {
        short b = this.mData.readShort();
        return this.readString(b);
    }

    String readSmallString() throws IOException {
        byte b = this.mData.readByte();
        return this.readString(b);
    }

    public byte[] readBytes(int nLen) throws IOException {
        byte[] data = new byte[nLen];
        this.mData.read(data);
        return data;
    }

    public byte[] readBytes() throws IOException {
        int nLen = this.mData.readInt();
        return this.readBytes(nLen);
    }
}

3 document 反序列化bytes

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.bson.Document;

import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Set;

@Slf4j
public class DocumentOutputStream {

    ByteArrayOutputStream out = new ByteArrayOutputStream();
    DataOutputStream dataOutputStream = new DataOutputStream(out);

    public  void packDocument(Document document)
    {
        try {
            dataOutputStream.writeByte(DataType.IS_DOCUMENT_HEAD);
            Set<Map.Entry<String, Object>> set =  document.entrySet();
            if(set.size()==0)
            {
                dataOutputStream.writeByte(DataType.IS_EMPTY_DOCUMENT);
                dataOutputStream.writeByte(DataType.IS_DOCUMENT_END);
                return;
            }

            for(Map.Entry<String,Object>entry:set)
            {

                if(entry.getValue() instanceof  Byte )
                {
                    byte value = ((Byte) entry.getValue()).byteValue();
                    dataOutputStream.writeByte(DataType.IS_BYTE);
                    writeSmallString(entry.getKey());
                    dataOutputStream.writeByte(value);
                }
                else if(entry.getValue() instanceof  Short)
                {
                    short value = ((Short) entry.getValue()).shortValue();
                    dataOutputStream.writeByte(DataType.IS_SHORT);
                    writeSmallString(entry.getKey());
                    dataOutputStream.writeShort(value);
                }
                else if(entry.getValue() instanceof  Integer)
                {
                    int value = ((Integer) entry.getValue()).intValue();
                    dataOutputStream.writeByte(DataType.IS_INT);
                    writeSmallString(entry.getKey());
                    dataOutputStream.writeInt(value);
                }
                else if(entry.getValue() instanceof  Float)
                {
                    float value = ((Float) entry.getValue()).floatValue();
                    dataOutputStream.writeByte(DataType.IS_FLOAT);
                    writeSmallString(entry.getKey());
                    dataOutputStream.writeFloat(value);
                }
                else if(entry.getValue() instanceof  Double)
                {
                    double value = ((Double) entry.getValue()).doubleValue();
                    dataOutputStream.writeByte(DataType.IS_DOUBLE);
                    writeSmallString(entry.getKey());
                    dataOutputStream.writeDouble(value);
                }
                else if(entry.getValue() instanceof  Long)
                {
                    long value = ((Long) entry.getValue()).longValue();
                    dataOutputStream.writeByte(DataType.IS_LONG);
                    writeSmallString(entry.getKey());
                    dataOutputStream.writeLong(value);
                }
                else if(entry.getValue() instanceof  String)
                {
                    String  value = (String) entry.getValue();
                    dataOutputStream.writeByte(DataType.IS_STRING);
                    writeSmallString(entry.getKey());
                    writeShortString(value);
                }
                else if(entry.getValue() instanceof byte[])
                {
                    byte[]  value = (byte[])entry.getValue();
                    dataOutputStream.writeByte(DataType.IS_BYTES);
                    writeSmallString(entry.getKey());
                    writeBytes(value);
                }
                else if(entry.getValue() instanceof  Boolean)
                {
                    boolean value = ((Boolean) entry.getValue()).booleanValue();
                    dataOutputStream.writeByte(DataType.IS_BOOLEAN);
                    writeSmallString(entry.getKey());
                    dataOutputStream.writeBoolean(value);
                }
                else if(entry.getValue() instanceof  Document)
                {
                    Document myDoc = (Document)entry.getValue();
                    dataOutputStream.writeByte(DataType.IS_DOCUMENT);
                    writeSmallString(entry.getKey());
                    packDocument(myDoc);
                }
                else if(entry.getValue() instanceof List)
                {
                    List list = ((List) entry.getValue());
                    dataOutputStream.writeByte(DataType.IS_LIST);
                    writeSmallString(entry.getKey());

                    writeList(list);
                }
                else
                {
                    //throw new IOException("key ="+entry.getKey()+" dont found type when packed document");
                }
            }
            dataOutputStream.writeByte(DataType.IS_DOCUMENT_END);
        }catch (IOException e)
        {
            log.error(ExceptionUtils.getStackTrace(e));
        }
    }

    void writeList(List list) throws  IOException
    {
        dataOutputStream.writeInt(list.size());
        if(list.size() !=0)
        {
            Object o  = list.get(0);
            if(o instanceof Byte)
            {
                dataOutputStream.writeByte(DataType.IS_BYTE);
                for(int i=0; i<list.size(); i++)
                {
                    dataOutputStream.writeByte((byte) list.get(i));
                }
            }
            else if(o instanceof  Short)
            {
                dataOutputStream.writeByte(DataType.IS_SHORT);
                for(int i=0; i<list.size(); i++)
                {
                    dataOutputStream.writeShort((short)list.get(i));
                }
            }
            else if(o instanceof  Integer)
            {
                dataOutputStream.writeByte(DataType.IS_INT);
                for(int i=0; i<list.size(); i++)
                {
                    dataOutputStream.writeInt((int)list.get(i));
                }
            }
            else if(o instanceof  Float)
            {
                dataOutputStream.writeByte(DataType.IS_FLOAT);
                for(int i=0; i<list.size(); i++)
                {
                    dataOutputStream.writeFloat((float)list.get(i));
                }
            }
            else if(o instanceof  Double)
            {
                dataOutputStream.writeByte(DataType.IS_DOUBLE);
                for(int i=0; i<list.size(); i++)
                {
                    dataOutputStream.writeDouble((double)list.get(i));
                }

            }
            else if(o instanceof  Long)
            {
                dataOutputStream.writeByte(DataType.IS_LONG);
                for(int i=0; i<list.size(); i++)
                {
                    dataOutputStream.writeLong((long)list.get(i));
                }
            }
            else if(o instanceof  String)
            {
                dataOutputStream.writeByte(DataType.IS_STRING);
                for(int i=0; i<list.size(); i++)
                {
                    writeShortString((String)list.get(i));
                }

            }
            else if(o instanceof byte[])
            {
                dataOutputStream.writeByte(DataType.IS_BYTES);
                for(int i=0; i<list.size(); i++)
                {
                    writeBytes((byte[]) list.get(i));
                }
            }
            else if(o instanceof  Boolean)
            {
                dataOutputStream.writeByte(DataType.IS_BOOLEAN);
                for(int i=0; i<list.size(); i++)
                {
                    dataOutputStream.writeBoolean((boolean)list.get(i));
                }
            }
            else  if(o instanceof  Document)
            {
                dataOutputStream.writeByte(DataType.IS_DOCUMENT);
                for(int i=0; i<list.size(); i++)
                {
                    packDocument((Document) list.get(i));
                }
            }

            else
            {
                //throw new IOException(" An error occurred,please check the document key");
                //dataOutputStream.writeByte(DataType.IS_NO_SUPPORT);
            }

        }
    }




    void writeSmallString(String value)
    {
        try {
            byte[] data = value.getBytes();
            dataOutputStream.writeByte(data.length);
            dataOutputStream.write(data);
        }catch (IOException e)
        {
            log.error(ExceptionUtils.getStackTrace(e));
        }
    }
    void writeShortString(String value)
    {
        try {
            byte[] data = value.getBytes();
            dataOutputStream.writeShort(data.length);
            dataOutputStream.write(data);
        }catch (IOException e)
        {
            log.error(ExceptionUtils.getStackTrace(e));
        }
    }


    void writeBytes(byte[] value)
    {
        try {
            dataOutputStream.writeInt(value.length);
            dataOutputStream.write(value,0,value.length);
        }catch (IOException e)
        {
            log.error(ExceptionUtils.getStackTrace(e));
        }
    }
    public  byte[] getBytes()
    {
        return out.toByteArray();
    }
}

 4 定义DataType类

/**
*对于mongodb ObjectId(MongoDB默认的id) 做了屏蔽,一般情况下我们是不需要MongoDB中默认的*ObjectID的,因为会自己设置索引,如果需要,请添加ObjectID类型,并在序列化和反序列化接口中添加
*如果以下类型不满足,那么也请自行添加
**/
public class DataType {

    public static byte IS_BYTE = 100;
    public static byte IS_SHORT = 101;
    public static byte IS_INT = 102;
    public static byte IS_LONG = 103;
    public static byte IS_FLOAT = 104;
    public static byte IS_DOUBLE = 105;
    public static byte IS_STRING = 106;
    public static byte IS_BYTES = 107;
    public static byte IS_BOOLEAN = 108;
    public static byte IS_DOCUMENT_HEAD = 109;
    public static byte IS_DOCUMENT_END = 110;
    public static byte IS_DOCUMENT = 111;
    public static byte IS_EMPTY_DOCUMENT = 112;
    public static byte IS_LIST = 113;
    //public static byte IS_DOCUMENT_ARRAY = 114;
    public static byte IS_NO_SUPPORT = 125;

}

5 开发环境

        工程环境 window10. gradle-6.8.3 ,编辑器idea 2019.3.4 

    原文作者:魂玉天成
    原文地址: https://blog.csdn.net/lejian/article/details/123463749
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞