java扫描包及其包下的子类方法,适配了win和linux环境

package cn.zflzqy.mysqldatatoes.util;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.elasticsearch.annotations.Document;

import java.io.File;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.net.JarURLConnection;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

/**
 * @Author: zfl
 * @Date: 2023-05-10-16:29
 * @Description: 包扫描器
 */
public class PackageScan {
    private static final Logger log = LoggerFactory.getLogger(PackageScan.class);
    // 索引数据
    private static final Map<String,Class> INDEXS = new HashMap();

    public static Map<String, Class> getIndexs() {
        return INDEXS;
    }

    /**
     * 扫描实体包并检查是否存在租户id
     * @param packageName:包名
     */
    public static void scanEntities(String packageName) {
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        String packagePath = packageName.replace('.', '/');
        String packageResource = packagePath + "/";
        // 获取包路径
        Enumeration<URL> resources = null;
        try {
            resources = classLoader.getResources(packageResource);
        } catch (IOException e) {
            log.error("IO 异常:", e);
        }
        while (resources.hasMoreElements()) {
            URL resource = resources.nextElement();
            scanEntitiesInDirectory(packageName, resource);
        }

        log.info("扫描的索引信息:{}",INDEXS.toString());
    }


    /**
     * 扫描包下的实体
     * @param packageName:包名
     * @param directoryURL:文件路径
     */
    private static void scanEntitiesInDirectory(String packageName, URL  directoryURL) {
        try {
            URI uri = directoryURL.toURI();
            if (uri.getScheme().equals("file")) {
                File directory = new File(uri);
                scanEntitiesInDirectory(packageName, directory);
            } else if (uri.getScheme().equals("jar")) {
                JarURLConnection jarURLConnection = (JarURLConnection) directoryURL.openConnection();
                try (JarFile jarFile = jarURLConnection.getJarFile()) {
                    Enumeration<JarEntry> entries = jarFile.entries();
                    while (entries.hasMoreElements()) {
                        JarEntry entry = entries.nextElement();
                        String entryName = entry.getName();
                        if (entryName.startsWith(packageName.replace('.', '/')) && entryName.endsWith(".class")) {
                            String className = entryName.replace('/', '.').substring(0, entryName.length() - 6);
                            try {
                                Class<?> clazz = Class.forName(className);
                                if (isEntityClass(clazz)) {
                                    INDEXS.put(getIndexName(clazz),clazz);
                                }
                            } catch (ClassNotFoundException e) {
                                log.error("类未找到异常", e);
                            }
                        }
                    }
                }
            }
        } catch (IOException | URISyntaxException e) {
            log.error("IO 异常", e);
        }
    }

    /**
     * 扫描包下的实体
     * @param packageName:包名
     * @param directory:文件路径
     */
    private static void scanEntitiesInDirectory(String packageName, File directory) {
        File[] files = directory.listFiles();
        if (files != null) {
            for (File file : files) {
                if (file.isDirectory()) {
                    String subPackageName = packageName + "." + file.getName();
                    scanEntitiesInDirectory(subPackageName, new File(file.getPath()));
                } else if (file.getName().endsWith(".class")) {
                    String className = packageName + "." + file.getName().substring(0, file.getName().length() - 6);
                    try {
                        Class<?> clazz = Class.forName(className);
                        if (isEntityClass(clazz)) {
                            INDEXS.put(getIndexName(clazz),clazz);
                        }
                    } catch (ClassNotFoundException e) {
                        log.error("类未找到异常", e);
                    }
                }
            }
        }
    }

    /**
     * 检查是否为符合条件的实体类
     * @param clazz
     * @return
     */
    private static boolean isEntityClass(Class<?> clazz) {
        // 判断是否带有@Document注解
        boolean annotationPresent = clazz.isAnnotationPresent(Document.class);

        if (annotationPresent){
            Class aClass = INDEXS.get(getIndexName(clazz));
            if (aClass == null){
                return  true;
            }
            // 如果已有的数据是当前类的父类,则返回false
            if (aClass.isAssignableFrom(clazz)){
                return  false;
            };
            return true;
        }
        return false;
    }

    /**
     * 获取索引名
     * @param clazz
     * @return
     */
    private static String getIndexName(Class<?> clazz) {
        Annotation annotation = clazz.getAnnotation(Document.class);
        if (annotation instanceof Document) {
            return ((Document) annotation).indexName();
        }
        return null;
    }
}