正则表达式.

正则表达式.前言正则表达式是烦琐的 但是强大的 学会之后的应用会让你除了提高效率外 会给你带来绝对的成就感

大家好,欢迎来到IT知识分享网。

前言

正则表达式是烦琐的,但是强大的,学会之后的应用会让你除了提高效率外,会给你带来绝对的成就感。只要认真去阅读这些资料,加上应用的时候进行一定的参考,掌握正则表达式不是问题。

索引

  正则表达式的使用,可以通过简单的办法来实现强大的功能。为了简单有效而又不失强大,造成了正则表达式代码的难度较大,学习起来也不是很容易,所以需要付出一些努力才行,入门之后参照一定的参考,使用起来还是比较简单有效的。

例子: ^.+@.+//..+$

  这样的代码曾经多次把我自己给吓退过。可能很多人也是被这样的代码给吓跑的吧。继续阅读本文将让你也可以自由应用这样的代码。

  注意:这里的第7部分跟前面的内容看起来似乎有些重复,目的是把前面表格里的部分重新描述了一次,目的是让这些内容更容易理解。

  随后,发现可以将这一工作应用于使用 Ken Thompson 的计算搜索算法的一些早期研究,Ken Thompson 是 Unix 的主要发明人。正则表达式的第一个实用应用程序就是 Unix 中的 qed 编辑器。

  如他们所说,剩下的就是众所周知的历史了。从那时起直至现在正则表达式都是基于文本的编辑器和搜索工具中的一个重要部分。

 

 

 

  一切从最基本的开始。模式,是正规表达式最基本的元素,它们是一组描述字符串特征的字符。模式可以很简单,由普通的字符串组成,也可以非常复杂,往往用特殊的字符表示一个范围内的字符、重复出现,或表示上下文。例如:

^once

  这个模式包含一个特殊的字符^,表示该模式只匹配那些以once开头的字符串。例如该模式与字符串”once upon a time”匹配,与”There once was a man from NewYork”不匹配。正如如^符号表示开头一样,$符号用来匹配那些以给定模式结尾的字符串。

bucket$

  这个模式与”Who kept all of this cash in a bucket”匹配,与”buckets”不匹配。字符^和$同时使用时,表示精确匹配(字符串与模式一样)。例如:

^bucket$

  只匹配字符串”bucket”。如果一个模式不包括^和$,那么它与任何包含该模式的字符串匹配。例如:模式

once

与字符串

是匹配的。

  在该模式中的字母(o-n-c-e)是字面的字符,也就是说,他们表示该字母本身,数字也是一样的。其他一些稍微复杂的字符,如标点符号和白字符(空格、制表符等),要用到转义序列。所有的转义序列都用反斜杠(/)打头。制表符的转义序列是:/t。所以如果我们要检测一个字符串是否以制表符开头,可以用这个模式:

^/t

类似的,用/n表示“新行”,/r表示回车。其他的特殊符号,可以用在前面加上反斜杠,如反斜杠本身用//表示,句号.用/.表示,以此类推。

7.2 字符簇

在INTERNET的程序中,正规表达式通常用来验证用户的输入。当用户提交一个form以后,要判断输入的电话号码、地址、EMAIL地址、信用卡号码等是否有效,用普通的基于字面的字符是不够的。

所以要用一种更自由的描述我们要的模式的办法,它就是字符簇。要建立一个表示所有元音字符的字符簇,就把所有的元音字符放在一个方括号里:

[AaEeIiOoUu]

这个模式与任何元音字符匹配,但只能表示一个字符。用连字号可以表示一个字符的范围,如:

同样的,这些也只表示一个字符,这是一个非常重要的。如果要匹配一个由一个小写字母和一位数字组成的字符串,比如”z2″、”t6″或”g7″,但不是”ab2″、”r2d3″ 或”b52″的话,用这个模式:

^[a-z][0-9]$

尽管[a-z]代表26个字母的范围,但在这里它只能与第一个字符是小写字母的字符串匹配。

前面曾经提到^表示字符串的开头,但它还有另外一个含义。当在一组方括号里使用^是,它表示“非”或“排除”的意思,常常用来剔除某个字符。还用前面的例子,我们要求第一个字符不能是数字:

^[^0-9][0-9]$

这个模式与”&5″、”g7″及”-2″是匹配的,但与”12″、”66″是不匹配的。下面是几个排除特定字符的例子:

特殊字符”.” (点,句号)在正规表达式中用来表示除了“新行”之外的所有字符。所以模式”^.5$”与任何两个字符的、以数字5结尾和以其他非“新行”字符开头的字符串匹配。模式”.”可以匹配任何字符串,除了空串和只包括一个“新行”的字符串。

PHP的正规表达式有一些内置的通用字符簇,列表如下:

7.3 确定重复出现

到现在为止,你已经知道如何去匹配一个字母或数字,但更多的情况下,可能要匹配一个单词或一组数字。一个单词有若干个字母组成,一组数字有若干个单数组成。跟在字符或字符簇后面的花括号({})用来确定前面的内容的重复出现的次数。

这些例子描述了花括号的三种不同的用法。一个数字,{x}的意思是“前面的字符或字符簇只出现x次”;一个数字加逗号,{x,}的意思是“前面的内容出现x或更多的次数”;两个用逗号分隔的数字,{x,y}表示“前面的内容至少出现x次,但不超过y次”。我们可以把模式扩展到更多的单词或数字:

最后一个例子不太好理解,是吗?这么看吧:与所有以一个可选的负号(/-{0,1})开头(^)、跟着0个或更多的数字([0-9]{0,})、和一个可选的小数点(/.{0,1})再跟上0个或多个数字([0-9]{0,}),并且没有其他任何东西($)。下面你将知道能够使用的更为简单的方法。

特殊字符”?”与{0,1}是相等的,它们都代表着:“0个或1个前面的内容”或“前面的内容是可选的”。所以刚才的例子可以简化为:

^/-?[0-9]{0,}/.?[0-9]{0,}$

特殊字符”*”与{0,}是相等的,它们都代表着“0个或多个前面的内容”。最后,字符”+”与 {1,}是相等的,表示“1个或多个前面的内容”,所以上面的4个例子可以写成:

ActiveX是从Microsoft的复合文档技术——OLE成长起来的。OLE最初发布的版本,只是瞄准复合文档,但在后续版本OLE2中,导入了 COM。COM是应OLE设计者的需求而诞生的。其基本的出发点是想让某个软件通过一个通用的机构为另一个软件提供服务。因而,COM的第一个使用者是 OLE2。实际上,COM与复合文档间,没有多大关系。后来,COM就作为与复合文档完全无关的技术,开始被广泛使用。这样一来,Microsoft就开始”染指”通用平台技术。但COM不是产品,它需要一个商标名称。不巧,市场专家们选用了”OLE”作为商标名称。于是,使用COM的技术都开始贴上了 OLE的标签。当然,这些技术中的绝大部分与复合文档没有关系。Microsoft要想向人们解释:”OLE不单单是指复合文档!”,这要花费相当的精力和时间。

于是,在1996年春,Microsoft改变了主意,选择了ActiveX作为新商标名。ActiveX是指宽松定义的、基于COM的技术集合,而OLE仍然仅指复合文档。当然,最重要的核心还是COM。

