WEB网站架构分析HTML静态化

发布时间:2013-03-28 09:43:40   来源:文档文库   
字号:

HTML静态化

1 介绍

其实大家都知道,效率最高、消耗最小的就是纯静态化的html页面,所以我们尽可能使我们的网站上的页面采用静态页面来实现,这个最简单的方法其实也是最有效的方法。但是对于大量内容并且频繁更新的网站,我们无法全部手动去挨个实现,于是出现了我们常见的信息发布系统CMS,像我们常访问的各个门户站点的新闻频道,甚至他们的其他频道,都是通过信息发布系统来管理和实现的,信息发布系统可以实现最简单的信息录入自动生成静态页面,还能具备频道管理、权限管理、自动抓取等功能,对于一个大型网站来说,拥有一套高效、可管理的CMS是必不可少的。
除了门户和信息发布类型的网站,对于交互性要求很高的社区类型网站来说,尽可能的静态化也是提高性能的必要手段,将社区内的帖子、文章进行实时的静态化,有更新的时候再重新静态化也是大量使用的策略,像Mop的大杂烩就是使用了这样的策略,网易社区等也是如此。
同时,html静态化也是某些缓存策略使用的手段,对于系统中频繁使用数据库查询但是内容更新很小的应用,可以考虑使用html静态化来实现,比如论坛中论坛的公用设置信息,这些信息目前的主流论坛都可以进行后台管理并且存储再数据库中,这些信息其实大量被前台程序调用,但是更新频率很小,可以考虑将这部分内容进行后台更新的时候进行静态化,这样避免了大量的数据库访问请求

提升网站性能的方式有很多,例如有效的使用缓存,生成静态页面等等,本文主要介绍Java高并发:HTML静态页化。

1.1 什么是静态页面

静态页面是独立的html、htm后缀文件,不需要经过服务器的编译,可以直接加载到客户浏览器上显示出来。

1.2 为什么要将网站修改为静态页面

1) 加快页面打开浏览速度,不用调用数据库,访问速度比一般动态网站快5-10倍。

2) 有利于搜索引擎优化SEO,百度谷歌等搜索引擎都会优先收录静态页面。不仅被收录的快还收录的全。并且在排名中静态页面的排名权重要高于动态路径的页面。

3) 网站更安全,静态页面从理论上讲是完全没有漏洞的。数据库出错时,不影响网站正常访问。

4) 缺点:无法即时更新,每次更新内容都需要生成静态页面。

1.3 静态化需要考虑三个方面的事情

1, SEO,能够让搜索引擎更方便的进行采集和分类,提升其速度和准确性。

2, 对用户,不能影响版面的展示,不能为了速度影响了美观和可用性

3, 对维护,一些内容可以方便的更换,比如菜单调整,连接调整,广告位的调整等

2 Java实现html静态化方案

java页面静态化解释:简单的说,我们如果访问一个链接 ,服务器对应的模块会处理这个请求,转到对应的jsp界面,最后生成我们想要看到的数据。这其中的缺点是显而易见的:因为每次请求服务器都会进行处理,如果有太多的高并发请求,那么就会加重应用服务器的压力,弄不好就把服务器搞down 掉了。那么如何去避免呢?如果我们把对 test.do 请求后的结果保存成一个 html 文件,然后每次用户都去访问 ,这样应用服务器的压力不就减少了?那么静态页面从哪里来呢?总不能让我们每个页面都手动处理吧?这里就牵涉到我们要讲解的内容了,静态页面生成方案… 我们需要的是自动的生成静态页面,当用户访问 ,会自动生成 test.html ,然后显示给用户。

2.1 页面静态化方案应该掌握的知识点

1、 基于- URL Rewrite

