如何在不访问类或类加载器的前提下读取JAR包内的跨模块资源?
解决方案
你已经通过getAllProviders()拿到了各个模块的服务实现实例,完全可以直接复用对应实例的类加载器加载同模块下的资源,不需要通过模块名查找类加载器,适配unnamed modules场景的实现逻辑如下:
步骤1:改造服务提供者接口,新增获取资源根路径的方法
给你的帮助页面服务Provider接口加一个方法,返回当前模块下帮助文件存放的根路径,示例:
public interface HelpProvider { // 保留原有其他方法 String getHelpResourceRoot(); }
每个模块的实现类返回自身模块内帮助文件的根目录即可,比如module1的实现就返回/path/to/,和你拿到的module1/path/to/help1a中的路径部分对应即可。
步骤2:用Provider实例的类加载器读取资源
拿到每个Provider实例后,直接用该实例的类加载器读取对应资源,示例代码:
List<InputStream> allHelpStreams = new ArrayList<>(); for (HelpProvider provider : getAllProviders()) { // 拼接你拿到的相对资源路径 String resourcePath = provider.getHelpResourceRoot() + "help1a.md"; // 用当前provider的类加载器读取同模块下的资源 InputStream is = provider.getClass().getResourceAsStream(resourcePath); if (is != null) { allHelpStreams.add(is); } }
注意事项
- 资源路径如果以
/开头,就是从该模块类路径的根目录开始匹配,没有前缀就是从当前Provider类的包路径开始匹配,按需调整即可 - unnamed modules下所有类加载器能访问的资源都是对调用方开放的,不需要配置模块导出/开放的相关指令,直接读取即可
- 该方案和你原有动态新增模块的逻辑完全兼容,新增模块只要实现了HelpProvider接口,自动就能被扫描到,资源也能正常读取,不管是在IDE运行还是打包成JAR运行都生效
内容的提问来源于stack exchange,提问作者aldebaran star
相关产品推荐
相关产品推荐

