Webwork生成静态文件的简单方法

接触模板技术的时间不是很长,原来一直通过io的方法去自己生成静态文件,后来发现了模板技术,大家都在学习,我也就跟风是的加入了行列,已开始接触的是velocity,后来看了je上的大牛的介绍,开始试用Freemarker。使用模板技术除了在web app中用来显示view之外,还有一个典型的应用就是将页面静态化,这也是提高网站性能的一个基本的办法。我的目标是这样的,通过一套模板在显示页面的同时,自动生成静态页面,并保存在用户自己的目录中。

已开始看了网上介绍的例子,基本上是通过freemarker的template来实现的,于是自己也做了这样的例子,做一个通用的接口,然后实现页面的静态化功能。

代码
  1. public class TemplateGenerateImpl implements TemplateGenerate {   
  2.        
  3.     private Configuration cfg;   
  4.        
  5.     public void init() {   
  6.         cfg = new Configuration();   
  7.         cfg.setClassForTemplateLoading(TemplateGenerateImpl.class"/templates");   
  8.         cfg.setTemplateUpdateDelay(0);   
  9.         cfg.setTemplateExceptionHandler(   
  10.                 TemplateExceptionHandler.HTML_DEBUG_HANDLER);   
  11.         cfg.setObjectWrapper(ObjectWrapper.BEANS_WRAPPER);   
  12.         cfg.setDefaultEncoding("ISO-8859-1");   
  13.         cfg.setOutputEncoding("UTF-8");   
  14.         cfg.setLocale(Locale.CHINA);   
  15.     }   
  16.        
  17.     public void init(ServletContext sc) {   
  18.         cfg = new Configuration();   
  19.         cfg.setServletContextForTemplateLoading(   
  20.                 sc, SystemConstant.TEMPLATESPATH);   
  21.         cfg.setTemplateUpdateDelay(0);   
  22.         cfg.setTemplateExceptionHandler(   
  23.                 TemplateExceptionHandler.HTML_DEBUG_HANDLER);   
  24.         cfg.setObjectWrapper(ObjectWrapper.BEANS_WRAPPER);   
  25.         cfg.setDefaultEncoding("ISO-8859-1");   
  26.         cfg.setOutputEncoding("UTF-8");   
  27.         cfg.setLocale(Locale.CHINA);   
  28.     }   
  29.   
  30.     public void init(String templatePath) {   
  31.         cfg = new Configuration();   
  32.         cfg.setClassForTemplateLoading(this.getClass(), templatePath);   
  33.         cfg.setTemplateUpdateDelay(0);   
  34.         cfg.setTemplateExceptionHandler(   
  35.                 TemplateExceptionHandler.HTML_DEBUG_HANDLER);   
  36.         cfg.setObjectWrapper(ObjectWrapper.BEANS_WRAPPER);   
  37.         cfg.setDefaultEncoding("ISO-8859-1");   
  38.         cfg.setOutputEncoding("UTF-8");   
  39.         cfg.setLocale(Locale.CHINA);   
  40.     }   
  41.        
  42.     public void show(String templateFileName, PageWrapper pw) throws IOException, TemplateException{   
  43.         Template temp = cfg.getTemplate(templateFileName);   
  44.            
  45.         pw.getResp().setContentType("text/html; charset=" + cfg.getOutputEncoding());   
  46.         pw.getResp().setHeader("Cache-Control""no-store, no-cache, must-revalidate, "  
  47.                 + "post-check=0, pre-check=0");   
  48.         pw.getResp().setHeader("Pragma""no-cache");   
  49.         Writer out = pw.getResp().getWriter();   
  50.         temp.process(pw.getRoot(), out);   
  51.     }   
  52.        
  53.     public void create(String templateFileName,  PageWrapper pw, String targetFileName) throws IOException, TemplateException{   
  54.         Template temp = cfg.getTemplate(templateFileName);   
  55.         targetFileName = "d:/temp/freemarker.html";   
  56.         File file = new File(targetFileName);       
  57.         if(!file.exists())       
  58.             file.mkdirs();   
  59.         Writer out = new OutputStreamWriter(new FileOutputStream(targetFileName),"UTF-8");   
  60.         temp.process(pw.getRoot(), out);   
  61.         out.flush();   
  62.     }   
  63. }  
render_code();中国经济网 经济博客%K8JKv6I:O/m
然后通过spring的注入功能,自动注入到webwork的action中,这样,在action中就可以调用生成静态页面的方法了。但是实际的实验结果是,如果freemarker的模板中使用了标签技术,在生成静态页面的时候,根本就不能render模板为正确的html文件,而是把ftl作为一个io流直接输出成html了,这样的结果是不行的。于是改变模板,不使用任何标签,而使用标准的html来写模板,然后在模板中使用freemarker的data+model方式来输出页面。这种方式解决了不解析tag的毛病,静态页面可以正确的输出了,但是发现一个问题,在ftl中使用i18n出现一些问题,比如:${action.getText('reg.title')}在生成静态页面的时候会出现错误。这里的原因主要是freemarker在处理静态文件生成的时候采用temp.process(Map root, Writer out);方法,如果webwork中的ognl中的stack value没有被放进root时,这样就会出现错误,一个最简单的办法是,定义一个super action,然后将stack初始化,并放入root中,然后每个action继承super action,这样root就能得到stack value了。这样的办法虽然能解决问题,但是总是感觉有些笨拙,于是考虑了下面一个更加简单的方法。

 

