1.1项目结构
1.2 babel环境配置
下载
javascript
yarn add @babel/cli @babel/core @babel/node @babel/preset-env babel-loader babel-plugin-module-resolver -D
配置
javascript
{
"presets": ["@babel/preset-env"],
"plugins": [
["module-resolver", {
"root": ["./src"],
"alias": {
"@": "./src"
}
}]
]
}
1.3webpack打包配置
下载
javascript
yarn add webpack-cli webpack webpack-dev-middleware webpack-hot-middleware webpack-merge
配置
根目录下新建webpack.common.js,webpack.pro.js,webpack.dev.js
拆分webpack
分公共,生产,开发不同环境打包配置
配置代码
公共配置
javascript
const path = require('path');
const webpack = require('webpack');
module.exports = {
target: 'node',
entry: './src/app.js',
output: {
path: path.resolve(__dirname, 'dist/js'),
filename: '[name].[contenthash].js',
clean: true,
},
mode: "production",
resolve:{
alias:{
extensions: ['.js', '.json'],
//@符号表示 src 这一层目录
'@': path.resolve(__dirname, './src')
}
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env'],
},
},
},
],
},
externals: {
'sequelize':"require('sequelize')"
},
resolve: {
extensions: ['.js'],
},
optimization: {
splitChunks: {
chunks: 'all',
},
minimize: true,
},
plugins: [
new webpack.ProgressPlugin(),
],
};
开发环境
javascript
const { merge } = require('webpack-merge');
const commonConfig = require('./webpack.common');
module.exports = merge(commonConfig, {
mode: 'development',
});
生产环境
javascript
const { merge } = require('webpack-merge');
const commonConfig = require('./webpack.common');
module.exports = merge(commonConfig, {
mode: 'production',
});
1.4package.json配置
json
{
"name": "koa_service",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"dev": "nodemon --watch @/ --exec babel-node ./src/app.js",
"build": "webpack --config ./build/webpack.prod.js && xcopy .env dist && xcopy ecosystem.config.js dist",
"build:dev": "webpack --config ./build/webpack.dev.js && xcopy .env dist && xcopy ecosystem.config.js dist"
},
"author": "",
"license": "ISC",
"dependencies": {
"@babel/cli": "^7.23.4",
"@babel/core": "^7.23.7",
"@babel/node": "^7.22.19",
"@babel/preset-env": "^7.23.8",
"babel-loader": "^9.1.3",
"babel-plugin-module-resolver": "^5.0.0",
"dotenv": "^16.3.1",
"fs": "^0.0.1-security",
"koa": "^2.14.2",
"koa-bodyparser": "^4.4.1",
"koa-cors": "^0.0.16",
"koa-ip": "^2.1.3",
"koa-router": "^12.0.1",
"mysql2": "^3.6.3",
"sequelize": "^6.35.0",
"webpack": "^5.89.0",
"webpack-cli": "^5.1.4",
"webpack-dev-middleware": "^6.1.1",
"webpack-hot-middleware": "^2.25.4",
"webpack-merge": "^5.10.0"
},
"devDependencies": {
"@babel/plugin-transform-runtime": "^7.23.7",
"@babel/runtime": "^7.23.8",
"nodemon": "^3.0.1"
}
}
2.配置koa
2.1安装 Koa 框架
javascript
yarn add koa
2.2 编写入口文件
javascript
const Koa = require('koa')
const app = new Koa()
app.use((ctx, next) => {
ctx.body = 'ws'
})
app.listen(3000, () => {
console.log('server is running on http://localhost:3000')
})
2.3使用nodemon
安装nodemon
javascript
yarn add nodemon -D
配置nodemon
json
{
"name": "koa_service",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"dev": "nodemon ./src/app.js",
},
"author": "",
"license": "ISC",
"dependencies": {
"koa": "^2.14.2",
},
"devDependencies": {
"nodemon": "^3.0.1"
}
}
nodemon使用成功
2.4解析body参数
安装koa-bodyparser
javascript
yarn add koa-bodyparser
在app/index.js入口配置文件注册
javascript
const koa = require("koa");
const app = new koa();
// 处理post参数解析中间件
app.use(bodyParser());
module.exports = app;
2.5解决跨域
安装koa-cors
yarn add koa-cors
javascript
const Koa = require("koa");
const cors = require("koa-cors");
const app = new Koa();
//处理跨域问题中间件
app.use(cors());
2.6获取ip
安装koa-ip
yarn add koa-ip
配置
javascript
/*
* @Description:
* @Author: Wang Su
* @Date: 2023-09-16 23:31:37
* @LastEditors: Wang Su
* @LastEditTime: 2023-09-21 14:36:46
*/
const Koa = require("koa");
const ip = require("koa-ip");
//获取用户ip的中间件
app.use(
ip({
checkProxyHeaders: true, // 选项示例
})
);
const port = 19001;
app.listen(port, () => {
console.log(`19001端口服务启用`);
});
3.config配置层
3.1根目录新建.env文件
typescript
# 后端服务端口号
APP_PORT=19801
# 数据库主机
MYSQL_HOST="localhost"
# 数据库端口号
MYSQL_PORT=3306
# 数据库用户名
MYSQL_USERNAME="root"
# 数据库的密码
MYSQL_PASSWORD="123456"
# 连接数据库连接名
MYSQL_DB="koa"
3.2使用dotenv
安装dotenv
javascript
yarn add dotenv
配置dotenv
javascript
const dotenv=require("dotenv")
dotenv.config()
module.exports=process.env
在入口文件引入config.default.js
typescript
const {APP_PORT}=require("./config/config.default.js")
const app =require("./app/index.js")
app.listen(APP_PORT,()=>{
console.log(`服务启动成功:http://localhost:${APP_PORT}`);
})
4.app启动层
4.1app入口文件
javascript
const {APP_PORT}=require("./config/config.default.js")
const app =require("./app/index.js")
app.listen(APP_PORT,()=>{
console.log(`服务启动成功:http://localhost:${APP_PORT}`);
})
4.2app配置文件
javascript
const koa = require("koa");
const bodyParser = require("koa-bodyparser");
const errHandle = require("./err.handle");
const userRouter = require("../router/users");
const app = new koa();
// 处理post参数解析中间件
app.use(bodyParser());
app.use(userRouter.routes()).use(userRouter.allowedMethods());
//错误处理
app.on("error", errHandle);
module.exports = app;
5.router路由层
5.1新增路由中间件
javascript
const koa = require("koa");
const userRouter = require("../router/users");
const app = new koa();
app.use(userRouter.routes()).use(userRouter.allowedMethods());
5.2路由层配置
根据功能划分路由层
javascript
const Router=require("koa-router")
const {userValidator,usernameValidator}=require("../../middlewares/users.middleware")
const router=new Router({prefix:"/users"})
const {regiest}=require("../../controller/users/index")
router.post("/regiest",userValidator,usernameValidator,regiest)
module.exports=router
6.controller业务控制层
处理对应路由的业务逻辑实现
6.1路由层注册controller层服务
javascript
const Router=require("koa-router")
const {userValidator,usernameValidator}=require("../../middlewares/users.middleware")
const router=new Router({prefix:"/users"})
//这里注册业务层代码
const {regiest}=require("../../controller/users/index")
router.post("/regiest",userValidator,usernameValidator,regiest)
module.exports=router
6.2controller代码实现
javascript
const { createUser } = require("../../service/user/index");
class UseController {
//用户注册逻辑
async regiest(ctx, next) {
//获取前端传入结果
const { user_name, password } = ctx.request.body;
//操作数据库
const res = await createUser(user_name, password);
//返回给前端结果
ctx.body = {
code: 0,
message: "用户注册成功",
result: {
id: res.id,
user_name: res.user_name,
},
};
}
}
module.exports = new UseController();
7.service服务层
7.1控制层注册服务层
下面的createUser方法来源于服务层
javascript
const { createUser } = require("../../service/user/index");
class UseController {
//注册逻辑
async regiest(ctx, next) {
//获取前端传入结果
const { user_name, password } = ctx.request.body;
//操作数据库,
const res = await createUser(user_name, password);
//返回给前端结果
ctx.body = {
code: 0,
message: "用户注册成功",
result: {
id: res.id,
user_name: res.user_name,
},
};
}
}
module.exports = new UseController();
7.2服务层代码实现
javascript
const User = require("../../model/users/index");
class UserService {
//创建,使用async,数据库操作是异步的
async createUser(user_name, password) {
try {
const res = await User.create({
user_name,
password,
});
return res.dataValues;
} catch (error) {
return error;
}
}
// 根据任意字段查询
async getUserInfo({id, user_name, password, is_admin}) {
try {
const whereOpt = {};
id && Object.assign(whereOpt, { id });
user_name && Object.assign(whereOpt, { user_name });
password && Object.assign(whereOpt, { password });
is_admin && Object.assign(whereOpt, { is_admin });
console.log(whereOpt,'whereOpt');
const res = await User.findOne({
attributes: ["id", "user_name", "password", "is_admin"],
where: whereOpt,
});
return res ? res.dataValues : null;
} catch (error) {
return error;
}
}
}
module.exports = new UserService();
8.DB数据层
8.1集成sequlize
官网 Sequelize 是一个基于 promise 的 Node.js ORM, 目前支持 Postgres, MySQL, MariaDB, SQLite 以及 Microsoft SQL Server. 它具有强大的事务支持, 关联关系, 预读和延迟加载,读取复制等功能。 Sequelize 遵从 语义版本控制。 支持 Node v10 及更高版本以便使用 ES6 功能。 请通过 Getting started - 入门 来学习更多相关内容. 如果你想要学习 Sequelize API 请通过 API 参考 (英文)。 ORM: 对象关系映射
- 数据表映射(对应)一个类
- 数据表中的数据行(记录)对应一个对象
- 数据表字段对应对象的属性
- 数据表的操作对应对象的方法
8.2安装mysql和 sequelize
javascript
yarn add mysql2 sequelize
8.3连接mysql数据库
javascript
const { Sequelize } = require("sequelize");
//连接数据库
const {
MYSQL_HOST,
MYSQL_PORT,
MYSQL_USERNAME,
MYSQL_PASSWORD,
MYSQL_DB,
} = require("../config/config.default.js");
const seq = new Sequelize(MYSQL_DB, MYSQL_USERNAME, MYSQL_PASSWORD, {
host: MYSQL_HOST,
port: MYSQL_PORT,
dialect: "mysql",
});
//检测数据库是否连接成功
seq
.authenticate()
.then((res) => {
console.log("数据库连接成功");
})
.catch((err) => {
console.log("数据库连接失败");
});
module.exports = seq;
9.model模型层
9.1服务层注册模型层
9.2模型层代码实现,引入数据层
javascript
const { Sequelize, DataTypes } = require("sequelize");
const seq = require("../../db/seq");
const User = seq.define(
"iotUser",
{
// 在这里定义模型属性
user_name: {
type: DataTypes.STRING,
unique: true,
allowNull: false,
comment: "用户名,唯一",
},
password: {
type: DataTypes.CHAR(64),
allowNull: false,
comment: "密码",
},
is_admin: {
type: DataTypes.BOOLEAN,
allowNull: false,
defaultValue: 0,
comment: "是否是管理员,0不是,1是",
},
},
{
// 这是其他模型参数
tableName: "iot_users",
}
);
//如果数据库没有这张表会强制创建
User.sync();
module.exports=User
10.middlewares中间件层
10.1路由层引入
javascript
const Router=require("koa-router")
const {userValidator,usernameValidator}=require("../../middlewares/users.middleware")
const router=new Router({prefix:"/users"})
const {regiest}=require("../../controller/users/index")
router.post("/regiest",userValidator,usernameValidator,regiest)
module.exports=router
10.2代码实现
javascript
const { getUserInfo } = require("../service/user/index");
const { userFormateError, userAlreadyExit } = require("../constant/err.type");
const userValidator = async (ctx, next) => {
const { user_name, password } = ctx.request.body;
if (!user_name || !password) {
ctx.app.emit("error", userFormateError, ctx);
return;
}
await next();
};
const usernameValidator = async (ctx, next) => {
const { user_name } = ctx.request.body;
if (await getUserInfo({ user_name })) {
ctx.app.emit("error", userAlreadyExit, ctx);
return;
}
await next();
};
module.exports = {
userValidator,
usernameValidator,
};
10.3公共错误处理
定义错误类型字典
javascript
module.exports = {
userFormateError: {
code: "1001",
message: "用户名密码为空",
result: [],
},
userAlreadyExit: {
code: "1002",
message: "用户已存在",
result: [],
},
};
错误映射表,映射状态码
javascript
module.exports = (err, ctx) => {
let status = 500;
switch (err.code) {
case "1001":
status = 400;
break;
case "1002":
status = 401;
break;
default:
status = 500;
break;
}
ctx.status=status;
ctx.body=err
};
全局注册错误处理中间件
javascript
const koa = require("koa");
const bodyParser = require("koa-bodyparser");
const errHandle = require("./err.handle");
const userRouter = require("../router/users");
const app = new koa();
// 处理post参数解析中间件
app.use(bodyParser());
app.use(userRouter.routes()).use(userRouter.allowedMethods());
//错误处理
app.on("error", errHandle);
module.exports = app;
用户已存在