JavaScript的IE和Firefox兼容性汇编

转自feng_sundy,仅作格式调整。

以下以 IE 代替 Internet Explorer,以 MF 代替 Mozzila Firefox

1. document.form.item 问题
    (1)现有问题:
        现有代码中存在许多 document.formName.item("itemName") 这样的语句,不能在 MF 下运行
    (2)解决方法:
        改用 document.formName.elements["elementName"]
    (3)其它
        参见 2

2. 集合类对象问题
    (1)现有问题:
        现有代码中许多集合类对象取用时使用 (),IE 能接受,MF 不能。
    (2)解决方法:
        改用 [] 作为下标运算。如:document.forms("formName") 改为 document.forms["formName"]。
        又如:document.getElementsByName("inputName")(1) 改为 document.getElementsByName("inputName")[1]
    (3)其它

3. window.event
    (1)现有问题:
        使用 window.event 无法在 MF 上运行
    (2)解决方法:
        MF 的 event 只能在事件发生的现场使用,此问题暂无法解决。可以这样变通:
        原代码(可在IE中运行):
            <input type="button" name="someButton" value="提交" onclick="javascript:gotoSubmit()"/>
            …
            <script language="javascript">
                function gotoSubmit() {
                    …
                    alert(window.event);    // use window.event
                    …
                }
            </script>

        新代码(可在IE和MF中运行):
            <input type="button" name="someButton" value="提交" onclick="javascript:gotoSubmit(event)"/>
            …
            <script language="javascript">
                function gotoSubmit(evt) {
                    evt = evt ? evt : (window.event ? window.event : null);
                    …
                    alert(evt);             // use evt
                    …
                }
            </script>
        此外,如果新代码中第一行不改,与老代码一样的话(即 gotoSubmit 调用没有给参数),则仍然只能在IE中运行,但不会出错。所以,这种方案 tpl 部分仍与老代码兼容。

4. HTML 对象的 id 作为对象名的问题
    (1)现有问题
        在 IE 中,HTML 对象的 ID 可以作为 document 的下属对象变量名直接使用。在 MF 中不能。
    (2)解决方法
        用 getElementById("idName") 代替 idName 作为对象变量使用。

5. 用idName字符串取得对象的问题
    (1)现有问题
        在IE中,利用 eval(idName) 可以取得 id 为 idName 的 HTML 对象,在MF 中不能。
    (2)解决方法
        用 getElementById(idName) 代替 eval(idName)。

6. 变量名与某 HTML 对象 id 相同的问题
    (1)现有问题
        在 MF 中,因为对象 id 不作为 HTML 对象的名称,所以可以使用与 HTML 对象 id 相同的变量名,IE 中不能。
    (2)解决方法
        在声明变量时,一律加上 var ,以避免歧义,这样在 IE 中亦可正常运行。
        此外,最好不要取与 HTML 对象 id 相同的变量名,以减少错误。
    (3)其它
        参见 问题4

7. event.x 与 event.y 问题
    (1)现有问题
        在IE 中,event 对象有 x, y 属性,MF中没有。
    (2)解决方法
        在MF中,与event.x 等效的是 event.pageX。但event.pageX IE中没有。
        故采用 event.clientX 代替 event.x。在IE 中也有这个变量。
        event.clientX 与 event.pageX 有微妙的差别(当整个页面有滚动条的时候),不过大多数时候是等效的。

        如果要完全一样,可以稍麻烦些:
        mX = event.x ? event.x : event.pageX;
        然后用 mX 代替 event.x
    (3)其它
        event.layerX 在 IE 与 MF 中都有,具体意义有无差别尚未试验。

8. 关于frame
   (1)现有问题
         在 IE中 可以用window.testFrame取得该frame,mf中不行
   (2)解决方法
         在frame的使用方面mf和ie的最主要的区别是:
如果在frame标签中书写了以下属性:
<frame src="xx.htm" id="frameId" name="frameName" />
那么ie可以通过id或者name访问这个frame对应的window对象
而mf只可以通过name来访问这个frame对应的window对象
例如如果上述frame标签写在最上层的window里面的htm里面,那么可以这样访问
ie: window.top.frameId或者window.top.frameName来访问这个window对象
mf: 只能这样window.top.frameName来访问这个window对象

