nodejs + express + mysql + redis 基础功能实现

nodejs + express + mysql + redis 基础功能实现

 
9 人赞同了该文章

本文大体介绍了nodejs项目的创建、express框架的使用、mysql数据库的连接、以及redis的数据交互等方法,并举例了些简单的例子进行说明,代码都是亲自重头跑了一遍的,拿来可用。

 

一、创建nodejs 项目

1. 创建一个文件夹,以node_demo 为例,运用cmd 进入该文件夹,输入指令初始化项目

npm init -y

生成package.json 文件

可先安装以下包,后面会用到

 

2. nodejs 启动服务测试

创建server.js 文件,以hellow word! 为例做测试

本人用的 vscode,敲node 发现没代码提示,敲着有点不得劲。(不过一个个字母敲出来有助于记忆,有闲情的可以试试。)于是先去搞个代码提示插件。

打开vscode 终端控制台,安装 @types

npm i @types/node --save-dev

好了,现在有提示了

直接上代码

const http = require('http');

http.createServer((req, res) => {
  res.writeHead(200, {
    'Content-Type': 'Text/plain'
  });

  res.end('hellow word!');
}).listen(3307, () => {
  console.log('服务启动');
})

浏览器中输入 localhost:3307

出现 hellow word! 一个简单的服务就写好了

 

3. 运用express框架写接口

以get 接口 /testGet,post接口/testPost 为例,server.js代码如下

const express = require('express');
const app = express();
app.use(express.json()); // 解析json请求
app.use(express.urlencoded({extended: false})) // 解析URL-encoded请求

app.listen(3307, () => {
  console.log('服务启动');
})

app.get('/testGet', (req, res) => { // 测试get 请求
  returnParams(req.query, res)
})

app.post('/testPost', (req, res) => { // 测试post 请求
  returnParams(req.body, res)
})

function returnParams(data, res) {
  res.json({ code: 1, status: 'S', data: data, msg: '成功' })
}

 

打开 postman,调用接口测试

get 接口测试返回如下,可见testGet 接口拿到参数且成功返回

post 接口测试返回如下,可见testPost 接口也成功返回

注:post 请求时,json 格式需调用express.json中间件,表单格式需调用express.urlencoded 中间件

app.use(express.json()); // 解析json请求
app.use(express.urlencoded({extended: false})) // 解析URL-encoded请求

有时我们在调用相应的接口前需要做相应的拦截判断,此时可使用以下代码

app.all('*', (req, res, next) => {
  // 写入相应的拦截操作
  next(); // 要继续往下跑记得写上 next()
})

 

4. 热加载 与 跨域

写到这里你应该会发现,每改一次文件,你都需重新node server.js 一次,非常麻烦,于是这里使用hotnode 热加载,每保存一次,它将自动重新加载服务。

npm i hotnode --save

然后使用 hotnode server.js 启动node 即可。

若觉得该命令太长懒得写,也可在package.json 文件做如下配置

如此一来,使用 npm start 即可,但这样会有如下报错

根据网上查到的方法,print 为打印方法,既然程序没找到,那么干脆把它改为 console.log 方法。

打开hotloader.js 文件,找到相应位置,改为如下代码

this.process.stdout.on("data", function(data) {
  return console.log(data.toString());
  // return util.print(data.toString());
});

然后使用 npm start 运行就正常了

跨域问题

A. 可以使用现有轮子

npm i cors --save

const cors = require("cors")
app.use(cors()) // 解决跨域

B. 也可以用如下代码设置

//设置跨域访问
app.all('*', (req, res, next) => {
 res.header("Access-Control-Allow-Origin", "*");
 res.header("Access-Control-Allow-Headers", "X-Requested-With");
 res.header("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS");
 res.header("X-Powered-By", ' 3.2.1');
 res.header("Content-Type", "application/json;charset=utf-8");
 next();
});

 

5. express router

以上虽然实现了接口的编写,但为了方便管理接口、区分功能模块,我们使用router 来划分下。

首先创建routes 文件夹,假设有一个“测试”模块,那么在routes 文件夹下创建test.js 文件

test.js 文件代码如下

const express = require('express');
const router = express.Router();

router.get('/testGet', (req, res) => { // 测试get 请求
  returnParams(req.query, res)
})

router.post('/testPost', (req, res) => { // 测试post 请求
  returnParams(req.body, res)
})

function returnParams(data, res) {
  res.json({ code: 1, status: 'S', data: data, msg: '成功' })
}

module.exports = router

则 server.js 文件代码更改如下

const express = require('express');
const app = express();
const test = require('./routes/test');

app.use(express.json()); // 解析json请求
app.use(express.urlencoded({extended: false})) // 解析URL-encoded请求

app.listen(3307, () => {
  console.log('服务启动');
})

app.all('*', (req, res, next) => {
  // 写入相应的拦截操作
  next(); // 要继续往下跑记得写上 next()
})

app.use('/test', test);

二、使用 sequelize 操作mysql 数据库

1. 开发准备

先下载安装mysql数据库,然后安装navicat 操作数据库,这里不过多说明,可自行百度。

以建好的表article 为例

项目中先安装 mysql、mysql2、sequelize 包

npm i mysql mysql2 sequelize --save

 

2. 连接数据库,建立模型

新建database 文件夹,在文件夹下新建db.js文件,写入代码如下

const Sequelize = require("sequelize");
const db = {}

const sequelize = new Sequelize('my_website', 'root', '123456', {
  host: 'localhost',
  dialect: 'mysql',
  pool: {
    max: 5,
    min: 0,
    acquire: 3000,
    idle: 10000,
  }
});

db.sequelize = sequelize
db.Sequelize = Sequelize

module.exports = db;

