likes
comments
collection
share

解决学习与开发Node接口无从下手的难题:一步步构建基于Node和Express的API应用

作者站长头像
站长
· 阅读数 14

如果你对学习和开发Node接口感到困惑,我将帮助你解决这个问题。

简介:

这篇文章是关于学习和开发Node.js接口的新手指南。文章首先介绍了使用Node.js和Express框架进行开发的经典技术。文章描述了一个示例项目的文件结构,包括主文件(app.js)、模型文件夹(models)、控制器文件夹(controllers)和路由文件夹(routes)之间的关系。

这是一份简单明了的Node.js接口开发入门指南,通过介绍项目结构、搭建步骤和示例案例,帮助你快速入门并理解Node.js接口开发的基本原理和技术。

一、开始

结构

这个简单的层级结构图显示了主文件app.js、模型文件夹models、控制器文件夹controllers和路由文件夹routes之间的关系。其中,模型文件夹中包含A.js,控制器文件夹中包含AController.js,而路由文件夹中包含a.js

    .
    ├── controller                      处理中心文件,负责路由及数据库的具体操作
    │   ├── a目录
    │   │   └── a.js     
    │   ├── b目录
    │       └── b.js                
    ├── models                          模型(数据库)文件
    │   ├── a目录
    │   │   └── a1.js    
    │   │   └── a2.js            
    │   ├── b目录
    │       └── b.js                
    ├── mongodb                         mongodb数据库的连接文件
    │   └── db.js
    ├── routes                          路由配置文件
    │   ├── arouter.js                   
    │   ├── brouter.js     
    ├── app.js                          主文件     

这只是一个示例层级结构图,你可以根据项目需求进行调整和扩展。

流程

解决学习与开发Node接口无从下手的难题:一步步构建基于Node和Express的API应用

  1. MongoDB(数据库):MongoDB是一个非关系型数据库,用于存储和管理数据。它以文档的形式存储数据,具有灵活的模式和可扩展性。可以使用MongoDB存储应用程序的数据。
  2. Mongoose(ODM库):Mongoose是一个Node.js的对象数据建模(ODM)库,它提供了一种与MongoDB进行交互的简单方式。Mongoose允许您在Node.js中定义模型和模式,并提供了一些功能,如数据验证、中间件和查询构建器。
  3. 模型(models):在使用Mongoose时,您需要定义模型来表示MongoDB中的集合。模型定义了文档的结构和行为,包括字段、验证规则和数据库操作方法。
  4. 控制器(controllers):控制器是处理请求并生成响应的组件。在Node.js中,控制器负责处理从路由接收到的请求,执行逻辑操作(如数据读取、数据处理等),然后生成相应的响应(res.send)。
  5. 路由(routes):路由定义了URL路径与控制器方法之间的映射关系
  6. API(应用程序接口):API代表应用程序接口,它定义了应用程序向外部提供的服务和功能。通过定义路由和关联的控制器方法,您可以创建API,使其他应用程序或客户端能够使用您的应用程序的功能。

使用MongoDB作为数据库,并使用Mongoose作为与MongoDB进行交互的ODM库。您将定义模型来表示数据结构,并编写控制器来处理请求和生成响应。通过定义路由,您将映射URL路径到相应的控制器方法,从而创建一个API,使其他应用程序能够访问和使用您的应用程序的功能。

二、搭建

搭建一个简单的框架。

首先,通过运行npm init命令初始化项目并生成package.json文件。

然后,通过安装Express和nodemon等包来搭建项目。

  • Express是一个流行的Node.js Web应用程序框架,用于构建Web应用程序和API。
  • nodemon是一个工具,用于在开发过程中监视文件的变化并自动重启应用。

另外,还介绍了使用Mongoose进行MongoDB数据库操作的步骤,包括安装Mongoose和连接数据库。

搭建package.json

初始化项目

    npm init

获得项目运行的package.json

安装express

引入

    cnpm i express

效果

Express 是一个流行的 Node.js Web 应用程序框架,用于构建 Web 应用程序和 API。

安装nodemon

