﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>IT博客-A JavaScript Fancier-随笔分类-Web开发相关知识</title><link>http://www.cnitblog.com/yemoo/category/3135.html</link><description>伟大的javascript技术研究中...</description><language>zh-cn</language><lastBuildDate>Mon, 26 Sep 2011 13:27:48 GMT</lastBuildDate><pubDate>Mon, 26 Sep 2011 13:27:48 GMT</pubDate><ttl>60</ttl><item><title>编写 Firefox Extension【转】</title><link>http://www.cnitblog.com/yemoo/archive/2008/07/10/46536.html</link><dc:creator>Yemoo'S JS Blog</dc:creator><author>Yemoo'S JS Blog</author><pubDate>Thu, 10 Jul 2008 02:22:00 GMT</pubDate><guid>http://www.cnitblog.com/yemoo/archive/2008/07/10/46536.html</guid><wfw:comment>http://www.cnitblog.com/yemoo/comments/46536.html</wfw:comment><comments>http://www.cnitblog.com/yemoo/archive/2008/07/10/46536.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/yemoo/comments/commentRss/46536.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/yemoo/services/trackbacks/46536.html</trackback:ping><description><![CDATA[<script type="text/javascript" src="http://www.cnitblog.com/Files/yemoo/gg1.js"></script><br><br>为Firefox编写插件很有意思，却又很费力气，因为调试手段太缺乏。<br><br>由于Firefox在版本升级中，插件的结构发生了一定变化，而Mozila的文档对这些变化显得很不统一，也造成了一些困扰。以下所有内容，只在Firefox 1.5.*上得到验证。<br><br>一个打包好的Firefox插件是一个扩展名为xpi的zip文件，它包括以下几个部分：<br>1、chrome.manifest<br>这是核心配置文件，是它指导Firefox内核把插件的各个模块配置并组装起来，安放到指定的位置。<br><br>2、install.rdf<br>这一个安装和卸载是使用的描述文件，包含大量的字符串，主要供Extension Manger获取文字性的描述信息。<br><br>3、chrome/your-name.jar<br>这也是一个zip文件，它将会被chrome.manifest引用。<br><br>这个your-name.jar将大部分插件的内容打包，其中又包含三个文件夹<br>1、content<br>这个文件夹中包含界面描述文件XUL，JavaScript，以及资源文件。<br>2、locale<br>这个文件夹中包含为各地区和语言定制的字符串资源，可供界面文件等引用。它们应使用UTF-8编码。<br>3、skin<br>这个文件夹包含CSS样式表，可用来修饰界面文件<br><br>Firefox对所有这些文件的要求都很严格，一个细小的错误就会造成整个程序的功能错误。因此，编写时必须十分小心。<p><script type="text/javascript" src="http://www.cnitblog.com/Files/yemoo/gg2.js"></script><img src ="http://www.cnitblog.com/yemoo/aggbug/46536.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/yemoo/" target="_blank">Yemoo'S JS Blog</a> 2008-07-10 10:22 <a href="http://www.cnitblog.com/yemoo/archive/2008/07/10/46536.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Firefox扩展一个xpi的目录结构 [转]</title><link>http://www.cnitblog.com/yemoo/archive/2008/07/10/46535.html</link><dc:creator>Yemoo'S JS Blog</dc:creator><author>Yemoo'S JS Blog</author><pubDate>Thu, 10 Jul 2008 02:21:00 GMT</pubDate><guid>http://www.cnitblog.com/yemoo/archive/2008/07/10/46535.html</guid><wfw:comment>http://www.cnitblog.com/yemoo/comments/46535.html</wfw:comment><comments>http://www.cnitblog.com/yemoo/archive/2008/07/10/46535.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/yemoo/comments/commentRss/46535.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/yemoo/services/trackbacks/46535.html</trackback:ping><description><![CDATA[<script type="text/javascript" src="http://www.cnitblog.com/Files/yemoo/gg1.js"></script><br><br>xpi文件就是firefox能够识别的扩展文件，将xpi安装到firefox的方法比较多，而且挺简单的，以后介绍。<br>将xpi文件以WinRAR或者WinZip打开并解压，可以得到如下目录结构：<br>\chrome<br>\components<br>\defaults<br>\install.js<br>\install.rdf<br>\chrome.manifest<a name=entrymore></a><br>这是顶层的目录结构，在chrome目录下还会有重要的东西，逐一介绍：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;chrome是Mozilla 规定扩展必须具备的目录，其中包含一个jar文件，为什么是jar呢？天知道Mozilla为什么要和Sun的Java这样纠缠不清！而实际上，他只是作为一种压缩结构而存在，就像zip包，rar包一样，只不过他是以Zip为压缩包结构，以.jar为扩展名。这个包里保存着完成扩展主要功能的文件。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;components文件夹用于存放自定义的 XPCOM 组件文件，就是将xpt和dll文件放在里面，上一片blog里说的install.js放在外面~。由于javascript功能还是挺强大的，一般简单的功能是可以完成的，所以这个目录是可选的，我现在在做的项目要用通过xpcom使用一些别的库，所以就要用到xpcom，就会有这个目录。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;defaults据说是负责存放一些默认的设置数据，我们现在正在做调研，东西做的还比较简单，没用到这个文件夹，当然这个文件夹也是可选的。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;install.js文件，作为一种安装脚本，他已经被Mozilla新的技术所代替，就是我们看到的另一个文件——install.rdf，但是这个js文件还是有他的作用的，比如将components文件夹里的xpt和dll通过xpinstall的api搬运到firefox的特定文件目录中去。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;install.rdf文件，用于描述当前扩展的注册信息和附加信息等。在firefox的扩展软件中找到我们安装的扩展，右键点出关于，about对话框里的信息都是出自这个文件，安装扩展的时候，firefox会自动分析这个文件，提取例如扩展名，版本号，作者之类的信息到系统中。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;chrome.manifest文件负责将扩展的各种包注册到 Mozilla 的 chrome 系统中。可以理解为一个注册文件。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;再来说一下chrome文件夹里的内容——jar文件包，解压这个包会得到三个目录：<br>\content<br>\local<br>\skin<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;content用于存放overlay或者Dialog、window这样的xul文件和负责控制逻辑响应事件的javascript文件。这个文件夹是必不可少的，我们扩展的核心内容就在这个文件夹中。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;local是本地化文件夹，当我们想支持多语言的时候，会用的到，由于我们要做对英语和日语的支持，说以会用到这个文件夹下的内容，以后会详细介绍的。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;skin文件夹是用于存储负责美化界面外观的样式表文件和图片文件，这些文件中的样式和图片会被 content 目录中的文件所引用，这点是初学者很不容易搞定的！content文件夹下的xul文件会用到！他们定义一个标示（ID），然后在本文件中什么也不做了！这点让我郁闷了一个上午，找啊找，翻啊翻的，结果在skin文件夹下的css文件中找到了！而css文件像一个桥梁一样，将skin中的图片文件与xul中的标签联系在一起！这个下一篇blog介绍。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 这样，一个xpi的基本目录就介绍完了！搞不明白为什么要分这老些文件夹，但是将content（实现）和skin（资源）分开会有他的好处的，至少很清晰！<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 做最简单的扩展你只需要这样的目录结构：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\chrome<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;---\content<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ---\XXX.xul和XXX.js<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\install.rdf<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\chrome.manifest<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 其实要做一个简单的扩展也不会那么难，以后的4篇blog我会依次介绍如何简单扩展我们可爱的firefox，状态栏，工具栏，菜单，还有定制工具栏那个面板。<p><script type="text/javascript" src="http://www.cnitblog.com/Files/yemoo/gg2.js"></script><img src ="http://www.cnitblog.com/yemoo/aggbug/46535.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/yemoo/" target="_blank">Yemoo'S JS Blog</a> 2008-07-10 10:21 <a href="http://www.cnitblog.com/yemoo/archive/2008/07/10/46535.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>浅谈javascript函数劫持[转自xfocus]</title><link>http://www.cnitblog.com/yemoo/archive/2008/06/23/45937.html</link><dc:creator>Yemoo'S JS Blog</dc:creator><author>Yemoo'S JS Blog</author><pubDate>Mon, 23 Jun 2008 05:35:00 GMT</pubDate><guid>http://www.cnitblog.com/yemoo/archive/2008/06/23/45937.html</guid><wfw:comment>http://www.cnitblog.com/yemoo/comments/45937.html</wfw:comment><comments>http://www.cnitblog.com/yemoo/archive/2008/06/23/45937.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cnitblog.com/yemoo/comments/commentRss/45937.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/yemoo/services/trackbacks/45937.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 一、概述javascript函数劫持，也就是老外提到的javascript hijacking技术。最早还是和剑心同学讨论问题时偶然看到的一段代码，大概这样写的：window.alert = function(s) {};觉得这种用法很巧妙新颖，和API Hook异曲同工，索性称之为javascript function hook，也就是函数劫持。通过替换js函数的实现来达到劫持这个函数调用的目的...&nbsp;&nbsp;<a href='http://www.cnitblog.com/yemoo/archive/2008/06/23/45937.html'>阅读全文</a><img src ="http://www.cnitblog.com/yemoo/aggbug/45937.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/yemoo/" target="_blank">Yemoo'S JS Blog</a> 2008-06-23 13:35 <a href="http://www.cnitblog.com/yemoo/archive/2008/06/23/45937.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>禁止页面缓存的方法</title><link>http://www.cnitblog.com/yemoo/archive/2008/05/22/44073.html</link><dc:creator>Yemoo'S JS Blog</dc:creator><author>Yemoo'S JS Blog</author><pubDate>Thu, 22 May 2008 02:53:00 GMT</pubDate><guid>http://www.cnitblog.com/yemoo/archive/2008/05/22/44073.html</guid><wfw:comment>http://www.cnitblog.com/yemoo/comments/44073.html</wfw:comment><comments>http://www.cnitblog.com/yemoo/archive/2008/05/22/44073.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/yemoo/comments/commentRss/44073.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/yemoo/services/trackbacks/44073.html</trackback:ping><description><![CDATA[<script type="text/javascript" src="http://www.cnitblog.com/Files/yemoo/gg1.js"></script><br><br>今天用到，突然发现自己不会写，网上找了一下，保存到自己blog上，以后查找方便。<br>1, 在jsp或者servlet中加入<br><br>&lt;%<br>response.setHeader("Pragma","No-cache");<br>response.setHeader("Cache-Control","no-cache");<br>response.setDateHeader("Expires", 0);<br>%&gt;2, 在页面中使用HTML标记，如下面：<br><br>&lt;HEAD&gt;<br>&lt;META http-equiv=Pragma content=no-cache&gt;<br>&lt;META http-equiv=Cache-Control content=no-cache&gt;<br>&lt;META http-equiv=Expires content=0&gt;<br>
<script type="text/javascript" src="http://www.cnitblog.com/Files/yemoo/gg2.js"></script><<img src ="http://www.cnitblog.com/yemoo/aggbug/44073.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/yemoo/" target="_blank">Yemoo'S JS Blog</a> 2008-05-22 10:53 <a href="http://www.cnitblog.com/yemoo/archive/2008/05/22/44073.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>软件接口的规范艺术[整理] </title><link>http://www.cnitblog.com/yemoo/archive/2008/03/31/41722.html</link><dc:creator>Yemoo'S JS Blog</dc:creator><author>Yemoo'S JS Blog</author><pubDate>Mon, 31 Mar 2008 03:40:00 GMT</pubDate><guid>http://www.cnitblog.com/yemoo/archive/2008/03/31/41722.html</guid><wfw:comment>http://www.cnitblog.com/yemoo/comments/41722.html</wfw:comment><comments>http://www.cnitblog.com/yemoo/archive/2008/03/31/41722.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/yemoo/comments/commentRss/41722.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/yemoo/services/trackbacks/41722.html</trackback:ping><description><![CDATA[<script type="text/javascript" src="http://www.cnitblog.com/Files/yemoo/gg1.js"></script><br><br>在软件开发中，总要制定这样那样的接口，一般来说分为两种：<br><strong>1、面向用户的操作接口 </strong><br><strong>2、面向开发者的程序接口</strong><br><br>对于这两种接口的定义规范，我们应该遵循下面两点：<br><br><strong>1、对于用户的接口（操作接口）：越简单越好。</strong><br><br>现在的设计讲究易用性，越简单越易用的功能接口越能被用户接受，反之用户就可能远远避开。<br>如在某blog上看到这样的一个示例：<br>一个软件，用户在输入一条记录后必须点击一下输入按钮这条数据才能真正输入，如果仅仅只需要输入一条记录那么这样也没什么，但很多时候用户一次性需要输入成百上千条数据，这样每输一条数据就点击一下输入按钮，估计没有几个人能不疯掉。这个可能是软件设计者因为技术或其他原因设计的这样一个用户使用接口。而这样来要求用户，就有些过分了，用户如果欣然接受你的软件那就怪了。类似这种设计应该学习excel，用户输入一条数据后按下enter自动进行下一个输入区。<br>&nbsp;&nbsp; 当然为用户提供越灵活自由简单的接口，后台的处理逻辑可能会越复杂，但是如果能够给用户带来更好的体验很多时候这都是值得的。<br><br><strong>2、对于开发者的接口（大多是程序接口）：越复杂越详细越好</strong><br><br>为什么不是越简单越好呢？因为刚才说了，这样后台逻辑处理就比较麻烦，开发难度高。<br>因此从开发成本和面向对象技术中的对象负责自己的原则来看，应该为每个部分制定详细的接口规范。<br>这样可以减少每个部分之间的耦合性，从而降低开发的难度，节约成本，。<br>举个例子：一个设备控制模块，他的一个使用规范是这样定义的：在调用控制命令之前，必须初始化通讯模块。有的人可能会问，难道我不能在控制软件模块加一个判 断，发现通讯模块不能工作，就自己调用一下通讯模块初始化命令的功能不行吗？我们从成本角度考虑就会发现这个建议确实不行。原因是，这个不但多写了一段代码，而且还增加了模块之间的不必要的耦合度。况且，照这个思路其他模块也许也要加上这个通讯模块初始化命令，更是错上加错了。从职责角度考虑，我们给设备控制模块附加上初始化通讯模块的功能，显然也是有问题的。<br>&nbsp;&nbsp;&nbsp;&nbsp;越复杂的项目越要有复杂的规范，否则就可能会变得很难维护。<br><br><strong>原文：</strong>http://blog.csdn.net/acloudhuang/archive/2007/12/14/1936057.aspx<br><br><script type="text/javascript" src="http://www.cnitblog.com/Files/yemoo/gg2.js"></script><img src ="http://www.cnitblog.com/yemoo/aggbug/41722.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/yemoo/" target="_blank">Yemoo'S JS Blog</a> 2008-03-31 11:40 <a href="http://www.cnitblog.com/yemoo/archive/2008/03/31/41722.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Web开发设计的五大准则【转】</title><link>http://www.cnitblog.com/yemoo/archive/2008/03/31/41721.html</link><dc:creator>Yemoo'S JS Blog</dc:creator><author>Yemoo'S JS Blog</author><pubDate>Mon, 31 Mar 2008 03:39:00 GMT</pubDate><guid>http://www.cnitblog.com/yemoo/archive/2008/03/31/41721.html</guid><wfw:comment>http://www.cnitblog.com/yemoo/comments/41721.html</wfw:comment><comments>http://www.cnitblog.com/yemoo/archive/2008/03/31/41721.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cnitblog.com/yemoo/comments/commentRss/41721.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/yemoo/services/trackbacks/41721.html</trackback:ping><description><![CDATA[<script type="text/javascript" src="http://www.cnitblog.com/Files/yemoo/gg1.js"></script><br><br>如果仓促而为，设计一个专题或者网站一定会成为恶梦。Web设计需要遵循一些准则并有计划地去做。<br><br><strong>Rule #1 : 先出设计图</strong><br><br>这是必须的。不要假设设计图在你的头脑中就开始设计web，必须要放到纸上。可以这样做：<br><br>1，&nbsp;&nbsp;拿尺子、笔和纸，按照具体的尺寸一行一行地画下来；<br><br>2，&nbsp;&nbsp;记得考虑分界线的长度等，这样才能符合CSS的像素；<br><br>3，&nbsp;&nbsp;记下设计的每一个细节免得忘记，如果把所有细节都累积到最后将是巨大的麻烦。<br><br><strong>Rule #2 :配色</strong><br><br>这是设计的核心部分，只有颜色搭配合适才能使你的网页看起来不错。首先要决定的是主色，也即你在网页中多数使用的颜色；然后选择跟主色调搭配的第二颜色；不要选择超过三种颜色不然你的设计看起来会很乱。如果你想要更多的颜色，可以使用浅色或者深色的阴影来搭配主色调。<br><br>1，&nbsp;&nbsp;浏览十个跟你网页有同样主色调的网页；<br><br>2，&nbsp;&nbsp;给几个人看你的配色方案并取得反馈；<br><br>3，&nbsp;&nbsp;从浏览的网页和反馈你将更好地完善你的颜色搭配。<br><br><strong>Rule #3 : 从基本的版块开始着手</strong><br><br>定下配色和设计图之后，从最基本的框架开始构建——我的意思是说不添加任何文本。因为在版面中加入文本会使得架构混乱。方法如下：<br><br>1，&nbsp;&nbsp;每一个版块设定边界线，这样能够看到具体的尺寸和位置；<br><br>2，&nbsp;&nbsp;对不同的版块使用不同的颜色，在完成版块后再改成你想要的颜色。<br><br><strong>Rule #4 : 理清CSS</strong><br><br>不要在你的HTML文件中将styling元素搞得太复杂，不然等到你修改的时候你就不得不到处搜索。所以将所有styling元素归置在一个单独的CSS文档中。<br><br>在styling之前理清你的CSS免得太过杂乱导致你多次重复同一件事。CSS支持继承，也即parent block的style可以用于child block.，充分利用这条特性。命名CSS分类名也要易懂易记。比如使用&#8220;main_content&#8221;而不是&#8220;div_1&#8221;。<br><br><strong>Rule #5 : 制订多重 CSS 文档</strong><br><br>我们都知道，使用浏览器可以轻易地看到网页的输出，但使用另一浏览器的时候则可能发现输出不正常。这不是什么稀奇事儿，因为每个浏览器对HTML和CSS的处理方式都不一样。<br><br>为避免这种情况，每个浏览器准备一个CSS文档，这样所有浏览器都可以正常浏览。虽然这有一定的难度，但是记着指望一个CSS文档来满足所有浏览器是不可能的。<br><br><br><strong>原文链接：</strong><a href="http://techtracer.com/2007/12/10/5-rules-for-a-good-web-design/" target=_blank><u><font color=#0000ff>http://techtracer.com/2007/12/10/5-rules-for-a-good-web-design/</font></u></a><br><script type="text/javascript" src="http://www.cnitblog.com/Files/yemoo/gg2.js"></script><img src ="http://www.cnitblog.com/yemoo/aggbug/41721.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/yemoo/" target="_blank">Yemoo'S JS Blog</a> 2008-03-31 11:39 <a href="http://www.cnitblog.com/yemoo/archive/2008/03/31/41721.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Mastering JavaScript — concept and resource guide</title><link>http://www.cnitblog.com/yemoo/archive/2007/11/04/35791.html</link><dc:creator>Yemoo'S JS Blog</dc:creator><author>Yemoo'S JS Blog</author><pubDate>Sat, 03 Nov 2007 17:09:00 GMT</pubDate><guid>http://www.cnitblog.com/yemoo/archive/2007/11/04/35791.html</guid><wfw:comment>http://www.cnitblog.com/yemoo/comments/35791.html</wfw:comment><comments>http://www.cnitblog.com/yemoo/archive/2007/11/04/35791.html#Feedback</comments><slash:comments>8</slash:comments><wfw:commentRss>http://www.cnitblog.com/yemoo/comments/commentRss/35791.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/yemoo/services/trackbacks/35791.html</trackback:ping><description><![CDATA[<script type="text/javascript" src="http://www.cnitblog.com/Files/yemoo/gg1.js"></script><br><br>    There is not a single interpreted language used today that causes more excitement, confusion, disdain, and conflict than JavaScript. The language is so incredibly flexible that it is difficult to separate a developer&#8217;s choice of coding style from JavaScript best practices. If you are an absolute beginner (as we all once were), this can be an incredibly frustrating experience.<br>The immensity of information available today is also adversely focused on AJAX, frameworks and APIs. I wonder how designers and developers manage to wade through the cruft to even begin learning the basics. If you are like me, and have evolved along with JavaScript, then the state of the language makes a little more sense. However, if you are in the first steps of your journey, it might seem like a long and winding road ahead.<br>This concept and resource guide is a way to deal with these issues. Instead of listing a compendium of resources too vast to matter to anyone, I have listed only those that I feel truly contribute to the process of mastering JavaScript. Preceding the list is an outline of advanced JavaScript concepts that will help &#8220;light the master&#8217;s path&#8221;.<br><br><font size=4>JavaScript Concepts</font><br><font size=4></font><br><em><strong>Access Control</strong></em><br>A JavaScript design pattern that prohibits another script from accessing portions of functionality in your JavaScript is enforcing &#8220;access control&#8221;. In a language like C# or Java, access control is explicitly declared with access control keywords such as <em>private</em>, <em>public</em> or <em>protected</em>. With JavaScript, achieving access control is a bit more work.<br><br>
<ul>
    <li><a href="http://www.crockford.com/javascript/private.html" target=_blank><font color=#0000ff><u>Private Members in JavaScript</u></font></a>
    <li><a href="http://www.dustindiaz.com/javascript-private-public-privileged/" target=_blank><font color=#0000ff><u>How to achieve private, public, and privileged members in JavaScript</u></font></a>
    <li><a href="http://www.snook.ca/archives/javascript/private_javascript/" target=_blank><font color=#0000ff><u>Private JavaScript</u></font></a></li>
</ul>
<br><em><strong>Accessible JavaScript</strong></em><br>The term &#8220;accessible JavaScript&#8221; refers to movements that support RIAs in conjunction with accessibility. The most notable methodology is Hijax, a term coined by Jeremy Keith, the author of <em>DOM Scripting</em>. Roger Johansson is a successful Web developer who also promotes accessible JavaScript techniques on his popular blog 456 Berea Street.<br><br>
<ul>
    <li><a href="http://domscripting.com/blog/display/41" target=_blank><font color=#0000ff><u>Hijax</u></font></a>
    <li><a href="http://www.456bereastreet.com/" target=_blank><font color=#0000ff><u>456 Berea Street</u></font></a></li>
</ul>
<br><em><strong>Closures</strong></em><br>Arguably the most difficult concept in JavaScript to understand, closures are complicated, and can have harmful consequences if not implemented correctly. Closures in JavaScript are essentially a design pattern that allows an inner (nested) function to access the variables associated with an outer function, even after that function has been executed (returned).<br><br>
<ul>
    <li><a href="http://blog.morrisjohns.com/javascript_closures_for_dummies" target=_blank><font color=#0000ff><u>JavaScript Closures for Dummies</u></font></a>
    <li><a href="http://www.jibbering.com/faq/faq_notes/closures.html" target=_blank><font color=#0000ff><u>JavaScript Closures</u></font></a>
    <li><a href="http://www.sitepoint.com/blogs/2004/05/26/closures-and-executing-javascript-on-page-load/" target=_blank><font color=#0000ff><u>Closures and executing JavaScript on page load</u></font></a></li>
</ul>
<br><em><strong>Classical OOP</strong></em><br>In several technical circles, JavaScript is often referred to as a prototype-based or object-based language, as it lacks some features available in full-blown object oriented programming. Regardless, in order to be a successful Web developer, you must understand the details surrounding classical object oriented programming with JavaScript.<br><br>
<ul>
    <li><a href="http://www.sitepoint.com/article/oriented-programming-1" target=_blank><font color=#0000ff><u>JavaScript Object-Oriented Programming Part 1</u></font></a>
    <li><a href="http://www.digital-web.com/articles/objectifying_javascript/" target=_blank><font color=#0000ff><u>Objectifying JavaScript</u></font></a>
    <li><a href="http://www.javascriptkit.com/javatutors/oopjs.shtml" target=_blank><font color=#0000ff><u>JavaScript and Object Oriented Programming (OOP)</u></font></a>
    <li><a href="http://ajaxian.com/archives/douglas-crockford-video-advanced-javascript" target=_blank><font color=#0000ff><u>Douglas Crockford Video: Advanced JavaScript</u></font></a></li>
</ul>
<br><em><strong>Concepts in AJAX</strong></em><br>AJAX is conceptually quite simple. Hundreds of examples are available, and the number of tutorials is too numerous to count these days. However, within an intricate RIA, several complicated problems can arise for the budding architect. Performance issues play center stage, and it is important to explore alternative methods of implementing AJAX solutions.<br><br>
<ul>
    <li><a href="http://www.cmarshall.net/MySoftware/ajax/" target=_blank><font color=#0000ff><u>AJAX Queue Class</u></font></a>
    <li><a href="http://keelypavan.**/2006/03/reusing-xmlhttprequest-object-in-ie.html" target=_blank><font color=#0000ff><u>Reusing XMLHttpRequest Object in IE</u></font></a>
    <li><a href="http://ajaxpatterns.org/" target=_blank><font color=#0000ff><u>AJAX Patterns</u></font></a>
    <li><a href="http://ajaxian.com/archives/managing-sessions-in-an-ajax-enabled-application" target=_blank><font color=#0000ff><u>Managing sessions in an Ajax-enabled application</u></font></a></li>
</ul>
<br><em><strong>Memory Leaks</strong></em><br>One of the most difficult issues plaguing JavaScript programmers today is memory leaks brought on by a combination of browser bugs and poor coding practices. Even though memory leaks are often identified with Internet Explorer, Web applications in several browsers have been known to freeze up the client interface and cause excessive memory leakage.<br><br>
<ul>
    <li><a href="http://javascript.crockford.com/memory/leak.html" target=_blank><font color=#0000ff><u>JScript Memory Leaks</u></font></a>
    <li><a href="http://talideon.com/weblog/2005/03/js-memory-leaks.cfm" target=_blank><font color=#0000ff><u>Fixing JavaScript memory leaks for good</u></font></a>
    <li><a href="http://www.ibm.com/developerworks/web/library/wa-memleak/?ca=dgr-lnxw97JavascriptLeaks" target=_blank><font color=#0000ff><u>Memory leak patterns in JavaScript</u></font></a></li>
</ul>
<br><em><strong>Namespaces and Self-invoking Functions</strong></em><br>At the forefront of every JavaScript library is a namespace. Although the style of execution can vary slightly, the concept is incredibly important if you are considering the release of an API or framework. Creating a non-conflicting namespace (which typically involves self-invoking functions), is both friendly and unobtrusive, and it should be a part of your repertoire.<br><br>
<ul>
    <li><a href="http://www.dustindiaz.com/namespace-your-javascript/" target=_blank><font color=#0000ff><u>Namespacing your JavaScript</u></font></a>
    <li><a href="http://snook.ca/archives/javascript/javascript_name/" target=_blank><font color=#0000ff><u>JavaScript Namespaces</u></font></a>
    <li><a href="http://www.lixo.org/archives/2007/09/14/javascript-put-everything-in-a-namespace/" target=_blank><font color=#0000ff><u>JavaScript: Put everything in a namespace</u></font></a></li>
</ul>
<br><em><strong>JSON and Object Literal Notation</strong></em><br>JavaScript Object Literal Notation and JSON both rely completely on JavaScript&#8217;s implementation of the hash object. Although a subset of object oriented programming with JavaScript, object literal notation is becoming a widely accepted alternative to functions as constructors for objects. I suggest first reading the classical OOP articles, and then move on to these articles.<br><br>
<ul>
    <li><a href="http://www.dustindiaz.com/json-for-the-masses/" target=_blank><font color=#0000ff><u>JSON for the masses</u></font></a>
    <li><a href="http://www.wait-till-i.com/index.php?p=239" target=_blank><font color=#0000ff><u>Show love to the object literal</u></font></a>
    <li><a href="http://www.snook.ca/archives/javascript/json_is_a_subse/" target=_blank><font color=#0000ff><u>JSON is a subset of the Object Literal</u></font></a>
    <li><a href="http://json.org/" target=_blank><font color=#0000ff><u>JSON</u></font></a></li>
</ul>
<br><em><strong>Security</strong></em><br>While security continues to be a major concern among Web developers, much of the hype surrounding XSS (cross-site scripting) has diminished. However, techniques for overcoming security flaws in JavaScript should be well known by all JavaScript programmers, new and old. Exploits are discovered often, and keeping up with hacker trends is important.<br><br>
<ul>
    <li><a href="http://en.wikipedia.org/wiki/Cross-site_scripting" target=_blank><font color=#0000ff><u>Wikipedia Cross-site scripting entry</u></font></a>
    <li><a href="http://ha.ckers.org/xss.html" target=_blank><font color=#0000ff><u>XSS (Cross Site Scripting) Cheat Sheet</u></font></a>
    <li><a href="http://getahead.org/blog/joe/2007/03/05/json_is_not_as_safe_as_people_think_it_is.html" target=_blank><font color=#0000ff><u>JSON is not as safe as people think it is</u></font></a>
    <li><a href="http://code.google.com/p/google-caja/" target=_blank><font color=#0000ff><u>Google Caja</u></font></a></li>
</ul>
<br><br><strong>JavaScript Topics, Articles &amp; Tutorials (Publications)</strong>
<ul>
    <li><a href="http://www.ajaxian.com/" target=_blank><font color=#0000ff><u>Ajaxian</u></font></a>
    <li><a href="http://www.alistapart.com/topics/code/scripting" target=_blank><font color=#0000ff><u>A List Apart: Topics: Code: Scripting</u></font></a>
    <li><a href="http://www.devguru.com/Technologies/ecmascript/quickref/javascript_index.html" target=_blank><font color=#0000ff><u>DevGuru JavaScript Reference</u></font></a>
    <li><a href="http://www.digital-web.com/topics/dom" target=_blank><font color=#0000ff><u>Digital Web Magazine - Articles by Topic: DOM</u></font></a>
    <li><a href="http://www.javascriptkit.com/" target=_blank><font color=#0000ff><u>JavaScript Kit</u></font></a>
    <li><a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/script56/html/js56jsoriJScript.asp?frame=true" target=_blank><font color=#0000ff><u>Microsoft JScript Reference on MSDN</u></font></a>
    <li><a href="http://developer.mozilla.org/en/docs/JavaScript" target=_blank><font color=#0000ff><u>Mozilla Developer Center Core JavaScript Reference</u></font></a>
    <li><a href="http://www.sitepoint.com/subcat/javascript" target=_blank><font color=#0000ff><u>Sitepoint JavaScript &amp; AJAX Tutorials</u></font></a>
    <li><a href="http://javascript-reference.info/" target=_blank><font color=#0000ff><u>Visibone JavaScript Reference</u></font></a>
    <li><a href="http://www.webreference.com/javascript/reference/core_ref/contents.html" target=_blank><font color=#0000ff><u>Web Reference Core JavaScript Reference</u></font></a>
    <li><a href="http://www.w3schools.com/default.asp" target=_blank><font color=#0000ff><u>W3 Schools JavaScript Tutorial</u></font></a></li>
</ul>
<br><strong>JavaScript Topics, Articles &amp; Tutorials (Personal)</strong><br>
<ul>
    <li><a href="http://simon.incutio.com/slides/2006/etech/javascript/js-reintroduction-notes.html" target=_blank><font color=#0000ff><u>A (Re)-Introduction to JavaScript</u></font></a>
    <li><a href="http://javascript.crockford.com/" target=_blank><font color=#0000ff><u>Douglas Crockford JavaScript</u></font></a>
    <li><a href="http://www.dustindiaz.com/" target=_blank><font color=#0000ff><u>Dustin Diaz</u></font></a>
    <li><a href="http://eloquentjavascript.net/" target=_blank><font color=#0000ff><u>Eloquent JavaScript</u></font></a>
    <li><a href="http://www.jackslocum.com/blog/" target=_blank><font color=#0000ff><u>Jack Slocum</u></font></a>
    <li><a href="http://home.cogeco.ca/~ve3ll/jstutor0.htm/" target=_blank><font color=#0000ff><u>JavaScript - Table of Contents</u></font></a>
    <li><a href="http://ejohn.org/" target=_blank><font color=#0000ff><u>John Resig</u></font></a>
    <li><a href="http://www.snook.ca/jonathan/" target=_blank><font color=#0000ff><u>Jonathan Snook</u></font></a>
    <li><a href="http://www.kevinyank.com/" target=_blank><font color=#0000ff><u>Kevin Yank</u></font></a>
    <li><a href="http://www.quirksmode.org/" target=_blank><font color=#0000ff><u>QuirksMode.org</u></font></a></li>
</ul>
<br><strong>JavaScript Development Tools</strong><br>
<ul>
    <li><a href="http://dean.edwards.name/packer" target=_blank><font color=#0000ff><u>Dean Edwards Packer</u></font></a>
    <li><a href="http://www.getfirebug.com/" target=_blank><font color=#0000ff><u>Firebug Firefox Extension</u></font></a>
    <li><a href="http://regexpal.com/" target=_blank><font color=#0000ff><u>RegExPal</u></font></a>
    <li><a href="http://www.microsoft.com/downloads/details.aspx?familyid=e59c3964-672d-4511-bb3e-2d5e1db91038&amp;displaylang=en" target=_blank><font color=#0000ff><u>Web Developer Toolbar Explorer Plugin</u></font></a>
    <li><a href="https://addons.mozilla.org/en-US/firefox/addon/60" target=_blank><font color=#0000ff><u>Web Developer Toolbar Firefox Add-on</u></font></a></li>
</ul>
<br><strong>JavaScript Frameworks</strong><br>
<ul>
    <li><a href="http://dedchain.dustindiaz.com/" target=_blank><font color=#0000ff><u>DED|Chain</u></font></a>
    <li><a href="http://dojotoolkit.org/" target=_blank><font color=#0000ff><u>Dojo</u></font></a>
    <li><a href="http://extjs.com/" target=_blank><font color=#0000ff><u>Ext JS</u></font></a>
    <li><a href="http://www.jquery.com/" target=_blank><font color=#0000ff><u>jQuery</u></font></a>
    <li><a href="http://mochikit.com/" target=_blank><font color=#0000ff><u>MochiKit</u></font></a>
    <li><a href="http://mootools.net/" target=_blank><font color=#0000ff><u>Mootools</u></font></a>
    <li><a href="http://www.prototypejs.org/" target=_blank><font color=#0000ff><u>Prototype</u></font></a>
    <li><a href="http://script.aculo.us/" target=_blank><font color=#0000ff><u>Script.aculo.us</u></font></a>
    <li><a href="http://developer.yahoo.com/yui/" target=_blank><font color=#0000ff><u>Yahoo! UI</u></font></a></li>
</ul>
<p><script type="text/javascript" src="http://www.cnitblog.com/Files/yemoo/gg2.js"></script><img src ="http://www.cnitblog.com/yemoo/aggbug/35791.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/yemoo/" target="_blank">Yemoo'S JS Blog</a> 2007-11-04 01:09 <a href="http://www.cnitblog.com/yemoo/archive/2007/11/04/35791.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>什么是框架？[转自5510.cn]</title><link>http://www.cnitblog.com/yemoo/archive/2007/10/12/34780.html</link><dc:creator>Yemoo'S JS Blog</dc:creator><author>Yemoo'S JS Blog</author><pubDate>Fri, 12 Oct 2007 09:52:00 GMT</pubDate><guid>http://www.cnitblog.com/yemoo/archive/2007/10/12/34780.html</guid><wfw:comment>http://www.cnitblog.com/yemoo/comments/34780.html</wfw:comment><comments>http://www.cnitblog.com/yemoo/archive/2007/10/12/34780.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/yemoo/comments/commentRss/34780.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/yemoo/services/trackbacks/34780.html</trackback:ping><description><![CDATA[<script type="text/javascript" src="http://www.cnitblog.com/Files/yemoo/gg1.js"></script><br><br>&nbsp;&nbsp;&nbsp;&nbsp; 框架是一个应用程序的半成品。框架提供了可在应用程序之间共享的可覆用的公共结构。开发者把框架融入他们自己的应用程序，并加以扩展，以满足他们特定的需要。框架和工具包的不同之处在于，框架提供了一致的结构，而不仅仅是一组工具类。<br>&nbsp;&nbsp;&nbsp; 框架其实就是一组组件，供你选用完成你自己的系统。简单说就是使用别人搭好的舞台，你来做表演。而且，框架一般是成熟的，不断升级的软件。 <br>&nbsp;&nbsp;&nbsp; 可以说，一个框架是一个可复用的设计构件，它规定了应用的体系结构，阐明了整个设计、协作构件之间的依赖关系、责任分配和控制流程，表现为一组抽象类以及其实例之间协作的方法，它为构件复用提供了上下文(Context)关系。因此构件库的大规模重用也需要框架。 <br>&nbsp;&nbsp;&nbsp; 构件领域框架方法在很大程度上借鉴了硬件技术发展的成就，它是构件技术、软件体系结构研究和应用软件开发三者发展结合的产物。在很多情况下，框架通常以构件库的形式出现，但构件库只是框架的一个重要部分。框架的关键还在于框架内对象间的交互模式和控制流模式。 <br>&nbsp;&nbsp;&nbsp; 框架比构件可定制性强。在某种程度上，将构件和框架看成两个不同但彼此协作的技术或许更好。框架为构件提供重用的环境，为构件处理错误、交换数据及激活操作提供了标准的方法。 <br>&nbsp;&nbsp;&nbsp; 应用框架的概念也很简单。它并不是包含构件应用程序的小片程序，而是实现了某应用领域通用完备功能（除去特殊应用的部分）的底层服务。使用这种框架的编程人员可以在一个通用功能已经实现的基础上开始具体的系统开发。框架提供了所有应用期望的默认行为的类集合。具体的应用通过重写子类(该子类属于框架的默认行为)或组装对象来支持应用专用的行为。 <br>&nbsp;&nbsp;&nbsp; 应用框架强调的是软件的设计重用性和系统的可扩充性,以缩短大型应用软件系统的开发周期，提高开发质量。与传统的基于类库的面向对象重用技术比较，应用框架更注重于面向专业领域的软件重用。应用框架具有领域相关性，构件根据框架进行复合而生成可运行的系统。框架的力度越大，其中包含的领域知识就更加完整。 <br>&nbsp;&nbsp;&nbsp; <strong>框架和设计模式的关系</strong> <br>&nbsp;&nbsp;&nbsp; 框架、设计模式这两个概念总容易被混淆，其实它们之间还是有区别的。构件通常是代码重用，而设计模式是设计重用，框架则介于两者之间，部分代码重用，部分设计重用，有时分析也可重用。在软件生产中有三种级别的重用：内部重用，即在同一应用中能公共使用的抽象块;代码重用，即将通用模块组合成库或工具集，以便在多个应用和领域都能使用；应用框架的重用，即为专用领域提供通用的或现成的基础结构，以获得最高级别的重用性。 <br>&nbsp;&nbsp;&nbsp; 框架与设计模式虽然相似，但却有着根本的不同。设计模式是对在某种环境中反复出现的问题以及解决该问题的方案的描述，它比框架更抽象；框架可以用代码表示，也能直接执行或复用，而对模式而言只有实例才能用代码表示;设计模式是比框架更小的元素，一个框架中往往含有一个或多个设计模式，框架总是针对某一特定应用领域，但同一模式却可适用于各种应用。可以说，框架是软件，而设计模式是软件的知识。 <br>&nbsp;&nbsp;&nbsp; <strong>为什么要用框架？ <br></strong>因为软件系统发展到今天已经很复杂了，特别是服务器端软件，设计到的知识，内容，问题太多。在某些方面使用别人成熟的框架，就相当于让别人帮你完成一些基础工作，你只需要集中精力完成系统的业务逻辑设计。而且框架一般是成熟，稳健的，他可以处理系统很多细节问题，比如，事物处理，安全性，数据流控制等问题。还有框架一般都经过很多人使用，所以结构很好，所以扩展性也很好，而且它是不断升级的，你可以直接享受别人升级代码带来的好处。 <br>框架一般处在低层应用平台（如J2EE）和高层业务逻辑之间的中间层。 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 衡量应用系统设计开发水平高低的标准就是：解耦性；你的应用系统各个功能是否能够彻底脱离？是否不相互依赖，也只有这样，才能体现可维护性、可拓展性的软件设计目标。<br>　　为了达到这个目的，诞生各种框架概念，J2EE框架标准将一个系统划分为WEB和EJB主要部分，当然我们有时不是以这个具体技术区分，而是从设计上抽象为表现层、服务层和持久层，这三个层次从一个高度将J2EE分离开来，实现解耦目的。<br>　　因此，我们实际编程中，也要将自己的功能向这三个层次上靠，做到大方向清楚，泾渭分明，但是没有技术上约束限制要做到这点是很不容易的，因此我们还是必须借助J2EE具体技术来实现，这时，你可以使用EJB规范实现服务层和持久层，Web技术实现表现层；<br>　　EJB为什么能将服务层从Jsp/Servlet手中分离出来，因为它对JavaBeans编码有强制的约束，现在有一种对JavaBeans弱约束，使用Ioc模式实现的（当然EJB 3.0也采取这种方式），在Ioc模式诞生前，一般都是通过工厂模式来对JavaBeans约束，形成一个服务层，这也正是Jive这样开源论坛设计原理之一。<br>　　由此，将服务层从表现层中分离出来目前有两种可选架构选择：管理普通JavaBeans（POJO）框架(如Spring、JdonFramework)以及管理EJB的EJB框架，因为EJB不只是框架，还是标准，而标准可以扩展发展，所以，这两种区别将来是可能模糊，被纳入同一个标准了。　但是，个人认为：标准制定是为某个目的服务的，总要牺牲一些换取另外一些，所以，这两种架构会长时间并存。<br>　　这两种架构分歧也曾经诞生一个新名词：完全POJO的系统也称为轻量级系统(lightweight)，其实这个名词本身就没有一个严格定义，更多是一个吸引人的招牌，轻量是指容易学习容易使用吗？按照这个定义，其实轻量Spring等系统并不容易学习；而且EJB 3.0（依然叫EJB）以后的系统是否可称为轻量级了呢？<br>　　前面谈了服务层框架，使用服务层框架可以将JavaBeans从Jsp/Servlet中分离出来，而使用表现层框架则可以将Jsp中剩余的JavaBeans完全分离，这部分JavaBeans主要负责显示相关，一般是通过标签库（taglib）实现，不同框架有不同自己的标签库，Struts是应用比较广泛的一种表现层框架。<br>　　这样，表现层和服务层的分离是通过两种框架达到目的，剩余的就是持久层框架了，通过持久层的框架将数据库存储从服务层中分离出来是其目的，持久层框架有两种方向：直接自己编写JDBC等SQL语句（如iBatis）；使用O/R Mapping技术实现的Hibernate和JDO技术；当然还有EJB中的实体Bean技术。<br>　　持久层框架目前呈现百花齐放，各有优缺点的现状，所以正如表现层框架一样，目前没有一个框架被指定为标准框架，当然，表现层框架现在又出来了一个JSF，它代表的页面组件概念是一个新的发展方向，但是复杂的实现让人有些忘而却步。<br>　　在所有这些J2EE技术中，虽然SUN公司发挥了很大的作用，不过总体来说：网络上有这样一个评价：SUN的理论天下无敌；SUN的产品用起来撞墙；对于初学者，特别是那些试图通过或已经通过SUN认证的初学者，赶快摆脱SUN的阴影，立即开溜，使用开源领域的产品来实现自己的应用系统。<br>　　最后，你的J2EE应用系统如果采取上面提到的表现层、服务层和持久层的框架实现，基本你也可以在无需深刻掌握设计模式的情况下开发出一个高质量的应用系统了。<br>　　还要注意的是: 开发出一个高质量的J2EE系统还需要正确的业务需求理解，那么域建模提供了一种比较切实可行的正确理解业务需求的方法，相关详细知识可从UML角度结合理解。<br>　　当然，如果你想设计自己的行业框架，那么第一步从设计模式开始吧，因为设计模式提供你一个实现JavaBeans或类之间解耦参考实现方法，当你学会了系统基本单元JavaBean或类之间解耦时，那么系统模块之间的解耦你就可能掌握，进而你就可以实现行业框架的提炼了，这又是另外一个发展方向了。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;框架的最大好处就是重用。面向对象系统获得的最大的复用方式就是框架，一个大的应用系统往往可能由多层互相协作的框架组成。 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 由于框架能重用代码，因此从一已有构件库中建立应用变得非常容易，因为构件都采用框架统一定义的接口，从而使构件间的通信简单。 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;框架能重用设计。它提供可重用的抽象算法及高层设计，并能将大系统分解成更小的构件，而且能描述构件间的内部接口。这些标准接口使在已有的构件基础上通过组装建立各种各样的系统成为可能。只要符合接口定义，新的构件就能插入框架中，构件设计者就能重用构架的设计。 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 框架还能重用分析。所有的人员若按照框架的思想来分析事务，那么就能将它划分为同样的构件，采用相似的解决方法，从而使采用同一框架的分析人员之间能进行沟通。 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <strong>采用框架技术进行软件开发的主要特点包括：</strong> <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 领域内的软件结构一致性好； <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 建立更加开放的系统； <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 重用代码大大增加，软件生产效率和质量也得到了提高； <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 软件设计人员要专注于对领域的了解，使需求分析更充分； <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 存储了经验，可以让那些经验丰富的人员去设计框架和领域构件，而不必限于低层编程； <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 允许采用快速原型技术； <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 有利于在一个项目内多人协同工作； <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 大量的重用使得平均开发费用降低，开发速度加快，开发人员减少，维护费用降低，而参数化框架使得适应性、灵活性增强。 <p><script type="text/javascript" src="http://www.cnitblog.com/Files/yemoo/gg2.js"></script><img src ="http://www.cnitblog.com/yemoo/aggbug/34780.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/yemoo/" target="_blank">Yemoo'S JS Blog</a> 2007-10-12 17:52 <a href="http://www.cnitblog.com/yemoo/archive/2007/10/12/34780.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>软件系统开发中的组件框架技术研究、设计和应用【转自lrn资源网】</title><link>http://www.cnitblog.com/yemoo/archive/2007/10/12/34779.html</link><dc:creator>Yemoo'S JS Blog</dc:creator><author>Yemoo'S JS Blog</author><pubDate>Fri, 12 Oct 2007 09:48:00 GMT</pubDate><guid>http://www.cnitblog.com/yemoo/archive/2007/10/12/34779.html</guid><wfw:comment>http://www.cnitblog.com/yemoo/comments/34779.html</wfw:comment><comments>http://www.cnitblog.com/yemoo/archive/2007/10/12/34779.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.cnitblog.com/yemoo/comments/commentRss/34779.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/yemoo/services/trackbacks/34779.html</trackback:ping><description><![CDATA[<script type="text/javascript" src="http://www.cnitblog.com/Files/yemoo/gg1.js"></script><p>&nbsp; 计算机的应用已经从过去单纯的科学计算渗透到政务管理、商品交易、金融证券、军事指挥、航天航空、通讯导航、生物工程、医疗服务等多个领域。随着计算机技术的发展和应用范围的不断延伸，作为计算机灵魂的软件系统，其规模也在不断扩大，结构越来越复杂，代码越来越长、维护越来越困难，从过去几百行代码扩大到几万甚至几十万、几百万行代码的软件系统俯首皆是。因此，设计一个功能完善、结构优良，开发效率高，稳定性和安全性强，扩展方便，维护简单，易于复用，生命周期长，投资成本低的软件系统，一直是系统管理、设计和开发者所追求的目标之一。遗憾的是，现实生活中，被抛弃的软件系统随处可见，造成极大的投资浪费。原因之一是系统开发仓促编码，结构劣拙，功能扩展困难，稍有修改，便错误百出，无法维护，唯有弃之不用。</p>
<p><span>&nbsp; 软件发展的实践证明，模块化的分层设计模型是提高系统可用性和可维护性的主要途径。分层模型设计，既将整个软件系统划分为若干个相互独立的层次进行描述，层与层之间通过事先约定的接口相互通讯。某个层只负责一个或多个功能，各负其则，不越俎代庖。分层设计把一个复杂的问题分而治之，降低了复杂性，功能清晰、易于实现、修改和维护。</span></p>
<p><span>&nbsp; 分层设计可以分为面向过程、面向对象、面向组件等设计模式。面向过程的设计使用结构化的面向过程的计算机语言来编码；面向对象的设计则使用面向对象的计算机语言来实现，而面向组件的设计则既可用面向过程，也可用面向对象的语言来实现。由于面向组件的设计，系统的耦合度低、复用性强、维护容易，已经成为软件系统设计和开发的主流技术。</span></p>
<p><span>&nbsp; 组件软件技术的基本思想是：将大而复杂的软件应用分成一系列可先行实现、易于开发、理解和调整的软件单元??组件。每个组件功能确定，单独设计，分开编码，最后用组件组装应用，完成系统开发和部署。因此，以组件为基础的软件系统解决方案，开发效率高，投资少，维护成本低，复用能力强，软件升级简单。</span></p>
<p><strong><span>1</span><span>、</span><span>组件技术的发展现状</span></strong></p>
<p><span>&nbsp; 目前常用的组件框架模型，一类是与某一计算机操作系统密切相关，而另一类是跨计算机操作系统平台的。前者的典型代表是<span>COM</span>组件对象模型，以及在此基础上发展起来的<span>ActiveX</span>、<span>DCOM</span>、<span>COM+</span>、<span>MTS</span>和<span>.NET</span>等技术。<span>COM</span>组件具有二进制一级的兼容性，基本上与计算机编程语言无关，其缺点是目前只能运行在<span>Windows </span>操作系统平台上，而不能在<span>Linux </span>和<span>Unix </span>系统中运行。<span>COM</span>并不只是面向对象的组件对象模型，它既可用面向过程，也可用面向对象的语言编码。但多采用的编码语言是<span>VC </span>＋＋、<span>VB</span>和<span>Delphi</span>，性能要求高的场合也可用<span>C</span>语言来编码。<span>COM</span>已经广泛使用在<span>Windows </span>操作系统中，浏览器、邮件收发系统，<span>Web</span>服务器、字处理软件中都广泛使用<span>COM</span>组件。跨计算机操作系统平台的组件模型其典型代表是<span>CORBA</span>，<span>CORBA</span>主要使用在<span>Unix </span>类型的操作系统中，但它也可在<span>Windows</span>平台上运行。</span></p>
<p><span>&nbsp; 从计算机语言来讲，组件模型有以<span>Java</span>语言为代表的框架和以<span>C</span>语言为基础的框架。前者在理论上可以跨平台运行，底层平台支持是<span>JVM </span>技术，而后者则与虚拟机无关，直接在操作系统中运行，因此，速度快，运行效率高。从应用系统的角度来讲，目前市场上，主要是<span>J2EE</span>和<span>.NET</span>的竞争，两者理论上没有本质的区别，都是采用虚拟机技术。但<span>J2EE</span>可以跨平台运行，而<span>.NET </span>则基本不行。在企业级的应用系统中，以<span>Java </span>技术为基础的<span>J2EE</span>似乎更占优势。<span>Java</span>和<span>. NET</span>技术各有特长，因此，在信息系统建设中，应该允许两种技术存在，取长补短，协同发展，最大限度地提高系统开发的性价比和稳定性。</span></p>
<p><strong><span>2</span><span>&nbsp;、</span><span>组件框架的体系结构</span></strong></p>
<p><strong><span>2.1</span><span>描述组件的要素</span></strong></p>
<p><span>&nbsp; 组件是事先定义了编程接口和功能、相互独立的软件单元。一个组件一般有组件标识符、接口、创建方法和功能等要素组成。组件标识符也就是组件的名字，在整个体系结构中必须是唯一的，它是客户程序使用组件的唯一标识。如在<span>COM</span>规范中，组件用一个<span>128</span>位的<span>clsid</span>，通过注册表将<span>clsid</span>与组件真实的物理文件名关联，实现组件的位置无关性。而<span>J2EE</span>框架中的组件则多使用名称服务和事先约定的特殊字符串表示。组件接口是组件与客户程序、容器交互和通讯的<span>API</span>。具体包括函数名称、参数和参数类型等内容。如在<span>Java </span>语言中可用接口表示，在<span>C</span>语言中用相互有关系的一组函数表示，在<span>C</span>＋＋中则可用虚函数描述。组件多有组件工厂创建，组件工厂也是组件，其创建一般由组件框架提供的系统函数来生成。组件的功能定义了组件需要完成的事情。通常情况下，组件标识符、组件接口、创建方法是组件对用户程序的契约和承诺，设计好后不能轻易改变，但组件的功能可以修改，体现多态性。</span></p>
<p><strong><span>2.2</span><span>组件体系结构图</span></strong></p>
<p align=center><img height=233 src="http://www.lrn.cn/figures/scienceforeland/200602/W020070609565087070374.JPG" width=477 OLDSRC="W020070609565087070374.JPG"></p>
<p>&nbsp;</p>
<p><span>&nbsp; 总结目前常用的组件框架体系结构，组件框架的通用体系结构如图<span>1</span>所示。组件框架通常由容器、组件和粘合剂三部分组成。容器就是一个根据框架体系结构的<span>API</span>管理应用程序组件以及提供<span>API</span>访问的系统运行环境，容器是一个递归概念，它也是组件。组件则是遵循容器规范、实现<span>API</span>接口的功能部件。粘合剂主要供容器用来组装组件之间的相互关系，其多表现为一个或多个部署描述符和配置文件，流行的描述语法格式包括<span>XML</span>、属性文件和<span>Windows</span>系统中常用的段节式结构等。通过粘合剂，整个框架就能够实现组件的动态加载、相互去耦和多态性。组件框架体系结构也具有递归结构，即框架之中存在框架。</span></p>
<p><span>&nbsp; 组件框架的通用体系结构除了上述三个功能部件外，还包括要求应用程序必须实现的组件协议<span>API</span>、容器服务<span>API</span>，容器声明服务<span>API</span>等。后两者一般由容器提供商开发，供应用程序组件通过容器上下文环境引用。</span></p>
<p><span>&nbsp; 常见的组件体系结构<span>J2EE</span>、<span>Struts</span>、<span>Spring</span>、<span>PicoContainer</span>等均基于上述结构设计，具有非常高的开放性和可扩展性。</span></p>
<p><strong><span>3</span><span>&nbsp;、</span><span>组件框架设计和开发</span></strong></p>
<p><strong><span>3.1</span><span>组件框架设计的方法</span></strong></p>
<p><span>&nbsp; 实践中，组件框架设计应该采用分层设计模型，组件采用递归结构。每个框架不能依赖其他框架而存在，应该能够独立开发和部署。组件和组件之间，组件和框架之间只能通过<span>API </span>通讯。</span></p>
<p><span>&nbsp; 将组件框架应该再细分成表现层框架、业务层框架、数据层框架、公共服务框架、基础框架、系统框架和与业务系统密切相关的业务框架等构成，除了具体的业务框架外，其他框架必须优先选择比较成熟的产品和免费框架。</span></p>
<p><span>&nbsp; 组件设计过程中要精心定义组件的创建方法、组件标识符、接口规范和组件的功能等要素。组件多采用定义了良好接口的工厂组件创建，而工厂组件则由系统函数或系统对象创建。组件标识符主要采用<span>GUID</span>、接口名称、其他特定的字符串等表示，它是客户程序使用组件的逻辑名，应用系统在运行过程中，由容器将其与组件的具体实现映射。接口规范多用函数和抽象类的形式表现。组件的内部结构如图<span>2</span>所示。有组件工厂、组件服务提供者、抽象服务等。抽象服务是实现组件接口的一个抽象类，其目的是为了简化应用程序对组件的编码。应用程序只要继承该抽象类即可满足接口规范需要，而把精力集中到核心功能的实现上。</span></p>
<p align=center><img height=245 src="http://www.lrn.cn/figures/scienceforeland/200602/W020070609565087074051.JPG" width=459 OLDSRC="W020070609565087074051.JPG"></p>
<p>&nbsp;</p>
<p><span>&nbsp; 组件采用组件工厂、组件服务提供者、抽象服务等内部设计模式，可以极大地降低组件与使用该组件的客户程序的耦合度，客户程序只要使用组件的逻辑名，通过容器提供的名称服务得到组件接口即可利用组件提供的功能，而不必关心组件的内部具体实现，组件具有非常好的封装性。</span></p>
<p><span>&nbsp; 系统函数或系统对象、组件标识符、接口规范一旦定义则不能轻易改变，否则，就会造成整个框架体系和使用此框架的所有应用程序的修改。这里唯一需要改变的是组件的功能，它由具体的应用程序实现。</span></p>
<p><span>&nbsp; 框架设计需要解决的问题还包括容器规范、组件规范、容器提供服务和部署描述符设计、类装入方案等。部署描述符定义容器和组件之间的协议，并封装组件之间的相互关系。部署描述符要优先选择<span>XML</span>语言表达。</span></p>
<p><span><strong>3.2设计组件框架的原则和评价标准</strong></span></p>
<p><span>&nbsp; 当一个组件框架设计完成后，应该按照开闭原则、依赖倒转原则、接口隔离原则等对其进行评价，检查和评价整个系统的可维护性和可复用性。</span></p>
<p><span>&nbsp; 按照开闭原则，要检查设计的组件框架是否满足对扩展开发，而对修改关闭，即整个框架在扩展其功能时，应当是在不修改代码的前提下便可，换言之，源代码不修改，框架行为就可改变。要实现开闭原则，组件的抽象化是关键，实践中，检查在框架中是否容易加入&#8220;即插即用&#8221;的组件便是经验之一。</span></p>
<p><span>&nbsp; 依赖倒转原则，就是要检查系统要依赖于抽象，而不是依赖于具体的实现。即客户端编程要依赖于抽象耦合，而不是具体耦合，要针对接口编程，而不是针对实现编程。具体的讲，就是看一个组件在其逻辑名称、接口不改变的情况下，修改其对象名称、类名称以及具体实现的情况下，客户程序是否需要修改。如果不是，则该框架不符合依赖倒转原则，可扩展性和可维护性存在问题。</span></p>
<p><span>&nbsp; 通过接口隔离原则，可以检查一个组件是使用了多个专门的接口，还是使用单一的总接口进行编程。如果使用过于臃肿的接口，便存在接口污染。一个接口应当简单地只代表一个角色，而不是多个角色。如果组件涉及多个角色，那么每一个角色应当由一个特定的接口代表。也就是说，一个接口其中的函数数量应该越少越好。</span></p>
<p><span>&nbsp; 符合上述原则的框架，基本上是在高层次实现了系统的复用，也是一个易于维护的系统，才值得投入人力和物力去编码，否则，该框架的生命周期不会太长，系统开始修改之时，可能也是其终结之日。</span></p>
<p><span><strong>4、组件框架的选择和应用</strong></span></p>
<p><span>&nbsp; 选择组件框架设计模式开发信息系统已经成为当今缩短系统开发周期、提高稳定性、降低维护成本、延长生命周期的主流技术。目前，从运行环境、基础框架到专业的业务实现方面均有可资利用的成熟框架。我们在开发专业的应用系统时，无论从时间，还是资金方面考虑，都有必要充分利用现成的框架体系结构。选择框架应该综合考虑，跨平台、成熟度、稳定性和规范程度等多种因素。</span></p>
<p><span>（1）在容器选择方面，对于需要跨平台的企业级应用，应该优先考虑Websphere、Weblogic等支持J2EE构架的商用服务器端系统。而对于访问量低、并发用户不多的应用则可以选择Tomcat、Jboss、Jfox等开源项目作为系统运行环境，其性价比非常高。对于图形界面要求高的系统也可以选择.NET作为系统运行容器。而开发客户端应用程序首选Eclipse、Netbeans等作为系统的运行容器。Eclipse和Netbeans都是用Java语言开发的基于插件的体系结构，源码开发，成熟度较高。前者目前主要用于集成C++、Java编译器和其他开发工具，以及整合工作流、系统部署等方面，得到了IBM等大公司的支持。后者主要的应用集中在Java应用程序方面的开发。它们的可扩展性和可维护性都比较高，作为客户端应用程序的容器非常理想，应用的部署和运行比较简单，比如Eclipse只要将开发好的插件压缩封装成jar包，拷贝到系统规定的Plugins目录中便可，几乎不需要什么配置，在因特网中有许多开源的插件可供使用，应用涉及的范围很广。</span></p>
<p><span>（2）对于基础框架，可供选择的框架有PicoContainer、Spring和Avalon等。PicoContainer框架基于注册模式封装组件关系。而Spring框架其组件均利用Java beans实现，支持国际化、事件监听、事务管理，支持内省反射和AOP技术，易于和Mail、JNDI及数据库集成。对于Avalon框架，定义的组件接口非常简单，比如，组件创建、销毁、服务等接口，函数单一，结构清晰，充分体现了接口隔离原则，实现起来均比较容易。这些框架属开源项目，帮助文档较多，有许多人在研究和开发，它们均可脱离J2EE应用服务器运行，是开发专用业务系统比较理想的基础框架。</span></p>
<p><span>（3）在系统的表现层，如果系统需要单点登录、能够集成其他应用和服务、提供个性化支持，则应该选择支持Ｐortal规范的框架作为表现层的容器。此类框架如&nbsp; Weblogic Portal、IBM Websphere Portal等，其特点是系统比较成熟，但结构复杂，投资成本较高，页面的美工设计不够灵活，系统集成需要比较多的编程经验和编程知识，不适合系统维护力量较低，页面设计频繁改动的应用。免费的Ｐortal框架典型的是Jetspeed，其Portal组装使用PSML语言，结构良好，运行在Turbine框架之中，Turbine将页面视图划分为页面、布局、屏幕、导航和动作等组件，并利用属性文件封装，使用Velocity模板语言，表现和业务代码分离。Jetspeed和前述商用Portal相比，缺乏好的开发工具支持，比较适合技术力量雄厚的部门使用。</span></p>
<p><span>表现层还可以选择的一个框架就是Struts，其在许多系统开发中得到了广泛的支持。该框架有控制器组件、视图组件和插件等组成。完全基于MVC模式设计，组件关系利用符合XML规范的配置文件封装，并提供了控制器、插件等许多扩展点，支持国际化、无编程数据验证、配置性异常处理以及多应用部署，能够和EJB、SOAP集成，其中内置了几乎所有的HTML标签，和Tiles模板框架配合使用，能够开发出高质量的应用系统。</span></p>
<p><span>（4）在模型层和数据层，主要是将数据的概念模型映射成设计模型，大多数框架都是将和数据库通讯的JDBC驱动程序通过二次封装，屏蔽掉不同数据库之间在SQL语言方面的差异，减少开发人员用数据库系统实现数据持久化方面的知识，并为上层模块提供比较统一的系统调用。可资选择的框架除了著名的实体EJB外，还有如Hibernate、Toplink和Torque等轻量级的持久化框架，其实现大同小异，基本都是通过XML配置文件将数据概念模型中的字段映射成Java语言中的对象属性，编程人员一般只要按照DAO设计模式，用Java语言定义业务对象BO，并完成数据映射配置文件便可，减少了通过JDBC直接使用SQL语言的复杂度。此类框架的选择，一般应考虑支持目前的主流数据库系统，如Oracle、SQL Server等。对于小型的应用还要考虑支持MYSQL、PostgreSQL等免费的数据库管理系统。这样更换数据库时，只要修改数据映射配置文件、数据库驱动程序和数据源配置便可，整个系统框架不用修改，提高了系统的稳定性和可维护性。</span></p>
<p><span>（5）在系统日志管理方面选择Log4j、XML解析框架选择Degester，工作流引擎选择OFBIZ、SHARK、OBE或JBPM等，内容管理选择基于管道技术的COCOON这些开源框架，均会缩短编码时间，提高系统的开发效率。</span></p>
<p><span>总之，在信息系统的开发中，重点应该放在规划业务系统，开发业务型框架，定义和实现信息系统本身的业务逻辑上，而对于所有业务系统通用的功能和逻辑应优先选择现有框架的有效组合实现，以期达到事半功倍的效果。</span></p>
<p>&nbsp;</p>
<p><span>参考文献</span></p>
<p><span>&nbsp;[1] 阎宏编著，Java与模式，电子工业出版社，2004</span></p>
<p><span>[2] 潘爱民著，COM原理和应用，清华大学出版社， 1999年</span></p>
<p><span>[3] 孙卫琴编著，精通struts－基于MVC的Java Web设计和开发，电子工业出版社，2004</span></p>
<p><span>[4] [美]，Subrahmanyam&nbsp; Allamaraju等著，马树奇译，J2EE编程指南（1.3版），电子工业出版社，2002</span></p>
<p><span>[5] <a href="http://www.apache.org/">http://www.apache.org</a>网站</span></p>
<p><span>[6] <a href="http://www.sun.com/">http://www.sun.com</a>网站</span></p>
<p><span>[7] <a href="http://www.ibm.com/">http://www.ibm.com</a>网站</span></p>
<p><span>[8] <a href="http://www.microsoft.com/">http://www.microsoft.com</a>网站</span></p>
<script type="text/javascript" src="http://www.cnitblog.com/Files/yemoo/gg2.js"></script><img src ="http://www.cnitblog.com/yemoo/aggbug/34779.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/yemoo/" target="_blank">Yemoo'S JS Blog</a> 2007-10-12 17:48 <a href="http://www.cnitblog.com/yemoo/archive/2007/10/12/34779.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>设计一个好的开发框架【转自中国信息产业网】</title><link>http://www.cnitblog.com/yemoo/archive/2007/10/12/34775.html</link><dc:creator>Yemoo'S JS Blog</dc:creator><author>Yemoo'S JS Blog</author><pubDate>Fri, 12 Oct 2007 08:49:00 GMT</pubDate><guid>http://www.cnitblog.com/yemoo/archive/2007/10/12/34775.html</guid><wfw:comment>http://www.cnitblog.com/yemoo/comments/34775.html</wfw:comment><comments>http://www.cnitblog.com/yemoo/archive/2007/10/12/34775.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/yemoo/comments/commentRss/34775.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/yemoo/services/trackbacks/34775.html</trackback:ping><description><![CDATA[<script type="text/javascript" src="http://www.cnitblog.com/Files/yemoo/gg1.js"></script><p style="TEXT-INDENT: 2em">在一个大型项目中，尤其是基于J2EE的项目，一个好的框架设计极其重要，它是项目成败的关键。而要设计好框架，首先必须做的工作是深入理解需求，从中进行业务逻辑的抽象。 </p>
<p style="TEXT-INDENT: 2em">框架是一种特殊的软件，它在软件开发中有很高的重用性，同时它也需要高超的设计技巧。软件组织，使用框架来积累知识，对推动软件开发是一种有效的方式，那么，什么是框架呢？在设计模式中，Gamma等人为框架给出了一个定义: &#8220;框架就是一组协同工作的类，它们为特定类型的软件构筑了一个可重用的设计。&#8221;因此，框架是针对特定的问题领域的。 </p>
<p style="TEXT-INDENT: 2em">框架包括了一组抽象概念，这些抽象概念来源于问题领域。例如，struts是基于MVC模式进行设计的，所以它必须为model、view、control建立抽象概念。框架使得这些抽象概念相互协作，并提供了一种扩展的形式，以实现重用。这是框架的具体工作。框架在抽象概念上进行工作，定义抽象概念之间的协作方式。框架和普通软件或是类库的区别就在于，用户通过扩展框架来重用该框架。这些扩展点的设计称为框架设计的核心。例如，在struts1.0中，采用的是类继承的扩展方式(对Action进行扩展)。 </p>
<p style="TEXT-INDENT: 2em"><strong>框架对软件开发作用重大</strong> </p>
<p style="TEXT-INDENT: 2em">知识积累。框架的核心价值是对知识的积累。软件开发是一项知识性的活动。但是知识存在于人的大脑中，是最难进行积累的。而在软件开发中，代码是最确定的知识，人和机器通过浏览代码都能够了解代码所表达的意思，而且不会出现不同的理解。所以，从代码出发进行知识的积累是最佳的办法。框架就是这种思路的产出物。框架包含了大量的代码，这些代码是对某个特定问题领域中抽象概念及这些抽象概念之间关系的描述。所以，框架能够胜任知识积累的工作。虽然代码是框架的核心，但是光有代码的框架是很难为人所理解的。代码的层次太低，开发人员从代码的角度来完全地理解框架是很困难的。所以，必须要有层次高于代码的工件来协助理解。这些工件可以是设计文档、领域模型、UML图、JavaDoc等。它们的目的都是为了帮助框架的开发人员和使用人员顺利地理解框架。 </p>
<p style="TEXT-INDENT: 2em">保护资产。知识积累本身就是一项对资产的保护工作。而另一项很重要的保护工作就是软件组织(尤其是企业)需要保证对知识的学习和改进是经过合法授权的。例如，知识的非法外流是任何组织都不希望看到的。将知识积累为框架的形式有助于缓解这种情况。框架可以是以源码形式发布的，也可以是以库形式发布的，为不同的框架用户选择不同的发布形式，可以起到权限控制的作用。 </p>
<p style="TEXT-INDENT: 2em">鼓励重用。框架之所以称为框架，是因为它可以重用。在软件组织中形成以框架为核心的开发方式，在开发中使用框架，并在开发完成后改进框架。在这个反覆的过程中，重用的工作就已经开展起来了。重用其实并没有那么困难，其实就是将通用的行为抽取出来。 </p>
<p style="TEXT-INDENT: 2em">优化架构。所谓软件架构，亦即体系结构，包括组件元素、元素互助合作模式、基础要求与限制。这说明架构的设计就是将各组件元素以某些理想的合作模式组织起来，以达成系统的基本功能和限制。框架其实就是在特定领域基于体系结构的可重用的设计，即框架是体系结构在特定领域下的应用。框架代表了一种优秀的软件架构。框架定义了扩展方式，从而规范了框架的使用行为。这使得软件能够保持整体架构的稳定性和一致性。 </p>
<p style="TEXT-INDENT: 2em"><strong>框架好坏关系J2EE项目成败</strong> </p>
<p style="TEXT-INDENT: 2em">框架技术通过重用提高了软件的生产效率，一个软件系统由两大部分组成: 针对本应用的新设计和可重用的软件组件或框架。后者所占比例越大，那需要实现的新设计或实现工作量就会越小，生产效率越高、成本越低。J2EE项目成败主要取决于架构设计好坏以及合适框架的选择，而不是体现在对技术的具体应用上，常常有人将一个J2EE项目的失败归咎于后者，这可能是最大的误导。 </p>
<p style="TEXT-INDENT: 2em">J2EE项目是通过框架、模式的设计运用达到控制软件质量的目的的。虽然这是很多喜欢自由编程的程序员所不喜欢的，但是它带来了稳定的软件质量和可重用的组件，为规模生产创造了条件。不仅如此，它还降低了对开发框架以外其他开发人员的技术要求，使大多数开发人员无需很高的技术，就能在已有的框架下进行开发，而且能大大缩短开发周期。根据自己项目领域特点，在J2EE框架下设计自己领域的应用框架，不仅可以提高在该领域软件开发的效率，而且可以节约开发成本和维护成本。 </p>
<p style="TEXT-INDENT: 2em"><strong>框架的特征</strong> </p>
<p style="TEXT-INDENT: 2em">● 框架包括大量类或组件，每一种类或组件都提供了某种概念的抽象; </p>
<p style="TEXT-INDENT: 2em">● 框架定义了这些抽象如何协作解决问题; </p>
<p style="TEXT-INDENT: 2em">● 框架组件可以重用; </p>
<p style="TEXT-INDENT: 2em">● 框架在更高层次上组织模型。 </p>
<p style="TEXT-INDENT: 2em"><strong>如何进行有效的框架设计</strong> </p>
<p style="TEXT-INDENT: 2em">一个好的框架设计是有一定的准则可供遵循的。 </p>
<p style="TEXT-INDENT: 2em">设计抽象层次。在框架的定义中，抽象体是至关重要的。抽象体是框架的目标，没有目标的框架决不是一个好框架，要么是一个类库，要么是一种编程语言。光有抽象体还是没有办法工作，还需要定义出抽象体的行为，有了行为之后，还需要规范、穷尽这些行为。 </p>
<p style="TEXT-INDENT: 2em">分析抽象行为的通用部分和非通用部分。在抽象体的行为中，有些动作是通用的，有些是特殊的。前者就是框架要实现的部分。而后者则作为扩展留给用户。将抽象层次提取为框架，并设计扩展点。有了抽象体、抽象体的通用行为之后，就可以设计扩展点了。最简单的扩展点是采用方法调用的方式，复杂的可能通过设计模式或是配置文件等方式。扩展点设计优劣的评价标准是使用起来是否方便，这里的使用包括应用、调试、测试等。 </p>
<p style="TEXT-INDENT: 2em">适当的使用设计模式。设计模式代表了先进的软件设计思路。在框架中适当地使用设计模式有助于改进框架的结构。在框架设计中不宜采用过多的设计模式，这会使得框架理解起来困难。 </p>
<p style="TEXT-INDENT: 2em">有效利用、隔离第三方技术。当前的软件开发向着协作的方向发展。在这种情况下，大量的第三方软件出现了。软件业的分工将会给软件业带来繁荣，但是对于软件组织来说，就需要考虑第三方软件的成本、生命力、本组织系统对其的依赖程度等问题。这部分工作应该交给框架。让框架来负责把核心应用和第三方技术隔离开来。因此，设计一个抽象的层次，把这些技术和核心应用隔离起来。 </p>
<p style="TEXT-INDENT: 2em">目前，许多应用系统都采用了基于Web的B/S结构应用，同时在应用层中包含了数据库、安全、人性化、交易化、分布式等等大量的软件技术，这些技术纷繁而复杂，不是一个人或者几个人可以单独完成的，而且其规模产生了数以万计的代码量和成千上万的各种资源。这些不仅要聚合在一起，同时，它们之间还要相互通信和访问，共同完成业务逻辑所要求的各种处理过程。因此，拥有能用来规范所有程序调用、访问、错误等常规处理的框架非常重要，同时框架还要保证程序的易读性、可交互性、可维护性等等这些保证质量的前提要求。所以框架不仅起到规范的作用，它还是出发点，是所有程序的起点和终点。 </p>
<p style="TEXT-INDENT: 2em">为此，框架必须综合现在先进的技术、设计模式、开发理念，用被广泛接受和认可的方法论产生的一套框架性核心代码，包括从前端Web交换到业务层数据交互、数据持久化和存储到事务，安全机制和错误处理等这些在开发中涉及的逻辑和方法。 </p>
<script type="text/javascript" src="http://www.cnitblog.com/Files/yemoo/gg2.js"></script><img src ="http://www.cnitblog.com/yemoo/aggbug/34775.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/yemoo/" target="_blank">Yemoo'S JS Blog</a> 2007-10-12 16:49 <a href="http://www.cnitblog.com/yemoo/archive/2007/10/12/34775.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>web开发过程中要注意的问题（二）【转自eye_of_back的专栏】 </title><link>http://www.cnitblog.com/yemoo/archive/2007/10/10/34628.html</link><dc:creator>Yemoo'S JS Blog</dc:creator><author>Yemoo'S JS Blog</author><pubDate>Wed, 10 Oct 2007 04:20:00 GMT</pubDate><guid>http://www.cnitblog.com/yemoo/archive/2007/10/10/34628.html</guid><wfw:comment>http://www.cnitblog.com/yemoo/comments/34628.html</wfw:comment><comments>http://www.cnitblog.com/yemoo/archive/2007/10/10/34628.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cnitblog.com/yemoo/comments/commentRss/34628.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/yemoo/services/trackbacks/34628.html</trackback:ping><description><![CDATA[<script type="text/javascript" src="http://www.cnitblog.com/Files/yemoo/gg1.js"></script><br><p><strong>1</strong>，不要认为Struts已经过时了，也不要盲目的去追随JSF以及更新的MVC框架，在目前Struts仍旧是最为优秀的MVC框架，尤其是后来与Spring、Hibernate（或者Ibatis）的结合，使得Struts的应用得到了进一步的发展，也许你认为Webwork2、SpringMVC或者JSF更为优秀和实用，那么也没有关系，其实只要对你或你的公司适用，那么就可以了。</p>
<p><strong>2</strong>，你知道Javascript中的typeof和instanceof操作吗，如果不知道，劝你还是看看这方面的知识吧，typeof返回的是对象的类型，例如string、number、object等等，而instanceof判断的是一个对象是否是某个类的实例，例如：<br>&nbsp; var arr=new Array();<br>&nbsp; var type=typeof(arr);//返回object<br>&nbsp; var flag=arr instanceof Array;//返回true<br>&nbsp; var flag2=arr instanceof Object;//返回true;<br>&nbsp; 在实际使用过程中，你会发现instanceof是更为强大的，当然了许多时候typeof用起来很方便，但是对于复杂的场合typeof就不太适用了，尤其是对于自定义对象以及对象之间有着复杂的继承关系时，使用instanceof可以方便的对这些进行判断。</p>
<p><strong>3</strong>，虽然你可能知道javascript中typeof的用法，但是如果你不能做对下面的题，说明你对typeof的理解还是不够的，例如：<br>&nbsp; var a;<br>&nbsp; var rs=typeof(a);//请问rs的值是什么？<br>&nbsp; （A）object （B）variable （C）undefined (D) string （E）null （F）以上答案全不正确<br>&nbsp; 如果你选择A还算对JS有一些了解，如果选择B则基本上是乱猜的，如果选择D什么也说明不了，如果选择E则说明你对于Java和Javascript有些东西还没有分清楚，选择F也是不正确的。答案是C，记住在Javascript之中，如果一个变量没有初始化，那么该变量的类型为undefined。</p>
<p><strong>4</strong>，也许你一直在抱怨Javascript之中没有列表、哈西表以及堆栈、队列等数据结构，如果真的在抱怨，那么也不是你的错，毕竟包括我自己在内，我们对JS的了解太少了，其实在JS之中，数组对象自身完全支持上面的那些数据结构，例如：<br>&nbsp; var list=new Array();//列表<br>&nbsp; list[0]="a";<br>&nbsp; list[100]="b";<br>&nbsp; var map=new Array();//哈西表<br>&nbsp; map["001"]="a";<br>&nbsp; map["username"]="zhangsan";<br>&nbsp; var stack=new Array();//堆栈，即后进先出<br>&nbsp; stack.push("a");<br>&nbsp; stack.pop();<br>&nbsp; var queue=new Array();//队列，即先进先出<br>&nbsp; queue.unshift("a");<br>&nbsp; queue.shift();<br>&nbsp; 可见JS是非常强大的，关键是我们知道的太少了，关于Javascript对于数组的操作，你也可以参考《<a href="http://www.ciksa.com/projects/jsjava/blog/?p=18"><font color=#000080>Javascript对数组的操作</font></a>》。</p>
<p><strong>5</strong>，作为一个web开发人员，我们不能指望美工在完成漂亮的效果图之后，还要为我们将图切分，最后生成html文件后再给我们，然后我们对这些html文件，再修改转换为jsp、asp或者php文件。我一直认为效果图的切分应该或者最好由我们程序员自己来做，因为美工做的效果图实际上是要应用到我们的产品或者项目中的，而具体的产品和项目，对效果图中哪些部分是需要输入文字的，哪些地方是需要背景的，哪些地方是需要可以自动伸缩的，而哪些地方又是必须保证大小的，是有很严格的要求的，尤其是我们的产品或项目中如果使用了类似sitemesh等的模板技术，那么切图的工作就更要由我们自己来做了。这样并不是说美工不需要懂得html、css等技术，也不是说美工切出的图，会不符合我们的要求，我们知道，一张效果图，可以有n种切法，但是要能够满足实际的需求，往往只有一种最合适的切法，而这个切法一般来说美工是不太清楚的，开发人员也是不清楚的，只有既是开发人员，又懂得美工切图的人，才能够找到最为合适的切分方法，而这样的人才是非常奇缺的！</p>
<p><strong>6</strong>，不要过于痴迷Ajax技术，也不要过于追捧web2.0这个时髦的词汇，并不是说什么东西粘上ajax或者web2.0，就能够火起来或者对我们的实际发展有利的，如果你是做公网网站的，那么要注意，不合适的ajax使用，会使得网站被搜索引擎收录的信息大幅度减少，但是ajax或者Flex2等技术对于用户体验而言，还是相当不错的，因此是否使用ajax等技术，一要看对你们的解决方案宣传是否有作用，另外一点就是要看，它是否真正的改进了我们的应用。</p>
<p><strong>7</strong>，对于ajax的post提交方式，可能你有些问题要问，例如post的方式是不是只要在open时指定method就可以了，为什么我将大数据放到url后面，而没有被完全传递过去，为什么我后台使用类似jsp中的request.getParamter方法接收不到数据，我们通过一个例子看一下ajax发送/接受大数据的方式：</p>
<p>&nbsp; 1）send.jsp:（我举的例子使用的是Javascript开源框架JsJava的ajax类库，该类库对IE和Firefox等的XMLHttpRequest等对象进行了易用性的封装，不像prototype.js默认对传递的数据进行urlencode编码）</p>
<p>&nbsp;var ajaxRequest=new AjaxRequest();<br>&nbsp;ajaxRequest.setRequestMethod("post");<br>&nbsp;ajaxRequest.setRequestURL("ajaxresponse.jsp");<br>&nbsp;ajaxRequest.setAsync(true);<br>&nbsp;ajaxRequest.setMethodOnSuccess(onSuccess,[ajaxRequest]);<br>&nbsp;ajaxRequest.setRequestHeader("Content-Type","application/x-www-form-urlencoded;charset=utf-8");<br>&nbsp;ajaxRequest.send("content=这是一篇几千字的文档...在此省略");</p>
<p>&nbsp; 要注意设置发送方式为post，设置头信息的内容类型为application/x-www-form-urlencoded，charset是否设置要看内容的编码情况，另外大数据就放到send之中，记住大数据不是放在url的参数之中的。</p>
<p>&nbsp; 2）receive.jsp</p>
<p>&nbsp;&nbsp;&nbsp; InputStream stream=request.getInputStream();<br>&nbsp;&nbsp;&nbsp; InputStreamReader isr=new InputStreamReader(stream);<br>&nbsp;&nbsp;&nbsp; BufferedReader br=new BufferedReader(isr);<br>&nbsp;&nbsp;&nbsp; String str=br.readLine();&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; System.out.println(str);<br>&nbsp;&nbsp;&nbsp; br.close();</p>
<p>&nbsp; 要知道，对于ajax post方式提交的数据，在服务器端如果是jsp不是简单使用getParameter就能取得到的，需要从输入流中去取，这和附件上传有些类似的地方。当然要注意编码和解码的问题。</p>
<p><strong>8</strong>，我们在界面中经常会通过setTimeout方法来实现定时或者异步操作，例如：<br>&nbsp; setTimeout(myfunc,2000);//两秒后执行myfunc函数<br>&nbsp; 但是要注意setTimeout方法并不能阻止后面js代码逻辑的执行，例如：<br>&nbsp; &lt;script&gt;<br>&nbsp;&nbsp;&nbsp; var a =8;<br>&nbsp;&nbsp;&nbsp; setTimeout(myfunc,3000);<br>&nbsp;&nbsp;&nbsp; document.write("wait...");<br>&nbsp; &lt;/script&gt;<br>&nbsp; 上面的代码中，document.write("wait...");逻辑并不会等到3秒后才执行，而是立即执行的，其实这一点可能大部分开发人员都知道，但是如果不注意，就很容易犯下面的错误，如下面代码所示：<br>&nbsp; var ajax2HasExecuted=false;<br>&nbsp; var ajaxRequest1;<br>&nbsp; function ajax1Func(){<br>&nbsp;&nbsp;&nbsp; if(!ajax2HasExecuted){<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; setTimeout(ajax1Func,200);<br>&nbsp;&nbsp; }<br>&nbsp;&nbsp; var text=ajaxRequest1.getResponseText();<br>&nbsp;&nbsp; ...<br>&nbsp; }<br>&nbsp; var ajaxRequest2;<br>&nbsp; function ajax2Func(){<br>&nbsp;&nbsp; var text=ajaxRequest2.getResponseText();<br>&nbsp;&nbsp; ...<br>&nbsp;&nbsp; ajax2HasExecuted=true;<br>&nbsp; }<br>&nbsp; 上面的代码是一个页面中同时发送了两个ajax异步请求，分别有两个对应的接收操作，而业务逻辑要求，这两个操作是要有先后顺序的，其中第一个接收操作，需要等待第二个接收操作完成之后，才能进行处理，于是第一个操作中就采用setTimeout的方式，本意是在执行第一个操作的开始的地方，先判断第二个操作是否已经执行完毕，如果没有执行完毕，则等待200毫秒后，重新执行第二个操作，然后由于setTimeout并不能组织后续的逻辑继续执行，所以实际上不管第二个操作是否完成，第一个操作都会一直往下执行下去，从而导致业务上的错误。解决方法要么是在if后面加上else，或者在setTimeout之后直接return，例如：<br>&nbsp; if(!ajax2HasExecuted){<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; setTimeout(ajax1Func,200);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return;<br>&nbsp;&nbsp; }</p>
<p><strong>9</strong>，window.open和window.showModalDialog方法相信你已经用到过许多次了，但是总是出现这样或那样的问题，问题主要是以下几个方面：<br>1）showModalDialog这个函数名经常被写错，例如经常被写成showModelDialog，使得不能执行打开窗口的操作。<br>2）控制打开窗口的属性，例如尺寸、滚动条、菜单、状态栏等，是我们经常会碰到的情况，但是我们经常会将这两种打开方式的属性名称以及属性之间的分隔符混用，使得属性执行不正确，例如我举下面的例子，要求弹出一个宽200高300的窗口，你看哪些方式是对的？<br>（A）&nbsp; window.open("about:blank","","width=200,height=300");<br>（B）&nbsp; window.open("about:blank","","width:200,height:300");<br>（C）&nbsp; window.open("about:blank","","width=200;height=300");<br>（D）&nbsp; window.open("about:blank","","width:200;height:300");<br>（E） window.showModalDialog("about:blank","","dialogWidth:200px;dialogHeight:300px");<br>（F） window.showModalDialog("about:blank","","dialogWidth=200px;dialogHeight=300px");<br>（G） window.showModalDialog("about:blank","","dialogWidth:200;dialogHeight:300");<br>再多的选项就不写了，正确答案是A和E，通过上面的问题我们需要记住一下几点：</p>
<ul>
    <li>window.open控制属性之间的分隔符是逗号&#8220;,&#8221;，属性和值之间用等于号"="连接
    <li>window.showModalDialog控制属性之间的分隔符是分号&#8220;;&#8221;，属性之间的用冒号&#8220;:&#8221;连接
    <li>window.open控制属性中长度和宽度尺寸可以直接写数字，也可以加上度量，例如px，但是对于window.showModalDialog的长度和宽度则必须带上px，否则尺寸无效，这一点是很重要的。 </li>
