最近项目用到FreeMarker,在网上学习一番,遂把它整理之!
一、什么是模板引擎,为什么要用模板引擎
在B/S程式设计中,常常有美工和程序员二个角色,他们具有不同专业技能:美工专注于表现——创建页面、风格、布局、效果等等可视元素;而程序员则忙于创建程式的商业流程,生成设计页面要显示的数据等等。
很多时候,要显示的资料在设计的时候并不存在,它们一般是在运行时由程式产生的,比如执行“价格不高于800NT的USB Disk”查询的返回结果。这种技术需求产生了JSP等Scriptlet,JSP十分强大,但是也常常被滥用,并导致一些不良的后果
- 将逻辑和表现混合在一起。
- 破坏了美工和程序员职责的正常分解。
- 使JSP页面难以阅读和维护。
模板引擎就是为了解决上面的问题而产生的。在设计HTML的时候,我们加入一些特定指令来指定要插入哪些数据,这些加了特殊指令的HTML或者其他文本,我们称为模板(Template)。而模板引擎会在输出页面时,用适当的数据替代这些代码。
模板和嵌入JSP的HTML是不同的,模板指令只有很有限的编程能力,可以避免混入商业逻辑。
二、FreeMarker与JSP、Velocity的对比
FreeMarker优点:
1. 不能编写Java代码,可以实现严格的MVC分离
2. 美工和技术的工作分离
3. 页面是静态化的,这样方便搜索引擎的收录
4. 模板可以存在数据库,可以实现cms定制功能
5. 性能不错,页面显示的速度非常快,省去了JSP编译的过程
6. 内置许多功能强大的标记、以及大量常用的函数
7. 带有宏定义(macro)功能,类似于JSP自定义标签,但是更加简单方便
8. 支持JSP标签
9. Struts2对其支持效果不错
10. 不一定非要在Servlet中去实现
FreeMarker缺点:
1. 性能没有Velocity高,学习起来没有Velocity简单
2. 需要花费时间重新学习
3. FreeMarker中不能读取值为null的变量,会报错,必须要设置默认值或者判断
4. 模板修改之后,如果没有更新模板生成的HTML,会看到过期的页面
5. MyEclipseIDE插件的效果不太好
三、一个简单的FreeMarkerDemo
1.导入Jar包:
FreeMarker需要freemarker-2.3.19.jar包,Struts2里面有这个Jar包。
2.编写模板文件
FreeMarker的模板文件的后缀名是ftl。这里是我写的一个Example.ftl,我把它放在WebRoot下的Template文件夹下。
- <html>
- <head>
- <title>Example</title>
- </head>
- <body >
- <h1>大家好,我的名字叫${name},我家住在${address},我今年${age}岁了!</h1>
- </body>
- </html>
3.模板的解析
模板需要被解析之后才能生成最终的文件,FreeMarker的数据模型也是在模板中配置的。
ExampleResolution.java
- publicclass ExampleResolution {
- publicvoid resolution(){
- Writer out = null;
- /**
- *创建Configuration对象
- *设置模板文件的基路径
- *设置读取模板的编码方式
- */
- Configuration cfg = new Configuration();
- cfg.setServletContextForTemplateLoading(ServletActionContext.getServletContext(),"TemplateFiles");
- cfg.setDefaultEncoding("UTF-8");
- /**
- *创建FreeMarker的数据模型
- */
- Map root = newHashMap();
- root.put("name","李鑫龙");
- root.put("address","合肥市望江西路666号");
- root.put("age", 23);
- /**
- *设置生成的模板的位置
- *合并数据模型与模板
- *生成最终的html页面
- */
- try {
- Template template = cfg.getTemplate("Example.ftl");
- String path = ServletActionContext.getServletContext().getRealPath("/");
- File file = new File(path +"example.html");
- out = new BufferedWriter(new OutputStreamWriter(newFileOutputStream(file)));
- template.process(root, out);
- } catch (IOException e) {
- e.printStackTrace();
- } catch (TemplateException e) {
- e.printStackTrace();
- }finally{
- try {
- out.flush();
- out.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
- }
4.Action配置