Harmony 鸿蒙应用开发之解决 Web 组件加载本地资源跨域问题

鸿蒙开发文档中有一节 加载本地页面 提到了可以通过 $rawfile 方法加载本地 HTML 网页:

Index.ets
1
Web({ src: $rawfile("local.html"), controller: this.webviewController })

但是如果在 local.html 中需要引用一些静态资源,例如图片、JS、CSS 等,静态资源放在 local.html 同级目录下,会出现跨域的错误:

Console
1
Access to ... at 'resource://...' from origin 'null' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, arkweb, data, chrome-extension, chrome, https, chrome-untrusted.
阅读更多

Harmony 鸿蒙应用开发之展示 PDF 文件

鸿蒙应用展示 PDF 文件有三种方式

  1. 通过 ArkWeb 先加载 PDF.js,再用 PDF.js 加载 PDF 文件
  2. 通过 ArkWeb 直接加载 PDF 文件
  3. 原生加载

第一种方式比较复杂,涉及到 PDF.js 资源的加载、跨域的处理等,我就直接放代码仓库,读者可以自行研究: https://gitee.com/imaegoo/hm-pdf-viewer

更加推荐第二种方式,写法更简单

阅读更多

HarmonyOS NEXT 应用开发踩坑笔记

What’s HarmonyOS NEXT

鸿蒙系统将移除 AOSP(Android 开源项目),不再兼容 apk 格式的安卓应用的安装。

比较 Harmony 与 Android

系统HarmonyAndroid
语言ArkTSJava
IDEDevEco StudioAndroid Studio
安装包格式APPAPK

API 版本

API 9 对应兼容安卓的鸿蒙,API 10 和 API 11 对应鸿蒙 NEXT。

阅读更多

讯飞星火、阿里云通义千问 Web 端调用示例

正在开发一个问答小网页,需要接入大模型,查看了:

讯飞星火的调用文档: https://www.xfyun.cn/doc/spark/Web.html

通义千问的调用文档: https://help.aliyun.com/zh/dashscope/developer-reference/api-details

发现官方文档对于前端浏览器直接调用 API 的示例都写得不够清楚,所以在此重新封装了示例。

星火用的是 WebSocket 协议,千问用的是 Server-Sent Events,也就是 SSE。

注意:示例中直接把密钥写进了前端代码,生产环境不推荐这么做,建议通过 nginx 代理等方式将密钥注入请求。

阅读更多

分享本站友链页源代码

应博友 Inuyasha 的请求,现分享本站友链页源代码如下。

特性

自适应浅色主题和深色主题,自适应内容区宽度,自适应电脑、平板、手机。

阅读更多

git clone ssh 走代理

新建一个 C:\Users\你的用户名\.ssh\config 文件(没有扩展名,如果已存在此文件则不用新建),编辑此文件增加以下内容:

1
2
3
Host github.com *.github.com
User git
ProxyCommand connect -S 127.0.0.1:7890 %h %p

其中 Host 右边为需要走代理的域名列表,127.0.0.1:7890 替换为自己的代理服务器地址。

阅读更多

导出百度地图收藏点列表

打开百度地图 https://map.baidu.com/fav/,登录自己的账号,按 F12 打开控制台,点击 Network,再按 F5 刷新页面,在 Filter 中输入 favdata,即可筛选出收藏点的 API 接口。如果你的收藏点多于 100 个,你会筛选出多个请求。依次点击每个请求,点击 Preview,展开 sync - newdata,右键 newdata,点击 Copy object 即可复制出来收藏数据。

阅读更多

解决 Electron 应用在国产信创 Kylin 系统下 new Date() 时区错误的问题

在做客户端国产化改造时,发现页面上的时间全都差了 8 个小时,打开控制台打印 new Date() 显示的时区是 GMT,进一步测试发现,只有 Kylin 桌面系统上有这个问题,统信 UOS 系统没问题,解决方法很简单,在程序启动前手动指定时区。

main.ts
1
process.env.TZ = 'Asia/Shanghai';

解决蓝牙鼠标卡顿

