基于node.js+ MongoDB的mircoblog,完成参考《Node.js开发指南》的mircoblog

1.首先用webstorm7.0.2创建一个Node.js的工程,注意Template engine类型选择EJS。


2.创建完工程之后,开始安装MongoDB数据库。

(1)下载MongoDB 下载地址http://www.mongodb.org/,根据自己机子的系统,选择相应的版本。

(2)设置MongoDB目录   比如,解压到F盘下面的MongDB文件夹,路径为F:\MongDB。这个目录路径是任意的。

(3)设置数据文件路径  在F:\MongoDB里面新建logs和data文件夹。

(4)配置MongoDB服务端

打开cmd窗口:输入下面命令:

> f:
> cd F:\MongoDB\bin
> mongod --dbpath "F:\MongoDB\data" --logpath "F:\MongoDB\logs\mongodb.log" --install

(5)验证数据库安装是否成功,在cmd窗口的F:\MongoDB\bin目录下,输入mongo
F:\mongodb\bin\mongo
MongoDB shell version: 1.8.1
connecting to: test
>
这个表示成功,如果有错误,会有提示信息。
如果有问题,可以查看日志 F:\MongoDB\logs下面的mongodb.log

这样配置之后,在管理工具->服务里就会多一个Mongo DB服务,这个是自动开始的。以后每次开机,MongoDB服务都是开启的,不用再配置了。

3. 建立微博网站

(1)功能分析

微博应该以用户为中心,因此需要有用户的注册和登录功能,微博网站最核心的功能是信息的发表,这个功能设计许多方面,包括数据库访问、前端显示。该微博不够完整,只是出于演示目的,信息的评论,转发,圈点用户等功能都没有。如果大家感兴趣,可以自己加。

(2)路由规划

路由规划,或者说控制器规划是整个网站的骨架部分,因为它处于整个架构的枢纽位置,相当于各个接口之间的粘合剂,所以应该优先考虑。
根据功能设计,我们把路由按照以下方案规划。
/:首页
/u/[user]:用户的主页
/post:发表信息
/reg:用户注册
/login:用户登录
/logout:用户登出
以上页面还可以根据用户状态细分。发表信息以及用户登出页面必须是已登录用户才能操作的功能,而用户注册和用户登入所面向的对象必须是未登入的用户。首页和用户主页则针对已登入和未登入的用户显示不同的内容。
其中 /post、/login 和 /reg 由于要接受表单信息,因此使用 app.post 注册路由。/login和 /reg 还要显示用户注册时要填写的表单,所以要以 app.get 注册。
具体app.js代码如下:

/**
 * Module dependencies.
 */

var express = require('express');
var http = require('http');
var routes = require('./routes');

var settings = require('./settings');

var MongoStore = require('connect-mongo')(express);

var partials = require('express-partials');
var flash = require('connect-flash');

var sessionStore = new MongoStore({
    db : settings.db
}, function() {
    console.log('connect mongodb success...');
});


var app = express();

app.configure(function(){
    app.set('port', process.env.PORT || 3000);
    app.set('views', __dirname + '/views');
    app.set('view engine', 'ejs');

    app.use(partials());
    app.use(flash());

    app.use(express.favicon());
    app.use(express.logger('dev'));
    app.use(express.bodyParser());
    app.use(express.methodOverride());

    app.use(express.cookieParser());

    app.use(express.session({
        secret : settings.cookie_secret,
        cookie : {
            maxAge : 60000 * 20	//20 minutes
        },
        store : sessionStore
    }));

    app.use(app.router);
    app.use(express.static(__dirname + '/public'));
});

app.configure('development', function(){
    app.use(express.errorHandler());
});

app.get('/', routes.index);
app.get('/u/:user', routes.user);
app.post('/post', routes.post);
app.get('/reg', routes.reg);
app.post('/reg', routes.doReg);
app.get('/login', routes.login);
app.post('/login', routes.doLogin);
app.get('/logout', routes.logout);


http.createServer(app).listen(app.get('port'), function(){
    console.log('Express server listening on port ' + app.get('port'));
});

connect-mongo、connect-flash、express-partials,mongodb这四个模块需要安装,不然运行app.js的时候 ,会报找不到模块。在Webostorm安装模块,选择File -> Settings,会弹出Settings对话框。

