当前位置: 首页 > news >正文

Egg:使用joi进行参数校验以及注册接口小demo

目录

前言:

准备工作:

前端代码:

后端目录截图:

1.获取参数

2.校验参数

3.查询数据库中是否已经存在该用户

4.用户入库

5.测试一哈

添加用户成功

 同样的用户名再注册一遍

​编辑总结:


前言:

        在阅读这篇文章之前,想必已经对Egg有了初步的了解,至于如何创建一个egg项目之类的,配置mysql数据库之类的等等这里就不再赘述,不知道的可以去egg官方了解--Egg官方文档;

        本文着重记录在Egg中如何使用Joi进行参数的校验,以及一个小型的用户注册接口开发!本人也不经常写node,所以代码不是很标准可能,还请各位多多包涵!

准备工作:

        先说说我设计的用户注册流程,很简单,一个用户名username,一个密码password。使用的uniapp运行到了h5,长下面这个样子。

        因为重点在于后端,所以在前端字段将不会做任何的校验,点击注册按钮请求我们写的接口即可,后端流程大概分以下几步!

  1. 拿到前端请求参数,进行参数校验,使参数符合我们的校验规则即可!
  2. 校验通过后,通过用户名username进行数据查询,不允许有重复的用户名存在!
  3. 用户名没有任何问题后,对password进行加密处理!
  4. 存入数据库,返回给前端响应内容!

前端代码:

<template><view class="register"><view class="input">username:<input type="text" v-model="user.username"></view><view class="input">password:<input type="text" v-model="user.password"></view><view class=""><button @click="formSubmit">注册</button></view></view>
</template><script setup>import { reactive } from 'vue';const user = reactive({username: '',password: ''})const formSubmit = () => {uni.request({url: "http://127.0.0.1:7001/api/user/register",method: "POST",data: user,success: (res) => {console.log(res);},fail: (err) => {console.log(err);}})};
</script><style lang="scss" scoped>.register {padding: 100rpx 0;width: 700rpx;margin: 0 auto;}.input {margin-bottom: 30rpx;input {border: solid 1px #cecece;height: 60rpx;padding: 0 20rpx;}}
</style>

后端目录截图:

着重关注我圈起来的目录文件

 

 app/extend/context.js:

这个相当于是对返回内容的一个小型封装,可以使用this.ctx访问到。

module.exports = {sendSuccess({ code = 200, data = {}, msg = "ok" }) {this.body = { code, data, msg };},sendFail({ code = 400, data = {}, msg = "fail" }) {this.body = { code, data, msg };},
};

1.获取参数

我们首先需要在app/controller下新建user.js,写入以下内容!

"use strict";const { Controller } = require("egg");class userController extends Controller {/* 用户注册 */async register() {const { ctx, service } = this;const { body } = ctx.request;console.log(body);ctx.sendSuccess({ msg: "egg进行中" });}
}module.exports = userController;

而后在app/router 新建user.js

module.exports = (app) => {const { router, controller } = app;router.post("/api/user/register", controller.user.register);
};

最后在app/router.js中写入如下内容

"use strict";module.exports = (app) => {require("./router/user")(app);
};

 可以看到,我们已经可以获取到前端传递的参数了

2.校验参数

我们在 app/rules 下新建 user.js

首先需要安装Joi,npm install joi 即可!joi文档

const Joi = require("joi");/* 验证注册信息 */
async function registerValidate(params) {const registerSchema = Joi.object({username: Joi.string().min(1).max(10).required().messages({"string.empty": "用户名不能为空","any.required": "用户名必填","string.max": "用户名长度不能超过10",}),password: Joi.string().min(6).max(12).pattern(new RegExp("^[a-zA-Z0-9]{6,12}$")).required().messages({"string.empty": "密码不能为空","any.required": "密码必填","string.min": "密码长度不低于6","string.max": "密码长度不能超过12","string.pattern.base": "密码只能包含大小写字母以及数字",}),});try {await registerSchema.validateAsync(params);} catch (error) {return error.message ?? "参数错误";}
}module.exports = { registerValidate };

要是问我为什么不用官方推荐的 egg-validate,理由就是用不熟,自定义错误信息很难受,我更喜欢joi!

这样的话,我们就可以在 app/controller/user.js 中引入使用

"use strict";const { Controller } = require("egg");
const validate = require("../rules/user");class userController extends Controller {/* 用户注册 */async register() {const { ctx, service } = this;const { body } = ctx.request;/* 用户字段验证 */const validateResult = await validate.registerValidate(body);if (validateResult) {ctx.sendFail({ msg: validateResult });return;}ctx.sendSuccess({ msg: "egg进行中" });}
}module.exports = userController;

测试一下:

当我不输入用户名

用户名长度大于10

密码不填写

密码填写不符合正则表达式

 

等等还有一些别的规则,自己尝试吧!

3.查询数据库中是否已经存在该用户

去到我们 app/service/user.js

const { Service } = require("egg");class userService extends Service {/* 添加用户 */async registerUser(params) {const { ctx } = this;const data = await this.app.mysql.get("users", {username: params.username,});if (data) {ctx.sendFail({ msg: "用户名重复,换一个吧" });return;}}
}module.exports = userService;

4.用户入库

依然还是在 app/service/user.js

我们需要执行 npm install bcryptjs 命令,使用bcryptjs的方法对密码进行加密处理

const { Service } = require("egg");
const bcrypt = require("bcryptjs");class userService extends Service {/* 添加用户 */async registerUser(params) {const { ctx } = this;const data = await this.app.mysql.get("users", {username: params.username,});if (data) {ctx.sendFail({ msg: "用户名重复,换一个吧" });return;}/* 密码入库前加密 */params.password = bcrypt.hashSync(params.password, 10);const result = await this.app.mysql.insert("users", params);return result.affectedRows === 1;}
}module.exports = userService;

 我们需要在 app/controller/user.js 接通数据库操作

"use strict";const { Controller } = require("egg");
const validate = require("../rules/user");class userController extends Controller {/* 用户注册 */async register() {const { ctx, service } = this;const { body } = ctx.request;/* 用户字段验证 */const validateResult = await validate.registerValidate(body);if (validateResult) {ctx.sendFail({ msg: validateResult });return;}/* 进行数据库操作 */try {const result = await service.user.registerUser(body);if (result) {ctx.sendSuccess({ msg: "用户添加成功!" });}} catch (error) {ctx.sendFail({ msg: "用户添加失败!" });}}
}module.exports = userController;

5.测试一哈

添加用户成功

 同样的用户名再注册一遍

总结:

用egg写后端服务的感觉还是很不错的,开箱即用,制定了一系列的规则,按照规则进行代码编写即可,而且具有很高的扩展性,确实还不错!

 

相关文章:

Egg:使用joi进行参数校验以及注册接口小demo

目录 前言&#xff1a; 准备工作&#xff1a; 前端代码&#xff1a; 后端目录截图&#xff1a; 1.获取参数 2.校验参数 3.查询数据库中是否已经存在该用户 4.用户入库 5.测试一哈 添加用户成功 同样的用户名再注册一遍 ​编辑总结&#xff1a; 前言&#xff1a; 在阅…...

天梯赛训练L1-016(查验身份证)

目录 1、L1-016 查验身份证 2、如果帮助到大家了&#xff0c;希望大家一键三连&#xff01;&#xff01;&#xff01; 1、L1-016 查验身份证 分数 15 题目通道 一个合法的身份证号码由17位地区、日期编号和顺序编号加1位校验码组成。校验码的计算规则如下&#xff1a; 首…...

技术方案评审

目录 参考一、流程&规范二、评审维度组件选型性能可伸缩性灵活性可扩展性可靠性安全性兼容性弹性处理事务性可测试性可运维性监控三、方案模板背景目标整体架构业务流程接口定义数据库表功能实现测试计划人力排期Check List整体评估<...

Python机器学习库scikit-learn在Anaconda中的配置

本文介绍在Anaconda环境中&#xff0c;安装Python语言scikit-learn模块的方法。 scikit-learn库&#xff08;简称sklearn&#xff09;是一个基于Python语言的机器学习库&#xff0c;提供了各种机器学习算法和相关工具&#xff0c;包括分类、回归、聚类、降维、模型选择和预处理…...

yarn init 没有 ts 类型声明

yarn 版本为 3. 的初始化项目里&#xff0c;我们下载的包会发现没有 ts 类型提示。那么跟着我做这几个命令&#xff0c;就可以轻松搞定&#xff0c;具体原因我就不贴了&#xff0c;如果有兴趣可以评论问这里只写 vscode 没有提示的修复方式yarn add typescript -Dyarn dlx yarn…...

孩子喜欢打人父母要怎么引导?听听专家的小建议

随着人们生活水平的提高。有些孩子被父母宠坏了&#xff0c;不仅脾气暴躁&#xff0c;还喜欢打人。面对这种情况&#xff0c;许多家长会选择暴制暴&#xff0c;导致孩子更崇尚暴力。被打后&#xff0c;孩子不仅没有悔改&#xff0c;而且变得更糟。即使孩子被说服了&#xff0c;…...

Hive中order by,sort by,distribute by,Cluster by

order by 对数据进行全局排序, 只有一个reducer Task, 效率低 mysql中strict模式下, order by必须要有limit, 不然会拒绝执行. 对于分区表, 必须显示指定分区字段查询。 sort by 可以有多个reduce Task(以distribute by后的字段个数为准) 每个reduce Task内部数据有序, 但…...

PyTorch的自动微分(autograd)

PyTorch的自动微分(autograd) 计算图 计算图是用来描述运算的有向无环图 计算图有两个主要元素&#xff1a;结点&#xff08;Node&#xff09;和边&#xff08;Edge&#xff09; 结点表示数据&#xff0c;如向量、矩阵、张量 边表示运算&#xff0c;如加减乘除卷积等 用计算…...

sum-check protocol

sumcheck是一个交互式证明协议&#xff0c;给定域F上的多元多项式g(x1,...,xv)g(x_1,...,x_v)g(x1​,...,xv​)&#xff0c;证明者Prover可以向验证者Verifier证明该多项式ggg的遍历求和值等于公开值HHH&#xff0c;即 H∑b1,b2,...,bv∈{0,1}vg(b1,b2,...,bv)H \sum_{b_1,b_2,…...

数据结构刷题(二十一):131分割回文串、78子集

1.分割回文串题目链接思路&#xff1a;回溯算法的组合方法&#xff08;分割问题类似组合问题&#xff09;。流程图&#xff1a;红色竖杠就是startIndex。 for循环是横向走&#xff0c;递归是纵向走。回溯三部曲&#xff1a;递归函数参数&#xff1a;字符串s和startIndex&#…...

Spring Aop 详解

主要内容&#xff1a; 了解Spring AOP的概念及其术语熟悉Spring AOP的JDK动态代理熟悉Spring AOP的CGLib动态代理掌握基于XML的AOP实现掌握基于注解的AOP实现AOP用官方话来说&#xff1a; AOP即面向切面编程。和OOP&#xff08;面向对象编程&#xff09;不同&#xff0c;AOP主…...

【数据库死锁】线上问题之数据库死锁

原本平静的一天&#xff0c;惊现生产项目瘫痪问题&#xff0c;马上打开日志&#xff0c;发现后台日志提示了多个“com.mysql.cj.jdbc.exceptions.MySQLTransactionRollbackException: Lock wait timeout exceeded; try restarting transaction” 大概去了解一下这个异常&#x…...

好友管理系统--课后程序(Python程序开发案例教程-黑马程序员编著-第4章-课后作业)

实例3&#xff1a;好友管理系统 如今的社交软件层出不穷&#xff0c;虽然功能千变万化&#xff0c;但都具有好友管理系统的基本功能&#xff0c;包括添加好友、删除好友、备注好友、展示好友等。下面是一个简单的好友管理系统的功能菜单&#xff0c;如图1所示。 图1 好友管理系…...

Redis 集群 Redis Cluster搭建

Redis集群需要至少三个master节点&#xff0c;我们这里搭建三个master节点192.168.20.130&#xff0c;192.168.20.131&#xff0c;192.168.20.132&#xff0c;并且给每个master再搭建一个slave节点&#xff08;一个节点一主一从&#xff0c;通过端口号区分&#xff09;&#xf…...

博客系统(前后端分离版)

博客系统的具体实现 文章目录博客系统的具体实现软件开发的基本流程具体实现的八大功能数据库设计创建数据库操作数据库引入依赖封装DataSource创建实体类将JDBC增删改查封装起来实现博客列表页web.xml的配置文件实现博客系统的展示功能登录功能强制要求用户登录显示用户信息退…...

第十二章 opengl之模型加载(Assimp)

OpenGLAssimp模型加载库构建Assimp网格网格渲染Assimp 我们不太能够对像是房子、汽车或者人形角色这样的复杂形状手工定义所有的顶点、法线和纹理坐标。我们要的是将这些模型(Model)导入(Import)到程序当中。模型通常都由3D艺术家在Blender、3DS Max或者Maya这样的工具中精心制…...

Stable Matching-稳定匹配问题【G-S算法,c++】

Stable Matching-稳定匹配问题【G-S算法&#xff0c;c】题目描述&#xff1a;(Gale-Shapley算法)解题思路一&#xff1a;G-S算法(Gale-Shapley算法)题目描述&#xff1a;(Gale-Shapley算法) Teenagers from the local high school have asked you to help them with the organ…...

TypeScript(四)接口

目录 前言 定义 用法 基本用法 约定规则 属性控制 任意属性 可选属性 只读属性 定义函数 冒号定义 箭头定义 接口类型 函数接口 索引接口 继承接口 类接口 总结 前言 在介绍TS对象类型中&#xff0c;为了让数组每一项更具体&#xff0c;我们使用 string [ ]…...

Python-基础知识

目录 Python 简介 Python 发展历史 Python 特点 Python 标识符 Python 保留字符 行和缩进 多行语句 Python 引号 Python注释 Python 简介 Python 是一个高层次的结合了解释性、编译性、互动性和面向对象的脚本语言。 Python 的设计具有很强的可读性&#xff0c;相比…...

【java基础】集合基础说明

文章目录基本介绍Collection接口Iterator和Iterable接口Map接口关于Iterator接口的一些说明框架中的接口具体集合总结基本介绍 集合就是存储用来存储一系列数据的一种数据结构。在这篇文章中会介绍集合的一些基本概念。 Collection接口 集合的基本接口是Collection接口&…...

手游刚开服就被攻击怎么办?如何防御DDoS?

开服初期是手游最脆弱的阶段&#xff0c;极易成为DDoS攻击的目标。一旦遭遇攻击&#xff0c;可能导致服务器瘫痪、玩家流失&#xff0c;甚至造成巨大经济损失。本文为开发者提供一套简洁有效的应急与防御方案&#xff0c;帮助快速应对并构建长期防护体系。 一、遭遇攻击的紧急应…...

Linux链表操作全解析

Linux C语言链表深度解析与实战技巧 一、链表基础概念与内核链表优势1.1 为什么使用链表&#xff1f;1.2 Linux 内核链表与用户态链表的区别 二、内核链表结构与宏解析常用宏/函数 三、内核链表的优点四、用户态链表示例五、双向循环链表在内核中的实现优势5.1 插入效率5.2 安全…...

FFmpeg 低延迟同屏方案

引言 在实时互动需求激增的当下&#xff0c;无论是在线教育中的师生同屏演示、远程办公的屏幕共享协作&#xff0c;还是游戏直播的画面实时传输&#xff0c;低延迟同屏已成为保障用户体验的核心指标。FFmpeg 作为一款功能强大的多媒体框架&#xff0c;凭借其灵活的编解码、数据…...

23-Oracle 23 ai 区块链表(Blockchain Table)

小伙伴有没有在金融强合规的领域中遇见&#xff0c;必须要保持数据不可变&#xff0c;管理员都无法修改和留痕的要求。比如医疗的电子病历中&#xff0c;影像检查检验结果不可篡改行的&#xff0c;药品追溯过程中数据只可插入无法删除的特性需求&#xff1b;登录日志、修改日志…...

FastAPI 教程:从入门到实践

FastAPI 是一个现代、快速&#xff08;高性能&#xff09;的 Web 框架&#xff0c;用于构建 API&#xff0c;支持 Python 3.6。它基于标准 Python 类型提示&#xff0c;易于学习且功能强大。以下是一个完整的 FastAPI 入门教程&#xff0c;涵盖从环境搭建到创建并运行一个简单的…...

RNN避坑指南:从数学推导到LSTM/GRU工业级部署实战流程

本文较长&#xff0c;建议点赞收藏&#xff0c;以免遗失。更多AI大模型应用开发学习视频及资料&#xff0c;尽在聚客AI学院。 本文全面剖析RNN核心原理&#xff0c;深入讲解梯度消失/爆炸问题&#xff0c;并通过LSTM/GRU结构实现解决方案&#xff0c;提供时间序列预测和文本生成…...

音视频——I2S 协议详解

I2S 协议详解 I2S (Inter-IC Sound) 协议是一种串行总线协议&#xff0c;专门用于在数字音频设备之间传输数字音频数据。它由飞利浦&#xff08;Philips&#xff09;公司开发&#xff0c;以其简单、高效和广泛的兼容性而闻名。 1. 信号线 I2S 协议通常使用三根或四根信号线&a…...

怎么让Comfyui导出的图像不包含工作流信息,

为了数据安全&#xff0c;让Comfyui导出的图像不包含工作流信息&#xff0c;导出的图像就不会拖到comfyui中加载出来工作流。 ComfyUI的目录下node.py 直接移除 pnginfo&#xff08;推荐&#xff09;​​ 在 save_images 方法中&#xff0c;​​删除或注释掉所有与 metadata …...

如何把工业通信协议转换成http websocket

1.现状 工业通信协议多数工作在边缘设备上&#xff0c;比如&#xff1a;PLC、IOT盒子等。上层业务系统需要根据不同的工业协议做对应开发&#xff0c;当设备上用的是modbus从站时&#xff0c;采集设备数据需要开发modbus主站&#xff1b;当设备上用的是西门子PN协议时&#xf…...

基于 HTTP 的单向流式通信协议SSE详解

SSE&#xff08;Server-Sent Events&#xff09;详解 &#x1f9e0; 什么是 SSE&#xff1f; SSE&#xff08;Server-Sent Events&#xff09; 是 HTML5 标准中定义的一种通信机制&#xff0c;它允许服务器主动将事件推送给客户端&#xff08;浏览器&#xff09;。与传统的 H…...