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

news2024/9/27 9:24:22

目录

前言:

准备工作:

前端代码:

后端目录截图:

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

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/399493.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C#基础之基础语法(一)

总目录 文章目录总目录前言一、C#简述1 C#是什么&#xff1f;2 .Net平台3. C# 和.Net的关系4. 集成开发环境&#xff08;IDE&#xff09;二、控制台应用程序1. 常用代码2.注意事项三、基础语法1.编写C#代码注意事项2.C#注释2. 变量&标识符&关键字4. 变量&#xff0c;字…

unity 面试汇总

1、什么是协同程序&#xff1f;答&#xff1a;在主线程运行时同时开启另一段逻辑处理&#xff0c;来协助当前程序的执行。换句话说&#xff0c;开启协程就是开启一个可以与程序并行的逻辑。可以用来控制运动、序列以及对象的行为。2、Unity3D中的碰撞器和触发器的区别&#xff…

【C++进阶】四、AVL树(二)

目录 前言 一、AVL树的概念 二、AVL树节点的定义 三、AVL树的插入 四、AVL树的旋转 4.1 左单旋 4.2 右单旋 4.3 左右双旋 4.4 右左双旋 五、AVL树的验证 六、AVL树的性能 七、完整代码 前言 前面对 map/multimap/set/multiset 进行了简单的介绍&#xff0c;在其文…

2023年湖北武汉安全员C证报考条件是什么?考试题型是什么 启程别

2023年湖北武汉安全员C证报考条件是什么&#xff1f;考试题型是什么 启程别 武汉安全员C证报考条件&#xff1a; 1.注册地在本市的施工单位在职“三类人员”可申请参加安全生产考核&#xff1b; 2、职业道德良好&#xff0c;身体健康&#xff0c;年龄不超过60周岁&#xff08…

pdf多页合并为一页方法总结,你觉得哪个最好?

PDF格式的文件在现代办公中是不可或缺的&#xff0c;许多人在工作中需要频繁处理PDF文档。然而&#xff0c;当我们需要阅读多个PDF文件时&#xff0c;不断切换不同的文件并一个一个地打开查阅会非常麻烦。为了提高阅读效率&#xff0c;人们一般会将pdf多页合并为一页。那么&…

传输线的物理基础(四):传输线的驱动和返回路径

驱动一条传输线对于将信号发射到传输线的高速驱动器&#xff0c;传输线在传输时间内的输入阻抗将表现得像一个电阻&#xff0c;相当于线路的特性阻抗。鉴于此等效电路模型&#xff0c;我们可以构建驱动器和传输线的电路&#xff0c;并计算发射到传输线中的电压。等效电路如下图…

虹科分享 | 网络流量监控 | 数据包丢失101

什么是数据包&#xff1f; 数据包是二进制数据的基本单位&#xff0c;在网络连接的设备之间编号和传输&#xff0c;无论是在本地还是通过互联网。一旦数据包到达其目的地&#xff0c;它就会与其他数据包一起按编号重新组合&#xff0c;回到最初传输的较大消息中。 数据包是我们…

2022(二等奖)C2594江淮分水岭植被碳汇时空可视化系统

作品介绍 一、需求分析 1.1 设计背景 气候变化是全球性问题&#xff0c;随着二氧化碳排放的增加生物的生存与生命受到威胁。人类活动对自然界生态系统的破坏&#xff0c;不仅降低了地球生物圈的生产力&#xff0c;威胁到人类社会未来经济的发展&#xff0c;同时还破坏了陆地与…

WireShark如何抓包,各种协议(HTTP、ARP、ICMP)的过滤或分析,用WireShark实现TCP三次握手和四次挥手

WireShark一、开启WireShark的大门二、如何抓包 搜索关键字2.1 协议过滤2.2 IP过滤2.3 过滤端口2.4 过滤MAC地址2.5 过滤包长度2.6 HTTP模式过滤三、ARP协议分析四、WireShark之ICMP协议五、TCP三次握手与四次挥手5.1 TCP三次握手实验5.2 可视化看TCP三次握手5.3 TCP四次挥手5.…

【大数据处理与可视化】一 、大数据分析环境搭建(安装 Anaconda 3 开发环境)

