使用Node.js+Koa 从零开始写个人博客系统——后端部分(一)

使用Node.js+Koa 从零开始写个人博客系统系列

提示:在此文章中你可以学习到的内容如下:

1 如何使用Koa快速搭建项目
2 对Koa的核心组件Koa-Route的简单使用
3 3层架构思想
4 nodejs的ORM框架——sequelize的使用
5 sequelize-auto的使用
6 简单的增删查改


提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

    • 使用Node.js+Koa 从零开始写个人博客系统系列
    • 前言
    • 开始吧
      • 1.0 关于node.js
        • 什么是Node.js?
        • 优缺点如何?
        • 适用场景如何?
      • 1.1 创建Node.js项目
        • 新建nodejs项目
      • 1.2 初步填充app.js文件
        • 什么是Koa?
        • 什么是Koa-router?
        • 在app.js中替换为以下代码
      • 1.3 创建router中的文件
      • 1.4 创建新的index.js
      • 1.5 新建控制器js文件
      • 1.6 替换路由文件
      • 2.1 使用sequelize
        • 简单使用
      • 2.2 执行sql语句
      • 2.3使用sequelize-automate
      • 2.5 更改config/dbconfig.js
      • 2.6 测试sequelize是否可以连接数据库
      • 2.7 使用增删改查
      • 2.8 抽离数据库连接代码至Core中


前言

此项目始终贯彻在做实际项目中,学习新的知识,适合看不进去视频,或者官方文档的人阅读,
小白也能上手操作,大佬也能理清思路,话不多说上车!!

例如:随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启了学习机器学习,本文就介绍了机器学习的基础内容。


开始吧


1.0 关于node.js

一心上手搓代码的可略过此概念

什么是Node.js?

Node.js是一个Javascript运行环境(runtime)。

优缺点如何?

优点:

1.事件驱动

2.异步编程

3.非阻塞模式的IO

4.轻量高效

缺点:

1.可靠性低

2.单进程,单线程,只支持单核cpu,不能充分的利用多核cpu服务器。一旦这个进程崩掉,那么整个web服务就崩掉了。

适用场景如何?

适用场景:

1.JSON APIL ——构建一个Rest/JSON API服务,node.js可以充分发挥其非堵塞IO模型以及javascript对JSON的功能支持

2.单页面、多Ajax请求应用——前端有大量的异步请求,需要服务器后端有极高的响应速度

3.基于node.js开发Unix命令行工具——node.js可以大量产生子进程,并以流的方式输出

4.流式数据——传统的web应用,通常会将HTTP 请求喝响应看成是原子事件。而node.js会充分利用流式数据这个特点,构建非常酷的应用

不适用场景:

cpu使用率较重、io使用率较轻的应用

1.1 创建Node.js项目

这一步的前提是你已经安装好Node.js环境了,没安装的简单安装下可以参照以下网站
https://www.runoob.com/nodejs/nodejs-install-setup.html

安装完毕后,我使用的工具是webstorm来写Nodejs项目,官网在这里
https://www.jetbrains.com/webstorm/

新建nodejs项目

在这里插入图片描述

新建以下的目录与文件
在这里插入图片描述

1.2 初步填充app.js文件

这里需要使用到两个东西

什么是Koa?

Koa 是一个使用 Node.js 的 web 开发框架,通过中间件的方式解决 web 开发中的 http 处理、业务逻辑实现。它提供 web 开发常见的各种基础功能
提供一套规范的编码方式,让开发者可以聚焦在业务逻辑实现,代码就可以在框架内按照预期执行。
​ 安装

安装Koa
npm install Koa

app.js中复制以下的代码

# 引入Koa
const Koa = require('koa');
# 创建Koa对象
const app = new Koa();
# 拦截任意访问链接
app.use(async ctx => {
  ctx.body = 'Hello World';
});
# 监听端口
app.listen(3000);

什么是Koa-router?

Koa-router 是 koa 的一个路由中间件,它可以将请求的URL和方法(如:GET 、 POST 、 PUT 、 DELETE 等) 匹配到对应的响应程序或页面。

在app.js中替换为以下代码

const Koa = require('koa');
const Router = require('koa-router')

