【编者按】:Node.js从2009年诞生至今,已经发展了两年有余,其成长的速度有目共睹。从在github的访问量超过Rails,到去年底Node.jsS创始人Ryan Dalh加盟Joyent获得企业资助,再到今年发布Windows移植版本,Node.js的前景获得了技术社区的肯定。InfoQ一直在关注Node.js的发展,在今年的两次Qcon大会(北京站和杭州站)都有专门的讲座。为了更好地促进Node.js在国内的技术推广,我们决定开设“深入浅出Node.js”专栏,邀请来自Node.js领域的布道师、开发人员、技术专家来讲述Node.js的各方面内容,让读者对Node.js有更深入的了解,并且能够积极投入到新技术的讨论和实践中。 专栏的第一篇文章《什么是Node.js》尝试从各个角度来阐述Node.js的基本概念、发展历史、优势等,对该领域不熟悉的开发人员可以通过本文了解Node.js的一些基础知识。 从名字说起 有关Node.js的技术报道越来越多,Node.js的写法也是五花八门,有写成NodeJS的,有写成Nodejs的,到底哪一种写法最标准呢,我们不妨遵循官方的说法。在Node.js的官方网站上,一直将其项目称之为”Node“或者”Node.js“,没有发现其他的说法,”Node“用的最多,考虑到Node这个单词的意思和用途太广泛,容易让开发人员误解,我们采用了第二种称呼——”Node.js“,js的后缀点出了Node项目的本意,其他的名称五花八门,没有确切的出处,我们不推荐使用。 Node.js不是JS应用、而是JS运行平台 看到Node.js这个名字,初学者可能会误以为这是一个Javascript应用,事实上,Node.js采用C++语言编写而成,是一个Javascript的运行环境。为什么采用C++语言呢?据Node.js创始人Ryan Dahl回忆,他最初希望采用Ruby来写Node.js,但是后来发现Ruby虚拟机的性能不能满足他的要求,后来他尝试采用V8引擎,所以选择了C++语言。既然不是Javascript应用,为何叫.js呢?因为Node.js是一个Javascript的运行环境。提到Javascript,大家首先想到的是日常使用的浏览器,现代浏览器包含了各种组件,包括渲染引擎、Javascript引擎等,其中Javascript引擎负责解释执行网页中的Javascript代码。作为Web前端最重要的语言之一,Javascript一直是前端工程师的专利。不过,Node.js是一个后端的Javascript运行环境(支持的系统包括*nux、Windows),这意味着你可以编写系统级或者服务器端的Javascript代码,交给Node.js来解释执行,简单的命令类似于:
1 |
#node helloworld.js |
Node.js采用了Google Chrome浏览器的V8引擎,性能很好,同时还提供了很多系统级的API,如文件操作、网络编程等。浏览器端的Javascript代码在运行时会受到各种安全性的限制,对客户系统的操作有限。相比之下,Node.js则是一个全面的后台运行时,为Javascript提供了其他语言能够实现的许多功能。 Node.js采用事件驱动、异步编程,为网络服务而设计 事件驱动这个词并不陌生,在某些传统语言的网络编程中,我们会用到回调函数,比如当socket资源达到某种状态时,注册的回调函数就会执行。Node.js的设计思想中以事件驱动为核心,它提供的绝大多数API都是基于事件的、异步的风格。以Net模块为例,其中的net.Socket对象就有以下事件:connect、data、end、timeout、drain、error、close等,使用Node.js的开发人员需要根据自己的业务逻辑注册相应的回调函数。这些回调函数都是异步执行的,这意味着虽然在代码结构中,这些函数看似是依次注册的,但是它们并不依赖于自身出现的顺序,而是等待相应的事件触发。事件驱动、异步编程的设计(感兴趣的读者可以查阅笔者的另一篇文章《Node.js的异步编程风格》),重要的优势在于,充分利用了系统资源,执行代码无须阻塞等待某种操作完成,有限的资源可以用于其他的任务。此类设计非常适合于后端的网络服务编程,Node.js的目标也在于此。在服务器开发中,并发的请求处理是个大问题,阻塞式的函数会导致资源浪费和时间延迟。通过事件注册、异步函数,开发人员可以提高资源的利用率,性能也会改善。 从Node.js提供的支持模块中,我们可以看到包括文件操作在内的许多函数都是异步执行的,这和传统语言存在区别,而且为了方便服务器开发,Node.js的网络模块特别多,包括HTTP、DNS、NET、UDP、HTTPS、TLS等,开发人员可以在此基础上快速构建Web服务器。以简单的helloworld.js为例:
1 2 3 4 5 |
var http = require('http'); http.createServer(function (req, res) { res.writeHead(200, {'Content-Type': 'text/plain'}); res.end('Hello World\n'); }).listen(80, "127.0.0.1"); |
上面的代码搭建了一个简单的http服务器(运行示例部署在http://helloworld.cnodejs.net/中,读者可以访问),在本地监听80端口,对于任意的http请求,服务器都返回一个头部状态码为200、Content-Type'值为text/plain'的”Hello World“文字响应。从这个小例子中,我们可以看出几点: Node.js的网络编程比较便利,提供的模块(在这里是http)开放了容易上手的API接口,短短几行代码就可以构建服务器。 体现了事件驱动、异步编程,在createServer函数的参数中指定了一个回调函数(采用Javascript的匿名函数实现),当有http请求发送过来时,Node.js就会调用该回调函数来处理请求并响应。当然,这个例子相对简单,没有太多的事件注册,在以后的文章中读者会看到更多的实际例子。 Node.js的特点 下面我们来说说Node.js的特点。事件驱动、异步编程的特点刚才已经详细说过了,这里不再重复。 Node.js的性能不错。按照创始人Ryan Dahl的说法,性能是Node.js考虑的重要因素,选择C++和V8而不是Ruby或者其他的虚拟机也是基于性能的目的。Node.js在设计上也是比较大胆,它以单进程、单线程模式运行(很吃惊,对吧?这和Javascript的运行方式一致),事件驱动机制是Node.js通过内部单线程高效率地维护事件循环队列来实现的,没有多线程的资源占用和上下文切换,这意味着面对大规模的http请求,Node.js凭借事件驱动搞定一切,习惯了传统语言的网络服务开发人员可能对多线程并发和协作非常熟悉,但是面对Node.js,我们需要接受和理解它的特点。由此我们是否可以推测出这样的设计会导致负载的压力集中在CPU(事件循环处理?)而不是内存(还记得Java虚拟机抛出OutOfMemory异常的日子吗?),眼见为实,不如来看看淘宝共享数据平台团队对Node.js的性能测试: 物理机配置:RHEL 5.2、CPU 2.2GHz、内存4G Node.js应用场景:MemCache代理,每次取100字节数据 连接池大小:50 并发用户数:100 测试结果(socket模式):内存(30M)、QPS(16700)、CPU(95%) 从上面的结果,我们可以看到在这样的测试场景下,qps能够达到16700次,内存仅占用30M(其中V8堆占用22M),CPU则达到95%,可能成为瓶颈。此外,还有不少实践者对Node.js做了性能分析,总的来说,它的性能让人信服,也是受欢迎的重要原因。既然Node.js采用单进程、单线程模式,那么在如今多核硬件流行的环境中,单核性能出色的Node.js如何利用多核CPU呢?创始人Ryan Dahl建议,运行多个Node.js进程,利用某些通信机制来协调各项任务。目前,已经有不少第三方的Node.js多进程支持模块发布,专栏后面的文章会详细讲述Node.js在多核CPU下的编程。 Node.js的另一个特点是它支持的编程语言是Javascript。关于动态语言和静态语言的优缺点比较在这里不再展开讨论。只说三点: Javascript作为前端工程师的主力语言,在技术社区中有相当的号召力。而且,随着Web技术的不断发展,特别是前端的重要性增加,不少前端工程师开始试水”后台应用“,在许多采用Node.js的企业中,工程师都表示因为习惯了Javascript,所以选择Node.js。 Javascript的匿名函数和闭包特性非常适合事件驱动、异步编程,从helloworld例子中我们可以看到回调函数采用了匿名函数的形式来实现,很方便。闭包的作用则更大,看下面的代码示例:
1 2 3 4 5 6 7 8 9 10 |
var hostRequest = http.request(requestOptions,function(response) { var responseHTML =''; response.on('data', function (chunk) { responseHTML = responseHTML + chunk; }); response.on('end',function(){ console.log(responseHTML); // do something useful }); }); |
在上面的代码中,我们需要在end事件中处理responseHTML变量,由于Javascript的闭包特性,我们可以在两个回调函数之外定义responseHTML变量,然后在data事件对应的回调函数中不断修改其值,并最终在end事件中访问处理。 Javascript在动态语言中性能较好,有开发人员对Javacript、Python、Ruby等动态语言做了性能分析,发现Javascript的性能要好于其他语言,再加上V8引擎也是同类的佼佼者,所以Node.js的性能也受益其中。 Node.js发展简史 2009年2月,Ryan Dahl在博客上宣布准备基于V8创建一个轻量级的Web服务器并提供一套库。 2009年5月,Ryan Dahl在GitHub上发布了最初版本的部分Node.js包,随后几个月里,有人开始使用Node.js开发应用。 2009年11月和2010年4月,两届JSConf大会都安排了Node.js的讲座。 2010年年底,Node.js获得云计算服务商Joyent资助,创始人Ryan Dahl加入Joyent全职负责Node.js的发展。 2011年7月,Node.js在微软的支持下发布Windows版本。 Node.js应用案例 虽然Node.js诞生刚刚两年多,但是其发展势头逐渐赶超Ruby/Rails,我们在这里列举了部分企业应用Node.js的案例,听听来自客户的声音。 在社交网站LinkedIn最新发布的移动应用中,NodeJS是该移动应用的后台基础。LinkedIn移动开发主管Kiran Prasad对媒体表示,其整个移动软件平台都由NodeJS构建而成: LinkedIn内部使用了大量的技术,但是在移动服务器这一块,我们完全基于Node。 (使用它的原因)第一,是因为其灵活性。第二,如果你了解Node,就会发现它最擅长的事情是与其他服务通信。移动应用必须与我们的平台API和数据库交互。我们没有做太多数据分析。相比之前采用的Ruby on Rails技术,开发团队发现Node在性能方面提高很多。他们在每台物理机上跑了15个虚拟服务器(15个实例),其中4个实例即可处理双倍流量。容量评估基于负载测试的结果。 企业社会化服务网站Yammer则利用Node创建了针对其自身平台的跨域代理服务器,第三方的开发人员可以通过该服务器实现从自身域托管的Javascript代码与Yammer平台API的AJAX通信。Yammer平台技术主管Jim Patterson对Node的优点和缺点提出了自己的看法: (优点)因为Node是基于事件驱动和无阻塞的,所以非常适合处理并发请求,因此构建在Node上的代理服务器相比其他技术实现(如Ruby)的服务器表现要好得多。此外,与Node代理服务器交互的客户端代码是由javascript语言编写的,因此客户端和服务器端都用同一种语言编写,这是非常美妙的事情。 (缺点)Node是一个相对新的开源项目,所以不太稳定,它总是一直在变,而且缺少足够多的第三方库支持。看起来,就像是Ruby/Rails当年的样子。 知名项目托管网站GitHub也尝试了Node应用。该Node应用称为NodeLoad,是一个存档下载服务器(每当你下载某个存储分支的tarball或者zip文件时就会用到它)。GitHub之前的存档下载服务器采用Ruby编写。在旧系统中,下载存档的请求会创建一个Resque任务。该任务实际上在存档服务器上运行一个git archive命令,从某个文件服务器中取出数据。然后,初始的请求分配给你一个小型Ruby Sinatra应用等待该任务。它其实只是在检查memcache flag是否存在,然后再重定向到最终的下载地址上。旧系统运行大约3个Sinatra实例和3个Resque worker。GitHub的开发人员觉得这是Node应用的好机会。Node基于事件驱动,相比Ruby的阻塞模型,Node能够更好地处理git存档。在编写新下载服务器过程中,开发人员觉得Node非常适合该功能,此外,他们还里利用了Node库socket.io来监控下载状态。 不仅在国外,Node的优点也同样吸引了国内开发人员的注意,淘宝就实际应用了Node技术: MyFOX 是一个数据处理中间件,负责从一个MySQL集群中提取数据、计算并输出统计结果。用户提交一段SQL语句,MyFOX根据该SQL命令的语义,生成各个数据库分片所需要执行的查询语句,并发送至各个分片,再将结果进行汇总和计算。 MyFOX的特点是CPU密集,无文件IO,并只处理只读数据。起初MyFOX使用PHP编写,但遇到许多问题。例如PHP是单线程的,MySQL又需要阻塞查询,因此很难并发请求数据,后来的解决方案是使用nginx和dirzzle,并基于HTTP协议实现接口,并通过curl_multi_get命 令进行请求。不过MyFOX项目组最终还是决定使用Node.js来实现MyFOX。 选择Node.js有许多方面的原因,比如考虑了兴趣及社区发展,同时也希望可以提高并发能力,榨干CPU。例如,频繁地打开和关闭连接会让大量端口处于等待状态,当并发数量上去之后,时常会因为端口不够用(处于TIME_WAIT状态)而导致连接失败。之前往往是通过修改系统设置来减少等待时间以绕开这个错误,然而使用连接池便可以很好地解决这个问题。此外,以前MyFOX会在某些缓存失效的情况下出现十分密集的访问压力,使用 Node.js便可以共享查询状态,让某些请求“等待片刻”,以便系统重新填充缓存内容。 小结 本文简要介绍了Node.js的基本知识,包括概念、特点、历史、案例等等。作为一个仅仅2岁的平台,Node.js的发展势头有目共睹,越来越多的企业开始关注并尝试Node.js,前后端开发人员应该了解相关的内容。 参考文献 [1] http://nodejs.org/ [2] http://beakkon.com/geek/node.js/why-node.js-single-thread-event-loop-javascript [3] http://www.tbdata.org/archives/1285 [4] http://www.infoq.com/interviews/node-ryan-dahl [5] http://www.infoq.com/cn/news/2011/08/enterprise-nodejs [6] http://www.infoq.com/cn/news/2010/11/nodejs-joyent [7] http://www.infoq.com/cn/news/2011/06/node-exe […]
View Detailsnodejs win下没有npm功能,应用各种库文件相当杯具,这里用了node-mongodb-native在win下操作mongodb,小D很菜,对nodejs各种不懂,勉强简单封装了个对mongodb的curd操作,,,, 首先去下载https://github.com/christkv/node-mongodb-native,把文件lib下的东西放到了如下目录 如何操作看他的文档吧,e文不行的估计看例子也能看个大概….下面是封装代码mghp.js
1 |
<span style="line-height:1.5;color:#0000ff;">var</span><span style="line-height:1.5;color:#000000;"> mongodb </span><span style="line-height:1.5;color:#000000;">=</span><span style="line-height:1.5;color:#000000;"> require(</span><span style="line-height:1.5;color:#000000;">'</span><span style="line-height:1.5;color:#000000;">./refLib/mongodb</span><span style="line-height:1.5;color:#000000;">'</span><span style="line-height:1.5;color:#000000;">);<br /><br /></span><span style="line-height:1.5;color:#0000ff;">var</span><span style="line-height:1.5;color:#000000;"> _server </span><span style="line-height:1.5;color:#000000;">=</span><span style="line-height:1.5;color:#000000;"></span><span style="line-height:1.5;color:#0000ff;">function</span><span style="line-height:1.5;color:#000000;">(mongoCollection, mongoDB) {<br /></span><span style="line-height:1.5;color:#0000ff;">var</span><span style="line-height:1.5;color:#000000;"> sv </span><span style="line-height:1.5;color:#000000;">=</span><span style="line-height:1.5;color:#000000;"></span><span style="line-height:1.5;color:#0000ff;">new</span><span style="line-height:1.5;color:#000000;"> mongodb.Server(</span><span style="line-height:1.5;color:#000000;">'</span><span style="line-height:1.5;color:#000000;">127.0.0.1</span><span style="line-height:1.5;color:#000000;">'</span><span style="line-height:1.5;color:#000000;">, </span><span style="line-height:1.5;color:#000000;">27017</span><span style="line-height:1.5;color:#000000;">, {});<br /></span><span style="line-height:1.5;color:#0000ff;">this</span><span style="line-height:1.5;color:#000000;">.mongoCollection </span><span style="line-height:1.5;color:#000000;">=</span><span style="line-height:1.5;color:#000000;"> mongoCollection </span><span style="line-height:1.5;color:#000000;">||</span><span style="line-height:1.5;color:#000000;"></span><span style="line-height:1.5;color:#000000;">'</span><span style="line-height:1.5;color:#000000;">nodeCollection</span><span style="line-height:1.5;color:#000000;">'</span><span style="line-height:1.5;color:#000000;">;<br /></span><span style="line-height:1.5;color:#0000ff;">this</span><span style="line-height:1.5;color:#000000;">.mongoDB </span><span style="line-height:1.5;color:#000000;">=</span><span style="line-height:1.5;color:#000000;"> mongoDB </span><span style="line-height:1.5;color:#000000;">||</span><span style="line-height:1.5;color:#000000;"></span><span style="line-height:1.5;color:#000000;">'</span><span style="line-height:1.5;color:#000000;">nodeDB</span><span style="line-height:1.5;color:#000000;">'</span><span style="line-height:1.5;color:#000000;">;<br /></span><span style="line-height:1.5;color:#0000ff;">this</span><span style="line-height:1.5;color:#000000;">.db </span><span style="line-height:1.5;color:#000000;">=</span><span style="line-height:1.5;color:#000000;"></span><span style="line-height:1.5;color:#0000ff;">new</span><span style="line-height:1.5;color:#000000;"> mongodb.Db(</span><span style="line-height:1.5;color:#0000ff;">this</span><span style="line-height:1.5;color:#000000;">.mongoDB, sv, {});<br />}<br /><br />_server.prototype.Open </span><span style="line-height:1.5;color:#000000;">=</span><span style="line-height:1.5;color:#000000;"></span><span style="line-height:1.5;color:#0000ff;">function</span><span style="line-height:1.5;color:#000000;">(callback) {<br /></span><span style="line-height:1.5;color:#0000ff;">var</span><span style="line-height:1.5;color:#000000;"> that </span><span style="line-height:1.5;color:#000000;">=</span><span style="line-height:1.5;color:#000000;"></span><span style="line-height:1.5;color:#0000ff;">this</span><span style="line-height:1.5;color:#000000;">;<br /></span><span style="line-height:1.5;color:#0000ff;">if</span><span style="line-height:1.5;color:#000000;"> (that.db </span><span style="line-height:1.5;color:#000000;">&&</span><span style="line-height:1.5;color:#000000;"> that.db.state </span><span style="line-height:1.5;color:#000000;">==</span><span style="line-height:1.5;color:#000000;"></span><span style="line-height:1.5;color:#000000;">'</span><span style="line-height:1.5;color:#000000;">connected</span><span style="line-height:1.5;color:#000000;">'</span><span style="line-height:1.5;color:#000000;">) {<br /> callback </span><span style="line-height:1.5;color:#000000;">&&</span><span style="line-height:1.5;color:#000000;"> callback();<br /> } </span><span style="line-height:1.5;color:#0000ff;">else</span><span style="line-height:1.5;color:#000000;"> {<br /> that.db.open(</span><span style="line-height:1.5;color:#0000ff;">function</span><span style="line-height:1.5;color:#000000;">(error, client) {<br /></span><span style="line-height:1.5;color:#0000ff;">if</span><span style="line-height:1.5;color:#000000;"> (error) </span><span style="line-height:1.5;color:#0000ff;">throw</span><span style="line-height:1.5;color:#000000;"> error;<br /> that.collection </span><span style="line-height:1.5;color:#000000;">=</span><span style="line-height:1.5;color:#000000;"></span><span style="line-height:1.5;color:#0000ff;">new</span><span style="line-height:1.5;color:#000000;"> mongodb.Collection(client, that.mongoCollection);<br /> callback </span><span style="line-height:1.5;color:#000000;">&&</span><span style="line-height:1.5;color:#000000;"> callback();<br /> });<br /> }<br />}<br /><br />_server.prototype.Close </span><span style="line-height:1.5;color:#000000;">=</span><span style="line-height:1.5;color:#000000;"></span><span style="line-height:1.5;color:#0000ff;">function</span><span style="line-height:1.5;color:#000000;">(isClose) {<br /></span><span style="line-height:1.5;color:#0000ff;">if</span><span style="line-height:1.5;color:#000000;"> (</span><span style="line-height:1.5;color:#000000;">!!</span><span style="line-height:1.5;color:#000000;">isClose </span><span style="line-height:1.5;color:#000000;">&&</span><span style="line-height:1.5;color:#000000;"></span><span style="line-height:1.5;color:#0000ff;">this</span><span style="line-height:1.5;color:#000000;">.db) {<br /></span><span style="line-height:1.5;color:#0000ff;">this</span><span style="line-height:1.5;color:#000000;">.db.close();<br /></span><span style="line-height:1.5;color:#0000ff;">this</span><span style="line-height:1.5;color:#000000;">.collection </span><span style="line-height:1.5;color:#000000;">=</span><span style="line-height:1.5;color:#000000;"></span><span style="line-height:1.5;color:#0000ff;">null</span><span style="line-height:1.5;color:#000000;">;<br /></span><span style="line-height:1.5;color:#0000ff;">this</span><span style="line-height:1.5;color:#000000;">.db </span><span style="line-height:1.5;color:#000000;">=</span><span style="line-height:1.5;color:#000000;"></span><span style="line-height:1.5;color:#0000ff;">null</span><span style="line-height:1.5;color:#000000;">;<br /> }<br />}<br /><br />_server.prototype.Insert </span><span style="line-height:1.5;color:#000000;">=</span><span style="line-height:1.5;color:#000000;"></span><span style="line-height:1.5;color:#0000ff;">function</span><span style="line-height:1.5;color:#000000;">(obj, func, isClose) {<br /></span><span style="line-height:1.5;color:#0000ff;">var</span><span style="line-height:1.5;color:#000000;"> that </span><span style="line-height:1.5;color:#000000;">=</span><span style="line-height:1.5;color:#000000;"></span><span style="line-height:1.5;color:#0000ff;">this</span><span style="line-height:1.5;color:#000000;">;<br /> that.Open(</span><span style="line-height:1.5;color:#0000ff;">function</span><span style="line-height:1.5;color:#000000;">() {<br /> that.collection.insert(obj, { safe: </span><span style="line-height:1.5;color:#0000ff;">true</span><span style="line-height:1.5;color:#000000;"> }, </span><span style="line-height:1.5;color:#0000ff;">function</span><span style="line-height:1.5;color:#000000;">(err) {<br /> that.Close(isClose);<br /></span><span style="line-height:1.5;color:#0000ff;">if</span><span style="line-height:1.5;color:#000000;"> (err) {<br /> console.warn(err.message);<br /> }<br /></span><span style="line-height:1.5;color:#0000ff;">if</span><span style="line-height:1.5;color:#000000;"> (err </span><span style="line-height:1.5;color:#000000;">&&</span><span style="line-height:1.5;color:#000000;"> err.message.indexOf(</span><span style="line-height:1.5;color:#000000;">'</span><span style="line-height:1.5;color:#000000;">E11000</span><span style="line-height:1.5;color:#000000;">'</span><span style="line-height:1.5;color:#000000;">) </span><span style="line-height:1.5;color:#000000;">!==</span><span style="line-height:1.5;color:#000000;"></span><span style="line-height:1.5;color:#000000;">-</span><span style="line-height:1.5;color:#000000;">1</span><span style="line-height:1.5;color:#000000;">) {<br /></span><span style="line-height:1.5;color:#008000;">//</span><span style="line-height:1.5;color:#008000;">this _id was already inserted in the database</span><span style="line-height:1.5;color:#008000;"><br /></span><span style="line-height:1.5;color:#000000;"> }<br /> func </span><span style="line-height:1.5;color:#000000;">&&</span><span style="line-height:1.5;color:#000000;"> func();<br /> });<br /> });<br />}<br /><br /><br />_server.prototype.Find </span><span style="line-height:1.5;color:#000000;">=</span><span style="line-height:1.5;color:#000000;"></span><span style="line-height:1.5;color:#0000ff;">function</span><span style="line-height:1.5;color:#000000;">(obj, func, isClose) {<br /></span><span style="line-height:1.5;color:#0000ff;">var</span><span style="line-height:1.5;color:#000000;"> that </span><span style="line-height:1.5;color:#000000;">=</span><span style="line-height:1.5;color:#000000;"></span><span style="line-height:1.5;color:#0000ff;">this</span><span style="line-height:1.5;color:#000000;">;<br /> that.Open(</span><span style="line-height:1.5;color:#0000ff;">function</span><span style="line-height:1.5;color:#000000;">() {<br /> that.collection.find(obj, </span><span style="line-height:1.5;color:#0000ff;">function</span><span style="line-height:1.5;color:#000000;">(err, cursor) {<br /> that.Close(isClose);<br /></span><span style="line-height:1.5;color:#0000ff;">if</span><span style="line-height:1.5;color:#000000;"> (err) {<br /> console.warn(err.message);<br /> }<br /> cursor.toArray(</span><span style="line-height:1.5;color:#0000ff;">function</span><span style="line-height:1.5;color:#000000;">(err, items) {<br /> func </span><span style="line-height:1.5;color:#000000;">&&</span><span style="line-height:1.5;color:#000000;"> func(items);<br /> });<br /><br /> });<br /> });<br />}<br /><br />_server.prototype.Update </span><span style="line-height:1.5;color:#000000;">=</span><span style="line-height:1.5;color:#000000;"></span><span style="line-height:1.5;color:#0000ff;">function</span><span style="line-height:1.5;color:#000000;">(obj, objN, func, isClose) {<br /></span><span style="line-height:1.5;color:#0000ff;">var</span><span style="line-height:1.5;color:#000000;"> that </span><span style="line-height:1.5;color:#000000;">=</span><span style="line-height:1.5;color:#000000;"></span><span style="line-height:1.5;color:#0000ff;">this</span><span style="line-height:1.5;color:#000000;">;<br /> that.Open(</span><span style="line-height:1.5;color:#0000ff;">function</span><span style="line-height:1.5;color:#000000;">() {<br /> that.collection.update(obj, { $set: objN }, { safe: </span><span style="line-height:1.5;color:#0000ff;">true</span><span style="line-height:1.5;color:#000000;"> }, </span><span style="line-height:1.5;color:#0000ff;">function</span><span style="line-height:1.5;color:#000000;">(err) {<br /> that.Close(isClose);<br /></span><span style="line-height:1.5;color:#0000ff;">if</span><span style="line-height:1.5;color:#000000;"> (err) {<br /> console.warn(err.message);<br /> }<br /> func </span><span style="line-height:1.5;color:#000000;">&&</span><span style="line-height:1.5;color:#000000;"> func();<br /> });<br /> });<br />}<br /><br />_server.prototype.Remove </span><span style="line-height:1.5;color:#000000;">=</span><span style="line-height:1.5;color:#000000;"></span><span style="line-height:1.5;color:#0000ff;">function</span><span style="line-height:1.5;color:#000000;">(obj, func, isClose) {<br /></span><span style="line-height:1.5;color:#0000ff;">var</span><span style="line-height:1.5;color:#000000;"> that </span><span style="line-height:1.5;color:#000000;">=</span><span style="line-height:1.5;color:#000000;"></span><span style="line-height:1.5;color:#0000ff;">this</span><span style="line-height:1.5;color:#000000;">;<br /> that.Open(</span><span style="line-height:1.5;color:#0000ff;">function</span><span style="line-height:1.5;color:#000000;">() {<br /> that.collection.remove(obj, </span><span style="line-height:1.5;color:#0000ff;">function</span><span style="line-height:1.5;color:#000000;">(err, result) {<br /> that.Close(isClose);<br /></span><span style="line-height:1.5;color:#0000ff;">if</span><span style="line-height:1.5;color:#000000;"> (err) {<br /> console.warn(err.message);<br /> }<br /> func </span><span style="line-height:1.5;color:#000000;">&&</span><span style="line-height:1.5;color:#000000;"> func(result);<br /> });<br /> });<br />}<br /><br />exports.Server </span><span style="line-height:1.5;color:#000000;">=</span><span style="line-height:1.5;color:#000000;"> _server;</span> |
因为是异步的所以连续操作的话要放在回调函数中,方法还有第三个参数,如果是true则关闭链接 s.Insert({ "ID": "10001", "name": "ygm" }, function() { …. },true); 查看操作结果 转自:http://www.cnblogs.com/ygm125/archive/2011/09/02/2163532.html
View Details
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
//防注入函数 function inject_check($sql_str){ $check = eregi('select|insert|update|delete|\*|\/\*|\'|\.\.\/|\.\/|UNION|into|load_file|outfile',$sql_str); if($check){ page_href("http://".$_SERVER['HTTP_HOST']."/home/sitemap.php"); exit(); }else{ return $sql_str; } } //防跨站攻击 function inject_check2($sql_str){ $check = eregi('javascript|vbscript|expression|applet|meta|xml|blink|link|style|script|embed|object|iframe|frame|frameset|ilayer|layer|bgsound|title|base|onabort|onactivate|onafterprint|onafterupdate|onbeforeactivate|onbeforecopy|onbeforecut|onbeforedeactivate|onbeforeeditfocus|onbeforepaste|onbeforeprint|onbeforeunload|onbeforeupdate|onblur|onbounce|oncellchange|onchange|onclick|oncontextmenu|oncontrolselect|oncopy|oncut|ondataavailable|ondatasetchanged|ondatasetcomplete|ondblclick|ondeactivate|ondrag|ondragend|ondragenter|ondragleave|ondragover|ondragstart|ondrop|onerror|onerrorupdate|onfilterchange|onfinish|onfocus|onfocusin|onfocusout|onhelp|onkeydown|onkeypress|onkeyup|onlayoutcomplete|onload|onlosecapture|onmousedown|onmouseenter|onmouseleave|onmousemove|onmouseout|onmouseover|onmouseup|onmousewheel|onmove|onmoveend|onmovestart|onpaste|onpropertychange|onreadystatechange|onreset|onresize|onresizeend|onresizestart|onrowenter|onrowexit|onrowsdelete|onrowsinserted|onscroll|onselect|onselectionchange|onselectstart|onstart|onstop|onsubmit|onunload',$sql_str); if($check){ page_href("http://".$_SERVER['HTTP_HOST']."/home/sitemap.php"); exit(); }else{ //return $sql_str; } } |
转自:http://www.oschina.net/code/snippet_875961_22517
View Details最近的译文距今已有4年之久,原文有一定的更新。今天踩着前辈们的肩膀,再次把这篇文章翻译整理下。一来让自己对web缓存的理解更深刻些,二来让大家注意力稍稍转移下,不要整天HTML5, 面试题啊叨啊叨的~~ 什么是Web缓存,为什么要使用它? Web缓存游走于服务器和客户端之间。这个服务器可能是源服务器(资源所驻留的服务器Add),数量可能是1个或多个;这个客户端也可能是1个或多个。Web缓存就在服务器-客户端之间搞监控,监控请求,并且把请求输出的内容(例如html页面、 图片和文件)(统称为副本)另存一份;然后,如果下一个请求是相同的URL,则直接请求保存的副本,而不是再次麻烦源服务器。 使用缓存的2个主要原因: 降低延迟:缓存离客户端更近,因此,从缓存请求内容比从源服务器所用时间更少,呈现速度更快,网站就显得更灵敏。 降低网络传输:副本被重复使用,大大降低了用户的带宽使用,其实也是一种变相的省钱(如果流量要付费的话),同时保证了带宽请求在一个低水平上,更容易维护了。 Web缓存的类型 1. 浏览器缓存在任何现代浏览器上(如IE, FireFox, Chrome)折腾清除隐私数据(//zxx: 原文说的是首选项,显然out了,这里有改动)的对话框,你很可能会注意到“缓存”这个设置项。 浏览器会在你的硬盘上专门开辟一个空间专门为你存储资源副本。浏览器缓存的工作规则很简单:检查以确保副本是最新的,通常只要一次会话(就是当前浏览器调用的这次N)。 浏览器缓存在用户触发“后退”操作或点击一个之前看过的链接的时候很管用。同样,如果你在网站上访问同一张图片,该图片可以从浏览器缓存中调出并几乎立即显现出来。 2. 代理服务器缓存Web代理服务器使用同样的缓存原理,只是规模更大。代理以同样的方式服务千万用户,大公司和ISP(Internet Server Provider, Internet服务提供商Add)经常在他们的防火墙或者单独的设备(也被称为中介(intermediaries))上架设代理缓存。 由于代理服务器缓存并非客户端或者源服务器的一部分,而是处于网络中,请求需要以某种方式路由到它们。一种方法是手动设置,告诉浏览器的你常用的代理服务器(//zxx: 翻墙的时候常用的),另外就是使用拦截。拦截代理(Interception proxies)把Web请求根据自己的底层网络重定向,因此,客户端无需配置,甚至都不需要知道它们。//zxx: 维基百科上提供的几种检测拦截代理服务器存在的方法add,您若有兴趣,可以点击这里查看。 代理缓存属于一种共享缓存;往往有大量的用户使用,因此,其在降低延时和网络流量上很有用,毕竟每个副本都被大量重用。//zxx: 这里我有疑问:就算是放在代理服务器上,每次获取还是要通过网络的啊,如何降低了网络流量呢?希望谁可以帮忙解惑下。 3. 网关缓存也被称为“反向代理缓存”或“替代缓存”。网关缓存同样是起中介作用的,不过不是(素不相识、不曾谋面的Add)网络管理员部署的,而多半是网站管理员(公司专门的运维工程师、或UED或程序组某人Add)他们自己部署,这样更容易扩展与维护。 可以有多种方法把请求路由到网关缓存,但通常使用某种形式的负载均衡器①,使它们中的一个或多个看起来像是源服务器。内容分发网络②(CDNs)为整个网络(或部分)分配网关缓存,然后把这些缓存卖给需要的网站。Speedera③和Akamai④就是代表性的网络内容发布商。 ①负载均衡器:是一种采用各种分配算法把网络请求分散到一个服务器集群中的可用服务器上去,通过管理进入的Web数据流量和增加有效的网络带宽,从而使网络访问者获得尽可能最佳的联网体验的硬件设备。 ②内容分发网络:即CDN, 基本思路是尽可能避开互联网上有可能影响数据传输速度和稳定性的瓶颈和环节,使内容传输的更快、更稳定。通过在网络各处放置节点服务器所构成的在现有的互 联网基础之上的一层智能虚拟网络,CDN系统能够实时地根据网络流量和各节点的连接、负载状况以及到用户的距离和响应时间等综合信息将用户的请求重新导向 离用户最近的服务节点上。其目的是使用户可就近取得所需内容,解决 Internet网络拥挤的状况,提高用户访问网站的响应速度。 ③Speedera:是一家全球性的内容服务提供商,它与北美、欧洲以及亚太地区的1000多家大型运营商都有联系,并为那些不想在自己服务器上寄存内容的公司提供软件下载、媒体及其它服务管理等业务。05年的时候被下面要介绍的Akamai以$130m的价格给收购了。 ④Akamai:美国Akamai是国际上最大的CDN服务商,它巨大的网络分发能力在峰值时可达到15Tbps。 Akamai公司是为数不多的旨在消除Internet瓶颈和提高下载速度的几家新公司之一,是一个致力于网络交通提速的”内容发布”公司,是波士顿高技 术区最卓越的新兴企业之一。Akamai公司向全球企业提供发送互联网内容,汇流媒体和应用程序的服务(目前,该公司为15个国家的企业管理着8000多 台服务器)。1998年,丹尼尔。L和麻省理工学院的一些研究人员一起创立了这家公司,他在麻省理工学院的硕士论文构成了Akamai公司最初的”自由 流”(Freeflow)技术的核心。 本教程重点在浏览器和代理缓存,尽管有些信息对网关缓存感兴趣的人也适用。 Web缓存无害吗?为什么要鼓励缓存? Web缓存是互联网中最容易被误解的技术之一。网站管理员特别希望知道网站的一举一动,比方说多少人访问啦,访问时间啊什么的,而缓存会“隐藏”他们的用户,他们就无从得知到底谁访问了这个站点。 捡了芝麻丢西瓜,自认为放弃缓存可以精确跟踪用户,实际上,互联网中有太多的变数,想精确得到一张用户查看网站的图片?没那么简单的,亲!如果你很重视这个问题,恭喜你,本文正好提供了解决之道,即保证缓存友好,同时又能获得统计。 另外需要注意的是,缓存的内容都是旧的过时的。因此,如何准确更新就成了一个问题。不过不要担心,本文会向你展示如何配置服务器,让缓存就像你的女仆——随便调教。 CDN算是个挺有意思的技术,不同于代理缓存,CDN的网关缓存和被缓存的Web站点的利益是一致的,因此,上面提到的问题对于CDN而言是没有的。不过,即使你使用了CDN,你仍要顾虑下游的代理和浏览器缓存。 以上为缓存可能的“糟粕”,那他好的地方呢?缓存可以让你的Web站点加载更快,让你的服务器和互联网链接间负担更小。这种差异会导致一些类似质的 变化,一个网站要几秒钟才能加载出来,而另外一个充分发挥缓存的优势,几乎瞬间显示。用户自然更喜欢那个加载迅速的站点,访问也更多。 再说个现实示例,许多大型互联网公司花费了数百万美元,在世界各地设立服务器集群来复制他们的内容,以使其尽可能快被他们的用户访问。缓存为你做同样的事情,而且他们更接近最终用户。最重要的是,你不要花银子。 实际上呢,无论你喜欢与否,代理和浏览器缓存都会被使用。如果你站点的缓存配置不正确,你只能听天由命了。 Web缓存如何工作 所以的缓存都有一套自己的规则,可以用来决定何时跟缓存暧昧往来。其中部分规则设定在协议中(HTTP 1.0 以及 1.1),部分由缓存管理员⑤设置。 ⑤缓存管理员:如果指的是浏览器缓存,则有可能就是我们服务器专家同事,在服务器上配置一些缓存规则;如果是代理缓存,则指的就是处理代理服务器这块的管理人员。 一般而言有如下常用规则N: 响应头明确说明,偶不想被缓存,则不会被缓存; 如果请求信息是需要认证或者安全加密的(如, HTTPS),相应内容也不会被缓存; 缓存如果有以下表现,则认为是fresh新鲜的(无需检查源服务器,直接发送给客户端): 含有完整的过期时间和寿命控制头信息,并且内容仍在保鲜期内,或者 缓存最近已展现,并且在不久前修改。 则内容缓存直取,绕过源服务器。 若内容陈旧,则会要求源服务器做验证 validate ,或者告诉缓存其拷贝副本是否是OK的。 特定情况下——例如,断网了,之前有过的响应缓存直取而不检查源服务器。 响应如果没有类似ETag或Last-Modified头这样的校验器,也没有明确的更新信息,通常(并不绝对)认为是不可缓存的。 总而言之,新鲜度freshness和校验validation是确定缓存内容是否可用的最重要途径。如果要展示的足够新,直接缓存取;如果检测发现展示内容并未变化,则不会再来一次完整的传输。 如何控制缓存和不缓存 有很多工具可以帮助设计师和网站管理员调整服务器缓存网站的方式,这也许需要你亲自动手对服务器的配置进行一些调整,但绝对值得。了解如何使用这些工具请参考本文后面的章节。 HTML Meta标签 vs. HTTP头信息HTML重构人员可以在文档的<head>中添加标签进行描述。这些meta标签通常用来标记不可缓存或过期时间。 Meta标签使用简单,但效果一般。因为只被少数几个浏览器宠幸,而代理缓存基本上就不访问HTML文档。尽管我们可以在页面上试图添加no-cache meta标签让页面一直是最新的,但其实没必要。 如果你的网站托管在ISP或者主机托管商那里,并且他们没有赋予您任意设置HTTP头信息的能力(比如Expires和Cache-Control),你要投诉争取,因为在你的工作中这些是必须的。 另外一方面: HTTP头信息可以让你对浏览器和代理服务器如何处理你的副本进行更多的控制。他们在HTML代码中是看不见的, 一般由Web服务器自动生成。但是,根据你使用的服务器,你可以在某种程度上进行控制。在下文中:你将看到一些有趣的HTTP头信息,以及如何在你的站点 上应用部署这些特性。 HTTP头信息发送在HTML代码之前,只能被浏览器和一些中间缓存能看到,一个典型的HTTP 1.1协议返回的头信息看上去像这样:
1 2 3 4 5 6 7 8 9 |
HTTP/1.1 200 OK Date: Fri, 30 Oct 1998 13:19:41 GMT Server: Apache/1.3.3 (Unix) Cache-Control: max-age=3600, must-revalidate Expires: Fri, 30 Oct 1998 14:19:41 GMT Last-Modified: Mon, 29 Jun 1998 02:28:12 GMT ETag: "3e86-410-3596fbbc" Content-Length: 1040 Content-Type: text/html |
[…]
View Details本文不仅适用于图片,同样实用于其它二进制文件。 需要四个类:WebRequest、WebResponse、Stream、FileStream。 WebRequest、WebResponse 的名称空间是: System.Net Stream、FileStream 的名称空间是: System.IO 核心代码 WebRequest request = WebRequest.Create("http://portrait7.sinaimg.cn/1859998982/blog/180.jpg");WebResponse response = request.GetResponse();Stream reader = response.GetResponseStream();FileStream writer = new FileStream("D:\\logo.jpg", FileMode.OpenOrCreate, FileAccess.Write);byte[] buff = new byte[512];int c = 0; //实际读取的字节数while ((c=reader.Read(buff, 0, buff.Length)) > 0){ writer.Write(buff, 0, c);}writer.Close(); 注意类 Stream,不是 StreamReader。 示例 <%@ Page Language="C#" %><%@ Import Namespace="System.Net" %><%@ Import Namespace="System.IO" %><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <script runat="server"> void Page_Load(object sender, EventArgs e) { try { WebRequest request = WebRequest.Create("http://portrait7.sinaimg.cn/1859998982/blog/180.jpg"); WebResponse response = request.GetResponse(); Stream reader = response.GetResponseStream(); FileStream writer = new […]
View DetailsCardKit 是来自豆瓣的一个移动 UI 框架,使用 Card\Unit\Component 概念快速构建移动 Web 应用。应用外观跟原生应用无异。 http://ozjs.org/CardKit 转自:http://www.oschina.net/p/cardkit
View Details远程调试应用场景 部署环境:ASP.NET(C#)+IIS+Win7 64 bit 很多公司的开发模式都是将开发机器和服务器分开,也就是开发一台机,服务器一台机。而测试人员会在服务器上录入测试数据,此时报错了【由于开发程序时忽略了数据类型或者数据是否合法导致的】,如果是简单的错误那还好办,看下代码直接消灭。要是生命力比较顽强的bug,那么就需要调试了。 此时开发人员会产生几种设想: 1、赶紧把服务器的环境部署到本地,然后把生成的dll扔进去进行调试。这时会出现几种结果,如果顺利的话,通过了调试解决了bug,如果不顺利的话,就会延长bug的解决时间。不顺利的情况可能会有:对程序的配置不熟悉,本地可能在注册表缺少了对那个插件的注册,目录可能存在中文……种种的,种种的问题。 2、在服务器上装上一个Visual Studio 2008/2010/2012[后面简称vs工具],然后把程序文件拷过去,然后将生成的文件dll附加到iis进程而进行调试,哈哈,顺利解决了bug,但是一看钟表半天过去了。而且服务器多了很多文件,仅仅是为了你调试这个程序的文件。如果是管理不是很严谨的公司那还说的过去,要不然少不了要被喷一顿。 好吧,不说口水话了,进入正题。 远程调试方法 第一步:将vs工具里的Remote Debugger文件夹拷贝到目标机器。大致的目录应该是:D:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\Remote Debugger,或者从开始菜单那里可以找到它的快捷方式,如下图: 第二步:在服务器上打开Remote Debugger文件夹,如果是32位的就运行X86里面的msvsmon.exe,如果是64位的就运行X64里面的msvsmon.exe。关于32位和64位这里要注意一下,以你的IIS应用程序池为主,在应用程序池那里右键,点击高级设置,可出现以下窗体。如果启用32位应用程序设置为true的话,那么就需要运行X86里面的msvsmon.exe。 运行后会出现以下界面 第三步【最关键一步】:将你本地的账号密码设置成跟服务器一样,因为远程调试也是需要用户凭证的。账号和密码都要一致哦!!! 第四步:用vs工具打开你的程序源码,用快捷键ctrl + alt + p 打开附加进程窗体,如下图 传输:默认 限定符:默认是本机的机器名称,设置为你的服务器IP(如:192.168.1.250) 设置好按回车就可以看到250这台机子的进程,然后找到w3wp.exe这个进程,点击附加。【如果没有看到w3wp.exe,可以把下面显示所有用户的进程勾上】 接下来就尽情享受代码的调试把。 关于调试那点技术 比较一下下面两种调试的方法,看谁犯过第一种,反正我犯过。^_^ 1、为了调试某个dll而直接在Web程序里直接按F5进行调试,如果是小项目小网站的话,那没问题。如果是一个几十M甚至几百M的网站那么问题就来了。这样子的调试非常的慢,而且每次都需要重新生成整个网站的dll,那速度,是可忍孰不可忍。 2、将你需要调试的dll重新生成一下,把dll和pdb文件拷到已发布好的网站bin目录底下,然后ctrl + alt + p附加到IIS进程w3wp.exe,然后就可以调试你的dll了。这样即快又方便,做个开心的程序员吧。 结束语 好久没写过东西了,距离上一篇Installshield有1年多了,哎。以后坚持有空就写点文章,多总结自己的经验。 转自:http://www.cnblogs.com/magicchaiy/archive/2013/05/28/VS%E8%BF%9C%E7%A8%8B%E8%B0%83%E8%AF%95%E6%8A%80%E5%B7%A7.html
View Details在Asp.net MVC中,我们能非常方便的使用Ajax。这篇文章将介绍三种Ajax使用的方式,分别为原始的Ajax调用、Jquery、Ajax Helper。分别采用这三种方式结合asp.net mvc去实现一个史上最简单的留言板。 首先看一下原始的Ajax的调用的 定义CommentController,代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<span style="color:blue;">public class </span><span style="color:#2B91AF;">CommentController </span>: <span style="color:#2B91AF;">Controller</span>{ <span style="color:blue;">private </span><span style="color:#2B91AF;">IList</span><<span style="color:blue;">string</span>> _comments = <span style="color:blue;">new </span><span style="color:#2B91AF;">List</span><<span style="color:blue;">string</span>>(); <span style="color:blue;">public </span><span style="color:#2B91AF;">ActionResult </span>Index() { <span style="color:blue;">return </span>View(); } <span style="color:blue;">public void </span>AddCommentServer() { <span style="color:green;"></span><span style="color:blue;">string </span>comment = Request[<span style="color:#A31515;">"comment"</span>].ToUpper(); _comments.Add(<span style="color:#A31515;">"<li>" </span>+ comment + <span style="color:#A31515;">"</li>"</span>); Response.ContentType = <span style="color:#A31515;">"text/html"</span>; Response.Write(<span style="color:blue;">string</span>.Join(<span style="color:#A31515;">"\n"</span>, _comments.ToArray())); } } |
在Asp.net MVC中添加一个custom_ajax.js,加入下面使用ajax的脚本代码,调用AddCommentServer方法。
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 |
<span style="color:blue;">function </span>getXmlHttpRequest() { <span style="color:blue;">var </span>xhr; <span style="color:#006400;">//check for IE implementation(s) </span><span style="color:blue;">if </span>(<span style="color:blue;">typeof </span>ActiveXObject != <span style="color:maroon;">'undefined'</span>) { <span style="color:blue;">try </span>{ xhr = <span style="color:blue;">new </span>ActiveXObject(<span style="color:maroon;">"Msxml2.XMLHTTP"</span>); } <span style="color:blue;">catch </span>(e) { xhr = <span style="color:blue;">new </span>ActiveXObject(<span style="color:maroon;">"Microsoft.XMLHTTP"</span>); } } <span style="color:blue;">else if </span>(XMLHttpRequest) { <span style="color:#006400;">//this works for Firefox, Safari, Opera </span>xhr = <span style="color:blue;">new </span>XMLHttpRequest(); } <span style="color:blue;">else </span>{ alert(<span style="color:maroon;">"对不起,你的浏览器不支持ajax"</span>); } <span style="color:blue;">return </span>xhr; } <span style="color:blue;">function </span>getMessage() { <span style="color:#006400;">//get our xml http request object </span><span style="color:blue;">var </span>xhr = getXmlHttpRequest(); <span style="color:#006400;">//prepare the request </span>xhr.open(<span style="color:maroon;">"GET"</span>, <span style="color:maroon;">"Comment/AddCommentServer?comment=" </span>+ document.getElementById(<span style="color:maroon;">"Comment"</span>).value, <span style="color:blue;">true</span>) <span style="color:#006400;">//setup the callback function </span>xhr.onreadystatechange = <span style="color:blue;">function</span>() { <span style="color:#006400;">//readyState 4 means we're done </span><span style="color:blue;">if</span>(xhr.readyState != 4) <span style="color:blue;">return</span>; <span style="color:#006400;">//populate the page with the result </span>document.getElementById(<span style="color:maroon;">'comments'</span>).innerHTML = document.getElementById(<span style="color:maroon;">'comments'</span>).innerHTML + xhr.responseText; }; <span style="color:#006400;">//fire our request </span>xhr.send(<span style="color:blue;">null</span>); } |
在View中引入此脚本,创建一个简单的表单,并添加触发的代码:
1 |
<span style="color:blue;"><</span><span style="color:maroon;">asp</span><span style="color:blue;">:</span><span style="color:maroon;">Content </span><span style="color:red;">ID</span><span style="color:blue;">="Content2" </span><span style="color:red;">ContentPlaceHolderID</span><span style="color:blue;">="MainContent" </span><span style="color:red;">runat</span><span style="color:blue;">="server"> <</span><span style="color:maroon;">h4</span><span style="color:blue;">></span>Comments<span style="color:blue;"></</span><span style="color:maroon;">h4</span><span style="color:blue;">> <</span><span style="color:maroon;">ul </span><span style="color:red;">id</span><span style="color:blue;">="comments"> </</span><span style="color:maroon;">ul</span><span style="color:blue;">> </span><span style="background:yellow;"><%</span><span style="color:blue;">= </span>Html.TextArea(<span style="color:#A31515;">"Comment"</span>, <span style="color:blue;">new</span>{rows=5, cols=50}) <span style="background:yellow;">%></span><span style="color:blue;"><</span><span style="color:maroon;">button </span><span style="color:red;">type</span><span style="color:blue;">="submit" </span><span style="color:red;">onclick</span><span style="color:blue;">="getMessage()"></span>Add Comment<span style="color:blue;"></</span><span style="color:maroon;">button</span><span style="color:blue;">> <</span><span style="color:maroon;">span </span><span style="color:red;">id</span><span style="color:blue;">="indicator" </span><span style="color:red;">style</span><span style="color:blue;">="</span><span style="color:red;">display</span><span style="color:blue;">:none"><</span><span style="color:maroon;">img </span><span style="color:red;">src</span><span style="color:blue;">="http://www.cnblogs.com/content/load.gif" </span><span style="color:red;">alt</span><span style="color:blue;">="loading..." /></</span><span style="color:maroon;">span</span><span style="color:blue;">> </</span><span style="color:maroon;">asp</span><span style="color:blue;">:</span><span style="color:maroon;">Content</span><span style="color:blue;">><</span><span style="color:maroon;">asp</span><span style="color:blue;">:</span><span style="color:maroon;">Content </span><span style="color:red;">ID</span><span style="color:blue;">="Content3" </span><span style="color:red;">ContentPlaceHolderID</span><span style="color:blue;">="headContent" </span><span style="color:red;">runat</span><span style="color:blue;">="server"> <</span><span style="color:maroon;">script </span><span style="color:red;">src</span><span style="color:blue;">="http://www.cnblogs.com/Scripts/custom_ajax.js" </span><span style="color:red;">type</span><span style="color:blue;">="text/javascript"></</span><span style="color:maroon;">script</span><span style="color:blue;">></</span><span style="color:maroon;">asp</span><span style="color:blue;">:</span><span style="color:maroon;">Content</span><span style="color:blue;">></span> |
1 |
<span style="color:blue;"><span style="color:#000000;"> 效果如下:</span></span> |
1 |
<pre class="code"><span style="color:blue;"><a href="http://images.cnblogs.com/cnblogs_com/zhuqil/WindowsLiveWriter/Asp.netmvc2Ajax_EBA5/3_2.png"><img width="900" height="321" title="3" style="border-width:0px;display:inline;" alt="3" src="//images.cnblogs.com/cnblogs_com/zhuqil/WindowsLiveWriter/Asp.netmvc2Ajax_EBA5/3_thumb.png" border="0" /></a></span> |
1 |
<span style="color:#000000;"><span style="font-size:24px;"><strong> </strong></span></span> |
1 |
<span style="color:#000000;"><span style="font-size:24px;"><strong> </strong></span></span> |
1 |
<span style="color:#000000;"><span style="font-size:24px;"><strong>第二种方式:利用Jquery:</strong></span></span> |
1 |
<span style="color:#000000;"> 在控制器中添加代码IndexJquery方法和AddComment方法的代码,<span style="color:#2B91AF;">CommentController代码</span>如下所示</span> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
<span style="color:blue;">public class </span><span style="color:#2B91AF;">CommentController </span>: <span style="color:#2B91AF;">Controller</span>{ <span style="color:blue;">private </span><span style="color:#2B91AF;">IList</span><<span style="color:blue;">string</span>> _comments = <span style="color:blue;">new </span><span style="color:#2B91AF;">List</span><<span style="color:blue;">string</span>>(); <span style="color:blue;">public </span><span style="color:#2B91AF;">ActionResult </span>Index() { <span style="color:blue;">return </span>View(); } <span style="color:blue;">public </span><span style="color:#2B91AF;">ActionResult </span>IndexJquery() { <span style="color:blue;">return </span>View(); } <span style="color:blue;">public </span><span style="color:#2B91AF;">ActionResult </span>AddComment(<span style="color:blue;">string </span>comment) { _comments.Add(<span style="color:#A31515;">"<li>" </span>+ comment + <span style="color:#A31515;">"</li>"</span>); <span style="color:blue;">return </span>Content(<span style="color:blue;">string</span>.Join(<span style="color:#A31515;">"\n"</span>, _comments.ToArray())); } <span style="color:blue;">public void </span>AddCommentServer() { |
1 2 3 4 5 6 7 8 9 |
<span style="color:green;"></span><span style="color:blue;">string </span>comment = Request[<span style="color:#A31515;">"comment"</span>].ToUpper(); _comments.Add(<span style="color:#A31515;">"<li>" </span>+ comment + <span style="color:#A31515;">"</li>"</span>); Response.ContentType = <span style="color:#A31515;">"text/html"</span>; Response.Write(<span style="color:blue;">string</span>.Join(<span style="color:#A31515;">"\n"</span>, _comments.ToArray())); } } |
1 |
根据IndexJquery,<span style="color:blue;"><span style="color:#000000;">创建View表单IndexJquery.aspx:</span></span> |
1 |
<span style="color:blue;"><</span><span style="color:maroon;">h4</span><span style="color:blue;">></span>Comments<span style="color:blue;"></</span><span style="color:maroon;">h4</span><span style="color:blue;">> <</span><span style="color:maroon;">ul </span><span style="color:red;">id</span><span style="color:blue;">="comments"> </</span><span style="color:maroon;">ul</span><span style="color:blue;">> </span><span style="background:yellow;"><%</span><span style="color:blue;">using </span>(Html.BeginForm(<span style="color:#A31515;">"AddComment"</span>,<span style="color:#A31515;">"Comment"</span>,<span style="color:#2B91AF;">FormMethod</span>.Post,<span style="color:blue;">new </span>{@class=<span style="color:#A31515;">"hijax"</span>})) { <span style="background:yellow;">%></span><span style="background:yellow;"><%</span><span style="color:blue;">= </span>Html.TextArea(<span style="color:#A31515;">"Comment"</span>, <span style="color:blue;">new</span>{rows=5, cols=50}) <span style="background:yellow;">%></span><span style="color:blue;"><</span><span style="color:maroon;">button </span><span style="color:red;">type</span><span style="color:blue;">="submit"></span>Add Comment<span style="color:blue;"></</span><span style="color:maroon;">button</span><span style="color:blue;">> <</span><span style="color:maroon;">span </span><span style="color:red;">id</span><span style="color:blue;">="indicator" </span><span style="color:red;">style</span><span style="color:blue;">="</span><span style="color:red;">display</span><span style="color:blue;">:none"><</span><span style="color:maroon;">img </span><span style="color:red;">src</span><span style="color:blue;">="http://www.cnblogs.com/content/load.gif" </span><span style="color:red;">alt</span><span style="color:blue;">="loading..." /></</span><span style="color:maroon;">span</span><span style="color:blue;">> </span><span style="background:yellow;"><%</span> } <span style="background:yellow;">%></span> |
1 |
<span style="color:#000000;"> 在View中引用Jquery:</span> |
1 |
<span style="color:blue;"><</span><span style="color:maroon;">script </span><span style="color:red;">src</span><span style="color:blue;">="http://www.cnblogs.com/Scripts/jquery-1.4.1.min.js" </span><span style="color:red;">type</span><span style="color:blue;">="text/javascript"></</span><span style="color:maroon;">script</span><span style="color:blue;">></span> |
添加下面脚本:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
<span style="color:blue;"><</span><span style="color:maroon;">script </span><span style="color:red;">type</span><span style="color:blue;">="text/javascript"> </span><span style="color:#006400;">//execute when the DOM has been loaded </span>$(document).ready(<span style="color:blue;">function </span>() { <span style="color:#006400;">//wire up to the form submit event </span>$(<span style="color:maroon;">"form.hijax"</span>).submit(<span style="color:blue;">function </span>(event) { event.preventDefault(); <span style="color:#006400;">//prevent the actual form post </span>hijack(<span style="color:blue;">this</span>, update_sessions, <span style="color:maroon;">"html"</span>); }); }); <span style="color:blue;">function </span>hijack(form, callback, format) { $(<span style="color:maroon;">"#indicator"</span>).show(); $.ajax({ url: form.action, type: form.method, dataType: format, data: $(form).serialize(), completed: $(<span style="color:maroon;">"#indicator"</span>).hide(), success: callback }); } <span style="color:blue;">function </span>update_sessions(result) { <span style="color:#006400;">//clear the form </span>$(<span style="color:maroon;">"form.hijax"</span>)[0].reset(); $(<span style="color:maroon;">"#comments"</span>).append(result); } <span style="color:blue;"></</span><span style="color:maroon;">script</span><span style="color:blue;">></span> |
1 |
<span style="color:blue;"><span style="color:#000000;"> </span></span> |
1 |
1 |
<span style="color:blue;"><span style="color:#000000;"> </span></span> |
1 |
<pre class="code"><span style="background:yellow;"> </span> |
1 |
<span style="color:blue;"><span style="color:#000000;"> </span></span> |
1 |
<span style="color:blue;"><span style="color:#000000;"><span style="font-size:24px;"><strong> </strong></span></span></span> |
1 |
<span style="color:blue;"><span style="color:#000000;"><span style="font-size:24px;"><strong> </strong></span></span></span> |
效果:与方式一效果一样
1 |
1 |
<span style="color:blue;"><span style="color:#000000;"><span style="font-size:24px;"><strong>第三种方式:Ajax Helper。</strong></span></span></span> |
1 |
<span style="color:blue;"></span> |
1 |
<span style="color:blue;"><span style="color:#000000;"> 将最简单的留言板修改成Ajax Helper的方式。</span></span> |
1、首先了解一下Ajax Helper下面四种方法。 a、Ajax.ActionLink():它将渲染成一个超链接的标签,类似于Html.ActionLink()。当它被点击之后,将获取新的内容并将它插入到HTML页面中。 b、Ajax.BeginForm():它将渲染成一个HTML的Form表单,类似于Html.BeginForm()。当它提交之后,将获取新的内容并将它插入到HTML页面中。 c、Ajax.RouteLink():Ajax.RouteLink()类似于Ajax.ActionLink()。不过它可以根据任意的routing参数生成URL,不必包含调用的action。使用最多的场景是自定义的IController,里面没有action。 d、Ajax.BeginRouteForm():同样Ajax.BeginRouteForm()类似于Ajax.BeginForm()。这个Ajax等同于Html.RouteLink()。 这个例子中使用Ajax.BeginForm(),下面具体了解Ajax.BeginForm()的参数。看下面代码
1 2 3 4 5 |
<span style="background:yellow;"><%</span><span style="color:blue;">using </span>(Ajax.BeginForm(<span style="color:#A31515;">"AddComment"</span>, <span style="color:blue;">new </span><span style="color:#2B91AF;">AjaxOptions </span>{ HttpMethod = <span style="color:#A31515;">"POST"</span>, UpdateTargetId = <span style="color:#A31515;">"comments"</span>, InsertionMode = <span style="color:#2B91AF;">InsertionMode</span>.InsertAfter })) { <span style="background:yellow;">%></span> |
actionName:AddComment(action的名字) controllerName:CommentController(Controller的名字) ajaxOptions: HttpMethod:Ajax的请求方式,这里为POST UpdateTargetId :Ajax请求的结果显示的标签的ID,这里为comments InsertionMode:将Ajax结果插入页面的方式,这里将ajax的结果放置到comments的后面 2、实现: 在CommentController中添加IndexAjaxHelp方法。
1 2 3 4 |
<span style="color:blue;">public </span><span style="color:#2B91AF;">ActionResult </span>IndexAjaxHelp() { <span style="color:blue;">return </span>View(); } |
根据IndexAjaxHelp生成View表单IndexAjaxHelp.aspx,定义表单:
1 2 3 4 5 |
<span style="color:blue;"><</span><span style="color:maroon;">h4</span><span style="color:blue;">></span>Comments<span style="color:blue;"></</span><span style="color:maroon;">h4</span><span style="color:blue;">> <</span><span style="color:maroon;">ul </span><span style="color:red;">id</span><span style="color:blue;">="comments"> </</span><span style="color:maroon;">ul</span><span style="color:blue;">> </span><span style="background:yellow;"><%</span><span style="color:blue;">using </span>(Ajax.BeginForm(<span style="color:#A31515;">"AddComment"</span>, <span style="color:blue;">new </span><span style="color:#2B91AF;">AjaxOptions </span>{ HttpMethod = <span style="color:#A31515;">"POST"</span>, UpdateTargetId = <span style="color:#A31515;">"comments"</span>, InsertionMode = <span style="color:#2B91AF;">InsertionMode</span>.InsertAfter })) { <span style="background:yellow;">%></span><span style="background:yellow;"><%</span><span style="color:blue;">= </span>Html.TextArea(<span style="color:#A31515;">"Comment"</span>, <span style="color:blue;">new</span>{rows=5, cols=50}) <span style="background:yellow;">%></span><span style="color:blue;"><</span><span style="color:maroon;">button </span><span style="color:red;">type</span><span style="color:blue;">="submit"></span>Add Comment<span style="color:blue;"></</span><span style="color:maroon;">button</span><span style="color:blue;">> </span><span style="background:yellow;"><%</span> } <span style="background:yellow;">%></span> |
要在此View中添加下面两个脚本文件:
1 |
<span style="color:blue;"><</span><span style="color:maroon;">script </span><span style="color:red;">src</span><span style="color:blue;">="http://www.cnblogs.com/Scripts/MicrosoftAjax.js" </span><span style="color:red;">type</span><span style="color:blue;">="text/javascript"></</span><span style="color:maroon;">script</span><span style="color:blue;">> <</span><span style="color:maroon;">script </span><span style="color:red;">src</span><span style="color:blue;">="http://www.cnblogs.com/Scripts/MicrosoftMvcAjax.js" </span><span style="color:red;">type</span><span style="color:blue;">="text/javascript"></</span><span style="color:maroon;">script</span><span style="color:blue;">></span> |
1 |
这样就行了,我们发现比用Jquery方便很多,但是使用Jquery将灵活很多。 3、效果:和方式一样。 总结:本文非常的简单,在asp.net mvc中实现了3中ajax的调用方式,实现了一个最简单的留言板程序。推荐使用Jquery和Ajax Helper这两种。Ajax Helper使用非常简单,Jquery比较灵活。 更新:三种方式都实现了一个最简单的留言板程序 参考: ASP.NET MVC 2 In Action Pro ASP.NET MVC 2 Framework, Second Edition 代码:http://files.cnblogs.com/zhuqil/AjaxDemo.rar 作者:朱祁林出处:http://zhuqil.cnblogs.com本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
View Details
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 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
/// <summary> /// 生成缩略图 /// </summary> /// <param name="imgPath">源图片路径</param> /// <param name="thumbnailPath">缩略图保存路径</param> /// <param name="newWidth">新宽度</param> /// <param name="newHeight">新高度</param> /// <param name="addSpace">是否添加空白</param> /// <returns></returns> public static void Thumbnail(string imgPath, string thumbnailPath, int newWidth, int newHeight, bool addSpace) { int sW, sH; // 按比例缩放 var imgSource = Image.FromFile(imgPath); var sWidth = imgSource.Width; var sHeight = imgSource.Height; if (sHeight > newHeight || sWidth > newWidth) { if ((sWidth * newHeight) > (sHeight * newWidth)) { sW = newWidth; sH = (newWidth * sHeight) / sWidth; } else { sH = newHeight; sW = (sWidth * newHeight) / sHeight; } } else { sW = sWidth; sH = sHeight; } var outBmp = addSpace ? new Bitmap(newWidth, newHeight) : new Bitmap(sW, sH); var x = 0; var y = 0; if (addSpace) { var whRate = newWidth > newHeight ? true : false; //宽是否大于高(新尺寸) x = whRate ? (newWidth - sW) / 2 : x; y = whRate ? (newHeight - sH) / 2 : y; } var g = Graphics.FromImage(outBmp); // 设置画布的描绘质量 g.CompositingQuality = CompositingQuality.HighQuality; g.SmoothingMode = SmoothingMode.HighQuality; g.InterpolationMode = InterpolationMode.HighQualityBicubic; g.DrawImage(imgSource, new Rectangle(x, y, sW, sH), new Rectangle(0, 0, imgSource.Width, imgSource.Height), GraphicsUnit.Pixel); g.Dispose(); try { //保存图片 outBmp.Save(thumbnailPath, ImageFormat.Jpeg); } finally { imgSource.Dispose(); g.Dispose(); outBmp.Dispose(); } } |
我们使用的是哪个 PHP 版本? 带有 Suhosin-补丁的PHP 5.3.10-1ubuntu3.6, 安装于 Ubuntu 12.04 LTS. PHP如同是网络世界的百年老龟。它的外壳上刻有一个丰富的,令人费解的,粗糙的历史。在一个共享主机的环境下,它的配置可能会限制你能做什么事情。 为了保留一丝明智,我们需要只专注于一个版本的PHP。截至2013年4月30,该版本是 带有Suhosin补丁的PHP5.3.10-1ubuntu3.6 。如果你使用apt-get从一个Ubuntu12.04 LTS服务器来安装PHP的话,你所得到的版本就是这个。换句话说,许多人在默认情况下已经很明智地使用了它。 您可能会发现本文这些解决方案能工作于不同或更旧版本的PHP。如果是这样的话,就要由你来研究在这些旧版本中的细微错误或安全问题的影响了。 保存密码 使用 phpass 库计算密码的哈希值进行比较。 用 phpass 0.3 进行的测试。 散列化是在把用户密码保存进数据库之前对其进行保护的标准方法。许多常见的散列算法,如MD5,乃至SHA1,用于存储密码都是不安全的,因为黑客可以使用这些散列算法轻松破解密码。 要散列化密码最安全的方法是使用bcrypt算法。开源的phpass 库用一个易于使用的类来提供这个功能。 例子: view source print? 01 <?php 02 // 包含phpass库 03 require_once('phpass-0.3/PasswordHash.php'); 04 05 // 初始化散列器为不可移植(这样更安全) 06 $hasher= newPasswordHash(8, false); 07 08 // 计算密码哈希值。$hashedPassword 将会是一长为60个字符的字符串. 09 $hashedPassword= $hasher->HashPassword('my super cool password'); 10 11 // 你现在可以安全地保存$hashedPassword到数据库中! 12 13 // 通过比较用户输入内容(产生的哈希值)和我们之前计算出的哈希值,来判断用户是否输入了正确的密码 14 $hasher->CheckPassword('the wrong password', $hashedPassword); // 返回假 15 16 $hasher->CheckPassword('my super cool password', $hashedPassword); // 返回真 17 ?> 陷阱 很多来源会建议你在计算密码的哈希值之前先给密码加点“作料”。这是个好主意,phpass已经利用HashPassword() 函数中的一部分代码来为你给密码加了作料。 这就意味着你并不需要自己再亲自做这个了。 进一步阅读 […]
View Details