使用Express.js和SQLite3构建简单TODO应用的后端API

使用Express.js和SQLite3构建简单TODO应用的后端API

        • 引言
        • 环境准备
        • 代码解析
          • 1. 导入必要的模块
          • 2. 创建Express应用实例
          • 3. 设置数据库连接
          • 4. 初始化数据库表
          • 5. 配置中间件
          • 6. 定义数据接口
          • 7. 定义路由
            • 7.1 获取所有TODO项
            • 7.2 创建TODO项
            • 7.3 更新TODO项
            • 7.4 删除TODO项
          • 8. 启动服务器
        • 优化建议
        • 总结

引言

在现代Web开发中,TODO列表应用是一个经典的示例,用于展示如何使用前端和后端技术构建一个简单的任务管理工具。本文将详细介绍如何使用Express.js框架和SQLite3数据库来构建一个TODO列表应用,并解释代码的各个部分,帮助读者理解其工作原理。

前端UI请参考,使用React和Material-UI构建TODO应用的前端UI

环境准备

在开始之前,请确保你已经安装了以下工具和库:

  1. Node.js:确保你已经安装了Node.js,可以从Node.js官网下载并安装。
  2. npm:Node.js的包管理工具,随Node.js一起安装。
  3. Express.js:一个轻量级的Node.js Web应用框架,可以通过npm安装。
  4. SQLite3:一个文件数据库,适用于小型应用,同样可以通过npm安装。
  5. TypeScript:可选,但推荐使用,以提升代码的可维护性和类型安全性。

安装所需的依赖:

npm install express cors sqlite3
代码解析

让我们逐步分析代码,理解每个部分的功能。

1. 导入必要的模块
import express from 'express';
import cors from 'cors';
import sqlite3 from 'sqlite3';
import path from 'path';
  • Express:用于创建Web服务器。
  • CORS:处理跨域请求,允许前端应用从不同的域名访问后端API。
  • SQLite3:用于与SQLite数据库进行交互。
  • Path:处理文件路径,确保在不同操作系统下路径正确。
2. 创建Express应用实例
const app = express();

这行代码创建了一个Express应用实例,后续的所有中间件和路由都将注册到这个实例上。

3. 设置数据库连接
const db = new sqlite3.Database(path.join(__dirname, '../database/db.sqlite'));

这里创建了一个SQLite3数据库连接,数据库文件位于../database/db.sqlitepath.join用于确保路径在不同操作系统下都能正确解析。

4. 初始化数据库表
db.serialize(() => {db.run(`CREATE TABLE IF NOT EXISTS todos(id INTEGER PRIMARY KEY AUTOINCREMENT,title TEXT NOT NULL,description TEXT,completed BOOLEAN DEFAULT 0,created_at DATETIME DEFAULT CURRENT_TIMESTAMP)`);
});

这段代码在数据库中创建了一个名为todos的表,如果该表不存在的话。表结构如下:

  • id:整数类型,主键,自增。
  • title:文本类型,非空。
  • description:文本类型,可选。
  • completed:布尔类型,默认值为0(即false)。
  • created_at:日期时间类型,默认值为当前时间戳。
5. 配置中间件
app.use(cors());
app.use(express.json());
  • CORS中间件:允许来自不同域名的请求,防止跨域问题。
  • JSON中间件:解析请求体中的JSON数据,使得req.body可以访问到客户端发送的数据。
6. 定义数据接口
interface Todo {id?: number;title: string;description?: string;completed?: boolean;created_at?: string;
}

这是一个TypeScript接口,定义了TODO项的结构。iddescriptioncompletedcreated_at是可选的,而title是必填的。

7. 定义路由
7.1 获取所有TODO项
app.get('/api/todos', (req: express.Request, res: express.Response) => {const search = (req.query.q as string) || '';db.all<Todo>(`SELECT *FROM todosWHERE title ILIKE ? OR description ILIKE ?ORDER BY created_at DESC`,[`%${search}%`, `%${search}%`],(err, rows) => {if (err) return res.status(500).json({ error: err.message });res.json(rows);});
});
  • 功能:获取所有TODO项,支持通过q参数进行模糊搜索。
  • 查询参数q用于模糊搜索标题或描述。
  • 数据库操作:使用ILIKE进行不区分大小写的匹配,按创建时间降序排列。
  • 错误处理:如果数据库操作失败,返回500状态码和错误信息。