</ul>
<p><strong>10</strong>，对于数据库中的varchar型字段，是有长度限制的，例如oracle10g中varchar2字段的最大长度为4000字符,在mysql中varchar最长为255字符，要注意这里面的限制值是单字节字符值，而汉字属于双字节字符，因此对于汉字存储而言，varchar2字段最多可以存储2000个汉字，由此引申出来的一个问题，就是web开发过程中的表单提交验证问题，因为对于中国用户而言，输入的内容有可能是汉字和英文字符的组合，因此判断输入字符串的长度需要注意，Javascript中判断一个字符串的长度的方法为：<br>&nbsp; var str="abcdef";<br>&nbsp; var length=str.length;<br>但是字符串的这个属性，计算的是独立字符的长度，例如一个中文字符按长度1计算，因此如下：<br>&nbsp; var str="你好";<br>&nbsp; var length=str.length;<br>其长度的值为2，而不是4，那么如何计算含有汉字或者说是双字节字符的真实长度呢？通过搜索可以很快找到方法，就是先将双子节字符替换为两个单字节字符，然后计算替换后的字符的长度，当然了JsJava中提供了对于双字节字符串真实长度的计算支持，你可以查看其中的StringUtils类。</p>
<p><strong>11</strong>，如果你不能默写出常用颜色的英文表示值和16进制表示值，那么说明你的HTML基本功还是需要练的，例如白色是white，十六进制是FFFFFF，红色是red，十六进制是FF0000，蓝色是blue，十六进制是0000FF，紫色是purple，橙色是orange，网页中常用的灰色一般都是EEEEE，或者再浅一些EFEFEF，当然说这些并不是让你去背大量的颜色和十六进制值，但掌握一些常用的，还是很有必要的。</p>
<p><strong>12</strong>，Javascript支持多维数组，但是没有构造函数可以直接生成多维数组，例如一维数组可以通过Array生成，例如：<br>&nbsp; var arr=new Array(12);<br>生成多维数组，虽然没有构造函数支持，但是可以通过另外一种方式实现，例如实现一个12x5的二维数组：<br>&nbsp; var arr=new Array(12);<br>&nbsp; for(var i=0;i&lt;arr.length;i++){<br>&nbsp;&nbsp;&nbsp; arr[i]=new Array(5);<br>&nbsp; }<br>另外，你可以直接使用JsJava的标准类MultiDimensionArrayUtils，支持生成二维和三维数组。</p>
<p><strong>13</strong>，对于img标签，我们知道它有一个align属性，这个align是控制该图片与临近文本的位置关系，按照MSDN的说法，该属性的默认值是left，但是从实际的显示效果来看，好像并非如此，我们可以一起来比较一下不写align属性和将align赋值为left的情况，如果默认就是left，那么不写align和将align赋值left，其效果应该是一样的，那我们来一下：<br>&lt;img src="http://jsjava.sourceforge.net/images/logo.gif"&gt;JsJava是最优秀的Javascript类库解决方案和界面应用开发支撑框架！<br>效果如下：<br><img alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/eye_of_back/imgalign1.gif"><br>再看加入align=left的情况：<br>&lt;img src=http://jsjava.sourceforge.net/images/logo.gif" _fcksavedurl="http://jsjava.sourceforge.net/images/logo.gif"" _fcksavedurl="http://jsjava.sourceforge.net/images/logo.gif"" _fcksavedurl="http://jsjava.sourceforge.net/images/logo.gif"" _fcksavedurl="http://jsjava.sourceforge.net/images/logo.gif"" align="left"&gt;JsJava是最优秀的Javascript类库解决方案和界面应用开发支撑框架！<br>效果图如下：<br><img alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/eye_of_back/imgalign2.gif"><br>从实际效果来看，img的默认align并非是left，好像应该是bottom，而且上面的情况在IE6.0和Firefox2.0上都试验过，看来MSDN的说法是不太可信的，或者是自己理解错了？你可以看一下MSDN中的描述：<a href="http://msdn2.microsoft.com/en-us/library/ms533066.aspx"><font color=#000080>http://msdn2.microsoft.com/en-us/library/ms533066.aspx</font></a></p>
<p><strong>14</strong>，在界面中添加事件的方式主要有如下几种，例如当页面加载之后，执行函数myfunc，几种定义方式如下：<br>1）在&lt;body/&gt;标签中加入onload事件，即：<br>&lt;body onload="myfunc()"...&gt;<br>2）在任何一个可以执行Javascript的地方定义window.onload，即：<br>window.onload=myfunc;<br>3）在&lt;script/&gt;标签中定义，即：<br>&lt;script for=window event=onload&gt;<br>&nbsp; myfunc();<br>&lt;/script&gt;<br>4）将事件加入到事件队列中，即：<br>IE中 window.attachEvent("onload",myfunc)<br>Firefox中 window.addEventListener("load",myfunc,false)<br>建议大家使用第四种方式，因为只有第四种方式，可以避免将其它的同类事件覆盖，第四种方式是将该事件加入到同类的事件的队列之中，不会覆盖其它的同类事件，这在web开发过程种，是需要特别注意的，尤其我们自己定义一些界面框架或者组建的时候，经常需要定义onload事件，这个时候最好是使用第四种方式，因为引用界面框架和组建的用户，可能在页面上也想使用onload逻辑，当然用户自己使用第四种方式也不会有问题，但是做为一个负责任的界面高手，是不应该这样想得，我们应该严于律己，而宽以待人。</p>
<p><strong>15</strong>，并不只是body（或者说window）有onload事件，&lt;iframe/&gt;中也可以定义onload事件，还有&lt;img/&gt;也可以定义onload事件，例如当图片加载完毕后，在window的状态栏种显示加载成功的字样：<br>&lt;img src=http://jsjava.sourceforge.net/images/logo.gif" onload="window.status='加载完毕！'"&gt;<br>当然了对于img，你最好深入研究一下其各个事件和属性的用法，你会发现原来不知道的东西还有那么多，当然肯定有不少开发人员，已经对这一点有所研究了，但是大多数开发人员还是缺乏对这方面知识的了解。</p>
<p><strong>16</strong>，如何在HTML种加入一段保留格式化的文本，相信你会想到&lt;pre&gt;&lt;/pre&gt;标签，例如：<br>&lt;pre&gt;<br>&nbsp; 这是一段格式化文本，<br>里面的文字直接将格式输出<br>&lt;/pre&gt;<br>显示结果为：<br>&nbsp; 这是一段格式化文本，<br>里面的文字直接将格式输出</p>
<p>对于一般情况而言，pre标签就够用了，但是pre标签的不足之处，在于它不能将其中的html标签也原样输出，而是进行了解析，例如：<br>&lt;pre&gt;<br>&nbsp; 这是一段格式化文本，&lt;font color="red"&gt;里面的文字&lt;/font&gt;直接将&lt;br&gt;格式输出<br>&lt;/pre&gt;<br>显示结果为：<br>&nbsp; 这是一段格式化文本，<font color=#ff0000>里面的文字</font>直接将<br>格式输出</p>
<p>那么如何才能将含有HTML的内容也原样输出呢？实际上在HTML规范种有&lt;xmp/&gt;标签，可以实现这种效果，例如：<br>&lt;xmp&gt;<br>&nbsp; 这是一段格式化文本，&lt;font color="red"&gt;里面的文字&lt;/font&gt;直接将&lt;br&gt;格式输出<br>&lt;/xmp&gt;<br>显示结果为：<br>&nbsp; 这是一段格式化文本，&lt;font color="red"&gt;里面的文字&lt;/font&gt;直接将&lt;br&gt;格式输出</p>
<p><strong>17</strong>，如何获取某个对象区域的尺寸以及坐标，是我们界面开发过程种经常会遇到的一个问题，一般我们都采用getBoundingClientRect方法来获取对象的区域，进而得到该区域的尺寸和坐标，但是该方法只能在IE中使用，当然Firefox也有类似的方法，相信大多数开发人员不知道，该方法就是getBoxObjectFor，为了不想为跨浏览器而操心，你可以直接下载JsJava，使用其中的DocumentUtils类的getElementRectangle静态方法，例如：<br>&lt;script src="jsjava.js"&gt;&lt;/script&gt;<br>&lt;script&gt;<br>&nbsp; var elemObj=document.getElementById("div1");//div1是一个div的id<br>&nbsp; var rect=DocumentUtils.getElementRectangle(elemObj);//返回的rect是JsJava中的Rectangle对象<br>&nbsp; var x=rect.getX();<br>&nbsp; var y=rect.getY();<br>&nbsp; var width=rect.getWidth();<br>&nbsp; var height=rect.getHeight();<br>&lt;/script&gt;<br>JsJava的类和方法都是经过IE和Firefox测试的，使用起来很方便。</p>
<p><strong>18</strong>，在界面中对象的位置的计算与理解是比较麻烦的一件事情，例如clientHeight、clientTop、scrollHeight、scrollTop、offsetHeight、offsetTop，这些该怎么区分，又分别代表什么意思，对位置属性的深入理解，非常有助于对HTML界面布局本质的理解，是成为高手的必由之路，下面就简单介绍一下：<br>1）clientHeight，代表对象区域的屏幕高度，不包含区域的border尺寸，但包含padding的尺寸<br>2）clientTop，对象区域offsetHeight与clientHeight的差的一半<br>3）scrollHeight，代表对象区域内容的底部距区域最上边的距离<br>4）scrollTop，代表对象区域滚动部分的高度，即区域的最上边距离该区域可见部分的最上边的距离<br>5）offsetHeight，代表对象区域的屏幕高度，包含border和padding尺寸<br>6）offsetTop，代表对象区域距离上一个对象高度<br>上面的解释如果没有实际的经验，多少会有些迷糊，没有关系，我给你一个示意图：<br><img alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/eye_of_back/objdim1.gif"><br>因此，scrollHeight并非总是大于或等于clientHeight，实际上确实有一些开发人员认为一个区域没有滚动时scrollHeight和clientHeight相等，有滚动时scrollHeight＝clientHeight+scrollTop，这种认识是不对的或者说是不准确的。<br>上面的图的html源码为：<br>&lt;script&gt;<br>&nbsp; function pos(){<br>&nbsp;&nbsp;&nbsp; debug(test1.clientHeight);<br>&nbsp;&nbsp;&nbsp; debug(test1.clientTop);<br>&nbsp;&nbsp;&nbsp; debug(test1.scrollHeight);<br>&nbsp;&nbsp;&nbsp; debug(test1.scrollTop);<br>&nbsp;&nbsp;&nbsp; debug(test1.offsetHeight);<br>&nbsp;&nbsp;&nbsp; debug(test1.offsetTop);<br>&nbsp;&nbsp;&nbsp; debug("--------------");<br>&nbsp;&nbsp;&nbsp; debug(test2.clientHeight);<br>&nbsp;&nbsp;&nbsp; debug(test2.clientTop);<br>&nbsp;&nbsp;&nbsp; debug(test2.scrollHeight);<br>&nbsp;&nbsp;&nbsp; debug(test2.scrollTop);<br>&nbsp;&nbsp;&nbsp; debug(test2.offsetHeight);<br>&nbsp;&nbsp;&nbsp; debug(test2.offsetTop);<br>&nbsp;&nbsp;&nbsp; debug("--------------");<br>&nbsp; }<br>&nbsp; function debug(str){<br>&nbsp;&nbsp;&nbsp; info.value+=str+"\n"; <br>&nbsp; }<br>&lt;/script&gt;<br>&lt;body onclick="pos()"&gt;<br>&nbsp; &lt;div id="test1" style="padding:5;border-width:15;border-color:black;border-</p>
<p>style:solid;background-color:red;height:100;width:200"&gt;区域1，高100&lt;/div&gt;<br>&nbsp; &lt;span id="test2" style="background-color:blue;height:50;width:200"&gt;区域2，高50&lt;/span&gt;<br>&nbsp; &lt;div id="test4" style="height:100;width:200;background-color:green"&gt;区域4，高100&lt;/div&gt;<br>&nbsp; &lt;textarea id="info" cols="50" rows="20"&gt;&lt;/textarea&gt;<br>&lt;body&gt;<br>显示结果为：<br>70<br>15<br>28<br>0<br>100<br>15<br>--------------<br>50<br>0<br>18<br>0<br>50<br>115<br>--------------</p>
<p><strong>19</strong>，网上许多人都问，如何将一个RGB颜色转换为HTML中的十六进制颜色，我看到了一些网友的实现，例如定义一个长度为256的数组，并按照十六进制的规律将其全部初始化，还有的利用了HTML标签的一些特点，不过有一定的局限性，其实我们只要理解了RGB颜色的基本知识，转换起来是很方便的，RGB分别代表红（Red）、绿（Green）、蓝（Blue）三种基色，其中每一种基色从浅到深又可以定义256色，这样RGB总共可以表示256x256x256种颜色，而对于十六进制颜色来说，其实就是用十六进制数字来表示RGB，例如FFFFFF代表rgb(256,256,256)，换算起来也很简单，就是十进制与十六进制之间的表示方法的转换，例如对于RGB颜色rgb(132,216,12)，用十六进制颜色表示的计算方式为：<br>132转换为十六进制数字为84<br>216转换为十六进制数字为D8<br>12转换为十六进制数字为0C<br>因此rgb(132,216,12)的十六进制颜色就是84D80C，我们可以看一下两者的效果：<br>&lt;div style="background-color:rgb(132,216,12);width:50;height:50"&gt;&lt;/div&gt;<br>&lt;br&gt;<br>&lt;div style="background-color:#84D80C;width:50;height:50"&gt;&lt;/div&gt;<br>显示为：<br><img alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/eye_of_back/rgbhexcolor.gif"><br>那么Javascript之中是否提供了十进制数与十六进制数的转换呢，Javascript没有提供内置的函数来进行这种转换，不过你可以下载JsJava，使用其中Integer类的静态方法：toHexString方法，例如<br>&lt;script src="jsjava.js"&gt;&lt;/script&gt;<br>&lt;script&gt;<br>&nbsp; var hex=Integer.toHexString(253);<br>&nbsp; document.write("&lt;br&gt;"+hex);//显示为FD<br>&lt;/script&gt;<br>或者你直接使用JsJava种的Color对象：<br>var color=new Color(132,216,12);<br>var hex=color.toHexValue();//hex的值为84d80c</p>
<p><strong>20</strong>，web开发过程中，经常会遇到原页面与弹出页面之间进行交互的问题，如果只是简单的变量传递，还是不难的，而我们经常遇到的一个实际场景是：例如有一个用户列表页面，点击&#8220;新建&#8221;按钮，弹出一个创建用户的页面，填写完信息后要提交表单并关闭窗口，同时列表页面中要列出新建的用户，这个时候我们一些开发人员喜欢使用的方式为：<br>userForm.submit();<br>opener.location.reload();//或者有些开发人员喜欢用opener.location=列表页面的请求url<br>window.close();<br>上面的代码有一个很明显的问题，就是如果表单提交给后台，后台还在处理，而此时原页面已经执行了重载，那么等新用户在后台存储后了，也不会反映到列表页面中了，当然刷新一个就有了，但是就达不到我们所要的效果了。下面给你介绍一种比较稳妥的方式（ajax方式就不介绍了）：<br>先让表单提交，提交后还是回到弹出的那个页面，或者一个其它的页面，然后在该页面中做判断，如果后台信息处理成功，那么就执行原页面的重载，然后关闭窗口。<br>当然有些开发人员说，前面的那种方式，一直在项目中使用没有发现什么问题，那我告诉你，那是因为你比较幸运，后台处理速度很快，列表重载的时候，后台已经处理完了，但是一旦后台处理慢了，客户就该找麻烦了。</p>
<p><strong>21</strong>，界面问题是当前web开发领域（不要认为只是asp、jsp和或者php等的开发，大的说可以包括ASP.NET以及J2EE等）最为棘手的问题之一，而且大部分开发人员，不懂得该如何去解决界面问题，而且经常会遇到一些不可思议的问题。其实我告诉你，界面问题的确有一些是非常奇怪的，但是不要因为这样，就不去深究问题的原因所在，我在这些年的开发中，遇到了不少的离奇的界面问题，包括自己碰到的和别人让我去解决的，不过我发现，在这些离奇的问题背后，体现的却是我们大部分开发人员，在界面能力和素养方面的一些问题，例如有些人就是太粗心，而有些人则是缺乏界面基础知识等等。成为界面高手不是目的，培养解决界面问题的能力和素养才是最关键的。</p>
<p><strong>22</strong>，在连接标签中加入onclick操作是很常用的一种方式，例如：<br>&lt;a href="#" onclick="window.open('yoururl')"&gt;人员管理&lt;/a&gt;<br>一般情况，这种方式是没有问题，但是如果页面内容比较长，出现了上下滚动条的时候，这种方式就会出一些问题，主要是由于href的#造成的，我们知道锚的作用就是让页面定位并移动到锚处，上面的代码开发人员的意图主要是想点击的时候不要执行链接href，所以写一个#，但是#对于滚动的页面，会在执行onclick的同时，页面出现移动定位行为，这样的用户体验是很不好，解决方式有如下几种：<br>&lt;a href="javascript:void 0" onclick="window.open('yoururl')"&gt;人员管理&lt;/a&gt;<br>&lt;a href="javascript:return" onclick="window.open('yoururl')"&gt;人员管理&lt;/a&gt;<br>建议使用void 0方式，因为return方式，有时会影响click事件的传播，尤其是return false的时候。</p>
<p><strong>23</strong>，在Window XP系统中，我们经常奇怪为什么我们使用的Javascript控制窗口尺寸和位置的一些操作，而IE竟然没有全部支持呢，例如下面的代码：<br>&lt;script&gt;<br>&nbsp; window.open("about:blank","","width=10000,height=15000");<br>&lt;/script&gt;<br>按道理应该弹出一个10000x15000的大窗口，然后实际上IE给我们弹出的不过是一个和浏览器尺寸大小一致的窗口，为什么会这样呢？其实我们理解微软，如果不这样限制，系统可能会因为大量的这种代码而最终崩溃，当然微软的IE也提供了配置入口，配置是否进行限制，具体入口为：<br><img alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/eye_of_back/iejsset1_1.gif"><br>对一般站点类说，默认都是禁用的，只要打开就可以了。</p>
<p><strong>24</strong>，我们页面中经常会以post方式提交表单数据，提交之后，如果我们刷新页面，IE中一般都会提示如下图所示的信息：<br><img alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/eye_of_back/ieinfo1.gif"><br>如果避免这种提示出现，一种是编程上去解决，即表单提交后，不要从其它窗口对该窗口继续执行location的reload方法等等，最好是使用location的href属性或者assign、replace等方法），在IE的高级选项中，也有一个条目可以设置重定向表单提交时是否给出提示信息，但是设置了之后，没有什么效果，因此也就不过多介绍了。</p>
<p><strong>25</strong>，现在很流行div+css方式的布局，的确这样做界面框架的灵活性大为增加，可以说什么布局都能出的来，而且目前的ajax方式的轻量级portal框架基本上都采用的是div+css的布局方式，但是也不要过度的使用，或者什么场合下都使用，例如对于一个中大型的项目而言，要考虑的不仅仅是布局这样的事情，还要考虑界面框架的许多东西，在这种情况下，还是使用模板的方式比较好，事实上div+css是一种布局，而模板是一种&#8220;框架&#8221;，两者可以结合使用，至于能结合到什么程度，就看你的实际本领了。</p>
<p><strong>26</strong>，做为一个项目经理、产品经理或者是技术总监，你应该要重视界面方面的问题了，想想吧我们现在的开发人员，大都能很快的完成后台逻辑的开发，但是到了界面展现却是捉襟见肘，界面效果和易用性做的都不到位，界面方面都调整好了，需要的时间往往并不比后台逻辑开发用的时间少多少，相信你见到过吧，为了调试一个界面中的奇怪的问题，往往会用掉一个人一两天的时间，如果再不重视界面技术的学习和素养的培养，我们的路还能走多远。</p>
<p>&nbsp; 又七七八八的为大家总结了一下我在web开发尤其是界面开发上的一些经验，这些都是摸爬滚打出来的，可以算作是经验，但不一定就特别的正确，许多东西还需要你自己去实践、检验和再总结，如果我写的这些东西，对你而言哪怕只是有一点的用处，我都是很欣慰的，另外一点我需要说的，就是我们应该逐步走出大师崇拜的阴影，不要再津津乐道于敏捷开发、极限编程等等，面对那些国外的大师，我们更为重要的是学习他们身上的精神和品质，而不是做一个忠实的传道士，对于这些精神和品质，我们中华民族实际上很早就有了，只是到现在已经少的可怜的，但并不是说我们就没有希望了，看看当今科学界和各个行业的民族精英们，看看他们骨子里面的那种精神，是很值得我们崇敬和学习的。</p><br><script type="text/javascript" src="http://www.cnitblog.com/Files/yemoo/gg2.js"></script> <img src ="http://www.cnitblog.com/yemoo/aggbug/34628.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/yemoo/" target="_blank">Yemoo'S JS Blog</a> 2007-10-10 12:20 <a href="http://www.cnitblog.com/yemoo/archive/2007/10/10/34628.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>web开发过程中要注意的问题（一)【转自eye_of_back的专栏】 </title><link>http://www.cnitblog.com/yemoo/archive/2007/10/10/34627.html</link><dc:creator>Yemoo'S JS Blog</dc:creator><author>Yemoo'S JS Blog</author><pubDate>Wed, 10 Oct 2007 04:18:00 GMT</pubDate><guid>http://www.cnitblog.com/yemoo/archive/2007/10/10/34627.html</guid><wfw:comment>http://www.cnitblog.com/yemoo/comments/34627.html</wfw:comment><comments>http://www.cnitblog.com/yemoo/archive/2007/10/10/34627.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/yemoo/comments/commentRss/34627.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/yemoo/services/trackbacks/34627.html</trackback:ping><description><![CDATA[<script type="text/javascript" src="http://www.cnitblog.com/Files/yemoo/gg1.js"></script><br><p><strong>1，</strong>document.getElementById方法只能获取到一个对象，即使有多个同名的对象，也只取第一个具有该名称的对象，例如在一个form（名称为myform）中，有三个id="mycheckbox"的复选框，那么使用document.getElementById("mycheckbox")，返回的是第一个checkbox对象，而不是返回一个数组，如果使用document.myform.mycheckbox则返回一个数组。</p>
<p><strong>2，</strong>使用showModalDialog打开一个页面，则在这个页面中，对于任何链接和任何表单提交，都会在新的窗口中执行，即使你在链接或form中指定了target="_self"也是没有用的。例如使用showModalDialog打开一个test.html，在该页面有一段代码<br>&lt;a href="test2.html" target="_seft"&gt;打开&lt;/a&gt;<br>如果点击该链接，那么将会在新窗口中打开test2.html，至少在ie中是这样的，那么是不是就没有办法解决了呢？不是的，我们可以通过在弹出的页面的head中加入下面的代码来解决这个问题：<br>&lt;head&gt;<br>&nbsp; &lt;base target="_self"&gt;<br>&lt;/head&gt;</p>
<p><strong>3，</strong>在一个页面含有某个iframe，其id="myframe" name="myframe"，此时使用document.getElementById("myframe")取到的是iframe标签对象，通过该对象可以获取iframe的各个属性，例如src、frameborder、style等等，但是不能获取到iframe所包含的子页面的各个对象。如果使用document.frames("myframe")取到的是iframe组件对象，通过该对象可以获取到iframe所包含的页面的子页面的各个对象，例如子页面的window对象，但是不能获得iframe标签得各个属性，例如上面说到的src等等。请参看如下类似代码：<br>1.html<br>&lt;script&gt;<br>&nbsp; function check(){<br>&nbsp;&nbsp;&nbsp; var obj1=document.getElementById("myframe");<br>&nbsp;&nbsp;&nbsp; alert(obj1.src);<br>&nbsp;&nbsp;&nbsp; //alert(obj1.window.document.myform.username.value);//Error<br>&nbsp;&nbsp;&nbsp; var obj2=document.frames("myframe");<br>&nbsp;&nbsp;&nbsp; alert(obj2.window.document.myform.username.value);<br>&nbsp;&nbsp;&nbsp; //alert(obj2.src);//Error<br>&nbsp; }<br>&lt;/script&gt;<br>&lt;body onload="check()"&gt;<br>&nbsp; &lt;iframe id="myframe" name="myframe" src="2.html" frameborder="3" style="width:300;height:200;border-width:1;border-color:red;border-style:solid"&gt;&lt;/iframe&gt;<br>&lt;/body&gt;<br>2.html<br>&lt;body&gt;<br>&nbsp; &lt;form name="myform"&gt;<br>&nbsp;&nbsp;&nbsp; 用户名：&lt;input type="text" name="username" value="test" /&gt;<br>&nbsp; &lt;/form&gt;<br>&lt;/body&gt;</p>
<p><strong>4，</strong>在table中，如果在table中加入border="1" bordercolor="red"，那么table中所有单元格都会加上厚度为1的红色边框，但是如果在table中加入css style="border-width:1;border-color:red;border-style:solid" 那么只会在整个table的最外面加上厚度为1的红色边框，分别如下图所示：<br><img alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/eye_of_back/web_tech_faq1.gif"><br>当然第一个出现了双边框，这是因为没有设置cellspacing的缘故，只要在table中设计cellspacing="0"，那么就变为单边框了。</p>
<p><strong>5，</strong>许多时候我们需要在页面加载时能够通过javascript去动态操作html中的一些对象，对于这些操作我们最好是在body中定义onload操作，然后在该操作中去完成这些任务，尽量避免在html中嵌入script执行代码，因为对于比较大的页面，当这些脚本执行的时候，页面往往还没有加载完毕，因此许多页面对象还没有被生成，此时动态去改变很可能会报异常。</p>
<p><strong>6，</strong>有时候我们需要在iframe子页面中调用父页面的javascript函数，例如在父窗口中定义了一个函数如下：<br>&lt;html&gt;<br>&nbsp; &lt;script&gt;<br>&nbsp;&nbsp;&nbsp; function loadImage(){<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //...<br>&nbsp;&nbsp; }<br>&nbsp;&lt;/script&gt;<br>&lt;body&gt;<br>//...<br>&lt;/body&gt;<br>&lt;/html&gt;<br>那么在iframe子页面中可以通过parent.loadImage()来实现调用，这也说明用户在页面定义的所有javascript函数都属于window对象之下。那么在父窗口如何调用子窗口中的函数呢，应该很简单了，就是获得子窗口对象，然后调用子窗口对象的window对象下的这些函数即可，例如iframe的name为myframe，在子窗口定义了一个函数getUserName，那么父窗口中的调用方式为document.frames("myframe").getUsername();另外对于父窗口调用子窗口中的方法，还要注意一个问题，就是子窗口的加载有时候会比较慢，如果子窗口正在加载，那么此时它的各种页面对象都不存在，那么当在父窗口调用子窗口的方法时，为了保险可以使用借助setTimeout来实现异步调用，即通过setTimeout指定一定时间之后（例如100ms），再执行调用，调用执行总是判断子窗口页面是否加载完毕，如果没有加载完毕，则继续使用setTimeout方法，循环往复直到子窗口被完全加载，然后执行子窗口的函数调用。既然这里解释了窗口间的异步调用，后面就不专门解释了。</p>
<p><strong>7，</strong>在一个网页中如何最小化窗口，当然你可能会说，网页的右上角不是有最小化、最大化和关闭三个按钮吗，当然了这里说这个问题是指，如果不点击网页右上角的最小化，如何实现网页的最小化操作，例如有些项目中，用户需要办公界面是全屏化的，这意味着网页自己提供的许多操作都不可见，更不用说去操作了。在网络上我们搜索最小化的解决方式，我们会发现千篇一律的使用如下的方式实现：<br><font size=2>&lt;object&nbsp;id=hh1&nbsp;classid="clsid:ADB880A6-D8FF-11CF-9377-00AA003B7A11"&gt;&nbsp; <br>&lt;param&nbsp;name="Command"&nbsp;value="Minimize"&gt;&lt;/object&gt;<br>&lt;input&nbsp;type=button&nbsp;value=最小化&nbsp;onclick=hh1.Click()&gt;&nbsp; <br>在win98和windows2000中这个方式可能是可以的，但是在windows XP中却是不再支持了，不仅如此在windows XP中对javascript不少函数做了限制。那么在XP中如何实现最小化呢，一个可以实现的方式就是自己写一个activeX控件，这个是在项目中证明可以实现的。（不要认为activeX控件很难写，也不要以为activeX控件用户不接受，在实际的项目中如果用户使用的都是ie，那么用户一般是会接受的，当然这里的项目最好是内网办公项目，对于公网项目来说，用户接不接受就很难说了）</font></p>
<p><font size=2><strong>8，</strong>注意td中nowrap的使用，这个属性是很有用的，例如如果一个td中含有多张图片，那么如果不加入nowrap，那么很可能这些图片会由于其它的td的挤压而产生细微的上下错位，这表现的页面上就是某处出现了一条横向的细缝。这一点很重要，页面中许多非常奇怪的现象都与此有关。</font></p>
<p><font size=2><strong>9，</strong>对于showModalDialog弹出的页面，不能使用右键菜单，也不支持F5和ctrl+r刷新，如果此时修改弹出页面的内容，那么必须关闭该窗口，然后重新弹出才可以。另外，对于许多web服务器，由于服务器都设置有缓存，如果修改了弹出页面的内容，那么许多时候只是关闭弹出页面还是不够的，往往还需要关闭弹出该页面的那个页面才可以。在这里多说一句，web开发许多奇怪的页面现象都和web服务器的缓存有着很大的关系，因此出现问题时考虑一下是否是由于服务器的缓存所致。</font></p>
<p><font size=2><strong>10，</strong>我们喜欢在form中定义onsubmit操作，主要是为了在表单提交之前可以做一些有意义的操作，例如检查输入域的有效性等等，但是一定要注意，如果我们通过点击该form中的submit按钮（type=submit或type=image）提交表单，那么该onsubmit操作会被执行，但是如果通过document.formName.submit()提交表单，那么此onsubmit操作将不被执行。</font></p>
<p><font size=2><strong>11，</strong>许多时候我们修改了页面的内容，但是我们刷新页面或重新打开该页面，却看不到修改的效果，除了前面提到过的showModalDialog和缓存的情况要考虑外，还要检查一下是否改对了地方，即你修改的那个页面是否是服务器上的那个页面，有可能你修改了其它地方的一个页面，如果不是这个原因，那么再进行其它方面的检查。</font></p>
<p><font size=2><strong>12，</strong>在没有系统规划好之前，请不要在css中定义html标签的统一行为，即下面的形式：<br>&lt;style&gt;<br></font><font size=2>&nbsp; TABLE{font-size:11pt;color:black;}<br>&nbsp;&nbsp;INPUT{border-width:1;border-color:pink;border-style:solid} <br>&lt;/style&gt;<br>因为一但定义了这些标签的属性，那么这将会影响页面中所有的这些标签属性，尤其在一些公用的css文件中，尽量不要定义html标签的统一行为。当然如果经过了系统的良好的规划，那么这样做将是非常好的，只是在国内在css上经过良好规划的并不多，因此虽然我们见到许多项目和产品中对html标签做了许多css的定义，但是真正起到作用的并不多。</font></p>
<p><font size=2><strong>13，</strong>在html标签中有许多属性的名称都是复合词，例如borderColor、frameBorder、readOnly等等，注意这些复合词在html的书写，一般来说我们在html标签中写为borderColor和bordercolor，各个浏览器的解析都会通过，但是我们在使用javascriopt引用这些属性时却需要注意了，一定使用正确的属性名称，严格来说，对于复合词而言，除了第一个有意义的词之外，其它任何有意义的词的首字母都要大写，例如对于上面列出的三个属性的引用，一定要使用borderColor、frameBorder、readOnly的形式。<br>&lt;input type="text" id="myinput" readonly /&gt;<br>&lt;script&gt;<br>&nbsp;&nbsp;&nbsp; var flag=document.getElementById("myinput").readOnly;//正确的方式<br>&nbsp;&nbsp;&nbsp; //var flag=document.getElementById("myinput").readonly;//错误的方式<br>&lt;/script&gt; </font></p>
<p><strong>&nbsp;14，</strong>我们知道当使用浏览器的菜单&#8220;查看&#8221;-&gt;&#8220;文字大小&#8221;来改变文字的显示时（或者有些浏览器也可以使用ctrl+滚轮键），网页中的文字的字号会发生相应的变化，如果我们在网页中的文字块中定义了style="font-size:10pt"，那么这些文字块中的文字的大小将是固定的了（注意在&lt;font/&gt;标签定义size属性是不能固定字号的），我想这一点多数人都应该知道的。但是我们使用中有时会出现一种非常奇怪的现象，例如下面的一段代码：<br>&lt;table&gt;&lt;tr&gt;&lt;td&gt;<br>&lt;div style="font-size:10pt;border-width:1;border-color:red;border-style:solid"&gt;<br>&nbsp; 这是上面<br>&lt;/div&gt;<br>&lt;br /&gt;<br>&lt;div style="font-size:10pt;border-width:1;border-color:green;border-style:solid"&gt;<br>&nbsp; 这是下面<br>&lt;/div&gt;<br>&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;<br>我们看一下在字号显示&#8220;最大&#8221;和&#8220;最小&#8221;下的差别：<br><img alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/eye_of_back/web_tech_faq2.gif"><img alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/eye_of_back/web_tech_faq3.gif"><br>从上图我们可以看到字号我们是固定住了，但是table的高度却会随着查看方式的不同而发生变化，这是为什么呢？原因就在于td当中的那个&lt;br /&gt;，我们知道&lt;br /&gt;是表示段内换行，但是要注意在网页中所谓的行也是有一定的默认高度的，而且这个高度随着查看方式的不同而发生相应的变化，因此如果我们想固定上面table的高度不发生变化，有下面两种方式：<br>方式一：在table标签中加入字号限制例如&lt;table style="font-size:10pt"...<br>方式二：在&lt;br /&gt;中加入字号限制例如&lt;br style="font-size:10pt" /&gt;...<br>如果你是一个web开发人员，你可以试着使用ctrl+滚轮键改变网页查看文字的大小，你会发现不少页面都存在这个问题的。</p>
<p><strong>15，</strong>网页中定位对象的方式有许多种，下面先简单总结一下，以后再专门写这个方面的文章的：<br>1）页面内通用定位方式（这些定位方式适用于后面其它元素的定位）<br>document.getElementById(objId);//通过对象的id获取对象，这个是各个浏览器都支持的，返回一个对象<br>document.getElementsByName(objName);//通过对象的name获取对象，这个是各个浏览器都支持的，返回一个数组<br>document.getElementsByTagName(tagName);//通过标签名称获取对象，这个是各个浏览器都支持的，返回一个数组<br>document.all.objId;//通过对象id获取对象，这个是ie支持的，返回一个对象<br>document.all(objId);//通过对象id获取对象，这个是ie支持的，返回一个对象<br>document.layers.objId;//通过对象id获取对象，这是Netscape支持的，返回一个对象<br>document.layers(objId);//通过对象id获取对象，这是Netscape支持的，返回一个对象<br>window.objName;//通过对象名称获取对象，至少在ie中如此<br>objName;//通过对象名称获取对象，至少在ie中如此<br>2）页面内集合元素的定位方式<br>我们知道在页面中有许多集合，例如form、frame、image等等，引用这些集合中某个对象的方式为，举其中一个为例，其它都差不多，以form为例：<br>document.formName;//通过表单name获取表单对象<br>document.forms[index];//通过索引获取表单对象，浏览器会按顺序将页面中所有的表单集合城数组，可以通过下标引用<br>document.forms(formName);//通过表单name获取表单对象<br>3）定位子窗口的方式（定位子窗口对象，不是标签对象，见前面3中的说明）<br>子窗口是指页面中frame或iframe窗口，定位方式为：<br>document.frames[index];//索引定位方式<br>document.frames(frameName);//通过名称定位<br>window.frameName;//通过名称定位<br>frameName;//直接通过名称来定位<br>4）在子定位父窗口的方式<br>通过关键字parent来引用即可，同理parent.parent则表示父父窗口，top则表示最上层窗口。<br>5）原窗口定位open弹出窗口的方式，例如下面代码：<br>window.open("test.html");<br>这里我们要知道window.open将会返回一个弹出窗口的句柄，即可以如下：<br>var owin=window.open("test.html");<br>owin即代码弹出窗口对象，通过改对象可以引用到弹出窗口的各个对象。<br>6）原窗口定位showModalDialog弹出窗口的方式，例如：<br>window.showModalDialog("test.html");<br>注意showModalDialog与open不同，open弹出窗口后，window.open后面的代码可以继续执行，而showModalDialog弹出窗口后，原页面被阻塞，即window.showModalDialog后面的代码不被执行，直到用户关闭了弹出窗口才会继续往下执行，但这时因为已经关闭了弹出窗口，所以已经无法再对该窗口进行引用。<br>7）open弹出的窗口对原窗口的定位方式，这个我们一般都知道，在弹出窗口中使用opener即可。<br>8）showModalDialog弹出的窗口对原窗口的定位方式，这个不是使用opener，而应该在弹出窗口中使用parent。</p>
<p><strong>16，</strong>编写页面代码尽量使用标准的html、css和javascript，不要以为只要在ie上通过就可以了，要注意最近浏览器市场已经开始发生变化了，不知道你是否听说过Firefox2.0，它的用户量已经不在ie之下了，至少你的代码要在ie和Firefox上都通过才可以，另外现在linux越来越吃香，保不准几年后我们的许多客户都开始使用linux，到那个时候，我们将不得不对原来已经完成的项目进行维护，与其这样的后果，还不如从现在开始就使用标准为好，不要认为跨浏览器是很虚的话题，觉得没有必要，要知道这已经不是几年前了，现在形式和市场都在发生变化，我们的思想也该变一变了。</p>
<p><strong>17，</strong>我们的产品或OA系统往往会有许多模块，例如用户管理、发文流程、物品管理等等，我们在为这些模块命名时往往都是不太讲究的，没有注意名字的结构、字数等的统一，例如在个人事务模块下面有三个子模块，名称分别如下：待办事项、已办事项，维护个人信息。对于字数而言我们往往不会苛求太多，但是对于词的结构，我们还是要讲究的，例如上面的三个模块，前两个是名词结构，而后一个是谓词结构（动宾结构），这是不太妥当的，也许你觉得这有些吹毛求疵，当然大多数项目中不会要求这么严格，但是有些客户的确会有这样的要求，另外对我们自己而言，这也体现了我们做事认真、一丝不苟的品格和态度。</p>
<p><strong>18，</strong>图标与文字的配比要合适，这不仅要求图标能够正确显示文字的意思，而且还要求图标不能盖过文字的显示与含义，即图标太显眼而文字无足轻重的情况需要避免，例如下面的情况就是不太合适的：<br><img height=18 alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/eye_of_back/web_tech_faq5.jpg" width=18>&nbsp;用户管理<br>之所以不合适，主要是因为图标的含义与用户管理关系不大，图标的含义更接近&#8220;XX编辑&#8221;的意思，和用户管理基本没有什么联系。</p>
<p><strong>19，</strong>在用户登录和表单处理页面，我们要处理用户按enter键的情况，即用户按enter键也要触发提交事件，不要只有用户点击&#8220;登录&#8221;或&#8220;提交&#8221;按钮才触发提交操作。</p>
<p><strong>20，</strong>如果我们在页面中使用&lt;a /&gt;标签，那么默认情况，当鼠标移到该链接时，鼠标自动会变为手的形状，许多时候我们希望鼠标移动到其它非链接的区域，也希望鼠标变为手的形状，我们一般的处理方式为在该区域的style中加入cursor属性，如下：<br>&lt;span style="cursor:hand" onclick="myfunc()"&gt;下一页&lt;/span&gt;<br>或者使用：<br>&lt;span style="cursor:url('http://webme.bokee.com/inc/mouse118.cur')" onclick="myfunc()"&gt;下一页&lt;/span&gt;<br>但是要注意，只有在ie中才支持cursor:hand，在firefox2.0中的cursor中是没有hand的，像wait、help等都是支持的，另外firefox中也不支持cursor:url方式。</p>
<p><strong>21，</strong>我们有时想通过javascript进行跨域页面的调用，不过出于安全性的考虑，各个浏览器一般都是不支持的，例如下面的代码：<br>&lt;iframe src="<a href='http://www.google.com"></iframe'><u><font color=#0000ff>http://www.google.com"&gt;&lt;/iframe</font></u></a>&gt;<br>&lt;script&gt;<br>&nbsp; setTimeout("document.frames[0].window.location.href",3000);<br>&lt;/script&gt;<br>使用setTimeout是为了可以让iframe子页面可以加载完毕，上面的调用会报安全性警告，例如在ie如下：<br><img alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/eye_of_back/web_tech_faq6.gif"><br><br>那么是不是说只要是跨域就能不能进行javascript访问了呢？不是的，一种比较常用的办法就是设置document.domain属性，这种方式的描述如下：<br>假设有两个页面<br>test1.html 所在域：aaa.maindomain.com 访问协议：http 端口：8080<br>test2.html 所在域：bbb.maindomain.com 访问协议：http 端口：8080<br>满足上面条件的两个页面test1.html、test2.html是可以通过javascript相互访问的，上面的条件即为两个页面位于同一个基础域（例如上面同为maindomain.com），遵循同一个访问协议和端口（例如上面同为http 8080）。只要在这样的两个页面中都设置document.domain为所在基础域名，就可以相互调用了，例如：<br>test1.html 所在域为aaa.mydomain.com<br>&lt;script&gt;<br>&nbsp; document.domain="mydomain.com";<br>&lt;/script&gt;<br>&lt;iframe src=http://bbb.mydomain.com/test2.html&gt;&lt;/iframe&gt;<br>&lt;script&gt;<br>&nbsp; setTimeout("document.frames[0].window.location.href",3000);<br>&lt;/script&gt;<br>test2.html 所在域为bbb.mydomain.com<br>&lt;script&gt;<br>&nbsp; document.domain="mydomain.com";<br>&lt;/script&gt;<br>...<br>这样一来，test1.html的调用就是可以的了。一般来说跨域调用的场景发生在集团型企业项目或多机构的政务项目中，而对于这种类型的项目，它们的基础域基本上是相同的，只是三级域名不同，因此可以使用上面的方式来进行跨域调用。</p>
<p><strong>22，</strong>你会页面中的javascript调试吗？也许你还不会使用ie或firefox提供的页面调试器或插件，那么没有关系，至少你懂得一种最基本的调试：alert调试，不要认为这是一种很土或很傻的方式，很多时候这种方式都很非常有用的，对于一段很长的javascrip代码，从头到尾加入几个alert，那么立即就能定位错误的大概位置，当然使用调试器的断点也可以很快定位，只是说alert也是一种不错的方式。当然还是希望你能够掌握更为高级的调试器的使用，毕竟调试器带给我的功能更强大。</p>
<p><strong>23，</strong>我们许多时候编写完网页之后，发现最终的显示效果和我们想象的不太一样，这有些时候是由于浏览器的不同造成的，但除此之外，我们如何具体定位到底是页面的哪块代码导致不太理想的页面效果呢？当然你可能会使用Dreamweaver或Frontpage打开出问题的页面，然后查找原因，但是这些所见即所得的网页设计器，并非我们想象的那么完美，例如明明在设计器种预览很好的效果，到了真实环境中页面竟然出现了错位等等，这里和你介绍一种非常不错的css的调试方式，这里就不具体说了，请参看我新写过的一篇文章【<a id=CategoryEntryList.ascx_EntryStoryList_Entries_ctl01_TitleUrl href="http://blog.csdn.net/eye_of_back/archive/2006/07/15/923320.aspx"><u><font color=#0000ff>css在html中的调试作用</font></u></a> 】</p>
<p><strong>24，</strong>网页打印我们都知道可以调用window.print函数，那么如果想打印iframe子窗口中页面呢，如果你只是获得子窗口对象，然后调用子窗口对象的print方法，此时打印机打印出却不是子窗口页面的内容，而是父窗口页面自身，为什么会这样呢？原来（至少在ie中如此）在父页面调用子窗口的print函数时，因为此时焦点还在父窗口之中，所以打印机此时会将获得焦点的窗口进行打印，我们在打印子窗口之前，只需做一件事即可完成对子窗口的打印，如下代码：<br>&lt;html&gt;<br>&nbsp;&lt;head&gt;<br>&nbsp; &lt;script&gt;<br>&nbsp;&nbsp;&nbsp; function myprint(){<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; document.frames("myframe").window.focus();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; document.frames("myframe").window.print();<br>&nbsp;&nbsp;&nbsp;}<br>&nbsp; &lt;/script&gt;<br>&nbsp;&lt;/head&gt;<br>&lt;body onload="myprint()"&gt;<br>&nbsp; &lt;iframe name="myframe"&nbsp;src="test2.html"&gt;&lt;/iframe&gt;<br>&lt;/body&gt;<br>&lt;/html&gt;</p>
<p><strong>25，</strong>网页切图许多人都习惯于网页三剑客的配合使用，网页三剑客就是网页开发者都熟悉的Dreamweaver、Fireworks和Flash，一般我们使用使用Flash或Fireworks将动画或图切分后输出成为html页面，然后通过Dreamweaver编辑输出后的页面，这是我们网页切图常用的配合方式，但是通过使用比较发现，在图片的切分方面，使用Photoshop要好于Fireworks，Photoshop不仅定位更加精确，而且由于自身是平面设计的标准，因此它提供了许多图片编辑的其它功能，这要比fireworks强大得多。目前专业的网页设计师都在开始或一直使用Photoshop进行网页设计并切分后输出成为HTML页面。如果你是三剑客的爱好者也没有关系，你可以使用一下看看效果如何，总之我从2000年就开始使用三剑客，现在才逐渐认识到Photoshop已经不仅仅是平面设计的标准了。</p>
<p><strong>26，</strong>在javascript中有一个方法可以列出当前对象所支持的所有属性、集合和事件，通过使用in关键字来实现，如下样例代码：<br>var str="";<br>for(var i in document){<br>&nbsp;&nbsp;&nbsp; str+=i+"\n";<br>}<br>alert("document's all attributes:"+str);</p>
<p><strong>27，</strong>在一个名称为myform的表单中，含有一个名称为mychckbox的复选框，那么document.myform.mycheckbox所取到的是那个复选框对象，那么此时调用document.myform.mycheckbox.length是错误的，如果该表单中含有多个名称为mycheckbox的复选框，那么document.myform.mycheckbox返回的是一个数组，此时调用document.myform.mycheckbox.length就是正确的。单独说这个问题，可能感觉比较简单，但是在实际应用中我们经常会犯与此相关的错误，如下图所示：<br><img alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/eye_of_back/web_tech_faq7.gif"><br>上图是我们在应用中经常遇到的&#8220;增、删、改&#8221;的逻辑，我们在其中经常会对复选框做操作，经常会使用类似document.myform.mycheckbox.length的方式，一般情况不会报错，这主要是因为在我们的列表中一般来说都不会只有一条记录，但是当列表中只有一条记录的时候（尽管这种时候不常见），这样引用就会报错，因为此时document.myform.mycheckbox返回的不是一个数组，则对length的引用就没有意义了，这种错误说起来很容易，但是在编程时往往就会忽略，因此在编程时我们建议如下方式：<br>if(document.myform.mycheckbox.length){<br>&nbsp; //...<br>}else{<br>&nbsp; //...<br>}</p>
<p><strong>28，</strong>在ie中有一个很特别的css语法，如果你听说过，那说明你的积累真是太丰富了！在css中有一种给汉语注音的语法，如下所示：<br>&lt;style&gt; <br>&nbsp;&nbsp;&nbsp; ruby{font-size:13pt;}&nbsp;<br>&nbsp;&nbsp;&nbsp; rt{font-size:18pt;color:red}<br>&lt;/style&gt;<br>&lt;ruby&gt;你知道这个语法吗？&lt;rt&gt;ni zhi dao zhe ge yu fa ma&lt;/rt&gt;&lt;br&gt;<br>不知道&lt;rt&gt;bu zhi dao&lt;/rt&gt;&nbsp;&nbsp;&nbsp; <br>&lt;/ruby&gt;<br>你运行这段代码看看什么效果（要在ie中运行），我这里效果如下：<br><img alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/eye_of_back/web_tech_faq8.gif"></p>
<p><strong>29，</strong>我们项目中经常会遇到页面打印的需求，许多时候用户需要只打印页面某一部分，如果直接调用window.print则打印的是整个网页的内容。解决办法不外乎两种，第一种方式是将整个页面分为几个部分，将需要打印的部分放在其中的一个部分，然后定义onbeforeprint和onafterprint两个操作，即打印之前将不要打印的部分隐藏，打印之后将隐藏的部分显示，类似代码如下：<br>&lt;script&gt;<br>&nbsp;&nbsp; function beforePrint(){<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; document.getElementById("hidden1").style.display="none";<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; document.getElementById("hidden2").style.display="none";<br>&nbsp;&nbsp; }<br>&nbsp;&nbsp; function afterPrint(){<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; document.getElementById("hidden1").style.display="block";<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; document.getElementById("hidden2").style.display="block";<br>&nbsp;&nbsp; }<br>&nbsp;&nbsp; document.onbeforeprint=beforePrint;<br>&nbsp;&nbsp; document.onafterprint=afterPrint;<br>&lt;/script&gt;<br>&lt;div id="hidden1" style="display:block"&gt;<br>这里不需要打印<br>&lt;/div&gt;<br>&lt;div id="printDiv" style="display:block"&gt;<br>这里需要打印<br>&lt;/div&gt;<br>&lt;div id="hidden2" style="display:block"&gt;<br>这里不需要打印<br>&lt;/div&gt;<br>&lt;input type="button" value="打印" onclick="window.print()"/&gt;<br>第二种方式是将需要打印的部分放到iframe之中，然后将焦点移到子窗口，然后调用子窗口的print方法即可。</p>
<p><strong>30，</strong>Javascript中的数组和我们一般的编程语言中的数组是不太一样，一般语言中数组的长度是固定的，有些语言中数组中的数据类型也要求是一样的，但是javascript数组却不受这些限制，在javascript中数组基本上是没有长度限制的，而且类型也没有限制，例如下面的一些使用方法：<br>var arr=new Array();<br>arr[1000]="ok";<br>arr[300]=255;<br>arr[200]=new Date();<br>var date=arr[200];<br>alert(date.getTime());<br>因为数组的这种机制，我们可以使用数组实现许多数据结构，例如列表、哈西表等等。</p>
<p><strong>31，</strong>对于XML的处理一般情况下都是在服务器端处理的，例如在Java中有W3C、JDOM、XPath等许多xml的解析器，但是现在许多时候我们需要在浏览器端处理xml字符串，目前在ie和netscape中都有针对xml字符串的解析，如果你喜欢使用，也没有什么关系，不过对于Java程序员，我给你介绍一个完全按照W3C Document API实现的XML解析器，相信你会非常喜欢的，因为完全是Java的风格，请从&nbsp;<a href="http://download.jsjava.com/"><u><font color=#0000ff>http://download.jsjava.com</font></u></a> 下载jsjava0.91，在其中的src/jsorg/w3c/dom下有XML各个对象的实现，在页面中只需引用其中的xmlp.js和i18n.js即可，具体使用可以参考里面的例子：位于下载包的examples/XMLParser/XMLW3CParser下面，也可以直接访问：<a href="http://jsjava.sourceforge.net/examples/XMLParser/XMLW3CParser/W3CXMLParser.html"><u><font color=#0000ff>http://jsjava.sourceforge.net/examples/XMLParser/XMLW3CParser/W3CXMLParser.html</font></u></a>&nbsp;查看例子。</p>
<p><strong>32，</strong>一段文本的首行文本缩进两个汉字，这是中文段落的格式要求，我们可以通过在首行加入多个&amp;nbsp;来实现，不过还是建议使用css的标准属性text-indent，例如下面的代码：<br>&lt;p style="text-indent:28;font-size:10pt"&gt;<br>这是一段文本，请注意它的格式，&lt;br&gt;<br>你看到了什么效果？如果你看到首行&lt;br&gt;<br>缩进了，那么说明起作用了。<br>&lt;/p&gt;<br>显示效果如下：<br><img alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/eye_of_back/web_tech_faq9.gif"></p>
<p><strong>33，</strong>在Javascript中字符串的替换函数为<span class=mono>replace(<em>regexp</em>, <em>newSubStr</em>)，其中第一个参数是一个正则表达式，但是我们在实际使用中，往往习惯使用为一个字符串，这虽然不会报错，但是得到的结果往往是不正确的，例如下面的例子：<br>var str=&#8220; abbbbacc&#8221;;<br>var rs=str.replace(&#8220;a&#8221;,&#8221;0&#8221;);<br>(A)0bbbbacc (B)0bbbb0cc<br>正确答案是A，当然A可能不是你想要的结果，你想要的结果是字符串中所有的&#8220;a&#8221;都被替换为&#8220;0&#8221;，可是上面的使用方式只能将第一个&#8220;a&#8221;替换为&#8220;0&#8221;，正确的使用方式，在第一个参数中输入一个正则表达式，如下所示：<br>var str=&#8220; abbbbacc&#8221;;<br>var rs=str.replace(&#8220;/a/g&#8221;,&#8221;0&#8221;);//注意如果第一个参数为/a/，结果也是不正确的。<br>(A)0bbbbacc (B)0bbbb0cc <br>这样的话答案就是B了，如果你不明白/a/g是什么意思，那么你就需要对Javascript的正则表达式好好学习了，具体可以参看我以前写过的一篇文章：<a href="http://blog.csdn.net/eye_of_back/archive/2006/07/14/922667.aspx"><u><font color=#0000ff>http://blog.csdn.net/eye_of_back/archive/2006/07/14/922667.aspx</font></u></a></span></p>
<p><span class=mono><strong>34，</strong>无论你使用的是ASP，还是PHP，或者JSP，都不建议在页面代码中夹杂着大量的业务逻辑代码。我们应该将业务逻辑代码封装到应用服务器层或者说业务层，web端只是进行调用。在JSP和PHP中我们可以将业务逻辑封装到BO（业务对象）中，由于支持类、接口等一套面向对象的机制，使得这种封装显得很容易，对于ASP，由于ASP.NET和C#的兴起，使得它对业务封装也变得相当方便。虽然我们都懂得服务器的三层架构，但是我们发现许多的项目之中，开发人员仍然在页面中直接编写业务逻辑，甚至直接访问数据库，面对这种情况，不能不说我们的项目管理是存在很大的问题的，我们的项目经理和程序设计师们，我们应该好好反思一下了。</span></p>
<p><span class=mono><strong>35，</strong>有些时候我们在&lt;a/&gt;标签的href中直接加入javascript代码，通过window.open来打开一个自己可以控制许多属性的窗口，例如下面的代码：<br>&lt;a href="javascript:window.open('http://www.google.com');"&gt;打开Google&lt;/a&gt;<br>当我们点击链接后，确实弹出了Google的页面，但同时原页面却变为了下面的样子：<br><img alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/eye_of_back/web_tech_faq10.gif"><br>这种情况相信有些人遇到过，解决方式如下：<br>&lt;a href="javascript:window.open('http://www.google.com');window.opener=null;window.close()"&gt;打开Google&lt;/a&gt;<br>但是为什么前面的那种方式就会出现那种情况呢，其实只要做个简单实验就会明白了，你运行一下下面的代码，点击链接看看会出现什么结果：<br>&lt;a href="javascript:window"&gt;打开Google&lt;/a&gt;<br>实验后你会发现，点击链接后页面出现的结果与上面那种结果相同，然后你再实验一下下面的代码：<br>&lt;a href="javascript:'test'"&gt;打开Google&lt;/a&gt;<br>点击链接后，你会发现页面中会显示test字样。可见对于类似<br>&lt;a href="javascript:js代码"&gt;点击&lt;/a&gt;<br>的代码，如果js代码执行完毕后返回一个对象，那么页面内容会被冲掉，然后将该对象的描述输出到页面中，我们知道window.open方法返回的是弹出的页面的窗口对象（window），因此javascript:window.open将会在弹出一个窗口的同时，原页面会冲掉原有内容并将返回的window对象输出到原页面中。如果在window.open后面加入window.opener=null;window.close()，则弹出窗口后，返回给原页面的对象为空，则原页面不执行任何其它操作。</span></p><p><script type="text/javascript" src="http://www.cnitblog.com/Files/yemoo/gg2.js"></script><img src ="http://www.cnitblog.com/yemoo/aggbug/34627.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/yemoo/" target="_blank">Yemoo'S JS Blog</a> 2007-10-10 12:18 <a href="http://www.cnitblog.com/yemoo/archive/2007/10/10/34627.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>大型Web2.0站点构建技术初探【转自CSDN Blog】</title><link>http://www.cnitblog.com/yemoo/archive/2007/09/30/34234.html</link><dc:creator>Yemoo'S JS Blog</dc:creator><author>Yemoo'S JS Blog</author><pubDate>Sun, 30 Sep 2007 01:53:00 GMT</pubDate><guid>http://www.cnitblog.com/yemoo/archive/2007/09/30/34234.html</guid><wfw:comment>http://www.cnitblog.com/yemoo/comments/34234.html</wfw:comment><comments>http://www.cnitblog.com/yemoo/archive/2007/09/30/34234.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cnitblog.com/yemoo/comments/commentRss/34234.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/yemoo/services/trackbacks/34234.html</trackback:ping><description><![CDATA[<script type="text/javascript" src="http://www.cnitblog.com/Files/yemoo/gg1.js"></script>
<div class=bvMsg id=msgcns!f815ecd7b3d086d9!226>
<p>一、 web2.0网站常用可用性功能模块分析 </p>
<p>二、 Flickr的幕后故事 </p>
<p>三、 YouTube 的架构扩展 </p>
<p>四、 mixi.jp：使用开源软件搭建的可扩展SNS网站 </p>
<p>五、 Technorati的后台数据库架构 </p>
<p>六、 通过了解MySpace的六次重构经历,来认识分布式系统到底该如何创建 </p>
<p>七、 从LiveJournal后台发展看大规模网站性能优化方法 </p>
<p>八、 说说大型高并发高负载网站的系统架构 </p>
<h4>一、 <a><font color=#0066a7>web2.0</font></a>网站常用可用性功能模块分析</h4>
<p>Web 2.0网站是指将传统的网站构架（平台、内容源、用户、传播方式等）转化到以用户为核心的网站构架上来，包括一系列体现web2.0概念的元素、定位和创意。web2.0网站在构架上须体现两大宗旨，即强大的后台系统和简单的前台页面，也即提供良好的用户体验，体现以人为本，技术服务人类的宗旨。 </p>
<p>web2.0网站常用功能块通常包括以下几大项： </p>
<p><strong>1.</strong> <strong>Tag</strong><strong>标签功能块</strong> </p>
<p>Tag(中文叫做"标签") 是一种新的组织和管理在线信息的方式。它不同于传统的、针对文件本身的关键字检索，而是一种模糊化、智能化的分类。 </p>
<p>　　网页使用Tag标签的好处： </p>
<p>为页面设置一个或者多个Tag标签可以引导读者阅读更多相关文章，为别人带去流量同理也为自己带来流量。 </p>
<p>可以帮助读者及时了解一些未知的概念和知识点，提高用户体验。 </p>
<p>Tag是人的意志和趋向的体现，Tag可以帮助你找到兴趣相投的人。 </p>
<p>　　基于以上优势，Tag标签代替了传统的分类法，成为web2.0网站使用率最高的功能块（与其说是功能块倒不如说是一种内容导航和内容组织形式）。 </p>
<p>　　一句话：Tag标签是一种更灵活的分类方法，功能在于引导，特点是无处不在，体现智能性、模糊性和趋向性。 </p>
<p><strong>2.</strong> <strong>RSS</strong><strong>订阅功能块</strong> </p>
<p>RSS是在线共享内容的一种简易方式（也叫聚合内容，Really Simple Syndication）。通常在时效性比较强的内容上使用RSS订阅能更快速获取信息，网站提供RSS输出，有利于让用户获取网站内容的最新更新。网络用户可以在客户端借助于支持RSS的聚合工具软件（例如SharpReader,NewzCrawler、FeedDemon），在不打开网站内容页面的情况下阅读支持RSS输出的网站内容。 </p>
<p>RSS订阅的方式： </p>
<p>订阅到客户端软件如周伯通、遨游浏览器RSS阅读、Foxmail RSS阅读等，此方式使用者较多 </p>
<p>订阅到在线阅读（聚合类）门户网站如Google Reader，Yahoo Reader，抓虾、Gougou等，省去了安装RSS阅读器的麻烦 </p>
<p>订阅到在线单用户聚合器如Lilina等，比较灵活 </p>
<p>RSS订阅功能的最大好处是定向投递，也就是说RSS机制更能体现用户的意愿和个性，获取信息的方式也最直接和简单，这是RSS订阅功能备受青睐的一大主要原因。 </p>
<p><strong>3.</strong> <strong>推荐和收藏功能块</strong> </p>
<p>　　说到推荐功能，不仅web2.0网站在大量使用，传统的以cms平台为代表的内容模式的网站也在大量使用，推荐功能主要是指向一些网摘或者聚合类门户网站推荐自己所浏览到的网页。当然，一种变相的推荐就是阅读者的自我收藏行为，在共享的模式下也能起到推荐的作用。 </p>
<p>　　比较有名的推荐目标有以del.icio.us为代表的网摘类网站包括国内比较有名气的365key、和讯网摘、新浪vivi、天极网摘等。这里值得一提的是前段时间曾涌现了大批网摘类网站，但他们坚持活下来的好像没有几个了，推荐使用前面提到的这几个网摘门户，人气基本上是使最旺的。 </p>
<p><strong>4.</strong> <strong>评论和留言功能块</strong> </p>
<p>web2.0强调参与性，强调发挥用户的主导作用，这里的参与性除了所谓的订阅、推荐功能外更多地体现在用户对内容的评价和态度，这就要靠评论功能块来完成。一个典型的web2.0网站或者说一个能体现人气的web2.0网站都会花大量篇幅来体现用户的观点和视觉。这里尤其要提到web2.0中的带头老大web blog，评论功能已经成为博客主人与浏览者交流的主要阵地，是体现网站人气的最直观因素。 </p>
<p>　　评论功能块应用在博客系统中实际上已经和博客内容相分离，而更好的应用恰恰是一些以点评为主的web2.0网站比如豆瓣、点评网等，这里的评论功能块直接制造了内容也极大地体现了网站的人气，所以说评论功能块是web2.0网站最有力的武器。 </p>
<p><strong>5.</strong> <strong>站内搜索功能块</strong> </p>
<p>　　搜索是信息来源最直接的方式之一，无论你的网站是否打上web2.0的烙印，搜索对于一个体系庞大、内容丰富的大型网站都是非常必要的。Tag标签在某种程度上起到搜索的作用，它能够有效聚合以此Tag为关键词的内容，但这种情况的前提是此Tag标签对浏览者是可见的，也就是说当Tag标签摆在浏览者的眼前时才成立，而对于那些浏览者想要的信息却没有Tag标签来引导时搜索就是达到此目的的最好方法。 </p>
<p>　　对于web2.0网站，站内搜索以标题或者Tag为搜索域都能起到好的效果，但本人不建议使用内容搜索域，因为这不符合搜索的高效性原则。同时，具有突出关键词的内容往往都可以用Tag标签来引导，因此使用内容域来搜索实际上是一种浪费服务器资源的行为，而且搜索结果的准确性将大打折扣。 </p>
<p><strong>6.</strong> <strong>群组功能块</strong> </p>
<p>　　我为什么要把群组作为web2.0网站的功能块来分析呢，因为群组是web2.0网站的一大特点，也是web2.0所要体现的服务宗旨所在。一个web2.0网站，博客也好、播客也好、点评也好，抑或是网摘、聚合门户，他们都强调人的参与性。物以类聚、人以群分，每个参与者都有自己的兴趣趋向，web2.0网站的另一主要功能就是帮助这些人找到同样兴趣的人并形成一个活跃的群体，这是web2.0网站的根本。 </p>
<p>总结：web2.0网站倡导的是集体创作、共享资源，靠的是人气，体现的是参与性，一个没有参与性的web2.0网站都不足以成为web2.0。以上提到的这几个功能块就是以吸引用户参与和引导用户参与为目的的，真正的web2.0不是什么深奥的东西，只有一点，那就是如何让浏览者沸腾起来。 </p>
<h4><a><font color=#0066a7>二、 Flickr</font></a>的幕后故事</h4>
<p>我们都看到 Flickr 的成功，而又有多少"精英"们了解过 Flickr 背后的过程是多么充满艰险。 </p>
<p>Flickr 是全 CGI 的动态构架，并以一种 .gne 的脚本作为 CGI 程序语言。不管网站制作菜鸟还是高手都会疑惑：gne 是哪种程序语言？答案：gne 不是一种语言，Flickr 是以极为经典的 PHP + MySQL 方式实现的，在被 Yahoo 收购服务器搬入美国之前，使用了 21 台（69.90.111.101-121） Apache/PHP 做 Web、23 台图片服务器、另有 MySQL 服务器组成的数据库集群的服务器数量未知。现在估计使用的是 Yahoo 的负载均衡系统，对外只有一个 Web 的 IP 和图片服务器的 IP 了。 </p>
<p>　　那为何 .php 的文件要改成 .gne 呢？以往有大型网站为向后兼容性考虑，隐藏以程序语言命名的脚本文件扩展名，比如 Baidu 隐藏了 .php（Google 的 http 服务器是自己写的，整合了脚本程序，个别页面是 .py--Python）；还有一些网站是改成自己网站名相关的扩展名，如 MSN 的群组则是 .msnw，榕树下是 .rs。 </p>
<p>　　那 Flickr 的 gne 是什么意思？我在维基百科的 Flickr 条目上找到了答案(中文 Flickr 条目上没有写明) 。原来 GNE 是 Game NeverEnding 的缩写，Flickr 的开发者 Ludicorp 在 2002-2004 年一直在开发这套以 Game NerverEnding 为名称的大型多人在线角色扮演游戏--一套基于浏览器的 Web 游戏系统，个人以为应该就是当年九城的虚拟城市。但是开发近 3 年后该计划不得不破产，最终只发布了一个 Beta 版，而 Ludicorp 将这套系统稍加移植，就有了 Flickr。呵呵，原来 gne 是一个项目的名称。关于 GNE 的一些连接：http://del.icio.us/schee/gne。 </p>
<p>　　早期的 Flickr 想做成在类似聊天室的地方让网友分享、交流自己的照片，注重社区形式和保护照片不被外部引用（见徐子涵2004年的文章），可能是看到了 Hello 的模式吧。但是聪明的 Flickr 团队不久就改变了策略，淡化了传统的社区形式--如聊天室、而加强了现在使其功成名就的 Tag 组织形式，一种更自由更随兴更轻松好玩的大社区形式，或者叫它广义社区吧，我随便叫的，可能太学究，看着别太在意就是了。另外，将原来照片只能在 Flash 内浏览的限制区除了，并大力推荐用户将照片引用到自己的 Blog，这无疑对于挑战传统相册系统有决定性意义。减少 Flash 后的网页更多地引进了新兴的 Ajax 技术，使界面操作变得非常 Cool。 </p>
<p>　　这就是 Flickr 的历史，清晰地看到了他们对于优秀产品的执著。有了技术和经验积累，加上不断坚持，总有一天时来运转，你的产品会成为新潮流的里程碑。 </p>
<p>　　还有一句话要告诉 Yupoo 等：把 Flickr 想成一个有 Tag 功能的在线相册就已经错远了；复制粘贴者们想当然将 Flickr 去其糟粕取其精华，结果无关紧要的拿来了，将令人激动的优点都去掉了，结果剩下什么？ </p>
<h4><a><font color=#0066a7>三、 YouTube</font></a> 的架构扩展</h4>
<p>在西雅图扩展性的技术研讨会上，YouTube 的 Cuong Do 做了关于 YouTube Scalability 的报告。视频内容在 Google Video 上有(地址)，可惜国内用户看不到。 </p>
<p>Kyle Cordes 对这个视频中的内容做了介绍。里面有不少技术性的内容。值得分享一下。(Kyle Cordes 的介绍是本文的主要来源) </p>
<p>简单的说 YouTube 的数据流量, "一天的YouTube流量相当于发送750亿封电子邮件.", 2006 年中就有消息说每日 PV 超过 1 亿,现在? 更夸张了,"每天有10亿次下载以及6,5000次上传", 真假姑且不论, 的确是超乎寻常的海量. 国内的互联网应用,但从数据量来看,怕是只有 51.com 有这个规模. 但技术上和 YouTube 就没法子比了. </p>
<p><strong>1.</strong> <strong>Web</strong> <strong>服务器</strong> </p>
<p>YouTube 出于开发速度的考虑，大部分代码都是 Python 开发的。Web 服务器有部分是 Apache， 用 FastCGI 模式。对于视频内容则用 Lighttpd 。据我所知，MySpace 也有部分服务器用 Lighttpd ，但量不大。YouTube 是 Lighttpd 最成功的案例。(国内用 Lighttpd 站点不多，豆瓣用的比较舒服。by Fenng) </p>
<p><strong>2.</strong> <strong>视频</strong> </p>
<p>视频的缩略图(Thumbnails)给服务器带来了很大的挑战。每个视频平均有4个缩略图，而每个 Web 页面上更是有多个，每秒钟因为这个带来的磁盘 IO 请求太大。YouTube 技术人员启用了单独的服务器群组来承担这个压力，并且针对 Cache 和 OS 做了部分优化。另一方面，缩略图请求的压力导致 Lighttpd 性能下降。通过 Hack Lighttpd 增加更多的 worker 线程很大程度解决了问题。而最新的解决方案是起用了 Google 的 BigTable， 这下子从性能、容错、缓存上都有更好表现。看人家这收购的，好钢用在了刀刃上。 </p>
<p>出于冗余的考虑，每个视频文件放在一组迷你 Cluster 上，所谓 "迷你 Cluster" 就是一组具有相同内容的服务器。最火的视频放在 CDN 上，这样自己的服务器只需要承担一些"漏网"的随即访问即可。YouTube 使用简单、廉价、通用的硬件，这一点和 Google 风格倒是一致。至于维护手段，也都是常见的工具，如 rsync, SSH 等，只不过人家更手熟罢了。 </p>
<p><strong>3.</strong> <strong>数据库</strong> </p>
<p>YouTube 用 MySQL 存储元数据--用户信息、视频信息什么的。数据库服务器曾经一度遇到 SWAP 颠簸的问题，解决办法是删掉了 SWAP 分区! 管用。 </p>
<p>最初的 DB 只有 10 块硬盘，RAID 10 ，后来追加了一组 RAID 1。够省的。这一波 Web 2.0 公司很少有用 Oracle 的(我知道的只有 Bebo,参见这里). 在扩展性方面，路线也是和其他站点类似，复制，分散 IO。最终的解决之道是"分区",这个不是数据库层面的表分区，而是业务层面的分区(在用户名字或者 ID 上做文章,应用程序控制查找机制) </p>
<p>YouTube 也用 Memcached. </p>
<p>很想了解一下国内 Web 2.0 网站的数据信息,有谁可以提供一点 ? </p>
<h4><a><font color=#0066a7>四、 mixi.jp</font></a>：使用开源软件搭建的可扩展SNS网站</h4>
<p>Mixi目前是日本排名第三的网站，全球排名42，主要提供SNS服务：日记，群组，站内消息，评论，相册等等，是日本最大的SNS网站。Mixi从2003年12月份开始开发，由现在它的CTO - Batara Kesuma一个人焊，焊了四个月，在2004年2月份开始上线运行。两个月后就注册了1w用户，日访问量60wPV。在随后的一年里，用户增长到了21w，第二年，增长到了200w。到今年四月份已经增长到370w注册用户，并且还在以每天1.5w人的注册量增长。这些用户中70%是活跃用户（活跃用户：三天内至少登录一次的用户），平均每个用户每周在线时间为将近3个半小时。 </p>
<p>下面我们来看它的技术架构。Mixi采用开源软件作为架构的基础：Linux 2.6，Apache 2.0，MySQL，Perl 5.8，memcached，Squid等等。到目前为止已经有100多台MySQL数据库服务器，并且在以每月10多台的速度增长。Mixi的数据库连接方式采用的是每次查询都进行连接，而不是持久连接。数据库大多数是以InnoDB方式运行。Mixi解决扩展问题主要依赖于对数据库的切分。 </p>
<p>首先进行垂直切分，按照表的内容将不同的表划分到不同的数据库中。然后是水平切分，根据用户的ID将不同用户的内容再划分的不同的数据库中，这是比较通常的做法，也很管用。划分的关键还是在于应用中的实现，需要将操作封装在在数据层，而尽量不影响业务层。当然完全不改变逻辑层也不可能，这时候最能检验以前的设计是否到位，如果以前设计的不错，那创建连接的时候传个表名，用户ID进去差不多就解决问题了，而以前如果sql代码到处飞，或者数据层封装的不太好的话那就累了。 </p>
<p>这样做了以后并不能从根本上解决问题，尤其是对于像mixi这种SNS网站，页面上往往需要引用大量的用户信息，好友信息，图片，文章信息，跨表，跨库操作相当多。这个时候就需要发挥memcached的作用了，用大内存把这些不变的数据全都缓存起来，而当修改时就通知cache过期，这样应用层基本上就可以解决大部分问题了，只会有很小一部分请求穿透应用层，用到数据库。Mixi的经验是平均每个页面的加载时间在0.02秒左右（当然根据页面大小情况不尽相似），可以说明这种做法是行之有效的。Mixi一共在32台机器上有缓存服务器，每个Cache Server 2G内存，这些Cache Server与App Server装在一起。因为Cache Server对CPU消耗不大，而有了Cache Server的支援，App Server对内存要求也不是太高，所以可以和平共处，更有效的利用资源。 </p>
<p>图片的处理就显得相对简单的多了。对于mixi而言，图像主要有两部分：一部分是经常要使用到的，像用户头像，群组的头像等等，大概有100多GB，它们被Squid和CDN所缓存，命中率相对比较高；另一部分是用户上传的大量照片，它们的个体访问量相对而言比较小，命中率也比较低，使用Cache不划算，所以对于这些照片的策略是直接在用户上传的时候分发到到图片存储服务器上，在用户访问的时候直接进行访问，当然图片的位置需要在数据库中进行记录，不然找不到放在哪台服务器上就郁闷了。 </p>
<h4><a><font color=#0066a7>五、 Technorati</font></a>的后台数据库架构</h4>
<p><a href="http://www.technorati.com/"><font color=#0066a7>Technorati</font></a> (现在被阻尼了, 可能你访问不了)的 <a href="http://www.mysqluc.com/cs/mysqluc2006/view/e_spkr/2216"><font color=#0066a7>Dorion Carroll</font></a>在 <a href="http://www.mysqluc.com/"><font color=#0066a7>2006 MySQL 用户会议</font></a>上介绍了一些关于 Technorati 后台数据库架构的情况. </p>
<p><strong>基本情况</strong> </p>
<p>目前处理着大约 10Tb 核心数据, 分布在大约 20 台机器上.通过复制, 多增加了 100Tb 数据, 分布在 200 台机器上. 每天增长的数据 1TB. 通过 SOA 的运用, 物理与逻辑的访问相隔离,　似乎消除了数据库的瓶颈. 值得一提的是, 该扩展过程始终是利用普通的硬件与开源软件来完成的. 毕竟 , Web 2.0 站点都不是烧钱的主. 从数据量来看，这绝对是一个相对比较大的 Web 2.0 应用. </p>
<p>Tag 是 Technorati 最为重要的数据元素. 爆炸性的 Tag 增长给 Technorati 带来了不小的挑战. </p>
<p>2005 年 1 月的时候, 只有两台数据库服务器, 一主一从. 到了 06 年一月份, 已经是一主一从, 6 台 MyISAM 从数据库用来对付查询, 3 台 MyISAM 用作异步计算. </p>
<p>一些核心的处理方法: </p>
<p>1) <strong>根据实体(tags/posttags))</strong><strong>进行分区</strong> </p>
<p>衡量数据访问方法，读和写的平衡.然后通过不同的维度进行分区．( Technorati 数据更新不会很多, 否则会成为数据库灾难) </p>
<p>2) <strong>合理利用 InnoDB</strong> <strong>与 MyISAM</strong> </p>
<p>InnoDB 用于数据完整性/写性能要求比较高的应用. MyISAM 适合进行 OLAP 运算. 物尽其用. </p>
<p>3) <strong>MySQL</strong> <strong>复制</strong> </p>
<p>复制数据到从主数据库到辅数据库上,平衡分布查询与异步计算, 另外一个功能是提供冗余． 如图: </p>
<p><a href="http://byfiles.storage.msn.com/y1pLfC-bv1f71MD7KAzVUgnp_rN0Fi1MvV55D6Ts-HPSOuY_VWl-b_5TeUo5jVasgIDPY2Jn0yjh-4"><img style="BORDER-TOP-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-RIGHT-WIDTH: 0px" height=175 alt=clip_image002[4] src="http://www.360doc.com/DownloadImg/3500/754206_1" width=240 border=0></a> <br></p>
<p><a><font color=#0066a7>六、 通过了解MySpace</font></a>的六次重构经历,来认识分布式系统到底该如何创建. </p>
<p>在每个里程碑，站点负担都会超过底层系统部分组件的最大载荷，特别是数据库和存储系统。接着，功能出现问题，用户失声尖叫。最后，技术团队必须为此修订系统策略。 </p>
<p>　　虽然自2005年早期，站点账户数超过7百万后，系统架构到目前为止保持了相对稳定，但MySpace仍然在为SQL Server支持的同时连接数等方面继续攻坚，Benedetto说，"我们已经尽可能把事情做到最好"。 </p>
<p><strong>1.</strong> <strong>里程碑一：50</strong><strong>万账户</strong> </p>
<p>　　按Benedetto 的说法，MySpace最初的系统很小，只有两台Web服务器和一个数据库服务器。那时使用的是Dell双CPU、4G内存的系统。 </p>
<p>　　单个数据库就意味着所有数据都存储在一个地方，再由两台Web服务器分担处理用户请求的工作量。但就像MySpace后来的几次底层系统修订时的情况一样，三服务器架构很快不堪重负。此后一个时期内，MySpace基本是通过添置更多Web服务器来对付用户暴增问题的。 </p>
<p>　　但到在2004年早期，MySpace用户数增长到50万后，数据库服务器也已开始汗流浃背。 </p>
<p>　　但和Web服务器不同，增加数据库可没那么简单。如果一个站点由多个数据库支持，设计者必须考虑的是，如何在保证数据一致性的前提下，让多个数据库分担压力。 </p>
<p>　　在第二代架构中，MySpace运行在3个SQL Server数据库服务器上--一个为主，所有的新数据都向它提交，然后由它复制到其他两个；另两个全力向用户供给数据，用以在博客和个人资料栏显示。这种方式在一段时间内效果很好--只要增加数据库服务器，加大硬盘，就可以应对用户数和访问量的增加。 </p>
<p><strong>2.</strong> <strong>里程碑二：1-2</strong><strong>百万账户</strong> </p>
<p>MySpace注册数到达1百万至2百万区间后，数据库服务器开始受制于I/O容量--即它们存取数据的速度。而当时才是2004年中，距离上次数据库系统调整不过数月。用户的提交请求被阻塞，就像千人乐迷要挤进只能容纳几百人的夜总会，站点开始遭遇"主要矛盾"，Benedetto说，这意味着MySpace永远都会轻度落后于用户需求。 </p>
<p>"有人花5分钟都无法完成留言，因此用户总是抱怨说网站已经完蛋了。"他补充道。 </p>
<p>　　这一次的数据库架构按照垂直分割模式设计，不同的数据库服务于站点的不同功能，如登录、用户资料和博客。于是，站点的扩展性问题看似又可以告一段落了，可以歇一阵子。 </p>
<p>　　垂直分割策略利于多个数据库分担访问压力，当用户要求增加新功能时，MySpace将投入新的数据库予以支持它。账户到达2百万后，MySpace还从存储设备与数据库服务器直接交互的方式切换到SAN（Storage Area Network，存储区域网络）--用高带宽、专门设计的网络将大量磁盘存储设备连接在一起，而数据库连接到SAN。这项措施极大提升了系统性能、正常运行时间和可靠性，Benedetto说。 </p>
<p><strong>3.</strong> <strong>里程碑三：3</strong><strong>百万账户</strong> </p>
<p>　　当用户继续增加到3百万后，垂直分割策略也开始难以为继。尽管站点的各个应用被设计得高度独立，但有些信息必须共享。在这个架构里，每个数据库必须有各自的用户表副本--MySpace授权用户的电子花名册。这就意味着一个用户注册时，该条账户记录必须在9个不同数据库上分别创建。但在个别情况下，如果其中某台数据库服务器临时不可到达，对应事务就会失败，从而造成账户非完全创建，最终导致此用户的该项服务无效。 </p>
<p>　　另外一个问题是，个别应用如博客增长太快，那么专门为它服务的数据库就有巨大压力。 </p>
<p>2004年中，MySpace面临Web开发者称之为"向上扩展"对"向外扩展"（译者注：Scale Up和Scale Out，也称硬件扩展和软件扩展）的抉择--要么扩展到更大更强、也更昂贵的服务器上，要么部署大量相对便宜的服务器来分担数据库压力。一般来说，大型站点倾向于向外扩展，因为这将让它们得以保留通过增加服务器以提升系统能力的后路。 </p>
<p>　　但成功地向外扩展架构必须解决复杂的分布式计算问题，大型站点如Google、Yahoo和Amazon.com，都必须自行研发大量相关技术。以Google为例，它构建了自己的分布式文件系统。 </p>
<p>　　另外，向外扩展策略还需要大量重写原来软件，以保证系统能在分布式服务器上运行。"搞不好，开发人员的所有工作都将白费"，Benedetto说。 </p>
<p>　　因此，MySpace首先将重点放在了向上扩展上，花费了大约1个半月时间研究升级到32CPU服务器以管理更大数据库的问题。Benedetto说，"那时候，这个方案看似可能解决一切问题。"如稳定性，更棒的是对现有软件几乎没有改动要求。 </p>
<p>　　糟糕的是，高端服务器极其昂贵，是购置同样处理能力和内存速度的多台服务器总和的很多倍。而且，站点架构师预测，从长期来看，即便是巨型数据库，最后也会不堪重负，Benedetto说，"换句话讲，只要增长趋势存在，我们最后无论如何都要走上向外扩展的道路。" </p>
<p>　　因此，MySpace最终将目光移到分布式计算架构--它在物理上分布的众多服务器，整体必须逻辑上等同于单台机器。拿数据库来说，就不能再像过去那样将应用拆分，再以不同数据库分别支持，而必须将整个站点看作一个应用。现在，数据库模型里只有一个用户表，支持博客、个人资料和其他核心功能的数据都存储在相同数据库。 </p>
<p>　　既然所有的核心数据逻辑上都组织到一个数据库，那么MySpace必须找到新的办法以分担负荷--显然，运行在普通硬件上的单个数据库服务器是无能为力的。这次，不再按站点功能和应用分割数据库，MySpace开始将它的用户按每百万一组分割，然后将各组的全部数据分别存入独立的SQL Server实例。目前，MySpace的每台数据库服务器实际运行两个SQL Server实例，也就是说每台服务器服务大约2百万用户。Benedetto指出，以后还可以按照这种模式以更小粒度划分架构，从而优化负荷分担。 </p>
<p>　　当然，还是有一个特殊数据库保存了所有账户的名称和密码。用户登录后，保存了他们其他数据的数据库再接管服务。特殊数据库的用户表虽然庞大，但它只负责用户登录，功能单一，所以负荷还是比较容易控制的。 </p>
<p><strong>4.</strong> <strong>里程碑四：9</strong><strong>百万到1</strong><strong>千7</strong><strong>百万账户</strong> </p>
<p>2005年早期，账户达到9百万后，MySpace开始用Microsoft的C#编写ASP.NET程序。C#是C语言的最新派生语言，吸收了C++和Java的优点，依托于Microsoft .NET框架（Microsoft为软件组件化和分布式计算而设计的模型架构）。ASP.NET则由编写Web站点脚本的ASP技术演化而来，是Microsoft目前主推的Web站点编程环境。 </p>
<p>　　可以说是立竿见影， MySpace马上就发现ASP.NET程序运行更有效率，与ColdFusion相比，完成同样任务需消耗的处理器能力更小。据技术总监Whitcomb说，新代码需要150台服务器完成的工作，如果用ColdFusion则需要246台。Benedetto还指出，性能上升的另一个原因可能是在变换软件平台，并用新语言重写代码的过程中，程序员复审并优化了一些功能流程。 </p>
<p>　　最终，MySpace开始大规模迁移到ASP.NET。即便剩余的少部分ColdFusion代码，也从Cold-Fusion服务器搬到了ASP.NET，因为他们得到了BlueDragon.NET（乔治亚州阿尔法利塔New Atlanta Communications公司的产品，它能将ColdFusion代码自动重新编译到Microsoft平台）的帮助。 </p>
<p>　　账户达到1千万时，MySpace再次遭遇存储瓶颈问题。SAN的引入解决了早期一些性能问题，但站点目前的要求已经开始周期性超越SAN的I/O容量--即它从磁盘存储系统读写数据的极限速度。 </p>
<p>　　原因之一是每数据库1百万账户的分割策略，通常情况下的确可以将压力均分到各台服务器，但现实并非一成不变。比如第七台账户数据库上线后，仅仅7天就被塞满了，主要原因是佛罗里达一个乐队的歌迷疯狂注册。 </p>
<p>　　某个数据库可能因为任何原因，在任何时候遭遇主要负荷，这时，SAN中绑定到该数据库的磁盘存储设备簇就可能过载。"SAN让磁盘I/O能力大幅提升了，但将它们绑定到特定数据库的做法是错误的。"Benedetto说。 </p>
<p>　　最初，MySpace通过定期重新分配SAN中数据，以让其更为均衡的方法基本解决了这个问题，但这是一个人工过程，"大概需要两个人全职工作。"Benedetto说。 </p>
<p>长期解决方案是迁移到虚拟存储体系上，这样，整个SAN被当作一个巨型存储池，不再要求每个磁盘为特定应用服务。MySpace目前采用了一种新型SAN设备--来自加利福尼亚州弗里蒙特的3PARdata。 </p>
<p>　　在3PAR的系统里，仍能在逻辑上按容量划分数据存储，但它不再被绑定到特定磁盘或磁盘簇，而是散布于大量磁盘。这就使均分数据访问负荷成为可能。当数据库需要写入一组数据时，任何空闲磁盘都可以马上完成这项工作，而不再像以前那样阻塞在可能已经过载的磁盘阵列处。而且，因为多个磁盘都有数据副本，读取数据时，也不会使SAN的任何组件过载。 </p>
<p>　　当2005年春天账户数达到1千7百万时，MySpace又启用了新的策略以减轻存储系统压力，即增加数据缓存层--位于Web服务器和数据库服务器之间，其唯一职能是在内存中建立被频繁请求数据对象的副本，如此一来，不访问数据库也可以向Web应用供给数据。换句话说，100个用户请求同一份资料，以前需要查询数据库100次，而现在只需1次，其余都可从缓存数据中获得。当然如果页面变化，缓存的数据必须从内存擦除，然后重新从数据库获取--但在此之前，数据库的压力已经大大减轻，整个站点的性能得到提升。 </p>
<p>　　缓存区还为那些不需要记入数据库的数据提供了驿站，比如为跟踪用户会话而创建的临时文件--Benedetto坦言他需要在这方面补课，"我是数据库存储狂热分子，因此我总是想着将万事万物都存到数据库。"但将像会话跟踪这类的数据也存到数据库，站点将陷入泥沼。 </p>
<p>　　增加缓存服务器是"一开始就应该做的事情，但我们成长太快，以致于没有时间坐下来好好研究这件事情。"Benedetto补充道。 </p>
<p><strong>5.</strong> <strong>里程碑五：2</strong><strong>千6</strong><strong>百万账户</strong> </p>
<p>2005年中期，服务账户数达到2千6百万时，MySpace切换到了还处于beta测试的SQL Server 2005。转换何太急？主流看法是2005版支持64位处理器。但Benedetto说，"这不是主要原因，尽管这也很重要；主要还是因为我们对内存的渴求。"支持64位的数据库可以管理更多内存。 </p>
<p>　　更多内存就意味着更高的性能和更大的容量。原来运行32位版本的SQL Server服务器，能同时使用的内存最多只有4G。切换到64位，就好像加粗了输水管的直径。升级到SQL Server 2005和64位Windows Server 2003后，MySpace每台服务器配备了32G内存，后于2006年再次将配置标准提升到64G。 </p>
<p>　　意外错误 </p>
<p>　　如果没有对系统架构的历次修改与升级，MySpace根本不可能走到今天。但是，为什么系统还经常吃撑着了？很多用户抱怨的"意外错误"是怎么引起的呢？ </p>
<p>　　原因之一是MySpace对Microsoft的Web技术的应用已经进入连Microsoft自己也才刚刚开始探索的领域。比如11月，超出SQL Server最大同时连接数，MySpace系统崩溃。Benedetto说，这类可能引发系统崩溃的情况大概三天才会出现一次，但仍然过于频繁了，以致惹人恼怒。一旦数据库罢工，"无论这种情况什么时候发生，未缓存的数据都不能从SQL Server获得，那么你就必然看到一个'意外错误'提示。"他解释说。 </p>
<p>　　去年夏天，MySpace的Windows 2003多次自动停止服务。后来发现是操作系统一个内置功能惹的祸--预防分布式拒绝服务攻击（黑客使用很多客户机向服务器发起大量连接请求，以致服务器瘫痪）。MySpace和其他很多顶级大站点一样，肯定会经常遭受攻击，但它应该从网络级而不是依靠Windows本身的功能来解决问题--否则，大量MySpace合法用户连接时也会引起服务器反击。 </p>
<p>"我们花了大约一个月时间寻找Windows 2003服务器自动停止的原因。"Benedetto说。最后，通过Microsoft的帮助，他们才知道该怎么通知服务器："别开枪，是友军。" </p>
<p>　　紧接着是在去年7月某个周日晚上，MySpace总部所在地洛杉矶停电，造成整个系统停运12小时。大型Web站点通常要在地理上分布配置多个数据中心以预防单点故障。本来，MySpace还有其他两个数据中心以应对突发事件，但Web服务器都依赖于部署在洛杉矶的SAN。没有洛杉矶的SAN，Web服务器除了恳求你耐心等待，不能提供任何服务。 </p>
<p>Benedetto说，主数据中心的可靠性通过下列措施保证：可接入两张不同电网，另有后备电源和一台储备有30天燃料的发电机。但在这次事故中，不仅两张电网失效，而且在切换到备份电源的过程中，操作员烧掉了主动力线路。 </p>
<p>2007年中，MySpace在另两个后备站点上也建设了SAN。这对分担负荷大有帮助--正常情况下，每个SAN都能负担三分之一的数据访问量。而在紧急情况下，任何一个站点都可以独立支撑整个服务，Benedetto说。 </p>
<p>MySpace仍然在为提高稳定性奋斗，虽然很多用户表示了足够信任且能原谅偶现的错误页面。 </p>
<p>"作为开发人员，我憎恶Bug，它太气人了。"Dan Tanner这个31岁的德克萨斯软件工程师说，他通过MySpace重新联系到了高中和大学同学。"不过，MySpace对我们的用处很大，因此我们可以原谅偶发的故障和错误。" Tanner说，如果站点某天出现故障甚至崩溃，恢复以后他还是会继续使用。 </p>
<p>　　这就是为什么Drew在论坛里咆哮时，大部分用户都告诉他应该保持平静，如果等几分钟，问题就会解决的原因。Drew无法平静，他写道，"我已经两次给MySpace发邮件，而它说一小时前还是正常的，现在出了点问题&#8230;&#8230;完全是一堆废话。"另一个用户回复说，"毕竟它是免费的。"Benedetto坦承100%的可靠性不是他的目标。"它不是银行，而是一个免费的服务。"他说。 </p>
<p>　　换句话说，MySpace的偶发故障可能造成某人最后更新的个人资料丢失，但并不意味着网站弄丢了用户的钱财。"关键是要认识到，与保证站点性能相比，丢失少许数据的故障是可接受的。"Benedetto说。所以，MySpace甘冒丢失2分钟到2小时内任意点数据的危险，在SQL Server配置里延长了"checkpoint"操作--它将待更新数据永久记录到磁盘--的间隔时间，因为这样做可以加快数据库的运行。 </p>
<p>Benedetto说，同样，开发人员还经常在几个小时内就完成构思、编码、测试和发布全过程。这有引入Bug的风险，但这样做可以更快实现新功能。而且，因为进行大规模真实测试不具可行性，他们的测试通常是在仅以部分活跃用户为对象，且用户对软件新功能和改进不知就里的情况下进行的。因为事实上不可能做真实的加载测试，他们做的测试通常都是针对站点。 </p>
<p>"我们犯过大量错误，"Benedetto说，"但到头来，我认为我们做对的还是比做错的多。" </p>
<h4><a><font color=#0066a7>七、 从LiveJournal</font></a>后台发展看大规模网站性能优化方法</h4>
<p><a href="http://www.livejournal.com/"><font color=#0066a7>LiveJournal</font></a>是99年始于校园中的项目，几个人出于爱好做了这样一个应用，以实现以下功能： </p>
<ul>
    <li>博客，论坛
    <li>社会性网络，找到朋友
    <li>聚合，把朋友的文章聚合在一起 </li>
