我使用以下代码来查找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() 通常不适用于子类化或自动代理方案。