ImageVerifierCode 换一换
格式:DOCX , 页数:10 ,大小:129.16KB ,
资源ID:9339391      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/9339391.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(文件Nodejs实现一个简单的WebMVC框架我要看明白的第一个mvc.docx)为本站会员(b****6)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

文件Nodejs实现一个简单的WebMVC框架我要看明白的第一个mvc.docx

1、文件Nodejs实现一个简单的WebMVC框架我要看明白的第一个mvc【关键字】文件Node.js实现一个简单的Web MVC框架-我要看明白的第一个mvcNode.js是什么Node让你可以用javascript编写服务器端程序,让javascript脱离web浏览器的限制,像C#、JAVA、Python等语言一样在服务器端运行,这也让一些熟悉Javascript的前端开发人员进军到服务器端开发提供了一个便利的途径。 Node是基于Google的V8引擎封装的,并提供了一些编写服务器程序的常用接口,例如文件流的处理。Node的目的是提供一种简单的途径来编写高性能的网络程序。(注:1、本文基于

2、Node.js V0.3.6; 2、本文假设你了解JavaScript; 3、本文假设你了解MVC框架;4、本文示例源代码:learnNode.zip)Node.js的性能hello world 测试: 300并发请求,返回不同大小的内容: 为什么node有如此高的性能?看node的特性。Node.js的特性1. 单线程2. 非阻塞IO3. Google V84. 事件驱动更详细的了解node请看淘宝UED博客上的关于node.js的一个幻灯片:你好,世界这,当然是俗套的Hello World啦(hello_world.js):var http = require(http); http.cr

3、eateServer(function (req, res) res.writeHead(200, Content-Type: text/plain); res.end(Hello Worldn); ).listen(8124, ); console.log(Server running at .1:8124/);require类似于C#的using、Python的import,用于导入模块(module)。node使用的是CommonJS的模块系统。http.createServer 的参数为一个函数,每当有新的请求进来的时候,就会触发这个函数。最后就是绑定要监听的端口。怎么运行?当然,是先

4、安装node.js啦。到,支持Linux、Mac,也支持windows下的Cygwin。具体的安装说明见: 装好node后,就可以运行我们的hello world了:$ node hello_world.js Server running at .1:8124/ 编程习惯的改变?我们来写一个读取文件内容的脚本:/output_me.js var fs = require(fs), fileContent = nothing; fs.readFile(_filename, utf-8, function(err, file) if(err) console.log(err); return; f

5、ileContent = file; console.log(end readfile n); ); console.log(doSomethingWithFile: + fileContent +n);这个脚本读取当前文件的内容并输出。_filename是node的一个全局变量,值为当前文件的绝对路径。我们执行这个脚本看一下: 有没发现结果不对呢?打印的fileContent并不是读取到的文件内容,而是初始化的时候赋值的nothing,并且end readfile最后才打印出来。前面我们提到node的一个特性就是非阻塞IO,而readFile就是异步非阻塞读取文件内容的,所以后面的代码并不会

6、等到文件内容读取完了再执行。请谨记node的异步非阻塞IO特性。所以我们需要将上面的代码修改为如下就能正常工作了:/output_me.js var fs = require(fs), fileContent = nothing; fs.readFile(_filename, utf-8, function(err, file) if(err) console.log(err); return; fileContent = file; /对于file的处理放到回调函数这里处理 console.log(doSomethingWithFile: + fileContent +n); ); cons

7、ole.log(我们先去喝杯茶n);写个Web MVC框架试试下面我们用node来写一个小玩具:一个Web MVC框架。这个小玩具我称它为n2Mvc,它的代码结构看起来大概如下: 和hello world一样,我们需要一个http的服务器来处理所有进来的请求:var http = require(http), querystring = require(querystring); exports.runServer = function(port) port = port | 8080; var server = http.createServer(function(req, res) var

8、 _postData = ; /on用于添加一个监听函数到一个特定的事件 req.on(data, function(chunk) _postData += chunk; ) .on(end, function() req.post = querystring.parse(_postData); handlerRequest(req, res); ); ).listen(port); console.log(Server running at .1:+ port +/); ;这里定义了一个runServer的方法来启动我们的n2Mvc的服务器。有没注意到runServer前面有个exports

9、?这个exports相当于C#中的publish,在用require导入这个模块的时候,runServer可以被访问到。我们写一个脚本来演示下node的模块导入系统:/moduleExample.js var myPrivate = 艳照,藏着; exports.myPublish = 冠西的相机; this.myPublish2 = this也可以哦; console.log(moduleExample.js loaded n);执行结果: 从结果中我们可以看出exports和this下的变量在外部导入模块后,可以被外部访问到,而var定义的变量只能在脚本内部访问。 从结果我们还可以看出,第

