【问题标题】:Not able to read file from jar in tomcat无法从tomcat中的jar读取文件
【发布时间】:2013-01-28 09:38:37
【问题描述】:

我有一个在 tomcat 7 下运行的 Web 应用程序,并且在其中一个类中,我试图读取 WEB-INF/lib 文件夹下的一个 jar 中的文件。

URL resourceURL = MyClass.class.getClassLoader().getResource("xml/xslt/master.xsl");
File xslfile = new File(resourceURL.getPath());
AssertUtil.assertTrue(xslfile.exists(),"xsl file not found");

MyClass 和 master.xsl 都在同一个 jar 中,打包没有问题。但是上面的 sn-p 在断言语句中失败,因为xslfile.exists 返回 false。 URL 正确解析为 jar 中文件的位置,如下所示

file:/<MY_WEBAPP_LOCATION>/MyApp/WEB-INF/lib/MyComponent.jar!/xml/xslt/master.xsl

其中 MY_WEBAPP_LOCATION 对应于我的 tomcat 服务器 webapp 目录的绝对路径。

但是如果我重写下面的代码以读取为输入流,它就可以正常工作。

InputStream xslFile = MyClass.class.getClassLoader().getResourceAsStream("xml/xslt/master.xsl");

任何人都可以解释是什么阻止了从 jar 资源创建文件,而输入流创建工作正常。是否需要从 tomcat 端进行任何其他权限设置才能读取 jar 内的文件?

编辑:再观察一下,如果文件放在 WEB-INF/classes 下,则使用上述代码创建文件可以正常工作。问题仅在于将其放置在 WEB-INF/lib 下的 jar 中

【问题讨论】:

  • 能否请您澄清一下master.xsl文件是否在MyClass的同一目录结构中?如果 getResource(...) 路径不以“/”开头,那么它只会将 MyClass 文件包路径附加到您提到的 xls 路径中。
  • 在上面的代码中,如果我添加一个前导斜杠 MyClass.class.getClassLoader().getResource("/xml/xslt/master.xsl"),它会返回一个空 URL 对象

标签: java file-io classloader tomcat7


【解决方案1】:

小心 ClassLoader.getResource 似乎不处理相对路径。 见this

GetResourceAsStream 恰好采用相对于 ClassLoader(而不是类!!)的路径。我认为你很幸运,这里有同样的东西。

【讨论】:

  • 如果我将其更改为 MyClass.class.getResource("/xml/xslt/master.xsl"),(唯一的更改是添加前导斜杠以表示绝对路径),我得到相同的上面提到的 URL,仍然无法读取文件。毕竟它返回的 URL 位置绝对没问题
【解决方案2】:

如果是桌面应用程序 getResource() 将起作用 但由于这是一个 Web 应用程序,因此需要从 Context 中提取资源,因此 getResoruceAsStream()

【讨论】:

  • 这是否意味着我永远无法将其作为文件读取?如果您看到问题中提到的 URL(由 resourceURL.getPath 返回),则它是 jar 中资源的有效位置。所以java应该能够从该位置创建一个文件
【解决方案3】:

不是权限问题,而是java.io.File API的使用——特别是构造函数http://docs.oracle.com/javase/7/docs/api/java/io/File.html#File%28java.lang.String%29

当你使用构建 File 对象时

File xslfile = new File(resourceURL.getPath());

您正在使用需要“抽象路径名”的 java.io.File#File(String) 方法。 File 类的 javadoc 描述了什么是可接受/有效的路径名:http://docs.oracle.com/javase/7/docs/api/java/io/File.html

您从 getPath() 方法获得的字符串值:

file:/<MY_WEBAPP_LOCATION>/MyApp/WEB-INF/lib/MyComponent.jar!/xml/xslt/master.xsl

根本不构成有效的“抽象路径名”——它是一个转换为 java.lang.String 的 URL(恕我直言,应该返回 URL 方案为“jar”而不是“file”)。因此调用

isExist() 

返回 false,因为您的磁盘上没有具有该名称的文件。 另一方面,如果资源在 jar 之外(例如,在 WEB-INF/classes 目录下),resourceURL.getPath() 将返回一个表示有效抽象路径名的值,因为相关资源确实是一个简单文件。

当您使用 java.lang.ClassLoader#getResourceAsStream(java.lang.String) 时,该方法将资源直接流出到 java.lang.InputStream 中,甚至可能在其实现中不使用 File 类。

【讨论】:

    猜你喜欢
    • 2013-02-20
    • 2014-06-07
    • 2017-11-08
    • 2021-03-05
    • 2017-10-07
    • 2014-01-15
    • 2012-05-06
    • 2012-10-26
    • 1970-01-01
    相关资源
    最近更新 更多