当前位置: 首页 > news >正文

Node.js--》简易资金管理系统后台项目实战(后端)

        今天开始使用 node + vue3 + ts搭建一个简易资金管理系统的前后端分离项目,因为前后端分离所以会分两个专栏分别讲解前端与后端的实现,后端项目文章讲解可参考:前端链接,我会在前后端的两类专栏的最后一篇文章中会将项目代码开源到我的GithHub上,大家可以自行去进行下载运行,希望本文章对有帮助的朋友们能多多关注本专栏,学习更多前端node知识,然后开篇先简单介绍一下本项目用到的技术栈都有哪几个方面(阅读本文章能够学习到的技术):

node:基于Chrome V8引擎的开源、跨平台的JavaScript运行环境。

express:基于node.js的Web应用框架,帮助开发者快速构建可靠、高效的Web应用程序。

pm2:针对node应用生产环境进程管理工具,可帮助简化应用程序部署运行和监视等工作。

MongoDB:面向文档的NoSQL数据库系统,它可以灵活地存储非结构化数据。

Apifox:易用界面和功能,帮助开发人员和团队更高效地创建、设计和管理 RESTful API。

jwt:用于定义在网络上传输的信息安全可验证和可信任的方式,用于身份验证和授权机制。

目录

express搭建服务器

连接MongoDB数据库

搭建注册接口

搭建登录接口

获取登录信息

添加和获取信息

编辑和删除信息


express搭建服务器

首先我们需要创建一个文件夹用于存放后端项目,然后将文件夹拖到编辑器vscode当中,接下来需要打开终端执行 npm init 初始化package.json文件,相关步骤如下:

接下来开始装载 express 框架,终端执行如下命令:

npm install express

接下来我们在项目文件夹中创建入口文件 server.js 然后开始使用 express 框架:

const express  = require("express")
const app = express()
// 设置路由
app.get('/', (req,res) =>{res.send('hello world')
})
// 设置端口号
const post = process.env.PORT || 8080
app.listen(post, () => {console.log(`Server is running on port ${post},url: http://127.0.0.1:${post}`)
})

为了方便代码的执行,这里我们采用 pm2 进程管理工具进行使用,关于pm2的安装和具体的使用教程可以参考我之前的文章:深入理解 PM2:Node.js 应用部署和管理利器 ,为了方便简介,这里我们可以直接在package.json文件中设置一下我们的命令,如 下:

pm2进程管理工具是不会随着你将终端关闭而停止运行的,如果是第一次运行项目的话,可以根据我们上面设置的命令执行:npm run start 即可,如果想关闭项目的话,执行 pm2 stop 加项目名称就行了,如果实时查看日志,执行 pm2 log 即可,具体的实操自己体会,这里不再赘述。

接下来我们打开我们本地的 5000 端口,可以看到我们后端运行的项目了:

连接MongoDB数据库

接下来我们在本地创建一个 MongoDB数据库,用来后面后端编写相应接口所需要存放的数据,如果不了解MongoDB的朋友推荐可以参考一下我之前的文章:MongoDB数据库 ,接下来我们需要开始执行 node 连接MongoDB数据库了。

启动MongoDB服务

点击win键输入cmd,点击以管理员身份运行

执行 net start MongoDB 命令,运行MongoDB数据库服务:

创建MongoDB数据库

使用 Navicat 图形化管理工具,创建数据库。点击新建连接,选择 MongoDB

配置相应参数,连接直接默认即可,一般情况下,我们连接只需要连接主库查数据,所以选择独立的这个连接方式就可以,填写好常规参数可以点击测试连接是否正常,即可连接!因为是个人测试嘛,使用的是本地的localhost:

出现如下界面说明连接成功,我们直接点击确定即可。 

注意:进入到数据库之后,我们删除默认的数据库,重新创建一个名为 node_fund 名称的数据库

连接MongoDB数据库

接下来我们需要借助vscode工具来连接mongodb数据库,首先终端执行如下命令安装相应的包:

npm install mongoose

安装完成之后,我们在server.js中执行如下命令进行验证是否连接数据库成功:

