什么是nodejs
node其实不是语言,是一个能够运行js的环境的平台,做前端的知道js,那么node中运行的js又跟前端运行的js又有什么差异呢。
前端的js: 脚本,不能单独运行的,需要嵌入在html里面。包括ECMAScript(js语法标准),Dom,Bom。
后端的js: node的作者把chrome的v8引擎抽取出来,做成了node平台,所以js可以独立的运行。但是后端的js只有ECMAScript(js语法标准),没有DOM和BOM。
可以查看官网学习:nodejs.cn/learn
javascript=ECMAScript + DOM + BOM
nodejs=ECMAScript + I/O(ps:i就是input输入,O就是output输出,一起就是基本输入输出设备)
为什么要学习nodejs
笔者因为不太懂接口的一些方式,比如post方式body里面的一些Content-Type参数,所以需要把它弄明白,顺便把nodejs学习一下,也为了方便自己写一些接口来测试前端的一些功能,再则现在更多的也是要求全栈了。
前端转全栈为什么选nodejs呢,经过上面的介绍,大家应该也明白了nodejs是一个环境,但是它的语言还是js,遵循ECMAScript语法标准(就是前端的js语法,只是后端少了BOM,DOM操作),那么学起来我们的成本更低,并且不会忘记js,如果选java那么学了那边这边忘了,或者那边久了没写又忘了不是得不偿失了,所以笔者很果断的选择了nodejs。
Content-Type 的认识
要学会nodejs一定需要知道Content-Type,那么我们先来了解一下什么是Content-Type,它有什么用,请接着往下读。
Content-Type 有什么用
接口发送参数、接收响应数据,都需要双方约定好使用什么格式的数据,例如 json、xml。
只有双方按照约定好的格式去解析数据才能正确的收发数据。
而 Content-Type 就是用来告诉你数据的格式,这样我们才能知道怎么解析参数。
如下图,我们可以看到接口的请求头和响应头中都有 Content-Type.
常见的 Content-Type
application/json:JSON数据格式,现在非常流行的格式
application/x-www-form-urlencoded:很常见的一种数据格式,post请求中通常默认是这个
multipart/form-data:上传文件时我们需要用到这个格式
application/xml:XML数据格式
text/html:HTML格式
text/plain:纯文本格式
image/png:png图片格式\
xml格式认识
1.2 XML的特点
有且只有一个根节点;
数据传输的载体;
所有的标签都需要自定义;
是纯文本文件
格式统一,符合标准;
容易与其他系统进行远程交互,数据共享比较方便。
1.3 XML的缺点
A、XML文件庞大,文件格式复杂,传输占带宽;
B、服务器端和客户端都需要花费大量代码来解析XML,导致服务器端和客户端代码变得异常复杂且不易维护;
C、客户端不同浏览器之间解析XML的方式不一致,需要重复编写很多代码;
D、服务器端和客户端解析XML花费较多的资源和时间。
<?xml version="1.0" encoding="utf-8"?>
<country>
<name>中国</name>
<province>
<name>黑龙江</name>
<citys>
<city>哈尔滨</city>
<city>大庆</city>
</citys> `
</province>
</country>
x-www-form-urlencoded 格式案例
这个格式会用=号连接参数名和参数值,并且会经过urlencode编码。
例如:title=test&sub%5B%5D=1&sub%5B%5D=2&sub%5B%5D=3
我们来看下 Chrome 中的请求参数(查看时需要点击view source才能看到原始数据,否则是经过解析后的),如下图,我们传递了 username 和 password 两个参数,可以看到他们是用=拼接参数和值,用&号拼接多个参数
multipart/form-data 格式案例
这个格式会在多个参数之前插入一段分隔字符,如下图,我们传递了 page 和 pageSize 两个参数,他的分隔字符串在 Content-Type 中用 boundary 标明了,这样服务端解析的时候才知道怎么拆分参数。
postman工具的使用
postman是我们学习nodejs需要的工具,用来调试接口,我们学习nodejs需要学会开服务器,学会中间件的使用,学会做一些简单的接口。
postman工具的界面
POST方法body类型的介绍
以post类型接口为例,先来介绍一下post类型接口的body有哪些Content-Type
| post参数格式 | Content-Type | 参考示例 |
|---|---|---|
| 表单提交 | application/x-www-form-urlencoded | username=abc123&password=123 |
| JSON提交 | application | {"username": "abc123","password": "123"} |
| xml提交 | text/xml | <?xml version="1.0" encoding="utf-8">悟空传 |
1.form-data(常用于上传文件)
Content-Type:multipart/form-data,它将表单的数据组织成Key-Value形式,用分隔符boundary(boundary可任意设置)处理成一条消息。由于有boundary隔离,所以既可以上传文件,也可以上传参数。
既可以上传文件等二进制数据,也可以上传表单键值对,只是最后会转化为一条信息。当设置multipart/form-data,http会忽略 contentType 属性
2.x-www-form-urlencoded(post请求常用)
Content-Type:application/x-www-from-urlencoded,将表单内的数据转换为Key-Value。
application/x-www-form-urlencoded是默认的MIME内容编码类型,它在传输比较大的二进制或者文本数据时效率极低。
只能上传键值对,不能用于文件上传。不同的field是用&区分开的。
3.raw(json数据)
Content-Type:application/json,可以上传任意格式的文本,可以上传text、json、xml、html等。
4.binary(只可以上传二进制文件)
Content-Type:application/octet-stream,只可以上传二进制数据,通常用来上传文件。由于没有键值,所以一次只能上传一个文件。
正式开始学习nodejs
安装nodejs
我们需要先安装一下nodejs,相信能看到这里的童鞋已经有一定的前端基础了,也安装了nodejs,如果没有的同学先去安装nodejs喔。
可以使用node -v来检测一下是否有安装nodejs,如果有会出现一个版本号,如下图。
没有的童鞋可以去官网下载一个来安装,一直下一步下一步就好没有什么技术含量。
官网下载地址:nodejs.cn/download/
nodejs可以直接执行js文件,假设我们有一个js文件(helloworld.js),在cmd中进入到helloword.js所在的文件夹,执行指令node helloworld.js
//helloworld.js
console.log("hello world")
cmd中就会输出hello world效果如下
js分模块化语法
方法一:module.exports 一个文件中只能出现一次,出现多次的话后者会覆盖前者
module.exports = show; //导出模块,暴露模块
let fn = require("./02 exports"); //相对路径的写法
module.exports = {//导出多个数据的时候:
show,
obj,
num,
};
let { num } = require("./02 exports");
方法二:export
exports.show = show;
exports.obj = obj;
exports.count = num;
let { count } = require("./04 exports");
模块化规范有哪些
AMD(异步,推崇依赖前置) 代表:requirejs(异步) 优点:模块化开发 define()定义模块,require()引入模块CMD(异步,依赖后置) 代表:seajs(中国人写的-王保平(玉伯),目前就职于阿里),现在seajs不再维护(异步) 优点:模块化开发 define()定义模块,require()引入模块ES6 module(同步) 导入:import 导出:export
commonjs代表:nodejs遵循的规范(同步) 实际上,nodejs提供很多的方法都是异步操作(回调函数) :导出:module.exports 、exports 导入:require()script标签引入js文件,一个js就是一个模块,依赖要放在前面(同步),缺点:前面的js会影响后面js的加载:导入:引入script写好src-
- 同步:阻塞模式(会影响后面的代码)
- 异步:非阻塞模式
node中的模块类型
原生模块:安装nodejs就自带的,直接引入使用。
文件模块:json数据。
第三方模块:安装再引入使用,如express,mysql,mongo。
自定义模块:exports,module.exports,require()。
express
安装express
npm init -y
npm install express -S
什么是express
它是一个开服务器的js文件,就是我们说的模块
Express 是一个第三方模块,对原生模块封装了一套更灵活、更简洁的应用框架,其在 Node.js 环境的地位和作用好比 jQuery 在前端的地位和作用。使用 Express 可以快速地搭建一个完整功能的网站;为了方便重启服务器,不用每次改完就要运行node命令,建议大家安装superviosor server.js 一旦你有更新,就会自动刷新服务器 官方中文API:www.expressjs.com.cn/
使用express
写一个简单的server.js文件,在同级下准备好index.html文件,node中去执行这个文件,浏览器访问http://localhost:8080 便能看到写的index.html文件
//1.安装 express : npm i express -S 保存生产依赖
//2.引入模块
let express = require("express"); //绝对路径
//3.使用模块
let app = express(); //实例化过程
// app.use(express.static("./",{index:'main.html',maxAge:5000})); //利用express的static方法开启静态资源服务器
app.use(express.static("./")); //利用express的static方法开启静态资源服务器
//4.开启服务器
app.listen(8080, () => {
console.log("服务器已开启,请访问:http://localhost:8080");
});
创建一个最小的demo
const express = require('express')
const app = express()
const port = 3000
app.get('/', (req, res) => {
res.send('Hello World!')
})
app.listen(port, () => {
console.log(`Example app listening on port ${port}`)
})
全局安装supervisor
yarn add supervisor -g
什么是supervisor
用supervisor管理的进程,当一个进程意外被杀死,supervisor监听到进程死后,会自动将它重启,很方便的做到进程自动恢复的功能,不再需要自己写shell脚本来控制。
官方中文API:www.expressjs.com.cn/
参考文献: www.cnblogs.com/hls-code/p/…
使用supervisor
supervisor server.js
开服务器的一些语法
app.METHOD(PATH, HANDLER)
- app是 的一个实例express。
- METHOD是一个HTTP 请求方法,小写
- PATH是服务器上的路径。
- HANDLER是路由匹配时执行的函数。
app.get('/', function (req, res) {
res.send('Hello World!')
})
app.use(express.static('./'))
app.use(express.static({path:"./",index:'main.html',maxAge: 500})
//访问index.html
app.use(express.static('files'))
//如果要使用多个静态资源目录,请多次调用 `express.static` 中间件函数
app.use(express.static('public'))
//通过如下代码就可以将 `public` 目录下的图片、CSS 文件、JavaScript 文件对外开放访问了
//http://localhost:3000/images/daji.jpg
express.static(root, [options])
app.use('/static', express.static('public'))
//虚拟路径
http://localhost:3000/static/images/daji.jpg
const path = require('path')
app.use('/static', express.static(path.join(__dirname, 'public')))
express中间件
中间件其实就是一个函数,但是函数不一定是中间件,中间件例如
app.use("/login", (request, response, next) => {
console.log('注意这里打印的东西是在命令行中显示的,通常被用来调试接口')
})
//其中后面的这个函数就是一个中间件
实现一个接口(实现一个路由),在postman中调用,通常是多个路由并用
//use() 代表什么请求方式都可以进入
app.use("/login", (request, response, next) => {
/*
request:请求对象,前端发送的请求相关数据都存在这个对象里面
response:响应对象,用这个对象里面的send()就可以给前端响应数据
next:进入下一个中间件
*/
console.log("进到这个login路由里面了"); //打印到cmd的命令行里面,一般是用于后端自己测试接口
response.send("登录成功"); //一个路由下只能有一个响应
});
端口范围,以及next()何时使用
一般端口范围尽量写1000~60000 除了最后一个路由,其余路由都需要使用
实现两个路由,并且分别调用
app.use("/login", (request, response, next) => {
/*
request:请求对象,前端发送的请求相关数据都存在这个对象里面
response:响应对象,用这个对象里面的send()就可以给前端响应数据
next:进入下一个中间件
*/
console.log("进到这个login路由里面了"); //打印到cmd的命令行里面,一般是用于后端自己测试接口
response.send("登录成功"); //一个路由下只能有一个响应
});
app.use("/reg", (request, response, next) => {
/*
request:请求对象,前端发送的请求相关数据都存在这个对象里面
response:响应对象,用这个对象里面的send()就可以给前端响应数据
next:进入下一个中间件
*/
console.log("进到这个reg路由里面了");
response.send("注册成功");
});
RESTful接口规范
- 根据请求类型实现不同的接口
- 根据url地址实现不同接口
- 接口可读性强
例如:
- 获取商品数据---get
- 增加一个商品---post
- 删除一个商品---delete
- 修改一个商品---patch/put
- patch---部分修改
- put---全部修改
需要给前端返回使用方法例如:
exapmle
用户管理:
* 验证用户名是否存在 :get
* 注册 : post
* 登录 : get
* 退出 : delete
* 删除用户 : delete
* 查询用户列表 :get
* 修改用户信息 :put
上面例子判断的依据可以根据是否要插入一条数据到数据库,需要插入则用post
制定接口时数据的接收
- get请求的数据---req.query.**
- post请求的数据---req.body---undefined---需要中间件转一下才能看的到
发送请求
post请求的处理
app.use(express.urlencoded());
//处理name=马源123&age=18
//body实际上传递过来的数据是这样的,不能直接访问到,需要转成对象才能直接访问到
app.use(express.json());
//处理json数据 '{name:王祖贤,age:18}'
//后端拿到的是字符串对象,将其转化为对象
接口的动态路由传参跟body传参的区别
//body传参
app.post("/user/reg", (req,res)=>{
res.sent('成功')
})
//动态路由传参
//http://localhost:8090/user/edit/2
app.put("/user/reg/:id", (req,res)=>{
console.log(req.params.is)
res.sent('成功')
})
路由的分模块化
结构如下图
api>server.js 开启服务器
//express的使用-开启服务器
//1.安装 express : npm i express -S 保存生产依赖
//2.引入模块
let express = require("express"); //绝对路径
let { PORT } = require("./config.json");
let allRouter = require("./router/index"); //allRouter是中间件
// console.log(config);
//3.使用模块
let app = express(); //实例化过程
// app.use(express.static({path:"./",index:'main.html',maxAge:5000})); //利用express的static方法开启静态资源服务器
app.use(express.static("./")); //利用express的static方法开启静态资源服务器
//使用路由进行接口管理:主路由
app.use(allRouter);
//4.开启服务器
app.listen(PORT, () => {
console.log("服务器已开启,请访问:http://localhost:" + PORT);
});
api>config.json-配置端口
{
"PORT": 2004
}
api>router>index.js
//主路由
let express = require("express"); //绝对路径
//创建路由对象
let Router = express.Router(); //Router==app
//引入子路由
let userRouter = require("./modules/users"); //用户管理子路由
let goodRouter = require("./modules/goods"); //用户管理子路由
let orderRouter = require("./modules/orders"); //用户管理子路由
Router.use("/user", userRouter); //用户管理子路由
Router.use("/good", goodRouter); //商品管理子路由
Router.use("/order", orderRouter); //订单管理子路由
// Router.use("/good", (req, res) => {
// console.log("进入主路由");
// res.send("进入good路由");
// });
// Router.use("/order", (req, res) => {
// console.log("进入主路由");
// res.send("进入order路由");
// });
module.exports = Router; //导出主路由
api>router>modules>goods.js
//子路由
let express = require("express"); //绝对路径
//创建路由对象
let Router = express.Router(); //Router==app
module.exports = Router;
api>router>modules>order.js
//子路由
let express = require("express"); //绝对路径
//创建路由对象
let Router = express.Router(); //Router==app
module.exports = Router;
api>router>modules>users.js
//子路由
let express = require("express"); //绝对路径
//创建路由对象
let Router = express.Router(); //Router==app
/*
用户管理:restful接口规范
* 验证用户名是否存在 :get
* 注册 : post
* 登录 : get
* 退出 : delete
* 删除用户 : delete
* 查询用户列表 :get
* 修改用户信息 :put
*/
let userinf = [
{
uid: 1,
name: "leyi",
},
{
uid: 2,
name: "jack",
},
{
uid: 3,
name: "志远",
},
];
//验证用户名是否存在
Router.get("/checkname", (req, res) => {
// console.log(req, 888);
// console.log(req.query, 999);
let { name } = req.query;
// console.log(name);
let result = userinf.filter((item) => item.name == name).length; //找到名字相同,返回数组
let data = {};
if (result) {
//非0数字都是真。 细节: 0 假; '0' 真; '' 假
//找到:不给注册
data = {
code: 0,
message: "该用户已存在,不能注册",
};
} else {
//没有找到:允许注册
data = {
code: 1,
message: "允许注册",
};
}
// res.send("666");
res.send(data);
});
module.exports = Router;
关系型数据库跟非关系型数据库基础差异
mongoDB下载中心
www.mongodb.com/try/downloa… 下载界面如下:
检测是否有安装好,随便打开一个目录
安装Robo3t
安装一个软件才能看到mongoDB数据库里面数据的变化
创建链接
创建数据库
查找数据
写mongoDB接口
安装mongoDB模块
npm install mongoDB --save
mongo链接数据库语法
//写代码对mongoDB的数据进行增删改查 CRUD
//1.安装数据库管理模块 npm i mongodb -S
//2.引入mongodb模块
const { MongoClient } = require("mongodb");
//连接mongoDB
MongoClient.connect("mongodb://localhost:27017", async (err, client) => {
if (err) throw err;
// 1.连接数据库,无则自动创建
let db = client.db("h52004");
//2.连接集合
let col = db.collection("users");
//3.CRUD 增删改查
//增 C create
//删 D delete
//改 U update
//查 R retrieve
let arr = await col.find({ username: "Jason Williams" }).toArray();
console.log(arr);
// db.createCollection("users", function (err, res) {
// if (err) throw err;
// console.log("创建集合!");
// //增
// //删
// //改
// //查
// client.close();
// });
});
数据库的备份和还原
链接数据库的几个必不可少的条件
1.必须有数据库 2.有开启node serve.js服务,开启端口可访问 3.链接url,数据库名,集合名