7.2 创建TODO项
app.post('/api/todos', (req: express.Request, res: express.Response) => {const { title, description } = req.body as Todo;if (!title) {return res.status(400).json({ error: 'Title is required' });}db.run('INSERT INTO todos (title, description) VALUES (?, ?)',[title, description],function (err) {if (err) return res.status(500).json({ error: err.message });db.get<Todo>('SELECT * FROM todos WHERE id = ?',[this.lastID],(err, row) => {if (err) return res.status(500).json({ error: err.message });res.status(201).json(row);});});
});
  • 功能:创建一个新的TODO项。
  • 请求体:必须包含titledescription可选。
  • 数据库操作:插入新记录,然后查询新插入的记录并返回。
  • 错误处理:检查title是否为空,返回400错误;数据库操作失败返回500错误。
7.3 更新TODO项
app.put('/api/todos/:id', (req: express.Request, res: express.Response) => {const { id } = req.params;const { title, description, completed } = req.body as Todo;db.run(`UPDATE todosSET title       = ?,description = ?,completed   = ?WHERE id = ?`,[title, description, completed ? 1 : 0, id],function (err) {if (err) return res.status(500).json({ error: err.message });if (this.changes === 0) {return res.status(404).json({ error: 'Todo not found' });}db.get<Todo>('SELECT * FROM todos WHERE id = ?',[id],(err, row) => {if (err) return res.status(500).json({ error: err.message });res.json(row);});});
});
  • 功能:更新指定ID的TODO项。
  • 请求体:包含titledescriptioncompleted
  • 数据库操作:更新记录,completed字段转换为10
  • 错误处理:如果没有记录被更新,返回404错误;数据库操作失败返回500错误。
7.4 删除TODO项
app.delete('/api/todos/:id', (req: express.Request, res: express.Response) => {const { id } = req.params;db.run('DELETE FROM todos WHERE id = ?',[id],function (err) {if (err) return res.status(500).json({ error: err.message });if (this.changes === 0) {return res.status(404).json({ error: 'Todo not found' });}res.status(204).send();});
});
  • 功能:删除指定ID的TODO项。
  • 数据库操作:删除记录。
  • 错误处理:如果没有记录被删除,返回404错误;数据库操作失败返回500错误。
8. 启动服务器
const PORT = 3002;
app.listen(PORT, () => {console.log(`Server running on port ${PORT}`);
});

服务器监听在3002端口,启动后在控制台输出提示信息。

优化建议

尽管这段代码已经可以正常工作,但为了提升应用的性能和可维护性,可以考虑以下优化:

  1. 使用连接池: SQLite3支持连接池,可以提高数据库操作的效率,特别是在高并发情况下。
  2. 添加输入验证:使用中间件如express-validator对请求体进行验证,确保数据的合法性和完整性。
  3. 添加分页功能:在获取TODO列表时,添加分页功能,限制每页返回的记录数,提高性能。
  4. 使用ORM工具:如SequelizeKnex.js,简化数据库操作,提高代码的可读性和可维护性。
  5. 添加日志记录:使用winstonmorgan记录请求和错误信息,便于调试和监控。
  6. 添加速率限制:防止恶意攻击,限制同一IP地址的请求频率。
总结

通过本文,我们详细解析了一个使用Express.js和SQLite3构建的TODO列表应用。从数据库的初始化、路由的定义到错误处理,每个部分都进行了详细的解释。希望这篇文章能够帮助读者理解如何使用这些技术构建一个简单的Web应用,并为进一步的学习和开发打下基础。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/12601.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python爬虫:1药城店铺爬虫(完整代码)