伪静态URL重写实际就是以静态地址(如:http://127.0.0.1:8080/pro/index.html)访问地态网页的方法(如:http://127.0.0.1:8080/pro/index.jsp)。

伪静态URL重写是通过微软公司封装好了的一个URL重写组件(UrlReswriter.jar)来实现的,导入JAR包,在WEB服务中加载伪静态地址拦截器,客户端以静态地址向服务器发起请求,服务器端的拦截器拦截客户端请求,查找XML配置文件,把静态的URL地址转换成动态地址,发起请求。

2、 基于 Servlet web.xml

Struts或servlet接收请求,如test.action,对请求的url进行处理,判断是否生成静态html页面。

其中,对于 URL Rewriter的部分,可以使用收费或者开源的工具来实现,如果 url不是特别的复杂,可以考虑在 servlet 中实现,那么就是下面这个样子:

2.2 JSP生成静态HTML页面最普遍的三种方法

Jsp静态化解释:对于现在的Web Application来说,动态页面是占有绝对高的地位的,正因为有了动态化,才有了现在Web的丰富多彩,但是如同所有别的事实一样,好处往往都是有代价的。为了产生出动态的效果,每一次对页面的请求都会要求服务器对页面进行编译或者执行,这些操作都很消耗系统资源。如果这期间还有和数据库的通讯,那么代价将会更大。
如果一个页面在一定的时间内,其内容没有发生改变,那么就不必为每一次对它的访问进行一次“新”的编译或执行。我们可以把它在这段没有发生改变的时间内的 结果保存到一个静态的页面里面,然后每次访问这个页面时,就用刚才保存的静态页面进行回复。这样便能大大地减少系统资源的消耗,并且提高对客户的响应速 度。而这个过程就称之为页面静态化。现在所面临的问题就是如何在JSP中将页面的内容保存下来。在访问JSP页面的时候,服务器会先将JSP文件编译为Servlet文件,然后对这个Servlet编译、执行,并最终把结果返回给客户端。而我们的任务就是要把这个最终生成的HTML静态页面保留下来,存放在服务器上。解决的方法其实很简单。普通的对于JSP的访问,最终的数据流是回写到客户端的,如果我们把它重定向,让它回写到服务器上一个本地的文件,这样就能把JSP的执行结果保存起来,而这个文件就是我们想要得到的静态化的结果。

2.2.1 从数据库中取相应数据并替换掉模板中的对应标签

1.buildhtml.jsp
<%@ page contentType="text/html; charset=gb2312" import="java.util.*,java.io.*"%>
<%
try{
String title="This is Title";
String content="This is Content Area";
String editer="LaoMao";
String filePath = "";
filePath = request.getRealPath("/")+"test/template.htm";
String templateContent="";
FileInputStream fileinputstream = new FileInputStream(filePath);//读取模块文件
int lenght = fileinputstream.available();
byte bytes[] = new byte[lenght];
fileinputstream.read(bytes);
fileinputstream.close();
templateContent = new String(bytes);
//out.print(templateContent);
templateContent=templateContent.replaceAll("###title###",title);
templateContent=templateContent.replaceAll("###content###",content);
templateContent=templateContent.replaceAll("###author###",editer);//替换掉模块中相应的地方
//out.print(templateContent);
// 根据时间得文件名
Calendar calendar = Calendar.getInstance();
String fileame = String.valueOf(calendar.getTimeInMillis()) +".html";
fileame = request.getRealPath("/")+fileame;//生成的html文件保存路径
FileOutputStream fileoutputstream = new FileOutputStream(fileame);//建立文件输出流
byte tag_bytes[] = templateContent.getBytes();
fileoutputstream.write(tag_bytes);
fileoutputstream.close();
}
catch(Exception e){
out.print(e.toString());
}
%>

2. template.htm


###title###






     
    
  
     
    
  
  
    
  
###title###
author###author###  
###content###


2.2.2 从动态页的URL获取相应页面内容并写入到文件

/*
* Created on 2013-3-19
* To change the template for this generated file go to
* Window>Preferences>Java>Code Generation>Code and Comments
*/
package com.easydone.cn.tools.utils;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Date;

/**
* @author Administrator
* To change the template for this generated type comment go to
* Window>Preferences>Java>Code Generation>Code and Comments
*/
public class MakeHtml {
         private static long star = 0;
         private static long end = 0;
         private static long ttime = 0;

         //返回html代码
         public static String getHtmlCode(String httpUrl){
         Date before = new Date();
         star = before.getTime();
         String htmlCode = "";
         try {
         InputStream   in;
         URL url = new java.net.URL(httpUrl);
         HttpURLConnection connection = (HttpURLConnection)url.openConnection();
         connection = (HttpURLConnection) url.openConnection();
         connection.setRequestProperty("User-Agent","Mozilla/4.0");
         connection.connect();
         in = connection.getInputStream();
         java.io.BufferedReader breader = new BufferedReader(new InputStreamReader(in , "GBK"));
         String currentLine;
           while((currentLine=breader.readLine())!=null){
         htmlCode+=currentLine;
           }
         } catch (Exception e) {
         e.printStackTrace();
         }finally{
         Date after = new Date();
         end = after.getTime();
         ttime = end-star ;
         System.out.println("执行时间:"+ttime +"");
         }
         return htmlCode;
         }
         //存储文件
         public static synchronized void writeHtml(String filePath,String info,String flag) {

         PrintWriter pw = null;
         try {
         File writeFile = new File(filePath);
         boolean isExit = writeFile.exists();
         if (isExit != true) {
         writeFile.createNewFile();
         } else {
         if (!flag.equals("NO")) {
         writeFile.delete();
         writeFile.createNewFile();
         }  
         }
         pw = new PrintWriter(new FileOutputStream(filePath, true));
         pw.println(info);
         pw.close();
         } catch (Exception ex) {
         System.out.println(ex.getMessage());
         }finally{
         pw.close();
         }
         }

         public static void main(String[] args) {
         String url = "http://www.easydone.cn/index.htm";
         writeHtml("c:/demo.htm",getHtmlCode(url),"NO");
         }
}

2.2.3 利用Filter定制Response,把服务器返回的JSP响应输出到我们自己的Response中,就可以将响应快速写入Html文件,然后再发送给客户。

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.util.Calendar;

public class CacheFilter implements Filter {
   ServletContext sc;
   FilterConfig fc;
   long cacheTimeout = Long.MAX_VALUE;

   public void doFilter(ServletRequest req,
                        ServletResponse res,
                        FilterChain chain)
       throws IOException, ServletException {
     HttpServletRequest request =
         (HttpServletRequest) req;
     HttpServletResponse response =
         (HttpServletResponse) res;

     // check if was a resource that shouldn't be cached.
     String r = sc.getRealPath("");
     String path =  
         fc.getInitParameter(request.getRequestURI());
     if (path!= null && path.equals("nocache")) {
       chain.doFilter(request, response);
       return;
     }
     path = r+path;

     String id = request.getRequestURI() +  
         request.getQueryString();
     File tempDir = (File)sc.getAttribute(
       "javax.servlet.context.tempdir");

     // get possible cache
     String temp = tempDir.getAbsolutePath();
     File file = new File(temp+id);

     // get current resource
     if (path == null) {
       path = sc.getRealPath(request.getRequestURI());
     }
     File current = new File(path);

     try {
       long now =
         Calendar.getInstance().getTimeInMillis();
       //set timestamp check
       if (!file.exists() || (file.exists() &&
           current.lastModified() > file.lastModified()) ||
           cacheTimeout < now - file.lastModified()) {
         String name = file.getAbsolutePath();
         name =
             name.substring(0,name.lastIndexOf("/"));
         new File(name).mkdirs();
         ByteOutputStream baos =
             new ByteOutputStream();
         CacheResponseWrapper wrappedResponse =
           new CacheResponseWrapper(response, baos);
         chain.doFilter(req, wrappedResponse);

         FileOutputStream fos = new FileOutputStream(file);
         fos.write(baos.toByte());
         fos.flush();
         fos.close();
       }
     } catch (ServletException e) {
       if (!file.exists()) {
         throw new ServletException(e);
       }
     }
     catch (IOException e) {
       if (!file.exists()) {
         throw e;
       }
     }

     FileInputStream fis = new FileInputStream(file);
     String mt = sc.getMimeType(request.getRequestURI());
     response.setContentType(mt);
     ServletOutputStream sos = res.getOutputStream();
     for (int i = fis.read(); i!= -1; i = fis.read()) {
       sos.write((byte)i);
     }
   }

   public void init(FilterConfig filterConfig) {
     this.fc = filterConfig;
     String ct =
         fc.getInitParameter("cacheTimeout");
     if (ct != null) {
       cacheTimeout = 60*1000*Long.parseLong(ct);
     }
     this.sc = filterConfig.getServletContext();
   }

   public void destroy() {
     this.sc = null;
     this.fc = null;
   }
}

2.3 使用URLRewirte实现url地址伪静态化

URLRewirte的用处: 
1.满足搜索引擎的要求 
2.隐藏技术实现,提高网站的移植性 
3.满足美感的要求

项目部署 
1.首先在http://tuckey.org/urlrewirte/下载urlrewirtefilter 
2.解压所下载的文件,urlrewrite-2.6.0.jar复制到项目的WebRoot/WEB-INF/lib/目录下,然后编译 
3.urlrewrite.xml复制到项目的WebRoot/WEB-INF/目录下 
4.web.xml文件中加入以下

 1word/media/image3.gif  
 2word/media/image3.gif<filter>  
 3word/media/image3.gif  <filter-name>UrlRewriteFilterfilter-name>  
 4word/media/image3.gif  <filter-class>org.tuckey.web.filters.urlrewrite.UrlRewriteFilterfilter-class>  
 5word/media/image3.gif  <init-param>  
 6word/media/image3.gif    <param-name>logLevelparam-name>  
 7word/media/image3.gif    <param-value>WARNparam-value>  
 8word/media/image3.gif  init-param>  
 9word/media/image3.giffilter>  
10word/media/image3.gif<filter-mapping>  
11word/media/image3.gif  <filter-name>UrlRewriteFilterfilter-name>  
12word/media/image3.gif  <url-pattern>/*url-pattern>  
13word/media/image3.giffilter-mapping>  
14word/media/image3.gif


5.需要配置urlrewrite.xml文件来实现url静态化,下面将详细说明 

到这里相关的配置已经完成,下面看如何把动态地址静态化 
1.普通url静态化 
例如:要把http://localhost/prjtest/user/list.jsp转换成http://localhost/prjtest/user/list.html 
这种是最简单的,当一个servlet跳转到list.jsp页面列出user列表时,urlrewrite.xml中这样配置: 

1word/media/image3.gif<rule>  
2word/media/image3.gif  <from>^/user/list.htmlfrom>  
3word/media/image3.gif  <to type="redirect">/user/list.jspto>  
4word/media/image3.gifrule>  

当请求/user/list.html这个页面时,实际上相当于请求/user/list.jsp页面 
servlet的跳转要这样写: 
response.sendRedirect("./user/list.html"); 
2.带参数的url静态化 
例如:要把http://localhost/prjtest/user/view.jsp?cid=1&cname=admin转换成 
       http://localhost/prjtest/user/view/1_admin.html 
urlrewrite.xml中这样配置: 

1word/media/image3.gif<rule>  
2word/media/image3.gif  <from>^/user/view/([0-9]+)_([a-z]+).html$from>  
3word/media/image3.gif  <to type="redirect">/user/view.jsp?cid=$1&cname=$2to>  
4word/media/image3.gifrule>  


当请求/user/view/1_admin.html这个页面时,实际上相当于请求/user/list.jsp?cid=1&cname=admin页面 
servlet的跳转要这样写(cid,cname为变量): 
response.sendRedirect("./user/view/"+ cid +"_"+ cname +".html"); 
注意:配置文件中用"&"来代替"&" 
一个通用的正则表达式:[a-zA-Z0-9]+ 

2.4 JAVA 利用freemarker生成html静态页面。

Freemarker是一个用java编写的模版引擎,主要用来生成web html页面,通常由java程序准备要显示的数据,与freemarker生成静态页面。编写ftl模版可以生成html代码,必须导入freemarker

核心代码:

1.  private Configuration tempConfiguration; 

2.   public void setTempConfiguration(Configuration tempConfiguration) {
        this.tempConfiguration = tempConfiguration;
    }

1.    

2.     public static void crateHTML(ServletContext context,  

3.            Map data, String templatePath, String targetHtmlPath) {

4.         try { 

5.              //filepath:ftl存放路径(/template/file/static

6.             this.tempConfiguration.setDirectoryForTemplateLoading(new File(filePath)); 

7.            //templatePath:ftl文件名称(template.ftl

8.             Template template = this.tempConfiguration.getTemplate(templatePath);  

9.             template.setEncoding("UTF-8");  

10.               

11.             String htmlPath = targetHtmlPath;  

12.             File htmlFile = new File(htmlPath);  

13.             Writer out = new BufferedWriter(new OutputStreamWriter(  

14.                     new FileOutputStream(htmlFile), "UTF-8"));  

15.              map数据 ,输出流

16.             template.process(data, out);  

17.             out.flush();  

18.             out.close();  

19.               

20.         } catch (Exception e) {  

21.             e.printStackTrace();  

22.         }  

23.           

24.     }  

本文来源:https://www.2haoxitong.net/k/doc/0fe976df28ea81c758f5787d.html

《WEB网站架构分析HTML静态化.doc》
将本文的Word文档下载到电脑,方便收藏和打印
推荐度:
点击下载文档

文档为doc格式