const app = new Koa();
const router = new Router()

router.get('/hello', (ctx)=>{
    ctx.body= 'hello world!';
})

// 注册路由
app.use(router.routes()).use(router.allowedMethods())

app.listen(3000,() => {
    console.log('Hello World');
});

运行方法,鼠标右击,选择运行app.js文件即可
在这里插入图片描述

运行当前文件,得到 并访问
localhost:3000/hello

在这里插入图片描述

恭喜你已经完成了第一个简单的项目!!!

1.3 创建router中的文件

新建如下目录
在这里插入图片描述

article.js中复制以下代码

const Router = require("koa-router");

const router=new Router({
    prefix:"/Admin"
});


//模糊查询加分页获取文章数据
router.post("/getArticles",(x)=>{
    //post的请求参数
    console.log(x.request.body)
})
//新增文章
router.post("/addArticles",(x)=>{

})

//更新文章
router.post("/updateArticles",x=>{

})

//删除文章
router.post("/removeArticles",x=>{

})

//模糊查询加分页获取评论数据
router.post("/getCommentPage",x=>{

})

//删除评论
router.post("/removeComment",x=>{

})

//更新评论
router.post("/updateComment",x=>{

})
module.exports = router
______________________________________________
login.js复制一下代码
-----------------
const Router=require("koa-router")
const router=new Router({
    prefix:'/Blog'
})
//开始登录
router.post("/Login",x=>{

})
module.exports=router;

--------------------------
article.js
--------------------------
const Router=require("koa-router")
const router=new Router({
    prefix:'/Blog'
})
//模糊查询加分页获取文章数据
router.post("/getPageData",x=>{

})
//获取详细文章内容
router.get("/getArticles:title",x=>{
    console.log(x.request.body)
})
//根据时间线获取文章
router.get("/getArticlesByTimeLine",x=>{

})
//获取文章通过指定搜索
router.get("/getArticlesSearch:search",x=>{

})
module.exports = router
------------------------
friendlink.js
------------------------
const Router=require("koa-router")
const router=new Router({
    prefix:'/Blog'
})
//获取所有友情链接
router.get("/getAllLink",x=>{
    console.log(111)
})
module.exports=router
--------------------
message.js
-------------------
const Router=require("koa-router")
const router=new Router({
    prefix:'/Blog'
})
//获取所有留言
router.post("/getAllMessage",x=>{
})
module.exports=router;

prefix
koa-router提供一种router.prefix方法,此方法对于某一个router来说,是一个全局配置,此router的所有路径都会自动被添加该前缀。

1.4 创建新的index.js

在这里插入图片描述
复制以下的代码

const fs = require('fs')

module.exports = (app) => {
    // 读取当前目录下所有文件
    fs.readdirSync(__dirname).forEach(file => {
        // 除去 `index.js` 文件外其他的都要注册到 `app` 中
        if (file === 'index.js')
            return
        const router = require(`./${file}`)
        console.log(router)
        app.use(router.routes()).use(router.allowedMethods())
    })
}

启动项目 浏览器访问

http://localhost:3000/Blog/getAllLink

控制台得到。
在这里插入图片描述

在这里插入图片描述

OK! 简单的路由也使用完毕了

1.5 新建控制器js文件

class Admincontroller{
    getArticles(x){
        console.log("这是控制器getArticles")
        return x.body="这是控制器getArticles!!!!!"
    }
    addArticles(x){
        return x.body="addArticles"
    }
    updateArticles(x){
        return x.body="updateArticles"
    }
    removeArticles(x){
        return x.body="removeArticles"
    }
    getCommentPage(x){
        return x.body="getCommentPage"
    }
    removeComment(x){
        return x.body="removeComment"
    }
    updateComment(x){
        return x.body="updateComment"
    }
}

module.exports=new Admincontroller()

----------
class Articlecontroller {
    getPageData(x) {
        return x.body = "getPageData"
    }

    getArticles(x) {
        return x.body = "getArticles"
    }

    getArticlesByTimeLine(x) {
        return x.body = "getArticlesByTimeLine"
    }

    getArticlesSearch(x) {
        return x.body = "getArticlesSearch"
    }
}