⭐️⭐️⭐️⭐️⭐️欢迎来到我的博客⭐️⭐️⭐️⭐️⭐️ &#x1f434;作者&#xff1a;秋无之地 &#x1f434;简介&#xff1a;CSDN爬虫、后端、大数据领域创作者。目前从事python爬虫、后端和大数据等相关工作&#xff0c;主要擅长领域有&#xff1a;爬虫、后端、大数据…

【蓝桥杯】日志统计

日志统计&#xff08;编程题&#xff09;https://dashoj.com/d/lqbproblem/p/53https://dashoj.com/d/lqbproblem/p/53https://dashoj.com/d/lqbproblem/p/53 题目 日志统计(编程题) 讲解 这个讲解感觉比较通俗易懂。 蓝桥杯2018年省赛B组08&#xff08;c/c&#xff09;日…

一文讲解Spring中应用的设计模式

我们都知道Spring 框架中用了蛮多设计模式的&#xff1a; 工厂模式呢&#xff0c;就是用来创建对象的&#xff0c;把对象的创建和使用分开&#xff0c;这样代码更灵活。代理模式呢&#xff0c;是用一个代理对象来控制对真实对象的访问&#xff0c;可以在访问前后做一些处理。单…

AI 算力瓶颈,硬件、算法、共享能否破局?

随着AI技术的蓬勃发展&#xff0c;它已经实现了从实验室走向千行百业&#xff0c;然而在它想要继续深入地探索各行各业&#xff0c;解锁更多应用场景时&#xff0c;算力却成为了它面前的一道关卡。 这道关卡由无数需要处理的数据和计算任务堆积而成&#xff0c;想要实现AI技术…

华为小米vivo向上,苹果荣耀OPPO向下

日前&#xff0c;Counterpoint发布的手机销量月度报告显示&#xff0c;中国智能手机销量在2024年第四季度同比下降3.2%&#xff0c;成为2024年唯一出现同比下滑的季度。而对于各大智能手机品牌来说&#xff0c;他们的市场份额和格局也在悄然发生变化。 华为逆势向上 在2024年第…

github下载失败网页打开失败 若你已经知道github地址如何cmd下载

直接打开命令行&#xff1a; winr cmd 输入&#xff1a;git clone 地址 eg&#xff1a;git clone https://github.com/akospasztor/stm32f103-dfu-bootloader

K8S学习笔记-------1.安装部署K8S集群环境

1.修改为root权限 #sudo su 2.修改主机名 #hostnamectl set-hostname k8s-master01 3.查看网络地址 sudo nano /etc/netplan/01-netcfg.yaml4.使网络配置修改生效 sudo netplan apply5.修改UUID&#xff08;某些虚拟机系统&#xff0c;需要设置才能生成UUID&#xff09;#…

二维数组 C++ 蓝桥杯

1.稀疏矩阵 #include<iostream> using namespace std;const int N 1e4 10; int a[N][N];int main() {int n, m; cin >> n >> m;for (int i 1; i < n; i) {for (int j 1; j < m; j) {cin >> a[i][j];}}for (int j m; j > 1; j--) {for (i…

macos系统jmap执行异常

jdk8环境下执行jmap异常 网上说mac环境jdk8不支持Jmap&#xff0c;需要替换成更高的jdk版本&#xff0c;更改zshrc文件的jdk版本 环境变量生效 执行jmap不再报错

Linux 传输层协议 UDP 和 TCP

UDP 协议 UDP 协议端格式 16 位 UDP 长度, 表示整个数据报(UDP 首部UDP 数据)的最大长度如果校验和出错, 就会直接丢弃 UDP 的特点 UDP 传输的过程类似于寄信 . 无连接: 知道对端的 IP 和端口号就直接进行传输, 不需要建立连接不可靠: 没有确认机制, 没有重传机制; 如果因…

HTB:UnderPass[WriteUP]

目录 连接至HTB服务器并启动靶机 信息收集 使用rustscan对靶机TCP端口进行开放扫描 使用nmap对靶机TCP开放端口进行脚本、服务扫描 使用nmap对靶机TCP开放端口进行漏洞、系统扫描 使用nmap对靶机常用UDP端口进行开放扫描 使用nmap对靶机UDP开放端口进行脚本、服务扫描 …