</ul>
<p>LiveJournal采用了大量的开源软件，甚至它本身也是一个开源软件。 </p>
<p>在上线后，LiveJournal实现了非常快速的增长： </p>
<ul>
    <li>2004年4月份：280万注册用户。
    <li>2005年4月份：680万注册用户。
    <li>2005年8月份：790万注册用户。
    <li>达到了每秒钟上千次的页面请求及处理。
    <li>使用了大量MySQL服务器。
    <li>使用了大量通用组件。 </li>
</ul>
<p><strong>二、LiveJournal</strong><strong>架构现状概况</strong> </p>
<p><a href="http://byfiles.storage.msn.com/y1pLfC-bv1f71Ng8NRsPI0kDc-Ikh9MpNQsQdk2hWYZj7EqSGMNCdy6_L0NCqVwf4Kdouk7Yyd1I7M"><img style="BORDER-TOP-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-RIGHT-WIDTH: 0px" height=178 alt=clip_image004[4] src="http://www.360doc.com/DownloadImg/3500/754206_2" width=240 border=0></a> </p>
<p><strong>三、从LiveJournal</strong><strong>发展中学习</strong> </p>
<p>LiveJournal从1台服务器发展到100台服务器，这其中经历了无数的伤痛，但同时也摸索出了解决这些问题的方法，通过对LiveJournal的学习，可以让我们避免LJ曾经犯过的错误，并且从一开始就对系统进行良好的设计，以避免后期的痛苦。 </p>
<p>下面我们一步一步看LJ发展的脚步。 </p>
<p><strong>1</strong><strong>、一台服务器</strong> </p>
<p>一台别人捐助的服务器，LJ最初就跑在上面，就像Google开始时候用的破服务器一样，值得我们尊敬。这个阶段，LJ的人以惊人的速度熟悉的Unix的操作管理，服务器性能出现过问题，不过还好，可以通过一些小修小改应付过去。在这个阶段里LJ把CGI升级到了FastCGI。 </p>
<p>最终问题出现了，网站越来越慢，已经无法通过优过化来解决的地步，需要更多的服务器，这时LJ开始提供付费服务，可能是想通过这些钱来购买新的服务器，以解决当时的困境。 </p>
<p>毫无疑问，当时LJ存在巨大的单点问题，所有的东西都在那台服务器的铁皮盒子里装着。 </p>
<p><a href="http://byfiles.storage.msn.com/y1pLfC-bv1f71P0Ctl55617UrDRVWacD8C-YyoV1p8Mjh3G3xC1ENgZFvH6K2cZYL18sYQf79Sx3uY"><img style="BORDER-TOP-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-RIGHT-WIDTH: 0px" height=89 alt=clip_image006[4] src="http://www.360doc.com/DownloadImg/3500/754206_3" width=240 border=0></a> </p>
<p><strong>2</strong><strong>、两台服务器</strong> </p>
<p>用付费服务赚来的钱LJ买了两台服务器：一台叫做Kenny的Dell 6U机器用于提供Web服务，一台叫做Cartman的Dell 6U服务器用于提供数据库服务。 </p>
<p><a href="http://byfiles.storage.msn.com/y1pLfC-bv1f71MYOwfHqsOqx2LZQeA6v74qsDAvbZorZpZFj2gr4fgXQOP3WxIdRovgimi1QAlsQKo"><img style="BORDER-TOP-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-RIGHT-WIDTH: 0px" height=240 alt=clip_image008[4] src="http://www.360doc.com/DownloadImg/3500/754206_4" width=187 border=0></a> </p>
<p>LJ有了更大的磁盘，更多的计算资源。但同时网络结构还是非常简单，每台机器两块网卡，Cartman通过内网为Kenny提供MySQL数据库服务。 </p>
<p>暂时解决了负载的问题，新的问题又出现了： </p>
<ul>
    <li>原来的一个单点变成了两个单点。
    <li>没有冷备份或热备份。
    <li>网站速度慢的问题又开始出现了，没办法，增长太快了。
    <li>Web服务器上CPU达到上限，需要更多的Web服务器。 </li>
