当前位置:编程学习 > JAVA >>

经验分享:Freemarker网站静态化的实现(原创)

   做程序也做了将近4年时间了,从来没有发过什么技术性的文章,今天发一个只在大家一起共同学习进步,如有错误地方请指正。
   最近自己做了一个做网络广告的网站叫全方位商机平台的项目,由于网站首页上板块划分很多,不同板块的数据库查询方式不同,首页内容量巨大,如果按照一般的动态jsp页面的话那么数据库查询将是巨大的开销,会导致首页访问速度的下降。于是考虑将这个首页全部静态化。参考地址:http://www.31pt.com/。首页的速度是非常快的。
   整个网站才用struts2 + spring + hibernate + freemarker + urlrewrite完成。首页纯静态化,频道及其他页面通过urlrewrite伪静态。现在废话少说。我先给出首页jsp body源代码:

<body>
<div id="wrap">
    <!--头部开始-->
    <jsp:include page="/html/top.html" flush="true"></jsp:include>
    <!--头部结束-->
    <!--导航开始-->
    <jsp:include page="/html/channel.html" flush="true"></jsp:include>
    <!--导航结束-->
    <jsp:include page="/html/center.html" flush="true"></jsp:include>
    <!--友情连接开始-->
    <jsp:include page="/html/index_link.html" flush="true"></jsp:include>
    <!--友情结束-->
    <!--底部开始-->
    <jsp:include page="/html/bottom.html" flush="true"></jsp:include>
    <!--底部结束-->
</div>
</body>

整个网站首页的基本结构是通过jsp的include标签将所有通过freemarker生成的静态页面组织起来。后台控制各个部分的静态页生成。这样做将首页进行了拆分,便于了静态页面的维护,当我们需要生成“友情链接”部分的时候就只生成友情链接部分,而不需要将整个页面都从新生成一次。
   以下是我生成静态页最核心的方法,使用freemarker。

         /**
 * 生成静态页面主方法
 * @param context ServletContext
 * @param data 一个Map的数据结果集
 * @param templatePath ftl模版路径
 * @param targetHtmlPath 生成静态页面的路径
 */
public static void crateHTML(ServletContext context,Map<String,Object> data,String templatePath,String targetHtmlPath){
Configuration freemarkerCfg = new Configuration();
//加载模版
freemarkerCfg.setServletContextForTemplateLoading(context, "/");
freemarkerCfg.setEncoding(Locale.getDefault(), "UTF-8");
try {
//指定模版路径
Template template = freemarkerCfg.getTemplate(templatePath,"UTF-8");
template.setEncoding("UTF-8");
//静态页面路径
String htmlPath = context.getRealPath("/html")+"/"+targetHtmlPath;
File htmlFile = new File(htmlPath);
            Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(htmlFile), "UTF-8"));
            //处理模版  
            template.process(data, out);
            out.flush();
            out.close();
} catch (Exception e) {
e.printStackTrace();
}
}

其实很简单,只要Google一下就有很多这方面的代码。我也是Google的代码然后自己再根据实际情况修改。简单说明一下参数:
ServletContext :这个不用说了吧。做java web的应该都知道,只不过struts2中这样获取ServletActionContext.getServletContext()
Map<String,Object> data : 模版的数据来源。freemarker通过一个Map给ftl模版送数据。
现在已友情链接为列子详细介绍静态页面如何生成。其他模块以此类推。
String templatePath : ftl所在的路径。我这里相对于网站的一个相对路径然后通过ServerContext获取绝对路径。
String targetHtmlPath : 最后生成静态页的路径:我这里相对于网站的一个相对路径然后通过ServerContext获取绝对路径。

友情链接根据这段代码<jsp:include page="/html/index_link.html" flush="true"></jsp:include>我们需要freemarker生成一个index_link.html文件。友情链接数据来源通过数据库查询获取。
然后再写一个方法专门生成友情链接静态页面:

         /**
 * 生成友情链接的静态页index_link.html
 * @param context
 * @param data
 */
public static void createIndexFriendLink(ServletContext context,Map<String,Object> data){
crateHTML(context,data,"index_link.ftl","index_link.html");
}

此方法调用上面的createHTML方法。
然后根据以上方法我们就可以再Struts2的action里面从数据库查询数据放入map调用createIndexFriendLink()方法生成静态页了。
这是action中的一个方法:

         /**
 * 生成友情链接静态页index_link.html
 * @return
 */