另外,在mf和ie中都可以使用window.top.document.getElementById("frameId")来访问frame标签
并且可以通过window.top.document.getElementById("testFrame").src = ‘xx.htm’来切换frame的内容
也都可以通过window.top.frameName.location = ‘xx.htm’来切换frame的内容
关于frame和window的描述可以参见bbs的‘window与frame’文章
以及/test/js/test_frame/目录下面的测试
—-adun 2004.12.09修改

9. 在mf中,自己定义的属性必须getAttribute()取得
10.在mf中没有  parentElement parement.children  而用
               parentNode parentNode.childNodes
   childNodes的下标的含义在IE和MF中不同,MF使用DOM规范,childNodes中会插入空白文本节点。
  一般可以通过node.getElementsByTagName()来回避这个问题。
   当html中节点缺失时,IE和MF对parentNode的解释不同,例如
   <form>
   <table>
        <input/>
   </table>
   </form>
   MF中input.parentNode的值为form, 而IE中input.parentNode的值为空节点

  MF中节点没有removeNode方法,必须使用如下方法 node.parentNode.removeChild(node)

11.const 问题
  (1)现有问题:
     在 IE 中不能使用 const 关键字。如 const constVar = 32; 在IE中这是语法错误。
  (2)解决方法:
     不使用 const ,以 var 代替。

12. body 对象
   MF的body在body标签没有被浏览器完全读入之前就存在,而IE则必须在body完全被读入之后才存在

13. url encoding
在js中如果书写url就直接写&不要写&amp;例如var url = ‘xx.jsp?objectName=xx&amp;objectEvent=xxx’;
frm.action = url那么很有可能url不会被正常显示以至于参数没有正确的传到服务器
一般会服务器报错参数没有找到
当然如果是在tpl中例外,因为tpl中符合xml规范,要求&书写为&amp;
一般MF无法识别js中的&amp;

14. nodeName 和 tagName 问题
  (1)现有问题:
     在MF中,所有节点均有 nodeName 值,但 textNode 没有 tagName 值。在 IE 中,nodeName 的使用好象
     有问题(具体情况没有测试,但我的IE已经死了好几次)。
  (2)解决方法:
     使用 tagName,但应检测其是否为空。

15. 元素属性
   IE下 input.type属性为只读,但是MF下可以修改

16. document.getElementsByName() 和 document.all[name] 的问题
  (1)现有问题:
     在 IE 中,getElementsByName()、document.all[name] 均不能用来取得 div 元素(是否还有其它不能取的元素还不知道)。

 
 

关于机器学习的讨论

Dr.Yang推荐文章一篇

《关于机器学习的讨论》王珏

另有箴言一段,摘自MSN聊天记录:

Yang: 你先粗略认识一下
Yang: 你会发现机器学习尤其是支持向量机所代表的统计学习理论 确实看起来很美妙
Yang: 你只要这样想就行了
Yang: 1 数据分析是一个很重要的事情 我们经常在实际中要遇到很多数据分析的问题
Yang: 2 拿到数据以后怎么分析呢?一般都是统计方法
Yang: 3 但是目前发展起来的统计方法都是基于样本无穷大的理论 就是说我们在分析的时候一定要假设样本趋于无穷多 才能得到理论上的结果 保证理论上是正确的

Yang: 3 并且假设数据总是满足正态分布或一个具体的分布 才能求解
Yang: 4 你可以从这2条明显的看到 实际情况肯定不是这样的
Yang: 实际是 1我们不知道数据分布是什么 2 样本数没有那么多
Yang: vapnik的伟大之处就在于他提出了有限样本情况下的统计理论
Yang: 就是说他提出的小样本统计方法 就是明确了:数据样本是有限的
Yang: 我们要依据数据样本的个数 进行适当的调整
Yang: 统计学习理论的两点假设是:1 样本数是有限的 2 数据都满足独立同分布的条件 但分布是未知的
Yang: vapnik就在这些东西上推除了一些新的概念 弄了几十年 弄出了一个形式比较简明的支持向量机
Yang: 支持向量机有很多独特的性质,我就不一一说明了

