`
zzc1684
  • 浏览: 1223143 次
  • 性别: Icon_minigender_1
  • 来自: 广州
文章分类
社区版块
存档分类
最新评论

FreeMarker页面静态化

阅读更多

目前的项目中需要对某些页面进行静态化,减轻服务器压力。前端是用FreeMarker编写的模板。在网上查阅的使用FreeMarker静态化页面的方案大致分为两种:

 

1.在controller层编写生成静态页的方法,实例化模板,准备好model数据,然后通过template.process(data, out)方法将页面内容写到文件。参考【博客A】

 

2.扩展FreeMarker的FreeMarkerView类,覆盖doRender方法,加入根据需求静态化页面的逻辑。参考【博客B】

 

我选择的是第二种方案,个人觉得它更加优雅,更大程度的做到了代码重用。第一种方案中做的很多事是FreeMarker正常逻辑中就在做的,比如获取模板页的绝对路径并实例化模板,配置FreeMarkerConfigurer等。

 

对于静态化后的文件命名可以有两种方式:

 

1.约定式,比如:首页就放在/index.html中,id为9527的文章的内容就存放在/blog/content_9527.html。

 

2.动态式,比如:某篇文章的内容存放在/blog/20121125/5446346.html,路径根据时间和其他随机数生成。

 

这两种方式各有特点,方式一逻辑简单,网站中对这些静态页的链接地址直接写为约定的地址即可,但是这种方式有个明显的弊端,必须保证这些页的静态页一直都要存在,后期不好扩展,假如某个页不想静态化了,这时候就不好办了。

 

第二种方式相对麻烦些,需要在数据库或者其他地方存上最新的静态的页的地址,因为地址和文件是动态生成的。但是这种方式有个明显的好处即“想动就动 想静就静”。通过数据中存放的该内容的静态页地址字段可以判断该内容是否已经静态化,然后返回静态或者动态的地址。后期比较好维护。

 

我两种方式都用了,几个肯定要静态化的页面采用了第一种方式,其他一些页面采用了第二种方式可以动静结合。

 

我在【博客B】的基础上做了修改,增加了一个处理结果回调接口。因为静态化工作发生在Controller的方法return之后,而静态化成功与否与具体的Controller业务相关,比如静态化成功了需要更改数据库中相应的静态页地址。

 

    package com.…….freemarker;  
      
    import ……  
      
    /** 
     * 扩展FreeMarker,支持静态化 
     * @author shannon 
     * 
     */  
    public class StaticSupportFreeMarkerView extends FreeMarkerView {  
      
          
        @Override  
        protected void doRender(Map<String, Object> model,  
                HttpServletRequest request, HttpServletResponse response)  
                throws Exception {  
            // Expose model to JSP tags (as request attributes).  
            exposeModelAsRequestAttributes(model, request);  
            // Expose all standard FreeMarker hash models.  
            SimpleHash fmModel = buildTemplateModel(model, request, response);  
      
            if (logger.isDebugEnabled()) {  
                logger.debug("Rendering FreeMarker template [" + getUrl()  
                        + "] in FreeMarkerView '" + getBeanName() + "'");  
            }  
            // Grab the locale-specific version of the template.  
            Locale locale = RequestContextUtils.getLocale(request);  
              
            /* 
             * 如果attribute中有key为“staticSupportInfo”的StaticSupportInfo对象就表示要生成静态页 
             */  
            StaticSupportInfo staticSupportInfo = (StaticSupportInfo)request.getAttribute("staticSupportInfo");  
            if (null == staticSupportInfo) {  
                processTemplate(getTemplate(locale), fmModel, response);  
            } else {  
                try {  
                    createHTML(getTemplate(locale), fmModel, request, response);  
                } catch (Exception e) {  
                    staticSupportInfo.staticHtmlFail();  
                }  
            }  
        }  
      
          
        /** 
         * 生成静态页 
         * @param template 
         * @param model 
         * @param request 
         * @param response 
         * @throws IOException 
         * @throws TemplateException 
         * @throws ServletException 
         */  
        public void createHTML(Template template, SimpleHash model,  
                HttpServletRequest request, HttpServletResponse response)  
                throws IOException, TemplateException, ServletException {  
            Writer writer = response.getWriter();  
            //获取配置文件中的静态页存放路径  
            String basePath = (String)CustomProperty.getContextProperty("staticHtmlPath");  
            StaticSupportInfo staticSupportInfo = (StaticSupportInfo)request.getAttribute("staticSupportInfo");  
              
            if(staticSupportInfo == null || staticSupportInfo.getTargetHtml() == null) {  
                writer.write("fail");  
                staticSupportInfo.staticHtmlFail();  
                return;  
            }  
              
            //静态页面绝对路径  
            String fullHtmlName = basePath + staticSupportInfo.getTargetHtml();  
      
            File htmlFile = new File(fullHtmlName);  
            if (!htmlFile.getParentFile().exists()) {  
                htmlFile.getParentFile().mkdirs();  
            }  
            if (!htmlFile.exists()) {  
                htmlFile.createNewFile();  
            }  
            Writer out = new BufferedWriter(new OutputStreamWriter(  
                    new FileOutputStream(htmlFile), "UTF-8"));  
              
            //处理模版    
            template.process(model, out);  
            out.flush();  
            out.close();  
            writer.write("success");  
            staticSupportInfo.staticHtmlSuccess();  
        }  
    }  

 

 

 

    package com.…….freemarker;  
      
      
    /** 
     * 封装静态化需要的属性,如果需要得知静态化处理结果,需要实现StatusCallBack回调接口 
     * @author shannon 
     * 
     */  
    public class StaticSupportInfo implements java.io.Serializable {  
          
        private static final long serialVersionUID = 295085193429020250L;  
        private String targetHtml;  
      
        private StatusCallBack statusCallBack;  
          
        /** 
         * 静态化成功,由StaticSupportFreeMarkerView类调用 
         */  
        public void staticHtmlSuccess() {  
            if (statusCallBack == null) {  
                return;  
            }  
            //回调  
            statusCallBack.success();  
        }  
          
        /** 
         * 静态化失败,由StaticSupportFreeMarkerView类调用 
         */  
        public void staticHtmlFail() {  
            if (statusCallBack == null) {  
                return;  
            }  
            //回调  
            statusCallBack.fail();  
        }  
          
        /** 
         * 目标html文件,除根目录外的其他路径和名字 
         * 如:category/app.html 
         * @return 
         */  
        public String getTargetHtml() {  
            return targetHtml;  
        }  
      
        /** 
         * 设置静态页面的文件名 
         * @param targetHtml    目标html文件,除根目录外的其他路径和名字,如:category/app.html 
         */  
        public void setTargetHtml(String targetHtml) {  
            this.targetHtml = targetHtml;  
        }  
      
        /** 
         * @return the statusCallBack 
         */  
        public StatusCallBack getStatusCallBack() {  
            return statusCallBack;  
        }  
      
        /** 
         * @param statusCallBack the statusCallBack to set 
         */  
        public void setStatusCallBack(StatusCallBack statusCallBack) {  
            this.statusCallBack = statusCallBack;  
        }  
          
        /** 
         * 静态化处理结果状态回调接口 
         * @author shannon 
         * 
         */  
        public interface StatusCallBack {  
            /** 
             * 成功 
             */  
            public void success();  
              
            /** 
             * 失败 
             */  
            public void fail();  
        }  
      
    }  

 

 

***-servlet.xml配置文件

 

    <!-- Simple ViewResolver for FreeMarker, appending ".ftl" to logical view names. -->  
        <bean id="viewResolver" class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">  
            <property name="cache" value="${view.cache}" />  
            <!-- spring对宏的支持 -->  
            <property name="exposeSpringMacroHelpers" value="true" />  
            <!-- spring 将session暴露出来 -->  
            <property name="exposeSessionAttributes" value="true" />  
            <property name="exposeRequestAttributes" value="true" />  
            <property name="requestContextAttribute" value="rc" />  
            <property name="suffix" value=".ftl" />  
            <property name="contentType" value="text/html; charset=UTF-8" />  
            <property name="viewClass" value="com.…….freemarker.StaticSupportFreeMarkerView" />  
        </bean>  

 这里以首页静态化为例,以下是首页对应的Controller层方法,只是在原来的方法上添加一个createHtml参数,这样做的好处是重用。管理员 访问http://www.***.com/index.htm?createHtml=true 链接就可以生成静态页。

 

    @RequestMapping(value = "index")  
    @NeedNavigation  
    public String index(HttpServletRequest request, Model model, String createHtml){  
        ……页面数据处理逻辑略……  
          
        //如果页面需要静态化  
        if (createHtml != null && "true".equals(createHtml)) {  
            StaticSupportInfo staticSupportInfo = new StaticSupportInfo();  
            //设置静态化文件名  
            staticSupportInfo.setTargetHtml("index.html");  
              
            //以下为实现静态化处理结果回调函数,如果不关心处理结果可以不做这一步  
            staticSupportInfo.setStatusCallBack(  
                new StaticSupportInfo.StatusCallBack() {  
                    public void fail() {  
                        System.out.println("静态化处理结果回调,静态化失败");  
                    }  
                    public void success() {  
                        System.out.println("静态化处理结果回调,静态化成功");                    
                    }  
                }  
            );  
              
            //将静态化信息支持对象放到Attribute中,注意key值不要写错  
            request.setAttribute("staticSupportInfo", staticSupportInfo);  
        }  
        return "web/home/index";   
           }  

 注:为了安全性的考虑,应该加上验证逻辑,只能是管理员访问才静态化。

 

参考博客:
【博客A】

【博客B】

分享到:
评论

相关推荐

    java Freemarker页面静态化实例详解

    总结起来,Java中的Freemarker页面静态化实例详解主要涉及Freemarker的基本用法、数据格式化以及处理空值的策略。通过对这些知识点的掌握,开发者可以有效地利用Freemarker进行静态页面生成,从而提高网站的响应速度...

    httpclient,freemarker的静态化分页

    总的来说,`httpclient`与`freemarker`在页面静态化分页中的结合使用,既保证了数据的动态获取,又实现了静态文件的高效生成,是Web开发中一种实用的优化手段。通过合理的代码组织和设计,可以构建出高效且易于维护...

    freemark 页面静态化

    总的来说,Freemarker页面静态化能够提高Web应用的性能,减少服务器负载,提升用户体验,尤其适合新闻资讯、博客等需要大量静态页面的网站。同时,它也有助于SEO优化,因为搜索引擎更容易抓取静态HTML页面。因此,...

    Jsp页面静态化(freemarker)教程及源码

    前台页面的静态化就有利于SEO,所以这个问题摆在了我的面前,在网上一搜,关于这方面的资料不是很多,又很杂,关于这方面的知识,越来或多的程序员将会碰到,原来项目中这部分静态化的功能主要由我来做的,现在我将...

    Freemarker网站静态化的实现实例源码(eclipse)

    本实例源码是关于如何利用Freemarker进行网站静态化的具体实践,主要涉及到以下几个核心知识点: 1. **Freemarker模板语言**:Freemarker使用简单的文本模板语言,将数据模型与HTML模板结合,生成最终的HTML页面。...

    SpringBoot2 整合FreeMarker模板,完成页面静态化处理.docx

    【SpringBoot2 整合FreeMarker模板,完成页面静态化处理】 在Web开发中,页面静态化是一种提高网站性能和用户体验的技术。它涉及到将原本动态生成的页面转换为静态HTML文件,减少对服务器的依赖,加快页面加载速度...

    struts1.2+freemarker实现登录成功页面静态化例子

    总结来说,这个例子展示了如何结合Struts1.2和Freemarker2.3.8实现登录成功页面的静态化,通过静态化可以提高网站性能,减轻服务器负担,提升用户体验。在实际开发中,开发者可以根据项目需求灵活运用这些技术和策略...

    freemarker把jsp静态化简单应用

    本教程将介绍如何在Java Web项目中利用FreeMarker进行JSP页面的静态化,适合初学者入门学习。 1. **FreeMarker基本概念** FreeMarker是一个基于模板的语言,它与编程语言不同,不包含任何控制结构或函数调用。它的...

    有关Java页面静态化

    Java页面静态化主要有两种方式:服务器端静态化和客户端静态化。 1. 服务器端静态化: - **预渲染(Prerendering)**:在用户请求之前,系统自动将一些常用或者热点页面生成静态HTML文件,存储在文件系统或CDN上。...

    java JSP页面静态化总结_动态页面变为静态页面以减少访问数据库的次数提高速度.zip

    1. **JSP页面静态化原理**: - JSP页面静态化的核心思想是将原本需要服务器实时解析的动态内容,提前转换为静态HTML文件,存储在服务器上。这样,当用户请求这些页面时,服务器不再需要执行JSP脚本,而是直接返回...

    java 页面静态化

    在进行页面静态化时,我们还需要考虑一些问题,比如如何处理动态内容(如用户登录状态、个性化推荐)、如何同步静态文件和动态数据、以及如何清理过期的静态文件等。这些问题可以通过设计合理的缓存策略和定时任务来...

    ssh+FreeMarker静态化网页例子

    ssh+FreeMarker静态化网页例子

    教你如何用FreeMarker生成静态页面.doc

    本篇文章将详细讲解如何利用FreeMarker来生成静态页面。 首先,我们需要理解FreeMarker的基本工作原理。在FreeMarker模板文件中,我们可以编写HTML结构,同时嵌入特定的FreeMarker语法,如`&lt;#if&gt;`、`&lt;#foreach&gt;`等...

    struts2+freemarker 生成静态页面

    4. **实现过程**:在Struts2中,可以通过自定义Result类型来实现静态化。这个Result类型会在Action处理完请求后,将生成的FreeMarker模板内容写入到一个静态HTML文件中。同时,需要设置适当的缓存策略,例如根据内容...

    Struts2整合Freemarker生成静态页面

    这通常通过在Action中触发静态化逻辑,将Freemarker渲染后的HTML保存到磁盘,然后直接返回这些静态页面。 9. **错误和异常处理**:Struts2和Freemarker都有自己的错误处理机制。当模板或Action执行出错时,可以通过...

    动态页面静态化汇总--页面静态化方案

    在动态页面静态化中,Freemarker可以用来生成静态HTML文件,模板中填入数据模型后,静态页面即可自动生成。 3. **URLRewrite**: URLRewrite是一个常用的Apache服务器模块,它可以实现URL重写功能。在静态化过程中...

    页面静态化

    页面静态化是Web开发中的一个重要概念,主要目的是提高网站的访问速度和搜索引擎优化(SEO)。在Java Web开发中,页面静态化通常涉及到将动态生成的HTML页面转化为纯HTML文件,以便用户请求时无需通过服务器执行复杂...

    springboot整合FreeMarker模板,完成页面静态化处理

    、页面静态化 1、动静态页面 静态页面 即静态网页,指已经装载好内容HTML页面,无需经过请求服务器数据和编译过程,直接加载到客户浏览器上显示出来。通俗的说就是生成独立的HTML页面,且不与服务器进行数据交互。 ...

Global site tag (gtag.js) - Google Analytics