文章大纲
加载中...

博客项目1——基于NodeJs的后端开发

6/6/2025 45 阅读
博客项目1——基于NodeJs的后端开发

Express简介

Express 是一个基于 Node.js 的极简、灵活的 Web 应用开发框架。它可以帮助你非常方便地搭建 Web 服务器和 API 服务。

主要特点如下:

  • 极简易用:用很少的代码就能搭建一个 Web 服务。
  • 中间件机制:通过中间件(middleware)可以灵活处理请求和响应,比如处理静态文件、解析请求体、处理跨域等。
  • 路由系统:可以很方便地定义不同的 URL 路径和对应的处理函数,支持 GET、POST、PUT、DELETE 等多种 HTTP 方法。
  • 生态丰富:有大量第三方中间件和插件,能快速扩展功能(如认证、日志、文件上传等)。
  • 适合 RESTful API:非常适合用来开发 RESTful 风格的接口。

一句话总结:
Express 是 Node.js 领域最流行的 Web 框架之一,适合快速开发各种 Web 应用和后端 API 服务。

与jakarta对比

对比项 Express(Node.js) Jakarta EE(Java)
开发语言 JavaScript/Node.js Java
生态 偏前端、全栈,npm包丰富 企业级后端主流,JCP标准,生态成熟
项目结构 灵活、自由,适合小中型项目 规范分层(Servlet、EJB、JPA等),适合大型项目
启动方式 直接 node app.js 启动 需部署到Servlet容器(如Tomcat、WildFly)
路由/控制器 app.get/postrouter.get/post Servlet类+注解(如@WebServlet、@Path)
数据库操作 直接写SQL或用ORM(如sequelize) JPA/EJB/JDBC,ORM强大,类型安全
中间件/拦截 app.use 中间件机制 Filter/Listener/Interceptor拦截器
配置部署 配置简单,轻量,适合云函数/轻量服务 配置项多,需XML/注解,适合传统服务器/容器化
性能场景 轻量高并发,I/O密集型,API、实时应用 业务复杂、强类型、安全性高的企业级应用
适合人群 前端转全栈、初学者、快速开发 后端开发、企业级团队、规范性要求高

总结: Express 更灵活、轻量、上手快,适合快速开发和小型项目;Jakarta EE 更规范、功能强大,适合大型、企业级项目。

创建Blog项目:

  1. 在某个磁盘分区创建一个Myblog的目录,进入该目录,然后用vscode打开它

  1. 在vscode的终端中依次运行下面的命令,创建项目目录并安装 Express:
mkdir backend
cd backend
npm install express --save
npm install bcryptjs --save
npm install mysql2 --save
  1. backend目录中创建一个app.js 文件,在其中插入下面的代码。
const express = require('express'); // 引入express
const app = express(); // 创建应用
//监听3000端口
app.listen(3000, () => {
  console.log('Server started on port 3000');
  console.log('http://localhost:3000');
})
//设置路由
app.get('/', (req, res) => {
  res.send('Hello World!');
})
  1. 在终端中运行下面的命令,启动应用:
node app.js
  1. 访问应用:
    打开浏览器,访问http://localhost:3000,可以看到"Hello World!"

创建数据库

我们的目标是做一个博客系统,可以实现登录、注册、发布文章、查看文章、修改文章、删除文章等功能。第一步我们首先要设计数据库,在数据库软件里创建一个数据库,名字为blog,然后创建一个用于保存文章的表,名字为articles,里面有id、uid、title、content、created_at、updated_at等字段,还要创建一个用户表,里面有id、username、password等字段。数据结构如下图所示:

可以直接使用sql语句创建数据库和表,具体做法如下:

打开Navicat软件,点击localhost建立连接,点击新建查询,粘贴下面的代码,最后点击运行

CREATE DATABASE IF NOT EXISTS blog;
USE blog;

CREATE TABLE users (
  id INT AUTO_INCREMENT PRIMARY KEY,
  username VARCHAR(255) NOT NULL,
  password VARCHAR(255) NOT NULL
) ENGINE=InnoDB;

CREATE TABLE articles (
  id INT AUTO_INCREMENT PRIMARY KEY,
  uid INT NOT NULL,
  title VARCHAR(255) NOT NULL,
  content TEXT NOT NULL,
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  FOREIGN KEY (uid) REFERENCES users(id)
) ENGINE=InnoDB;

