论坛首页 入门技术论坛

Freemarker网站静态化的实现(原创)

浏览 35741 次
该帖已经被评为新手帖
作者 正文
   发表时间:2009-06-13   最后修改:2009-06-13
   做程序也做了将近4年时间了,从来没有发过什么技术性的文章,今天发一个只在大家一起共同学习进步,如有错误地方请指正。
   最近自己做了一个做网络广告的网站叫全方位商机平台的项目,由于网站首页上板块划分很多,不同板块的数据库查询方式不同,首页内容量巨大,如果按照一般的动态jsp页面的话那么数据库查询将是巨大的开销,会导致首页访问速度的下降。于是考虑将这个首页全部静态化。参考地址:http://www.361pt.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这个网站我是采用了这两种方式。
   发表时间:2009-06-13  
太麻烦了,我还是用oscache好了
0 请登录后投票
   发表时间:2009-06-13  
popoer 写道
太麻烦了,我还是用oscache好了


0 请登录后投票
   发表时间:2009-06-15  
感觉是用偏门小搞搞
0 请登录后投票
   发表时间:2009-06-15  
inthesky 写道
popoer 写道
太麻烦了,我还是用oscache好了




用oscache 流量小的还可以
好像门户网站的首页都是静态的,其好处大家都是知道的。
0 请登录后投票
   发表时间:2009-06-15  
生成的页面错问题了怎么处理
比如ftl中 <#list books as book[0..10]>这里遍历了前11个 但是如果books只有10个 那么freemarker这里会把异常打出在生成的页面上
象这种freemarker把异常输入在页面的情况怎么办的
0 请登录后投票
   发表时间:2009-06-15  
我一般是用httpclient把动态页面读过来,如果动态页面包含动态链接,那么用正则替换成静态链接,再生成静态页面;如果动态页包含的就是静态链接,直接生成静态文件就可以了
0 请登录后投票
   发表时间:2009-06-15  
SQUID 为什么不用这个呀? 毕竟你不是生成静态就可以的了, 应该包含它的整个生命周期
0 请登录后投票
   发表时间:2009-06-15  
jianfeng008cn 写道
感觉是用偏门小搞搞

呵呵。只要能达到我的目的,管他是偏还是小。你说呢?
0 请登录后投票
   发表时间:2009-06-15  
你生成的静态页面只是片断,最后使用jsp合成,这样可以随时替换一些动态的信息。

这样数据库压力是减轻了,不过应用服务器jsp合成的工作量还在(当然这种工作量不大)。

我个人建议使用全静态的页面,一些动态要更新的信息(如广告)在客户端使用AJAX来加载,土一点可以用iframe。

这样的好处是可以充分利用apache/iis对静态页面的处理能力,应用服务器就基本上不会影响浏览性能了。App Server和apache的性能差距可不是一点半点。
0 请登录后投票
论坛首页 入门技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics