【Nodejs】基于node http模块的博客demo代码实现

目录

package.json

www.js

db.js

app.js

routes/blog.js

controllers/blog.js

mysql.js

responseModel.js


无开发,不安全。

这个demo项目实现了用Promise异步处理http的GET和POST请求,通过mysql的api实现了博客增删改查功能,但因没有写登录身份认证功能,所以限制具体博客增删时的权限就用了假数据。

下面直接贴出源码:

package.json

{
  "name": "nodetest",
  "version": "1.0.0",
  "description": "",
  "main": "bin/www.js",
  "scripts": {
    "dev": "nodemon bin/www.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "nodemon": "^3.0.2"
  },
  "dependencies": {
    "mysql": "^2.18.1"
  }
}

这里用的是nodemon监视文件系统的更改,并自动重启 Node.js 应用程序

运行:npm run dev

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 port 5000...');
})

db.js

let MYSQL_CONFIG={};

MYSQL_CONFIG={
    host:'localhost',
    user:'root',
    password:'root',
    port:3306,
    database:'nodeblog'
}

module.exports={
    MYSQL_CONFIG
}

app.js

//业务逻辑代码
const querystring = require('querystring');
const handleBlogRoute=require('./src/routes/blog');

//处理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');

    //获取path
    const url=req.url;
    req.path=url.split('?')[0];

    //解析query
    req.query=querystring.parse(url.split('?')[1]);
    //处理POST数据
    getPostData(req).then((postData)=>{
        req.body=postData;
        //博客相关的路由
        const blogDataPromise=handleBlogRoute(req,res);
        if (blogDataPromise){
            blogDataPromise.then((blogData)=>{
                res.end(
                    JSON.stringify(blogData)
                    );
            });
            return;
        }
        //未匹配到任何路由
        res.writeHead(404,{'Content-Type':'text/plain'});
        res.write('404 Not Found');
        res.end();
    });
    
}

module.exports=serverHandler;

routes/blog.js

//处理博客相关的路由
const {SuccessModel, ErrorModel}=require('../model/responseModel');
const {getList,getDetail,createNewBlog,updateBlog,deleteBlog} = require('../controllers/blog');


const handleBlogRoute=(req,res)=>
{
    const method=req.method;
    const blogData=req.body;
    const id=req.query.id;
    if(method==='GET' && req.path==='/api/blog/list'){
        
        const author=req.query.author||'';
        const keyword=req.query.keyword||'';
        const listDataPromise=getList(author,keyword);
        return listDataPromise.then((listData)=>{
            return new SuccessModel(listData);
        });
    }

    if(method==='GET' && req.path==='/api/blog/detail'){
        const detailDataPromise=getDetail(id);
        return detailDataPromise.then(detailData=>{
            return new SuccessModel(detailData);
        })
    }

    if(method==='POST' && req.path==='/api/blog/new'){
        const author='Hacker';
        req.body.author=author;
        const newBlogDataPromise=createNewBlog(blogData);
        
        return newBlogDataPromise.then(newBlogData=>{
            return new SuccessModel(newBlogData);
        });
    }

    if(method==='POST' && req.path==='/api/blog/update'){
        const updatedBlogDataPromise=updateBlog(id,blogData);

        return updatedBlogDataPromise.then((updatedBlogData)=>{
            if (updatedBlogData){
                return new SuccessModel('更新博客成功!');
            }else{
                return new ErrorModel('更新博客失败...');
            }
        });
    }

    if(method==='POST' && req.path==='/api/blog/delete'){
        const author='Hacker';
        const deleteBlogDataPromise=deleteBlog(id,author);
       
        return deleteBlogDataPromise.then((deleteBlogData)=>{
            if (deleteBlogData){
                return  new SuccessModel('删除博客成功!');
            }else{
                return new ErrorModel('删除博客失败...');
            }
        });
    }

}

module.exports=handleBlogRoute;

controllers/blog.js

const {execSQL}=require('../db/mysql');

//获取博客列表
const getList=(author,keyword)=>{
    let sql=`select * from blogs where`;
    if(author){
        sql+=` author='${author}' `;
    }

    if(keyword){
        sql+=`and title like '%${keyword}%'`;
    }
    return execSQL(sql);
}

//获取博客详情
const getDetail=(id)=>{
    const sql=`select * from blogs where id='${id}'`;

    return execSQL(sql).then(rows=>{
        console.log('rows',rows);
        return rows[0];
    });
}