【大数据处理与可视化】一 、大数据分析环境搭建&#xff08;安装 Anaconda 3 开发环境&#xff09;实验目的实验内容实验步骤一、下载Anaconda安装包二、安装Anaconda3三、验证Anaconda是否安装成功四、Jupyter Notebook的使用1. 启动Anaconda自带的Jupyter Notebook2. 在code…

Volatile关键字

Volatile关键字和JMM内存模型一JUC并发包API 包介绍二JMM&#xff08;Java Memory Model&#xff09;三 volatile关键字3.1.可⻅性3.1.1.问题演示3.1.1.1案例代码3.1.1.2.案例分析3.1.2.volatile 保证可见性演示3.1.2.1对number添加了volatile修饰3.1.2.2运⾏结果是&#xff1a…

Docker学习(二十一)构建 java 项目基础镜像

目录1.下载 JDK 包2.编写 Dockerfile3.构建镜像4.创建容器测试1.下载 JDK 包 JDK各版本官网下载地址&#xff1a; https://www.oracle.com/java/technologies/downloads/archive/#JavaSE 这里我们以 JDK 8u351 为例&#xff0c;点击 Java SE (8U211 and later)。 点击下载 jd…

Mysql问题:[Err] 1055 - Expression #1 of ORDER BY clause is not in GROUP BY clause

1 问题描述 使用Navicat连接到MySQL(版本&#xff1a;8.0.18)&#xff0c;执行查询&#xff1a; select * from t_user WHERE user_name admin查询结果没有问题&#xff0c;但是报错&#xff1a; [Err] 1055 - Expression #1 of ORDER BY clause is not in GROUP BY claus…

分布式 微服务

微服务学习 soa和微服务 业务系统实施服务化改造之后&#xff0c;原本共享的业务被拆分形成可复用的服务&#xff0c;可以在最大程度上避免共享业务的重复建设、资源连接瓶颈等问题。那么被拆分出来的服务是否也需要以业务功能为维度来进行拆分和独立部署&#xff0c;以降低业…

学习streamlit-4

st.slider 今天学习st.slider滑块组件的使用。 st.slider滑块组件通常被用来作为应用的输入&#xff0c;支持整数、浮点数、日期、时间和日期时间。 下面的示例程序包含以下简单功能&#xff0c;以演示st.slider滑块组件&#xff1a; 用户通过调整滑块选择值应用打印出所选…

C++面向对象编程之五:友元(friend)

C中&#xff0c;允许一个类的非共有成员被这个类授予友元&#xff08;friend&#xff09;关系的全局函数&#xff0c;另一个类&#xff0c;或另一个类中的成员函数访问。友元不是一个类中的成员&#xff0c;所以它们不受声明出现部分的访问权限&#xff08;public&#xff0c;p…

Binder通信原理与弊端解析

Binder 定义 简单来说&#xff0c;Binder 就是用来Client 端和 Server 端通信的。并且 Client 端和 Server 端 可以在一个进程也可以不在同一个进程&#xff0c;Client 可以向 Server 端发起远程调用&#xff0c;也可以向Server传输数据&#xff08;当作函数参数来传&#xff…

USART_GetITStatus与 USART_GetFlagStatus的区别

文章目录共同点不同点USART_GetITStatus函数详解USART_GetFlagStatus函数共同点 都能访问串口的SR寄存器 不同点 USART_GetFlagStatus(USART_TypeDef USARTx, uint16_t USART_FLAG)&#xff1a;* 该函数只判断标志位&#xff08;访问串口的SR寄存器&#xff09;。在没有使能…

TwinCAT3中ModbusTCP Server和C# Client连接

目录 一、硬件环境 1、设置PLC的ip地址 2、ModbusTCP软件安装 3、PLC操作系统防火墙设置 4、网络助手连接PLC 二、创建PLC工程 1、创建寄存器读写变量 2、添加ModbusTCP授权 3、激活和运行工程 三、ModbusTCP数据协议说明 1、写单个寄存器 2、读寄存器 &#xff08;1&…

反转链表相关的练习(下)

目录 一、回文链表 二、 重排链表 三、旋转链表 一、回文链表 给你一个单链表的头节点 head &#xff0c;请你判断该链表是否为回文链表。如果是&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 示例 1&#xff1a; 输入&#xff1a;head [1,2,2,1] 输…