Nodejs博客开发笔记
Nodejs博客开发笔记(持续更新)
接口设计
描述 | 接口 | 方法 | url参数 | 备注 |
---|---|---|---|---|
获取博客列表 | /api/blog/list | get | author 作者,keyword 搜索关键字 | 参数为空的话,则不进行查询过滤 |
获取一篇博客的内容 | /api/blog/detail | get | id | |
新增一篇博客 | /api/blog/new | post | post中有新增的信息 | |
更新一篇博客 | /api/blog/update | post | id | postData中有更新的内容 |
删除一篇博客 | /api/blog/del | post | id | |
登录 | /api/user/login | post | postData中有用户名和密码 |
基本目录结构
|-- bin
|-- www.js --- 服务启动文件
|-- src
|-- controller
|-- blog.js --- 数据文件
|-- model
|-- resModel.js --- 模型文件
|-- router
|-- blog.js --- 存放 blog 目录下的路由
|-- user.js --- 存放 user 目录下的路由
|-- app.js --- 处理路由的文件
|-- package.json --- 包管理文件
博客搭建过程
【梦初】
把服务跑起来
www.js
const http = require("http");
const serverHandle = require("../app");
const port = 3000;
const server = http.createServer(serverHandle);
server.listen(port, () => {
console.log(`服务启动成功 --- ${port}`);
});
serverHandle 是分离出去的回调函数
【梦入】
把 serverHandle 导出去
app.js
const serverHandle = (req, res) => {
// 设置返回格式 JSON
res.setHeader("Content-Type", "application/json");
res.end("Hello Blog!")
};
module.exports = serverHandle;
现在
127.0.0.1:3000
就能正常启动了
【梦时】
我需要写路由,怎么办呢?于是乎我便把 blog 和 user 两个目录下的路由分别写到不同的 js 文件中,然后导出供
app.js
文件进行路由处理
blog.js
const handleBlogRouter = (req, res) => {
const method = req.method; // GET POST
const url = req.url;
// 获取路由地址
const path = url.split("?")[0];
// 获取博客列表
if (method == "GET" && path == "/api/blog/list") {
return {
msg: "这是获取博客列表的接口",
};
}
// 获取博客详情
if (method == "GET" && path == "/api/blog/detail") {
return {
msg: "这是获取博客详情的接口",
};
}
// 新建一篇博客
if (method == "POST" && path == "/api/blog/new") {
return {
msg: "这是新建博客的接口",
};
}
// 更新一篇博客
if (method == "POST" && path == "/api/blog/update") {
return {
msg: "这是更新博客的接口",
};
}
};
module.exports = handleBlogRouter;
user.js
const handleUserRouter = (req, res) => {
const method = req.method; // GET POST
const url = req.url;
// 获取路由地址
const path = url.split("?")[0];
// 登录
if (method == "POST" && path == "/api/user/login") {
return {
msg: "这是用户登录的接口",
};
}
};
module.exports = handleUserRouter;
【梦境】
但是写好路由之后怎么使用它呢?这就需要通过
app.js
来处理路由了,我们通常会在处理路由时,先给它设置 JSON 的返回格式,然后处理时需要以字符串的形式响应给前端,具体如下
app.js
// 导入 blog 路由文件
const handleBlogRouter = require("./src/router/blog");
// 导入 user 路由文件
const handleUserRouter = require("./src/router/user");
const serverHandle = (req, res) => {
// 设置返回格式 JSON
res.setHeader("Content-Type", "application/json");
// 处理 blog 路由
const blogData = handleBlogRouter(req, res);
if (blogData) {
// 把 JSON 类型的数据先转换为字符串,再响应给前端
res.end(JSON.stringify(blogData));
// 最后需要返回
return;
}
// 处理 user 路由
const userData = handleUserRouter(req, res);
if (userData) {
// 把 JSON 类型的数据先转换为字符串,再响应给前端
res.end(JSON.stringify(userData));
// 最后需要返回
return;
}
// 未命中路由,返回 404
res.writeHead(404, { "Content-Type": "text/plain" });
res.write("404 Not Found\n");
res.end();
};
module.exports = serverHandle;
现在我们已经可以通过
http://127.0.0.1:3000/api/blog/list
来正常的访问了
【梦遇】
虽然已经可以正常的访问了,但是我们可以发现,
blog.js
user.js
中是有重复的代码的,这就需要通过路由设计来优化代码了
在 app.js
中处理它们重复的代码
const url = req.url;
req.path = url.split("?")[0];
app.js
// 导入 blog 路由文件
const handleBlogRouter = require("./src/router/blog");
// 导入 user 路由文件
const handleUserRouter = require("./src/router/user");
const serverHandle = (req, res) => {
// 设置返回格式 JSON
res.setHeader("Content-Type", "application/json");
const url = req.url;
req.path = url.split("?")[0];
// 处理 blog 路由
const blogData = handleBlogRouter(req, res);
if (blogData) {
// 把 JSON 类型的数据先转换为字符串,再响应给前端
res.end(JSON.stringify(blogData));
// 最后需要返回
return;
}
// 处理 user 路由
const userData = handleUserRouter(req, res);
if (userData) {
// 把 JSON 类型的数据先转换为字符串,再响应给前端
res.end(JSON.stringify(userData));
// 最后需要返回
return;
}
// 未命中路由,返回 404
res.writeHead(404, { "Content-Type": "text/plain" });
res.write("404 Not Found\n");
res.end();
};
module.exports = serverHandle;
在
blog.js
user.js
文件中就得写成req.path
了
blog.js
const handleBlogRouter = (req, res) => {
// 获取博客列表
if (req.method == "GET" && req.path == "/api/blog/list") {
return {
msg: "这是获取博客列表的接口",
};
}
// 获取博客详情
if (req.method == "GET" && req.path == "/api/blog/detail") {
return {
msg: "这是获取博客详情的接口",
};
}
// 新建一篇博客
if (req.method == "POST" && req.path == "/api/blog/new") {
return {
msg: "这是新建博客的接口",
};
}
// 更新一篇博客
if (req.method == "POST" && req.path == "/api/blog/update") {
return {
msg: "这是更新博客的接口",
};
}
};
module.exports = handleBlogRouter;
user.js
const handleUserRouter = (req, res) => {
// 登录
if (req.method == "POST" && req.path == "/api/user/login") {
return {
msg: "这是用户登录的接口",
};
}
};
module.exports = handleUserRouter;
【梦醒】
现在虽然能返回一些内容了,但是我们需要返回一些动态的数据,数据是由
router/blog.js
文件中的路由返回的,同样的道理,把数据单独做成一个文件
在
controller
目录下新建一个blog.js
文件
controller/blog.js
const getList = (author, keyword) => {
// 先返回假数据(格式是正确的)
return [
{
id: 1,
title: "标题A",
content: "内容A",
createTime: 1601305438637,
author: "张三",
},
{
id: 1,
title: "标题B",
content: "内容B",
createTime: 1601305527630,
author: "李四",
},
];
};
module.exports = {
getList,
};
这时我们就可以在
router/blog.js
文件中去使用这个数据文件中的数据了
// 导入 getList 数据文件
const { getList } = require("../controller/blog");
想要获取到用户提交的数据,需要解析 query,获取到 query 对象
首先引入 querystring,然后再使用 querystring.parse 对url进行解析
// 引入querystring
const querystring = require("querystring");
// 解析 query
req.query = querystring.parse(url.split("?")[1]);
app.js
// 导入 blog 路由文件
const handleBlogRouter = require("./src/router/blog");
// 导入 user 路由文件
const handleUserRouter = require("./src/router/user");
// 引入querystring
const querystring = require("querystring");
const serverHandle = (req, res) => {
// 设置返回格式 JSON
res.setHeader("Content-Type", "application/json");
const url = req.url;
req.path = url.split("?")[0];
// 解析 query
req.query = querystring.parse(url.split("?")[1]);
// 处理 blog 路由
const blogData = handleBlogRouter(req, res);
if (blogData) {
// 把 JSON 类型的数据先转换为字符串,再响应给前端
res.end(JSON.stringify(blogData));
// 最后需要返回
return;
}
// 处理 user 路由
const userData = handleUserRouter(req, res);
if (userData) {
// 把 JSON 类型的数据先转换为字符串,再响应给前端
res.end(JSON.stringify(userData));
// 最后需要返回
return;
}
// 未命中路由,返回 404
res.writeHead(404, { "Content-Type": "text/plain" });
res.write("404 Not Found\n");
res.end();
};
module.exports = serverHandle;
现在我们可以在
router/blog.js
文件中调用 getList 函数,来获取到需要返回的数据了
// 获取 query 中的 anthor ,如果没有则为空字符串
const author = req.query.author || "";
// 获取 query 中的 keyword ,如果没有则为空字符串
const keyword = req.query.keyword || "";
// 调用 getList 函数
const listData = getList(author, keyword);
但是又想到我们不能直接把这个数据直接返回给前端,我们需要返回给前端的只是需要一些 code 啊,message 、data 之类的东西
所以需要创建模型文件,把需要返回的数据用类来封装一下
resModel.js
class BaseModel {
constructor(data, message) {
if (typeof data === "string") {
this.message = data;
data = null;
message = null;
}
if (data) {
this.data = data;
}
if (message) {
this.message = message;
}
}
}
class SuccessModel extends BaseModel {
constructor(data, message) {
super(data, message);
this.errno = 0;
}
}
class ErrorModel extends BaseModel {
constructor(data, message) {
super(data, message);
this.errno = -1;
}
}
module.exports = {
SuccessModel,
ErrorModel,
};
在
router/blog.js
文件中导入数据模型
// 导入数据模型
const { SuccessModel, ErrorModel } = require("../model/resModel");
返回一个 SuccessModel 对象
// 返回一个 SuccessModel 对象
return new SuccessModel(listData);
意思就是说在 SuccessModel
中只传入一个 data 数据,当执行 SuccessModel
类时,会把 listData
的值赋给 this.data
类本身,并且 SuccessModel
自带 error为0
当我在浏览器输入
http://127.0.0.1:3000/api/blog/list
的时候,页面会返回以下内容
{
"data":[
{
"id":1,
"title":"标题A",
"content":"内容A",
"createTime":1601305438637,
"author":"张三"
},
{
"id":1,
"title":"标题B",
"content":"内容B",
"createTime":1601305527630,
"author":"李四"
}
],
"errno":0
}
【梦结】
来总结一下
代码是怎么运行的?
-
第一层 – www.js
- 开启服务
-
第二层 – app.js
- 设置返回格式 JSON
- 解析 query
- 处理 blog 路由
- 处理 user 路由
- 未命中路由,返回 404
-
第三层 – router/blog.js
- 路由文件
-
第四层 – controller/blog.js
- 最关心数据的一层
- 用来存放数据
欲知后事如何,请看下集~
本文地址:https://blog.csdn.net/Cool_breeze_/article/details/108860336
上一篇: PHP面试遇到面试官的swoole协程三连问,快哭了!
下一篇: Codeforces Round #665 (Div. 2) D. Maximum Distributed Tree(dfs)
推荐阅读
-
C/C+学习笔记:10个免费的c/c+集成开发环境(IDE)
-
Android开发笔记之: 数据存储方式详解
-
Android开发笔记之:在ImageView上绘制圆环的实现方法
-
Android开发笔记之:Handler Runnable与Thread的区别详解
-
Android开发笔记之:返回键的复写onBackPressed()介绍
-
Android开发笔记之:Log图文详解(Log.v,Log.d,Log.i,Log.w,Log.e)
-
Android开发笔记之:一分钟学会使用Logcat调试程序的详解
-
Android开发笔记之:如何安全中止一个自定义线程Thread的方法
-
Android开发学习笔记之通过API接口将LaTex数学函数表达式转化为图片形式
-
Android开发笔记之:复写按钮方法