node创建用户注册接口(从零到一搭建用户注册接口)

记录node所学,项目实战环节

一、数据库方面

1.使用mysql创建本次数据表

create database coderhub;

2.创建用户数据表users

CREATE TABLE IF NOT EXISTS `users`(
	id INT PRIMARY KEY AUTO_INCREMENT,
	name VARCHAR(20) NOT NULL UNIQUE,
	password VARCHAR(50) NOT NULL,
	createAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
	updateAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);
二、项目文件夹创建

1.创建项目目录coderhub文件夹
2.在终端打开生成package.json文件 :npm init -y;
3.安装koa2 : npm install koa;
4.新建src文件夹并在内部新建main.js文件作为整个项目的入口
5.在src文件夹下创建app文件夹作为全局相关的文件夹(配置信息、错误处理等)
6.在src文件夹下创建controller文件夹作为全局的控制器文件夹
7.在src文件夹下创建service文件夹作为数据库操作的相关文件夹
8.在src文件夹下创建router文件夹作为路由相关的文件夹
9.在src文件夹下创建utils文件夹作为项目的工具文件夹
10.后续有需要继续创建…
此时项目文件夹预览
在这里插入图片描述

三、编写main.js和项目基本结构的搭建

1.在main.js中写入以下代码先把项目跑起来

const Koa=require('koa');

const app= new Koa();

app.listen(8000,()=>{
    console.log("服务器启动成功~");
})

2.为了更方便的启动项目可编辑package.json文件添加对应指令,和下载node代码热更新插件nodemon

npm install nodemon --save-dev

在package.json文件中编辑scripts设置启动(start)命令

 "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "nodemon ./src/main.js"
  },

3.在终端输入npm start 项目启动成功!

四、拆解项目结构,模块化划分

1.在app文件夹中新建文件index.js并把main.js中的app代码部分移到app/index.js,在main.js文件中引入app/index.js文件(目的:在开发以后,app.use()需要很多中间件,比如:路由,错误处理等)
此时,main.js代码

const app=require('./app/index');

app.listen(8000,()=>{
    console.log("服务器启动成功~")
})

此时app/index.js代码

const Koa = require('koa');

const app = new Koa();

module.exports = app
五、程序监听端口8000是写死的(需要抽离出单独的配置文件—将配置信息写入到环境变量)

1.在coderhub(也就是项目根目录)创建.env文件并写入

APP_PORT=8000

2.安装dotenv插件可以帮助我们将根目录下的.env文件加载到项目的环境变量process.env里面

npm install dotenv

3.在app文件夹下创建config.js文件导入dotenv并配置后导出

// 使用此模块可导出根目录下.env里的变量

const dotenv=require('dotenv');

dotenv.config();
// console.log(process.env.APP_PORT)

module.exports={
    APP_PORT
}=process.env

然后在需要用到变量的文件中引入就可以使用了
例如:在main.js中引入app/config.js文件并使用

const app = require('./app/index');
const config = require('./app/config');

app.listen(config.APP_PORT, () => {
    console.log(`coderHub服务器${config.APP_PORT}启动成功!`)
});
六、编写用户注册接口

1.安装koa-router插件

npm install koa-router

2.因为 第四部 把app.use()中间件的业务从main.js中抽离到 app/index.js文件中,所以我现在只需要在app/index.js编写对应代码

const Koa = require('koa');

const Router = require('koa-router');

const app = new Koa();

const userRouter = new Router({
    prefix: '/users'
})

userRouter.post('/', (ctx, next) => {
    ctx.body = "创建用户成功~"
})

app.use(userRouter.routes());

// 判断请求方式有没有,如果没有的话返回不被允许,或不被支持的接口
app.use(userRouter.allowedMethods());

module.exports = app

现在已经可以使用localhost:8000/users访问端口的,
但是还需要完善很多东西,项目的接口肯定不止一个,将来都写到这个文件中,代码将变得非常乱,还需要进一步作出抽离

3.在router文件夹下新建user.router.js文件把刚刚users路由相关的代码抽离出来

//! 用户注册接口
const Router = require('koa-router');

const userRouter = new Router({
    prefix: "/users"
});

userRouter.post('/', (ctx, next) => {
    ctx.body = "创建用户成功~"
})

module.exports = userRouter;

