首页 文章 精选 留言 我的

精选列表

搜索[国产神器],共5639篇文章
优秀的个人博客,低调大师

TLog v1.3.6 正式发布,1.6K star 的日志神器

目前TLog参与了《2021年度OSC中国开源项目评选》活动,希望大家能为TLog投上你宝贵的一票,投票地址为: https://www.oschina.net/project/top_cn_2021/?id=579 一 TLog v1.3.6 正式发布!相关文档已经做了更新。 TLog是一款日志工具,十分钟即可接入,支持众多的框架和主流RPC,你几乎不需要做什么,TLog能自动你的日志进行增强,让你的日志马上升级,微服务之间的日志变得可追溯! 如果你想了解更多,请点击以下地址进行了解。 项目官网: https://tlog.yomahub.com gitee托管仓库: https://gitee.com/dromara/TLog github托管仓库: https://github.com/dromara/TLog 二 TLog开源1年以来,作为一款日志增强框架。因为便捷使用和支持众多的其他框架,获得了很多人的喜爱。拥有了一个非常好的社区。 本次更新主要解决了在log4j2日志框架下的标签重复问题以及支持了一个新的http框架。 feature: #I3UZNP TLog希望能支持RestTemplate https://gitee.com/dromara/TLog/issues/I3UZNP enhancement: #I4LNF8 切换默认ID生成器为Hutool包的中雪花生成器 https://gitee.com/dromara/TLog/issues/I4LNF8 bug: #I4LCD7 log4j2在普通异步场景和MDC异步场景下,traceId会重复 https://gitee.com/dromara/TLog/issues/I4LCD7

优秀的个人博客,低调大师

绝对神器,用 SQL查 Linux日志,查询效率高到飞起

大家好,我是小富~ 最近发现点好玩的工具,迫不及待的想跟大家分享一下。 大家平时都怎么查Linux日志呢? 像我平时会用tail、head、cat、sed、more、less这些经典系统命令,或者awk这类三方数据过滤工具,配合起来查询效率很高。但在使用过程中有一点让我比较头疼,那就是命令参数规则太多了,记的人脑壳疼。 那查日志有没有一种通用的方式,比如用SQL查询,毕竟这是程序员都比较熟悉的表达式。 今天分享的工具q,就实现了以写SQL的方式来查询、统计文本内容,一起看看这货到底有什么神奇之处。 搭个环境 q是一个命令行工具,允许我们在任意文件或者查询结果,比如可以在ps -ef查询进程命令的结果集上,直接执行SQL语句查询。 宗旨就是文本即数据库表,额~,当然这句话是我自己理解的,哈哈哈 它将普通文件或者结果集当作数据库表,几乎支持所有的SQL结构,如WHERE、GROUP BY、JOINS等,支持自动列名和列类型检测,支持跨文件连接查询,这两个后边详细介绍,支持多种编码。 安装比较简单,在Linux CentOS环境,只要如下三步搞定,Windows环境更是只需安装个exe就可以用了。 wget https://github.com/harelba/q/releases/download/1.7.1/q-text-as-data-1.7.1-1.noarch.rpm #下载版本 sudo rpm -ivh q-text-as-data-1.7.1-1.noarch.rpm # 安装 q --version #查看安装版本 官方文档:https://harelba.github.io/q 语法 q支持所有SQLiteSQL语法,标准命令行格式q + 参数命令 + "SQL" q <命令> "<SQL>" 我要查询myfile.log文件的内容,直接q "SELECT * FROM myfile.log"。 q "SELECT * FROM myfile.log" q不附加参数使用是完全没有问题的,但利用参数会让显示结果更加美观,所以这里简单了解一下,它的参数分为 2种。 input输入命令:指的是对要查询的文件或结果集进行操作,比如:-H命令,表示输入的数据包含标题行。 q -H "SELECT * FROM myfile.log" 在这种情况下,将自动检测列名,并可在查询语句中使用。如果未提供此选项,则列将自动命名为cX,以c1起始以此类推。 q "select c1,c2 from ..." output输出命令:作用在查询输出的结果集,比如:-O,让查询出来的结果显示列名。 [root@iZ2zebfzaequ90bdlz820sZ software]# ps -ef | q -H "select count(UID) from - where UID='root'" 104 [root@iZ2zebfzaequ90bdlz820sZ software]# ps -ef | q -H -O "select count(UID) from - where UID='root'" count(UID) 104 还有很多参数就不一一列举了,感兴趣的同学在官网上看下,接下来我们重点演示一下使用SQL如何应对各种查询日志的场景。 玩法贼多 下边咱们一起看几个查询日志的经常场景中,这个SQL该如何写。 1、关键字查询 关键字检索,应该是日常开发使用最频繁的操作,不过我个人认为这一点q并没有什么优势,因为它查询时必须指定某一列。 [root@iZ2zebfzaequ90bdlz820sZ software]# q "select * from douyin.log where c9 like '%待解析%'" 2021-06-11 14:46:49.323 INFO 22790 --- [nio-8888-exec-2] c.x.douyin.controller.ParserController : 待解析URL :url=https%3A%2F%2Fv.douyin.com%2Fe9g9uJ6%2F 2021-06-11 14:57:31.938 INFO 22790 --- [nio-8888-exec-5] c.x.douyin.controller.ParserController : 待解析URL :url=https%3A%2F%2Fv.douyin.com%2Fe9pdhGP%2F 2021-06-11 15:23:48.004 INFO 22790 --- [nio-8888-exec-2] c.x.douyin.controller.ParserController : 待解析URL :url=https%3A%2F%2Fv.douyin.com%2Fe9pQjBR%2F 2021-06-11 2 而用grep命令则是全文检索。 [root@iZ2zebfzaequ90bdlz820sZ software]# cat douyin.log | grep '待解析URL' 2021-06-11 14:46:49.323 INFO 22790 --- [nio-8888-exec-2] c.x.douyin.controller.ParserController : 待解析URL :url=https%3A%2F%2Fv.douyin.com%2Fe9g9uJ6%2F 2021-06-11 14:57:31.938 INFO 22790 --- [nio-8888-exec-5] c.x.douyin.controller.ParserController : 待解析URL :url=https%3A%2F%2Fv.douyin.com%2Fe9pdhGP%2F 2、模糊查询 like模糊搜索,如果文本内容列有名字直接用列名检索,没有则直接根据列号c1、c2、cN。 [root@iZ2zebfzaequ90bdlz820sZ software]# cat test.log abc 2 3 4 5 23 24 25 [root@iZ2zebfzaequ90bdlz820sZ software]# q -H -t "select * from test.log where abc like '%2%'" Warning: column count is one - did you provide the correct delimiter? 2 23 24 25 3、交集并集 支持UNION和UNION ALL操作符对多个文件取交集或者并集。 如下建了test.log和test1.log两个文件,里边的内容有重叠,用union进行去重。 q -H -t "select * from test.log union select * from test1.log" [root@iZ2zebfzaequ90bdlz820sZ software]# cat test.log abc 2 3 4 5 [root@iZ2zebfzaequ90bdlz820sZ software]# cat test1.log abc 3 4 5 6 [root@iZ2zebfzaequ90bdlz820sZ software]# q -H -t "select * from test.log union select * from test1.log" Warning: column count is one - did you provide the correct delimiter? Warning: column count is one - did you provide the correct delimiter? 2 3 4 5 6 4、内容去重 比如统计某个路径下的./clicks.csv文件中,uuid字段去重后出现的总个数。 q -H -t "SELECT COUNT(DISTINCT(uuid)) FROM ./clicks.csv" 5、列类型自动检测 注意:q会理解每列是数字还是字符串,判断是根据实数值比较,还是字符串比较进行过滤,这里会用到-t命令。 q -H -t "SELECT request_id,score FROM ./clicks.csv WHERE score > 0.7 ORDER BY score DESC LIMIT 5" 6、字段运算 读取系统命令查询结果,计算/tmp目录中每个用户和组的总值。可以对字段进行运算处理。 sudo find /tmp -ls | q "SELECT c5,c6,sum(c7)/1024.0/1024 AS total FROM - GROUP BY c5,c6 ORDER BY total desc" [root@iZ2zebfzaequ90bdlz820sZ software]# sudo find /tmp -ls | q "SELECT c5,c6,sum(c7)/1024.0/1024 AS total FROM - GROUP BY c5,c6 ORDER BY total desc" www www 8.86311340332 root root 0.207922935486 mysql mysql 4.76837158203e-06 7、数据统计 统计系统拥有最多进程数的前 3个用户ID,按降序排序,这就需要和系统命令配合使用了,先查询所有进程再利用SQL筛选,这里的q命令就相当grep命令。 ps -ef | q -H "SELECT UID,COUNT(*) cnt FROM - GROUP BY UID ORDER BY cnt DESC LIMIT 3" [root@iZ2zebfzaequ90bdlz820sZ software]# ps -ef | q -H "SELECT UID,COUNT(*) cnt FROM - GROUP BY UID ORDER BY cnt DESC LIMIT 3" root 104 www 16 rabbitmq 4 [root@iZ2zebfzaequ90bdlz820sZ software]# ps -ef | q -H -O "SELECT UID,COUNT(*) cnt FROM - GROUP BY UID ORDER BY cnt DESC LIMIT 3" UID cnt root 110 www 16 rabbitmq 4 我们看到加与不加-O命令的区别就是否显示查询结果的标题。 8,连文件查 一般情况下,我们的日志文件会按天分割成很多个固定容量的子文件,在没有统一的日志收集服务器的情况下,如果不给个报错时间区间去查一个关键词,那么无异于大海捞针。 如果可以将所有文件内容合并后在查就会省事很多,q支持将文件像数据库表那样联合查询。 q -H "select * from douyin.log a join douyin-2021-06-18.0.log b on (a.c2=b.c3) where b.c1='root'" 总结 看完可能会有人抬杠:q写这么多代码直接用awk不香吗?额~ 介绍这个工具的初衷并不是说要替换现有哪种工具,而是多提供一种更为便捷的查日志方法。 我也有在用awk确实很强大没得说,但这里边涉及到一个学习成本的问题,琳琅满目的命令、匹配规则想玩转还是要下点功夫的。而对于新手程序员稍微有点数据库经验,写SQL问题都不大,上手q则会容易的多。 整理了几百本各类技术电子书,送给小伙伴们。关注公号回复【666】自行领取。和一些小伙伴们建了一个技术交流群,一起探讨技术、分享技术资料,旨在共同学习进步,如果感兴趣就加入我们吧! 电子书地址