在Settings对话框里的JavaScript的Node.js and NPM, 点击 Install按钮,又会弹出一个Available Packages对话框,在放大镜那块输入你要安装的模块名称,找到后选中你要安装的模块,点击Install Package,就开始安装模块。当然,你也可以通过node.js的命令安装。


(3)界面设计

我们在开发网站的时候必须时刻意识到网站是为用户开发的,因而用户界面是非常重要的。现在我们就用 Bootstrap 开始设计我们的界面。从http://twitter.github.com/bootstrap下载bootstrap.zip。将 img 目录复制到工程 public 目录下,将 bootstrap.css、bootstrap-responsive.css 复制到 public/stylesheets 中,将 bootstrap.js 复制到 public/javascripts 目录中,然后从http://jquery.com/下载一份最新版的 jquery.js 也放入 public/javascripts 目录中。

接下来,修改 views/layout.ejs:

<!DOCTYPE html>
<html>
<head>
    <title><%= title %> - Microblog</title>
    <link rel='stylesheet' href='/stylesheets/bootstrap.css' />
    <style type="text/css">
        body {
            padding-top: 60px;
            padding-bottom: 40px;
        }
    </style>
    <link href="/stylesheets/bootstrap-responsive.css" rel="stylesheet">
</head>
<body>

<div class="navbar navbar-fixed-top">
    <div class="navbar-inner">
        <div class="container">
            <a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
            </a>
            <a class="brand" href="/">Microblog</a>
            <div class="nav-collapse">
                <ul class="nav">
                    <li class="active"><a href="/">首页</a></li>
                    <% if (!user) { %>
                    <li><a href="/login">登录</a></li>
                    <li><a href="/reg">注册</a></li>
                    <% } else { %>
                    <li><a href='javascript:;'>欢迎您,<%= user.name%></a></li>
                    <li><a href="/logout">退出</a></li>
                    <% } %>
                </ul>
            </div>
        </div>
    </div>
</div>

<div id="container" class="container">
    <% if (success) { %>
    <div class="alert alert-success">
        <%= success %>
    </div>
    <% } %>
    <% if (error) { %>
    <div class="alert alert-error">
        <%= error %>
    </div>
    <% } %>
    <%- body %>
    <hr />
    <footer>
        <p><a href="javascript:;">Meteoric</a> 2012</p>
    </footer>
</div>
</body>
<script src="/javascripts/jquery.js"></script>
<script src="/javascripts/bootstrap.js"></script>
</html>
上面代码是使用 Bootstrap部件实现的一个简单页面框架,整个页面分为顶部工具栏、正文和页脚三部分,其中正文和页脚包含在名为 container 的 div 标签中。
最后我们设计首页,修改 views/index.ejs:

<% if (!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 { %>
<%- partial('say') %>
<% } %>
<%- partial('posts', {posts:posts}) %>

4.用户注册和登录

要实现用户会话的功能,包括用户注册和登录状态的维护。为了实现这些功能,我们需要引入会话机制来记录用户状态,还要访问数据库来保存和读取用户信息。现在就让我们从数据库开始。
打开工程目录中的 package.json,修改如下:
接下来在工程的目录中创建 settings.js 文件,这个文件用于保存数据库的连接信息。我们将用到的数据库命名为 microblog,数据库服务器在本地,因此Settings.js文件的内容如下:

module.exports = {
    cookie_secret : 'secret_meteoric',
    db: 'microblog',
    host: 'localhost',
};

接下来在 models 子目录中创建 db.js,内容是:
var settings = require('../settings');
var Db = require('mongodb').Db;
var Connection = require('mongodb').Connection;
var Server = require('mongodb').Server;

module.exports = new Db(settings.db, new Server(settings.host, Connection.DEFAULT_PORT, {}));

(1)会话支持

在完成用户注册和登录功能之前,我们需要先了解会话的概念。会话是一种持久的网络协议,用于完成服务器和客户端之间的一些交互行为。会话是一个比连接粒度更大的概念,一次会话可能包含多次连接,每次连接都被认为是会话的一次操作。在网络应用开发中,有必要实现会话以帮助用户交互。例如网上购物的场景,用户浏览了多个页面,购买了一些物品,这些请求在多次连接中完成。许多应用层网络协议都是由会话支持的,如 FTP、Telnet 等,而 HTTP 协议是无状态的,本身不支持会话,因此在没有额外手段的帮助下,前面场景中服务器不知道用户购买了什么。
Express 也提供了会话中间件,默认情况下是把用户信息存储在内存中,但我们既然已经有了 MongoDB,不妨把会话信息存储在数据库中,便于持久维护。为了使用这一功
能,我们首先要获得一个叫做 connect-mongo 的模块,在 package.json 中添加一行代码:
{
  "name": "microblog",
  "version": "0.0.1",
  "private": true,
  "scripts": {
    "start": "node app.js"
  },
  "dependencies": {
    "express": "3.4.6",
    "ejs": "*",
    "connect-mongo": ">= 0.1.7",
     "mongodb": ">= 0.9.9"
  }
}

app.js的一段代码如下:

app.configure(function(){
    app.set('port', process.env.PORT || 3000);
    app.set('views', __dirname + '/views');
    app.set('view engine', 'ejs');

    app.use(partials());
    app.use(flash());

    app.use(express.favicon());
    app.use(express.logger('dev'));
    app.use(express.bodyParser());
    app.use(express.methodOverride());

    app.use(express.cookieParser());

    app.use(express.session({
        secret : settings.cookie_secret,
        cookie : {
            maxAge : 60000 * 20	//20 minutes
        },
        store : sessionStore
    }));

    app.use(app.router);
    app.use(express.static(__dirname + '/public'));
});

其中 express.cookieParser() 是 Cookie 解析的中间件。express.session() 则提供会话支持,设置它的 store 参数为 MongoStore 实例,把会话信息存储到数据库中,
以避免丢失。可以通过 req.session 获取当前用户的会话对象,以维护用户相关的信息。

5. 注册和登入

我们已经准备好了数据库访问和会话存储的相关信息,接下来开始实现网站的第一个功能,用户注册和登入。

(1)注册页面

首先来设计用户注册页面的表单,创建 views/reg.ejs 文件,内容是:

<form class="form-horizontal" method="post">
    <fieldset>
        <legend>用户注册</legend>
        <div class="control-group">
            <label class="control-label" for="username">用户名</label>
            <div class="controls">
                <input type="text" class="input-xlarge" id="username" name="username">
                <p class="help-block">你的帐号的名称,用于登录和显示</p>
            </div>
        </div>
        <div class="control-group">
            <label class="control-label" for="password">密码</label>
            <div class="controls">
                <input type="password" class="input-xlarge" id="password" name="password">
            </div>
        </div>
        <div class="control-group">
            <label class="control-label" for="password-repeat">重复密码</label>
            <div class="controls">
                <input type="password" class="input-xlarge" id="password-repeat" name="password-repeat">
            </div>
        </div>
        <div class="form-actions">
            <button type="submit" class="btn btn-primary">注册</button>
        </div>
    </fieldset>
</form>
这个表单中有3个输入单元,分别是 username、password 和 password-repeat。表单的请求方法是 POST,将会发送到相同的路径下。

(2)注册响应

现在实现 POST 请求发送后的功能,在 routes/index.js 中添加 /reg 的 POST 响应函数:

exports.post = function(req, res) {
    var currentUser = req.session.user;
    var post = new Post(currentUser.name, req.body.post);
    post.save(function(err) {
        if (err) {
            req.flash('error', err);
            return res.redirect('/');
        }
        req.flash('success', '发表成功');
        res.redirect('/u/' + currentUser.name);
    });
};

exports.reg = function(req, res) {
    res.render('reg', {
        title: '用户注册',
        user : req.session.user,
        success : req.flash('success').toString(),
        error : req.flash('error').toString()
    });
};

exports.doReg = function(req, res) {
    //检查密码
    if (req.body['password-repeat'] != req.body['password']) {
        req.flash('error', '两次输入的密码不一致');
        return res.redirect('/reg');
    }

    //生成md5的密码
    var md5 = crypto.createHash('md5');
    var password = md5.update(req.body.password).digest('base64');

    var newUser = new User({
        name: req.body.username,
        password: password,
    });

    //检查用户名是否已经存在
    User.get(newUser.name, function(err, user) {
        if (user)
            err = 'Username already exists.';
        if (err) {
            req.flash('error', err);
            return res.redirect('/reg');
        }
        //如果不存在則新增用戶
        newUser.save(function(err) {
            if (err) {
                req.flash('error', err);
                return res.redirect('/reg');
            }
            req.session.user = newUser;
            req.flash('success', '注册成功');
            res.redirect('/');
        });
    });
};
这段代码用到了一些新的东西,我们一一说明。
req.body 就是 POST 请求信息解析过后的对象,例如我们要访问用户传递的password 域的值,只需访问 req.body['password'] 即可。
req.flash 是 Express 提供的一个奇妙的工具,通过它保存的变量只会在用户当前和下一次的请求中被访问,之后会被清除,通过它我们可以很方便地实现页面的通知
和错误信息显示功能。
res.redirect 是重定向功能,通过它会向用户返回一个 303 See Other 状态,通知浏览器转向相应页面。
crypto 是 Node.js 的一个核心模块,功能是加密并生成各种散列,使用它之前首先要声明 var crypto = require('crypto')。我们代码中使用它计算了密码的散列值。
User 是我们设计的用户对象,在后面我们会详细介绍,这里先假设它的接口都是可用的,使用前需要通过 var User = require('../models/user.js') 引用。
User.get 的功能是通过用户名获取已知用户,在这里我们判断用户名是否已经存在。User.save 可以将用户对象的修改写入数据库。
通过 req.session.user = newUser 向会话对象写入了当前用户的信息,在后面我们会通过它判断用户是否已经登录。

(3)用户模型

在前面的代码中,我们直接使用了 User 对象。User 是一个描述数据的对象,即 MVC架构中的模型。前面我们使用了许多视图和控制器,这是第一次接触到模型。与视图和控制器不同,模型是真正与数据打交道的工具,没有模型,网站就只是一个外壳,不能发挥真实的作用,因此它是框架中最根本的部分。现在就让我们来实现 User 模型吧。
在 models 目录中创建 user.js 的文件,内容如下:

var mongodb = require('./db');

function User(user) {
    this.name = user.name;
    this.password = user.password;
};
module.exports = User;

User.prototype.save = function save(callback) {
    // 存入 Mongodb 的文檔
    var user = {
        name: this.name,
        password: this.password,
    };
    mongodb.open(function(err, db) {
        if (err) {
            return callback(err);
        }
        // 讀取 users 集合
        db.collection('users', function(err, collection) {
            if (err) {
                mongodb.close();
                return callback(err);
            }
            // 爲 name 屬性添加索引
            collection.ensureIndex('name', {unique: true});
            // 寫入 user 文檔
            collection.insert(user, {safe: true}, function(err, user) {
                mongodb.close();
                callback(err, user);
            });
        });
    });
};

User.get = function get(username, callback) {
    mongodb.open(function(err, db) {
        if (err) {
            return callback(err);
        }
        // 讀取 users 集合
        db.collection('users', function(err, collection) {
            if (err) {
                mongodb.close();
                return callback(err);
            }
            // 查找 name 屬性爲 username 的文檔
            collection.findOne({name: username}, function(err, doc) {
                mongodb.close();
                if (doc) {
                    // 封裝文檔爲 User 對象
                    var user = new User(doc);
                    callback(err, user);
                } else {
                    callback(err, null);
                }
            });
        });
    });
};
以上代码实现了两个接口,User.prototype.save 和 User.get,前者是对象实例的方法,用于将用户对象的数据保存到数据库中,后者是对象构造函数的方法,用于从数据
库中查找指定的用户。

(4)登入和登出

登入和登出仅仅是 req.session.user 变量的标记,非常简单。把下面的代码加到 routes/index.js 中:

exports.login = function(req, res) {
	res.render('login', {
		title: '用户登录',
		user : req.session.user,
		success : req.flash('success').toString(),
		error : req.flash('error').toString()
    });
};

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('/');
	});
};