ARM内核:嵌入式时代的核心引擎

引言 在当今智能设备无处不在的时代&#xff0c;ARM&#xff08;Advanced RISC Machines&#xff09;处理器凭借其高性能、低功耗的特性&#xff0c;成为智能手机、物联网设备、汽车电子等领域的核心引擎。作为精简指令集&#xff08;RISC&#xff09;的典范&#xff0c;ARM核…

基于RK3588/RK3576+MCU STM32+AI的储能电站电池簇管理系统设计与实现

伴随近年来新型储能技术的高质量规模化发展&#xff0c;储能电站作为新能源领域的重要载体&#xff0c; 旨在配合逐步迈进智能电网时代&#xff0c;满足电力系统能源结构与分布的创新升级&#xff0c;给予相应规模 电池管理系统的设计与实现以新的挑战。同时&#xff0c;电子系…

【HarmonyOS之旅】基于ArkTS开发(二) -> UI开发三

目录 1 -> 绘制图形 1.1 -> 绘制基本几何图形 1.2 -> 绘制自定义几何图形 2 -> 添加动画效果 2.1 -> animateTo实现闪屏动画 2.2 -> 页面转场动画 3 -> 常见组件说明 1 -> 绘制图形 绘制能力主要是通过框架提供的绘制组件来支撑&#xff0c;支…

【算法】经典博弈论问题——威佐夫博弈 python

目录 威佐夫博弈(Wythoff Game)【模板】 威佐夫博弈(Wythoff Game) 有两堆石子&#xff0c;数量任意&#xff0c;可以不同&#xff0c;游戏开始由两个人轮流取石子 游戏规定&#xff0c;每次有两种不同的取法 1)在任意的一堆中取走任意多的石子 2)可以在两堆中同时取走相同数量…

通过Redisson构建延时队列并实现注解式消费

目录 一、序言二、延迟队列实现1、Redisson延时消息监听注解和消息体2、Redisson延时消息发布器3、Redisson延时消息监听处理器 三、测试用例四、结语 一、序言 两个月前接了一个4万的私活&#xff0c;做一个线上商城小程序&#xff0c;在交易过程中不可避免的一个问题就是用户…

第一个Qt开发实例(一个Push Button按钮和两个Label)【包括如何在QtCreator中创建新工程、代码详解、编译、环境变量配置、测试程序运行等】

目录 Qt开发环境QtCreator的安装、配置在QtCreator中创建新工程在Forms→mainwindow.ui中拖曳出我们要的图形按钮查看拖曳出按钮后的代码为pushButton这个图形添加回调函数编译工程关闭开发板上QT的GUI(选做)禁止LCD黑屏(选做)设置Qt运行的环境变量运行Qt程序如何让程序在系统启…

Spring Security(maven项目) 3.0.3.0版本

前言&#xff1a; 通过实践而发现真理&#xff0c;又通过实践而证实真理和发展真理。从感性认识而能动地发展到理性认识&#xff0c;又从理性认识而能动地指导革命实践&#xff0c;改造主观世界和客观世界。实践、认识、再实践、再认识&#xff0c;这种形式&#xff0c;循环往…

携程Java开发面试题及参考答案 (200道-上)

说说四层模型、七层模型。 七层模型(OSI 参考模型) 七层模型,即 OSI(Open System Interconnection)参考模型,是一种概念模型,用于描述网络通信的架构。它将计算机网络从下到上分为七层,各层的功能和作用如下: 物理层:物理层是计算机网络的最底层,主要负责传输比特流…

【Rust自学】16.4. 通过Send和Sync trait来扩展并发

喜欢的话别忘了点赞、收藏加关注哦&#xff0c;对接下来的教程有兴趣的可以关注专栏。谢谢喵&#xff01;(&#xff65;ω&#xff65;) 16.4.1. Send和Sync trait Rust语言本身的并发特性较少&#xff0c;目前所提及的并发特性都来自于标准库&#xff0c;而不是语言本身。其…