让对象模型完全独立于编程语言,这是一个非常新奇的思想。从C++和Java的对象上,我们就能有所了解。但所谓COM对象究竟是什么?为了便于理解,可以把COM看作是某种(软件)打包技术,即把它看作是使软件的不同部分,按照一定的面向对象的形式,组合成可以交互的过程和一组支持库。COM对象可以用 C++、Java和VB等任意一种语言编写,并可以DLL或作为不同过程工作的执行文件的形式来实现。使用COM对象的客户端,无需关心对象是用什么语言写的,也无需关心它是以DLL、还是以另外的过程来执行的。从客户端来看,无任何区别。

这样一个通用的处理技巧非常有用。例如,由用户协调运行的两个应用,可以将它们的共同作业部分,作为COM对象间的交互来实现(当然,现在的OLE复合文档也能做到)。为在浏览器中执行而从Web服务器下载的代码,浏览器可把它看作是COM对象。即是说,COM技术也是一种打包可下载代码的标准方法 (ActiveX控件执行这种功能)。

甚至连应用与本机OS进行交互的方法,也可以用COM来指定(Windows和Windows NT用的新API,多数是作为COM对象来定义的)。COM虽然起源于复合文档,但却可有效地适用于许多软件问题。

Active Server实际上是中间层。使用组件或Active服务器页面,来提供用于业务逻辑和主要应用处理的场所。ActiveServer的技术,其核心是NT Server、Microsoft事务处理服务器、数据管理服务、目录服务、Web服务以及网络服务。

事务处理服务器是把线程产生和数据库多重化等传统的TP监控功能与Microsoft的基于组件的编程模型结合起来。数据管理服务等Active平台的其他组件是用OLE DB和ODBC,访问DB2、Oracle、SQL Server等的数据源。目录服务是在DCOM(Distributed COM,分布式COM)的周围,提供目录服务层,这样使远程对象在网络上能相互搜索。Web服务以Internet信息服务器为中心进行构筑,它为服务器上的Web应用开发,提供脚本生成(Scripting)机构。网络服务以DCOM为中心进行构筑,通过以同步MS-RPC为中介的网络,使之能够连接控件。

Active Client是一种交叉平台。Microsoft的技术纵然是独家所有,但也希望将这种技术向多个OS开放。具体实施计划是使用脚本引擎(Scripting Engine)。这种脚本引擎是由标准的HTML和带有Microsoft特色的Java虚拟机(JVM)、Microsoft的VBScript与JScript所构成的。Active Client组装进了Microsoft的IE 3.0和4.0,通过ActiveX,可以变成用户的C/S应用的一部分。

从清一色采用Windows的企业用户来看,Active平台可以提供坚固的、具有可缩放性的服务器应用开发平台。ActiveServer在TP监视器这类高端产品的场合,也利用常见的一些工具和技术。因此,小型工作组和Intranet应用不会超越Active Server的能力。Active平台的目标机虽是异种机环境,但由于过分依赖IE,所以不能驱动客户端。尽管在一些非Windows平台上也推出了Explorer,但最好的支持、最新版本的Explorer还是在Windows上。

COM的最初版本假定COM对象及其客户端是在同一个机器上运行(可以在同一个进程内,也可以在不同的进程内),DCOM是ActiveX家族中的重要成员。后来,它在Windows 95中也能使用。DCOM对于客户端制作COM对象、进行交互的方法没有做任何改变。

客户端使用完全相同的代码,可以访问本地以及远程对象。但许多场合下,客户想使用少数的DCOM附件。DCOM备有分布式安全保密机制,提供认证和数据加密。在1998年要发布的Windows NT 5.0中,要将Kerberos等安全保密协议,追加到DCOM中。DCOM已能够利用域名服务等简洁的目录服务,以用于搜寻在其他机器上的COM对象。NT 5.0要追加对Active Directory的支持。Active Directory是基于域名服务和轻型目录访问协议的。

DCOM的劲敌,此前一直是OMG(Object Management Group)的CORBA(Common Object Request Broker Architecture)。它被组装进了Iona的Orbix和Visigenic的VisiBroker等产品中。不久前,另一种支持分散对象的技术 ——Java的远程方法调用出台了。无论是CORBA,还是DCOM,都能在多种语言写的对象间进行通信。而RMI却不同,它只限于在由Java实现的对象间进行通信。显然,这是个制约。但RMI使用起来非常简单。另外,RMI的开发者可以用Java来设计协议规范。因此,在语言的功能上,可以做得浑然一体。若写一个只处理两三个客户端的DCOM服务器,还是比较简单的。但是,要构筑一个高效处理几百、几千个客户端的DCOM服务器,则相当之难。

为了便于编写可缩放的DCOM服务器,Microsoft发布了事务处理服务器(MTS)。MTS在支持事务处理的同时,也提供自动生成线索和智能对象的重复使用等服务。MTS使可缩放服务器的制作变得相当简单。即使是无需事务处理的应用,使用MTS也有好处。实际上,Microsoft鼓励人们用VB来写MTS应用。这与开发业务服务器的传统手法不同,所有的MTS应用,都是作为一个以上的COM对象来编写,且必须以DLL来实现。一般情况下,客户端看不到MTS。客户端只管一如既往地制作、使用COM对象即可。

2.组件的标准化

基于组件的应用开发,其方法和组装电子装置一样,可以用已制作好的组件部件来构筑应用。桌面用的、基于COM的组件叫做ActiveX控件。所谓ActiveX控件不过是遵从一定的标准、与客户端交互的COM对象而已。

例如,ActiveX控件必须通过Automation (即使用dispinterfaces)来公开方法。用这个被标准化的交互功能,可以在多个不同的上下文中,使用同一个控件。在这个标准接口的”幕后”, ActiveX控件几乎是什么都能执行。现在,许多软件公司都能提供实现各种功能的控件。

ActiveX控件是作为DDL编写的,为此,必须装载到某个容器中。ActiveX控件的原型容器是VB,除此之外,还有多种容器可供选择。目前,一个非常重要的控件容器是Microsoft的Web浏览器Internet Explorer。

现在所谓ActiveX控件的那些内容,是实现许多方法所必须的。已经把它们从机器的本地硬盘移到了VB等容器中。几百KB和几MB的控件,似乎没有什么大区别。但要将控件装载到Web浏览器时,很可能要通过速度很慢的电话线。现在,控件的大小已经是非常关键的问题。一旦要执行超过了某个限度以上的控件,就会延长下载时间。因此,Microsoft规定:在ActiveX控件中,只能执行绝对必要的功能。

Apple和IBM推行的OpenDoc,曾是ActiveX控件的主要竞争对手。现在OpenDoc的赞助企业,已正式宣告中止资助。大部分与 Microsoft对抗的企业,转而支持JavaBeans(基于Java的组件结构)。ActiveX控件,基本上都是和Windows捆绑在一起、以二进制机器代码发放的,而JavaBeans却不同,它在哪儿都能执行。这当然是有代价的。显而易见,只要不牺牲可移植性,就不可能完全、彻底地利用本地环境。要编写从公共Internet上能下载的组件时,应优先选择JavaBeans。

桌面组件市场在持续、急速增长。其中绝大部分是以ActiveX控件构筑的(目前JavaBeans仍然是少数)。但服务器组件的标准化要落后一些。在桌面上,Web浏览器、VB以及PowerBuilder这些编程环境,作为容器是强有力的。但服务器容器又该当如何呢?作为服务器上的组件容器, 事务处理服务器是一个较好的选择。

Microsoft的竞争对手,千方百计要阻止MTS和NT称霸市场。他们正在快马加鞭地制订服务器上的组件标准,其中最有前途的是Enterprise JavaBeans。它是JavaBeans的扩充,并定义了事务处理服务器接口。Enterprise JavaBeans的支持者们,希望独立软件厂商不是将服务器组件作为COM组件来编写,而是要作为Beans来编写。