优秀的个人博客,低调大师

阿里工程师亮出“刷脸神器

1. 背景介绍 疫情肆虐,有效隔离是尽快战胜病毒的有效手段,多个地方政府都提出了严格的居民出行管理条例,例如杭州市余杭区2月3日发布了实行“十项从严”管控措施: 这给社区管理带来新的挑战,传统门卫盯人存在以下几个问题: 进出人员情况全凭人工记录,出现错漏,不能及时对频繁外出居民有效劝阻。 缺乏全局角度对居民隔离整体情况的掌控和度量,例如有哪些人频繁出入,出入总人数。 为了解决居民出入管理的上述几个问题,阿里云智能数据库向量检索团队免费提供一套高度兼容戴口罩场景下的人脸识别模型,并基于AnalyticDB的向量检索能力, 搭建了一套小区人员管理的解决方案, 这个方案将开源给社区。 通过该方案可以有效的提升当下疫情中的小区出入管理效率.同时我们免费提供AnalyticDB给用户用于与当前肺炎疫情相关的出入管理应用。 下面首先介绍我们的方案,然后会对其中的人脸识别和AnalyticDB向量检索关键技术做详细介绍,方便开发者能够做二次开发,最后我们会附上开源地址。 2. 小区人员管理解决方案介绍 2.1小区人员管理解决方案功能 1)自动登记入册小区人口, 基本信息和人脸特征,界面如下: 2)通过摄像头自动做人脸识别,返回来访者家庭的所有出入记录。方便社区管理者进行高效的出入管理,在当前疫情环境下, 人们普遍佩戴口罩, 去掉口罩会增加肺炎感染的风险, 所以本方案提供一套支持戴口罩情况下人脸识别的算法, 演示效果如下: 3)可以通过人脸照片和结构化信息的任意组合来检索住户的来访记录,并提供统计分析能力,为小区管理者提供全局度量数据。 2.2 应用架构总体设计 出入管理系统的总体架构如下图所示,前端界面通过HTML和javascript实现, 功能包含支持戴口罩场景下的人脸门禁, 通过人脸识别查询来访者的全部家庭成员2日内的出入记录, 人员登记, 后台通过人脸和结构化信息自由组合搜索来访记录等功能.。 人脸识别模块将包含人脸的视频转换成人脸特征向量, 人脸识别模块主要使用了Seetafce引擎的人脸检测和人脸追踪模块和AnalyticDB团队自研的人脸识别, 眼部识别和口罩检测模型.AnalyticDB负责整个应用中的全部的结构化数据和人脸识别模块产生的人脸特征向量的存储和查询。 3. 关键技术介绍 3.1 针对疫情的人脸识别算法 算法流程如下图所示, 在人员登记过程中我们分别通过人脸识别模型和眼部识别模型提取登记人的面部整体特征和眼部特征, 并将提取的特征向量写入AnalyticDB。在查询过程中, 我们首先会通过口罩检测模型来检测来访人是否有佩戴口罩, 如果没有佩戴口罩, 我们会使用整体面部的特征在AnalyticDB中检索相似的特征, 如果有特征与来访者面部特征相似度满足阈值, 则返回对应的结果。 如果来访者有佩戴口罩, 那么鼻子、嘴巴等特征会缺失, 使用整体面部特征提取模型无法准确的检索到正确的记录。这时我们会使用眼部识别模型提取来访者眼部, 额头等不会被口罩遮挡的部位的特征, 然后再AnalyticDB中检索之前保存的眼部特征。 系统中使用的人脸识别模型, 眼部识别模型和口罩检测模型将全部开源给社区。经过测试口罩检测模型的准确率>99.5%. 人脸识别模型和眼部识别模型在学术界常用的数据集上的准确率如下表所示。 可以看到仅仅使用眼部特征, AnalyticDB的模型在LFW数据集上仍然有99+%以上的识别准确率.。 3.2 AnalyticDB向量版特性介绍 分析型数据库(AnalyticDB)是阿里云上的一种高并发低延时的PB级实时数据仓库,可以毫秒级针对万亿级数据进行即时的多维分析透视和业务探索。 AnalyticDB for MySQL 全面兼容MySQL协议以及SQL:2003 语法标准, AnalyticDB forPostgreSQL 支持标准 SQL:2003,高度兼容 Oracle 语法生态. 目前两款产品都包含向量检索功能, 可以支持人脸, 人体, 车辆等的相似查询和推荐系统。 目前AnalyticDB在真实应用场景中可以支持10亿级别的向量数据的查询, 100毫秒级别的响应时间. AnalyticDB已经在多个城市的安防项目中大规模部署。 在一般的包含向量检索的的应用系统中, 通常开发者会使用向量检索引擎(例如Faiss)来存储向量数据, 然后使用关系型数据库存储结构化数据. 在查询时也需要交替查询两个系统, 这种方案会有额外的开发工作并且性能也不是最优。 AnalyticDB支持结构化数据和非结构化数据(向量)的检索,仅仅使用SQL接口就可以快速的搭建起以图搜图或者图片+结构化数据混合检索等功能. AnalyticDB的优化器在混合检索场景中会根据数据的分布和查询的条件选择最优的执行计划,在保证召回的同时,得到最优的性能。 在我们的出入管理系统中, 我们通过AnalyticDB实现了同时使用照片, 性别, 年龄, 起始时间, 终止时间来查询出入记录的功能。 这样的以图搜图+结构化搜索功能, 可以通过一条SQL实现: 其中表demo.person存储了每个人的基本信息,demo.face_feature存储了人脸特征向量, demo.access_record存储了所有的来访记录. pid是每个人的独有ID。 结构化信息+非结构化信息(图片)混合检索在实际应用中被广泛使用的. 例如在人脸门禁系统被部署在多个小区时, 我们使用一张表存储了所有小区的人脸特征, 在人脸检索时我们只需要检索当前小区的人脸特征. 在这种情况下, 使用AnalyticDB我们只需要在SQL中增加where 小区名 ='xxx' 就可以轻易实现。 结尾 复制下方链接至浏览器打开或者识别下方二维码,即可查看项目开源详情: https://github.com/aliyun/alibabacloud-AnalyticDB-python-demo-face-recognition

优秀的个人博客,低调大师

阿里AI再出神器,“你是什么垃圾”一拍便知

“干垃圾,还是湿垃圾?你是什么垃圾?” 相信魔都的小伙伴已经要被垃圾分类逼疯了,还要面临垃圾桶前,志愿者们的灵魂一问:“你是什么垃圾?” 更糟糕的是,垃圾分类,还要“自学成才”,没人可问。 想人之所想,急人之所急,阿里AI懂你。 经过48小时紧急开发,阿里志愿者紧急开发了AI智能识别垃圾功能(测试版)在手机淘宝上线,这款功能通过阿里云搭建。 直接进入拍立淘,点击“戳我识别垃圾分类”的按钮,即可进入垃圾识别功能。 或者,打开手机淘宝搜索“你是什么垃圾”,系统可以通过阿里云异构计算能力进行快速智能识别,直接进入垃圾识别功能。 (淘宝已上线AI识别垃圾分类功能) 对于AI难以识别的垃圾,公众可以手动输入垃圾信息,与阿里AI共建垃圾分类数据库,而数据库也将上传至云端,并不断自我训练以AI提升识别能力。 (用户可补充垃圾分类信息到云端数据库) 事情源于最近大热

优秀的个人博客,低调大师

ElasticJob-分布式作业调度神器,你们还在用Quartz吗?!

