设为首页 收藏本站
查看: 986|回复: 0

[经验分享] nodejs实现简易MVC

[复制链接]

尚未签到

发表于 2017-2-22 10:34:45 | 显示全部楼层 |阅读模式
  相信大家对于nodejs应该不会陌生,如果真的比较陌生的请访问:http://nodejs.org或者http://cnodejs.org/了解。
  这个简易MVC的结构如下图:
DSC0000.png

  首先需要一个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++) {
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
<div>用户名:<input id="txtName" type="text" value="admin" /></div>
<input id="btn" type="button" value="登录" />
//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的效果如下:
DSC0001.png

DSC0002.png

  使用用户名登录
DSC0003.png

  直接访问/user/load
DSC0004.png

  简易mvc就完成啦,如有什么错误和建议请给我留言,^_^,源代码在此

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-345598-1-1.html 上篇帖子: 大熊君大话NodeJS之------Net模块 下篇帖子: 开始学nodejs —— 调试篇
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表