最近公司使用Freemarker开发一个网站,所以自己抽空学了一下,怎么说呢,刚入个门,给我的感觉Freemarker跟jsp实在是太像了,名字为模板引擎,其实理论上jsp同样也属于一种模板,如果动态的转发到页面上其使用步骤与Jsp一摸一样(当然,前提是需要配置视图解析器),我们这个项目主要使用它与数据结合生成静态页面,以文件的形式存储在本地。因此,你在控制器直接返回一个main.ftl其实没有多大意义个人感觉,还不如用Jsp,Jsp与SpringMVC结合更方便。
那么开始吧,使用Freemark生成静态页面肯定是需要两个东西的,一个就是页面模板,另外一个就是数据模型,项目业务是使用者发表文章,文章内容就是数据模型,所有文章共用一个模板文件,用户编辑好了文章之后后台就会调用Freemarker接口生成静态页面。
首先是配置文件:
freemarker的资源文件:
<bean id="freemarkerConfiguration" class="org.springframework.beans.factory.config.PropertiesFactoryBean">资源内容:
<property name="location" value="/WEB-INF/resource/freemarker.properties" />
</bean>
default_encoding=UTF-8
url_escaping_charset=UTF-8
locale=zh_CN
whitespace_stripping=true
template_update_delay=0
tag_syntax=square_bracket
#classic_compatible=true
datetime_format=yyyy-MM-dd HH:mm:ss
date_format=yyyy-MM-dd
time_format=HH:mm:ss
number_format=#;
接下来是设置属性:
<bean id="freemarkerConfiguration" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="location" value="/WEB-INF/resource/freemarker.properties" />
</bean>
<bean class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
<property name="templateLoaderPath" value="/WEB-INF/views/templates" />
<property name="defaultEncoding" value="utf-8" />
<property name="freemarkerSettings" ref="freemarkerConfiguration"/>
<!--设置一些常用的全局变量-->
<property name="freemarkerVariables">
<map>
<entry key="webRoot" value="/shop"/>
<entry key="jsRoot" value="/shop/js"/>
</map>
</property>
</bean>
这是Spring的部分配置文件,这一步是用来配置Freemarker基本属性,具体含义不说了,百度一大堆,接下来是配置视图解析器:
<!-- 配置jsp视图解析器 -->JSP试图解析器和Freemarker视图解析器,注意一下优先级,同名同路径的请求会有用。
<bean id="jspViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
<property name="prefix" value="/WEB-INF/views/jsp/"/>
<property name="suffix" value=".jsp"/>
<property name="order" value="2" />
</bean>
<!-- 配置freeMarker视图解析器 -->
<bean id="freemarkerViewResolver" class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.freemarker.FreeMarkerView"/>
<property name="suffix" value=".html" />
<!--
<property name="viewNames" value="*.ftl" />
-->
<property name="contentType" value="text/html; charset=utf-8" />
<property name="cache" value="true" />
<!-- 结果是请求和会话属性都被复制到模板的属性集中,可以使用FreeMarker的表达式语言来访问并显示 -->
<property name="exposeRequestAttributes" value="true" />
<property name="exposeSessionAttributes" value="true" />
<!-- 使用宏 -->
<property name="exposeSpringMacroHelpers" value="true" />
<property name="order" value="1" />
</bean>
配置文件写好了之后就可以来写FreemarkerUtil了,这个工具类主要就是将传入的数据模型生成静态页面:
private static String staticPagePath = "C:/Users/hao/Desktop/staticPages";
/**
* @param data 数据模型
* @param templatePath 模板路径 "WEB-INF/templates"
* @param templateFileName 模板文件名 "main.html"
* @param staticPageName 生成的静态文件的文件名
*/
public static void createStaticPage(Configuration cfg,HttpServletRequest request,String staticPageName ,Map<String, Object> data, String templatePath, String templateFileName) {
try {
cfg.setTagSyntax(Configuration.AUTO_DETECT_TAG_SYNTAX);// 设置标签
cfg.setServletContextForTemplateLoading(request.getServletContext(),templatePath);// 设置临时加载目录。
cfg.setDefaultEncoding("UTF-8");
cfg.setNumberFormat("#");
Template temp = cfg.getTemplate(templateFileName);// 获取模板对象
Writer out = new OutputStreamWriter(new FileOutputStream(staticPagePath+"/"+staticPageName+(new Date()).getTime()+".html"), "UTF-8");
temp.process(data, out);
out.flush();
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
还有一个工具方法是判断文件是否已经存在:
/**OK,以上就是FreemarkerUtil的内容,原理很简单。
* @param request
* @param filePath 文件存放的路径
* @param fileName 文件的名称,需要扩展名
* @author HuifengWang
* @return
*/
public static Map<String,Object> htmlFileHasExist(HttpServletRequest request,String filePath,
String fileName) {
Map<String,Object> map = new HashMap<String,Object>();
String htmlPath = request.getSession().getServletContext() .getRealPath(filePath) + "/" + fileName;
File htmlFile = new File(htmlPath);
if(htmlFile.exists()){
map.put("exist", true);
}else{
map.put("exist",false);
}
return map ;
}
最后生成的页面:
Demo的目录结构如下:
当然,以后要查询页面的时候涉及到了检索,我们用的是Lucene全文检索,后文在说。