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