“特征选择”通俗解释

在JavaEye上看到一个帖子,其中对特征选择的解释还是比较通俗易懂的,贴过来参考参考:)

特征选择(feature selection)是一种很有实用价值的技术,本质上来说是一种为数据挖掘消除数据噪声的技术。但我们对某件事务进行判断时,我们会根据以往的经验根据 某些信息,而不是所有的信息做出判断。比如,判断一辆车的品牌,我们会去看车头车尾的标志,更细致一点会去看车的铭牌,因为这是最权威,也是最容易判断车 辆品牌的信息。如果根据车的外形去判断车辆的品牌就有可能把QQ当作Spark,把F3当作花冠;如果根据车的价格去判断,也会把奥迪和大奔弄混。也就是说,人做判断时会选择出最有效的信息来做出自己的抉择。

计算机在面对类似问题的却无法根据已有的经验去选择最有效的信息,而大量无效信息对于计算机来说就是噪声,反而会影响计算机的判断结果。如果是前面对车辆品牌进行判断的例子,还可以人工的选择出最有效的信息。但是如果面对的是DNA序列、复杂的图片,那就只能依靠计算机了。于是这就诞生了特征选择技 术,选出与结果最相关的特征,从而提高判断的准确率。

一些常用的正则表达式(JS)

JavaScript代码
  1. //校验是否全由数字组成   
  2. function isDigit(s)   
  3. {   
  4.     var patrn=/^[0-9]{1,20}$/;   
  5.     if (!patrn.exec(s)) return false  
  6.     return true  
  7. }   
  8.   
  9. //校验登录名:只能输入5-20个以字母开头、可带数字、“_”、“.”的字串   
  10. function isRegisterUserName(s)   
  11. {   
  12.     var patrn=/^[a-zA-Z]{1}([a-zA-Z0-9]|[._]){4,19}$/;   
  13.     if (!patrn.exec(s)) return false  
  14.     return true  
  15. }   
  16.   
  17. //校验用户姓名:只能输入1-30个以字母开头的字串   
  18. function isTrueName(s)   
  19. {   
  20.     var patrn=/^[a-zA-Z]{1,30}$/;   
  21.     if (!patrn.exec(s)) return false  
  22.     return true  
  23. }   
  24.   
  25. //校验密码:只能输入6-20个字母、数字、下划线   
  26. function isPasswd(s)   
  27. {   
  28.     var patrn=/^(w){6,20}$/;   
  29.     if (!patrn.exec(s)) return false  
  30.     return true  
  31. }   
  32.   
  33. //校验普通电话、传真号码:可以“+”开头,除数字外,可含有“-”   
  34. function isTel(s)   
  35. {   
  36.     //var patrn=/^[+]{0,1}(d){1,3}[ ]?([-]?(d){1,12})+$/;   
  37.     var patrn=/^[+]{0,1}(d){1,3}[ ]?([-]?((d)|[ ]){1,12})+$/;   
  38.     if (!patrn.exec(s)) return false  
  39.     return true  
  40. }   
  41.   
  42. //校验手机号码:必须以数字开头,除数字外,可含有“-”   
  43. function isMobil(s)   
  44. {   
  45.     var patrn=/^[+]{0,1}(d){1,3}[ ]?([-]?((d)|[ ]){1,12})+$/;   
  46.     if (!patrn.exec(s)) return false  
  47.     return true  
  48. }   
  49.   
  50. //校验邮政编码   
  51. function isPostalCode(s)   
  52. {   
  53.     //var patrn=/^[a-zA-Z0-9]{3,12}$/;   
  54.     var patrn=/^[a-zA-Z0-9 ]{3,12}$/;   
  55.     if (!patrn.exec(s)) return false  
  56.     return true  
  57. }   
  58.   
  59. //校验搜索关键字   
  60. function isSearch(s)   
  61. {   
  62.     var patrn=/^[^`~!@#$%^&*()+=|][]{}:;‘,.<>/?]{1}[^`~!@$%^&()+=|][]{}:;’,.<>?]{0,19}$/;   
  63.     if (!patrn.exec(s)) return false  
  64.     return true  
  65. }   
  66.   
  67. //校验是否IP地址   
  68. function isIP(s) //by zergling   
  69. {   
  70.     var patrn=/^[0-9.]{1,20}$/;   
  71.     if (!patrn.exec(s)) return false  
  72.     return true  
  73. }   
  74.   
  75.     
  76.   
  77. "^d+$"  //非负整数(正整数 + 0)   
  78. "^[0-9]*[1-9][0-9]*$"  //正整数   
  79. "^((-d+)|(0+))$"  //非正整数(负整数 + 0)   
  80. "^-[0-9]*[1-9][0-9]*$"  //负整数   
  81. "^-?d+$"    //整数   
  82. "^d+(.d+)?$"  //非负浮点数(正浮点数 + 0)   
  83. "^(([0-9]+.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*.[0-9]+)|([0-9]*[1-9][0-9]*))$"  //正浮点数   
  84. "^((-d+(.d+)?)|(0+(.0+)?))$"  //非正浮点数(负浮点数 + 0)   
  85. "^(-(([0-9]+.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*.[0-9]+)|([0-9]*[1-9][0-9]*)))$"  //负浮点数   
  86. "^(-?d+)(.d+)?$"  //浮点数   
  87. "^[A-Za-z]+$"  //由26个英文字母组成的字符串   
  88. "^[A-Z]+$"  //由26个英文字母的大写组成的字符串   
  89. "^[a-z]+$"  //由26个英文字母的小写组成的字符串   
  90. "^[A-Za-z0-9]+$"  //由数字和26个英文字母组成的字符串   
  91. "^w+$"  //由数字、26个英文字母或者下划线组成的字符串   
  92. "^[w-]+(.[w-]+)*@[w-]+(.[w-]+)+$"    //email地址   
  93. "^[a-zA-z]+://(w+(-w+)*)(.(w+(-w+)*))*(?S*)?$"  //url   
  94. "^[A-Za-z0-9_]*$"  

 