exports.logout = function(req, res) {
	req.session.user = null;
    req.flash('success', '登出成功');
    res.redirect('/');
};

但这会不会有安全性问题呢?不会的,因为这个变量只有服务端才能访问到,只要不是黑客攻破了整个服务器,无法从外部改动。
最后我们创建 views/login.ejs,内容如下:

<form class="form-horizontal" method="post">
    <fieldset>
        <legend>用户登录</legend>
        <div class="control-group">
            <label class="control-label" for="username">用户名</label>
            <div class="controls">
                <input type="text" class="input-xlarge" id="username" name="username">
            </div>
        </div>
        <div class="control-group">
            <label class="control-label" for="password">密码</label>
            <div class="controls">
                <input type="password" class="input-xlarge" id="password" name="password">
            </div>
        </div>
        <div class="form-actions">
            <button type="submit" class="btn btn-primary">登录</button>
        </div>
    </fieldset>
</form>

6.发表微博

现在网站已经具备了用户注册、登入、页面权限控制的功能,这些功能为网站最核心的部分——发表微博做好了准备。

(1)微博模型

现在让我们从模型开始设计。仿照用户模型,将微博模型命名为 Post 对象,它拥有与User 相似的接口,分别是 Post.get 和 Post.prototype.save。Post.get 的功能是从
数据库中获取微博,可以按指定用户获取,也可以获取全部的内容。Post.prototype.save是 Post 对象实例的方法,用于将对象的变动保存到数据库。
创建 models/post.js,写入以下内容:

var mongodb = require('./db');

function Post(username, post, time) {
    this.user = username;
    this.post = post;
    if (time) {
        this.time = time;
    } else {
        this.time = new Date();
    }
};
module.exports = Post;

Post.prototype.save = function save(callback) {
    // 存入 Mongodb 的文檔
    var post = {
        user: this.user,
        post: this.post,
        time: this.time,
    };
    mongodb.open(function(err, db) {
        if (err) {
            return callback(err);
        }
        // 讀取 posts 集合
        db.collection('posts', function(err, collection) {
            if (err) {
                mongodb.close();
                return callback(err);
            }
            // 爲 user 屬性添加索引
            collection.ensureIndex('user');
            // 寫入 post 文檔
            collection.insert(post, {safe: true}, function(err, post) {
                mongodb.close();
                callback(err, post);
            });
        });
    });
};

Post.get = function get(username, callback) {
    mongodb.open(function(err, db) {
        if (err) {
            return callback(err);
        }
        // 讀取 posts 集合
        db.collection('posts', function(err, collection) {
            if (err) {
                mongodb.close();
                return callback(err);
            }
            // 查找 user 屬性爲 username 的文檔,如果 username 是 null 則匹配全部
            var query = {};
            if (username) {
                query.user = username;
            }
            collection.find(query).sort({time: -1}).toArray(function(err, docs) {
                mongodb.close();
                if (err) {
                    callback(err, null);
                }
                // 封裝 posts 爲 Post 對象
                var posts = [];
                docs.forEach(function(doc, index) {
                    var post = new Post(doc.user, doc.post, doc.time);
                    posts.push(post);
                });
                callback(null, posts);
            });
        });
    });
};
var mongodb = require('./db');

function Post(username, post, time) {
    this.user = username;
    this.post = post;
    if (time) {
        this.time = time;
    } else {
        this.time = new Date();
    }
};
module.exports = Post;

Post.prototype.save = function save(callback) {
    // 存入 Mongodb 的文檔
    var post = {
        user: this.user,
        post: this.post,
        time: this.time,
    };
    mongodb.open(function(err, db) {
        if (err) {
            return callback(err);
        }
        // 讀取 posts 集合
        db.collection('posts', function(err, collection) {
            if (err) {
                mongodb.close();
                return callback(err);
            }
            // 爲 user 屬性添加索引
            collection.ensureIndex('user');
            // 寫入 post 文檔
            collection.insert(post, {safe: true}, function(err, post) {
                mongodb.close();
                callback(err, post);
            });
        });
    });
};

