??xml version="1.0" encoding="utf-8" standalone="yes"?>亚洲国产精品线观看不卡,亚洲综合网美国十次,亚洲愉拍一区二区三区http://www.tkk7.com/xyzroundo/zh-cnSat, 10 May 2025 21:02:34 GMTSat, 10 May 2025 21:02:34 GMT60struts-config.xml配置說明http://www.tkk7.com/xyzroundo/articles/246585.htmlxyzxyzTue, 16 Dec 2008 03:11:00 GMThttp://www.tkk7.com/xyzroundo/articles/246585.htmlhttp://www.tkk7.com/xyzroundo/comments/246585.htmlhttp://www.tkk7.com/xyzroundo/articles/246585.html#Feedback0http://www.tkk7.com/xyzroundo/comments/commentRss/246585.htmlhttp://www.tkk7.com/xyzroundo/services/trackbacks/246585.html阅读全文

xyz 2008-12-16 11:11 发表评论
]]>
Javascript 闭包http://www.tkk7.com/xyzroundo/articles/240618.htmlxyzxyzFri, 14 Nov 2008 16:14:00 GMThttp://www.tkk7.com/xyzroundo/articles/240618.htmlhttp://www.tkk7.com/xyzroundo/comments/240618.htmlhttp://www.tkk7.com/xyzroundo/articles/240618.html#Feedback0http://www.tkk7.com/xyzroundo/comments/commentRss/240618.htmlhttp://www.tkk7.com/xyzroundo/services/trackbacks/240618.htmlJavascript 闭包

译Q?a title="Z漫笔" >Z漫笔
链接Q?a title="原文链接" >http://www.cn-cuckoo.com/2007/08/01/understand-javascript-closures-72.html
英文原版Q?a >http://jibbering.com/faq/faq_notes/closures.html

?/a>

Closure
所?#8220;闭包”Q指的是一个拥有许多变量和l定了这些变量的环境的表辑ּQ通常是一个函敎ͼQ因而这些变量也是该表达式的一部分?

闭包?ECMAScript QJavaScriptQ最强大的特性之一Q但用好闭包的前提是必须理解闭包。闭包的创徏相对ҎQh们甚至会在不l意间创建闭包,但这些无意创建的闭包却存在潜在的危害Q尤其是在比较常见的览器环境下。如果想要扬镉K短地使用闭包q一Ҏ,则必M解它们的工作机制。而闭包工作机制的实现很大E度上有赖于标识W(或者说对象属性)解析q程中作用域的角艌Ӏ?

关于闭包Q最单的描述是 ECMAScript 允许使用内部函数Q-卛_数定义和函数表达式位于另一个函数的函数体内。而且Q这些内部函数可以访问它们所在的外部函数中声明的所有局部变量、参数和声明的其他内部函数。当其中一个这L内部函数在包含它们的外部函数之外被调用时Q就会Ş成闭包。也是_内部函数会在外部函数q回后被执行。而当q个内部函数执行Ӟ它仍然必需讉K其外部函数的局部变量、参C及其他内部函数。这些局部变量、参数和函数声明Q最初时Q的值是外部函数q回时的|但也会受到内部函数的影响?

遗憾的是Q要适当地理解闭包就必须理解闭包背后q行的机Ӟ以及许多相关的技术细节。虽然本文的前半部分q没有涉?ECMA 262 规范指定的某些算法,但仍然有许多无法回避或简化的内容。对于个别熟悉对象属性名解析的h来说Q可以蟩q相关的内容Q但是除非你寚w包也非常熟悉Q否则最好是不要跌下面几节?

对象属性名解析