四、ActiveX的构筑工具

随着ActiveX控件的推广,ActiveX控件的开发工具逐日增加。由于ActiveX不依赖于语言,所以传统的开发工具基本上都能构筑、配备ActiveX控件。最常用的有Delphi、PowerBuilder以及Visual Basic、Visual C++、Visual J++等。

1. 基本概况

用3GL开发ActiveX控件的方法有:①MFC (Microsoft Foundation Class,Microsoft基础类),②ATL(ActiveX Template Library,ActiveX模板库),③BaseCtrl Framework等。MFC最经典,采用MFC,可以使开发者不去关心接口,而是集中精力关注对象的动作。缺点是控件的规模较大且执行时DLL必须与容器同时存在。ATL可利用模板生成代码。就是说,库和DLL无需与控件一起推出。在ATL中,需要从作为模板存在的几个基本类派生类。ATL也有缺点,即接口的处理较难,应用中必要的接口,必须分别制作。另外,ATL不支持类向导(Class Wizard)。遗憾的是,没有使对象描述语言(Object Description Language)和接口定义语言文件、与用户代码自动同步的向导。BaseCtrl是个简便型库。与ATL非常相似,但无模板。实际上,由于 BaseCtrl过于简便,Microsoft并不支持它。在BaseCtrl中,带有几个万能控件(Skeleton Control)。BaseCtrl提供容易理解的ActiveX开发模型,但与ATL相比并不简单,且灵活性也不及ATL。目前看来,对于 ActiveX控件开发者来说,BaseCtrl是个”苦涩”的选择。

2. 开发工具

可制作ActiveX控件的、最初的工具是Microsoft的Visual C++。它可为ActiveX开发者提供最多的控件。Visual J++也可以制作ActiveX控件。

Borland推出的两个工具(JBuilder和IntraBuilder)也非常令人瞩目。但是,用Borland的工具能制作ActiveX组件的, 只有Delphi 3.0和C++ Builder。Borland把Delphi的ActiveX开发功能,叫作Active Inside。它是将任意的Delphi Window做成ActiveX的形式。Active Inside备有配备在Web上的新控件。Delphi可以将控件链接到COM和DCOM。

PowerBuilder 5.0是改造成能用于ActiveX开发的、客户机/服务器开发工具。 PowerBuilder可以将Data Window(PowerBuilder应用开发的核心部分)作为ActiveX控件来配备。以使现在的PowerBuilder开发者,能使用 PowerScript编程语言等某些熟悉的功能。具有制作ActivX控件最好工具的,当属Microsoft。例如,若用Visual Basic 5.0,开发者就可使用可视化编程环境和本机的Visual Basic for Application语言,来开发控件。

COM已成为Windows 95和Windows NT环境下基础软件的重要部分,但它的未来还有许多不确定的因素。例如,Microsoft是否能将COM作为多平台技术,让其继续存在发展下去?为了使 NT服务器能适合已有的企业,就必须要使DCOM等分布式服务也能在非Microsoft平台上应用。要解决这些问题, 需花费相当长的一段时间。另外, 基于CORBA的产品和Java的RMI,已成功地运行在多OS环境下。多平台DCOM出台得越晚,CORBA和RMI就领先越多。ActiveX控件和 JavaBeans的竞争前景如何?无论使软件运行在Web浏览器上也好,还是在另外的地方运行也好,总之,组件式软件(ComponentWare)将是下一个软件开发的热点。

如果只是打价格战,

而在相关的手续上卡客户,始终赢不了客户的心。。。

因为域名本身就限制了只能企业注册,不能个人,很多人在注册的时候,都是用别人的公司或者假公司,做临时的。。迟早有一点要转回自己名下。

而相关的注册商又想在限制转移注册商,在过户方面等收费、老油水,谁敢去他那买,那怕是免费我都不要

因为我要的是域名不是在于你少那几个钱的问题。

而且国内域名市场还很广阔, 象时代那sb ,说自己米多便宜,可是过户要钱,我才不去,再便宜跟我没有关系。

如果你的域名设置为Auto-Renew(自动续费),则在到期前一个月,ENOM系统自动帮你续费。当然前提是你账号里有钱了(Reseller账号),Retail账号如果设置了信用卡,应该也是自动扣的。

如果自己没有美元支付手段(国际信用卡或PAYPAL),可以找可靠的人代续费,就是把域名PUSH到对方的账号里,由对方代续费,然后再PUSH回你的账号。如果你和对方没有上下线关系,PUSH回来需要等七天。如果是你的上线,可以续完费马上PUSH回来。

如果你的账号是Reseller型,因为Reseller一次充钱要100美元,如果不想一次充那么多,可以自己给自己开设一个下线Retail账号,然后把米PUSH进去,用这个账号续费,消费多少直接从信用卡扣多少。不过要注意,我刚才试了一下,$8.95代理账号开一个下线Retail账号,最低价格只能设到$10.21,不知道ENOM是怎么算的。

 

 

CacheEnable: 啟動 mod_cache,其後接兩個參數。第一個參數指定快取的種類,

應設為 mem (記憶體快取) 或 disk (磁碟快取) 之其一;第二個參數指定使用快

取的 URI 路徑,如果對整個網站 (或虛擬主機) 進行快取,簡單指定為根目錄

(/) 即可。

CacheForceCompletion: 這個值指定當 HTTP request 被取消時,內容的產生動

作要完成的百分比;預設是 60(%)。

CacheDefaultExpire: 指定快取的預設過期秒數;預設值是一小時 (3600)。

CacheMaxExpire: 指定快取最大的過期秒數;預設值是一天 (86400)。

CacheLastModifiedFactor: 用來從回應裡 Last Modified 資訊算出 expire

date。計算方式是:

expire period (過期時距) = 最後更新後至今的時間間距 *

CacheLastModifiedFactor

expire date = 目前時間 + expire period

不過無論如何,過期時間不能超過 CacheMaxExpire 的設定值。

mod_disk_cache:

(Bytes)。

 

系统中的 2 千万条记录主要是分布在两张名为 ad_adviews 和 ad_adclicks 的表中。我在系统中执行了这两句 SQL 创建了以 Archive 引擎存储的新表 ad_adviews_archive_2005 和 ad_adclicks_archive_2005∶

CREATE TABLE ad_adviews_archive_2005 ENGINE=archive AS SELECT * FROM ad_adviews WHERE t_stamp < ‘2006-01-01 00:00:00’;

CREATE TABLE ad_adclicks_archive_2005 ENGINE=archive AS SELECT * FROM ad_adclicks WHERE t_stamp < ‘2006-01-01 00:00:00’;

然后,在生成的新表 ad_adviews_archive_2005 中有 2,070,860 条记录,执行时间是∶

Your SQL query has been executed successfully (Query took 48.0973 sec)

ad_adclicks_archive_2005 中有 23,908,414 条记录,执行时间是∶

Your SQL query has been executed successfully (Query took 466.2194 sec)

大家可以把下面的这段代码copy下来测试。