INSERT INTO users (username, password) VALUES ('admin', '123456');
INSERT INTO articles (uid, title, content) VALUES (1, 'Hello World!', 'This is my first article.');

编写连接数据库的代码

在backend文件中创建一个db.js文件,插入如下所示的代码(注意!密码password要换成你自己数据库的密码哦!!!)

这段代码的作用是引入mysql2模块,创建一个数据库连接,并导出这个连接,完整代码如下:

const mysql = require('mysql2'); // 引入mysql2模块
const db = mysql.createConnection({ // 创建数据库连接
  host: 'localhost', // 数据库地址
  user: 'root', // 数据库用户名
  password: '123456789', // 数据库密码
  database: 'blog' // 数据库名称
});

db.connect(err => { // 连接数据库
  if (err) { // 如果连接失败  
    console.error('数据库连接失败:', err); // 打印错误信息
  } else { // 如果连接成功  
    console.log('数据库连接成功'); // 打印连接成功信息
  }
});

module.exports = db; // 导出数据库连接

编写用户注册和登录的接口

backend文件中创建routes文件夹,然后在routes文件夹中创建users.js文件,编写用户登录和注册接口:

const express = require('express');
const router = express.Router();
const db = require('../db');
const bcrypt = require('bcryptjs');

// 注册
router.post('/register', (req, res) => {
  const { username, password } = req.body;
  // 检查用户名是否已存在
  db.query('SELECT * FROM users WHERE username=?', [username], (err, results) => {
    if (results.length > 0) {
      return res.status(400).json({ message: '用户名已存在' });
    }
    // 密码加密
    const hash = bcrypt.hashSync(password, 10);
    db.query('INSERT INTO users (username, password) VALUES (?, ?)', [username, hash], (err) => {
      if (err) return res.status(500).json({ message: '注册失败' });
      res.json({ message: '注册成功' });
    });
  });
});

// 登录
router.post('/login', (req, res) => {
  const { username, password } = req.body;
  db.query('SELECT * FROM users WHERE username=?', [username], (err, results) => {
    if (results.length === 0) {
      return res.status(400).json({ message: '用户不存在' });
    }
    const user = results[0];
    if (!bcrypt.compareSync(password, user.password)) {
      return res.status(400).json({ message: '密码错误' });
    }
    // 登录成功,可以生成 token 或 session
    res.json({ message: '登录成功', userId: user.id });
  });
});

module.exports = router;

编写文章相关接口

routes 文件夹下新建 articles.js,实现文章的增删改查(CRUD)接口:

  • 发布文章(POST /api/article/add)
  • 获取文章列表(GET /api/article/list)
  • 获取单篇文章详情(GET /api/article/:id)
  • 修改文章(POST /api/article/update/:id)
  • 删除文章(POST /api/article/delete/:id)

// routes/articles.js
const express = require('express');
const router = express.Router();
const db = require('../db');

// 发布文章
router.post('/add', (req, res) => {
  const { uid, title, content } = req.body;
  db.query(
    'INSERT INTO articles (uid, title, content) VALUES (?, ?, ?)',
    [uid, title, content],
    (err, result) => {
      if (err) return res.status(500).json({ message: '发布失败' });
      res.json({ message: '发布成功', articleId: result.insertId });
    }
  );
});

// 文章列表
router.get('/list', (req, res) => {
  db.query('SELECT * FROM articles', (err, results) => {
    if (err) return res.status(500).json({ message: '获取失败' });
    res.json(results);
  });
});

// 文章详情
router.get('/:id', (req, res) => {
  db.query('SELECT * FROM articles WHERE id=?', [req.params.id], (err, results) => {
    if (err) return res.status(500).json({ message: '获取失败' });
    if (results.length === 0) return res.status(404).json({ message: '未找到' });
    res.json(results[0]);
  });
});

// 修改文章
router.post('/update/:id', (req, res) => {
  const { title, content } = req.body;
  db.query(
    'UPDATE articles SET title=?, content=? WHERE id=?',
    [title, content, req.params.id],
    (err) => {
      if (err) return res.status(500).json({ message: '修改失败' });
      res.json({ message: '修改成功' });
    }
  );
});

// 删除文章
router.post('/delete/:id', (req, res) => {
  db.query('DELETE FROM articles WHERE id=?', [req.params.id], (err) => {
    if (err) return res.status(500).json({ message: '删除失败' });
    res.json({ message: '删除成功' });
  });
});

