在改章节中,我们重要绍介模块文件的内容,自我感觉有个不错的议建和大家分享下
媒介
这篇文章所应用的例子是基于《node.js开辟指南》这本书中的例子和源码代来做的。express从2.x到3.x引入了非常大的化变,很多模块都被立独出去,并且用调的接口也发生了很大的化变,所以原有的码代在express3.x上是不能运行的。在试尝的程过中,做了很多移迁的任务,同时将一些模块行进了必定的分离和整合,使得全部项目更加拥有构结性和可扩展性。
这里首先要荐推一下《node.js开辟指南》这本书,想学习和应用Node.js的学同,这确实是一本非常面全的绍介Node.js的书籍,看完了后以,结合书中的例子码代,基本可以应用Node行进web应用的开辟。
我这里重要结合这个例子,以自己的解理和对例子的改修报告一下应用Node.js行进web开辟的全部程过。 我就直接从码代开始讲,对于境环的搭建,npm包装安,模块引入等大家可以另外找一些文章,或者从《node.js开辟指南》这本书的响应章节去解了。
目录构结:
首先贴出目录构结:
从每一个文件和文件夹的名字上,相信大家能看出他们各自的功能。
- main.js是全部应用的动启文件
- settings.js中寄存着系统的配置信息
- server.js是系统服务配置和创立的地方
- db.js是与数据库相干的内容
- models模块中中寄存着模型类如User,Post等,相似于Java中的Entity
- routes中是系统面页转跳和请求发分理处的模块
- views是系统现展给户用的面页
- daos分中装了有所对数据库的作操,熟习J2EE的学同该应都解理这一层做的事件
- web中是一些静态元素,如html,js,css,images
- package.json中定义了系统须要的其他的第三方模块,如express,ejs等
- node_modules中则是寄存通过npm装安的第三方包的地方
接下来会对这些分部分离做细详的绍介和析分。
基于express和ejs的MVC
在后台的各个模块中其实有一个基于express和ejs的MVC模式。对应的三个模块为:models(M)-views(V)-routes(C),详细会在面后解讲他们三者是如何任务的。
express
关于express,我在这里不做细详的绍介,大家可以上它的官网做比拟细详的解了。简略的讲,就是一套在Node.js上创立web应用的框架。供提了包含服务创立、动启、会话、路由等接口和现实。一个最基本的基于express的服务码代如下:
var express = require('express'); var app = express(); //创立服务 app.get('/', function(req, res){ //路由有所的到根目录的请求 res.send('hello world'); }); app.listen(3000); //动启服务,监听3000端口
ejs
ejs: ejs是一种基于js的模版技巧,即通过在html段片中插入js码代。在发送到客户端之前在现服务器端行进析解理处,动态设置一些段字或者加添一些节点。JSP就是一种基于java的模版语言。
在最新的ejs中可以支撑以html文件作为模版文件,并且引入了include机制,可以应用include语句来引入其他的面页内容。这点和jsp很像。
一个基于ejs的html文件可以写成如下:
<% include header.html %> <% if (!locals.user) { %> <div class="hero-unit"> <h1>迎欢离开 Microblog</h1> <p>Microblog 是一个基于 Node.js 的微博系统。</p> <p> <a class="btn btn-primary btn-large" href="/login">录登</a> <a class="btn btn-large" href="/reg">当即注册</a> </p> </div> <% } else { %> <% include say.html %> <% } %> <% include footer.html %>
exports.index = function(req, res) { res.render('index', { title: '首页', posts: posts }); };
MVC
在这个MVC模式中重要用到了express的route功能和ejs的模版机制。
在models模块中定义一些模型模块如User,Post等,这些相似与java中的Pojo或者Entity类。定义了模型的一些性属和法方。这些性属与数据库的段字相对应。比如一个简略的User model的模块可以定义如下:
function User(user) { this.name = user.name; this.password = user.password; }; module.exports = User;
var crypto = require('crypto'); var User = require('../models/User'); var Post = require('../models/Post'); var user = require('./user'); var that = exports; exports.index = function(req, res) { Post.get(null, function(err, posts) { if (err) { posts = []; } res.render('index', { title: '首页', posts: posts }); }); }; exports.login = function(req, res) { res.render('login', { title: '用戶登入', }); }; module.exports = function(app) { app.get('/', that.index); app.get('/login', checkNotLogin); app.get('/login', that.login); app.post('/login', checkNotLogin); app.post('/login', that.doLogin); app.get('/reg', user.reg); .... };
var crypto = require('crypto'); var User = require('../models/User'); var UserDao = require('../daos/UserDao'); var PostDao = require('../dao/PostDao'); exports.view = function(req, res) { UserDao.get(req.params.user, function(err, user) { if (!user) { req.flash('error', '户用不存在'); return res.redirect('/'); } PostDao.get(user.name, function(err, posts) { if (err) { req.flash('error', err); return res.redirect('/'); } res.render('user', { title: user.name, posts: posts, }); }); }); }; exports.reg = function(req, res) { res.render('reg', { title: '户用注册', }); };
Views中则是将要返回给客户端展示的内容,route中通过对model的理处,将理处结果或者model的内容通过ejs的式方植入到html面页中返回给客户端。
routes->models->daos
routes作为请求收接发分的模块,在收接到请求后以用调models中的接口理处数据,在models中通过daos中的数据库作操接口成完对数据库数据的查询活变动。这样三个层次各自的责职以及之间的赖依关系就非常确明。拿注册程过举例,典范的用调如下:
routes/index.js app.post('/login', checkNotLogin); app.post('/login', user.doLogin); routes/user.js exports.doLogin = function(req, res) { //成生令口的散列值 var md5 = crypto.createHash('md5'); var password = md5.update(req.body.password).digest('base64'); User.get(req.body.username, function(err, user) { if (!user) { req.flash('error', '户用不存在'); return res.redirect('/login'); } if (user.password != password) { req.flash('error', '密码错误'); return res.redirect('/login'); } req.session.user = user; req.flash('success', '录登功成'); res.redirect('/'); }); }; models/User.js var UserDao = require('../daos/UserDao'); User.get = function get(username, callback) { UserDao.get(username, callback); }; daos/UserDao.js exports.get = function get(username, callback) { mongodb.open(function(err, db) { if (err) { return callback(err); } db.collection('users', function(err, collection) { if (err) { mongodb.close(); return callback(err); } collection.findOne({name: username}, function(err, doc) { mongodb.close(); if (doc) { var user = new User(doc); callback(err, user); } else { callback(err, null); } }); }); }); };
服务配置和动启
main.js是系统动启的文件,在终端应用:node main.js将动启全部web应用。
var server = require('./server'); server.start();
var express = require('express'); var ejs = require('ejs'); var flash = require('connect-flash'); var MongoStore = require('connect-mongo')(express); var settings = require('./settings'); var routes = require('./routes'); var app = express(); app.configure(function() { console.log(__dirname); app.set('views', __dirname + '/views'); // app.set('view engine', 'ejs'); app.engine('.html', ejs.__express); app.set('view engine', 'html'); app.use(express.bodyParser()); app.use(flash()); app.use(express.methodOverride()); app.use(express.cookieParser()); app.use(express.session({ secret: settings.cookieSecret, store: new MongoStore({ db: settings.db }) })); app.use(function(req, res, next) { res.locals.error = req.flash('error').toString(); res.locals.success = req.flash('success').toString(); res.locals.user = req.session ? req.session.user : null; next(); }); app.use(app.router); routes(app); app.use(express.static(__dirname + '/web')); }); app.configure('development', function() { app.use(express.errorHandler({ dumpExceptions: true, showStack: true })); }); app.configure('production', function() { app.use(express.errorHandler()); }); exports.start = function() { app.listen(settings.port); console.log("Express server listening on port %d in %s mode", settings.port, app.settings.env); }
app.engine('.html', ejs.__express);
app.set('view engine', 'html');
这两句设置让ejs将.html文件作为模版文件。
app.use(flash());
express3.0后以移除了req.flash()法方,所以只有通过应用'connect-flash'中间件模块才能继承应用req.flash()法方。
app.use(function(req, res, next) {
res.locals.error = req.flash('error').toString();
res.locals.success = req.flash('success').toString();
res.locals.user = req.session ? req.session.user : null;
next();
});
由于express3.0移除了app.dynamicHelper()接口,所以要继承应用相似的功能,可以应用如上的码代,将flash或者session中的内容动态绑定到locals局部对象上。这样在模版文件中可以直接应用locals.xxx的式方来访问到这些变量。
到这里项目中比拟症结的码代分部都绍介完了,项目码代我放到了github上:https://github.com/owenXin/microblogByOwen
我当地win7境环运行畸形(记得起mongodb哦 )。这是我第一次在Node上做项目,只是开端想设的构结,迎欢大家起一交流,供提名贵的见意和议建。
文章结束给大家分享下程序员的一些笑话语录: 古鸽是一种搜索隐禽,在中国快绝迹了…初步的研究表明,古鸽的离去,很可能导致另一种长着熊爪,酷似古鸽,却又习性不同的猛禽类——犤毒鸟