数据库、MongoDB/Mongoose、cookie与session、密码加密、图片处理、web Socket和Socket.IO框架

一、传统数据库

数据库就是存储数据的,那么存储数据就用txt就行了啊,为什么要有数据库?

  • 理由1: 数据库有行、列的概念,数据有关系,数据不是散的。
    • 老牌数据库,比如MySQL、SQL Server、Oracle、Access,又叫做结构型数据库。
    • 为什么?因为每个表中都有明确的字段,每行记录都有这些字段。不能有的行有,有的行没有。
  • 理由2:数据库能够提供非常方便的接口,让增删改查操作变得简单
    • 老牌数据库,都使用SQL语言,管理数据库。SQL就是structure query language。
  • 理由3:数据库要给PHP、.net、jsp等语言提供接口。用php这些语言,能够向数据库中增删改查。

老牌数据库,都是结构型数据库,现在出了什么问题?

  • **数据不灵活。一个字段,需要是同样类型的数据。**不能一行记录是文本,一行记录是数字。也不能一行有字段,一行没有

  • 关系表还支持约束

    • 唯一的
    • 主键
    • 默认值
    • 非空

非结构型数据库NoSQL应运而生。

NoSQL是个怪胎,无法挑战老牌数据库,但是在大数据时代有自己的意义。

二、NoSQL

特点NoSQL分类NoSQL数据库适用场景
非结构型数据库键值存储数据库1、数据模型比较简单
没有行、列的概念。用JSON来存储数据列存储数据库2、需要灵活性更强的IT系统
集合就相当于“表”,文档就相当于“行”文档型数据库3、对数据库性能要求较高
图形数据库4、不需要高度的数据一致性
5、对于给定key,比较容易映射复杂值的环境

三、MongoDB

3.1 基本概念

MongoDB是最像关系型数据库的非关系型数据库

  • 数据库 ===》数据库
  • 数据表 ===》集合(数组)
  • 表记录 ===》(文档对象)

特点:

  • 可以有多个数据库
  • 一个数据库中可以有多个集合(表)
  • 一个集合中可以有多个文档(表记录)
  • 文档结构很灵活,没有任何限制
  • MongoDB很灵活,不像MySQL一样先创建数据库、表、设计表结构
    • 当自动插入数据的时候,只需要指定往哪个数据库的哪个集合操作就可以了
    • 一切都由MongoDB来帮助自动完成建库建档

开机命令:mongod --dbpath c:\mongo --dbpath就是选择数据库文档所在的文件夹。

mongoDB中,有物理文件对应一个个数据库,U盘可以拷贝。

开机这个CMD不能动,不能关,不能ctrl+c。 一旦这个cmd有问题了,数据库就自动关闭了。

所以,应该再开一个cmd。输入 mongo 那么,运行环境就是mongo语法了

命令功能
mongo使用数据库
exit退出连接
mongod开机
mongoimport导入数据
show dbs查看所有数据库列表
use 数据库名字新建 / 使用某个数据库
db查看当前所在数据库
cls清屏
db.dropDatabase();删除数据库,删除当前所在的数据库

3.2 增删改查

操作示例说明
插入数据db.student.insert({'name': 'aa', 'age': 12})student就是所谓的集合。集合中存储着很多json。
student是第一次使用,集合将自动创建
mongoimport --db test --collection restaurants --drop --file primer-dataset.json–db test 往哪个数据库导入
–collection restaurants 往哪个集合中导入
–drop 把集合清空
–file primer-dataset.json 哪个文件
查找数据db.student.find({"score.shuxue":{$gt:50}, $or:[{"age":9},{"age":11}]})没有参数将列出这个集合的所有文档

db.student.find({}).limit(10).skip(page*10) 每页10条
查找数学分数大于50,且年龄为9或11的学生
修改数据db.student.update({"sex":"男"},{$set:{"age":33}},{multi: true});所有男性的年龄改为33岁,{multi: true}表示更改所有匹配项目,否则只更改单个文档single document
db.student.update({"name":"小明"},{"name":"大明","age":16});完整替换,不出现$set关键字
删除数据db.restaurants.remove( { "borough": "Manhattan" } )默认移除匹配的所有文档
db.restaurants.remove( { "borough": "Queens" }, { justOne: true } ){ justOne: true }只移除匹配的一个文档

3.3 在Node中如何操作MongoDB数据

3.3.1使用官方的mongodb

npm搜安装包:https://www.npmjs.com/package/mongodb

跳转到github:https://github.com/mongodb/node-mongodb-native

有安装与使用规范,太原生了,一般不用

3.3.2 使用第三方mongoose

第三方包:mongoose基于MongoDB官方的mongodb包再一次做了封装

网址:https://mongoosejs.com/

四、Mongoose

4.1 概念

是一个将JavaScript对象与数据库产生关系的一个框架,object related model。

操作对象,就是操作数据库了;对象产生了,同时也持久化了。

这个思路是Java三大框架SSH中Hibernate框架的思路。彻底改变了人们使用数据库的方式。

  • 官网:https://mongoosejs.com/

  • 官方指南:https://mongoosejs.com/docs/guide.html

  • 官方API文档:https://mongoosejs.com/docs/api.html

hello world:

var mongoose = require('mongoose'); // 引包,并不需要引用mongodb这个包
mongoose.connect('mongodb://localhost/test', { useMongoClient: true });// 链接数据库,test是数据库名字
mongoose.Promise = global.Promise;
// 创建一个模型,就是在设计数据库
// MongoDB 是动态的,非常灵活,只需要在代码中设计你的数据库就可以了
// mongoose 这个包就可以让你的设计编写过程变的非常的简单
var Cat = mongoose.model('Cat', { name: String });// 创建了一个模型。猫的模型。所有的猫都有名字,是字符串。“类”

for (var i = 0; i < 100; i++) {
  // 实例化一个 Cat
  var kitty = new Cat({ name: '喵喵' + i });
  // 持久化保存 kitty 实例
  kitty.save(function (err) {
    if (err) {
      console.log(err);
    } else {
      console.log('meow');
    }
  });
}

上面的代码中,没有一个语句是明显的操作数据库,感觉都在创建类、实例化类、调用类的方法,都在操作对象,但是数据库同步被持久了。

mongoose的哲学,就是让你用操作对象的方式操作数据库。

4.2 设计Schema发布model

创造schema → 定义一些schema的静态方法 → 创造模型

var mongoose = require('mongoose')
var Schema = mongoose.Schema
// 1.连接数据库
// 指定连接的数据库不需要存在,当你插入第一条数据之后就会自动被创建出来
mongoose.connect('mongodb://localhost/itcast')

// 2.设计集合结构(表结构)
// 字段名称就是表结构中的属性名称,约束的目的是为了保证数据的完整性,不要有脏数据
var userSchema = new Schema({
    username:{
        type:String,
        required:true
    },
    password:{
        type:String,
        required:true
    },
    email:{
        type:String
    }
})
// 可创建静态方法:userSchema.statics.sayHi = ...

// 3.将文档结构发布为模型
// mongoose.model方法就是用来将用一个架构发布为model
// 第一个参数:传入一个大写名词单数字符串用来表示数据库名称
//			  mongoose会自动将大写名词的字符串生成 小写复数 的集合名称
//			  例如这里的 User 最终会变成 users 集合名称
// 第二个参数:架构 Schema
// 返回值:模型构造函数
var User = mongoose.model('User', userSchema);

// 4.有了模型构造函数以后,使用这个构造函数对 users 集合中的数据进行操作(增删改查)

什么是静态方法,什么是类方法:

// 类
function Student(){}
// 实例化一个学生
var xiaoming = new Student();
// 实例方法,因为这个sleep方法的执行者是类的实例
xiaoming.sleep();
// 静态方法(类方法),这个方法的执行者是这个类,不是这个类的实例。
Student.findAllBuJiGe();

前台界面:不操作数据库,只操作类!

4.3 增删改查

操作语法
增加数据var admin = new User({username:'admin'}); admin.save(function(err,ret){...})
查询所有User.find(callback)如果中间有改过数据,会把更改前后的数据都给显示出来
按条件查询所有User.find({username:'admin'},callback)
按条件查询单个User.findOne({username:'admin'},callback)只查询一个,显示的是对象{},不是数组[]
不带条件的话,显示第一个对象,一般都会带条件的
删除数据User.remove({username:'admin'},callback)
根据条件更新所有Model.update(conditions,doc,[options],[callback])
根据指定条件更新一个Model.findOneAndUpdate([conditions],[update],[options],[callback])
根据id更新一个User.findByIdAndUpdate('id',{password:'123'}, callback)

五、cookie、session

cookie是在res中设置,req中读取的。第一次访问没有cookie。

cookie的存储大小有限,4k。对用户可见,用户可以禁用、清除Cookie、可以被篡改。

cookie用来制作记录用户的一些信息

HTTP是无状态的协议,所以两次的访问,服务器不能认识到是同一个客户端的访问,就要用cookie来巧妙的解决这个问题。

Session就是利用cookie,实现的“会话”。就是第一次访问的时候,可以在服务器上为这个用户缓存一些信息,别的用户不能看见这个用户的信息。服务器会下发一个秘钥(cookie),客户端每次访问都携带这个秘钥,那么服务器如果发现这个秘钥吻合,就能够显示这个用户曾经保存的信息。

登陆就是用Session来制作的。任何语言的session都是透明的,不会体现cookie机理。

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("欢迎" + req.session.username);
    }else{
        res.send("没有成功登陆");
    }
});
app.get("/login",function(req,res){
    req.session.login = "1";	// 设置这个session
    req.session.username = "考拉"
    res.send("你已经成功登陆");
});

都是使用req对象。

六、加密

永远不要用明码写密码

MD5加密是函数型加密。就是每次加密的结果一定相同,没有随机位。

特点:

  • 不管加密的文字,多长多短,永远都是32位英语字母、数字混合

  • 哪怕只改一个字,密文都会大变

  • MD5没有反函数破解的可能,网上的破解工具,都是通过字典的模式,通过大量列出明-密对应的字典,找到明码。

  • 两次加密网上也有对应的字典,所以我们不要直接用一层md5,这样对黑客来说和明码一样。

MD5常用于作为版本校验。可以比对两个软件、文件是否完全一致。

node中自带了一个模块,叫做crypto模块,负责加密。

首先创建hash,然后update和digest:

var md5 = crypto.createHash('md5');
var password = md5.update(fields.password).digest('base64'); 

七、图片处理

http://www.graphicsmagick.org

只要服务器需要处理图片,那么这个服务器就要安装graphicsmagick软件,免费的。

装完之后,可视化工具一点用都没有,从桌面上删除。我们要把安装目录设置为环境变量。

控制台CMD命令:

  • gm convert a.bmp a.jpg: 格式转换
  • gm mogrify -resize 320x200 danny.jpg:更改当前目录下*.jpg的尺寸大小,并保存于目录.thumb里面

node要使用graphicsmagick,需要npm装一个gm的包。

node缩略图的制作:

var fs = require('fs');
var gm = require('gm');
gm('./danny.jpg')
    .resize(50, 50,"!")
    .write('./danny2.jpg', function (err) {
        if (err) {
            console.log(err);
        }
	}
);

node头像裁切:

gm("./danny.jpg").crop(141,96,152,181).write("./2.jpg",function(err){
    // 141  96 是宽高   152  181是坐标
});

总结

ejs模式:

// 写服务
app.get("/allstudent", function(req,res,next){
    db.find("students", {}, function(err,result){
        // 寻找完毕之后,result就是一个数组,服务已经成功了,但是,界面必须要可视化,所以要有模板引擎呈递
        res.render("allstudent",{
            "result" : result;
        });
        // 如果不用模板引擎呈递,可以直接输出JSON,前台用Ajax或者Angular调用
        // var obj = {"result":result};
        // res.json(obj);
    });
});
<% for(var i = 0 ; i < result.length ; i++) {%>
    <div class="grid">
        <p class="title"><%=result[i].name%></p>	
        <p class="xuehao"><%=result[i].xuehao%></p>	
        <p class="sex"><%=result[i].sex%></p>	
    </div> 
<%}%>

Ajax模式:

// 写服务
app.get("/allstudent", function(req,res,next){
	db.find("students",{},function(err,result){
		// 如果不用模板引擎呈递,可以直接输出JSON,前台用Ajax或者Angular调用
		var obj = {"result":result};
		res.json(obj);
	});
});
======================================
<script type="text/template" id="tem">
	// 这里是一个underscore模板
	<div class="grid">
		<p class="title">{{=name}}</p>
		<p class="xuehao">{{=xuehao}}</p>	
		<p class="sex">{{=sex}}</p>	
	</div>
</script

前端页面: jQuery片段:
// 得到模板html
var templateString = $("#tem").html();
// ajax请求
$.get("/allsutdent",function(result){
	// 这个result就是一个json对象
    // 要放到页面上,所以为了不字符串拼接,可以用模板引擎underscore
	for(var i = 0 ; i < result.result.length ; i++){
		// 组装模板
		var compiled = _.compiled(templateString,{
			"name" : result.result[i].name;
			"sex" : result.result[i].sex;
			"xuehao" : result.result[i].xuehao;
		});
		// 上DOM
		$(".liebiao").append($(compiled));
	}
});

八、web Socket和Socket.IO框架

HTTP无法轻松实现实时应用

  • HTTP协议是无状态的,服务器只会响应来自客户端的请求,但是它与客户端之间不具备持续连接。

  • 我们可以非常轻松的捕获浏览器上发生的事件(比如用户点击了盒子),这个事件可以轻松产生与服务器的数据交互(比如Ajax)。

  • 但是,反过来却是不可能的:服务器端发生了一个事件,服务器无法将这个事件的信息实时主动通知它的客户端。

  • 只有在客户端查询服务器的当前状态的时候,所发生事件的信息才会从服务器传递到客户端。

但是,聊天室确实存在。

解决方法

  • 长轮询:客户端每隔很短的时间,都会对服务器发出请求,查看是否有新的消息,只要轮询速度足够快,例如1秒,就能给人造成交互是实时进行的印象。这种做法是无奈之举,实际上对服务器、客户端双方都造成了大量的性能浪费。

  • 长连接:客户端只请求一次,但是服务器会将连接保持,不会返回结果(想象一下我们没有写res.end()时,浏览器一直转圈)。服务器有了新数据,就将数据发回来,又有了新数据,就将数据发回来,而一直保持挂起状态。这种做法的也造成了大量的性能浪费。

  • WebSocket

8.1 WebSocket

WebSocket协议能够让浏览器和服务器全双工实时通信,互相的,服务器也能主动通知客户端了。

● 原理:利用HTTP请求产生握手,HTTP头部中含有WebSocket协议的请求,所以握手之后,二者转用TCP协议进行交流(QQ的协议)。现在的浏览器和服务器之间,就是QQ和QQ服务器的关系了。

所以WebSocket协议,需要浏览器支持,更需要服务器支持。

● 支持WebSocket协议的浏览器有:Chrome 4、火狐4、IE10、Safari5

● 支持WebSocket协议的服务器有:Node 0、Apach7.0.2、Nginx1.3

Node上需要写一些程序,来处理TCP请求。

