首页 文章 精选 留言 我的

精选列表

搜索[bug],共10000篇文章
优秀的个人博客,低调大师

国产数据库管理工具 CloudDM v2.8.2 发布,修复 Bug 若干

CloudDM 个人版是ClouGence公司推出的一款一站式多数据源开发管理工具,使用它可以方便地访问和管理MySQL、Oracle、PostgreSQL、阿里云 RDS、Greenplum、TiDB、Redis、StarRocks、Doris、SelectDB、SQL SERVER、ClickHouse、OceanBase 、PolarDB-X 、IBM Db2 等多种不同类型的数据库。通过 CloudDM 丰富的数据源支持可以避免在多个专业工具之间切换,从而提高工作效率。 它是本地化的应用程序,没有后台进程。和DataGrip、Navicat一样在安装完成后,只需要双击应用程序图标,便可以方便的管理位于本地计算机或远程计算机上的数据库。已支持Windows和MacOS、Linux三个操作系统。 更新内容 [新增] 新增数据源连接状态显示,并提供重新连接按钮 新增数据源连接状态提示弹窗 [优化] 优化压力测试功能默认参数值调整为最佳性能 优化MySQL 数据源数据生成功能,数据写入速度平均可达到 5w/s 行 优化MySQL 数据源压力测试功能,数据随机写入速度平均可达到 2w/s 行 优化Oracle 数据源数据生成功能,数据写入速度平均可达到 2w/s 行 优化Oracle 数据源压力测试功能,数据随机写入速度平均可达到 1w/s 行 优化PostgreSQL、SQL SERVER、TiDB、OceanBase、PolarDBX 等数据源的数据生成和压力测试功能,数据写入速度较旧版有明显提升。 [修复] 修复Host 地址修改后没有生效的问题 修复MySQL 数据源控制台执行 show create table 语句无反应的问题 修复Hana 数据源添加失败的问题 修复 StarRocks、Doris 无法执行 create table 语句的错 修复 点击修改存储过程时,无法正常打开 下载与反馈 产品官网:https://www.clougence.com/clouddm-personal 问题反馈:https://gitee.com/clougence/clouddm-issue/issues 微信交流群:访问产品官网,扫描右侧二维码即可加入

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

魔豆文库 moredoc v3.1.0 发布,Bug 修复,以及提供 SSR SEO 过渡方案

魔豆文库MOREDOC,使用 Go 语言开发实现的文库解决方案,dochub文库的重构版本,支持 office (全部类型)、PDF、TXT、EPUB、MOBI 等多种文档格式的在线阅读浏览,支持无限级分类、文档批量上传、文档批量转换、全文搜索、云存储、网络爬虫、VIP、手机号登录注册以及支付宝和微信支付等功能,拥有简洁美观的用户视觉和功能体验,以及配套的微信小程序 ONEDOC。 技术栈 Golang :gin + gRPC + GORM Vue.js : nuxt2 + element-ui Database : MySQL 5.7+,MySQL 8.0 + 升级日志 社区版(开源版)升级日志 1. 新增:支持从Gitee或Github检测文库新版本,以便跟进升级程序(每小时检测一次,可能存在一定的滞后) 2. 新增:支持调整顶部导航栏文案和排序 配置入口:管理后台 -> 导航管理 3. 新增:提供SSR SEO过渡方案 使用puppeteer实现,仓库:https://gitee.com/mnt-ltd/morender 启动morender之后,在 管理后台->系统设置->SSR配置 进行设置 4. 新增:支持编辑文档文本内容,方便对少部分乱码文档进行处理(乱码文档的存在,大部分是因为服务器缺少相应字体导致) 5. 修复:前端报错提示不准确的问题 6. 修复:文档分类与文章分类混淆的问题 7. 增强:配置文件app.toml中 jwt 的secret配置项强制修改,不修改该配置项一律不允许启动程序 app.toml文件中jwt配置,一直有明确的提示要求修改其中默认的secret配置项,但是绝大部分人直接闭眼部署都不看提示。因此出于安全考虑,强制修改,不修改则程序直接退出。 专业版升级日志 专业版升级功能包含社区版 1. 修复:解决文档下载时因附件名称出现换行导致从对象存储下载文档失败的问题 2. 修复:文章索引问题导致文章相关功能没法正常工作的问题 3. 修复:重新调整文档分类之后,无法在该分类下检索不到该文档 4. 修复:文档采集,超大文档下载占用内存过高的问题 5. 增强:编辑文档的时候,支持重新上传源文档 升级方式 本次升级,升级前建议先做备份或直接使用云服务器商提供的快照功能打快照进行备份 从Gitee下载对应您的服务器系统的最新版本程序:https://gitee.com/mnt-ltd/moredoc/releases 更新数据库表结构 注意:本次升级,存在数据库表结构变更,请务必执行syncdb操作 复制代码 # windows moredoc.exe syncdb # Linux/Unix ./moredoc syncdb 重启程序。 演示站点 程序新功能体验,一睹为快! 网址: https://moredoc.mnt.ltd 管理员账号: admin 管理员密码: mnt.ltd 演示站点,每天凌晨 1:00 ~ 6:00,每隔一小时重置一次全部数据 开源地址 魔豆文库 MOREDOC Gitee - https://gitee.com/mnt-ltd/moredoc Github - https://github.com/mnt-ltd/moredoc 配套小程序 ONEDOC Gitee - https://gitee.com/mnt-ltd/onedoc Github - https://github.com/mnt-ltd/onedoc 使用手册 关于魔豆文库安装部署、二次开发等更详细的教程,详见书栈网《魔豆文库使用手册》

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

go-carbon 1.4.2 版本发布,新增年代和季节系列方法以及修复 bug

carbon 是一个轻量级、语义化、对开发者友好的Golang时间处理库,支持链式调用、农历和gorm、xorm等主流orm。 如果您觉得不错,请给个 star 吧 github:github.com/golang-module/carbon gitee:gitee.com/go-package/carbon 更新日志 Lunar().ToChineseYearString()方法更改为Lunar().ToYearString() Lunar().ToChineseMonthString()方法更改为Lunar().ToMonthString() Lunar().ToChineseDayString()方法更改为Lunar().ToDayString() New()方法更改为NewCarbon(),以避免New()和Now()相似而混淆 优化CreaterFromXXX系列方法对默认纳秒的处理,将默认纳秒设为当前纳秒 增加单元测试覆盖场景 增加对无效时间的判断 新增Decade()方法获取当前年代 新增StartOfDecade()方法获取当前年代的开始时间 新增EndOfDecade()方法获取当前年代的结束时间 新增Season()方法获取当前季节,支持i18n 新增StartOfSeason()方法获取当前季节的开始时间 新增EndOfSeason()方法获取当前季节结束时间 新增IsSpring()方法判断是否是春季 新增IsSummer()方法判断是否是夏季 新增IsAutumn()方法判断是否是秋季 新增IsWinter()方法判断是否是冬季

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

smart-doc 2.1.1发布,紧急修复推送文档到 Torna 的 bug

