静态化和伪静态化

参考:

http://www.cnblogs.com/JeffreyZhao/archive/2009/07/05/talk-about-page-statilization.html

http://www.cnblogs.com/zhengxiqiang/archive/2009/07/04/1516720.html

http://www.google.com.hk/ggblog/googlechinablog/2008/10/blog-post_210.html

动态网址与静态网址

什么是静态网址?
一个静态网址,顾名思义,就是一个不会发生变化的网址,它通常不包含任何网址参数。例如:http://www.example.com/archive/january.htm。更新此种类型网址的页面会比较耗费时间,尤其是当信息量增长很快时,因为每一个单独的页面都必须更改编译代码。这也是为什么网站管理员们在处理大型的、经常更新的网站,像在线购物网站、论坛社区、博客或者是内容管理系统时,会使用动态网址的原因。
什么是动态网址?
如果一个网站的内容存储于一个数据库,并且根据要求来显示页面,这时就可以使用动态网址。在这种情况下,网站提供的内容基本上是基于模板形式的。通常情况下,一个动态网址看起来像这样:http://code.google.com/p/google-checkout-php-sample-code/issues/detail?id=31。您可以通过寻找像? = & 这样的符号识别出动态网址。动态网址有一个缺陷是不同的网址可以拥有相同的内容。这样导致不同的用户可能链向含有不同参数的网址,但是这些网址却都含有相同的内容。这也是为什么网络管理员有时候想要将这些动态网址重写成静态网址的原因之一。

静态化:
新闻模块如果要制作好,还是有一定的难度的,其最主要的难度 就在于生成静态伪静态化。


在各种类型的网站中,例如腾讯,都可以看到首页被各种新闻版块内容所填充,包括时事、体育、娱乐等等,这些新闻和内容版块都是在后台相关人员进行采编并纳入数据库和页面中的。可以想象, 一个大型的门户网站每天会有多少的访问量,
如果每次的用户访问都需要从数据库中读取数据,那么一 天下来可能有几百万的读取次数,这样无疑会对 Web 应用带来极大的挑战。可以观察各种门户的新闻,可以看得出来这些门户的新闻的 URL 地址的后缀都是 .html 或者是 .sht ml的,那么是不是这些网站的开发人员和采编人员当有一条新闻时就手动进行页面编写呢?显然答案是否 定的。

动态生成一个页面的开销往往很大,例如需要多次查询数据库或者外部服务。为了减少服务器端的开销,为了加快网站的运行效率,有时候在服务器端会将一个页面的整体内容保存为一个文件,这样每次在服务器端获取客户端请求的时候,只要读取相应的文件即可,而不需要重新查询数据库或外部服务并重新生成页面内容

静态化优点:新闻网站可以将一些新闻静态化,这样就能够保证服务器只需要承受较少的压力依旧可以承担 百万级的访问量,有利于网站性能。

生成静态就是将数据库中的数据或相应的字段进行静态化,例如将 .aspx 页面的文件进行静态化生成成为 .html 页面。 .html 是静态页面,当用户访问 .html 页面时无需进行数据操作和逻辑操作,对于服 务器而言只需要将 .html 文本发送到浏览器就能够显示页面的内容。这样无疑增加了访问速度。如果网站要生成静态,其基本模块流程如图 :


生成静态缺点:虽然静态化能够降低服务器的压力,但是静态化同样会牺牲很多的空间。如果将新闻数据中的每 个数据进行静态化,这也就是说每一条新闻就会生成一个 .html 页面,那么有十万条新闻就会生成十万个 .html 页面,这对服务器操作系统和 I/O 读写也有更高的要求,如果文件太多,打开文件夹的速度还 不如读取数据库。虽然静态化是一个解决方案,但是很多情况下也可以不使用静态化。如果系统不使用 静态化,可以使用非静态化的解决方案





相比之下,非静态化的解决方案在实现上来说更加容易,因为静态化的实现方案还需要解析模板。在新闻模块的编写中,可以事先考虑是选择静态化的解决方案还是选择非静态化的解决方案,静态化 的解决方案和非静态化的解决方案在开发过程中虽然可以替换,但是也有一定的开发风险。

模板技术:
新闻模块的难度不在于数据库的设计上,而在于 前台显示和静态生成,静态生成主要是要利用模板解析技术进行静态生成,模板解析技术可以使用编程 的方法进行编写也可以使用数据库进行模板技术的支持,这里使用 htm 文本作为数据库进行技术解析处 理 。

