likes
comments
collection
share

构建用户信息 API 接口:Koa2 结合 Sequelize

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

本文将介绍如何使用 Koa2 和 Sequelize 在 Node.js 环境下构建一个用户信息 API 接口。此接口将包括用户信息的增删改查(CRUD)操作。首先,需要确保已安装 Node.js 环境。

准备工作

在开始前,确保安装了以下依赖项:

  • koa:Web 框架。
  • koa-router:用于路由管理。
  • sequelize:ORM 工具。
  • mysql2:MySQL 驱动。

可以通过以下命令安装:

npm install koa koa-router sequelize mysql2

初始化 Sequelize

首先,初始化 Sequelize 以连接 MySQL 数据库:

const Sequelize = require('sequelize');

const sequelize = new Sequelize('database', 'username', 'password', {
  host: 'localhost',
  dialect: 'mysql'
});

定义模型

定义一个 User 模型来代表数据库中的用户:

const User = sequelize.define('user', {
  name: {
    type: Sequelize.STRING,
    allowNull: false
  },
  email: {
    type: Sequelize.STRING,
    allowNull: false,
    unique: true
  }
});

sequelize.sync();

创建 Koa 应用

初始化 Koa 应用,并配置路由:

const Koa = require('koa');
const Router = require('koa-router');

const app = new Koa();
const router = new Router();

定义 API 路由

使用 Koa Router 定义 CRUD 操作的路由:

创建用户

router.post('/users', async (ctx) => {
  const { name, email } = ctx.request.body;
  try {
    const newUser = await User.create({ name, email });
    ctx.status = 201;
    ctx.body = newUser;
  } catch (error) {
    ctx.status = 400;
    ctx.body = { error: error.message };
  }
});

获取用户列表

router.get('/users', async (ctx) => {
  try {
    const users = await User.findAll();
    ctx.body = users;
  } catch (error) {
    ctx.status = 500;
    ctx.body = { error: 'Internal Server Error' };
  }
});

获取特定用户

router.get('/users/:id', async (ctx) => {
  const id = ctx.params.id;
  try {
    const user = await User.findByPk(id);
    if (user) {
      ctx.body = user;
    } else {
      ctx.status = 404;
      ctx.body = { error: 'User not found' };
    }
  } catch (error) {
    ctx.status = 500;
    ctx.body = { error: 'Internal Server Error' };
  }
});

更新用户信息

router.put('/users/:id', async (ctx) => {
  const id = ctx.params.id;
  const { name, email } = ctx.request.body;
  try {
    const [updated] = await User.update({ name, email }, { where: { id } });
    if (updated) {
      const updatedUser = await User.findByPk(id);
      ctx.body = updatedUser;
    } else {
      ctx.status = 404;
      ctx.body = { error: 'User not found' };
    }
  } catch (error) {
    ctx.status = 500;
    ctx.body = { error: 'Internal Server Error' };
  }
});

删除用户

router.delete('/users/:id', async (ctx) => {
  const id = ctx.params.id;
  try {
    const deleted = await User.destroy({ where: { id } });
    if (deleted) {
      ctx.status = 204;
    } else {
      ctx.status = 404;
      ctx.body = { error: 'User not found' };
    }
  } catch (error) {
    ctx.status = 500;
    ctx.body = { error: 'Internal Server Error' };
  }
});

启动应用

注册路由并启动 Koa 应用:

app.use(router.routes()).use(router.allowedMethods());

const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
  console.log(`Server running on port ${PORT}`);
});

总体代码

将上面分散的点结合起来,并且进行了数据库存在性的校验,如果不存在的话就会先创建此数据库。

const Sequelize = require('sequelize');

// 连接到MySQL服务器(而不是特定数据库)
const sequelize = new Sequelize('mysql://root:******@@localhost', {
  logging: false, // 可以关闭 Sequelize 的日志输出
});

