二、node的简介
node是一个运行js的环境。浏览器也是运行js的环境。
两者的差别在于:
- 浏览器会有window和document的调用。然而node没有
- node有许多模块的api,例如文件系统拜访性能
- node能够切换运行环境(切换版本?)
- node不必bable转换
- node应用的是commonJS,要应用require
2-2 nodejs与js的区别
nodejs = nodejsapi + ecmascript
解决http,解决文件等。
2-3 commonjs
module.export()require
2-4,5 debuger之inspect协定
--inspect==9229
chrome://inspect/#devices
四、开发博客我的项目之接口
4-1 http 概述
从url到浏览器的过程?
首先dns解析,解析完了发送申请,通过http协定建设tcp链接,而后传输文件。
浏览器拿到数据而后建设dom树,建设css树。合并成render树,而后渲染,注入js。DNS解析,建设TCP连贯,发送http申请
server接管到http申请,解决并返回。
客户端接管到返回数据,解决数据,(如渲染页面,执行js)
Remote address 就是dns查问的后果
4-4 解决http申请的综合示例
const http = require("http");const port = 3000const server = http.createServer((req, res) => { res.setHeader("Content-Type", "application/json") const url = req.url const method = req.method res.end(`${url}${method}`);})server.listen(port, () => { console.log(`服务器运行在 http://localhost:${port}/`)})console.log("ok")
4-5 搭建开发环境
- 应用nodemon检测文件变动,主动重启node。
- corss-env设置环境变量
npm i nodemon cross-env --save-dev
"scripts": { "test": "echo \"Error: no test specified\" && exit 1", "dev": "cross-env NODE_ENV=dev nodemon ./bin/www.js" },
4-6 初始化路由
hostname:nodejs.cn
pathname:/api/blog/list
query:?name=zhangsan&keyword=123
const method = res.method // post getconst url = res.url // urlconst path = res.url.split("?")[0] //
4-7 开发路由
创立SuccessModel
、ErrorModel
。
class BaseModel { constructor(data, message) { if (typeof data === "string") { this.message = data; message = null; data = null } if (data) { this.data = data; } if (message) { this.message = message; } }}class SuccessModel extends BaseModel { constructor(data, message) { super(data, message); this.error = 0 }}class ErrorModel extends BaseModel { constructor(data, message) { super(data, message); this.error = -1 }}module.exports = { SuccessModel, ErrorModel}
4-8 开发路由(博客详情路由)
const fs = require('fs');const path = require('path');function getFileContent(fileName) { const fullFileName = path.resolve(__dirname, 'file', fileName) const promise = new Promise((resolve, reject) => { fs.readFile(fullFileName, (err, data) => { if (err) { reject(err); } resolve(JSON.parse(data)); }) }) return promise;}getFileContent('a.json').then(aDate => { console.log(aDate); return getFileContent(aDate.next);}).then((bData) => { console.log(bData); return getFileContent(bData.next);}).then((cData) => { console.log(cData);});
4-9 开发路由(解决POSTData)
// 用于解决post dataconst getPostData = (req) => { const promise = new Promise(() => { if (req.method !== 'POST') { resolve({}) return } if (req.headers['content-type'] !== "application/json") { resolve({}) return } }) // 监听流数据 let postData = '' res.on('data', chunk => { postData += chunk.toString() }) res.on('end', () => { if (!postData) { resolve({}) return } resolve( JSON.parse(postData) ) }) return promise}
更新和删除数据等....
5 数据库
MySql
use myblog;-- 查表-- show tables;-- insert into blogs(title,content,createtime,author)values("市民胡女士2的题目","市民胡女士2的内容",1585645673144,"mjmjmj");SELECT * FROM myblog.users LIMIT 0,1000;-- select username from users;-- select * from users where password like '%1%' order by id desc;-- select * from blogs;-- ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'password' PASSWORD EXPIRE NEVER;-- ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '11111111';-- flush privileges-- insert into blogs (title, content, createtime, author)values ('hhhhhh', 'jjhhhhh', 1585646800912, 'mjmjmj');-- select username, realname from users where username='mjmjmj' and password='321654a.'-- 更新-- SET SQL_SAFE_UPDATES = 0;-- update users set state = 0;-- update users set username ='huhuhu' where id = '2';-- 删除-- delete from blogs where id='1';
5.4 nodejs 操作 数据库
const mysql = require('mysql');const con = mysql.createConnection({ host: 'localhost', user: 'root', password: '11111111', port: '3306', database: 'myblog',})// 开始连贯con.connect()// 执行sqlconst sql = 'select * from users;';con.query(sql, (err, result) => { if (err) { console.log(err); return; } console.log(result);})con.end();
const mysql = require('mysql');const { MYSQL_CONF } = require("../conf/db");// 创立链接对象const con = mysql.createConnection(MYSQL_CONF);// 建设连贯con.connect();// 对立执行sql 的函数function exec(sql) { const promise = new Promise((resolve, reject) => { con.query(sql, (err, result) => { if (err) { reject(err); return } resolve(result) }) }) return promise;}con.end();module.exports = { exec}
6.2 Cookie 介绍
什么是cookie?
js如何操作cookie,如何在浏览器中查看cookie?
server端操作cookie,实现登录验证、
特点:
- 最大5kb
- 跨域不共享,
- 可保留结构化数据
- 每次发送http申请,会将申请域的cookoie 一起发送给cookie
- server 端能够批改cookie,并返回给客户端
- 客户端也能够通过js批改cookie,并返回给server端(有限度)
- 看申请的哪个域,申请哪个域,带哪个cookie
申请头外部的cookie
本地的缓存cookie
domin:cookie失效的域名
path:是cookie失效门路
批改cookie
有了localStorage ,本地批改cookie的状况不多
nodejs批改cookie
// 解析 cookie req.cookie = {} const cookieStr = req.headers.cookie || '' // k1=v1;k2=v2;k3=v3 cookieStr.split(';').forEach(item => { if (!item) { return } const arr = item.split('=') const key = arr[0].trim() const val = arr[1].trim() req.cookie[key] = val })
nodejs setCookie
// 登录 if (method === 'POST' && req.path === '/api/user/login') { const { username, password } = req?.body const result = login(username, password) return result.then(data => { if (data.username) { // 操作cookie res.setHeader('SetCookie', `username=${data.username}`) return new SuccessModel() } return new ErrorModel('登录失败') }) }
6.4 cookie 做限度
设置httpOnly
res.setHeader('SetCookie', `username=${data.username}; path=/; httpOnly`)
// 获取 cookie 的过期工夫const getCookieExpires = () => { const d = new Date() d.setTime(d.getTime() + (24 * 60 * 60 * 1000)) console.log('d.toGMTString() is ', d.toGMTString()) return d.toGMTString()}
res.setHeader('Set-Cookie', `userid=${userId}; path=/; httpOnly; expires=${getCookieExpires()}`)
6.6 session
cookie 中 会裸露username,很危险userid
、sid
、conentid
,对应server端username.
- session间接是js变量,放在nodejs过程内存中;
- 内存过大,会把过程的空间挤爆
- 多过程之间,数据无奈共享
6.8 redis
redis 解决多过程
不可能互通session
的问题(挤爆,多过程之间无奈数据共享。),是服务端罕用的缓存工具。
web server
最罕用的缓存数据库,数据寄存在内存中,相比mysql 读写速度快,然而比拟低廉,断电失落。
- 独自的服务,与nodejs之间只是调用关系。就像mysql一样,所以不存在被挤爆的状况。
- 多过程之间拜访同一个redis。所以session会同步。
- redis 可拓展,就算用户量减少,那也能够减少机器,能够拓展成集群。
session 对性能的要求极高
,因为每次都会发送申请。断电失落没关系,从新登录即可。所以不可能间接存在mysql中。
6.9
const redis = require('redis');const { REDIS_CONF } = require('../conf/db');// 创立客户端const redisClient = redis.createClient(REDIS_CONF);redisClient.on('error', (error) => { console.log(error);})function set(key, val) { if (typeof val === "object") { val = JSON.stringify(val); } redisClient.set(key, val, redis.print);}function get(key) { const promise = new Promise((resolve, reject) => { redisClient.get(key, (err, val) => { if (err) { reject(err) return } if (val == null) { resolve(null); return } try { resolve(JSON.parse(val)) } catch (ex) { resolve(val) } resolve(val); }) }); return promise;}module.exports = { set, get}
set myname mjget myname // mjget * // 获取所有key value
// 获取 session req.sessionId = userId get(req.sessionId).then(sessionData => { if (sessionData == null) { // 初始化 redis 中的 session 值 set(req.sessionId, {}) // 设置 session req.session = {} } else { // 设置 session req.session = sessionData } // console.log('req.session ', req.session) // 解决 post data return getPostData(req) }) .then(postData => { ...... }
6.14 为什么应用nginx
因为前端起的一个服务和nodejs起的服务不是同一个端口,而cookie跨域不共享。
应用http-server 起一个前端的服务。端口设置为8001。
nodejs:8000 端口
大家都去8080端口。
6.15 高性能的web服务器nginx),开源,收费
如果申请/
根目录,申请html,那么,nginx间接返回返回html
如果申请/api/blog/...
先到nginx端口8000,而后再到node服务的端口,8001.
对客户端不可见的代理,称为反向代理
应用easyconnect连贯,被称为正向代理
,客户端能够管制
- 测试配置文件格式是否正确:
ngnix -t
- 启动nginx 重启 nginx -s reload
- 进行 ngnix -s stop
sudo vi /usr/local/etc/nginx/nginx.conf
次要就是增加这些代码,而后把下面的一些正文掉。
location / { proxy_pass <http://localhost:8001>;}location /api/{ proxy_pass <http://localhost:8000>; proxy_set_header Host $host;}
感觉搞了半天,就是看懂了什么是redis,什么是session,什么是ngnix,代码外面就是配一配。