参考资料:
http://mylfd.iteye.com/blog/1896501
http://www.cnblogs.com/xxt19970908/p/5553045.html
个人实践:
1、需求:创建优惠券功能模块,操作人员选择若干条商品,点击生成按钮,程序在服务器指定目录下生成静态的优惠券页面。
2、实现:此处只列出使用freemarker生成优惠券部分的解决方案。
2.1、dispatcher-servlet.xml文件
<!--freemarker页面解析器 -->
<bean id="viewResolver"
class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">
<property name="suffix" value=".ftl"></property>
<property name="contentType" value="text/html;charset=UTF-8" />
<!-- <property name="viewClass" value="org.springframework.web.servlet.view.freemarker.FreeMarkerView" /> -->
<!-- 将Spring的FreeMarkerView改成我们扩展的View -->
<property name="viewClass" value="com.fx.controller.ExFreeMarkerView" />
<property name="exposeRequestAttributes" value="true" />
<property name="exposeSessionAttributes" value="true" />
<property name="exposeSpringMacroHelpers" value="true" />
</bean>
<bean id="fmXmlEscape" class="freemarker.template.utility.XmlEscape" />
<!--配置Freemarker -->
<bean id="freemarkerConfigurer"
class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
<!-- 模版页面存放的位置 -->
<property name="templateLoaderPath" value="/WEB-INF/freemarker/"></property>
<property name="freemarkerVariables">
<map>
<entry key="xml_escape" value-ref="fmXmlEscape" />
</map>
</property>
<property name="freemarkerSettings">
<props>
<prop key="template_update_delay">10</prop>
<prop key="defaultEncoding">UTF-8</prop>
</props>
</property>
</bean>
<!-- 定义跳转的文件的前后缀 ,视图模式配置 -->
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass"
value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
说明:在加入freemarker以前,我的internalResourceViewResolver就存在,加入freemarker以后,需要把freemarker的viewResolver放在它前面,让freemarker优先过滤用户请求的url,如果发现模板
目录(用户自定义的templateLoaderPath属性)下有对应名字的模板文件(后缀名.ftl),就在contoller执行以后由freemarker的viewResolver处理页面的展示;如果没发现对应的模板文件,就由internalResourceViewResolver
处理。比如:用户有个请求"/abc",如果存在abc.ftl模板,则RequestMapping("/abc")的controller方法执行后,由freemarker的viewResolver的viewClass,来处理。
2.2、viewClass类
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.Locale;
import java.util.Map; import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import org.springframework.web.servlet.support.RequestContextUtils;
import org.springframework.web.servlet.view.freemarker.FreeMarkerView; import com.fx.util.PathUtil; import freemarker.template.SimpleHash;
import freemarker.template.Template;
import freemarker.template.TemplateException; public class ExFreeMarkerView extends FreeMarkerView {
@Override
protected void doRender(Map<String, Object> model, HttpServletRequest request, HttpServletResponse response)
throws Exception { exposeModelAsRequestAttributes(model, request); SimpleHash fmModel = buildTemplateModel(model, request, response); if (logger.isDebugEnabled()) {
logger.debug("Rendering FreeMarker template [" + getUrl() + "] in FreeMarkerView '" + getBeanName() + "'");
} Locale locale = RequestContextUtils.getLocale(request); /*
* 在这里我们默认生成静态文件,当ModelAndView有指定STATIC_HTML = false时,就不会输出HTML文件
* 例如:ModelAndView modelAndView = new ModelAndView("htmlTest");
* modelAndView.addObject("STATICHTML", false);
*/
if (Boolean.FALSE.equals(model.get("STATIC_HTML"))) {
processTemplate(getTemplate(locale), fmModel, response);
} else {
createHTML(getTemplate(locale), fmModel, request, response);
} } public void createHTML(Template template, SimpleHash model, HttpServletRequest request,
HttpServletResponse response) throws IOException, TemplateException, ServletException {
// create file
String ftlFilesSaveDiskFolderPath = PathUtil.getStaticHtmlsSaveDiskFolderPath(request);
String randomDatePath = PathUtil.getRandomDatePath();
String randomDatePath2 = PathUtil.parseRandomDatePathToUrlPattern(randomDatePath);
String fileName = PathUtil.getNewHtmlFileName("test.html");
File htmlFile = new File(ftlFilesSaveDiskFolderPath+randomDatePath+fileName);
htmlFile.deleteOnExit();
if (!htmlFile.getParentFile().exists()) {
htmlFile.getParentFile().mkdirs();
}
if (!htmlFile.exists()) {
htmlFile.createNewFile();
} // write file
Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(htmlFile), "UTF-8"));
template.process(model, out);
out.flush();
out.close(); // store info
request.getSession().setAttribute("addCoupon_staticPage", randomDatePath2+fileName); // request forward
request.getRequestDispatcher("/coupons/previewCoupon").forward(request, response);
}
}
说明:createHTML方法主要目的是将model通过输出流输出到我们自定义的文件中。doRender方法中,如果不需要静态页面,需要手动给model的STATIC_HTML传值为false,默认调用用户自定义的createHTML,当然,这个逻辑可以自己扩展。
3、freemarker模板页面的常用语法:
http://mylfd.iteye.com/blog/1894407