使用webSocket 实现给前端发消息

通过webSocket 去实现订阅的功能

例如将一个对象 通过ws 发给前端

import  一大堆 所有代码都有 缺哪个加哪个
import lombok.Data;

import java.io.Serializable;
import java.time.LocalDateTime;

@Data
public class AtomicWsTaskDTO extends StructBasic implements Serializable {

    private static final long serialVersionUID = 1L;


    @TStruct(order = 0, dataType = TStructGlobal.STRUCT, dataLength = 64)
    public TWsMessageHeader messageHeader = new TWsMessageHeader();


    /**
     * 客户端uid
     */
    @TStruct(order = 1, dataType = TStructGlobal.STRING, dataLength = TWebsocketGlobal.GUID_LEN)
    public String clientId;

    /**
     * 编号
     */
    private Long id;

    /**
     * 原子任务uid
     */
    private String uid;

    /**
     * 原子任务名称
     */
    private String atomicName;

    /**
     * 原子任务描述
     */
    private String atomicDescription;

    /**
     * 原子任务执行参数(JSON)
     */
    private String atomicParam;

    /**
     * 原子任务外设参数(JSON)
     */
    private String atomicPeripheralType;

    /**
     * 原子任务数据类型(广播、控制、采播等)
     */
    private TaskDataType atomicDataType;

    /**
     * 创建人
     */
    private String createBy;

    /**
     * 创建时间
     */
    private LocalDateTime createTime;

    /**
     * 更新人
     */
    private String lastUpdateBy;

    /**
     * 更新时间
     */
    private LocalDateTime lastUpdateTime;

    /**
     * 优先级 (0-100) 越低优先级越高
     */
    @JsonInclude(JsonInclude.Include.NON_NULL)
    private Integer priority;


    /**
     * 指定频道播放Vod
     */
    private String chanelId;


    /**
     * 状态 开始 1 0 结束
     */
    private String state;


StructBasic 类

package xxx.structs;

import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;

@Data
@Slf4j
public abstract class StructBasic {

    /**
     * 实例转换成byte数组
     */
    public byte[] toBytes() {
        byte[] bytes = new byte[getSize()];

        try {
            TDataPosition position = new TDataPosition(0);
            TStructProperty[] properties = TStructUtils.getTStructProperties(this);

            for (TStructProperty property : properties) {
                TStructUtils.putData(position, bytes, property);
            }
            return bytes;
        } catch (Exception ex) {
            log.error(ex.getMessage());
            return null;
        }
    }

    /**
     * byte数组转换成实例
     */
    public boolean fromBytes(byte[] bytes) {
        if (bytes == null || bytes.length == 0) {
            return false;
        }

        try {
            TDataPosition position = new TDataPosition(0);
            TStructProperty[] properties = TStructUtils.getTStructProperties(this);

            for (TStructProperty property : properties) {
                TStructUtils.getData(position, bytes, property);
            }
            return true;
        } catch (Exception ex) {
            log.error(ex.getMessage());
            return false;
        }
    }

    @JsonIgnore
    public int getSize() {
        return TStructUtils.getTStructLength(this);
    }
}

发送核心代码

AtomicWsTaskDTO atomicWsTaskDTO = new AtomicWsTaskDTO();
                                atomicWsTaskDTO.messageHeader = WebsocketMethods.getInstance().getSubscribeMessageHeader(
                                        0x21,
                                        0x02,
                                        177,
                                        0
                                );
                               atomicWsTaskDTO.setChanelId(message.getChannelId());
                                atomicWsTaskDTO.setId(message.getAssignmentId());
                                atomicWsTaskDTO.setClientId(wsClient.getClientId());

                                System.out.println("message.getState()==============" + message.getState());
                                atomicWsTaskDTO.setState(message.getState());
                                byte[] bytes = atomicWsTaskDTO.toBytes();
                                wsClient.getSession().sendBinary(bytes);

WebsocketMethods类

import  一大堆 所有代码都有 缺哪个加哪个

public class WebsocketMethods {

    private static WebsocketMethods instance;

    public static WebsocketMethods getInstance() {
        if (instance == null) {
            instance = new WebsocketMethods ();
        }

        return instance;
    }

    public static WsMessageHeader getWsMessageHeader(long commandType, long command, long size, long serial) {
        return new TWsMessageHeader()
                .setCookie(TWebsocketGlobal.TAIDEN_WEBSOCKET_COOKIE)
                .setSerial(serial)
                .setCommandType(commandType)
                .setCommand(command)
                .setLength(size)
                .setDestination(TWebsocketGlobal.MESSAGE_TYPE_NORMAL);
    }

    public static TWsMessageHeader getSetUpTypeWsMessageHeader(long command, long size) {
        return getWsMessageHeader(TWebsocketGlobal.TDWS_MESSAGE_TYPE_SETUP, command, size, 0);
    }

    public TWsMessageHeader getMessageHeader(long commandType, long command, long size, long serial) {
        return new TWsMessageHeader()
                .setCookie(TWebsocketGlobal.TAIDEN_WEBSOCKET_COOKIE)
                .setSerial(serial)
                .setCommandType(commandType)
                .setCommand(command)
                .setLength(size)
                .setDestination(TWebsocketGlobal.MESSAGE_TYPE_NORMAL);
    }

    public TWsMessageHeader getSubscribeMessageHeader(long commandType, long command, long size, long serial) {
        TWsMessageHeader messageHeader = new TWsMessageHeader();
        messageHeader.cookie = TWebsocketGlobal.TAIDEN_WEBSOCKET_COOKIE;
        messageHeader.serial = serial;
        messageHeader.commandType = commandType;
        messageHeader.command = command;
        messageHeader.length = size;
        messageHeader.destination = TWebsocketGlobal.MESSAGE_TYPE_SUBSCRIBE;

        return messageHeader;
    }