<?php

                fputs($File, $out);

  一般来说,当你执行管理员优化的时候,应该紧记以下规则:

  · 访问内存中的数据快于访问磁盘上的数据。

  · 尽量把数据保存在内存中可以减少磁盘操作。

  · 保留索引中的信息比保留数据记录的内容更重要。

  我们在后面将讨论如何应用这些规则。

  增加服务器缓存的大小。服务器拥有很多参数(系统变量),你可以改变这些参数来影响服务器的操作。其中的几个参数直接地影响查询处理的速度。你可以改变的最重要的参数是数据表缓存的大小和存储引擎用于缓冲索引操作信息的缓存大小。如果你拥有可用的内存,就把它分配给服务器的缓存,以允许信息存储在内存中并减少磁盘操作。这会有很好的效果,因为访问内存中的信息比从磁盘读取信息的速度快得多。

  · 当服务器打开表文件的时候,它试图保持这些文件的打开状态,以减少打开文件操作的数量。为了实现这样的功能,它在表缓存中维护打开文件的信息。table_cache系统变量控制着这个缓存的大小。如果服务器访问了大量的表,表缓存就会被填满,并且服务器会关闭那些有一段时间没有使用的表,为打开新表留出空间。你可以通过检查Opened_tables状态指示器来访问表缓存的效果:

SHOW STATUS LIKE ’Opened_tables’;

  Opened_tables显示了某个数据表必须打开的次数(因为它还没有打开)。这个值也显示为mysqladmin状态命令的输出信息中的Opens值。如果这个数字是稳定的或缓慢增长,那么它的设置可能是正确的。如果这个数字增长得很快,就意味着这个缓存太小了,必须经常关闭数据表来为打开其它的数据表留出空间。如果你拥有文件描述信息,增加表缓存大小将减少数据表打开操作的数量。

  · MyISAM存储引擎使用键缓冲来保持与索引相关的操作的索引信息块。它的大小是由key_buffer_size系统变量控制的。这个值越大,MySQL就一次性在内存中保持更多的索引信息块,可以增加在内存中(而不用从磁盘上读取新的信息块)找到键值的可能性。键缓存的默认大小是8MB。如果你拥有很多的内存,这是一个很保守的值,你可以直接增加它的大小,并且会看到基于索引的检索、索引的建立和修改操作的性能有很大改善。

  在MySQL 4.1以上版本中,你可以为MyISAM数据表建立附加的键缓存,并指定某些表使用它们。这样可以帮助提高这些数据表上的查询处理速度。

  · InnoDB和BDB引擎拥有自己的用于缓冲数据和索引值的缓存。它们的大小是由innodb_buffer_pool_size和bdb_cache_size变量控制的。InnoDB引擎还维护了一个日志缓冲。innodb_log_buffer_size变量可以控制它的大小。

  · 另一个专用的缓存是查询缓存,我们在”使用查询缓存”部分中解释。

  当你改变这些参数值的时候,应该遵循下面一些原则:

  · 每次只改变一个参数。如果你一次改变多个相互独立的变量,那么就很难评估每种改变的效果了。

  · 逐渐地增加系统变量值。根据理论,数量越多,性能越好,但是如果你使某个变量变得太大了,有可能造成系统资源匮乏,导致逆向效果,降低速度。

  · 不要在运行业务MySQL数据库的服务器上做调整参数的实验,最好建立一个独立的测试服务器。

  · 为了大致了解哪种参数变量可能适合自己的系统,你可以查看MySQL发布文档中包含的my-small.cnf、my-medium.cnf、my-large.cnf和my-huge.cnf选项文件(在Unix系统上,你可以在源发布文件的支持文件目录和二进制发布文件的共享目录总找到这些文件。在Windows上,它们位于基本的安装目录中,其扩展名可能是.ini)。这些文件可能让你知道最好改变服务器上的那些参数以适应不同的使用层次,并且为这些参数提供了一些典型值。

  用于提高服务器的操作性能的其它一些策略还包括:

  如果你从源文件建立MySQL,那么就把它配置为使用静态类库,而不要使用共享类库。使用共享类库的动态二进制文件节约磁盘空间,然而静态二进制文件速度更快。但是,如果你使用了用户自定义函数(UDF)机制,那么有些系统要求使用动态链接。在这类系统上,静态二进制文件不能工作。

  使用MyISAM键缓存

  当MySQL执行某个利用了MyISAM数据表索引的语句的时候,它会使用键缓存来保持索引值。这种缓存减少了磁盘I/O:如果在缓存中找到了某个数据表需要的键值,就不需要再次从磁盘中读取。不幸的是,这种键缓存是有限的,并且在默认情况下,它是所有的MyISAM数据表共享使用的。如果在键缓存中没有找到键值并且键缓存是满的,争用将会导致:必须丢弃缓存中的某些值,为新值留出空间。如果下次需要那些已经被丢弃的值,就必须再次从磁盘上读取。

  如果你很倚重MyISAM数据表,那么把它的键保存在内存中效果会很好,但是缓存中的争用却会导致相反的效果。从同一张表或不同的表读取数据都可能引起争用。你可以通过把键缓存设置成足以保存某个特定数据表的全部索引,从而避免同一张数据表的争用,但是其它数据表的键仍然需要争用缓存空间。

  MySQL 4.1以上版本为这个问题提供了一种解决方案:它支持我们建立多个键缓存,并允许我们把某张数据表的索引指定并且预先装入某个缓存。如果你的数据表使用得很频繁,并且你有足够的内存,能够把它的索引载入缓存中,那么这种操作就是有用的。这种能力允许你同时避免同一张表和不同的表的争用:建立一个足够大的缓存,让它保存数据表的全部索引,并且指定该缓存专门用于那张数据表。在键被载入缓存之后,不在需要磁盘I/O操作。同时,键值永远不会被丢弃,对数据表的键的查看操作可以在内存中完成。

  下面的例子显示了如何为sampdb数据库的member数据表建立一个键缓存,该缓存的名称是member_cache,大小为1MB。执行这些指令的时候,你必须有超级(SUPER)权限。

  1.建立一个足够容纳数据表索引的独立的缓存:

mysql> SET GLOBAL member_cache.key_buffer_size = 1024*1024;

  2.给数据表指定键缓存:

  3.把数据表索引预先读入它的键缓存中:

  如果你希望把其它的数据表载入同一个缓存中,或者为其它的数据表建立键缓存,上面的操作就足够了。

  使用查询缓存

  MySQL服务器可以使用查询缓存来提高那些重复执行的SELECT语句的处理速度。它对性能的提高通常都是惊人的。查询缓存的工作方式如下所示:

  · 第一次执行某条SELECT语句的时候,服务器记住该查询的文本内容和它返回的结果。

  · 服务器下一次碰到这个语句的时候,它不会再次执行该语句。作为代替,它直接从查询缓存中的得到结果并把结果返回给客户端。

  · 查询缓存是基于服务器所接收到的查询字符串的文本内容的。如果某些查询的文本完全相同,那些它就认为这些查询是相同的。如果某些查询的字符不同,或者来自那些使用了不同的字符集或通讯协议的客户端,那么它会认为这些查询是不同的。同样,如果某些查询采用其它的功能相当、但是实际上没有指向相同的数据表(例如引用了不同的数据库中的同名数据表),那么它们也是不同的。

  · 当数据表被更新了之后,涉及到该数据表的任何缓存查询都变成无效的,并且会被丢弃。这可以防止服务器返回过期的结果。

  在默认情况下,MySQL对查询缓存的支持是内建的。如果你不希望使用这种缓存,并且想避免它所导致的性能开销,可以使用–without-query-cache选项来运行配置脚本建立服务器。

  如果需要检测某个服务器是否支持查询缓存,可以检查它的have_query_cache系统变量:

  对于那些支持查询缓存的服务器来说,缓存的操作是基于三个系统变量值的:

  · query_cache_type决定查询缓存的操作模式。下表显示了可以使用的模式值:

  · query_cache_limit设置被缓存的最大结果集大小;比这个值大的查询结果不会被缓存。

  例如,为了激活查询缓存并为它分配16MB内存,在配置文件中使用下面的设置:

  即使query_cache_type的值设置为零,query_cache_size指定内存数量也会被分配。为了避免浪费内存,只有在希望激活缓存的时候才把大小设置成大于零。同时,即使query_cache_type不为零,查询缓存的大小设置为零也会禁用缓存。

  使用了查询缓存的独立客户端会在服务器的默认缓存模式状态下操作。客户端可以使用下面的语句改变自己的查询的默认缓存模式:

SET query_cache_type = val;

  其中的val可以是0、1或2,它的意义与设置服务器启动时的query_cache_type变量的意义是相同的。在SET语句中,OFF、ON和DEMAND这些符号值与0、1和2对应。

  客户端还可以通过在SELECT关键字后天添加调节符来控制个别查询的缓存操作。如果缓存模式是ON或DEMAND,那么SELECT SQL_CACHE语句会让查询结果被缓存。SELECT SQL_NO_CACHE语句会使查询结果不被缓存。

  如果某些查询从经常改变的数据表中检索信息,那么抑止对这些查询的缓存操作是有用的。在这种情况下,缓存未必有多大用处。假设你把Web服务器请求的日志存储在MySQL数据表中,同时周期性地运行该数据表上的一组统计查询。对于很繁忙的Web服务器来说,会频繁地出现新行插入该数据表的操作,因此该数据表的任何缓存了的查询结果很快就变成无效的了。其含义是,尽管你周期性地提交统计查询,但是查询缓存可能对这些查询没有什么价值。在这种情况下,最好使用SQL_NO_CACHE调节符告诉服务器不要缓存这些查询的结果。

  硬件问题

  本文前面的部分中讨论的帮助你提高服务器性能的技术是没有考虑硬件配置的。你当然可以通过使用更好的硬件来让服务器运行地更快。但是并非所有的与硬件相关的改变都有相同的价值。当我们评估哪些硬件提高了性能的时候,最重要的原则与调整服务器参数的原则是相同的:尽可能地把最多的信息放在最快的存储中,并让这些信息尽可能地保持在该存储中。

  你可以改变几种硬件配置来提升服务器的性能:

  在计算机上安装更多的内存。这可以让你把服务器的缓存和缓冲区大小值配置成更大的,从而使数据保存在内存中的时间更长,从磁盘上读取信息的需要更少。

  重新配置系统,如果你拥有足够的内存,能够在内存文件系统中执行全部的交换操作,那么就删除所有的磁盘交换设备。否则,即使你拥有足够的用于交换操作的RAM,某些系统仍然会跟磁盘进行交换操作。

  增加更快的磁盘以改善I/O等待时间。在这种情况下,寻道时间是有代表性的主要的性能决定因素。横向移动磁头的速度比较慢,在磁头定位以后,从磁道上读取信息块的速度相对较快。但是,如果需要选择是添加更多的内存还是更快的磁盘,那么最好选择添加更多的内存。内存总是比磁盘快,而且添加内存可以让你使用更大的缓存,从而减少磁盘活动。

  通过在物理设备上划分磁盘活动来获取并行操作的优势。如果你可以在多个物理设备上划分读操作和写操作,那么其速度就会比从同一个设备读写要快一些。例如,如果你把数据库存储在一个设备上,把日志存储在另一个设备上,那么同时向两个设备写入信息的速度就比数据库和日志共享同一个设备的速度要快。请注意,使用同一个物理设备上的不同分区不算是并行操作。这是没有好处的,因为它们仍然需要争用相同的物理资源(磁头)。

  在把数据重新部署到另外一个设备之前,你要确保自己知道系统的负载状况。如果在某个特定的物理设备上正在运行一些重要的业务,那么把数据库放在该设备上有可能使性能更差。例如,如果你正在处理大量的Web业务,同时把数据库移动到Web服务器文档目录所在的设备上,就可能感觉不到任何优势。

  使用RAID设备可以让你获取并行操作的优势。

笔者在应用项目的实施中发现,许多程序员在利用一些前端数据库开发工具(如PowerBuilder、Delphi等)开发数据库应用程序时,只注重用户界面的华丽,并不重视查询语句的效率问题,导致所开发出来的应用系统效率低下,资源浪费严重。因此,如何设计高效合理的查询语句就显得非常重要。本文以应用实例为基础,结合数据库理论,介绍查询优化技术在现实系统中的运用。

分析问题

许多程序员认为查询优化是DBMS(数据库管理系统)的任务,与程序员所编写的SQL语句关系不大,这是错误的。一个好的查询计划往往可以使程序性能提高数十倍。查询计划是用户所提交的SQL语句的集合,查询规划是经过优化处理之后所产生的语句集合。DBMS处理查询计划的过程是这样的:在做完查询语句的词法、语法检查之后,将语句提交给DBMS的查询优化器,优化器做完代数优化和存取路径的优化之后,由预编译模块对语句进行处理并生成查询规划,然后在合适的时间提交给系统处理执行,最后将执行结果返回给用户。在实际的数据库产品(如Oracle、Sybase等)的高版本中都是采用基于代价的优化方法,这种优化能根据从系统字典表所得到的信息来估计不同的查询规划的代价,然后选择一个较优的规划。虽然现在的数据库产品在查询优化方面已经做得越来越好,但由用户提交的SQL语句是系统优化的基础,很难设想一个原本糟糕的查询计划经过系统的优化之后会变得高效,因此用户所写语句的优劣至关重要。系统所做查询优化我们暂不讨论,下面重点说明改善用户查询计划的解决方案。

解决问题

下面以关系数据库系统Inf为例,介绍改善用户查询计划的方法。

1.合理使用索引

索引是数据库中重要的数据结构,它的根本目的就是为了提高查询效率。现在大多数的数据库产品都采用IBM最先提出的ISAM索引结构。索引的使用要恰到好处,其使用原则如下:

●在经常进行连接,但是没有指定为外键的列上建立索引,而不经常连接的字段则由优化器自动生成索引。

●在频繁进行排序或分组(即进行group by或order by操作)的列上建立索引。

●在条件表达式中经常用到的不同值较多的列上建立检索,在不同值少的列上不要建立索引。比如在雇员表的“性别”列上只有“男”与“女”两个不同值,因此就无必要建立索引。如果建立索引不但不会提高查询效率,反而会严重降低更新速度。

●如果待排序的列有多个,可以在这些列上建立复合索引(compound index)。

●使用系统工具。如Inf数据库有一个tbcheck工具,可以在可疑的索引上进行检查。在一些数据库服务器上,索引可能失效或者因为频繁操作而使得读取效率降低,如果一个使用索引的查询不明不白地慢下来,可以试着用tbcheck工具检查索引的完整性,必要时进行修复。另外,当数据库表更新大量数据后,删除并重建索引可以提高查询速度。

2.避免或简化排序

应当简化或避免对大型表进行重复的排序。当能够利用索引自动以适当的次序产生输出时,优化器就避免了排序的步骤。以下是一些影响因素:

●索引中不包括一个或几个待排序的列;

●group by或order by子句中列的次序与索引的次序不一样;

●排序的列来自不同的表。

为了避免不必要的排序,就要正确地增建索引,合理地合并数据库表(尽管有时可能影响表的规范化,但相对于效率的提高是值得的)。如果排序不可避免,那么应当试图简化它,如缩小排序的列的范围等。

3.消除对大型表行数据的顺序存取

