【Node.js项目】大事件项目:后台架构图(含具体技术栈)、典型代码

2023-10-30

项目学习自:https://www.bilibili.com/video/BV1a34y167AZ

1 项目后台架构图(含具体技术栈)

在这里插入图片描述

2 项目目录结构

上图是之前在 ProcessOn 中画的,原图文件被删了,但是项目目录又有了一些小改动,这里直接文字说明一下:

  • 配置目录 config:存放 jwt 的密钥以及过期时间
  • 参数校验目录 schema :存放入参校验规则,配合 router 目录下的路由文件进行校验规则的绑定

在这里插入图片描述

3 项目典型代码

各功能的代码都是类似的,这里除了必要的目录文件外,功能部分只写一下用户模块的代码

config/config.js

module.exports = {
  jwtSecretKey: "itheima No1. ^_^",
  expiresIn: "72h",
};

app.js

const express = require("express");
const app = express();
const cors = require("cors");
const joi = require("@hapi/joi");

const config = require("./config/config");
const userRouter = require("./router/user");
const userInfoRouter = require("./router/userInfo");
const articleRouter = require("./router/article");

// 解析 token 的中间件
const expressJWT = require("express-jwt");


app.use((req, res, next) => {
  res.cc = (err, status = 1) => {
    res.send({ status, msg: err instanceof Error ? err.message : err });
  };
  next();
});