    public int getTStructDataLength(StructBasic struct) {
        int result = 0;

        Field[] fields = struct.getClass().getFields();

        for (Field field : fields) {
            if (field.getType() == TWsMessageHeader.class){
                continue;
            }
            TStruct prop = field.getAnnotation(TStruct.class);
            if (prop != null) {
                result += prop.dataType() * prop.arrayLength();
            }
        }

        return result;
    }

    public TWsDateTime getNow() {
        TWsDateTime dateTimeMessage = new TWsDateTime();
        dateTimeMessage.setMessageHeader(getMessageHeader(
                TWebsocketGlobal.TDWS_MESSAGE_TYPE_SETUP,
                TWebsocketGlobal.TDWS_MESSAGE_SETUP_DATE_TIME,
                18, 0
        ));
        LocalDateTime dateTimeNow = LocalDateTime.now();

        TWsDate dateMsg = new TWsDate();
        dateMsg.setYear(dateTimeNow.getYear());
        dateMsg.setMonth(dateTimeNow.getMonthValue());
        dateMsg.setDay(dateTimeNow.getDayOfMonth());
        dateMsg.setWeek(dateTimeNow.getDayOfWeek().getValue());

        TWsTime timeMsg = new TWsTime();
        timeMsg.setHour(dateTimeNow.getHour());
        timeMsg.setMinute(dateTimeNow.getMinute());
        timeMsg.setSecond(dateTimeNow.getSecond());

        dateTimeMessage.setDate(dateMsg);
        dateTimeMessage.setTime(timeMsg);

        return dateTimeMessage;
    }

}

WsMessageHeader 类


import 一大堆 缺哪个加哪个 
import lombok.Data;
import lombok.experimental.Accessors;


@Accessors(chain = true)
@Data
public class WsMessageHeader extends StructBasic {

    /**
     * TAIDEN_WEBSOCKET_COOKIE: 0x74647773
     */
    @TStruct(order = 0, dataType = TStructGlobal.UINT32, dataLength = 4)
    public long cookie = TWebsocketGlobal.TAIDEN_WEBSOCKET_COOKIE;

    /**
     * 命令序列号 每次累加 (暂未启用 20210112)
     */
    @TStruct(order = 1, dataType = TStructGlobal.UINT32, dataLength = 4)
    public long serial;

    /**
     * 命令类型
     */
    @TStruct(order = 2, dataType = TStructGlobal.UINT16, dataLength = 2)
    public long commandType;

    /**
     * 命令
     */
    @TStruct(order = 3, dataType = TStructGlobal.UINT16, dataLength = 2)
    public long command;

    /**
     * 数据长度(不包括头)
     */
    @TStruct(order = 4, dataType = TStructGlobal.UINT32, dataLength = 4)
    public long length;

    /**
     * 发送目的
     * @see TWebsocketGlobal
     * MESSAGE_TYPE_NORMAL = 0x00;
     * MESSAGE_TYPE_SERVER = 0x01;
     * MESSAGE_TYPE_CLIENT = 0x02;
     * MESSAGE_TYPE_GROUP = 0x03;
     * MESSAGE_TYPE_CLIENT_TYPE = 0x04;
     * MESSAGE_TYPE_SUBSCRIBE = 0x05;
     */
    @TStruct(order = 5, dataType = TStructGlobal.UINT16, dataLength = 2)
    public long destination;

    /**
     * 目的数据
     * MESSAGE_TYPE_NORMAL: 0
     * MESSAGE_TYPE_SERVER: 0
     * MESSAGE_TYPE_CLIENT:Client_id(40)
     * MESSAGE_TYPE_GROUP: Group_name(40)
     * MESSAGE_TYPE_CLIENT_TYPE: Client_type(4)
     * MESSAGE_TYPE_SUBSCRIBE: Data(4) Type(4)
     */
    @TStruct(order = 6, dataType = TStructGlobal.UINT8, arrayLength = TWebsocketGlobal.GUID_LEN, dataLength = 1)
    public byte[] destData = new byte[TWebsocketGlobal.GUID_LEN];

    @TStruct(order = 7, dataType = TStructGlobal.UINT8, arrayLength = 6, dataLength = 1)
    public byte[] reserved = new byte[6];

    public void setDestData(byte[] val) {
        System.arraycopy(val, 0, destData, 0, Math.min(val.length, destData.length));
    }

    public String getDestStringData() {
        return (new String(destData)).trim();
    }

    public int getDestIntData() {
        byte[] data = new byte[4];
        System.arraycopy(destData, 0, data, 0, 4);

        return TStructUtils.toUInt32LH(data);
    }

    public int getDestIntData(int startIndex) {
        byte[] data = new byte[4];
        System.arraycopy(destData, startIndex, data, 0, 4);

        return TStructUtils.toUInt32LH(data);
    }
}

TStructUtils 类


import cn.hutool.core.lang.Assert;
import  一大堆 所有代码都有 缺哪个加哪个
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;

/**
 * 处理byte[]与类型的转换
 *
 */
@Slf4j
public class TStructUtils {