//创建新的博客
const createNewBlog=(blogData={})=>{
    const title=blogData.title;
    const content=blogData.content;
    const author=blogData.author;
    const createdAt=Date.now();

    const sql=`insert into blogs (title,content,author,createdAt) values ('${title}','${content}','${author}',${createdAt})`;

    return execSQL(sql).then(insertedResult=>{
        console.log('insertedResult',insertedResult);
        return {
            id:insertedResult.insertId
        }
    });
    
}

const updateBlog=(id,blogData={})=>{
   const title=blogData.title;
   const content=blogData.title;

   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;
   })
}

const deleteBlog=(id,author)=>{
    const sql=`delete from blogs where id=${id} and author='${author}'`;
    
    return execSQL(sql).then(deleteResult=>{
        console.log('deleteResult',deleteResult);
        if(deleteResult.affectedRows>0){
            return true;
        }
        return false;
    })
}
module.exports={
    getList,
    getDetail,
    createNewBlog,
    updateBlog,
    deleteBlog
}

mysql.js

const mysql=require('mysql');
const { MYSQL_CONFIG } = require('../config/db');

const connection=mysql.createConnection( MYSQL_CONFIG);

//开始连接
connection.connect();

//执行sql语句
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
}

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
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

elementui loading自定义图标和字体样式

需求:页面是用了很多个loading,需要其中有一个字体大些(具体到图标也一样的方法,换下类名就行) 遇见的问题:改不好的话会影响其他的loading样式(一起改变了) 效果展示 改之前 改之…

公司图纸该怎么管理? 公司图纸管理的方案

公司图纸管理是一个重要的环节,涉及到图纸的存储、分类、检索和使用等方面。以下是一些建议,帮助你有效地管理公司图纸: 建立图纸管理制度:制定明确的图纸管理制度,包括图纸的存储、分类、检索和使用等方面的规定。确保…

Eclipse下安装GDB

主要参考资料: 链接: https://blog.csdn.net/u013609041/article/details/18967837 目录 简介Eclipse中安装和配置GDB错误 简介 Eclipse是一款开发软件。 GDB是一个调试软件,但是GDB通常是运行在linux下的,无法直接在windows下运行&#xff…

C++程序设计兼谈对象模型(侯捷)笔记

C程序设计兼谈对象模型(侯捷) 这是C面向对象程序设计的续集笔记,仅供个人学习使用。如有侵权,请联系删除。 主要内容:涉及到模板中的类模板、函数模板、成员模板以及模板模板参数,后面包含对象模型中虚函数调用&…

python统计分析——直方图(df.hist)

使用dataframe.hist()或series.hist()函数绘制直方图 import numpy as np import pandas as pd from matplotlib import pyplot as plt.dfpd.DataFrame(data{type:[A,A,A,A,A,A,A,A,A,A,B,B,B,B,B,B,B,B,B,B],value:[2,3,3,4,4,4,4,5,5,6,5,6,6,7,7,7,7,8,8,9] }) serpd.Serie…

基于综合特征的细菌噬菌体宿主预测工具iPHoP (Integrated Phage HOst Prediction)的介绍以及使用方法详细流程

介绍 iPHoP(Integrated Phage HOst Prediction)是一种基于综合特征的细菌噬菌体宿主预测方法。它是通过整合基因组序列、蛋白质序列和宿主基因组信息来预测细菌噬菌体的宿主范围。 iPHoP的预测过程分为三个步骤:特征提取、特征选择和宿主预…

shell sshpass 主机交互 在另外一台主机上执行某个命令 批量管理主机 以及一些案例

目录 作用安装 sshpasssshpass 用法在远程主机执行某个命令 案例批量传输密匙批量拷贝文件批量修改密码 作用 就是用一台主机 控制另外一台主机免交互任务管理工具方便批量管理主机使用方法就是在ssh 前边加一个 sshpass 安装 sshpass # 安装 sshpass yum -y install sshpas…

晨控CK-GW08-EC与欧姆龙PLC工业EtherCAT协议通讯指南

晨控CK-GW08-EC与欧姆龙PLC工业EtherCAT协议通讯指南 晨控CK-GW08系列是一款支持标准工业通讯协议EtherCAT的网关控制器,方便用户集成到PLC等控制系统中。系统还集成了8路读写接口,用户可通过通信接口使用EtherCAT协议对8路读写接口所连接的读卡器进行相对独立的读…