在嵌套查询中,对表的顺序存取对查询效率可能产生致命的影响。比如采用顺序存取策略,一个嵌套3层的查询,如果每层都查询1000行,那么这个查询就要查询10亿行数据。避免这种情况的主要方法就是对连接的列进行索引。例如,两个表:学生表(学号、姓名、年龄……)和选课表(学号、课程号、成绩)。如果两个表要做连接,就要在“学号”这个连接字段上建立索引。

还可以使用并集来避免顺序存取。尽管在所有的检查列上都有索引,但某些形式的where子句强迫优化器使用顺序存取。下面的查询将强迫对orders表执行顺序操作:

SELECT * FROM orders WHERE (customer_num=104 AND order_num>1001) OR order_num=1008

虽然在customer_num和order_num上建有索引,但是在上面的语句中优化器还是使用顺序存取路径扫描整个表。因为这个语句要检索的是分离的行的集合,所以应该改为如下语句:

SELECT * FROM orders WHERE customer_num=104 AND order_num>1001

UNION

SELECT * FROM orders WHERE order_num=1008

这样就能利用索引路径处理查询。

4.避免相关子查询

一个列的标签同时在主查询和where子句中的查询中出现,那么很可能当主查询中的列值改变之后,子查询必须重新查询一次。查询嵌套层次越多,效率越低,因此应当尽量避免子查询。如果子查询不可避免,那么要在子查询中过滤掉尽可能多的行。

5.避免困难的正规表达式

MATCHES和LIKE关键字支持通配符匹配,技术上叫正规表达式。但这种匹配特别耗费时间。例如:SELECT * FROM customer WHERE zipcode LIKE “98_ _ _”

即使在zipcode字段上建立了索引,在这种情况下也还是采用顺序扫描的方式。如果把语句改为SELECT * FROM customer WHERE zipcode >“98000”,在执行查询时就会利用索引来查询,显然会大大提高速度。

另外,还要避免非开始的子串。例如语句:SELECT * FROM customer WHERE zipcode[2,3]>“80”,在where子句中采用了非开始子串,因而这个语句也不会使用索引。

6.使用临时表加速查询

把表的一个子集进行排序并创建临时表,有时能加速查询。它有助于避免多重排序操作,而且在其他方面还能简化优化器的工作。例如:

SELECT cust.name,rcvbles.balance,……other columns

FROM cust,rcvbles

WHERE cust.customer_id = rcvlbes.customer_id

AND rcvblls.balance>0

AND cust.postcode>“98000”

ORDER BY cust.name

如果这个查询要被执行多次而不止一次,可以把所有未付款的客户找出来放在一个临时文件中,并按客户的名字进行排序:

SELECT cust.name,rcvbles.balance,……other columns

FROM cust,rcvbles

WHERE cust.customer_id = rcvlbes.customer_id

AND rcvblls.balance>0

ORDER BY cust.name

INTO TEMP cust_with_balance

然后以下面的方式在临时表中查询:

SELECT * FROM cust_with_balance

WHERE postcode>“98000”

临时表中的行要比主表中的行少,而且物理顺序就是所要求的顺序,减少了磁盘I/O,所以查询工作量可以得到大幅减少。

注意:临时表创建后不会反映主表的修改。在主表中数据频繁修改的情况下,注意不要丢失数据。

7.用排序来取代非顺序存取

非顺序磁盘存取是最慢的操作,表现在磁盘存取臂的来回移动。SQL语句隐藏了这一情况,使得我们在写应用程序时很容易写出要求存取大量非顺序页的查询。

有些时候,用数据库的排序能力来替代非顺序的存取能改进查询。

实例分析

下面我们举一个制造公司的例子来说明如何进行查询优化。制造公司数据库中包括3个表,模式如下所示:

1.part表

比较这两种最流行的构建 web 应用程序的方法的优缺点

如今当提到 Web 开发时,您有许多选择。这些方法中许多都涉及到预处理 — 即,利用特定的标记将代码嵌入到 HTML 页面中,这些标记告诉预处理器,它们包含代码,并且应对它们作出处理。与 CGI 非常相似,这些代码在服务器上运行,并返回一些内容,这些内容表现为发回给浏览器的结果 HTML 页面的部分外观。开放源代码脚本语言 PHP 和 Microsoft 的 ASP.NET 框架中的语言都属于这种类型;JavaServer Pages (JSP) 和 Perl/Mason 也以这种方式运行。

在本文中,我将重点讲述 PHP — Oracle 已选择合并到其产品中的技术 — 和 ASP.NET。我将概述两者的各种优势和弱点,并着重讨论那些将帮助您决定开发项目应选择哪种技术的因素。有很多因素需要考虑,不同的项目可能诉诸于不同的技术。总之,您将看到在价格、速度和效率、安全性、跨平台支持等方面的逐项比较,以及开放源代码解决方案的优势。

什么是 ASP.NET?