webwork在render freemaker模板的时候,有一个缺省的result type,就是freemarker,查看了他的源代码,通过下面的方式来实现的页面输出

代码
  1. public void doExecute(String location, ActionInvocation invocation) throws IOException, TemplateException {   
  2.         this.location = location;   
  3.         this.invocation = invocation;   
  4.         this.configuration = getConfiguration();   
  5.         this.wrapper = getObjectWrapper();   
  6.         ...   
  7.         ...   
  8.                 if (preTemplateProcess(template, model)) {   
  9.             try {   
  10.                 // Process the template   
  11.                 // First, get the writer   
  12.                 Writer writer = null;   
  13.                 boolean useOutputStream = false;   
  14.                 try {   
  15.                     writer = getWriter();   
  16.                 }   
  17.                 ...   
  18.                 ...   
  19.             }   
  20.         }   
  21.     }  
render_code();中国经济网 经济博客 gE+rAgm3@E
我们完全可以将输出到页面上的流转换为输出到静态文件,于是自己做了一个result type,并且配置三个缺省的参数:userDirectory、staticFileName、pContentType,分别可以定义静态文件的路径、名称、类型。然后在xwork.xml中添加一种result type 中国经济网 经济博客M9_5H ~?
代码
  1. <result-types>  
  2.             <result-type name="viewstatic" class="com.example.ViewAndStaticResult">  
  3.                             </result-type>  
  4.          </result-types>  
render_code();

 

 

代码
  1. <action name="register" class="com.example.Register" method="init">  
  2.             <result name="success" type="freemarker">/WEB-INF/classes/templates/register/reg.ftl</result>  
  3.             <interceptor-ref name="wsStack"></interceptor-ref>  
  4.             <!--    
  5.             <result name="success" type="viewstatic">  
  6.                 <param name="location">${templateFile}</param>  
  7.                 <param name="userDirectory">${userDirectory}</param>  
  8.                 <param name="staticFileName">${staticFileName}</param>  
  9.             </result>  
  10.              -->  
  11.         </action>  
render_code(); 5jL7E s|?-jB1N$t0实现的方法如下: 中国经济网 经济博客hj:X{i+L
代码
  1. protected void doExecute(String location, ActionInvocation invocation) throws Exception {   
  2.            
  3.         this.location = location;   
  4.         this.invocation = invocation;   
  5.         this.configuration = getConfiguration();   
  6.         this.wrapper = getObjectWrapper();   
  7.         this.userDirectory = (String)conditionalParse(userDirectory, invocation);   
  8.         this.staticFileName = (String)conditionalParse(staticFileName, invocation);   
  9.         if (!location.startsWith("/")) {   
  10.             ActionContext ctx = invocation.getInvocationContext();   
  11.             HttpServletRequest req = (HttpServletRequest) ctx.get(ServletActionContext.HTTP_REQUEST);   
  12.             String base = ResourceUtil.getResourceBase(req);   
  13.             location = base + "/" + location;   
  14.         }   
  15.            
  16.         Template template = configuration.getTemplate(location, deduceLocale());   
  17.         TemplateModel model = createModel();   
  18.   
  19.         // Give subclasses a chance to hook into preprocessing   
  20.         if (preTemplateProcess(template, model)) {   
  21.             //make static file   
  22.             makeStatic(template,model);   
  23.             //make Browser view   
  24.             makeView(template,model);   
  25.         }   
  26.     }   
  27. private void makeStatic(Template template,TemplateModel model) throws IOException, TemplateException{   
  28.         try {   
  29.             // Process the template   
  30.             // First, get the writers   
  31.             Writer swriter = null;   
  32.             boolean useOutputStream = false;   
  33.             try {   
  34.                 if(getFilePath()){   
  35.                     swriter = getStaticFileWriter(userDirectory+"/"+staticFileName);   
  36.                 }else{   
  37.                     useOutputStream = true;   
  38.                 }   
  39.                    
  40.             }   
  41.             catch (IllegalStateException ise) {   
  42.                  useOutputStream = true;   
  43.             }   
  44.             ...   
  45.             ...   
  46.                 template.process(model, swriter);   
  47.                
  48.         } finally {   
  49.             // Give subclasses a chance to hook into postprocessing   
  50.             postTemplateProcess(template, model);   
  51.         }   
  52.     }  

render_code();中国经济网 经济博客1^/HQwEb$Tt P1Kh
这里可以看到location是缺省参数,定义模板的位置,对于另外两个参数,用户可以定义变量${userDirectory},然后在action中给它赋值,同时也可以定义常量,在reslut中都可以正确的被解析出来,主要的方法是通过WebWorkResultSupport.conditionalParse来实现的。用户可以在xwork.xml中使用这个reslut type,在view的同时生成静态页面  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值