博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
nodejs实现简易MVC
阅读量:6595 次
发布时间:2019-06-24

本文共 4684 字,大约阅读时间需要 15 分钟。

 相信大家对于nodejs应该不会陌生,如果真的比较陌生的请访问:或者了解。

  这个简易MVC的结构如下图:

    

  首先需要一个http服务来监听来自客户端的请求,大致代码如下:

var m_http = require('http'); var m_querystring = require('querystring'); var m_requestHandler = require('./requestHandler'); exports.run = function (port) { port || (port = 80); m_http.createServer(function (req, res) { req.setEncoding('utf8'); var postData = []; req.on('data', function (chunk) { postData.push(chunk); }).on('end', function () { req.post = m_querystring.parse(postData.join('')); m_requestHandler.handle(req, res); }); }).listen(port); console.log('服务器启动!'); };

  以上req.on('data', ...)内,使用的是一个postData的数组来保存请求的数据,但是当数据量大的时候,会出现一些问题,这个我们暂时不管,博友么可以自己去完善,^_^

  接收了请求之后,需要通过请求的url和method去查找与之相匹配的Contoller,并调用Controller相应的Action,大致代码如下:

var m_route = require('./route'); var m_controllerBase = require('./controllerBase'); var m_invalidHandler = require('./invalidHandler'); var m_getRequestArgs = { ... }; exports.handle = function (req, res) { var method = req.method ? req.method.toLowerCase() : 'get'; var route = m_route.find(req.url, method); var controller = require(m_util.format('./controllers/%s', route.controller)); if (controller[route.action]) { try { controller[route.action].call( new m_controllerBase(req, res), m_getRequestArgs.hasOwnProperty(method) ? m_getRequestArgs[method](req) : {}); } catch (e) { m_invalidHandler.handle500(req, res); } } else { m_invalidHandler.handle404(req, res); } };

  在这里引用了另外3个模块,route.js会根据请求的url和method去获取对应的controller和action信息,代码如下:

//缓存映射信息 var m_cache = {}; exports.addMap = function (map) { if (!(map && map.rule && map.controller)) return; var method = (map.method || 'get').toLowerCase(); m_cache[method] || (m_cache[method] = []); m_cache[method].push({ rule: map.rule, controller: map.controller, action: map.action || 'index' }); }; exports.find = function (url, method) { var route = { controller: null, action: null }; var routes; if (!(m_cache.hasOwnProperty(method) && (routes = m_cache[method]).length)) return route; for (var i = 0, r; r = routes[i]; i++) { if (r.rule.test(url)) { route.controller = r.controller; route.action = r.action; break; } } return route; };

  而controllerBase相当于是所有Controller的基类,会提供诸如缓存,输出html、json、script等方法,代码如下:

function controllerBase(req, res) { this.req = req; this.res = res; }; //添加缓存 controllerBase.prototype.addCache = function (key, value) { m_cache[key] = value; }; //添加缓存 controllerBase.prototype.getCache = function (key) { return m_cache[key]; }; //返回html controllerBase.prototype.html = function (viewName) { //coding }; //根据模板生成的,可以使用其他模板来实现 controllerBase.prototype.template = function (viewName, obj) { //coding }; //返回json controllerBase.prototype.json = function (obj) { //coding }; module.exports = controllerBase;

  但是在处理这些操作的事情,可能会出现错误,因此就需要一个invalidHandler来处理一些原因导致请求无法返回的情况,代码大致如下:

//简单实现了404和500 对于其他http状态码大家可以根据情况实现 exports.handle404 = function (req, res) { res.writeHead(404, {}); res.end(); }; exports.handle500 = function (req, res) { res.writeHead(500, {}); res.end(); };

  当我做到这里的时候,我突然发现并不是所有的请求都会触发Controller和Action,有的仅仅是请求一些如图片、js、css等方面的静态文件,所以我们在处理请求的时候,应该增加一个处理静态文件的,代码如下:

exports.handle = function (req, res) { var url = m_parseURL(req.url); //当请求的文件是网站图标时,不映射到静态文件夹下 var filePath = url.pathname == m_config.FAVICON ? m_path.join(__dirname, url.pathname) : m_path.join(__dirname, m_config.STATIC_FILE_DIR, url.pathname); m_fs.exists(filePath, function (exists) { if (!exists) { m_invalidHandler.handle404(req, res); return; } m_fs.readFile(filePath, FILE_ENCODING, function (err, file) { if (err) { m_invalidHandler.handle500(req, res, err); return; } var ext; ext = (ext = m_path.extname(filePath)) ? ext.slice(1) : 'html'; res.writeHead(200, { 'Content-Type': m_config.CONTENT_TYPE[ext] || m_config.CONTENT_TYPE.html }); res.write(file, FILE_ENCODING); res.end(); }); }); };

  写到这里已经将简易的MVC完成了,最后再增加几个功能来跑起来看看吧,代码如下:

//base.js exports.index = function () { this.view('index.html'); }; exports.login = function (data) { this.addCache('user', data.name); this.json({ success: true }); }; //user.js exports.load = function () { var msg = this.getCache('user') || '未登录'; this.template('main.html', { msg: msg }); }; //index.html 
用户名:
//main.html 欢迎你来到建议MVC,{ #msg}!

  以上增加了controllers和对应的action以及html页面,运行起来发现没效果,检查了代码原来是还没有配置对应route规则,于是我们再添加一些规则,代码如下:

m_route.addMap({
    rule: /^\/$/, controller: 'base' }); m_route.addMap({ method: 'post', rule: /^\/login/, controller: 'base', action: 'login' }); m_route.addMap({ rule: /^\/user\/load$/, controller: 'user', action: 'load' });

  整个mvc的效果如下:

  

  

  使用用户名登录

  

  直接访问/user/load

  

 

  简易mvc就完成啦,如有什么错误和建议请给我留言

转载于:https://www.cnblogs.com/yumingzhao/p/11039464.html

你可能感兴趣的文章
SQL SERVER 批量生成编号
查看>>
thinkjs——一个字段一种数字代表两种状态
查看>>
C++的那些事:类的拷贝控制
查看>>
numpy得到数组的index
查看>>
JSP页面重定向
查看>>
RecyclerView具体解释
查看>>
vue2.0 vue-loader
查看>>
美国埃博拉患者是怎样治愈的?
查看>>
[离散时间信号处理学习笔记] 9. z变换性质
查看>>
简单实用SQL脚本Part:查找SQL Server 自增ID值不连续记录
查看>>
关系型数据库的分片原则
查看>>
浅谈线段树中加与乘标记的下放
查看>>
【IDEA】IDEA中maven项目pom.xml依赖不生效解决
查看>>
scrapy-redis(七):部署scrapy
查看>>
Redis集群
查看>>
建立自己的NuGet服务器
查看>>
【编程之美】中国象棋将帅问题
查看>>
DroidCam 一片 红色 解决办法
查看>>
WINDOWS XP sp2 Platfrom SDK下载地址
查看>>
Citrix服务器虚拟化之二十九 XenApp 6.5发布服务器上的应用程序
查看>>