蓝牙鼠标的一大好处是不占用任何笔记本电脑接口,适用于USB Type-A接口不够甚至无接口的笔记本电脑使用。目前最便宜的蓝牙鼠标只需50元左右。缺点是灵敏度和延迟都比传统有线鼠标和2.4G无线鼠标差。有时还会遇到卡顿、断线的情况,可以用以下办法排查一下。

  1. 鼠标电量低——需要更换电池或者充电,电池推荐用南孚、小米等碱性电池,不要用碳性电池。
  2. 蓝牙开了省电——在设备管理器中找到蓝牙设备属性里的电源管理,把“允许计算机关闭此设备以节约电源”勾掉。
  3. 无线网卡忙——绝大多数笔记本,蓝牙和WiFi是由同一个无线网卡驱动的,如果正在使用WiFi下载东西,蓝牙带宽就会受限,导致鼠标变卡,这种情况可以给下载限速或者改用有线网络。
  4. 蓝牙信号干扰——推荐买双模的无线鼠标,如果蓝牙被干扰了就暂时改用2.4G接收器。
  5. 桌面介质——不雅在玻璃等介质上使用鼠标,最好垫个鼠标垫。
  6. 驱动程序——有时候更新显卡驱动,更新蓝牙驱动能解决问题。

electron-forge 流水线踩坑记录

环境变量

  1. 环境变量 PATH 需包含 node、git 的可执行文件目录
  2. 在中国大陆跑,建议替换阿里镜像源提升依赖安装速度
1
2
3
registry=https://registry.npmmirror.com/
ELECTRON_MIRROR=https://npmmirror.com/mirrors/electron/
NODEJS_ORG_MIRROR=https://npmmirror.com/mirrors/node/
阅读更多

Vue 2 this.$emit 方法无效问题的解决

分享一个 Vue 2 $emit 不生效问题的解决,子组件向父组件 $emit 事件,没有报错,但父组件就是收不到事件。首先排除拼错事件名称等基本错误。

最终发现原因是:由于我将 $emit 写在了异步方法里,子组件在还没 $emit 之前就销毁了,此时再调用 $emit 不会有任何报错,也不会有任何效果,特此记录。

阅读更多

Hexo 博客集成内容管理系统 Decap

背景

一开始在做个人博客的框架选型时,我考虑过 WordPress、Typecho 等 PHP 框架,它们都自带一个内容管理系统,非常便于管理。但因为不想在服务器上花太多成本,我仍然选择了 Hexo 这种静态博客生成器,因为有很多优秀的静态博客托管平台可以选择。从此开始了一段博客折腾之旅。

曾经我也向朋友推荐 Hexo,列举它的种种优点,现在我也开始觉得 Hexo 写作太繁琐了。

静态博客最主要的缺点,一是不支持评论,二是缺少一个后台。不支持评论,写好的内容,无法与读者交流,是一件挺痛苦的事情。为此我搜遍互联网,最终选择了自己开发 Twikoo 无服务器评论系统,评论这件难题算是解决了。

阅读更多

Puppeteer 踩坑笔记

Puppeteer 是最常见的服务端 Node.js 网页转 PDF 工具库之一,原理是启动 Chromium 无头模式,打开网页,输出PDF,由于其原理是直接操控浏览器,导出的 PDF 几乎和网页效果一致。本篇记录一下踩坑经历。

我的 Puppeteer 版本:19.4.1

无法安装 puppeteer

  1. Node.js 要求 >=14.1.0
  2. Puppeteer 安装过程中默认访问 Google 服务器下载 Chromium 安装包,建议切换到阿里源进行安装。
1
npm config set PUPPETEER_DOWNLOAD_HOST=https://registry.npmmirror.com/-/binary
阅读更多

如何修改 Microsoft Edge 浏览器新标签页 URL

Microsoft Edge 浏览器的新标签页固定为 https://ntp.msn.cn/edge/ntp,就这么一个新标签页,不仅加载慢,还有一堆控制台报错。然而浏览器还没有提供修改新标签页地址的功能。

