日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

快速的利用 Express 框架实现一个 Rustfull 接口的后端 Server

發布時間:2025/3/15 编程问答 13 豆豆
生活随笔 收集整理的這篇文章主要介紹了 快速的利用 Express 框架实现一个 Rustfull 接口的后端 Server 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

快速的利用 Express 框架實現一個 Rustfull 接口的后端 Server

附:基于 Nodejs 的服務器后端的框架用的比較多的是 Koa : github/kaojs/koa 但本文這里介紹的基于 Express 框架。

附錄: 前端開發,和一般開發 (非官方說法) 有三個階段:

  • 基于代碼 Code 的 log 打印階段調試開發
  • 基于 IDE,如(Vscode) 的代碼調試,斷點階段。
  • 基于測試用例 (TDD) 驅動開發的測試驅動開發階段,針對前端的或 nodejs 的項目,推薦使用Facebook 開源的 Jest 包做單元測試和測試驅動。

REST 介紹

  • REST是Representational State Transfer的縮寫。它是Web標準架構和HTTP協議。REST架構風格描述了Roy Fielding在博士論文中最初表達的六個限制,并將RESTful風格的基礎定義為:

    • 統一的界面
    • 無狀態
    • 可緩存
    • 客戶端服務器
    • 分層系統
    • 按需編碼

RESTful 的應用程序使用HTTP執行四種操作CRUD(C:create,R:read,U:update,D:delete)。Create和Update用來提交數據,get來讀取數據,delete用來移除數據。RESTful由基本URL,URL,媒體類型等組成。

使用的工具

  • Node.js
  • MySqL
  • Redis
  • Ticker (定時器)
  • Postman (測試接口)

構建工程

注:如果你的需求是基于 express 建立一個 Web 項目,建議可以使用官方的推薦框架生成器,通過應用生成器工具 express-generator 可以快速創建一個應用的骨架。具體可以參見:http://www.expressjs.com.cn/starter/generator.html

  • 進入你的工程目錄,打開你的終端并且進行以下步驟:

首先做下面的準備工作。

  • npx license mit 通過license包下載對應的協議npx gitignore node使用gitignore包自動的從Github倉庫中下載相關文件
  • npx covgen使用covgen包生成一份貢獻者契約,這會讓你的項目更受貢獻者的歡迎。
  • 創建一個 pcxProject 文件夾
  • mkdir pcxProject
  • 轉入你剛剛創建的目錄
  • cd pcxProject
  • 創建package.json文件
  • npm init
    • Package.json文件告訴了npm必要的信息,讓npm可以識別項目,同時處理項目的依賴。

    • npm初始化將會提示你輸入一些必要信息,比如說app名稱、描述、版本、作者、關鍵字以及你是否相應看見你喜歡的。

    你將會看到類似于下面這樣的結果:

    • 輸入yes,按下enter鍵來完成package.json文件的創建。
  • 創建server.js文件
  • touch server.js
    • 在這個server中,我們將會寫下創建我們server的代碼。創建一個api文件夾mkdir api
  • 在這個api文件夾中,創建三個獨立的models、routes、以及controllers文件夾
  • mkdir api/controllers api/models api/routes
  • 在api/controller文件夾中創建 Controller.js文件,在routes文件中創建 Routes.js 文件,在models文件夾中創建 Model.js 文件
    • 我們的文件目錄應該像下面這樣:

    • 其中,config 文件下面主要是程序啟動之前的初始化操作。如定義的初始化數據在 Express Server 啟動之前的初始化操作,或者一些數據庫連接的初始化。

    Express Server 安裝及開發

    • 現在來安裝express和nodmon,express用來創建server,nodmon幫助我們追蹤我們應用程序的改變,它會監視文件的改變并且自動重啟server。
    npm install --save-dev nodemon npm install express --save
    • 一旦成功安裝之后,你的package.json文件將會被修改,添加兩個新的依賴:
  • 打開 package.json 文件,并且把這個任務添加到文件中 。
  • "start" : "nodemon server.js"

  • 打開 server.js 文件,啟動 Express 可以采用如下的代碼:
  • var express = require('express'),app = express(),port = process.env.PORT || 3000;app.listen(port);console.log('todo list RESTful API server started on: ' + port);
  • 在你的終端中運行 npm run start,啟動你的server,你將會看到如下 Log.
  • todo list RESTful API server started on: 3000

    安裝數據庫

    mongoDB

    • 首先,我們要安裝mongoose

    yarn add mongoose

    • Mongoose 是我們用來與 MongoDB 數據庫交互的工具。安裝之后,打開 Model.js 文件,輸入以下代碼并且保存:
    'use strict'; var mongoose = require('mongoose'); var Schema = mongoose.Schema;var TaskSchema = new Schema({name: {type: String,Required: 'Kindly enter the name of the task'},Created_date: {type: Date,default: Date.now},status: {type: [{type: String,enum: ['pending', 'ongoing', 'completed']}],default: ['pending']} });module.exports = mongoose.model('Tasks', TaskSchema);
    • 通過上面的代碼,我們在我們的文件導入了mongoose,我們創建了一個模型,說明我們的數據集應該呈現的樣子。

    • 正如你所看到的,它指出了數據集(表)應該包含一個名稱,它的類型應該是string,還包括了創建日期。它也包含了任務狀態,每個任務被創建的時候都有默認值pending。

    MySqL

    • 這里使用 promise-mysql 可以避免寫回調函數。
    yarn add promise-mysql
    • 在程序服務啟動之前,在 config 文件加下面添加一個數據庫初始化的操作,touch promisePool.js 數據庫連接池。
    const mysql= require("promise-mysql");// For Mysql const pool = mysql.createPool({host: config.DBConfig.DBAddr,port: config.DBConfig.Port,user: config.DBConfig.UserName,password: config.DBConfig.Password,database: config.DBConfig.DbName,connectionLimit: 10, });async function getPool() {return pool; }async function getConnection() {return (await pool).getConnection(); }
    • 在使用的時候,直接可從連接池獲取一個連接。

    • 在 config 文件夾的另外一個文件 initServer.js 如其名字一樣,提供了初始化的變量的一些工作和導出函數。

    • 之外,在 model.js 中封裝了要使用的函數,比如:導出 getAllAddr( )

    // For Database async function getAllAddr(tableName,coinType){let connection = await getConnection();try {let sqlStr = `select * from ${tableName} where cointype='${coinType}';`// var sqlStr = sqlString.format('SELECT * FROM walletaddress WHERE cointype= ?',[coinType])console.log(sqlStr)const result = await connection.query(sqlStr)// console.log(result)return result;} finally {connection.release();} }
    • 其他,MySql 獲取數據的的接口,如上即可。

    Redis

    • Redis 這里采用 async-redis 異步的連接 redis 的庫。

    • 在 config/promisePool.js 中加入 Redis 的初始化函數。

    const redis = require("async-redis");// For redis const ccIp = config.CCConfig.RedisAddr.split(':',2)[0] const ccPort = config.CCConfig.RedisAddr.split(':',2)[1] const client = redis.createClient(ccPort,ccIp,{auth_pass: config.CCConfig.Password})async function ccInit() {await client.on("error", function (err) {console.log("Error " + err);}); }var redisDao = function() {};redisDao.prototype.get = async function (key){let resp = await client.get(key);console.log('AfterGet:', resp)return resp }redisDao.prototype.set = async function (key, value){await client.set(key, value) }redisDao.prototype.del = async function (key){await client.del(key, function(err, o) {console.log("Del error: " + err);}) }redisDao.prototype.hgetall = async function(key) {let resp = await client.hgetall(key);// console.log('AfterGetAll:',resp)return resp }redisDao.prototype.hmset = async function(Item, key, value) {await client.hmset(Item,key,value) }redisDao.prototype.hdel = async function(Item, key) {console.log("DelHash Item:%s,key:%s", Item, key)await client.hdel(Item, key) }

    安裝路由

    • 路由決定了應用程序如何響應特定終端的客戶端的請求,一個特定的URL(或path)以及特定的HTTP請求(GET、POST等等)。

    • 每個路由都有不同的路由處理方法,當路由匹配時被執行。下面我們將會用不同的方法定義兩個基本的路由(“tasks”以及“/tasks/taskId”)。

    • “/tasks”有POST和GET方法,“/tasks/taskId”有GET、PUT和DELETE方法。

    • 正如你所看到的,我們需要controller,每個路由方法都能調用它對應的處理程序。controller 下面可以寫業務相關的 Restfull api 的響應處理函數。

    use strict'; module.exports = function(app) {var todoList = require('../controllers/todoListController');// todoList Routesapp.route('/tasks').get(todoList.list_all_tasks).post(todoList.create_a_task);app.route('/tasks/:taskId').get(todoList.read_a_task).put(todoList.update_a_task).delete(todoList.delete_a_task); };

    安裝控制器

    • 打開todoListController.js文件,然后進行下一步:

    • 在這個controller中,我們將會寫出5個不同的方法:list_all_tasks, create_a_task,read_a_task,update_a_task, delete_a_task。我們將會到處每個方法。

    • 每個方法會用到不同的mongoose方法,例如find、findById、findOneAndUpdate、save 以及 remove。

    'use strict';var mongoose = require('mongoose'),Task = mongoose.model('Tasks');exports.list_all_tasks = function(req, res) {Task.find({}, function(err, task) {if (err)res.send(err);res.json(task);}); };exports.create_a_task = function(req, res) {var new_task = new Task(req.body);new_task.save(function(err, task) {if (err)res.send(err);res.json(task);}); };exports.read_a_task = function(req, res) {Task.findById(req.params.taskId, function(err, task) {if (err)res.send(err);res.json(task);}); };exports.update_a_task = function(req, res) {Task.findOneAndUpdate(req.params.taskId, req.body, {new: true}, function(err, task) {if (err)res.send(err);res.json(task);}); };exports.delete_a_task = function(req, res) {Task.remove({_id: req.params.taskId}, function(err, task) {if (err)res.send(err);res.json({ message: 'Task successfully deleted' });}); };

    schedule 定時器任務

    • 這里采用 while(true) + sleep 實現定時器,此處有兩個定時器,兩個 while(true) 但是考慮到 nodejs 的單線程異步的特性,當遇到需要同步的函數或阻塞的操作或 IO 操作的時候,如網絡請求的操作時,nodejs 便會切換到其他地方去執行。除非是,await promise 操作才會等待。

    • 在scheduleTask 文件夾下面的 task.js 里面放入如下內容:

    const schedule = require('./schedule')async function startQueryBlock() {try {schedule.ParseBlockTicker()schedule.HeartBeatTicker()} catch (error) {console.error(error);} }module.exports = {startQueryBlock }
    • 在具體的 Schedule 中完成特定的定時任務的操作。(如下)
    const ParseBlockTicker = async () => {while(true) {await sleep(2000) // Todo **** // console.log('scheduleCronstyle:' + new Date());const block = await Server.ServerData.api.rpc.chain.getBlock();const lastHeight = parseInt(block.block.header.blockNumber.words[0]) if(lastHeight <= Server.ServerData.currentHeight) {continue} else {while(Server.ServerData.currentHeight < lastHeight) {Server.ServerData.currentHeight ++ // Todo if(Server.ServerData.currentHeight % 100 == 0) {console.log("[PCX] update node block info: node height is %d,mgr height is %d",lastHeight, Server.ServerData.currentHeight)}while(true) {err = await syncTo()if( err != null) {// if err happen, sleep 5 second retryawait sleep(5000);console.log("[PCX] fail to parse block and will try again. height : %d, err : %s", Server.ServerData.currentHeight, err);continue}break}await PromisePool.redisDao.set(Server.ServerData.PCX + 'HEIGHT', Server.ServerData.currentHeight)}}} }const HeartBeatTicker = async () => {while(true) {await sleep(30000)// console.log('heartBeatTicker:' + new Date());let nodeStatus = new Server.RespParam.NodeStatusReq()nodeStatus.msgid = Server.RespParam.GetMsgId()nodeStatus.coinType = Server.ServerData.PCXconst block = await Server.ServerData.api.rpc.chain.getBlock();if(!block.block) {nodeStatus.message = Server.ServerData.PCX + Server.ServerData.NodeOfflineMessageconsole.log("[PCX] TRON node error, Report it!")let err = await reportSyncNodeStatus(nodeStatus)if(err != null) {console.log("reportNodeStatus failed")} else {console.log("reportNodeStatus successful.")}} else {nodeStatus.message = Server.ServerData.PCX + Server.ServerData.NodeAliveMessage}} }

    整合

    • 安裝 bodyParser, 使用 bodyParser 在處理之前,先在中間層解析請求中的body,在req.body屬性。它暴露了各種工廠來創建中間件。如果沒有body來解析或者空對象({}),中間件將會使用解析的req.body屬性來填充。

    • 關于主程序 Server.js 中可根據也業務調整如下:

    var ServerInit = require("./config/initServer") var express = require('express'); bodyParser = require('body-parser'); const parseBlock = require('./parseBlock/parseBlock')function startExpress() {app = express(),port = process.env.PORT || ServerInit.ServerData.HttpRestPort;app.use(bodyParser.urlencoded({ extended: true }));app.use(bodyParser.json());var routes = require('./api/routes/routes');routes(app); app.use(function(req, res) {res.status(404).send({url: req.originalUrl + ' not found'})});app.listen(port);console.log("Server has starting") }async function main() {await ServerInit.InitServer();startExpress();// 啟動定時任務parseBlock.startScheduleTask(); }main();

    通過Postman測試

    用 Postman 測試,略。

    總結

    以上是生活随笔為你收集整理的快速的利用 Express 框架实现一个 Rustfull 接口的后端 Server的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。