七、MongoDB
1、关系型数据库与非关系型数据库的区别
* 关系型数据库特点:
- sql语句增删改查操作
- 保持事务的一致性,事务机制(回滚)
mysql、sqlserver、db2、oracle
* 非关系型数据库特点:
- no sql:not only sql
- 轻量,高效,自由
mongodb、hbase、redis
* 为啥喜欢mongodb?
- 由于mongodb独特的数据处理方式,可以将热点数据加载到内存,
故而对查询来讲,会非常快(当然也会非常消耗内存);
同时由于采用了bson的方式存储数据,
故而对json格式数据具有非常好的支持性以及友好的表结构修改性,
文档式的存储方式,数据友好可见;
数据库的分片集群负载具有非常好的扩展性以及非常不错的自动故障转移
sql术语/概念
mongodb术语/概念
解释/说明
database
database
数据库
table
collection
数据库表/集合
row
document
数据记录行/文档
column
field
数据字段/域
index
index
索引
table joins
表连接,mongodb不支持
primary key
primary key
主键,mongodb自动将_id字段设置为主键
2、安装数据库
* https: //docs.mongodb.com/manual /administration/install -community/
3、启动数据库
mongod --dbpath d :/data/ db
mongo
mongod --config /usr/local /etc/mongod.conf
mongo
4、在命令行中操作数据库
* help查看命令提示
- help
- db.help()
- db.test.help()
- db.test.find().help()
* 创建/切换数据库
- use music
* 查询数据库
- show dbs
* 查看当前使用的数据库
- db/db.getName()
* 显示当前db状态
- db.stats()
* 查看当前db版本
- db.version()
* 查看当前db的链接机器地址
- db.getMongo()
* 删除数据库
- db.dropDatabase()
* 创建一个聚集集合
- db . createCollection("collName" ,{size:5242880 ,capped:true,max:5000 })
最大存储空间为5m,最多5000 个文档的集合
* 得到指定名称的聚集集合
- db . getCollection("account" )
* 得到当前db 的所有聚集集合
- db . getCollectionNames()
* 显示当前db 所有聚集的状态
- db . printCollectionStats()
* 删除
- db . users. drop()
* 添加
- db.users.save({name:"zhangsan" ,age:25,sex:true });
- db.users.save([{name:"zhangsan" ,age:25,sex:true },{name:"kerwin" ,age:100}]);
* 修改
- db.users.update({age:25},{$set :{name:"changeName" }},false ,true );
相当于:update users set name="changeName" where age=25;
- db.users.update({name:"lisi" },{$inc :{age:50}},false ,true );
相当于:update users set age=age+50 where name="lisi" ;
- db.users.update({name:"lisi" },{$inc :{age:50},$set :{name:"kerwin" }},false ,true );
相当于:update users set age=age+50,name="hoho" where name="kerwin" ;
* 删除
- db.users.remove({age:132});删除所有:db.users.remove({})
* 查询所有记录
- db.userInfo.find();
相当于:select * from userInfo;
* 查询某字段去重后数据
- db.userInfo.distinct("name" );
相当于:select distinct name from userInfo;
* 查询age=22 的记录
- db.userInfo.find({age:22 });
相当于:select * from userInfo where age=22 ;
* 查询age>22 的记录
- db.userInfo.find({age:{$gt:22 }});
相当于:select * from userInfo where age>22 ;
* 查询age<22 的记录
- db.userInfo.find({age:{$lt:22 }});
相当于:select * from userInfo where age<22 ;
* 查询age>=25 的记录
- db.userInfo.find({age:{$gte:25 }});
相当于:select * from userInfo where age>=25 ;
* 查询age<=25 的记录
- db.userInfo.find({age:{$lte:25 }});
* 查询age>=23 并且age<=26
- db.userInfo.find({age:{$gte:23 ,$lte:26 }});
* 查询name中包含mongo的数据
- db.userInfo.find({name:/mongo/});
相当于%%:select * from userInfo where name like "%mongo%" ;
* 查询name中以mongo开头的
- db.userInfo.find({name:/^mongo/});
相当于:select * from userInfo where name like "mongo%" ;
* 查询指定列name、age数据(想显示哪列,就将字段设置为1 ,不想显示就设置成0 )
- db.userInfo.find ({},{name:1 ,age:1 });
相当于:select name,age from userInfo;
* 查询指定列name、age数据,age>25
- db.userInfo.find ({age:{$gt:25 }},{name:1 ,age:1 });
相当于:select name,age from userInfo where age>25 ;
* 按照年龄排序(写成数组就是多列查询)
- 升序:db.userInfo.find ().sort ({age:1 });
- 降序:db.userInfo.find ().sort ({age:-1 });
* 查询name="zhangsan" ,age=22 的数据
- db.userInfo.find ({name:"zhangsan" ,age:22 });
相当于:select * from userInfo where name="zhangsan" and age=22 ;
* 查询前5 条数据
- db.userInfo.find ().limit(5 );
相当于:select top 5 * from userInfo;
* 查询10 条以后的数据
- db.userInfo.find().skip(10 );
相当于:select * from userInfo where id not in (select top 10 * from userInfo ) ;
* 查询在5 -10 之间的数据
- db.userInfo.find().skip(5 ).limit(5 );
* or 与查询
- db.userInfo.find({$or :[{age:22 },{age:25 }]});
相当于:select * from userInfo where age=22 or age=25 ;
* 查询第一条数据
- db.userInfo.findOne();
相当于:select top 1 * from userInfo;
相当于:db.userInfo.find().limit(1 );
* 查询某个结果集的记录条数
- db.userInfo.find({age:{$gte:25 }}).count();
相当于:select count (* ) from userInfo where age> =20 ;
5、可视化工具进行增删改查
* Robomongo Robo3T adminMongo
6、nodejs连接操作数据库
const mongoose = require ("mongoose" )
mongoose.connect ("mongodb://127.0.0.1:27017/company-system" )
const mongoose = require ("mongoose" )
const Schema = mongoose.Schema
const UserType = {
username : String ,
password : String ,
gender : Number ,
introduction : String ,
avatar : String ,
role : Number
}
const UserModel = mongoose.model ("user" , new Schema (UserType ))
module .exports = UserModel
UserModel.create ({
introduction, username, gender, avatar, password, role
})
UserModel.find ({username: "kerwin" }, ["username" , "role" , "introduction" , "password" ] )
.sort ({createTime: -1 }).skip (10 ).limit (10 )
UserModel.updateOne({
_id
}, {
introduction, username, gender, avatar
})
UserModel.deleteOne({_id })
八、接口规范与业务分层
1、接口规范
* restful架构:服务器上每一种资源,比如一个文件,一张图片,一部电影,都有对应的url地址,
如果我们的客户端需要对服务器上的这个资源进行操作,就需要通过http协议执行相应的动作来操作它,
比如进行获取,更新,删除。
* 简单来说就是url地址中只包含名词表示资源,使用http动词表示动作进行操作资源
* 举个例子:左边是错误的设计,而右边是正确的
- GET /blog/getArticles --> GET /blog/Articles 获取所有文章
- GET /blog/addArticles --> POST /blog/Articles 添加一篇文章
- GET /blog/editArticles --> PUT /blog/Articles 修改一篇文章
- GET /rest/api/deleteArticles?id =1 --> DELETE /blog/Articles/1 删除一篇文章
* 使用方式
- GET http://www.birjemin.com/api/user
- POST http://www.birjemin.com/api/user
- PUT http://www.birjemin.com/api/user/{id }
- DELETE http://www.birjemin.com/api/user/{id }
* 过滤信息
- 用于补充规范一些通用字段
- ?limit =10
- ?offset=10
- ?page=2&per_page=100
- ?sortby=name&order=asc
- ?state=close
2、业务分层
* router.js:负责将请求分发给C层
* controller.js:C层负责处理业务逻辑(V与M之间的沟通)
* views:V层负责展示页面
* model:M层负责处理数据(增删改查)
MVC架构
MVC架构
MVC架构
MVC架构
公司老板-接收客户请求(谈业务)
产品经理-自己啥也不干,负责将业务通知给项目经理
项目经理-分析业务逻辑,把任务分给UI和程序员
UI-负责看得见的界面
公司老板-接收客户请求(谈业务)
产品经理-自己啥也不干,负责将业务通知给项目经理
项目经理-分析业务逻辑,把任务分给UI和程序员
程序员-负责看不见的代码(页面的数据处理)
MVC架构
MVC架构
MVC架构
MVC架构
index.js服务器入口文件-负责接收客户端请求
router.js路由-负责将index.js接收到的请求分发给C层
C层controller-负责处理请求业务逻辑(把数据model交给视图view)
V层html文件
index.js服务器入口文件-负责接收客户端请求
router.js路由-负责将index.js接收到的请求分发给C层
C层controller-负责处理请求业务逻辑(把数据model交给视图view)
M层-hero.js负责数据的增删改查
九、登录鉴权
1、Cookie&Session
* 【http无状态】我们知道,http是无状态的。也就是说,http请求方和响应方间无法维护状态,都是一次性的,
它不知道前后的请求都发生了什么。但有的场景下,我们需要维护状态。最典型的,一个用户登陆微博,发布、
关注、评论,都应是在登录后的用户状态下的。【标记】那解决方法时什么呢?
* 浏览器 -> post账号密码 -> 服务端
服务端 -> 校验账号密码 -> 库(User)
库(User) -> 校验成功 -> 服务端
服务端 -> 存session -> 库(session)
服务端 -> Set-Cookie:sessionId -> 浏览器
浏览器 -> 请求接口(Cookie:sessionId) -> 服务端
服务端 -> 查session -> 库(session)
库(session) -> 校验成功 -> 服务端
服务端 -> 接口处理 -> 服务端
服务端 -> 接口返回 -> 浏览器
const express = require ("express" );
const session = require ("express-session" );
const MongoStore = require ("connect-mongo" );
const app = express ();
app.use (
session ({
secret : "this is session" ,
resave : true ,
saveUninitialized : true ,
cookie : {
maxAge : 1000 * 60 * 10 ,
secure : false ,
},
rolling : true ,
store : MongoStore .create ({
mongoUrl : 'mongodb://127.0.0.1:27017/kerwin_session' ,
ttl : 1000 * 60 * 10
}),
})
);
app.use ((req, res, next ) => {
if (req.url === "/login" ) {
next ()
return ;
}
if (req.session .user ) {
req.session .garbage = Date ();
next ();
} else {
res.redirect ("/login" )
}
})
2、json web token(jwt)
* 负载均衡 -> 机器A -session,session复制,机器B -session -> cluster
* 负载均衡 -> 机器A -session,cluster,机器B -session -> session存储
* 我为什么要保存这可恶的session呢,只让每个客户端去保存该多好?
- Header-{"UserID" :"ab14578" } -> 秘钥(HMAC-SHA256) -> 签名
- Header-{"UserID" :"ab14578" }-签名 -> 秘钥(HMAC-SHA256) -> 签名(相等吗?)
* 当然,如果一个人的token被别人偷走了,那我也没办法,我也会认为小偷就是合法用户,这其实和一个人的
session id被别人偷走是一样的。
* 这样一来,我就不保存session id了,我只是生成token,然后验证token,我用我的cpu计算时间获取了
我的session存储空间!
* 解除了session id这个负担,可以说是无事一身轻,我的机器集群现在可以轻松地做水平扩展,用户访问量
增大,直接加机器就行。这种无状态的感觉实在是太好了!
* 占带宽,正常情况下要比session_id更大,需要消耗更多流量,挤占更多带宽,假如你的网站每月有10 万次
的浏览器,就意味着要多开销几十兆的流量。听起来并不多,但日积月累也是不小一笔开销。实际上,许多人
会在jwt中存储的信息会更多。
* 无法在服务端注销,那么久很难解决劫持问题。
* 性能问题,jwt的卖点之一就是加密签名,由于这个特性,接收方得以验证jwt是否有效且被信任。对于有着
严格性能要求的web应用,这并不理想,尤其对于单线程环境。
* csrf攻击的原因是浏览器会自动带上cookie,而不会带上token;
* 以csrf攻击为例:
- cookie:用户点击了链接,cookie未失效,导致发起请求后后端以为是用户正常操作,于是进行扣款
操作
- token:用户点击链接,由于浏览器不会自动带上token,所以即使发了请求,后端的tokne验证不会
通过,所以不会进行扣款操作
const jsonwebtoken = require ("jsonwebtoken" )
const secret = "kerwin"
const JWT = {
generate (value, exprires ) {
return jsonwebtoken.sign (value, secret, {expiresIn : exprires})
},
verify (token ) {
try {
return jsonwebtoken.verify (token, secret)
} catch (e) {
return false
}
}
}
module .exports = JWT
app.use ((req, res, next ) => {
if (req.url === "/login" ) {
next ()
return ;
}
const token = req.headers ["authorization" ].split (" " )[1 ]
if (token) {
var payload = JWT .verify (token)
if (payload) {
const newToken = JWT .generate ({
_id : payload._id ,
username : payload.username
}, "1d" )
res.header ("Authorization" , newToken)
next ()
} else {
res.status (401 ).send ({errCode : "-1" , errorInfo : "token过期" })
}
}
})
const token = JWT.generate({
_id : result[0 ]._id,
username: result[0 ].username
}, "1d" )
res.header("Authorization" , token)
import axios from 'axios'
axios.interceptors .request .use (function (config ) {
const token = localStorage .getItem ("token" )
config.headers .Authorization = `Bearer ${token} `
return config;
}, function (error ) {
return Promise .reject (error);
});
axios.interceptors .response .use (function (response ) {
const {authorization} = response.headers
authorization && localStorage .setItem ("token" , authorization)
return response;
}, function (error ) {
const {status} = error.response
if (status === 401 ) {
localStorage .removeItem ("token" )
window .location .href = "/login"
}
return Promise .reject (error);
});
十、文件上传管理
* multer是一个node.js 中间件,用于处理multipart/form -data类型的表单数据,它主要用于上传文件。
* 注意:multer不会处理任何非multipart/form -data类型的表单数据
* npm install --save multer
* multer会添加一个body 对象以及file或files对象到express的request对象中。body 对象包含表单的
文本域信息,file或files对象包含对象表单上传的文件信息。
const params = new FormData()
params .append('kerwinfile' , file.file)
params .append('username' , this .username)
const config = {
headers: {
"Content-Type" : "multipart/form-data"
}
}
http.post('/api/upload' , params , config).then(res => {
this .imgpath = 'http://localhost:3000' + res.data
})
const multer = require ('multer' )
const upload = multer ({dest : 'public/uploads/' })
router.post ('/upload' , upload.single ('kerwinfile' ), function (req, res, next ) {
console .log (req.file )
})
十一、apidoc-api文档生成工具
* apidoc是一个简单的RESTful API文档生成工具,它从代码注释中提取特定格式的内容生成文档。
支持诸如Go、Java、C++、Rust等大部分开发语言,具体可使用apidoc lang命令行查看所有的支持列表。
* apidoc 拥有以下特点:
- 跨平台,linux、windows、macOS等都支持;
- 支持语言广泛,即使是不支持,也很方便扩展;
- 支持多个不同语言的多个项目生成一份文档;
- 输出模板可自定义;
- 根据文档生成 mock 数据;
* npm install -g apidoc
Add some apidoc comments anywhere in your source code:
Now generate the documentation from src/ into doc/.
$ apidoc -i src/ -o doc/
* 注意
- (1 ) 在当前文件夹下 apidoc.json
{
"name" : "****接口文档" ,
"version" : "1.0.0" ,
"description" : "关于****的接口文档描述" ,
"title" : "****"
}
- (2 )可以利用vscode apidoc snippets 插件创建api
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
2020-02-27 vue全家桶router、vuex、axios
2020-02-27 vue基础