或者类似的Redis
中针对zset
的操作也是类似的:
> ZRANGE
所以可能习惯性的就使用类似的方式创建分页请求接口,让客户端提供page
、size
两个参数。 这样的做法并没有什么问题,在PC
的表格,移动端的列表,都能够整整齐齐的展示数据。
但是这是一种比较常规的数据分页处理方式,适用于没有什么动态的过滤条件的数据。 而如果数据是实时性要求非常高的那种,存在有大量的过滤条件,或者需要和其他数据源进行对照过滤,用这样的处理方式看起来就会有些诡异。
页码+条数 的分页接口的问题
举个简单的例子,我司是有直播业务的,必然也是存在有直播列表这样的接口的。 而直播这样的数据是非常要求时效性的,类似热门列表、新人列表,这些数据的来源是离线计算好的数据,但这样的数据一般只会存储用户的标识或者直播间的标识,像直播间观看人数、直播时长、人气,这类数据必然是时效性要求很高的,不可能在离线脚本中进行处理,所以就需要接口请求时才进行获取。
而且在客户端请求的时候也是需要有一些验证的,举例一些简单的条件:
确保主播正在直播
确保直播内容合规
检查用户与主播之间的拉黑关系
这些在离线脚本运行的时候都是没有办法做到的,因为每时每刻都在发生变化,而且数据可能没有存储在同一个位置,可能列表数据来自MySQL
、过滤的数据需要用Redis
中来获取、用户信息相关的数据在XXX
数据库,所以这些操作不可能是一个连表查询就能够解决的,它需要在接口层来进行,拿到多份数据进行合成。
而此时采用上述的分页模式,就会出现一个很尴尬的问题。 也许访问接口的用户戾气比较重,将第一页所有的主播全部拉黑了,这就会导致,实际接口返回的数据是0
条,这个就很可怕了。
let data = [] // length: 10
data = data.filter(filterBlackList)
return data // length: 0
这种情况客户端是该按照无数据来展示还是说紧接着要去请求第二页数据呢。
所以这样的分页设计在某些情况下并不能够满足我们的需求,恰巧此时发现了Redis
中的一个命令:scan
。
游标+条数 的分页接口实现
scan
命令用于迭代Redis
数据库中所有的key
,但是因为数据中的key
数量是不能确定的,(线上直接执行keys
会被打死的 ),而且key
的数量在你操作的过程中也是时刻在变化的,可能有的被删除,可能期间又有新增的。 所以,scan
的命令要求传入一个游标,第一次调用的时候传入0
即可,而scan
命令的返回值则有两项,第一项是下次迭代时候所需要的游标,而第二项是一个集合,表示本次迭代返回的所有key
。 以及scan
是可以添加正则表达式用来迭代某些满足规则的key
,例如所有temp_
开头的key
:scan 0 temp_*
,而scan
并不会真的去按照你所指定的规则去匹配key
然后返回给你,它并不保证一次迭代一定会返回N
条数据,有极大的可能一次迭代一条数据都不返回。
如果我们明确的需要XX
条数据,那么按照游标多次调用就好了。
// 用一个递归简单的实现获取十个匹配的key
await function getKeys (pattern, oldCursor = 0, res = []) {
const [ cursor, data ] = await redis.scan(oldCursor, pattern)
res = res.concat(data)
if (res.length >= 10) return res.slice(0, 10)
else return getKeys(cursor, pattern, res)
}
await getKeys('temp_*') // length: 10
这样的使用方式给了我一些思路,打算按照类似的方式来实现分页接口。 不过将这样的逻辑放在客户端,会导致后期调整逻辑时候变得非常麻烦。需要发版才能解决,新老版本兼容也会使得后期的修改束手束脚。 所以这样的逻辑会放在服务端来开发,而客户端只需要将接口返回的游标cursor
在下次接口请求时携带上即可。
大致的结构
对于客户端来说,这就是一个简单的游标存储以及使用。 但是服务端的逻辑要稍微复杂一些:
首先,我们需要有一个获取数据的函数
其次需要有一个用于数据过滤的函数
有一个用于判断数据长度并截取的函数
function getData () {
// 获取数据
}
function filterData () {
// 过滤数据
}
function generatedData () {
// 合并、生成、返回数据
}
实现
node.js 10.x
已经变为了LTS
,所以示例代码会使用10
的一些新特性。
因为列表大概率的会存储为一个集合,类似用户标识的集合,在Redis
中是set
或者zset
。
如果是数据源来自Redis
,我的建议是在全局缓存一份完整的列表,定时更新数据,然后在接口层面通过slice
来获取本次请求所需的部分数据。
P.S. 下方示例代码假设list
的数据中存储的是一个唯一ID的集合,而通过这些唯一ID再从其他的数据库获取对应的详细数据。
redis> SMEMBER list
> 1
> 2
> 3
mysql> SELECT * FROM user_info
+-----+---------+------+--------+
| uid | name | age | gender |
+-----+---------+------+--------+
| 1 | Niko | 18 | 1 |
| 2 | Bellic | 20 | 2 |
| 3 | Jarvis | 22 | 2 |
+-----+---------+------+--------+
列表数据在全局缓存
// 完整列表在全局的缓存
let globalList = null
async function updateGlobalData () {
globalList = await redis.smembers('list')
}
updateGlobalData()
setInterval(updateGlobalData, 2000) // 2s 更新一次
获取数据 过滤数据函数的实现
因为上边的scan
示例采用的是递归的方式来进行的,但是可读性并不是很高,所以我们可以采用生成器Generator
来帮助我们实现这样的需求:
// 获取数据的函数
async function * getData (list, size) {
const count = Math.ceil(list.length / size)
let index = 0
do {
const start = index * size
const end = start + size
const piece = list.slice(start, end)
// 查询 MySQL 获取对应的用户详细数据
const results = await mysql.query(`
SELECT * FROM user_info
WHERE uid in (${piece})
`)
// 过滤所需要的函数,会在下方列出来
yield filterData(results)
} while (index++ < count)
}
同时,我们还需要有一个过滤数据的函数,这些函数可能会从一些其他数据源获取数据,用来校验列表数据的合法性,比如说,用户A有一个黑名单,里边有用户B、用户C,那么用户A访问接口时,就需要将B和C进行过滤。 抑或是我们需要判断当前某条数据的状态,例如主播是否已经关闭了直播间,推流状态是否正常,这些可能会调用其他的接口来进行验证。
// 过滤数据的函数
async function filterData (list) {
const validList = await Promise.all(list.map(async item => {
const [
isLive,
inBlackList
] = await Promise.all([
http.request(`https://XXX.com/live?target=${item.id}`), redis.sismember(`XXX:black:list`, item.id)
])
// 正确的状态
if (isLive && !inBlackList) {
return item
}
}))
// 过滤无效数据
return validList.filter(i => i)
}
最后拼接数据的函数
上述两个关键功能的函数实现后,就需要有一个用来检查、拼接数据的函数出现了。 用来决定何时给客户端返回数据,何时发起新的获取数据的请求:
async function generatedData ({
cursor,
size,
}) {
let list = globalList
// 如果传入游标,从游标处截取列表
if (cursor) {
// + 1 的作用在下边有提到
list = list.slice(list.indexOf(cursor) + 1)
}
let results = []
// 注意这里的是 for 循环, 而非 map、forEach 之类的
for await (const res of getData(list, size)) {
results = results.concat(res)
if (results.length >= size) {
const list = results.slice(0, size)
return {
list,
// 如果还有数据,那么就需要将本次
// 我们返回列表最后一项的 ID 作为游标,这也就解释了接口入口处的 indexOf 为什么会有一个 + 1 的操作了
cursor: list[size - 1].id,
}
}
}
return {
list: results,
}
}
非常简单的一个for
循环,用for
循环就是为了让接口请求的过程变为串行,在第一次接口请求拿到结果后,并确定数据还不够,还需要继续获取数据进行填充,这时才会发起第二次请求,避免额外的资源浪费。 在获取到所需的数据以后,就可以直接return
了,循环终止,后续的生成器也会被销毁。
以及将这个函数放在我们的接口中,就完成了整个流程的组装:
router.get('/list', async ctx => {
const { cursor, size } = this.query
const data = await generatedData({
cursor,
size,
})
ctx.body = {
code: 200,
data,
}
})
这样的结构返回值大概是,一个list
与一个cursor
,类似scan
的返回值,游标与数据。 客户端还可以传入可选的size
来指定一次接口期望的返回条数。 不过相对于普通的page
+size
分页方式,这样的接口请求势必会慢一些(因为普通的分页可能一页返回不了固定条数的数据,而这个在内部可能执行了多次获取数据的操作)。
不过用于一些实时性要求强的接口上,我个人觉得这样的实现方式对用户会更友好一些。
两者之间的比较
这两种方式都是很不错的分页方式,第一种更常见一些,而第二种也不是灵丹妙药,只是在某些情况下可能会好一些。
第一种方式可能更多的会应用在B
端,一些工单、报表、归档数据之类的。 而第二种可能就是C
端用会比较好一些,毕竟提供给用户的产品; 在PC页面可能是一个分页表格,第一个展示10
条,第二页展示出来8
条,但是第三页又变成了10
条,这对用户体验来说简直是个灾难。 而在移动端页面可能会相对好一些,类似无限滚动的瀑布流,但是也会出现用户加载一次出现2
条数据,又加载了一次出现了8
条数据,在非首页这样的情况还是勉强可以接受的,但是如果首页就出现了2
条数据,啧啧。
而用第二种,游标cursor
的方式能够保证每次接口返回数据都是size
条,如果不够了,那就说明后边没有数据了。 对用户来说体验会更好一些。(当然了,如果列表没有什么过滤条件,就是一个普通的展示,那么建议使用第一种,没有必要添加这些逻辑处理了)
小结
当然了,这只是从服务端能够做到的一些分页相关的处理,但是这依然没有解决所有的问题,类似一些更新速度较快的列表,排行榜之类的,每秒钟的数据可能都在变化,有可能第一次请求的时候,用户A在第十名,而第二次请求接口的时候用户A在第十一名,那么两次接口都会存在用户A的记录。
针对这样的情况,客户端也要做相应的去重处理,但是这样一去重就会导致数据量的减少。 这又是一个很大的话题了,不打算展开来讲。。 一个简单的欺骗用户的方式,就是一次接口请求16
条,展示10
条,剩余6
条存在本地下次接口拼接进去再展示。
文中如果有什么错误,或者关于分页各位有更好的实现方式、自己喜欢的方式,不妨交流一番。
参考资料
你可能感兴趣的:(基于游标的分页接口实现)
2020-01-25
晴岚85
郑海燕坚持分享590天2020.1.24在生活中只存在两个问题。一个问题是:你知道想要达成的目标是什么,但却不知道如何才能达成;另一个问题是:你不知道你的目标是什么。前一个是行动的问题,后一个是结果的问题。通过制定具体的下一步行动,可以解决不知道如何开始行动的问题。而通过去想象结果,对结果做预估,可以解决找不着目标的问题。对于所有吸引我们注意力,想要完成的任务,你可以先想象一下,预期的结果究竟是什
如何在 Fork 的 GitHub 项目中保留自己的修改并同步上游更新?github_fork_update
iBaoxing
github
如何在Fork的GitHub项目中保留自己的修改并同步上游更新?在GitHub上Fork了一个项目后,你可能会对项目进行一些修改,同时原作者也在不断更新。如果想要在保留自己修改的基础上,同步原作者的最新更新,很多人会不知所措。本文将详细讲解如何在不丢失自己改动的情况下,将上游仓库的更新合并到自己的仓库中。问题描述假设你在GitHub上Fork了一个项目,并基于该项目做了一些修改,随后你发现原作者对
《庄子.达生9》
钱江潮369
【原文】孔子观于吕梁,县水三十仞,流沫四十里,鼋鼍鱼鳖之所不能游也。见一丈夫游之,以为有苦而欲死也,使弟子并流而拯之。数百步而出,被发行歌而游于塘下。孔子从而问焉,曰:“吾以子为鬼,察子则人也。请问,‘蹈水有道乎’”曰:“亡,吾无道。吾始乎故,长乎性,成乎命。与齐俱入,与汩偕出,从水之道而不为私焉。此吾所以蹈之也。”孔子曰:“何谓始乎故,长乎性,成乎命?”曰:“吾生于陵而安于陵,故也;长于水而安于
腾讯云技术深度探索:构建高效云原生微服务架构
我的运维人生
云原生 架构 腾讯云 运维开发 技术共享
腾讯云技术深度探索:构建高效云原生微服务架构在当今快速发展的技术环境中,云原生技术已成为企业数字化转型的关键驱动力。腾讯云作为行业领先的云服务提供商,不断推出创新的产品和技术,助力企业构建高效、可扩展的云原生微服务架构。本文将深入探讨腾讯云在微服务领域的最新进展,并通过一个实际案例展示如何在腾讯云平台上构建云原生应用。腾讯云微服务架构概览腾讯云微服务架构基于云原生理念,旨在帮助企业快速实现应用的容
Pyecharts数据可视化大屏:打造沉浸式数据分析体验
我的运维人生
信息可视化 数据分析 数据挖掘 运维开发 技术共享
Pyecharts数据可视化大屏:打造沉浸式数据分析体验在当今这个数据驱动的时代,如何将海量数据以直观、生动的方式展现出来,成为了数据分析师和企业决策者关注的焦点。Pyecharts,作为一款基于Python的开源数据可视化库,凭借其丰富的图表类型、灵活的配置选项以及高度的定制化能力,成为了构建数据可视化大屏的理想选择。本文将深入探讨如何利用Pyecharts打造数据可视化大屏,并通过实际代码案例
Google earth studio 简介
陟彼高冈yu
旅游
GoogleEarthStudio是一个基于Web的动画工具,专为创作使用GoogleEarth数据的动画和视频而设计。它利用了GoogleEarth强大的三维地图和卫星影像数据库,使用户能够轻松地创建逼真的地球动画、航拍视频和动态地图可视化。网址为https://www.google.com/earth/studio/。GoogleEarthStudio是一个基于Web的动画工具,专为创作使用G
基于社交网络算法优化的二维最大熵图像分割
智能算法研学社(Jack旭)
智能优化算法应用 图像分割 算法 php 开发语言
智能优化算法应用:基于社交网络优化的二维最大熵图像阈值分割-附代码文章目录智能优化算法应用:基于社交网络优化的二维最大熵图像阈值分割-附代码1.前言2.二维最大熵阈值分割原理3.基于社交网络优化的多阈值分割4.算法结果:5.参考文献:6.Matlab代码摘要:本文介绍基于最大熵的图像分割,并且应用社交网络算法进行阈值寻优。1.前言阅读此文章前,请阅读《图像分割:直方图区域划分及信息统计介绍》htt
四章-32-点要素的聚合
彩云飘过
本文基于腾讯课堂老胡的课《跟我学Openlayers--基础实例详解》做的学习笔记,使用的openlayers5.3.xapi。源码见1032.html,对应的官网示例https://openlayers.org/en/latest/examples/cluster.htmlhttps://openlayers.org/en/latest/examples/earthquake-clusters.
深入理解 MultiQueryRetriever:提升向量数据库检索效果的强大工具
nseejrukjhad
数据库 python
深入理解MultiQueryRetriever:提升向量数据库检索效果的强大工具引言在人工智能和自然语言处理领域,高效准确的信息检索一直是一个关键挑战。传统的基于距离的向量数据库检索方法虽然广泛应用,但仍存在一些局限性。本文将介绍一种创新的解决方案:MultiQueryRetriever,它通过自动生成多个查询视角来增强检索效果,提高结果的相关性和多样性。MultiQueryRetriever的工
东南林氏之九牧林候选父系
祖缘树TheYtree
渊源介绍东晋初年晋安林始祖林禄公入闽,传十世隋右丞林茂,由晋安迁居莆田北螺村。又五世而至林万宠,唐开元间任高平太守,生三子:韬、披、昌。韬公之孙攒,唐德宗立双阙以旌表其孝,时号"阙下林家"。昌公字茂吉,乃万宠公第三子,官兵部司马,配宋氏,生一子名萍。萍于唐贞元间明经及第,官沣洲司马(后追赠中宪大夫)。唐太和年间归隐后,迁居仙游游洋,世称“游洋林”;其后裔居游洋后迁移漳州漳浦路下,由路下林第四房平和
在一台Ubuntu计算机上构建Hyperledger Fabric网络
落叶无声9
区块链 超级账本 Hyperledger fabric 区块链 ubuntu 构建 hyperledger fabric
在一台Ubuntu计算机上构建HyperledgerFabric网络Hyperledgerfabric是一个开源的区块链应用程序平台,为开发基于区块链的应用程序提供了一个起点。当我们提到HyperledgerFabric网络时,我们指的是使用HyperledgerFabric的正在运行的系统。即使只使用最少数量的组件,部署Fabric网络也不是一件容易的事。Fabric社区创建了一个名为Cello
关于城市旅游的HTML网页设计——(旅游风景云南 5页)HTML+CSS+JavaScript
二挡起步
web前端期末大作业 javascript html css 旅游 风景
⛵源码获取文末联系✈Web前端开发技术描述网页设计题材,DIV+CSS布局制作,HTML+CSS网页设计期末课程大作业|游景点介绍|旅游风景区|家乡介绍|等网站的设计与制作|HTML期末大学生网页设计作业,Web大学生网页HTML:结构CSS:样式在操作方面上运用了html5和css3,采用了div+css结构、表单、超链接、浮动、绝对定位、相对定位、字体样式、引用视频等基础知识JavaScrip
HTML网页设计制作大作业(div+css) 云南我的家乡旅游景点 带文字滚动
二挡起步
web前端期末大作业 web设计网页规划与设计 html css javascript dreamweaver 前端
Web前端开发技术描述网页设计题材,DIV+CSS布局制作,HTML+CSS网页设计期末课程大作业游景点介绍|旅游风景区|家乡介绍|等网站的设计与制作HTML期末大学生网页设计作业HTML:结构CSS:样式在操作方面上运用了html5和css3,采用了div+css结构、表单、超链接、浮动、绝对定位、相对定位、字体样式、引用视频等基础知识JavaScript:做与用户的交互行为文章目录前端学习路线
Redis系列:Geo 类型赋能亿级地图位置计算
Ly768768
redis bootstrap 数据库
1前言我们在篇深刻理解高性能Redis的本质的时候就介绍过Redis的几种基本数据结构,它是基于不同业务场景而设计的:动态字符串(REDIS_STRING):整数(REDIS_ENCODING_INT)、字符串(REDIS_ENCODING_RAW)双端列表(REDIS_ENCODING_LINKEDLIST)压缩列表(REDIS_ENCODING_ZIPLIST)跳跃表(REDIS_ENCODI
基于CODESYS的多轴运动控制程序框架:逻辑与运动控制分离,快速开发灵活操作
GPJnCrbBdl
python 开发语言
基于codesys开发的多轴运动控制程序框架,将逻辑与运动控制分离,将单轴控制封装成功能块,对该功能块的操作包含了所有的单轴控制(归零、点动、相对定位、绝对定位、设置当前位置、伺服模式切换等等)。程序框架由主程序按照状态调用分归零模式、手动模式、自动模式、故障模式,程序状态的跳转都已完成,只需要根据不同的工艺要求完成所需的动作即可。变量的声明、地址的规划都严格按照C++的标准定义,能帮助开发者快速
2019-08-16
希望在东方
《春游荣华山》春游荣华山,乍暖还寒。青苔路,石阶险。山路弯上弯!为寻古寺往幽探。细雨已润江南岸,初春芳草现。老树新芽冒枝端,人间又过到新年。今游荣华山,树茂参天,古寺悠闲。细雨飘落发端!三眼井旁,投币许心愿,并祷一世安然。更喜大女明事端,应心安,放开颜。修竹静默,雨中吐心愿。待得春风浩吹时,春笋节节攀。图片发自App图片发自App图片发自App
和自己结婚,是一种怎样的体验
只如初见_2020
一个17岁谈恋爱,19岁结婚,然后离了三次婚的女人,站在台上说:“现在我结婚了,和那个一直以来,真正想在一起的人结婚了,那个人就是我自己。”她说,在我9岁前,我已经在二十几个寄养家庭中待过。我从童年到成年,就只有一个目标,不要被落下。而我实现这一目标的方式就是,我要结婚。我第一次的结婚对象,是我17岁时遇到的人。我们两年之后结了婚,当时我19岁。他是个非常好的人,来自于非常棒的家庭,他是工商管理硕
不要偷走他人的声音
天天_27d6
朱会利焦点讲师班五期洛阳坚持分享第634天《来访者才是主角》2018.08.02今天的中级班课堂上,老师再一次给我们强调了咨询目标的建立过程中,作为咨询师一定要明白,我们只是在协助来访者解决他自身的问题,所以一切以来访者为主,他想解决的问题才是咨询的目标。所以如果在谈话的过程中,出现了我们感觉不是我们想要的答案的时候,我们不是再极力去引导来访者按照我们的思路走,而是觉察自己的预设并且进行调整,谨言
《太虚游》第六十二章。玄牝之威。
古楼臭道士
“好好好,流云这孩子深得我心,想必长爻知道是你的话定然会惊喜不已的。”白玄牝听得风流云应了下来,脸色慈和,伸手在他头顶轻轻抚了抚,如同抚在怀中九尾小狐一样自然,极其温柔。身后的四位青丘长老同时一怔,嘴角微动,似要开口劝阻。风流云只感到一道霞光瑞气如有实质一般顺着头顶百会大穴直沉在下丹田内,随后这股气息又逐渐凝聚,似乎给自己吃了什么东西一般。啊喔不好,这祖奶奶该不会是看中我这肉身,像人魔一样,要给她
基于Python给出的PDF文档转Markdown文档的方法
程序媛了了
python pdf 开发语言
注:网上有很多将Markdown文档转为PDF文档的方法,但是却很少有将PDF文档转为Markdown文档的方法。就算有,比如某些网站声称可以将PDF文档转为Markdown文档,尝试过,不太符合自己的要求,而且无法保证文档没有泄露风险。于是本人为了解决这个问题,借助GPT(能使用GPT镜像或者有条件直接使用GPT的,反正能调用GPT接口就行)生成Python代码来完成这个功能。笔记、代码难免存在
BART&BERT
Ambition_LAO
深度学习
BART和BERT都是基于Transformer架构的预训练语言模型。模型架构:BERT(BidirectionalEncoderRepresentationsfromTransformers)主要是一个编码器(Encoder)模型,它使用了Transformer的编码器部分来处理输入的文本,并生成文本的表示。BERT特别擅长理解语言的上下文,因为它在预训练阶段使用了掩码语言模型(MLM)任务,即
(121)DAC接口--->(006)基于FPGA实现DAC8811接口
FPGA系统设计指南针
FPGA接口开发(项目实战) fpga开发 FPGA IC
1目录(a)FPGA简介(b)IC简介(c)Verilog简介(d)基于FPGA实现DAC8811接口(e)结束1FPGA简介(a)FPGA(FieldProgrammableGateArray)是在PAL(可编程阵列逻辑)、GAL(通用阵列逻辑)等可编程器件的基础上进一步发展的产物。它是作为专用集成电路(ASIC)领域中的一种半定制电路而出现的,既解决了定制电路的不足,又克服了原有可编程器件门电
esp32开发快速入门 8 : MQTT 的快速入门,基于esp32实现MQTT通信
z755924843
ESP32开发快速入门 服务器 网络 运维
MQTT介绍简介MQTT(MessageQueuingTelemetryTransport,消息队列遥测传输协议),是一种基于发布/订阅(publish/subscribe)模式的"轻量级"通讯协议,该协议构建于TCP/IP协议上,由IBM在1999年发布。MQTT最大优点在于,可以以极少的代码和有限的带宽,为连接远程设备提供实时可靠的消息服务。作为一种低开销、低带宽占用的即时通讯协议,使其在物联
android 更改窗口的层次,浮窗开发之窗口层级
Ms.Bu
android 更改窗口的层次
最近在项目中遇到了这样的需求:需要在特定的其他应用之上悬浮自己的UI交互(拖动、输入等复杂的UI交互),和九游的浮窗类似,不过我们的比九游的体验更好,我们越过了很多授权的限制。浮窗效果很多人都知道如何去实现一个简单的浮窗,但是却很少有人去深入的研究背后的流程机制,由于项目中浮窗交互比较复杂,遇到了些坑查看了很多资料,故总结浮窗涉及到的知识点:窗口层级关系(浮窗是如何“浮”的)?浮窗有哪些限制,如何
06选课支付模块之基于消息队列发送支付通知消息
echo 云清
学成在线 java rabbitmq 消息队列 支付通知 学成在线
消息队列发送支付通知消息需求分析订单服务作为通用服务,在订单支付成功后需要将支付结果异步通知给其他对接的微服务,微服务收到支付结果根据订单的类型去更新自己的业务数据技术方案使用消息队列进行异步通知需要保证消息的可靠性即生产端将消息成功通知到服务端:消息发送到交换机-->由交换机发送到队列-->消费者监听队列,收到消息进行处理,参考文章02-使用Docker安装RabbitMQ-CSDN博客生产者确
基于STM32与Qt的自动平衡机器人:从控制到人机交互的的详细设计流程
极客小张
stm32 qt 机器人 物联网 人机交互 毕业设计 c语言
一、项目概述目标和用途本项目旨在开发一款基于STM32控制的自动平衡机器人,结合步进电机和陀螺仪传感器,实现对平衡机器人的精确控制。该机器人可以用于教育、科研、娱乐等多个领域,帮助用户了解自动控制、机器人运动学等相关知识。技术栈关键词STM32单片机步进电机陀螺仪传感器AD采集电路Qt人机界面实时数据监控二、系统架构系统架构设计本项目的系统架构设计包括以下主要组件:控制单元:STM32单片机传感器
基于STM32的汽车仪表显示系统:集成CAN、UART与I2C总线设计流程
极客小张
stm32 汽车 嵌入式硬件 物联网 单片机 c语言
一、项目概述项目目标与用途本项目旨在设计和实现一个基于STM32微控制器的汽车仪表显示系统。该系统能够实时显示汽车的速度、转速、油量等关键信息,并通过CAN总线与其他汽车控制单元进行通信。这种仪表显示系统不仅提高了驾驶的安全性和便捷性,还能为汽车提供更智能的用户体验。技术栈关键词微控制器:STM32显示技术:TFTLCD/OLED传感器:速度传感器、温度传感器、油量传感器通信协议:CAN总线、UA
Python多线程实现大规模数据集高效转移
sand&wich
网络 python 服务器
背景在处理大规模数据集时,通常需要在不同存储设备、不同服务器或文件夹之间高效地传输数据。如果采用单线程传输方式,当数据量非常大时,整个过程会非常耗时。因此,通过多线程并行处理可以大幅提升数据传输效率。本文将分享一个基于Python多线程实现的高效数据传输工具,通过遍历源文件夹中的所有文件,将它们移动到目标文件夹。工具和库这个数据集转移工具主要依赖于以下Python标准库:os:用于文件系统操作,如
《我的人间烟火》火遍全网,姐弟恋专业户魏大勋用演技为自己正名,他的代表作并非三个女人
天然农场
说起魏大勋,真是一言难尽!毕业于中央戏剧学院的他,出道十几年居然没有塑造出让观众记住的角色,一直被大家定位为综艺咖,甚至有人打趣道,魏大勋的代表作就是三段姐弟恋。他的绯闻女友,囊括了马苏、杨幂、秦岚这三位顶级女神。不得不承认,魏大勋虽然形象欠佳,但是眼光不错,艳福不浅,直逼当年的泡妞高手李亚鹏。与李亚鹏不同的是,魏大勋每次都是奔着结婚而去,并非玩玩而已,毕竟不以结婚为目标的恋爱都是耍流氓!有网友评
ESP32-C3入门教程 网络篇⑩——基于esp_https_ota和MQTT实现开机主动升级和被动触发升级的OTA功能
小康师兄
ESP32-C3入门教程 https 服务器 esp32 OTA MQTT
文章目录一、前言二、软件流程三、部分源码四、运行演示一、前言本文基于VSCodeIDE进行编程、编译、下载、运行等操作基础入门章节请查阅:ESP32-C3入门教程基础篇①——基于VSCode构建HelloWorld教程目录大纲请查阅:ESP32-C3入门教程——导读ESP32-C3入门教程网络篇⑨——基于esp_https_ota实现史上最简单的ESP32OTA远程固件升级功能二、软件流程
java责任链模式
3213213333332132
java 责任链模式 村民告县长
责任链模式,通常就是一个请求从最低级开始往上层层的请求,当在某一层满足条件时,请求将被处理,当请求到最高层仍未满足时,则请求不会被处理。
就是一个请求在这个链条的责任范围内,会被相应的处理,如果超出链条的责任范围外,请求不会被相应的处理。
下面代码模拟这样的效果:
创建一个政府抽象类,方便所有的具体政府部门继承它。
package 责任链模式;
/**
*
linux、mysql、nginx、tomcat 性能参数优化
ronin47
一、linux 系统内核参数
/etc/sysctl.conf文件常用参数 net.core.netdev_max_backlog = 32768 #允许送到队列的数据包的最大数目
net.core.rmem_max = 8388608 #SOCKET读缓存区大小
net.core.wmem_max = 8388608 #SOCKET写缓存区大
php命令行界面
dcj3sjt126com
PHP cli
常用选项
php -v
php -i PHP安装的有关信息
php -h 访问帮助文件
php -m 列出编译到当前PHP安装的所有模块
执行一段代码
php -r 'echo "hello, world!";'
php -r 'echo "Hello, World!\n";'
php -r '$ts = filemtime("
Filter&Session
171815164
session
Filter
HttpServletRequest requ = (HttpServletRequest) req;
HttpSession session = requ.getSession();
if (session.getAttribute("admin") == null) {
PrintWriter out = res.ge
连接池与Spring,Hibernate结合
g21121
Hibernate
前几篇关于Java连接池的介绍都是基于Java应用的,而我们常用的场景是与Spring和ORM框架结合,下面就利用实例学习一下这方面的配置。
1.下载相关内容: &nb
[简单]mybatis判断数字类型
53873039oycg
mybatis
昨天同事反馈mybatis保存不了int类型的属性,一直报错,错误信息如下:
Caused by: java.lang.NumberFormatException: For input string: "null"
at sun.mis
项目启动时或者启动后ava.lang.OutOfMemoryError: PermGen space
程序员是怎么炼成的
eclipse jvm tomcat catalina.sh eclipse.ini
在启动比较大的项目时,因为存在大量的jsp页面,所以在编译的时候会生成很多的.class文件,.class文件是都会被加载到jvm的方法区中,如果要加载的class文件很多,就会出现方法区溢出异常 java.lang.OutOfMemoryError: PermGen space.
解决办法是点击eclipse里的tomcat,在
我的crm小结
aijuans
crm
各种原因吧,crm今天才完了。主要是接触了几个新技术:
Struts2、poi、ibatis这几个都是以前的项目中用过的。
Jsf、tapestry是这次新接触的,都是界面层的框架,用起来也不难。思路和struts不太一样,传说比较简单方便。不过个人感觉还是struts用着顺手啊,当然springmvc也很顺手,不知道是因为习惯还是什么。jsf和tapestry应用的时候需要知道他们的标签、主
spring里配置使用hibernate的二级缓存几步
antonyup_2006
java spring Hibernate xml cache
.在spring的配置文件中 applicationContent.xml,hibernate部分加入
xml 代码
<prop key="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</prop>
<prop key="hi
JAVA基础面试题
百合不是茶
抽象实现接口 String类 接口继承 抽象类继承实体类 自定义异常
/* * 栈(stack):主要保存基本类型(或者叫内置类型)(char、byte、short、 *int、long、 float、double、boolean)和对象的引用,数据可以共享,速度仅次于 * 寄存器(register),快于堆。堆(heap):用于存储对象。 */ &
让sqlmap文件 "继承" 起来
bijian1013
java ibatis sqlmap
多个项目中使用ibatis , 和数据库表对应的 sqlmap文件(增删改查等基本语句),dao, pojo 都是由工具自动生成的, 现在将这些自动生成的文件放在一个单独的工程中,其它项目工程中通过jar包来引用 ,并通过"继承"为基础的sqlmap文件,dao,pojo 添加新的方法来满足项
精通Oracle10编程SQL(13)开发触发器
bijian1013
oracle 数据库 plsql
/*
*开发触发器
*/
--得到日期是周几
select to_char(sysdate+4,'DY','nls_date_language=AMERICAN') from dual;
select to_char(sysdate,'DY','nls_date_language=AMERICAN') from dual;
--建立BEFORE语句触发器
CREATE O
【EhCache三】EhCache查询
bit1129
ehcache
本文介绍EhCache查询缓存中数据,EhCache提供了类似Hibernate的查询API,可以按照给定的条件进行查询。
要对EhCache进行查询,需要在ehcache.xml中设定要查询的属性
数据准备
@Before
public void setUp() {
//加载EhCache配置文件
Inpu
CXF框架入门实例
白糖_
spring Web 框架 webservice servlet
CXF是apache旗下的开源框架,由Celtix + XFire这两门经典的框架合成,是一套非常流行的web service框架。
它提供了JAX-WS的全面支持,并且可以根据实际项目的需要,采用代码优先(Code First)或者 WSDL 优先(WSDL First)来轻松地实现 Web Services 的发布和使用,同时它能与spring进行完美结合。
在apache cxf官网提供
angular.equals
boyitech
AngularJS AngularJS API AnguarJS 中文API angular.equals
angular.equals
描述:
比较两个值或者两个对象是不是 相等。还支持值的类型,正则表达式和数组的比较。 两个值或对象被认为是 相等的前提条件是以下的情况至少能满足一项:
两个值或者对象能通过=== (恒等) 的比较
两个值或者对象是同样类型,并且他们的属性都能通过angular
java-腾讯暑期实习生-输入一个数组A[1,2,...n],求输入B,使得数组B中的第i个数字B[i]=A[0]*A[1]*...*A[i-1]*A[i+1]
bylijinnan
java
这道题的具体思路请参看 何海涛的微博:http://weibo.com/zhedahht
import java.math.BigInteger;
import java.util.Arrays;
public class CreateBFromATencent {
/**
* 题目:输入一个数组A[1,2,...n],求输入B,使得数组B中的第i个数字B[i]=A
FastDFS 的安装和配置 修订版
Chen.H
linux fastDFS 分布式文件系统
FastDFS Home:http://code.google.com/p/fastdfs/
1. 安装
http://code.google.com/p/fastdfs/wiki/Setup http://hi.baidu.com/leolance/blog/item/3c273327978ae55f93580703.html
安装libevent (对libevent的版本要求为1.4.
[强人工智能]拓扑扫描与自适应构造器
comsci
人工智能
当我们面对一个有限拓扑网络的时候,在对已知的拓扑结构进行分析之后,发现在连通点之后,还存在若干个子网络,且这些网络的结构是未知的,数据库中并未存在这些网络的拓扑结构数据....这个时候,我们该怎么办呢?
那么,现在我们必须设计新的模块和代码包来处理上面的问题
oracle merge into的用法
daizj
oracle sql merget into
Oracle中merge into的使用
http://blog.csdn.net/yuzhic/article/details/1896878
http://blog.csdn.net/macle2010/article/details/5980965
该命令使用一条语句从一个或者多个数据源中完成对表的更新和插入数据. ORACLE 9i 中,使用此命令必须同时指定UPDATE 和INSE
不适合使用Hadoop的场景
datamachine
hadoop
转自:http://dev.yesky.com/296/35381296.shtml。
Hadoop通常被认定是能够帮助你解决所有问题的唯一方案。 当人们提到“大数据”或是“数据分析”等相关问题的时候,会听到脱口而出的回答:Hadoop! 实际上Hadoop被设计和建造出来,是用来解决一系列特定问题的。对某些问题来说,Hadoop至多算是一个不好的选择,对另一些问题来说,选择Ha
YII findAll的用法
dcj3sjt126com
yii
看文档比较糊涂,其实挺简单的:
$predictions=Prediction::model()->findAll("uid=:uid",array(":uid"=>10));
第一个参数是选择条件:”uid=10″。其中:uid是一个占位符,在后面的array(“:uid”=>10)对齐进行了赋值;
更完善的查询需要
vim 常用 NERDTree 快捷键
dcj3sjt126com
vim
下面给大家整理了一些vim NERDTree的常用快捷键了,这里几乎包括了所有的快捷键了,希望文章对各位会带来帮助。
切换工作台和目录
ctrl + w + h 光标 focus 左侧树形目录ctrl + w + l 光标 focus 右侧文件显示窗口ctrl + w + w 光标自动在左右侧窗口切换ctrl + w + r 移动当前窗口的布局位置
o 在已有窗口中打开文件、目录或书签,并跳
Java把目录下的文件打印出来
蕃薯耀
列出目录下的文件 文件夹下面的文件 目录下的文件
Java把目录下的文件打印出来
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
蕃薯耀 2015年7月11日 11:02:
linux远程桌面----VNCServer与rdesktop
hanqunfeng
Desktop
windows远程桌面到linux,需要在linux上安装vncserver,并开启vnc服务,同时需要在windows下使用vnc-viewer访问Linux。vncserver同时支持linux远程桌面到linux。
linux远程桌面到windows,需要在linux上安装rdesktop,同时开启windows的远程桌面访问。
下面分别介绍,以windo
guava中的join和split功能
jackyrong
java
guava库中,包含了很好的join和split的功能,例子如下:
1) 将LIST转换为使用字符串连接的字符串
List<String> names = Lists.newArrayList("John", "Jane", "Adam", "Tom");
Web开发技术十年发展历程
lampcy
android Web 浏览器 html5
回顾web开发技术这十年发展历程:
Ajax
03年的时候我上六年级,那时候网吧刚在小县城的角落萌生。传奇,大话西游第一代网游一时风靡。我抱着试一试的心态给了网吧老板两块钱想申请个号玩玩,然后接下来的一个小时我一直在,注,册,账,号。
彼时网吧用的512k的带宽,注册的时候,填了一堆信息,提交,页面跳转,嘣,”您填写的信息有误,请重填”。然后跳转回注册页面,以此循环。我现在时常想,如果当时a
架构师之mima-----------------mina的非NIO控制IOBuffer(说得比较好)
nannan408
buffer
1.前言。
如题。
2.代码。
IoService
IoService是一个接口,有两种实现:IoAcceptor和IoConnector;其中IoAcceptor是针对Server端的实现,IoConnector是针对Client端的实现;IoService的职责包括:
1、监听器管理
2、IoHandler
3、IoSession
ORA-00054:resource busy and acquire with NOWAIT specified
Everyday都不同
oracle session Lock
[Oracle]
今天对一个数据量很大的表进行操作时,出现如题所示的异常。此时表明数据库的事务处于“忙”的状态,而且被lock了,所以必须先关闭占用的session。
step1,查看被lock的session:
select t2.username, t2.sid, t2.serial#, t2.logon_time
from v$locked_obj
javascript学习笔记
tntxia
JavaScript
javascript里面有6种基本类型的值:number、string、boolean、object、function和undefined。number:就是数字值,包括整数、小数、NaN、正负无穷。string:字符串类型、单双引号引起来的内容。boolean:true、false object:表示所有的javascript对象,不用多说function:我们熟悉的方法,也就是
Java enum的用法详解
xieke90
enum 枚举
Java中枚举实现的分析:
示例:
public static enum SEVERITY{
INFO,WARN,ERROR
}
enum很像特殊的class,实际上enum声明定义的类型就是一个类。 而这些类都是类库中Enum类的子类 (java.l