sequelize.query("CREATE DATABASE IF NOT EXISTS mydb2;")
  .then(() => {
    console.log('Database checked/created successfully');
    sequelize.close();

    // 重新连接到新创建的数据库
    const db = new Sequelize('mydb2', 'root', '******@', {
      host: 'localhost',
      dialect: 'mysql',
    });

    // 用户模型定义
    const User = db.define('user', {
      name: {
        type: Sequelize.STRING,
        allowNull: false
      },
      email: {
        type: Sequelize.STRING,
        allowNull: false,
        unique: true
      }
    });

    // 同步数据库
    db.sync();

    // Koa 和路由逻辑
    const Koa = require('koa');
    const Router = require('koa-router');
    const {koaBody} = require('koa-body');

    const app = new Koa();
    app.use(koaBody({ multipart: true }));

    const router = new Router();

    // 路由定义
    router.post('/users', async (ctx) => {
      const { name, email } = ctx.request.body;
      const createdAt = +new Date();
      const updatedAt = +new Date();
      try {
        const newUser = await User.create({ name, email, createdAt, updatedAt });
        ctx.status = 201;
        ctx.body = newUser;
      } catch (error) {
        ctx.status = 400;
        ctx.body = { error: error.message };
      }
    });
    router.get('/users', async (ctx) => {
      try {
        const users = await User.findAll();
        console.log('users:', users)
        ctx.body = users;
      } catch (error) {
        ctx.status = 500;
        ctx.body = { error: 'Internal Server Error' };
      }
    });
    router.get('/users/:id', async (ctx) => {
      const id = ctx.params.id;
      try {
        const user = await User.findByPk(id);
        if (user) {
          ctx.body = user;
        } else {
          ctx.status = 404;
          ctx.body = { error: 'User not found' };
        }
      } catch (error) {
        ctx.status = 500;
        ctx.body = { error: 'Internal Server Error' };
      }
    });
    router.put('/users/:id', async (ctx) => {
      const id = ctx.params.id;
      const { name, email } = ctx.request.body;
      try {
        const [updated] = await User.update({ name, email }, { where: { id } });
        if (updated) {
          const updatedUser = await User.findByPk(id);
          ctx.body = updatedUser;
        } else {
          ctx.status = 404;
          ctx.body = { error: 'User not found' };
        }
      } catch (error) {
        ctx.status = 500;
        ctx.body = { error: 'Internal Server Error' };
      }
    });
    router.delete('/users/:id', async (ctx) => {
      const id = ctx.params.id;
      try {
        const deleted = await User.destroy({ where: { id } });
        if (deleted) {
          ctx.status = 204;
        } else {
          ctx.status = 404;
          ctx.body = { error: 'User not found' };
        }
      } catch (error) {
        ctx.status = 500;
        ctx.body = { error: 'Internal Server Error' };
      }
    });

    app.use(router.routes()).use(router.allowedMethods());

    const PORT = process.env.PORT || 6666;
    app.listen(PORT, () => {
      console.log(`Server running on port ${PORT}`);
    });

  })

  .catch((error) => {
    console.error('Unable to create database:', error);
  });

这样的话一个文件基于有些冗长了,使用async/await简化之,接下来就可以放到不同的文件中去了。同时对于凭证最好设置为配置文件而不是明文。


// 设置 Koa 和路由逻辑
const Koa = require('koa');
const Router = require('koa-router');
const { koaBody } = require('koa-body'); const Sequelize = require('sequelize');

// 创建 Sequelize 实例并连接到 MySQL 服务器
const sequelize = new Sequelize('mysql://root:******@localhost', {
  logging: false, // 可以关闭 Sequelize 的日志输出
});

async function initializeDatabase() {
  try {
    // 创建数据库(如果不存在)
    await sequelize.query("CREATE DATABASE IF NOT EXISTS mydb2;");
    console.log('Database checked/created successfully');

    // 关闭初始连接
    await sequelize.close();

    // 重新连接到新创建的数据库
    const db = new Sequelize('mydb2', 'root', '******@', {
      host: 'localhost',
      dialect: 'mysql',
    });

    // 用户模型定义
    const User = db.define('user', {
      name: {
        type: Sequelize.STRING,
        allowNull: false
      },
      email: {
        type: Sequelize.STRING,
        allowNull: false,
        unique: true
      }
    });

    // 同步数据库
    await db.sync();
    return db;
  } catch (error) {
    console.error('Unable to create database:', error);
    throw error; // 抛出错误,阻止进一步执行
  }
}

async function startServer() {
  try {
    const db = await initializeDatabase(); // 确保数据库初始化完成
    const app = new Koa();
    app.use(koaBody({ multipart: true }));

    const router = new Router();
    // User 模型导入
    const User = db.models.user;

    // 路由定义
    // POST /users
    router.post('/users', async (ctx) => {
      const { name, email } = ctx.request.body;
      try {
        const newUser = await User.create({ name, email });
        ctx.status = 201;
        ctx.body = newUser;
      } catch (error) {
        ctx.status = 400;
        ctx.body = { error: error.message };
      }
    });

    // GET /users
    router.get('/users', async (ctx) => {
      try {
        const users = await User.findAll();
        ctx.body = users;
      } catch (error) {
        ctx.status = 500;
        ctx.body = { error: 'Internal Server Error' };
      }
    });

    // 更多路由...

    app.use(router.routes()).use(router.allowedMethods());

    const PORT = process.env.PORT || 6666;
    app.listen(PORT, () => {
      console.log(`Server running on port ${PORT}`);
    });
  } catch (error) {
    console.error('Failed to start the server:', error);
  }
}

startServer();

结论