smart-doc 是一款同时支持 java restful api 和 Apache Dubbo rpc 接口文档生成的工具,smart-doc 颠覆了传统类似 swagger 这种大量采用注解侵入来生成文档的实现方法。 smart-doc 完全基于接口源码分析来生成接口文档,完全做到零注解侵入,你只需要按照 java 标准注释编写,smart-doc 就能帮你生成一个简易明了的 markdown 或是一个像 GitBook 样式的静态 html 文档。如果你已经厌倦了 swagger 等文档工具的无数注解和强侵入污染,那请拥抱 smart-doc 吧! 功能特性 支持接口 debug。 零注解、零学习成本、只需要写标准 java 注释。 基于源代码接口定义自动推导,强大的返回结构推导。 支持 Spring MVC,Spring Boot,Spring Boot Web Flux(controller 书写方式)。 支持 Callable,Future,CompletableFuture 等异步接口返回的推导。 支持 JavaBean 上的 JSR303 参数校验规范,支持分组验证。 对 json 请求参数的接口能够自动生成模拟 json 参数。 对一些常用字段定义能够生成有效的模拟值。 支持生成 json 返回值示例。 支持从项目外部加载源代码来生成字段注释(包括标准规范发布的 jar 包)。 支持生成多种格式文档:Markdown、HTML5、Asciidoctor、Postman collection、Open Api 3.0+。 轻易实现在 Spring Boot 服务上在线查看静态 HTML5 api 文档。 开放文档数据,可自由实现接入文档管理系统。 一款代码注释检测工具,不写注释的小伙伴逃不过法眼了。 插件式快速集成(支持 maven 和 gradle 插件)。 支持 Apache Dubbo rpc 文档生成。 Smart-doc 和其他工具的支持 功能特性 smart-doc swagger 代码侵入 无 注解侵入性严重 集成复杂度 简单,只需插件 偏复杂 插件支持 有gradle和maven插件 无插件 openapi规范支持 支持openapi 3.0 完全支持openapi的版本 CI构建集成 可在ci构建阶段使用 maven或者gradle命令 启动插件生成文档 不支持 集中化文档中心集成 已经和torna企业级接口文档管理平台对接 不支持 维护持续性 值得信赖,开源后用户基础多,一直持续维护 全球用户多,开源维护值得信赖 接口debug 2.0.0版本开始已经支持debug,页面比swagger漂亮太多了。 支持 Smart-doc 从 2.0.0 后几乎实现了 swagger ui 的功能,并且比 swagger ui 更简洁大方,也更符合国内开发者的诉求。当然 smart-doc 的功能也已经 超过了 swagger 为 java 开发者提供的功能。当然 smart-doc 本身是只支持扫描代码生成 openapi 3.0 的文档的,也可以将生成的 openapi 3.0 文档导入到其他ui中渲染展示。 更新内容 从 2.0.0 版本开始,smart-doc 完全支持生成 debug 调试页面。从本次发布的 2.1.1版本起,smart-doc 的对接了企业级的接口文档管理平台。 1. 修复Map嵌套在某些结构体中栈溢出问题,gitee #I3CCLY。 2. 修复Torna数据推送问题。 debug 页面效果 maven或gradle插件 smart-doc 官方为了方便用户快速和无侵入的集成 smart-doc 的文档 api 生成能力,我们开发可相关的 maven 或者 gradle 插件。这里也推荐使用插件的方式来使用 smart-doc。 https://gitee.com/smart-doc-team/smart-doc-maven-plugin 官方推荐方案 smart-doc +Torna组成行业领先的文档生成和管理解决方案,使用smart-doc无侵入完成Java源代码分析和提取注释生成API文档,自动将文档推送到Torna企业级接口文档管理平台。 smart-doc+Torna文档自动化 smart-doc在国内很多企业中被用来替换了swagger,甚至是在国内Top 3内的大厂都有smart-doc的二次开发版本。Torna未来的目标是追赶和超越Yapi。smart-doc针对java spring技术栈的解析能力目前为业内最强(不服就拿工具来跑smart-doc的解析demo)。所以smart-doc+Torna的方案威力巨大,Torna目前处于高速迭代期,欢迎体验Torna,我们努力为社区提供高效好用的接口文档解决方案。 升级建议 smart-doc 这个版本最大的变更是对接了Torna企业级接口文档管理系统。 DEMO 使用demo轻松玩转接口文档生成,其他用户案例文档效果展示:https://api.doubans.com/ 知名用户 科大讯飞 一加 小米 鸣谢 smart-doc也是利用一些开源技术构建起来的,我在这里对下列开源项目表示感谢。 Beetl国内开源的JAVA模板引擎 QDOX 开源JAVA源代码解析库

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

Dataway 4.1.6 发布,修复社区反馈的 Bug,同时可以自定义返回结构了

Dataway介绍 Dataway 是基于 DataQL 服务聚合能力,为应用提供的一个接口配置工具。使得使用者无需开发任何代码就配置一个满足需求的接口。 整个接口配置、测试、冒烟、发布。一站式都通过 Dataway 提供的 UI 界面完成。UI 会以 Jar 包方式提供并集成到应用中并和应用共享同一个 http 端口,应用无需单独为 Dataway 开辟新的管理端口。 这种内嵌集成方式模式的优点是,可以使得大部分老项目都可以在无侵入的情况下直接应用 Dataway。进而改进老项目的迭代效率,大大减少企业项目研发成本。 Dataway 工具化的提供 DataQL 配置能力。这种研发模式的变革使得,相当多的需求开发场景只需要配置即可完成交付。 从而避免了从数据存取到前端接口之间的一系列开发任务,例如:Mapper、BO、VO、DO、DAO、Service、Controller 统统不在需要。 Hasor v4.1.6 (2020-05-10) 修复 issueoracle 分页模式下 select count 语句无法正确执行。 Hasor v4.1.5 (2020-05-09) 新增 issue接口可以自定义返回值,完美兼容老项目的接口规范。 issue增加 ConvertUdfSource 类型转换函数包。 优化 FxSql 工具类抽象出 FxQuery 接口 和 SqlFxQuery 实现类。 issue优化了一下交互,新建接口情况下 comment 不会主动显示出来。 修复 issueDatawayService 接口使用 @Bean 在 Spring 中配置报错。 issueSQL模式下保存api之后,点击编辑再进入,没有显示之前保存的信息。 issue分页模式下,FRAGMENT_SQL_COLUMN_CASE 不起作用。 本次升级数据库表结构有所变更 Mysql升级脚本: alter table interface_info add api_option mediumtext null comment '扩展配置信息' after api_sample; alter table interface_release add pub_option mediumtext null comment '扩展配置信息' after pub_sample; Oracle升级脚本: alter table interface_info add api_option clob / comment on column interface_info.api_option is '扩展配置信息' / alter table interface_release add pub_option clob / comment on column interface_release.pub_option is '扩展配置信息' / 接口除了 DataQL 查询结果可以完全自定义之外,编辑页面中还提供了最外层结构的定制化。

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

机器学习正在安全领域挂起一阵小旋风,但这里面有BUG

s3-eu-central-1.amazonaws 如今,安全领域是机器学习(Machine learning)正在大力进军的一个方向。 |把机器学习应用到安全领域,老板们跃跃欲试 如果你亲自参加了 2016 RSA 大会,就会发现几乎没有哪家公司在说自家安全领域的产品时,不提及机器学习。这是为什么呢? 可能对外行人来说,机器学习就像一种魔法,能解决所有的安全问题:你把一堆未标识的数据统统塞进会机器学习的系统中,它就能分辨出连人类专家都分辨不出的数据规律,并且还可以学习新的行为指令和适应环境威胁。不仅如此,就连为规则加密也劳烦不到你,因为系统已经自动为你搞定这一切。 要真是像这样的话,那机器学习可真就是今年的重头戏了!但讽刺的是,每个人都兴师动众说要在这个领域搞出点名堂来,但真正理解什么是机器学习,或明白机器学习到底能用来做什么的人,却是

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

MIUI 系统 BUG,Android 调用相机崩溃?将拍照适配方案进行到底!

