记录nodejs使用express搭建一个服务器程序,对外提供api,处理http请求(2)

此文章是我自己用来记录如何搭建一个以express为基础的api服务器框架的过程,并不是什么新手教程,并不会每一步都写得非常详细,如果您要阅读此文,需要一点nodejs和编写代码的基础知识

文接上篇 链接: 地址 https://blog.csdn.net/goodboy31985/article/details/106208989
在上文基础上,修改和完善api服务器的框架

修改最终的编译目录和启动文件

将tsc命令执行后的输出目录改为项目根目录下的app/ 文件夹(原为 dist/),这样功能更加明确,
并且将项目入口文件从app.ts 改为 start.ts
修改tsconfig.json中的输出目录
在这里插入图片描述
在这里插入图片描述
同时将通过vscode调试的功能配置文件中的入口文件也修改下
在这里插入图片描述
最终项目启动时,只要运行 node ./app/start.js 即可启动项目,比较清晰明了,此步骤按照个人习惯即可

增加配置文件,方便项目参数配置

之前我们的服务器端口是直接写在代码中的,但是这样灵活性很差,一般会使用一个配置文件,将一些参数写在配置文件中,项目启动时直接从配置文件中读取,这样项目部署的时候能更加灵活.

增加config.json5文件做完项目的配置文件

这里,我就增加一个config.json5的配置文件,以后一些可配置的内容,比如数据库地址,数据库名称,密码等,都可以写在配置中,可以更加灵活得进行部署
注意 我使用的是json5 格式,因为他是支持注释的
在这里插入图片描述

//config.json5
{ 
    //服务器设置
    "server": {
        "port": 40000, //端口
    }
}

这里暂时只配置一个端口,以后有需要可以增加其他内容
使用json5文件进行配置,由于json文件先天的格式优势,外加可以进行注释,就能让配置文件更加清晰和方便

让vscode认识json5文件

可以下载vscode的扩展 JSON5 syntax,方便我们编写文件
在这里插入图片描述

在程序启动时读取配置

配置文件在项目启动时就应该被读取,因此,我把读取配置文件的代码,写在项目入口start.ts的最前面,另外将config作为一个模块输出,让整个项目都可以使用
为了能够解析带有注释的json5文件,需要安装json5的包
使用 npm install --save json5 进行安装
修改start.ts文件,读取配置

//start.ts

import fs from "fs";
import json5 from "json5";
import path from 'path'

//项目根目录
export const rootDir = __dirname + "/";

//加载配置文件
//读取json5文件内容
let jsonFile = fs.readFileSync(path.join(rootDir, "./config.json5")).toString();
//解析为json文件,并作为模块输出
export let config = json5.parse(jsonFile);

async function main()
{

    console.log(config)
    //ApiServer.GetInstance().Init();
    //await ApiServer.GetInstance().Run();
}

main();

运行一下,看看是否能够正确读取到json文件的内容
在这里插入图片描述
已经成功输出了json内容

修改文件结构,项目更加清晰

为了让项目的文件结构更加清晰,我将ApiServer文件让入一个文件夹中,这样一来,项目的app目录下就只有start和config两个文件,其他都在文件夹中,包括以后新增的文件也根据功能划分到文件中,文件结构更加清晰
注意:一旦文件被移动了位置,所有引用到该文件的地方,都会受到影响,需要进行修改
另外在src中,增加一个public文件夹,放一些静态文件,比如图片,音频文件等,此文件夹中的内容,可以使用express.static(“path”)功能,让用户直接获取到文件
最终的目录结构如下
在这里插入图片描述
start.ts 文件

//start.ts

import fs from "fs";
import json5 from "json5";
import path from 'path'
import { ApiServer } from "./ApiServer/ApiServer";

//项目根目录
export const rootDir = __dirname + "/";

//加载配置文件
//读取json5文件内容
let jsonFile = fs.readFileSync(path.join(rootDir, "./config.json5")).toString();
//解析为json文件,并作为模块输出
export let config = json5.parse(jsonFile);

async function main()
{
    ApiServer.GetInstance().Init();
    await ApiServer.GetInstance().Run();
}

main();

ApiServer.ts 文件

// ApiServer/ApiServer.ts

import express, { Application } from "express"
import { config, rootDir } from "../start";
import path from 'path'



export class ApiServer
{
    //单例
    private static instance: ApiServer = null;
    private constructor()
    {

    }
    public static GetInstance()
    {
        if (ApiServer.instance == null)
        {
            ApiServer.instance = new ApiServer();
        }
        return ApiServer.instance;
    }

    //此类的核心成员
    private app: Application = null;

    //初始化
    Init()
    {
        this.app = express();
        //此处使用config.server.port 这是从配置文件中获取的内容
        //如果配置文件中有port定义,就使用配置文件中的,如果没有,则使用默认50000
        let serverPort = config.server.port || 50000;
        let server = this.app.listen(serverPort, () => { console.info(`Example app listening on port ${serverPort}`) })

        //让express 能够处理 async/await 中抛出的异常
        const layer = require('express/lib/router/layer');
        Object.defineProperty(layer.prototype, 'handle', {
            enumerable: true,
            get()
            {
                return this.__handle;
            },
            set(fn)
            {
                if (fn.length === 4)
                {
                    this.__handle = fn;
                }
                else
                {
                    this.__handle = (req, res, next) =>
                    {
                        Promise.resolve(fn(req, res, next)).catch(next);
                    }
                }
            }

        });
    }

    Run()
    {

        //测试消息
        this.StartTestResponse();

        //public文件夹下的静态资源,可以直接进行访问
        this.app.use(express.static(path.join(rootDir, 'public')));
    }

    //测试消息
    StartTestResponse()
    {
        this.app.all('/api/test', (req, res) =>
        {
            res.writeHead(200, {
                'Content-Type': 'text-plain'
            });
            res.end('Hello World\n' + new Date().toString());
        })
    }

}

此时调试一下程序
服务器已经成功运行,并且端口号为40000
在这里插入图片描述
在这里插入图片描述

增加build文件,让非ts文件也放进build目录

但是此时还有一个问题,当我们使用tsc命令编译项目的时候,发现public文件夹 和 config.json5文件,并没有复制到app文件夹中,tsc命令只是将ts文件编译为js并输出到指定目录,而忽略其他文件
在这里插入图片描述
此时如果我们直接将app文件夹部署到服务器上,必然会出现错误
解决方法是 我们可以另外编写一段代码,编译ts文件的同时,将我们需要的非ts文件,复制到对应的位置
我们在项目的根目录新建一个build.js文件,在里面编写复制其他文件的功能
build.js

const fs = require('fs-extra');
const childProcess = require('child_process');


try
{
    // 删除当前app文件夹中的所有内容
    fs.removeSync('./app/');
    // 复制配置文件到app目录
    fs.copySync('./src/config.json5', './app/config.json5');
    // 复制public文件夹内容到app目录
    fs.copySync('./src/public', './app/public');
    // 执行tsc命令 编译ts文件
    childProcess.exec('tsc');
} catch (err)
{
    console.log(err);
}

此时,我们只要运行 node ./build.js 命令,就可以实现我们需要的功能(先安装fs-extra包)
在这里插入图片描述
文件已经被全部复制到app目录下了

本节内容主要是让项目结构更加合理,并且增加了配置文件,可以更为灵活得进行部署,下节我们将为此框架增加更多的功能

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章