// 使用 .unless({ path: [/^\/api\//] }) 指定哪些接口不需要进行 Token 的身份认证
app.use(expressJWT({ secret: config.jwtSecretKey }).unless({ path: [/^\/api\//] }));

// 配置 cors 跨域
app.use(cors());
// 配置解析表单数据的中间件;
app.use(express.urlencoded({ extended: false }));

app.use("/api", userRouter);
app.use("/user", userInfoRouter);
app.use("/article", articleRouter);

// 错误中间件
app.use((err, req, res, next) => {
  // 表单校验错误
  if (err instanceof joi.ValidationError) return res.cc(err);
  // 捕获身份认证失败的错误
  if (err.name === "UnauthorizedError") return res.cc("身份认证失败!");
  // 未知错误
  res.cc(err);
});

app.listen(3007, () => {
  console.log("api server running at http://127.0.0.1:3007");
});

schema/user.js

const joi = require("@hapi/joi");

const username = joi.string().alphanum().min(1).max(10).required();
const password = joi
  .string()
  .pattern(/^[\S]{6,12}$/)
  .required();

const id = joi.number().integer().min(1).required();
const nickname = joi.string().required();
const email = joi.string().email().required();
const avatar = joi.string().dataUri().required();

exports.reg_login_schema = {
  // 表示需要对 req.body 中的数据进行验证
  body: {
    username,
    password,
  },
};
// 验证规则对象 - 更新用户基本信息
exports.update_userInfo_schema = {
  body: {
    id,
    nickname,
    email,
  },
};
// 验证规则对象 - 重置密码
exports.update_password_schema = {
  body: {
    oldPwd: password,
    newPwd: joi.not(joi.ref("oldPwd")).concat(password),
  },
};
// 验证规则对象 - 更新头像
exports.update_avatar_schema = {
  body: {
    avatar,
  },
};

router/user.js

const express = require("express");

const userHandler = require("../router_handler/user");
const expressJoi = require("@escook/express-joi");
// 2. 导入需要的验证规则对象
const { reg_login_schema } = require("../schema/user");

const router = express.Router();

// 注册新用户
router.post("/reguser", expressJoi(reg_login_schema), userHandler.regUser);

// 登录
router.post("/login", expressJoi(reg_login_schema), userHandler.login);

// 将路由对象共享出去
module.exports = router;

router_handler/user.js

这里的 sql 处理也可以移至 db 模块

const db = require("../db/index");

// 加密密码
const bcrypt = require("bcryptjs");
// 用这个包来生成 Token 字符串
const jwt = require("jsonwebtoken");
// 导入配置文件
const config = require("../config/config");
const { expiresIn } = require("../config/config");

// 注册用户处理函数
const regUser = (req, res) => {
  const userInfo = req.body;
  if (!userInfo.username || !userInfo.password) return res.send({ status: 1, msg: "用户名或密码不能为空!" });

  const sql = "SELECT * FROM ev_users WHERE username =?";
  db.query(sql, [userInfo.username], (err, results) => {
    if (err) return res.cc(err);
    if (results.length > 0) return res.cc("用户名被占用,请更换其他用户名!");

    // 对用户的密码,进行 bcrype 加密,返回值是加密之后的密码字符串
    // userInfo.password = bcrypt.hashSync(userInfo.password, 10);

    const sql = "INSERT INTO ev_users set ?";
    db.query(sql, { username: userInfo.username, password: userInfo.password }, (err, results) => {
      if (err) return res.send({ status: 1, message: err.message });
      if (results.affectedRows !== 1) return res.send({ status: 1, message: "注册用户失败,请稍后再试!" });

      // 注册成功
      res.send({ status: 0, message: "注册成功!" });
    });
  });
};

// 登录处理函数
const login = (req, res) => {
  const userInfo = req.body;
  const sql = "SELECT * FROM ev_users WHERE username =?";
  db.query(sql, userInfo.username, (err, results) => {
    if (err) return res.cc(err);
    if (results.length !== 1) return res.cc("用户不存在!");
    if (userInfo.password !== results[0].password) return res.cc("密码错误!");

    const userStr = { ...results[0], password: null, user_pic: null };
    // 生成token字符串
    const tokenStr = jwt.sign(userStr, config.jwtSecretKey, { expiresIn: config.expiresIn });
    res.send({ status: 0, msg: "登录成功", token: "Bearer " + tokenStr });
  });
};

module.exports = {
  regUser,
  login,
};

db/index.js

const mysql = require("mysql");

const db = mysql.createPool({
  host: "127.0.0.1",
  user: "root",
  password: "267845967",
  database: "my_db_01",
});

module.exports = db;
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【Node.js项目】大事件项目:后台架构图(含具体技术栈)、典型代码 的相关文章

  • 使用 Sequelize 实现单表继承

    有没有办法使用sequelize来创建单表继承 我希望有一个用于购买和 PartialPurchase 模型的 STI 其中我将有一个类型字段 该字段为 Purchase 或 PartialPurchase 以及类 Purchasing 和
  • 用隐藏单元格补充 colspanned 表格有什么不好吗?

    我一直在表格上开发一些排序和选择功能 我发现在具有跨单元格的表格中定位非常困难 我只是添加了跨区单元格并将其隐藏 它看起来不错 它与我的 js 一起工作 非常适合索引 但我想知道这是否是合法的方法 stuffing display none
  • 在Javascript中按降序对字符串进行排序(最有效)?

    W3Schools 有这个例子 var fruits Banana Orange Apple Mango fruits sort fruits reverse 这是在 Javascript 中按降序对字符串进行排序的最有效方法吗 Updat
  • 使用 moment.js 检查输入日期是否为星期一

    好吧 我想检查日期是否是星期一 例如 var myDate new Date moment myDate DD MM YYYY dayIs monday 在我的国家 一周的第一天是星期一 所以 我真的想检查输入日期是否是一周的开始 我尝试使
  • 即使我可以监视其他方法,也无法监视事件处理程序

    我想使用 Jest Jasmine Enzyme 测试 React 中的事件处理程序 MyComponent js import React from react class MyComponent extends React Compon
  • 如何检查请求是否通过 Express 中的 https 发送

    我想强制某些路线始终在我的 Express 应用程序中使用安全连接 我如何检查以确保它使用 https 我在 heroku 上使用搭载 ssl 进行部署 我也在 Heroku 上部署 当他们使用 nginx 进行反向代理时 他们添加了一堆标
  • javascript中按tab键时如何调用函数?

    我有一个这样的功能 function whenEmpty field if field value field style backgroundColor ffcccc alert Please fill the field field f
  • JavaScript 中数组的 HTML 数据列表值

    我有一个简单的程序 它必须从服务器上的文本文件中获取值 然后将数据列表填充为输入文本字段中的选择 为此 我想要采取的第一步是我想知道如何动态地将 JavaScript 数组用作数据列表选项 我的代码是
  • Cloudfoundry:如何组合两个运行时

    cloundfoundry 有没有办法结合两个运行时环境 我正在将 NodeJS 应用程序部署到 IBM Bluemix 现在 我还希望能够执行独立的 jar 文件 但应用程序失败 APP 0 bin sh 1 java not found
  • Google Chrome 106 可拖动导致元素消失

    使用拖放元素时 绝对定位元素中包含的大多数其他元素都会从屏幕上消失 如果我调整窗口大小 这些元素会出现 但在开始拖动时会再次消失 我在最新版本的 Google Chrome 106 和 Beta 版本 107 0 5304 18 以及现在的
  • 如何在 Angular 中从父组件访问子组件?

    I have mat paginator在子组件a中 如下所示 子组件 html
  • Typeahead.js substringMatcher 函数说明

    我只是在做一些研究Typeahead js这是一个非常酷的图书馆 感谢文档 我已经成功地获得了一个基本的示例 该文档也非常好 但是我试图弄清楚以下代码块实际上在做什么 var substringMatcher function strs r
  • Chartjs刻度标签位置

    尝试让 Y 轴刻度标签看起来像image https i stack imgur com XgoxX png 位于秤顶部且不旋转 缩放选项当前如下所示 scales yAxes id temp scaleLabel display true
  • 查询为空 Node Js Sequelize

    我正在尝试更新 Node js 应用程序中的数据 我和邮递员测试过 我的开发步骤是 从数据库 MySQL 获取ID为10的数据进行更新 gt gt 未处理的拒绝SequelizeDatabaseError 查询为空 我认识到 我使用了错误的
  • 如何在jquery中获取保存时间和当前时间的差异?

    我想在 javascript 或 jquery 中获取保存时间和当前时间之间的时差 我节省的时间看起来像Sun Oct 24 15 55 56 GMT 05 30 2010 java中的日期格式代码如下 String newDate 201
  • JavaScript 代码在不使用 ActiveX 的情况下截取网站屏幕截图

    我有一个用户与之交互的 JavaScript 应用程序 我需要保存当前界面的外观 裁剪出我需要的部分 或者通过指定div只拍摄我需要的部分 然后发送回服务器 显然任何外部服务都无法做到这一点 我需要一个 JavaScript 或Flash
  • 如果数字小于 10,则显示前导零 [重复]

    这个问题在这里已经有答案了 可能的重复 JavaScript 相当于 printf string format https stackoverflow com questions 610406 javascript equivalent t
  • 数据表日期范围过滤器

    如何添加日期范围过滤器 like From To 我开始进行常规搜索和分页等工作 但我不知道如何制作日期范围过滤器 我正在使用数据表 1 10 11 版本 My code var oTable function callFilesTable
  • 如何在 javascript 正则表达式中匹配平衡分隔符?

    我原以为这个问题是不可能的 据我所知 Javascript 的正则表达式既没有递归插值 也没有漂亮的 NET 平衡组功能 但问题就在那里 如问题 12 所示正则表达式 alf nu http regex alf nu 匹配平衡对 lt an
  • 如何在打字稿文件中导入没有定义文件的js库

    随着我们的项目变得越来越大 我想从 JavaScript 切换到 TypeScript 以帮助进行代码管理 然而 我们使用许多库作为 amd 模块 我们不想将其转换为 TypeScript 我们仍然想将它们导入 TypeScript 文件

随机推荐

  • 他在 B 站有 178 万粉丝,今天免费带你玩转 Python

    近几年 编程越来越火 网上也是铺天盖地的免费教程 中小学生都开始投入到学习中 编程学习从娃娃抓起 甚至有些小学生都做起了 UP 主 教大家学编程 光从编程的难易度来说 Python 简单 易学 零基础 跨专业都很容易上手 想学全网超详细 P
  • Linux内核配置选项详解

    对于每一个配置选项 用户可以回答 y m 或 n 其中 y 表示将相应特性的支持或设备驱动程序编译进内核 m 表示将相应特性的支持或设备驱动程序编译成可加载模块 在需要时 可由系统或用户自行加入到内核中去 n 表示内核不提供相应特性或驱动程
  • Qt连接SQL server数据库

    Qt连接SQL server数据库 由于课程设计需要 需要用qt设计一个界面来操作数据库 在建立数据库连接时 期间遇到各种问题 Qt 连接SQL server数据大致可以概括为下图的三层模型 箭头代表他们之间的依赖关系 第一步 建立目标数据
  • FeignClient的参数传递给服务提供方的方式(简单数据类型、对象)

    1 简单数据类型的参数采用的restFull的方式 发送Get请求 服务提供方的controller 类名加了窄化请求 RequestMapping path house produces application json charset
  • 前端制作简单的“注册页面——阅读协议”页面及效果

    注 如对文中的scrollHeight scrollTop clientHeight属性有所一伙 请参考博文 JavaScript中元素client offset scroll相关属性的应用 链接 https blog csdn net m
  • 开源进展

    作为一个友好的 功能丰富的区块链中间件平台 WeBASE一直致力于降低区块链开发者的研发门槛 提高区块链开发效率 如今 WeBASE v1 5 4来了 此次更新新增区块链应用实训课程案例集 以及管理台操作指引与设计说明 助力社区开发者更快捷
  • 自定义指令 v-clickoutside 使用方法

    引入 import Clickoutside from element ui src utils clickoutside 声明 export default directives Clickoutside data function re
  • CentOS 安装Vim 编辑器

    在CentOS环境下使用vim提示 vim command not found时 说明系统还没有安装vim 安装步骤 1 检查是否已安装 查看一下你本机已经存在的包 确认一下你的VIM是否已经安装 输入 rpm qa grep vim 如果
  • 【详解】Thymeleaf中的基本表达式:@{},#{},${},*{}

    1 thymeleaf中的超链接表达式 话说例子如下 a a a a 2 thymeleaf中的消息表达式 或者是资源表达式 一般和 th text一起使用多一点 取出来的值取代了标签中的值 key 对应的value 如果标签中间已经有值
  • STM32的I2C主从机通信

    最近一段时间在做I2C通信协议 需要在两块STM32之间做I2C通信 定的是主机用IO口模拟 从机用的是STM32的硬件I2C 我的项目要求是需要主从机之间能够进行一串数据收发而不出错 实验时在主机方面 利用IO口模拟主机 只需要理解时序就
  • Java IDEA辅助键和快捷键

    快速生成main方法 psvm 回车 快速生成输出语句 sout 回车 内容辅助键 Ctrl Alt space 内容提示 代码补全等 格式化 Ctrl Alt L
  • java nio 编程

    转自 http yangguangfu iteye com blog 774194 Java代码 晚上学习了下Java 的 NIO Socket编程 写了下面这个小程序 包括服务器端与客户端 实现的功能为客户端向服务器端发送随即数目的消息
  • Java Executors(线程池)

    Sun在Java5中 对Java线程的类库做了大量的扩展 其中线程池就是Java5的新特征之一 除了线程池之外 还有很多多线程相关的内容 为多线程的编程带来了极大便利 为了编写高效稳定可靠的多线程程序 线程部分的新增内容显得尤为重要 有关J
  • PHP学习记录--基础篇

    目录 一 变量定义 二 循环结构 三 函数 四 文件加载原理 五 错误处理 六 字符串 七 数组 一 变量定义
  • C进阶之实现数据库(mysql 5.0)版本通讯录

    前言 断断续续历时两天百度的知识探索 继静态 动态 文件版本的通讯录之后 倔强的我开启了数据库版本通讯录 在动态版本通讯录的基础上将通讯人信息数据插入数据库中 初始化通讯录完成后 再从数据库中查询通讯人信息数据 的痛苦长路 想说脏话但是稍微
  • 在九天毕昇平台运行paddle出现fatal error: ‘Segmentation fault‘ is detected by the operating system

    我在九天毕昇平台使用paddlepaddle框架训练实例时 调用GPU出现下文错误 C Traceback most recent call last No stack trace in paddle may be caused by ex
  • SQL查询结果去重

    SQL查询结果去重 使用distinct关键字 去除重复的记录行 SELECT loc FROM dept SELECT DISTINCT loc FROM dept 案例 描述 题目 现在运营需要查看用户来自于哪些学校 请从用户信息表中取
  • opengl 光线追踪_基于CUDA的GPU光线追踪

    先放最终效果 实时光线追踪https www zhihu com video 1073144630408941568 十天前我打算用我之前的CPU渲染器渲染一张博客封面 大概是这张 我之前的渲染器是使用C 写的 已经进行过多线程优化 但是为
  • H5页面怎么跳转到公众号主页?看过来

    前言 做公众号开发的小伙伴 可能会遇到这种需求 在一个H5页面点击一个关注公众号按钮跳转到公众号主页 听到这个需求的一瞬间 疑惑了 这不可能 摸了摸高亮的额头 没办法 做还是要做的 开始上解决方案 方案一 自己做一个关注公众号的引导页面 让
  • 【Node.js项目】大事件项目:后台架构图(含具体技术栈)、典型代码

    项目学习自 https www bilibili com video BV1a34y167AZ 文章目录 1 项目后台架构图 含具体技术栈 2 项目目录结构 3 项目典型代码 config config js app js schema u