编码 解码 序列化 加密解密 BCryptPasswordEncoder 星云二进制协议与Java之间的相互转换 unicode编码解码在线工具 JsonInclude

一。序列化器 (对象序列化,反序列化)

序列化反序列号其实是java对象类型和ByteBuf类型或者byte[]类型的互相转换( io.netty.buffer.ByteBuf;)

1、kryo方案序列化

<!--kryo序列号器-->
  <dependency>
      <groupId>de.javakaffee</groupId>
      <artifactId>kryo-serializers</artifactId>
      <version>0.42</version>
  </dependency>

KryoFactory 用来创建Kryo 对象

package com.test.netty.kryocodec;

import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.serializers.DefaultSerializers;
import de.javakaffee.kryoserializers.*;

import java.lang.reflect.InvocationHandler;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.URI;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Pattern;

public class KryoFactory {

    public static Kryo createKryo() {

        Kryo kryo = new Kryo();
        kryo.setRegistrationRequired(false);
        kryo.register(Arrays.asList("").getClass(), new ArraysAsListSerializer());
        kryo.register(GregorianCalendar.class, new GregorianCalendarSerializer());
        kryo.register(InvocationHandler.class, new JdkProxySerializer());
        kryo.register(BigDecimal.class, new DefaultSerializers.BigDecimalSerializer());
        kryo.register(BigInteger.class, new DefaultSerializers.BigIntegerSerializer());
        kryo.register(Pattern.class, new RegexSerializer());
        kryo.register(BitSet.class, new BitSetSerializer());
        kryo.register(URI.class, new URISerializer());
        kryo.register(UUID.class, new UUIDSerializer());
        UnmodifiableCollectionsSerializer.registerSerializers(kryo);
        SynchronizedCollectionsSerializer.registerSerializers(kryo);

        kryo.register(HashMap.class);
        kryo.register(ArrayList.class);
        kryo.register(LinkedList.class);
        kryo.register(HashSet.class);
        kryo.register(TreeSet.class);
        kryo.register(Hashtable.class);
        kryo.register(Date.class);
        kryo.register(Calendar.class);
        kryo.register(ConcurrentHashMap.class);
        kryo.register(SimpleDateFormat.class);
        kryo.register(GregorianCalendar.class);
        kryo.register(Vector.class);
        kryo.register(BitSet.class);
        kryo.register(StringBuffer.class);
        kryo.register(StringBuilder.class);
        kryo.register(Object.class);
        kryo.register(Object[].class);
        kryo.register(String[].class);
        kryo.register(byte[].class);
        kryo.register(char[].class);
        kryo.register(int[].class);
        kryo.register(float[].class);
        kryo.register(double[].class);

        return kryo;
    }
}

KryoSerializerUtil 序列化反序列化工具类

package com.test.netty.kryocodec;

import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.io.Input;
import com.esotericsoftware.kryo.io.Output;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufInputStream;

import java.io.ByteArrayOutputStream;
import java.io.IOException;

public class KryoSerializerUtil {
    private static Kryo kryo = KryoFactory.createKryo();

    /**
     * 对象转成ByteBuf
     * 
     * @param object 对象
     * @param byteBuf ByteBuf
     */
    public static void serialize(Object object, ByteBuf byteBuf) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        Output output = new Output(baos);
        kryo.writeClassAndObject(output, object);
        output.flush();
        output.close();

        byte[] b = baos.toByteArray();
        try {
            baos.flush();
            baos.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        byteBuf.writeBytes(b);
    }

    /**
     * ByteBuf转成对象
     * 
     * @param byteBuf ByteBuf
     * @return 对象
     */
    public static Object deserialize(ByteBuf byteBuf) {
        if (byteBuf == null) {
            return null;
        }
        Input input = new Input(new ByteBufInputStream(byteBuf));
        return kryo.readClassAndObject(input);
    }
}

2、protostuff序列化

   <!-- protostuff-->
        <dependency>
            <groupId>com.dyuproject.protostuff</groupId>
            <artifactId>protostuff-api</artifactId>
            <version>1.0.10</version>
        </dependency>
        <dependency>
            <groupId>com.dyuproject.protostuff</groupId>
            <artifactId>protostuff-core</artifactId>
            <version>1.0.10</version>
        </dependency>
        <dependency>
            <groupId>com.dyuproject.protostuff</groupId>
            <artifactId>protostuff-runtime</artifactId>
            <version>1.0.10</version>
        </dependency>

二。编码器解码器,其实就是序列化器和netty集成起来

