【问题标题】:Allow Apache's FreeMarker template engine to load templates from outside Resources folder允许 Apache 的 FreeMarker 模板引擎从外部资源文件夹加载模板
【发布时间】:2019-11-19 10:03:27
【问题描述】:

我使用 Spring Initilizr 创建了一个 Spring Boot 应用程序。然后我包含了Apache's Freemarker 模板引擎来从我的项目中加载模板。默认情况下,引擎从以下位置加载模板:src/main/resources/templates/ 文件夹。

当用户访问网页http://localhost:8080 时,我正在尝试加载一个简单的index.ftl 文件作为模板。但我需要从src/main/webapp/ 文件夹加载模板。每当我尝试从 resources 文件夹外部加载模板时,模板引擎都无法找到模板。

我已经阅读了各种教程和 Stack Overflow 问题。没有人回答我的问题,我被 404 ERROR 卡住了,因为引擎无法找到文件。

文件结构为:

|-src
|---main
|-----java
|-------MainApplication.java
|-------controllers
|---------ViewController.java
|-----resources
|-------static
|-------templates
|-------application.properties
|-----webapp
|-------index.ftl

经过大量挖掘,我发现了一篇帖子,他们建议更改模板引擎搜索文件的位置。它建议在 application.properties 中添加以下行:

spring.freemarker.enabled=true
spring.freemarker.template-loader-path=classpath:src/main/webapp/

这似乎根本不起作用。

当我访问http://localhost:8080 的网页时,我正在尝试解析简单的索引页面。我编写了以下代码来映射ViewController.java 中的 HTTP 请求:

@RequestMapping("/")
public ModelAndView home(Model model)
{
    return new ModelAndView("index");
}

不知道是我完全弄错了还是我错过了一些配置。

【问题讨论】:

  • 使用源代码路径 (src) 几乎是不正确的(考虑一下,您只部署一个 jar 或 war 或 ear,都不包含源代码)。由于文件在 servlet 上下文中,当然您应该只使用 / 作为模板加载器路径(这通常意味着 servlet 上下文资源,而不是类路径资源)。
  • 好的。谢谢..我会更改代码。尽管如此,我如何确保可以将上下文路径设置为指向webapps 文件夹..?我知道这很愚蠢,但真的很吃我的头..
  • 在 Maven 中 src/main/webapps 对应于 Servlet 上下文根目录,即它复制到输出 war 文件的根目录中的内容(如果有,请尝试)。所以在运行时它的内容应该可以通过ServletContext.getResource 访问。如果模板路径不是以 URL 方案开头(如 classpath:),对于 Spring Web 应用程序,它应该默认从 ServletContext 加载,因此路径已经相对于 Servlet 上下文根。当然,它假设一个适当的构建,等等,但这就是想法。
  • stackoverflow.com/a/55451851/592355 可能会有帮助/重复警告!!!
  • 对于 spring boot 静态上下文使用 spring.mvc.static-path-pattern=docs.spring.io/spring-boot/docs/current/reference/html/…

标签: java spring-boot freemarker


【解决方案1】:

来自 Spring 文档:

如果您的应用程序是,请不要使用 src/main/webapp 目录 包装成罐子。虽然这个目录是一个通用标准,但它 仅适用于战争包装,并且被大多数人默默忽略 生成战争时构建工具。

src/main/webapp 与 web 存档相关联,并在您生成战争时由 maven war 插件打包。

假设您需要一个单独的位置来保存 ftl 模板,并且您仍想打包为 jar,您可以按照以下步骤操作。

在构建 pom 文件中添加资源条目,以便资源插件可以将该目录复制到类路径。

<build>
    <resources>
      <resource>
         <directory>src/main/webapp</directory>
     </resource>
    <resources>
<build>

将加载器路径更改为从类路径的ROOT读取。

spring.freemarker.template-loader-path=classpath:

如果它仅用于 ftl 模板,我会将目录更改为 src/main/ftls 以避免混淆并在资源中更新。

更新

我其实是想构建一个WAR部署包

你必须使用战争插件来构建战争。在 pom.xml 中添加插件并将包装更改为 war。

有关传统部署的更多信息:https://docs.spring.io/spring-boot/docs/current/reference/html/howto-traditional-deployment.html#howto-create-a-deployable-war-file

【讨论】:

  • 你试过我的答案了吗?如果您有任何问题,请告诉我。您不应为 jar 包创建 webapp 文件夹。这不是一个好的做法,应该避免。它使应用程序看起来像一个战争项目。您应该遵循 Spring Boot 的建议并将所有文件保留在资源文件夹中。资源下的任何文件都打包到 jar 中。
  • 我检查了你的答案,意识到我实际上想要构建一个 WAR 部署包。我也修改了我的问题。谢谢你大开眼界。但是,我的模板引擎无法从 webapp 文件夹中获取模板。
  • Np。你必须使用战争插件来建立战争。在 pom 中添加插件并将类型更改为 war。
  • 实际上当我检查创建的war文件的结构时,我可以在这个包的根目录中看到index.ftl页面。但是当我在浏览器中输入网址时仍然无法加载它。
  • 你试过spring.freemarker.template-loader-path=classpath:吗?
【解决方案2】:

编辑

在嵌入式tomcat中,您可以在application-properties中定义静态资源路径

 spring.mvc.static-path-pattern=

如果你部署到tomcat,在tomcat中使用可以在server.xml里面定义static context可以保存freemarker文件,如

 <Context docBase="/home/stuff" path="/static" />

&lt;Context&gt; 元素被添加到 &lt;Host&gt; 元素中。 Context 有两个属性:docBase 是磁盘上包含您的静态文件的目录,path 是您要在其上提供文件的 URL。

【讨论】:

  • 其实我没有外装Tomcat。 Spring 自动初始化它。所以,我实际上找不到你提到的 server.xml 文件。
  • @ShivamNaik 查看spring静态资源的选项baeldung.com/spring-mvc-static-resources
  • 如果可行,我会仔细检查并回复。谢谢你
  • 是的@user7294900。我实际上尝试了您提供的第一个解决方案。虽然,它并没有解决我的问题。不过现在解决了。我选择了工作答案作为上面的正确答案:)
猜你喜欢
  • 2019-10-28
  • 2011-05-11
  • 2014-01-02
  • 1970-01-01
  • 2013-01-23
  • 2012-11-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-20
相关资源
最近更新 更多