浏览 8233 次
锁定老帖子 主题:Webwork生成静态文件的简单方法
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2007-06-13
已开始看了网上介绍的例子,基本上是通过freemarker的template来实现的,于是自己也做了这样的例子,做一个通用的接口,然后实现页面的静态化功能。 public class TemplateGenerateImpl implements TemplateGenerate { private Configuration cfg; public void init() { cfg = new Configuration(); cfg.setClassForTemplateLoading(TemplateGenerateImpl.class, "/templates"); cfg.setTemplateUpdateDelay(0); cfg.setTemplateExceptionHandler( TemplateExceptionHandler.HTML_DEBUG_HANDLER); cfg.setObjectWrapper(ObjectWrapper.BEANS_WRAPPER); cfg.setDefaultEncoding("ISO-8859-1"); cfg.setOutputEncoding("UTF-8"); cfg.setLocale(Locale.CHINA); } public void init(ServletContext sc) { cfg = new Configuration(); cfg.setServletContextForTemplateLoading( sc, SystemConstant.TEMPLATESPATH); cfg.setTemplateUpdateDelay(0); cfg.setTemplateExceptionHandler( TemplateExceptionHandler.HTML_DEBUG_HANDLER); cfg.setObjectWrapper(ObjectWrapper.BEANS_WRAPPER); cfg.setDefaultEncoding("ISO-8859-1"); cfg.setOutputEncoding("UTF-8"); cfg.setLocale(Locale.CHINA); } public void init(String templatePath) { cfg = new Configuration(); cfg.setClassForTemplateLoading(this.getClass(), templatePath); cfg.setTemplateUpdateDelay(0); cfg.setTemplateExceptionHandler( TemplateExceptionHandler.HTML_DEBUG_HANDLER); cfg.setObjectWrapper(ObjectWrapper.BEANS_WRAPPER); cfg.setDefaultEncoding("ISO-8859-1"); cfg.setOutputEncoding("UTF-8"); cfg.setLocale(Locale.CHINA); } public void show(String templateFileName, PageWrapper pw) throws IOException, TemplateException{ Template temp = cfg.getTemplate(templateFileName); pw.getResp().setContentType("text/html; charset=" + cfg.getOutputEncoding()); pw.getResp().setHeader("Cache-Control", "no-store, no-cache, must-revalidate, " + "post-check=0, pre-check=0"); pw.getResp().setHeader("Pragma", "no-cache"); Writer out = pw.getResp().getWriter(); temp.process(pw.getRoot(), out); } public void create(String templateFileName, PageWrapper pw, String targetFileName) throws IOException, TemplateException{ Template temp = cfg.getTemplate(templateFileName); targetFileName = "d:/temp/freemarker.html"; File file = new File(targetFileName); if(!file.exists()) file.mkdirs(); Writer out = new OutputStreamWriter(new FileOutputStream(targetFileName),"UTF-8"); temp.process(pw.getRoot(), out); out.flush(); } } 然后通过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,查看了他的源代码,通过下面的方式来实现的页面输出 public void doExecute(String location, ActionInvocation invocation) throws IOException, TemplateException { this.location = location; this.invocation = invocation; this.configuration = getConfiguration(); this.wrapper = getObjectWrapper(); ... ... if (preTemplateProcess(template, model)) { try { // Process the template // First, get the writer Writer writer = null; boolean useOutputStream = false; try { writer = getWriter(); } ... ... } } } 我们完全可以将输出到页面上的流转换为输出到静态文件,于是自己做了一个result type,并且配置三个缺省的参数:userDirectory、staticFileName、pContentType,分别可以定义静态文件的路径、名称、类型。然后在xwork.xml中添加一种result type <result-types> <result-type name="viewstatic" class="com.example.ViewAndStaticResult"> </result-type> </result-types> <action name="register" class="com.example.Register" method="init"> <result name="success" type="freemarker">/WEB-INF/classes/templates/register/reg.ftl</result> <interceptor-ref name="wsStack"></interceptor-ref> <!-- <result name="success" type="viewstatic"> <param name="location">${templateFile}</param> <param name="userDirectory">${userDirectory}</param> <param name="staticFileName">${staticFileName}</param> </result> --> </action> 实现的方法如下: protected void doExecute(String location, ActionInvocation invocation) throws Exception { this.location = location; this.invocation = invocation; this.configuration = getConfiguration(); this.wrapper = getObjectWrapper(); this.userDirectory = (String)conditionalParse(userDirectory, invocation); this.staticFileName = (String)conditionalParse(staticFileName, invocation); if (!location.startsWith("/")) { ActionContext ctx = invocation.getInvocationContext(); HttpServletRequest req = (HttpServletRequest) ctx.get(ServletActionContext.HTTP_REQUEST); String base = ResourceUtil.getResourceBase(req); location = base + "/" + location; } Template template = configuration.getTemplate(location, deduceLocale()); TemplateModel model = createModel(); // Give subclasses a chance to hook into preprocessing if (preTemplateProcess(template, model)) { //make static file makeStatic(template,model); //make Browser view makeView(template,model); } } private void makeStatic(Template template,TemplateModel model) throws IOException, TemplateException{ try { // Process the template // First, get the writers Writer swriter = null; boolean useOutputStream = false; try { if(getFilePath()){ swriter = getStaticFileWriter(userDirectory+"/"+staticFileName); }else{ useOutputStream = true; } } catch (IllegalStateException ise) { useOutputStream = true; } ... ... template.process(model, swriter); } finally { // Give subclasses a chance to hook into postprocessing postTemplateProcess(template, model); } } 这里可以看到location是缺省参数,定义模板的位置,对于另外两个参数,用户可以定义变量${userDirectory},然后在action中给它赋值,同时也可以定义常量,在reslut中都可以正确的被解析出来,主要的方法是通过WebWorkResultSupport.conditionalParse来实现的。用户可以在xwork.xml中使用这个reslut type,在view的同时生成静态页面 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |