附录3-大事件项目后端-项目准备工作,config.js,一些库的简易用法,main.js
目录
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,当值为字符时,最小长度为1
- required() 必须传入
- string() 必须为字符串
- alphanum() 只能包含 a-z,A-Z,0-9
- max(10) 当值为数字时,最大值为10,当值为字符时,最大长度为10
- pattern(/^[\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端口启动
相关文章:
附录3-大事件项目后端-项目准备工作,config.js,一些库的简易用法,main.js
目录 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.…...
并发编程-线程
并发编程-线程 一个进程是操作系统中运行的一个任务,进程独立拥有CPU、内存等资源一个线程是一个进程中运行的一个任务,线程之间共享CPU、内存等资源,进程里的每一个任务都是线程。 线程创建 创建线程:使用threading模块中的Th…...
图解LeetCode——剑指 Offer 34. 二叉树中和为某一值的路径
一、题目 给你二叉树的根节点 root 和一个整数目标和 targetSum ,找出所有 从根节点到叶子节点 路径总和等于给定目标和的路径。叶子节点 是指没有子节点的节点。 二、示例 2.1> 示例 1: 【输入】root [5,4,8,11,null,13,4,7,2,null,null,5,1], t…...
使用Python免费试用最新Openai API
一、背景介绍 3月2日凌晨,OpenAI放出了真正的ChatGPT API,不是背后的GPT-3.5大模型,是ChatGPT的本体模型!ChatGPT API价格为1k tokens/$0.002,等于每输出100万个单词,价格才2.7美金(约18元人民…...
04、启动 SVN 服务器端程序
启动 SVN 服务器端程序1 概述2 用命令行单项目启动2.1 采用 svnserve 命令2.2 验证服务是否启动2.3 命令行方式的缺陷3 注册Windows服务3.1 注册服务的命令3.2 命令说明3.3 启动服务1 概述 SVN 服务器和 Tomcat 服务器,Nexus 服务器一样, 必须处于运行状态才能响应…...
jsp船舶引航计费网站Myeclipse开发mysql数据库web结构java编程计算机网页项目
一、源码特点 JSP船舶引航计费网站是一套完善的java web信息管理系统,对理解JSP java编程开发语言有帮助,系统具有完整的源代码和数据库,系统主要采用B/S模式开发。开发环境为 TOMCAT7.0,Myeclipse8.5开发,数据库为Mysql5.0&…...
Allegro如何画半圆形的线操作指导
Allegro如何画半圆形的线操作指导 在用Allegro设计PCB的时候,在某些应用场合会需要画半圆形,如下图 如何画半圆形,具体操作如下 点击Add点击Arc w/Radius...
【强烈建议收藏:MySQL面试必问系列之SQL语句执行专题】
一.知识回顾 之前的文章我们一起学习了MySQL面试必问系列之事务专题、锁专题,没有学习的小伙伴可以直接通过该链接地址直接访问,MYSQL你真的了解吗专栏的文章,接下来我们就一起来学习一下MySQL中SQL语句的执行流程,看看你掌握的怎…...
详解Linux下的环境变量以及C++库文件和头文件、python库的配置
目录 Linux环境变量配置基本步骤 1.查看环境变量 2.设置环境变量 3.永久性设置环境变量 4.使用环境变量 C 库文件和头文件环境变量配置 1.配置so库文件的环境变量 2.配置头文件的环境变量 Python库环境变量配置 Linux配置执行文件环境变量 我们都习惯在Windows 上配置…...
企业级分布式数据库 - GaussDB介绍
目录 什么是GaussDB 简介 应用场景 产品架构 产品优势 安全 责任共担 身份认证与访问控制 数据保护技术 审计与日志 监控安全风险 故障恢复 认证证书 GaussDB与其他服务的关系 约束与限制 计费模式 什么是GaussDB …...
Linux I2C 驱动实验
目录 一、Linux I2C 驱动简介 1、I2C 总线驱动 2、I2C 设备驱动 1、 i2c_client 结构体 2、 i2c_driver 结构体 二、硬件分析 三、设备树编写 1、pinctrl_i2c1 2、在 i2c1 节点追加 ap3216c 子节点 3、验证 四、 代码编写 1、makefile 2、ap3216c.h 3、ap3216c.c …...
DC-DC模块电源隔离直流升压高压稳压输出5v12v24v转60v100v110v150v220v250v300v400v500v
特点效率高达80%以上1*1英寸标准封装单电压输出稳压输出工作温度: -40℃~85℃阻燃封装,满足UL94-V0 要求温度特性好可直接焊在PCB 上应用HRB 0.2~10W 系列模块电源是一种DC-DC升压变换器。该模块电源的输入电压分为:4.5~9V、9~18V、及18~36VDC标准&#…...
EF有几种模式,EF的三种模式分别是什么?
EF有几种模式,EF的三种模式分别是什么? 第一种:DataBase First DataBase First传统的表驱动方式创建EDM,然后通过EDM生成模型和数据层代码。除生成实体模型和自跟踪实现模型,还支持生成轻型DbContext。 解释…...
数据可视化展示:打工人常见职业病,颈腰椎病占比最高达66.51%
身体健康才是一切的根本。只有身体健健康康才能更好的去享受世间的美好,无论是谁都应当注重身体健康,而不是无度的挥霍它! 良好的身体,释放给工作,健壮的体魄,享受美好生活,良好的心态ÿ…...
【食品图像识别】Large Scale Visual Food Recognition
1 引言 视觉智能部与中科院计算所于2020-2021年度展开了《细粒度菜品图像识别和检索》科研课题合作,本文系双方联合在IEEE T-PAMI2023发布论文《Large Scale Visual Food Recognition》 (Weiqing Min, Zhiling Wang, Yuxin Liu, Mengjiang Luo, Liping Kang, Xiaom…...
RAN-in-the-Cloud:为 5G RAN 提供云经济性
RAN-in-the-Cloud:为 5G RAN 提供云经济性 5G 部署在全球范围内一直在加速。 许多电信运营商已经推出了5G服务并正在快速扩张。 除了电信运营商之外,企业也对使用 5G 建立私有网络产生了浓厚的兴趣,这些私有网络利用了更高的带宽、更低的延迟…...
vector、list、queue
引用:windows程序员面试指南 vector vector 类似于C语言中的数组 vector 支持随机访问,访问某个元素的时间复杂度 O(1) vector 插入和删除元素效率较低,时间复杂度O(n) vector 是连续存储,没有内存碎片,空间利用率高…...
操作系统面经
进程与线程区别 1.进程是资源分配的最小单位,线程是程序执行的最小单位(资源调度的最小单位) 2.进程有自己的独立地址空间,每启动一个进程,系统就会为它分配地址空间,建立数据表来维护代码段、堆栈段和数…...
一天约了4个面试,复盘一下面试题和薪资福利
除了最新的面经分享,还有字节大佬的求职面试答疑,告诉你关键问题是什么?少走弯路。**另外本文也汇总了6份大厂面试题:字节、腾讯、小米、腾讯云、滴滴、小米游戏。**希望对大家有帮助。 前言 昨天我的交流群里,有位宝…...
详解单链表(内有精美图示哦)
全文目录引言链表链表的定义与结构链表的分类单链表的实现及对数据的操作单链表的创建与销毁创建销毁单链表的打印单链表的头插与头删头插头删单链表的尾插与尾删尾插尾删单链表的查找单链表在pos位置后插入/删除插入删除单链表在pos位置插入/删除插入删除总结引言 在上一篇文…...
csdn文章导航
这里写自定义目录标题欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注…...
【Spring】掌握 Spring Validation 数据校验
个人简介:Java领域新星创作者;阿里云技术博主、星级博主、专家博主;正在Java学习的路上摸爬滚打,记录学习的过程~ 个人主页:.29.的博客 学习社区:进去逛一逛~ Spring Validation 数据校验一、什么是 Spring…...
定语 从句
回顾能作定语的成分 形容词:She is a responsible girl.她是一个负责任的姑娘。(前置定语) The girl responsible was expelled.对此负责的姑娘被开除了。(后置定语) 代词:Whose f…...
【数据可视化工具】浅谈 DataEase 和 FineBI 支持的数据源
前言最近对市面上比较火热的数据可视化工具 DataEase 和 FineBI 进行了调研,在支持的数据源方面感觉不太一样,所以就有了这篇文章,话不多说,我们一起来看一下吧!以下的内容,大多来自两个工具的官方文档&…...
100种思维模型之上帝视角思维模型-025
惊奇、愤怒、郁闷,我们觉得生活不精彩,事情乱作一团,但这仅仅是视角问题而已。 换个视角,可以看到不同的世界。 “上帝视角思维模型”,即以一个更高、更客观、更理性的角度来看问题,从而做出理性的决策。 …...
从这5个方面,总结我当PM的第一年
以下5个方面(学习、思考、沟通、执行、产品)的分享,都是我站在巨人的肩膀上,结合自己所学所做总结而来;同时,我也继续学习,不断完善这些知识。如有不当,欢迎大家指正~一、学习&#…...
ChatGPT可以作为一个翻译器吗?
论文地址:https://arxiv.org/abs/2301.08745.pdf 背景 自从OpenAI2022年11月30日发布ChatGPT以来,基本上把NLP所有任务大统一了,那么在机器翻译的表现到底如何呢?腾讯AI Lab在翻译Prompt、多语言翻译以及翻译鲁棒性三方面做了一…...
详述java的设计模式(三)
1.装饰者模式 装饰者模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。 使用场景: 在不影响其他对象的情况下ÿ…...
Linux命令·pwd
Linux中用 pwd 命令来查看”当前工作目录“的完整路径。 简单得说,每当你在终端进行操作时,你都会有一个当前工作目录。 在不太确定当前位置时,就会使用pwd来判定当前目录在文件系统内的确切位置。1.命令格式:pwd [选项…...
以图搜图服务快速搭建
以图搜图服务快速搭建 电商公司,管理的商品少则几千,多则上百万。如何帮助用户从多如牛毛的商品中找到类似的商品就成了问题。 以图搜图就可以很好的帮助解决这个问题,通过 Towhee(resnet50 模型) Milvus 如何实现本…...
汕头e京网/温州seo网站建设
本文实例讲述了Python操作mysql数据库实现增删查改功能的方法。分享给大家供大家参考,具体如下:#codingutf-8import MySQLdbclass Mysql_Oper:def __init__(self,host,user,passwd,db):self.hosthostself.useruserself.passwdpasswdself.databasedbdef d…...
东莞网站建设服务有什/东莞做好网络推广
SCALA解释器 后续我们会使用scala解释器来学习scala基本语法,scala解释器像Linux命令一样,执行一条代码,马上就可以让我们看到执行结果,用来测试比较方便。 我们接下来学习: 启动scala解释器 在scala解释器中执行scala…...
公众号开发者权限/seo系统
linux shell java lib(linux shell脚本加载java环境变量)用shell来启动java应用程序,只要遍历lib目录#!/bin/shPROJECT_HOME/home/admin/projectMAINCLASScom._8qiu.app.MainClassCLASS_PATH${PROJECT_HOME}/classes:$(echo ${PROJECT_HOME}/lib/*.jar|sed s/ /:/g)…...
湖南建设监理官方网站/ip域名查询网站入口
1.创建用户 在命令行中执行以下操作: Step1 创建用户 sudo useradd username -m 注意要在后面加-m,否则不会在home路径下创建该用户的文件夹 创建好之后可以在/home/路径下查看该用户名的文件夹 在CLI中执行cat /etc/passwd可以查看passwd文件中是否有…...
徐州小学网站建设/搜索引擎 磁力吧
说明: 本文以nvie的“a successful git branching model”为蓝本,结合我个人理解写成。如有谬误,还请各位指出。多谢! Note: This article is highly based on nvies a successful git branching model. Thanks nvie. Git Flow 是…...
代码网站怎么做的/百度指数怎么看地域数据
五、 部署Exchange 2013 CAS负载均衡高可用 现在的Exchange 2013中客户端的指向的是用户邮箱唯一的GUID。CAS服务器基于Active Directory站点查找这个GUID,然后找到正确的邮箱服务器目标。因此不再需要使用CAS Array对象。这里只需部署NLB高可用。 5.1. 创建NLB群集…...