虽然安装浏览器插件可以实现,但是浏览器插件修改新标签页时,会有弹窗提示插件修改了新标签页。本文提供一种通过注册表完美修改新标签页的方法,已在 Microsoft Edge 版本 99.0.1150.46 测试有效。Win 10 家庭版 / Win 11 家庭版无效。

阅读更多

Twikoo 评论数据导出教程

因为数据库导出还算方便,所以 Twikoo 没有提供内置的数据导出功能。想要导出数据的话,首先确认自己部署 Twikoo 所用的方式,然后参考下面的教程。

阅读更多

静态博客接入 freecdn 提升访问速度

引言

上周,jsDelivr 备案许可被注销,导致本站大量静态资源加载失败,遂寻找更稳定的 CDN 替换,但是,替换 CDN 治标不治本。几天后,我在 GitHub 看到了 freecdn 这个项目,很好地解决了这个问题。

项目描述

freecdn 是一个纯前端的 CDN 解决方案,用于降低网站流量成本,同时提高网站稳定性、安全性,并且无需修改现有的业务逻辑。

互联网上有很多免费的公共库 CDN,例如 cdnjsjsdelivrunpkg,但哪个最稳定,始终没有明确的答案。

现在你无需纠结这个问题,随意选择即可。freecdn 可根据用户的网络状况,实时切换到合适的 CDN。

本文将会利用 freecdn 自动选择公共库的特性,加速 hexo icarus 站点。

阅读更多

解决 Windows 任务栏 bug,鼠标悬停效果在鼠标离开任务栏后依旧存在

鼠标移过任务栏后,明明鼠标早已经离开任务栏了,但是任务栏程序还是保持在鼠标悬停在上面的状态,一直都是这样,重启电脑或者重启资源管理器才可以解决问题,但是重启资源管理器又会导致一部分任务栏图标消失,很烦。

这个 bug 从 Windows 7 延续到 Windows 10,包括 Windows Server,依然没有解决,Windows 11 的任务栏大改,似乎解决了,但 Windows 11 的资源管理器卡顿问题更让人苦恼……

阅读更多

解决 Webpack 5 Asset Modules 字体文件报 404 找不到资源问题

老项目从 Webpack 4 升级到 Webpack 5,把静态资源 file-loader 换成了 Webpack 5 新增的 Asset Modules 特性:

1
2
3
4
5
6
7
8
9
10
11
12
13
  webpackChain
.rule('font-rule')
.test(/\.(ttf|eot|woff|woff2)$/)
- .use('file-loader')
- .loader('file-loader')
- .options({
- name: 'fonts/[contenthash].[ext]'
- })
+ .type('asset/resource')
+ .generator({
+ filename: 'fonts/[contenthash][ext]'
+ })
.end()

然而替换的过程没有那么顺利,编译打包虽然没有任何报错,但运行时字体文件报了 404。

阅读更多

降本增效利器之 Serverless

引言

近年来,Serverless 成为云计算领域热门词汇。早在 2014 年,亚马逊就在 AWSre:Invent 2014 大会上推出了 AWSLambda,赢得了开发者的广泛好评。2018 年,国内云服务厂商相继开始跟进,阿里云、腾讯云也推出了自己的 Serverless 云服务。今天我们就通过国内云厂商的案例来了解,Serverless 是什么?为什么需要 Serverless?它是如何降低软件开发成本,同时增加软件开发效率的?

阅读更多

常用多媒体软件的开源或免费替代

以下软件,除 FFmpeg 外,均支持中文。

屏幕录像

开源:OBS(直播推流软件,录屏功能也非常强大)
收费:Bandicam(收费录屏软件中自认为最好用的)

屏幕录像(GIF)

开源:ScreenToGif

图片处理

免费:XnViewMP(图片批处理功能非常好用,商用收费)

图片编辑

开源:GIMP(GNU 出品)
收费:Adobe Photoshop(Ps)

视频剪辑

免费:Avidemux(用于简单的剪辑、合并,处理速度极快)
开源:Shotcut(同事推荐)
免费:DaVinci Resolve(有收费版,免费版足矣)
收费:Adobe Premiere(Pr)

阅读更多