public String createLink(){
//权限验证
if(! this.isAccess())
return "error";
try{
//得到友情链接
List links = friendLinkDAO.findAll();
//准备数据
HashMap<String,Object> data = new HashMap<String,Object>();
data.put("links", links);
//调用静态页面方法
HTML.createIndexFriendLink(ServletActionContext.getServletContext(), data);
addActionMessage("静态页面生成成功!");
return "message";
}catch(Exception e){
e.printStackTrace();
return "failure";
}
}

List links = friendLinkDAO.findAll();通过spring注入action的hiberate DAO获取数据给list然后通过以下代码
HashMap<String,Object> data = new HashMap<String,Object>();
data.put("links", links);
准备数据调用createIndexFriendLink()方法。
以下是:ftl模版源码:

<#if links?size != 0>
<div class="link">
    <strong>友情链接:</strong>
    <#list links as link>
<a href="${link.linkUrl}" target="_blank" title="${link.linkName}">${link.linkName}</a>
</#list>
</div>
<#else>
<div class="link"></div>
</#if>


这样友情链接静态页就生成了。然后其他静态页依此葫芦画瓢。

总结:虽然静态页访问速度快和其他的好处,但实现起来毕竟还是很麻烦了,维护也是一个麻烦事情。如果您的站点更新速度快那么就需要在你的后台数据更新部分调用相应的createHTML方法实时的生成静态页面。如果更新速度不慢可以在后台手动更新或者利用操作系统的定时任务功能去执行你的静态页面生成程序。www.361pt.com这个网站我是才用了这两种方式。

本人第一次发帖,还请大家各抒己见,指正不足! --------------------编程问答-------------------- 顶!一定要顶!
--------------------编程问答-------------------- 支持! --------------------编程问答-------------------- 推荐 --------------------编程问答-------------------- 顶一个。 --------------------编程问答-------------------- 崇拜。。 --------------------编程问答-------------------- 呵呵呵   顶一下哈。。  --------------------编程问答--------------------
引用 6 楼 haitao_hehe 的回复:
呵呵呵  顶一下哈。。 


不要笑人家嘛。。 --------------------编程问答-------------------- 嘿嘿
lz说的这个方法挺牛的,不过要是能够指导我做url重写那就好了。。。。
网上的说的都太麻烦了。。。。 --------------------编程问答--------------------
引用 8 楼 motow 的回复:
嘿嘿 
lz说的这个方法挺牛的,不过要是能够指导我做url重写那就好了。。。。 
网上的说的都太麻烦了。。。。

其实url重新用urlrewrite很简单的,只是做一个简单的xml配置就行了,要用到正则表达式。给你一个参考
<rule>
<from>^/notice/view_notice_([0-9]+).html$</from>
<to type="forward">/notice/notice.action?id=$1</to>
</rule> --------------------编程问答-------------------- 恩 还不错 --------------------编程问答-------------------- 向LZ学习。。。 --------------------编程问答-------------------- 占个位置
顶下 --------------------编程问答-------------------- thanks quite good! --------------------编程问答-------------------- 恩 还不错 ........ --------------------编程问答-------------------- 其实首页纯静态化后还需要解决一个问题就是登陆状态的问题。 --------------------编程问答-------------------- ~\(≧▽≦)/~  赞一个 --------------------编程问答-------------------- 支持! --------------------编程问答-------------------- 学习,帮顶了 --------------------编程问答-------------------- mark --------------------编程问答--------------------
引用 8 楼 motow 的回复:
嘿嘿 
lz说的这个方法挺牛的,不过要是能够指导我做url重写那就好了。。。。 
网上的说的都太麻烦了。。。。
顶 --------------------编程问答-------------------- 帮忙顶一下!如果不需要实时显示数据,静态页面是个不错的选择,不过动态的东西不一定就速度慢,关键是代码质量了! --------------------编程问答-------------------- 收藏!帮顶! --------------------编程问答-------------------- 顶,支持 --------------------编程问答-------------------- 虽看不懂但也要顶一下! --------------------编程问答-------------------- 虽看不懂但也要顶一下! --------------------编程问答--------------------
引用 21 楼 ProvidenceZY 的回复:
帮忙顶一下!如果不需要实时显示数据,静态页面是个不错的选择,不过动态的东西不一定就速度慢,关键是代码质量了!