    public static <T extends StructBasic> int getTStructLength(T struct) {
        int result = 0;

        Field[] fields = struct.getClass().getFields();

        for (Field field : fields) {
            TStruct prop = field.getAnnotation(TStruct.class);
            if (prop == null) {
                continue;
            }

            int dataLength = prop.dataLength(), arrayLength = prop.arrayLength();

            // 获取加载TStruct数据长度
            if (prop.dataLengthBasedOnData()) {
                try {
                    Object object = field.get(struct);
                    // 数组结构
                    if (field.getType().isArray()) {
                        if (field.getType().getComponentType().getSuperclass().equals(StructBasic.class)) {
                            StructBasic[] structs = (StructBasic[]) field.get(struct);
                            for (StructBasic structBasic : structs) {
                                result += getTStructLength(structBasic);
                            }
                        }
                    }
                    // 单个结构
                    else if (object instanceof StructBasic) {
                        result += getTStructLength((StructBasic) object);
                    }
                } catch (IllegalAccessException ignored) {
                }
            } else {
                // 获取动态数据结构长度
                if (prop.dataLengthDynamic()) {
                    final long[] dataLen = {0};
                    Arrays.stream(fields).filter(f -> prop.dataLengthDynamicOrder() == f.getAnnotation(TStruct.class).order()).findFirst().ifPresent(f -> {
                        try {
                            dataLen[0] = f.getLong(struct);
                        } catch (Exception ignored) {
                        }
                    });

                    dataLength = (int) dataLen[0];
                }
                // 获取动态数组长度
                if (arrayLength == 1 && prop.dynamic()) {
                    final long[] dynamicLen = {0};
                    Arrays.stream(fields).filter(f -> prop.dynamicOrder() == f.getAnnotation(TStruct.class).order()).findFirst().ifPresent(f -> {
                        try {
                            dynamicLen[0] = f.getLong(struct);
                        } catch (Exception ignored) {
                        }
                    });

                    arrayLength = (int) dynamicLen[0];
                }
                result += dataLength * arrayLength;
            }
        }

        return result;
    }

    public static TStructProperty[] getTStructProperties(StructBasic entity) {
        List<TStructProperty> list = new ArrayList<>();
        Field[] fields = entity.getClass().getFields();

        for (Field field : fields) {
            TStruct annotation = field.getAnnotation(TStruct.class);
            if (annotation != null) {
                TStructProperty property = new TStructProperty()
                        .setField(field)
                        .setAnnotation(annotation)
                        .setEntity(entity);
                list.add(property);
            }
        }

        // 根据TStruct标注顺序排序
        list.sort(Comparator.comparing(TStructProperty::getOrder));

        TStructProperty[] result = new TStructProperty[list.size()];
        list.toArray(result);
        return result;
    }

    public static int getUInt8(TDataPosition pos, byte[] dataArray) {
        int position = pos.getPosition();
        int result = dataArray[position] & 0xFF;
        pos.appendPosition(1);

        return result;
    }

    public static long getUInt32(TDataPosition pos, byte[] dataArray) {
        int position = pos.getPosition();

        byte[] data = new byte[4];
        data[0] = dataArray[position];
        data[1] = dataArray[position + 1];
        data[2] = dataArray[position + 2];
        data[3] = dataArray[position + 3];

        pos.appendPosition(4);

        return toUInt32LH(data);
    }

    public static long getUInt16(TDataPosition pos, byte[] dataArray) {
        int position = pos.getPosition();

        byte[] data = new byte[2];
        data[0] = dataArray[position];
        data[1] = dataArray[position + 1];
        pos.appendPosition(2);

        return toUInt16LH(data);
    }

    public static int getSInt8(TDataPosition pos, byte[] dataArray) {
        int position = pos.getPosition();
        int result = dataArray[position];
        pos.appendPosition(1);

        return result;
    }

    public static long getSInt32(TDataPosition pos, byte[] dataArray) {
        int position = pos.getPosition();

        byte[] data = new byte[4];
        data[0] = dataArray[position];
        data[1] = dataArray[position + 1];
        data[2] = dataArray[position + 2];
        data[3] = dataArray[position + 3];

        int result = 0;
        result = toUInt32LH(data);
        pos.appendPosition(4);

        return result;
    }

    public static long getSInt16(TDataPosition pos, byte[] dataArray) {
        int position = pos.getPosition();

        byte[] data = new byte[2];
        data[0] = dataArray[position];
        data[1] = dataArray[position + 1];

        short result = 0;
        result = (short) (toUInt16LH(data));
        pos.appendPosition(2);

        return result;
    }

    public static float getFloat(TDataPosition pos, byte[] dataArray) {
        byte[] val = new byte[4];

        System.arraycopy(dataArray, pos.getPosition(), val, 0, 4);
        float result = Float.intBitsToFloat((int) toUInt32LH(val));
        pos.appendPosition(4);

        return result;
    }

    public static void getBytes(TDataPosition pos, byte[] dataArray, byte[] bytes, int length) throws Exception {
        int position = pos.getPosition();

        if (dataArray.length - position < length) {
            throw new Exception("data length not enough");
        }

        if (bytes == null || bytes.length != length) {
            bytes = new byte[length];
        }

        for (int i = 0; i < length; i++) {
            bytes[i] = dataArray[position + i];
        }

        pos.appendPosition(length);
    }