● Node从诞生之日起,就支持WebSocket协议。不过,从底层一步一步搭建一个Socket服务器很费劲(想象一下Node写一个静态文件服务都那么费劲)。所以,有大神帮我们写了一个库Socket.IO。

8.2 Socket.IO

Socket.IO是业界良心,新手福音。

  • 屏蔽了所有底层细节,让顶层调用非常简单。
  • 还为不支持WebSocket协议的浏览器,提供了长轮询的透明模拟机制。

Node的单线程、非阻塞I/O、事件驱动机制,使它非常适合Socket服务器。

网址:http://socket.io/

下载库:npm install socket.io

写原生JS,搭建一个服务器,server创建好之后,创建一个io对象

var http = require("http");
var server = http.createServer(function(req,res){
    res.end("你好");
});
var io = require('socket.io')(server);
// 监听连接事件
io.on("connection",function(socket){
    console.log("1个客户端连接了");
}) 
server.listen(3000,"127.0.0.1");

写完这句话之后,你就会发现,http://127.0.0.1:3000/socket.io/socket.io.js 就是一个js文件的地址了。

现在需要制作一个index页面,这个页面中必须引用秘密js文件。调用io函数,取得socket对象。

<h1>我是index页面,我引用了秘密script文件</h1>
<script type="text/javascript" src="/socket.io/socket.io.js"></script>
<script type="text/javascript">
    var socket = io();
</script>

此时,在服务器上,app.js中就要书写静态文件呈递程序,能够呈递静态页面。

var server = http.createServer(function(req,res){
	if(req.url == "/"){
		// 显示首页
		fs.readFile("./index.html",function(err,data){
			res.end(data);
		});
	}
});

至此,服务器和客户端都有socket对象了。

每一个连接上来的用户,都有一个socket。 由于我们的emit语句,是socket.emit()发出的,所以指的是向这个客户端发出语句。

广播,就是给所有当前连接的用户发送信息:

// 创建一个io对象 
var io = require('socket.io')(server);
// 监听连接事件
io.on("connection",function(socket){
	console.log("1个客户端连接了");
	socket.on("tiwen",function(msg){
		console.log("本服务器得到了一个提问" + msg);
		io.emit("huida","吃了");
	});
});

复习顺序

  • Node.js特点:单线程、异步I/O(非阻塞I/O)、事件驱动(事件环)

  • 适合的程序:就是没有太多的计算,I/O比较多的业务。举例:留言本、考试系统、说说、图片裁切服务器

  • Node.js原生: http、fs、path、url。 静态服务、简单路由、GET、POST请求。

  • 模块:formidable、gm、express

  • Express:中间件、MVC建站、模板引擎ejs、静态服务、简单路由、GET、POST请求、MD5加密、图片上传。

服务器的一些概念:Cookie、Session

持久化NoSQL: 非关系型数据库,Not Only SQL。

  • 特点:没有schema,没有行和列。用文档(JSON)来存储。

MongoDB:安装、开启、导入数据、Shell管理数据库、Mongo Vue、Node.js做CRUD(增删改查)、DAO层的封装、索引、操作符$set $lt $gt $push $pull

Mongoose: ODM,不用直接操作数据库,操作对象,这个对象自动持久。

Defining your schema 定义文档结构

schema定义的时候,支持的类型:String、Number、Date、Buffer、Boolean、Mixed、ObjectId、Array

转换为对象:mongoose.model(modelName, schema):

定义对象(实例)方法:

// define a schema
var animalSchema = new Schema({ name: String, type: String });
// assign a function to the "methods" object of our animalSchema
animalSchema.methods.findSimilarTypes = function (cb) {
    return this.model('Animal').find({ type: this.type }, cb);
}

虚拟属性:

// define a schema
var personSchema = new Schema({
    name: {
        first: String,
        last: String
    }
});
// compile our model
var Person = mongoose.model('Person', personSchema);
// create a document
var bad = new Person({
    name: { first: 'Walter', last: 'White' }
});
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值