数据资源网站如何做,网页设计素材图片大全,香河县最新消息,网站模板下载源码目录
1 一些注意
2 创建数据库
3 项目结构
4 配置文件 config.js
5 参数规则包 hapi/joi与escook/express-joi
5.1 安装
5.2 文档中的demo
5.2.1 定义规则
5.2.2 使用规则
5.3 项目中的使用
5.3.1 定义信息规则
5.3.2 使用规则
6 密码加密包 bcrypt.…目录
1 一些注意
2 创建数据库
3 项目结构
4 配置文件 config.js
5 参数规则包 hapi/joi与escook/express-joi
5.1 安装
5.2 文档中的demo
5.2.1 定义规则
5.2.2 使用规则
5.3 项目中的使用
5.3.1 定义信息规则
5.3.2 使用规则
6 密码加密包 bcrypt.js
6.1 加密
6.2 对比
7 处理form-data数据包 multer
7.1 安装
7.2 项目中的使用
8 入口文件 main.js
8.1 约束一些请求
8.2 注册所有路由模块
8.3 处理请求体 1 一些注意
不要认为接口中的message没什么用就不写了写上在排错与前端调用的时候都比较方便这里面记录了该项目后端的详细实现方式 api_server_ev 在这个链接中关于文章列表后面几个视图没有写如果只看接口文档可以看这个 ShowDoc在实际开发的时候express有时会出现错误后服务就断掉且与其他模块可能会出现协同性的问题(不是一家开发的比如mysql出现了问题给express错误处理中间件服务也会断掉)实际开发中应该将路由与视图不在同一个文件写符合模块化开发的要求我这里就写在一起了因为对于一个小项目来讲一共就十几个url摊到每个模块也就四五个url你过度封装反而会导致你维护的时候不好找一会儿点开这个一会儿点开那个。分开写的原因是当路由多的时候可以一个人搞路由一个人搞视图分开写的缺点是从主函数到视图函数会出现多级的调用对于单人开发就显得不是很友好大事件项目后端视频 07.项目-初始化项目_哔哩哔哩_bilibili P77-P96
2 创建数据库
数据库使用的是mysql数据表有三个分别是 用户信息数据表文章分类数据表文章内容数据表
三个数据表的这些信息都是一样的 用户信息数据表其中user_pic是用户头像要求为base64字符串我们的Datatype可以写为TEXT 文章信息数据表 文章分类数据表 三张表都是没有外键的我们让用户在上传文章的时候要上传用户id(后端根据token自动添加参数)然后显示的时候根据用户id进行筛选(后端根据token自动筛选)从而用户只会看到自己的文章
文章分类没有给author_id实际上也可以再加一个author_id让每一个用户都有自己专属的分类
3 项目结构
项目结构如下最上面的uploads放前端传过来的文章封面config.js中有一些配置main.js是入口文件运行的时候node main.js router是四个模块的路由 4 配置文件 config.js
我使用了一个config.js文件作为配置文件里面有很多的全局变量config文件内容没有做导出在使用的时候直接引入config就行了
config.js中有需要导入的库token密钥数据库配置文章封面存放的文件夹以及一些验证规则
// 需要导入的库
joi require(joi)
mysql require(mysql)
express require(express)
jsonwebtoken require(jsonwebtoken)
bcryptjs require(bcryptjs)
expressJoi require(escook/express-joi)
cors require(cors)
multer require(multer)
path require(path)// token密钥
secretKey xifgnmuioherawbt// 数据库
db mysql.createPool({host:127.0.0.1,user:root,password:12345678,database:big_things
})// 文章封面存放的文件夹
uploads multer({dest:path.join(__dirname,../uploads)})// id的验证规则都是相同的所以可以统一来写
id_rule joi.number().integer().min(1).required()
// 用户信息表 验证规则
userinfo_username_rule joi.string().alphanum().min(1).max(10).required()
userinfo_password_rule joi.string().pattern(/^[\S]{6,12}$/)userinfo_nickname_rule joi.string().required()
userinfo_email_rule joi.string().email().required()
userinfo_avatar_rule joi.string().dataUri().required()// 文章分类表 验证规则
category_name_rule joi.string().required()
category_alias_rule joi.string().alphanum().required()// 文章列表 验证规则
article_title_rule joi.string().required()
article_content_rule joi.string().required().allow()
// 分类id与状态 有的时候需要必选有的时候不需要必选所以在总的规则中取消了required()需要的时候你再加上就行了
article_cate_id_rule joi.number().integer().min(1)
article_state_rule joi.string().valid(已发布, 草稿)
// 文章列表要做分页pagenum是要看第几页
article_pagenum_rule joi.number().integer().min(1).required()
// pagesize是每页显示多少条数据
article_pagesize_rule joi.number().integer().min(1).required()
简单看一下导入的库
joi与express-joi 前端传入信息规则验证mysql 数据库express 后端框架jsonwebtoken 做token的用于前后端跨域信息验证bcryptjs 密码加密cors 做跨域的multer 处理前端传入的form-data数据的path 路径拼接
其中 mysql在这里有具体用法 8.mysql模块_Suyuoa的博客-CSDN博客
express,jsonwebtoken,cors在这里有具体用法 7.Express模块基础用法_express 引入模块_Suyuoa的博客-CSDN博客
5 参数规则包 hapi/joi与escook/express-joi
后端是一定要加数据验证的不要因为前端做了验证后端就不做了宁可多做不要少做
我们如果每个验证都写if else那样的话代码量较多维护起来比较麻烦我们可以借助一些第三方的包来搞
如果规则较简单的时候也可以不用轮子太多也不利于项目的维护有时候搞来搞去发现轮子不好用最好还有查轮子的文档比如我就遇到了这个问题还得在网上查一下怎么搞定这个错误 【node.js】报错Cannot mix different versions of joi schemas解决方法_前端小二哥的博客-CSDN博客 hapi/joi 是定义规则用的escook/express-joi 是验证规则用的
hapi/joi是escook/express-joi的依赖在导入的时候要先导入hapi/joi再导入escook/express-joi
5.1 安装 5.2 文档中的demo
在npm官网上搜索escook/express-joi会出现它的简易demo
5.2.1 定义规则 我们看userSchema这个对象其中有body,query,params分别的意思就是req.body,req.query,req.params
有什么写什么就行比如只验证req.body就只写body就行
body,query,params这三个名称固定
下面看body中的内容里面username这些是参数名后面跟的是验证规则。可以给验证规则自己定义一个变量方便复用
验证规则的名字一般我们保持与接收的参数名一致就行如果不一致你就需要这样写
实则还是遵循键值的格式Joi.string()是先让其变成字符串形式Joi.number().integer()是让其先变成数字型然后变为整形
alphanum()表示这个字符串中只能包含 a-z A-Z 0-9
min()与max()是字符串的最小最大长度如果类型是数字那么就代表最大值最小值
required()表示是必选参数
patter()内加正则表达式用于验证规则
repassword这个就是重新输入密码的参数名joi.ref(password)的意思是必须与password保持一致
只有写在body中的内容才会被接收如果你多给了是存不到req.body中的比如上面我给了id,nickname.email如果你再多给一个password最后你查req.body中是没有password的
5.2.2 使用规则
userSchema是我们刚刚定义的规则如果在路由中出现了验证不通过的情况就会抛出一个错误抛出错误后下面定义一个错误级别中间件这个错误级别中间件会把错误的信息返回给客户端 5.3 项目中的使用
5.3.1 定义信息规则
我们下面看一下传入信息的规则规则都放在config.js中搞的全局变量后面在验证的时候直接使用这个全局变量就好 number() 必须为数字integer() 必须为整形min(1) 当值为数字时最小值为1当值为字符时最小长度为1required() 必须传入string() 必须为字符串alphanum() 只能包含 a-z,A-Z,0-9max(10) 当值为数字时最大值为10当值为字符时最大长度为10pattern(/^[\S]{6,12}$/) pattern中是正则的用法这里是6-12位非空字符串email() 必须为邮箱格式dataUri() 比如是dataUri格式比如 data:image/png;base64,VE9PTUFOWVNFQ1JFVFM 项目中用其处理base64图像字符串allow() 允许为空valid(已发布, 草稿) 值只能为 已发布 或 草稿
5.3.2 使用规则
首先定义一个对象如果是get的查询字符串传递就写query 如果是post就写body,form-data与xxx-www-form-urlencoded都用body 如果是拼接路由就用params 当有不符合规则的信息时在main.js中加入一个中间件提示客户端错误信息 6 密码加密包 bcrypt.js
可以通过 beryptjs 来对密码部分进行加密首先定义一个密钥这个密钥就随便写就行密码会根据这个密钥进行加密与解密我在config.js中定义了一个全局变量secretKey 6.1 加密
在注册的时候加密后存储数据库加密方法为 bcryptjs.hashSync()第一个参数为加密的内容第二个参数是哈希烟的长度 即使是相同的密码也会得到不同的加密结果
6.2 对比
使用bcyptjs.compareSync()将传入的密码与数据库中存储的真实密码进行比对 7 处理form-data数据包 multer
multer是处理 multipart/form-data 表单上传的数据用的(Multer 不会处理任何非 multipart/form-data 类型的表单数据)
7.1 安装 7.2 项目中的使用
我们先看几个关于multer的信息
传上来的文件被存储在uploads文件夹中每一次成功传输会生成一个这样的文件 在mysql中会存储文件的路径 下面我们来看使用
在config.js中我们指定了一个文件夹用来放文章封面,dest这个键就是放在那个位置的意思 这里只是管把文件存在哪个实际的地方和数据库中的数据无关
使用single()方法参数为传递的文件参数名single()方法会让cover_img存在req.file中我们打印出 req.file.filename 看一下 打印出来的结果只有文件名 下面用path.join()只和数据库中的信息有关和实际文件存在哪里无关
8 入口文件 main.js
const config require(./config.js)const login_register_router require(./router/login_register.js)
const personal_center_router require(./router/personal_center.js)
const article_category_management_router require(./router/article_category_management.js)
const article_list_management_router require(./router/article_list_management.js)const { expressjwt: jwt } require(express-jwt)const app express()app.use(function (req, res, next) {res.setTimeout(5*1000, function () {res.send(请求超时)});next();
});
app.use(jwt({secret: secretKey,algorithms: [HS256],}).unless({ path: [/^\/api\//] })
)
app.use(cors())
app.use(express.urlencoded({extended:false}))app.use(login_register_router)
app.use(personal_center_router)
app.use(article_category_management_router)
app.use(article_list_management_router)app.use((err,req,res,next) {// 判断用户提交的信息if (err instanceof joi.ValidationError) return res.send({status:1,message:err.message})// 判断tokenif (err.name UnauthorizedError) {return res.send({status:1,message:无效的token})}// 其他错误return res.send({status:1,message:err.message})
})app.listen(80,() {console.log(服务在80端口启动)
})
首先引入配置文件和所有的路由模块 引入jwt只有在main.js中需要所以就在这里引入了而且这个库的引入方式有一点奇特不方便在config.js中引入 初始化一个app 8.1 约束一些请求
放一个中间件当请求时间超过5秒时返回请求超时 放一个中间件只有使用/api开头的路由不需要token其余均需要token 支持跨域 支持前端post发送一些信息 8.2 注册所有路由模块 8.3 处理请求体
第一个if用来处理用户提交的信息(我们上面用joi定义的那些规则)第二个if用来判断token 在80端口启动