    public static void putData(TDataPosition pos, byte[] bytes, TStructProperty property) throws IllegalAccessException {
        int arrayLength = property.getAnnotation().arrayLength();
        final int dataLength = property.getAnnotation().dataLength();

        final boolean isDataLenDynamic = property.getAnnotation().dataLengthDynamic();
        final int dataLenDynamicOrder = property.getAnnotation().dataLengthDynamicOrder();
        final boolean dynamic = property.getAnnotation().dynamic();
        final int dynamicOrder = property.getAnnotation().dynamicOrder();

        if (property.getAnnotation().dataType() == TStructGlobal.UINT32) {
            if (arrayLength == 1) {
                long value = property.getField().getLong(property.getEntity());

                byte[] dataArray = property.getAnnotation().dataMode() == TStructGlobal.HighMode ? uint32ToHH(value) : uint32ToLH(value);
                putIntoArray(bytes, pos.getPosition(), dataArray);
                pos.appendPosition(dataArray.length);
            } else {
                long[] values = (long[]) property.getField().get(property.getEntity());

                for (int i = 0; i < arrayLength; i++) {
                    byte[] dataArray = property.getAnnotation().dataMode() == TStructGlobal.HighMode ? uint32ToHH(values[i]) : uint32ToLH(values[i]);
                    putIntoArray(bytes, pos.getPosition(), dataArray);
                    pos.appendPosition(dataArray.length);
                }
            }
        }
        else if (property.getAnnotation().dataType() == TStructGlobal.UINT16) {
            if (arrayLength == 1) {
                long value = property.getField().getLong(property.getEntity());

                byte[] dataArray = property.getAnnotation().dataMode() == TStructGlobal.HighMode ? uint16ToHH(value) : uint16ToLH(value);
                putIntoArray(bytes, pos.getPosition(), dataArray);
                pos.appendPosition(dataArray.length);
            } else {
                long[] values = (long[]) property.getField().get(property.getEntity());

                for (int i = 0; i < arrayLength; i++) {
                    byte[] dataArray = property.getAnnotation().dataMode() == TStructGlobal.HighMode ? uint16ToHH(values[i]) : uint16ToLH(values[i]);
                    putIntoArray(bytes, pos.getPosition(), dataArray);
                    pos.appendPosition(dataArray.length);
                }
            }
        }
        else if (property.getAnnotation().dataType() == TStructGlobal.UINT8) {
            if (!dynamic && arrayLength == 1) {
                long value = property.getField().getLong(property.getEntity());
                putIntoArray(bytes, pos.getPosition(), new byte[]{(byte) value});
                pos.appendPosition(1);
            } else {
                StructBasic struct = (StructBasic) property.getEntity();

                byte[] values = (byte[]) property.getField().get(property.getEntity());

                if (dynamic) {
                    TStructProperty orderProperty = getTStructPropertyByOrder(struct, dynamicOrder);
                    arrayLength = (int) orderProperty.getField().getLong(orderProperty.getEntity());

                    if (arrayLength == 0) {
                        return;
                    }
                }

                // 遍历值的长度而非指定的数组长度,避免值长度不足指定数组长度造成的数组边界问题
                for (int i = 0; i < values.length; i++) {
                    bytes[pos.getPosition() + i] = uint8(values[i]);
                }
                pos.appendPosition(arrayLength);
            }
        }
        else if (property.getAnnotation().dataType() == TStructGlobal.UINT64) {
            if (arrayLength == 1) {
                long value = property.getField().getLong(property.getEntity());

                byte[] dataArray = property.getAnnotation().dataMode() == TStructGlobal.HighMode ? uint64ToHH(value) : uint64ToLH(value);
                putIntoArray(bytes, pos.getPosition(), dataArray);
                pos.appendPosition(dataArray.length);
            } else {
                long[] values = (long[]) property.getField().get(property.getEntity());

                for (int i = 0; i < arrayLength; i++) {
                    byte[] dataArray = property.getAnnotation().dataMode() == TStructGlobal.HighMode ? uint64ToHH(values[i]) : uint64ToLH(values[i]);
                    putIntoArray(bytes, pos.getPosition(), dataArray);
                    pos.appendPosition(dataArray.length);
                }
            }
        }
        else if (property.getAnnotation().dataType() == TStructGlobal.STRING) {
            String[] strArr;
            // 单个字符串
            if (!dynamic && arrayLength == 1) {
                strArr = new String[]{(String) property.getField().get(property.getEntity())};
            }
            // 字符串数组/动态数组
            else {
                strArr = (String[]) property.getField().get(property.getEntity());
            }

            if (isDataLenDynamic) {
                StructBasic struct = (StructBasic) property.getEntity();
                TStructProperty orderProperty = getTStructPropertyByOrder(struct, dataLenDynamicOrder);
                int len = (int) orderProperty.getField().getLong(orderProperty.getEntity());

                for (String str : strArr) {
                    // 若字符串为空时无需赋值,仅递增position
                    putIntoArray(bytes, pos.getPosition(), StringUtils.isBlank(str) ? null : str.getBytes());
                    if (str != null) {
                        pos.appendPosition(len);
                    }
                }
            } else {
                for (String str : strArr) {
                    // 若字符串为空时无需赋值,仅递增position
                    putIntoArray(bytes, pos.getPosition(), StringUtils.isBlank(str) ? null : str.getBytes());
                    pos.appendPosition(dataLength);
                }
            }

        } else if (property.getAnnotation().dataType() == TStructGlobal.STRUCT) {

            final boolean dataLengthBasedOnData = property.getAnnotation().dataLengthBasedOnData();

            if (dynamic) {
                StructBasic struct = (StructBasic) property.getEntity();

                TStructProperty orderProperty = getTStructPropertyByOrder(struct, dynamicOrder);
                int length = (int) orderProperty.getField().getLong(orderProperty.getEntity());

                if (dataLengthBasedOnData) {
                    if (length > 0) {
                        StructBasic[] structs = (StructBasic[]) property.getField().get(property.getEntity());
                        for (int i = 0; i < length; i++) {
                            byte[] dataArray = structs[i].toBytes();
                            putIntoArray(bytes, pos.getPosition(), dataArray);
                            pos.appendPosition(dataArray.length);
                        }
                    }
                } else {
                    if (length > 0) {
                        StructBasic[] structs = (StructBasic[]) property.getField().get(property.getEntity());
                        for (int i = 0; i < length; i++) {
                            byte[] dataArray = structs[i].toBytes();
                            putIntoArray(bytes, pos.getPosition(), dataArray);
                            pos.appendPosition(dataArray.length);
                        }
                    }
                }
            } else {
                if (arrayLength == 1) {
                    StructBasic struct = (StructBasic) property.getField().get(property.getEntity());

                    byte[] dataArray = struct.toBytes();
                    putIntoArray(bytes, pos.getPosition(), dataArray);
                    pos.appendPosition(dataArray.length);
                } else {
                    StructBasic[] structs = (StructBasic[]) property.getField().get(property.getEntity());
                    for (int i = 0; i < arrayLength; i++) {
                        byte[] dataArray = structs[i].toBytes();
                        putIntoArray(bytes, pos.getPosition(), dataArray);
                        pos.appendPosition(dataArray.length);
                    }
                }
            }
        } else if (property.getAnnotation().dataType() == TStructGlobal.FLOAT) {
            if (arrayLength == 1) {
                float value = property.getField().getFloat(property.getEntity());

                byte[] dataArray = uint32ToLH(Float.floatToIntBits(value));
                putIntoArray(bytes, pos.getPosition(), dataArray);
                pos.appendPosition(dataArray.length);
            } else {
                float[] values = (float[]) property.getField().get(property.getEntity());

                for (int i = 0; i < arrayLength; i++) {
                    byte[] dataArray = uint32ToLH(Float.floatToIntBits(values[i]));
                    putIntoArray(bytes, pos.getPosition(), dataArray);
                    pos.appendPosition(dataArray.length);
                }
            }
        }
    }