// 引入 express 服务框架
const express  = require("express")
// 引入 mongoose 数据库服务
const mongoose = require("mongoose")
const app = express()
// 连接数据库的 URL
const MongoUrl = 'mongodb://localhost:27017/node_fund'
// 连接数据库
mongoose.connect(MongoUrl).then(() => {console.log('连接成功')
}).catch((err) => {console.log('连接失败', err)
})
// 设置路由
app.get('/', (req,res) =>{res.send('hello world')
})
// 设置端口号
const post = process.env.PORT || 5000
app.listen(post, () => {console.log(`Server is running on port ${post},url: http://127.0.0.1:${post}`)
})

当我们执行 pm2 log 查看日志的时候可以看到,我们的终端打印了连接成功的字眼:

当我们更改 MongoUrl 的默认url的时候,终端就会打印出相应的连接失败以及相应报错:

搭建注册接口

接下来我们需要开始搭建真正的接口了,首先我们需要在项目根目录下创建相关文件夹编写接口:

在编写接口之前,我们需要先安装 body-parser ,为了方便地在node中处理 POST 请求的请求体数据,从而更轻松地进行数据处理和响应,终端执行如下命令进行安装:

npm install body-parser

安装完成之后,我们还需要在入口文件 server.js 中使用它来解析请求体:

const express  = require("express")
const bodyParser = require("body-parser")
const app = express()// 使用 body-parser 中间件
app.use(bodyParser.urlencoded({ extended: false })) // 解析表单数据
app.use(bodyParser.json()) // 解析 JSON 格式的请求体

插件安装完成之后,我们还需要在项目根目录下创建一个models文件,用于存放从数据库获取数据所需要的数据及其相应的类型,这里需要借助 Schema 属性:

const mongoose = require('mongoose')// 定义模式,用于指定数据的结构和字段。
const Schema = mongoose.Schema
// 使用Schema变量来定义具体的数据模型
const userSchema = new Schema({name: {type: String,required: true},email: {type: String,required: true},password: {type: String,required: true},avatar: {type: String,},identity: {type: String,required: true},date: {type: Date,default: Date.now},
})
/** * 创建了一个名为users的MongoDB集合,并使用userSchema指定了集合中文档的结构* 将前一步创建的模型赋值给一个变量User,使其成为我们操作users集合的接口。*/
module.exports = User = mongoose.model('users', userSchema)

定义完相应的注册登录接口所需类型之后,接下来就需要正式在user.js文件中编写相应的注册接口,代码如下:

// 用户登录 / 注册相关的内容
const express = require('express')
const router = express.Router()// 引入具体的数据类型
const User = require('../../models/User')/*** 注册接口* POST api/users/register */
router.post('/register', (req,res) => {// 查询数据库中是否拥有邮箱User.findOne({ email: req.body.email }).then((user) => {if (user) {return res.status(400).json({ email: '邮箱已被注册' })} else {// 注册新邮箱const newUser = new User({name: req.body.name,email: req.body.email,avatar,password: req.body.password,identity: req.body.identity})}})
})module.exports = router

因为密码是至关重要的数据,所以这里我们需要对用户的密码进行一个加密,终端执行如下命令:

npm install bcrypt

下载成功之后,导入 bcrypt 然后对数据进行相应的hash加密,修改后的代码如下:

// 用户登录 / 注册相关的内容
const express = require('express')
const router = express.Router()
const bcrypt = require("bcrypt")// 引入具体的数据类型
const User = require('../../models/User')/*** 注册接口* POST api/users/register */
router.post('/register', (req,res) => {// 查询数据库中是否拥有邮箱User.findOne({ email: req.body.email }).then((user) => {if (user) {return res.status(400).json({ email: '邮箱已被注册' })} else {// 注册新邮箱const newUser = new User({name: req.body.name,email: req.body.email,avatar,password: req.body.password,identity: req.body.identity})// 进行密码加密bcrypt.genSalt(10, (err, salt) => {bcrypt.hash(newUser.password, salt, (err, hash) => {if (err) throw errnewUser.password = hashnewUser.save().then(user => res.json(user)).catch(err => console.log(err))})})}})
})module.exports = router

写完相应代码之后,这里我们还需要将该路由代码在入口文件 server.js 中进行一个引入:

const express  = require("express")
const app = express()// 引入user.js
const users = require('./routes/api/user')
// 使用routes
app.use('/api/users', users)

接下来我们需要借助接口测试工具 Apifox 进行相应的接口测试,如果不了解 Apifox 的朋友,可以参考我之前的文章:Apifox:详细使用教程,带你轻松拿捏 ,为了便于测试,我们先把 avatar 图像参数先删除,先测试一下其他参数。当我们输入相关路径及其参数点击发送之后:

当我们再次点击发送之后,就会出现当前的邮箱已被注册,符合逻辑规律:

接下来我们需要处理 avatar 头像参数,需要将图片数据保存到数据库中,可以使用 Buffer 对象来处理二进制数据,并将其存储为 Buffer 类型的字段。这里我们需要安装如下的这个插件进行处理

npm install multer

然后代码进行如下方式的修改:

// 用户登录 / 注册相关的内容
const express = require('express')
const router = express.Router()
const bcrypt = require("bcrypt")
const multer = require('multer');
const jwt = require("jsonwebtoken")
const passport = require("passport")// 引入具体的数据类型
const User = require('../../models/User')// 配置 multer
const storage = multer.diskStorage({destination: function (req, file, cb) {cb(null, 'public/images') // 设置图片保存的路径},filename: function (req, file, cb) {const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9)cb(null, file.fieldname + '-' + uniqueSuffix + '.' + file.mimetype.split('/')[1]) // 设置图片的文件名}
})
const upload = multer({ storage: storage })/*** 注册接口* POST api/users/register */
router.post('/register', upload.single('avatar'), (req,res) => {// 查询数据库中是否拥有邮箱User.findOne({ email: req.body.email }).then((user) => {if (user) {return res.status(400).json('邮箱已被注册')} else {const avatarUrl = req.protocol + '://' + req.get('host') + '/images/' + req.file.filename;// 注册新邮箱const newUser = new User({name: req.body.name,email: req.body.email,avatar: avatarUrl, // 使用上传的图片的文件名作为 avatar 字段的值password: req.body.password,identity: req.body.identity})// 进行密码加密bcrypt.genSalt(10, (err, salt) => {bcrypt.hash(newUser.password, salt, (err, hash) => {if (err) throw errnewUser.password = hashnewUser.save().then(user => res.json(user)).catch(err => console.log(err))})})}})
})

接下来进行Apifox接口测试之后,得到的结果如下:

如果想访问图片资源的话,这里我们还需要在入口文件出将静态资源设置为可访问:

app.use(express.static('public'));

当我们打开 Navicat 可视化管理工具之后,找到我们创建的对应数据,打开集合就能看到我们在测试工具Apifox生成的数据,在数据库当中也呈现出来了:

搭建登录接口

和注册接口一样,原理就是我们拿到用户请求过来的email和password之后,进行数据库的一个查询,如果查询当前数据库没有用户传递过来的email数据,就返回用户不存在,否则的话就开始比较密码进行相应的匹配得到对应的结果:

/*** 登录接口* POST api/users/login*/
router.post('/login', (req,res) => {const email = req.body.emailconst password = req.body.password// 查询数据库User.findOne({ email }).then(user => {if (!user) {return res.status(404).json({ email: '用户不存在!' })}// 密码匹配bcrypt.compare(password, user.password).then(isMatch => {if (isMatch) {res.json({ msg: 'success' })} else {return res.status(400).json({ password: '密码错误!' })}})})
})

比如说我们拿一下数据库当中真实存在的数据进行测试一下,得到的结果肯定是 success :

如果说我们随便输入密码或者用户名可能不是success了,举个例子改一下密码:

接下来我们需要给登录成功的 success 返回相应的token,终端执行如下命令按照相应包:

npm install jsonwebtoken

在导入 const jwt = require("jsonwebtoken") 之后,在密码匹配的地方执行jwt设置一个标记,过期时间我们设置了一个小时,然后token的话和前面的字符串进行了一个拼接:

在Apifox接口测试工具进行测试得到的相应结果如下:

获取登录信息

登录的接口写完,我们还需要写一个获取登录信息的接口函数,首先判断我们是否登录成功即需要验证一下我们当前登录的token是否存在且正确,所以这里我们需要借助 passport-jwt等工具进行:

npm install passport-jwt passport

接下来我们需要在入口文件 server.js 中初始化passport,然后将逻辑代码单独抽离出来:

// passport初始化
app.use(passport.initialize())
// 引入passport逻辑功能代码
require("./config/passport")(passport)

在抽离出来的config文件夹下的passport文件,这里我们开始书写真正的token校验:

const JwtStrategy = require("passport-jwt").Strategy
ExtractJwt = require("passport-jwt").ExtractJwt
const mongoose = require("mongoose")
const User = mongoose.model("users")const opts = {}
opts.jwtFromRequest = ExtractJwt.fromAuthHeaderAsBearerToken()
opts.secretOrKey = 'secret'module.exports = passport => {passport.use(new JwtStrategy(opts, (jwt_payload, done) => {User.findById(jwt_payload.id).then(user => {if (user) {return done(null, user)}return done(null, false)}).catch((err) => {console.log(err)})}))
}

在user.js路由文件夹下,我们开始书写获取登录信息的接口了,这里我们仍然将图片资源进行应该路径的拼接:

/*** 获取登录信息* POST api/users/current*/
router.get('/current', passport.authenticate("jwt", { session: false }), (req,res) => {res.json({id: req.user.id,name: req.user.name,email: req.user.email,avatar: req.user.avatar,identity: req.user.identity})
})

通过Apifox得到的结果如下:

添加和获取信息

注册和登录的功能写完之后,接下来需要我们开始编写添加和获取信息的接口,这里我们要在api文件夹下再新建一个 profile 文件,以及在模型models文件夹下新建 Profile文件:

创建的两个文件都要在入口文件 server.js 中进行引入:

// 引入profile.js
const profile = require('./routes/api/profile')
// 使用routes
app.use('/api/profile', profile)

接下来我们先编写数据模型文件的代码,具体代码如下:

const mongoose = require('mongoose')// 定义模式,用于指定数据的结构和字段。
const Schema = mongoose.Schema
// 使用Schema变量来定义具体的数据模型
const ProfileSchema = new Schema({type: {type: String,},describe: {type: String,},income: {type: String,required: true},expend: {type: String,required: true},cash: {type: String,required: true},remark: {type: String,},date: {type: Date,default: Date.now},
})
/** * 创建了一个名为users的MongoDB集合,并使用userSchema指定了集合中文档的结构* 将前一步创建的模型赋值给一个变量User,使其成为我们操作users集合的接口。*/
module.exports = Profile = mongoose.model('profile', ProfileSchema)

根据上面讲解的编写接口的经验,我们很容易就写出添加和获取信息的即可,如下:

// 用户登录 / 注册相关的内容
const express = require('express')
const router = express.Router()
const passport = require("passport")// 引入具体的数据类型
const Profile = require('../../models/Profile')/*** 创建信息接口* POST api/profiles/add*/
router.post("/add", (req, res, next) => {passport.authenticate("jwt", { session: false }, (err, user, info) => {// 判断错误情况if (err) return res.status(500).json({ error: "Internal Server Error" });if (!user) return res.status(401).json({ error: "Unauthorized" });const profileFields = {};if (req.body.type) profileFields.type = req.body.type;if (req.body.describe) profileFields.describe = req.body.describe;if (req.body.income) profileFields.income = req.body.income;if (req.body.expend) profileFields.expend = req.body.expend;if (req.body.cash) profileFields.cash = req.body.cash;if (req.body.remark) profileFields.remark = req.body.remark;new Profile(profileFields).save().then((profile) => {res.json(profile);}).catch(err => {res.status(500).json(err);})})(req, res, next);
})/*** 获取所有信息* POST api/profiles*/
router.get( '/', passport.authenticate('jwt', { session: false }), (req, res) => {Profile.find().then((profiles) => {if (!profiles || profiles.length === 0) return res.status(404).json({ error: '数据为空!' })const profileData = { profiles: profiles }res.json(profileData)}).catch((err) => res.status(404).json(err));}
);
module.exports = router

获取单个信息的接口也很简单,只需要在路径拼接上id,id后面前端传递给我们即可:

/*** 获取单个信息* POST api/profiles/:id*/
router.get('/:id', passport.authenticate('jwt', { session: false }), (req, res) => {Profile.findOne({ _id: req.params.id }).then((profile) => {if (!profile) return res.status(404).json({ error: '数据为空!' });res.json(profile);}).catch((err) => res.status(404).json(err));
});

通过Apifox测试的结果如下:

编辑和删除信息

编辑信息接口和添加信息接口写法大体一致,如下:

/*** 编辑信息接口* POST api/profiles/edit*/
router.post("/edit/:id", passport.authenticate("jwt", { session: false }), (req, res) => {const profileFields = {};if (req.body.type) profileFields.type = req.body.type;if (req.body.describe) profileFields.describe = req.body.describe;if (req.body.income) profileFields.income = req.body.income;if (req.body.expend) profileFields.expend = req.body.expend;if (req.body.cash) profileFields.cash = req.body.cash;if (req.body.remark) profileFields.remark = req.body.remark;Profile.findOneAndUpdate({ _id: req.params.id },{ $set: profileFields },{ new: true }).then(profile => res.json(profile))}
)

删除信息的接口也很简单:

/*** 删除信息* POST api/profiles/:id*/
router.delete('/delete/:id', passport.authenticate('jwt', { session: false }), (req, res) => {Profile.findOneAndDelete({ _id: req.params.id }).then(profile => {res.json(profile);}).catch(err => res.status(404).json('删除失败'));    
});

表示删除成功!

ok!后端的一些基础代码已经写完了,下一篇将借助这些接口开始前端页面的书写了,等前后端项目全部写完,我再将源码开源出来,敬请期待!!!

相关文章:

Node.js--》简易资金管理系统后台项目实战(后端)

今天开始使用 node vue3 ts搭建一个简易资金管理系统的前后端分离项目,因为前后端分离所以会分两个专栏分别讲解前端与后端的实现,后端项目文章讲解可参考:前端链接,我会在前后端的两类专栏的最后一篇文章中会将项目代码开源到我…...

执行autoreconf -fi的过程报错

https://xie.infoq.cn/article/6bba9dd34fb49b7adacb4aacd https://github.com/curl/curl/blob/master/docs/HTTP3.md#quiche-version curl配置quiche的过程中报错, configure:7902: error: possibly undefined macro: AC_LIBTOOL_WIN32_DLLIf this token and ot…...

GPT-3 内幕机制可视化解析

GPT-3 内幕机制可视化解析 GPT-3是一个基于Transformer的语言模型,通过不同的层次提取语言不同层面的特性,构建整个语言的语义信息,它学习的过程跟人类正常学习的过程是类似的,开始的时候是一个无监督预训练,如图5-5所示,GPT-3模型可以将网络上的所有文档下载下来,包含 …...

Linux命令行安装图形化界面

Linux命令行安装图形化界面 安装CentOS默认安装没有配置图形化界面,如何在命令行进行安装图形化界面? 首先要以root用户登录,输入用户名和密码。 切换root用户命令: su root ​ 查看ip地址和网卡编号。 ip addr show 知道网卡编号…...

Rust逆向学习 (2)

文章目录 Guess a number0x01. Guess a number .part 1line 1loopline 3~7match 0x02. Reverse for enum0x03. Reverse for Tuple0x04. Guess a number .part 20x05. 总结 在上一篇文章中,我们比较完美地完成了第一次Rust ELF的逆向工作,但第一次编写的R…...

Flink部署模式及核心概念

一.部署模式 1.1会话模式(Session Mode) 需要先启动一个 Flink 集群,保持一个会话,所有提交的作业都会运行在此集群上,且启动时所需的资源以确定,无法更改,所以所有已提交的作业都会竞争集群中…...

Pytorch公共数据集、tensorboard、DataLoader使用

本文将主要介绍torchvision.datasets的使用,并以CIFAR-10为例进行介绍,对可视化工具tensorboard进行介绍,包括安装,使用,可视化过程等,最后介绍DataLoader的使用。希望对你有帮助 Pytorch公共数据集 torc…...

【第三天】C++类和对象进阶指南:从堆区空间操作到友元的深度掌握

一、new和delete 堆区空间操作 1、new和delete操作基本类型的空间 new与C语言中malloc、delete和C语言中free 作用基本相同 区别: new 不用强制类型转换 new在申请空间的时候可以 初始化空间内容 2、 new申请基本类型的数组 3、new和delete操作类的空间 4、new申请…...

【PyTorch实战演练】自调整学习率实例应用(附代码)

目录 0. 前言 1. 自调整学习率的常用方法 1.1 ExponentialLR 指数衰减方法 1.2 CosineAnnealingLR 余弦退火方法 1.3 ChainedScheduler 链式方法 2. 实例说明 3. 结果说明 3.1 余弦退火法训练过程 3.2 指数衰减法训练过程 3.3 恒定学习率训练过程 3.4 结果解读 4. …...

app拉新渠道整合 一手地推、网推拉新平台整理

1.聚量推客 聚量推客自己本身是服务商,自己直营的平台,相对来说数据更好,我们也拿到了平台首码:000000 填这个就行,属于官方渠道 2.蓝猫推客 蓝猫推客我认为是比较又潜力的平台,经过几天测试数据和结算都…...

十六进制IP转换点分十进制代码

以下是一个可以实现将输入的十六进制格式的IP地址转换为点分十进制格式并输出的简单程序。它使用了 sscanf 函数将输入的字符串解析成无符号整数&#xff0c;然后使用 inet_ntoa 函数将其转换成点分十进制格式&#xff0c;并打印输出&#xff1a; #include <stdio.h> #i…...

面试官的一句话,让五年功能测试老手彻夜难眠!

小王是一名软件测试工程师&#xff0c;已经在目前的公司做了四五年的功能测试。虽然一直表现得非常努力&#xff0c;但他还是没能躲过裁员。只能被动跳槽&#xff0c;寻找更好的职业机会。 然而事情并没有像他想象中那样顺利。在多次面试中小王屡屡碰壁&#xff0c;被面试官吐槽…...

向量检索库Milvus架构及数据处理流程

文章目录 背景milvus想做的事milvus之前——向量检索的一些基础近似算法欧式距离余弦距离 常见向量索引1&#xff09; FLAT2&#xff09; Hash based3&#xff09; Tree based4&#xff09; 基于聚类的倒排5&#xff09; NSW&#xff08;Navigable Small World&#xff09;图 向…...

【华为路由器】配置企业通过5G链路接入Internet示例

场景介绍 5G Cellular接口是路由器用来实现5G技术的物理接口&#xff0c;它为用户提供了企业级的无线广域网接入服务&#xff0c;主要用于eMBB场景。与LTE相比&#xff0c;5G系统可以为企业用户提供更大带宽的无线广域接入服务。 路由器的5G功能&#xff0c;可以实现企业分支…...

python安装.whl文件

python --version https://www.lfd.uci.edu/~gohlke/pythonlibs/ 用CtrlF找需要安装的包 下载对应版本的whl python3.8 把下载好的whl放到安装路径下&#xff1a;C:\Users\Administrator\AppData\Local\Programs\Python\Python38\Lib\site-packages 并在该路径下打开cmd执行…...

Java方法调用动态绑定(多态性)详解

CONTENTS 1. 方法调用绑定2. 尝试重写Private方法3. 字段访问与静态方法的多态4. 构造器内部的多态方法行为 1. 方法调用绑定 我们首先来看下面这个例子&#xff1a; package com.yyj;enum Tone {LOW, MIDDLE, HIGH; }class Instrument {public void play(Tone t) {System.ou…...

【SwiftUI模块】0060、SwiftUI基于Firebase搭建一个类似InstagramApp 2/7部分-搭建TabBar

SwiftUI模块系列 - 已更新60篇 SwiftUI项目 - 已更新5个项目 往期Demo源码下载 技术:SwiftUI、SwiftUI4.0、Instagram、Firebase 运行环境: SwiftUI4.0 Xcode14 MacOS12.6 iPhone Simulator iPhone 14 Pro Max SwiftUI基于Firebase搭建一个类似InstagramApp 2/7部分-搭建Tab…...

代码随想录第50天 | 84.柱状图中最大的矩形

84.柱状图中最大的矩形 //双指针 js中运行速度最快 var largestRectangleArea function(heights) {const len heights.length;const minLeftIndex new Array(len);const maxRigthIndex new Array(len);// 记录每个柱子 左边第一个小于该柱子的下标minLeftIndex[0] -1; //…...

深度学习---卷积神经网络

卷积神经网络概述 卷积神经网络是深度学习在计算机视觉领域的突破性成果。在计算机视觉领域。往往输入的图像都很大&#xff0c;使用全连接网络的话&#xff0c;计算的代价较高。另外图像也很难保留原有的特征&#xff0c;导致图像处理的准确率不高。 卷积神经网络&#xff0…...

Windows系统下安装CouchDB3.3.2教程

安装 前往CouchDB官网 官网点击download下载msi文件 双击该msi文件&#xff0c;一直下一步 创建个人account 设置cookie value 用于进行身份验证和授权。 愉快下载 点击OK 重启 启动 重启电脑后 打开浏览器并访问以下链接&#xff1a;http://127.0.0.1:5984/ 如果没有问…...

Chapter03-Authentication vulnerabilities

文章目录 1. 身份验证简介1.1 What is authentication1.2 difference between authentication and authorization1.3 身份验证机制失效的原因1.4 身份验证机制失效的影响 2. 基于登录功能的漏洞2.1 密码爆破2.2 用户名枚举2.3 有缺陷的暴力破解防护2.3.1 如果用户登录尝试失败次…...

Flask RESTful 示例

目录 1. 环境准备2. 安装依赖3. 修改main.py4. 运行应用5. API使用示例获取所有任务获取单个任务创建新任务更新任务删除任务 中文乱码问题&#xff1a; 下面创建一个简单的Flask RESTful API示例。首先&#xff0c;我们需要创建环境&#xff0c;安装必要的依赖&#xff0c;然后…...

【Redis技术进阶之路】「原理分析系列开篇」分析客户端和服务端网络诵信交互实现(服务端执行命令请求的过程 - 初始化服务器)

服务端执行命令请求的过程 【专栏简介】【技术大纲】【专栏目标】【目标人群】1. Redis爱好者与社区成员2. 后端开发和系统架构师3. 计算机专业的本科生及研究生 初始化服务器1. 初始化服务器状态结构初始化RedisServer变量 2. 加载相关系统配置和用户配置参数定制化配置参数案…...

GitHub 趋势日报 (2025年06月08日)

&#x1f4ca; 由 TrendForge 系统生成 | &#x1f310; https://trendforge.devlive.org/ &#x1f310; 本日报中的项目描述已自动翻译为中文 &#x1f4c8; 今日获星趋势图 今日获星趋势图 884 cognee 566 dify 414 HumanSystemOptimization 414 omni-tools 321 note-gen …...

Redis数据倾斜问题解决

Redis 数据倾斜问题解析与解决方案 什么是 Redis 数据倾斜 Redis 数据倾斜指的是在 Redis 集群中&#xff0c;部分节点存储的数据量或访问量远高于其他节点&#xff0c;导致这些节点负载过高&#xff0c;影响整体性能。 数据倾斜的主要表现 部分节点内存使用率远高于其他节…...

人工智能(大型语言模型 LLMs)对不同学科的影响以及由此产生的新学习方式

今天是关于AI如何在教学中增强学生的学习体验&#xff0c;我把重要信息标红了。人文学科的价值被低估了 ⬇️ 转型与必要性 人工智能正在深刻地改变教育&#xff0c;这并非炒作&#xff0c;而是已经发生的巨大变革。教育机构和教育者不能忽视它&#xff0c;试图简单地禁止学生使…...

探索Selenium:自动化测试的神奇钥匙

目录 一、Selenium 是什么1.1 定义与概念1.2 发展历程1.3 功能概述 二、Selenium 工作原理剖析2.1 架构组成2.2 工作流程2.3 通信机制 三、Selenium 的优势3.1 跨浏览器与平台支持3.2 丰富的语言支持3.3 强大的社区支持 四、Selenium 的应用场景4.1 Web 应用自动化测试4.2 数据…...

淘宝扭蛋机小程序系统开发:打造互动性强的购物平台

淘宝扭蛋机小程序系统的开发&#xff0c;旨在打造一个互动性强的购物平台&#xff0c;让用户在购物的同时&#xff0c;能够享受到更多的乐趣和惊喜。 淘宝扭蛋机小程序系统拥有丰富的互动功能。用户可以通过虚拟摇杆操作扭蛋机&#xff0c;实现旋转、抽拉等动作&#xff0c;增…...

破解路内监管盲区:免布线低位视频桩重塑停车管理新标准

城市路内停车管理常因行道树遮挡、高位设备盲区等问题&#xff0c;导致车牌识别率低、逃费率高&#xff0c;传统模式在复杂路段束手无策。免布线低位视频桩凭借超低视角部署与智能算法&#xff0c;正成为破局关键。该设备安装于车位侧方0.5-0.7米高度&#xff0c;直接规避树枝遮…...

libfmt: 现代C++的格式化工具库介绍与酷炫功能

libfmt: 现代C的格式化工具库介绍与酷炫功能 libfmt 是一个开源的C格式化库&#xff0c;提供了高效、安全的文本格式化功能&#xff0c;是C20中引入的std::format的基础实现。它比传统的printf和iostream更安全、更灵活、性能更好。 基本介绍 主要特点 类型安全&#xff1a…...