【Nodejs博客项目开发】之原生nodejs实现博客系统(一)

    科技2022-08-13  101

    【Nodejs博客项目开发】之原生nodejs实现博客系统(一)

    >>目录

    【Nodejs博客项目开发】之原生nodejs实现博客系统(一)一、接口设计二、基本目录结构三、`www.js`四、`app.js`五、实现路由`blog.js``user.js` 六、处理路由七、优化代码八、处理动态数据`controller/bolg.js`在`router/blog.js`中使用`controller/bolg.js``app.js``resModel.js` 九、总结

    一、接口设计

    描述接口方法url参数备注获取博客列表/api/blog/listgetauthor 作者,keyword 搜索关键字参数为空的话,则不进行查询过滤获取一篇博客的内容/api/blog/detailgetid新增一篇博客/api/blog/newpostpost中有新增的信息更新一篇博客/api/blog/updatepostidpostData中有更新的内容删除一篇博客/api/blog/delpostid登录/api/user/loginpostpostData中有用户名和密码

    二、基本目录结构

    |-- 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 PORT = 3000 const serverHandle = require('../app') //serverHandle是分离出去的回调函数 const server = http.createServer(serverHandle) server.listen(PORT)

    四、app.js

    主要实现www.js分离出来的回调函数的逻辑

    const serverHandle = (req, res) => { // 设置返回格式 JSON res.setHeader("Content-Type", "application/json"); res.end("Hello Blog!") }; module.exports = serverHandle;

    五、实现路由

    将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: "这是更新博客的接口", }; } //删除一篇博客 if(method == "POST" && path == "/api/blog/del"){ 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 的返回格式,然后处理时需要以字符串的形式响应给前端,具体如下

    // 导入 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中

    在app.js中处理他们的代码:

    const url = req.url; req.path = url.split("?")[0]; // 导入 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代码

    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: "这是更新博客的接口", }; } //删除一篇博客 if(req.method == "POST" && path == "/api/blog/del"){ 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;

    八、处理动态数据

    controller/bolg.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中使用controller/bolg.js

    // 导入 getList 数据文件 const { getList } = require("../controller/blog");

    想要获取到用户提交的数据,需要解析 query,获取到 query 对象

    首先引入 querystring,然后再使用 querystring.parse 对url进行解析

    app.js

    const querystring = require('querystring') const handleBlogRouter = require('./src/router/blog') const handleUserRouter = require('./src/router/user') const serverHandle = (req, res) => { // 设置返回格式 JSON res.setHeader('Content-type', 'application/json') // 获取path const url = req.url //获取url地址 req.path = url.split("?")[0] //路由 // 解析query req.query = querystring.parse(url.split('?')[1]) // 处理blog路由 const blogData = handleBlogRouter(req, res) if (blogData) { res.end( //转换为json格式的字符串 JSON.stringify(blogData) ) return } // 处理user路由 const userData = handleUserRouter(req, res) if (userData) { res.end( JSON.stringify(userData) ) return } // 未命中路由,返回404 res.writeHead(404, { "Content-type": "text/plain" })//纯文本 res.write('404 Not Found') 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);

    resModel.js

    现在的问题是我们不能直接把这个数据返回给前端,需要给前端返回一些code、message、data之类的东西,所以需要创建模型文件来封装

    class BaseModel { /* data:对象类型 message:字符串类型 */ 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对象

    return new SuccessModel(listData)

    九、总结

    这些文件的逻辑是什么?怎么跑起来的?

    第一步 – www.js

    开启服务

    第二步 – app.js

    设置返回格式 JSON解析 query处理 blog 路由处理 user 路由未命中路由,返回 404

    第三步 – router/blog.js

    路由文件

    第四步 – ontroller/blog.js

    最关心数据的一层用来存放数据
    Processed: 0.018, SQL: 8