    /**
     * 从 byte[] 赋值
     *
     * @param pos
     * @param bytes
     * @param property
     * @return 读取长度
     * @throws IllegalAccessException
     */
    public static int getData(TDataPosition pos, byte[] bytes, TStructProperty property) throws Exception {
        int arrayLength = property.getAnnotation().arrayLength();
        final int dataType = property.getAnnotation().dataType();
        final int dataLength = property.getAnnotation().dataLength();

        final boolean isDataLenDynamic = property.getAnnotation().dataLengthDynamic();
        final int dataLenDynamicOrder = property.getAnnotation().dataLengthDynamicOrder();
        final boolean isDynamic = property.getAnnotation().dynamic();
        final int dynamicOrder = property.getAnnotation().dynamicOrder();

        // 根据数组长度和是否可变数组判断是否为单个数据
        // 单个数据意味着不是数组
        final boolean isSingleDataStruct = arrayLength == 1 && !isDynamic;

        if (dataType == TStructGlobal.UINT8 || dataType == TStructGlobal.UINT16 || dataType == TStructGlobal.UINT32 || dataType == TStructGlobal.UINT64) {

            if (isSingleDataStruct) {
                byte[] val = new byte[dataLength];
                System.arraycopy(bytes, pos.getPosition(), val, 0, dataType);
                pos.appendPosition(dataType);

                if (dataType == TStructGlobal.UINT32) {
                    long res = property.getAnnotation().dataMode() == TStructGlobal.HighMode ? toUInt32HH(val) : toUInt32LH(val);
                    property.getField().setLong(property.getEntity(), res);
                }
                else if (dataType == TStructGlobal.UINT16) {
                    long res = property.getAnnotation().dataMode() == TStructGlobal.HighMode ? toUInt16HH(val) : toUInt16LH(val);
                    property.getField().setLong(property.getEntity(), res);
                }
                else if (dataType == TStructGlobal.UINT64) {
                    long res = property.getAnnotation().dataMode() == TStructGlobal.HighMode ? toUInt64HH(val) : toUInt64LH(val);
                    property.getField().setLong(property.getEntity(), res);
                }
                else {
                    property.getField().set(property.getEntity(), val[0]);
                }
            } else {

                StructBasic struct = (StructBasic) property.getEntity();

                if (isDynamic) {
                    TStructProperty orderProperty = getTStructPropertyByOrder(struct, dynamicOrder);
                    arrayLength = (int) orderProperty.getField().getLong(orderProperty.getEntity());
                }

                if (dataType == TStructGlobal.UINT64 || dataType == TStructGlobal.UINT32 || dataType == TStructGlobal.UINT16) {
                    long[] res = new long[arrayLength];
                    for (int i = 0; i < arrayLength; i++) {
                        byte[] val = new byte[dataLength];
                        System.arraycopy(bytes, pos.getPosition(), val, 0, dataType);
                        pos.appendPosition(dataLength);

                        res[i] = property.getAnnotation().dataMode() == TStructGlobal.HighMode ? toUInt32HH(val) : toUInt32LH(val);
                    }

                    property.getField().set(property.getEntity(), res);
                } else {

                    //剩余数据长度
                    int len = bytes.length - pos.getPosition();

                    byte[] res = new byte[arrayLength];
                    for (int i = 0; i < Math.min(len, arrayLength); i++) {
                        res[i] = bytes[pos.getPosition()];
                        pos.appendPosition(1);
                    }

                    property.getField().set(property.getEntity(), res);
                }
            }
        } else if (dataType == TStructGlobal.STRUCT) {

            if (isSingleDataStruct) {
                StructBasic struct = (StructBasic) property.getField().get(property.getEntity());
                TStructProperty[] properties = TStructUtils.getTStructProperties(struct);

                for (TStructProperty prop : properties) {
                    TStructUtils.getData(pos, bytes, prop);
                }
            } else {
                StructBasic[] struct = (StructBasic[]) property.getField().get(property.getEntity());

                int length = arrayLength;
                if (isDynamic) {
                    TStructProperty orderProperty = getTStructPropertyByOrder((StructBasic) property.getEntity(), dynamicOrder);
                    length = (int) orderProperty.getField().getLong(orderProperty.getEntity());

                    // 未指定动态数组长度 -> 需调用无参构造函数,手动初始化数组
                    if (struct == null) {
                        // 获取声明类型,必须为某类型的数组
                        final Class fieldClass = property.getField().getType();
                        Assert.isTrue(fieldClass.isArray(), "结构未声明为数组类型");
                        // 获取声明数组的类型,因为是Struct类型,必须为StructBasic的子类
                        final Class componentClass = fieldClass.getComponentType();
                        Assert.isTrue(StructBasic.class.isAssignableFrom(componentClass), "结构不为StructBasic子类");

                        // 初始化数组长度
                        Object[] structArray = (Object[]) Array.newInstance(componentClass, length);
                        for (int j = 0; j < length; ++j) {
                            // 调用无参构造函数
                            structArray[j] = componentClass.getConstructor().newInstance();
                        }

                        // 利用反射获取set函数
                        final String fieldName = property.getField().getName();
                        final String setMethodName = "set" + Character.toUpperCase(fieldName.charAt(0)) +
                                (fieldName.length() > 1 ? fieldName.substring(1) : "");
                        Method setMethod = property.getEntity().getClass().getMethod(setMethodName, property.getField().getType());
                        Assert.isTrue(setMethod.getParameterCount() == 1, "set函数参数个数不为1");
                        Assert.isTrue(setMethod.getParameterTypes()[0].equals(fieldClass), "set函数参数类型不符");
                        // 设置原实例属性,使用类强制转换确保参数类型匹配
                        setMethod.invoke(property.getEntity(), fieldClass.cast(structArray));
                        struct = (StructBasic[]) property.getField().get(property.getEntity());
                    }
                }

                for (int j = 0; j < length; j++) {
                    TStructProperty[] structProperties = TStructUtils.getTStructProperties(struct[j]);
                    for (TStructProperty prop : structProperties) {
                        TStructUtils.getData(pos, bytes, prop);
                    }
                }
            }
        } else if (dataType == TStructGlobal.STRING) {
            // 单个字符串
            if (isSingleDataStruct) {
                // 2021.4.20 动态长度字符串解析
                // 动态长度
                if (isDataLenDynamic) {
                    StructBasic struct = (StructBasic) property.getEntity();
                    TStructProperty orderProperty = getTStructPropertyByOrder(struct, dataLenDynamicOrder);
                    int len = (int) orderProperty.getField().getLong(orderProperty.getEntity());
                    String res = StringUtils.byteToString(Arrays.copyOfRange(bytes, pos.getPosition(), pos.getPosition() + len));
                    pos.appendPosition(len);
                    property.getField().set(property.getEntity(), res);
                }
                // 固定长度
                else {
                    String res = StringUtils.byteToString(Arrays.copyOfRange(bytes, pos.getPosition(), pos.getPosition() + dataLength));
                    pos.appendPosition(dataLength);
                    // 非数组直接赋值
                    property.getField().set(property.getEntity(), res);
                }
            }
            // 字符串数组/动态数组
            else {
                int length = arrayLength;
                if (isDynamic) {
                    TStructProperty orderProperty = getTStructPropertyByOrder((StructBasic) property.getEntity(), dynamicOrder);
                    length = (int) orderProperty.getField().getLong(orderProperty.getEntity());
                }

                String[] res = new String[length];
                for (int i = 0; i < length; i++) {
                    res[i] = StringUtils.byteToString(Arrays.copyOfRange(bytes, pos.getPosition(), pos.getPosition() + dataLength));
                    pos.appendPosition(dataLength);
                }
                property.getField().set(property.getEntity(), res);
            }
        } else if (dataType == TStructGlobal.FLOAT) {
            if (isSingleDataStruct) {
                byte[] val = new byte[dataLength];
                System.arraycopy(bytes, pos.getPosition(), val, 0, dataLength);
                pos.appendPosition(dataLength);

                float res = Float.intBitsToFloat(toUInt32LH(val));
                property.getField().set(property.getEntity(), res);
            } else {
                float[] res = new float[arrayLength];
                for (int i = 0; i < arrayLength; i++) {
                    byte[] val = new byte[dataLength];
                    System.arraycopy(bytes, pos.getPosition(), val, 0, dataLength);
                    pos.appendPosition(dataLength);

                    res[i] = Float.intBitsToFloat(toUInt32LH(val));
                }
                property.getField().set(property.getEntity(), res);
            }
        }

        return dataLength * arrayLength;
    }

