Node.js的诞生
Nodejs的创始人Rayn DahlNodejs的创始人Rayn Dahl发现PHP这种脚本语言,在处理网页请求的时候,随着访问量上来,要让Web业务支持更多的用户,就需要增加服务器的配置或者增加搭建集群,则这个时候的成本就上升了。
Rayn Dahl这个时候将Chrome浏览器的V8引擎(目前世界上最快的JS解析引擎)移植到了服务器上,开发出了Node.js平台。
2009年底,Ryan Dahl在柏林举行的JSConf EU会议上发表关于Node.js的演讲,之后Node.js逐渐流行于世。
Node.js是一个平台不是一个语言,开发语言仍然是JavaScript。此时Node.js平台可以让我们用JavaScript语言来开发服务器程序。
Node.js的安装
node.js可以安装在windows、mac、linux上,只需要下载对应平台的软件即可。
nodejs官网:http://nodejs.org/
nodejs中文网:http://nodejs.cn/
本次使用 8.7.0 这个版本进行演示。
下载对应的版本后,全程下一步进行安装即可。
Node.js的入门使用
javascript需要宿主环境才能运行。一般来说我们的浏览器可以提供该环境;但是nodejs平台也可以提供该环境。
在nodejs平台中运行js文件,此时需要使用CMD窗口。此时需要将CMD的“光标路径”更改为我们的项目文件夹。在对应的文件里面编写代码,然后使用node运行即可。
> node demo1.js
由于nodejs平台没有DOM所以不能使用下面的语法:
window、document、alert、document.getElementById()……
但是nodejs能够识别函数、if语句、for、while等等js核心语法。
nodejs常见模块
http模块
nodejs中的内置模块http模块,可以提供web服务。
// 得到内置http模块
var http = require("http");
//创建服务器,使用createServer方法来创建服务器。
//回调函数中有一个req参数表示请求,res参数表示响应。
var server = http.createServer(function(req,res){
res.setHeader("Content-Type","text/html;charset=UTF8");
//输出
res.write("哈哈");
res.end("Hello World!!!");
});
// 监听3000端口
server.listen(3000);
fs模块
fs是nodejs提供的一个用于读取磁盘文件的模块
fs模块最重要的api就是readFile,可以异步读取文件,第一个参数就是要读取的文件路径(注意:必须以./开头,表示从当前js文件出发寻找文件)。第二个参数是回调函数,表示读取完毕之后做的事情。
var fs = require('fs');
fs.readFile("./data.txt" , function(err , data){
console.log(data);
});
Express框架
问题引入
做http服务的时候,不方便:
- 匹配URL很不方便
- 使用静态页面不方便 fs.readFile(function(err,data){res.end(data)})
- 不能静态化一个文件夹,我们想将一个文件夹中的所有文件自动拥有路由,实现不了
Express简化了HTTP应用程序的开发。
cnpm intsall --save express
创建app和app的监听
我们引入express之后,这个express是一个函数,这个函数可以调用创建出一个app对象。
今后所有的操作都是用app对象来完成,需要注意的是,一个程序中只有一个app。
也就是说express不能多次调用。
var express = require("express");
var app = express();
// 业务代码
app.listen(3000);
中间件
app.动词("地址" , function(req,res){
});
// 示例
var express = require("express");
var app = express();
app.get("/get" , function(req,res){
console.log("get");
});
app.post("/post" , function(req,res){
console.log("post");
});
app.listen(3000);
中间件通配符-get参数
用:来表示表示一个通配,在程序中可以通过req.params.***得到它。
app.get("/:uid/:typeid" , function(req,res){
var uid = req.params.uid;
var typeid = req.params.typeid;
res.send(uid + typeid);
});
用next()放行拦截
当一个中间件已经匹配了路径,但是自己不希望单独处理这次请求,可以用next来放行。
输出
输出可以用res.send()做输出,会自动加上utf-8。
- res.send("中文");
- res.json({"username":"andy"});
- res.jsonp({"username":"andy"}); // 如果输出的内容是一个JSONP,此时要用res.jsonp()来输出,此时它会自动检测callback的GET请求,并且加上圆括号的调用。
- res.sendFile(__dirname + "/public/index.html");//如果输出的是一个外置页面,此时要用sendFile()这个API,注意这里必须要用绝对路径,此时我们用__dirname来进行一个拼合。
- res.redirect("http://www.163.com");//如果想要跳转页面,用res.redirect()即可
静态化一个文件夹
如果我们想让某文件夹中的所有文件自动拥有路由,此时非常简单,一句话即可。
app.use( express.static("public") );
//更进一步,如果我们不希望静态的文件夹出现在底层,而是在URL中体现public的名字。
app.use("/public" , express.static("public"));
Express中的GET请求和POST请求参数
GET请求参数的获得
GET请求参数的识别实际上就是URL地址的解析。URL解析使用内置的url模块的parse方法即可。
var url = require("url");
app.get("/users" , function(req,res){
var query = url.parse(req.url , true).query;
console.log("服务器收到了前端交来的数据" , query);
});
POST请求参数的获得
POST请求的参数携带在上行报文的报文体中。
我们使用npm包formidable来识别这样的上行报文。
API:https://www.npmjs.com/package/formidable
cnpm intsall formidable --save
var formidable = require('formidable');
app.post("/posts" , function(req,res){
var form = new formidable.IncomingForm();
form.parse(req , function(err , fields , files){
console.log( fields );
});
});
其他请求
注意只有GET请求是通过URL缀?参数来传递参数的。其他的http请求,都是通过上行报文来传参数的。formidable能够识别其他的请求的参数。
MongoDB
NoSQL简介
NoSQL就是除开关系型数据库的统称。
MongoDB数据库的安装
mongobooster可视化数据库管理软件
NodeJS操作MongoDB
手册:https://docs.mongodb.com/ecosystem/drivers/node-js/
或者:https://www.npmjs.com/package/mongodb
> cnpm install --save mongodb
var MongoClient = require('mongodb').MongoClient;
//数据库的地址,最末尾的斜杠是数据库的名称
var url = 'mongodb://localhost:27017/ceshi';
MongoClient.connect(url, function(err, db) {
if(!err){
console.log("数据库连接成功");
}else{
console.log("数据库连接失败");
return;
}
//查询
db.collection("collect1").find({}).toArray(function(err , docs){
console.log(docs);
});
//增加
db.collection("collect1").insert({"name":"asion", "age":23},function(err){
if(!err){
console.log("插入成功");
}
});
});
原生nodejs操作mongodb问题很多:
- 语法形式上大的回调函数太大了,要包裹所有的代码,甚至要包裹express的中间件;
- 不利于MVC编程,因为这些写代码几乎不能将所有对数据库的操作封装到一个文件中。
Mongoose
简介
Mongoose简化了nodejs对nodejs的操作。
安装
> cnpm install --save mongoose
基本使用
- 创建schema,根据schema创建model
var mongoose = require("mongoose");
//创建schema
var studentSchema = new mongoose.Schema({
"id" : Number,
"username" : String,
"age" : Number,
"gender" : String
});
//通过schema创建model 对一个参数代表是集合的名称,到时候会在mongodb里面转换为小写,并且转换为复数形式
var Student = mongoose.model("Student" , studentSchema);
//暴露
module.exports = Student;
- 根据模型得到实例化对象
var mongoose = require('mongoose');
//连接数据库
mongoose.connect('mongodb://localhost/xsgl');
//连接我们的model
var Student = require("./models/Student.js");
//实例化一个Student类的实例:
var xiaoming = new Student({
"id" : 10001 ,
"age" : 12,
"gender" : "男",
"username" : "小明"
});
//调用它的save方法即可放到数据库中持久化
xiaoming.save(function(err){
if(err){
console.log("保存失败");
}else{
console.log("保存成功");
}
});
curd操作
增加
// 方式一
var xiaoming= new Student({
"id" : 10001 ,
"age" : 12,
"gender" : "男",
"username" : "小明"
});
xiaoming.save((err)=>{
!err && console.log("成功");
});
// 方式二
Student.create({
"id" : 10001 ,
"age" : 12,
"gender" : "男",
"username" : "小明"
},(err)=>{
!err && console.log("成功");
删
// 方式一:先查询记录,然后remove
Student.find({"username" : "asion"} , function(err , results){
var rs= results[0];
rs.remove((err)=>{
!err && console.log("成功");
});
});
// 方式二:
Student.remove({"username" : "asion"} , (err)=>{
!err && console.log("成功");
});
改
// 方式一
Student.find({"username" : "asion"} , function(err , results){
var thepeople = results[0];
thepeople.sex = "女";
thepeople.save((err)=>{
!err && console.log("成功");
});
});
// 方式二:
Student.update({"username" : "asion"} , {"$set" : {"age" : 99}} , function(err){
!err && console.log("成功");
});
查
Student.find({"username" : "asion"} , function(err , results){
});
模板引擎
简介
如果要使用模板引擎,分为如下四步:
- 安装依赖,npm install --save ejs
- 设置默认模板引擎 app.set("view engine" , "ejs");
- 在views文件夹中创建一个.ejs后缀的页面,就是模板
- 在express的中间件中用res.render()来呈递视图,语法就是res.render(模板文件名字 , {字典});
安装模板引擎
> cnpm install --save express ejs
// 视图代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
</head>
<body>
<div class="wrap">
<h1><%=content%></h1>
</div>
</body>
</html>
// 业务代码
var express = require("express");
var app = express();
//设置默认模板引擎为ejs
app.set("view engine" , "ejs");
app.get("/" , function(req,res){
//现在多了一个res.render()表示使用模板页面
//不需要加上views文件夹,因为模板引擎默认就是放在views文件夹中的,也不需要加上.ejs后缀
res.render("detail" , {
"contente" : "网页内容"
});
});
app.listen(3000);
注意事项
- views文件夹可以改变,使用语句
app.set("views" , "templates");
// 这样所有的.ejs文件都要放到 templates文件夹中。
- 拓展名必须是.ejs,render的时候不需要写.ejs
- 可以使用一些for循环和if语句
<ul>
<% for(var i = 0 ; i < data.length ; i++){ %>
<li><%= data[i] %></li>
<% } %>
</ul>
// <% %>表示for循环、if语句;
// <%= %>表示输出
扩展
其他的模板引擎pug(原名叫做Jade):
https://www.npmjs.com/package/pug
cookie和session
简介
HTTP是无连接的,所以产生了身份识别问题
使用
express中使用cookie需要安装一个依赖cookie-parser
> cnpm install --save cookie-parser
// 设置
res.cookie('uid', 1, { maxAge: 86400 });
// 读取
var cookieParser = require('cookie-parser');
app.use(cookieParser());
//中间件中
app.get("/users" , function(req,res){
req.cookies.uid;
});
session
session在express中的使用,需要npm包:express-session。
> npm install --save express express-session ejs
app.post("/login" , function(req,res){
var form = new formidable.IncomingForm();
form.parse(req , function(err , fields){
// 设置session数据
req.session.login = true;
req.session.username= "andy";
});
});
文件上传
头像的上传很简单,因为formidable天生支持文件的上传,用files来接收即可。
gm图片裁剪
http://www.graphicsmagick.org/
> cnpm install --save gm
var gm = require('gm');
gm(avatarurl).crop(w,h,x,y).write(avatarurl, function (err) {
console.log("裁剪成功!");
});
网友评论