nodeJS
1、nodeJS最大的缺点:单线程,线程奔溃将会导致所有服务崩溃。
最大的优点:也在于单线程,最大化利用了硬件资源,node善于I/O,不擅长计算。
2、node最擅长的是调度,如果计算比较复杂,会对单线程的效率产生影响,相当于因为计算阻塞了单线程。
eg:
百度贴吧——————>主要业务使用python
——————>表单提交,nodeJS
node适合的场景:长连接,websocket,并发I/O
3、node 和 php java 各有优势,也无法造成其地位撼动
nodeJS不可能用在银行、证券、电信等可靠性要求较高的业务中。
一般地,node会用来处理业务的某一功能模块,而非整个后台架构都用node完成。
4、nodeJS没有web根目录的概念,它没有web容器。
web容器需要引入中间件。
eg:
var http = require("http");
var fs = require("fs");
http.createServer((req,res)=>{
fs.readFile("./test.html",(err,data)=>{
res.writeHeader(200,{
"content-type":"text/html;charset=UTF-8"
});
res.end(data);
})
}).listen(3000,"127.0.0.1");
nodeJS顶层路由设计
通过对来源的url进行判断,来响应不同的文件,
因此node可以进行高度自由化的路由设计。
eg:
if(req.url == "/xxx"){
fs.readFile("./test.html",(err,data)=>{
res.writeHeader(200,{
content-type:"text/html;charset=UTF-8"
});
res.end(data);
})
}
Tips:如果在读取的文件中,存在引用的链接,这个链接需要单独的设定路由,
来指向对应路径的文件。
Tips:res.end(data),data必须为字符串;
Tips:mime文件类型,在返回数据的时候,需要在content-type指定,便于浏览器引擎解析,
并且地,只有mime类型正确的返回时,其静态资源才能被前端正确地解析。
node原生模块
1、url
var http = require("http");
var url = require("url");
http.createServer((req,res)=>{
var path = url.parse(req.url);
req.end();
}).listen(3000,"127.0.0.1");
url.parse(req.url).pathname ————>网址路径
url.parse(req.url).query ————>url 链接上带的参数 ( "?"分隔 )
url.parse(req.url,true).query ————>true代表了queryString,这里解析的url转换换成了对象
string.substr(0,9); ————>截取 0 到 9 位
string.substr(10); ————>截取 10 位到末尾
2、fs模块
fs.readFile("./test.html",(err,data)=>{
res.send(data);
});
fs.mkdir("./xx/yuy"); ————>创建文件夹
fs.stat(path,(err,data)=>{}); ————>检测文件的相关属性,检测其状态
eg:
fs.stat("./album/bb",(err,data)=>{
data.isDirectory(); ——————>判断当前文件是否是一个文件夹
})
fs.readdir("./album",(err,files)=>{
//读取某个文件夹中的内容,
//files是由 当前文件夹中的 所有文件或文件夹 的文件名 组成的数组
})
* 迭代器,可用来遍历文件夹中的文件
var xx = [];
(function iterator(i){
if(i ==files.length ){
return;
};
fs.stat("./album"+files[i],(err,stats)=>{
if(stats.isDirectory()){
xx.push(file[i]);
}
iterator(i+1);
})
})
express
原生的node架起服务,开发应用都较为繁琐,因此出现了一些对原生js的封装库,
类似jquery和原生javascript一样,
express应运而生,
express就是对原生node的封装,是后台nodeJS框架。
(1)、路由能力
app.get("url",(req,res)=>{
//res.originUrl = res.baseUrl + res.path;
});
app.post("url",(req,res)=>{
});
* restful 路由设计
get:读取
add:添加
post:提交
delete:删除
Tips:当前的浏览器只支持get和post,一些软件支持post、delete多种请求方式;
* 动态路由设计
app.get("/room/:roomid",(req,res)=>{
//req.params.roomid即可访问到当前路由的动态路由值
});
Tips:注意,如果有自定义路由,也有静态资源服务,二者共存条件下,
应当避免静态资源的路径和自定义路由的路径冲突。
(2)、静态资源的处理
var express = require("express");
var app = express();
app.use(express.static("./public"));
app.listen(3000);
(3)、模板引擎
典型模板引擎,ejs。
需要 npm i ejs -S
默认的模板文件的路径为views文件夹,如果要设置其他文件夹作为模板文件目录,
app.set("view","./abc");
app.set("view engine","ejs");
eg:
var express = require("express");
var app = express();
app.set("view engine","ejs");
app.get("/",(req,res)=>{
res.render("jahah",{
"news":[xx,x,xxx,x,x,]
});
//在这里render之后,文件 ./views/jahah.ejs 将会插入news数据,并返回渲染到前端页面
})
中间件
(1)、
app.get("/",(req,res,next)=>{
next(); //next()执行后,路由将会向下匹配。
});
这就是一个中间件的最小实现。
Tips:express的路由一经匹配,pipe将会被阻断。
(2)、use函数
use函数将请求交给了第三方进行处理。
例如静态资源服务:
app.use(express.static("./public"));
app.use([path],(req,res,next)=>{
//在use的内部对请求的来源进行处理,处理后next()呈递到下一个中间件。
next();
})
Tips:如果希望给所有的请求来源都加上中间件,可以不写path。
Tips:res.send(data)将会自动设置mime类型,不需要自己设置。
GET、POST请求
(1)、原生nodeJS中,需要使用url模块来识别请求url字符串,
express中,可直接req.query获取到请求的url参数。
(2)、post请求,需要使用中间件来解析请求来源的body数据。
request header中,不同的content-type将会使用不同的中间件进行处理。
application/x-www-form-urlencoded :form格式的数据
multipart/form-data :带有二进制数据和json数据
application/json :json数据
text/xml :xml格式的数据
1、body-parser
body-parser用来处理form和json格式的数据。
如果数据中带有二进制数据,body-parser无法处理
eg:
const bodyParser = require('body-parser');
app.use(bodyParser.json({limit: '50mb'})); //设置数据的最大限制
app.use(bodyParser.urlencoded({ limit: '50mb',extended: true }));
Tips:req.body 可以获取到请求的post数据。
2、multer
multer专门用来处理 [ 带有二进制数据和json数据 ] 的数据
即 content-type = multipart/form-data
eg:
const multer = require('multer');
app.use(multer());
Tips:req.body 可以获取到请求的post数据 ,
req.file 可以获取到request的文件数据。
3、formidable
formidable既可以处理form和json格式的数据,也可以处理带有文件的数据。
也就是说,formidable兼具了body-parser和multer的功能。
eg:
const formidable = require("formidable");
app.post("/abcdefg",(req,res)=>{
var form = new formidable.IncomingForm();
form.parse(req,(err,fields,files)=>{
//fields 即为请求的post数据
//files 即为请求的request的文件数据
})
});
MVC架构
config ————>配置文件
models ————>数据模型
views ————>ejs文件,页面文件
controller ————>路由或业务处理
public ————>静态资源文件
app.js ————>服务入口文件
nodeJS的编程思维 ————>所有逻辑都异步
app.js开启服务,接收请求 ————> 中间件
————> router分发到具体的controller中
————> 具体业务处理
————>res.send 返回到前端
后台
1997年,第一个后台网页由微软推出,asp动态网页。
随着互联网的发展,ajax技术兴起,前后端开始分离,
后端省去了模板渲染的过程,由前端进行页面ajax请求,后端返回数据。
前后端结合 ————> 后端在html模板中插入数据,直接返回静态资源,
静态资源即为页面结果。
前后端分离 ————> 前端发起ajax请求,后端接收到请求后,后端请求数据库,向前端发送json数据,
前端接收到数据后插入到页面。
数据库
(1)、MySQL,SQLServer,Oracle(未开源)、Access
结构型数据库:每个表中都由明确的字段,每行记录都必定有这些字段,无数据的用null返回。
SQL缺点:1、插入字段需要遍历所有的数据,耗时极大;
2、字段数据类型要求全部一致,不够灵活。
大数据时代,传统的结构型数据库在一些 场景下显得笨拙,NoSQL应运而生。
SQL擅长条件筛选,因为SQL具有行和列的概念。
NoSQL擅长高并发,存取插入,不擅长筛选,灵活性比较高,不要求数据的高度一致性。
(2)、MongoDB
启动数据库
mongod --dbpath "./dbdatas"
数据库文件表现为 .ns 后缀,可直接拷贝迁移
命令行执行mongo,即可连接到数据库,并对数据库进行操作。
show dbs 列出所有的数据库
use [database name] 使用某一个数据库
Tips:如果use了一个不存在的数据库,在插入数据的时候,该数据库会自动创建。
db 查看当前所在的数据库
db.student.insert({"name":"xxx"}) 插入一条数据
Tips:student 是当前数据库下的一个集合,即collection
一个数据库中可以有多个collection
show collections 查看当前数据库下的所有collection
show student 列出当前集合下的所有数据。
一个数据库 有 多个collection ,
一个collection有多条数据,每条数据叫做一个文档
db.student.find( { "xxx":70 } )
db.student.find( { "xxx":{ $gt:70 } } ) //查找大于70的所有数据
Tips:$gt —————> 大于,$lt —————> 小于
db.student.find({}).sort({ "_id":-1 }) //按照降序排列
db.student.update( {userId:"xxx"} , { $set:{ month:5 } } )
//$set 表明更改该项值, 如果不加 $set 则为替换这条数据