Freemarker 目录路径在 UAT 中不可读

Posted

技术标签:

【中文标题】Freemarker 目录路径在 UAT 中不可读【英文标题】:Freemarker directory path is not readable in UAT 【发布时间】:2021-10-29 14:23:11 【问题描述】:

我正在使用 freemarker 模板创建一个 pdf 文件。此代码在我的本地工作,但是当我部署到 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");

template.ftl 文件位于src/templates/ 文件夹内。我尝试了多种定义目录的方法。我也尝试使用 setClassForTemplateLoading 方法,但它一直报错。

【问题讨论】:

我假设您的代码已经高度简化,但只是为了防止复制粘贴错误等,不应在获取模板之前设置模板加载器。因为,配置应该只发生一次,更早,然后多次调用getTemplate 另外你的模板目录是一个绝对路径,"/templates/",所以它不会在根目录中寻找src/templates,而是templates。但无论如何,任何带有src 的东西都不起作用;见我的回答。 【参考方案1】:

src 目录在部署后(至少正常情况下)在服务器上不存在,因为它是源代码。相反,您可以将模板放在 src/main/resources/templates 下(假设是 Maven 或通常的 Gradle 项目结构),这样它将成为已部署的 jar 的一部分。然后使用cfg.setClassForTemplateLoading(SomeClassFromTheSameJar.class, "/templates")

【讨论】:

以上是关于Freemarker 目录路径在 UAT 中不可读的主要内容,如果未能解决你的问题,请参考以下文章

freemarker include必须在同一个目录下吗

Freemarker使用总结

当 URL 路径中出现双斜杠时,如何使用 Elastic Beanstalk (Apache+Tomcat) 解决 HTTP 404 错误,例如https://uat.myserver//rest/s

MySQL理论:脏读不可重复读幻读

MySQL理论:脏读不可重复读幻读

从类路径设置 freemarker 模板