简介 Elastic-Job是一个分布式调度解决方案,由两个相互独立的子项目Elastic-Job-Lite和Elastic-Job-Cloud组成。 Elastic-Job-Lite定位为轻量级无中心化解决方案,使用jar包的形式提供分布式任务的协调服务。 功能列表 1、任务分片 将整体任务拆解为多个子任务 可通过服务器的增减弹性伸缩任务处理能力 分布式协调,任务服务器上下线的全自动发现与处理 2、 多任务类型 基于时间驱动的任务 基于数据驱动的任务(TBD) 同时支持常驻任务和瞬时任务 多语言任务支持 3、云原生 完美结合Mesos或Kubernetes等调度平台 任务不依赖于IP、磁盘、数据等有状态组件 合理的资源调度,基于Netflix的Fenzo进行资源分配 4、容错性 支持定时自我故障检测与自动修复 分布式任务分片唯一性保证 支持失效转移和错过任务重触发 5、任务聚合 相同任务聚合至相同的执行器统一处理 节省系统资源与初始化开销 动态调配追加资源至新分配的任务 6、易用性 完善的运维平台 提供任务执行历史数据追踪能力 注册中心数据一键dump用于备份与调试问题 整体架构图 Elastic-Job-Lite Elastic-Job-Cloud 参考 官网:http://elasticjob.io/index_zh.html 码云:https://gitee.com/elasticjob GitHub:https://github.com/elasticjob/elastic-job 采用公司:http://elasticjob.io/docs/elastic-job-lite/00-overview/company 推荐阅读 成为架构师的四阶段学习资料 分享一套高级Java笔试题(实拍高清图) 春节跳槽最新Java面试题及答案整理 长按关注,更多精彩!

优秀的个人博客,低调大师

英伟达公布Jetson TX2 细节,堪称人工智能神器

Jetson TX2不仅性能优异,而且体积也很小,想必会成为人工智能领域的“爆款”模块。 就在本周,英伟达正式发布发布了旗下新款嵌入式开发模块Jetson TX2,该开发模块针对无人机、自动驾驶车辆、医疗工业设备等。这一仅有信用卡大小的平台可为终端应用提供人工智能计算支持,必将会成为人工智能领域的“爆款”模块。 在Jetson TX2推出之前,Nvidia还推出具有同样应用场景的Jetson TX1和TK1等嵌入式计算产品。Nvidia 副总裁兼 Tegra 业务总经理 Deepu Talla 表示:“这些设备可为智能视频分析提供支撑,让我们的城市变得更智能和更安全;或者优化新型机器人的制造、让它的长距离工作更具效率”。 据悉,Jetson TX2所提供的性能为早前版本的两倍,即能够以两倍以上的功效运行,且功率低于7.5瓦。这使得Jetson TX2能够在终端应用上运行更庞大、更深度的神经网络,让设备更加智能,具有更高的精度和更快的响应时间,以执行如图像分类、导航和语音识别等任务。 可以说Jetson TX2是NVIDIA嵌入式计算系列产品继Jetson TK1和TX1之后的又一突破。Jetson是一款开放式平台,无论是企业、初创公司、研究人员或高中生,任何人都能够访问并借助其为终端应用开发高级人工智能解决方案。 目前,NVIDIA Jetson TX2 开发套件已开放预定,出货时间为 2017 年 3 月 14 日,美欧市场售价为 599 美元(约合 4131 元 RMB)。另外,NVIDIA Jetson TX2 的标准模块会在 2 季度上市,千批采购价为 399 美元(约合 2752 元 RMB)。 原文发布时间: 2017-03-09 09:31 本文作者: JOKER 本文来自云栖社区合作伙伴镁客网,了解相关信息可以关注镁客网。

优秀的个人博客,低调大师

VR界的神器WakingApp让你零基础制作VR内容

WakingApp最新更新的系统版本,让任何人都可以为Oculus和Vive头显创作内容。 去年11月份完成C轮融资的WakingApp,最近发布了最新版本的VR/AR内容创作平台ENTiTi,将支持程序小白用户为Oculus Rift和HTC Vive头显创作属于自己的内容和游戏。 WakingApp是来自以色列的一家公司,他们的核心产品是一款基于云的创作平台ENTiTi,用户可通过ENTiTi平台上传文档、图片、视频、3D模型等内容,通过3D视角对上述原材料以及平台自带的工具进行查看编辑;其次通过可视化的逻辑系统建立VR/AR领域所特有的交互关系;最后所生产的内容还可通过WakingApp及合作平台进行分享与体验。简单地说,ENTiTi有点类似H5制作工具里大家熟知的易企秀、人人秀等,又有点像游戏《我的世界》,不需要任何特殊技能即可完成创建内容,并可以和朋友分享成果。 WakingApp在今年上半年就已经开放了相关平台,让所有人都可以为GearVR,Cardboard等头显创作内容。现在该应用再次更新,可以支持Oculus和Vive的内容创作。 WakingApp的董事长Alon Melchner表示:“我们的目标是为大家带来像虚拟现实、增强现实和物联网这样的未来科技,让每个人都可以参与其中,成为内容创作者,而不是当一个单纯的观众。”Alon Melchner还说,WakingApp下一次更新将会让VR和AR作为物联网的用户界面。 据了解到现在为止,并没有人通过WakingApp创作出一个完整的VR内容系统,但是WakingApp的出现,让VR和AR变得不再那么遥不可及,它会激发更多的人加入到内容创作,对于推动VR和AR产业是有很大的益处的。 原文发布时间: 2016-06-17 14:44 本文作者: 巫盼 本文来自云栖社区合作伙伴镁客网,了解相关信息可以关注镁客网。

优秀的个人博客,低调大师

Android图片加载神器之Fresco,基于各种使用场景的讲解