    /**
     * 转 byte[] 低字节在前(低字节序)
     *
     * @param val
     * @return
     */
    public static byte[] uint64ToLH(long val) {
        byte[] res = new byte[8];
        res[0] = (byte) (val & 0xff);
        res[1] = (byte) (val >> 8 & 0xff);
        res[2] = (byte) (val >> 16 & 0xff);
        res[3] = (byte) (val >> 24 & 0xff);
        res[4] = (byte) (val >> 32 & 0xff);
        res[5] = (byte) (val >> 40 & 0xff);
        res[6] = (byte) (val >> 48 & 0xff);
        res[7] = (byte) (val >> 54 & 0xff);
        return res;
    }

    /**
     * 转 byte[] 高字节在前(高字节序)
     *
     * @param val
     * @return
     */
    public static byte[] uint64ToHH(long val) {
        byte[] res = new byte[8];
        res[7] = (byte) (val & 0xff);
        res[6] = (byte) (val >> 8 & 0xff);
        res[5] = (byte) (val >> 16 & 0xff);
        res[4] = (byte) (val >> 24 & 0xff);
        res[3] = (byte) (val >> 32 & 0xff);
        res[2] = (byte) (val >> 40 & 0xff);
        res[1] = (byte) (val >> 48 & 0xff);
        res[0] = (byte) (val >> 54 & 0xff);
        return res;
    }

    /**
     * 转 int 低字节在前(低字节序)
     *
     * @param val
     * @return
     */
    public static int toUInt64LH(byte[] val) {
        int res = 0;
        for (int i = 0; i < val.length; i++) {
            res += (val[i] & 0xff) << (i * 8);
        }
        return res;
    }

    /**
     * 转 int 高字节在前(高字节序)
     *
     * @param val
     * @return
     */
    public static long toUInt64HH(byte[] val) {
        int res = 0;
        for (int i = 0; i < val.length; i++) {
            res += (val[i] & 0xff) << ((7 - i) * 8);
        }
        return res;
    }

    /**
     * 转 byte[] 低字节在前(低字节序)
     *
     * @param val
     * @return
     */
    public static byte[] uint32ToLH(long val) {
        byte[] res = new byte[4];
        res[0] = (byte) (val & 0xff);
        res[1] = (byte) (val >> 8 & 0xff);
        res[2] = (byte) (val >> 16 & 0xff);
        res[3] = (byte) (val >> 24 & 0xff);
        return res;
    }

    /**
     * 转 byte[] 高字节在前(高字节序)
     *
     * @param val
     * @return
     */
    public static byte[] uint32ToHH(long val) {
        byte[] res = new byte[4];
        res[3] = (byte) (val & 0xff);
        res[2] = (byte) (val >> 8 & 0xff);
        res[1] = (byte) (val >> 16 & 0xff);
        res[0] = (byte) (val >> 24 & 0xff);
        return res;
    }

