2025-06-19
29
因为屏幕大小限制,经常需要将Iframe页面在新标签页打开,因此开发一个扩展程序快速在新标签页打开IframeChrome扩展程序需要一个manifest.json用于定义一些基础数据manifest.json:{ "name": "Iframe In New Tab", "description": "Open iframe Page In New Tab Quickly", "version": "1.0", "manifest_version": 3, "action": { "default_popup": "popup.html", "default_icon": "newtab_16.png" }, "permissions": [ "contextMenus" ], "background": { "service_worker": "background.js", "type": "module" }, "icons": { "16": "newtab_16.png", "48": "newtab_48.png", "128": "newtab_128.png" }}需要注意action、permissions、backgroundaction定义安装扩展程序后,浏览器右上方扩展程序按钮相关行为,default_popup为点击扩展程序图标后对应的页面,因为我们程序没有交互,因此给出简单提示popup.html:htmlstyle html, body { min-width: 205px; min-height: 33px; } hr { width: 100%; }/stylebody h1/h1 p bIframe In New Tab/b br Right-click the iframe area for options. /p/body/htmlpermissions为该扩展程序需要的权限,我们的扩展程序需要在浏览器创建右键菜单,因此声明contextMenus扩展程序可以在后台通过扩展程序的"service worker"监听浏览器事件,background用于指定你的相关监听代码,我们会在这里监听扩展程序安装事件,为页面创建右键菜单,以及该菜单的点击事件background.js:// 注册扩展程序安装事件,会在扩展程序被安装、扩展程序更新、浏览器更新时执行chrome.runtime.onInstalled.addListener(function () { chrome.contextMenus.create({ id: "iframe_menu", title: 'Open In New Tab', type: 'normal', contexts: ['frame'] });});// 监听菜单点击事件chrome.contextMenus.onClicked.addListener((info, tab) = { if (info.menuItemId === "iframe_menu") { // 获取iframe的URL const frameUrl = info.frameUrl; if (frameUrl) { chrome.tabs.create({ url: frameUrl, index: tab.index + 1 }); } }});将以上代码及相关图片资源放入一个文件夹中,打开Chrome扩展程序页面,启用开发者模式后,点击加载已解压的扩展程序,即可使用扩展程序使用效果展示:[图片]完整源码:Github参考资料:Hello World extension
继续阅读»
2025-05-09
188
最新版chrome136禁用了默认--user-data-dir的调试功能,--user-data-dir的默认路径为C:\Users\dell\AppData\Local\Google\Chrome\User Data\Default以前只需要指定--remote-debugging-port=9222即可调试,现在需要额外指定--user-data-dir"C:\Program Files\Google\Chrome\Application\chrome.exe" --remote-debugging-port=9222 --user-data-dir="C:\Chrome_data"vscode文档已经更新提示:if this flag isn't given, then the command will open a new window of any running browser and not enter debug mode更改了远程调试开关以提高安全性attaching-to-browsers
继续阅读»
2025-04-10
160
使用的旧版centos7系统导致使用let's Encrypt证书的网站无法访问,比如docker使用了cf的dns,会连接cf的registry。ab012f07497a: Waiting e0979c892644: Waiting error pulling image configuration: Get https://production.cloudflare.docker.com/registry-v2/docker/registry/v2/blobs/sha256/6a/6aedcda31f51881fd13e67674d84cd6661e278547dc7b23602672fb5a1f76ee4/data?expires=1744254640signature=S%2BTo9ZcvNHuuweoW7qCirv%2Fe9Uo%3Dversion=2: x509: certificate signed by unknown authority[root@13 ~]# curl -v https://xxx* About to connect() to xxx port 443 (#0)* Trying xxx...* Connected to xxx (xx) port 443 (#0)* Initializing NSS with certpath: sql:/etc/pki/nssdb* CAfile: /etc/pki/tls/certs/ca-bundle.crt CApath: none* Server certificate:* subject: CN=xxx* start date: Apr 08 18:01:56 2025 GMT* expire date: Jul 07 18:01:55 2025 GMT* common name: xxx* issuer: CN=R11,O=Let's Encrypt,C=US* NSS error -8179 (SEC_ERROR_UNKNOWN_ISSUER)* Peer's Certificate issuer is not recognized.* Closing connection 0curl: (60) Peer's Certificate issuer is not recognized.More details here: http://curl.haxx.se/docs/sslcerts.html研究发现是系统信任的根证书过期导致需要更新ca-certificates程序包,更新ca-certificates程序包后会自动更新系统信任的根证书查看已安装的版本1.debian/ubuntu# 查看已安装版本dpkg -l ca-certificates | grep ^ii# 或直接提取版本号dpkg-query -W -f='${Version}' ca-certificates2.centos/RHEL# 查看已安装版本rpm -q ca-certificates# 或结合 yum 查看信息yum info ca-certificates | grep -E "Name|Version" [root@13 ~]# yum info ca-certificatesLoaded plugins: fastestmirrorRepodata is over 2 weeks old. Install yum-cron? Or run: yum makecache fastDetermining fastest mirrors * elrepo-kernel: mirror.fcix.net * epel: irltoolkit.mm.fcix.netInstalled PackagesName : ca-certificatesArch : noarchVersion : 2015.2.6Release : 73.el7Size : 1.1 MRepo : installedFrom repo : anacondaSummary : The Mozilla CA root certificate bundleURL : http://www.mozilla.org/License : Public DomainDescription : This package contains the set of CA certificates chosen by the : Mozilla Foundation for use with the Internet PKI.Available PackagesName : ca-certificatesArch : noarchVersion : 2022.2.54Release : 74.el7_9Size : 911 kRepo : updates/7/x86_64Summary : The Mozilla CA root certificate bundleURL : http://www.mozilla.org/License : Public DomainDescription : This package contains the set of CA certificates chosen by the : Mozilla Foundation for use with the Internet PKI.发现已安装的是2015年的版本了更新ca-certificates# Debian/Ubuntusudo apt update sudo apt install --reinstall ca-certificates# CentOS/RHELsudo yum update ca-certificates# Fedorasudo dnf update ca-certificates# Alpine Linuxsudo apk update sudo apk add ca-certificates更新完成后应该就可以使用了,若不行可尝试执行手动更新update-ca-trustupdate-ca-trust force-enableupdate-ca-trust extractdocker需要重启才能生效参考:CentOS 7 更新根证书(root certificates)"docker pull" certificate signed by unknown authority
继续阅读»
2025-03-03
249
在实现一个Excel异步导入功能需要异步解析excel,使用@Async注解启用了解析方法的异步功能。但在解析方法内有Feign远程调用,该接口涉及接口权限,而@Async标注的方法与web请求不在同一个线程中,获取不到request。因此需要从上传接口传递request至异步方法。了解到RequestContextHolder.setRequestAttributes(RequestAttributes attributes, boolean inheritable)方法该方法是 Spring 框架提供的一个工具方法,用于在当前线程中手动设置请求上下文(RequestAttributes)。它主要用于跨线程传递和管理请求的上下文。我们需要在开启新线程前通过该方法手动设置当前的请求,以在多线程中访问到当前的request请求对象。但是我在设置后,获取到的request为空。最后发现是excel解析完成时,之前的导入接口已经完成响应,request对象已经被销毁回收了。后又了解到AsyncContext,它用于控制异步请求的生命周期在HttpServletRequest中提供了一个startAsync()方法用于启动异步处理,它会返回 AsyncContext 对象。此时request在标记异步请求完成前不会被回收。在后台任务完成后,调用 asyncContext.complete() 来标记异步请求的完成。示例代码:private AsyncContext asyncContext = null;public void import(MultipartFile file){ ServletRequestAttributes sra = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); RequestContextHolder.setRequestAttributes(sra, true); if (sra != null) { asyncContext = sra.getRequest().startAsync(); }// 调用异步解析方法parseFile(file)}@Asyncpublic void parseFile(MultipartFile file){// 一些耗时内容ServletRequestAttributes sra = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); RequestContextHolder.setRequestAttributes(sra, true);// 此时能够正常完成Feign调用(已自定义RequestInterceptor拦截器,将所需信息传递)xxFeignClient.xxxxx();// 完成异步处理 asyncContext.complete();}更新:此方式会阻塞主线程执行,多线程失去了意义,我的场景是被调用方读取header获取用户信息,所以我后续改为在子线程里面将用户信息手动设置到header中实现。参考:记一次springboot @Async处理导致后续request请求参数获取为空的坑
继续阅读»