Post.get = function get(username, callback) {
    mongodb.open(function(err, db) {
        if (err) {
            return callback(err);
        }
        // 讀取 posts 集合
        db.collection('posts', function(err, collection) {
            if (err) {
                mongodb.close();
                return callback(err);
            }
            // 查找 user 屬性爲 username 的文檔,如果 username 是 null 則匹配全部
            var query = {};
            if (username) {
                query.user = username;
            }
            collection.find(query).sort({time: -1}).toArray(function(err, docs) {
                mongodb.close();
                if (err) {
                    callback(err, null);
                }
                // 封裝 posts 爲 Post 對象
                var posts = [];
                docs.forEach(function(doc, index) {
                    var post = new Post(doc.user, doc.post, doc.time);
                    posts.push(post);
                });
                callback(null, posts);
            });
        });
    });
};
约定通过 POST 方法访问 /post 以发表微博,现在让我们来实现这个控制器。在 routes/index.js 中添加下面的代码:
exports.post = function(req, res) {
	var currentUser = req.session.user;
	var post = new Post(currentUser.name, req.body.post);
	post.save(function(err) {
		if (err) {
			req.flash('error', err);
			return res.redirect('/');
		}
		req.flash('success', '发表成功');
		res.redirect('/u/' + currentUser.name);
	});
};
这段代码通过 req.session.user 获取当前用户信息,从 req.body.post 获取用户发表的内容,建立 Post 对象,调用 save() 方法存储信息,最后将用户重定向到用户页面。

(2)用户页面

用户页面的功能是展示用户发表的所有内容,在routes/index.js中加入以下代码:

exports.user = function(req, res) {
	User.get(req.params.user, function(err, user) {
		if (!user) {
			req.flash('error', '用户不存在');
			return res.redirect('/');
		}
		Post.get(user.name, function(err, posts) {
			if (err) {
				req.flash('error', err);
				return res.redirect('/');
			}
			res.render('user', {
				title: user.name,
				posts: posts,
				user : req.session.user,
				success : req.flash('success').toString(),
				error : req.flash('error').toString()
			});
		});
	});
};
它的功能是首先检查用户是否存在,如果存在则从数据库中获取该用户的微博,最后通过 posts 属性传递给 user 视图。views/user.ejs 的内容如下:

<% if (user) { %>
<%- partial('say') %>
<% } %>
<%- partial('posts', {posts:posts}) %> 
根据 DRY 原则,我们把重复用到的部分都提取出来,分别放入 say.ejs 和 posts.ejs。say.ejs的功能是显示一个发表微博的表单,它的内容如下:

<form method="post" action="/post" class="well form-inline center" style="text-align:center;">
    <input type="text" class="span8" name="post">
    <button type="submit" class="btn btn-success"><i class="icon-comment icon-white"></i> 发言</button>
</form>
posts.ejs 的目的是按照行列显示传入的 posts 的所有内容:
<% posts.forEach(function(post, index) {
        if (index % 3 == 0) { %>
<div class="row">
    <%} %>
    <div class="span4">
        <h2><a href="/u/<%= post.user %>"><%= post.user %></a> 说</h2>
        <p><small><%= post.time %></small></p>
        <p><%= post.post %></p>
    </div>
    <% if (index % 3 == 2) { %>
</div><!-- end row -->
<% } %>
<%}) %>
<% if (posts.length % 3 != 0) { %>
</div><!-- end row -->
<% } %>

(3)首页

最后一步是实现首页的内容。我们计划在首页显示所有用户发表的微博,按时间从新到旧的顺序。
在 routes/index.js 中添加下面代码:

exports.index = function(req, res){
	Post.get(null, function(err, posts) {
		if (err) {
			posts = [];
		}
		res.render('index', {
			title: '首页',
			posts : posts,
			user : req.session.user,
			success : req.flash('success').toString(),
			error : req.flash('error').toString()
		});
	});
};
它的功能是读取所有用户的微博,传递给页面 posts 属性。接下来修改首页的模板index.ejs:

<% if (!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 { %>
<%- partial('say') %>
<% } %>
<%- partial('posts', {posts:posts}) %>

整个代码编写完成之后,先运行app.js,然后在浏览器(支持html5)输入:http://localhost:3000/

就会打开下面的效果。


具体的代码,见参考链接:http://download.csdn.net/detail/noted2011/6938761

需要说明的是,由于《Node.js开发指南》里面的用的是Express2.x,而现在新的Express用的是3.X,有些接口函数和用法有所改变,不一样。

参考文档:

1. 《Node.js开发指南》

2. http://www.cnblogs.com/qq4004229/archive/2011/11/11/2245599.html

3. http://www.cnblogs.com/meteoric_cry/archive/2012/07/27/2604890.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值