10、二次require导入moduleExample模块的时候,并没有打印“moduleExample.js loaded”,因为require导入模块的时候,会先从require.cache 中检查模块是否已经加载,如果没有加载,才会从硬盘中查找模块脚本并加载。 require支持相对路径查找模块,例如上面代码中require(./moduleExample)中的“./”就代表在当前目录下查找。如果不是相当路径,例如 require(http),node则会到require.paths中去查找,例如我的系统require.paths为: 当require(http)的时候,node的查找路径为:

11、1、/home/qleelulu/.node_modules/http 2、/home/qleelulu/.node_modules/http.js 3、/home/qleelulu/.node_modules/http.node 4、/home/qleelulu/.node_modules/http/index.js 5、/home/qleelulu/.node_modules/http/index.node 6、/home/qleelulu/.node_libraries/http 7、/home/qleelulu/.node_libraries/http.js 8、参考前面再看回前面的代

12、码,http.createServer中的回调函数中的request注册了两个事件,前面提到过node的一个特点是事件驱动的,所以这种事件绑定你会到处看到(想想jQuery的事件绑定?例如$(a).click(fn)。关于node的事件我们在后面再细说。request对象的data事件会在接收客户端post上来的数据时候触发,而end事件则会在最后触发。所以我们在data事件里面处理接收到的数据(例如post过来的form表单数据),在end事件里面通过handlerRequest 函数来统一处理所有的请求并分发给相应的controller action处理。 handlerRequest的代

13、码如下:var route = require(./route); var handlerRequest = function(req, res) /通过route来获取controller和action信息 var actionInfo = route.getActionInfo(req.url, req.method); /如果route中有匹配的action,则分发给对应的action if(actionInfo.action) /假设controller都放到当前目录的controllers目录里面,还记得require是怎么搜索module的么? var controller = r

14、equire(./controllers/+actionInfo.controller); / ./controllers/blog if(controlleractionInfo.action) var ct = new controllerContext(req, res); /动态调用,动态语言就是方便啊 /通过apply将controller的上下文对象传递给action controlleractionInfo.action.apply(ct, actionInfo.args); else handler500(req, res, Error: controller + action

15、Info.controller + without action + actionInfo.action + ) else /如果route没有匹配到,则当作静态文件处理 staticFileServer(req, res); ;这里导入来一个route模块,route根据请求的url等信息去获取获取controller和action的信息,如果获取到,则通过动态调用调用action方法,如果没有匹配的action信息,则作为静态文件处理。 下面是route模块的代码:var parseURL = require(url).parse; /根据http请求的method来分别保存route规则

16、 var routes = get:, post:, head:, put:, delete:; /* * 注册route规则 * 示例: * route.map( * method:post, * url: /blog/post/(d+)/?$/i, * controller: blog, * action: showBlogPost * ) */ exports.map = function(dict) if(dict & dict.url & dict.controller) var method = dict.method ? : get; routesmethod.push( u:

17、dict.url, /url匹配正则 c: dict.controller, a: dict.action | index ); ; exports.getActionInfo = function(url, method) var r = controller:null, action:null, args:null, method = method ? method.toLowerCase() : get, / url: /blog/index?page=1 ,则pathname为: /blog/index pathname = parseURL(url).pathname; var m_

18、routes = routesmethod; for(var i in m_routes) /正则匹配 r.args = m_routesi.u.exec(pathname); if(r.args) r.controller = m_routesi.c; r.action = m_routesi.a; ; /第一个值为匹配到的整个url,去掉 break; /如果匹配到route,r大概是 controller:blog, action:index, args:1 return r; ;map方法用于注册路由规则,我们新建一个config.js的文件,来配置route规则:/config.js

19、 var route = require(./route); route.map( method:get, url: /blog/?$/i, controller: blog, action: index );如果请求的url有匹配的route规则,则会返回controller和action信息。例如上面的route配置,当访问 /blog 这个url的时候,则会调用 ./controllers/blog.js 模块里面的index函数。 当调用action的时候,会传递controllerContext给acation:var ct = new controllerContext(req,

20、res); /动态调用,动态语言就是方便啊 /通过apply将controller的上下文对象传递给action controlleractionInfo.action.apply(ct, actionInfo.args);这里会通过apply将controllerContext作为action的this,并传递args作为action的参数来调用action。 ontrollerContext封装了一些action会用到的方法:/controller的上下文对象 var controllerContext = function(req, res) this.req = req; this.r

21、es = res; this.handler404 = handler404; this.handler500 = handler500; ; = function(viewName, context) viewEngine.render(this.req, this.res, viewName, context); ; = function(json) viewEngine.renderJson(this.req, this.res, json); ;在action中处理完逻辑获取获取到用户需要的数据后,就要呈现给用户。这就需要viewEngine来处理了。ViewEngine的代码如下:v

22、ar viewEngine = render: function(req, res, viewName, context) var filename = path.join(_dirname, views, viewName); try var output = Shotenjin.renderView(filename, context); catch(err) handler500(req, res, err); return; res.writeHead(200, Content-Type: text/html); res.end(output); , renderJson: funct

23、ion(res, json) /TODO: ;这里viewEngine主要负责模板解析。node有很多的可用的模块,模板解析模块也有一大堆,不过这里我们是要“玩”,所以模板解析系统我们这里使用jstenjin来稍作修改:/shotenjin.js 增加的代码 /模板缓存,缓存解析后的模板 Shotenjin.templateCatch = ; /读取模板内容 /在模板中引用模板使用: # ./layout.html # Shotenjin.getTemplateStr = function(filename) /console.log(get template: + filename); va

24、r t = ; /这里使用的是同步读取 if(path.existsSync(filename) t = fs.readFileSync(filename, utf-8); else throw View: + filename + not exists; t = t.replace(/#s*(./w-+)s*#/ig, function(m, g1) var fp = path.join(filename, g1.trim() return Shotenjin.getTemplateStr(fp); ); return t; ; Shotenjin.renderView = function

25、(viewPath, context) var template = Shotenjin.templateCatchviewPath; if(!template) var template_str = Shotenjin.getTemplateStr(viewPath); var template = new Shotenjin.Template(); template.convert(template_str); /添加到缓存中 Shotenjin.templateCatchviewPath = template; var output = template.render(context);

26、 return output; ; global.Shotenjin = Shotenjin;增加的代码主要是读取模板的内容,并解析模板中类似 # ./layout.html # 的标签,递归读取所有的模板内容,然后调用jstenjin的方法来解析模板。 这里读取文件内容使用的是fs.readFileSync,这是同步阻塞读取文件内容的,和我们平时使用的大多编程语言一样,而fs.readFile的非阻塞异步读。 这里的shotenjin.js原来是给客户端web浏览器javascript解析模板用的,现在拿到node.js来用,完全不用修改就正常工作。Google V8真威武。 现在基本的东西

27、都完成了,但是对于静态文件,例如js、css等我们需要一个静态文件服务器:var staticFileServer = function(req, res, filePath) if(!filePath) filePath = path.join(_dirname, config.staticFileDir, url.parse(req.url).pathname); path.exists(filePath, function(exists) if(!exists) handler404(req, res); return; fs.readFile(filePath, binary, fun

28、ction(err, file) if(err) handler500(req, res, err); return; var ext = path.extname(filePath); ext = ext ? ext.slice(1) : html; res.writeHead(200, Content-Type: contentTypesext | text/html); res.write(file, binary); res.end(); ); ); ; var contentTypes = aiff: audio/x-aiff, arj: application/x-arj-comp

29、ressed /省略 简单来说就是读取文件内容并写入到response中返回给客户端。 现在该有的都有了,我们写一个action:/ ./controllers/blog.js exports.index = function() this.render(blog/index.html, msg:Hello World); ;blog/index.html的内容为:# ././header.html # n2Mvc Demo#msg# ././footer.html # 接着,就是写一个脚本来启动我们的n2Mvc了:/ run.js var n2MvcServer = require(./se

30、rver); n2MvcServer.runServer();ok,运行我们的启动脚本: 在浏览器访问看看: 嗯嗯,一切正常。 好,接下来我们再写一个获取新浪微博最新微博的页面。首先,我们在config.js中增加一个route配置:route.map( method:get, url: /tweets/?$/i, controller: blog, action: tweets );然后开始写我们的cnotroller action:var http = require(http), events = require(events); var tsina_client = http.createClient(80, ); var tweets_emitter = new events.EventEmitter(); / action: tweets exports.tweets = function(blogType) var _t = this; var listener = tweets_emitter.once(tweets, function(tweets) _t.render(blog/tweets.html, tweets: tweets); ); get_tweet

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1