<软考高项备考>《论文专题 - 48 范围管理(7) 》

8 收尾 8.1 经验教训 经验: 1、在规划范围管理的时候,对项目的复杂程度过于乐观,考虑的不够周详,制订的计划粒度过于粗糙 2、在收集需求前,没有对需求收集人员进行项目业务上的培训,导致需求收集人员与客…

Vue3中配置env环境变量

什么时候会用到这个呢,比如我们的后端开发有多名,很多时候需要切换调用不同人的接口地址,或者在打包的时候,需要指定环境中的后台接口地址,那么我们频繁修改代码,就很麻烦,这个时候,…

win10提示“KBDSF.DLL文件缺失”,游戏或软件无法启动运行,快速修复方法

很多用户在日常使用电脑的时候,或多或少都遇到过,在启动游戏或软件的时候,Windows桌面会弹出错误提示框“KBDSF.DLL文件缺失,造成软件无法启动或运行,请尝试重新安装解决”。 首先,先来了解DLL文件是什么&a…

JS运行机制、Event Loop

1、JS运行机制 JS最大的特点就是单线程,所以他同一时间只能做一件事情。使单线程不阻塞,就是事件循环。 在JS当中分为两种任务: 同步任务:立即执行的任务,一般放在主线程中(主执行栈)。异步任…

企业级 npm 私有仓库部署方案

本文作者系360奇舞团前端开发工程师 淘宝 NPM 镜像站切换新域名时,放了一张知乎博主天猪的图片,如下: _图片来源:https://zhuanlan.zhihu.com/p/432578145 看着逐年增长的访问量,不禁让人感慨,npm 的出现&a…

并发编程大杀器,京东多线程编排工具asyncTool

一、简介 并发编程大杀器,京东多线程编排工具asyncTool,可以解决任意的多线程并行、串行、阻塞、依赖、回调的并行框架,可以任意组合各线程的执行顺序,带全链路执行结果回调。多线程编排一站式解决方案。 二、特点 多线程编排&am…

GPT/GPT4科研应用与AI绘图技术及论文高效写作(建议收藏)

详情点击链接:GPT/GPT4科研实践应用与AI绘图技术及论文高效写作 一OpenAI 1.最新大模型GPT-4 Turbo 2.最新发布的高级数据分析,AI画图,图像识别,文档API 3.GPT Store 4.从0到1创建自己的GPT应用 5. 模型Gemini以及大模型Clau…

客服系统接入FastGPT

接入FastGPT 点击【应用】【外部使用】【API访问】【新建】新建一个KEY,同时也可以看到我们的API根地址 这个根地址和Key可以填入任何支持OpenAI接口的应用里,这个接口是兼容OpenAI格式。 在客服系统【知识库AI配置】里填上接口地址和接口密钥。这样我…

图像分割实战-系列教程10:U2NET显著性检测实战2

🍁🍁🍁图像分割实战-系列教程 总目录 有任何问题欢迎在下面留言 本篇文章的代码运行界面均在Pycharm中进行 本篇文章配套的代码资源已经上传 U2NET显著性检测实战1 U2NET显著性检测实战2 5、残差Unet模块 class RSU7(nn.Module):#UNet07DRES…

04.MySQL的基本操作

MySQL的基本操作 一、连接和断开MySQL服务器1、通过系统服务器启动、停止MySQL服务器2、通过命令提示符(DOS)启动、停止MySQL服务器2.1 启动 MySQL 服务器:2.2 停止 MySQL 服务器:2.3 登录和退出mysql 二、创建和管理数据库2.1 创…

k8s---pod基础下

k8s的pod与docker重启策略的区别 k8s的重启策略 always deployment的yaml文件只能是always,pod的yaml三种模式都可以。不论正常退出还是非正常退出都重启。OnFailure:正常退出不重启,非正常退出会重启Never:正常退出和非正常退出…

奇技淫巧:如何给项目中的RabbitMQ添加总开关

本文主要分享了如何给项目中的RabbitMQ添加总开关,通过简单配置开/关RabbitMQ。 一、需求背景 SpringBoot项目里使用了RabbitMQ,但某些场景下,不希望项目启动时自动检查RabbitMQ连接 例如: 在开发不需要RabbitMQ的功能过程中&…