    /**
     * 转 int 低字节在前(低字节序)
     *
     * @param val
     * @return
     */
    public static int toUInt32LH(byte[] val) {
        int res = 0;
        for (int i = 0; i < val.length; i++) {
            res += (val[i] & 0xff) << (i * 8);
        }
        return res;
    }

    /**
     * 转 int 高字节在前(高字节序)
     *
     * @param val
     * @return
     */
    public static long toUInt32HH(byte[] val) {
        int res = 0;
        for (int i = 0; i < val.length; i++) {
            res += (val[i] & 0xff) << ((3 - i) * 8);
        }
        return res;
    }

    /**
     * 转 byte[] 低字节在前(低字节序)
     *
     * @param val
     * @return
     */
    public static byte[] uint16ToLH(long val) {
        byte[] res = new byte[2];
        res[0] = (byte) (val & 0xff);
        res[1] = (byte) (val >> 8 & 0xff);
        return res;
    }

    /**
     * 转 byte[] 高字节在前(高字节序)
     *
     * @param val
     * @return
     */
    public static byte[] uint16ToHH(long val) {
        byte[] res = new byte[2];
        res[1] = (byte) (val & 0xff);
        res[0] = (byte) (val >> 8 & 0xff);
        return res;
    }

    /**
     * 转 int 低字节在前(低字节序)
     *
     * @param val
     * @return
     */
    public static long toUInt16LH(byte[] val) {
        long res = 0;
        for (int i = 0; i < val.length; i++) {
            res += (val[i] & 0xff) << (i * 8);
        }
        return res;
    }

    /**
     * 转 int 高字节在前(高字节序)
     *
     * @param val
     * @return
     */
    public static long toUInt16HH(byte[] val) {
        long res = 0;
        for (int i = 0; i < val.length; i++) {
            res += (val[i] & 0xff) << ((1 - i) * 8);
        }
        return res;
    }

    public static byte uint8(long val) {
        return (byte) (val & 0xff);
    }

    private static void putIntoArray(byte[] sources, int startIndex, byte[] dataArray) {
        if (dataArray == null) {
            return;
        }
        Assert.notNull(sources);
        Assert.isTrue(startIndex + dataArray.length <= sources.length);
        System.arraycopy(dataArray, 0, sources, startIndex, dataArray.length);
    }

    private static TStructProperty getTStructPropertyByOrder(StructBasic entity, int order) {
        return Arrays.stream(entity.getClass().getFields())
                .filter(field -> field.isAnnotationPresent(TStruct.class)
                        && field.getAnnotation(TStruct.class).order() == order)
                .findFirst()
                .map(field -> new TStructProperty()
                        .setField(field)
                        .setAnnotation(field.getAnnotation(TStruct.class))
                        .setEntity(entity))
                .orElse(null);
    }
}

WsClient 类


import  一大堆 所有代码都有 缺哪个加哪个
import lombok.Data;

import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicLong;

@Data
public class WsClient {

    private long dbId;
    private Session session;
    private String clientId;
    private String group;
    private byte[] userData = new byte[TWebsocketGlobal.MAX_USER_DATA];
    private long[] subscribe = new long[TWebsocketGlobal.MAX_SUBSCRIBE_TYPE];
    private long clientType;
    private AtomicLong serial = new AtomicLong();

    private String ipAddress;

    private byte[] clientData;
    private long clientDataLength;

    private boolean initialized = false;

    private WsClientData wsClientData;

    private LocalDateTime pingTime;

    private final Map<String, Object> clientObjectsMap = new HashMap<>();

    public final static String PASSWORD = "PASSWORD";

    //region Getter & Setter
    public void setUserData(byte[] val) {
        System.arraycopy(val, 0, userData, 0, val.length);
    }

    public Long getSerial() {
        return serial.incrementAndGet();
    }

    public void setSerial(Long serial) {
        this.serial = new AtomicLong(serial);
    }

    public void setClientData(byte[] val) {
        if (clientData == null || clientData.length < val.length) {
            clientData = new byte[val.length];
        }

        System.arraycopy(val, 0, clientData, 0, val.length);
    }
    //endregion

    //region toString
    @Override
    public String toString() {
        return "WsClient{" +
                "dbId=" + dbId +
                ", session=" + session +
                ", clientId='" + clientId + '\'' +
                ", group='" + group + '\'' +
                ", userData=" + Arrays.toString(userData) +
                ", subscribe=" + Arrays.toString(subscribe) +
                ", clientType=" + clientType +
                ", serial=" + serial +
                ", ipAddress='" + ipAddress + '\'' +
                ", clientData=" + Arrays.toString(clientData) +
                ", clientDataLength=" + clientDataLength +
                ", initialized=" + initialized +
                ", wsClientData=" + wsClientData +
                ", pingTime=" + pingTime +
                '}';
    }
    //endregion

    //region equals & hashCode
    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (!(o instanceof WsClient)) {
            return false;
        }
        WsClient wsClient = (WsClient) o;
        return clientId.equals(wsClient.clientId);
    }

    @Override
    public int hashCode() {
        return Objects.hash(clientId);
    }
    //endregion

    public boolean subscribe(int type, long value) {
        // 未改变值直接返回
        if ((subscribe[type] ^ value) == 0) {
            return false;`在这里插入代码片`
        }

        // 添加订阅
        subscribe[type] |= value;
        return true;
    }

    public boolean unsubscribe(int type, long value) {
        boolean changed = (subscribe[type] ^ value) != 0;

        // 取消订阅
        if (value == 0xFFFF && type == 0xFFFF) {
            subscribe[type] = 0;
        } else {
            subscribe[type] &= ~value;
        }
        return changed;
    }
}

Session类