写在前面 昨天也是为大家分享了 7.0 相机适配,今天就来为大家讲讲 Android 之相机适配。 提起 Android 调用系统相机拍照上传图片或者是显示图片,想必任何一位开发 Android 的朋友都不会陌生,基本这个功能已经涵盖各个应用了,今天,我就来给大家聊聊网上并不多见却有经常听到大家吐槽的问题。 根据相机适配对图片的操作,所以有了这款图片压缩库:[https://github.com/nanchen2251/CompressHelper 拍照功能实现 对于拍照功能的实现方式我这里就不多谈了,无非两种,一种是利用相机的 API 来自定义相机,另一种是利用 Intent 调用系统指定的相机拍照。而这两种方式的实现网上搜索一大把,我就不在这里啰嗦了。 有没有相机可用? 前面讲到我们是调用系统指定的相机 APP 来拍照,那么系统是否存在可以被我们调用的 APP 呢?这个我们不敢确定,毕竟 Android 奇葩问题多,还真有遇到过这种极端的情况导致闪退的。虽然很极端,但作为客户端人员还是要进行处理,方式有二: 调用相机时,简单粗暴的 try-catch 调用相机前,检测系统有没有相机 APP 可用 try-catch 这种粗暴的方式大家肯定很熟悉了,那么要如何检测系统有没有相机 APP 可用呢?系统在 PackageManager 里为我们提供这样一个 API: 通过这样一个 API ,可以知道系统是否存在 Action 为 MediaStore.ACTION_IMAGE_CAPTURE 的 Intent 可以唤起的拍照界面,具体实现代码如下: /** * 判断系统中是否存在可以启动的相机应用 * * @return 存在返回true,不存在返回false */ public boolean hasCamera() { PackageManager packageManager = mActivity.getPackageManager(); Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); List<ResolveInfo> list = packageManager.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY); return list.size() > 0; } 拍出来的照片“歪了”!!! 经常会遇到一种情况,拍照时看到照片是正的,但是当我们的 APP 获取到这张照片时,却发现旋转了 90 度(也有可能是 180、270,不过 90 度比较多见,貌似都是由于手机传感器导致的)。很多童鞋对此感到很困扰,因为不是所有手机都会出现这种情况,就算会是出现这种情况的手机上,也并非每次必现。要怎么解决这个问题呢?从解决的思路上看,只要获取到照片旋转的角度,利用 Matrix 来进行角度纠正即可。那么问题来了,要怎么知道照片旋转的角度呢?细心的童鞋可能会发现,拍完一张照片去到相册点击属性查看,能看到下面这样一堆关于照片的属性数据。 没错,这里面就有一个旋转角度,倘若拍照后保存的成像照片文件发生了角度旋转,这个图片的属性参数就能告诉我们到底旋转了多少度。只要获取到这个角度值,我们就能进行纠正的工作了。 Android 系统提供了 ExifInterface 类来满足获取图片各个属性的操作。 通过 ExifInterface 类拿到 TAG_ORIENTATION 属性对应的值,即为我们想要得到旋转角度。再根据利用 Matrix 进行旋转纠正即可。实现代码大致如下: /** * 获取图片的旋转角度 * * @param path 图片绝对路径 * @return 图片的旋转角度 */ public static int getBitmapDegree(String path) { int degree = 0; try { // 从指定路径下读取图片,并获取其EXIF信息 ExifInterface exifInterface = new ExifInterface(path); // 获取图片的旋转信息 int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL); switch (orientation) { case ExifInterface.ORIENTATION_ROTATE_90: degree = 90; break; case ExifInterface.ORIENTATION_ROTATE_180: degree = 180; break; case ExifInterface.ORIENTATION_ROTATE_270: degree = 270; break; } } catch (IOException e) { e.printStackTrace(); } return degree; } /** * 将图片按照指定的角度进行旋转 * * @param bitmap 需要旋转的图片 * @param degree 指定的旋转角度 * @return 旋转后的图片 */ public static Bitmap rotateBitmapByDegree(Bitmap bitmap, int degree) { // 根据旋转角度,生成旋转矩阵 Matrix matrix = new Matrix(); matrix.postRotate(degree); // 将原始图片按照旋转矩阵进行旋转,并得到新的图片 Bitmap newBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true); if (bitmap != null && !bitmap.isRecycled()) { bitmap.recycle(); } return newBitmap; } ExifInterface 能拿到的信息远远不止旋转角度,其他的参数感兴趣的童鞋可以看看 API 文档。 拍完照怎么闪退了? 曾在小米和魅族的某些机型上遇到过这样的问题,调用系统相机拍照,拍完点击确定回到自己的 APP 里面却莫名奇妙的闪退了。这种闪退有两个特点: 没有什么错误日志(有些机子啥日志都没有,有些机子会出来个空异常错误日志); 同个机子上非必现(有时候怎么拍都不闪退,有时候一拍就闪退); 对待非必现问题往往比较头疼,当初遇到这样的问题也是非常不解。上网搜罗了一圈也没方案,后来留意到一个比较有意思信息:有些系统厂商的 ROM 会给自带相机应用做优化,当某个 APP 通过 Intent 进入相机拍照界面时,系统会把这个 APP 当前最上层的 Activity 销毁回收。(注意:我遇到的情况是有时候很快就回收掉,有时候怎么等也不回收,没有什么必现规律)为了验证一下,便在启动相机的 Activity 中对 onDestory() 方法进行加 Log 。果不其然,终于发现进入拍照界面的时候 onDestory() 方法被执行了。所以,前面提到的闪退基本可以推测是 Activity 被回收导致某些非UI控件的成员变量为空导致的。(有些机子会报出空异常错误日志,但是有些机子闪退了什么都不报,是不是觉得很奇葩!) 既然涉及到 Activity 被回收的问题,自然要想起 onSaveInstanceState() 和 onRestoreInstanceState() 这对方法。去到 onSaveInstanceState() 把数据保存,并在 onRestoreInstanceState() 方法中进行恢复即可。大体代码思路如下: @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); mRestorePhotoFile = mCapturePhotoHelper.getPhoto(); if (mRestorePhotoFile != null) { outState.putSerializable(EXTRA_RESTORE_PHOTO, mRestorePhotoFile); } } @Override protected void onRestoreInstanceState(Bundle savedInstanceState) { super.onRestoreInstanceState(savedInstanceState); mRestorePhotoFile = (File) savedInstanceState.getSerializable(EXTRA_RESTORE_PHOTO); mCapturePhotoHelper.setPhoto(mRestorePhotoFile); } 对于 onSaveInstanceState() 和 onRestoreInstanceState() 方法的作用还不熟悉的童鞋,网上资料很多,可以自行搜索。 到这里,可能有童鞋要问,这种闪退并不能保证复现,我要怎么知道问题所在和是否修复了呢?我们可以去到开发者选项里开启不保留活动这一项进行调试验证。 它的作用是保留当前和用户接触的 Activity ,并将目前无法和用户交互 Activity 进行销毁回收。打开这个调试选项就可以满足验证的需求,当你的 app 的某个 Activity 跳转到拍照的 Activity 后,这个 Activity 立马就会被系统销毁回收,这样就可以很好的完全复现闪退的场景,帮助开发者确认问题有没有修复了。 涉及到 Activity 被销毁,还想提一下代码实现上的问题。假设当前有两个 Activity ,MainActivity 中有个 Button ,点击可以调用系统相机拍照并显示到 PreviewActivity 进行预览。有下面两种实现方案: MainActivity 中点击 Button 后,启动系统相机拍照,并在 MainActivity 的 onActivityResult() 方法中获取拍下来的照片,并启动跳转到 PreviewActivity 界面进行效果预览; MainActivity 中点击 Button 后,启动 PreviewActivity 界面,在 PreviewActivity 的 onCreate()(或者 onStart()、onResume())方法中启动系统相机拍照,然后在 PreviewActivity 的 onActivityResult() 方法中获取拍下来的照片进行预览; 上面两种方案得到的实现效果是一模一样的,但是第二种方案却存在很大的问题。因为启动相机的代码放在 onCreate()(或者 onStart() 、onResume())中,当进入拍照界面后,PreviewActivity 随即被销毁,拍完照确认后回到 PreviewActivity 时,被销毁的 PreviewActivity 需要重建,又要走一遍 onCreate() 、onStart() 、onResume(),又调用了启动相机拍照的代码,周而复始的进入了死循环状态。为了避免让你的用户抓狂,果断明智的选择方案一。 以上这种情况提到调用系统拍照时,Activity 就回收的情况,在小米 4S 和小米 4 LTE 机子上(MIUI 的版本是 7.3,Android 系统版本是 6.0)出现的概率很高。 所以,建议看到此文的童鞋也可以去验证适配一下。 图片无法显示 图片无法显示这个问题也是略坑,如何坑法?往下看,同样是在小米 4S 和小米 4 LTE 机子上(MIUI 的版本是 7.3,Android 系统版本是 6.0)出现概率很高的场景(当然,不保证其他机子没出现过)。按照我们前面提到的业务场景,调用相机拍照完成后,我们的 APP 会有一个预览图片的界面。但是在用了小米的机子进行拍照后,自己 APP 的预览界面却怎么也无法显示出照片来,同样是相当郁闷,郁闷完后还是要一步一步去排查解决问题的!为此,需要一步一步猜测验证问题所在。 猜测一:没有拿到照片路径,所以无法显示? 直接断点打 log 跟踪,猜测一很快被推翻,路径是有的。 猜测二:Bitmap太大了,无法显示? 直接在 Android Studio 的 log 控制台仔细的观察了一下系统 log ,发现了一些蛛丝马迹OpenGLRenderer: Bitmap too large to be uploaded into a texture 每次拍完照片,都会出现上面这样的 log ,果然,因为图片太大而导致在 ImageView 上无法显示。到这里有童鞋要吐槽了,没对图片的采样率 inSampleSize 做处理?天地良心啊,绝对做处理了,直接看代码: /** * 压缩Bitmap的大小 * * @param imagePath 图片文件路径 * @param requestWidth 压缩到想要的宽度 * @param requestHeight 压缩到想要的高度 * @return */ public static Bitmap decodeBitmapFromFile(String imagePath, int requestWidth, int requestHeight) { if (!TextUtils.isEmpty(imagePath)) { if (requestWidth <= 0 || requestHeight <= 0) { Bitmap bitmap = BitmapFactory.decodeFile(imagePath); return bitmap; } BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true;//不加载图片到内存,仅获得图片宽高 BitmapFactory.decodeFile(imagePath, options); options.inSampleSize = calculateInSampleSize(options, requestWidth, requestHeight); //计算获取新的采样率 options.inJustDecodeBounds = false; return BitmapFactory.decodeFile(imagePath, options); } else { return null; } } public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) { final int height = options.outHeight; final int width = options.outWidth; int inSampleSize = 1; Log.i(TAG, "height: " + height); Log.i(TAG, "width: " + width); if (height > reqHeight || width > reqWidth) { final int halfHeight = height / 2; final int halfWidth = width / 2; while ((halfHeight / inSampleSize) > reqHeight && (halfWidth / inSampleSize) > reqWidth) { inSampleSize *= 2; } long totalPixels = width * height / inSampleSize; final long totalReqPixelsCap = reqWidth * reqHeight * 2; while (totalPixels > totalReqPixelsCap) { inSampleSize *= 2; totalPixels /= 2; } } return inSampleSize; } 瞄了代码后,是不是觉得没有问题了?没错,inSampleSize 确确实实经过处理,那为什么图片还是太大而显示不出来呢? requestWidth、requestHeight 设置得太大导致 inSampleSize 太小了?不可能啊,我都试着把长宽都设置成 100 了还是没法显示!干脆,直接打印 inSampleSize 值,一打印,inSampleSize 值居然为 1 。 我去,彻底打脸了,明明说好的处理过了,居然还是 1 !!!!为了一探究竟,干脆加 log 。 public static Bitmap decodeBitmapFromFile(String imagePath, int requestWidth, int requestHeight) { if (!TextUtils.isEmpty(imagePath)) { Log.i(TAG, "requestWidth: " + requestWidth); Log.i(TAG, "requestHeight: " + requestHeight); if (requestWidth <= 0 || requestHeight <= 0) { Bitmap bitmap = BitmapFactory.decodeFile(imagePath); return bitmap; } BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true;//不加载图片到内存,仅获得图片宽高 BitmapFactory.decodeFile(imagePath, options); Log.i(TAG, "original height: " + options.outHeight); Log.i(TAG, "original width: " + options.outWidth); options.inSampleSize = calculateInSampleSize(options, requestWidth, requestHeight); //计算获取新的采样率 Log.i(TAG, "inSampleSize: " + options.inSampleSize); options.inJustDecodeBounds = false; return BitmapFactory.decodeFile(imagePath, options); } else { return null; } } 运行打印出来的日志如下: 图片原来的宽高居然都是 -1 ,真是奇葩了!难怪, inSampleSize 经过处理之后结果还是 1 。狠狠的吐槽了之后,总是要回来解决问题的。那么,图片的宽高信息都丢失了,我去哪里找啊? 像下面这样? public static Bitmap decodeBitmapFromFile(String imagePath, int requestWidth, int requestHeight) { ... BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true;//不加载图片到内存,仅获得图片宽高 Bitmap bitmap = BitmapFactory.decodeFile(imagePath, options); bitmap.getWidth(); bitmap.getHeight(); ... } else { return null; } } no,此方案行不通,inJustDecodeBounds = true 时,BitmapFactory 获得 Bitmap 对象是 null; 那要怎样才能获图片的宽高呢?前面提到的 ExifInterface 再次帮了我们大忙,通过它的下面两个属性即可拿到图片真正的宽高。 顺手吐槽一下,为什么高不是 TAG_IMAGE_HEIGHT 而是 TAG_IMAGE_LENGTH。改良过后的代码实现如下: public static Bitmap decodeBitmapFromFile(String imagePath, int requestWidth, int requestHeight) { if (!TextUtils.isEmpty(imagePath)) { Log.i(TAG, "requestWidth: " + requestWidth); Log.i(TAG, "requestHeight: " + requestHeight); if (requestWidth <= 0 || requestHeight <= 0) { Bitmap bitmap = BitmapFactory.decodeFile(imagePath); return bitmap; } BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true;//不加载图片到内存,仅获得图片宽高 BitmapFactory.decodeFile(imagePath, options); Log.i(TAG, "original height: " + options.outHeight); Log.i(TAG, "original width: " + options.outWidth); if (options.outHeight == -1 || options.outWidth == -1) { try { ExifInterface exifInterface = new ExifInterface(imagePath); int height = exifInterface.getAttributeInt(ExifInterface.TAG_IMAGE_LENGTH, ExifInterface.ORIENTATION_NORMAL);//获取图片的高度 int width = exifInterface.getAttributeInt(ExifInterface.TAG_IMAGE_WIDTH, ExifInterface.ORIENTATION_NORMAL);//获取图片的宽度 Log.i(TAG, "exif height: " + height); Log.i(TAG, "exif width: " + width); options.outWidth = width; options.outHeight = height; } catch (IOException e) { e.printStackTrace(); } } options.inSampleSize = calculateInSampleSize(options, requestWidth, requestHeight); //计算获取新的采样率 Log.i(TAG, "inSampleSize: " + options.inSampleSize); options.inJustDecodeBounds = false; return BitmapFactory.decodeFile(imagePath, options); } else { return null; } } 再看一下,打印出来的 log 以上总结了这么些身边童鞋经常问起,但网上又不多见的适配问题,希望可以帮到一些开发童鞋少走弯路。文中多次提到小米的机子,并不代表只有MIUI上有这样的问题存在,仅仅只是因为我身边带的几部机子大都是小米的。对待适配问题,在搜索引擎都无法提供多少有效的信息时,我们只能靠断点、打 log、观察控制台的日志、以及 API 文档来寻找一些蛛丝马迹作为突破口,相信办法总比困难多。 以上内容采自:There 至于为什么基本全文 copy,是因为我觉得作者已经讲的特别清楚了,我没必要做二次重复,也只是给大家分享一下。 那下面就让我来补充一下不一样的开发情景。 如果同事写好了压缩九宫格显示图片呢? 这时候你们大框架已经搞定了,只需要你传回一个文件的path,你可能会这样写:(下面所有代码都在 onActivityResult()` 方法) if (null != imageGridAdapter.uri) { final String url = PhotoUtil.getImageUrlFromActivityResult(this, imageGridAdapter.uri);//这个方法可以拿到图片的path Log.e(TAG, "onActivityResult: url:" + url); if (!TextUtils.isEmpty(url)) { file = new File(url); size = file.length(); Log.e(TAG, "onActivityResult: size:" + size); if (size > 0 ){ ImageItem imageItem = new ImageItem(); imageItem.ImageId = ImageItem.NEW_ID; imageItem.PhotoPath = url; imageGridAdapter.getmDataList().add(imageItem); imageGridAdapter.notifyDataSetChanged(); imageGridAdapter.uri = null; } } } 好像没啥问题呀,拿到图片的 path,new 一个文件,如果文件 size = 0,则不显示,大于 0 说明图片存在,则显示图片,提示 UI 刷新。 嗯,的确,绝大部分手机都测试通过了,然而在坑爹的部分MIUI系统上出现了,返回 size 为 0,进不到判断循环,自然不会显示那个图片。 这时候肯定要到 google 上去搜上一圈,一圈下来收获不少,却没找到真正解决的办法。 这里有位朋友就说啦,这个 size 为0,但是间隔一定的时间就可以 new 出 size 不为 0 的 file,而这个时间是不固定的。 可见遇上这个坑的小伙伴也是尽心尽力,想方设法。 所以我也尝试了这个方法,考虑到不能休眠主线程,就采用新开一个线程来延时处理,采用加载框,一旦 size 不为 0 了,才进行显示处理。 可能图片出问题,所以我们设置一个最大休眠时间。代码为:(其中 flag 和 time 为全局变量) flag = true; time = 0; final String url = PhotoUtil.getImageUrlFromActivityResult(this, imageGridAdapter.uri); if (size <= 0) { // 如果size小于0出现了,则使用加载框 new Thread(new Runnable() { @Override public void run() { runOnUiThread(new Runnable() { @Override public void run() { showLoading(SendQuestionActivity.this);// 该方法为显示加载框 } }); while (flag) { // 设置延迟步长是0.5s try { Thread.sleep(500); time += 0.5; file = null; file = new File(url); size = file.length(); Log.e(TAG, "onActivityResult: size:" + size); if (size > 0 || time >= 10) { flag = false; } } catch (InterruptedException e) { e.printStackTrace(); } } runOnUiThread(new Runnable() { @Override public void run() { stopLoading();//该方法为取消加载框 } }); } }).start(); } ImageItem imageItem = new ImageItem(); imageItem.ImageId = ImageItem.NEW_ID; imageItem.PhotoPath = url; imageGridAdapter.getmDataList().add(imageItem); imageGridAdapter.notifyDataSetChanged(); imageGridAdapter.uri = null; 这样问题是得到解决啦,但是用户取消的时候 size 也为 0 呀,这样无疑是画蛇添足,用户取消拍照都要显示加载框 10s,想想都可怕!!! 又听说在 new File 的前面加上下面的这句话可以解决,倒腾一番,然并卵。 // 小米4 LTE MIUI 7.0 版本下,file的size始终为0;通过提前获取ExifInterface信息,保证文件确实写入到外存 try { ExifInterface exifInterface = new ExifInterface(url); } catch (Exception e) { e.printStackTrace(); } 额,等等。上面说了,ExifInterface 可以拿到图片的宽高等参数,那我是不是可以直接通过判断图片宽高是否为 0 来判断用户是否拍照呢?如果 width 和 height 为 0,说明用户取消了拍照,不显示。否则显示图片,心动不如行动,直接上代码。 flag = true; Log.e(TAG, "onActivityResult: uri:" + imageGridAdapter.uri); if (null != imageGridAdapter.uri) { final String url = PhotoUtil.getImageUrlFromActivityResult(this, imageGridAdapter.uri); Log.e(TAG, "onActivityResult: url:" + url); boolean flag = true; // 小米4 LTE MIUI 7.0 版本下,file的size始终为0;通过提前获取ExifInterface信息,保证文件确实写入到外存 try { ExifInterface exifInterface = new ExifInterface(url); int height = exifInterface.getAttributeInt(ExifInterface.TAG_IMAGE_LENGTH, ExifInterface.ORIENTATION_NORMAL);//获取图片的高度 int width = exifInterface.getAttributeInt(ExifInterface.TAG_IMAGE_WIDTH, ExifInterface.ORIENTATION_NORMAL);//获取图片的宽度 Log.e(TAG, "onActivityResult: height:" + height); Log.e(TAG, "onActivityResult: width:" + width); if (height == 0 && width == 0) { flag = false; } } catch (Exception e) { e.printStackTrace(); } if (!TextUtils.isEmpty(url)) { file = new File(url); size = file.length(); Log.e(TAG, "onActivityResult: size:" + size); /** * MIUI8.0上面方案无法解决,经测试发现在一定时间后能保证size不为0 * 奇怪的发现当size为0的时候依然可以拿到图片,多款手机测试通过 */ if (flag) { ImageItem imageItem = new ImageItem(); imageItem.ImageId = ImageItem.NEW_ID; imageItem.PhotoPath = url; imageGridAdapter.getmDataList().add(imageItem); imageGridAdapter.notifyDataSetChanged(); imageGridAdapter.uri = null; } } } OK,终于解决了。希望能帮到大家! 做不完的开源,写不完的矫情。欢迎扫描下方二维码或者公众号搜索「nanchen」关注我的微信公众号,目前多运营 Android ,尽自己所能为你提升。如果你喜欢,为我点赞分享吧~ nanchen

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

.NET 11 来了:你写的 bug,编译器这次先替你看到了

引言:把不确定性收进类型里 年 11 月 10 日,.NET Conf 2026 开幕当天,微软正式发布 .NET 11。这是一个标准期限支持(STS)版本,提供两年支持;.NET 10 仍是当前的 LTS 选项。 如果只用一个词概括这一版,那就是——把不确定性收进类型里: C# 15 的联合类型,让「一个操作只有这几种结果」从口头约定变成编译器能检查的契约; Runtime Async 把异步状

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

Promise 链中 return 与不 return 的差异:一次真实 Bug 的排查记录

上周排查了一个数据上报丢失的问题,最终定位到 Promise 链中一个被忽略的 return。场景很简单:上报模块需要在发送请求前先获取一次设备指纹,拿到结果后再调用上报接口。代码里写了 `getFingerprint().then(fp => { report(fp) })` 这样的结构,看起来没问题,但监控显示大约有 3% 的上报请求在指纹接口超时后直接消失了。原因在于 then 回调没有返回内部 Promise,导致后续的 catch 无法捕获 report 内部的异步错误,同时链式调用的时序也出现了偏差。这个问题在业务代码里非常常见,尤其是从回调风格迁移到 Promise 时,开发者容易把 then 当作普通回调使用。下面从 Promise 的状态传递机制讲起,结合几个真实变体说明什么时候必须 return,以及如何用 async/await 重写来避免这类陷阱。 ## Promise 链的值传递到底依赖什么 Promise 的 then 方法会返回一个新的 Promise,这个新 Promise 的解决值取决于回调函数的返回值。如果回调返回一个值,新 Promise 就以该值 resolve;如果返回一个 Promise,新 Promise 会等待它 settle 并采用它的状态;如果抛出异常,新 Promise 就 reject。关键在于:如果回调函数没有显式 return,返回值是 undefined,新 Promise 会立即以 undefined resolve。 看下面这段代码: ```javascript function getFingerprint() { return fetch('/api/fingerprint').then(res => res.json()); } function report(data) { return fetch('/api/report', { method: 'POST', body: JSON.stringify(data), }); } // 错误写法 getFingerprint().then(fp => { report({ fp, ts: Date.now() }); }).catch(err => { console.error('上报失败', err); }); ``` 这里的 catch 只能捕获 getFingerprint 的失败,以及 then 回调同步执行时抛出的异常。report 返回的 Promise 如果 reject(比如网络错误、服务端 500),没有任何人处理它,浏览器会抛出 unhandledrejection。更隐蔽的是,如果后续还有 then,它会在 report 完成之前就执行,因为外层 Promise 已经以 undefined resolve 了。 ## 一个更接近线上的变体 实际代码往往包裹了一层业务函数,问题会更难发现: ```javascript function sendReport(payload) { return getFingerprint().then(fp => { // 这里忘记 return report({ ...payload, fp }); }).then(() => { markReported(payload.id); }); } ``` markReported 会在 report 请求真正完成之前就被调用。如果 report 失败并重试,标记逻辑已经执行过了,数据状态就对不上。这类问题在本地开发时很难复现,因为本地接口响应快,时序差异被掩盖;到了线上网络抖动时才会暴露。 修复只需要加一个 return: ```javascript function sendReport(payload) { return getFingerprint().then(fp => { return report({ ...payload, fp }); }).then(() => { markReported(payload.id); }); } ``` ## async/await 并不能自动解决 有人觉得换成 async/await 就安全了,但漏掉 await 是同样的错误: ```javascript async function sendReport(payload) { const fp = await getFingerprint(); report({ ...payload, fp }); // 缺少 await markReported(payload.id); } ``` 这里 report 的失败依然不会被 sendReport 的调用方感知,markReported 也会提前执行。区别只是错误变成了 unhandledrejection 而不是被吞掉。用 async/await 时,每个需要等待的异步调用都要显式 await,这一点和 then 里要 return 是同一个语义。 ## 在 lint 层面拦住这类问题 eslint 的 `no-floating-promises` 规则(需要 @typescript-eslint)能检查出未被处理的 Promise,但它对 then 回调里漏 return 的情况覆盖有限。更实用的是 `promise/no-return-wrap` 和 `promise/always-return` 这两个规则组合,后者要求 then 回调必须返回值,能在编码阶段就提示漏写 return。对于新项目,直接统一用 async/await 并开启 no-floating-promises,基本能杜绝大部分问题。 ```json { "rules": { "promise/always-return": "error", "promise/no-return-wrap": "error" } } ``` ## 一个容易混淆的边界:返回值的类型 then 回调返回 thenable 对象时,Promise 会尝试展开它。如果业务里返回的是类数组或者带 then 属性的普通对象,可能被误判。比如某些 ORM 的查询结果带有 then 方法,直接 return 会导致 Promise 链等待一个非预期的异步过程。遇到这种情况,用 `Promise.resolve(obj)` 包一层反而会触发展开,正确做法是返回一个不含 then 属性的普通对象,或者显式放在 `{ data: obj }` 里。 ```javascript // 假设 result 是一个带 then 方法的 QueryBuilder return { result }; // 安全,外层对象没有 then ``` 这类边界不常见,但一旦踩中,排查成本很高,因为错误表现往往是链式调用卡住或者后续 then 拿到奇怪的值。 回到最初的上报问题,最终改动是在业务封装层统一加了 return,并补了一条针对 unhandledrejection 的全局监控上报。Promise 链本身不难,难的是在团队协作中保持对返回值语义的一致理解。代码 review 时看到 then 回调,扫一眼有没有 return,已经成了习惯。 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5601.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5602.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5603.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5604.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5605.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5606.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5607.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5608.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5609.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5610.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5611.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5612.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5613.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5614.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5615.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5616.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5617.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5618.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5619.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5620.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5621.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5622.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5623.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5624.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5625.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5626.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5627.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5628.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5629.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5630.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5631.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5632.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5633.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5634.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5635.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5636.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5637.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5638.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5639.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5640.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5641.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5642.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5643.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5644.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5645.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5646.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5647.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5648.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5649.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5650.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5651.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5652.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5653.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5654.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5655.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5656.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5657.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5658.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5659.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5660.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5661.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5662.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5663.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5664.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5665.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5666.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5667.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5668.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5669.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5670.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5671.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5672.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5673.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5674.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5675.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5676.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5677.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5678.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5679.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5680.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5681.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5682.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5683.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5684.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5685.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5686.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5687.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5688.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5689.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5690.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5691.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5692.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5693.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5694.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5695.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5696.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5697.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5698.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5699.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5700.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5701.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5702.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5703.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5704.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5705.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5706.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5707.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5708.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5709.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5710.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5711.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5712.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5713.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5714.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5715.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5716.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5717.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5718.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5719.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5720.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5721.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5722.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5723.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5724.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5725.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5726.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5727.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5728.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5729.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5730.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5731.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5732.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5733.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5734.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5735.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5736.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5737.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5738.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5739.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5740.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5741.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5742.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5743.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5744.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5745.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5746.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5747.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5748.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5749.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5750.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5751.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5752.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5753.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5754.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5755.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5756.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5757.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5758.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5759.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5760.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5761.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5762.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5763.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5764.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5765.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5766.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5767.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5768.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5769.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5770.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5771.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5772.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5773.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5774.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5775.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5776.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5777.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5778.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5779.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5780.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5781.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5782.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5783.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5784.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5785.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5786.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5787.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5788.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5789.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5790.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5791.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5792.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5793.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5794.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5795.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5796.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5797.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5798.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5799.html 推荐查看天气:http://www.tianqi98.com/jizhuanwan/5800.html

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

Vue 3 中 watch 和 watchEffect 的依赖收集差异导致的一个隐蔽 bug

在最近维护的一个后台管理项目中,我遇到了一个很典型的问题:一个用于显示用户权限变更的 watch 回调在用户切换角色后偶尔不触发,但刷新页面后又恢复正常。排查后发现根源在于 watch 和 watchEffect 对响应式依赖的收集方式不同——watch 是惰性且显式声明依赖源,而 watchEffect 是立即执行并自动收集所有同步访问的响应式属性。这个差异在依赖包含条件分支或异步逻辑时尤其容易踩坑。文章会从实际代码出发,分析两者在依赖收集时机、副作用清除、以及嵌套引用场景下的行为区别,并给出如何根据业务场景正确选择的实践建议。 先看一段我最初写错的代码。这是一个权限管理组件,用 watchEffect 来监听用户角色和权限列表的变化,然后重新计算可访问的菜单。 ```vue ``` 问题出在 watchEffect 的依赖收集只跟踪同步执行期间访问的响应式属性。`await` 之后的代码属于微任务,此时 watchEffect 已经完成了初始的依赖收集。所以 `permissions.value` 的读取不会被记录为依赖。当 permissions 单独变化(比如其他地方更新了它)时,这个 effect 不会重新运行。而 currentRole 变化时因为它在 await 之前被访问,所以能触发——这就解释了为什么切换角色有时正常,但手动刷新权限列表时菜单不更新。 watch 的行为不同,它需要你明确指定监听源,并且不会自动追踪回调内部的任意访问。 ```javascript watch( () => currentRole.value, async (newRole) => { const perms = await getUserPermissions(newRole) permissions.value = perms menus.value = buildMenus(perms) }, { immediate: true } ) ``` 这样写虽然更啰嗦,但依赖关系清晰:只有 currentRole 变化才会重新请求权限。如果还需要监听 permissions 的变化,可以再写一个 watch,或者用 computed 组合。 另一个容易忽略的点是 watchEffect 的副作用清除。当依赖变化频繁时,前一次异步请求可能还没返回,新的请求又发出去了。Vue 提供了 onCleanup 来取消过期的请求。 ```javascript watchEffect((onCleanup) => { const controller = new AbortController() fetch(`/api/permissions?role=${currentRole.value}`, { signal: controller.signal }) .then(res => res.json()) .then(data => { permissions.value = data }) .catch(err => { if (err.name !== 'AbortError') throw err }) onCleanup(() => controller.abort()) }) ``` 这里 onCleanup 会在下一次 effect 执行前或组件卸载时调用,从而取消未完成的请求。如果不用 AbortController,至少也要用一个标志位来忽略过期响应。 那什么时候用 watch,什么时候用 watchEffect?我的经验是:只要依赖源是明确的一到两个 ref 或 props,并且需要拿到旧值、需要控制 immediate 或 deep 行为,就用 watch。如果副作用内部有多个条件分支,依赖项随着逻辑动态变化,或者你希望立即执行且不关心旧值,watchEffect 更合适。但务必注意:任何在 await 之后才读取的响应式数据,都不会被 watchEffect 追踪。如果确实需要,就把那部分逻辑拆到单独的 watch 里,或者用 computed 先算好。 还有一个隐藏的坑:在 watchEffect 里使用 `ref` 的解构或展开。比如 `const { role, permissions } = user`,如果 user 是 reactive 对象,解构会丢失响应性,watchEffect 自然也不会重新运行。保持对 `.value` 的完整访问路径是基本要求。 最后提一下调试技巧。Vue Devtools 可以查看组件内 effect 的依赖列表,但生产环境不方便。我通常会在 watchEffect 内部加一个计数,或者在 onCleanup 里打日志,观察 effect 重新执行的频率和时机。如果发现某个 effect 触发了但内部逻辑没有按预期走,优先检查 await 之后的代码是否访问了未被追踪的响应式属性。 推荐查看天气:https://www.40tianqi.com/yongxing/zuotian.html 推荐查看天气:https://www.40tianqi.com/yongxing/7tian.html 推荐查看天气:https://www.40tianqi.com/yongxing/10tian.html 推荐查看天气:https://www.40tianqi.com/yongxing/15tian.html 推荐查看天气:https://www.40tianqi.com/yongxing/40tian.html 推荐查看天气:https://www.40tianqi.com/jiahe/ 推荐查看天气:https://www.40tianqi.com/jiahe/zuotian.html 推荐查看天气:https://www.40tianqi.com/jiahe/7tian.html 推荐查看天气:https://www.40tianqi.com/jiahe/10tian.html 推荐查看天气:https://www.40tianqi.com/jiahe/15tian.html 推荐查看天气:https://www.40tianqi.com/jiahe/40tian.html 推荐查看天气:https://www.40tianqi.com/linwu/ 推荐查看天气:https://www.40tianqi.com/linwu/zuotian.html 推荐查看天气:https://www.40tianqi.com/linwu/7tian.html 推荐查看天气:https://www.40tianqi.com/linwu/10tian.html 推荐查看天气:https://www.40tianqi.com/linwu/15tian.html 推荐查看天气:https://www.40tianqi.com/linwu/40tian.html 推荐查看天气:https://www.40tianqi.com/rucheng/ 推荐查看天气:https://www.40tianqi.com/rucheng/zuotian.html 推荐查看天气:https://www.40tianqi.com/rucheng/7tian.html 推荐查看天气:https://www.40tianqi.com/rucheng/10tian.html 推荐查看天气:https://www.40tianqi.com/rucheng/15tian.html 推荐查看天气:https://www.40tianqi.com/rucheng/40tian.html 推荐查看天气:https://www.40tianqi.com/guidong/ 推荐查看天气:https://www.40tianqi.com/guidong/zuotian.html 推荐查看天气:https://www.40tianqi.com/guidong/7tian.html 推荐查看天气:https://www.40tianqi.com/guidong/10tian.html 推荐查看天气:https://www.40tianqi.com/guidong/15tian.html 推荐查看天气:https://www.40tianqi.com/guidong/40tian.html 推荐查看天气:https://www.40tianqi.com/anren/ 推荐查看天气:https://www.40tianqi.com/anren/zuotian.html 推荐查看天气:https://www.40tianqi.com/anren/7tian.html 推荐查看天气:https://www.40tianqi.com/anren/10tian.html 推荐查看天气:https://www.40tianqi.com/anren/15tian.html 推荐查看天气:https://www.40tianqi.com/anren/40tian.html 推荐查看天气:https://www.40tianqi.com/zixing/ 推荐查看天气:https://www.40tianqi.com/zixing/zuotian.html 推荐查看天气:https://www.40tianqi.com/zixing/7tian.html 推荐查看天气:https://www.40tianqi.com/zixing/10tian.html 推荐查看天气:https://www.40tianqi.com/zixing/15tian.html 推荐查看天气:https://www.40tianqi.com/zixing/40tian.html 推荐查看天气:https://www.40tianqi.com/yongzhou/ 推荐查看天气:https://www.40tianqi.com/yongzhou/zuotian.html 推荐查看天气:https://www.40tianqi.com/yongzhou/7tian.html 推荐查看天气:https://www.40tianqi.com/yongzhou/10tian.html 推荐查看天气:https://www.40tianqi.com/yongzhou/15tian.html 推荐查看天气:https://www.40tianqi.com/yongzhou/40tian.html 推荐查看天气:https://www.40tianqi.com/lingling/ 推荐查看天气:https://www.40tianqi.com/lingling/zuotian.html 推荐查看天气:https://www.40tianqi.com/lingling/7tian.html 推荐查看天气:https://www.40tianqi.com/lingling/10tian.html 推荐查看天气:https://www.40tianqi.com/lingling/15tian.html 推荐查看天气:https://www.40tianqi.com/lingling/40tian.html 推荐查看天气:https://www.40tianqi.com/lingshuitan/ 推荐查看天气:https://www.40tianqi.com/lingshuitan/zuotian.html 推荐查看天气:https://www.40tianqi.com/lingshuitan/7tian.html 推荐查看天气:https://www.40tianqi.com/lingshuitan/10tian.html 推荐查看天气:https://www.40tianqi.com/lingshuitan/15tian.html 推荐查看天气:https://www.40tianqi.com/lingshuitan/40tian.html 推荐查看天气:https://www.40tianqi.com/qiyang/ 推荐查看天气:https://www.40tianqi.com/qiyang/zuotian.html 推荐查看天气:https://www.40tianqi.com/qiyang/7tian.html 推荐查看天气:https://www.40tianqi.com/qiyang/10tian.html 推荐查看天气:https://www.40tianqi.com/qiyang/15tian.html 推荐查看天气:https://www.40tianqi.com/qiyang/40tian.html 推荐查看天气:https://www.40tianqi.com/dongan/ 推荐查看天气:https://www.40tianqi.com/dongan/zuotian.html 推荐查看天气:https://www.40tianqi.com/dongan/7tian.html 推荐查看天气:https://www.40tianqi.com/dongan/10tian.html 推荐查看天气:https://www.40tianqi.com/dongan/15tian.html 推荐查看天气:https://www.40tianqi.com/dongan/40tian.html 推荐查看天气:https://www.40tianqi.com/shuangpai/ 推荐查看天气:https://www.40tianqi.com/shuangpai/zuotian.html 推荐查看天气:https://www.40tianqi.com/shuangpai/7tian.html 推荐查看天气:https://www.40tianqi.com/shuangpai/10tian.html 推荐查看天气:https://www.40tianqi.com/shuangpai/15tian.html 推荐查看天气:https://www.40tianqi.com/shuangpai/40tian.html 推荐查看天气:https://www.40tianqi.com/daoxian/ 推荐查看天气:https://www.40tianqi.com/daoxian/zuotian.html 推荐查看天气:https://www.40tianqi.com/daoxian/7tian.html 推荐查看天气:https://www.40tianqi.com/daoxian/10tian.html 推荐查看天气:https://www.40tianqi.com/daoxian/15tian.html 推荐查看天气:https://www.40tianqi.com/daoxian/40tian.html 推荐查看天气:https://www.40tianqi.com/jiangyong/ 推荐查看天气:https://www.40tianqi.com/jiangyong/zuotian.html 推荐查看天气:https://www.40tianqi.com/jiangyong/7tian.html 推荐查看天气:https://www.40tianqi.com/jiangyong/10tian.html 推荐查看天气:https://www.40tianqi.com/jiangyong/15tian.html 推荐查看天气:https://www.40tianqi.com/jiangyong/40tian.html 推荐查看天气:https://www.40tianqi.com/ningyuan/ 推荐查看天气:https://www.40tianqi.com/ningyuan/zuotian.html 推荐查看天气:https://www.40tianqi.com/ningyuan/7tian.html 推荐查看天气:https://www.40tianqi.com/ningyuan/10tian.html 推荐查看天气:https://www.40tianqi.com/ningyuan/15tian.html 推荐查看天气:https://www.40tianqi.com/ningyuan/40tian.html 推荐查看天气:https://www.40tianqi.com/lanshan/ 推荐查看天气:https://www.40tianqi.com/lanshan/zuotian.html 推荐查看天气:https://www.40tianqi.com/lanshan/7tian.html 推荐查看天气:https://www.40tianqi.com/lanshan/10tian.html 推荐查看天气:https://www.40tianqi.com/lanshan/15tian.html 推荐查看天气:https://www.40tianqi.com/lanshan/40tian.html 推荐查看天气:https://www.40tianqi.com/xintian/ 推荐查看天气:https://www.40tianqi.com/xintian/zuotian.html 推荐查看天气:https://www.40tianqi.com/xintian/7tian.html 推荐查看天气:https://www.40tianqi.com/xintian/10tian.html 推荐查看天气:https://www.40tianqi.com/xintian/15tian.html 推荐查看天气:https://www.40tianqi.com/xintian/40tian.html 推荐查看天气:https://www.40tianqi.com/jianghua/ 推荐查看天气:https://www.40tianqi.com/jianghua/zuotian.html 推荐查看天气:https://www.40tianqi.com/jianghua/7tian.html 推荐查看天气:https://www.40tianqi.com/jianghua/10tian.html 推荐查看天气:https://www.40tianqi.com/jianghua/15tian.html 推荐查看天气:https://www.40tianqi.com/jianghua/40tian.html 推荐查看天气:https://www.40tianqi.com/huaihua/ 推荐查看天气:https://www.40tianqi.com/huaihua/zuotian.html 推荐查看天气:https://www.40tianqi.com/huaihua/7tian.html 推荐查看天气:https://www.40tianqi.com/huaihua/10tian.html 推荐查看天气:https://www.40tianqi.com/huaihua/15tian.html 推荐查看天气:https://www.40tianqi.com/huaihua/40tian.html 推荐查看天气:https://www.40tianqi.com/hecheng/ 推荐查看天气:https://www.40tianqi.com/hecheng/zuotian.html 推荐查看天气:https://www.40tianqi.com/hecheng/7tian.html 推荐查看天气:https://www.40tianqi.com/hecheng/10tian.html 推荐查看天气:https://www.40tianqi.com/hecheng/15tian.html 推荐查看天气:https://www.40tianqi.com/hecheng/40tian.html 推荐查看天气:https://www.40tianqi.com/zhongfang/ 推荐查看天气:https://www.40tianqi.com/zhongfang/zuotian.html 推荐查看天气:https://www.40tianqi.com/zhongfang/7tian.html 推荐查看天气:https://www.40tianqi.com/zhongfang/10tian.html 推荐查看天气:https://www.40tianqi.com/zhongfang/15tian.html 推荐查看天气:https://www.40tianqi.com/zhongfang/40tian.html 推荐查看天气:https://www.40tianqi.com/yuanling/ 推荐查看天气:https://www.40tianqi.com/yuanling/zuotian.html 推荐查看天气:https://www.40tianqi.com/yuanling/7tian.html 推荐查看天气:https://www.40tianqi.com/yuanling/10tian.html 推荐查看天气:https://www.40tianqi.com/yuanling/15tian.html 推荐查看天气:https://www.40tianqi.com/yuanling/40tian.html 推荐查看天气:https://www.40tianqi.com/chenxi/ 推荐查看天气:https://www.40tianqi.com/chenxi/zuotian.html 推荐查看天气:https://www.40tianqi.com/chenxi/7tian.html 推荐查看天气:https://www.40tianqi.com/chenxi/10tian.html 推荐查看天气:https://www.40tianqi.com/chenxi/15tian.html 推荐查看天气:https://www.40tianqi.com/chenxi/40tian.html 推荐查看天气:https://www.40tianqi.com/xupu/ 推荐查看天气:https://www.40tianqi.com/xupu/zuotian.html 推荐查看天气:https://www.40tianqi.com/xupu/7tian.html 推荐查看天气:https://www.40tianqi.com/xupu/10tian.html 推荐查看天气:https://www.40tianqi.com/xupu/15tian.html 推荐查看天气:https://www.40tianqi.com/xupu/40tian.html 推荐查看天气:https://www.40tianqi.com/huitong/ 推荐查看天气:https://www.40tianqi.com/huitong/zuotian.html 推荐查看天气:https://www.40tianqi.com/huitong/7tian.html 推荐查看天气:https://www.40tianqi.com/huitong/10tian.html 推荐查看天气:https://www.40tianqi.com/huitong/15tian.html 推荐查看天气:https://www.40tianqi.com/huitong/40tian.html 推荐查看天气:https://www.40tianqi.com/mayang/ 推荐查看天气:https://www.40tianqi.com/mayang/zuotian.html 推荐查看天气:https://www.40tianqi.com/mayang/7tian.html 推荐查看天气:https://www.40tianqi.com/mayang/10tian.html 推荐查看天气:https://www.40tianqi.com/mayang/15tian.html 推荐查看天气:https://www.40tianqi.com/mayang/40tian.html 推荐查看天气:https://www.40tianqi.com/xinhuang/ 推荐查看天气:https://www.40tianqi.com/xinhuang/zuotian.html 推荐查看天气:https://www.40tianqi.com/xinhuang/7tian.html 推荐查看天气:https://www.40tianqi.com/xinhuang/10tian.html 推荐查看天气:https://www.40tianqi.com/xinhuang/15tian.html 推荐查看天气:https://www.40tianqi.com/xinhuang/40tian.html 推荐查看天气:https://www.40tianqi.com/zhijiang/ 推荐查看天气:https://www.40tianqi.com/zhijiang/zuotian.html 推荐查看天气:https://www.40tianqi.com/zhijiang/7tian.html 推荐查看天气:https://www.40tianqi.com/zhijiang/10tian.html 推荐查看天气:https://www.40tianqi.com/zhijiang/15tian.html 推荐查看天气:https://www.40tianqi.com/zhijiang/40tian.html 推荐查看天气:https://www.40tianqi.com/jingzhouxian/ 推荐查看天气:https://www.40tianqi.com/jingzhouxian/zuotian.html 推荐查看天气:https://www.40tianqi.com/jingzhouxian/7tian.html 推荐查看天气:https://www.40tianqi.com/jingzhouxian/10tian.html 推荐查看天气:https://www.40tianqi.com/jingzhouxian/15tian.html 推荐查看天气:https://www.40tianqi.com/jingzhouxian/40tian.html 推荐查看天气:https://www.40tianqi.com/tongdao/ 推荐查看天气:https://www.40tianqi.com/tongdao/zuotian.html 推荐查看天气:https://www.40tianqi.com/tongdao/7tian.html 推荐查看天气:https://www.40tianqi.com/tongdao/10tian.html 推荐查看天气:https://www.40tianqi.com/tongdao/15tian.html 推荐查看天气:https://www.40tianqi.com/tongdao/40tian.html 推荐查看天气:https://www.40tianqi.com/hongjiang/ 推荐查看天气:https://www.40tianqi.com/hongjiang/zuotian.html 推荐查看天气:https://www.40tianqi.com/hongjiang/7tian.html 推荐查看天气:https://www.40tianqi.com/hongjiang/10tian.html 推荐查看天气:https://www.40tianqi.com/hongjiang/15tian.html 推荐查看天气:https://www.40tianqi.com/hongjiang/40tian.html 推荐查看天气:https://www.40tianqi.com/loudi/ 推荐查看天气:https://www.40tianqi.com/loudi/zuotian.html 推荐查看天气:https://www.40tianqi.com/loudi/7tian.html 推荐查看天气:https://www.40tianqi.com/loudi/10tian.html 推荐查看天气:https://www.40tianqi.com/loudi/15tian.html 推荐查看天气:https://www.40tianqi.com/loudi/40tian.html 推荐查看天气:https://www.40tianqi.com/louxing/ 推荐查看天气:https://www.40tianqi.com/louxing/zuotian.html 推荐查看天气:https://www.40tianqi.com/louxing/7tian.html

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Rocky Linux

Rocky Linux

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

用户登录
用户注册