zoukankan      html  css  js  c++  java
  • Node_进阶_5

    Node进阶第五天

    为什么mysql不用开mongod –dbpath xx…

    答:因为mysql会在”服务”中运行,也就是开机时自动启动并且长久驻扎在内存中了。

    mongodb其实也能通过设置来设成windows中的服务。

    案例:

    01每次GET /的时候插入一条数据。

    (具体api可以查看mongodb的文档)

    const MongoClient = require('mongodb').MongoClient;

    var express = require('express');

    var app = express();

     

    app.listen(3000);

     

    app.get("/", (req, res) => {

     

        const url = 'mongodb://localhost:27017/';

        const dbName = 'myproject';

     

        MongoClient.connect(url,{useNewUrlParser:true}, function (err, client) {

            //回调函数表示连接成功做的事情

             if(err){

                 console.log("数据库连接失败");

                 return;

             }

     

            console.log("数据库连接成功");

     

            const db = client.db(dbName);

     

           

            //插入数据,集合如果不存在,也没有关系,程序会帮你创建

            db.collection('student').insertOne({

     

                "name":"哈哈",

                "age": parseInt(Math.random() *100 + 10)

     

            },function(err,result){

     

                if(err){

                    console.log(err);

                    return;

                }

     

            //插入之后做的事情,result表示插入结果。

            console.log(result);

            res.send(result);

            client.close();

     

            });

     

        });

     

    });

     

    02把常用的增删改查,都封装成为module

    DAO data access object 数据访问对象

    是一个数据访问接口。

      使用我们自己写的模块来完成数据库的操作。

    一、     数据库

    想想我们的百度百家Ajax案例,当时调用了百度的JSON,有一个参数叫做page=3,生成的JSON,

    这个就是分页,就是我们像寻找所有的新闻,但是是位于第三页的新闻。那么有两种做法:

    1)     错误的做法:就是将所有的result都读取到数组,然后进行数据操作,进行分页;

    2)     正确的做法:就是在数据库中,只读取这么多内容。

    错误的,我们试图每次都读取全部数据,但是这样开销很大

       db.find(“student”,{},function(err,result){

           for(var i = 10*page;i<10*(page+1);i++)

    {

     a.push(result[i]);

    }

    res.send(a);

    });

    所以,mongodb提供了傻傻的两个函数,极傻无比。

    limit()、skip()

    db.student.find().limit(4).skip(4);

    limit表示读取的条数,skip表示略过的条数,limit和skip配合使用就是分页查询。

    加入,第一页是page=0。每页10条,所以当前页的查询语句

      db.student.find({}).limit(10).skip(page*10)

      能分页的个数

      db.student.stats().count;

    案例源代码:

    db.js:

    //这个模块封装了所有对数据库的常用操作。

     

    const MongoClient = require('mongodb').MongoClient;

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



    //不管数据库什么操作,都是先连接数据库,所以我们可以把连接数据库

    //封装成内部函数

    function __connectDB(callback) {

     

        var url = settings.dburl; //从settings文件中读数据库地址

     

        MongoClient.connect(url, function (err, client) {

     

            const db = client.db('huha');

     

            //这里是新增加的

            if (err) {

                callback(err, db);

                return;

            }

     

            callback(err, db, client);

     

        });

     

    };

     

    //插入数据

    exports.insertOne = function (collectionName, json, callback) {

     

        __connectDB(function (err, db, client) {

     

            if (err) {

                callback(err, null);

                return;

            }

     

            db.collection(collectionName).insertOne(json, function (err, result) {

                callback(err, result);

                client.close();//关闭数据库

            });

     

        })

     

    };

     

    //查找数据,找到所有数据

    exports.find = function (collectionName, json, C, D) {

     

        var result = [];//结果数组

     

        if (arguments.length == 3) {

     

            console.log("有三个参数");

     

            //那么参数C就是callback,参数D没有传。

            var callback = C;

            var skipnumber = 0;

     

            //数目限制

            var limit = 0;

     

        } else if (arguments.length == 4) {

     

            console.log("有四个参数");

     

            var callback = D;

            var args = C;

            //应该省略的条数

            var skipnumber = args.pageamount * args.page;

            //数目限制

            var limit = args.pageamount;

     

        } else {

            throw new Error("find函数的参数个数,必须是3个,或者4个");

        }



        //连接数据库,连接之后查找所有

        __connectDB(function (err, db, client) {

     

            var cursor = db.collection(collectionName).find(json).skip(skipnumber).limit(limit);

     

            cursor.each(function (err, doc) {

                if (err) {

                    callback(err, null);

                    return;

                }

                if (doc != null) {

                    result.push(doc); //放入结果数组

                } else {

                    //遍历结束,没有更多的文档了

                    callback(null, result);

                }

     

            });

     

            client.close();

     

        });

    }

     

    //删除

    exports.deleteMany = function (collectionName, json, callback) {

     

        __connectDB(function (err, db, client) {

     

            if (err) {

                callback(err, null);

                return;

            }

     

            //删除

            db.collection(collectionName).deleteMany(

                json,

                function (err, results) {

                    console.log(results);

     

                    client.close();

                    callback();

                }

            );

        });

    }

     

    //修改

    exports.updateMany = function (collectionName, json1, json2, callback) {

     

        __connectDB(function (err, db, client) {

     

            db.collection(collectionName).updateMany(

                json1,

                json2,

                function (err, results) {

                    callback(err, results);

                });

        });

    }

    settings.js:

    module.exports = {

     

        "dburl": 'mongodb://localhost:27017'

     

    }

    02.js:

    var express = require('express');

    var app = express();

    var db = require('./model/db.js')

     

    //增加

    app.get('/', function (req, res) {

     

        db.insertOne("student", { "name": "小红", "age": 18 }, function (err, result) {

            if (err) {

                console.log("插入失败");

                return;

            }

            res.send("插入成功");

        });

     

    });

     

    //查询

    app.get('/du', function (req, res) {

        //这个页面现在接收一个page参数,

        var page = parseInt(req.query.page); //express中读取get参数很简单

        //查找4个参数,在哪个集合查,查什么,分页设置,查完之后做什么

        db.find("student", {}, function (err, result) {

     

            if (err) {

                console.log(err);

            }

     

            res.send(result);

     

        });

     

    });

     

    //删除

    app.get('/shan', function (req, res) {

     

        var name = parseInt(req.query.name);

        db.deleteMany("teacher", { "name": "小红" }, function (err, result) {

     

            res.send(result);

     

        });

     

    });

     

    //修改

    app.get("/xiugai", function (req, res) {

     

        db.updateMany("student", { "name": "小红" }, { $set: { "name": "呼哈" } }, function (err, result) {

            if (err) {

                console.log(err);

            }

            res.send(result);

     

        });

     

    });

     

    app.listen(3000);

    项目—小小留言本

    做一个留言本,能够增删改:

    ejs页面中,如果我们想使用underscore的模板,就会有模板冲突的问题。

    underscore用的:

        <script type="text/template" id="moban">

            <div class="list-group">

                <a href="#" class="list-group-item active">

                  <h4 class="list-group-item-heading"><%=xingming%>></h4>

                  <p class="list-group-item-text"><%=liuyan%></p>

                </a>

              </div>

        </script>

    ejs以为是自己的模板。所以报错,提示你没有传递姓名参数。

    解决方法就是underscore源码。在源码中搜索<% 修改为{{即可。

    项目整体目录结构:

    03.js:

    var express = require('express');

    var app = express();

    var db = require('./model/db.js');

    var formidable = require('formidable');

    var ObjectId = require('mongodb').ObjectId;

     

    //设置模板引擎

    app.set("view engine", "ejs");

     

    //静态服务

    app.use(express.static("./public"));

     

    //显示留言列表

    app.get("/", function (req, res, next) {

     

        db.getAllCount("liuyanben", function (count) {

            res.render('index', {

                "pageamount": Math.ceil(count / 4)

            });

        });

     

    });

     

    //读取所有留言,这个页面是供ajax使用的

    app.get("/du", function (req, res, next) {

     

        //可以接受一个参数

        var page = parseInt(req.query.page) || "0";



        db.find("liuyanben", {}, { "sort": { "shijian": -1 }, "pageamount": 4, "page": page }, function (err, result) {

            res.json({ "result": result });

        });

    });



    //处理留言

    app.post("/tijiao", function (req, res, next) {

     

        console.log("对这里请求了");

     

        var form = new formidable.IncomingForm();

     

        form.parse(req, function (err, fields) {

     

            //写入数据库

            db.insertOne("liuyanben", {

                "xingming": fields.xingming,

                "liuyan": fields.liuyan,

                "shijian": new Date()

            }, function (err, result) {

                if (err) {

                    res.send({ "result": -1 }); //-1是给ajax看的

                    return;

                }

                res.send({ "result": 1 });

            });

     

            console.log("收到请求了" + fields.xingming + fields.liuyan);

     

        });

     

    });

     

    //得到总数量

    app.get("/count", function (req, res) {

     

    });

     

    //删除

    app.get('/shanchu', function (req, res, next) {

     

        //得到参数

        var id = req.query.id;

        db.deleteMany("liuyanben", { "_id": ObjectId(id) }, function (err, result) {

            res.redirect("/");

        });

     

    });

     

    app.listen(3000);

    settings.js:

    module.exports = {

     

        "dburl": 'mongodb://localhost:27017'

    }

    index.ejs:

    <!doctype html>

    <html lang="en">

     

    <head>

        <!-- Required meta tags -->

        <meta charset="utf-8">

        <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

     

        <!-- Bootstrap CSS -->

        <link rel="stylesheet" href="css/bootstrap.min.css">

        <style>

            .row h4 {

                text-align: center;

            }

     

            #chenggong,

            #shibai {

                display: none;

            }

     

            .liuyankuai {

                padding: 10px 0;

                border-bottom: 1px solid #ccc;

            }

        </style>

        <title>Hello, world!</title>

    </head>

     

    <body>

     

        <h1>我的留言本</h1>

     

        <div class="container">

     

            <div class="row">

     

                <form class="form-horizontal col-lg-6">

                    <div class="form-group">

                        <label for="xingming" class="col-sm-2 control-label">姓名</label>

                        <div class="col-sm-10">

                            <input type="text" class="form-control" id="xingming" placeholder="姓名">

                        </div>

                    </div>

                    <div class="form-group">

                        <label for="inputPassword3" class="col-sm-2 control-label">留言</label>

                        <div class="col-sm-10">

     

                            <textarea style="resize:none;" name="liuyan" id="liuyan" class="form-control" rows="3"></textarea>

     

                        </div>

                    </div>

     

                    <div class="form-group">

                        <div class="col-sm-offset-2 col-sm-10">

                            <button type="button" id="tijiao" class="btn btn-success">提交</button>

                        </div>

                    </div>

                    <div id="chenggong" class="alert alert-success" role="alert">

                        <a href="#" class="alert-link">表单已经成功提交</a>

                    </div>

                    <div class="alert alert-danger" id="shibai" role="alert">

                        <a href="#" class="alert-link">表单提交失败</a>

                    </div>

     

                </form>

     

            </div>

     

            <nav aria-label="Page navigation">

                <ul class="pagination">



                    <% for(var i =1;i<=pageamount; i++){ %>

                        <li data-page="<%=i%>" class="yemaanniu">

                            <a href="#">

                                <%=i%>

                            </a>

                        </li>

                        <% } %>



                </ul>

            </nav>

     

            <div id="quanbuliuyan">

     

            </div>

        </div>

     

        <script type="text/template" id="moban">

            <div class="liuyankuai">

     

                  <p>[_id]{{=id}}</p>

                  <p>[姓名]{{=xingming}}</p>

                  <p>[留言]{{=liuyan}}</p>

                  <p>[时间]{{=shijian}}</p>

                  <p><a href="/shanchu?id={{=id}}" class="shanchu" >删除</a></p>

             

            </div>

        </script>

     

        <script src="js/underscore.js"></script>

        <script src="js/jquery.min.js"></script>

        <script>

     

            var nowpage = 1;

     

            //删除



            //给第一个页面,补一个active

            $(".pagination").find("li").eq(0).addClass("active");

     

            //给所有的页码按钮,添加监听

            $(".yemaanniu").click(function () {

     

                nowpage = parseInt($(this).attr("data-page"));

     

                //重新发起请求即可

                getData(nowpage);

     

                $(this).addClass("active").siblings().removeClass("active");

     

            });

     

            $("#nextbtn").click(function () {

                nowpage++;

                if (nowpage)

                    getData(nowpage);

            });

     

            //默认请求第一页数据

            getData(1);

     

            //Ajax请求数据

     

            function getData(page) {

     

                $.get("/du?page=" + (page - 1), function (result) {

                    //这里接收时result,但是这个json里面有一个key叫做result。

                    //得到模板,弄成模板函数

                    var compiled = _.template($("#moban").html());

                    //清空全部留言中的所有节点

     

                    $("#quanbuliuyan").html("");

     

                    for (var i = 0; i < result.result.length; i++) {

                        //数据绑定

                        var html = compiled({

                            liuyan: result.result[i].liuyan,

                            xingming: result.result[i].xingming,

                            shijian: result.result[i].shijian,

                            id: result.result[i]._id,

                        });

                        //DOM操作,添加节点

                        $("#quanbuliuyan").append($(html));

                    }

                });

     

            }

     

            //Ajax提交表单

            $("#tijiao").click(function () {

     

                $("#shibai").hide();

                $("#chenggong").hide();

     

                //Ajax提交表单

                $.post("/tijiao", {

                    "xingming": $("#xingming").val(),

                    "liuyan": $("#liuyan").val()

                }, function (result) {

                    if (result.result == -1) {

                        $("#shibai").fadeIn();

                    } else if (result.result == 1) {

                        //提交成功

                        $("#chenggong").fadeIn();

                        //数据库真的存储了,但是当前页面无法显示,这是因为需要刷新

                        //才能用ajax从/du中得到新的。所以我们先用一个假盒子凑出来

                        var compiled = _.template($("#moban").html());

                        var html = compiled(

                            {

                                liuyan: $("#liuyan").val(),

                                xingming: $("#xingming").val(),

                                shijian: new Date()

                            }

                        );

     

                        console.log($("#quanbuliuyan"));

                        $(html).insertBefore($("#quanbuliuyan"));

                    }

                });



            });

     

        </script>

    </body>

     

    </html>

    db.js:

    //这个模块封装了所有对数据库的常用操作。

     

    const MongoClient = require('mongodb').MongoClient;

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



    //不管数据库什么操作,都是先连接数据库,所以我们可以把连接数据库

    //封装成内部函数

    function __connectDB(callback) {

     

        var url = settings.dburl; //从settings文件中读数据库地址

     

        MongoClient.connect(url, function (err, client) {

     

            const db = client.db('huha');

     

            //这里是新增加的

            if (err) {

                callback(err, db);

                return;

            }

     

            callback(err, db, client);

     

        });

     

    };

     

    //插入数据

    exports.insertOne = function (collectionName, json, callback) {

     

        __connectDB(function (err, db, client) {

     

            if (err) {

                callback(err, null);

                return;

            }

     

            db.collection(collectionName).insertOne(json, function (err, result) {

                callback(err, result);

                client.close();//关闭数据库

            });

     

        })

     

    };

     

    //查找数据,找到所有数据

    exports.find = function (collectionName, json, C, D) {

     

        var result = [];//结果数组

     

        if (arguments.length == 3) {

     

            //  console.log("有三个参数");

     

            //那么参数C就是callback,参数D没有传。

            var callback = C;

            var skipnumber = 0;

     

            //数目限制

            var limit = 0;

     

        } else if (arguments.length == 4) {

     

            // console.log("有四个参数");

     

            var callback = D;

            var args = C;

            //应该省略的条数

            var skipnumber = args.pageamount * args.page || 0;

            //数目限制

            var limit = args.pageamount || 0;

            //排序方式

            var sort = args.sort || {};

     

        } else {

            throw new Error("find函数的参数个数,必须是3个,或者4个");

        }



        //连接数据库,连接之后查找所有

        __connectDB(function (err, db, client) {

     

            var cursor = db.collection(collectionName).find(json).skip(skipnumber).limit(limit).sort(sort);

     

            cursor.each(function (err, doc) {

                if (err) {

                    callback(err, null);

                    return;

                }

                if (doc != null) {

                    result.push(doc); //放入结果数组

                } else {

                    //遍历结束,没有更多的文档了

                    callback(null, result);

                }

     

            });

     

            client.close();

     

        });

    }

     

    //删除

    exports.deleteMany = function (collectionName, json, callback) {

     

        __connectDB(function (err, db, client) {

     

            if (err) {

                callback(err, null);

                return;

            }

     

            //删除

            db.collection(collectionName).deleteMany(

                json,

                function (err, results) {

                    console.log(results);

                    callback(null,results);

                    client.close();

                }

            );

        });

    }

     

    //修改

    exports.updateMany = function (collectionName, json1, json2, callback) {

     

        __connectDB(function (err, db, client) {

     

            db.collection(collectionName).updateMany(

                json1,

                json2,

                function (err, results) {

                    callback(err, results);

     

                    //这里可能会有错误

                    client.close();

                });

        });

     

    }

     

    //得到文件总数

    exports.getAllCount = function (collectionName, callback) {

     

        __connectDB(function (err, db, client) {

            var a = db.collection(collectionName).count({}).then(function (count) {

     

                //  console.log(count);

                callback(count);

                client.close();

     

            });

     

        });

     

    }

    二、Cookie和Session

    HTTP是无状态协议。简单地说,当你浏览了一个页面,然后转到同一个网站的另一个页面,服务器无法认识到,这是同一个浏览器在访问同一个页面。每一次的访问,都是没有关系的。

    那么世界就乱套了,比如说我上一次访问,登陆了,下一次访问,又让我登录,不存在登录着事儿了。

    第一次访问一个服务器,不可能携带cookie。必须是服务器得到这次请求,在下行的响应报头中携带cookie信息,此后每一次浏览器往这个服务器发出的请求,都会携带这个cookie。

    ·cookie是不加密的,用户可以自由看到;

    ·用户可以删除cookie,或者禁用它

    ·cookie可以被篡改

    ·cookie可以用于攻击

    ·cookie存储量很小。未来实际上要被localStorage干掉。

    express中的cookie,你肯定能想到。res负责设置cookie,req负责识别cookie。

    Express中的Cookie

    ·Express中,使用cookie-parser中间件来设置cookie.

    ·主要设置选项:domain、path、maxAge、signed

    1.js:

    var express = require('express');

    var cookieParser = require('cookie-parser');

     

    var app = express();

    app.use(cookieParser());

     

    app.get('/', function (req, res) {

        res.cookie('xihao', 'tfboys', { maxAge: 900000, httpOnly: true })

        res.send();

    });

     

    app.listen(3000);

    这个图是服务器发给浏览器的cookie,是明码:

    再次请求的时候可以看到浏览器携带的cookie,是明码。

    test.js:

    var express = require('express');

    var cookieParser = require('cookie-parser');

     

    var app = express();

    //使用cookie必须要使用cookie-parser中间件

    app.use(cookieParser());

     

    app.get('/', function (req, res) {

        //maxAge在Express中毫秒为单位

        // res.cookie('xihao', 'tfboys', { maxAge: 900000, httpOnly: true })

        res.send("猜你喜欢" + JSON.stringify(req.cookies));

    });

     

    app.get("/gonglue", function (req, res) {

     

        //得到get请求,用户查询的目的地

        var mudidi = req.query.mudidi;

        //记录用户喜好

        //先读取用户的喜好,然后把新的数据push进入数组,设置新的数据

        var mudidiarray = req.cookies.mudidi || [];

        mudidiarray.push(mudidi);

        res.cookie("mudidi", mudidiarray, { maxAge: 900000, httpOnly: true });

        res.send(mudidi + '旅游攻略');

     

    });

     

    app.listen(3000);

    4.2 Session

    Session不是天生就有的,是依赖于cookie。

    cookie是明码传输的,

    浏览器通过给服务器发送一段”乱码”cookie,让服务器进行对比,看看这个客户端是谁。

    session依赖cookie,当一个浏览器禁用cookie的时候,登陆效果消失;或者用户清除了cookie,登录也消失。

    session比cookie不一样在哪里呢? session下发的是乱码,并且服务器自己缓存一些东西,下次浏览器的请求带着乱码上来,此时与缓存进行比较,看看是谁。

    所以,一个乱码,可以对应无限大的数据。

    任何语言中,session的使用,是”机理透明”的,他是帮你设置cookie的,但是足够方便,让你感觉不到这事儿和cookie有关。

    session中乱码和存储数据比对的这个库是存储在服务器的内存中的,一旦服务器关机了,就会消失了。

    nodejs中的session:

    express中使用express-session来使用session。

    05.js:

    var express = require('express');

    var app = express();

    var session = require('express-session');

     

    app.use(session({

        secret: 'keyboard cat',

        resave: false,

        saveUninitialized: true,

    }));

     

    app.get('/', function (req, res) {

     

        if (req.session.login == "1") {

            res.send("欢迎你");

        } else {

            res.send('你没有登陆!!');

        }

     

    })

     

    app.get('/login', function (req, res) {

     

        req.session.login = "1"; //设置这个session

        res.send('你已经成功登陆');

     

    });

     

    app.listen(3000);

     

    看看这段被加密的cookie:

    做一个利用session的登陆界面:

    var express = require('express');

    var app = express();

    var db = require('./model/db.js');

    var session = require('express-session');

     

    app.use(session({

        secret: 'keyboard cat',

        resave: false,

        saveUninitialized: true,

    }));

     

    app.set('view engine', 'ejs');

     

    app.get('/', function (req, res) {

        if (req.session.login == "1") {

            res.send("欢迎" + req.session.username);

        } else {

            res.send("没有成功登录");

        }

    });

     

    app.get('/login', function (req, res) {

        res.render('denglu');

    });

     

    app.get('/checklogin', function (req, res) {

     

        var tianxiedeusername = req.query.username;

        var tianxiepassword = req.query.password;

        //根据用户填写的姓名,去数据库里面找这个文档,读出密码

        //如果读取的密码,和填写的密码一样,那么登录成功了

        //如果读取的密码和填写的密码不一样,登陆失败.

        //如果根本没有找到这个记录,那么就说明用户名填写错了   

        db.find("users", { "username": tianxiedeusername }, function (err, result) {

            console.log(result);

            if (result.length == 0) {

                res.send('你的登录名写错了,没有这个注册用户');

                return;

            }

            var shujukuzhongdepassword = result[0].password;

     

            if (shujukuzhongdepassword == tianxiepassword) {

                req.session.login = "1";

                req.session.username = result[0].username;

     

                res.send('成功登录!你是' + result[0].username);

            } else {

                res.send('用户名对了密码错误');

            }

     

        });

     

    });

     

    app.listen(3000);

    加密使用的是MD5加密。

    加密’1’:

    md5(1,32) = c4ca4238a0b923820dcc509a6f75849b
    md5(1,16) = a0b923820dcc509a

    加密’2’:

    md5(2,32) = c81e728d9d4c2f636f067f89cc14862c
    md5(2,16) = 9d4c2f636f067f89

    不管你加密多大的东西,哪怕10M的文字,都会加密为32位的字符串,就是密码。并且神奇的,数学上能够保证,哪怕你更改一个文字,都能大变。

    MD5是数学上,不能破解的。不能反向破解。

    也就是说,c4ca4238a0b923820dcc509a6f75849b 没有一个函数,能够翻译成为1的。

    但是,有的人做数据库就是把1~999999所有数字都用MD5加密了,然后进行了列表,所以有破解的可能。

  • 相关阅读:
    [OS] 信号量(Semaphore)
    [OS] 进程互斥
    [剑指Offer] 52.正则表达式匹配
    [剑指Offer] 51.构建乘积数组
    [剑指Offer] 50.数组中重复的数字
    [剑指Offer] 49.把字符串转换成整数
    [剑指Offer] 48.不用加减乘除做加法
    [剑指Offer] 47.求1+2+3+...+n
    PHP知识库图谱汇总(完善中)
    修改thinkphp路由模式,去掉Home
  • 原文地址:https://www.cnblogs.com/eret9616/p/9111386.html
Copyright © 2011-2022 走看看