express简单实现登录及在线聊天室


安装express

express 是 Node.js 上最流行的 Web 开发框架,正如他的名字一样,使用它我们可以快速的开发一个 Web 应用。我们用 express 来搭建我们的博客,打开命令行,输入:

npm install -g express-generator

用express创建项目

express -e login
                                                     

-  e指令使用ejs模板引擎,默认使用jade模板(jade好难用)
cd 进入login文件夹安装所依赖模块
 npm install
运行项目  
 npm start  or node .bin/www

                                                    

工程目录

app.js:启动文件,或者说入口文件

package.json:存储着工程的信息及模块依赖,当在 dependencies 中添加依赖的模块时,运行 npm install ,npm 会检查当前目录下的 package.json,并自动安装所有指定的模块

node_modules:存放 package.json 中安装的模块,当你在 package.json 添加依赖的模块并安装后,存放在这个文件夹下

public:存放 image、css、js 等文件

routes:存放路由文件

views:存放视图文件或者说模版文件

bin:存放可执行文件

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');

var app = express();

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');

// 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({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

app.use('/', routes);
app.use('/users', users);

// catch 404 and forward 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;

不了解代码的去看express官网讲解很详细

看html比较习惯,可以将ejs后缀改为html,并修改app.js加载ejs模板代码如下:

app.set('views', path.join(__dirname, 'views'));
app.engine('html', require('ejs').__express);
app.set('view engine', 'html');

再来安装该项目所需模块

登录需要用到session模块,session有依赖于cookie,所以要安装session和cookie模块,最重要的是socket

npm install cookie-parser 
npm install express-session     
首先是主界面 index.html

<!DOCTYPE html>  
<html>  
  <head>  
    <title><%= title %></title>  
  </head>  
  <body>  
    <h1><%= title %></h1>  
    <p>Welcome to <%= title %></p>  
  
    <p><a href="/login">登录</a></p>  
    <p><a href="/register">注册</a></p>  
  </body>  
</html>  
登录页面 login.html

<div class="container">
        <%- message %>    //用户操作信息
            <form class="form-horizontal col-sm-4 col-sm-offset-4" role="form" method="post" onsubmit="return false">
                <fieldset>
                    <legend></legend>
                    <div class="panel panel-default">
                        <div class="page-header">
                            <p class="tc">请先登录</p>
                        </div>
                        <div class="panel-body m15">
                            <div class="form-group">
                                <div class="input-group">
                                    <span class="input-group-addon">  
                                    <span class="glyphicon glyphicon-user"></span>
                                    </span>
                                    <input type="text" class="form-control" id="username" name="username" placeholder="请输入用户名" required>
                                </div>
                            </div>
                            <div class="form-group">
                                <div class="input-group">
                                    <span class="input-group-addon">  
                                    <span class="glyphicon glyphicon-lock"></span>
                                    </span>
                                    <input type="password" class="form-control" id="password" name="password" placeholder="请输入密码" required>
                                </div>
                            </div>
                            <div class="form-group">
                                <button type="submit" class="btn bg-primary btn-block" id="register0">注册</button>
                            </div>
                            <div class="form-group">
                                <button type="button" class="btn btn-info btn-block" id="login0">登录</button>
                            </div>
                        </div>
                    </div>
                </fieldset>
            </form>
    </div> 

注册页面 register.html(和login页面同理)

<div class="container">
        <%- message %>
            <form class="form-horizontal col-sm-4 col-sm-offset-4" role="form" method="post" onsubmit="return false">
                <fieldset>
                    <legend></legend>
                    <div class="panel panel-default">
                        <div class="page-header">
                            <p class="tc">注册信息</p>
                        </div>
                        <div class="panel-body m15">
                            <div class="form-group">
                                <div class="input-group">
                                    <span class="input-group-addon">  
                                    <span class="glyphicon glyphicon-user"></span>
                                    </span>
                                    <input type="text" class="form-control" id="username" name="username" placeholder="请输入用户名" required>
                                </div>
                            </div>
                            <div class="form-group">
                                <div class="input-group">
                                    <span class="input-group-addon">  
                                    <span class="glyphicon glyphicon-lock"></span>
                                    </span>
                                    <input type="password" class="form-control" id="password" name="password" placeholder="请输入密码" required>
                                </div>
                            </div>
                            <div class="form-group">
                                <div class="input-group">
                                    <span class="input-group-addon">  
                                    <span class="glyphicon glyphicon-lock"></span>
                                    </span>
                                    <input type="text" class="form-control" id="passwordAgin" name="passwordAgin" placeholder="请再次输入密码">
                                </div>
                            </div>
                            <div class="form-group">
                                <button type="submit" class="btn bg-primary btn-block" id="register1">注册</button>
                            </div>
                        </div>
                    </div>
                </fieldset>
            </form>
    </div>