Fresco是Facebook开源Android平台上一个强大的图片加载库,也是迄今为止Android平台上最强大的图片加载库。 优点:相对于其他开源的第三方图片加载库,Fresco拥有更好的内存管理和强大的功能,基本上能满足所有的日常使用场景。 缺点:整体比较大,不过目前的版本已做了拆分,你只需要导入你使用到的功能相关的库。从代码层面来说侵入性太强,体现在要使用它需要用Fresco的组件SimpleDraweeView替换掉Android原生图片显示组件ImageView,这也是很多人不愿意在项目中接入Fresco的主要原因。 特性: 1、内存管理 解压后的图片,即Android中的Bitmap,占用大量的内存。大的内存占用势必引发更加频繁的GC。在5.0以下,GC将会显著地引发界面卡顿。 在5.0以下系统,Fresco将图片放到一个特别的内存区域。当然,在图片不显示的时候,占用的内存会自动被释放。这会使得APP更加流畅,减少因图片内存占用而引发的OOM。 2、Image Pipeline Fresco中设计有一个叫做 Image Pipeline 的模块。它负责从网络,从本地文件系统,本地资源加载图片和管理。为了最大限度节省空间和CPU时间,它含有3级缓存设计(2级内存,1级磁盘)。两个内存缓存为Bitmap缓存和未解码的图片缓存,这样既可以加快图片的加载速度,又能节省内存的占用(解码后的图片就是Bitmap,其占用内存相对未解码的图片数据而言会大很多)。 Image pipeline 负责完成加载图像,变成Android设备可呈现的形式所要经历的大致流程如下: a、根据Uri在已解码的(Bitmap缓存)内存缓存中查找,找到了则返回Bitmap对象;如果没找到,则开启后台线程开始后续的工作。 b、根据Uri在未解码的内存缓存中查找,若找到了则解码,然后缓存到已解码的内存缓存中,并且返回Bitmap对象。 d、如果在未解码的内存缓存中没找到,则根据Uri在磁盘缓存中查找,若找到了则读取数据(byte数组),并缓存到未解码的内存缓存中,解码、然后缓存到已解码的内存缓存中,并且返回Bitmap对象。 e、如果在磁盘缓存中没找到,则从网络或者本地加载数据。加载完成后,依次缓存到磁盘缓存、未解码的内存缓存中。解码、然后缓存到已解码的内存缓存中,并且返回Bitmap对象。 其流程图如下: 3、Drawees Fresco 中设计有一个叫做 Drawees 模块,负责图片的呈现。它由三个元素组成分别是: DraweeView 继承于 View, 负责图片的显示。 DraweeHierarchy 用于组织和维护最终绘制和呈现的 Drawable 对象。 DraweeController 负责和ImagePipeline的交互,可以创建一个这个类的实例,来实现对所要显示的图片做更多的控制。 一般情况下,使用 SimpleDraweeView 即可,你可以配置其XML属性来实现各式各样的展示效果。 a、在图片加载完成前显示占位图; b、在图片加载的过程中显示加载进度图; c、加载成功后,将占位图或者加载进度图,自动替换为目标图片。 d、加载失败后,它会显示加载失败的图(若没配置加载失败的图,则显示的是占位图) e、加载失败后,若配置过重试图,则会显示重试图,用户点击可以重新去加载图片(默认配置可重试3次) f、自定义居中焦点(配合Google提供的服务可以实现人脸识别,经测试国内目前使用不了) g、显示圆角图、圆形图和圆圈; h、添加覆盖物(图层叠加); j、 实现图片的按下效果; k、图片的渐进式呈现;(目前只支持Jpeg格式的图片) x、当图片不再显示在屏幕上时,它会及时地释放内存和空间占用。 4、Fresco目前所支持的图片格式 a、静态图:png、jpg、web b、动态图:gif、web格式的gif 以上聊了这么多,大概意思就是Fresco出身名门,很好很强大,超牛逼!接下来我们来聊聊在项目中的具体使用。我专门写了一个针对Fresco的使用帮助库,先给大家看看Demo的运行效果图: 常见的各种效果 从网络加载的图片墙 点击图片墙中的照片后,打开的浏览大图界面 一、Fresco的引入及ImagePipeline参数配置 1、在build.gradle文件中添加依赖 dependencies { // ...... compile 'com.facebook.fresco:fresco:0.14.1' compile 'com.facebook.fresco:animated-base-support:0.14.1' compile 'com.facebook.fresco:animated-gif:0.14.1' compile 'com.facebook.fresco:webpsupport:0.14.1' compile 'com.facebook.fresco:animated-webp:0.14.1' compile 'com.facebook.fresco:imagepipeline-okhttp3:0.14.1' } 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 a、在 API < 14 上的机器支持 WebP 时,需要添加以下依赖 compile 'com.facebook.fresco:animated-base-support:0.14.1' 1 1 b、支持GIF动图,需要添加以下依赖 compile 'com.facebook.fresco:animated-gif:0.14.1' 1 1 c、支持WebP,需要添加以下依赖 compile 'com.facebook.fresco:webpsupport:0.14.1' 1 1 d、支持WebP动图,需要添加以下依赖 compile 'com.facebook.fresco:animated-webp:0.14.1' 1 1 e、网络实现层想使用okhttp3,需要添加以下依赖 compile 'com.facebook.fresco:imagepipeline-okhttp3:0.14.1' 1 1 2、ImagePipeline配置 a、磁盘缓存目录,推荐缓存到应用本身的缓存文件夹,这么做的好处是:当应用被用户卸载后能自动清除缓存,增加用户好感(可能以后用得着时,还会想起我);一些内存清理软件可以扫描出来,进行内存的清理。 File fileCacheDir = context.getApplicationContext().getCacheDir(); 1 1 b、配置磁盘缓存,大部分的应用有一个磁盘缓存就够了,但是在一些情况下,你可能需要两个缓存。比如你想把小文件放在一个缓存中(50*50及以下尺寸),大文件放在另外一个文件中,这样小文件就不会因大文件的频繁变动而被从缓存中移除。 DiskCacheConfig mainDiskCacheConfig = DiskCacheConfig.newBuilder(context) .setBaseDirectoryName(IMAGE_PIPELINE_CACHE_DIR) .setBaseDirectoryPath(fileCacheDir) .build(); DiskCacheConfig smallDiskCacheConfig = DiskCacheConfig.newBuilder(context) .setBaseDirectoryPath(fileCacheDir) .setBaseDirectoryName(IMAGE_PIPELINE_SMALL_CACHE_DIR) .setMaxCacheSize(MAX_DISK_SMALL_CACHE_SIZE) .setMaxCacheSizeOnLowDiskSpace(MAX_DISK_SMALL_ONLOWDISKSPACE_CACHE_SIZE) .build(); 1 2 3 4 5 6 7 8 9 10 11 1 2 3 4 5 6 7 8 9 10 11 c、ImagePipeline的完整配置代码如下: package com.facebook.fresco.helper.config; import android.app.ActivityManager; import android.content.Context; import android.graphics.Bitmap; import com.facebook.cache.disk.DiskCacheConfig; import com.facebook.common.logging.FLog; import com.facebook.common.memory.MemoryTrimType; import com.facebook.common.memory.MemoryTrimmable; import com.facebook.common.memory.MemoryTrimmableRegistry; import com.facebook.common.memory.NoOpMemoryTrimmableRegistry; import com.facebook.common.util.ByteConstants; import com.facebook.drawee.backends.pipeline.Fresco; import com.facebook.fresco.helper.utils.MLog; import com.facebook.imagepipeline.backends.okhttp3.OkHttpImagePipelineConfigFactory; import com.facebook.imagepipeline.core.ImagePipelineConfig; import com.facebook.imagepipeline.decoder.ProgressiveJpegConfig; import com.facebook.imagepipeline.image.ImmutableQualityInfo; import com.facebook.imagepipeline.image.QualityInfo; import com.facebook.imagepipeline.listener.RequestListener; import com.facebook.imagepipeline.listener.RequestLoggingListener; import java.io.File; import java.util.HashSet; import java.util.Set; import okhttp3.OkHttpClient; import okhttp3.logging.HttpLoggingInterceptor; /** * * Created by android_ls on 16/9/8. */ public class ImageLoaderConfig { private static final String IMAGE_PIPELINE_CACHE_DIR = "image_cache"; private static final String IMAGE_PIPELINE_SMALL_CACHE_DIR = "image_small_cache"; private static final int MAX_DISK_SMALL_CACHE_SIZE = 10 * ByteConstants.MB; private static final int MAX_DISK_SMALL_ONLOWDISKSPACE_CACHE_SIZE = 5 * ByteConstants.MB; private static ImagePipelineConfig sImagePipelineConfig; /** * Creates config using android http stack as network backend. */ public static ImagePipelineConfig getImagePipelineConfig(final Context context) { if (sImagePipelineConfig == null) { /** * 推荐缓存到应用本身的缓存文件夹,这么做的好处是: * 1、当应用被用户卸载后能自动清除缓存,增加用户好感(可能以后用得着时,还会想起我) * 2、一些内存清理软件可以扫描出来,进行内存的清理 */ File fileCacheDir = context.getApplicationContext().getCacheDir(); // if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { // fileCacheDir = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/Fresco"); // } DiskCacheConfig mainDiskCacheConfig = DiskCacheConfig.newBuilder(context) .setBaseDirectoryName(IMAGE_PIPELINE_CACHE_DIR) .setBaseDirectoryPath(fileCacheDir) .build(); DiskCacheConfig smallDiskCacheConfig = DiskCacheConfig.newBuilder(context) .setBaseDirectoryPath(fileCacheDir) .setBaseDirectoryName(IMAGE_PIPELINE_SMALL_CACHE_DIR) .setMaxCacheSize(MAX_DISK_SMALL_CACHE_SIZE) .setMaxCacheSizeOnLowDiskSpace(MAX_DISK_SMALL_ONLOWDISKSPACE_CACHE_SIZE) .build(); FLog.setMinimumLoggingLevel(FLog.VERBOSE); Set<RequestListener> requestListeners = new HashSet<>(); requestListeners.add(new RequestLoggingListener()); // 当内存紧张时采取的措施 MemoryTrimmableRegistry memoryTrimmableRegistry = NoOpMemoryTrimmableRegistry.getInstance(); memoryTrimmableRegistry.registerMemoryTrimmable(new MemoryTrimmable() { @Override public void trim(MemoryTrimType trimType) { final double suggestedTrimRatio = trimType.getSuggestedTrimRatio(); MLog.i(String.format("Fresco onCreate suggestedTrimRatio : %d", suggestedTrimRatio)); if (MemoryTrimType.OnCloseToDalvikHeapLimit.getSuggestedTrimRatio() == suggestedTrimRatio || MemoryTrimType.OnSystemLowMemoryWhileAppInBackground.getSuggestedTrimRatio() == suggestedTrimRatio || MemoryTrimType.OnSystemLowMemoryWhileAppInForeground.getSuggestedTrimRatio() == suggestedTrimRatio ) { // 清除内存缓存 Fresco.getImagePipeline().clearMemoryCaches(); } } }); HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor(); loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY); OkHttpClient okHttpClient = new OkHttpClient.Builder() .addInterceptor(loggingInterceptor) // .retryOnConnectionFailure(false) .build(); sImagePipelineConfig = OkHttpImagePipelineConfigFactory.newBuilder(context, okHttpClient) // sImagePipelineConfig = ImagePipelineConfig.newBuilder(context) .setBitmapsConfig(Bitmap.Config.RGB_565) // 若不是要求忒高清显示应用,就用使用RGB_565吧(默认是ARGB_8888) .setDownsampleEnabled(true) // 在解码时改变图片的大小,支持PNG、JPG以及WEBP格式的图片,与ResizeOptions配合使用 // 设置Jpeg格式的图片支持渐进式显示 .setProgressiveJpegConfig(new ProgressiveJpegConfig() { @Override public int getNextScanNumberToDecode(int scanNumber) { return scanNumber + 2; } public QualityInfo getQualityInfo(int scanNumber) { boolean isGoodEnough = (scanNumber >= 5); return ImmutableQualityInfo.of(scanNumber, isGoodEnough, false); } }) .setRequestListeners(requestListeners) .setMemoryTrimmableRegistry(memoryTrimmableRegistry) // 报内存警告时的监听 // 设置内存配置 .setBitmapMemoryCacheParamsSupplier(new BitmapMemoryCacheParamsSupplier( (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE))) .setMainDiskCacheConfig(mainDiskCacheConfig) // 设置主磁盘配置 .setSmallImageDiskCacheConfig(smallDiskCacheConfig) // 设置小图的磁盘配置 .build(); } return sImagePipelineConfig; } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 d、替换网络实现为okhttp3 OkHttpClient okHttpClient = new OkHttpClient.Builder() .addInterceptor(loggingInterceptor) // .retryOnConnectionFailure(false) .build(); sImagePipelineConfig = OkHttpImagePipelineConfigFactory.newBuilder(context, okHttpClient) 1 2 3 4 5 6 1 2 3 4 5 6 e、支持调试时,显示图片加载的Log FLog.setMinimumLoggingLevel(FLog.VERBOSE); Set<RequestListener> requestListeners = new HashSet<>(); requestListeners.add(new RequestLoggingListener()); 1 2 3 1 2 3 f、内存缓存配置完整代码: package com.facebook.fresco.helper.config; import android.app.ActivityManager; import android.os.Build; import com.facebook.common.internal.Supplier; import com.facebook.common.util.ByteConstants; import com.facebook.fresco.helper.utils.MLog; import com.facebook.imagepipeline.cache.MemoryCacheParams; /** * 内存缓存配置 * https://github.com/facebook/fresco/issues/738 * * Created by android_ls on 16/9/8. */ public class BitmapMemoryCacheParamsSupplier implements Supplier<MemoryCacheParams> { private final ActivityManager mActivityManager; public BitmapMemoryCacheParamsSupplier(ActivityManager activityManager) { mActivityManager = activityManager; } @Override public MemoryCacheParams get() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { return new MemoryCacheParams(getMaxCacheSize(), // 内存缓存中总图片的最大大小,以字节为单位。 56, // 内存缓存中图片的最大数量。 Integer.MAX_VALUE, // 内存缓存中准备清除但尚未被删除的总图片的最大大小,以字节为单位。 Integer.MAX_VALUE, // 内存缓存中准备清除的总图片的最大数量。 Integer.MAX_VALUE); // 内存缓存中单个图片的最大大小。 } else { return new MemoryCacheParams( getMaxCacheSize(), 256, Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE); } } private int getMaxCacheSize() { final int maxMemory = Math.min(mActivityManager.getMemoryClass() * ByteConstants.MB, Integer.MAX_VALUE); MLog.i(String.format("Fresco Max memory [%d] MB", (maxMemory/ByteConstants.MB))); if (maxMemory < 32 * ByteConstants.MB) { return 4 * ByteConstants.MB; } else if (maxMemory < 64 * ByteConstants.MB) { return 6 * ByteConstants.MB; } else { // We don't want to use more ashmem on Gingerbread for now, since it doesn't respond well to // native memory pressure (doesn't throw exceptions, crashes app, crashes phone) if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) { return 8 * ByteConstants.MB; } else { return maxMemory / 4; } } } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 g、初始化Fresco Fresco.initialize(context,ImageLoaderConfig.getImagePipelineConfig(context)); 1 1 二、Fresco的各种使用场景 从网络加载一张图片 String url = "http://ww3.sinaimg.cn/large/610dc034jw1f6m4aj83g9j20zk1hcww3.jpg"; ImageLoader.loadImage((SimpleDraweeView)findViewById(R.id.sdv_1), url); 1 2 1 2 1、显示一张图片 <com.facebook.drawee.view.SimpleDraweeView android:id="@+id/sdv_1" android:layout_width="90dp" android:layout_height="90dp" app:actualImageScaleType="centerCrop"/> 1 2 3 4 5 1 2 3 4 5 效果图如下: 2、显示一张圆形图片 <com.facebook.drawee.view.SimpleDraweeView android:id="@+id/sdv_2" android:layout_width="90dp" android:layout_height="90dp" android:layout_marginTop="15dp" app:actualImageScaleType="centerCrop" app:roundAsCircle="true"/> 1 2 3 4 5 6 7 1 2 3 4 5 6 7 效果图如下: 3、显示一张圆形带边框的图片 <com.facebook.drawee.view.SimpleDraweeView android:id="@+id/sdv_3" android:layout_width="90dp" android:layout_height="90dp" android:layout_marginTop="15dp" app:actualImageScaleType="centerCrop" app:roundAsCircle="true" app:roundingBorderColor="#fff3cf44" app:roundingBorderWidth="2dp"/> 1 2 3 4 5 6 7 8 9 1 2 3 4 5 6 7 8 9 效果图如下: 4、显示一张圆角图片 <com.facebook.drawee.view.SimpleDraweeView android:id="@+id/sdv_4" android:layout_width="90dp" android:layout_height="90dp" android:layout_marginTop="15dp" app:actualImageScaleType="centerCrop" app:roundAsCircle="false" app:roundedCornerRadius="10dp"/> 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8 效果图如下: 5、显示一张底部是圆角的图片 <com.facebook.drawee.view.SimpleDraweeView android:id="@+id/sdv_5" android:layout_width="90dp" android:layout_height="90dp" android:layout_marginTop="15dp" app:actualImageScaleType="centerCrop" app:roundAsCircle="false" app:roundedCornerRadius="10dp" app:roundTopLeft="false" app:roundTopRight="false" app:roundBottomLeft="true" app:roundBottomRight="true"/> 1 2 3 4 5 6 7 8 9 10 11 12 1 2 3 4 5 6 7 8 9 10 11 12 效果图如下: 6、显示一张左上和右下是圆角的图片 <com.facebook.drawee.view.SimpleDraweeView android:id="@+id/sdv_6" android:layout_width="90dp" android:layout_height="90dp" android:layout_marginTop="15dp" app:actualImageScaleType="centerCrop" app:roundAsCircle="false" app:roundedCornerRadius="10dp" app:roundTopLeft="true" app:roundTopRight="false" app:roundBottomLeft="false" app:roundBottomRight="true"/> 1 2 3 4 5 6 7 8 9 10 11 12 1 2 3 4 5 6 7 8 9 10 11 12 效果图如下: 7、设置占位图 <com.facebook.drawee.view.SimpleDraweeView android:id="@+id/sdv_7" android:layout_width="90dp" android:layout_height="90dp" android:layout_marginTop="15dp" app:actualImageScaleType="centerCrop" app:placeholderImage="@mipmap/ic_launcher" app:placeholderImageScaleType="centerCrop" /> 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8 8、带动画的显示(从半透明到不透明) <com.facebook.drawee.view.SimpleDraweeView android:id="@+id/sdv_8" android:layout_width="90dp" android:layout_height="90dp" android:layout_marginTop="15dp" app:actualImageScaleType="centerCrop" app:fadeDuration="3000"/> 1 2 3 4 5 6 7 1 2 3 4 5 6 7 9、图层叠加显示 <com.facebook.drawee.view.SimpleDraweeView android:id="@+id/sdv_10" android:layout_width="90dp" android:layout_height="90dp" android:layout_marginTop="15dp" app:actualImageScaleType="centerCrop" app:overlayImage="@mipmap/ic_launcher"/> 1 2 3 4 5 6 7 1 2 3 4 5 6 7 10、其它的属性的配置,比如加载进度、加载失败、重试图 <com.facebook.drawee.view.SimpleDraweeView android:id="@+id/sdv_11" android:layout_width="90dp" android:layout_height="90dp" android:layout_marginTop="15dp" app:actualImageScaleType="centerCrop" app:failureImage="@mipmap/ic_launcher" app:failureImageScaleType="centerInside" app:retryImage="@mipmap/ic_launcher" app:retryImageScaleType="centerCrop" app:progressBarImage="@mipmap/ic_launcher" app:progressBarImageScaleType="centerCrop" app:progressBarAutoRotateInterval="5000"/> 1 2 3 4 5 6 7 8 9 10 11 12 13 1 2 3 4 5 6 7 8 9 10 11 12 13 11、从本地文件(比如SDCard上)加载图片 public static void loadFile(final SimpleDraweeView draweeView, String filePath, final int reqWidth, final int reqHeight) { Uri uri = new Uri.Builder() .scheme(UriUtil.LOCAL_FILE_SCHEME) .path(filePath) .build(); ImageRequest request = ImageRequestBuilder.newBuilderWithSource(uri) .setRotationOptions(RotationOptions.autoRotate()) .setLocalThumbnailPreviewsEnabled(true) .setResizeOptions(new ResizeOptions(reqWidth, reqHeight)) .build(); DraweeController controller = Fresco.newDraweeControllerBuilder() .setImageRequest(request) .setOldController(draweeView.getController()) .setControllerListener(new BaseControllerListener<ImageInfo>() { @Override public void onFinalImageSet(String id, @Nullable ImageInfo imageInfo, @Nullable Animatable anim) { if (imageInfo == null) { return; } ViewGroup.LayoutParams vp = draweeView.getLayoutParams(); vp.width = reqWidth; vp.height = reqHeight; draweeView.requestLayout(); } }) .build(); draweeView.setController(controller); } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 使用: ImageLoader.loadFile((SimpleDraweeView)itemView, photoInfo.thumbnailUrl, 120, 120); 1 1 12、从本地资源(Resources)加载图片 public static void loadDrawable(SimpleDraweeView draweeView, int resId) { Uri uri = new Uri.Builder() .scheme(UriUtil.LOCAL_RESOURCE_SCHEME) .path(String.valueOf(resId)) .build(); DraweeController controller = Fresco.newDraweeControllerBuilder() .setUri(uri) .setOldController(draweeView.getController()) .build(); draweeView.setController(controller); } 1 2 3 4 5 6 7 8 9 10 11 1 2 3 4 5 6 7 8 9 10 11 使用: ImageLoader.loadDrawable(simpleDraweeView, R.drawable.meizi); 1 1 效果图如下: 13、对图片进行性高斯模糊处理 public static void loadImageBlur(final SimpleDraweeView draweeView, String url) { loadImage(draweeView, url, new BasePostprocessor() { @Override public String getName() { return "blurPostprocessor"; } @Override public void process(Bitmap bitmap) { BitmapBlurHelper.blur(bitmap, 35); } }); } 1 2 3 4 5 6 7 8 9 10 11 12 13 1 2 3 4 5 6 7 8 9 10 11 12 13 其内部调用的方法 public static void loadImage(SimpleDraweeView simpleDraweeView, String url, BasePostprocessor processor) { if (TextUtils.isEmpty(url)) { return; } Uri uri = Uri.parse(url); ImageRequest request = ImageRequestBuilder.newBuilderWithSource(uri) .setRotationOptions(RotationOptions.autoRotate()) .setPostprocessor(processor) .build(); DraweeController controller = Fresco.newDraweeControllerBuilder() .setImageRequest(request) .setOldController(simpleDraweeView.getController()) .build(); simpleDraweeView.setController(controller); } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 使用: String url = "http://a.hiphotos.baidu.com/image/pic/item/55e736d12f2eb938d3de795ad0628535e4dd6fe2.jpg"; SimpleDraweeView simpleDraweeView = (SimpleDraweeView)findViewById(R.id.sdv_1); simpleDraweeView.setAspectRatio(0.7f); ViewGroup.LayoutParams lvp = simpleDraweeView.getLayoutParams(); lvp.width = DensityUtil.getDisplayWidth(this); ImageLoader.loadImageBlur(simpleDraweeView, url, DensityUtil.getDisplayWidth(this), DensityUtil.getDisplayHeight(this)); 1 2 3 4 5 6 7 8 9 10 11 1 2 3 4 5 6 7 8 9 10 11 效果图如下: 14、我们知道使用Fresco加载并显示一张图片,需要指定SimpleDraweeView的宽高或者指定其中一个值并设置宽高比,可是我真的不知道要显示的图片有多大,该显示多大?可以帮我搞定吗?答案是肯定的。 String url = "http://feed.chujianapp.com/20161108/452ab5752287a99a1b5387e2cd849006.jpg@1080w"; SimpleDraweeView simpleDraweeView = (SimpleDraweeView)findViewById(R.id.sdv_1); ImageLoader.loadImage(simpleDraweeView, url, new SingleImageControllerListener(simpleDraweeView)); 1 2 3 4 1 2 3 4 15、从网络加载并显示gif格式的图片 String url = "http://img4.178.com/acg1/201506/227753817857/227754566617.gif"; SimpleDraweeView simpleDraweeView = (SimpleDraweeView)findViewById(R.id.sdv_1); ImageLoader.loadImage(simpleDraweeView, url); 1 2 3 4 1 2 3 4 16、加载并显示webp格式的图片 SimpleDraweeView simpleDraweeView = (SimpleDraweeView)findViewById(R.id.sdv_1); ViewGroup.LayoutParams lvp = simpleDraweeView.getLayoutParams(); lvp.width = DensityUtil.getDisplayWidth(this); simpleDraweeView.setAspectRatio(0.6f); // 设置宽高比 ImageLoader.loadDrawable(simpleDraweeView, R.drawable.meizi_webp, DensityUtil.getDisplayWidth(this), DensityUtil.getDisplayHeight(this)); 1 2 3 4 5 6 7 1 2 3 4 5 6 7 其中R.drawable.meizi_webp为meizi_webp.webp 17、从内存缓存中移除指定图片的缓存 if (!TextUtils.isEmpty(photoInfo.originalUrl)) { ImagePipeline imagePipeline = Fresco.getImagePipeline(); Uri uri = Uri.parse(photoInfo.originalUrl); if (imagePipeline.isInBitmapMemoryCache(uri)) { imagePipeline.evictFromMemoryCache(uri); } } 1 2 3 4 5 6 7 1 2 3 4 5 6 7 18、从磁盘缓存中移除指定图片的缓存 ImagePipeline imagePipeline = Fresco.getImagePipeline(); Uri uri = Uri.parse(photoInfo.originalUrl); // 下面的操作是异步的 if (imagePipeline.isInDiskCacheSync(uri)) { imagePipeline.evictFromDiskCache(uri); } 1 2 3 4 5 6 1 2 3 4 5 6 19、清空磁盘缓存 Fresco.getImagePipeline().clearDiskCaches(); 1 1 20、清空内存缓存 Fresco.getImagePipeline().clearMemoryCaches(); 1 1 21、清空缓存(内存缓存 + 磁盘缓存) Fresco.getImagePipeline().clearCaches(); 1 1 22、在列表视图滚动时,不加载图片,等滚动停止后再开始加载图片,提升列表视图的滚动流畅度。 // 需要暂停网络请求时调用 public static void pause(){ Fresco.getImagePipeline().pause(); } // 需要恢复网络请求时调用 public static void resume(){ Fresco.getImagePipeline().resume(); } 1 2 3 4 5 6 7 8 9 1 2 3 4 5 6 7 8 9 23、下载图片存储到指定的路径 /** * 从网络下载图片 * 1、根据提供的图片URL,获取图片数据流 * 2、将得到的数据流写入指定路径的本地文件 * * @param url URL * @param loadFileResult LoadFileResult */ public static void downloadImage(Context context, String url, final DownloadImageResult loadFileResult) { if (TextUtils.isEmpty(url)) { return; } Uri uri = Uri.parse(url); ImagePipeline imagePipeline = Fresco.getImagePipeline(); ImageRequestBuilder builder = ImageRequestBuilder.newBuilderWithSource(uri); ImageRequest imageRequest = builder.build(); // 获取未解码的图片数据 DataSource<CloseableReference<PooledByteBuffer>> dataSource = imagePipeline.fetchEncodedImage(imageRequest, context); dataSource.subscribe(new BaseDataSubscriber<CloseableReference<PooledByteBuffer>>() { @Override public void onNewResultImpl(DataSource<CloseableReference<PooledByteBuffer>> dataSource) { if (!dataSource.isFinished() || loadFileResult == null) { return; } CloseableReference<PooledByteBuffer> imageReference = dataSource.getResult(); if (imageReference != null) { final CloseableReference<PooledByteBuffer> closeableReference = imageReference.clone(); try { PooledByteBuffer pooledByteBuffer = closeableReference.get(); InputStream inputStream = new PooledByteBufferInputStream(pooledByteBuffer); String photoPath = loadFileResult.getFilePath(); Log.i("ImageLoader", "photoPath = " + photoPath); byte[] data = StreamTool.read(inputStream); StreamTool.write(photoPath, data); loadFileResult.onResult(photoPath); } catch (IOException e) { loadFileResult.onFail(); e.printStackTrace(); } finally { imageReference.close(); closeableReference.close(); } } } @Override public void onFailureImpl(DataSource dataSource) { if (loadFileResult != null) { loadFileResult.onFail(); } Throwable throwable = dataSource.getFailureCause(); if (throwable != null) { Log.e("ImageLoader", "onFailureImpl = " + throwable.toString()); } } }, Executors.newSingleThreadExecutor()); } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 使用: String url = "http://feed.chujianapp.com/20161108/452ab5752287a99a1b5387e2cd849006.jpg@1080w"; String filePath = ""; ImageLoader.downloadImage(context, url, new DownloadImageResult(filePath) { @Override public void onResult(String filePath) { } @Override public void onFail() { } }); 1 2 3 4 5 6 7 8 9 10 11 12 13 14 1 2 3 4 5 6 7 8 9 10 11 12 13 14 24、不使用SimpleDraweeView组件,但是想使用Fresco去加载图片(两级内存缓存+磁盘缓存要有)并显示到其他组件上(比如显示在TextView的drawableLeft属性上或者显示为View的背景)。 public static void loadTextDrawable(final TextView view, String url, final int direction, final int iconWidth, final int iconHeight) { ImageLoader.loadImage(view.getContext(), url, new LoadImageResult() { @Override public void onResult(Bitmap bitmap) { Drawable drawable = new BitmapDrawable(view.getContext().getResources(), bitmap); final int width = DensityUtil.dipToPixels(view.getContext(), iconWidth); final int height = DensityUtil.dipToPixels(view.getContext(), iconHeight); drawable.setBounds(0, 0, width, height); switch (direction) { case 0: view.setCompoundDrawables(drawable, null, null, null); break; case 1: view.setCompoundDrawables(null, drawable, null, null); break; case 2: view.setCompoundDrawables(null, null, drawable, null); break; case 3: view.setCompoundDrawables(null, null, null, drawable); break; } } }); } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 三、推荐的使用方法 1、第一种用法 初始化 Phoenix.init(this); // Context 1 1 从网络加载一张图片 String url = "http://ww3.sinaimg.cn/large/610dc034jw1f6m4aj83g9j20zk1hcww3.jpg"; SimpleDraweeView simpleDraweeView = (SimpleDraweeView)findViewById(R.id.sdv_1); Phoenix.with(simpleDraweeView).load(url); 1 2 3 1 2 3 从本地加载一张图片 String filePath = "/sdcard/image/test.jpg"; SimpleDraweeView simpleDraweeView = (SimpleDraweeView)findViewById(R.id.sdv_1); Phoenix.with(simpleDraweeView).load(filePath); 1 2 3 1 2 3 从res下面加载一张图片 SimpleDraweeView simpleDraweeView = (SimpleDraweeView)findViewById(R.id.sdv_1); Phoenix.with(simpleDraweeView).load(R.drawable.meizi); 1 2 1 2 在写布局文件xml时,我不知道要显示的图片尺寸,需要根据业务逻辑动态的设置要显示的图片的大小,可以像下面这样写: String url = "http://ww3.sinaimg.cn/large/610dc034jw1f6m4aj83g9j20zk1hcww3.jpg"; SimpleDraweeView simpleDraweeView = (SimpleDraweeView)findViewById(R.id.sdv_1); Phoenix.with(simpleDraweeView) .setWidth(100) .setHeight(100) .load(url); 1 2 3 4 5 6 1 2 3 4 5 6 只知道要显示图片的高或者宽的值,另一个值可以从设置的比例得出 String url = "http://ww3.sinaimg.cn/large/610dc034jw1f6m4aj83g9j20zk1hcww3.jpg"; SimpleDraweeView simpleDraweeView = (SimpleDraweeView)findViewById(R.id.sdv_1); Phoenix.with(simpleDraweeView) .setWidth(100) .setAspectRatio(0.6f) // w/h = 6/10 .load(url); 1 2 3 4 5 6 1 2 3 4 5 6 图片的高斯模糊处理 String url = "http://ww3.sinaimg.cn/large/610dc034jw1f6m4aj83g9j20zk1hcww3.jpg"; SimpleDraweeView simpleDraweeView = (SimpleDraweeView)findViewById(R.id.sdv_1); Phoenix.with(simpleDraweeView) .setNeedBlur(true) .load(url); 1 2 3 4 5 1 2 3 4 5 加载并显示gif格式的图片 String url = "http://img4.178.com/acg1/201506/227753817857/227754566617.gif"; SimpleDraweeView simpleDraweeView = (SimpleDraweeView)findViewById(R.id.sdv_1); Phoenix.with(simpleDraweeView) .load(url); 1 2 3 4 1 2 3 4 加载并显示webp格式的图片 SimpleDraweeView simpleDraweeView = (SimpleDraweeView)findViewById(R.id.sdv_1); Phoenix.with(simpleDraweeView) .load(R.drawable.meizi_webp); 1 2 3 1 2 3 …… 2、第二种用法 初始化 Fresco.initialize(context, ImageLoaderConfig.getImagePipelineConfig(context)); 1 1 从网络加载一张图片 String url = "http://ww3.sinaimg.cn/large/610dc034jw1f6m4aj83g9j20zk1hcww3.jpg"; SimpleDraweeView simpleDraweeView = (SimpleDraweeView)findViewById(R.id.sdv_1); ImageLoader.loadImage(simpleDraweeView, url); 1 2 3 1 2 3 从本地加载一张图片 String filePath = "/sdcard/image/test.jpg"; SimpleDraweeView simpleDraweeView = (SimpleDraweeView)findViewById(R.id.sdv_1); ImageLoader.loadFile(simpleDraweeView, filePath); 1 2 3 1 2 3 从res下面加载一张图片 SimpleDraweeView simpleDraweeView = (SimpleDraweeView)findViewById(R.id.sdv_1); ImageLoader.loadDrawable(simpleDraweeView, R.drawable.meizi, 100, 100); 1 2 1 2 在写布局文件xml时,我不知道要显示的图片尺寸,需要根据业务逻辑动态的设置要显示的图片的大小,可以像下面这样写: String url = "http://ww3.sinaimg.cn/large/610dc034jw1f6m4aj83g9j20zk1hcww3.jpg"; SimpleDraweeView simpleDraweeView = (SimpleDraweeView)findViewById(R.id.sdv_1); ImageLoader.loadImage(simpleDraweeView, url, 120, 120); 1 2 3 1 2 3 只知道要显示图片的高或者宽的值,另一个值可以从设置的比例得出 String url = "http://ww3.sinaimg.cn/large/610dc034jw1f6m4aj83g9j20zk1hcww3.jpg"; SimpleDraweeView simpleDraweeView = (SimpleDraweeView)findViewById(R.id.sdv_1); ViewGroup.LayoutParams lvp = simpleDraweeView.getLayoutParams(); lvp.width = DensityUtil.getDisplayWidth(this); // 取值为手机屏幕的宽度 simpleDraweeView.setAspectRatio(0.6f); // 设置宽高比 ImageLoader.loadDrawable(simpleDraweeView, R.drawable.meizi); 1 2 3 4 5 6 1 2 3 4 5 6 图片的高斯模糊处理 String url = "http://ww3.sinaimg.cn/large/610dc034jw1f6m4aj83g9j20zk1hcww3.jpg"; SimpleDraweeView simpleDraweeView = (SimpleDraweeView)findViewById(R.id.sdv_1); ImageLoader.loadImageBlur(simpleDraweeView, url); 1 2 3 1 2 3 加载并显示gif格式的图片 String url = "http://img4.178.com/acg1/201506/227753817857/227754566617.gif"; SimpleDraweeView simpleDraweeView = (SimpleDraweeView)findViewById(R.id.sdv_1); ImageLoader.loadImage(simpleDraweeView, url); 1 2 3 1 2 3 加载并显示webp格式的图片 SimpleDraweeView simpleDraweeView = (SimpleDraweeView)findViewById(R.id.sdv_1); ImageLoader.loadDrawable(simpleDraweeView, R.drawable.meizi_webp); 1 2 1 2 …… 3、大图浏览器 带动画的效果打开方式,详细细节请查看PhotoWallActivity中的使用 ArrayList<PhotoInfo> photos = null; PictureBrowse.newBuilder(PhotoWallActivity.this) .setParentView(parent) .setCurrentPosition(position) .setPhotoList(photos) .enabledAnimation(true) .build() .start(); 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8 无动画效果的打开方式 ArrayList<PhotoInfo> photos = null; PictureBrowse.newBuilder(PhotoWallActivity.this) .setParentView(parent) .setCurrentPosition(position) .setPhotoList(photos) .build() .start(); 1 2 3 4 5 6 7 1 2 3 4 5 6 7 我提供了两种图片加载使用方式,你想使用那种图片加载方式,全看个人爱好(推荐使用第一种方式)。 代码我已上传到github上了,地址:https://github.com/hpdx/fresco-helper 本文转自 一点点征服 博客园博客,原文链接:http://www.cnblogs.com/ldq2016/p/6674594.html,如需转载请自行联系原作者

优秀的个人博客,低调大师

纯本地化国产落地 AI 产品 - GodoAI

GodoAI是一款集前沿AI技术与高效办公功能于一体的创新型办公产品,通过深度整合模型下载、模型对话、知识库管理、图片生成、语音转文字、文字转语音、以及全面的图像处理能力,GodoAI实现了办公场景的全覆盖,让每一位用户都能享受到智能化带来的便捷与高效。 💝良心产品,匠心独运,核心功能全面实现本地化部署,仅需8G内存,即可轻松驾驭。 💝 亮点 内置丰富的AI模型库,用户可根据需求一键下载所需模型 零配置,无需注册,下载即用 纯golang开发后端,低资源消耗和高性能 跨平台,Windows、Linux、MacOS都可以安装,无需docker部署 💖 开源地址 Gitee 🚀 演示视频 模型下载与创作 知识库与绘图 ⚡ 功能说明和预览 一、模型 内置丰富的AI模型库,用户可根据需求一键下载所需模型 几乎涵盖了市面上所有的基础大模型,包含聊天模型、文字转图片、图片转文字、图片转图片、文字转语音、语音转文字、Embeddings等模型 二、知识库 支持绝大多数类型文件上传,可抓取远程网页 支持本地向量数据库 三、创作 功能全面,包括从标题设定到内容编辑、保存、导出的全过程管理 支持关联知识库,可以不限制长度任意创作,发挥无限空间 支持段落生成、选中生成和全部生成 创作完成后可直接导出为word 支持查看创作列表、配置prompt高级设置等 四、绘图 无需GPU显卡也能生成图片 利用StableDiffusion,快速生成高质量图片,满足设计、广告、营销等多种场景需求。 支持SD中的所有模型,支持自定义SD中的参数 支持标签式生成prompt提示 生成的图片会自动保存到本地,支持实时查看后端的生成日志 五、聊天 支持多模态模型对话 支持保存聊天内容 支持自定义聊天参数 支持关联知识库 六、翻译 借助大模型可翻译多国语言 支持自定义翻译参数 七、语聊 声音转文字中建议选择telespeech模型,支持多地方言识别。不同的模型语音识别语言不同。 支持语音转文字、文字转语音功能,无需打字即可快速和大模型沟通。 八、听录 支持语音转文字功能,会议记录、访谈笔记轻松搞定。 支持保存会议记录,方便后续管理和查看。

优秀的个人博客,低调大师

故乡的云·国产大模型普惠计划

百度智能云千帆推出大模型普惠计划,0成本切换至国内调用量第一的大模型平台。场景更丰富、模型更全面、工具链更完整易用、更安全可靠! 即日起为新注册企业用户提供: 0元调用: 文心旗舰模型首次免费,赠送ERNIE3.5旗舰模型5000万Tokens包,主力模型ERNIE Speed/ERNIE Lite和轻量模型ERNIE Tiny持续免费 针对OpenAI迁移用户额外赠送与OpenAI使用规模对等的ERNIE3.5旗舰模型Tokens包 0元训练:免费模型精调训练服务 0元迁移:零成本SDK迁移工具 0元服务:专家服务(迁移&使用指导) 立即体验百度智能云千帆大模型平台 (以上优惠活动均在2024年7月25日24点前适用,最终解释权归百度智能云所有)

优秀的个人博客,低调大师

国产 Java ORM:sqltoy-orm 5.2.91 发版

开源地址: github:https://github.com/sagframe/sagacity-sqltoy gitee:https://gitee.com/sagacity/sagacity-sqltoy idea 插件 (可直接在 idea 中检索安装):https://github.com/threefish/sqltoy-idea-plugins sqltoy 脚手架项目:https://gitee.com/momoljw/sss-rbac-admin sqltoy lambda 项目:https://gitee.com/gzghde/sqltoy-plus 更新内容 1、修复updateByQuery中UnifyFieldsHandler未判null引发的空指针异常 sqltoy-orm 是 JPA 和超强查询的融合体 JPA 部分 类似 JPA 的对象化 CRUD、对象级联加载和新增、更新 强化 update 操作,提供弹性字段修改能力,不同于 hibernate 先 load 后修改,而是一次数据库交互完成修改,确保了高并发场景下数据的准确性 改进了级联修改,提供了先删除或者先置无效,再覆盖的操作选项 增加了 updateFetch、updateSaveFetch 功能,强化针对强事务高并发场景的处理,类似库存台账、资金台账,实现一次数据库交互,完成锁查询、不存在则插入、存在则修改,并返回修改后的结果 增加了树结构封装,便于统一不同数据库树型结构数据的递归查询 支持分库分表、支持多种主键策略 (额外支持基于 redis 的产生特定规则的业务主键)、加密存储、数据版本校验 提供了公共属性赋值 (创建人、修改人、创建时间、修改时间、租户)、扩展类型处理等 提供了多租户统一过滤和赋值、提供了数据权限参数带入和越权校验 查询部分 极为直观的 sql 编写方式,便于从客户端 <--> 代码 双向快速迁移,便于后期变更维护 支持缓存翻译、反向缓存匹配 key 代替 like 模糊查询 提供了跨数据库支持能力:不同数据库的函数自动转换适配,多方言 sql 根据实际环境自动匹配、多数据库同步测试,大幅提升了产品化能力 提供了取 top 记录、随机记录等特殊场景的查询功能 提供了最强大的分页查询机制:1) 自动优化 count 语句;2) 提供基于缓存的分页优化,避免每次都执行 count 查询;3) 提供了独具特色的快速分页;4) 提供了并行分页 提供了分库分表能力 提供了在管理类项目中极为价值的:分组汇总计算、行列转换 (行转列、列转行)、同比环比、树形排序、树形汇总 相关算法自然集成 提供了基于查询的层次化数据结构封装 提供了大量辅助功能:数据脱敏、格式化、条件参数预处理等 支持多种数据库 常规的 mysql、oracle、db2、postgresql、 sqlserver、dm、kingbase、sqlite、h2、 oceanBase、polardb、guassdb、tidb 支持分布式 olap 数据库: clickhouse、StarRocks、greenplum、impala (kudu) 支持 elasticsearch、mongodb 所有基于 sql 和 jdbc 各类数据库查询 sqltoy 特点介绍: sqltoy 的核心构建思想 sqltoy 的对比 mybatis (plus) 的核心点:查询语句编写、可阅读性、可维护性 对象化 crud 是基础,但 sqltoy 有针对性的改进:update、updateSaveFetch、updateFetch 等 sqltoy 的缓存翻译,大幅减少表关联简化 sql,让你的查询性能成几何级提升 极致的分页,同样帮助你实现查询的性能大幅提升 快速分页:@fast () 实现先取单页数据然后再关联查询,极大提升速度 分页优化器:page-optimize 让分页查询由两次变成 1.3~1.5 次 (用缓存实现相同查询条件的总记录数量在一定周期内无需重复查询 sqltoy 的分页取总记录的过程不是简单的 select count (1) from (原始 sql);而是智能判断是否变成:select count (1) from 'from 后语句 ', 并自动剔除最外层的 order by sqltoy 支持并行查询:parallel="true",同时查询总记录数和单页数据,大幅提升性能 便利的跨数据库统计计算:数据旋转 便利的跨数据库统计计算:无限极分组统计 (含汇总求平均) 便利的跨数据库统计计算:同比环比 5、树形表排序汇总 6、扩展集成

优秀的个人博客,低调大师

国产 Java ORM:sqltoy-orm 5.2.90 发版

开源地址: github:https://github.com/sagframe/sagacity-sqltoy gitee:https://gitee.com/sagacity/sagacity-sqltoy idea 插件 (可直接在 idea 中检索安装):https://github.com/threefish/sqltoy-idea-plugins sqltoy 脚手架项目:https://gitee.com/momoljw/sss-rbac-admin sqltoy lambda 项目:https://gitee.com/gzghde/sqltoy-plus 更新内容 1、增强loop中LocalDateTime和LocalTime的输出精度 sqltoy-orm 是 JPA 和超强查询的融合体 JPA 部分 类似 JPA 的对象化 CRUD、对象级联加载和新增、更新 强化 update 操作,提供弹性字段修改能力,不同于 hibernate 先 load 后修改,而是一次数据库交互完成修改,确保了高并发场景下数据的准确性 改进了级联修改,提供了先删除或者先置无效,再覆盖的操作选项 增加了 updateFetch、updateSaveFetch 功能,强化针对强事务高并发场景的处理,类似库存台账、资金台账,实现一次数据库交互,完成锁查询、不存在则插入、存在则修改,并返回修改后的结果 增加了树结构封装,便于统一不同数据库树型结构数据的递归查询 支持分库分表、支持多种主键策略 (额外支持基于 redis 的产生特定规则的业务主键)、加密存储、数据版本校验 提供了公共属性赋值 (创建人、修改人、创建时间、修改时间、租户)、扩展类型处理等 提供了多租户统一过滤和赋值、提供了数据权限参数带入和越权校验 查询部分 极为直观的 sql 编写方式,便于从客户端 <--> 代码 双向快速迁移,便于后期变更维护 支持缓存翻译、反向缓存匹配 key 代替 like 模糊查询 提供了跨数据库支持能力:不同数据库的函数自动转换适配,多方言 sql 根据实际环境自动匹配、多数据库同步测试,大幅提升了产品化能力 提供了取 top 记录、随机记录等特殊场景的查询功能 提供了最强大的分页查询机制:1) 自动优化 count 语句;2) 提供基于缓存的分页优化,避免每次都执行 count 查询;3) 提供了独具特色的快速分页;4) 提供了并行分页 提供了分库分表能力 提供了在管理类项目中极为价值的:分组汇总计算、行列转换 (行转列、列转行)、同比环比、树形排序、树形汇总 相关算法自然集成 提供了基于查询的层次化数据结构封装 提供了大量辅助功能:数据脱敏、格式化、条件参数预处理等 支持多种数据库 常规的 mysql、oracle、db2、postgresql、 sqlserver、dm、kingbase、sqlite、h2、 oceanBase、polardb、guassdb、tidb 支持分布式 olap 数据库: clickhouse、StarRocks、greenplum、impala (kudu) 支持 elasticsearch、mongodb 所有基于 sql 和 jdbc 各类数据库查询 sqltoy 特点介绍: sqltoy 的核心构建思想 sqltoy 的对比 mybatis (plus) 的核心点:查询语句编写、可阅读性、可维护性 对象化 crud 是基础,但 sqltoy 有针对性的改进:update、updateSaveFetch、updateFetch 等 sqltoy 的缓存翻译,大幅减少表关联简化 sql,让你的查询性能成几何级提升 极致的分页,同样帮助你实现查询的性能大幅提升 快速分页:@fast () 实现先取单页数据然后再关联查询,极大提升速度 分页优化器:page-optimize 让分页查询由两次变成 1.3~1.5 次 (用缓存实现相同查询条件的总记录数量在一定周期内无需重复查询 sqltoy 的分页取总记录的过程不是简单的 select count (1) from (原始 sql);而是智能判断是否变成:select count (1) from 'from 后语句 ', 并自动剔除最外层的 order by sqltoy 支持并行查询:parallel="true",同时查询总记录数和单页数据,大幅提升性能 便利的跨数据库统计计算:数据旋转 便利的跨数据库统计计算:无限极分组统计 (含汇总求平均) 便利的跨数据库统计计算:同比环比 5、树形表排序汇总 6、扩展集成

优秀的个人博客,低调大师

可替代 Spring,国产 Solon v2.6.3 发布

Solon 是什么框架? Java 新的"生态级"应用开发框架。从零开始构建,有自己的标准规范与开放生态(历时六年,具备全球第二级别的生态规模)。 相对于 Spring,有什么特点? 启动快 5 ~ 10 倍。(更快) qps 高 2~ 3 倍。(更高) 低流量内存节省 1/3 ~ 1/2。(更少) 打包可以缩小到 1/2 ~ 1/10;比如,300Mb 的变成了 23Mb。(更小) 同时支持 jdk8, jdk11, jdk17, jdk21,graalvm native image 入门探索视频(用户录制): 最近更新了什么? 发布 Solon FaaS 修复 solon.luffy 插件 JtFunctionLoaderClasspath 可能会出现 null 异常的问题 修复 solon.luffy 插件 XFun.callFile 的执行兼容性(添加 file_id 赋值) 修复 Solon.cfg().stopSafe() 自动配置失效的问题 修复 war 部署时 contextPath 自动识别失效的问题 调整 contextPath 配置,支持 '!' 开头(表示强制模式,即不再支持旧的地址请求) 调整 solon.net 把 socketd 包改为 provided 调整 Utils::mime 添加默认处理 添加 ConvertUtil 对 Byte 类型的默认解析 smart-http 升为 1.3.6 luffy 升为 1.7.2 folkmq 升为 1.0.22 socket.d 升为 2.1.14 sqltoy 升为 5.2.86 beetl 升为 3.15.12.RELEASE beetlsql 升为 3.27.3-RELEASE netty 升为 4.1.101.Final 项目仓库地址? gitee:https://gitee.com/noear/solon github:https://github.com/noear/solon

资源下载

更多资源
Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册