import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import io.netty.channel.*;
import io.netty.handler.codec.http.websocketx.BinaryWebSocketFrame;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.util.AttributeKey;

import java.net.SocketAddress;
import java.nio.ByteBuffer;

public class Session {

    private final Channel channel;

    Session(Channel channel) {
        this.channel = channel;
    }

    public void setSubProtocols(String subPropocols) {
        setAttribute("subprotocols", subPropocols);
    }

    public ChannelFuture sendText(String message) {
        return channel.writeAndFlush(new TextWebSocketFrame(message));
    }

    public ChannelFuture sendText(ByteBuf byteBuf) {
        return channel.writeAndFlush(new TextWebSocketFrame(byteBuf));
    }

    public ChannelFuture sendText(ByteBuffer byteBuffer) {
        ByteBuf buffer = channel.alloc().buffer(byteBuffer.remaining());
        buffer.writeBytes(byteBuffer);
        return channel.writeAndFlush(new TextWebSocketFrame(buffer));
    }

    public ChannelFuture sendText(TextWebSocketFrame textWebSocketFrame) {
        return channel.writeAndFlush(textWebSocketFrame);
    }

    public ChannelFuture sendBinary(byte[] bytes) {
        ByteBuf buffer = channel.alloc().buffer(bytes.length);
        return channel.writeAndFlush(new BinaryWebSocketFrame(buffer.writeBytes(bytes)));
    }

    public ChannelFuture sendBinary(ByteBuf byteBuf) {
        return channel.writeAndFlush(new BinaryWebSocketFrame(byteBuf));
    }

    public ChannelFuture sendBinary(ByteBuffer byteBuffer) {
        ByteBuf buffer = channel.alloc().buffer(byteBuffer.remaining());
        buffer.writeBytes(byteBuffer);
        return channel.writeAndFlush(new BinaryWebSocketFrame(buffer));
    }

    public ChannelFuture sendBinary(BinaryWebSocketFrame binaryWebSocketFrame) {
        return channel.writeAndFlush(binaryWebSocketFrame);
    }

    public ChannelFuture sendBinary(StructBasic structBasic) {
        return this.sendBinary(structBasic.toBytes());
    }

    public <T> void setAttribute(String name, T value) {
        AttributeKey<T> sessionIdKey = AttributeKey.valueOf(name);
        channel.attr(sessionIdKey).set(value);
    }

    public <T> T getAttribute(String name) {
        AttributeKey<T> sessionIdKey = AttributeKey.valueOf(name);
        return channel.attr(sessionIdKey).get();
    }

    public Channel channel() {
        return channel;
    }

    public ChannelId id() {
        return channel.id();
    }

    public ChannelConfig config() {
        return channel.config();
    }

    public boolean isOpen() {
        return channel.isOpen();
    }

    public boolean isRegistered() {
        return channel.isRegistered();
    }

    public boolean isActive() {
        return channel.isActive();
    }

    public ChannelMetadata metadata() {
        return channel.metadata();
    }

    public SocketAddress localAddress() {
        return channel.localAddress();
    }

    public SocketAddress remoteAddress() {
        return channel.remoteAddress();
    }

    public ChannelFuture closeFuture() {
        return channel.closeFuture();
    }

    public boolean isWritable() {
        return channel.isWritable();
    }

    public long bytesBeforeUnWritable() {
        return channel.bytesBeforeUnwritable();
    }

    public long bytesBeforeWritable() {
        return channel.bytesBeforeWritable();
    }

    public Channel.Unsafe unsafe() {
        return channel.unsafe();
    }

    public ByteBufAllocator alloc() {
        return channel.alloc();
    }

    public Channel read() {
        return channel.read();
    }

    public Channel flush() {
        return channel.flush();
    }

    public ChannelFuture close() {
        return channel.close();
    }

    public ChannelFuture close(ChannelPromise promise) {
        return channel.close(promise);
    }
}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
使用WebSocket实现数据库更新时前端页面的实时刷新,你可以按照以下步骤进行操作: 1. 在后端,使用WebSocket协议与前端建立连接。你可以使用一些流行的WebSocket库,如Socket.io(Node.js)或Tornado(Python)来简化这个过程。 2. 在前端使用JavaScript的WebSocket API与后端建立连接。可以使用以下代码示例: ```javascript const socket = new WebSocket('ws://your-server-url'); socket.onopen = () => { console.log('WebSocket连接已建立'); }; socket.onmessage = (event) => { console.log('收到消息:', event.data); // 在收到消息时执行相应的操作,如更新页面内容 }; socket.onclose = () => { console.log('WebSocket连接已关闭'); }; ``` 3. 在后端,监听数据库的更新操作。当数据库发生更新时,通过WebSocket前端发送消息。具体实现方式取决于你使用的数据库和后端语言。 例如,如果你使用Node.js和MongoDB,可以使用MongoDB的Change Streams功能来监听数据库的变化,并通过WebSocket发送消息前端。以下是一个简单的示例: ```javascript const { MongoClient } = require('mongodb'); const WebSocket = require('ws'); const url = 'mongodb://localhost:27017'; const dbName = 'your-database-name'; const collectionName = 'your-collection-name'; const wss = new WebSocket.Server({ port: 8080 }); (async function () { const client = await MongoClient.connect(url, { useUnifiedTopology: true }); const db = client.db(dbName); const collection = db.collection(collectionName); const changeStream = collection.watch(); changeStream.on('change', (change) => { const message = JSON.stringify(change); wss.clients.forEach((client) => { if (client.readyState === WebSocket.OPEN) { client.send(message); // 向前端发送更新消息 } }); }); })(); ``` 这样,当数据库中的数据发生变化时,后端会将变化信息通过WebSocket发送前端前端页面可以根据接收到的消息来实时更新内容。 请注意,以上代码只是一个简单的示例,实际上,你需要根据你的具体需求和技术栈进行相应的配置和开发。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Owen_Number_One

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

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

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

打赏作者

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

抵扣说明:

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

余额充值