把 Win11 的文件资源管理器改回 Win10 的 Ribbon 风格

Windows 11 快速预览通道经过几个小版本更新后,修复了不少 bug,已经成为了我的主力系统。但是,作为平常使用最多的文件资源管理器,其新界面对性能的影响很大,尤其是在使用方向键切换选中的文件的时候,卡顿感严重。经过一番搜索,我找到了改回 Ribbon 风格文件资源管理器的方法,后者更稳定,性能更好。

阅读更多

集成 Twikoo 与 lightGallery 插件,实现评论图片的点击放大

Twikoo 文档页和本站的评论区,支持评论图片点击放大,你现在就可以就下拉到本文评论区试一试!

为什么 Twikoo 没有官方支持图片点击放大?

  1. 会增加包体大小
  2. 涉及 body DOM 节点操作,为了不影响在不同主题下的显示效果,需要杜绝这类操作
  3. lightGallery 库是 GPLv3 协议的

我就想要实现图片点击放大功能!

首先需要你拥有修改博客主题的能力。

阅读更多

关闭 Ubuntu 20 桌面版动画,使应用程序菜单不再卡顿

Ubuntu Desktop 应用程序菜单带有从屏幕底角到屏幕中心的动画。虽然这看起来很酷,但我感觉它很卡,优化很差,尤其是在集成显卡和虚拟机的环境中。如果你的想法和我一样,有一种方法可以关闭此动画,从而可以更快地从“应用程序”菜单中启动应用程序。

  1. 打开“终端”
  2. 执行以下命令,关闭动画,立即生效
    1
    gsettings set org.gnome.desktop.interface enable-animations false

想要重新开启动画,只需要执行

1
gsettings set org.gnome.desktop.interface enable-animations true

看看百度的答案都是些啥,还需要安装 compizconfig-settings-manager,其实一行命令就解决啦。

Twikoo 多个页面共用一个评论区

有时候博主希望多个页面共用一个评论区,我们可以自定义 path 做到这一点。

首先要确定自己所用的博客主题支持 Twikoo path 配置,否则需要自己修改主题源码添加 path 配置。

设置主题的 Twikoo path 配置为 window.TWIKOO_MAGIC_PATH||window.location.pathname

然后在所有需要共用评论区的页面正文中增加以下代码 <script>window.TWIKOO_MAGIC_PATH="评论区名称"</script>

把中间的“评论区名称”替换为你指定的名称,共用的页面请起 相同的 评论区名称,其他页面不做改动即可。

试试看!

阅读更多

Cloudflare Worker 无服务器追查 Git 仓库代码泄露

大部分 Git 平台,如 Github、Gitlab 等,会在打开仓库时自动渲染 README.md,而我们利用这一特性,通过对 README.md 中的图片访问日志加以记录,可以实现追查代码泄露的目的。

如果你还没有 Cloudflare 账号,可以申请一个

登录 Cloudflare 后,进入 Workers 页面,点击 KV。

阅读更多

体验 VitePress:文档编译还能这么快!

基于 VuePress 的项目文档的编译速度一直让我很苦恼,启动一次 dev server 要大约半分钟的时间,而且哪怕只有一个 Hello World,速度也是这么慢。相比之下,Hexo 都比它快。这当然不只是 VuePress 本身的问题,要说还得归咎于 Webpack。

于是 Vite 诞生了,一起诞生的还有 VitePress。好耶!虽然 VitePress 仍处于 WIP 阶段,告诉我们不要在任何地方使用,但我们可以提前对比一下,它究竟能比 VuePress 快多少?我们使用基于 VuePress 的 Twikoo 文档测试一下。

安装

1
yarn add -D vitepress
阅读更多

腾讯云云开发云函数 之 异步执行,提前返回

云函数的特性是,当 main 函数 return 时,执行进程会被立即冻结。这一点在官方文档Node.js 8 的异步行为中有提到。

对于异步函数,主流程执行完成后,函数实例进程会被冻结,进程中的所有异步任务会暂停执行,直到这个进程被再次唤起。
另一方面,如果函数实例进程由于某些原因没被复用(例如更新了函数代码),这个异步流程中的代码就永远不会被执行