一个继承MessageToByteEncoder
一个继承ByteToMessageDecoder

//编码器   将对象转为字节
public class KryoEncoder extends MessageToByteEncoder<MyMessage> {
    @Override
    protected void encode(ChannelHandlerContext ctx, MyMessage message, byteBuf out) throws Exception {
        KryoSerializer.serialize(message, out);
        ctx.flush();
    }
}

//解码器   将字节转为对象
public class KryoDecoder extends ByteToMessageDecoder {
    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
        Object obj = KryoSerializer.deserialize(in);
        out.add(obj);
    }
}

三。base64的编码与解码

//方法1:cn.hutool
	 //编码
     String str = "abc";
     String base64Str = Base64Encoder.encode(str.getBytes());
     System.out.println(base64Str);
     //解码
     str = new String(Base64Decoder.decode(base64Str), StandardCharsets.UTF_8);
     System.out.println(str);


//方法2:google的guava
 //编码
 String temp = "abcsd";
 String base64Str = BaseEncoding.base64().encode(temp.getBytes());
 System.out.println(base64Str);
 //解码
 temp = new String(BaseEncoding.base64().decode(base64Str), StandardCharsets.UTF_8);
 System.out.println(temp);

四。BCryptPasswordEncoder

import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

/**
 * @author ccp24 on 2017/12/8 14:45
 */
public class EncryptUtil {

    /**
     * 密码加密
     *
     * @param password 原始密码
     * @return 加密后的密码
     */
    public static String encryptPassword(String password) {
        BCryptPasswordEncoder crypt = new BCryptPasswordEncoder();
        return crypt.encode(password);
    }

    /**
     * 密码匹配
     *
     * @param rawPassword     未加密密码
     * @param encodedPassword 加密密码
     * @return 如果匹配一致,返回true。否则返回false
     */
    public static boolean matchPassword(String rawPassword, String encodedPassword) {
        BCryptPasswordEncoder crypt = new BCryptPasswordEncoder();
        return crypt.matches(rawPassword, encodedPassword);
    }
}

把密码123456转成 BCrypt格式

orgOperationUserDO.setPassword(EncryptUtil.encryptPassword(123456));

五。根据星云通讯项目测试

Arrays.asList 把数组转成集合
concatAll 把二进制集合转成一个字节数组

package com.king.bytetest;

import com.king.bytetest.util.BitOperator;
import com.king.bytetest.util.ByteUtil;

import java.util.Arrays;

/**
 * @Author lhc
 * @Date 2020-09-28 10:00
 **/
public class Test {

    /**
     * @Author lhc
     * @Date 2020-09-27 18:15
     **/
    public static void main(String[] args) {
        Charge charge = new Charge();
        charge.setReverd1(3);
        charge.setAge(20);
        charge.setName("chargeName");
        charge.setColor("bule");
        byte[] bytes = javaObjectChangeToByteArray(charge);
        Charge charge1 = byteArrayChangeToObject(bytes);
        System.out.println(charge1);
    }


    /**
     * java对象转成字节数组
     *
     * @param charge java对象
     * @return 字节数组
     */
    public static byte[] javaObjectChangeToByteArray(Charge charge) {
        byte[] msgBody = BitOperator.concatAll(Arrays.asList(
                //预留1
                BitOperator.integerToBytes(charge.getReverd1(), 1),
                //年龄
                BitOperator.integerToBytes(charge.getAge(), 2),
                //名称
                ByteUtil.stringToByteByASCII(charge.getName(), 32),
                //颜色
                ByteUtil.stringToByteByASCII(charge.getColor(), 4)
        ));
        return msgBody;
    }

    /**
     * 字节数组转成java对象
     *
     * @param byteArray
     * @return java对象
     */
    public static Charge byteArrayChangeToObject(byte[] byteArray) {
        Charge charge = new Charge();
        //   1.预留1
        int reverd1 = ByteUtil.intFromBytes(byteArray, 0, 1);
        charge.setReverd1(ByteUtil.intFromBytes(byteArray, 0, 1));
        //   2.年龄
        int age = ByteUtil.intFromBytes(byteArray, 1, 2);
        charge.setAge(ByteUtil.intFromBytes(byteArray, 1, 2));
        //   3.名称
        String name = ByteUtil.strFromBytesByASCII(byteArray, 3, 32);
        charge.setName(ByteUtil.strFromBytesByASCII(byteArray, 3, 32));
        //   4.颜色
        String color = ByteUtil.strFromBytesByASCII(byteArray, 35, 4);
        charge.setColor(ByteUtil.strFromBytesByASCII(byteArray, 35, 4));
        return charge;
    }
}