ECMAScript 认可两类对象Q原生(NativeQ对象和宿主QHostQ对象,其中宿主对象包含一个被UCؓ内置对象的原生对象的子类QECMA 262 3rd Ed Section 4.3Q。原生对象属于语aQ而宿d象由环境提供Q比如说可能是文档对象、DOM {类似的对象?

原生对象h松散和动态的命名属性(对于某些实现的内|对象子cd而言Q动态性是受限的-Q但q不是太大的问题Q。对象的命名属性用于保存|该值可以是指向另一个对象(ObjectsQ的引用Q在q个意义上说Q函C是对象)Q也可以是一些基本的数据cdQ比如:String、Number、Boolean、Null ?Undefined。其中比较特D的?Undefined cdQ因为可以给对象的属性指定一?Undefined cd的|而不会删除对象的相应属性。而且Q该属性只是保存着 undefined 倹{?

下面要介l一下如何设|和d对象的属性|q最大程度地体现相应的内部细节?

值的赋予

对象的命名属性可以通过命名属性赋值来创徏Q或重新赋倹{即Q对于:

var objectRef = new Object(); //创徏一个普通的 javascript 对象?/span>

可以通过下面语句来创建名?“testNumber” 的属性:

objectRef.testNumber = 5;
/* - ? */
objectRef["testNumber"] = 5;

在赋g前,对象中没?#8220;testNumber” 属性,但在赋值后Q则创徏一个属性。之后的M赋D句都不需要再创徏q个属性,而只会重新设|它的|

objectRef.testNumber = 8;
/* - ? */
objectRef["testNumber"] = 8;

E后我们会介l,Javascript 对象都有原型QprototypesQ属性,而这些原型本w也是对象,因而也可以带有命名的属性。但是,原型对象命名属性的作用q不体现在赋值阶Dc同P在将Dl其命名属性时Q如果对象没有该属性则会创命名属性,否则会重设该属性的倹{?

值的d

当读取对象的属性值时Q原型对象的作用便体现出来。如果对象的原型中包含属性访问器Qproperty accessorQ所使用的属性名Q那么该属性的值就会返回:

/* 为命名属性赋倹{如果在赋值前对象没有相应的属性,那么赋值后׃得到一个:*/
objectRef.testNumber = 8;
/* 从属性中d?*/
var val = objectRef.testNumber;
/* 现在Q?- val - 中保存着刚赋l对象命名属性的?8*/

而且Q由于所有对象都有原型,而原型本w也是对象,所以原型也可能有原型,q样构成了所谓的原型链。原型链l止于链中原型ؓ null 的对象?code>Object 构造函数的默认原型有一?null 原型Q因此:

var objectRef = new Object(); //创徏一个普通的 JavaScript 对象?/span>

创徏了一个原型ؓ Object.prototype 的对象,而该原型自n则拥有一个gؓ null 的原型。也是_objectRef 的原型链中只包含一个对象-Q?Object.prototype。但对于下面的代码而言Q?

/* 创徏 - MyObject1 - cd对象的函?/
function MyObject1(formalParameter){
/* l创建的对象d一个名?- testNumber -
的属性ƈ传递给构造函数的W一个参数指定ؓ该属性的|*/
this.testNumber = formalParameter;
}
/* 创徏 - MyObject2 - cd对象的函?/
function MyObject2(formalParameter){
/* l创建的对象d一个名?- testString -
的属性ƈ传递给构造函数的W一个参数指定ؓ该属性的|*/
this.testString = formalParameter;
}

/* 接下来的操作?MyObject1 cȝ实例替换了所有与 MyObject2
cȝ实例相关联的原型。而且Qؓ MyObject1 构造函C递了参数
- 8 - Q因而其 - testNumber - 属性被赋予该|*/
MyObject2.prototype = new MyObject1( 8 );

/* 最后,一个字W串作ؓ构造函数的W一个参敎ͼ
创徏一?- MyObject2 - 的实例,q将指向该对象的
引用赋给变量 - objectRef - Q?/
var objectRef = new MyObject2( "String_Value" );

被变?objectRef 所引用?MyObject2 的实例拥有一个原型链。该链中的第一个对象是在创建后被指定给 MyObject2 构造函数的 prototype 属性的 MyObject1 的一个实例?code>MyObject1 的实例也有一个原型,即与 Object.prototype 所引用的对象对应的默认?Object 对象的原型。最后, Object.prototype 有一个gؓ null 的原型,因此q条原型铑ֈ此结束?

当某个属性访问器试d?objectRef 所引用的对象的属性值时Q整个原型链都会被搜索。在下面q种单的情况下:

var val = objectRef.testString;

因ؓ objectRef 所引用?MyObject2 的实例有一个名?#8220;testString”的属性,因此被设|ؓ“String_Value”的该属性的D赋给了变?val。但是:

var val = objectRef.testNumber;

则不能从 MyObject2 实例自n中读取到相应的命名属性|因ؓ该实例没有这个属性。然而,变量 val 的g然被讄?8Q而不是未定义Q-q是因ؓ在该实例中查扄应的命名属性失败后Q解释程序会l箋查其原型对象。而该实例的原型对象是 MyObject1 的实例,q个实例有一个名?#8220;testNumber”的属性ƈ且gؓ 8Q所以这个属性访问器最后会取得?8。而且Q虽?MyObject1 ?MyObject2 都没有定?toString ҎQ但是当属性访问器通过 objectRef d toString 属性的值时Q?

var val = objectRef.toString;

变量 val 也会被赋予一个函数的引用。这个函数就是在 Object.prototype ?toString 属性中所保存的函数。之所以会q回q个函数Q是因ؓ发生了搜?code>objectRef 原型铄q程。当在作为对象的 objectRef 中发现没?#8220;toString”属性存在时Q会搜烦其原型对象,而当原型对象中不存在该属性时Q则会l搜索原型的原型。而原型链中最l的原型?Object.prototypeQ这个对象确实有一?toString ҎQ因此该Ҏ的引用被q回?

最后:

var val = objectRef.madeUpProperty;

q回 undefinedQ因为在搜烦原型铄q程中,直至 Object.prototype 的原型-QnullQ都没有扑ֈM对象有名?#8220;madeUpPeoperty”的属性,因此最l返?undefined?

不论是在对象或对象的原型中,d命名属性值的时候只q回首先扑ֈ的属性倹{而当为对象的命名属性赋值时Q如果对象自w不存在该属性则创徏相应的属性?

q意味着Q如果执行像 objectRef.testNumber = 3 q样一条赋D句,那么q个 MyObject2 的实例自w也会创Z个名?#8220;testNumber”的属性,而之后Q何读取该命名属性的试都将获得相同的新倹{这时候,属性访问器不会再进一步搜索原型链Q但 MyObject1 实例gؓ 8 ?#8220;testNumber”属性ƈ没有被修攏V给 objectRef 对象的赋值只是遮挡了其原型链中相应的属性?

注意QECMAScript ?Object cd定义了一个内?[[prototype]] 属性。这个属性不能通过脚本直接讉KQ但在属性访问器解析q程中,则需要用到这个内?[[prototype]] 属性所引用的对象链Q-卛_型链。可以通过一个公q prototype 属性,来对与内部的 [[prototype]] 属性对应的原型对象q行赋值或定义。这两者之间的关系?ECMA 262Q?rd editionQ中有详l描qͼ但超Z本文要讨论的范畴?

标识W解析、执行环境和作用域链

执行环境

执行环境?ECMAScript 规范QECMA 262 W?3 版)用于定义 ECMAScript 实现必要行ؓ的一个抽象的概念。对如何实现执行环境Q规范没有作规定。但׃执行环境中包含引用规范所定义l构的相兛_性,因此执行环境中应该保有(甚至实现Q带有属性的对象Q-即属性不是公共属性?

所?JavaScript 代码都是在一个执行环境中被执行的。全局代码Q作为内|的 JS 文g执行的代码,或?HTML 面加蝲的代码)是在我将UC?#8220;全局执行环境”的执行环境中执行的,而对函数的每ơ调用(有可能是作ؓ构造函敎ͼ同样有关联的执行环境。通过 eval 函数执行的代码也有截然不同的执行环境Q但因ؓ JavaScript E序员在正常情况下一般不会?evalQ所以这里不作讨论。有x行环境的详细说明请参?ECMA 262Q第 3 版)W?10.2 节?

当调用一?JavaScript 函数Ӟ该函数就会进入相应的执行环境。如果又调用了另外一个函敎ͼ或者递归地调用同一个函敎ͼQ则又会创徏一个新的执行环境,q且在函数调用期间执行过E都处于该环境中。当调用的函数返回后Q执行过E会q回原始执行环境。因而,q行中的 JavaScript 代码构成了一个执行环境栈?

在创建执行环境的q程中,会按照定义的先后序完成一pd操作。首先,在一个函数的执行环境中,会创Z?#8220;zd”对象。活动对象是规范中规定的另外一U机制。之所以称之ؓ对象Q是因ؓ它拥有可讉K的命名属性,但是它又不像正常对象那样h原型Q至没有预定义的原型)Q而且不能通过 JavaScript 代码直接引用zd对象?

为函数调用创建执行环境的下一步是创徏一?arguments 对象Q这是一个类似数l的对象Q它以整数烦引的数组成员一一对应C存着调用函数时所传递的参数。这个对象也?length ?callee 属性(q两个属性与我们讨论的内Ҏ养I详见规范Q。然后,会ؓzd对象创徏一个名?#8220;arguments”的属性,该属性引用前面创建的 arguments 对象?

接着Qؓ执行环境分配作用域。作用域由对象列表(链)l成。每个函数对象都有一个内部的 [[scope]] 属性(该属性我们稍后会详细介绍Q,q个属性也由对象列表(链)l成。指定给一个函数调用执行环境的作用域,p函数对象?[[scope]] 属性所引用的对象列表(链)l成Q同Ӟzd对象被添加到该对象列表的剙Q链的前端)?

之后会发生由 ECMA 262 中所?#8220;可变”对象完成?#8220;变量实例?#8221;的过E。只不过此时使用zd对象作ؓ可变对象Q这里很重要Q请注意Q它们是同一个对象)。此时会函数的形式参数创徏为可变对象命名属性,如果调用函数时传递的参数与Ş式参C_则将相应参数的Dl这些命名属性(否则Q会l命名属性赋 undefined |。对于定义的内部函数Q会以其声明时所用名UCؓ可变对象创徏同名属性,而相应的内部函数则被创徏为函数对象ƈ指定l该属性。变量实例化的最后一步是在函数内部声明的所有局部变量创Zؓ可变对象的命名属性?

Ҏ声明的局部变量创建的可变对象的属性在变量实例化过E会被赋?undefined 倹{在执行函数体内的代码、ƈ计算相应的赋D辑ּ之前不会对局部变量执行真正的实例化?

事实上,拥有 arguments 属性的zd对象和拥有与函数局部变量对应的命名属性的可变对象是同一个对象。因此,可以标识符 arguments 作ؓ函数的局部变量来看待?

回到剙

最后,在this可以被用之前,q必d对其赋倹{如果赋的值是一个对象的引用Q则 this.m 讉K的便是该对象上的 m。如果(内部Q赋的值是 nullQ则this指向全局对象?Q此D는 pangba 刘未?/a> 译Q?

Q原文备考:Finally a value is assigned for use with the this keyword. If the value assigned refers to an object then property accessors prefixed with the this keyword reference properties of that object. If the value assigned (internally) is null then the this keyword will refer to the global object. Q?

创徏全局执行环境的过E会E有不同Q因为它没有参数Q所以不需要通过定义的活动对象来引用q些参数。但全局执行环境也需要一个作用域Q而它的作用域铑֮际上只由一个对象-Q全局对象Q-l成。全局执行环境也会有变量实例化的过E,它的内部函数是涉及大部?JavaScript 代码的、常规的函数声明。而且Q在变量实例化过E中全局对象是可变对象Q这是Z么全局性声明的函数是全局对象属性的原因。全局性声明的变量同样如此?

全局执行环境也会使用 this 对象来引用全局对象?

作用域链?[[scope]]

调用函数时创建的执行环境会包含一个作用域链,q个作用域链是通过该执行环境的活动(可变Q对象添加到保存于所调用函数对象?[[scope]] 属性中的作用域铑։端而构成的。所以,理解函数对象内部?[[scope]] 属性的定义q程臛_重要?

?ECMAScript 中,函数也是对象。函数对象在变量实例化过E中会根据函数声明来创徏Q或者是在计函数表辑ּ或调?Function 构造函数时创徏?

通过调用 Function 构造函数创建的函数对象Q其内部?[[scope]] 属性引用的作用域链中始l只包含全局对象?

通过函数声明或函数表辑ּ创徏的函数对象,其内部的 [[scope]] 属性引用的则是创徏它们的执行环境的作用域链?

在最单的情况下,比如声明如下全局函数Q?

function exampleFunction(formalParameter){
...   // 函数体内的代?/span>
}

当ؓ创徏全局执行环境而进行变量实例化Ӟ会根据上面的函数声明创徏相应的函数对象。因为全局执行环境的作用域链中只包含全局对象Q所以它q自己创徏的、ƈ以名?#8220;exampleFunction”的属性引用的q个函数对象的内?[[scope]] 属性,赋予了只包含全局对象的作用域链?

当在全局环境中计函数表辑ּӞ也会发生cM的指定作用域铄q程Q?

var exampleFuncRef = function(){
...   // 函数体代?/span>
}

在这U情况下Q不同的是在全局执行环境的变量实例化q程中,会先为全局对象创徏一个命名属性。而在计算赋D句之前,暂时不会创徏函数对象Q也不会该函数对象的引用指定给全局对象的命名属性。但是,最l还是会在全局执行环境中创个函数对象(当计函数表辑ּ时。译者注Q,而ؓq个创徏的函数对象的 [[scope]] 属性指定的作用域链中仍然只包含全局对象?

内部的函数声明或表达式会D在包含它们的外部函数的执行环境中创徏相应的函数对象,因此q些函数对象的作用域链会E微复杂一些。在下面的代码中Q先定义了一个带有内部函数声明的外部函数Q然后调用外部函敎ͼ

function exampleOuterFunction(formalParameter){
function exampleInnerFuncitonDec(){
... // 内部函数体代?/span>
}
...  // 其余的外部函C代码
}
exampleOuterFunction( 5 );

与外部函数声明对应的函数对象会在全局执行环境的变量实例化q程中被创徏。因此,外部函数对象?[[scope]] 属性中会包含一个只有全局对象?#8220;单项?#8221;作用域链?

当在全局执行环境中调?exampleOuterFunction 函数Ӟ会ؓ该函数调用创Z个新的执行环境和一个活动(可变Q对象。这个新执行环境的作用域q新的zd对象后跟外部函数对象?[[scope]] 属性所引用的作用域链(只有全局对象Q构成。在新执行环境的变量实例化过E中Q会创徏一个与内部函数声明对应的函数对象,而同时会l这个函数对象的 [[scope]] 属性指定创函数对象的执行环境(x执行环境。译者注Q的作用域|Q即一个包含活动对象后跟全局对象的作用域链?

到目前ؓ止,所有过E都是自动、或者由源代码的l构所控制的。但我们发现Q执行环境的作用域链定义了执行环境所创徏的函数对象的 [[scope]] 属性,而函数对象的 [[scope]] 属性则定义了它的执行环境的作用域(包括相应的活动对象)。不q,ECMAScript 也提供了用于修改作用域链 with 语句?

with 语句会计一个表辑ּQ如果该表达式是一个对象,那么将q个对象d到当前执行环境的作用域链中(在活?lt;可变>对象之前Q。然后,执行 with 语句Q它自n也可能是一个语句块Q中的其他语句。之后,又恢复到调用它之前的执行环境的作用域链中?

with 语句不会影响在变量实例化q程中根据函数声明创建函数对象。但是,可以在一?with 语句内部对函数表辑ּ求|-

/* 创徏全局变量 - y - 它引用一个对象:- */
var y = {x:5}; // 带有一个属?- x - 的对象直接量
function exampleFuncWith(){
var z;
/* 全局对象 - y - 引用的对象添加到作用域链的前端:- */
with(y){
/* 对函数表辑ּ求|以创建函数对象ƈ该函数对象的引用指定给局部变?- z - :-  */
z = function(){
... // 内部函数表达式中的代?
}
}
...
}
/* 执行 - exampleFuncWith - 函数:- */
exampleFuncWith();

在调?exampleFuncWith 函数所创徏的执行环境中包含一个由其活动对象后跟全局对象构成的作用域链。而在执行 with 语句Ӟ又会把全局变量 y 引用的对象添加到q个作用域链的前端。在对其中的函数表达式求值的q程中,所创徏函数对象?[[scope]] 属性与创徏它的执行环境的作用域保持一_Q即Q该属性会引用一个由对象 y 后跟调用外部函数时所创徏执行环境的活动对象,后跟全局对象的作用域链?

当与 with 语句相关的语句块执行l束Ӟ执行环境的作用域得以恢复Q?code>y 会被U除Q,但是已经创徏的函数对象(z。译者注Q的 [[scope]] 属性所引用的作用域链中位于最前面的仍然是对象 y?

标识W解?/a>

标识W是沿作用域N向解析的。ECMA 262 ?this 归类为关键字而不是标识符Qƈ非不合理。因?this 值时始终要根据用它的执行环境来判断Q而与作用域链无关?

标识W解析从作用域链中的W一个对象开始。检查该对象中是否包含与标识W对应的属性名。因Z用域链是一条对象链Q所以这个检查过E也会包含相应对象的原型链(如果有)。如果没有在作用域链的第一个对象中发现相应的|解析q程会l搜索下一个对象。这样依ơ类推直xC用域链中包含以标识符为属性名的对象ؓ止,也有可能在作用域铄所有对象中都没有发现该标识W?

当基于对象用属性访问器Ӟ也会发生与上面相同的标识W解析过E。当属性访问器中有相应的属性可以替换某个对象时Q这个属性就成ؓ表示该对象的标识W,该对象在作用域链中的位置q而被定。全局对象始终都位于作用域铄?

因ؓ与函数调用相关的执行环境会把活动(可变Q对象添加到作用域链的前端,所以在函数体内使用的标识符会首先检查自己是否与形式参数、内部函数声明的名称或局部变量一致。这些都可以由活动(可变Q对象的命名属性来定?

闭包

自动垃圾攉

ECMAScript 要求使用自动垃圾攉机制。但规范中ƈ没有详细说明相关的细节,而是留给了实现来军_。但据了解,相当一部分实现对它们的垃圾攉操作只赋予了很低的优先。但是,大致的思想都是相同的,卛_果对象不?#8220;可引用(׃不存在对它的引用Q执行代码无法再访问到它)”Ӟ该对象就成ؓ垃圾攉的目标。因而,在将来的某个时刻会将q个对象销毁ƈ它所占用的一切资源释放,以便操作pȝ重新利用?

正常情况下,当退Z个执行环境时׃满cM的条件。此Ӟ作用域链l构中的zdQ可变)对象以及在该执行环境中创建的M对象Q-包括函数对象Q都不再“可引?#8221;Q因此将成ؓ垃圾攉的目标?

构成闭包

闭包是通过在对一个函数调用的执行环境中返回一个函数对象构成的。比如,在对函数调用的过E中Q将一个对内部函数对象的引用指定给另一个对象的属性。或者,直接这样一个(内部Q函数对象的引用指定l一个全局变量、或者一个全局性对象的属性,或者一个作为参C引用方式传递给外部函数的对象。例如:-

function exampleClosureForm(arg1, arg2){
var localVar = 8;
function exampleReturned(innerArg){
return ((arg1 + arg2)/(innerArg + localVar));
}
/* q回一个定义ؓ exampleReturned 的内部函数的引用 -:-  */
return exampleReturned;
}
var globalVar = exampleClosureForm(2, 4);

q种情况下,在调用外部函?exampleClosureForm 的执行环境中所创徏的函数对象就不会被当作垃圾收集,因ؓ该函数对象被一个全局变量所引用Q而且仍然是可以访问的Q甚臛_以通过 globalVar(n) 来执行?

的确Q情冉|正常的时候要复杂一些。因为现在这个被变量 globalVar 引用的内部函数对象的 [[scope]] 属性所引用的作用域链中Q包含着属于创徏该内部函数对象的执行环境的活动对象(和全局对象Q。由于在执行?globalVar 引用的函数对象时Q每ơ都要把该函数对象的 [[scope]] 属性所引用的整个作用域链添加到创徏的(内部函数的)执行环境的作用域中(x时的作用域中包括Q内部执行环境的zd对象、外部执行环境的zd对象、全局对象。译者注Q, 所以这个(外部执行环境的)zd对象不会被当作垃圾收集?

闭包因此而构成。此Ӟ内部函数对象拥有自由的变量,而位于该函数作用域链中的zdQ可变)对象则成Z变量l定的环境?

׃zdQ可变)对象受限于内部函数对象(现在?globalVar 变量引用Q的 [[scope]] 属性中作用域链的引用,所以活动对象连同它的变量声明-Q即属性的|都会被保留。而在对内部函数调用的执行环境中进行作用域解析Ӟ会把与zdQ可变)对象的命名属性一致的标识W作对象的属性来解析。活动对象的q些属性值即使是在创建它的执行环境退出后Q仍然可以被d和设|?

在上面的例子中,当外部函数返回(退出它的执行环境)Ӟ其活动(可变Q对象的变量声明中记录了形式参数、内部函数定义以及局部变量的倹{?code>arg1 属性的gؓ 2Q?arg2 属性的gؓ 4Q?code>localVar 的值是 8Q还有一?exampleReturned 属性,它引用由外部函数q回的内部函数对象。(为方便v见,我们在后面的讨ZQ称q个zd<可变>对象?"ActOuter1"Q?

如果再次调用 exampleClosureForm 函数Q如Q?

var secondGlobalVar = exampleClosureForm(12, 3);

- 则会创徏一个新的执行环境和一个新的活动对象。而且Q会q回一个新的函数对象,该函数对象的 [[scope]] 属性引用的作用域链与前一ơ不同,因ؓq一ơ的作用域链中包含着W二个执行环境的zd对象Q而这个活动对象的属?arg112 而属?arg23。(为方便v见,我们在后面的讨ZQ称q个zd<可变>对象?"ActOuter2"Q?

通过W二ơ执?exampleClosureForm 函数Q第二个、也是截然不同的闭包诞生了?

通过执行 exampleClosureForm 创徏的两个函数对象分别被指定l了全局变量 globalVar ?secondGlobalVarQƈq回了表辑ּ ((arg1 + arg2)/(innerArg + localVar))。该表达式对其中的四个标识符应用了不同的操作W。如何确定这些标识符的值是体现闭包价值的关键所在?

我们来看一看,在执行由 globalVar 引用的函数对象-Q如 globalVar(2)Q-时的情Ş。此Ӟ会创Z个新的执行环境和相应的活动对象(我们称之ؓ“ActInner1”Q,q把该活动对象添加到执行的函数对象的 [[scope]] 属性所引用的作用域铄前端。ActInner1 会带有一个属?innerArgQ根据传递的形式参数Q其D指定?2。这个新执行环境的作用域铑֏成: ActInner1->ActOuter1->全局对象.

Zq回表达?((arg1 + arg2)/(innerArg + localVar)) 的|要沿着作用域链q行标识W解析。表辑ּ中标识符的值将通过依次查找作用域链中每个对象(与标识符名称一_的属性来定?

作用域链中的W一个对象是 ActInner1Q它有一个名?innerArg 的属性,值是 2。所有其他三个标识符?ActOuter1 中都有对应的属性:arg1 ?2Q?code>arg2 ?4 ?localVar ?8。最后,函数调用q回 ((2 + 2)/(2 + 8))?

现在再来看一看由 secondGlobalVar 引用的同一个函数对象的执行情况Q比?secondGlobalVar(5)。我们把q次创徏的新执行环境的活动对象称?“ActInner2”Q相应的作用域链变成了Q?span class="scopeCh">ActInner2->ActOuter2->全局对象。ActInner2 q回 innerArg 的?5Q?ActOuter2 分别q回 arg1?code>arg2 ?localVar 的?12?code>3 ?8。函数调用返回的值就?((12 + 3)/(5 + 8))?

如果再执行一?secondGlobalVarQ则又会有一个新zd对象被添加到作用域链的前端,?ActOuter2 仍然是链中的W二个对象,而他的命名属性会再次用于完成标识W?arg1?code>arg2 ?localVar 的解析?

q就?ECMAScript 的内部函数获取、维持和讉K创徏他们的执行环境的形式参数、声明的内部函数以及局部变量的q程。这个过E说明了构成闭包以后Q内部的函数对象在其存箋q程中,如何l持对这些值的引用、如何对q些D行读取的机制。即Q创建内部函数对象的执行环境的活动(可变Q对象,会保留在该函数对象的 [[scope]] 属性所引用的作用域链中。直到所有对q个内部函数的引用被释放Q这个函数对象才会成为垃圾收集的目标Q连同它的作用域链中M不再需要的对象Q?

内部函数自n也可能有内部函数。在通过函数执行q回内部函数构成闭包以后Q相应的闭包自n也可能会q回内部函数从而构成它们自q闭包。每ơ作用域铑ֵ套,都会增加由创建内部函数对象的执行环境引发的新zd对象。ECMAScript 规范要求作用域链是时性的Q但对作用域铄长度却没有加以限制。在具体实现中,可能会存在实际的限制Q但q没有发现有具体限制数量的报告。目前来看,嵌套的内部函数所拥有的潜能,仍然出了用它们的人的惛_能力?

通过闭包可以做什么?

对这个问题的回答可能会o你惊ӞQ闭包什么都可以做。据我所知,闭包使得 ECMAScript 能够模仿M事物Q因此局限性在于设计和实现要模仿事物的能力。只是从字面上看可能会觉得这么说很深奥,下面我们来看一些更有实际意义的例子?

?1Qؓ函数引用讄延时

闭包的一个常见用法是在执行函C前ؓ要执行的函数提供参数。例如:函C?setTimout 函数的第一个参敎ͼq在 Web 览器的环境下是非常常见的一U应用?

setTimeout 用于有计划地执行一个函敎ͼ或者一?JavaScript 代码Q不是在本例中)Q要执行的函数是其第一个参敎ͼ其第二个参数是以毫秒表示的执行间隔。也是_当在一D代码中使用 setTimeout Ӟ要将一个函数的引用作ؓ它的W一个参敎ͼ而将以毫U表C的旉g为第二个参数。但是,传递函数引用的同时无法划执行的函数提供参数?

然而,可以在代码中调用另外一个函敎ͼ由它q回一个对内部函数的引用,再把q个对内部函数对象的引用传递给 setTimeout 函数。执行这个内部函数时要用的参数在调用返回它的外部函数时传递。这PsetTimeout 在执行这个内部函数时Q不用传递参敎ͼ但该内部函数仍然能够讉K在调用返回它的外部函数时传递的参数Q?

function callLater(paramA, paramB, paramC){
/* q回一个由函数表达式创建的匿名内部函数的引?- */

return (function(){
/* q个内部函数通过 - setTimeout - 执行Q?
而且当它执行时它会读取ƈ按照传递给
外部函数的参数行事:
*/
paramA[paramB] = paramC;
});
}
...
/* 调用q个函数返回一个在其执行环境中创徏的内部函数对象的引用?
传递的参数最l将作ؓ外部函数的参数被内部函数使用?
q回的对内部函数的引用被赋给一个全局变量:-
*/

var functRef = callLater(elStyle, "display", "none");
/* 调用 setTimeout 函数Q将赋给变量 - functRef -
的内部函数的引用作ؓ传递的W一个参?- */

hideMenu=setTimeout(functRef, 500);

?2: 通过对象实例Ҏ兌函数

回到剙

许多时候我们需要将一个函数对象暂时挂C个引用上留待后面执行Q因Z{到执行的时候是很难知道其具体参数的Q而先前将它赋l那个引用的时候更是压根不知道的?Q此D는 pangba 刘未?/a> 译Q?

Qluyy朋友的翻译_2008-7-7更新Q很多时候需要将一个函数引用进行赋|以便在将来某个时候执行该函数Q在执行q些函数时给函数提供参数会是有用处的,但这些参数在执行时不Ҏ获得Q他们只有在上面赋值给时才能确定?

Q原文备考:There are many other circumstances when a reference to a function object is assigned so that it would be executed at some future time where it is useful to provide parameters for the execution of that function that would not be easily available at the time of execution but cannot be known until the moment of assignment.Q?/p>

一个相关的例子是,?JavaScript 对象来封装与特定 DOM 元素的交互。这?JavaScript 对象h doOnClick?code>doMouseOver ?doMouseOut ҎQƈ且当用户在该特定?DOM 元素中触发了相应的事件时要执行这些方法。不q,可能会创Z不同?DOM 元素兌的Q意数量的 JavaScript 对象Q而且每个对象实例q不知道实例化它们的代码会如何操纵它们Q即注册事g处理函数与定义相应的事g处理函数分离。译者注Q。这些对象实例ƈ不知道如何在全局环境中引用它们自w,因ؓ它们不知道将会指定哪个全局变量Q如果有Q引用它们的实例?

因而问题可以归lؓ执行一个与特定?JavaScript 对象兌的事件处理函敎ͼq且要知道调用该对象的哪个方法?/p>

下面q个例子使用了一个基于闭包构建的一般化的函敎ͼ此句多谢未鹏指点Q,该函C对象实例与 DOM 元素事g兌hQ安排执行事件处理程序时调用对象实例的指定方法,l象的指定方法传递的参数是事件对象和与元素关联的引用Q该函数q回执行相应Ҏ后的q回倹{?

/* 一个关联对象实例和事g处理器的函数?
它返回的内部函数被用作事件处理器。对象实例以 - obj - 参数表示Q?
而在该对象实例中调用的方法名则以 - methodName - Q字W串Q参数表C?
*/

function associateObjWithEvent(obj, methodName){
/* 下面q个q回的内部函数将作ؓ一?DOM 元素的事件处理器*/

return (function(e){
 /* 在支持标?DOM 规范的浏览器中,事g对象会被解析为参?- e - Q?
若没有正常解析,则?IE 的事件对象来规范化事件对象?
*/

e = e||window.event;
/* 事g处理器通过保存在字W串 - methodName - 中的Ҏ名调用了对象
- obj - 的一个方法。ƈ传递已l规范化的事件对象和触发事g处理器的元素
的引?- this - Q之所?this 有效是因个内部函数是作ؓ该元素的Ҏ执行的)
*/

return obj[methodName](e, this);
});
}
/* q个构造函数用于创建将自n?DOM 元素兌的对象,
DOM 元素?ID 作ؓ构造函数的字符串参数?
所创徏的对象会在相应的元素触发 onclick?
onmouseover ?onmouseout 事gӞ
调用相应的方法?
*/

function DhtmlObject(elementId){
/* 调用一个返?DOM 元素Q如果没扑ֈq回 nullQ引用的函数Q?
必需的参数是 ID?返回的Dl局部变?- el -?
*/ 
var el = getElementWithId(elementId);
 /* - el - g在内部通过cd转换变ؓ布尔|以便 - if - 语句加以判断?
因此Q如果它引用一个对象结果将q回 trueQ如果是 null 则返?false?
下面的代码块只有?- el - 变量q回一?DOM 元素时才会被执行?
*/
if(el){
/* 为给元素的事件处理器指定一个函敎ͼ该对象调用了
- associateObjWithEvent - 函数?
同时对象自w(通过 - this - 关键字)作ؓ调用Ҏ的对象,
q提供了调用的方法名U?- associateObjWithEvent - 函数会返?
一个内部函敎ͼ该内部函数被指定?DOM 元素的事件处理器?
在响应事件时Q执行这个内部函数就会调用必要的Ҏ?
*/
el.onclick = associateObjWithEvent(this, "doOnClick");
el.onmouseover = associateObjWithEvent(this, "doMouseOver");
el.onmouseout = associateObjWithEvent(this, "doMouseOut");
...
}
}
DhtmlObject.prototype.doOnClick = function(event, element){
... // doOnClick Ҏ体?/span>.
}
DhtmlObject.prototype.doMouseOver = function(event, element){
... // doMouseOver Ҏ体?/span>
}
DhtmlObject.prototype.doMouseOut = function(event, element){
... // doMouseOut Ҏ体?/span>
}

q样Q?code>DhtmlObject 的Q何实例都会将自n与相应的 DOM 元素兌hQ而这?DOM 元素不必知道其他代码如何操纵它们Q即当触发相应事件时Q会执行什么代码。译者注Q,也不必理会全局命名I间的媄响以及与 DhtmlObject 的其他实例间存在冲突的危险?

?3Q包装相关的功能

闭包可以用于创徏额外的作用域Q通过该作用域可以相关的和具有依赖性的代码l织hQ以便将意外交互的风险降到最低。假设有一个用于构建字W串的函敎ͼZ避免重复性的q接操作Q和创徏众多的中间字W串Q,我们的愿望是使用一个数l按序来存储字W串的各个部分,然后再?Array.prototype.join ҎQ以I字W串作ؓ其参敎ͼ输出l果。这个数l将作ؓ输出的缓冲器Q但是将数组作ؓ函数的局部变量又会导致在每次调用函数旉重新创徏一个新数组Q这在每ơ调用函数时只重新指定数l中的可变内容的情况下ƈ不是必要的?

一U解x案是这个数l声明ؓ全局变量Q这样就可以重用q个数组Q而不必每ơ都建立新数l。但q个Ҏ的结果是Q除了引用函数的全局变量会用这个缓冲数l外Q还会多Z个全局属性引用数l自w。如此不仅代码变得不容易管理,而且Q如果要在其他地方用这个数l时Q开发者必要再次定义函数和数l。这样一来,也得代码不Ҏ与其他代码整合,因ؓ此时不仅要保证所使用的函数名在全局命名I间中是唯一的,而且q要保证函数所依赖的数l在全局命名I间中也必须是唯一的?

而通过闭包可以使作为缓冲器的数l与依赖它的函数兌hQ优雅地打包Q,同时也能够维持在全局命名I间外指定的~冲数组的属性名Q免除了名称冲突和意外交互的危险?

其中的关键技巧在于通过执行一个单行(in-lineQ函数表辑ּ创徏一个额外的执行环境Q而将该函数表辑ּq回的内部函C为在外部代码中用的函数。此Ӟ~冲数组被定义ؓ函数表达式的一个局部变量。这个函数表辑ּ只需执行一ơ,而数l也只需创徏一ơ,可以供依赖它的函数重复使用?

下面的代码定义了一个函敎ͼq个函数用于q回一?HTML 字符Ԍ其中大部分内定w是常量,但这些常量字W序列中需要穿插一些可变的信息Q而可变的信息p用函数时传递的参数提供?

通过执行单行函数表达式返回一个内部函敎ͼq将q回的函数赋l一个全局变量Q因此这个函C可以UCؓ全局函数。而缓冲数l被定义为外部函数表辑ּ的一个局部变量。它不会暴露在全局命名I间中,而且无论什么时候调用依赖它的函数都不需要重新创个数l?

/* 声明一个全局变量 - getImgInPositionedDivHtml -
q将一ơ调用一个外部函数表辑ּq回的内部函数赋l它?
q个内部函数会返回一个用于表C绝对定位的 DIV 元素
包围着一?IMG 元素 ?HTML 字符Ԍq样一来,
所有可变的属性值都p用该函数时的参数提供Q?
*/
var getImgInPositionedDivHtml = (function(){
/* 外部函数表达式的局部变?- buffAr - 保存着~冲数组?
q个数组只会被创Zơ,生成的数l实例对内部函数而言永远是可用的
因此Q可供每ơ调用这个内部函数时使用?
其中的空字符串用作数据占位符Q相应的数据
由内部函数插入到这个数l中Q?
*/
var buffAr = [
'<div id="',
'',   //index 1, DIV ID 属?/span>
'" style="position:absolute;top:',
'',   //index 3, DIV 剙位置
'px;left:',
'',   //index 5, DIV 左端位置
'px;width:',
'',   //index 7, DIV 宽度
'px;height:',
'',   //index 9, DIV 高度
'px;overflow:hidden;\"><img src=\"',
'',   //index 11, IMG URL
'\" width=\"',
'',   //index 13, IMG 宽度
'\" height=\"',
'',   //index 15, IMG 调蓄
'\" alt=\"',
'',   //index 17, IMG alt 文本内容
'\"><\/div>'
];
/* q回作ؓ对函数表辑ּ求值后l果的内部函数对象?
q个内部函数是每次调用执行的函?
- getImgInPositionedDivHtml( ... ) -
*/
return (function(url, id, width, height, top, left, altText){
/* 不同的参数插入到缓冲数l相应的位置Q?
*/
buffAr[1] = id;
buffAr[3] = top;
buffAr[5] = left;
buffAr[13] = (buffAr[7] = width);
buffAr[15] = (buffAr[9] = height);
buffAr[11] = url;
buffAr[17] = altText;
/* q回通过使用I字W串Q相当于数l元素连接v来)
q接数组每个元素后Ş成的字符Ԍ
*/
return buffAr.join('');
}); //:内部函数表达式结束?/span>
})();
/*^^- :单行外部函数表达式?/

如果一个函C赖于另一Q或多)个其他函敎ͼ而其他函数又没有必要被其他代码直接调用,那么可以q用相同的技术来包装q些函数Q而通过一个公开暴露的函数来调用它们。这P将一个复杂的多函数处理过E封装成了一个具有移植性的代码单元?

其他例子

有关闭包的一个可能是最qؓ人知的应用是 Douglas Crockford's technique for the emulation of private instance variables in ECMAScript objects。这U应用方式可以扩展到各种嵌套包含的可讉K性(或可见性)的作用域l构Q包?the emulation of private static members for ECMAScript objects?

闭包可能的用途是无限的,可能理解其工作原理才是把握如何用它的最好指南?

意外的闭?/a>

在创建可讉K的内部函数的函数体之外解析该内部函数׃构成闭包。这表明闭包很容易创建,但这样一来可能会D一U结果,x有认识到闭包是一U语aҎ的 JavaScript 作者,会按照内部函数能完成多种d的想法来使用内部函数。但他们对用内部函数的l果q不明了Q而且Ҏ意识不到创徏了闭包,或者那样做意味着什么?

正如下一节谈?IE 中内存泄漏问题时所提及的,意外创徏的闭包可能导致严重的负面效应Q而且也会影响C码的性能。问题不在于闭包本nQ如果能够真正做到}慎地使用它们Q反而会有助于创建高效的代码。换句话_使用内部函数会媄响到效率?

使用内部函数最常见的一U情况就是将其作?DOM 元素的事件处理器。例如,下面的代码用于向一个链接元素添?onclick 事g处理器:

/* 定义一个全局变量Q通过下面的函数将它的?
作ؓ查询字符串的一部分d到链接的 - href - 中:
*/
var quantaty = 5;
/* 当给q个函数传递一个链接(作ؓ函数中的参数 - linkRef -Q时Q?
会将一?onclick 事g处理器指定给该链接,该事件处理器
全局变量 - quantaty - 的g为字W串d到链接的 - href -
属性中Q然后返?true 使该链接在单d定位到由  - href -
属性包含的查询字符串指定的资源Q?
*/
function addGlobalQueryOnClick(linkRef){
/* 如果可以参?- linkRef - 通过cd转换?ture
Q说明它引用了一个对象)Q?
*/
if(linkRef){
/* 对一个函数表辑ּ求|q将对该函数对象的引?
指定l这个链接元素的 onclick 事g处理器:
*/
linkRef.onclick = function(){
/* q个内部函数表达式将查询字符?
d到附加事件处理器的元素的 - href - 属性中Q?
*/
this.href += ('?quantaty='+escape(quantaty));
return true;
};
}
}

无论什么时候调?addGlobalQueryOnClick 函数Q都会创Z个新的内部函敎ͼ通过赋值构成了闭包Q。从效率的角度上看,如果只是调用一两次 addGlobalQueryOnClick 函数q没有什么大的妨,但如果频J用该函数Q就会导致创多截然不同的函数对象Q每对内部函数表辑ּ求一ơ|׃产生一个新的函数对象)?

上面例子中的代码没有x内部函数在创建它的函数外部可以访问(或者说构成了闭包)q一事实。实际上Q同L效果可以通过另一U方式来完成。即单独地定义一个用于事件处理器的函敎ͼ然后该函数的引用指定给元素的事件处理属性。这P只需创徏一个函数对象,而所有用相同事件处理器的元素都可以׃n对这个函数的引用Q?

/* 定义一个全局变量Q通过下面的函数将它的?
作ؓ查询字符串的一部分d到链接的 - href - 中:
*/
var quantaty = 5;
/* 当把一个链接(作ؓ函数中的参数 - linkRef -Q传递给q个函数Ӟ
会给q个链接d一?onclick 事g处理器,该事件处理器?
全局变量  - quantaty - 的g为查询字W串的一部分d?
链接?- href -  中,然后q回 trueQ以便单击链接时定位到由
作ؓ - href - 属性值的查询字符串所指定的资源:
*/
function addGlobalQueryOnClick(linkRef){
/* 如果 - linkRef - 参数能够通过cd转换?true
Q说明它引用了一个对象)Q?
*/
if(linkRef){
/* 一个对全局函数的引用指定给q个链接
的事件处理属性,使函数成为链接元素的事g处理器:
*/
linkRef.onclick = forAddQueryOnClick;
}
}
/* 声明一个全局函数Q作为链接元素的事g处理器,
q个函数一个全局变量的gd事g处理器的
链接元素? - href - 值的一部分Q?
*/
function forAddQueryOnClick(){
this.href += ('?quantaty='+escape(quantaty));
return true;
}

在上面例子的W一个版本中Q内部函数ƈ没有作ؓ闭包发挥应有的作用。在那种情况下,反而是不用闭包更有效率,因ؓ不用重复创徏许多本质上相同的函数对象?

cM地考量同样适用于对象的构造函数。与下面代码中的构造函数框架类似的代码q不|见Q?

function ExampleConst(param){
/* 通过对函数表辑ּ求值创建对象的ҎQ?
q将求值所得的函数对象的引用赋l要创徏对象的属性:
*/
this.method1 = function(){
... // Ҏ体?/span>
};
this.method2 = function(){
... // Ҏ体?/span>
};
this.method3 = function(){
... // Ҏ体?/span>
};
/* 把构造函数的参数赋给对象的一个属性:
*/
this.publicProp = param;
}

每当通过 new ExampleConst(n) 使用q个构造函数创Z个对象时Q都会创Zl新的、作为对象方法的函数对象。因此,创徏的对象实例越多,相应的函数对象也p多?

Douglas Crockford 提出的模?JavaScript 对象U有成员的技术,利用了对内部函数的引用指定给在构造函C构造对象的公共属性而Ş成的闭包。如果对象的Ҏ没有利用在构造函C形成的闭包,那么在实例化每个对象时创建的多个函数对象Q会使实例化q程变慢Q而且有更多的资源被占用Q以满创徏更多函数对象的需要?

q那U情况下Q只创徏一ơ函数对象,q把它们指定l构造函?prototype 的相应属性显然更有效率。这样一来,它们p被构造函数创建的所有对象共享了Q?

function ExampleConst(param){
/* 构造函数的参数赋给对象的一个属性:
*/
this.publicProp = param;
}
/* 通过对函数表辑ּ求|q将l果函数对象的引?
指定l构造函数原型的相应属性来创徏对象的方法:
*/
ExampleConst.prototype.method1 = function(){
... // Ҏ体?/span>
};
ExampleConst.prototype.method2 = function(){
... // Ҏ体?/span>
};
ExampleConst.prototype.method3 = function(){
... // Ҏ体?/span>
};

Internet Explorer 的内存泄漏问?

Internet Explorer Web 览器(?IE 4 ?IE 6 中核实)的垃圾收集系l中存在一个问题,卛_?ECMAScript 和某些宿d象构成了 "循环引用"Q那么这些对象将不会被当作垃圾收集。此时所谓的宿主对象指的是Q?DOM 节点Q包?document 对象及其后代元素Q和 ActiveX 对象。如果在一个@环引用中包含了一或多个这L对象Q那么这些对象直到浏览器关闭都不会被释放Q而它们所占用的内存同样在览器关闭之前都不会交回pȝ重用?

当两个或多个对象以首q的方式怺引用Ӟ构成了循环引用。比如对?1 的一个属性引用了对象 2 Q对?2 的一个属性引用了对象 3Q而对?3 的一个属性又引用了对?1。对于纯_的 ECMAScript 对象而言Q只要没有其他对象引用对?1??Q也是说它们只是相互之间的引用Q那么仍然会被垃圾收集系l识别ƈ处理。但是,?Internet Explorer 中,如果循环引用中的M对象?DOM 节点或?ActiveX 对象Q垃圾收集系l则不会发现它们之间的@环关pMpȝ中的其他对象是隔ȝq攑֮们。最l它们将被保留在内存中,直到览器关闭?

闭包非常Ҏ构成循环引用。如果一个构成闭包的函数对象被指定给Q比如一?DOM 节点的事件处理器Q而对该节点的引用又被指定l函数对象作用域中的一个活动(或可变)对象Q那么就存在一个@环引用?span class="scopeCh">DOM_Node.onevent ->function_object.[[scope]] ->scope_chain ->Activation_object.nodeRef ->DOM_Node。Ş成这样一个@环引用是轻而易丄Q而且E微览一下包含类似@环引用代码的|站Q通常会出现在|站的每个页面中Q,׃消耗大量(甚至全部Q系l内存?

多加注意可以避免形成循环引用Q而在无法避免Ӟ也可以用补偿的ҎQ比如?IE ?onunload 事g来来清空QnullQ事件处理函数的引用。时L识到q个问题q理解闭包的工作机制是在 IE 中避免此c问题的关键?

comp.lang.javascript FAQ notes T.O.C.

  • 撰稿 Richard CornfordQ?004 q?3 ?
  • 修改来自Q?br />
    • Martin Honnen.
    • Yann-Erwan Perio (Yep).
    • Lasse Reichstein Nielsen. (definition of closure)
    • Mike Scirocco.
    • Dr John Stockton.


xyz 2008-11-15 00:14 发表评论
]]>
struts-config.xml配置文g說明http://www.tkk7.com/xyzroundo/articles/239907.htmlxyzxyzTue, 11 Nov 2008 08:36:00 GMThttp://www.tkk7.com/xyzroundo/articles/239907.htmlhttp://www.tkk7.com/xyzroundo/comments/239907.htmlhttp://www.tkk7.com/xyzroundo/articles/239907.html#Feedback0http://www.tkk7.com/xyzroundo/comments/commentRss/239907.htmlhttp://www.tkk7.com/xyzroundo/services/trackbacks/239907.html阅读全文

xyz 2008-11-11 16:36 发表评论
]]>
web.xml學習{記 http://www.tkk7.com/xyzroundo/articles/237791.htmlxyzxyzFri, 31 Oct 2008 04:38:00 GMThttp://www.tkk7.com/xyzroundo/articles/237791.htmlhttp://www.tkk7.com/xyzroundo/comments/237791.htmlhttp://www.tkk7.com/xyzroundo/articles/237791.html#Feedback0http://www.tkk7.com/xyzroundo/comments/commentRss/237791.htmlhttp://www.tkk7.com/xyzroundo/services/trackbacks/237791.html阅读全文

xyz 2008-10-31 12:38 发表评论
]]>
区别.htm.html.dhtml.xhtml.shtm.shtmlQASP、JSP、PHPhttp://www.tkk7.com/xyzroundo/articles/229376.htmlxyzxyzWed, 17 Sep 2008 03:43:00 GMThttp://www.tkk7.com/xyzroundo/articles/229376.htmlhttp://www.tkk7.com/xyzroundo/comments/229376.htmlhttp://www.tkk7.com/xyzroundo/articles/229376.html#Feedback0http://www.tkk7.com/xyzroundo/comments/commentRss/229376.htmlhttp://www.tkk7.com/xyzroundo/services/trackbacks/229376.html來源:http://hi.baidu.com/yangfan356/blog/item/78b98f3dedd6fcc29f3d62ab.html
解密.htm.html.shtm.shtml的区别与联系 

  每一个网|者说是web都有其固定的后~名,不同的后~名对应着不同的文件格式和不同的规则、协议、用法,最常见的web늚后缀名是.html?htmQ但q只是web|基本的两U文件格式,今天我们来介l一下web늚其它一些文件格式?br />
首先Q介l一下html与htmQ?br />
  关于HTMLQHTML(HyperTextMark-upLanguage)卌文本标记语言Q是WWW的描q语a。设计HTML语言的目的是Z能把存放在一台电脑中的文本或囑Ş与另一台电脑中的文本或囑Ş方便地联pd一P形成有机的整体,Z不用考虑具体信息是在当前电脑上还是在|络的其它电脑上。我们只需使用鼠标在某一文档中点取一个图标,Internet׃马上转到与此图标相关的内容上去,而这些信息可能存攑֜|络的另一台电脑中?HTML文本是由HTML命ol成的描q性文本,HTML命o可以说明文字、图形、动甅R声韟뀁表根{链接等。HTML的结构包括头?Head)、主?Body)两大部分Q其中头部描q浏览器所需的信息,而主体则包含所要说明的具体内容?br />
  关于HTMQ实际上HTM与HTML没有本质意义的区别,只是Z满DOS仅能识别8+3的文件名而已Q因Z些老的pȝ(win32)不能识别四位文g名,所以某些网|务器要求index.html最后一个l不能省略。MSIE能自动识别和打开q些文gQ但~写|页地址的时候必L完全对应的,也就是说index.htm和index.html是两个不同的文gQ对应着不同的地址。值得一提的是UNIXpȝ中对大小写敏感,不吻合的话就可能报没有文件或者找不到文g?br />
其次Q介l一下shtml和shtmQ?br />
  关于shtmlQshtml是一U基于SSI技术的文gQ也是Server Side Include--SSI 服务器端包含指oQ一些Web Server如果有SSI功能的话׃对shtml文gҎ招待Q服务器会先扫一ơshtml文g看没有特D的SSI指o存在Q如果有的话按Web Server讑֮规则解释SSI指oQ解释完后跟一般html一赯dL?br />
  关于shtmQshtm与shtml的关pdhtm与html的关pd致相|q里׃多说了?br />
html或htm与shtml或shtm的关pL什么?

  html或者htm是一U静态的面格式Q也是说不需要服务器解析其中的脚本,或者说里面没有服务器端执行的脚本,而shtml或者shtm׃它基于SSI技术,当有服务器端可执行脚本时被当作一U动态编E语a来看待,如asp、jsp或者php一栗当shtml或者shtm中不包含服务器端可执行脚本时其作用和html或者htm是一L?/p>

 

什么是SHTML?与HTML的区?

  问vSHTML和HTML的区别,如果用一句话来解释就是:SHTML 不是HTML而是一U服务器 APIQshtml是服务器动态成的html?

  虽然两者都是超文本格式Q但shtml是一U用于SSI技术的文g。也是Server Side Include--SSI 服务器端包含指o。如果Web Server有SSI功能的话(大多敎ͼ其是基于Unixq_Q的WEB服务器如Netscape Enterprise Server{均支持SSI命o)?会对shtml文gҎ招待?先扫一ơshtml文g看没有特D的SSI指o现在?有就按Web Server讑֮规则解释SSI指o?解释完后跟一般html一hdL?

shtmlQ?br />   使用SSI(Server Side Include)的html文g扩展名,SSIQServer Side Include)Q通常UCؓ"服务器端嵌入"或者叫"服务器端包含"Q是一U类gASP的基于服务器的网制作技术?

SSI工作原理Q?
  内容发送到览器之前,可以使用“服务器端包含 (SSI)”指o文本、图形或应用E序信息包含到网中。例如,可以使用 SSI 包含旉/日期戟뀁版权声明或供客户填写ƈq回的表单。对于在多个文g中重复出现的文本或图形,使用包含文g是一U简便的Ҏ。将内容存入一个包含文件中卛_Q而不必将内容输入所有文件。通过一个非常简单的语句卛_调用包含文gQ此语句指示 Web 服务器将内容插入适当|页。而且Q用包含文件时Q对内容的所有更改只需在一个地方就能完成?

  因ؓ包含 SSI 指o的文件要求特D处理,所以必Mؓ所?SSI 文g赋予 SSI 文g扩展名。默认扩展名?.stm?shtm ?.shtml

  Web 服务器在处理|页的同时处?SSI 指o。当 Web 服务器遇?SSI 指oӞ直接包含文件的内容插入 HTML |页。如?#8220;包含文g”中包?SSI 指oQ则同时插入此文件。除了用于包含文件的基本指o之外Q还可以使用 SSI 指o插入文g的相关信息(如文件的大小Q或者运行应用程序或 shell 命o?

  |站l护常常到的一个问题是Q网站的l构已经固定Q却Z更新一点内容而不得不重做一大批|页。SSI提供了一U简单、有效的Ҏ来解册一问题Q它一个网站的基本l构攑֜几个单的HTML文g中(模板Q,以后我们要做的只是将文本传到服务器,让程序按照模板自动生成网,从而ɽ理大型|站变得Ҏ?

  所以,利用SHTML格式的页面目的和 ASP 差不多,但是因ؓ?API 所以运转速度更快Q效率更高,比ASP快,比HTML慢,但由于可以用服务器端包含,因此佉K面更新容易(特别是批量更新bannerQ版权等Q,惌一下吧Q你有一D?HTMLQ要在中间穿插一些特D的服务端脚本,比如插入其他 HTML D落Q你选择 ASP 来完成这个Q务,但是如果d更繁重,需要更多的旉Q比?5 sQ这个时候你不用 ASP 而用 SHTMLQ或许处理时间就只用 4 s ?

 

  动态网|与静态网늛对应的,也就是说Q网?URL的后~不是.htm?html?shtml?xml{静态网늚常见形式Q而是?asp?jsp?php?perl?cgi{Ş式ؓ后缀Qƈ且在动态网늽址中有一个标志性的W号“?”Q如有这样一个动态网늚地址?

  http://www.pagehome.cn/ip/index.asp?id=1

  q就是一个典型的动态网URL形式?br />
  q里说的动态网,与网上的各U动甅R滚动字q等视觉上的“动态效?#8221;没有直接关系Q动态网也可以是纯文字内容的,也可以是包含各种动画的内容,q些只是|页具体内容的表现Ş式,无论|页是否h动态效果,采用动态网站技术生成的|页都称为动态网c?br />
  从网站浏览者的角度来看Q无论是动态网还是静态网,都可以展C基本的文字和图片信息,但从|站开发、管理、维护的角度来看有很大的差别。网l营销教学|站动态网늚一般特点简要归U_?

  (1)动态网以数据库技术ؓ基础Q可以大大降低网站维护的工作?

  (2)采用动态网|术的|站可以实现更多的功能,如用h册、用L录、在U调查、用L理、订单管理等{?

  (3)动态网实际上q不是独立存在于服务器上的网|Ӟ只有当用戯求时服务器才q回一个完整的|页;

  (4)动态网中?#8220;?”Ҏ索引擎检索存在一定的问题Q搜索引擎一般不可能从一个网站的数据库中讉K全部|页Q或者出于技术方面的考虑Q搜索蜘蛛不L取网址?#8220;?”后面的内容,因此采用动态网늚|站在进行搜索引擎推q时需要做一定的技术处理才能适应搜烦引擎的要求?

dhtml:


  切地说QDHTML只是一U制作网늚概念Q实际上没有一个组l或机构推出q所谓的DHTML标准或技术规范之cȝ。DHTML不是一U技术、标准或规范QDHTML只是一U将目前已有的网|术、语a标准整和q用Q制作出能在下蝲后仍然能实时变换面元素效果的网늚设计概念?
  DHTML大致包含以下|页技术、标准或规范Q?
  HTML 4.0 Q没什么好说的Q网늚基础语言标准?
  CSSLQ注意!不是CSSQ是CSSLQ它是Clent-Side Scripting Language的羃写,译作“客户端脚本语a”Q主要有JavaScript(JS)QVBScript(VBS)QJScript。Netscape主要支持JSQIE主要支持JSQVBS和JScript?
  DOMQDocument Object Model的羃写,译作“文档对象模型”Q是W3C日前极力推广的web技术标准之一Q它网中的内Ҏ象成对象Q每个对象拥有各自的属?Properties)、方?Method)和事?Events)Q这些都可以通过上面讲到的CSSL来进行控制。IE和NS的对象模型都是以W3C的公布的DOM为基准,加上自己的Extended Object(扩展对象)来生成的?
  CSS Q这才是Cascading Style Sheets(层叠样式表单)的羃写,也是在论坛讨论最多的技术规范,它是HTML的辅助设计规范,用来弥补HTML在排版上的所受的限制D的不I它是DOM的一部分。理Z说通过CSSL动态地改变CSS属性可以做ZQ何你惌的页面视觉效果?
  所以,单地_要实现DHTMLQ就是以HTML为基Q运用DOM页面元素对象化Q利用CSSL控制q些对象的CSS属性以辑ֈ|页的动态视觉效果?

shtml:

  问vSHTML和HTML的区?如果用一句话来解释就?SHTML 不是HTML而是一U服务器 API,shtml是服务器动态成的html.

  虽然两者都是超文本格式,但shtml是一U用于SSI技术的文g?也就是Server Side Include--SSI 服务器端包含指o?如果Web Server有SSI功能的话(大多敎ͼ其是基于Unixq_Q的WEB服务器如Netscape Enterprise Server{均支持SSI命o)?会对shtml文gҎ招待?先扫一ơshtml文g看没有特D的SSI指o现在?有就按Web Server讑֮规则解释SSI指o?解释完后跟一般html一hdL?
shtmlQ用SSI(Server Side Include)的html文g扩展名,SSIQServer Side Include)Q通常UCؓ"服务器端嵌入"或者叫"服务器端包含"Q是一U类gASP的基于服务器的网制作技术?

  SSI工作原理Q将内容发送到览器之前,可以使用“服务器端包含 (SSI)”指o文本、图形或应用E序信息包含到网中。例如,可以使用 SSI 包含旉/日期戟뀁版权声明或供客户填写ƈq回的表单。对于在多个文g中重复出现的文本或图形,使用包含文g是一U简便的Ҏ。将内容存入一个包含文件中卛_Q而不必将内容输入所有文件。通过一个非常简单的语句卛_调用包含文gQ此语句指示 Web 服务器将内容插入适当|页。而且Q用包含文件时Q对内容的所有更改只需在一个地方就能完成?

  因ؓ包含 SSI 指o的文件要求特D处理,所以必Mؓ所?SSI 文g赋予 SSI 文g扩展名。默认扩展名?.stm?shtm ?.shtml

  Web 服务器在处理|页的同时处?SSI 指o。当 Web 服务器遇?SSI 指oӞ直接包含文件的内容插入 HTML |页。如?#8220;包含文g”中包?SSI 指oQ则同时插入此文件。除了用于包含文件的基本指o之外Q还可以使用 SSI 指o插入文g的相关信息(如文件的大小Q或者运行应用程序或 shell 命o?

  |站l护常常到的一个问题是Q网站的l构已经固定Q却Z更新一点内容而不得不重做一大批|页。SSI提供了一U简单、有效的Ҏ来解册一问题Q它一个网站的基本l构攑֜几个单的HTML文g中(模板Q,以后我们要做的只是将文本传到服务器,让程序按照模板自动生成网,从而ɽ理大型|站变得Ҏ?

  所?利用SHTML格式的页面目的和 ASP 差不多,但是因ؓ?API 所以运转速度更快Q效率更?比ASP快,比HTML慢,但由于可以用服务器端包含,因此佉K面更新容易(特别是批量更新bannerQ版权等Q?惌一下吧,你有一D?HTML,要在中间I插一些特D的服务端脚?比如插入其他 HTML D落,你选择 ASP 来完成这个Q?但是如果d更繁重,需要更多的旉Q比?5 s,q个时候你不用 ASP 而用 SHTML,或许处理旉只?4 s ?

xhtml:
  HTML是一U基本的WEB|页设计语言QXHTML是一个基于XML的置标语aQ看h与HTML有些相象Q只有一些小的但重要的区别,XHTML是一个扮演着cMHTML的角色的XMLQ所以,本质上说QXHTML是一个过渡技术,l合了XMLQ有几分Q的强大功能及HTMLQ大多数Q的单特性?

  2000q底Q国际W3C(World Wide Web Consortium)l织公布发行了XHTML 1.0版本。XHTML 1.0是一U在HTML 4.0基础上优化和改进的的新语aQ目的是ZXML应用。XHTML是一U增Z的HTML,它的可扩展性和灉|性将适应未来|络应用更多的需求。下面是W3C的HTML工作l主席Steven Pemberton回答的关于XHTML的常见基问题?

  Q?QXHTML解决HTML语言所存在的严重制U其发展的问题。HTML发展C天存在三个主要缺点:不能适应现在多的网l设备和应用的需要,比如手机、PDA、信息家电都不能直接昄HTMLQ由于HTML代码不规范、臃肿,览器需要够智能和庞大才能够正显CHTMLQ数据与表现hQ这样你的页面要改变昄Q就必须重新制作HTML。因此HTML需要发展才能解册个问题,于是W3C又制定了XHTMLQXHTML是HTML向XMLq度的一个桥梁?

  Q?QXML是web发展的趋势,所以h们急切的希望加入XML的潮中。XHTML是当前替代HTML4标记语言的标准,使用XHTML 1.0Q只要你心遵守一些简单规则,可以设计出既适合XMLpȝQ又适合当前大部分HTML览器的面。这个意思就是说Q你可以立刻设计使用XMLQ而不需要等Ch们都使用支持XML的浏览器。这个指导方针可以webqx的过渡到XML?

  Q?Q用XHTML的另一个优势是Q它非常严密。当前网l上的HTML的糟p情况让人震惊,早期的浏览器接受U有的HTML标签Q所以h们在面设计完毕后必M用各U浏览器来检页面,看是否兼容,往往会有许多莫名其妙的差异,Z不得不修改设计以侉K应不同的浏览器?

  Q?QXHTML是能与其它基于XML的标记语a、应用程序及协议q行良好的交互工作?

  Q?QXHTML是Web标准家族的一部分Q能很好在无U设备等其它用户代理上?

  Q?Q在|站设计斚wQXHTML可助你去掉表现层代码的恶习,帮助你养成标记校验来试面工作的习惯?br />

ASP,JSP,PHP有什么区别和共同点?

回答Q一Q?br /> 不同Q?br />   1.web服务器不一P是q行环境不一栗一般ASP用IISQPHP用APACHE
  2.语法不一?ASP是VBS/JSQJSP和JAVA语法怼QPHP语法和CQJAVA怼
  3.q行方式不一PASPQPHP是解释型的,JSP是可~译型的
相同Q?br />   1.都是服务器端嵌入式脚本语a
  2.能实现CGI所能实现的大部分东ѝ?br />
回答Q二Q?br />   asp是vb
  jsp是java
  php是c/c++

回答Q三Q?br />
ASP、JSP与PHP的比?br />

  目前Q最常用的三U动态网语a有ASP(Active Server Pages),JSP(Java Server Pages),PHP (Hypertext Preprocessor)?

?
  ASP全名Active Server PagesQ是一个WEB服务器端的开发环境, 利用它可以生和q行动态的、交互的、高性能的WEB服务应用E序。ASP采用脚本语言VB ScriptQJava scriptQ作q开发语a?

  PHP是一U跨q_的服务器端的嵌入式脚本语a. 它大量地借用C,Java和Perl语言的语? q耦合PHP自己的特?使WEB开发者能够快速地写出动态生成页?它支持目前绝大多数数据库。还有一点,PHP是完全免费的Q不用花钱,你可以从PHP官方站点(http://www.php.net)自由下蝲。而且你可以不受限制地获得源码Q甚臛_以从中加q你自己需要的特色?

  JSP 是Sun公司推出的新一代站点开发语aQ它完全解决了目前ASP,PHP的一个通病Q-脚本U执行(据说PHP4 也已l在Zend 的支持下Q实现编译运行).Sun 公司借助自己在Java 上的不凡造诣Q将Java 从Java 应用E序 ?Java Applet 之外Q又有新的硕果,是JspQ-Java Server Page。Jsp 可以在Serverlet和JavaBean的支持下Q完成功能强大的站点E序?

  三者都提供?HTML 代码中؜合某U程序代码、由语言引擎解释执行E序代码的能力。但JSP代码被编译成 Servlet q由 Java 虚拟释执行,q种~译操作仅在?JSP 面的第一ơ请求时发生。在 ASP 、PHP、JSP 环境下, HTML 代码主要负责描述信息的显C样式,而程序代码则用来描述处理逻辑。普通的 HTML 面只依赖于 Web 服务器,?ASP 、PHP、JSP 面需要附加的语言引擎分析和执行程序代码。程序代码的执行l果被重新嵌入到HTML 代码中,然后一起发送给览器?ASP 、PHP?JSP三者都是面?Web 服务器的技术,客户端浏览器不需要Q何附加的软g支持?

技术特?

ASP:

  1. 使用 VBScript ?JScript {简单易懂的脚本语言Q结?HTML 代码Q即可快速地完成|站的应用程序?

  2. 无须 compile ~译Q容易编写,可在服务器端直接执行?

  3. 使用普通的文本~辑器,?Windows 的记事本Q即可进行编辑设计?

  4. 与浏览器无关 (Browser Independence), 用户端只要用可执行 HTML 码的览器,卛_览 Active Server Pages 所设计的网内宏V?Active Server Pages 所使用的脚本语a (VBScript ?Jscript) 均在 WEB 服务器端执行Q用L的浏览器不需要能够执行这些脚本语a?
  5.Active Server Pages 能与M ActiveX scripting 语言相容。除了可使用 VBScript ?JScript 语言来设计外Q还通过 plugQin 的方式,使用q三方所提供的其他脚本语aQ譬?REXX ?Perl ?Tcl {。脚本引擎是处理脚本E序?COM(Component Object Model) 物g?

  6. 可用服务器端的脚本来生客L的脚本?

  7.ActiveX Server Components(ActiveX 服务器元?) h无限可扩充性。可以?Visual Basic ?Java ?Visual CQ+ ?COBOL {编E语a来编写你所需要的ActiveX Server Component ?

PHP:

1Q数据库q接
  PHP可以~译成具有与许多数据库相q接的函数。PHP与MySQL是现在绝佳的l合。你q可以自q写外围的函数取间接存取数据库。通过q样的途径当你更换使用的数据库Ӟ可以L地更改编码以适应q样的变。PHPLIB是最常用的可以提供一般事务需要的一pd基库。但PHP提供的数据库接口支持彼此不统一Q比如对Oracle,  MySQLQ?Sybase的接口,彼此都不一栗这也是PHP的一个弱炏V?br />
2Q面向对象编E?
  PHP提供了类和对象。基于web的编E工作非帔R要面向对象编E能力。PHP支持构造器、提取类{?

JSP:

1Q将内容的生成和昄q行分离

  使用JSP技术,Web面开发h员可以用HTML或者XML标识来设计和格式化最l页面。用JSP标识或者小脚本来生成页面上的动态内宏V生成内容的逻辑被封装在标识和JavaBeanslg中,q且捆绑在小脚本中,所有的脚本在服务器端运行。如果核心逻辑被封装在标识和Beans中,那么其他人,如Web理人员和页面设计者,能够~辑和用JSP面Q而不影响内容的生成?

  在服务器端,JSP引擎解释JSP标识和小脚本Q生成所h的内容(例如Q通过讉KJavaBeanslgQ用JDBCTM技术访问数据库Q或者包含文ӞQƈ且将l果以HTMLQ或者XMLQ页面的形式发送回览器。这有助于作者保护自q代码Q而又保证MZHTML的Web览器的完全可用性?

2Q强调可重用的组?

  l大多数JSP面依赖于可重用的,跨^台的lgQJavaBeans或者Enterprise JavaBeansTMlgQ来执行应用E序所要求的更为复杂的处理。开发h员能够共享和交换执行普通操作的lgQ或者得这些组件ؓ更多的用者或者客户团体所使用。基于组件的Ҏ加速了M开发过E,q且使得各种l织在他们现有的技能和优化l果的开发努力中得到q?

3Q采用标识简化页面开?

  Web面开发h员不会都是熟悉脚本语a的编Eh员。JavaServer Page技术封装了许多功能Q这些功能是在易用的、与JSP相关的XML标识中进行动态内容生成所需要的。标准的JSP标识能够讉K和实例化JavaBeanslgQ设|或者检索组件属性,下蝲AppletQ以及执行用其他Ҏ更难于编码和耗时的功能?

  通过开发定制化标识库,JSP技术是可以扩展的。今后,W三方开发h员和其他人员可以为常用功能创q标识库。这使得Web面开发h员能够用熟悉的工具和如同标识一L执行特定功能的构件来工作?

  JSP技术很Ҏ整合到多U应用体pȝ构中Q以利用现存的工具和技巧,q且扩展到能够支持企业的分布式应用。作为采用Java技术家族的一部分Q以及Java 2Q企业版体系l构Q的一个组成部分,JSP技术能够支持高度复杂的ZWeb的应用?

  ׃JSP面的内|脚本语a是基于Java~程语言的,而且所有的JSP面都被~译成ؓJava ServletQJSP面具有Java技术的所有好处,包括健壮的存储管理和安全性?

  作ؓJavaq_的一部分QJSP拥有Java~程语言“一ơ编写,各处q行”的特炏V随着来多的供应商JSP支持dC们的产品中,您可以用自己所选择的服务器和工P更改工具或服务器q不影响当前的应用?

应用范围

  ASP是Microsoft开发的动态网语aQ也l承了微软品的一贯传l——只能运行于微Y的服务器产品,IIS (Internet Information Server) (windows NT)和PWS(Personal Web Server)(windows 98)上。Unix下也有ChiliSoft的插件来支持ASPQ但是ASP本n的功能有限,必须通过ASPQCOM的组合来扩充QUnix下的COM实现h非常困难?

  PHP3可在Windows,Unix,Linux的Web服务器上正常q行,q支持IIS,Apache{通用Web服务?用户更换q_?无需变换PHP3代码,可即拿即?

  JSP同PHP3cMQ几乎可以运行于所有^台。如Win NT,Linux,Unix. NT下IIS通过一个插Ӟ例如JRUN或者ServletExecQ就能支持JSP。著名的Web服务器Apache已经能够支持JSP。由于Apacheq泛应用在NT、Unix和Linux上,因此JSP有更q泛的运行^台。虽然现在NT操作pȝ占了很大的市Z额,但是在服务器斚wUnix的优势仍然很大,而新崛v的Linux更是来势不小。从一个^台移植到另外一个^収ͼJSP和JavaBean甚至不用重新~译Q因为Java字节码都是标准的与^台无关的?

性能比较

  有h做过试验Q对q三U语a分别做@环性能试及存取Oracle数据库测试?

  在@环性能试中,JSP只用了o人吃惊的四秒钟就l束?0000Q?0000的@环。而ASP、PHP试的是2000Q?000循环Q少一个数量Q,却分别用?3U和84U。(参考PHPLIBQ?

  数据库测试中Q三者分别对 Oracle 8 q行 1000 ?Insert,Update,Select,和DeleteQ?Jsp 需?13 U,Php 需?69 U,ASP?需?73 U?

前景分析

  目前在国内PHP与ASP应用最为广泛。而JSP׃是一U较新的技术,国内采用的较。但在国外,JSP已经是比较流行的一U技术,其是电子商务类的网站,多采用JSP?

  采用PHP的网站如新浪|(sinaQ、中国hQChinarenQ等,但由于PHP本n存在的一些缺点,使得它不适合应用于大型电子商务站点,而更适合一些小型的商业站点?

  首先QPHP~Z规模支持。其ơ,~Z多层l构支持。对于大负荷站点Q解x法只有一个:分布计算。数据库、应用逻辑层、表C逻辑层彼此分开Q而且同层也可以根据流量分开Q组成二l阵列。而PHP则缺乏这U支持。还有上面提到过的一点,PHP提供的数据库接口支持不统一Q这׃得它不适合q用在电子商务中?

  ASP和JSP则没有以上缺PASP可以通过Microsoft Windowsd的COM/DCOM获得ActiveX规模支持Q通过DCOM和Transcation Server获得l构支持QJSP可以通过SUN Java的Java Class和EJB获得规模支持Q通过EJB/CORBA以及众多厂商的Application Server获得l构支持?

  三者中QJSP应该是未来发展的势。世界上一些大的电子商务解x案提供商都采用JSP/Servlet。比较出名的如IBM的EQbusinessQ它的核心是采用JSP/Servlet的WebSphereQ西方另外一个非常著名的电子商务软g提供商,Intershop。它原来的品Intershop1 2, 3, 4占据了主要的电子商务软g份额。它们都是通过CGI来提供支?的。但d10月后它推ZEnfinityQ一个采用JSP/Servlet的电子商务Application ServerQ而且声言不再开发传lY件?

M

  ASPQPHP,JSP三者都有相当数量的支持者,由此也可以看Z者各有所ѝ正在学习或使用动态页面的朋友可根据三者的特点选择一U适合自己的语a?

 

asp jsp cgi php之间的区别和优点

发布者:Iease 发布旉Q?006-7-22

  我个h的意见,PHP只适合做小型的|站开发,大型的站点就很困难了Q能做,但是很痛苦!Q?

扩充性:
  1、PHP用光了自q一堆函C后,要扩充似乎是很困隄。据我一位玩PHP和c比较好的朋友_“可以扩充Q要用c来写Q然后编译进PHP里面?#8221;。请问,用PHP的朋友中有多能辑ֈq个水^的?
  2、ASP。如果你认ؓasp只是那几个response/request{对象,那你错了?
  个h认ؓQASP只是一U技术,如果没有MS的com/comQ,asp׃么都没有了。说得过份一点,asp本nq一个赋D句,q一个if都没有!
  正是Z此,ASP拥有很强的扩充性。你不熟悉vbsQ你可以用jscriptQ你可以用perlscriptQ你可以通过安装xscript来用你熟悉的脚本语a。你会vb/delphi/vc/bcb..吗?那你可以写自qlgQ然后用asp来用它?
  3、java Q同asp一Pjava通过不断增多的(公司发布的或是自q译的Qclass来扩展自巌Ӏ而且jsp与asp相比有一个大的优点:jsp是基于java的,拥有强大的程序语法和天然的^台无x?

执行效率Q?
  1、PHP是基于解释型的?
  “因ؓ不用~译而且高阶Q所以这c语a的程序效率通常很差Q又因ؓ原始E序代码暴露在外Q所以拿它来写写工具E序自己用可以,但是拿来开发Y件品比较不恰当Q除非你不在乎原始码外流Q?#8221;Q此D引用蔡学墉文章“你该学什么程序语aQ?#8221;Q?
  虽然PHP可以通过使用W三方的zendQ我对PHP不是太熟悉)来I补这个缺P但是gZend是收费的Q而且使用W三方的东西已经不是PHP本n的讨Z?
  2、ASP
  asp发展较早Q因此早期的asp1.0、asp2.0、asp3.0都是Z解释的,有同PHP相同的问题。不q自MS?net以后Qasp.net在第一ơ加载时q行~译Qƈ加蝲于内存中Q因此第一ơ以后的执行效率已经是相当快速了?
  3、JSP?
  java本n是属于~译的语aQ目前的jsp服务器品大多是做JIT~译的,JSP在第一ơ加载时被编译,因而与PHP相比在执行效率上有明昄提高?



xyz 2008-09-17 11:43 发表评论
]]>
DWR与Struts整合http://www.tkk7.com/xyzroundo/articles/228547.htmlxyzxyzFri, 12 Sep 2008 03:21:00 GMThttp://www.tkk7.com/xyzroundo/articles/228547.htmlhttp://www.tkk7.com/xyzroundo/comments/228547.htmlhttp://www.tkk7.com/xyzroundo/articles/228547.html#Feedback3http://www.tkk7.com/xyzroundo/comments/commentRss/228547.htmlhttp://www.tkk7.com/xyzroundo/services/trackbacks/228547.html 1.下載DWR Version 2
https://dwr.dev.java.net/files/documents/2427/47504/dwr.jar

2.安裝DWR,把dwr.jar攑ֈWEB-INF/lib?

web.xml中加入DWRServlet & ActionServlet
其中<load-on-startup>的部分要特別注意,ActionServlet要先初始?所以數字要比較?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
  <servlet>    
<servlet-name>action</servlet-name>    
<servlet-class>org.apache.struts.action.ActionServlet
</servlet-class>    
<init-param>      
<param-name>config</param-name>      
<param-value>/WEB-INF/struts-config.xml</param-value>    
</init-param>    
<init-param>      
<param-name>debug</param-name>      
<param-value>2</param-value>    
</init-param>    
<load-on-startup>2</load-on-startup>  
</servlet>  
<servlet-mapping>    
<servlet-name>action</servlet-name>    
<url-pattern>*.do</url-pattern>  
</servlet-mapping>  
<servlet>    
<servlet-name>dwr-invoker</servlet-name>    
<servlet-class>uk.ltd.getahead.dwr.DWRServlet</servlet-class>    
<init-param>      
<param-name>debug</param-name>      
<param-value>true</param-value>    
</init-param>    
<load-on-startup>10</load-on-startup>  
</servlet>  
<servlet-mapping>   
 <servlet-name>dwr-invoker</servlet-name>    
<url-pattern>/dwr/*</url-pattern>  
</servlet-mapping>



dwr.xml中加入struts的設?其中formBean的參數的value?會對應到struts-config.xml?lt;form-beans>的設?
1
2
3
4
5
6
7
8
  <dwr>  
<allow>    
<create creator="struts" javascript="testFrm">      
<param name="formBean" value="testActionForm"/>    
</create>  
</allow>  
</dwr>  


struts-config.xml
1
2
3
4
5
6
7
8
9
10
11
  <struts-config>  
<form-beans>    
<form-bean name="testActionForm" type="test.struts.testActionForm" />  
</form-beans>  
<action-mappings>    
<action name="testActionForm" path="/testAction" scope="session" type="test.struts.testAction" validate="false">      
<forward name="display" path="/display.jsp" />    
</action>  
</action-mappings>  
<message-resources parameter="ApplicationResources" />
</struts-config>


testActionForm.java,getDate()會透過dwr,取得珑֜最新的日期

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package test.struts; 
import org.apache.struts.action.*;
import java.util.*; 
public class testActionForm extends ActionForm {     
private String strDate;     
public void setStrDate(String strDate) {        
this.strDate = strDate;    
}     
public String getStrDate() {        
return strDate;    
}    
 //dwr    public String getDate() {        
Date date = new Date();        
return date.toString();   
 } 
}


testAction.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package test.struts; 
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionForm;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.Action;
import org.apache.struts.action.*; 
public class testAction extends Action {    
	public ActionForward execute(ActionMapping mapping, ActionForm form,                                 
HttpServletRequest request,                                 
HttpServletResponse response) {         
testActionForm actionForm = (testActionForm) form;       
 System.out.println(actionForm.getStrDate());        
return mapping.findForward("display");    
}
}

date.jsp,在form的部?請用struts ?tag library,我把<html:text property="strDate" size="30" >Ҏ<input type="text" name="strDate">?無法正常的接受到?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<%@ page contentType="text/html; charset=Big5" %>
<%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %>
<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
<%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %>
<html><head>
<title>title</title>  
<script type='text/javascript' src='dwr/interface/testFrm.js'></script>  
<script type='text/javascript' src='dwr/engine.js'></script>  
<script type='text/javascript' src='dwr/util.js'></script>
</head>
<SCRIPT LANGUAGE="JavaScript" type=""
function refreshDate() {   
 testFrm.getDate(populateDate)
;} 
function populateDate(data){   
DWRUtil.setValue('strDate', data);
} 
</script> 
<body> 
<html:form action="testAction.do">
dateQ?lt;html:text property="strDate" size="30" ></html:text> 
<input type="button" onclick="refreshDate();" value="更新日期"/><br/>   
<html:submit>送出  </html:submit>
</html:form></body></html>


display.jsp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<%@ page contentType="text/html; charset=Big5" %>
<%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %>
%@page import="test.struts.*"%
<html>
<head>
<title>test</title>
</head><body bgcolor="#ffffff"><h1>您送出的日?<br>
<bean:write name="testActionForm" property="strDate"/></h1>
</body>
</html>
 


xyz 2008-09-12 11:21 发表评论
]]>
如何使用Eclipse导入q运行源?/title><link>http://www.tkk7.com/xyzroundo/articles/212637.html</link><dc:creator>xyz</dc:creator><author>xyz</author><pubDate>Fri, 04 Jul 2008 08:26:00 GMT</pubDate><guid>http://www.tkk7.com/xyzroundo/articles/212637.html</guid><wfw:comment>http://www.tkk7.com/xyzroundo/comments/212637.html</wfw:comment><comments>http://www.tkk7.com/xyzroundo/articles/212637.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.tkk7.com/xyzroundo/comments/commentRss/212637.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/xyzroundo/services/trackbacks/212637.html</trackback:ping><description><![CDATA[来源Qforest077<br /> <br /> 如何使用Eclipse导入q运行源?原创哦,如有转蝲Q请注明作者forest077Q?span style="display: none"> </span><br /> <span style="display: none">OfwFypR </span> <br />   |上关于Eclipse配置和开发入门程序的文章很多Q可是要么很_浅Q要么很高深Q却很少看到讲解如何把别人的源码导入到自qEclipse环境中编译运行的描述。做为初学者,能够学习|上一些优U源码是提高的必由之\Q可是Eclipse却不象VC和Delphi那样Ҏ上手Q对于很多初学者来_它似乎还是太难了炏V在找不到很好的关于Eclipse入门教程的情况下Qؓ了能q行|上下蝲的Java源码Q我颇费了一些时间寻扑֦何正的导入源码q运行的ҎQ不敢独,特A献出来与初学者共享?span style="display: none"> pV!kC$]`@ </span> <br />   q行环境Q?span style="display: none"> Y,EXoMs46 </span> <br />     Java EE 5.0<span style="display: none"> OLX1{a </span> <br />     Eclipse 3.1 中文?span style="display: none"> fL]MQUazf@ </span> <br />   源代码用例(都是Java ApplicationQ:<span style="display: none"> 5)`J6fs} </span> <br />     仿真WindowsC?span style="display: none"> .E$ </span> <br />     q连?span style="display: none"> @Elps8~+b </span> <br />   上述的两个源代码在赛q网上可以找到。关于JDK的配|、安装和Eclipse的安装本文不再赘qͼ读者可以很Ҏ地找到相关的资料。本文只讲用Eclipse来导入源代码的方法?span style="display: none"> WgdGwabFo </span> <br />   首先保你的工作I间已经创徏好,在我的机器上工作I间所在的目录?#8220;e:\workspace”。源代码存放路径假设?#8220;我的文档\cai\Java\一个仿windows的记事本”?#8220;我的文档\cai\Java\q连看\kyodai”?span style="display: none"> OwF]?t=F| </span> <br />   下面开始介l导入源码的Ҏ?span style="display: none"> f51^7|W4# </span> <br />   ◎选择菜单“文g/新徏/目”Q选择“Java目”Q弹?#8220;创徏Java目”对话框?span style="display: none"> lf 8ja6M </span> <br />   ◎在“创徏Java目”中输?#8220;目?#8221;Q项目名可以ZQ意名字,不必和maincȝ名字一栗这里假设ؓ“Notepad”?span style="display: none"> U 6icH I </span> <br />     ?#8220;内容”中有两个单选按钮,视你的需要来使用。其?#8220;在工作空间中创徏新项?#8221;会在你的工作I间中创Z个新目录Q目录名与项目名一_“从现有资源创建项?#8221;可以在源码所在目录中直接~译q行Q生成的class文g也会存放在源码目录中?span style="display: none">  @c2'  </span> <br />   <span style="display: none">~dL[qP </span> <br />   下面先讲“在工作空间中创徏新项?#8221;的方法?span style="display: none"> ,$_1,e  </span> <br />   ◎在“内容”中单?#8220;在工作空间中创徏新项?#8221;Q点?#8220;完成”按钮。此时在e:\workspace下生成Notepad目录?span style="display: none"> )z8.W$l </span> <br />   ◎下面需要导入源码到工作I间厅R选择菜单“文g/导入”Q选择“文gpȝ”。弹?#8220;文gpȝ”对话框?span style="display: none"> NNFl;^X </span> <br />   ◎在“从目?#8221;中选择源码存放目录“我的文档\cai\Java\一个仿windows的记事本”Q勾选上所有的.java源码Q其他的垃圾不要选上。下面又有两个选择Q对话框下方有两个选项Q若选择“创徏完整的文件夹l构”Q就会按源码所存放的\径完整地在工作空间中创徏目录Q创建完毕会׃mainҎcȝ路径不对而在包资源管理器内的图标上显C叉叉,无法~译成功Q若选择“只创建选择的文件夹”Q则会在工作I间创徏的目录下导入所有的文g而不会保留原目录Q此时可以编译成功?span style="display: none"> _GPk^)) </span> <br />   ◎若选择“创徏完整的文件夹l构”Q导入完成后Q选择菜单“目/属?Java构徏路径/源代?#8221;Q点?#8220;d文g?#8221;Q把子目录逐点开Q直到源代码所在这U目录ؓ止,N上该目录。弹出的提示对话框点ȝ定即可。注意上U目录不要勾选,否则会报错。这栯U方法导入的源码也可以编译运行了?span style="display: none"> y90cZ0Y5 </span> <br />   ◎注意若源代码中含有子目录,在mainE序中会有import ...的语句,此时要注意import后面的目录别,在选择Java构徏路径时要N上import指明的上U目录名。例如,q连看代码中有子目录topbarQ在mainE序中有import kyodai.topbar语句Q那么就要勾选到“我的文档\cai\Java\q连看\”q目录Q而非源码所在的“我的文档\cai\Java\q连看\kyodai”目录?span style="display: none"> }C. ?$i_ </span> <br />   ◎在q连看源码中Q作者已l把所有源码都打包成了一个JarQ此时只需要添加该Jar包而不需要导入其他源码就可以q行了(但不能调试,因ؓJar包中不含源码Q。方法是创徏完新目后,选择菜单“目/属?Java构徏路径”Q点?#8220;?#8221;,点击“d外部JAR”按钮Q选择源码自带的Jar包即可运行?span style="display: none"> ?f[*aQ% </span> <br />   <span style="display: none">KwZ:"=3hk </span> <br />   下面介绍“从现有资源创建项?#8221;的方法?span style="display: none"> n^c3\F~xg </span> <br />   ◎在“创徏Java目”对话框中Q点?#8220;下一?#8221;按钮Q弹?#8220;Java讄”对话框?span style="display: none"> x|Gr/ 1 </span> <br />   ◎在“Java讄”对话框中选择“?#8221;,选择“dJAR”Q若找不到随源码提供的Jar包,选择“d外部JAR”。一般如果Jar存放的目录正,?#8220;dJAR”中是可以扑ֈ该条目的。双d现的Jar包即可添加进厅R若不需要额外的库支持,则点?#8220;完成”?span style="display: none"> [Z/gQ RR| </span> <br />   <span style="display: none">w~Oy9.Br </span> <br />   q样Q用上面两种Ҏ创徏的项目就可以~译q行了。下面就介绍q行的方法?span style="display: none"> sz.Ow*zx </span> <br />   ◎选择菜单“Run/q行”Q弹?#8220;创徏、管理和q行配置”对话框?span style="display: none"> GQcz \ </span> <br />   ◎根据源码的U类在左边的列表中进行选择。我们用的两个例子都是Java应用E序Q所以双?#8220;Java应用E序”Q在对话框右边可以输入运行的配置?span style="display: none"> 3#1U2uKW& </span> <br />   ◎如果新Z目q没有运行过Q那么右边的“目”栏缺省值即为刚创徏的项目。在“名称”栏中输入q行配置的名Uͼ与项目名UC_也可以不一_Q不能与其他的运行配|重名?span style="display: none"> L&Rxv2G </span> <br />   ◎点?#8220;Mainc?#8221;栏右方的“搜烦”按钮Q一般只有一个mainc,在弹出的对话框中双击下面那个栏目的maincd可。如果需要以其他的mainҎ做ؓE序入口Q可以勾选上“Mainc?#8221;栏下方的两个复选框Q选择其他的入口?span style="display: none"> V3GyK"4\U9 </span> <br />   ◎如果需要增加特D的环境变量Q例如有的源码可能需要添加classpath环境变量Q则可以?#8220;环境”中d?span style="display: none"> '#Fu@zb </span> <br />   ◎运行配|中的内容也会同样反映在调试配置中,q行和调试用相同的配置?span style="display: none"> @ vcOG&+j </span> <br />   <span style="display: none">c_JQIv\@ </span> <br />   创徏了一堆新目后,包资源管理器中会有一堆ؕ七八p项目,有些是你需要的Q有些是早已废弃不用的,你可以删除那些不用的目Q方法是右键点击该项目,选择“删除”。这里要提醒读者一下的是,删除对话框有两个选项Q问你是否删除该目目录下的内容Q缺省是“不删除内?#8221;Q如果选择删除Q那么那个目录就整个被删除掉了,如果你这个目录下的东西还有用Q那你只好哭了?span style="display: none"> .ag-Y4y </span> <br />   删除掉没用的目后,q行/调试对话框中多余的配|也可以删除Q方法是右键点击不用的配|名Q选择删除?span style="display: none"> H0QCprVN%S </span> <br />   <span style="display: none">nkBA.AS </span> <br />   好了Q这是我初学Eclipse的一些心得,希望能对q大惌使用Eclipse又担心它烦琐的初学者有些帮助? <img src ="http://www.tkk7.com/xyzroundo/aggbug/212637.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/xyzroundo/" target="_blank">xyz</a> 2008-07-04 16:26 <a href="http://www.tkk7.com/xyzroundo/articles/212637.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>谈XMLhttp://www.tkk7.com/xyzroundo/articles/207438.htmlxyzxyzThu, 12 Jun 2008 08:58:00 GMThttp://www.tkk7.com/xyzroundo/articles/207438.htmlhttp://www.tkk7.com/xyzroundo/comments/207438.htmlhttp://www.tkk7.com/xyzroundo/articles/207438.html#Feedback0http://www.tkk7.com/xyzroundo/comments/commentRss/207438.htmlhttp://www.tkk7.com/xyzroundo/services/trackbacks/207438.html
xml在java语言中的三大作用:
1)对小扚w数据的格式化存储
2)数据的传?包括从服务器向IE览器传?br /> 3)用户构造java webE序的展现技?br /> ===========================
XML的存?br /> 1)xml 配置文g
?自定义一个实现有x据库q接的XML文g
然后写一个读取配|文件的javaE序,可以利用DOM,SAX{API实现XML的读取和解析?br />
2Qxml数据?br />     DOM 接口对XML文g的地位与JDBC相对于关pL据库的地位相当,都是数据操作的统一接口。可以通过DOM接口Q将XML文g中的数据套上特定界面模板昄在IE览器中?br />
XML的生?br /> 1)通过标记完成XML数据发布Q提取数据库数据Qƈ所提取数据按照字符串拼接Ş式发布成XMLQ?br /> 2Q通过E序语句完成XML数据发布Q思\核心首先在内存中指定数据生成document对象Q然后再比Document对象保存到硬盘上Q从而实现XML文g的创?q种创徏方式要比字符串拼接方式稳定而高效?br />
|页数据展现
1)传统数据展现技?br />     jsp asp html
2)XML服务器数据展?br />
3)XML客户端数据展?br /> XML数据文g和相应的XSL展现文g同时发送到客户览器上Q借助客户览上的XSLT引擎Q将XML文g转变为HTML文g昄

׃q种设计Ҏ实现了数据和样式的彻底分,因此E序的运行效率和l护效率有根本性提高?br /> 2008q??2?6:57:39

xyz 2008-06-12 16:58 发表评论
]]>
实践中整理出tomcat集群和负载均?/title><link>http://www.tkk7.com/xyzroundo/articles/200280.html</link><dc:creator>xyz</dc:creator><author>xyz</author><pubDate>Tue, 13 May 2008 11:25:00 GMT</pubDate><guid>http://www.tkk7.com/xyzroundo/articles/200280.html</guid><wfw:comment>http://www.tkk7.com/xyzroundo/comments/200280.html</wfw:comment><comments>http://www.tkk7.com/xyzroundo/articles/200280.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/xyzroundo/comments/commentRss/200280.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/xyzroundo/services/trackbacks/200280.html</trackback:ping><description><![CDATA[<p>来源Qhttp://macrochen.blogdriver.com/macrochen/1207263.html</p> <p>(一)环境说明<br /> (1)服务器有4収ͼ一台安装apache,三台安装tomcat<br /> (2)apache2.0.55、tomcat5.5.15、jk2.0.4、jdk1.5.6或jdk1.4.2<br /> (3)ip配置,一台安装apache的ip?92.168.0.88,三台安装tomcat的服务器ip分别?92.168.0.1/2/4<br /> (?安装q程<br /> (1)在三台要安装tomcat的服务器上先安装jdk<br /> (2)配置jdk的安装\?在环境变量path中加入jdk的bin路径,新徏环境变量JAVA_HOME指向jdk的安装\?br /> (3)在三台要安装tomcat的服务器上分别安装tomcat,调试三个tomcat到能够正常启?br /> (4)tomcat的默认WEB服务端口?080,默认的模式是单独服务,我的三个tomcat的WEB服务端口修改?080/8888/9999<br /> 修改位置为tomcat的安装目录下的conf/server.xml<br /> 修改前的配置?br />     <Connector port="8080" maxHttpHeaderSize="8192"<br />                maxThreads="150" minSpareThreads="25" maxSpareThreads="75"<br />                enableLookups="false" redirectPort="8443" acceptCount="100"<br />                connectionTimeout="20000" disableUploadTimeout="true" /><br /> 修改后的配置?br />     <Connector port="7080" maxHttpHeaderSize="8192"<br />                maxThreads="150" minSpareThreads="25" maxSpareThreads="75"<br />                enableLookups="false" redirectPort="8443" acceptCount="100"<br />                connectionTimeout="20000" disableUploadTimeout="true" /><br /> 依次修改每个tomcat的监听端?7080/8888/9999)<br /> <br /> (5)分别试每个tomcat的启动是否正?br /> http://192.168.0.1:7080<br /> http://192.168.0.2:8888<br /> http://192.168.0.4:9999<br /> (?负蝲均衡配置q程<br /> (1)在那台要安装apache的服务器上安装apache2.0.55,我的安装路径为默认C:\Program Files\Apache Group\Apache2<br /> (2)安装后测试apache能否正常启动Q调试到能够正常启动http://192.168.0.88<br /> (3)下蝲jk2.0.4后解压羃文g<br /> (4)解压羃后的目录中的modules目录中的mod_jk2.so文g复制到apache的安装目录下的modules目录?我的为C:\Program Files\Apache Group\Apache2\modules<br /> (5)修改apache的安装目录中的conf目录的配|文件httpd.confQ在文g中加LoadModule模块配置信息的最后加上一句LoadModule jk2_module modules/mod_jk2.so<br /> (6)分别修改三个tomcat的配|文件conf/server.xmlQ修改内容如?br /> 修改?br />     <!-- An Engine represents the entry point (within Catalina) that processes<br />          every request.  The Engine implementation for Tomcat stand alone<br />          analyzes the HTTP headers included with the request, and passes them<br />          on to the appropriate Host (virtual host). --><br /> <br />     <!-- You should set jvmRoute to support load-balancing via AJP ie :<br />     <Engine name="Standalone" defaultHost="localhost" jvmRoute="jvm1">         <br />     --> <br />          <br />     <!-- Define the top level container in our container hierarchy --><br />     <Engine name="Catalina" defaultHost="localhost"><br /> 修改?br />     <!-- An Engine represents the entry point (within Catalina) that processes<br />          every request.  The Engine implementation for Tomcat stand alone<br />          analyzes the HTTP headers included with the request, and passes them<br />          on to the appropriate Host (virtual host). --><br /> <br />     <!-- You should set jvmRoute to support load-balancing via AJP ie :--><br />     <Engine name="Standalone" defaultHost="localhost" jvmRoute="tomcat1">         <br />      <br />          <br />     <!-- Define the top level container in our container hierarchy <br />     <Engine name="Catalina" defaultHost="localhost"><br />     --><br /> 其中的jvmRoute="jvm1"分别修改为jvmRoute="tomcat1"和jvmRoute="tomcat2"和jvmRoute="tomcat3"<br /> <br /> (7)然后重启三个tomcatQ调试能够正常启动?br /> (8)在apache的安装目录中的conf目录下创建文件workers2.propertieQ写入文件内容如?br /> <br /> # fine the communication channel <br /> [channel.socket:192.168.0.1:8009] <br /> info=Ajp13 forwarding over socket<br /> #配置W一个服务器 <br /> tomcatId=tomcat1 #要和tomcat的配|文件server.xml中的jvmRoute="tomcat1"名称一?br /> debug=0 <br /> lb_factor=1 #负蝲q因子Q数字越大请求被分配的几率越?br /> <br /> # Define the communication channel <br /> [channel.socket:192.168.0.2:8009] <br /> info=Ajp13 forwarding over socket<br /> tomcatId=tomcat2 <br /> debug=0 <br /> lb_factor=1 <br /> <br /> # Define the communication channel <br /> [channel.socket:192.168.0.4:8009] <br /> info=Ajp13 forwarding over socket<br /> tomcatId=tomcat3 <br /> debug=0 <br /> lb_factor=1 <br /> <br /> [status:] <br /> info=Status worker, displays runtime information.  <br /> <br /> [uri:/jkstatus.jsp] <br /> info=Display status information and checks the config file for changes. <br /> group=status: <br /> <br /> [uri:/*] <br /> info=Map the whole webapp <br /> debug=0<br /> (9)在三个tomcat的安装目录中的webapps建立相同的应?我和应用目录名ؓTomcatDemo,在三个应用目录中建立相同 WEB-INF目录和页面index.jsp,index.jsp的页面内容如?br /> <%@ page contentType="text/html; charset=GBK" %><br /> <%@ page import="java.util.*" %><br /> <html><head><title>Cluster App Test</title></head><br /> <body><br /> Server Info:<br /> <%<br /> out.println(request.getLocalAddr() + " : " + request.getLocalPort()+"<br>");%><br /> <%<br />   out.println("<br> ID " + session.getId()+"<br>");<br /> <br />   // 如果有新?Session 属性设|?br />   String dataName = request.getParameter("dataName");<br />   if (dataName != null && dataName.length() > 0) {<br />      String dataValue = request.getParameter("dataValue");<br />      session.setAttribute(dataName, dataValue);<br />   }<br /> <br />   out.print("<b>Session 列表</b>");<br /> <br />   Enumeration e = session.getAttributeNames();<br />   while (e.hasMoreElements()) {<br />      String name = (String)e.nextElement();<br />      String value = session.getAttribute(name).toString();<br />      out.println( name + " = " + value+"<br>");<br />          System.out.println( name + " = " + value);<br />    }<br /> %><br />   <form action="index.jsp" method="POST"><br />     名称:<input type=text size=20 name="dataName"><br />      <br><br />     ?<input type=text size=20 name="dataValue"><br />      <br><br />     <input type=submit><br />    </form><br /> </body><br /> </html><br /> (10)重启apache服务器和三个tomcat服务?到此负蝲 均衡已配|完成。测试负载均衡先试apache,讉Khttp://192.168.0.88/jkstatus.jsp<br /> 能否正常讉KQƈ查询其中的内容,有三个tomcat的相关配|信息和负蝲说明,讉Khttp://192.168.0.88/TomcatDemo/index.jsp看能够运?<br /> 能运行,则已建立负蝲均衡?br /> (?tomcat集群配置<br /> (1)负蝲均衡配置的条件下配置tomcat集群<br /> (2)分别修改三个tomcat的配|文件conf/server.xml,修改内容如下<br /> 修改?br />         <!-- <br />         <Cluster className="org.apache.catalina.cluster.tcp.SimpleTcpCluster"<br />                  managerClassName="org.apache.catalina.cluster.session.DeltaManager"<br />                  expireSessionsOnShutdown="false"<br />                  useDirtyFlag="true"<br />                  notifyListenersOnReplication="true"><br /> <br />             <Membership <br />                 className="org.apache.catalina.cluster.mcast.McastService"<br />                 mcastAddr="228.0.0.4"<br />                 mcastPort="45564"<br />                 mcastFrequency="500"<br />                 mcastDropTime="3000"/><br /> <br />             <Receiver <br />                 className="org.apache.catalina.cluster.tcp.ReplicationListener"<br />                 tcpListenAddress="auto"<br />                 tcpListenPort="4001"<br />                 tcpSelectorTimeout="100"<br />                 tcpThreadCount="6"/><br /> <br />             <Sender<br />                 className="org.apache.catalina.cluster.tcp.ReplicationTransmitter"<br />                 replicationMode="pooled"<br />                 ackTimeout="5000"/><br /> <br />             <Valve className="org.apache.catalina.cluster.tcp.ReplicationValve"<br />                    filter=".*\.gif;.*\.js;.*\.jpg;.*\.png;.*\.htm;.*\.html;.*\.css;.*\.txt;"/><br />                    <br />             <Deployer className="org.apache.catalina.cluster.deploy.FarmWarDeployer"<br />                       tempDir="/tmp/war-temp/"<br />                       deployDir="/tmp/war-deploy/"<br />                       watchDir="/tmp/war-listen/"<br />                       watchEnabled="false"/><br />                       <br />             <ClusterListener className="org.apache.catalina.cluster.session.ClusterSessionListener"/><br />         </Cluster><br />         -->   <br /> 修改?br />         <!-- modify by whh --><br />         <Cluster className="org.apache.catalina.cluster.tcp.SimpleTcpCluster"<br />                  managerClassName="org.apache.catalina.cluster.session.DeltaManager"<br />                  expireSessionsOnShutdown="false"<br />                  useDirtyFlag="true"<br />                  notifyListenersOnReplication="true"><br /> <br />             <Membership <br />                 className="org.apache.catalina.cluster.mcast.McastService"<br />                 mcastAddr="228.0.0.4"<br />                 mcastPort="45564"<br />                 mcastFrequency="500"<br />                 mcastDropTime="3000"/><br /> <br />             <Receiver <br />                 className="org.apache.catalina.cluster.tcp.ReplicationListener"<br />                 tcpListenAddress="auto"<br />                 tcpListenPort="4001"<br />                 tcpSelectorTimeout="100"<br />                 tcpThreadCount="6"/><br /> <br />             <Sender<br />                 className="org.apache.catalina.cluster.tcp.ReplicationTransmitter"<br />                 replicationMode="pooled"<br />                 ackTimeout="5000"/><br /> <br />             <Valve className="org.apache.catalina.cluster.tcp.ReplicationValve"<br />                    filter=".*\.gif;.*\.js;.*\.jpg;.*\.png;.*\.htm;.*\.html;.*\.css;.*\.txt;"/><br />                    <br />             <Deployer className="org.apache.catalina.cluster.deploy.FarmWarDeployer"<br />                       tempDir="/tmp/war-temp/"<br />                       deployDir="/tmp/war-deploy/"<br />                       watchDir="/tmp/war-listen/"<br />                       watchEnabled="false"/><br />                       <br />             <ClusterListener className="org.apache.catalina.cluster.session.ClusterSessionListener"/><br />         </Cluster><br />        <!-- modify by whh -->       <br /> 集配|选项的注释放开卛_Q如上?br /> (3)重启三个tomcat。到此tomcat的集已配置完成?/p> <p>(?应用配置<br /> 对于要进行负载和集群的的tomcat目录下的webapps中的应用中的WEB-INF中的web.xml文g要添加如下一句配|?br /> <distributable/><br /> 配置?br /> <?xml version="1.0" encoding="UTF-8"?><br /> <web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" version="2.4"><br />   <display-name>TomcatDemo</display-name><br /> </web-app><br /> 配置?br /> <?xml version="1.0" encoding="UTF-8"?><br /> <web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" version="2.4"><br />   <display-name>TomcatDemo</display-name><br />    <distributable/><br /> </web-app></p> <img src ="http://www.tkk7.com/xyzroundo/aggbug/200280.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/xyzroundo/" target="_blank">xyz</a> 2008-05-13 19:25 <a href="http://www.tkk7.com/xyzroundo/articles/200280.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Tomcat集群与负载均?/title><link>http://www.tkk7.com/xyzroundo/articles/200279.html</link><dc:creator>xyz</dc:creator><author>xyz</author><pubDate>Tue, 13 May 2008 11:23:00 GMT</pubDate><guid>http://www.tkk7.com/xyzroundo/articles/200279.html</guid><wfw:comment>http://www.tkk7.com/xyzroundo/comments/200279.html</wfw:comment><comments>http://www.tkk7.com/xyzroundo/articles/200279.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/xyzroundo/comments/commentRss/200279.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/xyzroundo/services/trackbacks/200279.html</trackback:ping><description><![CDATA[<p>来源:http://blog.csdn.net/ladofwind/archive/2006/08/29/1138484.aspx<br /> <br />   在单一的服务器上执行WEB应用E序有一些重大的问题Q当|站成功建成q开始接受大量请求时Q单一服务器终I无法满需要处理的负荷量,所以就有点昑־有点力不从心了。另外一个常见的问题是会产生单点故障Q如果该服务器坏掉,那么|站qL法运作了。不论是因ؓ要有较佳的扩充性还是容错能力,我们都会惛_一C上的服务器计机上执行WEB应用E序。所以,q时候我们就需要用到集这一门技术了?br /> <br />          在进入集系l架构探讨之前,先定义一些专门术语:<br /> 1. 集群(Cluster)Q是一l独立的计算机系l构成一个松耦合的多处理器系l,它们之间通过|络实现q程间的通信。应用程序可以通过|络׃n内存q行消息传送,实现分布式计机?nbsp;<br /> 2. 负蝲均衡(Load Balance)Q先得从集群讲vQ集就是一l连在一L计算机,从外部看它是一个系l,各节点可以是不同的操作系l或不同g构成的计机。如一个提供Web服务的集,对外界来看是一个大Web服务器。不q集的节点也可以单独提供服务?br /> 3. 特点Q在现有|络l构之上Q负载均衡提供了一U廉h效的Ҏ扩展服务器带宽和增加吞吐量,加强|络数据处理能力Q提高网l的灉|性和可用性。集系l?Cluster)主要解决下面几个问题Q?nbsp;<br /> 高可靠性(HAQ:利用集群理软gQ当L务器故障Ӟ备䆾服务器能够自动接主服务器的工作Qƈ及时切换q去Q以实现对用L不间断服务?br /> 高性能计算QHPQ:卛_分利用集中的每一台计机的资源,实现复杂q算的ƈ行处理,通常用于U学计算领域Q比如基因分析,化学分析{?nbsp;<br /> 负蝲qQ即把负载压力根据某U算法合理分配到集群中的每一台计机上,以减M服务器的压力Q降低对L务器的硬件和软g要求?br /> <br /> 目前比较常用的负载均衡技术主要有Q?nbsp;<br />   1. ZDNS的负载均?nbsp;<br />   通过DNS服务中的随机名字解析来实现负载均衡,在DNS服务器中Q可以ؓ多个不同的地址配置同一个名字,而最l查询这个名字的客户机将在解析这个名字时得到其中一个地址。因此,对于同一个名字,不同的客h会得C同的地址Q他们也p问不同地址上的Web服务器,从而达到负载均衡的目的?nbsp;<br /> <br />   2. 反向代理负蝲均衡 Q如Apache+JK2+Tomcatq种l合Q?br />   使用代理服务器可以将h转发l内部的Web服务器,让代理服务器请求均匀地{发给多台内部Web服务器之一上,从而达到负载均衡的目的。这U代理方式与普通的代理方式有所不同Q标准代理方式是客户使用代理讉K多个外部Web服务器,而这U代理方式是多个客户使用它访问内部Web服务器,因此也被UCؓ反向代理模式?br /> <br />   3. ZNATQNetwork Address TranslationQ的负蝲均衡技?nbsp;Q如Linux Virtual ServerQ简ULVSQ?br />   |络地址转换为在内部地址和外部地址之间q行转换Q以便具备内部地址的计机能访问外部网l,而当外部|络中的计算问地址转换|关拥有的某一外部地址Ӟ地址转换|关能将其{发到一个映的内部地址上。因此如果地址转换|关能将每个q接均匀转换Z同的内部服务器地址Q此后外部网l中的计机各自与自己转换得到的地址上服务器q行通信Q从而达到负载分担的目的?br /> <br /> 介绍完上面的集群技术之后,下面基于Tomcat的集架构方案进行说明:<br /> <br /> 上面是采用了Apache httpd作ؓweb服务器的Q即作ؓTomcat的前端处理器Q根据具体情况而定Q有些情况下是不需要Apache httpd作ؓ web 服务器的Q如pȝ展现没有静态页面那׃需要Apache httpdQ那时可以直接用Tomcat作ؓweb 服务器来使用。用Apache httpd主要是它在处理静态页面方面的能力比Tomcat强多了?br /> 1?nbsp;用户的网|览器做完本地 DNS和企业授权的DNS之的h/响应后,q时候企业授权的DNSQ即21cn BOSS DNSQ会l用h地的DNS服务器提供一个NATh分配器(即网养IIP?br /> <br /> <br /> 2?nbsp;NAT分配器,它会Ҏ特定的分配算法,来决定要连接交l哪一台内?nbsp;Apache httpd来处理请求。大多数的NATh分配器提供了定w能力Q根据侦各UWEB服务器的失效状况Q停止将h分配l已l宕掉的服务器。ƈ且有些分配器q可以监到WEB服务器机器的负蝲情况Qƈ请求分配给负蝲最ȝ服务器等{。Linux Virtual Server是一个基于Linux操作pȝ上执行的VS-NAT开源Y件套Ӟ而且它有丰富的功能和良好的说明文件。商业硬件解x?nbsp;Foundry Networks的ServerIron是目前业界公认最佳的h分配器之一?br /> <br /> <br /> 3?nbsp;Apache httpd + Mod_JK2在这里是作ؓ负蝲均衡器,那ؓ什么要做集呢Q如果集系l要具备定w能力Q以便在M单一的硬件或软glg失效时还?00%可用Q那么集系l必L有单Ҏ障之忧。所以,不能只架设一台有mod_jk2的Apache httpdQ因为如?nbsp;httpd或mod_jk2失效了,不会再有请求被会送交CQ何一个Tomcat 实例。这U情况下QApache httpd是瓶劲Q特别在讉K量大的网站?br /> <br /> <br /> 4?nbsp;Mod_JK2负蝲均衡与故障复原,军_把Apache httpd当成web服务器,而且使用mod_jk2请求传送给TomcatQ则可以使用mod_jk2的负载均衡与定w功能。在集群pȝ中,带有mod_jk2的Apache httpd可以做的事情包括Q?br /> A?nbsp;请求分配至一或多个Tomcat实例?br /> 你可以在mod_jk2的workers.properties文g中,讑֮许多Tomcat实例Qƈ赋于每个实例一个lb_factor|以作求分配的加权因子?br /> <br /> <br /> B?nbsp;侦测Tomcat实例是否p|<br /> 当Tomcat实例的连接器服务不再响应Ӟmod_jk2会及时侦到Qƈ停止请求送给它。其他的Tomcat实例则会接受失效实例的负载?br /> <br /> <br /> C?nbsp;侦测Tomcat实例在失效后的何时恢?br /> 因连接器服务失效Q而停止将h分配lTomcat实例之后Qmod_jk2会周期性地查是否已恢复使用性,q自动将其加入现行的Tomcat实例池中?br /> <br /> <br /> 5?nbsp;Tomcat中的集群原理是通过l播的方式进行节点的查找q用TCPq接q行会话的复制。这里提CZ下就是,Ҏ个请求的处理QTomcat都会q行会话复制Q复制后的会话将会慢慢变得庞大?br /> <br /> <br /> 6?nbsp;Mod_jk2同时支持会话亲和和会话复制。在tomcat 5中如何实C话亲和和会话复制Q把server.xml中的<cluster/>标签L实C话亲和,?lt;cluster/>标签加上实C话复制?br /> <br /> <br /> 7?nbsp;会话亲和Q就是表C来自同会话的所有请求都q同的Tomcat 实例来处理,q种情况下,如果Tomcat实例或所执行的服务器机器失效Q也会失Servlet的会话数据。即使在集群pȝ中执行更多的Tomcat实例Q也永远不会复制会话数据。这h提高集群性能的一U方案,但不具备有容错能力了?br /> <br /> <br /> 8?nbsp;使用会话复制Q则当一个Tomcat实例宕掉Ӟ׃臛_q有另一个Tomcat实例保有一份会话状态数据,因而数据不会失。但性能会有所降低?nbsp;</p> <img src ="http://www.tkk7.com/xyzroundo/aggbug/200279.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/xyzroundo/" target="_blank">xyz</a> 2008-05-13 19:23 <a href="http://www.tkk7.com/xyzroundo/articles/200279.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss> <footer> <div class="friendship-link"> <p>лǵվܻԴȤ</p> <a href="http://www.tkk7.com/" title="亚洲av成人片在线观看">亚洲av成人片在线观看</a> <div class="friend-links"> </div> </div> </footer> վ֩ģ壺 <a href="http://www026qqcom.com" target="_blank">ҹƵѹۿ</a>| <a href="http://www09191z.com" target="_blank">ƷһëƬ</a>| <a href="http://mtsp5.com" target="_blank">þù</a>| <a href="http://440878.com" target="_blank">һþۺ³³</a>| <a href="http://gysysz.com" target="_blank"></a>| <a href="http://sdsupuchem.com" target="_blank">߹ۿѸƵ</a>| <a href="http://hnlchb.com" target="_blank">ձһ߶</a>| <a href="http://wwwxue1888.com" target="_blank">޺ݺۺϾþ</a>| <a href="http://s4lm0x.com" target="_blank">鶹ƷѹƬ</a>| <a href="http://an930.com" target="_blank">ѴƬ߹ۿ</a>| <a href="http://6atb.com" target="_blank">ŵ</a>| <a href="http://ti166.com" target="_blank">Ů18ëƬëƬ</a>| <a href="http://jdv6.com" target="_blank">߹ۿƷ</a>| <a href="http://lyaa60.com" target="_blank">aëƬѹۿ</a>| <a href="http://www-01313.com" target="_blank">ŮͬavƬ߹ۿ</a>| <a href="http://2002tw.com" target="_blank">þѿٸ߳VƬػ</a>| <a href="http://szyujiaxing.com" target="_blank">רVAV</a>| <a href="http://chn139.com" target="_blank">ŮƵaƵȫվһ</a>| <a href="http://lyaa60.com" target="_blank">ʮ˽Ƶ߹ۿڵ </a>| <a href="http://863409.com" target="_blank">avӰѿ</a>| <a href="http://199291.com" target="_blank">ŮƵ</a>| <a href="http://xtolm.com" target="_blank">Ʒһ߹ۿ</a>| <a href="http://686kp.com" target="_blank">һëƬڲƵ</a>| <a href="http://ssni703.com" target="_blank">þùƷһ</a>| <a href="http://sztsa.com" target="_blank">AVרAëƬ</a>| <a href="http://lookvod.com" target="_blank">лиëƬѿ</a>| <a href="http://4p5e.com" target="_blank">ǿ˫ͽˬˬƵ</a>| <a href="http://tzntrip.com" target="_blank">޾Ʒ޲߲ </a>| <a href="http://zzyqr.com" target="_blank">վ18ѹۿ</a>| <a href="http://semaopu.com" target="_blank">޸պƷһ</a>| <a href="http://xx2015.com" target="_blank">Ʒѹۿþ</a>| <a href="http://117949b.com" target="_blank">Ѹ߹ۿ</a>| <a href="http://222941.com" target="_blank">þþþAV</a>| <a href="http://tccqdy.com" target="_blank">AëƬƵ</a>| <a href="http://yuntuzy.com" target="_blank">ȫ߲ëƬ</a>| <a href="http://fsweicheng.com" target="_blank">լ</a>| <a href="http://anyliz.com" target="_blank">Ҹ߳Ƶ</a>| <a href="http://bxd888.com" target="_blank">˾Ʒձ</a>| <a href="http://2266511.com" target="_blank">޾Ʒ</a>| <a href="http://yy1514.com" target="_blank">96ѾƷƵ߹ۿ</a>| <a href="http://nsmtv.com" target="_blank">avһĦ</a>| <script> (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })(); </script> </body>