对头!~其实静态页最大的好处是在于减轻了服务器的压力,其次才是速度。在一个大型高并发的网站优势是明显的。 --------------------编程问答-------------------- 不错,学习 --------------------编程问答-------------------- 可以参考 呵呵 ... --------------------编程问答-------------------- 狂顶,我喜欢你。。。的这段代码! --------------------编程问答-------------------- 我想问一下不建一个虚拟路径么?如果网站重新部署一下原来生成的 HTML 文件不就没有了么? --------------------编程问答-------------------- public static void crateHTML(ServletContext context,Map<String,Object> data,String templatePath,String targetHtmlPath){

不要把 ServletContext 传进去,可以直接传个路径或者 File 对象进去,这样耦合性会更小一些。

就这个方法的参数,我感觉就有很多的东西可以改进一下。 --------------------编程问答-------------------- 给其其顶一个 哈哈! --------------------编程问答-------------------- 顶一个.. --------------------编程问答-------------------- 不错,支持一下 --------------------编程问答-------------------- 值得学习 --------------------编程问答-------------------- 学习 --------------------编程问答-------------------- liu --------------------编程问答-------------------- 学习下 --------------------编程问答-------------------- 很好  学习中 --------------------编程问答-------------------- 蛮好的嘛!!继续加油↖(^ω^)↗,,给我们提供好的(*^__^*) 嘻嘻……!! --------------------编程问答--------------------
引用 31 楼 bao110908 的回复:
public static void crateHTML(ServletContext context,Map <String,Object> data,String templatePath,String targetHtmlPath){ 

不要把 ServletContext 传进去,可以直接传个路径或者 File 对象进去,这样耦合性会更小一些。 

就这个方法的参数,我感觉就有很多的东西可以改进一下。

我把ServletContext 传进来其实是为了能过得到模版的绝对路径,其实也可以再action里面获取后传进来路径,我是为了想减少action里面的代码行数才把ServletContext 传进来的,传进来了确实这个方法就只能用在action或者servlet里了。 --------------------编程问答-------------------- 支持!!! --------------------编程问答-------------------- 学习了 --------------------编程问答--------------------
引用 30 楼 bao110908 的回复:
我想问一下不建一个虚拟路径么?如果网站重新部署一下原来生成的 HTML 文件不就没有了么?

呵呵在开发的时候重新部署肯定就没了,没了你在重新生成一次就行了撒,毕竟是开发。但是我们在实际的生产应用中部署到服务器上了你就只会对他更新了,就不存在重新部署的问题了。那么你的html文件就不会没有了。我们只会对他进行重新覆盖生成。 --------------------编程问答-------------------- 学习学习 --------------------编程问答-------------------- 路过,顶一个 --------------------编程问答-------------------- 学习中 --------------------编程问答-------------------- 向您学习啦 --------------------编程问答-------------------- 采用这种            //准备数据
            HashMap<String,Object> data = new HashMap<String,Object>();
            data.put("links", links);
方式替换数据没什么复杂的,关键如果采用自定义标签,而该标签有属性,你这个就行不通了。
比如:
<div class="channel_news_list_m">
[@cms.ArtiList count='20' sysContent='1-1' titLen='50' lineHeight='7' dateFormat='1' datePosition='2' headMark='4' bottomLine='1' sysPage='1' isPage='1' pageClass='pagination'/]
</div>

如果想实现简单的静态化,可以采纳,但是复杂的这种方式是行不通的,大家可以讨论讨论,
我也写了一篇帖子,大家多多交流下。 --------------------编程问答-------------------- 我不是打击你哈,望谅解,大家可以讨论下,JAVA的静态化方案,使用这种方式不行。 --------------------编程问答-------------------- 俺顶! --------------------编程问答-------------------- 学习下 --------------------编程问答-------------------- 很不错的思路





--------------------编程问答-------------------- up......
--------------------编程问答-------------------- 学习 --------------------编程问答-------------------- 顶!!! --------------------编程问答-------------------- --------------------编程问答-------------------- 没做过静态页面,不过自己有想法。能不能做个非公开的动态首页,在写个小程序,监测数据库或按时间做触发条件,触发后把动态首页生成的HTML源码填充覆盖到让人访问的首页不就得了。。
小程序只需要抓取www.xxxx.com/indexBeck的源码,然后操作文件流把源码写到xxxx/index.html就好了。 --------------------编程问答-------------------- mark下,以后看,谢谢分享。 --------------------编程问答-------------------- mark! --------------------编程问答-------------------- mark --------------------编程问答--------------------
引用 50 楼 shshy39 的回复:
我不是打击你哈,望谅解,大家可以讨论下,JAVA的静态化方案,使用这种方式不行。

我不怕打击,这种方式我觉得已经实现了静态化,虽然首页还是index.jsp但是它里面全是静态html代码。还有你说的自定义标签我觉得没这个必要,别人给你提供了标签了已经可以达到要求,为什么要自己去发明轮子呢?如果你有更好的方式我们可以一起来探讨! --------------------编程问答-------------------- 只会使用DREAMWEAVER8.0的飘过 --------------------编程问答-------------------- 学习... --------------------编程问答--------------------
引用 62 楼 imyourgod 的回复:
引用 50 楼 shshy39 的回复:
我不是打击你哈,望谅解,大家可以讨论下,JAVA的静态化方案,使用这种方式不行。 


我不怕打击,这种方式我觉得已经实现了静态化,虽然首页还是index.jsp但是它里面全是静态html代码。还有你说的自定义标签我觉得没这个必要,别人给你提供了标签了已经可以达到要求,为什么要自己去发明轮子呢?如果你有更好的方式我们可以一起来探讨!

那你看看这个帖子,你就知道了:
http://topic.csdn.net/u/20090611/16/e82c88f3-70b8-457b-b898-b125a5da65c1.html --------------------编程问答-------------------- 学习··· --------------------编程问答-------------------- 好 学习中 --------------------编程问答-------------------- 学习学习,方法挺好。 --------------------编程问答-------------------- --------------------编程问答-------------------- 先回个帖再看 --------------------编程问答-------------------- 我也做这个,而且就现在,以前没有做过,感觉一头雾水啊 --------------------编程问答-------------------- 为什么不直接生成HTML呢? --------------------编程问答-------------------- 不错的~~顶一个~~ --------------------编程问答-------------------- 学习中... --------------------编程问答-------------------- 学习中…… --------------------编程问答-------------------- 关注。。 --------------------编程问答--------------------
引用 65 楼 shshy39 的回复:
引用 62 楼 imyourgod 的回复:
引用 50 楼 shshy39 的回复: 
我不是打击你哈,望谅解,大家可以讨论下,JAVA的静态化方案,使用这种方式不行。 


我不怕打击,这种方式我觉得已经实现了静态化,虽然首页还是index.jsp但是它里面全是静态html代码。还有你说的自定义标签我觉得没这个必要,别人给你提供了标签了已经可以达到要求,为什么要自己去发明轮子呢?如果你有更好的方式我们可以一起来探讨! 


那你看看这个帖子,…

... --------------------编程问答-------------------- 用一个嵌入的js 来实现 --------------------编程问答-------------------- cool! --------------------编程问答-------------------- very good --------------------编程问答--------------------
引用 72 楼 wwwwzf 的回复:
为什么不直接生成HTML呢?


如果整个首页直接生成一个html的话那么每次生成都做重复的动作比如导航。导航一般是不怎么变化,在我们需要变化的时候生成就行了。我将首页各个部分拆分开来对各个分别进行维护。这样好像就是所谓的低耦合吧。 --------------------编程问答-------------------- 还不错,谢谢分享 --------------------编程问答-------------------- 打不开          --------------------编程问答-------------------- 学习下 --------------------编程问答-------------------- 学习。。不错。。 --------------------编程问答-------------------- 刚刚开始学习freemarker,不知道楼主的文章对于学习freemarker是否具有代表性,建议csdn网编在推荐文章到首页的时候也考虑一下文章是不是真的有价值,不另类。否则会将初学者误入歧途。 --------------------编程问答-------------------- velocity+ssi  不是更好,连jsp都省了 --------------------编程问答-------------------- 顶+学习 --------------------编程问答-------------------- 回帖是一种美德!每天回帖即可获得 10 分可用分!  --------------------编程问答-------------------- 帮顶!学习! --------------------编程问答-------------------- 顶,向楼主学习 --------------------编程问答-------------------- 顶一个  --------------------编程问答-------------------- 不错~学习 --------------------编程问答-------------------- 学习 --------------------编程问答-------------------- 大家讨论蛮热烈的
好现象 --------------------编程问答-------------------- 回帖是一种美德!每天回帖即可获得 10 分可用分!  --------------------编程问答-------------------- 路过,顶下,再收藏!! --------------------编程问答-------------------- 请教楼主一个问题!  那如果你在后台删除了一条首页的数据了!而那条数据对应了相应一个静态页面  !
     
你是在删除数据的时候  需要把生成的那条数据的静态页面也删除掉吗? 同时还要不要重新更新下首页! --------------------编程问答--------------------
引用 15 楼 imyourgod 的回复:
其实首页纯静态化后还需要解决一个问题就是登陆状态的问题。


这个我觉得不必要去担心!  用dwr就可以解决! 看了下 楼主的网站就是用了dwr!    --------------------编程问答-------------------- 顶!
补充:Java ,  Web 开发
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,