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

利用node.js搭配express框架写后端接口(一)

Node.js 凭借其高效的非阻塞 I/O 操作、事件驱动架构以及轻量级的特点,成为了开发高性能服务器应用的热门选择。Express 框架作为 Node.js 上最流行的 Web 应用框架之一,以其简洁的 API 和丰富的中间件生态系统,极大地简化了 Web 后端开发流程。本文将引导你如何使用 Node.js 和 Express 框架构建一个简单的后端接口。

目录

一、初始化项目

1.创建项目

2.配置cors跨域

3.配置解析表单数据的中间件

4.初始化路由相关的文件夹

 5.初始化用户路由模块

6.抽离用户路由模块中的处理函数

二、新建数据库表

1.新建数据库

2.新建表

三、安装并配置MySQL模块

1.安装MySQL模块

2.连接数据库

四、登录、注册

1.注册

1.1检测表单数据是否合法

1.2检测用户名是否被占用

1.3对密码进行加密处理

1.4插入新用户

1.5优化res.send()代码

1.6优化表单数据验证

2.登录

 2.1检测登录表单的数据是否合法

2.2根据用户名查询用户的数据

2.3判断用户输入的密码是否正确

2.4生成jwt的token字符串

2.5配置解析token的中间件


一、初始化项目

1.创建项目

新建一个文件夹作为项目的根目录,并在项目根目录中运行如下命令,初始化包的管理配置文件:

npm i express@4.17.1

然后在项目中新建app.js作为整个项目的入口文件,并初始化如下代码:

//导入express
const express = require('express')
//创建服务器对象
const app = express() 
//启动服务器
app.listen(3007, () => {console.log('api server htttp://127.0')
})

2.配置cors跨域

在文件夹的终端运行如下的命令,安装cors中间件:

npm i cors@2.8.5

然后再app.js中导入并配置cors中间件:

//导入并配置cors中间件
const cors = require('cors')
app.use(cors())

3.配置解析表单数据的中间件

通过使用如下代码,配置解析application/x-www-form-urlencoded格式的表单数据的中间件:

//配置解析表单数据的中间件--注意:只能解析application/x-www-from-urlencoded格式的表单数据的中间件
app.use(express.urlencoded({extended:false}))

4.初始化路由相关的文件夹

(1)在项目的根目录中,新建router文件夹,用来存放所有的路由模块。路由模块中,只存放客户端的请求与处理函数之间的映射关系。

 (2)在项目的根目录中,新建router_handler文件夹,用来存放所有的路由处理函数模块,这里专门负责存放每个路由对应的处理函数。

 5.初始化用户路由模块

在router文件夹中,新建user.js文件,作为用户的路由模块,代码如下:

const express = require('express')
//创建路由对象
const router = express.Router()//注册新用户
router.post('/register', (req, res) => { res.send('注册成功')
})//登录
router.post('/login', (req, res) => { res.send('登录成功')
})//导出路由对象
module.exports = router

在app.js中导入并使用该用户路由模块

//导入并注册用户路由模块
const userRouter = require('./routes/user')
app.use('/api', userRouter)

6.抽离用户路由模块中的处理函数

为了保证路由模块的纯粹性,所有的路由处理函数,必须抽离到对应的路由处理函数模块中。

在router_handler/user.js文件中,使用exports对象,分别向外共享如下两个路由处理函数:

//注册用户的处理函数
exports.regUser = (req, res) => {res.send('注册成功')
}
//登录的处理函数
exports.login = (req, res) => {res.send('登录成功')
}

将router/user.js文件中的代码修改如下结构

const express = require('express')
//创建路由对象
const router = express.Router()//打入用户路由处理函数模块
const userHandler = require('./router_handler/user')//注册新用户---原
// router.post('/register', (req, res) => { 
//     res.send('注册成功')
// })
//注册新用户--新
router.post('/register',userHandler.regUser )//登录----原
// router.post('/login', (req, res) => { 
//     res.send('登录成功')
// })
//登录---新
router.post('/login',userHandler.login)//导出路由对象
module.exports = router

二、新建数据库表

在创建库表之前确保已经安装了数据库。