在app/index.js中导入

const Koa = require('koa');

// 导入users路由
const userRouter=require('../router/user.router')

const app = new Koa();

// 使用users路由
app.use(userRouter.routes());

// 判断请求方式有没有,如果没有的话返回不被允许,或不被支持的接口
app.use(userRouter.allowedMethods());

module.exports = app

但是,到时候users下的接口多了,router/user.router.js中的代码量也是比较大的,例如:用户账号密码校验逻辑,查询数据库逻辑等具体的处理逻辑,所以将router/user.router.js文件也进行代码的抽离拆分
4.在controller文件夹下新建user.controller.js文件,把抽离出来的逻辑写入这个文件,如下:

class UserController {
    async create(ctx, next) {
        // 1.获取用户请求传递的参数
        
        // 2.查询数据库
        
        // 3.返回客户端数据
    }
}

module.exports = new UserController

在router/user/router.js中引入及使用,如下

//! 用户注册接口
const Router = require('koa-router');
const {
    create
} = require('../controller/user.controller')


const userRouter = new Router({
    prefix: "/users"
});

// create 使用controller/user.controller.js中的方法
// 就相当于给这个路由添加了一个中间件
userRouter.post('/', create)

module.exports = userRouter;

但是,可以看到controller/user.controller.js文件需要做的事情也是非常多的,又需要获取用户传入的数据进行处理(如:密码加密),又需要查询数据库(如:用户名是否已存在or验证用户账号密码)等,所以需要继续抽离

5.获取用户传入的参数
安装koa-bodyparser插件并在app/index.js文件中导入使用

npm install koa-bodyparser

在app/index.js中引入代码

const Koa=require('koa');
// 导入bodyparser插件
const bodyParser = require('koa-bodyparser');
// 导入路由
const userRouter=require('../router/user.router')
// 导入错误处理函数
const errorHandler=require('./error-handle')
const app=new Koa();

// 必须在注册路由中间件的前面执行这个中间件
app.use(bodyParser())
// 使用路由
app.use(userRouter.routes());
app.use(userRouter.allowedMethods())


module.exports=app

这样,就可以解析到用户传过来的数据了
回到controller/user.controller.js中获取用户传过来的参数:如下


class UserController {
    async create(ctx, next) {
        // 获取用户请求传递的参数
        const user=ctx.request.body;
        // 查询数据库
        
        // 返回客户端数据
        
    }
}

module.exports = new UserController

6.【抽离查询数据库这块】在service文件夹下新建user.service.js文件 如:将user存储到数据库中,或查询数据库是否已存在此用户,并返回结果

class UserService {
    // 将user存储到数据库中
    async create(user) {
    	// console.log(`将用户${user.name}保存到数据库中`)
       return "创建用户成功~"
    }
}

module.exports = new UserService();

然后在controller/user.controller.js文件中导入

const service = require('../service/user.service')

class UserController {
    async create(ctx, next) {
        // 获取用户请求传递的参数
        const user=ctx.request.body;
        // 查询数据库
        const result = await service.create(user)
        // 返回客户端数据
        ctx.body=result;
    }
}

module.exports = new UserController
这样就差不多完成了一个注册接口的闭合,下面就差查询添加用户信息到数据库,以及对用户传入的账号密码进行校验
七、连接数据库

1.安装mysql2

npm install mysql2

2.在app文件夹下新建database.js文件创建数据库连接池,但是mysql的用户名,密码,端口及ip尽量不要写死,单独提取出来,放到环境变量里面(也就是.env文件里)
.env代码:

APP_PORT=8000

MYSQL_HOST=localhost
MYSQL_PORT=3306
MYSQL_DATABASE=coderhub
MYSQL_ROOT=root
MYSQL_PASSWORD=root

app/database.js代码

const mysql = require('mysql2');

const config = require('./config');
const connections = mysql.createPool({
    host: config.MYSQL_HOST,
    port: config.MYSQL_PORT,
    database: config.MYSQL_DATABASE,
    user: config.MYSQL_ROOT,
    password: config.MYSQL_PASSWORD
})

connections.getConnection((err, conn) => {
    conn.connect((err) => {
        if (err) {
            console.log('连接失败', err)
        } else {
            console.log('数据库连接成功!')
        }
    })
})

module.exports = connections.promise();

现在,就可以使用连接池将用户传过来的用户信息写入数据库,实现用户注册功能了

八、将用户信息插入数据库

1.service/user.service.js文件中引入数据库连接池文件app/database.js
2.获取到用户名及密码
3.写对应sql语句
整改后代码如下:

const connection = require('../app/database');

class UserService {
    // 将user存储到数据库中
    async create(user) {
        const {
            name,
            password
        } = user;
        const statement = `INSERT INTO users (name,password) VALUES (?,?);`
        const result = await connection.execute(statement, [name, password]);
        return result[0];
    }
}

module.exports = new UserService();

用户信息就可以保存到数据库中了

九、用户名、密码校验

1.在src文件夹下创建middleware文件夹并在里面创建user.middleware.js文件用作校验用户账号密码的中间件文件
代码如下:

const verifyUser = async (ctx, next) => {
    // 1.获取用户名和密码
    const {
        name,
        password
    } = ctx.request.body;
    // 2.判断用户名或者密码不能为空
   
    // 3.判断这次注册的用户名是没有被注册过的
    

    await next();
}

在router/user.router.js中使用如下

//! 用户注册接口
const Router = require('koa-router');
const {
    create
} = require('../controller/user.controller')

const {
    verifyUser
} = require('../middleware/user.middleware')

const userRouter = new Router({
    prefix: "/users"
});

// userRouter.post('/', (ctx, next) => {
//     ctx.body = "创建用户成功~"
// })
// 分离出去写法 
// verifyUser   验证用户,不能为空,不能被别人使用过
// verifyUser 是个在create前面的中间件  next()
// 就相当于给这个路由添加了一个中间件
userRouter.post('/', verifyUser, create)

module.exports = userRouter;

写这个模块会碰到错误处理问题,和查询用户名是否存在的问题,先解决错误处理模块,在写对应的查询sql
1.在app文件夹下创建error-handle.js文件
2.创建错误常量,在src文件夹下新建contants文件夹内部新建error-types.js用于存放错误常量
contants/error-types.js代码如下:(主要是用变量保存,防止出错写错)

const NAME_OR_PASSWORD_IS_REQUIRED = "name_or_password_id_required";
const USER_ALREADY_EXISTS = "user_already_exists";


module.exports = {
    NAME_OR_PASSWORD_IS_REQUIRED,
    USER_ALREADY_EXISTS
}

定义错误处理信息app/error-handle.js
代码如下:

const errorTypes = require('../constants/error-types');
// 错误处理函数
const errorHandler = (error, ctx) => {
    let status, message;
    switch (error.message) {
        case errorTypes.NAME_OR_PASSWORD_IS_REQUIRED:
            status = 400; //Bad Request
            message = "用户名或者密码不能为空~";
            break;
        case errorTypes.USER_ALREADY_EXISTS:
            status = 409; //conflict
            message = "用户名已存在~"
            break;
        default:
            status = 404;
            message = "NOT FOUND"
    }
    ctx.status = status;
    ctx.body = message
}

module.exports = errorHandler

在验证出错的地方引入错误常量并使用(如,上面校验用户账号密码的时候就可以这样写)
整改user/user.middleware.js代码如下:

const errorTypes = require('../constants/error-types')

const verifyUser = async (ctx, next) => {
    // 1.获取用户名和密码
    const {
        name,
        password
    } = ctx.request.body;
    // 2.判断用户名或者密码不能为空
    if (!name || !password) {
        // 返回错误信息
        const error = new Error(errorTypes.NAME_OR_PASSWORD_IS_REQUIRED)
        console.log('发生了错误')
        return ctx.app.emit('error', error, ctx)
    }
    // 3.判断这次注册的用户名是没有被注册过的
    
    await next();
}

这里使用了ctx.app.emit(“error”,error,ctx);
所以要在app/index.js文件夹下监听错误,需要引入刚刚创建的错误处理函数方法app/error-handle.js的errorHandler()
app/index.js代码整理如下:

const Koa=require('koa');
const bodyParser = require('koa-bodyparser');
// 导入路由
const userRouter=require('../router/user.router')
// 导入错误处理函数
const errorHandler=require('./error-handle')
const app=new Koa();

app.use(bodyParser())
// 使用路由
app.use(userRouter.routes());
app.use(userRouter.allowedMethods())

