koa2 mysql增删改查_react+koa2+mysql零门槛的全栈体验,附上完整项目分享

写在前面

本文适用于对后端开发领域较为陌生的初级前端开发小伙伴,如果你想一个人搞定一整个项目(服务端接口定义开发+前端页面渲染+数据库搭建+服务器搭建+部署上线),希望这篇文章能给你带来一点点参考价值。

项目简介

实现简单的登录、表单的增删改查、文件上传等功能。以下是项目地址:

技术栈

前端

主要基于React全家桶,UI框架选用ant-design-pro。

前端部分不做过多赘述,有兴趣的可以直接查看源码。

服务端

服务端采用Nodejs,框架采用的是Koa2.0

目录结构说明├── bin

│   ├── index.js # 项目入口文件│   ├── www # 配置引入├── config

│   ├── config.js # 配置项目│   ├── db.js # 数据库配置│   ├── redis # redis配置│   ├── render.js # 数据接口渲染├── app

│   ├── controllers # 操作层 执行服务端模板渲染,json接口返回数据,页面跳转│   │   ├── admin.js

│   │   ├── index.js

│   │   ├── user.js

│   │   └── work.js

│   ├── middleware # 中间件集合│   │   └── index.js

│   ├── models # 数据模型层 执行数据操作│   │   └── user.js

│   ├── routers # 路由层 控制路由│   │   ├── user.js # /user/* 子路由│   │   ├── home.js # 主页子路由│   │   ├── index.js # 子路由汇总文件├── static  #静态资源复制代码

数据库

数据库采用Mysql,框架采用的是Sequelize,是一个基于promise的关系型数据库Node.js ORM框架,用起来还蛮方便,推荐使用。

安装mySql数据库

可以参考官方文档

这里顺便推荐一款比较实用的数据库管理工具:Navicat Premium

集群管理

集群管理采用PM2,是一个带有负载均衡功能的 Node 应用的进程管理器。pm2的安装和使用非常容易,具体可参考pm2的安装和使用

a898d793afa9873972da69156071f93c.png

API文档工具

这里再分享一个能自动生成API文档的库koa2-swagger-ui,可以把 json 文件的 api 数据渲染成 swagger ui,具体使用方法可以参考项目代码。npm i koa2-swagger-ui -D复制代码

f711f092c94ccc75cd9a9b65d6fcad87.png

服务端配置说明

www入口文件配置const koa = require("koa");

const koaSwagger = require('koa2-swagger-ui');

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

const path = require('path');

const koaBody = require('koa-body');

const { cross, onerror, onheader } = require("../app/middleware");

const pkg = require("../package.json");

const app = new koa();

app.use(onerror()); // 系统错误,统一错误捕获

/*更多的配置可以拉取仓库代码进行查看*/复制代码

数据库配置配置文件路径:/config/db.js

针对不同环境,配置不同的数据库地址:const Sequelize = require('sequelize');

const { env } = require("./config");

let config = {};

switch (env) {

case "dev":

config = {

database: 'testDB', // 使用哪个数据库

username: 'root', // 用户名

password: 'dev@123', // 口令

host: '127.0.01', // 主机名

port: 3306 // 端口号,MySQL默认3306

};

break;

case "test":

config = {

database: 'testDB', // 使用哪个数据库

username: 'root', // 用户名

password: 'test@123', // 口令

host: 'test.mysql.rds.aliyuncs.com', // 主机名

port: 3306 // 端口号,MySQL默认3306

};

break;

case "prd":

config = {

database: 'testDB', // 使用哪个数据库

username: 'root', // 用户名

password: 'prd@123', // 口令

host: 'prd.mysql.rds.aliyuncs.com', // 主机名

port: 3306 // 端口号,MySQL默认3306

};

break;

}

export const sequelize = new Sequelize(config.database, config.username, config.password, {

host: config.host,

dialect: 'mysql',

pool: {

max: 5,

min: 0,

idle: 30000

}

});复制代码

路由配置配置文件路径:/app/routers/index.jsconst router = new require('koa-router')()

const home = require('./home')

const user = require("./backend/user")

const swaggerJSDoc = require('swagger-jsdoc')

const pkg = require("../../package.json")

const swaggerDefinition = {

info: {

title: 'API',

version: '1.0.0',

description: 'API',

},

host: `localhost:${pkg.port}`,

basePath: '/' // Base path (optional)

};

const options = {

swaggerDefinition,

apis: ['./app/routers/backend/*.js', './app/routers/front/*.js'], // 写有注解的router的存放地址

};

