⭐️学习视频教程来自 B站
✨笔记源码——点击下载
javascript可以运行在浏览器上,因为google浏览器内置V8引擎
NodeJS是基于V8引擎的一个容器,又是C++编写的 所以JS代码也可以运行在NodeJS中
nodejs用url替换querystring
谷歌json格式美化插件:蓝奏云 密码:63mj
const http = require("http");
const url = require("url");const server = http.createServer((req, res) => {const method = req.method;console.log("method", method);let reqUrl = req.url;let query = url.parse(reqUrl, true).query;res.end(JSON.stringify(query));
});server.listen(5000, () => {console.log("server running at prot 5000");
});
const http = require("http");const server = http.createServer((req, res) => {if (req.method === "POST") {let postData = "";// 流streamreq.on("data", (chunk) => {postData += chunk.toString();});req.on("end", () => {console.log("postData", postData);res.end("数据接收完毕");});console.log("post data content type", req.headers["content-type"]);}
});server.listen(5000, () => {console.log("server running at prot 5000");
});
const http = require("http");
const url = require("url");const server = http.createServer((req, res) => {const method = req.method;const reqUrl = req.url;const path = reqUrl.split("?")[0];const query = url.parse(reqUrl, true).query;const responseData = {method,reqUrl,path,query,};res.setHeader("Content-Type", "application/json");if (method === "GET") {res.end(JSON.stringify(responseData));}if (method === "POST") {let postData = "";req.on("data", (chunk) => {postData += chunk.toString();});req.on("end", () => {responseData.postData = postData;res.end(JSON.stringify(responseData));});}
});server.listen(5000, () => {console.log("server running at prot 5000");
});
npm init -y
npm install nodemon -D --registry=https://registry.npm.taobao.org
bin/www.js
// 创建服务器
const http = require("http");
const serverHandler = require("../app");
const PORT = 5000;const server = http.createServer(serverHandler);server.listen(PORT, () => {console.log("server running at prot 5000");
});
app.js
const serverHandler = (req, res) => {res.setHeader("Content-Type", "application/json");const responseData = {name: "nodeJS学习",age: 21,};res.end(JSON.stringify(responseData));
};module.exports = serverHandler;
src/routes/blog.js
// 处理博客相关的路由
const handleBlogRoute = (req, res) => {// 定义处理路由的逻辑const method = req.method;if (method === "GET" && req.path === "/api/blog/list") {return {message: "获取博客列表的接口",};}if (method === "GET" && req.path === "/api/blog/detail") {return {message: "获取博客详情的接口",};}if (method === "POST" && req.path === "/api/blog/new") {return {message: "新建博客接口",};}if (method === "POST" && req.path === "/api/blog/update") {return {message: "更新博客接口",};}if (method === "POST" && req.path === "/api/blog/delete") {return {message: "删除博客接口",};}
};module.exports = handleBlogRoute;
app.js
const handleBlogRoute = require("./src/routes/blog");
const serverHandler = (req, res) => {res.setHeader("Content-Type", "application/json");const url = req.url;req.path = url.split("?")[0];const blogData = handleBlogRoute(req, res);if (blogData) {res.end(JSON.stringify(blogData));return;}res.writeHead(404, { "Content-Type": "text/plain" });res.write("404 Not Found");res.end();
};module.exports = serverHandler;
想让返回的数据格式更加规范
src/model/responseModel.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,
};
src/controllers/blog.js
// 博客相关的方法
const getList = (author, keyword) => {// 从数据库里拿数据// 先返回假数据return [{id: 1,title: "标题1",content: "内容1",author: "zhangsan",createdAt: 1667208603225,},{id: 2,title: "标题2",content: "内容2",author: "zhangsan",createdAt: 1667208603277,},];
};module.exports = {getList,
};
把获取博客详情的接口先补充一下
post请求处理逻辑实际上是异步的
if (req.method === "POST") {let postData = "";// 流streamreq.on("data", (chunk) => {// 处理数据内容, 这里会是一个异步的过程postData += chunk.toString();});req.on("end", () => {console.log("postData", postData);res.end("数据接收完毕");});}
const fs = require("fs");
const path = require("path");// 读取文件内容
// function getFileContent(filename, callback) {
// 数据文件的绝对路径
// const fullFilename = path.resolve(__dirname, "data", filename);// fs.readFile(fullFilename, (err, data) => {
// if (err) {
// console.error(err);
// return;
// }// callback(JSON.parse(data.toString()));
// });
// }// 回调地狱
// getFileContent("a.json", (aData) => {
// console.log("aData", aData);
// getFileContent(aData.next, (bData) => {
// console.log("bData", bData);
// getFileContent(bData.next, (cData) => {
// console.log("cData", cData);
// });
// });
// });function getFileContent(filename) {const promise = new Promise((resolve, reject) => {// 数据文件的绝对路径const fullFilename = path.resolve(__dirname, "data", filename);fs.readFile(fullFilename, (err, data) => {if (err) {reject(err);return;}resolve(JSON.parse(data.toString()));});});return promise;
}getFileContent("a.json").then((aData) => {console.log("aData", aData);return getFileContent(aData.next);}).then((bData) => {console.log("bData", bData);return getFileContent(bData.next);}).then((cData) => {console.log("cData", cData);});
app.js
const handleBlogRoute = require("./src/routes/blog");
const url = require("url");// 处理POST数据
const getPostData = (req) => {const promise = new Promise((resolve, reject) => {if (req.method !== "POST") {resolve({});return;}if (req.headers["content-type"] !== "application/json") {resolve({});return;}let postData = "";req.on("data", (chunk) => {postData += chunk.toString();});req.on("end", () => {if (!postData) {resolve({});return;}resolve(JSON.parse(postData));});});return promise;
};
const serverHandler = (req, res) => {// 设置响应格式res.setHeader("Content-Type", "application/json");// 获取pathconst reqUrl = req.url;req.path = reqUrl.split("?")[0];// 解析queryreq.query = url.parse(reqUrl, true).query;// 处理POST数据getPostData(req).then((postData) => {req.body = postData;// 博客相关的路由const blogData = handleBlogRoute(req, res);if (blogData) {res.end(JSON.stringify(blogData));return;}// 未匹配到任何路由res.writeHead(404, { "Content-Type": "text/plain" });res.write("404 Not Found");res.end();});
};module.exports = serverHandler;
src/controllers/blog.js
// 博客相关的方法
const getList = (author, keyword) => {// 从数据库里拿数据// 先返回假数据return [{id: 1,title: "标题1",content: "内容1",author: "zhangsan",createdAt: 1667208603225,},{id: 2,title: "标题2",content: "内容2",author: "zhangsan",createdAt: 1667208603277,},];
};const getDeatil = (id) => {// 先返回假数据return {id: 1,title: "标题1",content: "内容1",author: "zhangsan",createdAt: 1667208603225,};
};// 新建博客路由
const createNewBlog = (blogData) => {// blogData title contentconsole.log(blogData);return {id: 1,};
};// 更新
const updateBlog = (id, blogData) => {console.log("id", id);console.log("blogData", blogData);return true;
};
// 删除
const deleteBlog = (id) => {console.log("id", id);return true;
};
module.exports = {getList,getDeatil,createNewBlog,updateBlog,deleteBlog,
};
src/routes/blog.js
const {getList,getDeatil,createNewBlog,updateBlog,deleteBlog,
} = require("../controllers/blog");
const { SuccessModel, ErrorModel } = require("../model/responseModel");// 处理博客相关的路由
const handleBlogRoute = (req, res) => {// 定义处理路由的逻辑const method = req.method;const id = req.query.id;const blogData = req.body;// 博客列表路由if (method === "GET" && req.path === "/api/blog/list") {// /api/blog/list?author=zhangsan&keyword=123// new SuccessModel()const author = req.query.author || "";const keyword = req.query.keyword || "";const listData = getList(author, keyword);return new SuccessModel(listData);}// 博客详情路由if (method === "GET" && req.path === "/api/blog/detail") {const detailData = getDeatil(id);return new SuccessModel(detailData);}// 新建博客路由if (method === "POST" && req.path === "/api/blog/new") {const newBlogData = createNewBlog(blogData);return new SuccessModel(newBlogData);}// 更新博客路由if (method === "POST" && req.path === "/api/blog/update") {const updateBlogData = updateBlog(id, blogData);if (updateBlogData) {return new SuccessModel("更新博客成功");} else {return new ErrorModel("更新博客失败...");}}// 删除博客路由if (method === "POST" && req.path === "/api/blog/delete") {const deleteBlogData = deleteBlog(id, blogData);if (deleteBlogData) {return new SuccessModel("删除博客成功");} else {return new ErrorModel("删除博客失败...");}}
};module.exports = handleBlogRoute;
use myblog;-- show tables;-- insert into blogs (title, content, author, createAt) values ('标题2', '内容2', 'zhangsan', 1234567890888)-- select * from blogs;
-- select id, author from blogs;
-- select count(*) as total from blogsselect * from blogs where author like '%zhang%' order by id desc;
update blogs set content="内容1" where id=1
delete from blogs where title="标题2"; -- 不安全
update blogs set status='0' where author='zhangsan' -- 软删除
select * from blogs where status<>0
npm i mysql
const mysql = require("mysql");// 创建连接对象
const connection = mysql.createConnection({host: "localhost",user: "root",password: "IKUN1220",port: 3306,database: "myblog",
});
// 开始连接
connection.connect();
// 执行sql
const sql = `select * from blogs`;
connection.query(sql, (error, result) => {if (error) {console.error(error);return;}console.log("result", result);
});
// 关闭连接
connection.end();
src/db/mysql.js
const mysql = require("mysql");
const { MY_CONFIG } = require("../config/db");// 创建连接对象
const connection = mysql.createConnection(MY_CONFIG);
// 开始连接
connection.connect();
// 执行sql// function execSQL(sql, callback) {
// connection.query(sql, callback);
// }// promise优化 避免出现回调地狱
function execSQL(sql) {const promise = new Promise((resolve, reject) => {connection.query(sql, (err, result) => {if (err) {reject(err);return;}resolve(result);});});return promise;
}module.exports = {execSQL,
};
src/config/db.js
let MY_CONFIG = {};MY_CONFIG = {host: "localhost",user: "root",password: "IKUN1220",port: 3306,database: "myblog",
};module.exports = {MY_CONFIG,
};
// 更新
const updateBlog = (id, blogData = {}) => {const title = blogData.title;const content = blogData.content;const sql = `update blogs set title = '${title}', content = '${content}' where id = ${id}`;return execSQL(sql).then((updateResult) => {console.log("updateResult", updateResult);if (updateResult.affectedRows > 0) {return true;}return false;});
};
-------------------
// 更新博客路由if (method === "POST" && req.path === "/api/blog/update") {const updateBlogDataPrmise = updateBlog(id, blogData);return updateBlogDataPrmise.then((updateBlogData) => {if (updateBlogData) {return new SuccessModel("更新博客成功");} else {return new ErrorModel("更新博客失败...");}});}
// 删除
const deleteBlog = (id) => {const sql = `delete from blogs where id = ${id}`; //实际开发使用update进行软删除return execSQL(sql).then((deleteResult) => {if (deleteResult.affectedRows > 0) {return true;}return false;});
};------
// 删除博客路由if (method === "POST" && req.path === "/api/blog/delete") {const deleteBlogDataPromise = deleteBlog(id);return deleteBlogDataPromise.then((deleteBlogData) => {if (deleteBlogData) {return new SuccessModel("删除博客成功");} else {return new ErrorModel("删除博客失败...");}});}
删除还要对作者进行一个限制,只有对应的作者才能够删除
// 删除
const deleteBlog = (id, author) => {const sql = `delete from blogs where id = ${id} and author = '${author}'`;return execSQL(sql).then((deleteResult) => {if (deleteResult.affectedRows > 0) {return true;}return false;});
};
---------------
// 删除博客路由if (method === "POST" && req.path === "/api/blog/delete") {// 未写登录 暂时写死const author = "zhangsan";const deleteBlogDataPromise = deleteBlog(id, author);return deleteBlogDataPromise.then((deleteBlogData) => {if (deleteBlogData) {return new SuccessModel("删除博客成功");} else {return new ErrorModel("删除博客失败...");}});}