</ul>
<p><strong>3</strong><strong>、四台服务器</strong> </p>
<p>又买了两台，Kyle和Stan，这次都是1U的，都用于提供Web服务。目前LJ一共有3台Web服务器和一台数据库服务器。这时需要在3台Web服务器上进行负载均横。 </p>
<p><a href="http://byfiles.storage.msn.com/y1pLfC-bv1f71NbrJH5rdoo9Q6nZVx-GHS1h4I5aOqUMyFyTc55NtAnXQH_GQMklSqagAoLl7zoEww"><img style="BORDER-TOP-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-RIGHT-WIDTH: 0px" height=115 alt=clip_image010[4] src="http://www.360doc.com/DownloadImg/3500/754206_5" width=240 border=0></a> </p>
<p>LJ把Kenny用于外部的网关，使用mod_backhand进行负载均横。 </p>
<p>然后问题又出现了： </p>
<ul>
    <li>单点故障。数据库和用于做网关的Web服务器都是单点，一旦任何一台机器出现问题将导致所有服务不可用。虽然用于做网关的Web服务器可以通过保持心跳同步迅速切换，但还是无法解决数据库的单点，LJ当时也没做这个。
    <li>网站又变慢了，这次是因为IO和数据库的问题，问题是怎么往应用里面添加数据库呢？ </li>
