标签:
通用大型网站页面静态化解决方案(一)
网站首页上板块划分很多,不同板块的数据库查询方式不同,首页内容量巨大,如果按照一般的动态jsp页面的话那么数据库查询将是巨大的开销,会导致首页访问速度的下降。于是考虑将这个首页全部静态化。
整个网站才用struts2 + spring + hibernate + freemarker + urlrewrite完成。首页纯静态化,频道及其他页面通过urlrewrite伪静态。现在废话少说。我先给出首页jsp body源代码:
Java代码
<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>
<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。
Java代码
/**
* 生成静态页面主方法
* @param context ServletContext
* @param data 一个Map的数据结果集
* @param templatePath ftl模版路径
* @param targetHtmlPath 生成静态页面的路径
*/
ublic 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();
}
/**
* 生成静态页面主方法
* @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文件。友情链接数据来源通过数据库查询获取。
然后再写一个方法专门生成友情链接静态页面:
Java代码
/**
* 生成友情链接的静态页index_link.html
* @param context
* @param data
*/
ublic static void createIndexFriendLink(ServletContext context,Map<String,Object> data){
crateHTML(context,data,”index_link.ftl”,”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中的一个方法:
Java代码
/**
* 生成友情链接静态页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”;
}
}
/**
* 生成友情链接静态页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模版源码:
Java代码
<#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>
<#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方法实时的生成静态页面。如果更新速度不慢可以在后台手动更新或者利用操作系统的定时任务功能去执行你的静态页面生成程序。
在开发大型网站时,避免不了处理大量的页面静态化操作,这样方便加快网站访问速度与流量分流,那么如何来实现呢?其实说白了比较简单,网站静态化主要包括以下几方面的工作
多个文件服务器读写,这里可采用SMB协议
页面静态化,可采用freemarker开源框架
如果考虑到大量的读写请求,则将请求分布式或采用调度的办法来解决
第一点我们首先应该考虑文件服务器与静态页面的映射关系,即什么文件应该读写到哪台服务器,这个关系最简单的办法是随机映射,然后将映射关系保存到数据库中即可,SMB常用的操作代码如下:
1. public static boolean exists(String filepath,String username,String pwd) throws Exception
2. {
3. SmbFile file = new SmbFile("smb://"+username+":"+pwd+"@"+filepath);
4. try{
5. return file.exists();
6. }catch(Exception ex){
7. return false;
8. }
9. }
10. public static boolean fileRename(String filepath,String newFilename,String username,String pwd)
11. {
12. try{
13. SmbFile f=new SmbFile("smb://"+username+":"+pwd+"@"+filepath);
14. if(f.isFile()){
15. String str=filepath.substring(0,filepath.lastIndexOf("/"));
16. str="smb://"+username+":"+pwd+"@"+str+"/"+newFilename;
17. f.renameTo(new SmbFile(str));
18. }else if(f.isDirectory()){
19. String str=filepath.substring(0,filepath.length()-1);
20. str=filepath.substring(0,str.lastIndexOf("/"));
21. str="smb://"+username+":"+pwd+"@"+str+"/"+newFilename;
22. f.renameTo(new SmbFile(str));
23. }
24. return true;
25. }catch(Exception ex){
26. return false;
27. }
28. }
29. public static void mkdir(String dir,String username,String pwd)
30. {
31. try{
32. SmbFile f=new SmbFile("smb://"+username+":"+pwd+"@"+dir);
33. if(!f.exists())
34. f.mkdir();
35. }catch(Exception ex)
36. {
37. }
38. }
39. public static void mkfile(String filepath,String username,String pwd)
40. {
41. try
42. {
43. SmbFile f=new SmbFile("smb://"+username+":"+pwd+"@"+filepath);
44. if(!f.exists())
45. f.createNewFile();
46. }catch(Exception ex)
47. {
48. }
49. }
50. public static void mkfile(String filepath,String username,String pwd,String content)
51. {
52. try
53. {
54. SmbFile f=new SmbFile("smb://"+username+":"+pwd+"@"+filepath);
55. if(!f.exists())
56. f.createNewFile();
57. writeFile(filepath,content,username,pwd);
58. }catch(Exception ex)
59. {
60. }
61. }
62. public static boolean isdir(String filepath,String username,String pwd) throws Exception
63. {
64. String dir="smb://"+username+":"+pwd+"@"+filepath;
65. SmbFile f=new SmbFile(dir);
66. return f.isDirectory();
67. }
复制代码
第二点,页面静态化可由freemarker生成,freemarker的使用比较简单,我这里不再啰嗦,重复说了
第三点,调度中心,或把静态化的请求先保存到Task中,然后通过调度中心异步执行,可用我在博客中说道的另外一篇文章解决即可
http://chinaxxren.iteye.com/blog/793764#bc2366476
标签:
原文地址:http://www.cnblogs.com/mfc-itblog/p/5156910.html