1.新建数据库

2.新建表

在新建的test_mysql数据库中,新建ev_users表 。点击新建查询,输入一下SQL语句

use test_mysql;
CREATE TABLE ev_users
(id INT NOT NULL AUTO_INCREMENT,username VARCHAR(255) NOT NULL,password VARCHAR(255) NOT NULL,nickname VARCHAR(255),email VARCHAR(255),user_pic TEXT,PRIMARY KEY (id)
)

然后点击旁边的运行,下方如果出现OK,就表示创建成功

 然后在表那边点击刷新就可以看见新创建的表了

三、安装并配置MySQL模块

在api接口项目中,需要安装并配置MySQL这个第三方模块,俩连接和操作MySQL数据库

1.安装MySQL模块

在根目录的终端中运行如下命令:

npm i mysql@2.18.1

2.连接数据库

在项目中的根目录下新建db文件夹,并在其下方新建index.js文件,在此文件中创建数据库的连接对象

//导入MySQL模块
const mysql = require('mysql')
//创建数据库连接对象
const db = mysql.createPool({host: '127.0.0.1',       // 数据库主机名user: '你的数据库用户名',            // 数据库用户名password: '你的数据库密码', // 数据库密码database: 'test_mysql' // 数据库名
})
// 导出连接池
module.exports = db;

四、登录、注册

1.注册

1.1检测表单数据是否合法

在router_handle/user.js这个文件中判断用户名和密码是否为空,具体代码如下:

//注册用户的处理函数
exports.regUser = (req, res) => {//获取客户端提交到服务器的用户信息const userInfo = req.body// console.log(userInfo, '这个信息是:')//对表单中的数据,进行合法的校验if (!userInfo.username || !userInfo.password) {return res.send({code: 404,message: 'fail',detail:'用户名或密码不合法'})}
}

1.2检测用户名是否被占用

(1)导入数据库操作模块

在router_handle/user.js这个文件中导入数据库模块

//导入数据库
const db = require('../db/index')

(2)定义SQL语句

//定义SQL语句,查询用户名是否被占用const sqlStr='select * from ev_users where username=?'

(3)执行SQL语句并根据结果判断用户名是否被占用

