一、 概述
freemarker是java编写的一款模版引擎,是一种基于模版和要改变的数据,并用于输出文本(html、电子邮件、配置文件和源代码等)的通用工具。与web容器无关,即在web运行时,它并不知道servlet或HTTP。不仅可以用于表现层的实现技术,还可以用于生成XML,JPS或java等。在企业中,一般用于生成静态页面或是页面展示。
二、 使用freemarker
导入jar包或者引入依赖。
编写测试程序。
创建一个最简单的模版
在webapp的WEB-INF目录下,新建ftl目录,新建hello.ftl,一般是ftl后缀,也可以使用其他的。
${hello}
测试程序
@Test
publicvoid testFreemarker() throws Exception {
// 创建模版文件
// 创建Configuration对象
Configuration configuration = newConfiguration(Configuration.getVersion());
// 设置模版文件的保存路径
configuration.setDirectoryForTemplateLoading(
new File("H:\\001java\\eclipseSTSworkspace\\e3-item-web\\src\\main\\webapp\\WEB-INF\\ftl"));
// 设置默认文件的编码格式,一般是utf-8
configuration.setDefaultEncoding("utf-8");
// 加载一个模版文件,创建一个模版对象
Template template = configuration.getTemplate("hello.ftl");
// 创建一个数据集,pojo或者map
Map map = newHashMap<>();
map.put("hello", "你好福瑞马克");
// 创建一个Writer对象,指定输出文件的路径名及文件名
Writer out = new FileWriter(new File("H:\\vv\\hello.txt"));
// 生成静态页面
template.process(map, out);
// 关闭流
out.close();
}
三、 freemarker语法
1. 访问pojo属性
创建一个student的pojo。
创建模版
<!DOCTYPE html>
<html>
<head>
<metacharset="utf-8" />
<title>学生</title>
</head>
<body>
学生信息<br />
<table>
<tr>
<td>id</td>
<td>姓名</td>
<td>年龄</td>
<td>地址</td>
</tr>
<tr>
<td>${student.id}</td>
<td>${student.name}</td>
<td>${student.age}</td>
<td>${student.address}</td>
</tr>
</table>
</body>
</html>
编写根据模版创建html文件的方法。
@Test
public void testFreemarker2()throws Exception {
// 创建模版文件
// 创建Configuration对象
Configuration configuration =new Configuration(Configuration.getVersion());
// 设置模版文件的保存路径
configuration.setDirectoryForTemplateLoading(
newFile("H:\\001java\\eclipseSTSworkspace\\e3-item-web\\src\\main\\webapp\\WEB-INF\\ftl"));
// 设置默认文件的编码格式,一般是utf-8
configuration.setDefaultEncoding("utf-8");
// 加载一个模版文件,创建一个模版对象
Template template =configuration.getTemplate("student.ftl");
// 创建一个数据集,pojo或者map
Map map = newHashMap<>();
map.put("hello","你好福瑞马克");
// 创建一个pojo对象
Student student = newStudent(2, "tom2", 22, "北京");
map.put("student",student);
// 创建一个Writer对象,指定输出文件的路径名及文件名
Writer out = newFileWriter(new File("H:\\vv\\student.html"));
// 生成静态页面
template.process(map, out);
// 关闭流
out.close();
}
2. 取集合中的数据
在模版文件中取集合,取集合的下标使用元素_index
<#list stuList as student>
<tr>
<td>${student_index}</td>
<td>${student.id}</td>
<td>${student.name}</td>
<td>${student.age}</td>
<td>${student.address}</td>
</tr>
<#/list>
在生成文件中添加一个集合
List<Student> stuList = newArrayList<>();
stuList.add(new Student(1,"tom", 23, "海淀"));
stuList.add(new Student(3,"lily", 19, "中关村"));
stuList.add(new Student(2,"mke", 20, "上地"));
stuList.add(new Student(4,"lucy", 21, "西二旗"));
map.put("stuList",stuList);
测试。
3. if
<#list stuList as student>
<#if student_index % 2 ==0>
<trbgcolor="yellow">
<#else>
<trbgcolor="grey">
</#if>
<td>${student_index}</td>
<td>${student.id}</td>
<td>${student.name}</td>
<td>${student.age}</td>
<td>${student.address}</td>
</tr>
</#list>
4. date类型的处理
向模版添加一个日期数据
map.put("date", new Date());
在模版中处理日期
当前日期:${date?date} ${date?time} ${date?datetime}
<br />
当前日期(自定义格式):${date?string("dd/MM/yyyy HH:mm:ss")}
5. null值的处理
使用!设置默认值,防止空值报错。
也可以通过判断做处理。
向页面传递空值。
map.put("null", null);
在模版做处理
空值:${null!} ${null!"值为null"} ${null!"默认值为1"}
<br />
判断值是否为空:
<#if null??>
值不为空
<#else>
值为空
</#if>
6. include
引入模版
<#include "hello.ftl">
注意将引入的模版中用到的数据,在创建时传入。
四、 freemarker整合spring
导入freemarker的jar包或者引入依赖后,在配置文件中
<bean id="freemarkerConfig" class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
<propertyname="templateLoaderPath" value="/WEB-INF/ftl/" />
<propertyname="defaultEncoding" value="UTF-8" />
</bean>
编写控制器类
@Controller
public class HtmlGenerateController {
@Autowired
private FreeMarkerConfigurerfreeMarkerConfigurer;
@RequestMapping("/generalHtml")
@ResponseBody
public String generalHtml()throws Exception {
Configuration configuration =freeMarkerConfigurer.getConfiguration();
// 加载模版
Template template =configuration.getTemplate("hello.ftl");
// 创建数据集
Map map = newHashMap<>();
map.put("hello","hello spring freemarker");
// 指定文件输出路径和文件名
Writer writer = newFileWriter(new File("H:\\vv\\hello2.html"));
// 输出文件
template.process(map, writer);
// 关闭流
writer.close();
return "success";
}
}
五、 网页的静态化解决方案
输出文件的名称为:商品id+”.html”。输出的文件的路径为工程外部的任意目录。网页访问时,使用nginx访问网页,这样tomcat只有一个作用是生成静态页面。工程部署时,可以把商品详情页项目部署到多个服务器上。生成静态页面的时机,商品添加后,生成静态页面,使用activemq,订阅topic商品添加消息。
将jsp改造为freemarker的模版。
编写商品添加消息侦听,生成静态页面的类和方法。
public class HtmlGenListener implements MessageListener {
@Autowired
private ItemService itemService;
@Autowired
private FreeMarkerConfigurerfreeMarkerConfigure;
@Value("${HTML_GEN_PATH}")
private String HTML_GEN_PATH;
@Override
public void onMessage(Messagemessage) {
// 创建模版,参考jsp
// 从消息中获取商品id
TextMessage textMessage =(TextMessage) message;
try {
String text =textMessage.getText();
// 根据商品id,查询商品信息
long id =Long.parseLong(text);
// 等待事务提交
Thread.sleep(1000);
TbItem tbitem =itemService.findItemById(id);
Item item = newItem(tbitem);
TbItemDesc itemDesc =itemService.getItemDesc(id);
// 创建数据集,封装商品信息
Map data = newHashMap<>();
data.put("item",item);
data.put("itemDesc",itemDesc);
// 加载模版对象
Configurationconfiguration = freeMarkerConfigure.createConfiguration();
Template template =configuration.getTemplate("item.ftl");
// 创建一个文件输出流,指定文件的路径和文件名
Writer out = newFileWriter(new File(HTML_GEN_PATH + text + ".html"));
// 执行生成静态页面
template.process(data,out);
// 关闭流
out.close();
} catch (Exception e) {
// TODO Auto-generatedcatch block
e.printStackTrace();
}
}
}
配置activemq到spring
<!-- 真正可以产生Connection的ConnectionFactory,由对应的 JMS服务厂商提供 -->
<bean id="targetConnectionFactory"class="org.apache.activemq.ActiveMQConnectionFactory">
<propertyname="brokerURL" value="tcp://192.168.0.121:61616" />
</bean>
<!-- Spring用于管理真正的ConnectionFactory的ConnectionFactory -->
<beanid="connectionFactory"
class="org.springframework.jms.connection.SingleConnectionFactory">
<!-- 目标ConnectionFactory对应真实的可以产生JMS Connection的ConnectionFactory -->
<propertyname="targetConnectionFactory"ref="targetConnectionFactory" />
</bean>
<!-- 配置生产者 -->
<!-- Spring提供的JMS工具类,它可以进行消息发送、接收等 -->
<beanid="jmsTemplate"class="org.springframework.jms.core.JmsTemplate">
<!-- 这个connectionFactory对应的是我们定义的Spring提供的那个ConnectionFactory对象 -->
<propertyname="connectionFactory" ref="connectionFactory" />
</bean>
<!--这个是队列目的地,点对点的 -->
<beanid="queueDestination"class="org.apache.activemq.command.ActiveMQQueue">
<constructor-arg>
<value>spring-queue</value>
</constructor-arg>
</bean>
<!--这个是主题目的地,一对多的 -->
<beanid="topicDestination" class="org.apache.activemq.command.ActiveMQTopic">
<constructor-argvalue="itemAddTopic" />
</bean>
<!--自定义的消息侦听实现类 -->
<beanid="htmlGenListener"class="com.ten.e3shop.item.listener.HtmlGenListener"></bean>
<!--消息侦听容器 -->
<beanclass="org.springframework.jms.listener.DefaultMessageListenerContainer">
<propertyname="connectionFactory" ref="connectionFactory" />
<propertyname="destination" ref="topicDestination" />
<propertyname="messageListener" ref="htmlGenListener" />
</bean>
配置nginx服务器,在虚拟目录下创建一个item目录,将生成的静态文件的输出目录指定为这个目录,将静态文件的css样式、图片和js等静态资源放在虚拟目录的localhost/可以访问到的目录下。
使用nginx测试。