const swaggerSpec = swaggerJSDoc(options)

// 通过路由获取生成的注解文件

router.get('/swagger.json', async function (ctx) {

ctx.set('Content-Type', 'application/json');

ctx.body = swaggerSpec;

})

router.use('', home.routes())

router.use('/backend/user', user.routes())

module.exports = router复制代码

中间件集合通俗的讲:中间件就是匹配路由之前或者匹配路由完成做的一系列的操作。const { renderData } = require("../../config/render")

const { log } = require("../../util/utils")

const koajwt = require('koa-jwt')

/**

* 跨域处理

* @example app.use(cross())

*/

export function cross() {

return async function (ctx, next) {

ctx.set('Access-Control-Allow-Origin', ctx.get("Origin") == null ? "*" : ctx.get("Origin"));

ctx.set('Access-Control-Allow-Methods', ctx.get("Access-Control-Request-Method") || "PUT, GET, POST, DELETE, OPTIONS");

ctx.set('Access-Control-Allow-Headers', ctx.get("Access-Control-Request-Headers") || "Content-Type");

ctx.set('Access-Control-Allow-Credentials', "true");

if (ctx.method == "OPTIONS") {

ctx.status = 204

}

await next();

}

}

/**

* 兼容路由后缀,如 xxx/xxx.json == xxx/xxx 地址

* @param suffixes string[] 后缀列表

* @example app.use(adaptRouteSuffix([".json"]))

*/

export function adaptRouteSuffix(suffixes = []) {

return async function (ctx, next) {

suffixes.forEach(e => {

var re = new RegExp(e);

ctx.path = ctx.path.replace(re, "")

})

await next();

}

}

/**

* 错误日志捕获

* @example app.use(onerror())

*/

export function onerror() {

return async function (ctx, next) {

return next().catch((err) => {

if (err.status === 401) {

ctx.status = 200;

renderData(ctx, null, 401, "用户没有权限(令牌、用户名、密码错误)", err.message)

} else if (ctx.status === 404) {

var err = new Error('Not Found');

err.status = 404;

renderData(ctx, null, 404, "系统繁忙,请联系管理员", err.message);

} else {

renderData(ctx, null, -1, "服务端错误", err.message);

log(err.message);

}

})

}

}

/**

* 延迟

* @example await delay(5000) // 延迟5s

*/

export function delay(time) {

return new Promise(function (resolve) {

setTimeout(function () {

resolve();

}, time);

});

};

/**

* 请求头拦截

*/

export function onheader() {

return koajwt({

secret: 'polo_token'

}).unless({

path: [/\/user\/login|swagger|front/]

})

}复制代码

基本功能展示

登录

登录模块,这里就介绍下服务端的实现,主要依赖两个插件,jsonwebtoken(jwt)和koa-jwt,前者主要负责加密,生成token返回给前端,后者实现对token的校验,在中间件中实现请求头拦截,验证失败返回401。具体可以参考代码./app/controllers/user.js。/**

* 用户登录

* @return 用户登录成功对象

*/

export async function login(ctx) {

const data = ctx.request.body;

if (!data.name || !data.password) {

renderData(ctx, null, 102, '参数不合法');

}

const result = await GetUser({

name: data.userName,

password: data.password

})![](https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/c5ea9616f33a49988ca9244991c63df1~tplv-k3u1fbpfcp-watermark.image)

if (result !== null) {

const token = jwt.sign({

name: result.name,

password: result.password

}, 'polo_token', { expiresIn: '2h' });

const userData = {

userName: result.name,

token: 'Bearer ' + token

}

renderData(ctx, userData, 0, '登录成功');

} else {

renderData(ctx, null, 101, '用户名或密码错误');

}

}

/**

* 请求头拦截

*/

export function onheader() {

return koajwt({

secret: 'polo_token'

}).unless({

path: [/\/user\/login|swagger|front/]

})

}复制代码

6b21075c3c8d6dd1b41a52a0c7e9fd10.png

后台部分内容展示

4b6b97f9b7a98d58f310c4a46bec3349.png

c1d93ba96fe358fa22cf4ff807823496.png

4037908a7f973ddbfe05b01ef1d85df9.png

632e9fa0996ea38687a02a3d6858348c.png

写在最后

以上文章是我前段时间全栈开发已上线项目的简略版分享,文章开头已附上了该项目的前后端源码,顺便提供了测试数据(rnpxDemo.sql),只需把代码克隆下来并保证电脑已安装所需软件,另有不足之处也请多多指正,非常感谢。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值