问题背景
将p1整合到p0平台时候,freemarker读取jar包中模板文件失败,报错信息:freemarker.template.TemplateNotFoundException: Template not found for name "
原因排查
在p0测试服务器可复测,但在p1中未出现此问题;怀疑是安装问题导致,由于p1跟p0分别安装在服务器不同路径下, 可能跟文件路径权限有关,所以将p0安装路径改为跟p1一致,重装后测试,发现问题仍然存在,故排除安装路径问题;因为涉及模块为brick1模块,读取jar包时候路径报错,怀疑跟文件权限有关,将brick1模块jar包权限修改,重启后发现问题依然存在,故排查安装文件用户权限问题; 因为考虑到p1跟p0中业务代码一致,freemarker配置也
一致,由于p0中有其他模块也使用了freemarker,猜测可能是有更高优先级的配置,故在本地打不同产品(p0/p1)生产模式下的war包,经测试,都存在此问题,故排除其他模块配置的影响;排除影响因素外,打断点调试,在Configuration.getTempalte()方法中抛出的报错信息。从Freemarker.render()方法入手,发现初始化时候在Configuration中获取到的Template为空,继续追,发现在cache.getTemplate()时候获取到的Template为空,然后在TemplateCache 初始化时候断点测试,最终发现p0平台代码最后在FreemarkerViewMaker.make()时候,追溯发现Freemarker.initFreeMarkerConfigurer()时候加载器为FileTemplateLoader:
protected void initFreeMarkerConfigurer() throws IOException, TemplateException {
String path = freemarkerDirectiveFactory.getFreemarker();
File file = Files.findFile(path);
if (!Lang.isEmpty(file)) {
Properties p = new Properties();
p.load(Streams.fileIn(file));
configuration.setSettings(p);
}
File f = Files.findFile(prefix);
configuration.setDirectoryForTemplateLoading(f);
}
public void setDirectoryForTemplateLoading(File dir) throws IOException {
TemplateLoader tl = getTemplateLoader();
if (tl instanceof FileTemplateLoader) {
String path = ((FileTemplateLoader) tl).baseDir.getCanonicalPath();
if (path.equals(dir.getCanonicalPath()))
return;
}
setTemplateLoader(new FileTemplateLoader(dir));
}
而在读取jar包路径文件时候,应该用ClassTemplateLoader,查看p1平台代码发现,Freemarker.initFreeMarkerConfigurer()时候为MultiTemplateLoader,支持类路径加载器:
protected void initFreeMarkerConfigurer() throws IOException, TemplateException {
Properties p = new Properties();
String path = this.freemarkerDirectiveFactory.getFreemarker();
File file = Files.findFile(path);
if (Lang.isEmpty(file)) {
p.load(Streams.wrap(this.pro.toString().getBytes()));
} else {
p.load(Streams.fileIn(file));
}
this.configuration.setSettings(p);
File f = Files.findFile(this.prefix);
FileTemplateLoader ftl = new FileTemplateLoader(f);
ClassTemplateLoader ctl = new ClassTemplateLoader(this.getClass().getClassLoader(), "/META-INF/resources/WEB-INF");
MultiTemplateLoader mtl = new MultiTemplateLoader(new TemplateLoader[]{ftl, ctl});
this.configuration.setTemplateLoader(mtl);
}
比对图如下:

到此,比对发现,nutz框架集成的freemarker组件版本不一致(nutz-plugins-views-1.r.62 & nutz-plugins-views-1.r.60.r4),升级后加载器问题导致模板加载失败。
解决方案
将freemarker模板文件放在WEB-INF路径下,直接读取配置路径加载。

4120

被折叠的 条评论
为什么被折叠?