但是有些场景下,云函数需要很长的执行时间,例如,Twikoo 通过 Akismet 检测垃圾评论的过程。按照特性,在检测过程结束前,就不能异步检测,提前返回结果给前端,否则检测进程就会被冻结,导致检测失败。我们只能 await 同步检测,造成请求响应慢,用户体验差。

按照 Java 的习惯,我们会启动新的线程执行长时间的任务,在云函数中怎样实现?

阅读更多

腾讯云云开发云函数 之 文件导入功能

背景

Twikoo 评论系统要实现导入功能,导入,就需要上传文件。

通过调用云函数,我们能够传递 string、number 等简单的参数,想要上传文件?不太行。

想到云开发环境有一块默认开通的 COS 空间,这块空间允许登录用户上传文件,只要利用这片空间,就可以实现将文件上传给云函数的功能了。

主要思路

  1. 前端调用 js-sdk 上传文件,获取到 fileID
  2. 前端将 fileID 作为参数,调用云函数
  3. 云函数通过 fileID 获取到文件,并解析
阅读更多

解决微信小程序在 iPhone iOS 上 text 宽度只有一半导致的不居中等种种问题

现象

当小程序中使用第三方字体时,在 iPhone 11 和 iPhone 12 机型下

  • 中文字正常
  • 英文字和数字,居中和右对齐异常

这个问题只能在几个特定的机型下出现,不用第三方字体也没有这个问题,安卓机型和开发者工具也重现不了,甚至 iPhone 12 mini 用同一版本也不能重现。

微信版本:7.0.18
小程序基础库:2.14.0
iOS:14.2

这未免也太奇怪了。

阅读更多

腾讯云云开发云函数 之 代码共用

腾讯云云开发云函数的文档中写道——

不同的云函数可以共用代码文件(目录)吗
未上线

如果是简单的云函数,这一点还能接受,在开发 Twikoo 评论系统的过程中,云函数要实现的 API 越来越多,逐渐让我发现了它的弊端:

  1. 大量的代码复制!
  2. 版本管理非常不便!
  3. 依赖管理非常不便!
  4. 一次要部署十来个云函数,很麻烦!
  5. 每个云函数都有独立的冷启动时间,很慢!

显然违反了开发的 DRY 原则,这迫使我开始思考解决方案。

正常的思维是,一个 API 写一个云函数,如果将云函数合并,用一个云函数实现不同的功能,能否解决这样的问题呢?

阅读更多

无需开发/体验权限,获取任意微信小程序卡片页面路径

背景

工作上正在开发的一款小程序,需要链接到京东购物的一个活动页面。经过搜索发现,除了在小程序内嵌 Webview,小程序内不能直接跳转一个网页,但是京东也是有自己的小程序的,我们可以跳转到京东的小程序吗?查找文档发现可以用 wx.navigateToMiniProgram 打开另一个小程序。

1
2
3
4
wx.navigateToMiniProgram({
appId: '', // 要打开的小程序 appId
path: '' // 打开的页面路径,如果为空则打开首页
})

现在需要的就是京东小程序的 appId 和活动页面的 path 了!

一番操作后,我发现微信 APP 上既不能获取到小程序的 appId 也不能获取到活动页面的 path,若要获得这两样东西,得开启调试才行,想开启调试,至少要成为小程序开发者……

京东小程序的开发者,我怎么可能拿得到嘛,我连他们的开发者都接触不到!

阅读更多

VuePress 自定义默认主题页眉页脚

方式

添加 2 个文件

.vuepress/theme/index.js
1
2
3
module.exports = {
extend: '@vuepress/theme-default'
}
.vuepress/theme/layouts/Layout.vue
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
<template>
<ParentLayout>
<template #sidebar-top>
<div>My custom sidebar-top</div>
</template>
<template #sidebar-bottom>
<div>My custom sidebar-bottom</div>
</template>
<template #page-top>
<div>My custom page-top</div>
</template>
<template #page-bottom>
<div>My custom page-bottom</div>
</template>
</ParentLayout>
</template>