// 错误处理
app.on('error',errorHandler)

module.exports=app

解决了用户名与密码校验,在判断用户名是否已存在
在service/user.service.js文件中添加对应查询方法
整改代码如下:

const connection = require('../app/database');

class UserService {
    // 将user存储到数据库中
    async create(user) {
        const {
            name,
            password
        } = user;
        const statement = `INSERT INTO users (name,password) VALUES (?,?);`
        const result = await connection.execute(statement, [name, password]);
        return result[0];
    }
    
    // 查询用户名是否存在
    async getUserByName(name) {
        const statement = `SELECT * FROM users WHERE name=?;`;
        const result = await connection.execute(statement, [name]);
        return result[0];
    }
}

module.exports = new UserService();

middleware/user.middleware.js代码引入getUserByName方法
整改代码如下:

const errorTypes = require('../constants/error-types')
const service = require('../service/user.service')

const verifyUser = async (ctx, next) => {
    // 1.获取用户名和密码
    const {
        name,
        password
    } = ctx.request.body;
    // 2.判断用户名或者密码不能为空
    if (!name || !password) {
        // 返回错误信息
        const error = new Error(errorTypes.NAME_OR_PASSWORD_IS_REQUIRED)
        console.log('发生了错误')
        return ctx.app.emit('error', error, ctx)
    }
    // 3.判断这次注册的用户名是没有被注册过的
    const result = await service.getUserByName(name);
    if (result.length) {
        const error = new Error(errorTypes.USER_ALREADY_EXISTS);
        return ctx.app.emit('error', error, ctx);
    }


    await next();
}


module.exports = {
    verifyUser
}

此时注册接口基本完全结束,但用户密码还是明文显示的

十、md5用户密码加密

1.和密码校验差不多,这也是一个中间件,需要在router/user.router.js注册路由那里使用
2.在utils文件夹下创建password-handle.js文件,用于加密用户密码
代码如下:

// node自带加密模块crypto
const crypto = require('crypto');

const md5password = (password) => {
    const md5 = crypto.createHash('md5');
    // digest 默认为二进制 参数hex代表转成16进制
    const result = md5.update(password).digest('hex');
    return result;
}

module.exports = md5password;

2.在middleware/user.middleware.js文件中引入utils/password-handle.js中的md5password 方法,然后添加handlePassword函数
整改后,代码如下:

const errorTypes = require('../constants/error-types')
const service = require('../service/user.service')
const md5password = require('../utils/password-handle')

const verifyUser = async (ctx, next) => {
    // 1.获取用户名和密码
    const {
        name,
        password
    } = ctx.request.body;
    // 2.判断用户名或者密码不能为空
    if (!name || !password) {
        // 返回错误信息
        const error = new Error(errorTypes.NAME_OR_PASSWORD_IS_REQUIRED)
        console.log('发生了错误')
        return ctx.app.emit('error', error, ctx)
    }
    // 3.判断这次注册的用户名是没有被注册过的
    const result = await service.getUserByName(name);
    if (result.length) {
        const error = new Error(errorTypes.USER_ALREADY_EXISTS);
        return ctx.app.emit('error', error, ctx);
    }


    await next();
}

const handlePassword = async (ctx, next) => {
    const {
        password
    } = ctx.request.body
    // password=密码加密函数(password)
    ctx.request.body.password = md5password(password);

    await next();

}

module.exports = {
    verifyUser,
    handlePassword
}

3.在router/user.router.js中引入刚刚在middleware/user.middleware.js文件中创建的handlePassword中间件并使用
整改代码如下:

//! 用户注册接口
const Router = require('koa-router');
const {
    create
} = require('../controller/user.controller')

const {
    verifyUser,
    handlePassword
} = require('../middleware/user.middleware')

const userRouter = new Router({
    prefix: "/users"
});

// userRouter.post('/', (ctx, next) => {
//     ctx.body = "创建用户成功~"
// })
// 分离出去写法 
// verifyUser   验证用户,不能为空,不能被别人使用过
// verifyUser 是个在create前面的中间件  next()
// handlePassword 用于加密用户密码的中间件
// 就相当于给这个路由添加了一个中间件
userRouter.post('/', verifyUser, handlePassword, create)

module.exports = userRouter;

源码:提取码【dcys】

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值