02.项目初体验,创建用户登陆注册接口-服务端篇

79 阅读4分钟

谈谈MVC模式

www.ruanyifeng.com/blog/2007/1…

MVC是模型(Model)、视图(View)和控制器(Controller)的缩写。这一软件架构模式诞生于20世纪70年代后期,被用于创建桌面应用。当然现在这一模式也在web应用中被广泛使用。

什么是mvc,为什么使用它?

在计算机科学中,MVC是一种软件设计模式,这种模式将应用代码组织成三个相互交织的部分——模型、视图和控制器。

MVC 是三个单词的首字母缩写,它们是Model(模型)、View(视图)和 Controller (控制)。

模型是与数据库交互的逻辑;视图是用户接口和交互,控制器是是视图和数据库之间的中介。

大多数情况下,视图不直接和模型交互——这个功能由控制器执行。

在其他一些框架中,模型与视图直接交互。

MVC 设计模式旨在将应用代码分成各自的单位,来简化维护和优化。这种方式被称为“ 关注点分离 ”。

用Windows的计算器小程序为例,解释一下 MVC 模式

Mvc的模型是什么?

需要运算的数字就是"模型",

Mvc的视图是什么?

计算器上的那些按钮和最上面的显示条,就是"视图",

视图负责直接和用户交互,视图与控制器沟通用户通过鼠标或者键盘发出的请求,将信息显示给用户(可以定义多个视图)。

Mvc的控制器是什么?

执行加减乘除的那些内部运算步骤就是"控制器"。

处理用户输入的信息。负责从视图读取数据,控制用户输入,并向模型发送数据,是应用程序中处理用户交互的部分。负责管理与用户交互交互控制。

类比

  • 打电话给餐厅点了一份披萨 – 你是view
  • 你向服务员点单 – 服务员是controller
  • 服务员从披萨店拿到披萨并送给你 – 披萨店是model

需求分析

在Web系统中,用户登录是最基本的功能。要实现用户名+密码登录,很多同学的第一想法就是直接创建一个Users集合,包含usernamepassword两个字段,这样,就可以实现登录了:

好了,回到正题,我们从下面逻辑当中可以抽离出如下字段:usernamepasswordemail

模块拆分解耦

开始编码

安装相关依赖

jsonwebtoken 用于生成token
bcrypt 用于加密用户提交的信息
pnpm add bcrypt     
pnpm add @types/bcrypt -D 
pnpm add jsonwebtoken
pnpm add @types/jsonwebtoken -D
  1. 定义Model,表示数据库保存用户登陆注册的字段类型:

user.model.ts

import { model, Schema } from "mongoose"//对象的解构赋值
import { IUser } from "./user.interface"
// 定义和约束文档字段的类型
const userScema = new Schema<IUser>({
    name:{
        type:String,
        required:true,
        trim: true,
    },
    //此处额外定义该字段是为了用来验证用户是否已注册过
    email:{
        type:String,
        required:true,
        trim: true,
    },
    password:{
        type:String,
        required:true,
        trim: true,
    },
})


export const User =  model("User", userScema)
  1. 定义相关字段的TS类型声明

user.interface.ts

export interface IUser {
    name:string;
    email:string;
    password:string;
}
  1. 定义路由,负责响应用户的请求

user.route.ts

//路由进行模块化,更好的管理路由 
import express from "express";
import {
  createUser,
  loginUser,
} from "./user.controller";
const UserRouter = express.Router();
UserRouter.post("/register", createUser);
UserRouter.post("/login", loginUser);


export default UserRouter;

app.ts

import express, { Application } from "express"; import UserRouter from "./app/modules/user/user.route"; const app: Application = express(); // 解析请求体的内容 app.use(express.json()); app.use(express.urlencoded({ extended: true })); // 挂载路由 app.use("/user", UserRouter); export default app; 
  1. 定义controller,负责通知model进行数据更新

user.controller.ts

import { Request, Response } from "express";
import bcrypt from "bcrypt";
import { User } from "./user.model";
require("dotenv").config();

export const createUser = async (req: Request, res: Response) => {
  try {
    const userinfo = req.body;
    const { name,email, password } =
      userinfo;
    const enryptedpass = await bcrypt.hash(password, 10);
    const alreayExist = await User.findOne({ email: email });
    if (alreayExist) {
      res.send({ message: "User Is Alreay Exist" });
    } else {
      const user = new  User({
        name,
        email,
        password,
      });

      await user.save();
      res.status(200).send({ message: "success" });
    }
  } catch (e) {
    res.send({ message: "custome error" });
  }
};


export const loginUser = async (req: Request, res: Response) => {
  try {
    const userinfo = req.body;
    const { email, password } = userinfo;
    const validuser = await User.findOne({ email: email });

    if (validuser) {
      const validPass = await bcrypt.compare(password, validuser.password);

      if (validPass) {
        const token = jwt.sign(
          { email: validuser.email },
          `${process.env.JWT_SECRET}`,
          { expiresIn: "1d" }
        );
        res.status(200).send({ message: "Login Successful", data: token });
      } else {
        res.send({ message: "password not Match" });
      }
    } else {
      res.send({ message: "user not Valid" });
    }
  } catch (e) {
    res.send({ message: "custom error" });
  }
};
  1. 调用接口进行登陆
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div>
    <form action="http://localhost:5001/user/login" method="POST">
        email<input type="text" name="email">
        password<input type="password" name="password">
        <button type="submit">提交</button>
    </form>
</div>
</body>
</html>

可以看到已登陆成功并收到来自服务器的响应

  1. 注册
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div>
    <form action="http://localhost:5001/user/register" method="POST">
        name<input type="text" name="name">
        email<input type="text" name="email">
        password<input type="password" name="password">
        <button type="submit">提交</button>
    </form>
</div>
</body>
</html>