module.exports=new Articlecontroller()

-----------
class Friendlinkcontroller {
    getAllLink(x) {
        return x.body = "getAllLink"
    }
}

module.exports=new Friendlinkcontroller()
--------------------
class Logincontroller {
    Login(x) {
        return x.body = "Login"
    }
}

module.exports=new Logincontroller()

-------------------------
class Messagecontroller {
    getAllMessage(x) {
        return x.body = "getAllMessage"
    }
}

module.exports=new Messagecontroller()


这里我准备使用3层架构。所以才有了Controller层。

1.6 替换路由文件

在这里插入图片描述

------admin.js-----
const Router = require("koa-router");
const Controller=require("./../controller/admincontroller")
const router=new Router({
    prefix:"/Admin"
});


//模糊查询加分页获取文章数据
router.post("/getArticles",Controller.getArticles)
//新增文章
router.post("/addArticles",Controller.addArticles)

//更新文章
router.post("/updateArticles",Controller.updateArticles)

//删除文章
router.post("/removeArticles",Controller.removeArticles)

//模糊查询加分页获取评论数据
router.post("/getCommentPage",Controller.getCommentPage)

//删除评论
router.post("/removeComment",Controller.removeComment)

//更新评论
router.post("/updateComment",Controller.updateComment)
module.exports = router