</ul>
<p><strong>4</strong><strong>、五台服务器</strong> </p>
<p>又买了一台数据库服务器。在两台数据库服务器上使用了数据库同步(Mysql支持的Master-Slave模式)，写操作全部针对主数据库（通过Binlog，主服务器上的写操作可以迅速同步到从服务器上），读操作在两个数据库上同时进行(也算是负载均横的一种吧)。 </p>
<p><a href="http://byfiles.storage.msn.com/y1pLfC-bv1f71N6odCri1KVxP_h3bcvZO-Hnp66GTpNHNZxnI4t4kfzDn7kQCzK-l7YwwyBR8BWcBU"><img style="BORDER-TOP-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-RIGHT-WIDTH: 0px" height=127 alt=clip_image012[4] src="http://www.360doc.com/DownloadImg/3500/754206_6" width=240 border=0></a> </p>
<p>实现同步时要注意几个事项： </p>
<ul>
    <li>读操作数据库选择算法处理，要选一个当前负载轻一点的数据库。
    <li>在从数据库服务器上只能进行读操作
    <li>准备好应对同步过程中的延迟，处理不好可能会导致数据库同步的中断。只需要对写操作进行判断即可，读操作不存在同步问题。 </li>
</ul>
<p><strong>5</strong><strong>、更多服务器</strong> </p>
<p>有钱了，当然要多买些服务器。部署后快了没多久，又开始慢了。这次有更多的Web服务器，更多的数据库服务器，存在 IO与CPU争用。于是采用了BIG-IP作为负载均衡解决方案。 </p>
<p><a href="http://byfiles.storage.msn.com/y1pLfC-bv1f71N3IagF7BfIWUPsYyeGzaDRWdW0UYgoESHvPFnoPcXbRayC0ujr6c_3EIcd5uQjeLM"><img style="BORDER-TOP-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-RIGHT-WIDTH: 0px" height=240 alt=clip_image014[4] src="http://www.360doc.com/DownloadImg/3500/754206_7" width=225 border=0></a> </p>
<p><strong>6</strong><strong>、现在我们在哪里：</strong> </p>
<p><a href="http://byfiles.storage.msn.com/y1pLfC-bv1f71P3I0DKW-AYfsw9T4JlR-Ln3M8GJI3Mta9xvoKJ93LBpylAlMTlVU5v8gkKbVVExSU"><img style="BORDER-TOP-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-RIGHT-WIDTH: 0px" height=142 alt=clip_image016[4] src="http://www.360doc.com/DownloadImg/3500/754206_8" width=240 border=0></a> </p>
<p>现在服务器基本上够了，但性能还是有问题，原因出在架构上。 </p>
<p>数据库的架构是最大的问题。由于增加的数据库都是以Slave模式添加到应用内，这样唯一的好处就是将读操作分布到了多台机器，但这样带来的后果就是写操作被大量分发，每台机器都要执行，服务器越多，浪费就越大，随着写操作的增加，用于服务读操作的资源越来越少。 </p>
<p><a href="http://byfiles.storage.msn.com/y1pLfC-bv1f71MPya6rCW77VuC79TgWb_o4GOMvkefOyFMYGGKSUVWUw4MZCKw4rMtdIB1VRPgpQKg"><img style="BORDER-TOP-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-RIGHT-WIDTH: 0px" height=93 alt=clip_image018[4] src="http://www.360doc.com/DownloadImg/3500/754206_9" width=240 border=0></a> </p>
<p>由一台分布到两台 </p>
<p><a href="http://byfiles.storage.msn.com/y1pLfC-bv1f71ML3RaIG8BvZTf5z0i_5ooooXQ0mQ6Qh4RD1iaj-qP0hY8b1ffaQKnVtz-kjhV42RM"><img style="BORDER-TOP-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-RIGHT-WIDTH: 0px" height=131 alt=clip_image020[4] src="http://www.360doc.com/DownloadImg/3500/754206_10" width=240 border=0></a> </p>
<p>最终效果 </p>
<p>现在我们发现，我们并不需要把这些数据在如此多的服务器上都保留一份。服务器上已经做了RAID，数据库也进行了备份，这么多的备份完全是对资源的浪费，属于冗余极端过度。那为什么不把数据分布存储呢？ </p>
<p>问题发现了，开始考虑如何解决。现在要做的就是把不同用户的数据分布到不同的服务器上进行存储，以实现数据的分布式存储，让每台机器只为相对固定的用户服务，以实现平行的架构和良好的可扩展性。 </p>
<p>为了实现用户分组，我们需要为每一个用户分配一个组标记，用于标记此用户的数据存放在哪一组数据库服务器中。每组数据库由一个master及几个slave组成，并且slave的数量在2-3台，以实现系统资源的最合理分配，既保证数据读操作分布，又避免数据过度冗余以及同步操作对系统资源的过度消耗。 </p>
<p><a href="http://byfiles.storage.msn.com/y1pLfC-bv1f71Pt9Hb_mHfbR9yubMZd0NMrk7Q_s1_RbC03CvTx-1yJEjgwRdkISUsWYw25yzSlX1w"><img style="BORDER-TOP-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-RIGHT-WIDTH: 0px" height=155 alt=clip_image022[4] src="http://www.360doc.com/DownloadImg/3500/754206_11" width=240 border=0></a> </p>
<p>由一台（一组）中心服务器提供用户分组控制。所有用户的分组信息都存储在这台机器上，所有针对用户的操作需要先查询这台机器得到用户的组号，然后再到相应的数据库组中获取数据。 </p>
<p>这样的用户架构与目前LJ的架构已经很相像了。 </p>
<p>在具体的实现时需要注意几个问题： </p>
<ul>
    <li>在数据库组内不要使用自增ID，以便于以后在数据库组之间迁移用户，以实现更合理的I/O，磁盘空间及负载分布。
    <li>将userid，postid存储在全局服务器上，可以使用自增，数据库组中的相应值必须以全局服务器上的值为准。全局服务器上使用事务型数据库InnoDB。
    <li>在数据库组之间迁移用户时要万分小心，当迁移时用户不能有写操作。 </li>
</ul>
<p><strong>7</strong><strong>、现在我们在哪里</strong> </p>
<p><a href="http://byfiles.storage.msn.com/y1pLfC-bv1f71Pu4DMG0Os_qdTIzpK9fuMXimE3UUNik8HfzE8uLLktV0-AwIW3tULtxR4pUB1Lw9w"><img style="BORDER-TOP-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-RIGHT-WIDTH: 0px" height=175 alt=clip_image024[4] src="http://www.360doc.com/DownloadImg/3500/754206_12" width=240 border=0></a> </p>
<p>问题： </p>
<ul>
    <li>一个全局主服务器，挂掉的话所有用户注册及写操作就挂掉。
    <li>每个数据库组一个主服务器，挂掉的话这组用户的写操作就挂掉。
    <li>数据库组从服务器挂掉的话会导致其它服务器负载过大。 </li>
</ul>
<p>对于Master-Slave模式的单点问题，LJ采取了Master-Master模式来解决。所谓Master-Master实际上是人工实现的，并不是由MySQL直接提供的，实际上也就是两台机器同时是Master，也同时是Slave，互相同步。 </p>
<p>Master-Master实现时需要注意： </p>
<ul>
    <li>一个Master出错后恢复同步，最好由服务器自动完成。
    <li>数字分配，由于同时在两台机器上写，有些ID可能会冲突。 </li>
</ul>
<p>解决方案： </p>
<ul>
    <li>奇偶数分配ID，一台机器上写奇数，一台机器上写偶数
    <li>通过全局服务器进行分配(LJ采用的做法)。 </li>
</ul>
<p>Master-Master模式还有一种用法，这种方法与前一种相比，仍然保持两台机器的同步，但只有一台机器提供服务（读和写），在每天晚上的时候进行轮换，或者出现问题的时候进行切换。 </p>
<p><strong>8</strong><strong>、现在我们在哪里</strong> </p>
<p><a href="http://byfiles.storage.msn.com/y1pLfC-bv1f71MZdrtXDHuDnf_tJozpHnLCL3UmzCGpqxOM9odGbkvKFUlPa_ydtTnif7Y9ffe1Af8"><img style="BORDER-TOP-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-RIGHT-WIDTH: 0px" height=167 alt=clip_image026[4] src="http://www.360doc.com/DownloadImg/3500/754206_13" width=240 border=0></a> </p>
<p>现在插播一条广告，MyISAM VS InnoDB。 </p>
<p>使用InnoDB： </p>
<ul>
    <li>支持事务
    <li>需要做更多的配置，不过值得，可以更安全的存储数据，以及得到更快的速度。 </li>
</ul>
<p>使用MyISAM： </p>
<ul>
    <li>记录日志（LJ用它来记网络访问日志）
    <li>存储只读静态数据，足够快。
    <li>并发性很差，无法同时读写数据（添加数据可以）
    <li>MySQL非正常关闭或死机时会导致索引错误，需要使用myisamchk修复，而且当访问量大时出现非常频繁。 </li>
</ul>
<p><strong>9</strong><strong>、缓存</strong> </p>
<p>去年我写过<a href="http://www.example.net.cn/archives/2006/01/eoamemcachedoea.html"><font color=#0066a7>一篇文章介绍memcached</font></a>，它就是由LJ的团队开发的一款缓存工具，以key-value的方式将数据存储到分布的内存中。LJ缓存的数据： </p>
<ul>
    <li>12台独立服务器（不是捐赠的）
    <li>28个实例
    <li>30GB总容量
    <li>90-93%的命中率（用过squid的人可能知道，squid内存加磁盘的命中率大概在70-80%） </li>
</ul>
<p>如何建立缓存策略？ </p>
<p>想缓存所有的东西？那是不可能的，我们只需要缓存已经或者可能导致系统瓶颈的地方，最大程度的提交系统运行效率。通过对MySQL的日志的分析我们可以找到缓存的对象。 </p>
<p>缓存的缺点？ </p>
<ul>
    <li>没有完美的事物，缓存也有缺点：
    <li>增大开发量，需要针对缓存处理编写特殊的代码。
    <li>管理难度增加，需要更多人参与系统维护。
    <li>当然大内存也需要钱。 </li>
</ul>
<p><strong>10</strong><strong>、Web</strong><strong>访问负载均衡</strong> </p>
<p>在数据包级别使用BIG-IP，但BIG-IP并不知道我们内部的处理机制，无法判断由哪台服务器对这些请求进行处理。反向代理并不能很好的起到作用，不是已经够快了，就是达不到我们想要的效果。 </p>
<p>所以，LJ又开发了<a href="http://www.danga.com/perlbal/"><font color=#0066a7>Perlbal</font></a>。特点： </p>
<ul>
    <li>快，小，可管理的http web 服务器/代理
    <li>可以在内部进行转发
    <li>使用Perl开发
    <li>单线程，异步，基于事件，使用epoll , kqueue
    <li>支持Console管理与http远程管理，支持动态配置加载
    <li>多种模式：web服务器，反向代理，插件
    <li>支持插件：GIF/PNG互换？ </li>
</ul>
<p><strong>11</strong><strong>、MogileFS</strong> </p>
<p>LJ使用开源的<a href="http://www.danga.com/mogilefs/"><font color=#0066a7>MogileFS</font></a>作为分布式文件存储系统。MogileFS使用非常简单，它的主要设计思想是： </p>
<ul>
    <li>文件属于类（类是最小的复制单位）
    <li>跟踪文件存储位置
    <li>在不同主机上存储
    <li>使用MySQL集群统一存储分布信息
    <li>大容易廉价磁盘 </li>
</ul>
<p>到目前为止就这么多了，更多文档可以在<a href="http://www.danga.com/words/"><font color=#0066a7>http://www.danga.com/words/</font></a>找到。<a href="http://www.danga.com/"><font color=#0066a7>Danga.com</font></a>和<a href="http://www.livejournal.com/"><font color=#0066a7>LiveJournal.com</font></a>的同学们拿这个文档参加了两次MySQL Con，两次OS Con，以及众多的其它会议，无私的把他们的经验分享出来，值得我们学习。在web2.0时代快速开发得到大家越来越多的重视，但良好的设计仍是每一个应用的基础，希望web2.0们在成长为Top500网站的路上，不要因为架构阻碍了网站的发展。 </p>
<h4><a><font color=#0066a7><strong>八、</strong> <strong>说说大型高并发高负载网站的系统架构</strong></font></a></h4>
<p>我在Cernet做过拨号接入平台的搭建，而后在Yahoo3721负载搜索引擎前端平台开发，又在猫扑处理过大型社区猫扑大杂烩的架构升级等工作，同时自己接触和开发过不少大中型网站的模块，因此在大型网站应对高负载和并发的解决方案上有一些积累和经验，可以和大家一起探讨一下。 </p>
<p>一个小型的网站，比如个人网站，可以使用最简单的html静态页面就实现了，配合一些图片达到美化效果，所有的页面均存放在一个目录下，这样的网站对系统架构、性能的要求都很简单，随着互联网业务的不断丰富，网站相关的技术经过这些年的发展，已经细分到很细的方方面面，尤其对于大型网站来说，所采用的技术更是涉及面非常广，从硬件到软件、编程语言、数据库、WebServer、防火墙等各个领域都有了很高的要求，已经不是原来简单的html静态网站所能比拟的。 </p>
<p>大型网站，比如门户网站。在面对大量用户访问、高并发请求方面，基本的解决方案集中在这样几个环节：使用高性能的服务器、高性能的数据库、高效率的编程语言、还有高性能的Web容器。但是除了这几个方面，还没法根本解决大型网站面临的高负载和高并发问题。 </p>
<p>上面提供的几个解决思路在一定程度上也意味着更大的投入，并且这样的解决思路具备瓶颈，没有很好的扩展性，下面我从低成本、高性能和高扩张性的角度来说说我的一些经验。 </p>
<p>1、HTML静态化 </p>
<p>其实大家都知道，效率最高、消耗最小的就是纯静态化的html页面，所以我们尽可能使我们的网站上的页面采用静态页面来实现，这个最简单的方法其实也是最有效的方法。但是对于大量内容并且频繁更新的网站，我们无法全部手动去挨个实现，于是出现了我们常见的信息发布系统CMS，像我们常访问的各个门户站点的新闻频道，甚至他们的其他频道，都是通过信息发布系统来管理和实现的，信息发布系统可以实现最简单的信息录入自动生成静态页面，还能具备频道管理、权限管理、自动抓取等功能，对于一个大型网站来说，拥有一套高效、可管理的CMS是必不可少的。 </p>
<p>除了门户和信息发布类型的网站，对于交互性要求很高的社区类型网站来说，尽可能的静态化也是提高性能的必要手段，将社区内的帖子、文章进行实时的静态化，有更新的时候再重新静态化也是大量使用的策略，像Mop的大杂烩就是使用了这样的策略，网易社区等也是如此。 </p>
<p>同时，html静态化也是某些缓存策略使用的手段，对于系统中频繁使用数据库查询但是内容更新很小的应用，可以考虑使用html静态化来实现，比如论坛中论坛的公用设置信息，这些信息目前的主流论坛都可以进行后台管理并且存储再数据库中，这些信息其实大量被前台程序调用，但是更新频率很小，可以考虑将这部分内容进行后台更新的时候进行静态化，这样避免了大量的数据库访问请求。 </p>
<p>2、图片服务器分离 </p>
<p>大家知道，对于Web服务器来说，不管是Apache、IIS还是其他容器，图片是最消耗资源的，于是我们有必要将图片与页面进行分离，这是基本上大型网站都会采用的策略，他们都有独立的图片服务器，甚至很多台图片服务器。这样的架构可以降低提供页面访问请求的服务器系统压力，并且可以保证系统不会因为图片问题而崩溃，在应用服务器和图片服务器上，可以进行不同的配置优化，比如apache在配置ContentType的时候可以尽量少支持，尽可能少的LoadModule，保证更高的系统消耗和执行效率。 </p>
<p>3、数据库集群和库表散列 </p>
<p>大型网站都有复杂的应用，这些应用必须使用数据库，那么在面对大量访问的时候，数据库的瓶颈很快就能显现出来，这时一台数据库将很快无法满足应用，于是我们需要使用数据库集群或者库表散列。 </p>
<p>在数据库集群方面，很多数据库都有自己的解决方案，Oracle、Sybase等都有很好的方案，常用的MySQL提供的Master/Slave也是类似的方案，您使用了什么样的DB，就参考相应的解决方案来实施即可。 </p>
<p>上面提到的数据库集群由于在架构、成本、扩张性方面都会受到所采用DB类型的限制，于是我们需要从应用程序的角度来考虑改善系统架构，库表散列是常用并且最有效的解决方案。我们在应用程序中安装业务和应用或者功能模块将数据库进行分离，不同的模块对应不同的数据库或者表，再按照一定的策略对某个页面或者功能进行更小的数据库散列，比如用户表，按照用户ID进行表散列，这样就能够低成本的提升系统的性能并且有很好的扩展性。sohu的论坛就是采用了这样的架构，将论坛的用户、设置、帖子等信息进行数据库分离，然后对帖子、用户按照板块和ID进行散列数据库和表，最终可以在配置文件中进行简单的配置便能让系统随时增加一台低成本的数据库进来补充系统性能。 </p>
<p>4、缓存 </p>
<p>缓存一词搞技术的都接触过，很多地方用到缓存。网站架构和网站开发中的缓存也是非常重要。这里先讲述最基本的两种缓存。高级和分布式的缓存在后面讲述。 </p>
<p>架构方面的缓存，对Apache比较熟悉的人都能知道Apache提供了自己的缓存模块，也可以使用外加的Squid模块进行缓存，这两种方式均可以有效的提高Apache的访问响应能力。 </p>
<p>网站程序开发方面的缓存，Linux上提供的Memory Cache是常用的缓存接口，可以在web开发中使用，比如用Java开发的时候就可以调用MemoryCache对一些数据进行缓存和通讯共享，一些大型社区使用了这样的架构。另外，在使用web语言开发的时候，各种语言基本都有自己的缓存模块和方法，PHP有Pear的Cache模块，Java就更多了，.net不是很熟悉，相信也肯定有。 </p>
<p>5、镜像 </p>
<p>镜像是大型网站常采用的提高性能和数据安全性的方式，镜像的技术可以解决不同网络接入商和地域带来的用户访问速度差异，比如ChinaNet和EduNet之间的差异就促使了很多网站在教育网内搭建镜像站点，数据进行定时更新或者实时更新。在镜像的细节技术方面，这里不阐述太深，有很多专业的现成的解决架构和产品可选。也有廉价的通过软件实现的思路，比如Linux上的rsync等工具。 </p>
<p>6、负载均衡 </p>
<p>负载均衡将是大型网站解决高负荷访问和大量并发请求采用的终极解决办法。 </p>
<p>负载均衡技术发展了多年，有很多专业的服务提供商和产品可以选择，我个人接触过一些解决方法，其中有两个架构可以给大家做参考。 </p>
<ul>
    <li>硬件四层交换 </li>
</ul>
<p>第四层交换使用第三层和第四层信息包的报头信息，根据应用区间识别业务流，将整个区间段的业务流分配到合适的应用服务器进行处理。　第四层交换功能就象是虚IP，指向物理服务器。它传输的业务服从的协议多种多样，有HTTP、FTP、NFS、Telnet或其他协议。这些业务在物理服务器基础上，需要复杂的载量平衡算法。在IP世界，业务类型由终端TCP或UDP端口地址来决定，在第四层交换中的应用区间则由源端和终端IP地址、TCP和UDP端口共同决定。 </p>
<p>在硬件四层交换产品领域，有一些知名的产品可以选择，比如Alteon、F5等，这些产品很昂贵，但是物有所值，能够提供非常优秀的性能和很灵活的管理能力。Yahoo中国当初接近2000台服务器使用了三四台Alteon就搞定了。 </p>
<ul>
    <li>软件四层交换 </li>
</ul>
<p>大家知道了硬件四层交换机的原理后，基于OSI模型来实现的软件四层交换也就应运而生，这样的解决方案实现的原理一致，不过性能稍差。但是满足一定量的压力还是游刃有余的，有人说软件实现方式其实更灵活，处理能力完全看你配置的熟悉能力。 </p>
<p>软件四层交换我们可以使用Linux上常用的LVS来解决，LVS就是Linux Virtual Server，他提供了基于心跳线heartbeat的实时灾难应对解决方案，提高系统的鲁棒性，同时可供了灵活的虚拟VIP配置和管理功能，可以同时满足多种应用需求，这对于分布式的系统来说必不可少。 </p>
<p>一个典型的使用负载均衡的策略就是，在软件或者硬件四层交换的基础上搭建squid集群，这种思路在很多大型网站包括搜索引擎上被采用，这样的架构低成本、高性能还有很强的扩张性，随时往架构里面增减节点都非常容易。这样的架构我准备空了专门详细整理一下和大家探讨。 </p>
<p>对于大型网站来说，前面提到的每个方法可能都会被同时使用到，我这里介绍得比较浅显，具体实现过程中很多细节还需要大家慢慢熟悉和体会，有时一个很小的squid参数或者apache参数设置，对于系统性能的影响就会很大，希望大家一起讨论，达到抛砖引玉之效。 </p>
</div> <br><script type="text/javascript" src="http://www.cnitblog.com/Files/yemoo/gg2.js"></script><img src ="http://www.cnitblog.com/yemoo/aggbug/34234.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/yemoo/" target="_blank">Yemoo'S JS Blog</a> 2007-09-30 09:53 <a href="http://www.cnitblog.com/yemoo/archive/2007/09/30/34234.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>推荐四款JS代码压缩工具</title><link>http://www.cnitblog.com/yemoo/archive/2007/09/29/34174.html</link><dc:creator>Yemoo'S JS Blog</dc:creator><author>Yemoo'S JS Blog</author><pubDate>Sat, 29 Sep 2007 04:23:00 GMT</pubDate><guid>http://www.cnitblog.com/yemoo/archive/2007/09/29/34174.html</guid><wfw:comment>http://www.cnitblog.com/yemoo/comments/34174.html</wfw:comment><comments>http://www.cnitblog.com/yemoo/archive/2007/09/29/34174.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/yemoo/comments/commentRss/34174.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/yemoo/services/trackbacks/34174.html</trackback:ping><description><![CDATA[<script type="text/javascript" src="http://www.cnitblog.com/Files/yemoo/gg1.js"></script>
<br><br>每个做web开发的朋友都会有一些珍藏的小工具，对于web程序的开发调试发布有时有着很大的帮助。<br><br>偶今天就发出几个自己常用的JS压缩工具，希望各位朋友喜欢，以后我会陆续发布一些其他小工具！<br><br><br><strong>Javascript代码压缩工具：</strong><br><br><span style="COLOR: #00008b">jsMinGUI：这个很少用，大家可以试试</span><br>下载及介绍：<a href="http://jsdoc.cn/archive/show.do?archive.archiveId=8" target=_blank><u><font color=#0000ff>http://jsdoc.cn/archive/show.do?archive.archiveId=8</font></u></a><br><br><span style="COLOR: #00008b">ESC：非EXE文件，使用windows的WSF进行压缩，压缩率还可以</span><br>下载及介绍：<a href="http://www.saltstorm.net/depo/esc/?pod=js" target=_blank><u><font color=#0000ff>http://www.saltstorm.net/depo/esc/?pod=js</font></u></a><br><br><span style="COLOR: #00008b">Packer：压缩率很多，操作方便</span><br>下载地址：<a href="http://dean.edwards.name/download/packer.net.zip" target=_blank><u><font color=#0000ff>http://dean.edwards.name/download/packer.net.zip</font></u></a><br><br><span style="COLOR: #00008b">JAS：压缩率相当高，但需要java运行时支持。</span><br>下载及介绍：<a href="http://www.xidea.org/project/jsa/" target=_blank><u><font color=#0000ff>http://www.xidea.org/project/jsa/</font></u></a><br><script type="text/javascript" src="http://www.cnitblog.com/Files/yemoo/gg2.js"></script><img src ="http://www.cnitblog.com/yemoo/aggbug/34174.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/yemoo/" target="_blank">Yemoo'S JS Blog</a> 2007-09-29 12:23 <a href="http://www.cnitblog.com/yemoo/archive/2007/09/29/34174.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>解决iframe中输入框自动完成错位的bug</title><link>http://www.cnitblog.com/yemoo/archive/2007/07/27/30772.html</link><dc:creator>Yemoo'S JS Blog</dc:creator><author>Yemoo'S JS Blog</author><pubDate>Fri, 27 Jul 2007 02:39:00 GMT</pubDate><guid>http://www.cnitblog.com/yemoo/archive/2007/07/27/30772.html</guid><wfw:comment>http://www.cnitblog.com/yemoo/comments/30772.html</wfw:comment><comments>http://www.cnitblog.com/yemoo/archive/2007/07/27/30772.html#Feedback</comments><slash:comments>-1</slash:comments><wfw:commentRss>http://www.cnitblog.com/yemoo/comments/commentRss/30772.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/yemoo/services/trackbacks/30772.html</trackback:ping><description><![CDATA[<script type="text/javascript" src="http://www.cnitblog.com/Files/yemoo/gg1.js"></script><br><br>  在ie中如果在iframe页面中有输入框，则会发现自动提示位置错位，一般是跑到了下面很远的地方，这其实是ie的bug，郁闷了好久终于在网上找到了解决办法。<br><br>通用解决办法：<br><strong>在&lt;iframe&gt;标签里加入style="position:relative"就可以了。<br><br>==========================================================<br>下面的办法是解决系统bug的，这个办法对我们没有多大用处（毕竟不可能让所有的用户都装上这个补丁）<br></strong>This problem occurs because the window.screenTop property value is calculated incorrectly. <br><br>RESOLUTION: <br>安装XP-SP2（Win2003-sp1） 和 最新的windows更新程序 <br>然后重新启动系统 <br><br>一般来说还需要配置以下注册表（可以先检查问题是否仍然存在）： <br>1. 开始 ， 运行，键入 regedit ，回车 <br>2. 找到并单击以下注册表项： <br>HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\Main\FeatureControl <br>3. 编辑 \新建\KEY <br>4. 键入 FEATURE_SKIP_ROW_IN_OFFSET_HEIGHT_CALCULATION_KB920681 , 然后按 Enter。 <br>5. 编辑,新建 ,DWORD <br>6. 键入 iexplore.exe , Enter。 <br>7. 右击 iexplore.exe , 然后单击 修改 。 <br>8. 键入 1 , 然后单击 确定 。 <br>9. 退出注册表编辑器。 <br>10. 重新启动 InternetExplorer。 <p><script type="text/javascript" src="http://www.cnitblog.com/Files/yemoo/gg2.js"></script><img src ="http://www.cnitblog.com/yemoo/aggbug/30772.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/yemoo/" target="_blank">Yemoo'S JS Blog</a> 2007-07-27 10:39 <a href="http://www.cnitblog.com/yemoo/archive/2007/07/27/30772.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>收藏几个web相关的站点</title><link>http://www.cnitblog.com/yemoo/archive/2007/06/07/28152.html</link><dc:creator>Yemoo'S JS Blog</dc:creator><author>Yemoo'S JS Blog</author><pubDate>Thu, 07 Jun 2007 02:11:00 GMT</pubDate><guid>http://www.cnitblog.com/yemoo/archive/2007/06/07/28152.html</guid><wfw:comment>http://www.cnitblog.com/yemoo/comments/28152.html</wfw:comment><comments>http://www.cnitblog.com/yemoo/archive/2007/06/07/28152.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/yemoo/comments/commentRss/28152.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/yemoo/services/trackbacks/28152.html</trackback:ping><description><![CDATA[<script type="text/javascript" src="http://www.cnitblog.com/Files/yemoo/gg1.js"></script>
几个web开发的国外站点,收藏备忘.<a href="http://www.cssremix.com/"><br><br>http://www.cssremix.com/</a><br><br><a href="http://www.smashingmagazine.com/">http://www.smashingmagazine.com/</a><br><br><a href="http://www.ndesign-studio.com/">http://www.ndesign-studio.com/</a> <br><br><br>JS组件:<br>http://scbr.com/docs/products.shtml
 <script type="text/javascript" src="http://www.cnitblog.com/Files/yemoo/gg2.js"></script><img src ="http://www.cnitblog.com/yemoo/aggbug/28152.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/yemoo/" target="_blank">Yemoo'S JS Blog</a> 2007-06-07 10:11 <a href="http://www.cnitblog.com/yemoo/archive/2007/06/07/28152.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>不容忽视的注释--saved from url</title><link>http://www.cnitblog.com/yemoo/archive/2007/05/10/26804.html</link><dc:creator>Yemoo'S JS Blog</dc:creator><author>Yemoo'S JS Blog</author><pubDate>Thu, 10 May 2007 00:10:00 GMT</pubDate><guid>http://www.cnitblog.com/yemoo/archive/2007/05/10/26804.html</guid><wfw:comment>http://www.cnitblog.com/yemoo/comments/26804.html</wfw:comment><comments>http://www.cnitblog.com/yemoo/archive/2007/05/10/26804.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.cnitblog.com/yemoo/comments/commentRss/26804.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/yemoo/services/trackbacks/26804.html</trackback:ping><description><![CDATA[<script type="text/javascript" src="http://www.cnitblog.com/Files/yemoo/gg1.js"></script><br><br>  今天帮朋友改一个页面，改好後发现连接都无法打，明明地址正确，查看源码，发现了&lt;saved from url=(0022)...-&gt;，当时只是随便吧改行删掉了，没想到所有的连接都可以点击了，哈哈，原来这个注释还有这个特点，在网上狂搜了一把，在蓝色上发现了下面这段介绍，感觉写的挺好，于是收藏于此。<br><br>==========================================<br>注意：您可以向本地 HTML 文件中添加一条&#8220;saved from URL&#8221;注释，以指示 Internet Explorer 对本地计算机上的 HTML 内容应用其他区域的设置。例如，您可以向一个本地 HTML 文件中添加一条&#8220;saved from URL&#8221;注释，以便可以将该 HTML 文件分配到 Internet 区域而不是本地计算机区域。如果您在 Internet 区域中允许脚本、签名的 ActiveX 控件和 Java 小程序，那么该本地 HTML 文件将使用这些缩减的安全权限运行。要指示 Internet Explorer 对名为 Test.htm 的本地 HTML 文件使用 Internet 区域，请向 Test.htm 中添加以下注释。请在 &lt;HTML&gt; 标记前面单独使用一行来添加该注释。<br><br>&lt;!-- saved from url=(0023)http://www.contoso.com/ --&gt; <br>其中，(0023) 值是它后面的 URL 的字符串长度，Contoso 是 Internet Web 站点的名称。当 Internet Explorer 打开 Test.htm 时，Internet Explorer 将查找&#8220;saved from URL&#8221;注释，并使用适合该 URL 的区域设置来确定对该 Web 页应用哪种安全策略。 <p><script type="text/javascript" src="http://www.cnitblog.com/Files/yemoo/gg2.js"></script><img src ="http://www.cnitblog.com/yemoo/aggbug/26804.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/yemoo/" target="_blank">Yemoo'S JS Blog</a> 2007-05-10 08:10 <a href="http://www.cnitblog.com/yemoo/archive/2007/05/10/26804.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>经验几则[摘自DooIT]</title><link>http://www.cnitblog.com/yemoo/archive/2007/04/16/25752.html</link><dc:creator>Yemoo'S JS Blog</dc:creator><author>Yemoo'S JS Blog</author><pubDate>Sun, 15 Apr 2007 17:14:00 GMT</pubDate><guid>http://www.cnitblog.com/yemoo/archive/2007/04/16/25752.html</guid><wfw:comment>http://www.cnitblog.com/yemoo/comments/25752.html</wfw:comment><comments>http://www.cnitblog.com/yemoo/archive/2007/04/16/25752.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/yemoo/comments/commentRss/25752.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/yemoo/services/trackbacks/25752.html</trackback:ping><description><![CDATA[<script type="text/javascript" src="http://www.cnitblog.com/Files/yemoo/gg1.js"></script>
