参考资料:
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类
1 import java.io.BufferedWriter; 2 import java.io.File; 3 import java.io.FileOutputStream; 4 import java.io.IOException; 5 import java.io.OutputStreamWriter; 6 import java.io.Writer; 7 import java.util.Locale; 8 import java.util.Map; 9 10 import javax.servlet.ServletException; 11 import javax.servlet.http.HttpServletRequest; 12 import javax.servlet.http.HttpServletResponse; 13 14 import org.springframework.web.servlet.support.RequestContextUtils; 15 import org.springframework.web.servlet.view.freemarker.FreeMarkerView; 16 17 import com.fx.util.PathUtil; 18 19 import freemarker.template.SimpleHash; 20 import freemarker.template.Template; 21 import freemarker.template.TemplateException; 22 23 public class ExFreeMarkerView extends FreeMarkerView { 24 @Override 25 protected void doRender(Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) 26 throws Exception { 27 28 exposeModelAsRequestAttributes(model, request); 29 30 SimpleHash fmModel = buildTemplateModel(model, request, response); 31 32 if (logger.isDebugEnabled()) { 33 logger.debug("Rendering FreeMarker template [" + getUrl() + "] in FreeMarkerView '" + getBeanName() + "'"); 34 } 35 36 Locale locale = RequestContextUtils.getLocale(request); 37 38 /* 39 * 在这里我们默认生成静态文件,当ModelAndView有指定STATIC_HTML = false时,就不会输出HTML文件 40 * 例如:ModelAndView modelAndView = new ModelAndView("htmlTest"); 41 * modelAndView.addObject("STATICHTML", false); 42 */ 43 if (Boolean.FALSE.equals(model.get("STATIC_HTML"))) { 44 processTemplate(getTemplate(locale), fmModel, response); 45 } else { 46 createHTML(getTemplate(locale), fmModel, request, response); 47 } 48 49 } 50 51 public void createHTML(Template template, SimpleHash model, HttpServletRequest request, 52 HttpServletResponse response) throws IOException, TemplateException, ServletException { 53 // create file 54 String ftlFilesSaveDiskFolderPath = PathUtil.getStaticHtmlsSaveDiskFolderPath(request); 55 String randomDatePath = PathUtil.getRandomDatePath(); 56 String randomDatePath2 = PathUtil.parseRandomDatePathToUrlPattern(randomDatePath); 57 String fileName = PathUtil.getNewHtmlFileName("test.html"); 58 File htmlFile = new File(ftlFilesSaveDiskFolderPath+randomDatePath+fileName); 59 htmlFile.deleteOnExit(); 60 if (!htmlFile.getParentFile().exists()) { 61 htmlFile.getParentFile().mkdirs(); 62 } 63 if (!htmlFile.exists()) { 64 htmlFile.createNewFile(); 65 } 66 67 // write file 68 Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(htmlFile), "UTF-8")); 69 template.process(model, out); 70 out.flush(); 71 out.close(); 72 73 // store info 74 request.getSession().setAttribute("addCoupon_staticPage", randomDatePath2+fileName); 75 76 // request forward 77 request.getRequestDispatcher("/coupons/previewCoupon").forward(request, response); 78 } 79 }
说明:createHTML方法主要目的是将model通过输出流输出到我们自定义的文件中。doRender方法中,如果不需要静态页面,需要手动给model的STATIC_HTML传值为false,默认调用用户自定义的createHTML,当然,这个逻辑可以自己扩展。
3、freemarker模板页面的常用语法:
http://mylfd.iteye.com/blog/1894407