引入

    cnpm i nodemon

效果:

用于在开发过程中监视文件的变化并自动重启应用。

使用:

    "scripts": {
        "dev": "nodemon index.js"
     },

安装mongoose

Mongoose是NodeJS的驱动,不能作为其他语言的驱动。

引入:

    cnpm i mongoose

效果:

连接到 MongoDB、定义模型和模式、执行数据库操作、数据验证和转换、中间件支持等

简单使用:

    // 替换为实际的 MongoDB 连接字符串
    const mongodbConfigUrl = 'mongodb://localhost:27017/mydatabase'; 
    
    mongoose.connect(mongodbConfigUrl, {
      useNewUrlParser: true,
      useUnifiedTopology: true,
      useCreateIndex: true,
       // ....
    }).then(() => {
      console.log('连接成功');
    }).catch((error) => {
      console.error('连接失败:', error);
    });
    

三、案例

文章提供了一个示例案例,包括主文件(app.js)、模型文件(models)、控制器文件(controllers)和路由文件(routes)的代码示例。主文件是整个应用程序的入口点,负责创建Express应用程序实例、配置中间件、连接数据库、定义路由等。模型文件定义了MongoDB中集合的模型和模式。控制器文件是处理请求并生成响应的组件,负责执行逻辑操作和生成响应。路由文件定义了URL路径与控制器方法之间的映射关系。

app.js主文件

整个应用程序的入口点和核心文件。

承载的一些常见功能:创建 Express 应用程序实例、配置中间件、连接数据库、定义路由、错误处理、监听端口等

它是构建和运行应用程序的核心文件

    const express = require("express");
    const router = require("./routes/index.js");
    const db = require("./mongodb/db.js");
    const app = express();
    
    const config = {
      port: 8002,
      url: 'mongodb://localhost:27017/xxx',
    }
    
    // 給router路由送去app参数对象
    router(app);
    
    db(config);
    
    app.listen(config.port, () => {
      console.log(`${config.port}端口:监听打开了`);
    })

models

假设我们有一个user的对象

mongodb的数据存储内容为

    /** 
    * Paste one or more documents here
    */
    {
      "id": 1,
      "user_name": "maotou",
      "password": "123456",
      "city": "上海",
      "create_time": "2023-07-04 13:36",
      "avatar": "16aaf980b9a39581.jpg",
      "__v": 0
    }

在使用Mongoose时,您需要定义模型来表示MongoDB中的集合

    const mongoose = require("mongoose");
    
    const Schema = mongoose.Schema;
    
    const userSchema = new Schema({
      id: Number,
      user_name: String,
      password: String,
      city: String,
      create_time: String,
      avatar: { type: String, default: 'default.jpg' }
    })
    
    userSchema.index({ id: 1 });
    
    const User = mongoose.model('User', userSchema);
    
    module.exports = User;

controller

控制器是处理请求并生成响应的组件。在Node.js中,控制器负责处理从路由接收到的请求,执行逻辑操作(如数据读取、数据处理、调用其他模块等),然后生成相应的响应(res.send)。

简单说就是:

你要拿数据库的数据,做什么用,就写什么代码。

    const UserModel = require("../models/user.js")
    
    class User {
    
      constructor() {
    
      }
    
      async search (req, res, next) {
        const { user_name } = req.query;
        console.log("user_name", user_name);
        try {
          const user = await UserModel.findOne({}, "-_id -__v");
          res.send(user)
        } catch (err) {
          console.log(err);
        }
      }
    }
    
    module.exports = new User();

routes

路由定义了URL路径与控制器方法之间的映射关系

练controller的数据都处理完成了,那么就要考虑传递出去了

    const express = require("express");
    const User = require("../controller/user")
    
    const router = express.Router();
    
    router.get('/search', User.search);
    
    module.exports = router;

定义一个集中导出

    import user from "./user.js";
    
    // 接受 app.js 传递来的 app
    module.exports = (app) => {
      app.use(user);
    
    }

mongodb连接

