diff --git a/boot/pom.xml b/boot/pom.xml index d5e9d62b..25111875 100644 --- a/boot/pom.xml +++ b/boot/pom.xml @@ -36,7 +36,6 @@ 4.1.84.Final 2.4.17 5.3.0 - 0.10.2 5.3.0 diff --git a/event/pom.xml b/event/pom.xml index a4690658..6992ea0d 100644 --- a/event/pom.xml +++ b/event/pom.xml @@ -36,7 +36,6 @@ 4.1.84.Final 2.4.17 5.3.0 - 0.10.2 5.3.0 diff --git a/hotswap/pom.xml b/hotswap/pom.xml index ab6caf07..50d5ac2d 100644 --- a/hotswap/pom.xml +++ b/hotswap/pom.xml @@ -36,7 +36,6 @@ 4.1.84.Final 2.4.17 5.3.0 - 0.10.2 5.3.0 diff --git a/monitor/pom.xml b/monitor/pom.xml index 72d951e4..fd6d2339 100644 --- a/monitor/pom.xml +++ b/monitor/pom.xml @@ -36,7 +36,6 @@ 4.1.84.Final 2.4.17 5.3.0 - 0.10.2 5.3.0 diff --git a/net/pom.xml b/net/pom.xml index fce4ab5e..e9a90177 100644 --- a/net/pom.xml +++ b/net/pom.xml @@ -36,7 +36,6 @@ 4.1.84.Final 2.4.17 5.3.0 - 0.10.2 5.3.0 diff --git a/net/src/main/java/com/zfoo/net/config/model/NetConfig.java b/net/src/main/java/com/zfoo/net/config/model/NetConfig.java index adef8f6b..bc557c82 100644 --- a/net/src/main/java/com/zfoo/net/config/model/NetConfig.java +++ b/net/src/main/java/com/zfoo/net/config/model/NetConfig.java @@ -36,7 +36,7 @@ public class NetConfig { /** * 生成协议列表 */ - private String protocolList; + private String codeLanguages; /** * 注册中心 @@ -135,12 +135,12 @@ public class NetConfig { this.consumer = consumer; } - public String getProtocolList() { - return protocolList; + public String getCodeLanguages() { + return codeLanguages; } - public void setProtocolList(String protocolList) { - this.protocolList = protocolList; + public void setCodeLanguages(String codeLanguages) { + this.codeLanguages = codeLanguages; } @Override diff --git a/net/src/main/java/com/zfoo/net/packet/PacketService.java b/net/src/main/java/com/zfoo/net/packet/PacketService.java index 78311027..ebceb662 100644 --- a/net/src/main/java/com/zfoo/net/packet/PacketService.java +++ b/net/src/main/java/com/zfoo/net/packet/PacketService.java @@ -31,6 +31,7 @@ import io.netty.buffer.ByteBuf; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.context.ConfigurableApplicationContext; import org.springframework.stereotype.Component; import org.springframework.util.ResourceUtils; @@ -95,15 +96,14 @@ public class PacketService implements IPacketService { generateOperation.setFoldProtocol(netConfig.isFoldProtocol()); generateOperation.setProtocolPath(netConfig.getProtocolPath()); generateOperation.setProtocolParam(netConfig.getProtocolParam()); - var protocolArr = StringUtils.tokenize(netConfig.getProtocolList(), StringUtils.SEMICOLON_COMMA); + var codeLanguageArr = StringUtils.tokenize(netConfig.getCodeLanguages(), ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS); - for (var protocolCode : protocolArr) { - protocolCode = protocolCode.replaceAll(StringUtils.SPACE_REGEX, ""); - var codeLanguage = getProtocolList(protocolCode); - if (CollectionUtils.isEmpty(codeLanguage)) { + for (var codeLanguage : codeLanguageArr) { + var codeLanguageSet = getProtocolList(codeLanguage); + if (CollectionUtils.isEmpty(codeLanguageSet)) { continue; } - generateOperation.getGenerateLanguages().addAll(codeLanguage); + generateOperation.getGenerateLanguages().addAll(codeLanguageSet); } // 设置生成协议的过滤器 GenerateProtocolFile.generateProtocolFilter = netGenerateProtocolFilter; @@ -127,20 +127,20 @@ public class PacketService implements IPacketService { /** * 获取要生成协议列表 - * @param protocolCode + * @param codeLanguage * @return */ - private Set getProtocolList(String protocolCode) { + private Set getProtocolList(String codeLanguage) { var languageSet = new HashSet(); - boolean isNumeric = StringUtils.isNumeric(protocolCode); - for (var codeLanguage : CodeLanguage.values()) { + boolean isNumeric = StringUtils.isNumeric(codeLanguage); + for (var language : CodeLanguage.values()) { if (isNumeric) { - var protocolBit = Integer.valueOf(protocolCode); - if ((protocolBit & codeLanguage.id) != 0) { - languageSet.add(codeLanguage); + var code = Integer.valueOf(codeLanguage); + if ((code & language.id) != 0) { + languageSet.add(language); } - } else if (codeLanguage.name().equalsIgnoreCase(protocolCode)) { - languageSet.add(codeLanguage); + } else if (language.name().equalsIgnoreCase(codeLanguage)) { + languageSet.add(language); break; } } diff --git a/net/src/main/java/com/zfoo/net/schema/NetDefinitionParser.java b/net/src/main/java/com/zfoo/net/schema/NetDefinitionParser.java index b82cbe87..5c2e02ca 100644 --- a/net/src/main/java/com/zfoo/net/schema/NetDefinitionParser.java +++ b/net/src/main/java/com/zfoo/net/schema/NetDefinitionParser.java @@ -105,7 +105,7 @@ public class NetDefinitionParser implements BeanDefinitionParser { // 文件是否折叠 resolvePlaceholder("fold-protocol", "foldProtocol", builder, element, parserContext); // 生成各种语言的协议列表 - resolvePlaceholder("protocol-list", "protocolList", builder, element, parserContext); + resolvePlaceholder("code-languages", "codeLanguages", builder, element, parserContext); resolvePlaceholder("protocol-path", "protocolPath", builder, element, parserContext); diff --git a/net/src/main/resources/net-1.0.xsd b/net/src/main/resources/net-1.0.xsd index 578c0951..efc15536 100644 --- a/net/src/main/resources/net-1.0.xsd +++ b/net/src/main/resources/net-1.0.xsd @@ -66,7 +66,7 @@ - + diff --git a/orm/pom.xml b/orm/pom.xml index 47f7732b..c030c29c 100644 --- a/orm/pom.xml +++ b/orm/pom.xml @@ -36,7 +36,6 @@ 4.1.84.Final 2.4.17 5.3.0 - 0.10.2 5.3.0 diff --git a/protocol/pom.xml b/protocol/pom.xml index 908cec8d..36816536 100644 --- a/protocol/pom.xml +++ b/protocol/pom.xml @@ -36,7 +36,6 @@ 4.1.84.Final 2.4.17 5.3.0 - 0.10.2 5.3.0 @@ -157,12 +156,6 @@ provided - - org.reflections - reflections - ${reflections.version} - - junit junit 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 3b62ee42..592e039d 100644 --- a/protocol/src/main/java/com/zfoo/protocol/registration/ProtocolAnalysis.java +++ b/protocol/src/main/java/com/zfoo/protocol/registration/ProtocolAnalysis.java @@ -42,7 +42,6 @@ import com.zfoo.protocol.util.StringUtils; import com.zfoo.protocol.xml.XmlProtocols; import javassist.CannotCompileException; import javassist.NotFoundException; -import org.reflections.Reflections; import java.io.IOException; import java.lang.reflect.*; @@ -73,6 +72,9 @@ public class ProtocolAnalysis { // 临时变量,启动完成就会销毁,是一个基本类型序列化器 private static Map, ISerializer> baseSerializerMap = new HashMap<>(128); + //临时变量,存储xml配置协议id,启动完成销毁 + private static Map protocolNameMap = new HashMap<>(MAX_PROTOCOL_NUM); + static { // 初始化基础类型序列化器 baseSerializerMap.put(boolean.class, BooleanSerializer.INSTANCE); @@ -99,193 +101,201 @@ public class ProtocolAnalysis { */ public static synchronized void analyze(Set> protocolClassSet, GenerateOperation generateOperation) { AssertionUtils.notNull(subProtocolIdMap, "[{}]已经初始完成,请不要重复初始化", ProtocolManager.class.getSimpleName()); - try { - // 检查协议类是否合法 - for (var protocolClass : protocolClassSet) { - var protocolId = getProtocolIdAndCheckClass(protocolClass); - AssertionUtils.isTrue(protocolId >= 0, "[class:{}]必须使用注解@Protocol注解标注或者使用[{}]字段", protocolClass.getCanonicalName(), PROTOCOL_ID); - initProtocolClass(protocolId, protocolClass); - } - - // 协议id和协议信息对应起来 - for (var protocolClass : protocolClassSet) { - var registration = parseProtocolRegistration(protocolClass, ProtocolModule.DEFAULT_PROTOCOL_MODULE); - protocols[registration.protocolId()] = registration; - } - - // 通过指定类注册的协议,全部使用字节码增强 - var enhanceList = Arrays.stream(protocols).filter(Objects::nonNull).collect(Collectors.toList()); - enhance(generateOperation, enhanceList); - } catch (Exception e) { - throw new RuntimeException(e); + // 检查协议类是否合法 + for (var protocolClass : protocolClassSet) { + var protocolId = getProtocolIdAndCheckClass(protocolClass); + AssertionUtils.isTrue(protocolId >= 0, "[class:{}]必须使用注解@Protocol注解标注或者使用[{}]字段", protocolClass.getCanonicalName(), PROTOCOL_ID); + initProtocolClass(protocolId, protocolClass); } + + // 协议id和协议信息对应起来 + for (var protocolClass : protocolClassSet) { + var registration = parseProtocolRegistration(protocolClass, ProtocolModule.DEFAULT_PROTOCOL_MODULE); + protocols[registration.protocolId()] = registration; + } + + // 通过指定类注册的协议,全部使用字节码增强 + var enhanceList = Arrays.stream(protocols).filter(Objects::nonNull).collect(Collectors.toList()); + enhance(generateOperation, enhanceList); } public static synchronized void analyzeAuto(Set> protocolClassSet, GenerateOperation generateOperation) { AssertionUtils.notNull(subProtocolIdMap, "[{}]已经初始完成,请不要重复初始化", ProtocolManager.class.getSimpleName()); - try { - // 获取所有协议类 - var relevantClassSet = new HashSet<>(protocolClassSet); - for (var clazz : protocolClassSet) { - relevantClassSet.addAll(ClassUtils.relevantClass(clazz)); - } - - var relevantClassList = relevantClassSet.stream() - .sorted((a, b) -> a.getCanonicalName().compareTo(b.getCanonicalName())) - .collect(Collectors.toList()); - - // 检查协议类是否合法 - var noProtocolIds = new ArrayList>(); - for (var protocolClass : relevantClassList) { - var protocolId = getProtocolIdAndCheckClass(protocolClass); - if (protocolId >= 0) { - initProtocolClass(protocolId, protocolClass); - } else { - noProtocolIds.add(protocolClass); - } - } - var countProtocolId = (short) 0; - for (var protocolClass : noProtocolIds) { - while (protocolClassMap.containsKey(countProtocolId)) { - countProtocolId++; - } - initProtocolClass(countProtocolId, protocolClass); - } - - // 协议id和协议信息对应起来 - for (var protocolClass : relevantClassSet) { - var registration = parseProtocolRegistration(protocolClass, ProtocolModule.DEFAULT_PROTOCOL_MODULE); - protocols[registration.protocolId()] = registration; - } - - // 通过指定类注册的协议,全部使用字节码增强 - var enhanceList = Arrays.stream(protocols).filter(Objects::nonNull).collect(Collectors.toList()); - enhance(generateOperation, enhanceList); - } catch (Exception e) { - throw new RuntimeException(e); + // 获取所有协议类 + var relevantClassSet = new HashSet<>(protocolClassSet); + for (var clazz : protocolClassSet) { + relevantClassSet.addAll(ClassUtils.relevantClass(clazz)); } + + var relevantClassList = relevantClassSet.stream() + .sorted((a, b) -> a.getCanonicalName().compareTo(b.getCanonicalName())) + .collect(Collectors.toList()); + + // 检查协议类是否合法 + var noProtocolIds = new ArrayList>(); + for (var protocolClass : relevantClassList) { + var protocolId = getProtocolIdAndCheckClass(protocolClass); + if (protocolId >= 0) { + initProtocolClass(protocolId, protocolClass); + } else { + noProtocolIds.add(protocolClass); + } + } + var countProtocolId = (short) 0; + for (var protocolClass : noProtocolIds) { + while (protocolClassMap.containsKey(countProtocolId)) { + countProtocolId++; + } + initProtocolClass(countProtocolId, protocolClass); + } + + // 协议id和协议信息对应起来 + for (var protocolClass : relevantClassSet) { + var registration = parseProtocolRegistration(protocolClass, ProtocolModule.DEFAULT_PROTOCOL_MODULE); + protocols[registration.protocolId()] = registration; + } + + // 通过指定类注册的协议,全部使用字节码增强 + var enhanceList = Arrays.stream(protocols).filter(Objects::nonNull).collect(Collectors.toList()); + enhance(generateOperation, enhanceList); } public static synchronized void analyze(XmlProtocols xmlProtocols, GenerateOperation generateOperation) { - if (xmlProtocols.isPackages()) { - analyzePackage(xmlProtocols, generateOperation); - return; - } AssertionUtils.notNull(subProtocolIdMap, "[{}]已经初始完成,请不要重复初始化", ProtocolManager.class.getSimpleName()); - try { - var enhanceList = new ArrayList(); - for (var moduleDefinition : xmlProtocols.getModules()) { - var module = new ProtocolModule(moduleDefinition.getId(), moduleDefinition.getName()); + var protocolDefinitionMap = new HashMap(); + for (var moduleDefinition : xmlProtocols.getModules()) { + var module = new ProtocolModule(moduleDefinition.getId(), moduleDefinition.getName()); + AssertionUtils.isTrue(module.getId() > 0, "[module:{}] [id:{}] 模块必须大于等于1", module.getName(), module.getId()); + AssertionUtils.isNull(modules[module.getId()], "duplicate [module:{}] [id:{}] Exception!", module.getName(), module.getId()); - AssertionUtils.isTrue(module.getId() > 0, "[module:{}] [id:{}] 模块必须大于等于1", module.getName(), module.getId()); - AssertionUtils.isNull(modules[module.getId()], "duplicate [module:{}] [id:{}] Exception!", module.getName(), module.getId()); - AssertionUtils.notNull(moduleDefinition.getProtocols(), "[module:{}] does not have any protocols", module.getName()); - - modules[module.getId()] = module; - - for (var protocolDefinition : moduleDefinition.getProtocols()) { - var location = protocolDefinition.getLocation(); - var clazz = Class.forName(location); - var protocolId = protocolDefinition.getId(); - - // 如果xml文件中没有填protocolId则只需要获取到protocolId即可 - if (protocolId < 0) { - protocolId = getProtocolIdAndCheckClass(clazz); - AssertionUtils.isTrue(protocolId >= 0, "[class:{}]在使用xml方式注册协议,如果xml没有提供协议号,则需要使用注解或者协议字段标注协议号", clazz.getCanonicalName()); - } else { - var id = getProtocolIdAndCheckClass(clazz); - // 使用xml方式注册协议可以,协议class不需要使用注解或者字段标注协议号 - if (id >= 0) { - AssertionUtils.isTrue(protocolId == id, "[class:{}]协议序列号[{}]和协议文件里的协议序列号不相等", clazz.getCanonicalName(), PROTOCOL_ID); - } - } - AssertionUtils.isTrue(protocolId >= moduleDefinition.getMinId(), "模块[{}]中的协议[{}]的协议号必须大于或者等于[{}]", moduleDefinition.getName(), clazz.getSimpleName(), moduleDefinition.getMinId()); - AssertionUtils.isTrue(protocolId < moduleDefinition.getMaxId(), "模块[{}]中的协议[{}]的协议号必须小于[{}]", moduleDefinition.getName(), clazz.getSimpleName(), moduleDefinition.getMaxId()); - initProtocolClass(protocolId, clazz); - } + modules[module.getId()] = module; + if (CollectionUtils.isEmpty(moduleDefinition.getProtocols())) { + continue; + } + for (var protocolDefinition : moduleDefinition.getProtocols()) { + protocolDefinitionMap.put(protocolDefinition.getLocation(), protocolDefinition.isEnhance()); + protocolNameMap.put(protocolDefinition.getLocation(), protocolDefinition.getId()); } - for (var moduleDefinition : xmlProtocols.getModules()) { - var module = modules[moduleDefinition.getId()]; - for (var protocolDefinition : moduleDefinition.getProtocols()) { - var location = protocolDefinition.getLocation(); - var clazz = Class.forName(location); - var protocolId = ProtocolManager.protocolId(clazz); - var registration = parseProtocolRegistration(clazz, module); - if (protocolDefinition.isEnhance()) { - enhanceList.add(registration); - } - // 注册协议 - protocols[protocolId] = registration; - } - } - enhance(generateOperation, enhanceList); - } catch (Exception e) { - throw new UnknownException(e); } + + // 获取所有IPack子类 + var packetClazzList = new HashSet>(); + if (xmlProtocols.isPackages()) { + packetClazzList.addAll(scanPackageList(protocolDefinitionMap.keySet())); + } else { + packetClazzList.addAll(scanClassList(protocolDefinitionMap.keySet())); + } + + for (Class clazz : packetClazzList) { + var protocolId = getProtocolIdAndCheckClass(clazz); + initProtocolClass(protocolId, clazz); + } + + var enhanceList = new ArrayList(); + for (var moduleDefinition : xmlProtocols.getModules()) { + var module = modules[moduleDefinition.getId()]; + for (Class clazz : packetClazzList) { + var protocolId = ProtocolManager.protocolId(clazz); + if (protocolId < moduleDefinition.getMinId() || protocolId >= moduleDefinition.getMaxId()) { + continue; + } + var registration = parseProtocolRegistration(clazz, module); + if (xmlProtocols.isPackages() && !clazz.isAnnotationPresent(NotEnhance.class)) { + enhanceList.add(registration); + } else if (!xmlProtocols.isPackages() && protocolDefinitionMap.getOrDefault(clazz.getName(), true)) { + enhanceList.add(registration); + } + // 注册协议 + protocols[protocolId] = registration; + } + } + enhance(generateOperation, enhanceList); } public static void analyzePackage(XmlProtocols xmlProtocols, GenerateOperation generateOperation) { AssertionUtils.notNull(subProtocolIdMap, "[{}]已经初始完成,请不要重复初始化", ProtocolManager.class.getSimpleName()); - try { - var packageList = new HashSet(); - for (var moduleDefinition : xmlProtocols.getModules()) { - var module = new ProtocolModule(moduleDefinition.getId(), moduleDefinition.getName()); + var packageList = new HashSet(); + for (var moduleDefinition : xmlProtocols.getModules()) { + var module = new ProtocolModule(moduleDefinition.getId(), moduleDefinition.getName()); - AssertionUtils.isTrue(module.getId() > 0, "[module:{}] [id:{}] 模块必须大于等于1", module.getName(), module.getId()); - AssertionUtils.isNull(modules[module.getId()], "duplicate [module:{}] [id:{}] Exception!", module.getName(), module.getId()); - AssertionUtils.notNull(moduleDefinition.getProtocols(), "[module:{}] does not have any protocols", module.getName()); - modules[module.getId()] = module; + AssertionUtils.isTrue(module.getId() > 0, "[module:{}] [id:{}] 模块必须大于等于1", module.getName(), module.getId()); + AssertionUtils.isNull(modules[module.getId()], "duplicate [module:{}] [id:{}] Exception!", module.getName(), module.getId()); + AssertionUtils.notNull(moduleDefinition.getProtocols(), "[module:{}] does not have any protocols", module.getName()); + modules[module.getId()] = module; - for (var protocolDefinition : moduleDefinition.getProtocols()) { - packageList.add(protocolDefinition.getLocation()); - } + for (var protocolDefinition : moduleDefinition.getProtocols()) { + packageList.add(protocolDefinition.getLocation()); } + } - // 获取所有IPack子类 - var packetClazzList = scanClassList(packageList); + // 获取所有IPack子类 + var packetClazzList = scanClassList(packageList); + for (Class clazz : packetClazzList) { + var protocolId = getProtocolIdAndCheckClass(clazz); + initProtocolClass(protocolId, clazz); + } + + var enhanceList = new ArrayList(); + for (var moduleDefinition : xmlProtocols.getModules()) { + var module = modules[moduleDefinition.getId()]; for (Class clazz : packetClazzList) { - var protocolId = getProtocolIdAndCheckClass(clazz); - initProtocolClass(protocolId, clazz); - } - - var enhanceList = new ArrayList(); - for (var moduleDefinition : xmlProtocols.getModules()) { - var module = modules[moduleDefinition.getId()]; - for (Class clazz : packetClazzList) { - var protocolId = ProtocolManager.protocolId(clazz); - if (protocolId < moduleDefinition.getMinId() || protocolId >= moduleDefinition.getMaxId()) { - continue; - } - var registration = parseProtocolRegistration(clazz, module); - if (!clazz.isAnnotationPresent(NotEnhance.class)) { - enhanceList.add(registration); - } - // 注册协议 - protocols[protocolId] = registration; + var protocolId = ProtocolManager.protocolId(clazz); + if (protocolId < moduleDefinition.getMinId() || protocolId >= moduleDefinition.getMaxId()) { + continue; } + var registration = parseProtocolRegistration(clazz, module); + if (!clazz.isAnnotationPresent(NotEnhance.class)) { + enhanceList.add(registration); + } + // 注册协议 + protocols[protocolId] = registration; } - enhance(generateOperation, enhanceList); + } + enhance(generateOperation, enhanceList); + } + + public static Set> scanPackageList(Set packageList) { + //获取该路径下所有类 + var clazzSet = new HashSet(); + for (var packageName : packageList) { + try { + var clazzList = ClassUtils.getAllClasses(packageName); + clazzSet.addAll(clazzList); + } catch (Exception e) { + throw new RunException("[{}]包扫描类异常", packageName, e); + } + } + return scanClassList(clazzSet); + } + + public static Set> scanClassList(Set classList) { + var clazzSet = new HashSet>(); + for (var className : classList) { + try { + Class clazz = Class.forName(className); + if (!IPacket.class.isAssignableFrom(clazz) || clazz.isInterface()) { + continue; + } + clazzSet.add(clazz); + } catch (Exception e) { + throw new RunException("[class:{}]类不存在", className); + } + } + return clazzSet; + } + + private static void enhance(GenerateOperation generateOperation, List enhanceList) { + try { + enhanceProtocolBefore(generateOperation); + enhanceProtocolRegistration(enhanceList); + enhanceProtocolAfter(generateOperation); } catch (Exception e) { throw new UnknownException(e); } } - public static Set> scanClassList(Set packageList) { - //获取该路径下所有类 - Reflections reflections = new Reflections(packageList); - //获取继承了IPacket的所有类 - Set> classSet = reflections.getSubTypesOf(IPacket.class); - return classSet.stream().filter(k -> !k.isInterface()).collect(Collectors.toSet()); - } - - private static void enhance(GenerateOperation generateOperation, List enhanceList) throws IOException, ClassNotFoundException, NotFoundException, CannotCompileException, NoSuchFieldException, InvocationTargetException, NoSuchMethodException, IllegalAccessException, InstantiationException { - enhanceProtocolBefore(generateOperation); - enhanceProtocolRegistration(enhanceList); - enhanceProtocolAfter(generateOperation); - } - private static void enhanceProtocolBefore(GenerateOperation generateOperation) throws IOException, ClassNotFoundException { // 检查协议格式 checkAllProtocolClass(); @@ -324,6 +334,7 @@ public class ProtocolAnalysis { subProtocolIdMap = null; protocolReserved = null; baseSerializerMap = null; + protocolNameMap = null; EnhanceUtils.clear(); @@ -635,6 +646,10 @@ public class ProtocolAnalysis { } } else { // 可能通过xml的方式注册协议,xml注册协议不需要注解和PROTOCOL_ID协议字段号 + Short id = protocolNameMap.get(clazz.getName()); + if (id != null) { + protocolId = id; + } } return protocolId; diff --git a/protocol/src/main/java/com/zfoo/protocol/util/ClassUtils.java b/protocol/src/main/java/com/zfoo/protocol/util/ClassUtils.java index 047b552e..87d8206f 100644 --- a/protocol/src/main/java/com/zfoo/protocol/util/ClassUtils.java +++ b/protocol/src/main/java/com/zfoo/protocol/util/ClassUtils.java @@ -20,10 +20,10 @@ import java.io.IOException; import java.io.InputStream; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.net.*; +import java.util.*; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; /** * @author godotg @@ -31,6 +31,274 @@ import java.util.Set; */ public abstract class ClassUtils { + public final static String CLASS_FILE_EXT = ".class"; + + public final static String FILE_PROTOCOL = "file"; + + public final static String FILE_URL_PREFIX = "file:"; + + public final static String JAR_PROTOCOL = "jar"; + + public final static String JAR_URL_SEPARATOR = "!/"; + + /** + * 扫描指定包下的class文件 + * + * @param packageName 包名称(xxx.xxx) + * @return 返回指定包下的class全称集合 + * @throws IOException 假如扫描失败,则抛出该异常 + */ + public static Set getAllClasses(String packageName) throws IOException { + Set classSet = new HashSet<>(); + String packagePath = packageName.replaceAll(StringUtils.PERIOD_REGEX, StringUtils.SLASH); + Enumeration resourceUrls = getDefaultClassLoader().getResources(packagePath); + while (resourceUrls.hasMoreElements()) { + URL packageUrl = resourceUrls.nextElement(); + // 如果是以文件的形式保存在服务器上 + if (isFileProtocol(packageUrl)) { + // file类型的扫描 + File file = getFile(packageUrl); + // 以文件的方式扫描整个包下的文件 并添加到集合中 + findClassesInPackageByFile(packageName, file, classSet); + } else if (isJarProtocol(packageUrl)) { + findClassesInJarFile(packageName, packageUrl, classSet); + } + } + return classSet; + } + + /** + * 扫描jar文件中的class + * + * @param packageName + * 包名称 + * @param packageUrl + * jar的url + * @param classSet + * class全路径集合 + * @throws IOException 假如解析出现io异常时,则抛出该异常 + */ + private static void findClassesInJarFile(String packageName, URL packageUrl, + Set classSet) throws IOException { + URLConnection con = packageUrl.openConnection(); + JarFile jarFile = null; + String jarFileUrl = ""; + boolean closeJarFile = true; + + if (con instanceof JarURLConnection) { + JarURLConnection jarCon = (JarURLConnection) con; + useCachesIfNecessary(jarCon); + jarFile = jarCon.getJarFile(); + jarFileUrl = jarCon.getJarFileURL().toExternalForm(); + closeJarFile = !jarCon.getUseCaches(); + } else { + //不是JarURLConnection->需要依赖于URL文件解析。 + //我们假设URL的格式为“jar:path!/entry”,只要遵循条目格式,协议就是任意的。 + //我们还将处理带和不带前导“file:”前缀的路径。 + String urlFile = packageUrl.getFile(); + try { + int separatorIndex = urlFile.indexOf(JAR_URL_SEPARATOR); + if (separatorIndex != -1) { + jarFileUrl = urlFile.substring(0, separatorIndex); + jarFile = getJarFile(jarFileUrl); + } else { + jarFile = new JarFile(urlFile); + jarFileUrl = urlFile; + } + closeJarFile = true; + } catch (Exception ex) { + throw new RunException(ex); + } + } + + if (jarFile == null) { + return; + } + try { + classSet.addAll(findByJarFile(packageName, jarFile)); + } finally { + if (closeJarFile) { + jarFile.close(); + } + } + } + + /** + * 获取指定jar文件中所有class名称(包名+类名称)格式为xx.xx.yy + * + * @param jarFile jar文件 + * @return class名称集合, 假如参数为null,返回大小为0的集合 + */ + public Set findByJarFile(JarFile jarFile) { + return findByJarFile(StringUtils.EMPTY, jarFile); + } + + /** + * 获取指定jar文件中所有class名称(包名+类名称) xx.xx.yy + * + * @param packageName 包名前缀xx.xx + * @param jarFile jar文件 + * @return class名称集合, 假如参数为null,返回大小为0的集合 + */ + public static Set findByJarFile(String packageName, JarFile jarFile) { + Set classSet = new HashSet<>(); + if (jarFile == null) { + return classSet; + } + String packageBasePath = packageName.replaceAll(StringUtils.PERIOD_REGEX, StringUtils.SLASH); + if (!"".equals(packageBasePath) && !packageBasePath.endsWith("/")) { + // 根条目路径必须以斜杠结束,以允许正确的匹配。匹配sunjre在这里不返回斜杠,但是beajrockit返回。 + packageBasePath = packageBasePath + StringUtils.SLASH; + } + for (Enumeration entries = jarFile.entries(); entries.hasMoreElements();) { + JarEntry entry = entries.nextElement(); + String entryPath = entry.getName(); + if (entryPath.startsWith(packageBasePath)) { + int index = entryPath.indexOf(CLASS_FILE_EXT); + String relativePath = entryPath.substring(0, index); + String className = relativePath.replaceAll(StringUtils.SLASH, StringUtils.PERIOD); + classSet.add(className); + } + } + return classSet; + } + + /** + * 将给定的jar文件URL解析为JarFile对象 + * + * @param jarFileUrl + */ + private static JarFile getJarFile(String jarFileUrl) throws IOException { + if (jarFileUrl.startsWith(FILE_URL_PREFIX)) { + try { + return new JarFile(toURI(jarFileUrl).getSchemeSpecificPart()); + } catch (Exception ex) { + return new JarFile(jarFileUrl.substring(FILE_URL_PREFIX.length())); + } + } else { + return new JarFile(jarFileUrl); + } + } + + /** + * 以文件的方式扫描整个包下的文件 并添加到集合中 + * + * @param packageName + * 包名称 + * @param dirOrFile + * 查找包对应的文件或文件夹 + * @param classSet + * class全路径集合 + */ + private static void findClassesInPackageByFile(String packageName, File dirOrFile, + Set classSet) { + // 如果不存在或者 也不是目录就直接返回 + if (!dirOrFile.exists()) { + return; + } + if (!dirOrFile.isDirectory()) { + return; + } + // 如果存在 就获取包下的所有文件 包括目录 + File[] dirFiles = dirOrFile.listFiles(); + if (dirFiles == null) { + return; + } + + // 循环所有文件 + for (File file : dirFiles) { + String name = file.getName(); + // 如果是目录 则继续扫描 + if (file.isDirectory()) { + findClassesInPackageByFile(packageName + "." + name, file, classSet); + } else { + String filename = file.getName(); + // 如果是java类文件 去掉后面的.class 只留下类名 + String className = filename.substring(0, filename.length() - CLASS_FILE_EXT.length()); + className = packageName + "." + className; + //去掉前缀“.” + if (className.startsWith(".")) { + className = className.substring(1); + } + classSet.add(className); + } + } + } + + public static File getFile(URL url) { + if (!FILE_PROTOCOL.equals(url.getProtocol())) { + throw new IllegalArgumentException("给定的URL无法解析为绝对文件路径: " + url); + } + try { + return new File(toURI(url).getSchemeSpecificPart()); + } catch (Exception ex) { + return new File(url.getFile()); + } + } + + /** + * 用给定的URL创建URI + * 用“%20”编码替换URI的空格。 + * @param url 要转换为URI实例的URL + * @return URI对象 + * @see java.net.URL#toURI() + */ + public static URI toURI(URL url) { + return toURI(url.toString()); + } + + /** + * 用给定的字符串创建URI + * 用“%20”编码替换URI的空格。 + * @param location 要转换为URI实例的字符串 + * @return URI对象 + */ + public static URI toURI(String location) { + try { + return new URI(location.replace(" ", "%20")); + } catch (URISyntaxException e) { + throw new RunException("uri配置错误"); + } + } + + /** + * 判断给定的URL是不是file协议 + * + * @param url url + * @return 假如是file协议,返回true,否则返回false + */ + public static boolean isFileProtocol(URL url){ + if (url == null) { + return false; + } + return FILE_PROTOCOL.equals(url.getProtocol()); + } + + /** + * 判断给定的URL是不是Jar协议 + * + * @param url url + * @return 假如是Jar协议,返回true,否则返回false + */ + public static boolean isJarProtocol(URL url){ + if (url == null) { + return false; + } + String protocol = url.getProtocol(); + return JAR_PROTOCOL.equals(protocol); + } + + /** + * 在给定的连接上设置“useCaches”标志,对于基于JNLP的资源,设置false,其他资源该标志保留原样 + * + * @param urlConnection urlConnection + */ + public static void useCachesIfNecessary(URLConnection urlConnection){ + if (urlConnection != null) { + urlConnection.setUseCaches(urlConnection.getClass().getSimpleName().startsWith("JNLP")); + } + } + /** * 从类路径中读取文件 * diff --git a/protocol/src/main/java/com/zfoo/protocol/util/StringUtils.java b/protocol/src/main/java/com/zfoo/protocol/util/StringUtils.java index 4e20e488..a9517d9d 100644 --- a/protocol/src/main/java/com/zfoo/protocol/util/StringUtils.java +++ b/protocol/src/main/java/com/zfoo/protocol/util/StringUtils.java @@ -16,6 +16,7 @@ import com.zfoo.protocol.collection.ArrayUtils; import java.nio.charset.Charset; import java.util.*; +import java.util.regex.Matcher; import java.util.regex.Pattern; /** @@ -485,21 +486,14 @@ public abstract class StringUtils { } /** - * 判断是否是数字 + * 判断是否是正数 * @param str * @return */ public static boolean isNumeric(String str) { - if(str == null) { - return false; - } - int sz = str.length(); - for(int i = 0; i < sz; i++) { - if (!Character.isDigit(str.charAt(i))) { - return false; - } - } - return true; + Pattern pattern = Pattern.compile("[0-9]*"); + Matcher isNum = pattern.matcher(str); + return isNum.matches(); } } diff --git a/scheduler/pom.xml b/scheduler/pom.xml index f8bc0cbb..a3394f10 100644 --- a/scheduler/pom.xml +++ b/scheduler/pom.xml @@ -36,7 +36,6 @@ 4.1.84.Final 2.4.17 5.3.0 - 0.10.2 5.3.0 diff --git a/scheduler/src/main/java/com/zfoo/scheduler/manager/SchedulerBus.java b/scheduler/src/main/java/com/zfoo/scheduler/manager/SchedulerBus.java index 4f8b707c..6f23656c 100644 --- a/scheduler/src/main/java/com/zfoo/scheduler/manager/SchedulerBus.java +++ b/scheduler/src/main/java/com/zfoo/scheduler/manager/SchedulerBus.java @@ -166,24 +166,18 @@ public abstract class SchedulerBus { /** * 不断执行的周期循环任务 */ - public static void scheduleAtFixedRate(Runnable runnable, long period, TimeUnit unit) { - if (SchedulerContext.isStop()) { - return; - } + public static ScheduledFuture scheduleAtFixedRate(Runnable runnable, long period, TimeUnit unit) { - executor.scheduleAtFixedRate(SafeRunnable.valueOf(runnable), 0, period, unit); + return executor.scheduleAtFixedRate(SafeRunnable.valueOf(runnable), 0, period, unit); } /** * 固定延迟执行的任务 */ - public static void schedule(Runnable runnable, long delay, TimeUnit unit) { - if (SchedulerContext.isStop()) { - return; - } + public static ScheduledFuture schedule(Runnable runnable, long delay, TimeUnit unit) { - executor.schedule(SafeRunnable.valueOf(runnable), delay, unit); + return executor.schedule(SafeRunnable.valueOf(runnable), delay, unit); } /** diff --git a/storage/pom.xml b/storage/pom.xml index 20a2b765..7d64a33c 100644 --- a/storage/pom.xml +++ b/storage/pom.xml @@ -36,7 +36,6 @@ 4.1.84.Final 2.4.17 5.3.0 - 0.10.2 5.3.0 diff --git a/util/pom.xml b/util/pom.xml index 58bae1e7..ab0815c7 100644 --- a/util/pom.xml +++ b/util/pom.xml @@ -36,7 +36,6 @@ 4.1.84.Final 2.4.17 5.3.0 - 0.10.2 5.3.0