原文: http://cwbuecheler.com/web/tutorials/2013/node-express-mongo/
太多的教程教你些一个Hello, World!了, 但是仅凭Hello, World! 是找不到工作的, 因此有了这篇教程.
PART I – 安装开发环境
作者是在Windows 8上开发的.
STEP 1 – 安装NODE.JS
打开 Node.js website 点击绿色的安装按钮. 运行安装程序就安装好了, 就是这么简单. 现在你已经安装好Node.js了, 同样NPM(Node Package Manager)也安装好了
- 打开命令终端 cmd
- cd到你想要建立应用的目录
(本教程是 C: ode).
STEP 2 – 安装EXPRESS
现在我们安装Express, Express是一个框架他能让我们更简单的建立一个web应用. 在命令终端运行:
C: ode>npm install -g express
(-g代表安装到全局, 我感觉express不应该安装到全局)
好消息: 你可以安装一个express的"generator". 他能帮我们生成一个网站基本的框架, 让我们少些了好多的代码(如果你想了解更多可以去Yeoman 看看). 安装generator也很容易, 在命令终端运行:
C: ode>npm install -g express-generator
好了是时候生成一个网站的基本框架了
STEP 3 – CREATE AN EXPRESS PROJECT
我们使用Express 和 Jade, 在命令终端输入:
C: ode>express nodetest1
点击回车, 你可以看到下面的东西
C: ode>express nodetest1 create : nodetest1 create : nodetest1/package.json create : nodetest1/app.js create : nodetest1/public create : nodetest1/public/javascripts create : nodetest1/public/images create : nodetest1/routes create : nodetest1/routes/index.js create : nodetest1/routes/users.js create : nodetest1/public/stylesheets create : nodetest1/public/stylesheets/style.css create : nodetest1/views create : nodetest1/views/index.jade create : nodetest1/views/layout.jade create : nodetest1/views/error.jade create : nodetest1/bin create : nodetest1/bin/www install dependencies: $ cd nodetest1 && npm install run the app: $ DEBUG=my-application ./bin/www
STEP 4 – 编辑依赖
现在我们的网站已经有一个基本的结构了, 但是我们现在还有一些事没做. 你能注意到nodetest1目录有一个叫package.json的文件. 文件的内容如下:
{ "name": "application-name", "version": "0.0.1", "private": true, "scripts": { "start": "node ./bin/www" }, "dependencies": { "express": "~4.0.0", "serve-favicon": "~2.1.3", "morgan": "~1.0.0", "cookie-parser": "~1.0.1", "body-parser": "~1.0.0", "debug": "~0.7.4", "jade": "~1.3.0" } }
这些json内容描述了我们的网站和他的一些依赖. 我们需要添加一些东西. 现在让我们在依赖里面添加MongoDB和Monk.
"dependencies": { "express": "~4.0.0", "serve-favicon": "~2.1.3", "morgan": "~1.0.0", "cookie-parser": "~1.0.1", "body-parser": "~1.0.0", "debug": "~0.7.4", "jade": "~1.3.0", "mongodb": "*", "monk": "*" }
STEP 5 – 安装依赖
现在我们已经定义了我们的依赖. 注意星号代表获取最新的版本. 打开终端 cd到nodetest1目录, 输入:
C: ode odetest1>npm install
现在终端会输出一大堆的东西. 因为读取JSON文件安装我们定义的依赖对象. 运行完后, 你可以发现一个node_modules目录, 里面包含了我们之前定义的依赖.
现在你的网站基本可以运行了. 在运行前我们需要设置一个数据库目录. 在终端输入:
C: ode odetest1>mkdir data
这个目录用来存储我们的MongoDB数据. 如果这个目录不存在的话, 数据库会阻塞我们的网站. 好了现在我们可以来运行看看我们的网站了. 在终端输入:
C: ode odetest1>npm start
回车后, 你可以在终端看到下面的东西
> application-name@0.0.1 start D:sites ode odetest1 > node ./bin/www
打开浏览器, 输入http://localhost:3000 你可以看到一个Express的欢迎页面
PART 2 – 好了让我们做个"HELLO, WORLD!"
用IDE打开app.js, 内容如下:
var express = require('express'); var path = require('path'); var favicon = require('serve-favicon'); var logger = require('morgan'); var cookieParser = require('cookie-parser'); var bodyParser = require('body-parser'); var routes = require('./routes/index'); var users = require('./routes/users');
上面的代码给package、依赖、node functionality和路由创建了相应的变量. 路由是modles和controllers的一种关联. 这里我们忽略不去管user路由只关注于顶级路由 (c: ode odetest1 outesindex.js).
app.js
var app = express();
这个非常重要. 他实例化了一个Express并且分配给了app变量. 下面的代码片段使用这个变量配置一堆express的东西.
app.js
// view engine setup app.set('views', path.join(__dirname, 'views')); app.set('view engine', 'jade'); // uncomment after placing your favicon in /public //app.use(favicon(__dirname + '/public/favicon.ico')); app.use(logger('dev')); app.use(bodyParser.json()); app.use(bodyParser.urlencoded()); app.use(cookieParser()); app.use(express.static(path.join(__dirname, 'public'))); app.use('/', routes); app.use('/users', users);
上面的代码告诉app去哪查找views(视图), 使用何种视图引擎展现我们的视图(Jade), 另外调用了一些方法. 倒数第三行代码告诉Express静态文件放在public目录, 我们获取这些静态文件的时候不需要在url中输入public . 比如, 图片目录在c: ode odetest1publicimages, 但是我们通过http://localhost:3000/images 来进入到图片目录.
app.js
/// catch 404 and forwarding to error handler app.use(function(req, res, next) { var err = new Error('Not Found'); err.status = 404; next(err); }); /// error handlers // development error handler // will print stacktrace if (app.get('env') === 'development') { app.use(function(err, req, res, next) { res.status(err.status || 500); res.render('error', { message: err.message, error: err }); }); } // production error handler // no stacktraces leaked to user app.use(function(err, req, res, next) { res.status(err.status || 500); res.render('error', { message: err.message, error: {} }); });
这里有两种错误处理器, 一个是给开发环境用的,另一个是给生产环境使用的.
app.js
module.exports = app;
Node的一个核心部分就是module.exports. 我们的主app导出app对象.
我们先看看app.js现有的路由:
app.use('/', routes); app.use('/users', users);
上面的代码告诉Express使用那些路由文件. 一般我提倡为应用的不同部分写对应的路由文件. 例如, users路由文件可能包含添加用户、删除用户、更新用户的路由,locations路由文件处理添加、删除、编辑、展示location的路由. 在我们的这个教程中, 为了简单的演示, 我们只关注index路由.
Express generator已经定义了一个"routes" 变量指向index路由. 我们在index路由中添加"helloworld"方法展示一个新的页面. 打开index.js:
var express = require('express'); var router = express.Router(); /* GET home page. */ router.get('/', function(req, res) { res.render('index', { title: 'Express' }); }); module.exports = router;
在最后一行前加入下面的代码:
/* GET Hello World page. */ router.get('/helloworld', function(req, res) { res.render('helloworld', { title: 'Hello, World!' }) });
现在我们还没创建一个helloworld页面. 打开views文件夹, 打开index.jade. 创建一个helloworld.jade文件内容拷贝index.jade的内容.
现在helloworld.jade的内容如下:
extends layout block content h1= title p Welcome to #{title}
使用("extends") 将layout.jade作为一个模板, 接下来在layout文件定义的content block下面输出一个h1和p标签. 注意"title"参数是我们在index.js路由中已经定义了的.
下面让我们改变p的内容:
p Hello, World! Welcome to #{title}
保存文件,回到终端, 按ctrl-c退出服务, 输入:
npm start
顺便说一下, 修改Jade模板不需要重启服务, 但是修改app.js或者路由这样的.js文件需要重启服务.
现在打开http://localhost:3000/helloworld 页面, 效果如下:
PART 3 – 创建数据库
STEP 1 – 安装MONGODB
打开http://mongodb.org/ 下载Mongo. 你会得到一个zip文件, 解压到一个临时的目录. 创建一个目录放Mongo, 把解压后的文件放到这个新的目录下.
STEP 2 – 运行MONGOD和MONGO
在你的nodetest1目录, 新建一个data子目录. 先cd到你安装mongo的目录, 然后输入:
mongod --dbpath c: ode odetest1data
Mongo服务运行了. 第一次会消耗一定的时间, 因为mongo要预先分配一些空间, 另外还要运行一些任务. 当看到终端输出"[initandlisten] waiting for connections on port 27017", 这代表启动完成了. 现在另开一个终端cd到mongo的安装目录, 输入:
mongo
回车后看到下面的内容
c:mongo>mongo MongoDB shell version: 2.4.5 connecting to: test
这告诉你连接已经建立好了
STEP 3 – 创建数据库
"connecting to: test" …test是mongo默认使用的数据库. 其实这个时候还没有真正的创建了一个名为test的数据库, 除非你给test创建了一条记录, 这个时候test数据库才真正的被创建. 在Mongo console 中输入:
use nodetest1
现在我们使用"nodetest1数据库, 和上面讲到的"test"一样, 这个时候我们并没有真正的创建了nodetest1数据库. 为了真正的创建这个数据库, 我们应该添加一些数据.
STEP 4 – 添加数据
添加一些数据到我们的collection. 在这个教程中, 我们的数据比较简单, 只需要一个username和email.数据格式如下:
{ "_id" : 1234, "username" : "cwbuecheler", "email" : "cwbuecheler@nospam.com" }
在mongo终端输入:
db.usercollection.insert({ "username" : "testuser1", "email" : "testuser1@testdomain.com" })
这里要注意的是: "db" 代表我们的数据库, 这里是我们上面定义的"nodetest1"."usercollection" 是我们的collection. 注意我们没有一个创建usercollection的步骤. 因为第一次使用的时候他会自动被创建.回车. 如果一切顺利的话, 终端不会输出任何东西. 现在输入:
db.usercollection.find().pretty()
.pretty() 方法会使得输出自动换行, 这样返回的内容的可读性更好. 返回内容如下:
{ "_id" : ObjectId("5202b481d2184d390cbf6eca"), "username" : "testuser1", "email" : "testuser1@testdomain.com" }
现在我们一次插入多条记录
newstuff = [{ "username" : "testuser2", "email" : "testuser2@testdomain.com" }, { "username" : "testuser3", "email" : "testuser3@testdomain.com" }] db.usercollection.insert(newstuff);
是的, 我们可以传递一个对象数组给我们的collection
STEP 5 – HOOK MONGO UP TO NODE
让我们开始创建一个页面显示数据路里面的内容. 这里是我们期望的得到的html
<ul> <li><a href="mailto:testuser1@testdomain.com">testuser1</a></li> <li><a href="mailto:testuser2@testdomain.com">testuser2</a></li> <li><a href="mailto:testuser3@testdomain.com">testuser3</a></li> </ul>
我们需要在app.js文件中添加几行代码, 用来连接我们的MongoDB. 打开app.js文件:
var express = require('express'); var path = require('path'); var favicon = require('serve-favicon'); var logger = require('morgan'); var cookieParser = require('cookie-parser'); var bodyParser = require('body-parser');
现在让我们来添加3行代码
var express = require('express'); var path = require('path'); var favicon = require('serve-favicon'); var logger = require('morgan'); var cookieParser = require('cookie-parser'); var bodyParser = require('body-parser'); // New Code var mongo = require('mongodb'); var monk = require('monk'); var db = monk('localhost:27017/nodetest1');
这几行代码告诉我们的应用我们想使用MongoDB, 这里使用的是Monk(现在Mongoose比较流行), 我们的数据库位于localhost:27017/nodetest1. 注意27017是MOngoDB的默认端口. 现在看到app.js文件的底部, 代码如下:
app.use('/', routes); app.use('/users', users);
在这我们需要做点工作.app.use语句是为Express建立中间件. 简短的说: 他们提交了一些自定义的函数使得你的app更加有用. 他们很简单, 但是要注意的是他们必须放在路由定义前才能生效.
在上面两行代码前加入下面的代码
// Make our db accessible to our router app.use(function(req,res,next){ req.db = db; next(); });
注意: 如果你不是将上面的代码放在 app.use('/', routes) 之上, 你新加的代码就不会起作用.
当我们添加Mongo和Monk到app.js的时候我们已经定义了db. db是我们的Monk连接对象. 在把上面的代码添加到app.use后, 每个HTTP request对象都有一个db了. 注意: 这个对性能来说可能不是最好的选择, 但是我们这里是讲快速搭建.
再次强调, 上面的代码必须放在我们的路由之上. 现在你的app.js应该是这样子的:
var express = require('express'); var path = require('path'); var favicon = require('serve-favicon'); var logger = require('morgan'); var cookieParser = require('cookie-parser'); var bodyParser = require('body-parser'); // New Code var mongo = require('mongodb'); var monk = require('monk'); var db = monk('localhost:27017/nodetest1'); var routes = require('./routes/index'); var users = require('./routes/users'); var app = express(); // view engine setup app.set('views', path.join(__dirname, 'views')); app.set('view engine', 'jade'); // uncomment after placing your favicon in /public //app.use(favicon(__dirname + '/public/favicon.ico')); app.use(logger('dev')); app.use(bodyParser.json()); app.use(bodyParser.urlencoded()); app.use(cookieParser()); app.use(express.static(path.join(__dirname, 'public'))); // Make our db accessible to our router app.use(function(req,res,next){ req.db = db; next(); }); app.use('/', routes); app.use('/users', users); /// catch 404 and forwarding to error handler app.use(function(req, res, next) { var err = new Error('Not Found'); err.status = 404; next(err); }); /// error handlers // development error handler // will print stacktrace if (app.get('env') === 'development') { app.use(function(err, req, res, next) { res.status(err.status || 500); res.render('error', { message: err.message, error: err }); }); } // production error handler // no stacktraces leaked to user app.use(function(err, req, res, next) { res.status(err.status || 500); res.render('error', { message: err.message, error: {} }); }); module.exports = app;
接下来我们要修改我们的路由, 这样我们就能使用数据库来展现数据了.
STEP 6 – PULL YOUR DATA FROM MONGO AND DISPLAY IT
在编辑器中打开 C: ode odetest1 outesindex.js. 现在让我们来添加一个路由:
/* GET Userlist page. */ router.get('/userlist', function(req, res) { var db = req.db; var collection = db.get('usercollection'); collection.find({},{},function(e,docs){ res.render('userlist', { "userlist" : docs }); }); });
下一步我们要设置我们的Jade 模版. 导航到C: ode odetest1views打开index.jade文件. 复制其内容到新建的userlist.jade, 编辑内容如下:
extends layout block content h1. User List ul each user, i in userlist li a(href="mailto:#{user.email}")= user.username
each中的user代表迭代中的user, i(index)是一个计数器.
保存文件, 重启node服务:
C: ode odetest1>npm start
Now open your browser and head to http://localhost:3000/userlist and marvel in the results.
现在你从数据库里面取出来数据展现在网页上了!
PART 4 – 数据库的写操作
数据库的写操作不难. 记住写操作一般用 HTTP POST
STEP 1 – 创建数据输入框CREATE YOUR DATA INPUT
我们先为添加用户的表单页面添加一个路由. 打开/routes/index.js 添加下面的代码(在module.exports前) :
/* GET New User page. */ router.get('/newuser', function(req, res) { res.render('newuser', { title: 'Add New User' }); });
现在我们添加一个jade模版页面 newuser.jade:
extends layout block content h1= title form#formAddUser(name="adduser",method="post",action="/adduser") input#inputUserName(type="text", placeholder="username", name="username") input#inputUserEmail(type="text", placeholder="useremail", name="useremail") button#btnSubmit(type="submit") submit
重启node服务, 打开 http://localhost:3000/newuser 内容如下:
现在点击submit按钮会得到一个404错误.
STEP 2 – 创建我们的数据功能
现在我们要做的是添加一个Post路由名为 /adduser.
打开 /routes/index.js 添加下面的内容:
/* POST to Add User Service */ router.post('/adduser', function(req, res) { // Set our internal DB variable var db = req.db; // Get our form values. These rely on the "name" attributes var userName = req.body.username; var userEmail = req.body.useremail; // Set our collection var collection = db.get('usercollection'); // Submit to the DB collection.insert({ "username" : userName, "email" : userEmail }, function (err, doc) { if (err) { // If it failed, return error res.send("There was a problem adding the information to the database."); } else { // If it worked, set the header so the address bar doesn't still say /adduser res.location("userlist"); // And forward to success page res.redirect("userlist"); } }); });
STEP 3 – 连结并且添加一些数据到数据库
确定mongod是正在运行的! 下面重启node :
C: ode odetest1>npm start
现在我们打开 http://localhost:3000/newuser 添加一些内容(下面的网址不正确请忽略网址).
点击submit, 我们会跳转到 /userlist 页面, 在这个页面中可以看到我们添加的新用户!