通过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 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 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 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 void setAttribute(String name, T value) {
AttributeKey sessionIdKey = AttributeKey.valueOf(name);
channel.attr(sessionIdKey).set(value);
}
public T getAttribute(String name) {
AttributeKey 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);
}
}