jfinal中使用freemarker进行include的路径问题

kenny0x00 发布于 2012/08/26 02:55
阅读 6K+
收藏 2
在使用jfinal时,自定义了freemarker的baseViewPath,但在<#include><#import>等语句里会报错,必须使用完整路径才行。
比如:
@Override
public void configConstant(Constants me) {
 me.setBaseViewPath("WEB-INF/pages");
}


使用render时一切正常:
public void index(){
 render("index.ftl");//该路径在WEB-INF/pages/index.ftl
}



然后freemarker页面里include的时候会报错:
<#include "/common/common.ftl"> <!-- 相当于WEB-INF/pages/common/common.ftl -->
必须使用<#include " /WEB-INF/pages/common/common.ftl ">

经过调试发现,在render方法里,会在最终调用FreeMarkerRender.render方法前,将viewpath与view相加,形成完整的路径,如:WEB-INF/pages/index.ftl
而通过include方法时,仅使用freemarker自己的模板查找机制,最终是通过WebappTemplateLoader的findTemplateSource去找模板:
public Object findTemplateSource(String name) throws IOException {
   String fullPath = path + name;
  //...


这里的path,被FreeMarkerRender的初始化方法写死为"/"
    static void init(ServletContext servletContext, Locale locale, int template_update_delay) {
        config.setServletContextForTemplateLoading(servletContext, "/");


并没有使用到之前所提到的Constants.setBaseViewPath("WEB-INF/pages");

也就是说,就算我们设置过setBaseViewPath,在include时,也必须写相对于WebRoot的全路径。
在1.1.1的代码里, FreeMarkerRender.init地方已经加了一句注释:
config.setServletContextForTemplateLoading(servletContext, "/"); // "WEB-INF/templates"
不知道后面计划如何修改?
加载中
1
27号
27号
如果是freemarker的话,可以在自己的properties文件中加入:auto_import=/WEB-INF/path/template.ftl as template .这样ftl文件中,就不用定义include了,直接使用<@template>即可。 
0
JFinal
JFinal

    非常好的问题    FreeMarkerRender.init(...) 方法 config.setServletContextForTemplateLoading(servletContext, "/"); 方法最初是打算带上 WEB-INF/path 路径的,后来因为考虑到开发者可能希望把动态页面(ftl)放 "WEB-INF/path"下的同时,却想把 css、js、images文件放在 WebRoot/path下,如果该参数为"WEB-INF/path"那么WebRoot可能就回不去了,所以才是现在的做法。

    至于 include 需要带全路径的问题,我记得是可以通过相对路径来解决的,只要你的 include 不要以 "/" 开头,就不会从 WebRoot 去找文件了,另外上级路径可以用 ".." 代替。

    你提出的这个问题,提醒了我,我抽时间再想办法做得更合理些,再次感谢 

首席救火队员
首席救火队员
詹总,如果我想把静态模板连同资源文件同时放在WEB-INF/view目录下,目前有什么好的方法吗?我用的jfinal2.2
0
谦谦君子淑女好逑
谦谦君子淑女好逑

首先,挖坟是不对的。

我也遇到这个问题了,然后我是直接把jfinal源码建成一个我自己的maven模块,然后把FreeMarkerRender里init方法的模板加载配置改成下面这样了。

config.setServletContextForTemplateLoading(servletContext, "/WEB-INF/views");



这样,包含模板的时候就直接写斜杠开头的路径了。

对于静态资源文件,jfinal配置加上Handle,页面加个${basepath}就行了,这样是不影响静态资源加载的,就是升级jfinal的时候要麻烦点。

希望波总下次更新的时候能够把模板配置那里加个配置入口,可以修改模板加载路径。@JFinal

0
JFinal
JFinal

引用来自“公子千”的评论

首先,挖坟是不对的。

我也遇到这个问题了,然后我是直接把jfinal源码建成一个我自己的maven模块,然后把FreeMarkerRender里init方法的模板加载配置改成下面这样了。

config.setServletContextForTemplateLoading(servletContext, "/WEB-INF/views");



这样,包含模板的时候就直接写斜杠开头的路径了。

对于静态资源文件,jfinal配置加上Handle,页面加个${basepath}就行了,这样是不影响静态资源加载的,就是升级jfinal的时候要麻烦点。

希望波总下次更新的时候能够把模板配置那里加个配置入口,可以修改模板加载路径。@JFinal

      后来添加了 FreemarkerRender.getConfiguration() 是可以做到的,只需要在 YourJFinalConfig.afterJFinalStart() 中添加一行代码,大致如下:

public YourJFinalConfig extends JFinalConfig {
 public void configRoutes(...) {}
 public void configConstant(...) {}
 public void configHandler(...) {}
 public void configPlugin(...) {}
 public void afterJFinalStart() {
  FreemarkerRender.getConfiguration().setServletContextForTemplateLoading(
    JFinal.me().getServletContext(),  path); 
 }
}

 


谦谦君子淑女好逑
谦谦君子淑女好逑
谢谢波总热情指导,怪我太粗心没看到。好使!我已经把源码做的修改回退了,哈哈:)
返回顶部
顶部