db.query(sqlStr, userInfo.username, (err, results) => {//执行SQL语句失败if (err) {return res.send({code:500,message: 'fail',detail:err.message})}//判断用户名是否被占用if (results.length > 0) {return res.send({code:409,message: 'fail',detail:'用户名被占用,请更换其他用户名'})}})

1.3对密码进行加密处理

为了保证密码的安全性,不建议在数据库以明文的形式保存用户密码,推荐对密码进行加密存储。

在当前所做项目中,使用bcryptjs对用户密码进行加密,优点在于:

  • 加密之后的密码,无法被逆向破解;
  • 同一明文密码多次加密,得到的加密结果各不相同,保证了安全性。

(1)安装bcryptjs

在项目终端运行如下命令:

npm i bcryptjs@2.4.3

 (2)导入bcryptjs

在router_handle/user.js这个文件中导入bcryptjs

//导入bcryptjs
const bcrypt=require('bcryptjs')

(3)使用bcryptjs

在注册用户的处理函数中,确认用户名可用之后,调用bcrypt.hashSync(明文密码,随机盐的长度)方法,对用户的密码进行加密处理:

//调用bcryptjs-hashSync()对密码进行加密console.log(userInfo,'加密前:')userInfo.password = bcrypt.hashSync(userInfo.password, 10)console.log(userInfo,'加密后:')

1.4插入新用户

(1)定义插入用户的SQL语句

 //定义插入新用户的SQL语句const sql='insert into ev_users set ?'

(2)调用db.query()执行SQL语句,插入新用户

//调用db.query()执行SQL语句db.query(sql, { username: userInfo.username, password: userInfo.password }, (err, results) => {//判断SQL语句是否执行成功if (err) {return res.send({code:500,message: 'fail',detail:err.message})}//判断影响函数是否为1if (results.affectedRows != 1) {return res.send({code: 500,message: 'fail',detail:'注册用户失败,请稍后再试'})} else {return res.send({code: 200,message: 'success',detail:'注册成功'})}})

1.5优化res.send()代码

在以上的处理函数中我们可以发现,需要多次调用到res.send()向客户端响应处理失败的结果,为了简化以上代码,这里重新封装了一个res.trans()函数。

在app.js中,所有路由之前,声明一个全局中间件,为res对象挂载一个res.trans()函数

//封装res.trans
app.use((req, res, next) => {//code默认值为500,表示失败的情况//err可能是一个错误对象,也可能是一个错误的描述字符串res.trans = (err,code=500) => {res.send({code,message: 'fail',detail:err instanceof Error?err.detail:err})}next()
})

在router_handle/user.js这个文件中有关注册这个处理函数进行重新修改

//注册用户的处理函数
exports.regUser = (req, res) => {//获取客户端提交到服务器的用户信息const userInfo = req.body// console.log(userInfo, '这个信息是:')//对表单中的数据,进行合法的校验if (!userInfo.username || !userInfo.password) {// return res.send({//     code: 400,//     message: 'fail',//     detail: '用户名或密码不合法'// })return res.trans('用户名或密码不合法',400)}// } else {//     return res.send({//         code: 200,//         message: 'success',//         detail:''//     })// }//定义SQL语句,查询用户名是否被占用const sqlStr='select * from ev_users where username=?'db.query(sqlStr, userInfo.username, (err, results) => {//执行SQL语句失败if (err) {//原--未封装// return res.send({//     code:500,//     message: 'fail',//     detail:err.message// })//现--分装后return res.trans(err)}//判断用户名是否被占用if (results.length > 0) {//原--未封装// return res.send({//     code:409,//     message: 'fail',//     detail:'用户名被占用,请更换其他用户名'// })//现--分装后return res.trans('用户名被占用,请更换其他用户名',409)}//调用bcryptjs-hashSync()对密码进行加密// console.log(userInfo,'加密前:')userInfo.password = bcrypt.hashSync(userInfo.password, 10)// console.log(userInfo, '加密后:')//定义插入新用户的SQL语句const sql = 'insert into ev_users set ?'//调用db.query()执行SQL语句db.query(sql, { username: userInfo.username, password: userInfo.password }, (err, results) => {//判断SQL语句是否执行成功if (err) {// return res.send({//     code:500,// message: 'fail',// detail:err.message// })//现--分装后return res.trans(err)}//判断影响函数是否为1if (results.affectedRows != 1) {// return res.send({//     code: 500,//     message: 'fail',//     detail:'注册用户失败,请稍后再试'// })//现--分装后return res.trans('注册用户失败,请稍后再试')} else {return res.send({code: 200,message: 'success',detail:'注册成功'})}})})
}

1.6优化表单数据验证

表单验证的原则:前端验证为辅,后端验证为主,后端不能相信前端提交过来的任何内容。在实际开发中,前后端都需要对表单的数据进行合法性的验证,而且,后端做为数据合法性验证的最后一个关口,在拦截非法数据方面,起到了至关重要的作用。
单纯的使用 if...e1se...的形式对数据合法性进行验证,效率低下、出错率高、维护性差。因此,推荐使用第三方数据验证模块,来降低出错率、提高验证的效率与可维护性,让后端程序员把更多的精力放在核心业务逻辑的处理上。

(1)安装joi包,为表单中携带的每个数据项,定义验证规则

npm i joi

(2)安装@escook/express-joi中间件,来实现自动对表单数据进行验证的功能

npm i @escook/express-joi

(3)新建/schema/user.js用户信息验证规则模块,并初始化代码

//导入joi
const joi = require('joi')
/*** string 值必须是字符串* alphanum 值只能是包含a-zA-Z0-9的字符串* min(length)最小长度* max(length)最大长度* required() 值是必填项,不能为undefined* pattern(正则表达式) 值必须符合正则表达式的规则*/
//定义用户名和密码的验证
const username = joi.string().alphanum().min(1).max(10).required()
const password = joi.string().pattern(/^[\S]{6,12}$/).required()//定义验证注册和登录表单数据的规则对象
exports.reg_login_schema = {body: {username,password}
}

(4)修改router/user.js中的代码

const express = require('express')
//创建路由对象
const router = express.Router()//打入用户路由处理函数模块
const userHandler = require('../router_handler/user')//导入验证数据的中间件
const expressJoi = require('@escook/express-joi')
//导入需要的验证规则对象
const {reg_login_schema} = require('../schema/user')//注册新用户--新
//1.在注册新用户的路由中,声明局部中间件,对当前请求中携带的数据进行验证
//2.数据验证通过后,会把这次请求流转给后面的路由处理函数
//3.数据验证失败后,终止后端代码的执行,并抛出一个全局的error错误,进入全局错误级别中间件中进行处理
router.post('/register',expressJoi(reg_login_schema),userHandler.regUser )//登录---新
router.post('/login',userHandler.login)//导出路由对象
module.exports = router

(5)在app.js的全局错误级别中间件中,捕获验证失败的错误,并把验证失败的结果响应给客户端

//导入joi
const joi = require('joi')
//中间部分的省略//定义错误级别的中间件
app.use((err, req, res) => {//验证失败导致的错误if (err instanceof joi.ValidationError) {return res.trans(err)}//未知的错误res.trans(err)})

(6)在router_handler/user.js文件中,注册用户处理函数这一块注释掉下面的代码

// if (!userInfo.username || !userInfo.password) {//     return res.trans('用户名或密码不合法',400)// }

2.登录

2.1检测登录表单的数据是否合法

将router/user.js中登录的路由代码修改如下

//登录---新
router.post('/login',expressJoi(reg_login_schema),userHandler.login)

2.2根据用户名查询用户的数据

(1)接收表单数据

//获取客户端提交到服务器的用户信息const userInfo = req.body

(2)定义SQL语句

//定义SQL语句,查询用户名是否被占用const sqlStr='select * from ev_users where username=?'

(3)执行SQL语句,查询用户的数据

db.query(sqlStr, userInfo.username, (res, results) => {//执行SQL语句失败if (err) {return res.trans(err)}//执行SQL语句成功,但是查询到数据条数不等于1if (results.length != 1) {return res.trans('登录失败')}})

2.3判断用户输入的密码是否正确

核心:调用bcrypt.compareSync(用户提交的密码,数据库中的密码)方法比较密码是否一致。

 db.query(sqlStr, userInfo.username, (err, results) => {//执行SQL语句失败if (err) {return res.trans(err)}//执行SQL语句成功,但是查询到数据条数不等于1if (results.length != 1) {return res.trans('登录失败',405)}//用户输入的密码和数据库中存储的密码进行对比const compareResult = bcrypt.compareSync(userInfo.password, results[0].password)console.log('这是:',compareResult,results[0].password,userInfo.password)//如果对比的结果等于false,则证明用户输入的密码错误if (!compareResult) {return res.trans('登录失败',400)} res.send('ok')})

2.4生成jwt的token字符串

注意:在生成token字符串的时候,一定要提出密码和头像的值

(1)通过es6的高级语法,快速剔除密码和头像的值,该代码书写于上述对比输入密码语句之后

//在服务器端生成token字符串const user = { ...results[0] ,password:'',user_pic:''}console.log(user,'这是:')

(2)安装生成token字符串的包

npm i jsonwebtoken

(3)在router_handler/user.js文件的头部区域,导入jsonwebtoken包

//导入生成的token包
const jwt=require('jsonwebtoken')

(4)创建config.js文件,并向外共享加密和还原token的jwtSecretKey字符串

module.exports = {//加密和解密的token密钥jwtSecretKey: 'test',//token有效期expiresIn:'10h'
}

(5)将用户信息对象加密成token字符串

//导入密钥配置文件
const config=require('../config.js')//对用户的信息进行加密,生成token字符串
const tokenStr = jwt.sign(user, config.jwtSecretKey, { expiresIn: config.expiresIn })
console.log('这是:', tokenStr)

(6)将生成的token字符串响应给客户端

 //调用res.send()将token响应给客户端res.send({code: 200,message: 'success',token: 'Bearer '+tokenStr,detail:'登
})

2.5配置解析token的中间件

(1)安装解析token的中间件

npm i express-jwt@5.3.3

(2)在app.js中注册路由之前,配置解析token的中间件

//一定要在路由之前配置解析token的中间件
const { expressJwt } = require('express-jwt')
const config = require('./config')
app.use(expressJwt({ secret: config.jwtSecretKey}).unless({path:[/^\/api/]}))

(3)在app.js中的错误级别中间件中,铺货并处理token认证失败后的错误

//定义错误级别的中间件---暂不使用
app.use((err, req, res,next) => {//验证失败导致的错误// if (err instanceof joi.ValidationError) return res.trans(err)if(err.name==='UnauthorizedError') return res.trans('身份认证失败',401)// //未知的错误res.trans(err)    
})

相关文章:

利用node.js搭配express框架写后端接口(一)

Node.js 凭借其高效的非阻塞 I/O 操作、事件驱动架构以及轻量级的特点,成为了开发高性能服务器应用的热门选择。Express 框架作为 Node.js 上最流行的 Web 应用框架之一,以其简洁的 API 和丰富的中间件生态系统,极大地简化了 Web 后端开发流程…...

CentOS中shell脚本对多台机器执行下载安装

1.建立免密ssh连接 详情见这篇: CentOS建立ssh免密连接(含流程剖析)-CSDN博客 2.脚本编写 我这里只是简单写了个demo进行演示,如果服务器很多可以先暂存成文件再逐行读取host进行连接并执行命令 用node1去ssh连接node2和node…...

Go 语言内存池 (`sync.Pool`) 深度解析

Go 语言内存池 (sync.Pool) 深度解析 在高并发和性能敏感的应用中,频繁的内存分配和释放会带来显著的性能开销,并增加垃圾回收(GC)的压力。Go 语言通过 sync.Pool 提供了一种高效的对象复用机制,能够显著减少内存分配…...

深入剖析:自定义实现C语言中的atoi函数

在C语言的标准库中, atoi 函数是一个非常实用的工具,它能够将字符串形式的数字转换为对应的整数。然而,当我们深入探究其实现原理时,会发现其中蕴含着许多有趣的编程技巧和细节。本文将详细讲解如何自定义实现一个类似 atoi 功能的…...

Flutter 学习之旅 之 flutter 在 Android 端读取相册图片显示

Flutter 学习之旅 之 flutter 在 Android 端读取相册图片显示 目录 Flutter 学习之旅 之 flutter 在 Android 端读取相册图片显示 一、简单介绍 二、简单介绍 image_picker 三、安装 image_picker 四、简单案例实现 五、关键代码 代码说明: 一、简单介绍 Fl…...

数据结构秘籍(一)线性数据结构

1.数组 数组(Array)是一种很常见的数据结构。它由相同类型的元素(element)组成,并且是使用一块连续的内存来存储。 我们直接可以利用元素的索引(index)计算出该元素对应的存储地址。 数组的特…...

推荐律师事务管理系统(SpringCloud+mysql+rocketmq+deepseek)

1.深圳慧钛科技有限公司成立于2024年7月24日,官网地址:深圳慧钛律师事务管理系统(官网)-案件管理系统-律所档案管理-律所管理软件-律师办案系统-电子签章-律所印章-律师办公软件、律师办公系统、律所OA 。系统访问地址:深圳慧钛律…...

mysql怎样优化where like ‘%字符串%‘这种模糊匹配的慢sql

一 问题描述 工作中经常遇到这种模糊匹配的慢sql: select * from 表名 where 字段 like %字符串%; 由于前面有%,导致无法走该字段上的索引。 二 解决办法 ① 给该字段创建一个全文索引 CREATE FULLTEXT INDEX 索引名 ON 表名 (字段名); ② 改写sq…...

SpringSecurity基于JWT实现Token的处理

前面介绍了手写单点登录和JWT的应用,本文结合SpringSecurity来介绍下在SpringBoot项目中基于SpringSecurity作为认证授权框架的情况下如何整合JWT来实现Token的处理。 一、认证思路分析 SpringSecurity主要是通过过滤器来实现功能的!我们要找到SpringSecurity实现认证和校验…...

让AI“看见”光影变幻!华为云专利解锁动态光源渲染新境界

华为云计算技术有限公司(申请人,申请号:202311653495.3)通过一项创新专利,首次实现隐式对象模型与显式渲染管线深度融合,让动态光源下的图像渲染真实度与灵活性兼得! 一、技术深度解析 技术背景…...

Linux(centos)系统安装部署MySQL8.0数据库(GLIBC版本)

前言 MySQL 是一款开源的关系型数据库管理系统(RDBMS),主要用于‌结构化数据的存储、管理和检索‌。 一、检查环境 安装前检查服务器glibc版本,下载对应版本包 rpm -qa | grep glibc mysql安装包及依赖包已整理好&#xff0c…...

Redis缓存一致性难题:如何让数据库和缓存不“打架”?

标题:Redis缓存一致性难题:如何让数据库和缓存不“打架”?(附程序员脱发指南) 导言:当数据库和缓存成了“异地恋” 想象一下:你刚在美团下单了一份麻辣小龙虾,付款后刷新页面&#…...

【R包】pathlinkR转录组数据分析和可视化利器

介绍 通常情况下,基因表达研究如微阵列和RNA-Seq会产生数百到数千个差异表达基因(deg)。理解如此庞大的数据集的生物学意义变得非常困难,尤其是在分析多个条件和比较的情况下。该软件包利用途径富集和蛋白-蛋白相互作用网络&…...

PyCharm 的使用 + PyCharm快捷键 + 切换中文界面

2025 - 02 - 27 - 第 62 篇 Author: 郑龙浩 / 仟濹 【PyCharm的使用】 文章目录 如何使用Pycharm1 新建工程,新建 .py 文件,运行2 常用快捷键3 其他快捷键 - DeepSeek 总结如下**代码编辑****导航与定位****查找与替换****运行与调试****代码重构****其…...

1.68M 免安装多格式图片批量转 webp 无广告软件推荐

软件介绍 今天要给大家分享一款超实用的图片处理工具,它能实现多格式图片向 webp 格式的转换,无论是 jpg、png、tif、gif 还是 webp 格式自身的图片,都能批量且借助多线程技术进行转换。 直接打开就能用,体积小巧,仅 …...

总结gcc与msvc在标准库实现上的不同

1. std::string::data()的返回类型区别 在C17以及之前的标准中,std::string::data()仅有一个返回类型const char *,MSVC遵守了这个规定。而GCC很早就有非标准扩展,重载了一个 char *data() noexcept;C20标准引入了这个非标准扩展。...

《Qt窗口动画实战:Qt实现呼吸灯效果》

Qt窗口动画实战:Qt实现呼吸灯效果 在嵌入式设备或桌面应用中,呼吸灯效果是一种常见且优雅的UI动画,常用于指示系统状态或吸引用户注意。本文将介绍如何使用Qt动画框架实现平滑的呼吸灯效果。 一、实现原理 利用Qt自带的动画框架来实现&…...

Rider 安装包 绿色版 Win/Mac/Linux 适合.NET和游戏开发者使用 2025全栈开发终极指南:从零配置到企业级实战

下载链接: https://pan.baidu.com/s/1cfkJf6Zgxc1XfYrVpwtHkA?pwd1234 导语:JetBrains Rider以跨平台支持率100%、深度.NET集成和智能代码分析能力,成为2025年全栈开发者的首选工具。本文涵盖环境配置、核心功能、框架集成、性能调优、团队…...

CVE-2025-1094: 通过 WebSocket 的 SQL 注入到 RCE

该存储库包含一个针对 CVE-2025-1094 的概念验证(PoC)漏洞利用,该漏洞存在于 PostgreSQL 中,允许通过 WebSocket 劫持将 SQL 注入(SQLi)攻击升级为远程代码执行(RCE)。 概述 该漏洞利用 PostgreSQL 中的 SQL 注入漏洞,注入恶意代码读取敏感文件(如 /etc/passwd),…...

详解Tomcat下载安装以及IDEA配置Tomcat(2023最新)

目录 步骤一:首先确认自己是否已经安装JDK步骤二:下载安装Tomcat步骤三:Tomcat配置环境变量步骤四:验证Tomcat配置是否成功步骤五:为IDEA配置Tomcat 步骤一:首先确认自己是否已经安装JDK jdk各版本通用安…...

AI如何通过大数据分析提升制造效率和决策智能化

人工智能(AI)与大数据技术的融合,不仅重新定义了生产流程,更让企业实现了从“经验驱动”到“数据智能驱动”的跨越式升级。 从“模糊经验”到“精准洞察”​​ 传统制造业依赖人工经验制定生产计划,但面对复杂多变的市…...

开源程序wordpress在海外品牌推广中的重要作用

WordPress作为全球最流行的开源内容管理系统(CMS),在全球网站搭建中占据超过40%的市场份额。其强大的功能、灵活性和易用性使其成为企业进行海外品牌推广的首选平台。以下是WordPress在海外品牌推广中的重要性分析: 1. 多语言支持与本地化 WordPress通…...

kafka-关于ISR-概述

一. 什么是ISR ? Kafka 中通常每个分区都有多个副本,其中一个副本被选举为 Leader,其他副本为 Follower。ISR 是指与 Leader 副本保持同步的 Follower 副本集合。ISR 机制的核心是确保数据在多个副本之间的一致性和可靠性,同时在 …...

Android 8.0 (API 26) 对广播机制做了哪些变化

大部分隐式广播无法通过静态注册接收,除了以下白名单广播: ACTION_BOOT_COMPLETED ACTION_TIMEZONE_CHANGED ACTION_LOCALE_CHANGED ACTION_MY_PACKAGE_REPLACED ACTION_PACKAGE_ADDED ACTION_PACKAGE_REMOVED 需要以动态注册方案替换: cl…...

使用 Polars 进行人工智能医疗数据分析(ICU数据基本测试篇)

引言 在医疗领域,数据就是生命的密码,每一个数据点都可能蕴含着拯救生命的关键信息。特别是在 ICU 这样的重症监护场景中,医生需要实时、准确地了解患者的病情变化,以便做出及时有效的治疗决策。而随着医疗技术的飞速发展&#x…...

超过DeepSeek、o3,Claude发布全球首个混合推理模型,并将完成新一轮35亿美元融资...

Anthropic于2025年2月25日发布全球首个“混合推理”AI模型Claude 3.7 Sonnet,并在融资层面取得重大进展,计划完成35亿美元的新一轮融资,估值将达615亿美元。以下是核心信息整理: 技术突破:双思维模型与代码能力 1. 混合…...

# C# 中堆(Heap)与栈(Stack)的区别

在 C# 中,堆和栈是两种不同的内存分配机制,它们在存储位置、生命周期、性能和用途上存在显著差异。理解堆和栈的区别对于优化代码性能和内存管理至关重要。 1. 栈(Stack) 1.1 定义 栈是一种后进先出(LIFO&#xff0…...

OmniParser v2本地部署(2)部署omnitool(包含自动化控制工具)

1 配置omniparserserver 1.1 配置conda环境、下载依赖和权重 我建议按照OmniParser v2本地部署(1)部署OmniParser_v2模型先设置一次,其中所创造的conda环境,和这一步相似 1.2 启动omniparserserver 进入OmniParser/omnitool/o…...

“深入解析 SQL Server 子查询:从基础到应用”

目录 引言什么是子查询? 子查询的定义子查询的类型 子查询的使用 标量子查询多行子查询多列子查询相关子查询 子查询的性能优化子查询的实际案例总结 引言 在 SQL Server 中,子查询是一种强大的工具,允许我们在一个查询中嵌套另一个查询&am…...

音频进阶学习十六——LTI系统的差分方程与频域分析一(频率响应)

文章目录 前言一、差分方程的有理式1.差分方程的有理分式2.因果系统和ROC3.稳定性与ROC 二、频率响应1.定义2.幅频响应3.相频响应4.群延迟 总结 前言 本篇文章会先复习Z变换的有理分式,这是之前文章中提过的内容,这里会将差分方程和有理分式进行结合来看…...