用于web引用与mongodb的连接

    const mongoose = require("mongoose")
    
    module.exports = (config) => {
    
      mongoose.connect(config.url, {
        useNewUrlParser: true,
        useUnifiedTopology: true
      });
    
      mongoose.Promise = global.Promise;
    
      const db = mongoose.connection;
    
      db.once('open', () => {
        console.log('连接数据库成功');
      })
    
      db.on('error', (error) => {
        console.error('Error in MongoDb connection: ' + error);
        mongoose.disconnect();
      });
    
      db.on('close', () => {
        console.log('数据库断开,重新连接数据库');
        mongoose.connect(config.url, { server: { auto_reconnect: true } });
      });
    };

效果

本地测试接口api:http://localhost:8001/search?user_name=maotou

响应数据:

    user_name maotou
    
    实时响应:
    {
        "avatar": "default.jpg",
        "username": "maotou",
        "password": "IEdv0tn+Q5r4w95+2J9EDg==",
        "user_id": 1
    }

四、问答

1、models中的代码

adminSchema.index({id: 1})

这行代码创建了一个名为 id 的索引,以加快根据 id 字段进行查询的速度。

2、mongodb中的代码

mongoose.Promise = global.Promise

在早期的版本中,Mongoose 使用了自己的 Promise 实现。然而,自 ECMAScript 2015(ES6)起,JavaScript 提供了原生的 Promise 对象作为异步操作的标准机制。为了兼容性和一致性,Mongoose 提供了选项来使用全局的 Promise 实现,即全局环境中可用的 Promise 对象。

通过将 mongoose.Promise 设置为 global.Promise,您将使用全局环境中的 Promise 实现,即全局的 Promise 对象。这样做可以确保在 Mongoose 的异步操作中使用标准的 Promise 语法和功能。

3、希望使用ES6的导入导出

需要安装使用babel来解析

4、req,res,next

在 Express 中,req 是表示请求对象的参数,res 是表示响应对象的参数,next 是表示下一个中间件或路由处理函数的参数。

  • req 对象包含了客户端发送的请求信息,例如请求头、请求参数、请求体等。
  • res 对象用于设置服务器响应的信息,例如响应头、响应状态码、响应数据等。
  • next 参数是一个函数,用于将请求传递给下一个中间件或路由处理函数,类似于链式调用中的"下一个"。

通过 req.headers 可以访问请求头的信息,而通过 res.header 可以设置响应头的信息。通过使用这些信息,可以实现自定义的请求头和响应头配置,以满足特定的需求。

5、post请求使用json文件传递

app.js中开启即可

    app.use(express.json());

使用接收

    async login (req, res, next) {
      const { username, password } = req.body;
      console.log(username, password)
    }

6、解决跨域访问的问题

设置app处理请求的中间件

任何请求就会进来这个中间件,判断来源、请求类型等有无问题。

app.all('*', (req, res, next) => {
  const { origin, Origin, referer, Referer } = req.headers;
  const allowOrigin = origin || Origin || referer || Referer || '*';
	res.header("Access-Control-Allow-Origin", allowOrigin);
	res.header("Access-Control-Allow-Headers", "Content-Type, Authorization, X-Requested-With");
	res.header("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS");
  res.header("Access-Control-Allow-Credentials", true); //可以带cookies
	res.header("X-Powered-By", 'Express');
	if (req.method == 'OPTIONS') {
  	res.sendStatus(200);
	} else {
    next();
	}
});

这段代码的作用是解决跨域访问的问题,允许来自不同域的请求访问你的服务器资源,并设置必要的 CORS 响应头。

设置响应头 Access-Control-Allow-Origin,将允许访问的域名作为值。这样就允许指定的域名发送跨域请求。

设置响应头 X-Powered-By,表示使用 Express 框架处理请求。

如果请求方法是 OPTIONS,表示这是一个预检请求(preflight request),则返回状态码 200 表示请求成功。预检请求是浏览器在发送真正的跨域请求之前发送的一种探测请求,用于检查服务器是否允许实际请求的跨域访问。

如果不是预检请求,调用 next() 方法将请求传递给下一个中间件或路由处理函数


以后有问题再补充🐅