六。星云接收充电桩消息 根据协议把二进制数据转成java对象

协议背景:通信数据报⽂采⽤⼆进制格式,把传过来的二进制数据根据协议转为Java对象

1. 根据如下截图创建java对象,见下面类CNTEPackageHeadData 
2. 转换,见下面

在这里插入图片描述
1.根据如上截图创建java对象

@Data
public class CNTEPackageHeadData {
    /**
     * 起始域 2个字节
     */
    private int originateId;
    /**
     * 长度   2个字节
     */
    private int length;
    /**
     * 信息域 1个字节
     */
    private int infoDomain;
    /**
     * 序列号域 1个字节
     */
    private int serialNumber;
    /**
     * 命令ID
     */
    private int commandId;
    /**
     * 流水ID  协议是数据域校验和域
     */
    private int flowId;
}

2.把二进制数据根据如上截图内容转成java对象

private static CNTEPackageHeadData parseHeaderFromBytes(byte[] data) {
      CNTEPackageHeadData headData = new CNTEPackageHeadData();
      //   1.起始域
      headData.setOriginateId(ByteUtil.intFromBytes(data, 0, 2));
      //   2.长度
      headData.setLength(ByteUtil.intFromBytes(data, 2, 2));
      //   3.信息域
      headData.setInfoDomain(ByteUtil.intFromBytes(data, 4, 1));
      //   4.序列号域
      headData.setSerialNumber(ByteUtil.intFromBytes(data, 5, 1));
      //   5.命令代码
      headData.setCommandId(ByteUtil.intFromBytes(data, 6, 2));
      return headData;
}

ByteUtil见有道云笔记——星云——通讯项目与协议

七。星云发送消息给充电桩 java对象转成二进制

1.根据协议创建一个java对象     例如上面的类CNTEPackageHeadData 
2.new CNTEPackageHeadData() 并把信息set属性进去, 如setCommandId(108)
3.CNTEPackageHeadData对象转成二进制数据(字节数组类型)
4.发送

java对象转成字节数组(二进制对象)

 /**
     * 服务器应答充电桩上报充电信息报文
     *
     * @param bodyData 数据消息体
     * @param flowId   流水号
     * @return 服务器应答充电桩上报充电信息报文数据
     */
public static byte[] encode4ServerReportChargingRecordCmdMsg(ServerReportChargingRecordBody bodyData, int flowId) {
    byte[] msgBody = BitOperator.concatAll(Arrays.asList(
            //预留1 (2)
            BitOperator.integerToBytes(bodyData.getReserved1(), 2),
            //预留1 (4)
            BitOperator.integerToBytes(bodyData.getReserved2(), 2),
            //充电枪口
            BitOperator.integerToBytes(bodyData.getChargingGunsNumber(), 1),
            //用户卡号/用户识别号  (32)
            ByteUtil.stringToByteByASCII(bodyData.getChargingCardNumber(), 32),
            //内部索引号
            BitOperator.integerToBytes(bodyData.getInternalIndexNumber(), 4),
            //字段有效标志  (1)
            BitOperator.integerToBytes(bodyData.getFieldValidFlag(), 1),
            //充电优惠前金额  (4)
            BitOperator.integerToBytes(bodyData.getChargingAmount(), 4),
            //充电折扣金额  (4)
            BitOperator.integerToBytes(bodyData.getChargingDiscountAmount(), 4),
            //充电实扣金额  (4)
            BitOperator.integerToBytes(bodyData.getChargingDeductionAmount(), 4)
    ));
    byte[] msgHeader = generateMsgHeader(InstructionCodeConsts.msg_id_terminal_report_charging_record, msgBody, flowId);
    byte[] headerAndBody = BitOperator.concatAll(msgHeader, msgBody);
    // 校验码
    int checkSum = BitOperator.getCRC16CheckSum(headerAndBody, 0, headerAndBody.length);
    // 连接并且转义
    return doEncode(headerAndBody, checkSum);
}

八。unicode编码解码在线工具

http://www.jsons.cn/unicode

九。为null的字段不序列化 @JsonInclude(JsonInclude.Include.NON_NULL)

@JsonInclude(JsonInclude.Include.NON_NULL)
public class BusinessDetailsVO {

    private String name;

    private String website;

    private ImageVO logo;

}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

飘然生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值