java-freemarker-实现layout布局框架的一些思路
在 web 开发中经常会用到母版页、布局页的概念,将页面公共部分提炼出来,
有两种思路可以服用公共页,这里使用 使用 body.html、header.html、footer.html 举例
方法一:在当 body.html 使用 include 方式引用 header.html、footer.html,这需要在项目中的所有页面中都需要 include 这两个页面
方法二:提炼出一个 全局公共的 布局页 layout.html ,里面引用固定的 header.html、footer.html,动态引用 body.html 页
两种方案比较:
假如现在项目有 100 个页面,现在当需要在所有页面的底部添加一个 version.html 页;
使用“方法一”需要在所有的页面中修改一次(当然也可以把 version.html 写到 footer.html 中实现);
使用“方法二”只需要修改 layout.html 即可;
下面就使用 freemarker 完成 “方法二” 的功能。
逻辑大概是:每次返回模板地址时,都返回 layout.html 的地址,儿 body.html 地址则通过动态参数形式下发到 layout.html 中;
注:按照 freemarker 的习惯,模板文件都改用 .ftl 命名,思想可以用于 web 项目,但这里只用变成方式实现,没有引用web框架;
1.需要四个页面:
tmpLayout.ftl //布局页
tmpBody.ftl //主业务页
tmpFooter.ftl //页脚
tmpHeader.ftl //页头
2.测试类,运行 testLayout 方法,查看效果
3.需要四个页面的代码如下:
3.1 tmpLayout.ftl //布局页
3.2 tmpBody.ftl //主业务页
3.3 tmpFooter.ftl //页脚
3.4 tmpHeader.ftl //页头
在 web 开发中经常会用到母版页、布局页的概念,将页面公共部分提炼出来,
有两种思路可以服用公共页,这里使用 使用 body.html、header.html、footer.html 举例
方法一:在当 body.html 使用 include 方式引用 header.html、footer.html,这需要在项目中的所有页面中都需要 include 这两个页面
方法二:提炼出一个 全局公共的 布局页 layout.html ,里面引用固定的 header.html、footer.html,动态引用 body.html 页
两种方案比较:
假如现在项目有 100 个页面,现在当需要在所有页面的底部添加一个 version.html 页;
使用“方法一”需要在所有的页面中修改一次(当然也可以把 version.html 写到 footer.html 中实现);
使用“方法二”只需要修改 layout.html 即可;
下面就使用 freemarker 完成 “方法二” 的功能。
逻辑大概是:每次返回模板地址时,都返回 layout.html 的地址,儿 body.html 地址则通过动态参数形式下发到 layout.html 中;
注:按照 freemarker 的习惯,模板文件都改用 .ftl 命名,思想可以用于 web 项目,但这里只用变成方式实现,没有引用web框架;
1.需要四个页面:
tmpLayout.ftl //布局页
tmpBody.ftl //主业务页
tmpFooter.ftl //页脚
tmpHeader.ftl //页头
2.测试类,运行 testLayout 方法,查看效果
package freemarker.razor;
import java.io.*;
import java.util.*;
import org.junit.Before;
import org.junit.Test;
import freemarker.core.ParseException;
import freemarker.template.Configuration;
import freemarker.template.MalformedTemplateNameException;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import freemarker.template.TemplateNotFoundException;
/**
*
* @author xxj
*/
public class testRazor {
@Before
public void init(){
cfg = new Configuration(Configuration.VERSION_2_3_23);
//加载模板
cfg.setClassForTemplateLoading(this.getClass(), "");
cfg.setDefaultEncoding("utf-8");
}
Configuration cfg = null;
@Test
public void testLayout(){
//参数
Map<String,Object> pars = new HashMap<String,Object>();
pars.put("name", "张三");
pars.put("date", new Date());
layoutViewer("tmpBody.ftl",pars);
}
/**
* 使用 布局页
* @param pagePath 必须:当前页面地址
*/
public void layoutViewer(String pagePath
,Map<String, Object> pars){
//定义 body 页路径参数
pars.put("body_file_path", pagePath);
try{
String layoutPath="tmpLayout.ftl";//布局页地址固定
//模板(默认加载布局页)
Template tmp = cfg.getTemplate(layoutPath);
//合并模板和数据模型
Writer out = new OutputStreamWriter(System.out);//创建一个输出流,这里指打印到控制台
tmp.process(pars, out);
}catch(Exception ex){
ex.printStackTrace();
}
}
}
3.需要四个页面的代码如下:
3.1 tmpLayout.ftl //布局页
<!doctype html>
<html lang="en">
<head>
<#attempt>
<title>${title_name}</title>
<#recover>
<title>标题</title>
</#attempt>
</head>
<body>
<!--页头 begin -->
<#include "tmpHeader.ftl">
<!--body begin -->
<#include "${body_file_path}"><#--body页内容动态输出-->
<!--页脚 begin -->
<#include "tmpFooter.ftl">
</body>
</html>
3.2 tmpBody.ftl //主业务页
<!--body内容-->
<div>
name:${name}
date:${date?string("yyyy-MM-dd HH:mm:ss zzzz")}
</div>
3.3 tmpFooter.ftl //页脚
<div>页头部分</div>
3.4 tmpHeader.ftl //页头
<div>页尾部分</div>