Node_進階_5

Node進階第五天css

 

爲何mysql不用開mongod –dbpath xx…html

答:由於mysql會在」服務」中運行,也就是開機時自動啓動而且長久駐紮在內存中了。node

 

mongodb其實也能經過設置來設成windows中的服務。mysql

 

案例:jquery

01每次GET /的時候插入一條數據。ajax

(具體api能夠查看mongodb的文檔)sql

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

var express = require('express');數據庫

var app = express();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 數據訪問對象

是一個數據訪問接口。

  使用咱們本身寫的模塊來完成數據庫的操做。

 

1、     數據庫

 

想一想咱們的百度百家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();

 

        });

 

    });

 

}

 

 

 

2、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加密了,而後進行了列表,因此有破解的可能。

相關文章
相關標籤/搜索