`---------------
const Router=require("koa-router")
const Controller=require("./../controller/articlecontroller")

const router=new Router({
    prefix:'/Blog'
})
//模糊查询加分页获取文章数据
router.post("/getPageData",Controller.getPageData)
//获取详细文章内容
router.get("/getArticles:title",Controller.getArticles)
//根据时间线获取文章
router.get("/getArticlesByTimeLine",Controller.getArticlesByTimeLine)
//获取文章通过指定搜索
router.get("/getArticlesSearch:search",Controller.getArticlesSearch)
module.exports = router

-------------
const Router=require("koa-router")
const Controller=require("./../controller/friendlinkcontroller")

const router=new Router({
    prefix:'/Blog'
})

//获取所有友情链接
router.get("/getAllLink",Controller.getAllLink)
module.exports=router

----------------
const Router=require("koa-router")
const Controller=require("./../controller/messagecontroller")

const router=new Router({
    prefix:'/Blog'
})
//获取所有留言
router.post("/getAllMessage",Controller.getAllMessage)
module.exports=router;

--------------
const Router=require("koa-router")
const Controller=require("./../controller/logincontroller")
const router=new Router({
    prefix:'/Blog'
})
//开始登录
router.post("/Login",Controller.Login)
module.exports=router;


启动测试

http://localhost:3000/Blog/getAllLink

在这里插入图片描述

OK 控制器使用完毕了

2.1 使用sequelize

Sequelize是一个强大的jsORM框架,可快速操作数据库
官网
https://www.sequelize.cn/core-concepts/getting-started
安装

# 使用 npm
npm i sequelize # 这将安装最新版本的 Sequelize


npm i mysql2 # MySQL

并建立以下的文件
在这里插入图片描述

修改配置文件内容

module.exports = {
    environment: 'dev',
    database: {
        dbName: 'boblog_0321',
        host: 'localhost',
        port: 3306,
        user: 'root',
        password: 'xx'
    },
}

要想使用sequelize 这个ORM框架,则必须先建立数据库中各个表对应的Model
而建立model。是通过sequelize的define方法建立模型的,Model相当于数据库中的表,该对象不能通过构造函数实例化,而只能通过sequelize.define()或sequelize.import()方法创建。

简单使用

看下面的代码,这样就创建了一个简单的model(article_model),其中article_model对应数据库中的article表。其中article_summary是表中的一个字段,article_summary{}中写的都是当前字段的属性信息。
需要注意通过这种方式同步的表会在表名称后面添加一个s作为复数。同步数据库是会默认添加两个字段createdAt和updatedAt有的时候可能不需要这两个字段。这个时候需要在第三个字段中添加timestamps为false默认为true。


  const ArticleModel = sequelize.define("article_model", {
      article_summary: 
      {
	      type: DataTypes.TEXT,
	      allowNull: true,
	      defaultValue: null,
	      primaryKey: false,
	      autoIncrement: false,
	      comment: "摘要",
	      field: "article_summary"
	    }
	},
    { 
    tableName: "article",
    comment: "",
    indexes: [], timestamps:false
    }
  );

上面可以看出通过Sequelize.STRING设置当前字段的类型,Sequelize提供了很多数据类型供我们进行使用:如下
在这里插入图片描述
但是这样一个个的建立太麻烦了,所以请看下面的

2.2 执行sql语句

xx看文章末尾

2.3使用sequelize-automate

我们开发时,是先创建表,然后再写业务代码。
而且我们的表结构不能轻易变更,变更表结构可能有单独的流程。
所以大部分情况下,我们都是根据表结构手动写 Models,而不能直接使用 sequelize.sync() 去更新表结构。
然而当表非常多的时候,手动写 Models 是一件非常繁琐的事情,并且都是低级的重复性的事情。显然这种事情应该交由工具来做,这个工具就是 sequelize-automate 。
官网:
https://github.com/nodejh/sequelize-automate

安装
npm install sequelize-automate --save
使用
找到package.json文件
在这里插入图片描述

替换scripts的代码块

  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "sequelize-automate": "sequelize-automate"
  },

*** sequelize-automate 命令详解 ***
sequelize-automate 命令支持的参数主要有:

–type, -t 指定 models 代码风格,当前可选值:js ts egg midway
–dialect, -e 数据库类型,可选值:mysql sqlite postgres mssql mariadb
–host, -h 数据库 host
–database, -d 数据库名
–user, -u 数据库用户名
–password, -p 数据库密码
–port, -P 数据库端口,默认:MySQL/MariaDB 3306,Postgres 5432,SSQL: 1433
–output, -o 指定输出 models 文件的目录,默认会生成在当前目录下 models 文件夹中
–camel, -C models 文件中代码是否使用驼峰发命名,默认 false
–emptyDir, -r 是否清空 models 目录(即 -o 指定的目录),如果为 true,则生成 models 之前会清空对应目录,默认 false
–config, -c 指定配置文件,可以在一个配置文件中指定命令的参数

新建配置文件
在这里插入图片描述
复制以下内容
注意修改


module.exports = {
    dbOptions: {
        database: 'yyy',
        username: 'root',
        password: 'xx',
        dialect:"mysql",
        host: 'localhost',
        port: 3306
    },
    options: {
        type: "js",
        dir: "./app/entity"
    }
}

然后打开终端运行以下命令

sequelize-automate -c dbInit.js

等待执行完成可以看到
在这里插入图片描述
这样就是成功了。
修改冗余字段,选中entity鼠标右键选择如图所示
在这里插入图片描述
使用以下规则进行替换
indexes: []
indexes: [], timestamps:false
在这里插入图片描述
替换完成就OK了

2.5 更改config/dbconfig.js

module.exports = {
    dbOptions: {
        database: 'yyy',
        username: 'root',
        password: 'xx',
        dialect:"mysql",
        host: 'localhost',
        port: 3306
    },
    options: {
        type: "js",
        dir: "./app/entity"
    }
}

2.6 测试sequelize是否可以连接数据库

复制以下代码直到app.js中进行测试

const Conf = require("./config/dbconfig");

const sequelize = new Sequelize(Conf.dbOptions.database, Conf.dbOptions.username, Conf.dbOptions.password, {
    host: Conf.dbOptions.host,
    dialect: Conf.dbOptions.dialect
});
try {
     sequelize.authenticate();
    console.log('Connection has been established successfully.');
} catch (error) {
    console.error('Unable to connect to the database:', error);
}

运行程序,如下即为成功!
在这里插入图片描述

2.7 使用增删改查

app.js中加入以下代码

const {Sequelize} = require("sequelize");
const Conf = require("./config/dbconfig");
const Ar=require("./app/entity/article")
const sequelize = new Sequelize(Conf.dbOptions.database, Conf.dbOptions.username, Conf.dbOptions.password, {
    host: Conf.dbOptions.host,
    dialect: Conf.dbOptions.dialect
});

try {
     sequelize.authenticate();
     // 查询所有文章信息
     Ar(sequelize).findAll().then(x=>{
         console.log(x)
     })
     console.log('Connection has been established successfully.');
} catch (error) {
    console.error('Unable to connect to the database:', error);
}

2.8 抽离数据库连接代码至Core中

新建如下文件
在这里插入图片描述
DbConn.js中
复制这些

//创建数据库链接
const {Sequelize} = require("sequelize");
const Conf = require("../config/dbconfig");
module.exports=new Sequelize(Conf.dbOptions.database, Conf.dbOptions.username, Conf.dbOptions.password, {
    host: Conf.dbOptions.host,
    dialect: Conf.dbOptions.dialect
});

替换app.js中的代码为如下

const Koa = require('koa');
const Router = require('koa-router')
const MyRouter=require("./app/router/index");
const Ar=require("./app/entity/article")
const conn=require("./core/DBConn")

const app = new Koa();
const router = new Router()

MyRouter(app)

//查询全部
Ar(conn).findAll().then(x=>{
    console.log(x)
})


// 注册路由
app.use(router.routes()).use(router.allowedMethods())

app.listen(3000,() => {
    console.log('Hello World');
});

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

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

相关文章

【蓝桥杯嵌入式】第十三届蓝桥杯嵌入式国赛客观题以及详细题解

题1 概念题。 USRAT:异步串口通信,常用于数据传输;SW-DP:SWD 的全称应该是 The Serial Wire Debug Port (SW-DP),也就是串行调试端口,是 >ARM 目前支持的两种调试端口之一;JTAG-DP:另一个调试…

git基本用法教程(fork软件+git命令)

git基本用法教程1. git commit2. git branch3. git checkout4. git merge5. git rebase6. 在提交树中移动7. 撤销变更8. 整理提交记录9. 提交的技巧10. git clone11. git push12. git pull13. git fetch14. git flow15. git stash16. fork的使用当然除了环境和demo的运行和改写…

chartgpt 告诉我的,loss 函数的各种知识

一、libtorch中常见的损失函数及其使用场景的总结1. CrossEntropyLoss:CrossEntropyLoss(交叉熵损失)主要用于分类任务。它适用于多分类问题,其中每个样本只属于一个类别(互斥)。该损失函数将预测概率与真实标签的one-…

应届生投腾讯,被面试官问了8个和 ThreadLocal 相关的问题。

问:谈一谈ThreadLocal的结构。 ThreadLocal内部维护了一个ThreadLocalMap静态内部类,ThreadLocalMap中又维护了一个Entry静态内部类,和Entry数组。 Entry类继承弱引用类WeakReference,Entry类有一个有参构造函数,参数…

【数据结构】用队列实现栈

💯💯💯 本篇总结利用队列如何实现栈的相关操作,不难观察,栈和队列是可以相互转化的,需要好好总结它们的特性,构造出一个恰当的结构来实现即可,所以本篇难点不在代码思维,…

大数据应用——Hadoop运行模式(伪分布式运行)

4.2 伪分布式运行模式4.2.1 启动HDFS并运行MapReduce程序1. 分析 (1)配置集群(2)启动、测试集群增、删、查没有改(多台机子麻烦)(3)执行WordCount案例2. 执行步骤(1&…

前端vue实现导出pdf文件报告组件

大屏项目有一个需求,需要对展示的内容进行文件导出,但是目前后台没有相关的逻辑,所以只能前端硬上,在参考了其他许多的逻辑之后,目前我自己这边做了一套比较笨的组件,通过拼接标签这种方法来实现对你想需要…

队列-我的基础算法刷题之路(六)

本篇博客旨在整理记录自已对队列的一些总结,以及刷题的解题思路,同时希望可给小伙伴一些帮助。本人也是算法小白,水平有限,如果文章中有什么错误之处,希望小伙伴们可以在评论区指出来,共勉 💪。…

seaborn从入门到精通03-绘图功能实现02-分类绘图Categorical plots

seaborn从入门到精通03-绘图功能实现02-分类绘图Categorical plots总结参考关系-分布-分类分类绘图-Visualizing categorical data图形级接口catplot--figure-level interface导入库与查看tips和diamonds 数据分类散点图参考分布散点图stripplot分布密度散点图-swarmplot&#…

进程与线程

文章目录进程与线程进程什么是进程进程的组成程序段数据段程序控制块例子线程什么是线程线程的组成线程描述信息程序计数器栈内存例子进程与线程的区别进程与线程 进程 什么是进程 ​ 什么是进程呢?简单来说,进程是程序的一次启动执行。什么是 程序呢…

【C#进阶】C# 集合类

序号系列文章16【C#进阶】C# 索引器17【C#进阶】C# 委托18【C#进阶】C# 事件文章目录前言1、集合类是什么2、动态数组(ArrayList)3、压缩数组(BitArray)4、哈希表(Hashtable)5、队列(Queue&…

【数据结构】链表OJ题

目录面试题 02.04 分割链表剑指 Offer II 027 回文链表160 相交链表141 环形链表142 环形链表 II138 复制带随机指针的链表面试题 02.04 分割链表 定义lesshead和greaterhead链接小于和大于等于k的值分别设置哨兵位和尾节点指针最后将两表去除哨兵位再链接 struct ListNode* p…

内存泄漏和内存溢出的区别

参考答案 内存溢出(out of memory):指程序在申请内存时,没有足够的内存空间供其使用,出现 out of memory。内存泄露(memory leak):指程序在申请内存后,无法释放已申请的内存空间,内存泄露堆积会导致内存被…

论文解读:PP-LiteSeg: A Superior Real-Time Semantic Segmentation Model

发表时间:2022 论文地址:https://arxiv.org/abs/2204.02681 项目地址:https://github.com/PaddlePaddle/PaddleSeg PP-LiteSeg,一个新的轻量级实时语义分割任务模型,在分割精度和推理速度之间实现了一种最先进的权衡…

JVM垃圾回收机制

文章目录JVM垃圾回收机制如何确定该对象是垃圾引用计数可达性分析如何释放对象常用策略JVM垃圾回收机制 以对象为单位来进行回收 如何确定该对象是垃圾 Java 中使用 可达性分析方法 Python 中时使用 引用计数方法 引用计数 使用额外的计数器,来记录某个对象有多少个…

【致敬未来的攻城狮计划】连续打卡第4天+物联网操作系统概述

开启攻城狮的成长之旅!这是我参与的由 CSDN博客专家 架构师李肯(http://yyds.recan-li.cn)和 瑞萨MCU (https://www.renesas.cn/cn/zh) 联合发起的「 致敬未来的攻城狮计划 」的第 4 天,点击查看活动计划详…

【Vue3】用Element Plus实现列表界面

🏆今日学习目标:用Element Plus实现列表界面 😃创作者:颜颜yan_ ✨个人格言:生如芥子,心藏须弥 ⏰本期期数:第四期 🎉专栏系列:Vue3 文章目录前言效果图目录简介修改vite…

基于springboot框架实现心理健康心灵治愈交流平台【源码+论文】展示

基于springboot框架实现心灵心理健康 【源码论文】开发语言:Java 框架:springboot JDK版本:JDK1.8 服务器:tomcat7 数据库:mysql 5.7 数据库工具:Navicat11 开发软件:eclipse/myeclipse/idea Ma…

CSS 7种居中效果实现原理与案例

目录 1.标准盒子居中 2.定位-绝对定位实现居中 3.表格方式实现垂直居中 4.弹性盒子:实现垂直居中 5.通过行高line-height实现垂直居中 6.变形定位实现居中 7.网格实现垂直居中 1.标准盒子居中 不需要设置display,只能实现水平居中 效果&#xff1…

代码随想录算法训练营第五十二天| ● 300.最长递增子序列 ● 674. 最长连续递增序列 ● 718. 最长重复子数组

300.最长递增子序列 看完题后的思路 dp[i] [0,i]子数组中,以nums[i]结尾的子序列的长度 dp[i]dp[j]1 j从i-1向0遍历,在所有nums[j]<nums[i]中dp[j]最大 初始化 dp[0]1 代码 class Solution {public int lengthOfLIS(int[] nums) {if (nums.length0){return 0;}int[] dpne…
最新文章