<script>
import ParentLayout from '@parent-theme/layouts/Layout.vue'

export default {
name: 'Layout',
components: {
ParentLayout
}
}
</script>
阅读更多

博客已启用 Twikoo 评论系统

评论系统一直是静态网站的痛点。

  • Valine:安全性不高
  • Gitalk:需要评论者注册Github
  • Disqus:需要注册,国内访问不畅
  • 畅言:广告多,需要验证手机号

难道就没有一个完美的方案?

咕咕咕了近三个月后,我自己搞出了一套评论系统,并命名为 Twikoo。

  • 成本上,腾讯云云开发环境可以免费搭建
  • 安全性上,使用腾讯云云函数开发接口,不开放一丁点数据库权限,未来更新将接入 Akismet 反垃圾检查
  • 易用性上,支持点赞、邮件通知、微信通知(限博主),未来会增加更多玩法

欢迎访问 twikoo.js.org 了解更多。

阅读更多

Valine 1.4 如何保护评论者的邮箱和 IP

前言

AyagawaSeirin 提出了一个 Valine 隐私安全漏洞,发送请求中响应内容明文暴露评论者IP、邮箱等隐私内容,所以我就去查了一下 LeanCloud 文档,发现可以手动更改字段权限,但是,如果设置 mail 客户端不可见,将不会显示评论者的 Gravatar,转为显示默认头像,因为原版是取到明文邮箱后再转 MD5 取头像的。想到的解决办法是新增一个可见字段存储 mail 的 MD5,需要改 Valine 源码,还需要处理现有数据。

以下是我实现的魔改版本,基于 Valine.min.js 版本 1.4.14 修改。该魔改版新增一个可见字段(mailMd5)存储 mail 的 MD5,并提供了脚本处理现有评论数据。

阅读更多

神奇的 @media (prefers-color-scheme: dark)

夜间模式已经实现很久了,当初有人跟我讲,可以增加一个按时间切换的功能。

直到我在无意间查看 Reabble 阅读器的 CSS 样式时,发现了 @media (prefers-color-scheme: dark) 选择器。

来自prefers-color-scheme - CSS(层叠样式表) | MDN
prefers-color-scheme CSS 媒体特性用于检测用户是否有将系统的主题色设置为亮色或者暗色。

简而言之,就是可以实现随系统(或浏览器)的深、浅色模式设置,改变网页配色。

我觉得这是比按时间切换更好的一个实现,跟随系统设置比跟随时间更加人性化一些,毕竟还有我这种,白天开深色,晚上开浅色的异类(逃)

阅读更多

VuePress 密码加密文章

前言

事情的起因是,我需要一个存放未分类整理知识点,以及收藏转载文章的私人知识库,和 iMaeGoo’s Blog 区别开来。

我尝试过简书、语雀、Evernote、OneNote、有道云笔记,对它们的 markdown 支持、导出能力、搜索能力、容量、安全性都有体会。

频繁的整顿让我对其安全性产生担忧

最后我决定建一个私人 Git 仓库,用 markdown 来记笔记。然后通过 CI/CD 自动构建到一个叫 iMaeGoo’s Diary 的 VuePress 网站。写笔记 Notepad + Git 就能搞定,还能自由选择多种多样的 markdown 编辑器,手机端也可以通过在线 IDE 更新内容,VuePress 的搜索非常好用,安全性也完全在自己的掌控范围之内。

反正是知识库嘛,我配置了完全公开,方便自己随时随地查看,但由于是未经整理的知识库,也不建议访客去看啦。

问题就来了,有些笔记包含了敏感信息,怎么在公开的知识库中保护这类信息?

在寻找 VuePress 加密时,我发现了 vuepress-plugin-encrypt 这个好用的插件,使用了 aes-128-ctr 来加密内容,你可以直接查看它的英文官方文档

阅读更多

PC 浏览器平滑惯性滚动(smooth scroll)一套简单实现

前言

主要是 Bing 找了许多 libraries。效果在 Chrome for Windows 上都不理想,要么滚动很生硬,要么就是太复杂,就自己实现了。