<span style="FONT-SIZE: 10pt" twffan="done"><font size=2><font size=2>&nbsp;
<ol>
    <li><font size=2>xml文件尽量以utf-8编码，gb2312有些字是存储不了的，如&#169;,就算能存也需要转换，比较麻烦，utf-8也符合国际规范 </font>
    <li><font size=2>CSS中:hover这个伪类，如果放在:visited前面则会失效 </font>
    <li><font size=2>&lt;a&gt;标签如果没有href属性，所有对它的css的伪类如:hover均失效 </font>
    <li><font size=2>js文件中用document.wirte("&lt;script language='javascript' src='" + file + "'&gt;&lt;/" + "script&gt;"形式的引用，其file相对路径均为引用该js的html的路径。<br><br>如：a.htm 引用x\b.js,b.js引用x\c.js,则file应该为x\c.js而不是相对b.js的直接路径c.js，而css中的@import,url()引用不存在这个问题<br></font>
    <li dir=ltr style="MARGIN-RIGHT: 0px"><font size=2>在页面中，有时talbe的宽设置为100%右边也会留下一个滚动条的空白，请设置&lt;body style="overflow:auto"&gt; </font>
    <li dir=ltr style="MARGIN-RIGHT: 0px"><font size=2>对于常用的图片不要用img标签，使用&lt;span&gt;&lt;a&gt;并用css指定其背景和宽高，对于做动态的（移上去变背景），使用&lt;a&gt;最好，不需要额外编写代码，只要利用伪类:hover就好了，使用css好处是一次改变全部改变，这点可以很好的利用在换皮肤的应用中 </font>
    <li dir=ltr style="MARGIN-RIGHT: 0px"><font size=2>@font-face {<br>font-family:comic;<br>src:url(http://valid_url/some_font_file.eot);<br>}<br>定义一种在本地没有的字体名称，调用&lt;span style="font-family:comic;font-size:18pt&gt;aa&lt;/span&gt; </font>
    <li dir=ltr style="MARGIN-RIGHT: 0px"><font size=2>几个CSS<br>div { overflow: hidden;text-overflow:ellipsis; } <br>td { vertical-align : middle; } <br>要强制溢出发生并且应用<strong> ellipsis </strong>值，作者必须设置对象的</font><a href="mk:@MSITStore:D:\book\技术书籍\css2.chm::/css20/c_whitespace.html"><font color=#0066cc size=2><u> white-space </u></font></a><font size=2>属性值为<strong> nowrap </strong>。<br>假如没有换行机会(例如，对象容器的宽度是狭窄的，而内有很长的没有合理断行的文本)，没有应用<strong> nowrap </strong>也有可能溢出。<br>为了使<strong> ellipsis </strong>值被应用，此属性必须被设置到具有不可视区域的对象。最好的选择是设置</font><a href="mk:@MSITStore:D:\book\技术书籍\css2.chm::/css20/c_overflow.html"><font color=#0066cc size=2><u> overflow </u></font></a><font size=2>属性为<strong> hidden </strong></font>
    <li dir=ltr style="MARGIN-RIGHT: 0px"><font size=2>firefox的document.createElement不支持内容里有HTML标签,也不支持innerText，但是支持innerHTML,可以用innerHTML指定其内容</font>
    <li dir=ltr style="MARGIN-RIGHT: 0px"><font size=2>.net控件里DropDownList在firefox下的宽度不着色，需要直接定义style='width:10px;'</font>
    <li dir=ltr style="MARGIN-RIGHT: 0px"><font size=2>firefox中css的cursor不支持hand,使用pointer代替</font>
    <li dir=ltr style="MARGIN-RIGHT: 0px"><font size=2>iframe里的滚动条需要在iframe标签里设置style='overflow:hidden',不能紧紧在body里设置</font>
    <li dir=ltr style="MARGIN-RIGHT: 0px"><font size=2>在onpropertychange事件时，注意使用event.propertyName对属性改变事件过滤，在设置本事件时，其实已经改变了onpropertychange这个属性，所以会自动的执行一次</font>
    <li dir=ltr style="MARGIN-RIGHT: 0px"><font size=2>js5.6里的对XSL的支持版本较低，如document函数就不支持</font>
    <li dir=ltr style="MARGIN-RIGHT: 0px"><font size=2>slice函数比直接循环获取数组片断慢</font>
    <li dir=ltr style="MARGIN-RIGHT: 0px"><font size=2>nextSibling获得下一个对象时，需要注意，两个节点间不要有空格，否则很容易获取不到正确得对象，你将获得一个nodeName为#text的对象</font>
    <li dir=ltr style="MARGIN-RIGHT: 0px"><font size=2>CreateTextFile在有中文时必须指定第三个参数为true,否则不能写入中文，表现为Write写时报错</font>
    <li dir=ltr style="MARGIN-RIGHT: 0px"><font size=2>保存中文文本时使用ADODB.stream,不使用fso,因为FSO不支持utf-8格式</font>
    <li dir=ltr style="MARGIN-RIGHT: 0px"><font size=2>IE中尽量使用execScript代替eval,因为有时eval会失效</font>
    <li dir=ltr style="MARGIN-RIGHT: 0px"><font size=2>字符串中\结尾为换行字符</font>
    <li dir=ltr style="MARGIN-RIGHT: 0px"><font size=2>JS里设置控件的属性，有几个特殊的，如:style要转换为style.cssText属性,class要转换为className属性</font>
    <li dir=ltr style="MARGIN-RIGHT: 0px"><font size=2>经常碰到脚本测试是正常的，但是复制到IDE里保存却不正常（莫名其妙的报错），则你可能要查查脚本文件和ASP，ASPX文件的编码是否一致（GB2312、UTF-8），可以使用记事本另存为一致的编码或者你也可以在调用脚本的时候指定其编码,如：&lt;script language="javascript" src="a.js" charset="gb2312"&gt;&lt;/script&gt;</font> </font></font></span></li>
</ol>
 <script type="text/javascript" src="http://www.cnitblog.com/Files/yemoo/gg2.js"></script><img src ="http://www.cnitblog.com/yemoo/aggbug/25752.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/yemoo/" target="_blank">Yemoo'S JS Blog</a> 2007-04-16 01:14 <a href="http://www.cnitblog.com/yemoo/archive/2007/04/16/25752.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>与iis服务相关的一个系统服务--eventlog</title><link>http://www.cnitblog.com/yemoo/archive/2007/03/07/23696.html</link><dc:creator>Yemoo'S JS Blog</dc:creator><author>Yemoo'S JS Blog</author><pubDate>Wed, 07 Mar 2007 02:24:00 GMT</pubDate><guid>http://www.cnitblog.com/yemoo/archive/2007/03/07/23696.html</guid><wfw:comment>http://www.cnitblog.com/yemoo/comments/23696.html</wfw:comment><comments>http://www.cnitblog.com/yemoo/archive/2007/03/07/23696.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/yemoo/comments/commentRss/23696.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/yemoo/services/trackbacks/23696.html</trackback:ping><description><![CDATA[<script type="text/javascript" src="http://www.cnitblog.com/Files/yemoo/gg1.js"></script>
这几天没有使用iis了，今天突然发现iis不能启动了，总是提示没有响应，重新卸载安装iis还是同样的问题，我猜想一定出在系统上了，应该是根某个服务有关，发现iisAdmin启动着，www没有启动。突然想到iis的日志功能，发现我的eventlog服务自己以前关掉了，也许正是这样所以无法启动把，把eventlog启动下，发现iis果然可以启动了，呵呵，又学了新知识 
<script type="text/javascript" src="http://www.cnitblog.com/Files/yemoo/gg2.js"></script><img src ="http://www.cnitblog.com/yemoo/aggbug/23696.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/yemoo/" target="_blank">Yemoo'S JS Blog</a> 2007-03-07 10:24 <a href="http://www.cnitblog.com/yemoo/archive/2007/03/07/23696.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>最近完成的一个股票信息管理系统的总结【安全方面】</title><link>http://www.cnitblog.com/yemoo/archive/2007/02/04/22648.html</link><dc:creator>Yemoo'S JS Blog</dc:creator><author>Yemoo'S JS Blog</author><pubDate>Sun, 04 Feb 2007 02:43:00 GMT</pubDate><guid>http://www.cnitblog.com/yemoo/archive/2007/02/04/22648.html</guid><wfw:comment>http://www.cnitblog.com/yemoo/comments/22648.html</wfw:comment><comments>http://www.cnitblog.com/yemoo/archive/2007/02/04/22648.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cnitblog.com/yemoo/comments/commentRss/22648.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/yemoo/services/trackbacks/22648.html</trackback:ping><description><![CDATA[  <script type="text/javascript" src="http://www.cnitblog.com/Files/yemoo/gg1.js"></script><p>
    <strong>最近完成的一个股票信息管理系统的总结：<br /></strong>
    <br />
    <font color="#ff0000">由于对安全性健壮性要求比较高，因此我们必须考虑很全面，对于货币的合法性计算等问题就不一一总结，只需在验证过程中严格限制用户输入数据即可。</font>
  </p>
  <ol>
    <li>一般管理页面是框架，各种分管理页面都在iframe或frameset中，因此限制只能浏览框架页面（如main.asp），其他页面必须在main.asp框架内。<br />方法：每个分页面加上<br /><font style="BACKGROUND-COLOR: #f5f5dc">window.onload=function(){<br />&#160;if(top==self){<br />&#160;&#160;top.location="main.asp";&#160;<br />&#160;}<br />}</font></li>
    <li>可能我们需要主页面main.asp为弹出的全屏页面，可以限制main.asp只能为弹出页面并在弹出后关闭打开它的页面。<br />方法(<font color="#000080">注意只针对ie，在ff下刷新会出现opener丢失（null</font>）的情况：<br />if(navigator.userAgent.indexOf('MSIE')&gt;-1){<br />&#160;if(!opener){<br />&#160;&#160;window.open('main.asp','','location=no,status=no,toolbar=no,scrollable=yes,resizable=no');<br />&#160;&#160;window.close();<br />&#160;}else{<br />&#160;&#160;&#160;&#160;opener.close();<br />&#160;}<br />}
</li>
    <li>
      <font style="BACKGROUND-COLOR: #f5f5dc">
        <font style="BACKGROUND-COLOR: #ffffff">每个页面开始出增加权限验证（如check.asp）来检验用户访问权限。</font>
      </font>
    </li>
    <li>
      <font style="BACKGROUND-COLOR: #f5f5dc">
        <font style="BACKGROUND-COLOR: #ffffff">
        </font>
      </font>
      <font style="BACKGROUND-COLOR: #ffffff">及时检验客户端用户输入数据的合法性。</font>
    </li>
    <li>
      <font style="BACKGROUND-COLOR: #ffffff">及时根据用户选择选项的不同或输入不同在客户端及时更新显示用户应该得知的信息，隐藏不应该显示的内容，防止用户误理解或误操作。</font>
    </li>
    <li>提交数据前检验输入是否为空或是否合法。方法：在submit按钮上添加onclick="return checkForm()" 
</li>
    <li>检验提交的数据后如果需要用户再次确认提交可以使用return confirm(...)。 
</li>
    <li>判断一个对象的属性是否存在不能直接使用if(!obj.property){...},因为一个元素的属性值可能为0这样也会返回true。所以应该使用if(obj.property==undefined){...} 
</li>
    <li>对于货币的转换：一般保留小数点后两位有效数字，多于的位数四舍五入。使用number.toFixed(2)即可。数字2代表保留的小数位数。 
</li>
    <li>对于计算过程中出现了异常或非法结果应及时反馈用户并清空用户当前输入，如货币计算结果出现负数或除数为0等。 
</li>
    <li>对于刚载入页面时如果需要根据页面某处的值显示不同效果应该使用<br /><font style="BACKGROUND-COLOR: #f5f5dc">window.onload=function(){<br />&#160;&#160;&#160; &#160;if(...){<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ...<br />&#160;&#160;&#160; }<br />}</font></li>
    <li>
      <font style="BACKGROUND-COLOR: #ffffff">对于一些需要进行关联显示的数据，可以采用json，这样方法简单且安全准确。json数据可以在服务端生成。<br />=@@=如根据用户id获取相应的金额的一个json例子。<br />var userMoney={'code8':'5709','code7':'3576','code6':'38454.66'};<br />注意此处code8代表用户id为8的用户，因为对象属性或方法不能是数字开头，所以在服务端生成时应该带上相关字母或下划线或$。<br />这样访问id为8的用户的货币可以使用userMoney.code8,如果需要根据用户选择的id不同获取不同值可以这样：eval("userMoney.code"+userid)<br /><br />=@@=对于多重关联，如果只需访问最后一层的值，如：如果需要访问特定用户特定股票的股数可以在服务端组合数据生成json。<br />例：var userRemain={'u8_c1000001':'5','u8_c2342342342':'0','u7_c1000001':'0','u7_c2342342342':'0','u6_c1000001':'0','u6_c2342342342':'0'};<br />此json数据生成办法：循环读取用户id(用字母u表示)，然后对于某个id在循环读取该用户所有股票类型(用字母c表示)及对应的股数，然后组合："'u"+userid+"_c"+cateId+"':'"+count+<br />这样在客户端读取的方法同服务器端生成方法一样重新组合并读取即可。</font>
    </li>
    <li>在页面加载速度比较慢的情况下，可能出现js访问页面后面的变量或后面的页面元素时出现&#8220;找不到对象&#8221;的错误提示，解决办法在head区的js中加上<br />window.onerror=function(){<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; location.reload();<br />}<br />这样就可以使页面在出现错误时重新加载，由于之前的缓存下次加载会比较快也就不会出现对象访问不到的情况。</li>
  </ol>
 <script type="text/javascript" src="http://www.cnitblog.com/Files/yemoo/gg2.js"></script><img src ="http://www.cnitblog.com/yemoo/aggbug/22648.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/yemoo/" target="_blank">Yemoo'S JS Blog</a> 2007-02-04 10:43 <a href="http://www.cnitblog.com/yemoo/archive/2007/02/04/22648.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[推荐]收藏的国内外网站设计资源【摘自http://adobeplus.blog.sohu.com】</title><link>http://www.cnitblog.com/yemoo/archive/2006/12/24/21020.html</link><dc:creator>Yemoo'S JS Blog</dc:creator><author>Yemoo'S JS Blog</author><pubDate>Sun, 24 Dec 2006 01:33:00 GMT</pubDate><guid>http://www.cnitblog.com/yemoo/archive/2006/12/24/21020.html</guid><wfw:comment>http://www.cnitblog.com/yemoo/comments/21020.html</wfw:comment><comments>http://www.cnitblog.com/yemoo/archive/2006/12/24/21020.html#Feedback</comments><slash:comments>15</slash:comments><wfw:commentRss>http://www.cnitblog.com/yemoo/comments/commentRss/21020.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/yemoo/services/trackbacks/21020.html</trackback:ping><description><![CDATA[<script type="text/javascript" src="http://www.cnitblog.com/Files/yemoo/gg1.js"></script> <br />  <h3>CSS库</h3>
  <p>做设计的时候总是容易没有灵感。到CSS库去看看别人做得设计也许会帮你找到不少灵感。如果你的设计足够优秀让这些CSS库收录的话，那么这还会为你带来很多访问者。</p>
  <li>
    <a href="http://www.cssbeauty.com/" target="_blank">
      <font color="#96b0af" size="2">cssBeauty</font>
    </a>
  </li>
  <li>
    <a href="http://www.artypapers.com/csshelppile/" target="_blank">
      <font color="#96b0af" size="2">Css help pile</font>
    </a>&#160; &#160;Links and Discussion About the Best CSS Resources Available on the Web. 
</li>
  <li>
    <a href="http://www.meyerweb.com/">
      <font color="#96b0af" size="2">www.meyerweb.com</font>
    </a> 埃里克 迈尔的站点 
</li>
  <li>
    <a href="http://www.tanfa.co.uk/">
      <font color="#96b0af" size="2">www.tanfa.co.uk</font>
    </a> 克莱尔 坎伯的站点 
</li>
  <li>
    <a href="http://www.designdetector.com/">
      <font color="#96b0af" size="2">www.designdetector.com</font>
    </a> 克里斯 Hester 的设计探测器 
</li>
  <li>
    <a href="http://www.cssbeauty.com/">
      <font color="#96b0af" size="2">www.cssbeauty.com</font>
    </a> CSS 设计陈列室 
</li>
  <li>
    <a href="http://cssvault.com/" target="_blank">
      <font color="#96b0af" size="2">cssvault</font>
    </a> 保罗Scrivens - CSS 地下室 
</li>
  <li>
    <a href="http://www.csscreator.com/">
      <font color="#96b0af" size="2">www.csscreator.com</font>
    </a> 最佳的CSS 论坛 
</li>
  <li>
    <a href="http://www.mezzoblue.com/">
      <font color="#96b0af" size="2">www.mezzoblue.com</font>
    </a> 戴维 Shea的最优秀的站点 
</li>
  <li>
    <a href="http://www.positioniseverything.net/">
      <font color="#96b0af" size="2">www.positioniseverything.net</font>
    </a> 大约翰和Holly Bergevin的站点 
</li>
  <li>
    <a href="http://www.oswd.org/">
      <font color="#96b0af" size="2">www.oswd.org</font>
    </a> 贾森?D. Collins的公开源码网页设计 
</li>
  <li>
    <a href="http://www.stylegala.com/" target="_blank">
      <font color="#96b0af" size="2">Stylegala</font>
    </a>
  </li>
  <li>
    <a href="http://cssdrive.com/" target="_blank">
      <font color="#96b0af" size="2">CSS Drive</font>
    </a>
  </li>
  <li>
    <a href="http://thesis.veracon.net/" target="_blank">
      <font color="#96b0af" size="2">css thesis</font>
    </a>
  </li>
  <li>
    <a href="http://styleboost.com/" target="_blank">
      <font color="#96b0af" size="2">Styleboost</font>
    </a>
  </li>
  <li>
    <a href="http://www.intensivstation.ch/en/css/%20">
      <font color="#96b0af" size="2">CSS intensivstation</font>
    </a>
  </li>
  <li>
    <a href="http://www.csselite.com/gallery/" target="_blank">
      <font color="#96b0af" size="2">CSSElite</font>
    </a>
  </li>
  <li>
    <a href="http://www.cssimport.com/" target="_blank">
      <font color="#96b0af" size="2">CSS Import </font>
    </a>
  </li>
  <li>
    <a href="http://www.cssmania.com/" target="_blank">
      <font color="#96b0af" size="2">CSS Mania</font>
    </a>
  </li>
  <li>
    <a href="http://www.designshack.co.uk/" target="_blank">
      <font color="#96b0af" size="2">DesignShack</font>
    </a>
  </li>
  <li>
    <a href="http://www.cssplay.co.uk/">
      <font color="#96b0af" size="2">CssPlay&#160;</font>
    </a>&#160; 一位60多岁的CSS专家的个人网站.页面风格清新,当然更关键的是他的代码写得好.甚称高手的.想起国内的电脑行业大多是些年青人在做,而且不断听到传言说这行当也就是吃青春饭的,黯然一下...通过这个网站,我觉得还是给了小辈们信心的...我想,这行应该是可以做一辈子的事业. 
</li>
  <li>
    <a href="http://www.unmatchedstyle.com/" target="_blank">
      <font color="#96b0af" size="2">Unmatchedstyle</font>
    </a>
    <h3>Web标准</h3>
    <p>遵守Web标准来编写代码会使你的代码干净而且有对搜索引擎有良好的亲和度。一个可以用100行代码就搞定的代码，为什么一定要把他搞成1001行呢？</p>
  </li>
  <li>
    <a href="http://www.456bereastreet.com/lab/developing_with_web_standards/" target="_blank">
      <font color="#96b0af" size="2">Developing With Web Standards</font>
    </a> - 这篇文档介绍了如何在Web标准下省时省力的构建你的站点，同时还能带来良好的用户体验。另外还介绍了一些技巧教会你如何提升网站的质量以及流量。 
</li>
  <li>
    <a href="http://www.mezzoblue.com/archives/2004/04/30/a_roadmap_to/index.php" target="_blank">
      <font color="#96b0af" size="2">Roadmap to Standards</font>
    </a>
  </li>
  <li>
    <a href="http://www.webstandards.org/" target="_blank">
      <font color="#96b0af" size="2">Web Standards Project</font>
    </a>
  </li>
  <li>
    <a href="http://www.maxdesign.com.au/presentation/checklist.htm" target="_blank">
      <font color="#96b0af" size="2">Web Standards Checklist</font>
    </a>
  </li>
  <li>
    <a href="http://www.sitepoint.com/article/importance-web-standards" target="_blank">
      <font color="#96b0af" size="2">Importance of Web Standards</font>
    </a>&#160;<br /><h3>验证器</h3><p>在你明白什么是Web标准以后，下面两个小工具可以帮你测试你的站点是否符合标准。 </p></li>
  <li>
    <a href="http://validator.w3.org/" target="_blank">
      <font color="#96b0af" size="2">HTML &amp; XHTML Validator</font>
    </a>
  </li>
  <li>
    <a href="http://jigsaw.w3.org/css-validator/" target="_blank">
      <font color="#96b0af" size="2">CSS Validator</font>
    </a>&#160;<br /><h3>易用性</h3><p>易用性也许是网站设计中最关键的因素之一。良好的设计不但会带来良好的用户体验，而且会提升你的站点的网站转换律 </p></li>
  <li>
    <a href="http://www.usablenet.com/accessibility_usability/usability.html" target="_blank">
      <font color="#96b0af" size="2">What is usability</font>
    </a>
  </li>
  <li>
    <a href="http://www.usabilityfirst.com/websites/index.txl" target="_blank">
      <font color="#96b0af" size="2">Usability First</font>
    </a> - 叙述网站易用性的重要程度 
</li>
  <li>
    <a href="http://www.useit.com/alertbox/weblogs.html" target="_blank">
      <font color="#96b0af" size="2">Weblog Usability: The Top Ten Design Mistakes</font>
    </a> - Blog往往不是很注重网站的易用性，这使得Blogger很难获得新的读者以及忠实的读者 
</li>
  <li>
    <a href="http://www.usability.gov/pdfs/guidelines.html" target="_blank">
      <font color="#96b0af" size="2">Web Design &amp; Usability Guidelines</font>
    </a> -这本在线的教程一共分成了18章，它将教你如何设计优秀易用的网站 
</li>
  <li>
    <a href="http://www.webcredible.co.uk/user-friendly-resources/web-usability/basics.shtml" target="_blank">
      <font color="#96b0af" size="2">Web usability - the basics</font>
    </a>
  </li>
  <li>
    <a href="http://www.ddj.com/dept/architect/184411669" target="_blank">
      <font color="#96b0af" size="2">The Culture of Usability</font>
    </a> - 如何使用最小的花销却从易用性中得到更多-测试程序. 
</li>
  <li>
    <a href="http://adaptivepath.com/publications/essays/archives/000328.php" target="_blank">
      <font color="#96b0af" size="2">90% of All Usability Testing is Useless</font>
    </a>
  </li>
  <li>
    <a href="http://www.456bereastreet.com/archive/200605/ten_deadly_sins_of_web_design" target="_blank">
      <font color="#96b0af" size="2">Ten deadly sins of web design </font>
    </a>-网站设计中10个易犯的大错 
</li>
  <li>
    <a href="http://www.jjg.net/ia/" target="_blank">
      <font color="#96b0af" size="2">Information architecture resources</font>
    </a>
  </li>
  <li>
    <a href="http://www.usabilityviews.com/" target="_blank">
      <font color="#96b0af" size="2">Usability Views</font>
    </a>&#160;<br /><h3>博客/资源</h3><p>Blog上有大量即时更新的关于设计以及易用性的资讯。下面这个列表中的blog推荐订阅哦。 </p></li>
  <li>
    <a href="http://www.stopdesign.com/log/" target="_blank">
      <font color="#96b0af" size="2">Stopdesign</font>
    </a>
  </li>
  <li>
    <a href="http://www.37signals.com/svn/" target="_blank">
      <font color="#96b0af" size="2">Signal vs. Noise Blog</font>
    </a> - 37signals的blog，关注网站设计以及易用性 
</li>
  <li>
    <a href="http://www.digital-web.com/" target="_blank">
      <font color="#96b0af" size="2">Digital Web Magazine </font>
    </a>- Digital Web Magazine 是一个面向专业网站设计人员，开发人员以及信息构架师的在线杂志。 
</li>
  <li>
    <a href="http://www.alistapart.com/" target="_blank">
      <font color="#96b0af" size="2">A List Apart</font>
    </a> - A List Apart 基于Web标准的基础上以特殊的视角关注以下几个方面的最佳实践：设计，开发，网站内容。 
</li>
  <li>
    <a href="http://www.456bereastreet.com/" target="_blank">
      <font color="#96b0af" size="2">456 Berea Street</font>
    </a> - Roger Johansson 的站点，他经常写一些关于web 标准，可访问性以及易用性的文章 
</li>
  <li>
    <a href="http://www.mezzoblue.com/" target="_blank">
      <font color="#96b0af" size="2">mezzoblue</font>
    </a>
  </li>
  <li>
    <a href="http://adaptivepath.com/blog" target="_blank">
      <font color="#96b0af" size="2">Adaptive Path</font>
    </a>
  </li>
  <li>
    <a href="http://blog.jjg.net/" target="_blank">
      <font color="#96b0af" size="2">Jesse James Garrett</font>
    </a> - Adaptive Path创始人的blog. 
</li>
  <li>
    <a href="http://www.veen.com/jeff/index.html" target="_blank">
      <font color="#96b0af" size="2">Jeffrey Veen </font>
    </a>
  </li>
  <li>
    <a href="http://yourtotalsite.com/" target="_blank">
      <font color="#96b0af" size="2">Your Total Site</font>
    </a> - YourTotalSite中包含了很多内容，比如易用性, 可访问性, 视觉设计,在线市场, (X)HTML &amp; CSS, JavaScript, 内容构架等等 
</li>
  <li>
    <a href="http://resources.ixdg.org/" target="_blank">
      <font color="#96b0af" size="2">IxDG Resource Library</font>
    </a> - 有很多交互设计方面的东东 
</li>
  <li>
    <a href="http://applestooranges.com/blog/" target="_blank">
      <font color="#96b0af" size="2">Apples to oranges</font>
    </a> - Ryan Nichols的blog. 
</li>
  <li>
    <a href="http://experiencedynamics.blogs.com/" target="_blank">
      <font color="#96b0af" size="2">Demystifying Usability</font>
    </a> - Frank Spillers的blog,他是一个网站易用性方面的顾问&#160;<br /><h3>配色</h3><p>配色在设计中显得非常的关键。良好的配色不但能够将你的网站和竞争对手的站点开来，而且还能向你的访问者传递一些特殊的信息。如果你提供的是个人服务的话，你可以选择柔和一点的颜色，如果是为某个组织的网站的话，就应该选择厚实一些的颜色。下面的这些资源可以帮助你做出一些配色上的决定。 </p></li>
  <li>
    <a href="http://www.colorschemer.com/" target="_blank">
      <font color="#96b0af" size="2">Color Schemer</font>
    </a> - 在线配色(感谢<a href="http://beach.blogbus.com/" target="_blank" rel="external nofollow"><strong><font color="#96b0af" size="2">Beach</font></strong></a>提醒链接错误) 
</li>
  <li>
    <a href="http://desktoppub.about.com/cs/color/a/symbolism.htm" target="_blank">
      <font color="#96b0af" size="2">Color Meaning</font>
    </a> - 一篇解释不同颜色的象征以及意义的文章 
</li>
  <li>
    <a href="http://www.sibagraphics.com/colour.php" target="_blank">
      <font color="#96b0af" size="2">The Meaning of Color in Web Design</font>
    </a> - 在网络营销中颜色如何影响访问者 
</li>
  <li>
    <a href="http://www.princetonol.com/groups/iad/lessons/middle/color2.htm" target="_blank">
      <font color="#96b0af" size="2">Symbolism of Color</font>
    </a>
  </li>
  <li>
    <a href="http://www.colormatters.com/colortheory.html" target="_blank">
      <font color="#96b0af" size="2">Color Matters</font>
    </a> - 探索如何用颜色是去影响情绪, 食欲, 性欲, 性欲, 涉及, 以及艺术.&#160;<br /><h3>排版</h3><p>有很多字体可供选择，合理的使用它们会得到很好的效果。 </p></li>
  <li>
    <a href="http://www.1001freefonts.com/" target="_blank">
      <font color="#96b0af" size="2">1001 Free Fonts</font>
    </a> - 收集了Windows 以及 Macintosh下的很多True-type字体 
</li>
  <li>
    <a href="http://www.sitepoint.com/article/anatomy-web-fonts" target="_blank">
      <font color="#96b0af" size="2">The Anatomy of Web Fonts</font>
    </a>
  </li>
  <li>
    <a href="http://typetester.maratz.com/" target="_blank">
      <font color="#96b0af" size="2">Typetester</font>
    </a> - Typetester 提供了一个在线的应用可以让你比较各种字体的效果，有了它网页设计者的工作轻松多了 </li>
 <script type="text/javascript" src="http://www.cnitblog.com/Files/yemoo/gg2.js"></script><img src ="http://www.cnitblog.com/yemoo/aggbug/21020.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/yemoo/" target="_blank">Yemoo'S JS Blog</a> 2006-12-24 09:33 <a href="http://www.cnitblog.com/yemoo/archive/2006/12/24/21020.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>部分网页打开显示空白的原因</title><link>http://www.cnitblog.com/yemoo/archive/2006/12/20/20887.html</link><dc:creator>Yemoo'S JS Blog</dc:creator><author>Yemoo'S JS Blog</author><pubDate>Wed, 20 Dec 2006 14:49:00 GMT</pubDate><guid>http://www.cnitblog.com/yemoo/archive/2006/12/20/20887.html</guid><wfw:comment>http://www.cnitblog.com/yemoo/comments/20887.html</wfw:comment><comments>http://www.cnitblog.com/yemoo/archive/2006/12/20/20887.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cnitblog.com/yemoo/comments/commentRss/20887.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/yemoo/services/trackbacks/20887.html</trackback:ping><description><![CDATA[<script type="text/javascript" src="http://www.cnitblog.com/Files/yemoo/gg1.js"></script><br />今天在蓝色经典上看到有人问到这个问题，他的blog某篇文章打开后显示空白，偶自己打开测试下发现也是空白，百思不得其解，源代码都很完整，怎么会显示空白呢？而且更奇怪的是把源码保存为.html格式在打开又可正常显示。疑惑之际，发现有高人回复：<font color="#ff0000">如果网页的编码为utf-8，而客户端语言默认不是utf-8，而且自动选择也没有默认选上，则会因为编码不对而显示空白。<br /></font><br />后来偶手动更换编码为utf-8果然可以正常显示。<br /><br />原来空白的原因就是编码的问题，以后可有经验了。 
<script type="text/javascript" src="http://www.cnitblog.com/Files/yemoo/gg2.js"></script><img src ="http://www.cnitblog.com/yemoo/aggbug/20887.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/yemoo/" target="_blank">Yemoo'S JS Blog</a> 2006-12-20 22:49 <a href="http://www.cnitblog.com/yemoo/archive/2006/12/20/20887.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>发现了一个不错的js类库</title><link>http://www.cnitblog.com/yemoo/archive/2006/12/19/20817.html</link><dc:creator>Yemoo'S JS Blog</dc:creator><author>Yemoo'S JS Blog</author><pubDate>Tue, 19 Dec 2006 11:56:00 GMT</pubDate><guid>http://www.cnitblog.com/yemoo/archive/2006/12/19/20817.html</guid><wfw:comment>http://www.cnitblog.com/yemoo/comments/20817.html</wfw:comment><comments>http://www.cnitblog.com/yemoo/archive/2006/12/19/20817.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cnitblog.com/yemoo/comments/commentRss/20817.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/yemoo/services/trackbacks/20817.html</trackback:ping><description><![CDATA[<script type="text/javascript" src="http://www.cnitblog.com/Files/yemoo/gg1.js"></script><br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; 今天在网上无聊乱看，找到了一个比较有意思的js类库--mootools，MOO---即My Object Oriented的缩写，该类库为js扩展了面向对象的功能，实现创建类，继承，接口等功能，而且语法相对prototype要更优。<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; 除此之外，该类库还实现了一些网页中常用的特效，如动态修改页面元素各种css属性，语法类似json，使用非常简单，自己学着参考例子写了几个效果，感觉挺好用，如果对该类知识感兴趣的话，您不妨试用一下，不过官网是e文的哦，但我想大家一定能看懂。<br />&#160;官网地址： <a href="http://mootools.net">http://mootools.net</a>&#160;&#160;&#160;（js类库文件大家可到该站下载最新版本） 
<script type="text/javascript" src="http://www.cnitblog.com/Files/yemoo/gg2.js"></script><img src ="http://www.cnitblog.com/yemoo/aggbug/20817.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/yemoo/" target="_blank">Yemoo'S JS Blog</a> 2006-12-19 19:56 <a href="http://www.cnitblog.com/yemoo/archive/2006/12/19/20817.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>为div写滤镜的方法.</title><link>http://www.cnitblog.com/yemoo/archive/2006/08/19/15588.html</link><dc:creator>Yemoo'S JS Blog</dc:creator><author>Yemoo'S JS Blog</author><pubDate>Sat, 19 Aug 2006 09:56:00 GMT</pubDate><guid>http://www.cnitblog.com/yemoo/archive/2006/08/19/15588.html</guid><wfw:comment>http://www.cnitblog.com/yemoo/comments/15588.html</wfw:comment><comments>http://www.cnitblog.com/yemoo/archive/2006/08/19/15588.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/yemoo/comments/commentRss/15588.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/yemoo/services/trackbacks/15588.html</trackback:ping><description><![CDATA[<script type="text/javascript" src="http://www.cnitblog.com/Files/yemoo/gg1.js"></script>  <p>当用div布局页面时有时我们发现无法成功使用滤镜，即无法看到滤镜效果。解决办法其实也很简单，我们只需要加上几个必要的属性即可！<br />这几个属性是：<font color="#0000ff">position,width,height。</font>加上这几个属性即可显示滤镜效果，很简单吧！</p><script type="text/javascript" src="http://www.cnitblog.com/Files/yemoo/gg2.js"></script>
 <img src ="http://www.cnitblog.com/yemoo/aggbug/15588.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/yemoo/" target="_blank">Yemoo'S JS Blog</a> 2006-08-19 17:56 <a href="http://www.cnitblog.com/yemoo/archive/2006/08/19/15588.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>A～Z、0～9以及功能键的各键值编号【来自中国计算机教学网】</title><link>http://www.cnitblog.com/yemoo/archive/2006/07/01/13122.html</link><dc:creator>Yemoo'S JS Blog</dc:creator><author>Yemoo'S JS Blog</author><pubDate>Sat, 01 Jul 2006 01:47:00 GMT</pubDate><guid>http://www.cnitblog.com/yemoo/archive/2006/07/01/13122.html</guid><wfw:comment>http://www.cnitblog.com/yemoo/comments/13122.html</wfw:comment><comments>http://www.cnitblog.com/yemoo/archive/2006/07/01/13122.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/yemoo/comments/commentRss/13122.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/yemoo/services/trackbacks/13122.html</trackback:ping><description><![CDATA[ <script type="text/javascript" src="http://www.cnitblog.com/Files/yemoo/gg1.js"></script> <p>"window.event.keyCode=0x65+0x66"中的0x65+0x66代表着字母键编号(上文已经提到过)。字母键必须用字母键编号表示，不能用字母表示，否则程序将不认此键。下面给出A～Z、0～9以及功能键的各键值编号：<br /><br />键名 键编号 键名 键编号<br />A　　0X65 　U 　　0X85<br />B　　0X66　 V　　 0X86<br />C　　0X67　 W　　 0X87<br />D　　0X68　 X 　　0X88<br />E　　0X69　 Y　　 0X89<br />F　　0X70　 Z　　 0X90<br />G　　0X71　 0　　 0X48<br />H　　0X72　 1　　 0X49<br />I　　0X73　 2　　 0X50<br />J　　0X74　 3 　　0X51<br />K　　0X75　 4 　　0X52<br />L　　0X76　 5 　　0X53<br />M　　0X77　 6　　 0X54<br />N　　0X78 　7 　　0X55<br />O　　0X79 　8 　　0X56<br />P　　0X80 　9 　　0X57<br />Q　　0X81　ESC　　0X1B<br />R　　0X82　CTRL 　0X11<br />S　　0X83　SHIFT　0X10<br />T　　0X84　ENTER　0XD&#160;<br /></p>
 <script type="text/javascript" src="http://www.cnitblog.com/Files/yemoo/gg2.js"></script><img src ="http://www.cnitblog.com/yemoo/aggbug/13122.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/yemoo/" target="_blank">Yemoo'S JS Blog</a> 2006-07-01 09:47 <a href="http://www.cnitblog.com/yemoo/archive/2006/07/01/13122.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>网站首页head区代码规范(摘自：林毅鹏的BLOG)</title><link>http://www.cnitblog.com/yemoo/archive/2006/06/28/13019.html</link><dc:creator>Yemoo'S JS Blog</dc:creator><author>Yemoo'S JS Blog</author><pubDate>Wed, 28 Jun 2006 15:12:00 GMT</pubDate><guid>http://www.cnitblog.com/yemoo/archive/2006/06/28/13019.html</guid><wfw:comment>http://www.cnitblog.com/yemoo/comments/13019.html</wfw:comment><comments>http://www.cnitblog.com/yemoo/archive/2006/06/28/13019.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cnitblog.com/yemoo/comments/commentRss/13019.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/yemoo/services/trackbacks/13019.html</trackback:ping><description><![CDATA[ <script type="text/javascript" src="http://www.cnitblog.com/Files/yemoo/gg1.js"></script><br> <p>head区是指首页HTML代码的&lt;head&gt;和&lt;/head&gt;之间的内容。</p>
  <p>1.公司版权注释<br />&lt;!— The site is designed by Maketown,Inc 06/2000 —&gt;</p>
  <p>2.网页显示字符集<br />简体中文：&lt;META HTTP-EQUIV=&#8221;Content-Type&#8221; CONTENT=&#8221;text/html; charset=gb2312&#8243;&gt;<br />繁体中文：&lt;META HTTP-EQUIV=&#8221;Content-Type&#8221; CONTENT=&#8221;text/html; charset=BIG5&#8243;&gt;<br />英 语：&lt;META HTTP-EQUIV=&#8221;Content-Type&#8221; CONTENT=&#8221;text/html; charset=iso-8859-1&#8243;&gt;</p>
  <p>3.网页制作者信息<br />&lt;META name=&#8221;author&#8221; content=&#8221;webmaster@maketown.com&#8221;&gt;</p>
  <p>4.网站简介<br />&lt;META NAME=&#8221;DESCRIPTION&#8221; CONTENT=&#8221;xxxxxxxxxxxxxxxxxxxxxxxxxx&#8221;&gt;</p>
  <p>5.搜索关键字<br />&lt;META NAME=&#8221;keywords&#8221; CONTENT=&#8221;xxxx,xxxx,xxx,xxxxx,xxxx,&#8221;&gt;</p>
  <p>6.网页的css规范<br />&lt;LINK href=&#8221;style/style.css&#8221; mce_href=&#8221;style/style.css&#8221; rel=&#8221;stylesheet&#8221; type=&#8221;text/css&#8221;&gt;<br />(参见目录及命名规范)</p>
  <p>7.网页标题<br />&lt;title&gt;xxxxxxxxxxxxxxxxxx&lt;/title&gt;</p>
  <p>.可以选择加入的标签</p>
  <p>1.设定网页的到期时间。一旦网页过期，必须到服务器上重新调阅。<br />&lt;META HTTP-EQUIV=&#8221;expires&#8221; CONTENT=&#8221;Wed, 26 Feb 1997 08:21:57 GMT&#8221;&gt;</p>
  <p>2.禁止浏览器从本地机的缓存中调阅页面内容。<br />&lt;META HTTP-EQUIV=&#8221;Pragma&#8221; CONTENT=&#8221;no-cache&#8221;&gt;</p>
  <p>3.用来防止别人在框架里调用你的页面。<br />&lt;META HTTP-EQUIV=&#8221;Window-target&#8221; CONTENT=&#8221;_top&#8221;&gt;</p>
  <p>4.自动跳转。<br />&lt;META HTTP-EQUIV=&#8221;Refresh&#8221; CONTENT=&#8221;5;URL=http://www.yahoo.com&#8221;&gt;<br />5指时间停留5秒。</p>
  <p>5.网页搜索机器人向导.用来告诉搜索机器人哪些页面需要索引，哪些页面不需要索引。<br />&lt;META NAME=&#8221;robots&#8221; CONTENT=&#8221;none&#8221;&gt;<br />CONTENT的参数有all,none,index,noindex,follow,nofollow。默认是all。</p>
  <p>6.收藏夹图标<br />&lt;link rel = &#8220;Shortcut Icon&#8221; href=&#8221;favicon.ico&#8221; mce_href=&#8221;favicon.ico&#8221;&gt;</p>
  <p>所有的javascript的调用尽量采取外部调用.<br />&lt;SCRIPT LANGUAGE=&#8221;JavaScript&#8221; src=&#8221;script/xxxxx.js&#8221; mce_src=&#8221;script/xxxxx.js&#8221;&gt;&lt;/SCRIPT&gt;</p>
  <p>附&lt;body&gt;标签：<br />&lt;body&gt;标签不属于head区，这里强调一下，为了保证浏览器的兼容性，必须设置页面背景&lt;body bgcolor=&#8221;#FFFFFF&#8221;&gt; </p>
 <script type="text/javascript" src="http://www.cnitblog.com/Files/yemoo/gg2.js"></script><img src ="http://www.cnitblog.com/yemoo/aggbug/13019.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/yemoo/" target="_blank">Yemoo'S JS Blog</a> 2006-06-28 23:12 <a href="http://www.cnitblog.com/yemoo/archive/2006/06/28/13019.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>嵌入式web视频点播系统实现方法(转自langzhou.com)</title><link>http://www.cnitblog.com/yemoo/archive/2006/06/27/12920.html</link><dc:creator>Yemoo'S JS Blog</dc:creator><author>Yemoo'S JS Blog</author><pubDate>Tue, 27 Jun 2006 03:26:00 GMT</pubDate><guid>http://www.cnitblog.com/yemoo/archive/2006/06/27/12920.html</guid><wfw:comment>http://www.cnitblog.com/yemoo/comments/12920.html</wfw:comment><comments>http://www.cnitblog.com/yemoo/archive/2006/06/27/12920.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/yemoo/comments/commentRss/12920.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/yemoo/services/trackbacks/12920.html</trackback:ping><description><![CDATA[<script type="text/javascript" src="http://www.cnitblog.com/Files/yemoo/gg1.js"></script><br /><br />近年来，视频点播vod（video on demand）的名字在媒体上出现得越来越多。vod技术使人们可以根据自己的兴趣，不用借助录像机、影碟机、有线电视而在电脑或电视上自由地点播节目库中的视频节目和信息，是可以对视频节目内容进行自由选择的交互式系统。 <br />vod的本质是信息的使用者根据自己的需求主动获得多媒体信息，它区别于信息发布的最大不同:一是主动性、二是选择性。从某种意义上说这是信息的接受者根据自身需要进行自我完善和自我发展的方式，这种方式在当今的信息社会中将越来越符合信息资源消费者的深层需要，可以说vod是信息获取的未来主流方式在多媒体视音频方面的表现。vod的概念将会在信息获取的领域快速扩展,具有无限广阔的发展前景。<br /><br />【背景】<br /><br />笔者所在的单位建设有一个内部网站，为了进一步提高网络的可用性，完善网站的功能，决定在网络上提供视频点播功能。经过一段时间的摸索和比较，笔者最后选择了realsystem公司的realplayer作为视频文件的播放工具，主要基于以下几点考虑：<br /><br />1、 realplayer 支持当今绝大多数的音视频流媒体格式，包括当前流行的mp3等音频媒质；<br /><br />2、 realplayer 默认的.rm格式在保证播放质量的同时，文件压缩比高，使其更利于网络传输；<br /><br />3、 realplayer在internet上拥有广泛的用户群和服务商支持。<br /><br />可供选择的还有microsoft的mediaplayer、apple 的quicktime等。具体请参看&#8220;搜新网&#8221;评测文章：《三大主流流媒体技术对比》（http://www.souxin.com/stream/txt/3_stream_comp/www.souxin.com.htm）<br /><br /><br /><br />【播放方式的选择】<br /><br />一般而言，安装好realplayer之后，有两种方式可供选择来连接视频文件。一种是直接在web页面上提供视频文件的url地址，当用户点击链接时，realplayer自动识别并实时连接进行播放；第二种方法是通过activex控件方式在web页面中嵌入realplayer对象，并通过dhtml为内嵌对象动态指定视频流url，从而为视频播放提供了一个统一的友好界面。<br /><br />前一种方法对于设计者来说相对比较简单，只需要提供视频文件的播放路径。realplayer的熟练用户，还可以通过自定义realplayer的播放方式、下载视觉插件、添加到收藏夹等方式进行视频管理。但这种方式也存在以下几点缺陷：<br /><br />1、对于含有中文路径和中文名的视频文件，浏览器并不能很好支持，常常出现找不到文件等错误信息。<br /><br />2、需要系统进行文件关联，如果文件关联出错，浏览器将无所适从。<br /><br />3、对终端用户来说，往往希望看到统一的播放界面，而不是弹出式播放。<br /><br />通过web嵌入式视频流管理，可以把用户端的操作请求减少到最小（用户只需简单的安装realplayer播放器）。如果再辅以精心的美工设计，还可以按照设计者的意愿定制出精美大方的播放界面。<br /><br /><br /><br />【基本概念】<br /><br />在进行设计之前，我们先来了解一些相关的基本概念。<br /><br />1、&lt;object&gt;、&lt;embed&gt;标签<br /><br />&lt;object&gt;是microsoft在ie4.0之后推出的，用来替代&lt;embed&gt;标签的对象定义标签(ie仍然支持&lt;embed&gt;)，通过classid属性定义相应的对象类型。&lt;embed&gt;标签是netscape浏览器支持的对象定义标签。如果开发者需要同时获得ie和netscape两种浏览器用户的支持，最好使用&lt;embed&gt;标签。<br /><br />2、定义ram文件<br /><br />ram格式文件同rm文件一样，也是realplayer所支持的视频文件压缩格式，所不同的是ram文件可以仅简单的包括视频文件的url地址。也就是说，ram文件可以为简单的文本格式，每一行定义一个视频文件的url地址。<br /><br />笔者在测试时发现，嵌入式realplayer在播放视频文件时，一般采用把视频文件整个下载到本地然后进行播放。这对于较大的视频文件来说，速度让人难以忍受。解决这个问题的方法，一是把视频文件简单的分割成大小适中的小文件分段播放（由于 real 公司对 rm 格式的实行&#8220;封闭管理&#8221;，所以 rm 到目前为止还不能像 mpeg 等视频文件一样用视频软件自由的编辑）；另外一种就是采用ram文件。realplayer简单的下载文本格式的ram文件，然后取出其中的真实地址，然后自动连接到网络进行实时的点对点播放。其缺点是增加了服务器负担。<br /><br />类似的，microsoft media player采用asx格式来定义asf文件。<br /><br />3、dhtml<br /><br />dhtml是dynamic html的缩写，dhtml通过传统的html语言，利用css（cascading style sheets，即样式表），并依靠javascript使一向静止不变的页面得以&#8220;动&#8221;起来。 netscape 4.0和ie 4.0/5.0版本支持dhtml，dhtml是一种完全&#8220;客户端&#8221;技术，直接通过web页面实现页面与用户之间的交互性。dhtml的优秀之处在于增强了web页面的功能，在web页面直接建立动画、游戏和应用软件等等，提供了浏览站点的全新方式，与java、flash等技术不同的是，用dhtml编制的页面不需要插件的支持就能完整的实现。<br /><br /><br /><br />【设计过程】<br /><br />下面笔者以ie5.0为例，说明一个嵌入式web视频点播系统的实现方法，其中用到了部分php和javascript技术，有疑惑的读者请参考相关资料。<br /><br />一、插入realplayer activex对象（如果要进行测试，需要先安装realplayer播放器）<br /><br />假定以下代码包含在video.php文档中（该文件将在主页面中通过&lt;iframe&gt;进行链接）。<br /><br />&lt;object width="320" height="250" classid="clsid:cfcdaa03-8be4-11cf-b84b-0020afbbccfa"&gt;<br /><br />&lt;param name="controls" value="imagewindow"&gt;<br /><br />&lt;param name="console" value="video"&gt;<br /><br />&lt;param name="center" value="true"&gt;<br /><br />&lt;param name="maintainspect" value="true"&gt;<br /><br />&lt;/object&gt; //定义播放界面<br /><br />&lt;object width="320" height="30" classid="clsid:cfcdaa03-8be4-11cf-b84b-0020afbbccfa"&gt;<br /><br />&lt;param name="controls" value="statusbar"&gt;<br /><br />&lt;param name="console" value="video"&gt;<br /><br />&lt;/object&gt; //定义状态栏<br /><br />&lt;object width="320" height="30" classid="clsid:cfcdaa03-8be4-11cf-b84b-0020afbbccfa"&gt;<br /><br />&lt;param name="controls" value="controlpanel"&gt;<br /><br />&lt;param name="console" value="video"&gt;<br /><br />&lt;param name="src" value="&lt;?php echo getsrc(); ?&gt;"&gt;<br /><br />&lt;param name="autostart" value="true"&gt;<br /><br />&lt;param name="prefetch" value="0"&gt;<br /><br />&lt;param name="loop" value="0"&gt;<br /><br />&lt;param name="numloop" value="0"&gt;<br /><br />&lt;/object&gt; //定义控制面板<br /><br />其中，controls参数用来指定播放器的控件外观，可以用多个控件进行组合，并通过console参数进行关联。<br /><br />有关param参数，读者可以参阅realplayer官方网站http://service.real.com/help/library/guides/production/htmfiles/control.htm。<br /><br />这里的src参数尤为重要，用来指定视频流文件的url地址。这里笔者使用php代码的方法动态的指定src，读者也可以使用其它如asp，或完全通过 javascript 实现。<br /><br /><br /><br />二、使用dhtml动态控制realplayer控件的播放<br /><br />小技巧：&lt;iframe&gt;的妙用。由于为realplayer控件指定新的src需要刷新页面，使用&lt;iframe&gt;可以把realplayer控件嵌入到单独的页面中，这样，动态刷新就是在&lt;iframe&gt;内进行，不会影响用户观看页面其它内容。<br /><br />以下代码包含在主页面中：<br /><br />&lt;iframe id="ivideo" src="video.php" width=500 height=345 frameborder=0 scrolling="no"&gt;<br /><br />&lt;/iframe&gt;，其中，video.php文件用力显示realplayer控件。<br /><br /><br /><br />下面我们加入简单的javascript 代码用来控制视频的播放。<br /><br />&lt;script language="javascript"&gt;<br /><br />function play(filename)&lt;<br /><br />top.document.all("ivideo").src = "video.php?src="+filename;<br /><br />&gt; // ivideo 是刚刚定义的iframe 的标识符<br /><br />&lt;/script&gt;<br /><br />我们可以使用javascript控制realplayer插件更复杂的功能，如提取视频的长宽、测试用户的网络速率、自定义播放事件等等。关于realplayer activex开发的具体细节，请参阅realplayer官方网站http://service.real.com/help/library/guides/extend/embed.htm。<br /><br />我们假设有一个视频文件，其url为http://yoururl/filename.ram，那么我们就可以这样定义：<br /><br />&lt;a href="javascript:play(http://yoururl/filename.ram)"&gt;文件1&lt;/a&gt;，如果文件是在本地，url也可以为相对路径。<br /><br /><br /><br />三、检测用户是否安装realplayer播放器<br /><br />在页面的&lt;head&gt;&lt;/head&gt;部分加入以下javascript代码，用以检测用户是否安装realplayer播放器：<br /><br />&lt;script language=javascript&gt;<br /><br />&lt;!--<br /><br />var realmode=0;<br /><br />var realplayer5=0;<br /><br />var realplayer4=0;<br /><br />var realplayerg2=0;<br /><br /><br /><br />if (navigator.useragent.indexof("msie")&lt; 0 )&lt;<br /><br />numplugins = navigator.plugins.length;<br /><br />for (i = 0; i &lt; numplugins; i++)&lt;<br /><br />plugin = navigator.plugins[i];<br /><br />if (plugin.name.substring(0,10)=="realplayer")&lt;<br /><br />realmode=1;<br /><br />&gt;<br /><br />&gt;<br /><br />&gt;<br /><br />// 以下代码通过vbscript的createobject()函数动态的创建realplayer对象<br /><br />document.write(&lt;script language=vbscript\&gt; \n);<br /><br />document.write(on error resume next \n);<br /><br />document.write(realplayerg2 = (not isnull(createobject("rmocx.realplayer g2 control")))\n);<br /><br />document.write(realplayer5 = (not isnull(createobject("realplayer.realplayer(tm) activex control (32-bit)")))\n);<br /><br />document.write(realplayer4 = (not isnull(createobject("realvideo.realvideo(tm) activex control (32-bit)")))\n);<br />document.write(&lt;/script\&gt; \n);<br /><br />if ( realplayerg2 || realplayer5 || realplayer4 )&lt;<br /><br />//可以在此处添加&lt;object&gt;对象<br /><br />&gt;else if ( realmode )&lt; // netscape浏览器用户<br /><br />// 可以在此处加入&lt;embed&gt;对象<br /><br />&gt;else&lt;<br /><br />window.location.replace("install.htm"); // 转入install.htm页面指导用户进行安装<br /><br />&gt;<br /><br />--&gt;<br /><br />&lt;/script&gt;<br /><br /><br /><br />至此，我们已经实现了一个基于web的视频点播的基本功能。但我们要想把功能做的更完美一些，还需要其它更复杂的考虑。如流媒体的制作、网页美工的设计、网络流速的考虑，以及网站视频文件的有效组织。这些话题已经超出了本文的讨论范围，请读者自行参考相关资料。<br /> 
<script type="text/javascript" src="http://www.cnitblog.com/Files/yemoo/gg2.js"></script><img src ="http://www.cnitblog.com/yemoo/aggbug/12920.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/yemoo/" target="_blank">Yemoo'S JS Blog</a> 2006-06-27 11:26 <a href="http://www.cnitblog.com/yemoo/archive/2006/06/27/12920.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Cookie详解</title><link>http://www.cnitblog.com/yemoo/archive/2006/06/16/12398.html</link><dc:creator>Yemoo'S JS Blog</dc:creator><author>Yemoo'S JS Blog</author><pubDate>Fri, 16 Jun 2006 14:54:00 GMT</pubDate><guid>http://www.cnitblog.com/yemoo/archive/2006/06/16/12398.html</guid><wfw:comment>http://www.cnitblog.com/yemoo/comments/12398.html</wfw:comment><comments>http://www.cnitblog.com/yemoo/archive/2006/06/16/12398.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/yemoo/comments/commentRss/12398.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/yemoo/services/trackbacks/12398.html</trackback:ping><description><![CDATA[<script type="text/javascript" src="http://www.cnitblog.com/Files/yemoo/gg1.js"></script><br><br>Cookies现在经常被大家提到，那么到底什么是Cookies，它有什么作用呢？Cookies是一种能够让网站服务器把少量数据储存到客户端的硬盘或内存，或是从客户端的硬盘读取数据的一种技术。Cookies是当你浏览某网站时，由Web服务器置于你硬盘上的一个非常小的文本文件，它可以记录你的用户ID、密码、浏览过的网页、停留的时间等信息。 <br /><br />当你再次来到该网站时，网站通过读取Cookies，得知你的相关信息，就可以做出相应的动作，如在页面显示欢迎你的标语，或者让你不用输入ID、密码就直接登录等等。从本质上讲，它可以看作是你的身份证。但Cookies不能作为代码执行，也不会传送病毒，且为你所专有，并只能由提供它的服务器来读取。保存的信息片断以"名/值"对(name-value pairs)的形式储存，一个"名/值"对仅仅是一条命名的数据。一个网站只能取得它放在你的电脑中的信息，它无法从其它的Cookies文件中取得信息，也无法得到你的电脑上的其它任何东西。 Cookies中的内容大多数经过了加密处理，因此一般用户看来只是一些毫无意义的字母数字组合，只有服务器的CGI处理程序才知道它们真正的含义。 <br /><br />由于Cookies是我们浏览的网站传输到用户计算机硬盘中的文本文件或内存中的数据，因此它在硬盘中存放的位置与使用的操作系统和浏览器密切相关。在Windows 9X系统计算机中，Cookies文件的存放位置为C:/Windows/Cookies，在Windows NT/2000/XP的计算机中，Cookies文件的存放位置为C:/Documents and Settings/用户名/Cookies。 <br /><br />硬盘中的Cookies文件可以被Web浏览器读取，它的命令格式为：用户名@网站地址[数字].txt。如笔者计算机中的一个Cookies文件名为：ch@163[1].txt。要注意的是：硬盘中的Cookies属于文本文件，不是程序。 <br /><br />Cookies的设置 <br /><br />你可以在IE的"工具/Internet选项"的"常规"选项卡中，选择"设置/查看文件"，查看所有保存到你电脑里的Cookies。这些文件通常是以user@domain格式命名的，user是你的本地用户名，domain是所访问的网站的域名。如果你使用NetsCape浏览器，则存放在"C:/PROGRAMFILES/NETS- CAPE/USERS/"里面，与IE不同的是，NETSCAPE是使用一个Cookie文件记录所有网站的Cookies。 <br /><br />我们可对Cookie进行适当设置：打开"工具/Internet选项"中的"隐私"选项卡（注意该设置只在IE6.0中存在，其他版本IE可以单击"工具/Internet选项" "安全"标签中的"自定义级别"按钮，进行简单调整），调整Cookie的安全级别。通常情况，可以调整到"中高"或者"高"的位置。多数的论坛站点需要使用Cookie信息，如果你从来不去这些地方，可以将安全级调到"阻止所有Cookies";如果只是为了禁止个别网站的Cookie，可以单击"编辑"按钮，将要屏蔽的网站添加到列表中。在"高级"按钮选项中，你可以对第一方Cookie和第三方的Cookie进行设置，第一方Cookie是你正在浏览的网站的Cookie，第三方Cookie是非正在浏览的网站发给你的Cookie，通常要对第三方Cookie选择"拒绝"。你如果需要保存Cookie，可以使用IE的"导入导出"功能，打开"文件/导入导出"，按提示操作即可。 <br /><br />Cookies的写入与读取 <br /><br />Cookies集合是附属于Response对象及Request对象的数据集合，使用时需要在前面加上Response或Request。 <br /><br />用于给客户机发送Cookies的语法通常为： <br /><br />当给不存在的Cookies集合设置时，就会在客户机创建，如果该Cookies己存在，则会被代替。由于Cookies是作为HTTP传输的头信息的一部分发给客户机的，所以向客户机发送Cookies的代码一般放在发送给浏览器的HTML文件的标记之前。 <br /><br />如果用户要读取Cookies，则必须使用Request对象的Cookies集合，其使用方法是： 需要注意的是，只有在服务器未被下载任何数据给浏览器前，浏览器才能与Server进行Cookies集合的数据交换，一旦浏览器开始接收Server所下载的数据，Cookies的数据交换则停止，为了避免错误，要在程序和前面加上response.Buffer=True。 <br />Cookies的应用 <br /><br />几乎所有的网站设计者在进行网站设计时都使用了Cookie，因为他们都想给浏览网站的用户提供一个更友好的、人文化的浏览环境，同时也能更加准确地收集访问者的信息。 <br /><br />网站浏览人数管理 <br /><br />由于代理服务器、缓存等的使用，唯一能帮助网站精确统计来访人数的方法就是为每个访问者建立一个唯一的ID。使用Cookie，网站可以完成以下工作：测定多少人访问过；测定访问者中有多少是新用户（即第一次来访），多少是老用户；测定一个用户多久访问一次网站。 <br /><br />通常情况下，网站设计者是借助后台数据库来实现以上目的的。当用户第一次访问该网站时，网站在数据库中建立一个新的ID，并把ID通过Cookie传送给用户。用户再次来访时，网站把该用户ID对应的计数器加1，得到用户的来访次数或判断用户是新用户还是老用户。 <br /><br />按照用户的喜好定制网页外观 <br /><br />有的网站设计者，为用户提供了改变网页内容、布局和颜色的权力，允许用户输入自己的信息，然后通过这些信息对网站的一些参数进行修改，以定制网页的外观。 <br /><br />在电子商务站点中实现诸如"购物篮"等功能 <br /><br />可以使用Cookie记录用户的ID，这样当你往"购物篮"中放了新东西时，网站就能记录下来，并在网站的数据库里对应着你的ID记录当你"买单"时，网站通过ID检索数据库中你的所有选择就能知道你的"购物篮"里有些什么。 <br /><br />在一般的事例中，网站的数据库能够保存的有你所选择的内容、你浏览过的网页、你在表单里填写的信息等；而包含有你的唯一ID的Cookie则保存在你的电脑里。 <br /><br />Cookies的缺陷 <br /><br />Cookie虽然被广泛的应用，并能做到一些使用其它技术不可能实现的功能。但也存在一些不够完美的方面，给应用带来不便。 <br /><br />多人共用一台电脑的问题 <br /><br />任何公共场合的电脑或者许多在办公室或家里使用的电脑，都会同时被两个以上的人使用。这样，当你用它在网上超市购物时，网上超市或网站会在这台机器上留下一个Cookie，将来也许就会有某个人试图使用你的账户购物，带来了不安全的可能。当然，在一些使用多用户操作系统如Windows NT或UNIX的电脑上，这并不会成为一个问题。因为在多用户操作系统下不同的账户的Cookie分别放在不同的地方。 <br />Cookies被删除时 <br /><br />假如你的浏览器不能正常工作，你可能会删除电脑上所有的临时Internet文件。然而，一旦这样操作以后，你就会丢掉所有的Cookies文件。当你再次访问一个网站时，网站会认为你是一位新用户并分配给你一个新的用户ID以及一个新的Cookie。结果将会造成网站统计的新老用户比发生偏差，而你也难以恢复过去保存的参数选择。 <br /><br />一人使用多台电脑时 <br /><br />有的人一天之中经常使用一台以上的电脑。例如在办公室里有一台电脑、家里有一台、还有移动办公用的笔记本电脑。除非网站使用了特别的技术来解决这一问题，否则，你将会有三个不同的Cookies文件在这三台机器上，而在三台机器上访问过的任何网站都将会把你看成三个不同的用户。 <br /><br />防范Cookies泄密 <br /><br />想知道你访问的网站是否在你的硬盘或内存中写入了Cookies信息吗？只需执行下面的操作步骤，就可以了解和控制你正在访问的网站的Cookies信息。 <br /><br />步骤一点击IE窗口中的"工具" "In-ernet选项"，打开"Internet选项"设置窗口； <br /><br />步骤二点击"Internet选项"设置窗口中的"安全"标签，然后再点击"自定义级别"按钮，进入"安全设置"窗口； <br /><br />步骤三 找到"安全设置"窗口中的"Cookies"设置项。"Cookies"设置项下有两个分选项，其中"允许使用存储在您计算机上的ookies"是针对存储在用户计算机硬盘中的Cookies文件；"允许使用每个对话Cookies（未存储）"是针对存储在用户计算机内存中的Cookies信息。存储在硬盘中的Cookies文件是永久存在的，而存储在内存中的Cookies信息是临时的。要想IE在即将接收来自Web站点的所有Cookies时进行提示，可分别选择上面两个分选项中的"提示"项。当然，你也可以选择"启用"，允许IE接受所有的Cookies信息（这也是IE的默认选项）；选择"禁止"，则是不允许Web站点将Cookies存储到您的计算机上，而且Web站点也不能读取你计算机中已有的Cookies。 <br /><br />IE6.0提供了更为可靠的个人隐私及安全保护措施，可以让用户来控制浏览器向外发送信息的多少。在"Internet 选项"窗口中新增了"隐私"选项卡（图1），用户可以在其中直接设置浏览时的隐私级别，按需要控制其他站点对自己电脑所使用的Cookies。 <br /><br />如果我们正在浏览的站点使用了Cookie，那么在浏览器状态栏中会有一个黄色惊叹号的标记，双击后可打开"隐私报告"对话框，用户可以在其中查看具体的隐私策略，还可直接点击"设置"按钮后在上述"隐私"选项卡中调节安全隐私级别。 <br /><br />在"常规"选项卡中还增加了"删除Cookies"按钮（图2），方便用户直接清除本机上的Cookies。另外，在"工具" "选项" "高级"选项卡中也增加了一些进一步提高安全性的选项（如关闭浏览器时清空Internet临时文件）。其实，如何更好地保护个人隐私和安全是微软下一代".NET"战略软件中的关键技术，现在IE6.0已经尝试着迈出了第一步。 <br /><br />另外，由于Cookies的信息并不都是以文件形式存放在计算机里，还有部分信息保存在内存里。比如你在浏览网站的时候，Web服务器会自动在内存中生成Cookie，当你关闭IE浏览器的时候又自动把Cookie删除，那样上面介绍的两种方法就起不了作用，我们需要借助注册表编辑器来修改系统设置。要注意的是，修改注册表前请作备份，以便出现问题后能顺利恢复。 <br /><br />运行Regedit，找到如下键值：HKEY_LOCAL_MACHINE/Software/Microsoft/Windows/CurrentVersion/Internet Settings/Cache/Special Paths/Cookies，这是Cookies在内存中的键值，把这个键值删除。至此Cookies无论以什么形式存在，我们都不用再害怕了。 <br /><br />最后有必要说明的一点是：杜绝Cookies虽然可以增强你电脑的信息安全程度，但这样做同样会有一些弊端。比如在一些需要Cookies支持的网页上，会发生一些莫名其妙的错误，典型的例子就是你以后不能使用某些网站的免费信箱了。 <br />Cookies欺骗 <br /><br />通过分析Cookie的格式，我们知道，最后两项中分别是它的URL路径和域名，服务器对Cookie的识别靠的就是这两个参数。正常情况下，我们要浏览一个网站时输入的URL便是它的域名，需要经过域名管理系统DNS将其转化为IP地址后进行连接。若能在DNS上进行一些设置，把目标域名的IP地址对应到其它站点上，我们便可以非法访问目标站点的Cookie了。 <br /><br />要进行Cookies欺骗，其实很简单。比如在Win9X下的安装目录下，有一名为hosts.sam的文件，以文本方式打开后会看到这样的格式： <br /><br />127.0.0.1 localhost <br /><br />经过设置，便可以实现域名解析的本地化，只需将IP和域名依上面的格式添加到文件中并另存为hosts即可。hosts文件实际上可以看成一个本机的DNS系统，它可以负责把域名解释成IP地址，它的优先权比DNS服务器要高，它的具体实现是TCP/IP协议中的一部分。 <br /><br />比如我们要读取的目标站点 <a href="http://www.abc.com/" target="_blank">www.abc.com</a> 所生成的Cookies信息，可以借助<a href="http://www.def.com/" target="_blank">www.def.com</a>（自己的站点）。<a href="http://www.def.com/" target="_blank">www.def.com</a> 存放用来进行欺骗所需的文件，通过它读取和修改对方的Cookie。 <br /><br />步骤一 ping<a href="http://www.def.com/" target="_blank">www.def.com</a> 的IP地址： <br /><br />ping <a href="http://www.def.com/" target="_blank">www.def.com</a><br /><br />Reply from 192.168.0.1: bytes=32 time=20ms TTL=244 <br /><br />然后修改hosts.sam文件如下： <br /><br />192.168.0.1 <a href="http://www.abc.com/" target="_blank">www.abc.com</a><br /><br />并保存为hosts文件。 <br /><br />步骤二 读取Cookies信息： <br /><br />将用来读取Cookie的页面传<a href="http://www.def.com/" target="_blank">www.def.com</a> ，此时连<a href="http://www.abc.com/" target="_blank">www.abc.com</a>，由于我们进行本机DNS域名解析的修改，这时网络连接的并不<a href="http://www.abc.com/" target="_blank">www.abc.com</a>，而<a href="http://www.def.com/" target="_blank">www.def.com</a> 。 <br /><br />这<a href="http://www.abc.com/" target="_blank">www.abc.com</a>设在本地的Cookie便可被读出。 <br /><br />步骤三 同样道理，你可对读出的数据进行修改，并可将修改后的信息写入Cookie中。修改完毕后，删掉hosts文件，再重新进<a href="http://www.abc.com/" target="_blank">www.abc.com</a>，此时所使用的Cookies数据就是你制定的数据。 <br /><br />总之，在某种程度上虽然可以实现Cookies的欺骗，给网络应用带来不安全的因素，但Cookies文件本身并不会造成用户隐私的泄露，也不会给黑客提供木马程序的载体，只要合理使用，它们会给网站管理员进行网站的维护和管理以及广大用户的使用都带来便利。 <br />Cookies集合具有以下几种属性： <br /><br />1.Expires属性：此属性用来给Cookies设置一个期限，在期限内只要打开网页就可以调用被保存的Cookies，如果过了此期限Cookies就自动被删除。如： <br /><br />设定Cookies的有效期到2004年4月1日，到时将自动删除。如果一个Cookies没有设定有效期，则其生命周期从打开浏览器开始，到关闭浏览器结束，每次运行后生命周期将结束，下次运行将重新开始。 <br /><br />2.Domain属性：这个属性定义了Cookies传送数据的唯一性。若只将某Cookies传送给_blank"&gt;搜狐主页时，则可使用如下代码： <br /><br />3.Path属性：定义了Cookies只发给指定的路径请求，如果Path属性没有被设置，则使用应用软件的缺省路径。 <br /><br /><br />4.Srcure属性：指定Cookies能否被用户读取。 <br /><br />5.Haskeys属性：如果所请求的Cookies是一个具有多个键值的Cookies字典，则返回True，它是一个只读属性  <p><script type="text/javascript" src="http://www.cnitblog.com/Files/yemoo/gg2.js"></script><img src ="http://www.cnitblog.com/yemoo/aggbug/12398.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/yemoo/" target="_blank">Yemoo'S JS Blog</a> 2006-06-16 22:54 <a href="http://www.cnitblog.com/yemoo/archive/2006/06/16/12398.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>