You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

UAT环境Freemarker目录路径不可读,本地正常部署后报错如何解决

Freemarker模板加载UAT环境报错解决方案

错误信息

| ERROR | PrintServlet       | /templates does not exist.
java.io.FileNotFoundException: /templates does not exist.
        at freemarker.cache.FileTemplateLoader$1.run(FileTemplateLoader.java:128)
        at java.security.AccessController.doPrivileged(Native Method)
        at freemarker.cache.FileTemplateLoader.<init>(FileTemplateLoader.java:125)
        at freemarker.cache.FileTemplateLoader.<init>(FileTemplateLoader.java:101)
        at freemarker.template.Configuration.setDirectoryForTemplateLoading(Configuration.java:1171)
        at com.abg.wizardgui.servlet.PrintServlet.processRequest(PrintServlet.java:256)
        at com.abg.wizardgui.servlet.PrintServlet.doPost(PrintServlet.java:420)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:707)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
        at weblogic.servlet.internal.StubSecurityHelper$ServletServiceAction.run(StubSecurityHelper.java:286)
        at weblogic.servlet.internal.StubSecurityHelper$ServletServiceAction.run(StubSecurityHelper.java:260)
        at weblogic.servlet.internal.StubSecurityHelper.invokeServlet(StubSecurityHelper.java:137)
        at weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:350)
        at weblogic.servlet.internal.TailFilter.doFilter(TailFilter.java:25)
        at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:78)
        at com.abg.wizardgui.filter.JsessionIdRemoverFilter.doFilter(JsessionIdRemoverFilter.java:88)
        at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:78)
        at weblogic.servlet.internal.RequestEventsFilter.doFilter(RequestEventsFilter.java:32)
        at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:78)
        at weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.wrapRun(WebAppServletContext.java:3706)
        at weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.run(WebAppServletContext.java:3672)
        at weblogic.security.acl.internal.AuthenticatedSubject.doAs(AuthenticatedSubject.java:328)
        at weblogic.security.service.SecurityManager.runAsForUserCode(SecurityManager.java:197)
        at weblogic.servlet.provider.WlsSecurityProvider.runAsForUserCode(WlsSecurityProvider.java:203)
        at weblogic.servlet.provider.WlsSubjectHandle.run(WlsSubjectHandle.java:71)
        at weblogic.servlet.internal.WebAppServletContext.doSecuredExecute(WebAppServletContext.java:2443)
        at weblogic.servlet.internal.WebAppServletContext.securedExecute(WebAppServletContext.java:2291)
        at weblogic.servlet.internal.WebAppServletContext.execute(WebAppServletContext.java:2269)
        at weblogic.servlet.internal.ServletRequestImpl.runInternal(ServletRequestImpl.java:1705)
        at weblogic.servlet.internal.ServletRequestImpl.run(ServletRequestImpl.java:1665)
        at weblogic.servlet.provider.ContainerSupportProviderImpl$WlsRequestExecutor.run(ContainerSupportProviderImpl.java:272)
        at weblogic.invocation.ComponentInvocationContextManager._runAs(ComponentInvocationContextManager.java:352)
        at weblogic.invocation.ComponentInvocationContextManager.runAs(ComponentInvocationContextManager.java:337)
        at weblogic.work.LivePartitionUtility.doRunWorkUnderContext(LivePartitionUtility.java:57)
        at weblogic.work.PartitionUtility.runWorkUnderContext(PartitionUtility.java:41)
        at weblogic.work.SelfTuningWorkManagerImpl.runWorkUnderContext(SelfTuningWorkManagerImpl.java:652)
        at weblogic.work.ExecuteThread.execute(ExecuteThread.java:420)
        at weblogic.work.ExecuteThread.run(ExecuteThread.java:360)

问题代码

cfg.setDirectoryForTemplateLoading(new File("/templates/"));
Template template = cfg.getTemplate("template.ftl");

根因分析

你使用了操作系统根目录绝对路径/templates加载模板,本地运行时巧合存在该路径所以运行正常,UAT服务器系统根目录不存在该目录,因此抛出文件不存在异常。你的模板存放在项目src/templates目录下,属于项目内部类路径资源,不应该使用文件系统绝对路径加载。
如果之前使用setClassForTemplateLoading仍报错,90%以上的概率是模板没有被正确打包到类路径,或者填写的路径和实际编译后路径不匹配。

修复步骤

1. 调整模板加载方式

优先使用类路径加载,适配容器环境,正确写法如下:

// 第二个参数为类路径下模板所在的目录路径,确认编译后templates在类路径根目录就填"/templates/"
cfg.setClassForTemplateLoading(this.getClass(), "/templates/");
Template template = cfg.getTemplate("template.ftl");

如果是Weblogic等类加载隔离严格的Servlet容器,也可以用Servlet上下文获取真实路径加载:

String templatePath = getServletContext().getRealPath("/WEB-INF/classes/templates/");
cfg.setDirectoryForTemplateLoading(new File(templatePath));

2. 确认模板被正确打包

检查构建配置(Maven/Gradle),确保src/templates下的ftl文件会被复制到编译后的类路径中,Maven项目参考配置:

<build>
    <resources>
        <!-- 保留原有资源配置,新增templates目录的资源规则 -->
        <resource>
            <directory>src/templates</directory>
            <includes>
                <include>**/*.ftl</include>
            </includes>
        </resource>
    </resources>
</build>

打包后解压war包,确认WEB-INF/classes/templates/template.ftl文件存在。

3. 适配Weblogic类加载规则

如果还是报错,可在WEB-INF/weblogic.xml中添加优先加载项目内部类的配置,避免容器自带的Freemarker包冲突:

<container-descriptor>
    <prefer-web-inf-classes>true</prefer-web-inf-classes>
</container-descriptor>

内容的提问来源于stack exchange,提问作者newbie

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 18:51:03