diff --git a/protocol/src/main/java/com/zfoo/protocol/generate/GenerateProtocolDocument.java b/protocol/src/main/java/com/zfoo/protocol/generate/GenerateProtocolDocument.java index e7631d4c..7f964537 100644 --- a/protocol/src/main/java/com/zfoo/protocol/generate/GenerateProtocolDocument.java +++ b/protocol/src/main/java/com/zfoo/protocol/generate/GenerateProtocolDocument.java @@ -16,7 +16,8 @@ package com.zfoo.protocol.generate; import com.zfoo.protocol.model.Pair; import com.zfoo.protocol.registration.IProtocolRegistration; import com.zfoo.protocol.registration.ProtocolRegistration; -import com.zfoo.protocol.serializer.anno.Description; +import com.zfoo.protocol.serializer.anno.ProtocolClass; +import com.zfoo.protocol.serializer.anno.ProtocolField; import com.zfoo.protocol.util.AssertionUtils; import com.zfoo.protocol.util.StringUtils; @@ -72,25 +73,24 @@ public abstract class GenerateProtocolDocument { public static void initProtocolDocument(List protocolRegistrations) { AssertionUtils.notNull(protocolDocumentMap, "[{}]已经初始完成,初始化完成过后不能调用initProtocolDocument", GenerateProtocolDocument.class.getSimpleName()); - - // 文件的注释生成 + for (var protocolRegistration : protocolRegistrations) { var protocolClazz = protocolRegistration.protocolConstructor().getDeclaringClass(); var docFieldMap = new HashMap(); var docTitle = StringUtils.EMPTY; - var description = protocolClazz.getDeclaredAnnotation(Description.class); - if (description != null) { - var docTitleBuilder = new StringBuilder().append("//").append(description.value()); + var protocolClass = protocolClazz.getDeclaredAnnotation(ProtocolClass.class); + if (protocolClass != null && StringUtils.isNotEmpty(protocolClass.description())) { + var docTitleBuilder = new StringBuilder().append("//").append(protocolClass.description()); docTitle = docTitleBuilder.toString(); } var registration = (ProtocolRegistration) protocolRegistration; for (var field : registration.getFields()) { - var fieldDescrption = field.getDeclaredAnnotation(Description.class); - if (fieldDescrption == null) { + var protocolField = field.getDeclaredAnnotation(ProtocolField.class); + if (protocolField == null || StringUtils.isEmpty(protocolField.description())) { continue; } - var docBuilder = new StringBuilder().append("//").append(fieldDescrption.value()); + var docBuilder = new StringBuilder().append("//").append(protocolField.description()); var fieldName = field.getName(); docFieldMap.put(fieldName, docBuilder.toString()); } diff --git a/protocol/src/main/java/com/zfoo/protocol/registration/ProtocolAnalysis.java b/protocol/src/main/java/com/zfoo/protocol/registration/ProtocolAnalysis.java index f8b4a570..ad5a689d 100644 --- a/protocol/src/main/java/com/zfoo/protocol/registration/ProtocolAnalysis.java +++ b/protocol/src/main/java/com/zfoo/protocol/registration/ProtocolAnalysis.java @@ -24,6 +24,7 @@ import com.zfoo.protocol.generate.GenerateProtocolFile; import com.zfoo.protocol.generate.GenerateProtocolPath; import com.zfoo.protocol.registration.anno.Compatible; import com.zfoo.protocol.registration.field.*; +import com.zfoo.protocol.serializer.anno.ProtocolClass; import com.zfoo.protocol.serializer.cpp.GenerateCppUtils; import com.zfoo.protocol.serializer.csharp.GenerateCsUtils; import com.zfoo.protocol.serializer.gdscript.GenerateGdUtils; @@ -448,11 +449,6 @@ public class ProtocolAnalysis { return allSubProtocolIdSet; } - public static short getProtocolIdByClass(Class clazz) { - var protocolIdField = ReflectionUtils.getFieldByNameInPOJOClass(clazz, PROTOCOL_ID); - return (short) ReflectionUtils.getField(protocolIdField, null); - } - // 协议智能语法分析,错误的协议定义将无法启动程序并给出错误警告 //----------------------------------------------------------------------- @@ -464,13 +460,49 @@ public class ProtocolAnalysis { // 不能是泛型类 AssertionUtils.isTrue(ArrayUtils.isEmpty(clazz.getTypeParameters()), "[class:{}]不能是泛型类", clazz.getCanonicalName()); - Field protocolIdField; + var protocolId = getProtocolIdByClass(clazz); + // 验证protocol()方法的返回是否和PROTOCOL_ID相等 + Method protocolMethod; + try { + protocolMethod = clazz.getDeclaredMethod(PROTOCOL_METHOD); + } catch (NoSuchMethodException e) { + protocolMethod = null; + } + + if (protocolMethod != null) { + // 必须要有一个空的构造器 + Constructor constructor = ReflectionUtils.publicEmptyConstructor(clazz); + IPacket packet = (IPacket) constructor.newInstance(); + var methodReturnId = (short) protocolMethod.invoke(packet); + AssertionUtils.isTrue(methodReturnId == protocolId, "[class:{}]的protocolId方法返回的值[{}]和协议号返回值[{}]不相等", clazz.getCanonicalName(), methodReturnId, protocolId); + } + + var previous = protocolClassMap.put(protocolId, clazz); + if (previous != null) { + throw new RunException("[{}][{}]协议号[protocolId:{}]重复", clazz.getCanonicalName(), previous.getCanonicalName(), protocolId); + } + //存储class和protocolId的映射 + protocolIdMap.put(clazz, protocolId); + } + + public static short getProtocolIdByClass(Class clazz) { + var protocolClass = clazz.getDeclaredAnnotation(ProtocolClass.class); + short annoProtocolId = 0; + if (protocolClass != null && protocolClass.protocolId() != 0) { + annoProtocolId = protocolClass.protocolId(); + } + + Field protocolIdField = null; try { protocolIdField = clazz.getDeclaredField(PROTOCOL_ID); } catch (NoSuchFieldException e) { - throw new UnknownException(e, "[class:{}]没有[{}]协议序列号", clazz.getCanonicalName(), PROTOCOL_ID); + if (annoProtocolId != 0) { + return annoProtocolId; + } } + // 是否被public修饰 + AssertionUtils.isTrue(protocolIdField != null, "[class:{}]协议序列号[{}]没有被public修饰", clazz.getCanonicalName(), PROTOCOL_ID); // 是否被public修饰 AssertionUtils.isTrue(Modifier.isPublic(protocolIdField.getModifiers()), "[class:{}]协议序列号[{}]没有被public修饰", clazz.getCanonicalName(), PROTOCOL_ID); // 是否被static修饰 @@ -481,31 +513,13 @@ public class ProtocolAnalysis { AssertionUtils.isTrue(Modifier.isTransient(protocolIdField.getModifiers()), "[class:{}]协议序列号[{}]没有被transient修饰", clazz.getCanonicalName(), PROTOCOL_ID); // 命名只能包含字母,数字,下划线 AssertionUtils.isTrue(clazz.getSimpleName().matches("[a-zA-Z0-9_]*"), "[class:{}]的命名只能包含字母,数字,下划线", clazz.getCanonicalName(), PROTOCOL_ID); - - // 必须要有一个空的构造器 - Constructor constructor = ReflectionUtils.publicEmptyConstructor(clazz); - + ReflectionUtils.makeAccessible(protocolIdField); - IPacket packet = (IPacket) constructor.newInstance(); - var protocolId = (short) protocolIdField.get(null); - // 验证protocol()方法的返回是否和PROTOCOL_ID相等 - Method protocolMethod; - try { - protocolMethod = clazz.getDeclaredMethod(PROTOCOL_METHOD); - } catch (NoSuchMethodException e) { - protocolMethod = null; + var protocolId = (short) ReflectionUtils.getField(protocolIdField, null); + if (annoProtocolId != 0) { + AssertionUtils.isTrue(annoProtocolId == protocolId, "[class:{}]协议序列号[{}]:[{}]与注解协议号[{}]值不相等", clazz.getCanonicalName(), PROTOCOL_ID, protocolId, annoProtocolId); } - if (protocolMethod != null) { - var methodReturnId = (short) protocolMethod.invoke(packet); - AssertionUtils.isTrue(methodReturnId == protocolId, "[class:{}]的protocolId返回的值和协议号的静态变量[{}]不相等", clazz.getCanonicalName(), PROTOCOL_ID); - } - - var previous = protocolClassMap.put(protocolId, clazz); - if (previous != null) { - throw new RunException("[{}][{}]协议号[protocolId:{}]重复", clazz.getCanonicalName(), previous.getCanonicalName(), protocolId); - } - //存储class和protocolId的映射 - protocolIdMap.put(clazz, protocolId); + return protocolId; } private static void checkSubProtocol(Class clazz, short id, Class subClass) { diff --git a/protocol/src/main/java/com/zfoo/protocol/serializer/anno/ProtocolClass.java b/protocol/src/main/java/com/zfoo/protocol/serializer/anno/ProtocolClass.java new file mode 100644 index 00000000..f084a449 --- /dev/null +++ b/protocol/src/main/java/com/zfoo/protocol/serializer/anno/ProtocolClass.java @@ -0,0 +1,19 @@ +package com.zfoo.protocol.serializer.anno; + +import java.lang.annotation.*; + +/** + * @author meiw + * @version 3.0 + * + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE}) +public @interface ProtocolClass { + + short protocolId() default 0; + + String description() default ""; + +} diff --git a/protocol/src/main/java/com/zfoo/protocol/serializer/anno/Description.java b/protocol/src/main/java/com/zfoo/protocol/serializer/anno/ProtocolField.java similarity index 60% rename from protocol/src/main/java/com/zfoo/protocol/serializer/anno/Description.java rename to protocol/src/main/java/com/zfoo/protocol/serializer/anno/ProtocolField.java index 89273042..602dd207 100644 --- a/protocol/src/main/java/com/zfoo/protocol/serializer/anno/Description.java +++ b/protocol/src/main/java/com/zfoo/protocol/serializer/anno/ProtocolField.java @@ -9,9 +9,9 @@ import java.lang.annotation.*; */ @Documented @Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.FIELD, ElementType.TYPE}) -public @interface Description { +@Target({ElementType.FIELD}) +public @interface ProtocolField { - String value() default ""; + String description() default ""; }