通过以上步骤,可以使用 Koa2 和 Sequelize 构建一个简单的用户信息 API 接口。这个接口包括了用户的增加、查询、更新和删除操作,覆盖了基本的 CRUD 功能。通过 ORM 工具 Sequelize,可以方便地将 JavaScript 对象和数据库操作相映射,而 Koa 提供了一个轻量级且灵活的方式来处理 HTTP 请求和路由。

记得在实际部署前,根据具体需求对代码进行适当的调整和优化,比如增加错误处理、验证输入数据等。此外,可能还需要考虑安全性问题,如防止 SQL 注入、管理敏感信息等。

综上,Koa 结合 Sequelize 提供了一种高效且易于理解的方式来构建 Node.js 中的数据库驱动应用。


English version

Building a User Information API Interface: Combining Koa2 with Sequelize

This article will demonstrate how to build a user information API interface using Koa2 and Sequelize in a Node.js environment. This interface will include the creation, deletion, updating, and retrieval (CRUD) operations of user information. First, ensure that Node.js is installed in your environment.

Preparation

Before starting, ensure the following dependencies are installed:

  • koa: A web framework.
  • koa-router: For route management.
  • sequelize: An ORM tool.
  • mysql2: A MySQL driver.

These can be installed with the following commands:

npm install koa koa-router sequelize mysql2

Initializing Sequelize

First, initialize Sequelize to connect to the MySQL database:

const Sequelize = require('sequelize');

const sequelize = new Sequelize('database', 'username', 'password', {
  host: 'localhost',
  dialect: 'mysql'
});

Defining the Model

Define a User model to represent users in the database:

const User = sequelize.define('user', {
  name: {
    type: Sequelize.STRING,
    allowNull: false
  },
  email: {
    type: Sequelize.STRING,
    allowNull: false,
    unique: true
  }
});

sequelize.sync();

Creating the Koa Application

Initialize the Koa application and configure the routes:

const Koa = require('koa');
const Router = require('koa-router');

const app = new Koa();
const router = new Router();

Defining API Routes

Use Koa Router to define routes for CRUD operations:

Creating a User

router.post('/users', async (ctx) => {
  const { name, email } = ctx.request.body;
  try {
    const newUser = await User.create({ name, email });
    ctx.status = 201;
    ctx.body = newUser;
  } catch (error) {
    ctx.status = 400;
    ctx.body = { error: error.message };
  }
});

Retrieving a List of Users

router.get('/users', async (ctx) => {
  try {
    const users = await User.findAll();
    ctx.body = users;
  } catch (error) {
    ctx.status = 500;
    ctx.body = { error: 'Internal Server Error' };
  }
});

Retrieving a Specific User

router.get('/users/:id', async (ctx) => {
  const id = ctx.params.id;
  try {
    const user = await User.findByPk(id);
    if (user) {
      ctx.body = user;
    } else {
      ctx.status = 404;
      ctx.body = { error: 'User not found' };
    }
  } catch (error) {
    ctx.status = 500;
    ctx.body = { error: 'Internal Server Error' };
  }
});

Updating User Information

router.put('/users/:id', async (ctx) => {
  const id = ctx.params.id;
  const { name, email } = ctx.request.body;
  try {
    const [updated] = await User.update({ name, email }, { where: { id } });
    if (updated) {
      const updatedUser = await User.findByPk(id);
      ctx.body = updatedUser;
    } else {
      ctx.status = 404;
      ctx.body = { error: 'User not found' };
    }
  } catch (error) {
    ctx.status = 500;
    ctx.body = { error: 'Internal Server Error' };
  }
});

Deleting a User

router.delete('/users/:id', async (ctx) => {
  const id = ctx.params.id;
  try {
    const deleted = await User.destroy({ where: { id } });
    if (deleted) {
      ctx.status = 204;
    } else {
      ctx.status = 404;
      ctx.body = { error: 'User not found' };
    }
  } catch (error) {
    ctx.status = 500;
    ctx.body = { error: 'Internal Server Error' };
  }
});

Launching the Application

Register routes and launch the Koa application:

app.use(router.routes()).use(router.allowedMethods());

const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
  console.log(`Server running on port ${PORT}`);
});

Conclusion

Through the above steps, a simple user information API interface can be constructed using Koa2 and Sequelize. This interface covers basic CRUD functionality, including the addition, querying, updating, and deletion of users. Utilizing the ORM tool Sequelize allows for the mapping of JavaScript objects to database operations conveniently, while Koa provides a lightweight and flexible approach to handling HTTP requests and routing.

Before actual deployment, the code should be appropriately adjusted and optimized according to specific requirements, such as adding error handling, validating input data, etc. Additionally, security considerations, like preventing SQL injection and managing sensitive information, should be taken into account.

In summary, Koa combined with Sequelize offers an efficient and intuitive way to build database-driven applications in Node.js.