这里可参照官方文档

 

然后建立模型

新建文件夹models,在文件夹下新建 Article.js 文件,写入代码如下(字段与数据库字段对应)

const Sequelize = require("sequelize");
const db = require("../database/db");

module.exports = db.sequelize.define('article', {
  aid: {
    type: Sequelize.INTEGER,
    primaryKey: true, // 主键
  },
  title: {
    type: Sequelize.STRING,
  },
  title_map: {
    type: Sequelize.STRING,
  },
  content: {
    type: Sequelize.TEXT,
  },
  create_time: {
    type: Sequelize.DATE,
  },
  agree_num: {
    type: Sequelize.INTEGER,
  },
  disagree_num: {
    type: Sequelize.INTEGER,
  },
  comments_num: {
    type: Sequelize.INTEGER,
  },
}, {
  timestamps: false, // 不自动加上 createdAt 和 updatedAt
  freezeTableName: true, // 强制表名称等于模型名称,不自动将模型名复数并将其用作表名
})

注:nodejs 连接数据库时,可能会报错,文章最下方“参考资料”中给出了两个常见问题解决链接

 

3. 查询文章列表接口

routes 文件夹下建立article.js 文件,代码如下

const express = require('express');
const router = express.Router();
const Article = require('../models/Article');
 
router.post('/searchArticle', (req, res) => {
 Article.findAll().then(sqlRes => {
 res.json({ code: 1, status: 'S', data: sqlRes, msg: '成功' })
  }).catch(sqlError => {
 res.json({ code: 0, status: 'E', data: sqlError, msg: sqlError })
  })
})
 
module.exports = router;

回到server.js 文件引入article

const article = require('./routes/article');
app.use('/article', article);

 

启动服务,用postman做测试,查询article 表中的数据

可见已查询成功,那么查询表数据就实现了。其他的增、删、改等操作在此不过多赘述,有兴趣的可以去官网看看。

 

三、nodejs 操作redis

1. 开发准备

下载安装redis后,启动redis,启动成功界面如下

保留该窗口,另启一个窗口,redis安装文件夹目录下输入命令

redis-cli -h localhost -p 6379

项目中安装 redis 包

npm i redis --save

 

2. 编写代码

创建redis 文件夹

新建redisOptions.js 文件,代码如下

const options = {
 host: 'localhost',
 port: 6379,
 // password: '', // 本人未设置密码,所以隐藏,若你设了密码,则输入密码
 detect_buffers: true // 传入buffer 返回也是buffer 否则会转换成String
}
 
module.exports = options

 

新建redisConfig.js 文件,代码如下(想要用到什么redis 操作,可自行写入方法)

const redis = require('redis')
const redisOptions = require('./redisOptions')

const options = {
  host: redisOptions.host,
  port: redisOptions.port,
  password: redisOptions.password,
  detect_buffers: redisOptions.detect_buffers, // 传入buffer 返回也是buffer 否则会转换成String
  retry_strategy: function (options) {
    // 重连机制
    if (options.error && options.error.code === "ECONNREFUSED") {
      // End reconnecting on a specific error and flush all commands with
      // a individual error
      return new Error("The server refused the connection");
    }
    if (options.total_retry_time > 1000 * 60 * 60) {
      // End reconnecting after a specific timeout and flush all commands
      // with a individual error
      return new Error("Retry time exhausted");
    }
    if (options.attempt > 10) {
      // End reconnecting with built in error
      return undefined;
    }
    // reconnect after
    return Math.min(options.attempt * 100, 3000);
  }
}

// 生成redis的client
const client = redis.createClient(options)

// 存储值
const setValue = (key, value) => {
  if (typeof value === 'string') {
    client.set(key, value)
  } else if (typeof value === 'object') {
    for (let item in value) {
      client.hmset(key, item, value[item], redis.print)
    }
  }
}

// 数值自增
const incrValue = (key, value) => {
  client.incr(key, value)
}

// 获取string
const getValue = (key) => {
  return new Promise((resolve, reject) => {
    client.get(key, (err, res) => {
      if (err) {
        reject(err)
      } else {
        resolve(res)
      }
    })
  })
}

// 获取hash
const getHValue = (key) => {
  return new Promise((resolve, reject) => {
    client.hgetall(key, function (err, value) {
      if (err) {
        reject(err)
      } else {
        resolve(value)
      }
    })
  })
}

// 导出
module.exports = {
  setValue,
  incrValue,
  getValue,
  getHValue
}

回到 test.js 文件,写入如下代码测试

const redis = require('../redis/redisConfig');
redis.setValue('testKey', 'testValue');

 

在命令行窗口中输入get testKey,发现值成功返回

 

nodejs 获取redis 值则使用 redis.getValue()

redis.getValue('testKey').then(val => {
 console.log('val:', val);
})

 

到此,nodejs 基本功能差不多算说完了,最终目录结构如下

 

##### 废话star (可跳过)

本文主要是借鉴他人文章整合而成,在此特做说明,借鉴资料出处文后有说明。

写此文目的有三:

1. 梳理下知识以便更好的记忆;

2. 整合起来方便阅读,避免东查一点功能、西查一点功能,节省时间。方便自学者学习,也方便本人复制黏贴;

3. 以往都是复制别人的代码,拿别人的知识,现在怎么说也由小白晋级菜鸟了,也输出下知识做点回馈吧。

 

另:本人nodejs 用的较少,受限于眼界与项目经验,多有不足之处还望指正,有更优的方案或思路也望不吝赐教,感谢。

第一次写文,啰嗦了点,咳咳,

##### 废话end

posted @ 2024-05-23 16:08  商君治国安邦之张莽  阅读(75)  评论(0编辑  收藏  举报