本来是 PC only 的,写好后测试了一下移动端,是兼容的,效果也还不错……

不过反正移动端都自带惯性滑动了

效果

无惯性滚动

有惯性滚动

阅读更多

解决 Edge 浏览器 SCRIPT5022: Exception thrown and not caught

JS 代码在 Safari, Chrome, Firefox 都是好的,就只有 Edge 莫名其妙地报错。

1
SCRIPT5022: Exception thrown and not caught

未捕获的异常?EXM?你倒是说是什么异常啊?行号还是错的?点过去无法定位错误位置?hash-navigation.js?我的项目里根本都没有这个 js 啊喂!

阅读更多

纯 CSS 实现椭圆轨迹旋转小球

话不多说看效果

阅读更多

JDBC 连接 Azure Database for MySQL 报错 SSL peer shut down incorrectly 的解决

这个问题找了一天的原因,如果你也遇到了这个问题,希望能帮到你。

完整错误信息:

点击展开 >folded
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
03-Jun-2020 07:52:22.772 SEVERE [main] org.apache.tomcat.jdbc.pool.ConnectionPool.init Unable to create initial connections of pool.
com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure

The last packet successfully received from the server was 384 milliseconds ago. The last packet sent successfully to the server was 376 milliseconds ago.
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:490)
at com.mysql.jdbc.Util.handleNewInstance(Util.java:411)
at com.mysql.jdbc.SQLError.createCommunicationsException(SQLError.java:1117)
at com.mysql.jdbc.ExportControlled.transformSocketToSSLSocket(ExportControlled.java:105)
at com.mysql.jdbc.MysqlIO.negotiateSSLConnection(MysqlIO.java:5126)
at com.mysql.jdbc.MysqlIO.proceedHandshakeWithPluggableAuthentication(MysqlIO.java:1666)
at com.mysql.jdbc.MysqlIO.doHandshake(MysqlIO.java:1244)
at com.mysql.jdbc.ConnectionImpl.coreConnect(ConnectionImpl.java:2397)
at com.mysql.jdbc.ConnectionImpl.connectOneTryOnly(ConnectionImpl.java:2430)
at com.mysql.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:2215)
at com.mysql.jdbc.ConnectionImpl.<init>(ConnectionImpl.java:813)
at com.mysql.jdbc.JDBC4Connection.<init>(JDBC4Connection.java:47)
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:490)
at com.mysql.jdbc.Util.handleNewInstance(Util.java:411)
at com.mysql.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:399)
at com.mysql.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:334)
at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:319)
at org.apache.tomcat.jdbc.pool.PooledConnection.connect(PooledConnection.java:212)
at org.apache.tomcat.jdbc.pool.ConnectionPool.createConnection(ConnectionPool.java:744)
at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:676)
at org.apache.tomcat.jdbc.pool.ConnectionPool.init(ConnectionPool.java:483)
at org.apache.tomcat.jdbc.pool.ConnectionPool.<init>(ConnectionPool.java:154)
at org.apache.tomcat.jdbc.pool.DataSourceProxy.pCreatePool(DataSourceProxy.java:118)
at org.apache.tomcat.jdbc.pool.DataSourceProxy.createPool(DataSourceProxy.java:107)
at org.apache.tomcat.jdbc.pool.DataSourceFactory.createDataSource(DataSourceFactory.java:560)
at org.apache.tomcat.jdbc.pool.DataSourceFactory.getObjectInstance(DataSourceFactory.java:244)
at org.apache.naming.factory.FactoryBase.getObjectInstance(FactoryBase.java:96)
at java.naming/javax.naming.spi.NamingManager.getObjectInstance(NamingManager.java:325)
at org.apache.naming.NamingContext.lookup(NamingContext.java:857)
at org.apache.naming.NamingContext.lookup(NamingContext.java:160)
at org.apache.naming.NamingContext.lookup(NamingContext.java:843)
at org.apache.naming.NamingContext.lookup(NamingContext.java:174)
at org.apache.catalina.core.NamingContextListener.addResource(NamingContextListener.java:1017)
at org.apache.catalina.core.NamingContextListener.createNamingContext(NamingContextListener.java:557)
at org.apache.catalina.core.NamingContextListener.lifecycleEvent(NamingContextListener.java:253)
at org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:123)
at org.apache.catalina.core.StandardServer.startInternal(StandardServer.java:924)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
at org.apache.catalina.startup.Catalina.start(Catalina.java:633)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:344)
at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:475)
Caused by: javax.net.ssl.SSLHandshakeException: Remote host terminated the handshake
at java.base/sun.security.ssl.SSLSocketImpl.handleEOF(SSLSocketImpl.java:1322)
at java.base/sun.security.ssl.SSLSocketImpl.decode(SSLSocketImpl.java:1160)
at java.base/sun.security.ssl.SSLSocketImpl.readHandshakeRecord(SSLSocketImpl.java:1063)
at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:402)
at com.mysql.jdbc.ExportControlled.transformSocketToSSLSocket(ExportControlled.java:90)
... 44 more
Suppressed: java.net.SocketException: Broken pipe (Write failed)
at java.base/java.net.SocketOutputStream.socketWrite0(Native Method)
at java.base/java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:110)
at java.base/java.net.SocketOutputStream.write(SocketOutputStream.java:150)
at java.base/sun.security.ssl.SSLSocketOutputRecord.encodeAlert(SSLSocketOutputRecord.java:81)
at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:351)
at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:263)
at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:405)
... 45 more
Caused by: java.io.EOFException: SSL peer shut down incorrectly
at java.base/sun.security.ssl.SSLSocketInputRecord.decode(SSLSocketInputRecord.java:167)
at java.base/sun.security.ssl.SSLTransport.decode(SSLTransport.java:108)
at java.base/sun.security.ssl.SSLSocketImpl.decode(SSLSocketImpl.java:1152)
... 47 more