module.exports = router;

修改app.js

app.js改成下面这样

const express = require('express'); // 引入express
const app = express(); // 创建应用
const userRouter = require('./routes/users'); // 引入用户路由
const articleRouter = require('./routes/articles');  // 引入文章路由


app.use(express.json()); // 解析json请求体
app.use(express.urlencoded({ extended: true })); // 解析urlencoded请求体
app.use('/api/user', userRouter); // 使用用户路由
app.use('/api/article', articleRouter); // 使用文章路由


//监听3000端口
app.listen(3000, () => {
  console.log('Server started on port 3000'); // 打印服务器启动信息
  console.log('http://localhost:3000'); // 打印服务器地址
})
//设置根路由,返回Hello World!
app.get('/', (req, res) => {
  res.send('Hello World!'); // 发送Hello World!响应
})

在终端中按键盘Ctrl+C停止服务器,然后运行node app.js重启服务器,然后按住Ctrl健用鼠标左键单击那个网址。

测试接口

  1. 首先打开微软的Edge浏览器,按下图所示的方式安装前端助手扩展

  1. 测试注册用户

按下图所示的步骤打开建议Postman

如下图所示,首先点一下【Post示例】,然后再点【参数专JSON格式】

接下来再接口地址输入 http://localhost:3000/api/user/register

再请求参数里面输入

{
  "username": "youngshu",
  "password": "123456"
}

点击【发送请求】按钮,可以看到服务器响应了注册成功信息,说明注册接口正常工作

打开数据库的用户表,可以看到表格中确实添加了我们刚发送过去的用户名,密码进行了加密。

  1. 测试用户登录

把接口地址换成http://localhost:3000/api/user/login

请求参加就用我们刚才注册的用户名和密码

{
  "username": "youngshu",
  "password": "123456"
}

然后点击【发送请求】,可看到服务器响应了登录成功的信息,说明登录接口也可以正常工作

  1. 测试添加文章

把接口地址换成http://localhost:3000/api/article/add

请求参数为:(注意!uid为用户id,你的不一定是3,要去数据库的user表格里面看你的用户名对应的id是多少)

{
  "uid": 3,
  "title": "我的第一篇文章",
  "content": "这是内容"
}

发送请求后,可以看到服务器响应信息,如果是如下图所示,则说明增加文章成功

打开数据库的文章表格,可以看到刚才测试的数据确实增加到了数据库中,说明增加文章的功能OK。

接下来,请利用前端助手,多添加几篇文章

  1. 测试获取文章列表

首先把请求方式改成GET

然后把接口地址改成(注意,你的id不一定是3哦):http://localhost:3000/api/article/list?id=3

发送请求后,可以看到服务器把数据库中用户id为3的用户的所有文章返回过来了。

  1. 测试获取单篇文章

把接口地址改成http://localhost:3000/api/article/2,然后发送请求,可以查询第2篇文章。

最后的数字改成3,可以查询第3篇文章,以此类推

  1. 测试更新文章

把请求方式改成POST

接口地址改成 http://localhost:3000/api/article/update/2(2是你要修改的文章id)

请求参数为:

{
  "title": "新标题",
  "content": "新内容"
}

点击【发送请求】按钮,可以看到服务器响应了"修改成功"的信息,说明更新文章接口正常工作。

你可以去数据库的文章表格里查看,发现对应id的文章内容已经被修改。

  1. 测试删除文章

把请求方式改成POST

接口地址改成 http://localhost:3000/api/article/delete/2(2是你要删除的文章id)

无需请求参数,直接点击【发送请求】按钮。

可以看到服务器响应了"删除成功"的信息,说明删除文章接口正常工作。

你可以去数据库的文章表格里查看,发现对应id的文章已经被删除。

作业

请自学一下GET请求和POST请求的区别

然后做一个说明文档说明为什么文章相关的接口有的使用GET请求,有的使用POST请求

  • 发布文章(POST /api/article/add)
  • 获取文章列表(GET /api/article/list)
  • 获取单篇文章详情(GET /api/article/:id)
  • 修改文章(POST /api/article/update/:id)
  • 删除文章(POST /api/article/delete/:id)

评论 (0)

暂无评论,来发表第一条评论吧!