发现Weka

这两天没啥任务,挺无聊的,自己学点东西吧。
既然在学Java就找点Java的资源来看看,上次Hily推荐了几个Open Source的BI系统,还劝我改用Java,呵呵,没想到现在我真的在用Java了,既如此,不若找找基于Java的DM/BI/ML的应用吧。
顺藤摸瓜,发现了Weka。目前正在研究中!

References:

Weka
Weka is a collection of machine learning algorithms for data mining tasks. The algorithms can either be applied directly to a dataset or called from your own Java code. Weka contains tools for data pre-processing, classification, regression, clustering, association rules, and visualization. It is also well-suited for developing new machine learning schemes.

Pentaho(an open source BI base on Weka)
The Pentaho Open BI Suite provides a full spectrum of business intelligence (BI) capabilities including reporting, analysis, dashboards, data mining, data integration, and a BI platform that have made it the world’s most popular open source BI suite. Pentaho’s products are used by leading organizations including MySQL, Motorola, Terra Industries, DivX and more.

Weka CN

 

JavaScript中this关键字使用方法详解

*转载文章,仅作格式调整。

  在面向对象编程语言中,对于this关键字我们是非常熟悉的。比如C++、C#和Java等都提供了这个关键字,虽然在开始学习的时候觉得比较难,但只要 理解了,用起来是非常方便和意义确定的。JavaScript也提供了这个this关键字,不过用起来就比经典OO语言中要"混乱"的多了。

  下面就来看看,在JavaScript中各种this的使用方法有什么混乱之处?

  1、在HTML元素事件属性中inline方式使用this关键字:

XML/HTML代码
  1. <div onclick="   
  2.     // 可以在里面使用this   
  3.     ">division element</div>  

  我们一般比较常用的方法是在此使用:javascirpt: EventHandler(this),这样的形式。不过这里其实可以写任何合法的JavaScript语句,要是高兴在此定义个类也可以(不过将会是个 内部类)。这里的原理是脚本引擎生成了一个div实例对象的匿名成员方法,而onclick指向这个方法。

  2、用DOM方式在事件处理函数中使用this关键字:

XML/HTML代码
  1. <div id="elmtDiv">division element</div>  
  2. <script language="javascript">  
  3.     var div = document.getElementById(‘elmtDiv’);   
  4.     div.attachEvent(‘onclick’, EventHandler);   
  5.   
  6.     function EventHandler()   
  7.     {   
  8.        // 在此使用this   
  9.     }   
  10. </script>  

   这时的EventHandler()方法中的this关键字,指示的对象是IE的window对象。这是因为 EventHandler只是一个普通的函数,对于attachEvent后,脚本引擎对它的调用和div对象本身没有任何的关系。同时你可以再看看 EventHandler的caller属性,它是等于null的。如果我们要在这个方法中获得div对象引用,应该使 用:this.event.srcElement。

  3、用DHTML方式在事件处理函数中使用this关键字:

XML/HTML代码
  1. <div id="elmtDiv">division element</div>  
  2. <script language="javascript">  
  3.   var div = document.getElementById(‘elmtDiv’);   
  4.   div.onclick = function(){   
  5.     // 在此使用this   
  6.   };   
  7. </script>  

  这里的this关键字指示的内容是div元素对象实例,在脚本中使用DHTML方式直接为div.onclick赋值一个 EventHandler的方法,等于为div对象实例添加一个成员方法。这种方式和第一种方法的区别是,第一种方法是使用HTML方式,而这里是 DHTML方式,后者脚本解析引擎不会再生成匿名方法。

  4、类定义中使用this关键字:

JavaScript代码
  1. function JSClass(){   
  2.     var myName = ‘jsclass’;   
  3.     this.m_Name = ‘JSClass’;   
  4.     }   
  5.   
  6. JSClass.prototype.ToString = function(){   
  7.     alert(myName + ‘, ‘ + this.m_Name);   
  8.     };   
  9.   
  10. var jc = new JSClass();   
  11. jc.ToString();  

  这是JavaScript模拟类定义中对this的使用,这个和其它的OO语言中的情况非常的相识。但是这里要求成员属性和方法必须使用this关键字来引用,运行上面的程序会被告知myName未定义。 

  5、为脚本引擎内部对象添加原形方法中的this关键字:

JavaScript代码
  1. Function.prototype.GetName = function()   
  2. {   
  3.     var fnName = this.toString();    
  4.     fnName = fnName.substr(0, fnName.indexOf(‘(‘));    
  5.     fnName = fnName.replace(/^function/, );    
  6.     return fnName.replace(/(^s+)|(s+$)/g, );   
  7. }   
  8. function foo(){}   
  9. alert(foo.GetName());     

   这里的this指代的是被添加原形的类的实例,和4中类定义有些相似,没有什么太特别的地方。

  6、结合2&4,说一个比较迷惑的this关键字使用:

JavaScript代码
  1. function JSClass(){   
  2.     this.m_Text = ‘division element’;   
  3.     this.m_Element = document.createElement(‘DIV’);   
  4.     this.m_Element.innerHTML = this.m_Text;   
  5.   
  6.     this.m_Element.attachEvent(‘onclick’this.ToString);   
  7.     }   
  8.   
  9. JSClass.prototype.Render = function(){   
  10.     document.body.appendChild(this.m_Element);   
  11.     }        
  12.   
  13. JSClass.prototype.ToString = function(){   
  14.     alert(this.m_Text);   
  15.     };   
  16.   
  17. var jc = new JSClass();   
  18. jc.Render();    
  19. jc.ToString();  

  我就说说结果,页面运行后会显示:"division element",确定后点击文字"division element",将会显示:"undefined"。

  7、CSS的expression表达式中使用this关键字:

XML/HTML代码
  1. <table width="100" height="100">  
  2.   <tr>  
  3.       <td>  
  4.           <div style="width: expression(this.parentElement.width);    
  5.                 height: expression(this.parentElement.height);">  
  6.               division element</div>  
  7.       </td>  
  8.   </tr>  
  9. </table>  

  这里的this看作和1中的一样就可以了,它也是指代div元素对象实例本身。

  8、函数中的内部函数中使用this关键字:

JavaScript代码
  1. function OuterFoo(){   
  2.     this.Name = ‘Outer Name’;   
  3.   
  4.     function InnerFoo(){   
  5.         var Name = ‘Inner Name’;    
  6.         alert(Name + ‘, ‘ + this.Name);   
  7.         }   
  8.     return InnerFoo;   
  9. }   
  10. OuterFoo()();  

  运行结果显示是:"Inner Name, Outer Name"。按我们在2中的讲解,这里的结果如果是"Inner Name, undefined"似乎更合理些吧?但是正确的结果确实是前者,这是由于JavaScript变量作用域的问题决定的,详细了解推荐参看"原来JScript中的关键字’var’还是有文章的"一文及回复。

  说了这么多JavaScript中this的用法,其实this最根本的特性还是和OO语言中的定义相吻合的。之所以有这么多看似混乱的使用方式,是因为 JavaScript语言(解释器和语言本身的内容)本身在实现上是遵循OO的(Object-based),连它的所有数据类型都是对象,也有 Object这样一个super Object。但是这个语言在运行上(runtime),就没有遵循完备的OO特点,所以就出现了this的指代混乱。

  JavaScript里还有什么地方有this的使用呢?我暂时能想到的就这些了,欢迎讨论补充

Servlet和JSP和Javabean的区别

servlet和JSP和javabean的区别
悬赏分:0解决时间:2007-8-17 13:14
javabean和servlet在使用的功能上有什么区别吗?
它们都是.java文件,都要编译成.class文件放到WEB-INF目录下,好象都是为了封装某一些业务逻辑啊。
除了使用的方法上有些不同,其它似乎都一样。
小弟一头雾水。
servlet和JSP都用来编写页面的业务逻辑处理,但JSP更简单为什么还要用servlet呢?都说JSP页面注重页面效果,而 servlet注重逻辑处理,但具体什么时候用JSP什么时候用servlet我还不是很清楚,最好举个简单的例子,谢谢各位高手了,COPY别人的东西 不给分,自己说说自己的理解也可以
问题补充:回答的好自然有追加分,没有诚意的回答也自然没有分
提问者: birdnic魔法师 四级
最佳答案
首先,JavaBean和Servlet虽都是Java程序,但是是完全不同的两个概念。
引用mz3226960提出的MVC的概念,即M-model-模型:JavaBean;V-view-表现:JSP页面;C-control-控制和处理:Servlet。
其实所有的程序都可以写在jsp页面里,但是存在以下问题:
1、执行效率低下;
2、不安全,所有的程序都在jsp文件中可见,毫无知识保护可言;
3、逻辑混乱。这样让JSP文件的逻辑很难懂。
于是提出了MVC模式,即将一些处理用的程序从JSP中分离出来,让JSP页面只负责显示,几乎是html,只不过可以动态的读取数据和进行少量的逻辑处理,比如循环、判断等。
可能不举例说你还是不懂,我就举个最简单的例子——留言板。
JSP的职责:从数据库取出数据,显示所有的留言信息(当中要用少量的,简单的逻辑处理:循环)、显示签写留言的页面(几乎全部都是html)。
Servlet的职责:接受签写留言页面提交过来的标单数据,进行数据检验,如果正确,则存入数据库并返回留言的显示页面;如果数据有误,给出错误提示后 返回签写留言的页面。可以看到,这个就叫做逻辑处理。这些你也完全可以放在JSP中实现,但是用Servlet,其效率和安全性高多了,也让JSP页面变 得很简洁明了。
JavaBean的职责:其实一般的留言板是不需要用到JavaBean的,但在这里,为了让你明白,还是牵强的把JavaBean用进来。所谓 JavaBean,就是一个很简单的Java类,比如说,网上商城的所有商品是一个商品类,论坛中所有的帖子是一个帖子类,这里,留言板的所有留言是一个 留言类,叫做Message类。每个类有着它特定的属性和方法。对于Message类,其属性有主题、内容、日期、留言者等,其方法可以有添加留言、删除 留言、修改留言等。使用JavaBean,主要是为了让JSP编程能够适应Java程序员的习惯,直接对类和实例进行操作,而不是直接去操作数据库。
回答者:boyyf 试用期 一级  8-8 23:57

训练任务

TODO:

  • 学习Spring MVC step-by-step [DONE]
  • 学习ExtJs Tutorial [DONE]
  • 训练任务:实现 在地图上完成标记通过Ajax获取标记所需数据。(结合Spring MVC、ExtJS、Google Map API 和 PDMarke)。[DONE]

References:

Spring:
http://www.springframework.org/

ExtJS:
http://www.extjs.com

Google map API:
http://code.google.com/apis/maps/documentation/demogallery.html
http://code.google.com/apis/maps/documentation/reference.html

PDMarker:
 

Spring

Spring是一个开源框架,它由Rod Johnson创建。它是为了解决企业应用开发的复杂性而创建的。Spring使用基本的JavaBean来完成以前只可能由EJB完成的事情。然而,Spring的用途不仅限于服务器端的开发。从简单性、可测试性和松耦合的角度而言,任何Java应用都可以从Spring中受益。

• 目的:解决企业应用开发的复杂性

• 功能:使用基本的JavaBean代替EJB,并提供了更多的企业应用功能

• 范围:任何Java应用

简单来说,Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架。

■ 轻量——从大小与开销两方面而言Spring都是轻量的。完整的Spring框架可以在一个大小只有1MB多的JAR文件里发布。并且Spring所需的处理开销也是微不足道的。此外,Spring是非侵入式的:典型地,Spring应用中的对象不依赖于Spring的特定类。

■ 控制反转——Spring通过一种称作控制反转(IoC)的技术促进了松耦合。当应用了IoC,一个对象依赖的其它对象会通过被动的方式传递进来,而不是这个对象自己创建或者查找依赖对象。你可以认为IoC与JNDI相反——不是对象从容器中查找依赖,而是容器在对象初始化时不等对象请求就主动将依赖传递给它。

■ 面向切面——Spring提供了面向切面编程的丰富支持,允许通过分离应用的业务逻辑与系统级服务(例如审计(auditing)和事务()管理)进行内聚性的开发。应用对象只实现它们应该做的——完成业务逻辑——仅此而已。它们并不负责(甚至是意识)其它的系统级关注点,例如日志或事务支持。

■ 容器——Spring包含并管理应用对象的配置和生命周期,在这个意义上它是一种容器,你可以配置你的每个bean如何被创建——基于一个可配置原型(prototype),你的bean可以创建一个单独的实例或者每次需要时都生成一个新的实例——以及它们是如何相互关联的。然而,Spring不应该被混同于传统的重量级的EJB容器,它们经常是庞大与笨重的,难以使用。

■ 框架——Spring可以将简单的组件配置、组合成为复杂的应用。在Spring中,应用对象被声明式地组合,典型地是在一个XML文件里。Spring也提供了很多基础功能(事务管理、持久化框架集成等等),将应用逻辑的开发留给了你。

所有Spring的这些特征使你能够编写更干净、更可管理、并且更易于测试的代码。它们也为Spring中的各种模块提供了基础支持。

Spring简介
关于Spring Framework,今年夏天你可能已经听见很多的议论。在本文中,我将试图解释Spring能完成什么,和我怎么会认为它能帮助你开发J2EE应用程序。

另一framework?
你可能正在想“不过是另外一个的framework”。当已经有许多开放源代码(和专有) J2EE framework时,为什么你应该费心读这篇文章,或下载Spring Framework?

我相信Spring是独特的,因为若干个原因:
. 它定位的领域是许多其他流行的framework没有的。Spring关注提供一种方法管理你的业务对象。
. Spring是全面的和模块化的。Spring有分层的体系结构,这意味着你能选择使用它孤立的任何部分,它的架构仍然是内在稳定的。因此从你的学习中,你可得到最大的价值。例如,你可能选择仅仅使用Spring来简单化JDBC的使用,或用来管理所有的业务对象。
. 它的设计从底部帮助你编写易于测试的代码。Spring是用于测试驱动工程的理想的framework。

Spring对你的工程来说,它不需要一个以上的framework。Spring是潜在地一站式解决方案,定位于与典型应用相关的大部分基础结构。它也涉及到其他framework没有考虑到的内容。

尽管它仅仅是一个从2003年2月才开始的开源工程,但Spring有较长的历史根基。这个开源工程是起源自我在2002年后期出版的《Expert One-on-One J2EE设计与开发》书中的基础代码。这本书展示了Spring背后的基础架构。然而,这个基础架构的概念要追溯到2000年的早些时候,并且反映了我为一系列成功的商业工程开发基础结构的经验。

从2003年1月,Spring已经落户于SourceForge上。现在有10个开发人员,其中6是高度投入的积极分子。

Spring的架构性的好处

在我们进入细节以前,让我们看一下Spring可以给一个工程带来的一些好处:

. Spring能有效地组织你的中间层对象,无论你是否选择使用了EJB。如果你仅仅使用了Struts或其他的包含了J2EE特有APIs的framework,你会发现Spring关注了遗留下的问题,。

. Spring能消除在许多工程上对Singleton的过多使用。根据我的经验,这是一个主要的问题,它减少了系统的可测试性和面向对象特性。

. Spring能消除使用各种各样格式的属性定制文件的需要,在整个应用和工程中,可通过一种一致的方法来进行配置。曾经感到迷惑,一个特定类要查找迷幻般的属性关键字或系统属性,为此不得不读Javadoc乃至源编码吗?有了Spring,你可很简单地看到类的JavaBean属性。倒置控制的使用(在下面讨论)帮助完成这种简化。

. Spring能通过接口而不是类促进好的编程习惯,减少编程代价到几乎为零。
. Spring被设计为让使用它创建的应用尽可能少的依赖于他的APIs。在Spring应用中的大多数业务对象没有依赖于Spring。
. 使用Spring构建的应用程序易于单元测试。
. Spring能使EJB的使用成为一个实现选择,而不是应用架构的必然选择。你能选择用POJOs或local EJBs来实现业务接口,却不会影响调用代码。
. Spring帮助你解决许多问题而无需使用EJB。Spring能提供一种EJB的替换物,它们适于许多web应用。例如,Spring能使用AOP提供声明性事务而不通过使用EJB容器,如果你仅仅需要与单个的数据库打交道,甚至不需要JTA实现。
. Spring为数据存取提供了一致的框架,不论是使用JDBC或O/R mapping产品(如Hibernate)。
Spring确实使你能通过最简单可行的解决办法解决你的问题。这些特性是有很大价值的。

Spring能做什么?

Spring提供许多功能,在此我将快速地依次展示其各个主要方面。

任务描述:
首先,让我们明确Spring范围。尽管Spring覆盖了许多方面,但我们已经有清楚的概念,它什么应该涉及和什么不应该涉及。

Spring的主要目的是使J2EE易用和促进好编程习惯。
Spring不重新开发已有的东西。因此,在Spring中你将发现没有日志记录的包,没有连接池,没有分布事务调度。这些均有开源项目提供(例如 Commons Logging 用来做所有的日志输出,或Commons DBCP用来作数据连接池),或由你的应用程序服务器提供。因为同样的的原因,我们没有提供O/R mapping层,对此,已有有好的解决办法如Hibernate和JDO。

Spring的目标是使已存在的技术更加易用。例如,尽管我们没有底层事务协调处理,但我们提供了一个抽象层覆盖了JTA或任何其他的事务策略。

Spring没有直接和其他的开源项目竞争,除非我们感到我们能提供新的一些东西。例如,象许多开发人员,我们从来没有为Struts高兴过,并且感到在 MVC web framework中还有改进的余地。在某些领域,例如轻量级的IoC容器和AOP框架,Spring有直接的竞争,但是在这些领域还没有已经较为流行的解决方案。(Spring在这些区域是开路先锋。)

Spring也得益于内在的一致性。
所有的开发者都在唱同样的的赞歌,基础想法依然是Expert One-on-One J2EE设计与开发的那些。
并且我们已经能够使用一些主要的概念,例如倒置控制,来处理多个领域。

Spring在应用服务器之间是可移植的。
当然保证可移植性总是一次挑战,但是我们避免任何特定平台或非标准化,并且支持在WebLogic,Tomcat,Resin,JBoss,WebSphere和其他的应用服务器上的用户。