跳至主要內容

热部署功能设计

HeChuangJun约 396 字大约 1 分钟

Hot Deployment:涉及到类的加载和卸载机制,在不重启应用情况下动态替换或更新组件

用文件监控机制(如NIO的WatchService)监控类文件的变更。触发热部署
class FileWatcher {
    public static void watchDirectoryPath(Path path) {
        //检查路径是否是文件夹
        try {
            Boolean isFolder = (Boolean) Files.getAttribute
            (path, "basic:isDirectory", LinkOption.NOFOLLOW_LINKS);
            if (!isFolder) {
                throw new IllegalArgumentException("Path: " + path + " is not a folder");
            }
        } catch (IOException ioe) {
            ioe.printStackTrace();
        }

        System.out.println("Watching path: " + path);

        //获得文件系统的WatchService对象
        FileSystem fs = path.getFileSystem();

        try (WatchService service = fs.newWatchService()) {
            // 注册路径到监听服务
            // 监听目录内文件的创建、修改、删除事件
            path.register(service, ENTRY_CREATE, ENTRY_MODIFY, ENTRY_DELETE);

            // 开始无限循环,等待事件发生
            WatchKey key = null;
            while (true) {
                key = service.take(); // 阻塞直到有事件发生

                for (WatchEvent<?> watchEvent : key.pollEvents()) {
                    WatchEvent.Kind<?> kind = watchEvent.kind();

                    // 获取文件路径
                    @SuppressWarnings("unchecked")
                    WatchEvent<Path> ev = (WatchEvent<Path>) watchEvent;
                    Path fileName = ev.context();

                    System.out.println(kind.name() + ": " + fileName);
                }

                // 重置watchKey
                boolean valid = key.reset();
                // 如果watchKey无效退出循环
                if (!valid) {
                    break;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public static void main(String[] args) {
        //监控当前目录
        Path pathToWatch = Paths.get(".");
        watchDirectoryPath(pathToWatch);
    }
}
自定义类加载器继承java.lang.ClassLoader,重写findClass()方法,实现类加载
public class HotSwapClassLoader extends ClassLoader {
    public HotSwapClassLoader() { super(ClassLoader.getSystemClassLoader());}

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        // 加载指定路径下的类文件字节码
        byte[] classBytes = loadClassData(name);
        if (classBytes == null) {
            throw new ClassNotFoundException(name);
        }
        // 调用defineClass将字节码转换为Class对象
        return defineClass(name, classBytes, 0, classBytes.length);
    }

    private byte[] loadClassData(String name) {
        // 实现从文件系统或其他来源加载类文件的字节码
        return null;
    }
}