//提交用户注册信息
    $(function() {
        $("#register1").click(function() {
            var username = $("#username").val();
            var password = $("#password").val();
            var passwordAgin = $("#passwordAgin").val();
            if (password !== passwordAgin) {
                $("#password").css("boder", "1px solid red");
                $("#passwordAgin").css("boder", "1px solid red");
            } else if (password === passwordAgin) {
                var data = {
                    "uname": username,
                    "upwd": password
                };
                $.ajax({
                    url: '/register',
                    type: 'post',
                    data: data,
                    success: function(data, status) {
                        if (status == 'success') {
                            location.href = 'login';
                        }
                    },
                    error: function(data, err) {
                        location.href = 'register';
                    }
                });
            }
        });
    });
登录后进入home.html

<h1>your name:<%- user.name%></h1>  
    <p>Welcom to your home</p>  
    <p><a href="/chat">进入聊天室</a></p>
    <p><a href="/logout">我要注销</a></p>  
聊天页面 chat.html

<div id="chatbox">
        <div style="background:#3d3d3d;height: 28px; width: 100%;font-size:12px;">
            <div style="line-height: 28px;color:#fff;">
                <span style="text-align:left;margin-left:10px;">Websocket多人聊天室</span>
                <span style="float:right; margin-right:10px;"><span id="showusername"></span> |
                <a href="javascript:;" onclick="CHAT.logout()" style="color:#fff;">退出</a></span>
            </div>
        </div>
        <div id="doc">
            <div id="chat">
                <div id="message" class="message">
                    <div id="onlinecount" style="background:#EFEFF4; font-size:12px; margin-top:10px; margin-left:10px; color:#666;">
                    </div>
                </div>
                <div class="input-box">
                    <div class="input">
                        <input type="text" maxlength="140" placeholder="请输入聊天内容,按Enter提交" id="content" name="content">
                    </div>
                    <div class="action">
                        <button type="button" id="mjr_send" onclick="CHAT.submit();">提交</button>
                    </div>
                </div>
            </div>
        </div>
    </div> 

使用express中间件,对每个请求进行处理,获取session(获取不到session对象则没有正常登录,或登录失效,并返回错误信息),代码如下:


app.use(cookieParser());
app.use(session({
    secret: 'secret',
    cookie: {
        maxAge: 1000 * 60 * 30
    }
}));
app.use(function(req, res, next) {
    res.locals.user = req.session.user; //从session获取user对象  
    var err = req.session.error; //获取错误信息  
    delete req.session.error;
    res.locals.message = ""; //展示信息的message  
    if (err) {
        res.locals.message = '<div class="alert alert-danger" style="margin-bottom:20px;color:red;text-align:center;">' + err + '</div>';
    }

    next(); //中间件传递  

});

本项目用的是mongodb数据库,首先安装mongoose模块

npm install -g mongoose

引入连接并创建数据模型,db.js如下:

var mongoose = require('mongoose');
var db = mongoose.connect('mongodb://127.0.0.1:27017');//mongodb默认端口27017.
var Schema = mongoose.Schema;   //  创建模型
var userScheMa = new Schema({
	name: String,
	password: String
}); //  定义了一个新的模型,但是此模式还未和users集合有关联
exports.Model = db.model('users', userScheMa); //  与users集合关联

 服务端登录检查,login.js如下:

var users = require('../database/db').Model;//引入usersji'h
function login(req,res){
	var username = req.body.username,
		password = req.body.password;
	users.find({name:username},function(err,result){
		if(!result[0]){
			res.end(JSON.stringify({'code':500,'data':'用户名不存在'}));
		}
		else{
			if(result[0].password==password){
				res.end(JSON.stringify({'code':200,'data':{name:result[0].name,maxproject:result[0].maxProjects}}));
			}
			else{
				res.end(JSON.stringify({'code':500,'data':'密码不正确'}));
			}
		}
	})
}
module.exports = login;

 服务端用户注册功能,register.js如下:

var users = require('../database/db').Model;
function register(req,res){
	var username = req.body.username,
		password = req.body.password;
	users.find({name:username},function(err,result){
		if(result[0]){
			res.end(JSON.stringify({'code':500,'data':'用户名已存在'}))
		}
		else{
			users.create({name:username,password:password,maxProjects:6,projects:[],recycle:[]},function(err){
				if(!err){
					res.end(JSON.stringify({'code':200,'data':'注册成功'}));
				}
			});
		}
	})
}
module.exports = register;

 客户端用户登录,代码如下:

 $(function() {
        $("#register0").click(function() {
            location.href = 'register';
        });
        $("#login0").click(function() {
            var username = $("#username").val();
            var password = $("#password").val();
            var data = {
                "uname": username,
                "upwd": password
            };
            $.ajax({
                url: '/login',
                type: 'post',
                data: data,
                success: function(data, status) {
                    location.href = 'home';
                    localStorage.setItem('name', username);
                },
                error: function(data, status) {
                    location.href = 'login';
                }
            });
        });
    });

 客户端用户注册,代码如下:

 $(function() {
        $("#register1").click(function() {
            var username = $("#username").val();
            var password = $("#password").val();
            var passwordAgin = $("#passwordAgin").val();
            if (password !== passwordAgin) {
                $("#password").css("boder", "1px solid red");
                $("#passwordAgin").css("boder", "1px solid red");
            } else if (password === passwordAgin) {
                var data = {
                    "uname": username,
                    "upwd": password
                };
                $.ajax({
                    url: '/register',
                    type: 'post',
                    data: data,
                    success: function(data, status) {
                        if (status == 'success') {
                            location.href = 'login';
                        }
                    },
                    error: function(data, err) {
                        location.href = 'register';
                    }
                });
            }
        });
    });

 接下来是聊天功能,服务端需要安装socket.io模块,该模块可以对socket套接字操作,代码如下:

 function chatready(io) {
    //在线用户
    var onlineUsers = {};
    //当前在线人数
    var onlineCount = 0;


    io.on('connection', function(socket) {
        console.log('a user connected');


        //监听新用户加入
        socket.on('login', function(obj) {
            //将新加入用户的唯一标识当作socket的名称,后面退出的时候会用到
            socket.name = obj.username;


            //检查在线列表,如果不在里面就加入
            if (!onlineUsers.hasOwnProperty(obj.username)) {
                onlineUsers[obj.username] = obj.username;
                //在线人数+1
                onlineCount++;
            }


            //向所有客户端广播用户加入
            io.emit('login', { onlineUsers: onlineUsers, onlineCount: onlineCount, user: obj });
            console.log(obj.username + '加入了聊天室');
        });


        //监听用户退出
        socket.on('disconnect', function() {
            //将退出的用户从在线列表中删除
            if (onlineUsers.hasOwnProperty(socket.name)) {
                //退出用户的信息
                var obj = { username: onlineUsers[socket.name] };


                //删除
                delete onlineUsers[socket.name];
                //在线人数-1
                onlineCount--;


                //向所有客户端广播用户退出
                io.emit('logout', { onlineUsers: onlineUsers, onlineCount: onlineCount, user: obj });
                console.log(obj.username + '退出了聊天室');
            }
        });


        //监听用户发布聊天内容
        socket.on('message', function(obj) {
            //向所有客户端广播发布的消息
            io.emit('message', obj);
            console.log(obj.username + '说:' + obj.content);
        });


    });
}
module.exports = chatready;
找到bin文件夹下的www文件,引入chatready模块,并绑定socket到http服务器上var server = http.createServer(app);
var io = require('socket.io')(server);
chartready(io);

 客户端需要引入socket.io 这个js文件,可从node_modules模块文件夹下找到socket.io中找到改文件,客户端代码如下:

 (function() {
    var d = document,
        w = window,
        p = parseInt,
        dd = d.documentElement,
        db = d.body,
        dc = d.compatMode == 'CSS1Compat',
        dx = dc ? dd : db,
        ec = encodeURIComponent;


    w.CHAT = {
        msgObj: d.getElementById("message"),
        screenheight: w.innerHeight ? w.innerHeight : dx.clientHeight,
        username: null,
        socket: null,
        //让浏览器滚动条保持在最低部
        scrollToBottom: function() {
            w.scrollTo(0, this.msgObj.clientHeight);
        },
        //退出,本例只是一个简单的刷新
        logout: function() {
            //this.socket.disconnect();
            location.href = 'login';
        },
        //提交聊天消息内容
        submit: function() {
            var content = d.getElementById("content").value;
            if (content != '') {
                var obj = {
                    userid: this.userid,
                    username: this.username,
                    content: content
                };
                this.socket.emit('message', obj);
                d.getElementById("content").value = '';
            }
            return false;
        },
        genUid: function() {
            return new Date().getTime() + "" + Math.floor(Math.random() * 899 + 100);
        },
        //更新系统消息,本例中在用户加入、退出的时候调用
        updateSysMsg: function(o, action) {
            //当前在线用户列表
            var onlineUsers = o.onlineUsers;
            //当前在线人数
            var onlineCount = o.onlineCount;
            //新加入用户的信息
            var user = o.user;


            //更新在线人数
            var userhtml = '';
            var separator = '';
            for (key in onlineUsers) {
                if (onlineUsers.hasOwnProperty(key)) {
                    userhtml += separator + onlineUsers[key];
                    separator = '、';
                }
            }
            d.getElementById("onlinecount").innerHTML = '当前共有 ' + onlineCount + ' 人在线,在线列表:' + userhtml;


            //添加系统消息
            var html = '';
            html += '<div class="msg-system">';
            html += user.username;
            html += (action == 'login') ? ' 加入了聊天室' : ' 退出了聊天室';
            html += '</div>';
            var section = d.createElement('section');
            section.className = 'system J-mjrlinkWrap J-cutMsg';
            section.innerHTML = html;
            this.msgObj.appendChild(section);
            this.scrollToBottom();
        },
        init: function(username) {
            /*
            客户端根据时间和随机数生成uid,这样使得聊天室用户名称可以重复。
            实际项目中,如果是需要用户登录,那么直接采用用户的uid来做标识就可以
            */
            this.username = username;


            d.getElementById("showusername").innerHTML = this.username;
            //this.msgObj.style.minHeight = (this.screenheight - db.clientHeight + this.msgObj.clientHeight) + "px";
            this.scrollToBottom();


            //连接websocket后端服务器
            this.socket = io.connect('ws://127.0.0.1:3000');


            //告诉服务器端有用户登录
            this.socket.emit('login', { username: this.username });


            //监听新用户登录
            this.socket.on('login', function(o) {
                CHAT.updateSysMsg(o, 'login');
            });


            //监听用户退出
            this.socket.on('logout', function(o) {
                CHAT.updateSysMsg(o, 'logout');
            });


            //监听消息发送
            this.socket.on('message', function(obj) {
                var isme = (obj.username == CHAT.username) ? true : false;
                var contentDiv = '<div>' + obj.content + '</div>';
                var usernameDiv = '<span>' + obj.username + '</span>';


                var section = d.createElement('section');
                if (isme) {
                    section.className = 'user';
                    section.innerHTML = contentDiv + usernameDiv;
                } else {
                    section.className = 'service';
                    section.innerHTML = usernameDiv + contentDiv;
                }
                CHAT.msgObj.appendChild(section);
                CHAT.scrollToBottom();
            });


        }
    };
    //通过“回车”提交信息
    d.getElementById("content").onkeydown = function(e) {
        e = e || event;
        if (e.keyCode === 13) {
            CHAT.submit();
        }
    };
    CHAT.init(localStorage.getItem('name'));
})();

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值