静态生成原理:
静态生成听上去非常的复杂,但是其实静态生成非常的简单。当管理员发布一条新闻,就会在数 据库中插入数据,数据插入后就应该解析模板进行静态生成。静态生成的是一个文件,这个文件可以是 一个 .html 文件或者 .shtml 文件。在生成文件之前,可以运行以下代码,示例代码如下所示。

protected void Page_Load(object sender, EventArgs e)
{
    if (!IsPostBack) // 判断加载
    {
        string str = "<b>*title*</b>"; // 模板代码
        string database = " 新闻标题 "; // 数据库字段
        string output = str.Replace("*title*", database); // 替换操作
        Response.Write(output); // 输出字符串
    }
}



上述代码简单的定义了一个模板代码,其中 str 变量被定义为标签, database 变量被定义为新闻标 题 ,当需要生成静态时,可以将模板中代码的关键字进行替换,例如这里的 *title* 替换成为 database 变量中的标签,替换完成后输出替换后的字符串生成即可。在模板代码中,模板代码如下所示。
string str = "<b>*title*</b>";

其中 *title* 是定义的标签,用于替换关键字, *title* 可以替换新闻标题数据进行呈现。


在了解了静 态生成的原理之后,就能够使用模板解析进行静态生成,示例代码如下所示。

        protected void Button1_Click(object sender, EventArgs e)
        {
            try
            {
                SqlConnection con = new SqlConnection("Data Source=(local);
                Initial Catalog=news;Integrated Security=True"); // 创建连接
                con.Open(); // 打开连接

                string strsql = "insert into news (title,time,author,content,weather,level,hits,classname) values
                ('" + TextBox1.Text + "','" + TextBox2.Text + "','" + TextBox3.Text + "','" +
                TextBox5.Text + "','" + TextBox4.Text + "','" + DropDownList1.Text + "',0,'" +
                DropDownList2.Text + "')"; //SQL 语句

                SqlCommand cmd = new SqlCommand(strsql, con); // 创建执行对象
                cmd.ExecuteNonQuery(); // 执行 SQL

                StreamReader aw = File.OpenText(Server.MapPath("template.htm")); // 打开模板
                string template = aw.ReadToEnd(); // 读取模板
                aw.Close(); // 关闭对象
                template = template.Replace("[ 新闻标题 ]", TextBox1.Text); // 替换标签
                template = template.Replace("[ 发布时间 ]", TextBox2.Text); // 替换标签
                template = template.Replace("[ 新闻作者 ]", TextBox3.Text); // 替换标签
                template = template.Replace("[ 新闻天气 ]", TextBox4.Text); // 替换标签
                template = template.Replace("[ 新闻内容 ]", TextBox5.Text); // 替换标签

                StreamWriter sw = File.CreateText(Server.MapPath("../html/" + DateTime.Now.Year.ToString()
                + DateTime.Now.Month.ToString() + DateTime.Now.Day.ToString()
                + DateTime.Now.Hour.ToString() + DateTime.Now.Second.ToString()
                + ".htm")); // 生成文件

                sw.Write(template); // 编写内容
                sw.Close(); // 关闭对象
                Response.Redirect("manage.aspx"); // 页面跳转
            }
            catch(Exception ee)
            {
                Response.Write(ee.ToString()); // 抛出异常
            }
        }


上述代码首先使用 ADO.NET 进行数据插入操作,在数据操作成功后,就进行静态生成。静态生 成的模板为 template.htm ,通过编写 template.htm 文件能够为静态文件编辑相应的模板。在模板读取之后,系统会将一些关键字进行替换,例如将 “ [ 新闻标题 ] ” 这个字符串替换为数据库中的新闻标题,当emplate.htm 模板中包含 “ [ 新闻标题 ] ” 字符串时,就能够通过程序将该字符串替换成相应的数据库中 的数据。

在使用 File 类之前,需要使用 System.IO 命名空间,以提供对文件的读取操作。当读取模板并替换了关键字符串之后,就能够通过 File 类的 CreateText 进行文件的存储,示例代码如下所示。

StreamWriter sw = File.CreateText(Server.MapPath("../html / " + DateTime.Now.ToString() + ".htm"));
sw.Write(template); // 编写内容
sw.Close(); // 关闭对象


上述代码生成了一个以时间为文件名的 htm 静态文件,当文件生成后,就会保存在 html 文件夹中 。在编写静态标签时,需要注意的是就是静态标签应该比较复杂,例如不能够将 title 作为标签进行替换,因为可能文章中的很多字段都包含 title ,而 html 页面本身就包含 title 字符串,如果将 title 进行替换, 很有可能会将不应该替换的字符串替换成数据库文件,这样很有可能会造成模板输出错误。在制作模板时,尽量使用一些符号进行标签规则,例如标题可以编写成为 {$title$} 或者 [*title*] 等 ,就不会与现有的字符串中的字符进行冲突,替换了不该替换的字符串。

进一步代码:

using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Net;
using System.Text.RegularExpressions;

namespace Zxq.Common
{
    //郑希强
    //www.cnblogs.com/zhengxiqiang
    //生成静态页操作
    //2009.2
    public class ToHtml
    {
        #region 读取模板
        /// <summary>
        /// 读取模板
        /// </summary>
        /// <param name="templateUrl">模板地址</param>
        /// <param name="coding">编码</param>
        /// <returns>模板内容</returns>
        public string ReadTemplate(string templateUrl, Encoding code)
        {
            string tlPath = System.Web.HttpContext.Current.Server.MapPath(templateUrl);
            StreamReader sr = null;
            string str = null;
            //读取模板内容
            try
            {
                sr = new StreamReader(tlPath, code);
                str = sr.ReadToEnd();
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                sr.Close();
            }
            return str;
        }
        #endregion

        #region 生成文件
        /// <summary>
        /// 生成文件
        /// </summary>
        /// <param name="str">文件内容</param>
        /// <param name="htmlFile">文件存放地址</param>
        /// <param name="fileName">文件名</param>
        /// <param name="coding">编码</param>
        /// <returns>文件名</returns>
        public bool CreateHtml(string str, string htmlFile, string fileName, Encoding code)
        {
            StreamWriter sw = null;
            bool a = false;
            //写入生成
            try
            {
                htmlFile = System.Web.HttpContext.Current.Server.MapPath(htmlFile);
                this.FolderCreate(htmlFile);
                sw = new StreamWriter(htmlFile + fileName, false, code);
                sw.Write(str);
                sw.Flush();
                a = FileExists(htmlFile + fileName);
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                sw.Close();
            }
            return a;
        }
        #endregion

        #region 判断文件是否存在
        /// <summary>
        /// 判断文件是否存在
        /// </summary>
        /// <param name="FilePath">文件路径</param>
        /// <returns></returns>
        public bool FileExists(string FilePath)
        {
            if (System.IO.File.Exists(FilePath))
                return true;
            else
                return false;
        }
        #endregion

        #region 创建目录
        /// <summary>
        /// 创建目录
        /// </summary>
        /// <param name="Path"></param>
        /// <returns></returns>
        public bool FolderCreate(string Path)
        {
            // 判断目标目录是否存在如果不存在则新建之
            if (!FolderExists(Path))
                Directory.CreateDirectory(Path);
            return FolderExists(Path);
        }
        #endregion

        #region 判断目录是否存在
        /// <summary>
        /// 判断目录是否存在
        /// </summary>
        /// <param name="Path">路径</param>
        /// <returns></returns>
        public bool FolderExists(string Path)
        {
            if (Directory.Exists(Path))
                return true;
            else
                return false;
        }
        #endregion

        #region 静态列表页分页
        /// <summary>
        /// 静态列表页分页
        /// </summary>
        /// <param name="pageCount">总页数</param>
        /// <param name="currentPage">当前页</param>
        /// <param name="prefix">如:list</param>
        /// <param name="suffix">如:.shtml</param>
        /// <returns></returns>
        public string GetHtmlPager(int pageCount, int currentPage, string prefix, string suffix)
        {
            int stepNum = 4;
            int pageRoot = 1;
            pageCount = pageCount == 0 ? 1 : pageCount;
            currentPage = currentPage == 0 ? 1 : currentPage;
            StringBuilder sb = new StringBuilder();
            sb.Append("<ul>");
            sb.Append("<li class=pagerTitle> 分页 " + currentPage.ToString() + "/" + pageCount.ToString() + " </li>\r");
            if (currentPage - stepNum < 2)
                pageRoot = 1;
            else
                pageRoot = currentPage - stepNum;
            int pageFoot = pageCount;
            if (currentPage + stepNum >= pageCount)
                pageFoot = pageCount;
            else
                pageFoot = currentPage + stepNum;
            if (pageRoot == 1)
            {
                if (currentPage > 1)
                {
                    sb.Append("<li> <a href='" + prefix + "1" + suffix + "' title='首页'>首页</a> </li>\r");
                    sb.Append("<li> <a href='" + prefix + Convert.ToString(currentPage - 1) + suffix + "' title='上页'>上页</a> </li>\r");
                }
            }
            else
            {
                sb.Append("<li> <a href='" + prefix + "1" + suffix + "' title='首页'>首页</a> </li>");
                sb.Append("<li> <a href='" + prefix + Convert.ToString(currentPage - 1) + suffix + "' title='上页'>上页</a> </li>\r");
            }
            for (int i = pageRoot; i <= pageFoot; i++)
            {
                if (i == currentPage)
                {
                    sb.Append("<li class='current'> " + i.ToString() + " </li>\r");
                }
                else
                {
                    sb.Append("<li> <a href='" + prefix + i.ToString() + suffix + "' title='第" + i.ToString() + "页'>" + i.ToString() + "</a> </li>\r");
                }
                if (i == pageCount)
                    break;
            }
            if (pageFoot == pageCount)
            {
                if (pageCount > currentPage)
                {
                    sb.Append("<li> <a href='" + prefix + Convert.ToString(currentPage + 1) + suffix + "' title='下页'>下页</a> </li>\r");
                    sb.Append("<li> <a href='" + prefix + pageCount.ToString() + suffix + "' title='尾页'>尾页</a> </li>\r");
                }
            }
            else
            {
                sb.Append("<li> <a href='" + prefix + Convert.ToString(currentPage + 1) + suffix + "' title='下页'>下页</a> </li>\r");
                sb.Append("<li> <a href='" + prefix + pageCount.ToString() + suffix + "' title='尾页'>尾页</a> </li>\r");
            }
            sb.Append("</ul>");
            return sb.ToString();
        }
        #endregion

        #region 压缩Html文件
        /// <summary>
        /// 压缩Html文件
        /// </summary>
        /// <param name="html">Html文件</param>
        /// <returns></returns>
        public string ZipHtml(string Html)
        {
            Html = Regex.Replace(Html, @">\s+?<", "><");//去除Html中的空白字符.
            Html = Regex.Replace(Html, @"\r\n\s*", "");
            Html = Regex.Replace(Html, @"<body([\s|\S]*?)>([\s|\S]*?)</body>", @"<body$1>$2</body>", RegexOptions.IgnoreCase);
            return Html;
        }
        #endregion

        #region 从HTML中获取文本,保留br,p,img
        /// <summary>
        /// 从HTML中获取文本,保留br,p,img
        /// </summary>
        /// <param name="Html">文本内容</param>
        /// <returns></returns>
        public string GetTextFromHtml(string Html)
        {
            Regex regEx = new Regex(@"</?(?!br|/?p|img)[^>]*>", RegexOptions.IgnoreCase);
            return regEx.Replace(Html, "");
        }
        #endregion
    }
}


静态模板编写:

如果新闻模块不需要静态生成,那么就可以通过 id 参数进行 articles.aspx 页面的访问,例如可以通过 articles.aspx?id=1 这样规则的地址进行访问。但是动态的访问不仅数据访问量大,还不能很好的被搜索引擎搜录,如果选择新闻模块要生成静态,就需要编写相应的模板。由于新闻模块在添加新闻时就 需要生成静态文件,其静态文件的模板读取的是 template.htm ,所以编写 template.htm 的 HTML 代码就能够编写模板文件 。


在模板文件中,添加模板标签,其中 [ 新闻标题 ] 、 [ 新闻作者 ] 等都是模板标签。当生成静态文件时,系统会根据标签替换数据库中的数据,例如把 [ 新闻标题 ] 替换成 “ 新闻标题 ” ,然后生成到 html 文件夹 中形成一个静态文件。当用户单击新闻列表的时候,就可以跳转到相应的静态文件进行静态访问而无需动态读取文件, 这样就能够快速的提高读取效率并降低服务器压力。



伪静态化(也成为URL重写):是在服务器端把客户端请求的URL(如Article_3.html)当作另一个请求进行处理(如Article.aspx?id=3)。请注意,这个工作是在服务器端完成的。




伪静态化(URL重写)优点:主要目的还是对用户友好,SEO效果怎样倒真不清楚,都是一些坊间传言,至今没有看到一篇以数据说明的文章来谈这个问题

是不是应该重写URL?
看一下谷歌提供的资料:

我是不是应该让我的动态网址看起来是静态的呢?
在处理动态网址时,希望您能了解以下几点事实:
1:要正确地生成和维护从动态网址到静态化网址的重写转变实际上是一件很难的事情。:
2:将原始的动态网址提供给我们会比较安全,请让我们来处理诸如探测和避开那些有问题的参数的事情。
3:如果您想重写网址,请去掉那些不必要的参数,同时请保持它动态网址的样子。
4:如果您想提供一个静态网址代替动态网址,那么您应该切实地生成相应的静态内容。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值