|  |  | 
 |  |  | import java.io.DataOutputStream; | 
 |  |  | import java.lang.reflect.Array; | 
 |  |  | import java.lang.reflect.Field; | 
 |  |  | import java.nio.charset.StandardCharsets; | 
 |  |  | import java.util.*; | 
 |  |  |  | 
 |  |  | /** | 
 |  |  |  * Tcp协议报文基类 | 
 |  |  |  * @author vincent | 
 |  |  |  */ | 
 |  |  | public class Struct implements java.io.Serializable { | 
 |  |  |     | 
 |  |  |    private transient Map<String,byte[]> decodeByteMapping = new HashMap<>(); | 
 |  |  |    private transient Map<String,byte[]> encodeByteMapping = new HashMap<>(); | 
 |  |  |    // 解码前的原生字节数组 | 
 |  |  |    private transient byte[] dataBytes = null; | 
 |  |  |    private transient byte[] decodeBytes = null; | 
 |  |  |    private transient byte[] encodeBytes = null; | 
 |  |  | 
 |  |  |    public Class getClassType(String name){ | 
 |  |  |       return null; | 
 |  |  |    } | 
 |  |  | 	 | 
 |  |  |  | 
 |  |  |    /** | 
 |  |  |     * 判断大小端 | 
 |  |  |     * @return true: 小端 / false: 大端 | 
 |  |  |     */ | 
 |  |  |    public boolean isReverse() { | 
 |  |  |       return this.getClass().getAnnotation(little.class)!=null; | 
 |  |  |    } | 
 |  |  | 	 | 
 |  |  |  | 
 |  |  |    /** | 
 |  |  |     * 获取字节数组 | 
 |  |  |     */ | 
 |  |  |    public byte[] toBytes() throws Exception { | 
 |  |  |       return encode(this); | 
 |  |  |    } | 
 |  |  |     | 
 |  |  |    public Map<String,String> toDecodeHexMapping() throws Exception{ | 
 |  |  |       if(this.decodeByteMapping==null)this.decodeByteMapping=new HashMap(); | 
 |  |  |       if(this.decodeByteMapping==null)this.decodeByteMapping=new HashMap<>(); | 
 |  |  |       Map<String, String> mapping = getHex(this.decodeByteMapping); | 
 |  |  |       if(this.decodeBytes!=null){ | 
 |  |  |          mapping.put("byte[]", Struct.toHex(this.decodeBytes)); | 
 |  |  | 
 |  |  |    } | 
 |  |  |    public Map<String,String> toEncodeHexMapping() throws Exception{ | 
 |  |  |       if(this.encodeBytes==null)this.encode(this); | 
 |  |  |       if(this.encodeByteMapping==null)this.encodeByteMapping=new HashMap(); | 
 |  |  |       if(this.encodeByteMapping==null)this.encodeByteMapping=new HashMap<>(); | 
 |  |  |       Map<String, String> mapping = getHex(this.encodeByteMapping); | 
 |  |  |       mapping.put("byte[]", Struct.toHex(this.encodeBytes)); | 
 |  |  |       return mapping; | 
 |  |  |    } | 
 |  |  |    public Map<String,String> getHex(Map<String,byte[]> bytemapping) throws Exception { | 
 |  |  |       Map<String,String> map = new LinkedHashMap(); | 
 |  |  |       Map<String,String> map = new LinkedHashMap<>(); | 
 |  |  |       Field[] fields = this.getClass().getFields(); | 
 |  |  |       for (Field field : fields) { | 
 |  |  |          byte[] bytes = bytemapping.get(field.getName()); | 
 |  |  | 
 |  |  |     *  | 
 |  |  |     * @param dos | 
 |  |  |     * @param entity | 
 |  |  |     * @throws Exception | 
 |  |  |     */ | 
 |  |  |    public void write(DataOutputStream dos, Struct entity) throws Exception { | 
 |  |  |       if(entity==null)return; | 
 |  |  |       if(entity.encodeByteMapping==null)entity.encodeByteMapping=new HashMap(); | 
 |  |  |       if(entity.encodeByteMapping==null)entity.encodeByteMapping=new HashMap<>(); | 
 |  |  |       Field[] fields = entity.getClass().getFields(); | 
 |  |  |       EvaluationContext context = new StandardEvaluationContext(); | 
 |  |  |       for (Field field : Objects.requireNonNull(ReflectUtils.removeStaticField(fields))) { | 
 |  |  | 
 |  |  |       return instance.decode(bytes); | 
 |  |  |    } | 
 |  |  |  | 
 |  |  |    /** | 
 |  |  |     * 解码: 字节数组 ====>> java对象 | 
 |  |  |     */ | 
 |  |  |    @SuppressWarnings({ "unchecked", "rawtypes" }) | 
 |  |  |    public <T extends Struct> T decode(byte[] bytes) throws Exception{ | 
 |  |  |       this.dataBytes = bytes; | 
 |  |  | 
 |  |  |       Class<? extends Struct> cls = this.getClass(); | 
 |  |  |       Field[] fields = cls.getFields(); | 
 |  |  |       if(this.decodeByteMapping==null)instance.decodeByteMapping=new HashMap(); | 
 |  |  |       // spring el表达式 | 
 |  |  |       EvaluationContext context = new StandardEvaluationContext(); | 
 |  |  |       context.setVariable("_", bytes.length); | 
 |  |  |       int bited = 0;//已读位数 | 
 |  |  | 
 |  |  |          bit bit = field.getAnnotation(bit.class); | 
 |  |  |          expr expr = field.getAnnotation(expr.class); | 
 |  |  |          flag flag = field.getAnnotation(flag.class); | 
 |  |  |          // 没有size、bit、expr注解的变量不进行解析 | 
 |  |  |          if(size==null && bit==null && expr==null){ | 
 |  |  |             continue; | 
 |  |  |             //throw new RuntimeException(cls.getSimpleName()+"字段"+field.getName()+"未标记@size|@bit|@expr"); | 
 |  |  |          } | 
 |  |  |          String name = field.getName(); | 
 |  |  |          Class<?> type = field.getType(); | 
 |  |  | 
 |  |  |          }else if (typeName.equals("byte[]")){ | 
 |  |  |             field.set(instance, bts); | 
 |  |  |          }else if (typeName.equals("String")) { | 
 |  |  |             String strStr = new String(bts,"UTF-8"); | 
 |  |  |             String strStr = new String(bts, StandardCharsets.UTF_8); | 
 |  |  |             if(flag!=null && flag.value().equals("BCD")){ | 
 |  |  |                strStr = bcd2Str(bts); | 
 |  |  |             }else if(flag!=null && flag.value().equals("ASCII")){ | 
 |  |  | 
 |  |  |       instance.unusedBytes = unusedBytes; | 
 |  |  |       return (T) instance; | 
 |  |  |    } | 
 |  |  |  | 
 |  |  |    // 字节数组 ===>> 转为十六进制字符串 | 
 |  |  |    public static String toHex(byte[] bytes) { | 
 |  |  |         StringBuilder buf = new StringBuilder(bytes.length * 2); | 
 |  |  |         for(byte b : bytes) { // 使用String的format方法进行转换 | 
 |  |  |             buf.append(String.format("%02x", new Integer(b & 0xff))); | 
 |  |  |             buf.append(String.format("%02x", b & 0xff)); | 
 |  |  |         } | 
 |  |  |         return buf.toString().toUpperCase(); | 
 |  |  |     } | 
 |  |  | 
 |  |  |       return bbt; | 
 |  |  |    } | 
 |  |  |      | 
 |  |  |      | 
 |  |  |     public static class TestMessage { | 
 |  |  |       public @size(1) byte begin = 0x7e;//起始符 | 
 |  |  |       public @size(2) short type = 0;//消息ID | 
 |  |  | 
 |  |  |   //字符串转换为ascii | 
 |  |  |     public static byte[] StrToAsc(String content){ | 
 |  |  |       try { | 
 |  |  |       return content.getBytes("US-ASCII"); | 
 |  |  |       return content.getBytes(StandardCharsets.US_ASCII); | 
 |  |  |    } catch (Exception e) { | 
 |  |  |       e.printStackTrace(); | 
 |  |  |       return null; | 
 |  |  | 
 |  |  |     | 
 |  |  |     //ascii转换为string | 
 |  |  |     public static String AscToStr(byte[] bytes){ | 
 |  |  |        StringBuffer sbu = new StringBuffer();   | 
 |  |  |        for(int i=0;i<bytes.length;i++){ | 
 |  |  |           sbu.append(Character.toString((char)bytes[i])); | 
 |  |  |        } | 
 |  |  |        StringBuffer sbu = new StringBuffer(); | 
 |  |  |       for (byte aByte : bytes) { | 
 |  |  |          sbu.append(Character.toString((char) aByte)); | 
 |  |  |       } | 
 |  |  |         return sbu.toString();  | 
 |  |  |     } | 
 |  |  |  |