提取关键信息:

1
2
Caused by: javax.net.ssl.SSLHandshakeException: Remote host terminated the handshake
Caused by: java.io.EOFException: SSL peer shut down incorrectly

得知 SSL 握手失败,于是我找了 Azure 的示例代码(https://docs.azure.cn/zh-cn/mysql/connect-java)来测,也是同样的问题。

阅读更多
网页中文字体压缩(woff2)、拆分、去繁体字库,提高加载速度

网页中文字体压缩(woff2)、拆分、去繁体字库,提高加载速度

从客户得到的网页字体足足有 10MB 大小,会严重拖慢网页加载,如何处理?

阅读下面的解决方法前,建议先阅读网页字体优化,了解一些基本知识,以及,为什么。

字体去繁体

GBK 结尾的字体偏大的原因是包含庞大的繁体字库,大多数网页并不需要,可以使用 fontTools 得到字体的简体中文子集。

阅读更多
让 Icarus Insight 搜索插件支持拼音检索文章
屏蔽安卓 QQ 8.2 聊天个性字体

屏蔽安卓 QQ 8.2 聊天个性字体

摸索过程

我一直在用 Google Play 版本的 QQ,简洁没有花里胡哨的功能,要问我为什么不用 TIM?因为 TIM 实在太简洁了,连表情都不能下载。

今天突然发现 Play 里的 QQ 更新了!终于不是那个远古版本的 7.7.6 了。

我比较喜欢消息气泡,有时候我甚至可以看气泡认人,但我非常讨厌个性字体,一些字体的辨识度实在低,虽然可以双击查看消息,但能够屏蔽就舒服了。在 7.7.6 中我通过删除 Tencent/MobileQQ/.font_info 目录并创建同名文件来屏蔽字体,新版不起作用了。

找了一圈,发现是这个目录位置变了,现在是 Android/data/com.tencent.mobileqq/Tencent/MobileQQ/.font_info/

马上删掉,创建同名文件!

然后就遇到问题,QQ 学聪明了,删除了我创建的文件,然后重新加载了字体。

我又想到了给 000 权限,但是 Android 内部存储中的文件是不能设权限的,此路不通。

经过一番尝试,我找到了新的办法屏蔽字体,简而言之,就是用空文件替换所有的 ttf。

阅读更多