<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
  <channel>
    <title>bufanliu</title>
    <description></description>
    <link>http://bufanliu.javaeye.com</link>
    <language>UTF-8</language>
    <copyright>Copyright 2003-2008, JavaEye.com</copyright>
    <docs>http://blogs.law.harvard.edu/tech/rss</docs>
    <generator>JavaEye - 做最棒的软件开发交流社区</generator>
      <item>
        <title>如何优化JavaScript脚本的性能</title>
        <author>bufanliu</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://bufanliu.javaeye.com">bufanliu</a>&nbsp;
          链接：<a href="http://bufanliu.javaeye.com/blog/230047" style="color:red;">http://bufanliu.javaeye.com/blog/230047</a>&nbsp;
          发表时间: 2008年08月19日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          如何优化JavaScript脚本的性能作者：ShiningRay @ Nirvana Studio<br /><br />随着网络的发展，网速和机器速度的提高，越来越多的网站用到了丰富客户端技术。而现在Ajax则是最为流行的一种方式。JavaScript是一种解释型语言，所以能无法达到和C/Java之类的水平，限制了它能在客户端所做的事情，为了能改进他的性能，我想基于我以前给JavaScript做过的很多测试来谈谈自己的经验，希望能帮助大家改进自己的JavaScript脚本性能。<br /><br />语言层次方面<br />循环<br />循环是很常用的一个控制结构，大部分东西要依靠它来完成，在JavaScript中，我们可以使用for(;;),while(),for(in)三种循环，事实上，这三种循环中for(in)的效率极差，因为他需要查询散列键，只要可以就应该尽量少用。for(;;)和while循环的性能应该说基本（平时使用时）等价。<br /><br />而事实上，如何使用这两个循环，则有很大讲究。我在测试中有些很有意思的情况，见附录。最后得出的结论是：<br /><br />如果是循环变量递增或递减，不要单独对循环变量赋值，应该在它最后一次读取的时候使用嵌套的++或--操作符。<br /><br />如果要与数组的长度作比较，应该事先把数组的length属性放入一个局部变量中，减少查询次数。<br /><br />举例，假设arr是一个数组，最佳的遍历元素方式为：<br /><br />for(var i=0, len = arr.length;i&lt;len;i++){...}或者，如果无所谓顺序的话：<br /><br />for(var i=arr.length;i>0;i--){...}局部变量和全局变量<br />局部变量的速度要比全局变量的访问速度更快，因为全局变量其实是全局对象的成员，而局部变量是放在函数的栈当中的。<br /><br />不使用Eval<br />使用eval相当于在运行时再次调用解释引擎对内容进行运行，需要消耗大量时间。这时候使用JavaScript所支持的闭包可以实现函数模版（关于闭包的内容请参考函数式编程的有关内容）<br /><br />减少对象查找<br />因为JavaScript的解释性，所以a.b.c.d.e，需要进行至少4次查询操作，先检查a再检查a中的b，再检查b中的c，如此往下。所以如果这样的表达式重复出现，只要可能，应该尽量少出现这样的表达式，可以利用局部变量，把它放入一个临时的地方进行查询。<br /><br />这一点可以和循环结合起来，因为我们常常要根据字符串、数组的长度进行循环，而通常这个长度是不变的，比如每次查询a.length，就要额外进行一个操作，而预先把var<br />len=a.length，则就少了一次查询。<br /><br />字符串连接<br />如果是追加字符串，最好使用s+=anotherStr操作，而不是要使用s=s+anotherStr。<br /><br />如果要连接多个字符串，应该少使用+=，如<br /><br />s+=a;s+=b;s+=c;应该写成<br /><br />s+=a + b + c；而如果是收集字符串，比如多次对同一个字符串进行+=操作的话，最好使用一个缓存。怎么用呢？使用JavaScript数组来收集，最后使用join方法连接起来，如下<br /><br />var buf = new Array();for(var i = 0; i &lt; 100; i++){	buf.push(i.toString());}var all = buf.join("");类型转换<br />类型转换是大家常犯的错误，因为JavaScript是动态类型语言，你不能指定变量的类型。<br /><br />1.<br />把数字转换成字符串，应用"" + 1，虽然看起来比较丑一点，但事实上这个效率是最高的，性能上来说：<br /><br />("" + ) > String() > .toString() > new String() <br /><br />这条其实和下面的“直接量”有点类似，尽量使用编译时就能使用的内部操作要比运行时使用的用户操作要快。<br /><br />String()属于内部函数，所以速度很快，而.toString()要查询原型中的函数，所以速度逊色一些，new String()用于返回一个精确的副本。<br /><br />2.<br />浮点数转换成整型，这个更容易出错，很多人喜欢使用parseInt()，其实parseInt()是用于将字符串转换成数字，而不是浮点数和整型之间的转换，我们应该使用Math.floor()或者Math.round()。<br /><br />另外，和第二节的对象查找中的问题不一样，Math是内部对象，所以Math.floor()其实并没有多少查询方法和调用的时间，速度是最快的。<br /><br />3.<br />对于自定义的对象，如果定义了toString()方法来进行类型转换的话，推荐显式调用toString()，因为内部的操作在尝试所有可能性之后，会尝试对象的toString()方法尝试能否转化为String，所以直接调用这个方法效率会更高<br /><br />使用直接量<br />其实这个影响倒比较小，可以忽略。什么叫使用直接量，比如，JavaScript支持使用[param,param,param,...]来直接表达一个数组，以往我们都使用new Array(param,param,...)，使用前者是引擎直接解释的，后者要调用一个Array内部构造器，所以要略微快一点点。<br /><br />同样，var foo = {}的方式也比var foo = new Object();快，var reg = /../;要比var reg=new RegExp()快。<br /><br />字符串遍历操作<br />对字符串进行循环操作，譬如替换、查找，应使用正则表达式，因为本身JavaScript的循环速度就比较慢，而正则表达式的操作是用C写成的语言的API，性能很好。<br /><br />高级对象<br />自定义高级对象和Date、RegExp对象在构造时都会消耗大量时间。如果可以复用，应采用缓存的方式。<br /><br />DOM相关<br />插入HTML<br />很多人喜欢在JavaScript中使用document.write来给页面生成内容。事实上这样的效率较低，如果需要直接插入HTML，可以找一个容器元素，比如指定一个div或者span，并设置他们的innerHTML来将自己的HTML代码插入到页面中。<br /><br />对象查询<br />使用[""]查询要比.items()更快，这和前面的减少对象查找的思路是一样的，调用.items()增加了一次查询和函数的调用。<br /><br />创建DOM节点<br />通常我们可能会使用字符串直接写HTML来创建节点，其实这样做<br /><br />无法保证代码的有效性<br /><br />字符串操作效率低<br /><br />所以应该是用document.createElement()方法，而如果文档中存在现成的样板节点，应该是用cloneNode()方法，因为使用createElement()方法之后，你需要设置多次元素的属性，使用cloneNode()则可以减少属性的设置次数——同样如果需要创建很多元素，应该先准备一个样板节点。<br /><br />定时器<br />如果针对的是不断运行的代码，不应该使用setTimeout，而应该是用setInterval。setTimeout每次要重新设置一个定时器。<br /><br />其他<br />脚本引擎<br />据我测试Microsoft的JScript的效率较Mozilla的Spidermonkey要差很多，无论是执行速度还是内存管理上，因为JScript现在基本也不更新了。但SpiderMonkey不能使用ActiveXObject<br /><br />文件优化<br />文件优化也是一个很有效的手段，删除所有的空格和注释，把代码放入一行内，可以加快下载的速度，注意，是下载的速度而不是解析的速度，如果是本地，注释和空格并不会影响解释和执行速度。<br /><br />总结<br />本文总结了我在JavaScript编程中所找到的提高JavaScript运行性能的一些方法，其实这些经验都基于几条原则：<br /><br />直接拿手头现成的东西比较快，如局部变量比全局变量快，直接量比运行时构造对象快等等。<br /><br />尽可能少地减少执行次数，比如先缓存需要多次查询的。<br /><br />尽可能使用语言内置的功能，比如串链接。<br /><br />尽可能使用系统提供的API，因为这些API是编译好的二进制代码，执行效率很高<br /><br />同时，一些基本的算法上的优化，同样可以用在JavaScript中，比如运算结构的调整，这里就不再赘述了。但是由于JavaScript是解释型的，一般不会在运行时对字节码进行优化，所以这些优化仍然是很重要的。<br /><br />当然，其实这里的一些技巧同样使用在其他的一些解释型语言中，大家也可以进行参考。<br /><br />参考<br />http://www.umsu.de/jsperf/ 各种浏览器的测试对比<br /><br />http://home.earthlink.net/~kendrasg/info/js_opt/ <br /><br />附录1<br />由于是以前做过的测试，测试代码已经不全，我补充了一部分如下：<br /><br />var print;<br /><br />if(typeof document != "undefined" ){<br />    print = function(){<br />		document.write(arguments[0]);<br />	}<br />}else if(typeof WScript != "undefined" ){<br />    print = function(){<br />        WScript.Echo(arguments[0],arguments[1],arguments[2]);<br />    }<br />}<br /><br />function empty(){<br />}<br /><br />function benchmark(f){<br />    var i = 0;<br />    var start = (new Date()).getTime();<br /><br />    while(i &lt; pressure){<br />        f(i++);<br />    }<br />    var end = (new Date()).getTime();<br />    WScript.Echo(end-start);<br />}<br /><br />/*<br />i=0<br />start = (new Date()).getTime();<br />while(i &lt; 60000){<br />    c = [i,i,i,i,i,i,i,i,i,i];<br />    i++;<br />}<br />end = (new Date()).getTime();<br />WScript.Echo(end-start);<br />i=0<br />start = (new Date()).getTime();<br />while(i &lt; 60000){<br />    c = new Array(i,i,i,i,i,i,i,i,i,i);<br />    i++;<br />}<br />var end = (new Date()).getTime();<br />WScript.Echo(end-start);<br />*/<br /><br />function internCast(i){<br />    return "" + i;<br />}<br /><br />function StringCast(i){<br />    return String(i)<br />}<br />function newStringCast(i){<br />    return new String(i)<br />}<br />function toStringCast(i){<br />    return i.toString();<br />}<br />function ParseInt(){<br />    return parseInt(j);<br />}<br />function MathFloor(){<br />    return Math.floor(j);<br />}<br />function Floor(){<br />    return floor(j);<br />}<br />var pressure = 50000;<br />var a  = "";<br />var floor = Math.floor;<br />j = 123.123;<br />print("-------------\nString Conversion Test");<br />print("The empty:", benchmark(empty));<br />print("intern:", benchmark(internCast));<br />print("String:");<br />benchmark(StringCast);<br />print("new String:");<br />benchmark(newStringCast);<br />print("toString:");<br />benchmark(toStringCast);<br />print("-------------\nFloat to Int Conversion Test");<br />print("parseInt");<br />benchmark(ParseInt);<br />print("Math.floor");<br />benchmark(MathFloor);<br />print("floor")<br />benchmark(Floor);<br /><br />function newObject(){<br />    return new Object();<br />}<br /><br />function internObject(){<br />    return {};<br />}<br />print("------------\nliteral Test");<br />print("runtime new object", benchmark(newObject));<br />print("literal object", benchmark(internObject));<br />附录2<br />代码1：<br /><br />    for(var i=0;i&lt;100;i++){<br />        arr[i]=0;<br />    }<br /><br /><br />代码2：<br /><br />    var i = 0;<br />    while(i &lt; 100){<br />        arr[i++]=0;<br />    }<br /><br /><br />代码3：<br /><br />    var i = 0;<br />    while(i &lt; 100){<br />        arr[i]=0;<br />        i++;<br />    }<br /><br /><br />在firefox下测试这两段代码，结果是代码2优于代码1和3，而代码1一般优于代码3，有时会被代码3超过；而在IE<br />6.0下，测试压力较大的时候（如测试10000次以上）代码2和3则有时候优于代码1，有时候就会远远落后代码1，而在测试压力较小（如5000次），则代码2>代码3>代码1。<br /><br />代码4：<br /><br />    var i = 0;<br />    var a;<br />    while(i &lt; 100){<br />        a = 0;<br />        i++;<br />    }<br /><br /><br />代码5：<br /><br />    var a;<br />    for(var i=0;i&lt;100;i++){<br />        a = 0;<br />    }上面两段代码在Firefox和IE下测试结果都是性能接近的。<br /><br />代码6：<br /><br />    var a;<br />    var i=0;<br />    while(i&lt;100){<br />        a=i;<br />        i++;<br />    }<br /><br /><br />代码7：<br /><br />    var a;<br />    var i=0;<br />    while(i&lt;100){<br />        a=i++;<br />    }<br /><br /><br />代码8：<br /><br />    var a;<br />    for(var i=0;i&lt;100;i++){<br />        a = i;<br />    }<br /><br /><br />代码9：<br /><br />    var a;<br />    for(var i=0;i&lt;100;){<br />        a = i++;<br />    }这四段代码在Firefox下6和8的性能接近，7和9的性能接近，而6,<br />8 &lt; 7, 9；<br /><br />最后我们来看一下空循环<br /><br />代码10：<br /><br />    for(var i=0;i&lt;100;i++){   }<br /><br /><br />代码11：<br /><br />    var i;<br />    while(i&lt;100){        i++;    }<br />最后的测试出现了神奇的结果，Firefox下代码10所花的时间与代码11所花的大约是24:1。所以它不具备参考价值，于是我没有放在一开始给大家看。<br /><br />This entry was written by ShiningRay, posted on 2005-11-07 at 08:Nov, filed under 日记 and tagged javascript, 性能. Bookmark the permalink. Follow any comments here with the RSS feed for this post. Post a comment or leave a trackback: Trackback URL.
          <br/>
          <span style="color:red;">
            <a href="http://bufanliu.javaeye.com/blog/230047#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Tue, 19 Aug 2008 10:01:41 +0800</pubDate>
        <link>http://bufanliu.javaeye.com/blog/230047</link>
        <guid>http://bufanliu.javaeye.com/blog/230047</guid>
      </item>
      <item>
        <title>java的23种设计模</title>
        <author>bufanliu</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://bufanliu.javaeye.com">bufanliu</a>&nbsp;
          链接：<a href="http://bufanliu.javaeye.com/blog/229862" style="color:red;">http://bufanliu.javaeye.com/blog/229862</a>&nbsp;
          发表时间: 2008年08月18日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          1、FACTORY—追MM少不了请吃饭了，麦当劳的鸡翅和肯德基的鸡翅都是MM爱吃的东西，虽然口味有所不同，但不管你带MM去麦当劳或肯德基，只管向服务员说“来四个鸡翅”就行了。麦当劳和肯德基就是生产鸡翅的Factory<br /><br />工厂模式：客户类和工厂类分开。消费者任何时候需要某种产品，只需向工厂请求即可。消费者无须修改就可以接纳新产品。缺点是当产品修改时，工厂类也要做相应的修改。如：如何创建及如何向客户端提供。<br /><br />2、BUILDER—MM最爱听的就是“我爱你”这句话了，见到不同地方的MM,要能够用她们的方言跟她说这句话哦，我有一个多种语言翻译机，上面每种语言都有一个按键，见到MM我只要按对应的键，它就能够用相应的语言说出“我爱你”这句话了，国外的MM也可以轻松搞掂，这就是我的“我爱你”builder。（这一定比美军在伊拉克用的翻译机好卖）<br /><br />建造模式：将产品的内部表象和产品的生成过程分割开来，从而使一个建造过程生成具有不同的内部表象的产品对象。建造模式使得产品内部表象可以独立的变化，客户不必知道产品内部组成的细节。建造模式可以强制实行一种分步骤进行的建造过程。<br /><br />3、FACTORY METHOD—请MM去麦当劳吃汉堡，不同的MM有不同的口味，要每个都记住是一件烦人的事情，我一般采用Factory Method模式，带着MM到服务员那儿，说“要一个汉堡”，具体要什么样的汉堡呢，让MM直接跟服务员说就行了。<br /><br />工厂方法模式：核心工厂类不再负责所有产品的创建，而是将具体创建的工作交给子类去做，成为一个抽象工厂角色，仅负责给出具体工厂类必须实现的接口，而不接触哪一个产品类应当被实例化这种细节。<br /><br />4、PROTOTYPE—跟MM用QQ聊天，一定要说些深情的话语了，我搜集了好多肉麻的情话，需要时只要copy出来放到QQ里面就行了，这就是我的情话prototype了。（100块钱一份，你要不要）<br /><br />原始模型模式：通过给出一个原型对象来指明所要创建的对象的类型，然后用复制这个原型对象的方法创建出更多同类型的对象。原始模型模式允许动态的增加或减少产品类，产品类不需要非得有任何事先确定的等级结构，原始模型模式适用于任何的等级结构。缺点是每一个类都必须配备一个克隆方法。<br /><br />5、SINGLETON—俺有6个漂亮的老婆，她们的老公都是我，我就是我们家里的老公Sigleton，她们只要说道“老公”，都是指的同一个人，那就是我(刚才做了个梦啦，哪有这么好的事)<br /><br />单例模式：单例模式确保某一个类只有一个实例，而且自行实例化并向整个系统提供这个实例单例模式。单例模式只应在有真正的“单一实例”的需求时才可使用。<br /><br />结构型模式<br /><br />6、ADAPTER—在朋友聚会上碰到了一个美女Sarah，从香港来的，可我不会说粤语，她不会说普通话，只好求助于我的朋友kent了，他作为我和Sarah之间的Adapter，让我和Sarah可以相互交谈了(也不知道他会不会耍我)<br /><br />适配器（变压器）模式：把一个类的接口变换成客户端所期待的另一种接口，从而使原本因接口原因不匹配而无法一起工作的两个类能够一起工作。适配类可以根据参数返还一个合适的实例给客户端。<br /><br />7、BRIDGE—早上碰到MM，要说早上好，晚上碰到MM，要说晚上好；碰到MM穿了件新衣服，要说你的衣服好漂亮哦，碰到MM新做的发型，要说你的头发好漂亮哦。不要问我“早上碰到MM新做了个发型怎么说”这种问题，自己用BRIDGE组合一下不就行了<br /><br />桥梁模式：将抽象化与实现化脱耦，使得二者可以独立的变化，也就是说将他们之间的强关联变成弱关联，也就是指在一个软件系统的抽象化和实现化之间使用组合/聚合关系而不是继承关系，从而使两者可以独立的变化。<br /><br />8、COMPOSITE—Mary今天过生日。“我过生日，你要送我一件礼物。”“嗯，好吧，去商店，你自己挑。”“这件T恤挺漂亮，买，这条裙子好看，买，这个包也不错，买。”“喂，买了三件了呀，我只答应送一件礼物的哦。”“什么呀，T恤加裙子加包包，正好配成一套呀，小姐，麻烦你包起来。”“……”，MM都会用Composite模式了，你会了没有？<br /><br />合成模式：合成模式将对象组织到树结构中，可以用来描述整体与部分的关系。合成模式就是一个处理对象的树结构的模式。合成模式把部分与整体的关系用树结构表示出来。合成模式使得客户端把一个个单独的成分对象和由他们复合而成的合成对象同等看待。<br /><br />9、DECORATOR—Mary过完轮到Sarly过生日，还是不要叫她自己挑了，不然这个月伙食费肯定玩完，拿出我去年在华山顶上照的照片，在背面写上“最好的的礼物，就是爱你的Fita”，再到街上礼品店买了个像框（卖礼品的MM也很漂亮哦），再找隔壁搞美术设计的Mike设计了一个漂亮的盒子装起来……，我们都是Decorator，最终都在修饰我这个人呀，怎么样，看懂了吗？<br /><br />装饰模式：装饰模式以对客户端透明的方式扩展对象的功能，是继承关系的一个替代方案，提供比继承更多的灵活性。动态给一个对象增加功能，这些功能可以再动态的撤消。增加由一些基本功能的排列组合而产生的非常大量的功能。<br /><br />10、FACADE—我有一个专业的Nikon相机，我就喜欢自己手动调光圈、快门，这样照出来的照片才专业，但MM可不懂这些，教了半天也不会。幸好相机有Facade设计模式，把相机调整到自动档，只要对准目标按快门就行了，一切由相机自动调整，这样MM也可以用这个相机给我拍张照片了。<br /><br />门面模式：外部与一个子系统的通信必须通过一个统一的门面对象进行。门面模式提供一个高层次的接口，使得子系统更易于使用。每一个子系统只有一个门面类，而且此门面类只有一个实例，也就是说它是一个单例模式。但整个系统可以有多个门面类。<br /><br />11、FLYWEIGHT—每天跟MM发短信，手指都累死了，最近买了个新手机，可以把一些常用的句子存在手机里，要用的时候，直接拿出来，在前面加上MM的名字就可以发送了，再不用一个字一个字敲了。共享的句子就是Flyweight，MM的名字就是提取出来的外部特征，根据上下文情况使用。<br /><br />享元模式：FLYWEIGHT在拳击比赛中指最轻量级。享元模式以共享的方式高效的支持大量的细粒度对象。享元模式能做到共享的关键是区分内蕴状态和外蕴状态。内蕴状态存储在享元内部，不会随环境的改变而有所不同。外蕴状态是随环境的改变而改变的。外蕴状态不能影响内蕴状态，它们是相互独立的。将可以共享的状态和不可以共享的状态从常规类中区分开来，将不可以共享的状态从类里剔除出去。客户端不可以直接创建被共享的对象，而应当使用一个工厂对象负责创建被共享的对象。享元模式大幅度的降低内存中对象的数量。<br /><br />12、PROXY—跟MM在网上聊天，一开头总是“hi,你好”,“你从哪儿来呀？”“你多大了？”“身高多少呀？”这些话，真烦人，写个程序做为我的Proxy吧，凡是接收到这些话都设置好了自动的回答，接收到其他的话时再通知我回答，怎么样，酷吧。<br /><br />代理模式：代理模式给某一个对象提供一个代理对象，并由代理对象控制对源对象的引用。代理就是一个人或一个机构代表另一个人或者一个机构采取行动。某些情况下，客户不想或者不能够直接引用一个对象，代理对象可以在客户和目标对象直接起到中介的作用。客户端分辨不出代理主题对象与真实主题对象。代理模式可以并不知道真正的被代理对象，而仅仅持有一个被代理对象的接口，这时候代理对象不能够创建被代理对象，被代理对象必须有系统的其他角色代为创建并传入。<br /><br />行为模式<br /><br />13、CHAIN OF RESPONSIBLEITY—晚上去上英语课，为了好开溜坐到了最后一排，哇，前面坐了好几个漂亮的MM哎，找张纸条，写上“Hi,可以做我的女朋友吗？如果不愿意请向前传”，纸条就一个接一个的传上去了，糟糕，传到第一排的MM把纸条传给老师了，听说是个老处女呀，快跑!<br /><br />责任链模式：在责任链模式中，很多对象由每一个对象对其下家的引用而接<br /><br />起来形成一条链。请求在这个链上传递，直到链上的某一个对象决定处理此请求。客户并不知道链上的哪一个对象最终处理这个请求，系统可以在不影响客户端的情况下动态的重新组织链和分配责任。处理者有两个选择：承担责任或者把责任推给下家。一个请求可以最终不被任何接收端对象所接受。<br /><br />14、COMMAND—俺有一个MM家里管得特别严，没法见面，只好借助于她弟弟在我们俩之间传送信息，她对我有什么指示，就写一张纸条让她弟弟带给我。这不，她弟弟又传送过来一个COMMAND，为了感谢他，我请他吃了碗杂酱面，哪知道他说：“我同时给我姐姐三个男朋友送COMMAND，就数你最小气，才请我吃面。”，<br /><br />命令模式：命令模式把一个请求或者操作封装到一个对象中。命令模式把发出命令的责任和执行命令的责任分割开，委派给不同的对象。命令模式允许请求的一方和发送的一方独立开来，使得请求的一方不必知道接收请求的一方的接口，更不必知道请求是怎么被接收，以及操作是否执行，何时被执行以及是怎么被执行的。系统支持命令的撤消。<br /><br />15、INTERPRETER—俺有一个《泡MM真经》，上面有各种泡MM的攻略，比如说去吃西餐的步骤、去看电影的方法等等，跟MM约会时，只要做一个Interpreter，照着上面的脚本执行就可以了。<br /><br />解释器模式：给定一个语言后，解释器模式可以定义出其文法的一种表示，并同时提供一个解释器。客户端可以使用这个解释器来解释这个语言中的句子。解释器模式将描述怎样在有了一个简单的文法后，使用模式设计解释这些语句。在解释器模式里面提到的语言是指任何解释器对象能够解释的任何组合。在解释器模式中需要定义一个代表文法的命令类的等级结构，也就是一系列的组合规则。每一个命令对象都有一个解释方法，代表对命令对象的解释。命令对象的等级结构中的对象的任何排列组合都是一个语言。<br /><br /><br /><br />16、ITERATOR—我爱上了Mary，不顾一切的向她求婚。<br /><br />Mary：“想要我跟你结婚，得答应我的条件”<br /><br />我：“什么条件我都答应，你说吧”<br /><br />Mary：“我看上了那个一克拉的钻石”<br /><br />我：“我买，我买，还有吗？”<br /><br />Mary：“我看上了湖边的那栋别墅”<br /><br />我：“我买，我买，还有吗？”<br /><br />Mary：“你的小弟弟必须要有50cm长”<br /><br />我脑袋嗡的一声，坐在椅子上，一咬牙：“我剪，我剪，还有吗？”<br /><br />……<br /><br />迭代子模式：迭代子模式可以顺序访问一个聚集中的元素而不必暴露聚集的内部表象。多个对象聚在一起形成的总体称之为聚集，聚集对象是能够包容一组对象的容器对象。迭代子模式将迭代逻辑封装到一个独立的子对象中，从而与聚集本身隔开。迭代子模式简化了聚集的界面。每一个聚集对象都可以有一个或一个以上的迭代子对象，每一个迭代子的迭代状态可以是彼此独立的。迭代算法可以独立于聚集角色变化。<br /><br />17、MEDIATOR—四个MM打麻将，相互之间谁应该给谁多少钱算不清楚了，幸亏当时我在旁边，按照各自的筹码数算钱，赚了钱的从我这里拿，赔了钱的也付给我，一切就OK啦，俺得到了四个MM的电话。<br /><br />调停者模式：调停者模式包装了一系列对象相互作用的方式，使得这些对象不必相互明显作用。从而使他们可以松散偶合。当某些对象之间的作用发生改变时，不会立即影响其他的一些对象之间的作用。保证这些作用可以彼此独立的变化。调停者模式将多对多的相互作用转化为一对多的相互作用。调停者模式将对象的行为和协作抽象化，把对象在小尺度的行为上与其他对象的相互作用分开处理。<br /><br />18、MEMENTO—同时跟几个MM聊天时，一定要记清楚刚才跟MM说了些什么话，不然MM发现了会不高兴的哦，幸亏我有个备忘录，刚才与哪个MM说了什么话我都拷贝一份放到备忘录里面保存，这样可以随时察看以前的记录啦。<br /><br />备忘录模式：备忘录对象是一个用来存储另外一个对象内部状态的快照的对象。备忘录模式的用意是在不破坏封装的条件下，将一个对象的状态捉住，并外部化，存储起来，从而可以在将来合适的时候把这个对象还原到存储起来的状态。<br /><br />19、OBSERVER—想知道咱们公司最新MM情报吗？加入公司的MM情报邮件组就行了，tom负责搜集情报，他发现的新情报不用一个一个通知我们，直接发布给邮件组，我们作为订阅者（观察者）就可以及时收到情报啦<br /><br />观察者模式：观察者模式定义了一种一队多的依赖关系，让多个观察者对象同时监听某一个主题对象。这个主题对象在状态上发生变化时，会通知所有观察者对象，使他们能够自动更新自己。<br /><br />20、STATE—跟MM交往时，一定要注意她的状态哦，在不同的状态时她的行为会有不同，比如你约她今天晚上去看电影，对你没兴趣的MM就会说“有事情啦”，对你不讨厌但还没喜欢上的MM就会说“好啊，不过可以带上我同事么？”，已经喜欢上你的MM就会说“几点钟？看完电影再去泡吧怎么样？”，当然你看电影过程中表现良好的话，也可以把MM的状态从不讨厌不喜欢变成喜欢哦。<br /><br />状态模式：状态模式允许一个对象在其内部状态改变的时候改变行为。这个对象看上去象是改变了它的类一样。状态模式把所研究的对象的行为包装在不同的状态对象里，每一个状态对象都属于一个抽象状态类的一个子类。状态模式的意图是让一个对象在其内部状态改变的时候，其行为也随之改变。状态模式需要对每一个系统可能取得的状态创立一个状态类的子类。当系统的状态变化时，系统便改变所选的子类。<br /><br />21、STRATEGY—跟不同类型的MM约会，要用不同的策略，有的请电影比较好，有的则去吃小吃效果不错，有的去海边浪漫最合适，单目的都是为了得到MM的芳心，我的追MM锦囊中有好多Strategy哦。<br /><br />策略模式：策略模式针对一组算法，将每一个算法封装到具有共同接口的独立的类中，从而使得它们可以相互替换。策略模式使得算法可以在不影响到客户端的情况下发生变化。策略模式把行为和环境分开。环境类负责维持和查询行为类，各种算法在具体的策略类中提供。由于算法和环境独立开来，算法的增减，修改都不会影响到环境和客户端。<br /><br />22、TEMPLATE METHOD——看过《如何说服女生上床》这部经典文章吗？女生从认识到上床的不变的步骤分为巧遇、打破僵局、展开追求、接吻、前戏、动手、爱抚、进去八大步骤(Template method)，但每个步骤针对不同的情况，都有不一样的做法，这就要看你随机应变啦(具体实现)；<br /><br />模板方法模式：模板方法模式准备一个抽象类，将部分逻辑以具体方法以及具体构造子的形式实现，然后声明一些抽象方法来迫使子类实现剩余的逻辑。不同的子类可以以不同的方式实现这些抽象方法，从而对剩余的逻辑有不同的实现。先制定一个顶级逻辑框架，而将逻辑的细节留给具体的子类去实现。<br /><br />23、VISITOR—情人节到了，要给每个MM送一束鲜花和一张卡片，可是每个MM送的花都要针对她个人的特点，每张卡片也要根据个人的特点来挑，我一个人哪搞得清楚，还是找花店老板和礼品店老板做一下Visitor，让花店老板根据MM的特点选一束花，让礼品店老板也根据每个人特点选一张卡，这样就轻松多了；<br /><br />访问者模式：访问者模式的目的是封装一些施加于某种数据结构元素之上的操作。一旦这些操作需要修改的话，接受这个操作的数据结构可以保持不变。访问者模式适用于数据结构相对未定的系统，它把数据结构和作用于结构上的操作之间的耦合解脱开，使得操作集合可以相对自由的演化。访问者模式使得增加新的操作变的很容易，就是增加一个新的访问者类。访问者模式将有关的行为集中到一个访问者对象中，而不是分散到一个个的节点类中。当使用访问者模式时，要将尽可能多的对象浏览逻辑放在访问者类中，而不是放到它的子类中。访问者模式可以跨过几个类的等级结构访问属于不同的等级结构的成员类。
          <br/>
          <span style="color:red;">
            <a href="http://bufanliu.javaeye.com/blog/229862#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Mon, 18 Aug 2008 16:54:54 +0800</pubDate>
        <link>http://bufanliu.javaeye.com/blog/229862</link>
        <guid>http://bufanliu.javaeye.com/blog/229862</guid>
      </item>
      <item>
        <title>几种流行的AJAX框架jQuery,Mootools,Dojo,Ext JS的对比</title>
        <author>bufanliu</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://bufanliu.javaeye.com">bufanliu</a>&nbsp;
          链接：<a href="http://bufanliu.javaeye.com/blog/229861" style="color:red;">http://bufanliu.javaeye.com/blog/229861</a>&nbsp;
          发表时间: 2008年08月18日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          AJAX是web20的基石，现在网上流行几种开源的AJAX框架，比如：jQuery,Mootools,Dojo,Ext JS等等，那么我们到底在什么情况下该使用那个框架？以下是一组摘抄的数据：<br /><br />Ajaxian在2007年底对Ajax工具进行了调查，部分调查结果见下表（其中数字为调查者使用该工具的百分比，详细的请参见网页）：http://ajaxian.com/archives/2007-ajax-tools-usage-survey-results<br /><br />Prototype jQuery Ext Script.aculo.us Mootools YUI JSON Dojo Backbase <br />34.1% 29.3% 22.5% 22.3% 14.3% 13% 12.9% 11.8% 8.3% <br /><br />其中Prototype使用率最高，很大程度上是因为它是最早成熟的框架，很多以前在项目中采用，所以现在一直在用<br /><br />让我们来看看选择AJAX框架的基础：<br /><br />你的项目需求（即你需要哪些特性，例如是否要求做出精美的界面、特效或其它功能）<br />是否支持A等级的浏览器（IE, Firefox等）?<br />文档的质量：是否完善（包含教程，API，代码示例等）<br />框架的可扩展性如何？为框架写插件容易吗？<br />你是否喜欢它的API的风格？<br />能大多程度上统一你的JavaScript代码的风格？<br />框架大小（太大的框架导致用户下载时间的延长）<br />框架是否强迫你改变写HTML的方式（Dojo就是这样）？<br />代码执行速度：性能如何？<br />代码是否为模块化（Mootools为高度模块化）？代码可重用性如何？<br /><br />一、jQuery<br />主页：http://jquery.com/<br />设计思想<br />简洁的思想：几乎所有操作都是以选择DOM元素（有强大的Selector）开始，然后是对其的操作（Chaining等特性）。<br /><br />优点<br />小，压缩后代码只有20多k（无压缩代码94k）。<br />Selector和DOM操作的方便：jQuery的Selector与mootools的Element.Selectors.js比较，CSS Selector, XPath Selector（1.2后已删除）<br />Chaining：总是返回一个jQuery对象，可以连续操作。<br />文档的完整，易用性（每个API都有完整的例子，这是其它框架现在不能比的），而且网上还有很多其它的文档，书籍。<br />应用的广泛，包括google code也使用了jQuery。<br /><br />使用jQuery的站点：http://docs.jquery.com/Sites_Using_jQuery<br />核心的开发团队和核心人员：John Resig等。<br />简洁和简短的语法，容易记。<br />可扩展性：有大量用户开发的插件可供使用（http://jquery.com/plugins/）<br />jQuery UI（http://jquery.com/plugins/，基于jQuery，但和核心的jQuery是独立的），不断发展中。<br />友好和活跃的社区：google groups: http://docs.jquery.com/Discussion<br />事件处理有很多方便的方法，如click，而不是单一的addEvent之类的。<br /><br />缺点<br />由于设计思想是追求高效和简洁，没有面向对象的扩展。设计思路和Mootools不一样。<br />CSS Selector的速度稍微有些慢（但是现在速度已经大幅提高）<br /><br /><br />Mootools<br />主页：http://mootools.net/<br />设计思想<br />面向对象的设计思想。<br /><br />优点<br />模块化，各模块代码非常独立，最小的核心只有8k，最大的优点是可选择使用哪些模块，用的时候只导入使用的模块即可，完整的也不到180k（没有压缩），压缩后不到70k。<br />语法的简洁，直观。<br />特效（Effects）：这一点比jQuery稍强，现在也正在开发Mootools UI（这应该是Ajax框架开发的一个趋势）。<br />代码写的优美，易阅读和修改。<br />文档的完整（最新的1.2beta的文档比以前更详细）。<br />活跃的社区：官网(http://forum.mootools.net/)，还有一个IRC。<br />性能：见：http://mootools.net/slickspeed/<br /><br />缺点<br />修改了低层的一些类：如Array, String等，这也是设计思想的不同。<br />在DOM和CSS Selector上不如jQuery强大。<br /><br /><br />Dojo<br />主页：http://dojotoolkit.org/<br /><br /><br />优点<br />背后强大的支持：IBM、Sun、BEA等，这是非常重要的优势。<br />功能的强大，Full Stack的框架，扩展了DHTML的能力，例如：<br />支持与浏览器Back/Forward按钮的集成。<br />Dojo Offline，一个跨平台的离线存储API。<br />Chart组件，可以方便地在浏览器端生成图表。<br />基于SVG/VML的矢量图形库。<br />Google Maps、Yahoo! Maps组件，方便开发Mashup应用。<br />Comet支持，通过通用的Buyeux协议。<br />强大的UI（Dijit）。<br />面向对象的设计，统一的命名空间，包管理机制（The Package System and Custom Builds）<br />可扩展性。<br /><br />缺点<br />复杂，学习曲线陡。<br />文档的极端不全，这是一个很大的问题。<br />API很多不稳定，各版本间改动较大，现在还不是一个成熟的框架。<br />侵入性太大，页面中大量使用dojo的属性，例如&lt;button dojoType="dijit.form.Button" id="helloButton">，如果将来dojo升级或者换一个框架时，负担会很大。<br />性能问题，由于dojo加载采用了同步的机制，会暂时锁定浏览器，导致CPU使用率达到100%。另外，很多Widget的速度很慢。<br /><br /><br />Ext JS<br />主页：http://extjs.com/<br /><br /><br />设计思想<br />组件化，推进RIA（Rich Internet Application）的应用。<br /><br />优点<br />强大的UI，而且性能不错，这是其最大的优点。<br />速度快，管是UI还是其它模块。<br />100%面向对象和组件化的思想，一致的语法，全局的命名空间。<br />文档的完整，规范，方便。<br />核心的开发团队，Jack Slocum等。<br />活跃的社区，迅速增加的用户量。<br />模块化实现，可扩展性强。<br />所有的组件（widgets）都可直接使用，而无需进行设置（当然，用户可以选择重新配置）。<br /><br />缺点<br />稍复杂。<br />为重量级的框架（包含大量UI），体积大。如果导入ext-all.js，压缩后也有近500k。<br /><br />注意：EXT的商业使用：如果只是把extjs包含在自己的项目中，而且这个项目不是卖给用户做二次开发的工具箱，或组件库，就可以遵守LGPL协议免费使用；否则要付费。<br /><br /><br />总结<br />轻量级选择<br />轻量级的选择：主要是mootools和jquery，由于它们的设计思想的不同，jQuery是追求简洁和高效，Mootools除了追求这些目标以外，其核心在于面向对象，所以jQuery适合于快速开发，Mootools适合于稍大型和复杂的项目，其中需要面向对象的支持；另外，在Ajax的支持上，jQuery稍强一些；在Comet的支持上，jQuery有相关的插件，Mootools目前没有，但是Comet的核心在于服务器的支持，浏览器端的接口很简单，开发相关的插件很简单。<br /><br />在面向对象的Javascript Library中，mootools逐渐战胜了prototype（体积大，面向对象的设计不合理等），也包括script.acul.ous（基于prototype，实际上就是prototype上的UI库）。<br /><br />面向RIA的框架<br /><br />考虑纯JavaScripty库，目前主要是Dojo和ExtJS（还有YUI）。Dojo更适合企业应用和产品开发的需要，因为离线存储、 DataGrid、2D、3D图形、Chart、Comet等组件对于企业应用来说都是很重要的（当然这些组件还要等一段时间才能稳定下来）。例如，BEA基于Mashup技术开发的产品中已经使用了Dojo。<br /><br />ExtJS：美观和"易用"，并且足够强大。在对UI有比较大的需求时，是首选。
          <br/>
          <span style="color:red;">
            <a href="http://bufanliu.javaeye.com/blog/229861#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Mon, 18 Aug 2008 16:53:03 +0800</pubDate>
        <link>http://bufanliu.javaeye.com/blog/229861</link>
        <guid>http://bufanliu.javaeye.com/blog/229861</guid>
      </item>
      <item>
        <title>CSS技巧集合</title>
        <author>bufanliu</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://bufanliu.javaeye.com">bufanliu</a>&nbsp;
          链接：<a href="http://bufanliu.javaeye.com/blog/227982" style="color:red;">http://bufanliu.javaeye.com/blog/227982</a>&nbsp;
          发表时间: 2008年08月14日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          一.使用css缩写<br /><br />　　使用缩写可以帮助减少你CSS文件的大小，更加容易阅读。css缩写的主要规则请参看《常用css缩写语法总结》，这里就不展开描述。<br /><br />　　二.明确定义单位，除非值为0<br /><br />　　忘记定义尺寸的单位是CSS新手普遍的错误。在HTML中你可以只写width="100"，但是在CSS中，你必须给一个准确的单位，比如：width:100px width:100em。只有两个例外情况可以不定义单位：行高和0值。除此以外，其他值都必须紧跟单位，注意，不要在数值和单位之间加空格。<br /><br />　　三.区分大小写<br /><br />　　当在XHTML中使用CSS，CSS里定义的元素名称是区分大小写的。为了避免这种错误，我建议所有的定义名称都采用小写。<br /><br />　　class和id的值在HTML和XHTML中也是区分大小写的，如果你一定要大小写混合写，请仔细确认你在CSS的定义和XHTML里的标签是一致的。<br /><br />　　四.取消class和id前的元素限定<br /><br />　　当你写给一个元素定义class或者id，你可以省略前面的元素限定，因为ID在一个页面里是唯一的，而clas s可以在页面中多次使用。你限定某个元素毫无意义。例如：<br /><br />　　div#content { /* declarations */ } <br />　　fieldset.details { /* declarations */ } <br /><br />　　可以写成<br /><br />　　#content { /* declarations */ } <br />　　.details { /* declarations */ } <br />　<br />　　这样可以节省一些字节。<br /><br />　　五.默认值<br /><br />　　通常padding的默认值为0，background-color的默认值是transparent。但是在不同的浏览器默认值可能不同。如果怕有冲突，可以在样式表一开始就先定义所有元素的margin和padding值都为0，象这样：<br /><br />　　* { <br />　　　　margin:0; <br />　　　　padding:0; <br />　　　} <br /><br />　　六.不需要重复定义可继承的值<br /><br />　　CSS中，子元素自动继承父元素的属性值，象颜色、字体等，已经在父元素中定义过的，在子元素中可以直接继承，不需要重复定义。但是要注意，浏览器可能用一些默认值覆盖你的定义。<br /><br />　　七.最近优先原则<br /><br />　　如果对同一个元素的定义有多种，以最接近(最小一级)的定义为最优先，例如有这么一段代码<br /><br />　　Update: Lorem ipsum dolor set<br /><br />　　在CSS文件中，你已经定义了元素p，又定义了一个class"update"<br /><br />　　p { <br />　　　　margin:1em 0; <br />　　　　font-size:1em; <br />　　　　color:#333; <br />　　　} <br />　　.update { <br />　　　　　　　font-weight:bold; <br />　　　　　　　color:#600; <br />　　　　　　　} <br /><br />　　这两个定义中，class="update"将被使用，因为class比p更近。你可以查阅W3C的《 Calculating a selector’s specificity》 了解更多。<br /><br />　　八.多重class定义<br /><br />　　一个标签可以同时定义多个class。例如：我们先定义两个样式，第一个样式背景为#666；第二个样式有10 px的边框。<br /><br />　　.one{width:200px;background:#666;}<br />　　.two{border:10px solid #F00;} <br /><br />　　在页面代码中，我们可以这样调用<br /><br />　　&lt;div class="one two">&lt;/div> <br /><br />　　这样最终的显示效果是这个div既有#666的背景，也有10px的边框。是的，这样做是可以的，你可以尝试一下。<br /><br />　　九.使用子选择器(descendant selectors)<br /><br />　　CSS初学者不知道使用子选择器是影响他们效率的原因之一。子选择器可以帮助你节约大量的class定义。我们来看下面这段代码：<br /><br />　　&lt;div id="subnav"> <br />　　&lt;ul> <br />　　&lt;li class="subnavitem"> &lt;a href="#" class="subnavitem">Item 1&lt;/a>&lt;/li>> <br />　　&lt;li class="subnavitemselected"> &lt;a href="#" class="subnavitemselected"> Item 1&lt;/a> &lt;/li> <br />　　&lt;li class="subnavitem"> &lt;a href="#" class="subnavitem"> Item 1&lt;/a> &lt;/li><br />　　&lt;/ul> <br />　　&lt;/div> <br /><br />　　这段代码的CSS定义是：<br /><br />　　div#subnav ul { /* Some styling */ } <br />　　div#subnav ul li.subnavitem { /* Some styling */ } <br />　　div#subnav ul li.subnavitem a.subnavitem { /* Some styling */ } <br />　　div#subnav ul li.subnavitemselected { /* Some styling */ } <br />　　div#subnav ul li.subnavitemselected a.subnavitemselected { /* Some styling */ } <br /><br />　　你可以用下面的方法替代上面的代码<br /><br />　　&lt;ul id="subnav"> <br />　　&lt;li> &lt;a href="#"> Item 1&lt;/a> &lt;/li> <br />　　&lt;li class="sel"> &lt;a href="#"> Item 1&lt;/a> &lt;/li> <br />　　&lt;li> &lt;a href="#"> Item 1&lt;/a> &lt;/li> <br />　　&lt;/ul> <br /><br />　　样式定义是：<br /><br />　　#subnav { /* Some styling */ } <br />　　#subnav li { /* Some styling */ } <br />　　#subnav a { /* Some styling */ } <br />　　#subnav .sel { /* Some styling */ } <br />　　#subnav .sel a { /* Some styling */ } <br /><br />　　用子选择器可以使你的代码和CSS更加简洁、更加容易阅读。<br /><br />　　十.不需要给背景图片路径加引号<br /><br />　　为了节省字节，我建议不要给背景图片路径加引号，因为引号不是必须的。例如：<br /><br />　　background:url("images/***.gif") #333; <br /><br />　　可以写为<br /><br />　　background:url(images/***.gif) #333; <br /><br />　　如果你加了引号，反而会引起一些浏览器的错误。<br /><br />　　十一.组选择器(Group selectors)<br /><br />　　当一些元素类型、class或者id都有共同的一些属性，你就可以使用组选择器来避免多次的重复定义。这可以节省不少字节。<br /><br />　　例如：定义所有标题的字体、颜色和margin，你可以这样写：<br /><br />　　h1,h2,h3,h4,h5,h6 { <br />　　　　　　　　　　　　　font-family:"Lucida Grande",Lucida,Arial,Helvetica,sans-serif; <br />　　　　　　　　　　　　　color:#333;　 <br />　　　　　　　　　　　　　margin:1em 0; <br />　　　　　　　　　　　　　} <br /><br />　　如果在使用时，有个别元素需要定义独立样式，你可以再加上新的定义，可以覆盖老的定义，例如：<br /><br />　　h1 { font-size:2em; } <br />　　h2 { font-size:1.6em; } <br /><br />　　十二.用正确的顺序指定链接的样式<br /><br />　　当你用CSS来定义链接的多个状态样式时，要注意它们书写的顺序，正确的顺序是：:link :visited :hover :active。抽取第一个字母是"LVHA"，你可以记忆成"LoVe HAte"(喜欢讨厌)。为什么这么定义，可以参考Eric Meyer的《Link Specificity》。<br /><br />　　如果你的用户需要用键盘来控制，需要知道当前链接的焦点，你还可以定义:focus属性。:focus属性的效果也取决与你书写的位置，如果你希望聚焦元素显示:hover效果，你就把:focus写在:hover前面；如果你希望聚焦效果替代:hover效果，你就把:focus放在:hover后面。<br /><br />　　十三.清除浮动<br /><br />　　一个非常常见的CSS问题，定位使用浮动的时候，下面的层被浮动的层所覆盖，或者层里嵌套的子层超出了外层的范围。<br /><br />　　通常的解决办法是在浮动层后面添加一个额外元素，例如一个div或者一个br，并且定义它的样式为clear: both。这个办法有一点牵强，幸运的是还有一个好办法可以解决，参看这篇文章《How To Clear Floats Without Structural Markup》(注：本站将尽快翻译此文)。<br /><br />　　上面2种方法可以很好解决浮动超出的问题，但是如果当你真的需要对层或者层里的对象进行clear的时候怎么办？一种简单的方法就是用overflow属性，这个方法最初的发表在《Simple Clearing of Floats》，又在《Clearance》和《Super simple clearing floats》中被广泛讨论。<br /><br />　　上面那一种clear方法更适合你，要看具体的情况，这里不再展开论述。另外关于float的应用，一些优秀的文章已经说得很清楚，推荐你阅读：《Floatutorial》、《Containing Floats》和《Float Layouts》<br /><br />　　十四.横向居中(centering)<br /><br />　　这是一个简单的技巧，但是值得再说一遍，因为我看见太多的新手问题都是问这个：CSS如何横向居中？你需要定义元素的宽，并且定义横向的margin，如果你的布局包含在一个层(容器)中，就象这样：<br /><br />　　你可以这样定义使它横向居中：<br /><br />　　#wrap　{ <br />　　　　　　width:760px; /* 修改为你的层的宽度 */ <br />　　　　　　margin:0 auto; <br />　　　　　　} <br /><br />　　但是IE5/Win不能正确显示这个定义，我们采用一个非常有用的技巧来解决：用text-align属性。就象这样：<br /><br />　　body　{ <br />　　　　　　text-align:center; <br />　　　　　　} <br />　　#wrap { <br />　　　　　　width:760px; /* 修改为你的层的宽度 */ <br />　　　　　　margin:0 auto; <br />　　　　　　text-align:left; <br />　　　　　　} <br /><br />　　第一个body的text-align:center; 规则定义IE5/Win中body的所有元素居中(其他浏览器只是将文字居中) ，第二个text-align:left;是将#warp中的文字居左。<br /><br />　　十五.导入(Import)和隐藏CSS<br /><br />　　因为老版本浏览器不支持CSS，一个通常的做法是使用@import技巧来把CSS隐藏起来。例如：<br /><br />　　@import url("main.css"); <br /><br />　　然而，这个方法对IE4不起作用，这让我很是头疼了一阵子。后来我用这样的写法：<br /><br />　　@import "main.css"; <br /><br />　　这样就可以在IE4中也隐藏CSS了，呵呵，还节省了5个字节呢。想了解@import语法的详细说明，可以看这里《centricle’s css filter chart》<br /><br />　　十六.针对IE的优化<br /><br />　　有些时候，你需要对IE浏览器的bug定义一些特别的规则，这里有太多的CSS技巧(hacks)，我只使用其中的两种方法，不管微软在即将发布的IE7 beta版里是否更好的支持CSS，这两种方法都是最安全的。<br /><br />　　1.注释的方法 <br /><br />　　(a)在IE中隐藏一个CSS定义，你可以使用子选择器(child selector):<br /><br />　　html>body p { <br />　　　　　　　　　　/* 定义内容 */ <br />　　　　　　　　　} <br /><br />　　(b)下面这个写法只有IE浏览器可以理解(对其他浏览器都隐藏) <br /><br />　　* html p　{ <br />　　　　　　　　/* declarations */ <br />　　　　　　　　} <br /><br />　　(c)还有些时候，你希望IE/Win有效而IE/Mac隐藏，你可以使用"反斜线"技巧：<br /><br />　　/* \*/ <br />　　* html p　{ <br />　　　　　　　　declarations <br />　　　　　　　　} <br />　　/* */ 　<br /><br />　　2.条件注释(conditional comments)的方法 <br /><br />　　另外一种方法，我认为比CSS　Hacks更加经得起考验就是采用微软的私有属性条件注释(conditional comments)。用这个方法你可以给IE单独定义一些样式，而不影响主样式表的定义。就象这样：<br /><br />　　&lt;!--[if IE]> <br />　　&lt;link rel="stylesheet" type="text/css" href="ie.css" /> <br />　　&lt;![endif]--> <br /><br />　　十七.调试技巧：层有多大？<br /><br />　　当调试CSS发生错误，你就要象排版工人，逐行分析CSS代码。我通常在出问题的层上定义一个背景颜色，这样就能很明显看到层占据多大空间。有些人建议用border，一般情况也是可以的，但问题是，有时候border 会增加元素的尺寸，border-top和boeder-bottom会破坏纵向margin的值，所以使用background更加安全些。 <br /><br />　　另外一个经常出问题的属性是outline。outline看起来象boeder，但不会影响元素的尺寸或者位置。只有少数浏览器支持outline属性，我所知道的只有Safari、OmniWeb、和Opera。<br /><br />　　十八.CSS代码书写样式<br /><br />　　在写CSS代码的时候，对于缩进、断行、空格，每个人有每个人的书写习惯。在经过不断实践后，我决定采用下面这样的书写样式：<br /><br />　　selector1, <br />　　selector2 { <br />　　　　　　　　property:value; <br />　　　　　　　　} <br /><br />　　当使用联合定义时，我通常将每个选择器单独写一行，这样方便在CSS文件中找到它们。在最后一个选择器和大括号{之间加一个空格，每个定义也单独写一行，分号直接在属性值后，不要加空格。<br /><br />　　我习惯在每个属性值后面都加分号，虽然规则上允许最后一个属性值后面可以不写分号，但是如果你要加新样式时容易忘记补上分号而产生错误，所以还是都加比较好。<br /><br />　　最后，关闭的大括号}单独写一行。<br /><br />　　空格和换行有助与阅读。
          <br/>
          <span style="color:red;">
            <a href="http://bufanliu.javaeye.com/blog/227982#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Thu, 14 Aug 2008 13:08:22 +0800</pubDate>
        <link>http://bufanliu.javaeye.com/blog/227982</link>
        <guid>http://bufanliu.javaeye.com/blog/227982</guid>
      </item>
      <item>
        <title>IE6下png图片和png背景透明</title>
        <author>bufanliu</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://bufanliu.javaeye.com">bufanliu</a>&nbsp;
          链接：<a href="http://bufanliu.javaeye.com/blog/227980" style="color:red;">http://bufanliu.javaeye.com/blog/227980</a>&nbsp;
          发表时间: 2008年08月14日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <a href="http://www.163show.cn/blog/index.html" target="_blank">http://www.163show.cn/blog/index.html</a><br />应用PNG图片的透明或半透明的特性能做出非常漂亮的网页来。Firefox和Opera对PNG的支持非常的好，都是IE却无视PNG图片这一特性的“存在”，虽然IE7已经支持都是IE6还是不行。查了一些资料，基本解决了这一问题，准备应用到PJskin上。<br />虽然有让IE6支持PNG透明背景的JS程序，都是不是很方便，还是用CSS来实现的好。使用到的就是：<br />IE5.5+的AlphaImageLoader滤镜<br /><br />语法：<br />filter : progid:DXImageTransform.Microsoft.AlphaImageLoader ( enabled=bEnabled , sizingMethod=sSize , src=sURL ) <br />属性：<br />enabled : 可选项。布尔值(Boolean)。设置或检索滤镜是否激活。true | false <br />　　　　　　true : 默认值。滤镜激活。 <br />　　　　　　false : 滤镜被禁止。 <br /><br />sizingMethod : 可选项。字符串(String)。设置或检索滤镜作用的对象的图片在对象容器边界内的显示方式。 crop : 剪切图片以适应对象尺寸。 <br />　　　　　　　　image : 默认值。增大或减小对象的尺寸边界以适应图片的尺寸。 <br />　　　　　　　　scale : 缩放图片以适应对象的尺寸边界。 <br />　　　　　　　　src : 必选项。字符串(String)。使用绝对或相对 url 地址指定背景图像。假如忽略此参数，滤镜将不会作用。 <br /><br />说明：<br />在对象容器边界内，在对象的背景和内容之间显示一张图片。并提供对此图片的剪切和改变尺寸的操作。如果载入的是PNG(Portable Network Graphics)格式，则0%-100%的透明度也被提供。<br />PNG(Portable Network Graphics)格式的图片的透明度不妨碍你选择文本。也就是说，你可以选择显示在PNG(Portable Network Graphics)格式的图片完全透明区域后面的内容。<br /><br /><br />了解了以上的内容，可以写一段简单的CSS代码（还不是完全正确的代码）：<br /><br />#div1 {<br />   height: 600px;<br />   width: 260px;<br />   padding: 20px;<br />   background-repeat: repeat;<br />   filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true, sizingMethod=scale, src="bj1.png"<br /><br />}<br /><br /><br /><br />这段简单的CSS代码就可以在IE中正常的显示PNG透明背景，但是会发现在FF下不会出现背景，分析原因：<br />AlphaImageLoader滤镜只能被IE支持，FF是不支持该滤镜的<br />有些初次写的时候很多人会这样：<br />在代码中添加这样一段： background-image: url(bj1.png);<br />添加这样一段代码虽然能解决FF下的问题，都是IE又出现问题：新的背景会覆盖在滤镜的背景之上，导致滤镜显示无效，这时候就用到IE和FF对CSS读取的区别特性了：<br />Firefox、Opera等完全支持PNG透明图片的浏览器也支持子选择器（>），而IE不识别（包括IE7），所有我们可以通过这来定义Firefox、Opera等浏览器中PNG图片的样式。代码如下：<br /><br />html>body #div1 {<br />   background-repeat: repeat;background-image: url(bj1.png);<br />}<br /><br /><br />同时，我们通过只有IE才识别的通配符（*），来定义IE浏览器中的滤镜。代码如下：<br /><br />* #div1 {filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true, sizingMethod=scale, src="bj1.png")<br /><br />}<br /><br /><br />而#div1 {}就放一些IE和FF共用的设置来减少代码文件的大小。最终就是这样：<br /><br />#div1 {<br />   height: 600px;<br />   width: 260px;<br />   padding: 20px;<br />   background-repeat: repeat;<br />   <br /><br />}<br /><br />/* for ie7 ff*/<br />html>body #div1 {<br />    background:url(../images/menu1.png) no-repeat;<br />}<br />/* for ie6 */<br />* #div1 {<br />    background:none;<br />    filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src='images/menu1.png', sizingMethod='crop');<br />}<br /><br />需要注意的是：AlphaImageLoader滤镜会导致该区域的链接和按钮无效，解决的办法是为链接或按钮添加：position: relative;这样条代码，使其相对浮动。AlphaImageLoader无法设置背景的重复，所以对图片的切图精度会有很高的精确度要求。 <br />--------------------------------------------------------------------<br />如果在网页中直接插入png图片想使其透明只需加入以下js代码，整个页面内的所有直接插入的png图片都可以实现透明：<br /><br />&lt;script language="JavaScript"><br />function correctPNG() // correctly handle PNG transparency in Win IE 5.5 & 6.<br />{<br />    var arVersion = navigator.appVersion.split("MSIE")<br />    var version = parseFloat(arVersion[1])<br />    if ((version >= 5.5) && (document.body.filters)) <br />    {<br />       for(var j=0; j&lt;document.images.length; j++)<br />       {<br />          var img = document.images[j]<br />          var imgName = img.src.toUpperCase()<br />          if (imgName.substring(imgName.length-3, imgName.length) == "PNG")<br />          {<br />             var imgID = (img.id) ? "id='" + img.id + "' " : ""<br />             var imgClass = (img.className) ? "class='" + img.className + "' " : ""<br />             var imgTitle = (img.title) ? "title='" + img.title + "' " : "title='" + img.alt + "' "<br />             var imgStyle = "display:inline-block;" + img.style.cssText <br />             if (img.align == "left") imgStyle = "float:left;" + imgStyle<br />             if (img.align == "right") imgStyle = "float:right;" + imgStyle<br />             if (img.parentElement.href) imgStyle = "cursor:hand;" + imgStyle<br />             var strNewHTML = "&lt;span " + imgID + imgClass + imgTitle<br />             + " style=\"" + "width:" + img.width + "px; height:" + img.height + "px;" + imgStyle + ";"<br />             + "filter:progid:DXImageTransform.Microsoft.AlphaImageLoader"<br />             + "(src=\'" + img.src + "\', sizingMethod='scale');\">&lt;/span>" <br />             img.outerHTML = strNewHTML<br />             j = j-1<br />          }<br />       }<br />    }    <br />}<br />window.attachEvent("onload", correctPNG);<br />&lt;/script><br /><br />--------------------------------------------------------------------<br /><br />如果是想使用png做背景透明的话，需要用到css滤镜和hack：<br /><br />html>body .png { background:url(1.png); width:300px; height:100px; border:#000 solid 1px;}<br /><br />/* ie6 */* html .png { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true, sizingMethod=scale, src='1.png');<br />    background:none; width:300px; height:100px; border:#000 solid 1px;}
          <br/>
          <span style="color:red;">
            <a href="http://bufanliu.javaeye.com/blog/227980#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Thu, 14 Aug 2008 12:56:45 +0800</pubDate>
        <link>http://bufanliu.javaeye.com/blog/227980</link>
        <guid>http://bufanliu.javaeye.com/blog/227980</guid>
      </item>
      <item>
        <title>基于MVC的Flex framework比较</title>
        <author>bufanliu</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://bufanliu.javaeye.com">bufanliu</a>&nbsp;
          链接：<a href="http://bufanliu.javaeye.com/blog/227480" style="color:red;">http://bufanliu.javaeye.com/blog/227480</a>&nbsp;
          发表时间: 2008年08月13日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          关键字: mvc framework <br />原文出处：<a href="http://blogs.warwick.ac.uk/stevencarpenter/entry/flex_mvc_frameworks/ " target="_blank">http://blogs.warwick.ac.uk/stevencarpenter/entry/flex_mvc_frameworks/ </a><br /><br />当我打算选用一种MVC framework开发Flex应用时，我想我得看看目前有哪些框架可供选择。Rob已经使用Cairngorm做了一些实际项目，Cairngorm是Adobe推荐的解决方案，但还存在着一些别的框架，包括PureMVC，Model-Glue和Guasax，再加上一些我以前闻所未闻的或不成熟或成熟的框架。 <br /><br />Pattern Park公司的一些研究人员最近对已存在框架做了一个比较。他们使用三大标准：Approachability（可实现性，创建一个工程并让它跑起来的过程是否简单，以及文档的丰富程度和支持力度），Scalability（扩展性，添加新特性是否困难，代码是否可测试） 和Flexibility （灵活性，代码是否开源，可修改以及是否环境独立等）对每个框架的质量进行评分。 <br /><br />这个演讲值得一看，他们给出的结论是，PureMVC在全部三项指标中得到最高，Cairngorm紧随其后。不过正如某人在演讲上指出的那样，要使用这些框架，了解Cairngorm是一个先决条件，因为很多已存在的项目使用了较早出现的框架。Luke Bayes对演讲做了进入探讨，详细介绍了这些要点。 <br /><br />下面是他们将PureMVC排在首位的原因： <br /><br />* 组合优于继承（Composition over inheritence） <br />* 无约束的接口（Liberal use of Interfaces） <br />* 有点拐弯抹角但还不至于迷失方向（Indirection is used but not overwhelming） <br />* 在应用代码中实例成员隐藏了单例引用（？不清楚确切含义）（Instance members hide singleton references from application code） <br />* MXML文件非常简洁（MXML views can be extremely thin） <br />* 吸取了Cairngorm的优点，但也包含一些缺点（Benefits of Cairngorm, with few of the disadvantages） <br /><br />这个演讲对任何考虑使用设计模式/框架进行Flex开发的人都非常有用，我打算本周开始研究PureMVC，看看它到底如何...
          <br/>
          <span style="color:red;">
            <a href="http://bufanliu.javaeye.com/blog/227480#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Wed, 13 Aug 2008 10:13:44 +0800</pubDate>
        <link>http://bufanliu.javaeye.com/blog/227480</link>
        <guid>http://bufanliu.javaeye.com/blog/227480</guid>
      </item>
      <item>
        <title>色彩模式(RGB、CMYK、HSB、Lab、Duotone等)</title>
        <author>bufanliu</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://bufanliu.javaeye.com">bufanliu</a>&nbsp;
          链接：<a href="http://bufanliu.javaeye.com/blog/224508" style="color:red;">http://bufanliu.javaeye.com/blog/224508</a>&nbsp;
          发表时间: 2008年08月05日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          色彩是一门很深的学问，每种色彩都有自己的特点和原理。设计师要在网页设计中灵活、巧妙运用，使网页达到各种精彩效果。先详细了解色彩的模式是很有必要的。<br />在这里，按照我的理解。把色彩模式做下解释：<br />RGB色彩模式：<br />RGB模型通常用于光照原理的视频和屏幕图像。只要是在显示器上显示的图像，最终还是以RGB方式来呈现的。还多用于荧光屏的视觉效果呈现，比如电子幻灯片、FLASH动画和各种多媒体用途。大家都知道，RGB代表红色（Red）、绿色（Green）、蓝色（Blue）。该模式下，每个像素在每种颜色上可以负载2的8次即256种亮度级别，这样、三种颜色通道合在一起，就可以产生256的3次方，即16777216种颜色。纯红色的R值为255，G值为0，B值为0。灰色的R、G、B三个值相等（0、25除外），白色的R、G、B值都为255。黑色的三个值都是0。它在理论上可以还原自然界中存在的任何颜色。<br />一般情况下，我们出去拍完照片回家，需要处理的时候。就应该把色彩模式设为RGB模式。<br />RGB色彩是一种发光的色彩，比如，你在一间黑暗的房间内仍然可以看见屏幕上播放的画面。而后面的CMYK则是一种依附反光的色彩模式。需要外界光源做帮助。看书看报，则是由于阳光或者台灯的照射。而反射进我们的眼球中的。在RGB色彩模式上的图像中，某种颜色的含量越多，那么这种颜色的亮度也越高。换句话说，如果RGB三色的亮度级别都是0，那么他们混合的色彩就是黑色。因为没有了亮度。<br /><br />CMYK：<br />CMYK是指青色（Cyan）、洋红色（Magenta）、黄色（Yellow）、黑色（Black）四个色彩构成的。K取的是Black单词的最后一个字母，之所以不取首字母。这里要注意一下。是为了避免与蓝色相冲突。前面的RGB色彩不运用于印刷行业，因为它不能像CMYK色彩模式那样，更好的还原真实客观的自然色彩。而只是理论上可以还原。<br />CMYK模式一般运用于印刷类。比如画报、杂志、报纸、宣传画册等。以打印油墨在纸张上的光线吸收特性为基础，每个像素的每种印刷油墨都会被分配一个百分比值，<br />CMYK模式是以对光线的反射原理来庙宇的，所以它的混合方式则刚好与RGB色彩模式相反，采用了“减法混合”-----当它们的色彩相互叠合时，亮度就会降低。<br /><br />HSB：<br />HSB色彩模式是以色相（H）、饱和度（S）、亮度（B）来描述颜色的基本特性的。<br />HSB色彩模式是根据日常生活中人眼的视觉特征而直接制定的一套色彩模式。最接近人们对色彩辩认的思考方式。所以经较直接与直观。<br />人类的大脑对色彩的直觉感知，首先是色相，即红、橙、黄、绿、青、蓝、紫中的一个。然后是它的一个深浅度。简单说来，色相即色彩的变化，饱和度高，色彩较艳丽，饱和度低，色彩就接近灰色。明度与称为亮度，亮度高，色彩明亮。亮度低，色彩暗淡。<br /><br />Lab色彩模式：<br />Lab颜色是以一个亮度分量L及两个颜色分量a和b来表示颜色的，L的取值范围是0-100，a分量代表由绿色到红色的光谱变化，而b分量代表由蓝色到黄色的光谱变化。<br />这种色彩模式通常运用于处理Photo CD（照片光盘）图像、单独编辑图像中的亮度和颜色值、在不同系统中转移图像。<br /><br />索引色（Indexed color）：<br />这种模式最多使用256种颜色。目的是在Web页面上和其他基于计算机的图像中显示，该模式把图像限制成不超过256种颜色。主要是为了保护文件具有较小尽寸，索引色最多只有256种色彩。<br />图像转换为索引色彩模式时，通常会构建一个调色板存放并索引图像中的颜色。如果原图像中的一种颜色没有出现在调色版中，程序会选取已有颜色中最接近的颜色或使用已有颜色模拟该种颜色。在索引色彩模式下。通过限制调色版中颜色的数目可以减小文件大小。同时保持视觉上的品质没有太大的变化。在网页设计中常常需要使用索引色彩模式的图像。<br /><br />Bitmap（位图模式）：<br />位图模式的图像只有黑色和白色两种像素组成。每个像素用“位”来表示。“位”只有两种状态。0表示有点，1表示无点。位图模式主要用于早期不能识别颜色和灰度的设备。如果需要表示灰度，则需要通过点的抖动来模拟。位图模式通常用于文字识别。如果需要使用OCR（光学文字识别）技术识别图像文件，需要将图像转化为位图模式。<br /><br />灰度（Grayscale）：<br />灰度模式最多使用256级灰度来表现图像，图像中的每个像素有一个0-255之间的亮度值。灰度值与可以用黑色油墨覆盖的百分比来表示。<br />在将色彩模式的图像转换为灰度模式时，会丢掉原图像中的所有的色彩信息。与位图模式相比，灰度模式能够更好的表现高品质的图像效果。<br />需要注意的是，尽管一些图像处理软件可以把一个灰度模式的图像重新转换成彩色模式的图像，但转换粕不可能将原先丢失的颜色恢复。所以，在将彩色图像转换为灰度模式的图像时，请记得保存好原件。<br /><br />Duotone（双色调）<br />双色调模式采用2-4种彩色油墨来创建由双色调、三色调和四色调混合其色阶来组成图像。在将灰度模式的图像转换为双色调模式的过程中，可以对色调进行编辑。产生特殊的效果。而使用双色调模式最主要的用途是，使用尽量少的颜色表现尽量多的颜色层次，这对于减少印刷成本是很重要的。因为在印刷时，每增加一种色调都需要投入更大的成本。
          <br/>
          <span style="color:red;">
            <a href="http://bufanliu.javaeye.com/blog/224508#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Tue, 05 Aug 2008 13:10:00 +0800</pubDate>
        <link>http://bufanliu.javaeye.com/blog/224508</link>
        <guid>http://bufanliu.javaeye.com/blog/224508</guid>
      </item>
      <item>
        <title>colormatrixFilter</title>
        <author>bufanliu</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://bufanliu.javaeye.com">bufanliu</a>&nbsp;
          链接：<a href="http://bufanliu.javaeye.com/blog/222155" style="color:red;">http://bufanliu.javaeye.com/blog/222155</a>&nbsp;
          发表时间: 2008年07月31日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <a href="http://hi.baidu.com/fmz1206/blog/item/2c7d96c3b3382f51b319a83e.html" target="_blank">http://hi.baidu.com/fmz1206/blog/item/2c7d96c3b3382f51b319a83e.html</a>
          <br/>
          <span style="color:red;">
            <a href="http://bufanliu.javaeye.com/blog/222155#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Thu, 31 Jul 2008 12:38:29 +0800</pubDate>
        <link>http://bufanliu.javaeye.com/blog/222155</link>
        <guid>http://bufanliu.javaeye.com/blog/222155</guid>
      </item>
      <item>
        <title>webservice参考</title>
        <author>bufanliu</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://bufanliu.javaeye.com">bufanliu</a>&nbsp;
          链接：<a href="http://bufanliu.javaeye.com/blog/221130" style="color:red;">http://bufanliu.javaeye.com/blog/221130</a>&nbsp;
          发表时间: 2008年07月29日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <a href="http://www.blogjava.net/zhip/archive/2007/05/17/118182.html" target="_blank">http://www.blogjava.net/zhip/archive/2007/05/17/118182.html</a>
          <br/>
          <span style="color:red;">
            <a href="http://bufanliu.javaeye.com/blog/221130#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Tue, 29 Jul 2008 16:00:00 +0800</pubDate>
        <link>http://bufanliu.javaeye.com/blog/221130</link>
        <guid>http://bufanliu.javaeye.com/blog/221130</guid>
      </item>
      <item>
        <title>在myeclipse中写webservice</title>
        <author>bufanliu</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://bufanliu.javaeye.com">bufanliu</a>&nbsp;
          链接：<a href="http://bufanliu.javaeye.com/blog/220970" style="color:red;">http://bufanliu.javaeye.com/blog/220970</a>&nbsp;
          发表时间: 2008年07月29日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <a href="http://www.cnblogs.com/stephencat/archive/2006/11/16/561816.html" target="_blank">http://www.cnblogs.com/stephencat/archive/2006/11/16/561816.html</a>
          <br/>
          <span style="color:red;">
            <a href="http://bufanliu.javaeye.com/blog/220970#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Tue, 29 Jul 2008 10:34:54 +0800</pubDate>
        <link>http://bufanliu.javaeye.com/blog/220970</link>
        <guid>http://bufanliu.javaeye.com/blog/220970</guid>
      </item>
      <item>
        <title>记录没有看完</title>
        <author>bufanliu</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://bufanliu.javaeye.com">bufanliu</a>&nbsp;
          链接：<a href="http://bufanliu.javaeye.com/blog/218890" style="color:red;">http://bufanliu.javaeye.com/blog/218890</a>&nbsp;
          发表时间: 2008年07月24日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <a href="http://www.javaeye.com/news/1816" target="_blank">http://www.javaeye.com/news/1816</a>
          <br/>
          <span style="color:red;">
            <a href="http://bufanliu.javaeye.com/blog/218890#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Thu, 24 Jul 2008 10:50:47 +0800</pubDate>
        <link>http://bufanliu.javaeye.com/blog/218890</link>
        <guid>http://bufanliu.javaeye.com/blog/218890</guid>
      </item>
      <item>
        <title>一个可以阅读的java博客</title>
        <author>bufanliu</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://bufanliu.javaeye.com">bufanliu</a>&nbsp;
          链接：<a href="http://bufanliu.javaeye.com/blog/218885" style="color:red;">http://bufanliu.javaeye.com/blog/218885</a>&nbsp;
          发表时间: 2008年07月24日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <a href="http://blog.csdn.net/allenjay2003/category/169211.aspx" target="_blank">http://blog.csdn.net/allenjay2003/category/169211.aspx</a>
          <br/>
          <span style="color:red;">
            <a href="http://bufanliu.javaeye.com/blog/218885#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Thu, 24 Jul 2008 10:45:39 +0800</pubDate>
        <link>http://bufanliu.javaeye.com/blog/218885</link>
        <guid>http://bufanliu.javaeye.com/blog/218885</guid>
      </item>
      <item>
        <title>实现不同域（Domain）之间的数据交换</title>
        <author>bufanliu</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://bufanliu.javaeye.com">bufanliu</a>&nbsp;
          链接：<a href="http://bufanliu.javaeye.com/blog/215007" style="color:red;">http://bufanliu.javaeye.com/blog/215007</a>&nbsp;
          发表时间: 2008年07月15日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          引言<br />前些天在对公司原有的 web 应用进行改版时遇到一个问题，当时需要从原有的应用中提取出一部分，用一个更为通用的来进行替换，并且仍然保留原有的应用接口。原有的应用属于 news.mycompany.com 域，而新应用将被部署到 upload.mycopany.com。当我试着从新的域向 news.mycompany.com 传递数据时，在前台遇到了浏览器返回的“拒绝访问(Access Denied)” 的错误信息，通过参考在 google 中查到的大量英文资料找到了问题的症结，并通过指定两个域中页面的 docment.domain 属性使问题得到了部分解决。后来一时兴起在 google 中查找与 document.domain 相关的中文资料，但得到的大部分是网络安全方面的文章，很少有文章提及通过指定页面的 document.domain 属性能够实现两个域之间的数据交换，于是决定写下此文，希望能够做到抛砖引玉吧。<br /><br />关键字： JavaScript, Domain, Access Denied<br /><br />问题的提出<br />在开发 Web 应用时经常会遇到需要在两个帧之间传递数据的情况，这里的帧可以是 frameset 中的 frame 也可以是独立的窗口。常见的情况是一个帧作为应用的主体，另一个帧则提供一些供用户选择的选项，用户选择完毕后，该帧把用户作出的选择发送到服务器并向主要的帧传递一些信息，这里的信息可能是用户的选择也可能是服务器返回的数据。当两个帧中的内容同属于一个域时实现以来比较简单，但是当它们分属于不同域时问题就变得复杂而棘手了，因为这里涉及到了数据访问的安全性问题,搞不好就会遇到浏览器返回的“拒绝访问(Access Denied)” 的错误信息。<br /><br />可能的解决方案<br />下面我们将通过几个试验来分析一下在分属于不同域的帧之间传递数据的一些方法。 <br />利用客户端脚本(如 JavaScript)和窗口句柄在两个帧之间传递数据 <br />利用 MSIE 提供的对话框在两个帧之间传递数据 <br />利用服务器端的应用，通过 session 来传递数据 <br />方案一<br /><br />用客户端脚本实现两个帧之间的数据交换应该是最为轻量级的方式之一了，这样做不会增加服务器的负载也不会占用网络带宽，数据交换完全是在客户端完成。下面就让我们先来了解一下用客户端脚本（以 JavaScript 为例）和窗口句柄如何实现一个域内的数据交换。<br /><br />我们通过一个实例来进行说明：假设需要给用户提供一个新闻的录入界面，用户可以用它录入新闻的原始内容，并且可以在其中嵌入一副图片。为了实现这个功能界面我们设计了两个帧，或者说是两个窗口：<br /><br />主窗口： 新闻内容的主要编辑界面，用户可以在里面录入新闻的标题、作者、新闻主体等内容，还有一个图片框可以预览上传的图片<br /><br />弹出窗口： 处理图片上传的界面，用户可以选择本地图片进行上传，成功后它把服务器上文件的 url 返回给主窗口进行预览<br /><br />为了简单起见，我们假设两个窗口中的内容都是静态的，主窗口对应的文件为 NewsEdit.html，弹出窗口对应的文件为 ImgUpload.html（而大多数情况下两个窗口的内容都应该是动态生成的）。<br /><br />其中 NewsEdit.html 位于 news.mycompany.com 的主目录下，其源代码如下所示：<br />&lt;!-- File: NewsEdit.html (http://news.mycompany.com/NewsEdit.html) --><br />&lt;html><br />&lt;head><br />&lt;title>The Content Editing Interface&lt;/title><br />&lt;meta http-equiv="Content-Type" content="text/html; charset=gb2312"><br />&lt;script language="JavaScript"><br />&lt;!--<br />  /* OpenWin 用来在一个弹出窗口中显示 ImgUpload.html 的内容*/<br />  function OpenWin(){//Open window<br />    url='http://news.mycompany.com/upload/ImgUpload.html';<br />    newwindow = window.open(url,"ImgUpload","height=135,width=300");<br />    if (!newwindow.opener) newwindow.opener=self;<br />  }<br />--><br />&lt;/script><br />&lt;/head><br /><br />&lt;body><br />&lt;h2>Edit your content here&lt;/h2><br />&lt;!-- 调用后台应用 newsedit 来保存新闻内容 --><br />&lt;form action="http://news.mycompany.com/newsedit" method="post" name="addnews"><br />  &lt;!-- 新闻标题 --><br />  Title:&lt;input type="text" name="title">&lt;br><br />  &lt;!-- 新闻作者 --><br />  Author:&lt;input type="text" name="author">&lt;br><br />  The content &lt;br><br />  &lt;!-- 新闻内容 --><br />  &lt;textarea name="contentBody" cols="100" rows="10">&lt;/textarea><br />  &lt;br><br />  &lt;!-- 点击连接打开上传图片的小窗口 --><br />  &lt;a href="JavaScript:OpenWin()">Upload Image File&lt;/a> <br />  &lt;br><br />  &lt;!-- UserImg 用来预览上传成功后的图片文件 --><br />  &lt;img name="UserImg" style="width: 100px; height: 100px;" src="" border="1"><br />  &lt;br>&lt;br><br />  &lt;input type="submit" name="SaveContent" value="Submit"><br />  &lt;input type="reset" name="ClearContent" value="Reset"><br />&lt;/form><br />&lt;/html><br /> <br /><br />ImgUpload.html 位于 news.mycompany.com 的 upload 子目录下，其源代码如下所示： &lt;!-- File: ImgUpload.html (http://news.mycompany.com/upload/ImgUpload.html) --><br />&lt;html><br />&lt;head><br />&lt;title>Imgage Upload Interface&lt;/title><br />&lt;meta http-equiv="Content-Type" content="text/html; charset=gb2312"><br />&lt;/head><br /><br />&lt;body><br />&lt;h2>Image Upload&lt;/h2><br />&lt;!-- 调用后台应用来处理上传的图片 --><br />&lt;form action="http://news.mycompany.com/upload/imgupload" method="post" enctype="multipart/form-data" name="upload"><br />  &lt;!-- 由用户选择本地文件 --><br />  &lt;input type="file" name="imgfile"><br />  &lt;input type="submit" name="Submit" value="Upload"><br />&lt;/form><br />&lt;/html><br /> <br /><br />另外介绍一下我们的两个后台应用： <br />newsedit: 位于 news.mycompany.com 的主目录下,接受用户的 POST 请求，将编辑界面的新闻元素存储到后台数据库<br /><br />imgupload:  位于 news.mycompany.com 的 upload 子目录下，接受用户的 POST 请求，将本地的图片文件上传到服务器，并返回图片文件完整的 url。<br /><br />下面是 imgupload 处理完 POST 请求后返回的页面内容，该内容显示在 ImgUpload.html 所占据的弹出窗口中：<br />&lt;html><br />&lt;head><br />&lt;title>File Upload Successfully&lt;/title><br />&lt;/head><br />&lt;body><br />&lt;h3>File Uploaded Successfully！&lt;/h3><br />&lt;script language="JavaScript"><br />  &lt;!-- 获取主窗口的句柄 --><br />  parwin=self.opener;<br />  &lt;!-- 获取对 img 元素的引用，并用上传文件的 url 为 img 元素的 src 属性赋值，这样在客户端就可以预览了 --><br />  &lt;!-- 为了简化问题，我们将对 img 元素的引用直接写在程序中 --><br />  parwin.addnews.UserImg.src="http://news.mycompany.com/img/2003_07/06/1057478464859.gif";<br />&lt;/script><br />&lt;/body><br />&lt;/html><br /> <br /><br />返回的页面除了显示成功信息外，还利用脚本向主窗口传递了上传文件的 url，具体过程是：<br />首先通过 "self.opener" 获得主窗口（即 NewsEdit.html 所在窗口）的句柄；然后用上传文件的 url 对主窗口中 UserImg 元素的 src 属性进行赋值，这样在主窗口中就可以看到上传后的图片了。<br /><br />好了，我们的第一个实验已经成功了，实验结果告诉我们：当两个帧中的内容同属于一个域时，利用客户端脚本和窗口句柄在其中传递数据是没有问题的。接下来我们把 ImgUpload.html 和 imgupload 从 news.mycompany.com 提取出来,部署到 img.mycompany.com 的对应目录下,并修改 NewsEdit.html 中引用 ImgUpload.html 时的 url。这样当我们试着用 JavaScript 从 img.yourcompanu.com 向 bbs.yourcompany.com 传递数据时，浏览器就会弹出“拒绝访问(Access Denied)” 的错误框，表明我们违反了他的安全策略，并且数据无法正常传递过来。<br /><br />其实，你可以直接把实验一中 imgupload 返回的内容另存为一个文件并部署到 img.mycompany.com，在 NewsEdit.html 中调用 window.open() 方法直接引用这个文件就可以进行测试了。 <br /><br />我们之所以会遇到“拒绝访问(Access Denied)” 的的错误信息，其原因在于：<br /><br />最初，浏览器的开发商、开发团体出于安全性的考虑，默认情况下是不允许在分属于不同域的页面之间进行数据交换和方法调用的，当遇到这种情况时浏览器就会返回“拒绝访问(Access Denied)”的错误。<br /><br />“那为什么即使我的两个页面属于同一个域我还是会遇到‘拒绝访问’的错误呀？”<br />如果是这种情况，那就要看你的弹出窗口中的内容是否始终属于同一个域，看一下你的 ImgUpload.html 是不是调用了属于其他域的应用，并且该应用在窗口中重新写入了内容，如果是这样那你的弹出窗口就变质了，它最后属于另外一个域，你当然会遇到“拒绝访问”的错误。<br /><br />“这么说如果两个页面分属于不同域的话我们就无法在两个窗口之间传递数据了吗？”<br />事实基本上是这样的－－一个令人沮丧的消息。<br />但答案也并非绝的－－好像还有希望。<br /><br />是的，一些浏览器的开发商、开发团体在开发高版本的浏览器时对原有策略进行了部分调整，这些调整给我们带来了一线生机：<br />当两个页面在进行数据交换时，浏览器会首先比较两个页面的 domain 属性，如果 domain 属性相同，那么浏览器就允许它们之间的数据交换，否则就返回“拒绝访问(Access Denied)”的错误。<br /><br />“那么我们如何才能蒙蔽浏览器，让它认为两个页面的 domain 属性相同呢？”<br />这就要靠脚本来实现了，在 JavaScript 中我们可以通过在页面中加入如下声明来强制指定页面所属的域。<br /><br />&lt;script language="JavaScript"><br />&lt;!--<br />document.domain = "mycompany.com"; //指定 document 所属的域<br />--><br />&lt;/script><br /><br />加入上面的声明就可以蒙蔽浏览器，在原本属于两个不同域的页面之间进行数据交换了。但需要注意：只有把上面的声明加入到需要进行数据交换的所有文件中才会有效，只在一个域的文件中加入上面的声明是不起作用的。另外，声明部分最好能插入到页面的 &lt;head>&lt;/head> 标记中间，这一点也是用脚本进行开发时所被提倡的。有关 JavaScript 中的 document 和 domain 等可以参考 http://www.werelight.com/docs/JavaScript_Quick_Reference.htm<br /><br /><br />“使用这种方法有什么限制码？”<br />因该说用这种方法来实现不同域之间的数据传递还是有很多的限制的，主要表现为以下两点：<br /><br />document.domain 属性是不可以随便设置的，它只能被设置为文件所属域的上级域。如假设 ImgUpload.html 属于 img.mycompany.com ，那么它的 document.domain 属性可以设置为“mycompany.com” ，但不能设置为“img.mycompany” 或其他的，如“foo.com”。 <br />只有当两个域存在相同的上级域时，才能通过指定 document.domain 来实现它们之间的数据交换，并且 document.domain 属性必须被 设置为二者的公共域。例如，假设 NewsEdit.html 属于 news.mycompany.com，而 ImgUpload.html 属于 img.yourcompany.com，那么无论你如何设置 document.domain 都无法在它们之间交换数据；再比如，假设 ImgUpload.html 属于 img.mycompany.com，那么我们可以把两个页面的 document.domain 属性设置为“mycompany.com”，但不可以设置为“img.mycompany” 或其他的什么域，如“foo.com”。 <br />并非所有的浏览器都支持对 document.domain 属性进行设置。如 MSIE 和 Netscape 它们4.0以前的版本是不支持对该属性的设置的；另外有趣的是虽然 Netscape 在4.0以后开始支持对 domain 进行设置了，但在4.03 和4.04两个版本中 Netscapre 居然又把上面的功能给取消了。 <br />利用其他脚本，如 vbscript 或 jscript 实现这种跨域的数据交换其原理与用 JavaScript 是一样的，大家可以参考相关资料来实现。 <br /><br />方案二<br />下面我们来看一下利用 MSIE 提供的对话框能不能解决两个域之间的数据交换问题<br />首先我来简单介绍一下 MSIE 对话框：MSIE 提供的 showModalDialog 和 showModelessDialog 方法可以用来在一个单独的帧中显示一个模态或非模态对话框，两个方法都通过一个 URI 参数来指定对话框帧中的内容；可选的参数 vArguments 用来向对话框帧传递任何类型（包括数组类型）的参数；另外还有一个可选的参数 sFeatures 是用来定义对话框帧的显示效果，如位置、字体等等的；<br /><br />注意 Netscape Navigator 、Mozilla 和 Opera 浏览器是没有与之对应的方法的，也就是说除了 MSIE 之外其他几大浏览器都不支持用 showModalDialog 或 showModelessDialog 显示对话框，如果你感兴趣的话这里有一篇文章能够教你如何通过其他方式来模拟一个模态对话框，详见 Simulating Modal Dialog Windows <br /><br />“Because a modal dialog box can include a URL to a resource in a different domain, do not pass information through the vArguments parameter that the user might consider private. The vArguments parameter can be referenced within the modal dialog box using the dialogArguments property of the window object.”－－引自 MSDN showModalDialog<br />上面一段话说明：通过 sURL 参数我们可以将另一个域的资源用为话框的内容，但这种情况下我们就不能再向对话框传递任何参数了，只有当所引用的资源与引用它的页面属于同一个域时，我们才可以利用 window.dialogArguments 获得从引用页中传递过来的参数。<br /><br />“那么我能不能像方案一中那样通过强制指定两个页面中的 document.domain 属性来蒙蔽浏览器，使其认为两个页面属于同一个域呢？”<br />确实有人提出过这种想法，笔者也试着这样做过，但最后还以失败而告终：在两个页面中强制指定 document.domain 了属性后，无论两个页面是否属于同一个域，对话框都无法正常识别从主页面传递过来的参数。<br /><br />在此次实验中我使用了3个文件 <br /><br />main.html : 部署在 a.mycompany.com，通过调用 showModalDialog 引用另外两个文件 <br />localdialog.html  : 与 main.html 一起部署在 a.mycompany.com <br />remotedialog.html : 部署在 b.mycompany.com，其内容与 localdialog.html 完全一样<br /><br />main.html 在调用用 showModalDialog 方法时，通过 vArguments 向对话框传递了参数："Can you hear me?"，希望对话框能够接收到这个参数；如果对话框接收到了，那么它将调用 window.alert() 方法打印出这条消息，然后向main.html 返回一个结果："Yes I do, I hear you from " + document.domain ；如果main.html 接收到了对话框返回的结果，那么它同样会调用 window.alert() 打印出结果的内容。<br /><br />其中 main.html 的源代码如下所示： &lt;html><br />&lt;head><br />&lt;title>show modal dialog&lt;/title><br />&lt;script><br />&lt;!--<br />//document.domain  = "mycompany.com";<br /><br />&lt;!-- 打开一个模态对话框，显示 url 所代表的资源 --><br />function openDialog(url) {<br />    &lt;!-- 向对话框传递参数 --><br />    var args = new Object();<br />    args.content = "Can you hear me?";<br />    var rv = window.showModalDialog(url, args);<br />    &lt;!-- 显示对话框所返回的结果 --><br />    if (rv) {<br />        alert("dialog returns :" + rv);<br />    } else {<br />        alert("dialog returns nothing");<br />    }<br />}<br />--><br />&lt;/script><br />&lt;/head><br /><br />&lt;body><br />&lt;!-- 引用 b.mycompany.com 中的资源 --><br />&lt;a href="#" onclick="openDialog('http://b.mycompany.com/remotedialog.html');return false;"><br />  I will Open a remote dialog from news.soufun.com<br />&lt;/a><br />&lt;br><br />&lt;!-- 引用本地的资源 --><br />&lt;a href="#" onclick="openDialog('./invokebyhouse.html');return false;"><br />  I will Open a local dialog<br />&lt;/a><br />&lt;/body><br />&lt;/html><br /> <br /><br />localdialog.html(remotedialog.html) 的源代码如下所示： &lt;html><br />&lt;head><br />&lt;title>a remote dialog&lt;/title><br />&lt;script><br />&lt;!--<br />//document.domain  = "mycompany.com";<br /><br />onload = function() {<br />  var args = window.dialogArguments;<br />  alert("You send me: " + args.content);<br />  btnCan.onclick = function() {<br />    window.returnValue = "Yes I do, I hear you from " + document.domain;<br />    close();<br />  }<br />}<br />--><br />&lt;/script><br />&lt;/head><br /><br />&lt;body><br />Im here, Im a dialog &lt;br><br />I will return something to the main window&lt;br><br />&lt;input id="btnCan" type="button" style="text-align:center;" value="Close"><br />&lt;/body><br />&lt;/html><br /> <br /><br />通过实验发现：<br /><br />main.html 总是能正常的接收从对话框中返回的结果，无论对话框是位于a.mycompany.com 还是 b.mycompany.com,也无论是否设置了 document.domain 属性； <br />在没有设置 document.domain 属性时，localdialog.html 可以正常接收从 main.html 传递过来的参数，但如果设置了 document.domain 属性， localdialog.html 读取到的参数就变成 null 了。 <br />而无论是否设置了 document.domain 属性，在 remotedialog.html 读取从 main.html 传递过来的参数得到的始终都是 null。 <br />非常遗憾，实验结果告诉我们：用对话框是无法实现这种跨域的数据交换的。<br /><br />如果我的实验中存在某些漏洞，或者在你的实验中对话框读取到了从 main.html 传递过来的参数，有劳你通过 Email告知我，谢谢！<br /><br />注(2004-12-28):您在进行测试的时候可能会得到不同的测试结果，因为随着IE 的更新或者补丁的作用，这种跨域的数据交换行为可能会被调整。例如笔者在加入这段注解的时候上面的第1条就已经不再成立了——main.html 并不是总能接收到从隶属于b.mycompany.com 的对话框返回的数据，只有两者都把document.domain 属性设置为mycompany.com 后main.html 才能接收到对话框返回的结果。见相关讨论：about showModalDialog<br />"Even though there is no mention in the documentation of passing arguments or returning a value being blocked in the cross-domain case, I think that may actually have changed as the consequence of one of the *many* IE upgrades and/or security patches."<br /> <br /><br />方案三<br />应该说利用服务器端应用实现这种跨域的数据交换是最为可靠的方式了，因为这几乎不会受到客户端的限制，不像前面两种方式：有的客户端不支持 document.domain 属性，有的不支持对话框等等。那么是不是说用服务器端应用解决不同域之间的数据交换是应该最优先考虑的方案呢？答案是否定的，因为服务器端应用也有它的致命伤：即接收数据的一方不能实时的显示从对方传递过来的数据，它只有在处理了 GET 或 POST 请求后才能使数据得到展现，在这个过程中如果未做任何特殊处理，那么用户在该帧中编辑的内容将被清除掉，这往往是我们所不希望看到的。有关用服务器端应用实现跨域的数据交换我们就不再举例子了，如果您有兴趣的话可以到 google 上查一下相关的资料。<br /><br />总结<br />在上面介绍的三种方案中，除方案二尚不能实现在分属于不同域的帧之间进行数据交换之外，经证明方案一和方案三都是可行的，不过这两种方案又各有利弊：<br /><br />方案一的优点在于：用客户端脚本和窗口句柄不必占用服务器资源和网络带宽，可以做到数据的实时展现，并且不会影响到对方帧中的已有内容，其缺点是应用范围较小，要受到客户端浏览器的限制； <br />方案三由于是利用的服务器端应用，所以几乎不会受到客户端的影响，其缺点是无法做到数据的实时展现，有时候还要采取某种措施来维持对方帧中的已有内容。 <br />针对这两种可行方案，大家在应用时应该灵活选择，如果你比较看重数据的实时展现那么就可以考虑采用前者；而如果应用的平台无关性是你衡量应用的标准那就应该考虑采用后者。<br /><br />另外，如果您有其他可选方案的话，非常感谢您能通过 Email 告知我，以填补我在这面方面的空白，谢谢！<br /><br />编后语：<br />非常感谢您能够看到这里，对于因为本文的晦涩难懂而给您带来的对自己理解能力的怀疑我深表歉意:)，希望以后能做的更好!
          <br/>
          <span style="color:red;">
            <a href="http://bufanliu.javaeye.com/blog/215007#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Tue, 15 Jul 2008 15:49:43 +0800</pubDate>
        <link>http://bufanliu.javaeye.com/blog/215007</link>
        <guid>http://bufanliu.javaeye.com/blog/215007</guid>
      </item>
      <item>
        <title>网页中超长文字的断行问题</title>
        <author>bufanliu</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://bufanliu.javaeye.com">bufanliu</a>&nbsp;
          链接：<a href="http://bufanliu.javaeye.com/blog/214807" style="color:red;">http://bufanliu.javaeye.com/blog/214807</a>&nbsp;
          发表时间: 2008年07月15日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          网页中超长文字的断行问题2006/9/25 at 01:50 · PHP, XHTML&CSS <br /><br />这个应该是比较常见的问题了，通常是连续的一长串无空格的半角字符所引起的，比如比较长的超链接就很有可能把你的页面撑开。网上常见的解决办法就是使用css属性 break-word:break-all; ，但是这个只对IE浏览器有效。<br /><br />下面介绍一种办法，可以保证各浏览器的兼容。<br /><br />&lt;wbr>标记，它的作用是建议浏览器在这个标记处可以断行，只是建议而不是必定会在此处断行，还要根据整行文字长度而定。因此只要在连续的文字中间适当的插入若干&lt;wbr>标记就能解决断行问题。<br /><br />我最初看到这个解决办法是在Gmail的代码中，它是这么实现的:(All rights reserved by Google.)<br /><br />JS实现<br />function HtmlEscapeInsertWbrs(str, n, chars_to_break_after,<br />                              chars_to_break_before)<br />{<br />    var out = '';<br />    var strpos = 0;<br />    var spc = 0;<br />    for (var i = 1; i &lt; str.length; ++i) {<br />        var prev_char = str.charAt(i - 1);<br />        var next_char = str.charAt(i);<br />        if (IsSpace(next_char)) {<br />            spc = i;<br />        } else {<br />            if (i - spc == n<br />            || chars_to_break_after.indexOf(prev_char) != -1<br />            || chars_to_break_before.indexOf(next_char) != -1)<br />            {<br />                out += HtmlEscape(str.substring(strpos, i))<br />                      + '&lt;wbr>';<br />                strpos = i;<br />                spc = i;<br />            }<br />        }<br />    }<br />    out += HtmlEscape(str.substr(strpos));<br />    return out;<br />}<br />/////<br />function IsSpace(ch)<br />{<br />    return (" trn".indexOf(ch) >= 0);<br />}<br />function HtmlEscape(str){<br />    return<br />        str.replace(/&/g,"&amp;").replace(/&lt;/g,"&lt;")<br />        .replace(/>/g,"&gt;").replace(/\"/g,"&quot;");<br />}<br />说明： 函数已经帮你处理了Html敏感的符号(&&lt;>),用了这个函数并不是说字符串显示的时候就会在某个点断行，只是在其中设置了可能的断行点(&lt;wbr>)标记，在显示宽度不够的时候的情况下才指示浏览器做出断行。<br /><br /><br />用法： 参数说明<br />str： 你要处理的原始字符串<br />n: 每行最多多少个字符<br />chars_to_break_after: 一个字符串，比如"-:_",就会在这些字符后面发生断行(如果有断行必要) 如果不需要特别设置，那么使用空字符串 ""就行了<br /><br />chars_to_break_before: 功能类似于上面这个， 没有特殊需要就设置成 "" 就可以了<br /><br />函数是JavaScript的实现， 我根据这个做了一个PHP的实现，它工作得很好。<br /><br />PHP实现<br />/*<br /> * support UTF-8 only,<br /> * ** the function return HTML Format string **<br /> */<br />function HtmlEscapeInsertWbrs($str, $n=10,<br />         $chars_to_break_after='',$chars_to_break_before='')<br />{<br />    $out = '';<br />    $strpos = 0;<br />    $spc = 0;<br />    $len = mb_strlen($str,'UTF-8');<br />    for ($i = 1; $i &lt; $len; ++$i) {<br />      $prev_char = mb_substr($str,$i-1,1,'UTF-8');<br />      $next_char = mb_substr($str,$i,1,'UTF-8');<br />      if (_u_IsSpace($next_char)) {<br />        $spc = $i;<br />      } else {<br />        if ($i - $spc == $n<br />         || mb_strpos( $chars_to_break_after,<br />            $prev_char,0,'UTF-8' ) !== FALSE<br />         || mb_strpos( $chars_to_break_before,<br />            $next_char,0,'UTF-8')  !== FALSE )<br />          {<br />            $out .= HtmlEscape(<br />                mb_substr($str,$strpos, $i-$strpos,'UTF-8')<br />                       ) . '&lt;wbr>';<br />            $strpos = $i;<br />            $spc = $i;<br />          }<br />      }<br />    }<br />    $out .= HtmlEscape(<br />             mb_substr($str,$strpos,$len-$strpos,'UTF-8')<br />               );<br />    return $out;<br />}<br />/////<br />function _u_IsSpace($ch)<br />{<br />  return mb_strpos(" trn",$ch,0,'UTF-8') !== FALSE;<br />}<br />function HtmlEscape($s)<br />{<br />  return htmlspecialchars($s);<br />}<br />同样，该函数会对传入的字符串中的特殊字符做转义处理(htmlspecialchars())，因此传入的字符串必须是原始的(未经htmlspecialchars()处理过的),函数返回后的结果可以直接在网页中输出。<br />参数使用方法跟上面的JS版本类似，我就不罗唆了。<br /><br />你可以改写成其他语言的，到时候也记得发给我一份<img src="/images/smiles/icon_smile.gif"/>
          <br/>
          <span style="color:red;">
            <a href="http://bufanliu.javaeye.com/blog/214807#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Tue, 15 Jul 2008 10:11:18 +0800</pubDate>
        <link>http://bufanliu.javaeye.com/blog/214807</link>
        <guid>http://bufanliu.javaeye.com/blog/214807</guid>
      </item>
      <item>
        <title>JS中的instanceof和typeof</title>
        <author>bufanliu</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://bufanliu.javaeye.com">bufanliu</a>&nbsp;
          链接：<a href="http://bufanliu.javaeye.com/blog/207567" style="color:red;">http://bufanliu.javaeye.com/blog/207567</a>&nbsp;
          发表时间: 2008年06月24日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          对于instanceof和typeof，以前偶尔的用到过，特别是typeof用到的相对更多一些，今日研究ext源码，很多地方都用到了instanceof，突然觉得他们两个有些相似但也应该有他们区别，网上看了一些文章，对它们之间的关系有了一定的了解。<br /><br />instanceof和typeof都能用来判断一个变量是否为空或是什么类型的变量。<br />typeof用以获取一个变量的类型，typeof一般只能返回如下几个结果：number,boolean,string,function,object,undefined。我们可以使用typeof来获取一个变量是否存在，如if(typeof a!="undefined"){}，而不要去使用if(a)因为如果a不存在（未声明）则会出错，对于Array,Null等特殊对象使用typeof 一律返回object，这正是typeof的局限性。<br /><br />如果我们希望获取一个对象是否是数组，或判断某个变量是否是某个对象的实例则要选择使用instanceof。instanceof用于判断一个变量是否某个对象的实例，如var a=new Array();alert(a instanceof Array);会返回true，同时alert(a instanceof Object)也会返回true;这是因为Array是object的子类。再如：function test(){};var a=new test();alert(a instanceof test)会返回true。<br /><br />谈到instanceof我们要多插入一个问题，就是function的arguments，我们大家也许都认为arguments是一个Array，但如果使用instaceof去测试会发现arguments不是一个Array对象，尽管看起来很像。
          <br/>
          <span style="color:red;">
            <a href="http://bufanliu.javaeye.com/blog/207567#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Tue, 24 Jun 2008 16:35:14 +0800</pubDate>
        <link>http://bufanliu.javaeye.com/blog/207567</link>
        <guid>http://bufanliu.javaeye.com/blog/207567</guid>
      </item>
      <item>
        <title>JavaScript　OOP</title>
        <author>bufanliu</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://bufanliu.javaeye.com">bufanliu</a>&nbsp;
          链接：<a href="http://bufanliu.javaeye.com/blog/204169" style="color:red;">http://bufanliu.javaeye.com/blog/204169</a>&nbsp;
          发表时间: 2008年06月16日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          JavaScript的对象总有4类：<br />        脚本对象：如Object，Math，Date 等。<br />        浏览器对象：window，document，location等。<br />        Dom对象：对dom操作的对象，document，Node等<br />        自定义对象：程序员自身定义的对象。<br />   本次介绍程序员如何定义对象,对象是由类创建出来的，在Java中，我们可以通过语法：<br />     类 obj=new 类()；<br />   来定义对象，那么在JavaScript中如何定义对象呢？<br />   在JavaScript中，我们首先讨论一下JavaScript的一个重要特性：动态性。<br />   JavaScript是一门动态语言，什么意思呢？我认为包含两个含义：<br />   一是任何变量都可以不用考虑数据类型，在运行时才能区分当前变量的数据类型，也就是说JavaScript是弱类型的，在声明变量<br /><br />时，变量类型都是var ,不能是Object ,String,Date等。比如：<br />    var a=1;        //此时变量a是数字类型<br />    a="hello";      //此时变量a是字符串类型<br />    a=new Object(); 此时变量a是对象<br />    上面程序运行没有问题。<br />    <br />   动态性的第二个含义是对象属性可以在运行时，动态添加属性和方法，我们知道，在JavaScript中，任何对象都是Object的子类<br /><br />。有如下示例：<br />   var obj=new Object();<br />   obj.name="Jerry";<br />   obj.sayHello=function ()<br />   {<br />      alert("Hello,world!");<br />   }<br />   alert(obj.name);<br />   obj.sayHello();<br />   <br />   我们在上面的代码里，动态的为一个对象obj添加一个属性name 和一个方法sayHello.<br /><br />   在JavaScript中任何函数都可以new，例如：<br />   function Hello()<br />   {<br />        alert("Hello");<br />   }<br />   var h=new Hello();<br />   上面代码的解释是：创建一个对象h，对象没有任何属性和方法。在new一个函数时，函数的函数体自动执行，此时，函数体就犹如对象的构造方法。<br />   继续观察如下代码：<br />   function Hello()<br />   {<br />        var obj=new Object();<br />        obj.name="Jerry";<br />        return obj;<br />   }<br />   var h=new Hello();<br />   alert(h.name);<br />   输出Jerry;<br />   这时，对象h就是函数返回的Object对象,因此可以说，JavaScript通过  new 函数()  这样的语法来获取对象时，如果函数有return ，那么return 的结果就是实例化后的对象。<br />   <br />   另一方面，在JavaScript中，与java一样，任何对象都有内部关键字this ，表示当前对象，那么一个函数既然是对象的构造方法，能否这样使用呢？<br />   function Hello()<br />   {<br />        this.name="Jerry";<br />   }<br />   var h=new Hello();<br />   alert(h.name);<br />   运行结果与前面的一样，此时，该函数就与java中的类有点相似了，那么如何添加方法呢？可以这样：<br />   function Hello()<br />   {<br />        this.name="Jerry";<br />        this.sayHello=function()<br />        {<br />            alert("Hello,world");<br />        }<br />   }<br />   var h=new Hello();<br />   //alert(h.name);<br />   h.sayHello();<br />   OK,到此为止，类就定义出来了，接下来我们看看讨论一下JavaScript的封装，继承，多态。<br />   封装，不用说了，既然是类，那么天生就具备封装功能，只不过这里类的所有属性和方法都是public 的，这一点与java不一样。<br />   继承，就是扩展，在JavaScript中，任何时候都可以动态的给对象添加属性和方法，那么是不是就是继承呢？也可以这么理解：<br /><br />   function SubHello()<br />   {<br />      var h=new Hello();<br />      h.age=20;<br />      return h;<br />   }<br />   var sub=new SubHello();<br />   sub.sayHello();<br />   alert(sub.age);<br />   我们可以看出，调用结果正常运行，可以说SubHello扩展了Hello，即相当于继承，但是这种继承方式感觉别扭，JavaScript给我们提供了一个关键字，prototype,就是原型的意思。先测试一下使用方法<br />   Hello.prototype.age=20;<br />   var h=new Hello();<br />   alert(h.age);<br />   运行结果正常20。<br />   <br />   封装为函数实现继承<br />   function SubHello()<br />   {<br />      Hello.prototype.age=20;<br />      return new Hello();<br />   }<br />   这就是说SubHello是从Hello继承过来，并且发生的扩展。<br /><br />   接下来看看多态，多态形式是把子类对象赋值给父类的引用，但是在JavaScript中所有的对象都是var类型的，因此，JavaScript天生就是多态的，其实任何动态语言天生就是多态的，如Ruby.<br /><br />   当然，JavaScript不支持方法重载，这一点非常重要。<br /><br />   我们看看对象的应用。<br />   调用属性：<br />   var h=new Hello();<br />   alert(h.name);<br />   着非常简单。其实JavaScirpt对象就是属性和方法的集合，因此我们调用属性时可以这样调用：<br />    var h=new Hello();<br />    alert(h["name"]);<br />   并且对象动态添加属性时也可以这样：<br />   var h=new Hello();<br />   h["test"]=1234;<br />   alert(h.test);<br />   结果正常。<br />   <br />   调用方法：<br />   方法定义的时候可以是这样的<br />   var h=new Hello();<br />   h.testMethod=function()<br />   {<br />       alert("test");<br />   }<br />   可以看出，这个h的testMethod属性就是c语言中的函数指针，可以把方法进行赋值，方法名称就是方法的地址，因此还可以这样：<br />   function test(){<br />      alert("test");<br />    }<br />   h.testMethod=test;<br />   既然函数的名称就是函数的指针，当然和c语言一样不能对方法进行重载。那么如何传递参数呢？<br />   function test(a,b,c)<br />   {<br />      alert(a+b+c);<br />   }<br />   test(1,2,3);<br />   上面函数调用是正常的方法，那么下面的调用呢：<br />   test(1,2,3，4，5);<br />   当然也能正常运行，因为函数名是函数的唯一地址，那么参数4，5呢？丢失了吗？<br />   当函数传递参数时，所有的参数保存在JavaScirpt的内置对象arguments中，可以这样得到结果。<br />   function test()<br />   {<br />       if(arguments.length>=3)<br />       {<br />              return arguments[0]+arguments[1]+arguments[2];<br />       }<br />   }<br />   alert(test(1,2,3));<br />   这就是方法调用时要注意的地方arguments。<br /><br />  当然，JavaScript还可以直接定义对象：<br />   var obj={};<br />  定义一个没有属性和方法的对象obj；<br />   var obj={<br />      name:"Jerry",            <br />      "age":23,<br />      "sayHello":function（）<br />       {<br />             alert(name+",I love you");<br />       }<br /><br />   };<br />   obj.sayHello();<br />   alert(obj["name"]);<br />   这样调用完全可以运行。并且根据这种做法可以当作JavaScript中的Hashtable
          <br/>
          <span style="color:red;">
            <a href="http://bufanliu.javaeye.com/blog/204169#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Mon, 16 Jun 2008 15:25:43 +0800</pubDate>
        <link>http://bufanliu.javaeye.com/blog/204169</link>
        <guid>http://bufanliu.javaeye.com/blog/204169</guid>
      </item>
      <item>
        <title>使用BlazeDS实现Java和Flex通信</title>
        <author>bufanliu</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://bufanliu.javaeye.com">bufanliu</a>&nbsp;
          链接：<a href="http://bufanliu.javaeye.com/blog/203975" style="color:red;">http://bufanliu.javaeye.com/blog/203975</a>&nbsp;
          发表时间: 2008年06月16日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <a href="http://blog.chinaunix.net/u/21684/showart_725388.html" 