Jetty 和 Tomcat 之间的 getResource 差异会产生文件未找到异常



我使用以下代码来查找Freemarker从HTML创建PDF所需的资源。

public static URL lookupResource(String resource) {
    System.out.println("Looking up resource: " + resource);
    ClassLoader classLoader =  Thread.currentThread().getContextClassLoader();      
    URL templateFileUrl = classLoader.getResource(resource);        
    System.out.println("path: " + templateFileUrl.getPath());   
    return templateFileUrl;
}

在 Eclipse Maven 项目中的 Jetty 上运行,我得到以下结果:

Looking up resource: abc.html
path: /C:/Projects/WebDocs/EclipseProjects/webdocs2/webdocs/target/classes/abc.xhtml

这是资源所在并且工作正常的地方。

当我将战争文件导出到雄猫时,资源被放入/C:/Program%20Files/Apache%20Software%20Foundation/Tomcat%207.0/webapps/webdocs

在Tomcat上运行,我得到以下内容:

Looking up resource: abc.html
path: /C:/Program%20Files/Apache%20Software%20Foundation/Tomcat%207.0/webapps/webdocs/WEB-INF/classes/abc.xhtml

这不是资源所在的地方,并导致找不到文件异常。

我做错了什么?

理想情况下,您应该:

  • 使用 ServletContext.getResource("/abc.html") 从 Web 应用程序中访问内容。
  • 不使用/WEB-INF/classes/来存储静态资源。 使用/WEB-INF/resources/

由于 Web 应用容器可以移动内容以满足自己的需求。

(有关详细信息,请参阅 Javadoc on javax.servlet.ServletContext.getResource(String path)

此外,实用程序类不应依赖于 Thread.currentThread().getContextClassLoader() 。 相反,请使用从请求资源的类获取的类装入器。

public class MyClass {
  public void doIt() {
    URL url = Utils.getResource(this,"abc.html");
  }
}
public final class Utils {
  public static URL getResource(Object obj, String resource) {
    return obj.getClass().getClassLoader().getResource(resource);
  }
}

如果您想将模板(或任何其他资源)存储为 jar 的一部分,我会查看代码以改用 InputStreams。要获取模板,请使用this.getClass().getClassLoader().getResourceAsStream()(甚至更好,this.getClass().getResourceAsStream()和组织包结构中的资源)。之后,使用构造器Template(InputStream stream)来构造模板。这样,即使在 jar/war 没有"爆炸"成物理文件的情况下,您的代码也可以工作。

要使用 this.getClass().getResourceAsStream() ,当编译到 jar 中时,您的资源必须与类文件位于同一目录中。如果使用 maven,请将资源放在"resources/path/to/yourpackage/resource.file"中。注意:更安全的方法是在此解决方案中使用类名本身,例如 MyClass.getResourceAsStream(),因为 this.getClass() 通常不适用于子类化或自动代理方案。

最新更新