ASP 最新的版本 ASP.NET 并不完全与 ASP 早期的版本后向兼容,因为该软件进行了完全重写。早期的 ASP 技术实际上与 PHP 的共同之处比与 ASP.NET 的共同之处多得多,ASP.NET 是用于构建 Web 应用程序的一个完整的框架。这个模型的主要特性之一是选择编程语言的灵活性。ASP.NET 可以使用脚本语言(如 VBScript、JScript、Perlscript 和 Python)以及编译语言(如 VB、C#、C、Cobol、Smalltalk 和 Lisp)。新框架使用通用语言运行环境 (CLR);先将您语言的源代码编译成 Microsoft 中间语言代码,然后 CLR 执行这些代码。

这个框架还提供真正的面向对象编程 (OOP),并支持真正的继承、多态和封装。.NET 类库根据特定的任务(例如,使用 XML 或图像处理)组织成可继承的类。

除了编程语言和方法之外,数据库访问也是要着重关心的一个因素。当您用 ASP.NET 编程时,可以用 ODBC 来集成数据库;ODBC 提供了一组一致的调用函数来访问您的目标数据库。

优势和弱点

ASP.NET 的优势很明显在于它简洁的设计和实施。这是面向对象的编程人员的梦想:语言灵活,并支持复杂的面向对象特性。在这种意义下,它真正能够与编程人员现有的技能进行互操作。

ASP.NET 的另一个优势是其开发环境。例如,开发人员可以使用 WebMatrix(一个社区支持的工具)、Visual Studio .NET 或各种 Borland 工具(如 Delphi 和 C++ Builder)。例如,Visual Studio 允许设置断点、跟踪代码段和查看调用堆栈。总而言之,它是一个复杂的调试环境。许多其他第三方的 ASP.NET IDE 解决方案也将必然出现。

但您得到了强健性,就将以损失效率为代价。ASP.NET 在内存使用和执行时间方面耗费非常大,这大部分归因于较长的代码路径。对基于 Web 的应用程序,这些局限可能是一个严重的问题,因为在 Web 上,您的应用程序可能扩展为每秒成千上万的用户。内存使用率还可能成为 Web 服务器上的一个问题。

什么是 PHP?

PHP 是基于预处理 HTML 页面模型的一种脚本语言。当 Web 服务器中的 PHP 预处理器发现像下面这样的 PHP 语言标记时,将调用 PHP 引擎来执行该代码:

在上面对 ASP.NET 的讨论中,我提到了 ODBC 驱动程序,以及在考虑数据库抽象的情况下如何构建应用程序。在 PHP 中,您也可以使用 ODBC 与数据库对话,因此您已经有了一系列支持的数据库可供选择。也有 MySQL、Oracle 和 Postgres 的原生驱动程序。此外,如果要使用 Oracle,则有一个特殊的 OCI8 库将提供对 Oracle 更多访问功能,从而允许您使用诸如 LOB、BLOB、CLOB 和 BFILE 之类的特性。

这时您可能会问“为什么与数据库相关的资料库被称为 PHP 的特性?”数据库抽象或独立性是您在设法构建使用多种数据库或需要在数据库间移植(例如,从开发到投产时的移植)的应用程序时所要考虑的一个因素。而这些确实是应该关心和考虑的。

但正如 Tom Kyte 在他的新书 — Effective Oracle by Design (Oracle 出版社) — 中指出的那样,数据库相关性将成为您真正的目标,因为这将使您在该技术中的投资最大化。如果您对 Oracle 进行一般的访问 — 无论通过 ODBC 或 Perl 的 DBI 库,那么您将无法使用其他数据库所不具有的特性。此外,优化查询在各个数据库中各不相同。

Zend Technologies 是一家商业软件公司,它对 PHP 作出了重大贡献。它创建了一个称为 Zend Studio 的商业开发环境,这个环境包含了一个复杂的调试器、一个监测器和其他特性。该公司还构建了免费的 Zend Optimizer,它与 Zend Encoder 结合使用来编译 PHP 代码,以提升性能。还有其他商业产品,如 Zend Performance Suite,它可以缓存预编译的 PHP 页面,从而进一步显著提升总体性能。

优势和弱点

到测试版 4 为止,PHP 5 仍然有一些缺点,包括缺少异常和基于事件的错误处理例程 — 它们能够中断正常的程序流,并将代码跳转到一个特殊的错误处理部分。Java 也提供了用于错误处理的异常,而 C++ 通过 try、catch 和 throw 语法提供异常处理。当然,您仍然可以在 PHP 中管理错误,但其结构不是标准化的,因而使得编程人员必须使用自己的工具来决定执行错误处理的方式,这将导致更低的一致性并往往导致推倒重来。

另一个弱点是 PHP 的函数名是不区分大小写的。虽然这不是一个严重的缺点,但有些程序员可能会觉得这一特性很讨厌。

不过,我的确对 PHP 的对象模型心存疑虑。PHP 不是专门设计为一种面向对象的语言。这些特性中的一部分是后来添加的 — 尽管注意了保持与 PHP 3 的后向兼容性,因此两种模型的特性都留有一些。实际上,在 PHP 5 中这些弱点中的许多都得到了解决。请留心关注。

PHP 在一些领域中缺少什么,它就会在擅长的领域中迅速地弥补什么。价格合理,因此您不需要担心许可问题。它也是开放源代码的,因此整个社区将密切关注开发过程:发现错误并将其修复。如果有一个特性您不喜欢,那么您可以修改代码。此外,PHP 可与 Apache 自然结合:它可以作为一个模块编译,或直接编译成 Apache 二进制文件。

但在 Apache 上运行意味着,利用 PHP,您能够利用您已经在任意服务器投资,这是因为 Apache 能够运行在 Windows、Linux、Solaris 和各种其他 Unix 平台上。此外,使用拥有 Apache 的跟踪记录的 web 服务器意味着安全性能够保持在最高的优先级上。最后,PHP 拥有更小的代码路径,这意味着更少的分析和执行 PHP 页面服务器端代码,这将带来更高效的内存和使用率以及更快的运行。

在 PHP 5 中新增了哪些特性?

PHP 5 的第 4 个测试版在 2003 年 12 月底推出,更改日志清楚地显示已发现许多错误并已将其消除。虽然它仍在进行测试,但它的所有新特性和进步都确实值得关注。

PHP 5 的主要新成就在于它的异常处理和一个新对象,这个新对象引入的特性赋予了 PHP 真正的 OOP。异常处理无疑是 PHP 4 中最显著的缺憾之一,而 PHP 5 对异常处理的引入无疑是一个成熟的标志。异常处理意味着您在您的软件中拥有了根据语言定义的和标准化的错误处理方法。只需使用 try、catch 和 throw 方法,您的 PHP 代码就变得更加强健和简洁。

class blue {

$blueObj = new blue ();

# rest of blue methods here

?>

PHP 5 中新的面向对象的特性(包括构造器和析构器)值得关注。与 C++ 和 Java 相同,它们提供了一种标准方法,即通过一个构造器方法来创建对象、分配内存和执行任何必要的设置,并通过一个析构器方法来执行清理。

PHP 5 还引入了对类中方法和变量的更精细控制。在 PHP 4,一切都是公有的:您可以从类外或在继承类中访问您类中的变量。在 PHP 5 中,您仍然可以使变量或方法为公有,但您也可以使它们为私有,以使得只能在类本身中使用它们。还可以将它们保护起来,也就是说,可以在类内或在子类中查看方法和变量。

此外,PHP 5 引进了类型提示或更好的类型检查。当您将一个对象传递给一个例程时,PHP 能够检查它是否是正确的类型,并在检查失败时产生类型不匹配错误。

由于还有其他特性(如静态方法和变量以及抽象类),因此请务必查看文档,以获取详细信息。

安全性比较

ASP.NET 官方要求您使用 IIS。不幸的是,IIS 易受攻击的历史由来已久,这使得许多管理员不愿意部署它来处理 Web 站点。这些弱点是因为 Microsoft 的缺陷或是因为 IIS 是黑客们攻击的目标无关紧要:这些系统有被黑或被攻击的历史。PHP 也运行在 Apache 上,Apache 快速并且是开放源代码的,并拥有很好的安全性记录。此外,正如我提到过的,Apache 可以在许多平台上运行。

如果您在考虑 ASP.NET,但您想用 Apache 作为 Internet 门户,那么很幸运您可以有一些选择。首先,您可以使用 Apache 将请求转发给在另一台计算机上内部运行的 IIS。然后 Apache 处理静态内容,并将 aspx 内容传送给 IIS 服务器(不暴露给 Internet)。

不过,如果您想利用 Apache 承载 ASP.NET,那么提供了一些选项,这些选项 Microsoft 可能支持也可能不支持。作为最后一种选择,有 Ximian 的 Project Mono,它致力于构建一个开放源代码模块。请浏览 [url]www.go-mono.com[/url],以获取更多信息。

数据库编码示例

您在选用 PHP 或 ASP.NET 时首先要考虑因素之一就是与数据库的连接。不过,利用 ASP.NET 更复杂,因为您可以从许多备选语言中选择任意一种语言。当然,这些代码示例将必须嵌入到 HTML 页面、实例化的类等之中。不过,以下信息将使您对二者的编码风格有所了解。

PHP 5 与 Oracle 连接

下面是一个 PHP 5 类,它提供了一个 Oracle 连接和断开例程,用以演示利用 PHP 5(也可以使用其他驱动程序(如 ODBC 驱动程序)和通用的数据库接口)与 Oracle 连接的一种方式:

简单来讲它是一套配合PHP(支持PHP5)运作的缓存系统,通过共享内存或磁盘文件方式交换数据。

它被广为使用的是PHP源码“编码”(不太贴切的称为“加密”)和缓存PHP执行的中间码以加速。关于 eA 的安装使用的文章已经很多而且也很详细了,这次我想推荐的是用它辅助程序设计缓存,它提供了一组API如下:

是一个非常便捷而又稳定的本机缓存实现方式,目前这部分设计似乎只支持于共享内存,所以只能用于 Unix -Like OS 了,windows的就没这个福气了。

index.html

 

weather.js

weather.asp

<%@LANGUAGE=”j” CODEPAGE=”65001″%>
<%
Session.CodePage = “65001”
Response.contentType=”application/xml”
Response.Expires = 0
var N=Request(“n”)
var Num=Request(“id”)
var url=”http://xml.weather.yahoo.com/forecastrss?p=”+N+”&u=c&id=”+Num;
var xmldoc=Server.CreateObject(“Microsoft.Xmlhttp”);
xmldoc.open(’GET’,url,false);
xmldoc.send(null);
var response = xmldoc.responseXML.documentElement;
var lastNode=response.selectNodes(“//rss/channel/lastBuildDate”);
var cityNode=response.selectNodes(“//rss/channel/yweather:location”);
var windNode=response.selectNodes(“//rss/channel/yweather:wind”);
var atmosphereNode=response.selectNodes(“//rss/channel/yweather:atmosphere”);
var astronomyNode=response.selectNodes(“//rss/channel/yweather:astronomy”);
var conditionNode=response.selectNodes(“//rss/channel/item/yweather:condition”);
var forecastNode=response.selectNodes(“//rss/channel/item/yweather:forecast”);
var lastV=lastNode(0).firstChild.nodeValue
//编辑属性
function attri(a,b,c){

        return a(b).attributes.getNamedItem(c).value
}
var cityV=attri(cityNode,0,”city”)
var chillV=attri(windNode,0,”chill”)
var directionV=attri(windNode,0,”direction”)
var speedV=attri(windNode,0,”speed”)
var humidityV=attri(atmosphereNode,0,”humidity”)
var visibilityV=attri(atmosphereNode,0,”visibility”)
var sunriseV=attri(astronomyNode,0,”sunrise”)
var sunsetV=attri(astronomyNode,0,”sunset”)
var textV=attri(conditionNode,0,”text”)
var codeV=attri(conditionNode,0,”code”)
var tempV=attri(conditionNode,0,”temp”)
//转换英文为中文
var cityCH=EN2CH(cityV)
function EN2CH(obj){

        if(obj==”Wuhan”){return “武汉”}
        else if(obj==”Nanchang”){return “南昌”}
        else if(obj==”Haikou”){return “海口”}
        else if(obj==”Beijing”){return “北京”}
        else if(obj==”Shanghai”){return “上海”}
        else if(obj==”Guangzhou”){return “广州”}
        else if(obj==”Yinchuan”){return “银川”}
        else if(obj==”Zhengzhou”){return “郑州”}
        else if(obj==”Changsha”){return “长沙”}
        else if(obj==”Hanzhong”){return “杭州”}
        else if(obj==”Hong Kong”){return “香港”}
        else if(obj==”Xin’an”){return “西安”}
        else if(obj==”Chengdu”){return “成都”}
        else if(obj==”Qingdao”){return “青岛”}
        else if(obj==”Guiyang”){return “贵阳”}
        else if(obj==”Jinan”){return “济南”}
        else if(obj==”Hefei”){return “合肥”}
        else if(obj==”Fuzhou”){return “福州”}
        else if(obj==”Nanjing”){return “南京”}
        else{return obj}
}
//风向函数
var windCH=wind(directionV)
function wind(a){

        if(a>337 && a<=360){return “北风”};
        else if(a>=0 && a<=22){return “北风”};
        else if(a>22 && a<=67){return “东北风”};
        else if(a>67 && a<=112){return “东风”};
        else if(a>112 && a<=157){return “东南风”};
        else if(a>157 && a<=202){return “南风”};
        else if(a>202 && a<=247){return “西南风”};
        else if(a>247 && a<=292){return “西风”};
        else if(a>292 && a<=337){return “西北风”};
}
//能见度函数
visibility=vis(visibilityV)
function vis(a){

        return a/100
}
//转换天气为中文
var textCH=tEN2CH(textV)
function tEN2CH(obj){

        if(obj==”Clear”){return “晴朗”}
        else if(obj==”Sunny”){return “晴天”}
        else if(obj==”Partly Cloudy”){return “局部有云”}
        else if(obj==”Mostly Clear”){return “晴”}
        else if(obj==”Mostly Sunny”){return “小云”}
        else if(obj==”Mostly Cloudy”){return “多云”}
        else if(obj==”Cloudy”){return “云”}
        else if(obj==”Sunny/Wind”){return “晴转云”}
        else if(obj==”AM Clouds/PM Sun/Wind”){return “云转晴”}
        else if(obj==”AM Showers”){return “晨雨”}
        else{return obj}
}
//天气图片
var weaNum=weaimg(codeV)
function weaimg(obj){

        return “<img src=”http://us.i1.yimg.com/us.yimg.com/i/us/we/52/”+obj+”.gif” />”
}
//星期替换
function dayEn(obj){

        if(obj==”Sun”){return “星期曰”}
        else if(obj==”Mon”){return “星期一”}
        else if(obj==”Tue”){return “星期二”}
        else if(obj==”Wed”){return “星期三”}
        else if(obj==”Thu”){return “星期四”}
        else if(obj==”Fri”){return “星期五”}
        else if(obj==”Sat”){return “星期六”}
        else{return obj}
}
%>
<table width=”163″ border=”0″ align=”center” cellpadding=”0″ cellspacing=”0″>
  <tr>
    <td rowspan=”6″ align=”center”><%=cityCH%><br />
      <%=weaNum%><br />
      <%=textCH%></td>
    <td align=”right”>感觉:</td>
    <td align=”center”><%=chillV%>&deg;</td>
  </tr>
  <tr style=”background-color:#E6F5FF”>
    <td align=”right”>实际:</td>
    <td align=”center”><%=tempV%>&deg;</td>
  </tr>
  <tr>
    <td align=”right”>风向:</td>
    <td align=”center”><%=windCH%></td>
  </tr>
  <tr style=”background-color:#E6F5FF”>
    <td align=”right”>风速:</td>
    <td align=”center”><%=speedV%>Kph</td>
  </tr>
  <tr>
    <td align=”right”>湿度:</td>
    <td align=”center”><%=humidityV%>%</td>
  </tr>
  <tr style=”background-color:#E6F5FF”>
    <td align=”right”>能见度:</td>
    <td align=”center”><%=visibility%>km</td>
  </tr>
</table>
<table width=”163″ border=”0″ align=”center” cellpadding=”0″ cellspacing=”0″>
  <tr>
    <td colspan=”2″ align=”center” class=”time”><%=lastV%></td>
  </tr>
  <tr>
    <td bgcolor=”#FFFFCC”>曰出:<%=sunriseV%></td>
    <td bgcolor=”#FFCC00″>曰落:<%=sunsetV%></td>
  </tr>
</table>
<table width=”163″ border=”0″ align=”center” cellpadding=”0″ cellspacing=”0″>
  <tr>
<%
for(var i=0; i<2; i++){

        var dayV=attri(forecastNode,i,”day”)
        var dateV=attri(forecastNode,i,”date”)
        var lowV=attri(forecastNode,i,”low”)
        var highV=attri(forecastNode,i,”high”)
        var texttV=attri(forecastNode,i,”text”)
        var codetV=attri(forecastNode,i,”code”)
        var dayCH=dayEn(dayV)
        var texttCH=tEN2CH(texttV)
        var weabmp=weaimg(codetV)
        //var weatNum=weaimg(codetV)
%>
                <td align=”center”><%=dayCH%><br /><%=weabmp%><br /><%=texttCH%><br />最高<%=highV%>&deg;<br />最低<%=lowV%>&deg;</td>
<%
}
%>
</tr>
</table> 






































































































































































 

要想自己加天气的话,在

<option value=”CHXX0097″>南昌</option> 

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/122329.html

(0)
上一篇 2025-10-17 14:33
下一篇 2025-10-17 15:00

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信