<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <id>https://shuhangli.com/</id>
    <title>个人资料系统日志扩展备份 Blog</title>
    <updated>2026-10-10T00:00:00.000Z</updated>
    <generator>https://github.com/jpmonette/feed</generator>
    <link rel="alternate" href="https://shuhangli.com/"/>
    <subtitle>个人资料系统日志扩展备份 Blog</subtitle>
    <icon>https://shuhangli.com/logo.jpeg</icon>
    <entry>
        <title type="html"><![CDATA[RustDesk iOS 定制：接入私有 Rustk API Server，改善移动端远控体验]]></title>
        <id>https://shuhangli.com/2026/10/10/2026-10-10/rustdesk-ios-enhanced</id>
        <link href="https://shuhangli.com/2026/10/10/2026-10-10/rustdesk-ios-enhanced"/>
        <updated>2026-10-10T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[现有远程控制环境采用 Rustk API Server、hbbs 和 hbbr 组合部署：账号与地址簿服务只在 Tailnet 内开放，远控信令和中继保留公网入口，私有网络由自建 Headscale 管理。]]></summary>
        <content type="html"><![CDATA[<p>现有远程控制环境采用 Rustk API Server、hbbs 和 hbbr 组合部署：账号与地址簿服务只在 Tailnet 内开放，远控信令和中继保留公网入口，私有网络由自建 Headscale 管理。</p>
<p>这次基于 RustDesk <code>1.5.0</code> 定制 iOS 客户端，重点解决两件事：让应用自身访问私有 API，同时让 iPhone、iPad 上的设备选择、画面方向和触摸操作更顺手。</p>
<p>这套部署将账号管理、连接协调和会话数据传输分开处理：</p>
<ul>
<li class=""><strong>Rustk API Server</strong>：提供账号登录、设备管理和地址簿同步，服务端口为 <code>21114</code>，仅通过 Tailnet 私网访问。</li>
<li class=""><strong>hbbs</strong>：提供设备注册、ID 查询和连接协调，主入口为公网 <code>21116</code>；当前部署使用支持 TCP KeyExchange 的补丁版本。</li>
<li class=""><strong>hbbr</strong>：使用官方 RustDesk OSS 中继服务，主入口为公网 <code>21117</code>，负责需要中继时的会话数据转发。</li>
<li class=""><strong>Headscale</strong>：自建的 Tailscale 控制服务，负责节点注册、授权及网络信息分发。它与 Rustk API Server 是两个独立服务，不承担远程桌面流量中继。</li>
</ul>
<p>下图展示定制后的 iOS 客户端如何接入现有部署。按服务职责划分逻辑链路，不表示这些组件必须部署在不同物理主机上；图中省略了域名、节点地址及其他辅助端口。</p>
<p><img decoding="async" loading="lazy" alt="RustDesk iOS、Rustk API Server、hbbs、hbbr 与自建 Headscale 的网络拓扑" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMTYwIiBoZWlnaHQ9Ijg4MCIgdmlld0JveD0iMCAwIDExNjAgODgwIiByb2xlPSJpbWciIGFyaWEtbGFiZWxsZWRieT0idGl0bGUgZGVzYyI+CiAgPHRpdGxlIGlkPSJ0aXRsZSI+UnVzdERlc2sgaU9TIOWumuWItuWQjueahOe9kee7nOaLk+aJkTwvdGl0bGU+CiAgPGRlc2MgaWQ9ImRlc2MiPmlPUyDlrqLmiLfnq6/pgJrov4fljp/mnInnvZHnu5zorr/pl67lhaznvZEgaGJicyDlkowgaGJicu+8jOS4juiiq+aOp+iuvuWkh+W7uueri+S/oeS7pOWSjOS4ree7p+i/nuaOpeOAguW6lOeUqOWGheW1jCB0c25ldCDoioLngrnpgJrov4cgVGFpbG5ldCDnp4HnvZHorr/pl64gUnVzdGsgQVBJIFNlcnZlcuOAguiHquW7uiBIZWFkc2NhbGUg54us56uL6LSf6LSj6IqC54K55rOo5YaM5LiO5o6I5p2D44CC5Zu+5Lit5bGV56S65Lit57un6Lev5b6E77yM55yB55Wl55u06L+e6Lev5b6E44CB5Z+f5ZCN5ZKM6L6F5Yqp56uv5Y+j44CCPC9kZXNjPgogIDxkZWZzPgogICAgPG1hcmtlciBpZD0iYmx1ZS1hcnJvdyIgbWFya2VyV2lkdGg9IjgiIG1hcmtlckhlaWdodD0iOCIgcmVmWD0iNyIgcmVmWT0iNCIgb3JpZW50PSJhdXRvLXN0YXJ0LXJldmVyc2UiPjxwYXRoIGQ9Ik0wIDBMOCA0TDAgOFoiIGZpbGw9IiMyNTYzZWIiLz48L21hcmtlcj4KICAgIDxtYXJrZXIgaWQ9ImdyZWVuLWFycm93IiBtYXJrZXJXaWR0aD0iOCIgbWFya2VySGVpZ2h0PSI4IiByZWZYPSI3IiByZWZZPSI0IiBvcmllbnQ9ImF1dG8tc3RhcnQtcmV2ZXJzZSI+PHBhdGggZD0iTTAgMEw4IDRMMCA4WiIgZmlsbD0iIzA4N2Y3MCIvPjwvbWFya2VyPgogICAgPG1hcmtlciBpZD0iZ3JheS1hcnJvdyIgbWFya2VyV2lkdGg9IjgiIG1hcmtlckhlaWdodD0iOCIgcmVmWD0iNyIgcmVmWT0iNCIgb3JpZW50PSJhdXRvLXN0YXJ0LXJldmVyc2UiPjxwYXRoIGQ9Ik0wIDBMOCA0TDAgOFoiIGZpbGw9IiM2NDc0OGIiLz48L21hcmtlcj4KICAgIDxzdHlsZT4KICAgICAgdGV4dCB7IGZvbnQtZmFtaWx5OiAiTWljcm9zb2Z0IFlhSGVpIiwgIlBpbmdGYW5nIFNDIiwgIk5vdG8gU2FucyBDSksgU0MiLCBzYW5zLXNlcmlmOyBmaWxsOiAjMTcyYjRkOyB9CiAgICAgIC50aXRsZSB7IGZvbnQtc2l6ZTogMjlweDsgZm9udC13ZWlnaHQ6IDcwMDsgfQogICAgICAuaGVhZGluZyB7IGZvbnQtc2l6ZTogMjNweDsgZm9udC13ZWlnaHQ6IDcwMDsgfQogICAgICAuYm9keSB7IGZvbnQtc2l6ZTogMjBweDsgfQogICAgICAuc21hbGwgeyBmb250LXNpemU6IDE4cHg7IGZpbGw6ICM1MjY0N2I7IH0KICAgICAgLmJsdWUgeyBmaWxsOiAjMjU2M2ViOyB9CiAgICAgIC5ncmVlbiB7IGZpbGw6ICMwODdmNzA7IH0KICAgICAgLndpcmUgeyBmaWxsOiBub25lOyBzdHJva2Utd2lkdGg6IDIuNTsgc3Ryb2tlLWxpbmVqb2luOiByb3VuZDsgfQogICAgPC9zdHlsZT4KICA8L2RlZnM+CiAgPHJlY3Qgd2lkdGg9IjExNjAiIGhlaWdodD0iODgwIiByeD0iMTYiIGZpbGw9IiNmZmZmZmYiLz4KICA8dGV4dCBjbGFzcz0idGl0bGUiIHg9IjQwIiB5PSI1MCI+QVBJIOi1sOengee9ke+8jOi/nOaOp+S/oeS7pOS4juS4ree7p+S/neeVmeWFrOe9keWFpeWPozwvdGV4dD4KICA8dGV4dCBjbGFzcz0ic21hbGwiIHg9IjQwIiB5PSI4NCI+6YC76L6R5ouT5omRIMK3IOS7hSBBUEkg5YiG5rWB5byA5ZCvIMK3IOWbvuekuuS4ree7p+i/nuaOpe+8jOecgeeVpeebtOi/nui3r+W+hDwvdGV4dD4KICA8cmVjdCB4PSI0MCIgeT0iMTI1IiB3aWR0aD0iMjUwIiBoZWlnaHQ9IjUxNSIgcng9IjEyIiBmaWxsPSIjZjhmYWZjIiBzdHJva2U9IiNjYmQ1ZTEiIHN0cm9rZS13aWR0aD0iMiIvPgogIDx0ZXh0IGNsYXNzPSJoZWFkaW5nIiB4PSI2NSIgeT0iMTYzIj5pUGhvbmUgLyBpUGFkPC90ZXh0PgogIDx0ZXh0IGNsYXNzPSJib2R5IiB4PSI2NSIgeT0iMTk1Ij5SdXN0RGVzayBpT1Mg5a6a5Yi254mIPC90ZXh0PgogIDxyZWN0IHg9IjY1IiB5PSIyMzUiIHdpZHRoPSIyMDAiIGhlaWdodD0iMTUwIiByeD0iMTAiIGZpbGw9IiNmZmZmZmYiIHN0cm9rZT0iI2NiZDVlMSIvPgogIDx0ZXh0IGNsYXNzPSJoZWFkaW5nIiB4PSI4NSIgeT0iMjcxIj5GbHV0dGVyICsgUnVzdDwvdGV4dD4KICA8dGV4dCBjbGFzcz0iYm9keSIgeD0iODUiIHk9IjMwNiI+5Y6f5pyJ5Y2P6K6u5LiO6K6k6K+BPC90ZXh0PgogIDx0ZXh0IGNsYXNzPSJzbWFsbCIgeD0iODUiIHk9IjM0MiI+SUQgLyDkuK3nu6fvvJrljp/mnInnvZHnu5w8L3RleHQ+CiAgPHBhdGggY2xhc3M9IndpcmUiIGQ9Ik0xNjUgMzg1VjQ3NSIgc3Ryb2tlPSIjMDg3ZjcwIiBtYXJrZXItZW5kPSJ1cmwoI2dyZWVuLWFycm93KSIvPgogIDx0ZXh0IGNsYXNzPSJzbWFsbCBncmVlbiIgeD0iMTgzIiB5PSI0MzIiPkFQSSDor7fmsYI8L3RleHQ+CiAgPHJlY3QgeD0iNjUiIHk9IjQ4NSIgd2lkdGg9IjIwMCIgaGVpZ2h0PSIxMTAiIHJ4PSIxMCIgZmlsbD0iI2VjZmRmNSIgc3Ryb2tlPSIjMDg3ZjcwIiBzdHJva2Utd2lkdGg9IjIiLz4KICA8dGV4dCBjbGFzcz0iaGVhZGluZyBncmVlbiIgeD0iODYiIHk9IjUyNCI+5YaF5bWMIHRzbmV0PC90ZXh0PgogIDx0ZXh0IGNsYXNzPSJib2R5IiB4PSI4NiIgeT0iNTU5Ij7ni6znq4sgVGFpbG5ldCDoioLngrk8L3RleHQ+CiAgPHJlY3QgeD0iMzcwIiB5PSIxMjUiIHdpZHRoPSIzNjUiIGhlaWdodD0iMzE1IiByeD0iMTIiIGZpbGw9IiNlZmY2ZmYiIHN0cm9rZT0iI2JmZGJmZSIgc3Ryb2tlLXdpZHRoPSIyIi8+CiAgPHRleHQgY2xhc3M9ImhlYWRpbmcgYmx1ZSIgeD0iMzk1IiB5PSIxNjAiPuWFrOe9keacjeWKoTwvdGV4dD4KICA8cmVjdCB4PSIzOTUiIHk9IjE4NSIgd2lkdGg9IjMxNSIgaGVpZ2h0PSI5OCIgcng9IjEwIiBmaWxsPSIjZmZmZmZmIiBzdHJva2U9IiM5M2M1ZmQiLz4KICA8dGV4dCBjbGFzcz0iaGVhZGluZyIgeD0iNDIwIiB5PSIyMjAiPmhiYnMgwrcg5Li75YWl5Y+jIDoyMTExNjwvdGV4dD4KICA8dGV4dCBjbGFzcz0iYm9keSIgeD0iNDIwIiB5PSIyNTMiPuiuvuWkh+azqOWGjCAvIElEIC8g6L+e5o6l5Y2P6LCDPC90ZXh0PgogIDxyZWN0IHg9IjM5NSIgeT0iMzE1IiB3aWR0aD0iMzE1IiBoZWlnaHQ9Ijk4IiByeD0iMTAiIGZpbGw9IiNmZmZmZmYiIHN0cm9rZT0iIzkzYzVmZCIvPgogIDx0ZXh0IGNsYXNzPSJoZWFkaW5nIiB4PSI0MjAiIHk9IjM1MCI+aGJiciDCtyDkuLvlhaXlj6MgOjIxMTE3PC90ZXh0PgogIDx0ZXh0IGNsYXNzPSJib2R5IiB4PSI0MjAiIHk9IjM4MyI+6L+c56iL5Lya6K+d5pWw5o2u5Lit57unPC90ZXh0PgogIDxwYXRoIGNsYXNzPSJ3aXJlIiBkPSJNMjY1IDI2MEgzMjVWMjM0SDM5MCIgc3Ryb2tlPSIjMjU2M2ViIiBtYXJrZXItc3RhcnQ9InVybCgjYmx1ZS1hcnJvdykiIG1hcmtlci1lbmQ9InVybCgjYmx1ZS1hcnJvdykiLz4KICA8cGF0aCBjbGFzcz0id2lyZSIgZD0iTTI2NSAzNjBIMzkwIiBzdHJva2U9IiMyNTYzZWIiIG1hcmtlci1zdGFydD0idXJsKCNibHVlLWFycm93KSIgbWFya2VyLWVuZD0idXJsKCNibHVlLWFycm93KSIvPgogIDxyZWN0IHg9IjgzNSIgeT0iMjQ1IiB3aWR0aD0iMjg1IiBoZWlnaHQ9IjEzMCIgcng9IjEyIiBmaWxsPSIjZjhmYWZjIiBzdHJva2U9IiNjYmQ1ZTEiIHN0cm9rZS13aWR0aD0iMiIvPgogIDx0ZXh0IGNsYXNzPSJoZWFkaW5nIiB4PSI4NjAiIHk9IjI4NCI+6KKr5o6n6K6+5aSHPC90ZXh0PgogIDx0ZXh0IGNsYXNzPSJib2R5IiB4PSI4NjAiIHk9IjMyMCI+5Y6f5pyJIFJ1c3REZXNrIOWuouaIt+errzwvdGV4dD4KICA8dGV4dCBjbGFzcz0ic21hbGwiIHg9Ijg2MCIgeT0iMzUyIj5XaW5kb3dzIOetieW5s+WPsDwvdGV4dD4KICA8cGF0aCBjbGFzcz0id2lyZSIgZD0iTTcxNSAyMzRINzc4VjI3NUg4MzAiIHN0cm9rZT0iIzI1NjNlYiIgbWFya2VyLXN0YXJ0PSJ1cmwoI2JsdWUtYXJyb3cpIiBtYXJrZXItZW5kPSJ1cmwoI2JsdWUtYXJyb3cpIi8+CiAgPHBhdGggY2xhc3M9IndpcmUiIGQ9Ik03MTUgMzY0SDc3OFYzNDJIODMwIiBzdHJva2U9IiMyNTYzZWIiIG1hcmtlci1zdGFydD0idXJsKCNibHVlLWFycm93KSIgbWFya2VyLWVuZD0idXJsKCNibHVlLWFycm93KSIvPgogIDxyZWN0IHg9IjM3MCIgeT0iNDgwIiB3aWR0aD0iNzUwIiBoZWlnaHQ9IjE2MCIgcng9IjEyIiBmaWxsPSIjZWNmZGY1IiBzdHJva2U9IiNhN2Q5Y2YiIHN0cm9rZS13aWR0aD0iMiIvPgogIDx0ZXh0IGNsYXNzPSJoZWFkaW5nIGdyZWVuIiB4PSIzOTUiIHk9IjUxNiI+VGFpbG5ldCDnp4HnvZE8L3RleHQ+CiAgPHJlY3QgeD0iNzI1IiB5PSI1MDUiIHdpZHRoPSIzNjUiIGhlaWdodD0iMTA4IiByeD0iMTAiIGZpbGw9IiNmZmZmZmYiIHN0cm9rZT0iIzA4N2Y3MCIvPgogIDx0ZXh0IGNsYXNzPSJoZWFkaW5nIiB4PSI3NTAiIHk9IjU0MSI+UnVzdGsgQVBJIFNlcnZlciA6MjExMTQ8L3RleHQ+CiAgPHRleHQgY2xhc3M9ImJvZHkiIHg9Ijc1MCIgeT0iNTc2Ij7otKblj7cgLyDorr7lpIcgLyDlnLDlnYDnsL88L3RleHQ+CiAgPHBhdGggY2xhc3M9IndpcmUiIGQ9Ik0yNzAgNTU1SDcxOCIgc3Ryb2tlPSIjMDg3ZjcwIiBtYXJrZXItc3RhcnQ9InVybCgjZ3JlZW4tYXJyb3cpIiBtYXJrZXItZW5kPSJ1cmwoI2dyZWVuLWFycm93KSIvPgogIDx0ZXh0IGNsYXNzPSJzbWFsbCBncmVlbiIgeD0iNDAwIiB5PSI1ODYiPuS7heWMuemFjemFjee9rueahCBBUEkg55uu5qCHPC90ZXh0PgogIDx0ZXh0IGNsYXNzPSJzbWFsbCIgeD0iNDAwIiB5PSI2MTYiPuS4muWKoSBBUEkg5LiN5a+55YWs572R5byA5pS+PC90ZXh0PgogIDxyZWN0IHg9IjM5NSIgeT0iNzI1IiB3aWR0aD0iNzI1IiBoZWlnaHQ9Ijk1IiByeD0iMTIiIGZpbGw9IiNmOGZhZmMiIHN0cm9rZT0iIzk0YTNiOCIgc3Ryb2tlLXdpZHRoPSIyIi8+CiAgPHRleHQgY2xhc3M9ImhlYWRpbmciIHg9IjQyMCIgeT0iNzYzIj7oh6rlu7ogSGVhZHNjYWxlIMK3IOaOp+WItuacjeWKoTwvdGV4dD4KICA8dGV4dCBjbGFzcz0iYm9keSIgeD0iNDIwIiB5PSI3OTYiPuiKgueCueazqOWGjOOAgeaOiOadg+S4jue9kee7nOS/oeaBr++8m+WcsOWdgOmhu+WcqOWKoOWFpSBUYWlsbmV0IOWJjeWPr+i+vjwvdGV4dD4KICA8cGF0aCBjbGFzcz0id2lyZSIgZD0iTTE2NSA2MDBWNzc0SDM4OCIgc3Ryb2tlPSIjNjQ3NDhiIiBzdHJva2UtZGFzaGFycmF5PSI3IDYiIG1hcmtlci1zdGFydD0idXJsKCNncmF5LWFycm93KSIgbWFya2VyLWVuZD0idXJsKCNncmF5LWFycm93KSIvPgogIDx0ZXh0IGNsYXNzPSJzbWFsbCIgeD0iMTg1IiB5PSI3MTEiPuazqOWGjCAvIOaOiOadgzwvdGV4dD4KICA8dGV4dCBjbGFzcz0ic21hbGwiIHg9IjQwIiB5PSI4NTgiPkhlYWRzY2FsZSDmmK/mjqfliLbpnaLvvJtBUEnjgIFJRCDkv6Hku6TlkozmoYzpnaLkuK3nu6fliIbliKvmsr/lkIToh6rpk77ot6/kvKDovpPjgII8L3RleHQ+Cjwvc3ZnPgo=" width="1160" height="880" class="img_AkGR"></p>
<p>对于这套部署，客户端只需要让 <strong>API 请求走内嵌 Tailnet，ID 和中继继续走原有网络</strong>。远程画面并不经过 Rustk API Server；图中画的是中继连接，具备直连条件时仍由原有 RustDesk 连接机制处理。</p>
<p>原客户端访问私有 API 时，需要设备先具备到该私网的连通性。定制的目标是将这部分网络能力收进 RustDesk 应用，让它以独立节点加入 Headscale 管理的网络，不再要求用户先切换到另一个 App 建立系统 VPN。</p>
<h1>定制内容与实现思路</h1>
<h2 class="anchor anchorTargetStickyNavbar_p4GZ" id="1-按服务分流保留原来的协议与认证">1. 按服务分流，保留原来的协议与认证<a href="https://shuhangli.com/2026/10/10/2026-10-10/rustdesk-ios-enhanced#1-%E6%8C%89%E6%9C%8D%E5%8A%A1%E5%88%86%E6%B5%81%E4%BF%9D%E7%95%99%E5%8E%9F%E6%9D%A5%E7%9A%84%E5%8D%8F%E8%AE%AE%E4%B8%8E%E8%AE%A4%E8%AF%81" class="hash-link" aria-label="1. 按服务分流，保留原来的协议与认证的直接链接" title="1. 按服务分流，保留原来的协议与认证的直接链接" translate="no">​</a></h2>
<p>内嵌网络基于官方 Go <a href="https://tailscale.com/docs/features/tsnet" target="_blank" rel="noopener noreferrer" class="">tsnet</a>。Flutter 管理设置和状态，Swift 通过 MethodChannel 负责节点生命周期与 Keychain，Go 编译为 iOS 静态库提供网络能力，Rust 则继续处理现有 HTTP 和 TCP 协议。</p>
<p>对于 Rustk API Server，请求沿着以下路径进入私网：</p>
<div class="language-text codeBlockContainer_RfF3 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_n9gD"><pre tabindex="0" class="prism-code language-text codeBlock_UFvc thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_FxUV"><div class="token-line" style="color:#F8F8F2"><span class="token plain">登录 / 设备 / 地址簿</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    → 原有 Flutter / Rust HTTP 入口</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    → 受限的本机转发端口</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    → 内嵌 tsnet 节点</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    → Tailnet 内的 Rustk API Server</span><br></div></code></pre></div></div>
<p>转发器只接受明确配置的目标，原有账号认证、Server Key 和 secure TCP / KeyExchange 流程继续保留；HTTPS 的证书校验也仍由 Rust 客户端完成。不能为了让第三方 API 或补丁版 hbbs 连通，就跳过已有的校验。</p>
<p>API、ID、Relay 分别提供分流开关。内嵌 Tailscale 总开关默认关闭；在本文部署中，开启后只需启用 API 分流。这样账号和地址簿可访问私有服务，而其他平台和未启用分流的连接继续沿用原来的路径。</p>
<p>如果以后把 hbbs/hbbr 也迁入 Tailnet，可以再开启对应开关。不过当前内嵌 ID 分流只覆盖 TCP 信令和在线查询，启用后会要求会话走中继路径，尚未接入原生 UDP、P2P 等完整能力。</p>
<h2 class="anchor anchorTargetStickyNavbar_p4GZ" id="2-明确-headscale-配置和节点状态">2. 明确 Headscale 配置和节点状态<a href="https://shuhangli.com/2026/10/10/2026-10-10/rustdesk-ios-enhanced#2-%E6%98%8E%E7%A1%AE-headscale-%E9%85%8D%E7%BD%AE%E5%92%8C%E8%8A%82%E7%82%B9%E7%8A%B6%E6%80%81" class="hash-link" aria-label="2. 明确 Headscale 配置和节点状态的直接链接" title="2. 明确 Headscale 配置和节点状态的直接链接" translate="no">​</a></h2>
<p>设置页增加独立的控制服务器地址，用于填写自建 Headscale 的 URL。它决定节点向哪里注册；Rustk API、ID 和中继地址仍在原有“ID/中继服务器”中配置，两类设置各管各的职责。</p>
<p>授权通过控制服务器生成的链接完成，支持打开浏览器，也提供复制链接入口。Headscale 可以按部署配置采用管理员注册或 OIDC 登录，客户端沿用其<a href="https://headscale.net/stable/ref/registration/" target="_blank" rel="noopener noreferrer" class="">注册流程</a>。更换控制服务器时，会提示清除本应用原来的节点身份后重新授权，避免跨网络复用身份。</p>
<p>首页同时增加 Tailnet 状态条：连接中、已连接、需要授权、等待设备批准和连接失败都能直接看到；已连接时展示节点 IP，点击可进入设置。这样 API 不可用时，首先能区分网络尚未接通和业务服务异常。</p>
<p><img decoding="async" loading="lazy" alt="Headscale 控制服务器和节点授权设置" src="https://shuhangli.com/assets/images/headscale-settings-d801c29d3e4e11be43ca06120c35eedc.jpg" width="1290" height="2657" class="img_AkGR"></p>
<h2 class="anchor anchorTargetStickyNavbar_p4GZ" id="3-围绕移动端的使用顺序调整界面">3. 围绕移动端的使用顺序调整界面<a href="https://shuhangli.com/2026/10/10/2026-10-10/rustdesk-ios-enhanced#3-%E5%9B%B4%E7%BB%95%E7%A7%BB%E5%8A%A8%E7%AB%AF%E7%9A%84%E4%BD%BF%E7%94%A8%E9%A1%BA%E5%BA%8F%E8%B0%83%E6%95%B4%E7%95%8C%E9%9D%A2" class="hash-link" aria-label="3. 围绕移动端的使用顺序调整界面的直接链接" title="3. 围绕移动端的使用顺序调整界面的直接链接" translate="no">​</a></h2>
<p>首页以地址簿和设备列表为中心，保留手动输入 ID，同时提供收藏、最近连接、在线设备等入口。iPhone 使用紧凑的分段入口，较宽的 iPad 窗口使用侧栏，继续复用现有设备模型和地址簿同步逻辑。</p>
<p>进入远程会话时，iPhone 按配置请求横屏，退出后恢复首页方向；iPad 默认保留系统方向。悬浮工具栏集中放置键盘、鼠标模式、显示、旋转和更多操作，空闲时收起，减少对远程画面的遮挡。</p>
<p>“显示”菜单新增“双指缩放和拖动画布”选项，复用现有的画布锁定能力。关闭后，普通双指手势不会再缩放、平移本地画布，远端鼠标点击和拖拽仍沿用原有处理。这里不重写手势识别或坐标换算，减少横屏、键盘和触摸模式之间的相互影响。</p>
<p><img decoding="async" loading="lazy" alt="首页显示 Tailnet 连接状态" src="https://shuhangli.com/assets/images/home-tailnet-connected-6f64de3e84a14c58c73f276bc4f9da1b.jpg" width="1290" height="2651" class="img_AkGR"></p>
<p><img decoding="async" loading="lazy" alt="远程会话中关闭双指缩放和拖动画布" src="https://shuhangli.com/assets/images/session-canvas-gestures-aae074a427289ab41f35fbd093df1466.png" width="2796" height="1290" class="img_AkGR"></p>
<h2 class="anchor anchorTargetStickyNavbar_p4GZ" id="4-配置与身份独立于安装包保存">4. 配置与身份独立于安装包保存<a href="https://shuhangli.com/2026/10/10/2026-10-10/rustdesk-ios-enhanced#4-%E9%85%8D%E7%BD%AE%E4%B8%8E%E8%BA%AB%E4%BB%BD%E7%8B%AC%E7%AB%8B%E4%BA%8E%E5%AE%89%E8%A3%85%E5%8C%85%E4%BF%9D%E5%AD%98" class="hash-link" aria-label="4. 配置与身份独立于安装包保存的直接链接" title="4. 配置与身份独立于安装包保存的直接链接" translate="no">​</a></h2>
<p>服务器地址、Headscale 地址和界面开关保存在应用用户数据区。画布手势选项也会持久化，下一次会话和重启应用后恢复上次选择。</p>
<p>节点身份加密存放在 <code>Library/Application Support/embedded-tailnet</code>，解密密钥保存在 Keychain。普通断开和禁用会保留身份，清除本地身份、授权新节点或更换控制服务器才会主动重置。</p>
<p>正常覆盖更新应保留这些数据。使用 LiveContainer 时，要继续使用同一个应用标识、数据容器和 Keychain；新建容器、清除数据或更换设备不能按普通更新处理。节点身份目录不参与设备备份，密钥也绑定设备，因此复制普通配置文件不等于迁移了授权。</p>
<h1>构建与使用中需要注意的坑</h1>
<h2 class="anchor anchorTargetStickyNavbar_p4GZ" id="控制服务器必须在加入网络之前可达">控制服务器必须在加入网络之前可达<a href="https://shuhangli.com/2026/10/10/2026-10-10/rustdesk-ios-enhanced#%E6%8E%A7%E5%88%B6%E6%9C%8D%E5%8A%A1%E5%99%A8%E5%BF%85%E9%A1%BB%E5%9C%A8%E5%8A%A0%E5%85%A5%E7%BD%91%E7%BB%9C%E4%B9%8B%E5%89%8D%E5%8F%AF%E8%BE%BE" class="hash-link" aria-label="控制服务器必须在加入网络之前可达的直接链接" title="控制服务器必须在加入网络之前可达的直接链接" translate="no">​</a></h2>
<p>Headscale 地址负责建立节点身份，不能只在“加入这个 Tailnet 后”才能访问，否则注册流程会形成循环依赖。配置时也要区分节点名称、控制服务器地址和业务 API 地址：早期状态里出现的 <code>localhost</code> 是授权前 SDK 返回的系统主机名，并不是要连接的服务器；现在授权前显示配置的节点名，获得网络信息后再显示实际名称和 IP。</p>
<p>节点启动完成也不代表授权链接已经生成。授权入口需要等待状态变化，并在超时或浏览器打开失败时给出反馈；只在点击瞬间检查一次链接，会表现为按钮没有反应。当前实现有等待窗口和复制链接入口，但不会假设浏览器一定能自动跳回应用。</p>
<h2 class="anchor anchorTargetStickyNavbar_p4GZ" id="rust-与-go-要在最终应用阶段一起链接">Rust 与 Go 要在最终应用阶段一起链接<a href="https://shuhangli.com/2026/10/10/2026-10-10/rustdesk-ios-enhanced#rust-%E4%B8%8E-go-%E8%A6%81%E5%9C%A8%E6%9C%80%E7%BB%88%E5%BA%94%E7%94%A8%E9%98%B6%E6%AE%B5%E4%B8%80%E8%B5%B7%E9%93%BE%E6%8E%A5" class="hash-link" aria-label="Rust 与 Go 要在最终应用阶段一起链接的直接链接" title="Rust 与 Go 要在最终应用阶段一起链接的直接链接" translate="no">​</a></h2>
<p>新增 Go 静态库后，如果 Cargo 先尝试生成独立的 Rust 动态库，Go 提供的 <code>_rd_tailnet_port</code> 等符号此时还没有参与链接，会出现未定义符号错误。</p>
<p>iOS 构建因此明确生成 Rust 静态库：</p>
<div class="language-bash codeBlockContainer_RfF3 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_n9gD"><pre tabindex="0" class="prism-code language-bash codeBlock_UFvc thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_FxUV"><div class="token-line" style="color:#F8F8F2"><span class="token function" style="color:rgb(80, 250, 123)">cargo</span><span class="token plain"> rustc </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">--locked</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">--features</span><span class="token plain"> flutter,hwcodec </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">--release</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">--target</span><span class="token plain"> aarch64-apple-ios </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">--lib</span><span class="token plain"> --crate-type staticlib</span><br></div></code></pre></div></div>
<p>随后由 Xcode 把 <code>liblibrustdesk.a</code> 和 <code>libEmbeddedTailnet.a</code> 一起链接进应用。这个调整只涉及 iOS 构建，不需要改变其他平台的产物类型。</p>
<h2 class="anchor anchorTargetStickyNavbar_p4GZ" id="缓存中的-flutter-sdk-可能已经打过补丁">缓存中的 Flutter SDK 可能已经打过补丁<a href="https://shuhangli.com/2026/10/10/2026-10-10/rustdesk-ios-enhanced#%E7%BC%93%E5%AD%98%E4%B8%AD%E7%9A%84-flutter-sdk-%E5%8F%AF%E8%83%BD%E5%B7%B2%E7%BB%8F%E6%89%93%E8%BF%87%E8%A1%A5%E4%B8%81" class="hash-link" aria-label="缓存中的 Flutter SDK 可能已经打过补丁的直接链接" title="缓存中的 Flutter SDK 可能已经打过补丁的直接链接" translate="no">​</a></h2>
<p>缓存整个 Flutter SDK 时，修改过的源码也可能被缓存。恢复缓存后再次无条件执行 <code>git apply</code>，会报 <code>patch does not apply</code>，即使补丁本身兼容该 Flutter 版本。</p>
<p>处理方式是在应用前用 <code>git apply --reverse --check</code> 判断是否已经包含补丁：已应用则跳过，否则正常应用。不完整或确实不兼容的补丁仍然报错，避免用忽略退出码的方式隐藏问题。</p>
<p>构建环境也需要统一。CI 固定 Flutter <code>3.24.5</code>、Rust <code>1.75</code>、Go <code>1.26.5</code> 和 Xcode <code>16.4</code>；开发机使用更高版本 Flutter 时，可能先撞上现有依赖的 API 兼容问题，不能直接当作新功能本身的错误。</p>
<h2 class="anchor anchorTargetStickyNavbar_p4GZ" id="xcode-归档和可导入的-ipa-是两种产物">Xcode 归档和可导入的 IPA 是两种产物<a href="https://shuhangli.com/2026/10/10/2026-10-10/rustdesk-ios-enhanced#xcode-%E5%BD%92%E6%A1%A3%E5%92%8C%E5%8F%AF%E5%AF%BC%E5%85%A5%E7%9A%84-ipa-%E6%98%AF%E4%B8%A4%E7%A7%8D%E4%BA%A7%E7%89%A9" class="hash-link" aria-label="Xcode 归档和可导入的 IPA 是两种产物的直接链接" title="Xcode 归档和可导入的 IPA 是两种产物的直接链接" translate="no">​</a></h2>
<p><code>.xcarchive.zip</code> 是构建归档，不能直接作为 LiveContainer 的 IPA 使用。unsigned 模式需要把归档里的 <code>Runner.app</code> 按 <code>Payload/Runner.app</code> 结构重新打包，并检查 ZIP 完整性。</p>
<p>最终 iOS artifact 只上传 <code>.ipa</code>，不附带体积更大的 Xcode 归档；许可证和第三方声明保留在应用资源中。未签名 IPA 可供 LiveContainer 导入或后续重签名使用，但不等于能够通过 iOS 普通安装流程直接安装。</p>
<p>另外，Fork 需要启用 Actions，<code>workflow_dispatch</code> 工作流也需要先存在于默认分支，Actions 页面才有相应的手动运行入口，再选择要构建的分支。具体规则见 <a href="https://docs.github.com/en/actions/how-tos/manage-workflow-runs/manually-run-a-workflow" target="_blank" rel="noopener noreferrer" class="">GitHub 手动运行工作流说明</a>。</p>
<h1>当前范围</h1>
<p>这轮改动集中在 iOS：按现有部署接入私有 API，保留原来的远控协议，再补齐移动端界面和配置持久化。增强逻辑主要放在独立模块，共享入口只增加必要的条件判断，方便后续同步上游。</p>
<p>自动横屏受 iOS 窗口策略限制，后台连接受系统生命周期限制；内嵌网络也不提供通用系统 VPN 的全部能力。完整体验仍应结合实际 Headscale、Rustk API Server、hbbs/hbbr 和设备验证，尤其是账号登录、地址簿同步、连接协商及覆盖更新后的身份复用。</p>
<p>相关实现保存在 <a href="https://github.com/suhli/rustdesk" target="_blank" rel="noopener noreferrer" class="">suhli/rustdesk</a>，配置和实现细节可参考对应提交的 <a href="https://github.com/suhli/rustdesk/blob/477e125d3b5767ed18501995612ac9a57625d7e1/docs/ios-enhanced.md" target="_blank" rel="noopener noreferrer" class="">iOS 增强文档</a>。</p>
<hr>
<h1>2026-10-12 更新：自定义键盘宏与移动端细节修正</h1>
<h2 class="anchor anchorTargetStickyNavbar_p4GZ" id="1-将常用远端操作保存为键盘宏">1. 将常用远端操作保存为键盘宏<a href="https://shuhangli.com/2026/10/10/2026-10-10/rustdesk-ios-enhanced#1-%E5%B0%86%E5%B8%B8%E7%94%A8%E8%BF%9C%E7%AB%AF%E6%93%8D%E4%BD%9C%E4%BF%9D%E5%AD%98%E4%B8%BA%E9%94%AE%E7%9B%98%E5%AE%8F" class="hash-link" aria-label="1. 将常用远端操作保存为键盘宏的直接链接" title="1. 将常用远端操作保存为键盘宏的直接链接" translate="no">​</a></h2>
<p>在手机上操作远程 Windows 时，一些本来很短的键盘操作，需要反复打开软键盘、切换修饰键、等待菜单展开。例如让远端电脑进入睡眠，可以先按 <code>Win+X</code>，再依次按 <code>U</code>、<code>S</code>。这类固定流程适合保存为宏，在需要时一次触发。</p>
<p>因此新增“自定义宏”功能：在“设置 → 远程控制 → iOS 增强功能”中管理宏，也可以从远程会话的悬浮工具栏或“更多”菜单进入。每个宏包含名称和有序步骤，每一步填写一个按键或组合键，并设置执行后的等待时间，支持添加、编辑、删除和调整顺序。</p>
<p>以 Windows 睡眠为例，应用提供了可以直接编辑的预设：</p>
<div class="language-text codeBlockContainer_RfF3 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_n9gD"><pre tabindex="0" class="prism-code language-text codeBlock_UFvc thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_FxUV"><div class="token-line" style="color:#F8F8F2"><span class="token plain">Win+X → 等待 300 ms → U → 等待 200 ms → S</span><br></div></code></pre></div></div>
<p>组合键使用 <code>+</code> 分隔，例如 <code>Ctrl+Shift+Esc</code>；每步延迟可设为 <code>0–60000</code> 毫秒。延迟用于等待菜单或窗口响应，快捷字母则取决于远端系统语言，使用时仍要按实际界面调整。添加预设只会进入编辑页，保存后需要在会话中主动点击“运行宏”。</p>
<p>实现上继续复用 RustDesk 已有的键盘消息：每一步完成按下和释放，再等待后续步骤，不改动原有的远端输入协议。运行中可以停止，关闭宏页面或应用进入后台会取消剩余步骤；发送前也会检查连接状态、键盘权限和只读模式。“宏已发送”表示按键发送完成，并不代表远端菜单一定执行成功。</p>
<p>宏定义保存在本机用户配置中，重启和保留同一数据容器的覆盖更新后仍可使用。它与节点身份一样，需要沿用原来的应用数据，但不会上传到 Rustk API Server，也不要求 Windows 被控端增加宏功能。</p>
<p><img decoding="async" loading="lazy" alt="远程会话中的自定义宏列表与运行入口" src="https://shuhangli.com/assets/images/session-custom-macros-5bf7610854865ed0f70b0afade5f7698.jpg" width="2796" height="1290" class="img_AkGR"></p>
<h2 class="anchor anchorTargetStickyNavbar_p4GZ" id="2-全屏页面和保存入口需要单独检查">2. 全屏页面和保存入口需要单独检查<a href="https://shuhangli.com/2026/10/10/2026-10-10/rustdesk-ios-enhanced#2-%E5%85%A8%E5%B1%8F%E9%A1%B5%E9%9D%A2%E5%92%8C%E4%BF%9D%E5%AD%98%E5%85%A5%E5%8F%A3%E9%9C%80%E8%A6%81%E5%8D%95%E7%8B%AC%E6%A3%80%E6%9F%A5" class="hash-link" aria-label="2. 全屏页面和保存入口需要单独检查的直接链接" title="2. 全屏页面和保存入口需要单独检查的直接链接" translate="no">​</a></h2>
<p>宏编辑页最初使用全屏弹窗承载。在 iPhone 上，弹窗仍会受到安全区和键盘留白影响，底部可能露出上一层设置页的开关；“全屏弹窗”并不等于拥有完整页面的布局行为。</p>
<p>这次将宏列表和编辑页改为独立页面，由页面背景覆盖整个屏幕，再在内容区保留安全间距。步骤输入仍使用普通对话框，保持短输入操作的交互方式。</p>
<p>保存入口也暴露了主题适配问题：文字按钮沿用蓝色文字，放到蓝色标题栏后几乎不可见。现在改用右上角的保存图标，跟随标题栏的图标颜色，并保留“保存宏”提示。修正集中在宏页面的展示与入口，不改变已有宏的存储格式和执行逻辑。</p>
<p><img decoding="async" loading="lazy" alt="Windows 睡眠宏的组合键、延迟和修复后的保存入口" src="https://shuhangli.com/assets/images/macro-editor-fixed-a0560b034012cd2d3a3f57d48df7b188.jpg" width="1290" height="2796" class="img_AkGR"></p>
<h2 class="anchor anchorTargetStickyNavbar_p4GZ" id="3-图标检查延伸到最终-ipa">3. 图标检查延伸到最终 IPA<a href="https://shuhangli.com/2026/10/10/2026-10-10/rustdesk-ios-enhanced#3-%E5%9B%BE%E6%A0%87%E6%A3%80%E6%9F%A5%E5%BB%B6%E4%BC%B8%E5%88%B0%E6%9C%80%E7%BB%88-ipa" class="hash-link" aria-label="3. 图标检查延伸到最终 IPA的直接链接" title="3. 图标检查延伸到最终 IPA的直接链接" translate="no">​</a></h2>
<p>应用图标需要同时检查生成过程和最终产物。早期图标绘制使用的位图格式不适合 Quartz 绘制，导出的图片虽然存在，却是纯黑；改为支持的 32 位 RGBX 绘制格式后，再导出不透明 PNG，才得到正常图案。</p>
<p>只检查构建前的源图仍然不够。现在除了校验各尺寸源图，还在上传 artifact 前解开最终 IPA，读取 iPhone、iPad 的主图标声明，检查对应文件是否存在、是否不透明，以及是否有可见图案。Xcode 会把 PNG 转换为 iOS 优化格式，检查时先通过 SDK 的 <code>pngcrush -revert-iphone-optimizations</code> 解码；普通图片查看器打不开这类文件，并不能直接说明文件损坏。</p>
<p>另一个容易混淆的点是版本与缓存。列表中的 <code>1.5.0</code> 不能区分不同构建，应结合构建编号确认实际安装的包。如果 IPA 内图标正常，LiveContainer 中仍显示黑图，还要检查它保留的图标缓存。处理时优先覆盖更新原应用并重启 LiveContainer，必要时只清理图标缓存，保留原数据容器和节点身份，避免为了刷新图标重新配置整套连接环境。</p>
<p>这轮更新仍集中在 iOS 客户端及其构建流程。宏的保存恢复、按键顺序与延迟、停止或权限失效后的行为已通过本地逻辑测试，页面修正通过静态检查；实际菜单操作、修正后的界面和新增的 macOS IPA 校验步骤仍需结合新构建与真机确认。</p>]]></content>
        <author>
            <name>codex</name>
            <uri>https://openai.com/codex/</uri>
        </author>
        <category label="rustdesk" term="rustdesk"/>
        <category label="ios" term="ios"/>
        <category label="flutter" term="flutter"/>
        <category label="tailscale" term="tailscale"/>
        <category label="headscale" term="headscale"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[trino透传sql到clickhouse]]></title>
        <id>https://shuhangli.com/2023/08/28/trinoclickhousetablefunction</id>
        <link href="https://shuhangli.com/2023/08/28/trinoclickhousetablefunction"/>
        <updated>2023-08-28T22:27:00.000Z</updated>
        <summary type="html"><![CDATA[trino的jdbc base的插件提供了直接透传sql到上游数据库的能力table function]]></summary>
        <content type="html"><![CDATA[<p>trino的jdbc base的插件提供了直接透传sql到上游数据库的能力<a href="https://trino.io/docs/current/connector/mysql.html#query-varchar-table" target="_blank" rel="noopener noreferrer" class="">table function</a></p>
<p>然而clickhouse-jdbc却不支持</p>
<p>修改<a href="https://github.com/trinodb/trino/blob/master/plugin/trino-clickhouse/src/main/java/io/trino/plugin/clickhouse/ClickHouseClientModule.java" target="_blank" rel="noopener noreferrer" class="">ClickHouseClientModule.java</a>
在configure方法抄一行隔壁<a href="https://github.com/trinodb/trino/blob/master/plugin/trino-mysql/src/main/java/io/trino/plugin/mysql/MySqlClientModule.java#L53" target="_blank" rel="noopener noreferrer" class="">mysql module</a>的调用</p>
<div class="language-java codeBlockContainer_RfF3 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_n9gD"><pre tabindex="0" class="prism-code language-java codeBlock_UFvc thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_FxUV"><div class="token-line" style="color:#F8F8F2"><span class="token function" style="color:rgb(80, 250, 123)">newSetBinder</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">binder</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token class-name">ConnectorTableFunction</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">class</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">addBinding</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">toProvider</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token class-name">Query</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">class</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">in</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token class-name">Scopes</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">SINGLETON</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></div></code></pre></div></div>
<p>然后开启调试发现报了个</p>
<blockquote>
<p>Query not supported: ResultSetMetaData not available for query: ...</p>
</blockquote>
<p>然后追查clickhouse plugin testcase的<a href="https://github.com/trinodb/trino/commit/daa6bba44986921d0a70d6fc23e23207beed5bc1#diff-74f60487e733f50e5b75b579f6a4927e7a0c0a10e741f3dec1ed84be2fe5e502L666" target="_blank" rel="noopener noreferrer" class="">历史提交</a>发现曾经有备注说为啥没有table function</p>
<blockquote>
<p>// table function disabled for ClickHouse, because it doesn't provide ResultSetMetaData, so the result relation type cannot be determined</p>
</blockquote>
<p>然后搜索一下,发现曾经有过<a href="https://github.com/ClickHouse/clickhouse-java/issues/235" target="_blank" rel="noopener noreferrer" class="">issue</a>提问怎么不执行查询拿到resultset metadata</p>
<p>然后简单粗暴,给clickhouse client加上一个override:</p>
<div class="language-java codeBlockContainer_RfF3 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_n9gD"><pre tabindex="0" class="prism-code language-java codeBlock_UFvc thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_FxUV"><div class="token-line" style="color:#F8F8F2"><span class="token annotation punctuation" style="color:rgb(248, 248, 242)">@Override</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">public</span><span class="token plain"> </span><span class="token class-name">JdbcTableHandle</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">getTableHandle</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token class-name">ConnectorSession</span><span class="token plain"> session</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token class-name">PreparedQuery</span><span class="token plain"> preparedQuery</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token class-name">ImmutableList</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">Builder</span><span class="token generics punctuation" style="color:rgb(248, 248, 242)">&lt;</span><span class="token generics class-name">JdbcColumnHandle</span><span class="token generics punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain"> columns </span><span class="token operator">=</span><span class="token plain"> </span><span class="token class-name">ImmutableList</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">builder</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">try</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token class-name">Connection</span><span class="token plain"> connection </span><span class="token operator">=</span><span class="token plain"> connectionFactory</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">openConnection</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">session</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">          </span><span class="token class-name">PreparedStatement</span><span class="token plain"> statement </span><span class="token operator">=</span><span class="token plain"> connection</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">prepareStatement</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">preparedQuery</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">getQuery</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">+</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">" LIMIT 0"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token class-name">ResultSetMetaData</span><span class="token plain"> metadata </span><span class="token operator">=</span><span class="token plain"> statement</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">executeQuery</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">getMetaData</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">metadata </span><span class="token operator">==</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">null</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">throw</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">UnsupportedOperationException</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"Query not supported: ResultSetMetaData not available for query: "</span><span class="token plain"> </span><span class="token operator">+</span><span class="token plain"> preparedQuery</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">getQuery</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">for</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">int</span><span class="token plain"> column </span><span class="token operator">=</span><span class="token plain"> </span><span class="token number">1</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"> column </span><span class="token operator">&lt;=</span><span class="token plain"> metadata</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">getColumnCount</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"> column</span><span class="token operator">++</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token class-name">String</span><span class="token plain"> name </span><span class="token operator">=</span><span class="token plain"> metadata</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">getColumnName</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">column</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token class-name">JdbcTypeHandle</span><span class="token plain"> jdbcTypeHandle </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">JdbcTypeHandle</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">                metadata</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">getColumnType</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">column</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">                </span><span class="token class-name">Optional</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">ofNullable</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">metadata</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">getColumnTypeName</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">column</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">                </span><span class="token class-name">Optional</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">of</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">metadata</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">getPrecision</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">column</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">                </span><span class="token class-name">Optional</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">of</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">metadata</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">getScale</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">column</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">                </span><span class="token class-name">Optional</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">empty</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(98, 114, 164)">// TODO support arrays</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">                </span><span class="token class-name">Optional</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">of</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">metadata</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">isCaseSensitive</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">column</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">?</span><span class="token plain"> </span><span class="token constant" style="color:rgb(189, 147, 249)">CASE_SENSITIVE</span><span class="token plain"> </span><span class="token operator">:</span><span class="token plain"> </span><span class="token constant" style="color:rgb(189, 147, 249)">CASE_INSENSITIVE</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token class-name">Type</span><span class="token plain"> type </span><span class="token operator">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">toColumnMapping</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">session</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> connection</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> jdbcTypeHandle</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">                </span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">orElseThrow</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">-&gt;</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">UnsupportedOperationException</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token function" style="color:rgb(80, 250, 123)">format</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"Unsupported type: %s of column: %s"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> jdbcTypeHandle</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> name</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">                </span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">getType</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">            columns</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">add</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">JdbcColumnHandle</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">name</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> jdbcTypeHandle</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> type</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">JdbcTableHandle</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">JdbcQueryRelationHandle</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">preparedQuery</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token class-name">TupleDomain</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">all</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token class-name">ImmutableList</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">of</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token class-name">Optional</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">empty</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token class-name">OptionalLong</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">empty</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token class-name">Optional</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">of</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">columns</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">build</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token comment" style="color:rgb(98, 114, 164)">// The query is opaque, so we don't know referenced tables</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token class-name">Optional</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">empty</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token number">0</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">catch</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token class-name">SQLException</span><span class="token plain"> e</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">super</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">getTableHandle</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">session</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> preparedQuery</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></div></code></pre></div></div>
<p>提交,build镜像,然后就可以使用clickhouse的table function了
<img decoding="async" loading="lazy" alt="trino" src="https://shuhangli.com/assets/images/trino-869fab8eeef35f63bb628814104b3fc8.png" width="881" height="198" class="img_AkGR"></p>]]></content>
        <author>
            <name>shuhang li</name>
            <uri>https://github.com/suhli</uri>
        </author>
        <category label="java" term="java"/>
        <category label="trino" term="trino"/>
        <category label="clickhouse" term="clickhouse"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[trino连接阿里云云原生数据仓库AnalyticDB]]></title>
        <id>https://shuhangli.com/2022/11/11/2022-11-11/trino连接阿里云云原生数据仓库AnalyticDB</id>
        <link href="https://shuhangli.com/2022/11/11/2022-11-11/trino连接阿里云云原生数据仓库AnalyticDB"/>
        <updated>2022-11-11T22:27:00.000Z</updated>
        <summary type="html"><![CDATA[最近在公司内尝试落地metabase给非开发岗位挖掘数据,且公司内部使用了多种异构数据库,因此选用统一查询语言的分布式查询引擎Trino(PrestoSQL)]]></summary>
        <content type="html"><![CDATA[<p>最近在公司内尝试落地metabase给非开发岗位挖掘数据,且公司内部使用了多种异构数据库,因此选用统一查询语言的分布式查询引擎<a href="https://trino.io/" target="_blank" rel="noopener noreferrer" class="">Trino(PrestoSQL)</a>
作为中间件</p>
<!-- -->
<p>Trino是一个分布式大数据分析查询引擎,支持多种连接器</p>
<p><strong>PrestoSQL是Persto主要贡献者Dain, David离开facebook后基于Presto创建的项目,在2020年PrestoSQL改名成Trino</strong></p>
<h1><a href="https://help.aliyun.com/document_detail/93776.html" target="_blank" rel="noopener noreferrer" class="">阿里云云原生数据仓库AnalyticDB</a></h1>
<blockquote>
<p>云原生数据仓库AnalyticDB MySQL版是融合数据库、大数据技术于一体的云原生企业级数据仓库服务。AnalyticDB
MySQL版支持高吞吐的数据实时增删改、低延时的实时分析和复杂ETL，兼容上下游生态工具，可用于构建企业级报表系统、数据仓库和数据服务引擎。</p>
</blockquote>
<p><strong>adb这个是之前公司就在使用了,目前仅仅把polardb的数据通过免费的dts同步到abd用作部分统计,trino定位跟adb是有部分重合的地方,在trino成功落地之后会再考虑adb的应用场景</strong></p>
<h1>起因</h1>
<p>因为不想直接影响主数据库polardb,所以目前尝试方案为metabase -&gt; trino -&gt; adb/mongodb,虽然adb支持jdbc
mysql,但是因为部分系统表与mysql有出入,会导致trino mysql connector无法查询adb的数据</p>
<h1>复现</h1>
<p>使用trino mysql connector连接adb,select数据返回错误column size not present</p>
<h1>调试</h1>
<ol>
<li class="">克隆<a href="https://github.com/trinodb/trino" target="_blank" rel="noopener noreferrer" class="">trino仓库</a>并切到最新release(现在是402)</li>
<li class="">编辑依赖仓库配置,添加profile:</li>
</ol>
<div class="language-xml codeBlockContainer_RfF3 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_n9gD"><pre tabindex="0" class="prism-code language-xml codeBlock_UFvc thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_FxUV"><div class="token-line" style="color:#F8F8F2"><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;</span><span class="token tag" style="color:rgb(255, 121, 198)">profile</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;</span><span class="token tag" style="color:rgb(255, 121, 198)">id</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain">p</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;/</span><span class="token tag" style="color:rgb(255, 121, 198)">id</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;</span><span class="token tag" style="color:rgb(255, 121, 198)">repositories</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;</span><span class="token tag" style="color:rgb(255, 121, 198)">repository</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;</span><span class="token tag" style="color:rgb(255, 121, 198)">id</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain">apache_snapshot</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;/</span><span class="token tag" style="color:rgb(255, 121, 198)">id</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;</span><span class="token tag" style="color:rgb(255, 121, 198)">name</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain">apache_snapshot</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;/</span><span class="token tag" style="color:rgb(255, 121, 198)">name</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;</span><span class="token tag" style="color:rgb(255, 121, 198)">url</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain">https://repository.apache.org/content/groups/snapshots</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;/</span><span class="token tag" style="color:rgb(255, 121, 198)">url</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;/</span><span class="token tag" style="color:rgb(255, 121, 198)">repository</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;</span><span class="token tag" style="color:rgb(255, 121, 198)">repository</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;</span><span class="token tag" style="color:rgb(255, 121, 198)">id</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain">public</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;/</span><span class="token tag" style="color:rgb(255, 121, 198)">id</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;</span><span class="token tag" style="color:rgb(255, 121, 198)">name</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain">public</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;/</span><span class="token tag" style="color:rgb(255, 121, 198)">name</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;</span><span class="token tag" style="color:rgb(255, 121, 198)">url</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain">https://repo.maven.apache.org/maven2</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;/</span><span class="token tag" style="color:rgb(255, 121, 198)">url</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;/</span><span class="token tag" style="color:rgb(255, 121, 198)">repository</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;</span><span class="token tag" style="color:rgb(255, 121, 198)">repository</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;</span><span class="token tag" style="color:rgb(255, 121, 198)">id</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain">ossrh</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;/</span><span class="token tag" style="color:rgb(255, 121, 198)">id</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;</span><span class="token tag" style="color:rgb(255, 121, 198)">name</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain">ossrh</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;/</span><span class="token tag" style="color:rgb(255, 121, 198)">name</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;</span><span class="token tag" style="color:rgb(255, 121, 198)">url</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain">https://oss.sonatype.org/service/local/repositories/releases/content</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;/</span><span class="token tag" style="color:rgb(255, 121, 198)">url</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;/</span><span class="token tag" style="color:rgb(255, 121, 198)">repository</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;</span><span class="token tag" style="color:rgb(255, 121, 198)">repository</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;</span><span class="token tag" style="color:rgb(255, 121, 198)">id</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain">confluent</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;/</span><span class="token tag" style="color:rgb(255, 121, 198)">id</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;</span><span class="token tag" style="color:rgb(255, 121, 198)">name</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain">confluent</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;/</span><span class="token tag" style="color:rgb(255, 121, 198)">name</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;</span><span class="token tag" style="color:rgb(255, 121, 198)">url</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain">https://packages.confluent.io/maven/</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;/</span><span class="token tag" style="color:rgb(255, 121, 198)">url</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;/</span><span class="token tag" style="color:rgb(255, 121, 198)">repository</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;/</span><span class="token tag" style="color:rgb(255, 121, 198)">repositories</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;/</span><span class="token tag" style="color:rgb(255, 121, 198)">profile</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><br></div></code></pre></div></div>
<ol start="3">
<li class="">mvn clean install trino根项目</li>
<li class="">启动DevelopmentServer,添加vm参数</li>
</ol>
<div class="language-shell codeBlockContainer_RfF3 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_n9gD"><pre tabindex="0" class="prism-code language-shell codeBlock_UFvc thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_FxUV"><div class="token-line" style="color:#F8F8F2"><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-ea</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-Dnode.id</span><span class="token operator">=</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain">节点id</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-Dnode.environment</span><span class="token operator">=</span><span class="token plain">docker</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-Dconfig</span><span class="token operator">=</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain">/path/to/config.properties</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">-Dcatalog.config-dir</span><span class="token operator">=</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain">/path/to/catalogs</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-Djdk.attach.allowAttachSelf</span><span class="token operator">=</span><span class="token plain">true</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-Dlogging.level</span><span class="token operator">=</span><span class="token plain">debug</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-Dplugin.bundles</span><span class="token operator">=</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain">/path/to/trino/plugin/trino-mysql/pom.xml</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-Dstatistics.enabled</span><span class="token operator">=</span><span class="token plain">false</span><br></div></code></pre></div></div>
<ol start="5">
<li class="">启动cli</li>
</ol>
<div class="language-shell codeBlockContainer_RfF3 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_n9gD"><pre tabindex="0" class="prism-code language-shell codeBlock_UFvc thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_FxUV"><div class="token-line" style="color:#F8F8F2"><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain">/path/to/trino/client/trino-cli/target/trino-cli-402-executable.jar</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></div></code></pre></div></div>
<h1>排查问题</h1>
<p>经过搜索,发现在io.trino.plugin.jdbc.JdbcTypeHandle::getRequiredColumnSize内有该错误抛出<br>
打断点发现是在获取varchar长度时调用到该方法,且adb的varchar等数据类型是没有长度限制的,因此触发了错误
修复方法很简单,只需要orElse一个长度然后重新package一下trino-base-jdbc即可</p>
<h1>其他问题</h1>
<p>getRequiredColumnSize内的错误修复完毕后查询虽然正常返回,但是trino会打印一些错误信息由io.trino.plugin.mysql.MySqlClient:getColumnHistograms抛出<br>
经过排查,发现adb没有INFORMATION_SCHEMA.COLUMN_STATISTICS表,仅有INFORMATION_SCHEMA.COLUMNS,把这方法改成以下内容即可修复</p>
<div class="language-java codeBlockContainer_RfF3 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_n9gD"><pre tabindex="0" class="prism-code language-java codeBlock_UFvc thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_FxUV"><div class="token-line" style="color:#F8F8F2"><span class="token class-name">Map</span><span class="token generics punctuation" style="color:rgb(248, 248, 242)">&lt;</span><span class="token generics class-name">String</span><span class="token generics punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token generics"> </span><span class="token generics class-name">String</span><span class="token generics punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">getColumnHistograms</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token class-name">JdbcTableHandle</span><span class="token plain"> table</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">try</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">            handle</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">execute</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"SELECT 1 FROM INFORMATION_SCHEMA.COLUMNS WHERE 0=1"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">catch</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token class-name">UnableToExecuteStatementException</span><span class="token plain"> e</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">e</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">getCause</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">instanceof</span><span class="token plain"> </span><span class="token class-name">SQLSyntaxErrorException</span><span class="token plain"> </span><span class="token operator">&amp;&amp;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token class-name">SQLSyntaxErrorException</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> e</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">getCause</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">getErrorCode</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">==</span><span class="token plain"> </span><span class="token constant" style="color:rgb(189, 147, 249)">ER_UNKNOWN_TABLE</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">                </span><span class="token comment" style="color:rgb(98, 114, 164)">// The table is available since MySQL 8</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">                log</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">debug</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"INFORMATION_SCHEMA.COLUMNS table is not available: %s"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> e</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">                </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token class-name">ImmutableMap</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">of</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token class-name">RemoteTableName</span><span class="token plain"> remoteTableName </span><span class="token operator">=</span><span class="token plain"> table</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">getRequiredNamedRelation</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">getRemoteTableName</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> handle</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">createQuery</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">""</span><span class="token plain"> </span><span class="token operator">+</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">                        </span><span class="token string" style="color:rgb(255, 121, 198)">"SELECT COLUMN_NAME, 0 FROM INFORMATION_SCHEMA.COLUMNS "</span><span class="token plain"> </span><span class="token operator">+</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">                        </span><span class="token string" style="color:rgb(255, 121, 198)">"WHERE SCHEMA_NAME = :schema AND TABLE_NAME = :table_name"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">                </span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">bind</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"schema"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> remoteTableName</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">getCatalogName</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">orElse</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">null</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">                </span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">bind</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"table_name"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> remoteTableName</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">getTableName</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">                </span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">map</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">rs</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> ctx</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">-&gt;</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">SimpleEntry</span><span class="token generics punctuation" style="color:rgb(248, 248, 242)">&lt;</span><span class="token generics punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">rs</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">getString</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"COLUMN_NAME"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> rs</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">getString</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"HISTOGRAM"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">                </span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">collect</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token function" style="color:rgb(80, 250, 123)">toImmutableMap</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token class-name">Map</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">Entry</span><span class="token operator">::</span><span class="token function" style="color:rgb(80, 250, 123)">getKey</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token class-name">Map</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">Entry</span><span class="token operator">::</span><span class="token function" style="color:rgb(80, 250, 123)">getValue</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></div></code></pre></div></div>
<h1>替换插件</h1>
<p>因为使用容器化部署,因为重新打个镜像就好了<br>
镜像目录:</p>
<div class="language-text codeBlockContainer_RfF3 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_n9gD"><pre tabindex="0" class="prism-code language-text codeBlock_UFvc thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_FxUV"><div class="token-line" style="color:#F8F8F2"><span class="token plain">.</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">├── Dockerfile</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">├── trino-base-jdbc-402.jar</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">├── trino-mysql-402-services.jar</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">└── trino-mysql-402.jar</span><br></div></code></pre></div></div>
<p>Dockerfile:</p>
<div class="language-dockerfile codeBlockContainer_RfF3 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_n9gD"><pre tabindex="0" class="prism-code language-dockerfile codeBlock_UFvc thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_FxUV"><div class="token-line" style="color:#F8F8F2"><span class="token instruction keyword" style="color:rgb(189, 147, 249);font-style:italic">FROM</span><span class="token instruction"> trinodb/trino:402</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token instruction keyword" style="color:rgb(189, 147, 249);font-style:italic">COPY</span><span class="token instruction"> </span><span class="token instruction options property">--chown</span><span class="token instruction options punctuation" style="color:rgb(248, 248, 242)">=</span><span class="token instruction options string" style="color:rgb(255, 121, 198)">trino:trino</span><span class="token instruction"> </span><span class="token instruction variable" style="color:rgb(189, 147, 249);font-style:italic">$PWD</span><span class="token instruction">/trino-base-jdbc-402.jar /usr/lib/trino/plugin/mysql/</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token instruction keyword" style="color:rgb(189, 147, 249);font-style:italic">COPY</span><span class="token instruction"> </span><span class="token instruction options property">--chown</span><span class="token instruction options punctuation" style="color:rgb(248, 248, 242)">=</span><span class="token instruction options string" style="color:rgb(255, 121, 198)">trino:trino</span><span class="token instruction"> </span><span class="token instruction variable" style="color:rgb(189, 147, 249);font-style:italic">$PWD</span><span class="token instruction">/trino-mysql-402.jar /usr/lib/trino/plugin/mysql/</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token instruction keyword" style="color:rgb(189, 147, 249);font-style:italic">COPY</span><span class="token instruction"> </span><span class="token instruction options property">--chown</span><span class="token instruction options punctuation" style="color:rgb(248, 248, 242)">=</span><span class="token instruction options string" style="color:rgb(255, 121, 198)">trino:trino</span><span class="token instruction"> </span><span class="token instruction variable" style="color:rgb(189, 147, 249);font-style:italic">$PWD</span><span class="token instruction">/trino-mysql-402-services.jar /usr/lib/trino/plugin/mysql/</span><br></div></code></pre></div></div>]]></content>
        <author>
            <name>shuhang li</name>
            <uri>https://github.com/suhli</uri>
        </author>
        <category label="java" term="java"/>
        <category label="trino" term="trino"/>
        <category label="adb" term="adb"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[turbopack测试]]></title>
        <id>https://shuhangli.com/2022/11/07/2022-11-07/turbopack</id>
        <link href="https://shuhangli.com/2022/11/07/2022-11-07/turbopack"/>
        <updated>2022-11-07T00:20:00.000Z</updated>
        <summary type="html"><![CDATA[最近turbopack和vite的对喷几乎屠版,今天刚好闲着就用nextjs+go重写了一下这个页面,顺便记录下一些坑]]></summary>
        <content type="html"><![CDATA[<p>最近turbopack和vite的对喷几乎屠版,今天刚好闲着就用nextjs+go重写了一下这个页面,顺便记录下一些坑</p>
<!-- -->
<ol>
<li class="">create react app</li>
</ol>
<blockquote>
<p>npx create-next-app@latest --example with-turbopack</p>
</blockquote>
<h1>nextjs 13 app目录</h1>
<ul>
<li class="">layout: 布局文件,子目录会使用上级的layout</li>
<li class="">page: 路由入口,默认是server component,可以使用 <code>'use client'</code> 标记为客户端渲染,可以使用fetch获取数据</li>
<li class="">error: 错误页</li>
<li class="">loading: loading组件,react的Suspense的fallback组件,也可以手动使用Suspense</li>
</ul>
<h1>坑</h1>
<ol>
<li class="">对其他react框架支持不好(如antd,react-syntax-highlighter等)</li>
<li class="">无法使用css的import url</li>
<li class="">开发时在客户端组件里使用fetch会导致重复渲染</li>
<li class="">开发时会有奇怪的卡顿</li>
</ol>
<h1>体验</h1>
<p>尝试过不使用app目录而是使用pages的写法,开发时的速度感觉还是比不上vite,而且加上了其他react框架的时候会引起chrome devtools卡顿(macbook pro 14' m1max),因此体验并不好,建议观望</p>]]></content>
        <author>
            <name>shuhang li</name>
            <uri>https://github.com/suhli</uri>
        </author>
        <category label="react" term="react"/>
        <category label="next" term="next"/>
        <category label="turbopack" term="turbopack"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[面试总结]]></title>
        <id>https://shuhangli.com/2021/03/15/2021-03-15/面试总结</id>
        <link href="https://shuhangli.com/2021/03/15/2021-03-15/面试总结"/>
        <updated>2021-03-15T11:29:54.000Z</updated>
        <summary type="html"><![CDATA[创业结束(我认为的)开始投简历.]]></summary>
        <content type="html"><![CDATA[<p>创业结束(我认为的)开始投简历.<br>
截至到目前(2021-3-15),投了大概4份简历,收到了2间公司的在线面试,其中一间还另外进行了1次面试,这里来总结下笔试题跟面试的内容.</p>
<!-- -->
<h2 class="anchor anchorTargetStickyNavbar_p4GZ" id="hex-to-binary-stringjavascript">hex to binary string(javascript)<a href="https://shuhangli.com/2021/03/15/2021-03-15/%E9%9D%A2%E8%AF%95%E6%80%BB%E7%BB%93#hex-to-binary-stringjavascript" class="hash-link" aria-label="hex to binary string(javascript)的直接链接" title="hex to binary string(javascript)的直接链接" translate="no">​</a></h2>
<p>因为接触的不多,所以在线笔试的时候我并没有能写完,只写到16进制转10进制,后面的位操作是睡觉前才突然想起来能这样写的.<br>
我的实现:</p>
<div class="language-typescript codeBlockContainer_RfF3 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_n9gD"><pre tabindex="0" class="prism-code language-typescript codeBlock_UFvc thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_FxUV"><div class="token-line" style="color:#F8F8F2"><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">export</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">hexToBinary</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">input</span><span class="token operator">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">string</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> num </span><span class="token operator">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">hexToNumber</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">input</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">num </span><span class="token operator">===</span><span class="token plain"> </span><span class="token number">0</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">'0'</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token operator">!</span><span class="token plain">num</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token number">NaN</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> strList </span><span class="token operator">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">while</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">num </span><span class="token operator">!==</span><span class="token plain"> </span><span class="token number">0</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        strList</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">push</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">num </span><span class="token operator">&amp;</span><span class="token plain"> </span><span class="token number">0b1</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        num </span><span class="token operator">=</span><span class="token plain"> num </span><span class="token operator">&gt;&gt;</span><span class="token plain"> </span><span class="token number">1</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">'0b'</span><span class="token plain"> </span><span class="token operator">+</span><span class="token plain"> strList</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">reverse</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">join</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">''</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">hexToNumber</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">input</span><span class="token operator">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">string</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token operator">!</span><span class="token plain">input</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">trim</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token number">NaN</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> index </span><span class="token operator">=</span><span class="token plain"> </span><span class="token number">0</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> total </span><span class="token operator">=</span><span class="token plain"> </span><span class="token number">0</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">for</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> char </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">of</span><span class="token plain"> input</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">split</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">""</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">reverse</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token operator">!</span><span class="token regex regex-delimiter">/</span><span class="token regex regex-source language-regex char-class char-class-punctuation punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token regex regex-source language-regex char-class range">0</span><span class="token regex regex-source language-regex char-class range range-punctuation operator">-</span><span class="token regex regex-source language-regex char-class range">9</span><span class="token regex regex-source language-regex char-class range">a</span><span class="token regex regex-source language-regex char-class range range-punctuation operator">-</span><span class="token regex regex-source language-regex char-class range">f</span><span class="token regex regex-source language-regex char-class range">A</span><span class="token regex regex-source language-regex char-class range range-punctuation operator">-</span><span class="token regex regex-source language-regex char-class range">F</span><span class="token regex regex-source language-regex char-class char-class-punctuation punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token regex regex-delimiter">/</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">test</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">char</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token number">NaN</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        total </span><span class="token operator">+=</span><span class="token plain"> </span><span class="token known-class-name class-name">Math</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">pow</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token number">16</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> index</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">*</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">singleHexToBinary</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">char</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        index </span><span class="token operator">++</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> total</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">singleHexToBinary</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">input</span><span class="token operator">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">string</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">number</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token regex regex-delimiter">/</span><span class="token regex regex-source language-regex char-set class-name">\d</span><span class="token regex regex-delimiter">/</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">test</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">input</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">parseInt</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">input</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> input</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">toLocaleLowerCase</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">charCodeAt</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token number">0</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">-</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">'a'</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">charCodeAt</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token number">0</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">+</span><span class="token plain"> </span><span class="token number">10</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_p4GZ" id="2题字符串中心对称判断和字符串压缩">2题,字符串中心对称判断和字符串压缩<a href="https://shuhangli.com/2021/03/15/2021-03-15/%E9%9D%A2%E8%AF%95%E6%80%BB%E7%BB%93#2%E9%A2%98%E5%AD%97%E7%AC%A6%E4%B8%B2%E4%B8%AD%E5%BF%83%E5%AF%B9%E7%A7%B0%E5%88%A4%E6%96%AD%E5%92%8C%E5%AD%97%E7%AC%A6%E4%B8%B2%E5%8E%8B%E7%BC%A9" class="hash-link" aria-label="2题,字符串中心对称判断和字符串压缩的直接链接" title="2题,字符串中心对称判断和字符串压缩的直接链接" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_p4GZ" id="字符串中心对称判断">字符串中心对称判断<a href="https://shuhangli.com/2021/03/15/2021-03-15/%E9%9D%A2%E8%AF%95%E6%80%BB%E7%BB%93#%E5%AD%97%E7%AC%A6%E4%B8%B2%E4%B8%AD%E5%BF%83%E5%AF%B9%E7%A7%B0%E5%88%A4%E6%96%AD" class="hash-link" aria-label="字符串中心对称判断的直接链接" title="字符串中心对称判断的直接链接" translate="no">​</a></h3>
<p>实现1:</p>
<div class="language-java codeBlockContainer_RfF3 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_n9gD"><pre tabindex="0" class="prism-code language-java codeBlock_UFvc thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_FxUV"><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">public</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">static</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">main</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token class-name">String</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"> args</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token class-name">System</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">out</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">println</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token function" style="color:rgb(80, 250, 123)">isPalindrome</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">""</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token comment" style="color:rgb(98, 114, 164)">//false</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token class-name">System</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">out</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">println</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token function" style="color:rgb(80, 250, 123)">isPalindrome</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"a"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token comment" style="color:rgb(98, 114, 164)">//true</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token class-name">System</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">out</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">println</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token function" style="color:rgb(80, 250, 123)">isPalindrome</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"aba"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token comment" style="color:rgb(98, 114, 164)">//true</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token class-name">System</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">out</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">println</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token function" style="color:rgb(80, 250, 123)">isPalindrome</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"abccba"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token comment" style="color:rgb(98, 114, 164)">//true</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token class-name">System</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">out</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">println</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token function" style="color:rgb(80, 250, 123)">isPalindrome</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"abcdcba"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token comment" style="color:rgb(98, 114, 164)">//true</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token class-name">System</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">out</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">println</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token function" style="color:rgb(80, 250, 123)">isPalindrome</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"abcdcba"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token comment" style="color:rgb(98, 114, 164)">//true</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">public</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">static</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">boolean</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">isPalindrome</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token class-name">String</span><span class="token plain"> s</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">s </span><span class="token operator">==</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">null</span><span class="token plain"> </span><span class="token operator">||</span><span class="token plain"> s</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">trim</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">isEmpty</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token boolean">false</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">s</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">length</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">==</span><span class="token plain"> </span><span class="token number">1</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token class-name">String</span><span class="token plain"> sub1</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain">sub2</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">int</span><span class="token plain"> mid </span><span class="token operator">=</span><span class="token plain"> s</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">length</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">/</span><span class="token plain"> </span><span class="token number">2</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">s</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">length</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">%</span><span class="token plain"> </span><span class="token number">2</span><span class="token plain"> </span><span class="token operator">==</span><span class="token plain"> </span><span class="token number">0</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">            sub1 </span><span class="token operator">=</span><span class="token plain"> s</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">substring</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token number">0</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain">mid</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">            sub2 </span><span class="token operator">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">reverse</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">s</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">substring</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">mid</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">else</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">            sub1 </span><span class="token operator">=</span><span class="token plain"> s</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">substring</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token number">0</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> mid</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">            sub2 </span><span class="token operator">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">reverse</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">s</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">substring</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">mid </span><span class="token operator">+</span><span class="token plain"> </span><span class="token number">1</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> sub1</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">equals</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">sub2</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">public</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">static</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">reverse</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token class-name">String</span><span class="token plain"> s</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token class-name">Stack</span><span class="token generics punctuation" style="color:rgb(248, 248, 242)">&lt;</span><span class="token generics class-name">String</span><span class="token generics punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain"> stack </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">Stack</span><span class="token generics punctuation" style="color:rgb(248, 248, 242)">&lt;</span><span class="token generics class-name">String</span><span class="token generics punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">for</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">char</span><span class="token plain"> c </span><span class="token operator">:</span><span class="token plain"> s</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">toCharArray</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">            stack</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">push</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">c </span><span class="token operator">+</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">""</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token class-name">StringBuilder</span><span class="token plain"> str </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">StringBuilder</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">while</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token operator">!</span><span class="token plain">stack</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">empty</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">            str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">append</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">stack</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">pop</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">toString</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div></code></pre></div></div>
<p>实现2:</p>
<div class="language-java codeBlockContainer_RfF3 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_n9gD"><pre tabindex="0" class="prism-code language-java codeBlock_UFvc thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_FxUV"><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">public</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">static</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">main</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token class-name">String</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"> args</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token class-name">System</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">out</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">println</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token function" style="color:rgb(80, 250, 123)">isPalindrome</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">""</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token comment" style="color:rgb(98, 114, 164)">//false</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token class-name">System</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">out</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">println</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token function" style="color:rgb(80, 250, 123)">isPalindrome</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"a"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token comment" style="color:rgb(98, 114, 164)">//true</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token class-name">System</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">out</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">println</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token function" style="color:rgb(80, 250, 123)">isPalindrome</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"aba"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token comment" style="color:rgb(98, 114, 164)">//true</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token class-name">System</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">out</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">println</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token function" style="color:rgb(80, 250, 123)">isPalindrome</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"abccba"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token comment" style="color:rgb(98, 114, 164)">//true</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token class-name">System</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">out</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">println</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token function" style="color:rgb(80, 250, 123)">isPalindrome</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"abcdcba"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token comment" style="color:rgb(98, 114, 164)">//true</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token class-name">System</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">out</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">println</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token function" style="color:rgb(80, 250, 123)">isPalindrome</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"abcdcba"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token comment" style="color:rgb(98, 114, 164)">//true</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">public</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">static</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">boolean</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">isPalindrome</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token class-name">String</span><span class="token plain"> s</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">char</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"> chars </span><span class="token operator">=</span><span class="token plain"> s</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">toCharArray</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:rgb(248, 248, 242)">&lt;</span><span class="token generics class-name">String</span><span class="token generics punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain"> matching </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">ArrayList</span><span class="token generics punctuation" style="color:rgb(248, 248, 242)">&lt;</span><span class="token generics class-name">String</span><span class="token generics punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">for</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">int</span><span class="token plain"> i </span><span class="token operator">=</span><span class="token plain"> </span><span class="token number">0</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"> i </span><span class="token operator">&lt;</span><span class="token plain"> s</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">length</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"> i </span><span class="token operator">++</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">chars</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain">s</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">length</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">-</span><span class="token plain"> </span><span class="token number">1</span><span class="token plain"> </span><span class="token operator">-</span><span class="token plain"> i</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"> </span><span class="token operator">==</span><span class="token plain"> chars</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain">i</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">                matching</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">add</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">chars</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain">i</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"> </span><span class="token operator">+</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">""</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">else</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">                </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">break</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token operator">!</span><span class="token plain">matching</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">isEmpty</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">&amp;&amp;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">s</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">length</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">-</span><span class="token plain"> matching</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">size</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">*</span><span class="token plain"> </span><span class="token number">2</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">&lt;=</span><span class="token plain"> </span><span class="token number">1</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_p4GZ" id="字符串压缩">字符串压缩<a href="https://shuhangli.com/2021/03/15/2021-03-15/%E9%9D%A2%E8%AF%95%E6%80%BB%E7%BB%93#%E5%AD%97%E7%AC%A6%E4%B8%B2%E5%8E%8B%E7%BC%A9" class="hash-link" aria-label="字符串压缩的直接链接" title="字符串压缩的直接链接" translate="no">​</a></h3>
<div class="language-java codeBlockContainer_RfF3 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_n9gD"><pre tabindex="0" class="prism-code language-java codeBlock_UFvc thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_FxUV"><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">public</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">static</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">main</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token class-name">String</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"> args</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token class-name">System</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">out</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">println</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token function" style="color:rgb(80, 250, 123)">compressString</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"aabcccccaaa"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token comment" style="color:rgb(98, 114, 164)">//输出：a2b1c5a3</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token class-name">System</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">out</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">println</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token function" style="color:rgb(80, 250, 123)">compressString</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"abbccd"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"> </span><span class="token comment" style="color:rgb(98, 114, 164)">//输出：abbccd。 abbccd"压缩后为"a1b2c2d1"，比原字符串长度更长</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token comment" style="color:rgb(98, 114, 164)">/**</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)">     * 实现这个函数</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)">     */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">public</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">static</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">compressString</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token class-name">String</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token comment" style="color:rgb(98, 114, 164)">//实现1</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">trim</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">length</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">&lt;=</span><span class="token plain"> </span><span class="token number">2</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token class-name">StringBuilder</span><span class="token plain"> builder </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">StringBuilder</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">char</span><span class="token plain"> matching </span><span class="token operator">=</span><span class="token plain"> </span><span class="token char" style="color:rgb(255, 121, 198)">'#'</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">int</span><span class="token plain"> count </span><span class="token operator">=</span><span class="token plain"> </span><span class="token number">1</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">for</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">char</span><span class="token plain"> c </span><span class="token operator">:</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">toCharArray</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">matching </span><span class="token operator">==</span><span class="token plain"> </span><span class="token char" style="color:rgb(255, 121, 198)">'#'</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">                matching </span><span class="token operator">=</span><span class="token plain"> c</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">else</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">                </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">matching </span><span class="token operator">!=</span><span class="token plain"> c</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">                    builder</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">append</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">matching</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">append</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">count</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">                    matching </span><span class="token operator">=</span><span class="token plain"> c</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">                    count </span><span class="token operator">=</span><span class="token plain"> </span><span class="token number">1</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">                </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">else</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">                    count </span><span class="token operator">++</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">                </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        builder</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">append</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">matching</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">append</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">count</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> builder</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">length</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">&gt;=</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">length</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">?</span><span class="token plain"> str </span><span class="token operator">:</span><span class="token plain"> builder</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">toString</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></div></code></pre></div></div>
<h1>面试</h1>
<h2 class="anchor anchorTargetStickyNavbar_p4GZ" id="公司1">公司1<a href="https://shuhangli.com/2021/03/15/2021-03-15/%E9%9D%A2%E8%AF%95%E6%80%BB%E7%BB%93#%E5%85%AC%E5%8F%B81" class="hash-link" aria-label="公司1的直接链接" title="公司1的直接链接" translate="no">​</a></h2>
<p>提了几个问题,答的都不是很好,这里记录下</p>
<h3 class="anchor anchorTargetStickyNavbar_p4GZ" id="nodejs和java的区别">nodejs和java的区别<a href="https://shuhangli.com/2021/03/15/2021-03-15/%E9%9D%A2%E8%AF%95%E6%80%BB%E7%BB%93#nodejs%E5%92%8Cjava%E7%9A%84%E5%8C%BA%E5%88%AB" class="hash-link" aria-label="nodejs和java的区别的直接链接" title="nodejs和java的区别的直接链接" translate="no">​</a></h3>
<p>这区别大了去了,唯一沾点边的就是jit?还是java?</p>
<p>但是我回答的是nodejs单线程时间循环,java则是有对线程的掌控能力.<br>
略显肤浅的回答.</p>
<p>现在来整理下我对这2种语言的异同.</p>
<ul>
<li class="">语法上
js有部分类似java的语法,但是越新的版本差别越大,套上ts以后与其说是像java不如说像c#;</li>
<li class="">编译上
js基本是通过babel和插件转换,混淆,但是实际递交虚拟机执行的还是js;
java编译出来,实际递交虚拟机执行的是字节码(.class);</li>
<li class="">运行时
js的运行时是v8等js引擎;
java的运行时是各种jvm/dvm实现;</li>
<li class="">语言上
js是一种弱类型语言(所以才有了ts);
java是一种强类型语言(有了var也改变不了);</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_p4GZ" id="nodejs单线程的理解">nodejs单线程的理解<a href="https://shuhangli.com/2021/03/15/2021-03-15/%E9%9D%A2%E8%AF%95%E6%80%BB%E7%BB%93#nodejs%E5%8D%95%E7%BA%BF%E7%A8%8B%E7%9A%84%E7%90%86%E8%A7%A3" class="hash-link" aria-label="nodejs单线程的理解的直接链接" title="nodejs单线程的理解的直接链接" translate="no">​</a></h3>
<p>我的回答是:单线程的是事件循环,实际执行时还是有多线程的能力的;</p>
<p>回答太过粗糙.</p>
<p>首先,nodejs是有多线程能力的,在N-API中也能找到对应的描述:</p>
<p><img decoding="async" loading="lazy" alt="napi文档" src="https://shuhangli.com/assets/images/napi-6b62f33e5dec0084542dba66c2262516.jpg" width="2638" height="1446" class="img_AkGR"></p>
<p>底层是有thread safe multiple threads的能力的,上层js也有worker threads提供多线程能力.</p>
<p><img decoding="async" loading="lazy" alt="nodejs文档" src="https://shuhangli.com/assets/images/nodejs-313d1d6f8fdb1a2cf00b883ef43eba9c.jpg" width="2816" height="1736" class="img_AkGR"></p>
<p>按照文档的描述,worker threads</p>
<blockquote>
<p>They do so by transferring ArrayBuffer instances or sharing SharedArrayBuffer instances</p>
</blockquote>
<blockquote>
<p>When implementing a worker pool, use the AsyncResource API to inform diagnostic tools (e.g. to provide asynchronous stack traces) about the correlation between tasks and their outcomes. See "Using AsyncResource for a Worker thread pool" in the async_hooks documentation for an example implementation.</p>
</blockquote>
<blockquote>
<p>Worker threads inherit non-process-specific options by default. Refer to Worker constructor options to know how to customize worker thread options, specifically argv and execArgv options.</p>
</blockquote>
<h3 class="anchor anchorTargetStickyNavbar_p4GZ" id="刚才提到了nodejs-native-addon能描述下怎么写插件吗">刚才提到了nodejs native addon,能描述下怎么写插件吗?<a href="https://shuhangli.com/2021/03/15/2021-03-15/%E9%9D%A2%E8%AF%95%E6%80%BB%E7%BB%93#%E5%88%9A%E6%89%8D%E6%8F%90%E5%88%B0%E4%BA%86nodejs-native-addon%E8%83%BD%E6%8F%8F%E8%BF%B0%E4%B8%8B%E6%80%8E%E4%B9%88%E5%86%99%E6%8F%92%E4%BB%B6%E5%90%97" class="hash-link" aria-label="刚才提到了nodejs native addon,能描述下怎么写插件吗?的直接链接" title="刚才提到了nodejs native addon,能描述下怎么写插件吗?的直接链接" translate="no">​</a></h3>
<p>这里我只给了一个自己写的napi的demo的<a href="https://github.com/suhli/NAPIPC" target="_blank" rel="noopener noreferrer" class="">仓库地址</a><br>
并简单地说了下,写binding.gyp和在cpp中描述对应的方法即可</p>
<p>实际可以参考<a href="https://nodejs.org/api/addons.html" target="_blank" rel="noopener noreferrer" class="">native addon文档</a>或<a href="https://nodejs.org/api/n-api.html" target="_blank" rel="noopener noreferrer" class="">N-API文档</a></p>
<h2 class="anchor anchorTargetStickyNavbar_p4GZ" id="公司2">公司2<a href="https://shuhangli.com/2021/03/15/2021-03-15/%E9%9D%A2%E8%AF%95%E6%80%BB%E7%BB%93#%E5%85%AC%E5%8F%B82" class="hash-link" aria-label="公司2的直接链接" title="公司2的直接链接" translate="no">​</a></h2>
<p>线上面试交流的东西主要是工作经历/公司状况之类的,并无太多技术上的东西<br>
技术方面主要还是在线下面试</p>
<h3 class="anchor anchorTargetStickyNavbar_p4GZ" id="mysql-如何调优">mysql 如何调优<a href="https://shuhangli.com/2021/03/15/2021-03-15/%E9%9D%A2%E8%AF%95%E6%80%BB%E7%BB%93#mysql-%E5%A6%82%E4%BD%95%E8%B0%83%E4%BC%98" class="hash-link" aria-label="mysql 如何调优的直接链接" title="mysql 如何调优的直接链接" translate="no">​</a></h3>
<p>我的回答是explain SQL;然后看对应的描述,是否有用filesort,filesort是否过大;是否有添加索引等并做对应处理.</p>
<p>太那啥,主要这问题也有点泛,糙一点的explain,然后哪里有问题填哪里.
细一点就加各种软件,监控mysql的状态然后再找问题.
不过这方面经验的确不足,之前的公司mysql直接用的rds mysql,有很全的监控与自动化备份等功能.
出问题了小一点的复制索引优化建议,中型问题改业务逻辑,大问题提工单就能解决,实在没怎么认真了解过.</p>
<h3 class="anchor anchorTargetStickyNavbar_p4GZ" id="树的类型">树的类型<a href="https://shuhangli.com/2021/03/15/2021-03-15/%E9%9D%A2%E8%AF%95%E6%80%BB%E7%BB%93#%E6%A0%91%E7%9A%84%E7%B1%BB%E5%9E%8B" class="hash-link" aria-label="树的类型的直接链接" title="树的类型的直接链接" translate="no">​</a></h3>
<p>从mysql突然跳到树,我第一反应是数值的数,萌蠢的我说了什么int,big int之类的.
后面才反应到说的是tree.
遂回答:BTree,B+Tree,B*Tree,RBTree</p>
<h3 class="anchor anchorTargetStickyNavbar_p4GZ" id="rbtree跟btree的区别">RBTree跟BTree的区别<a href="https://shuhangli.com/2021/03/15/2021-03-15/%E9%9D%A2%E8%AF%95%E6%80%BB%E7%BB%93#rbtree%E8%B7%9Fbtree%E7%9A%84%E5%8C%BA%E5%88%AB" class="hash-link" aria-label="RBTree跟BTree的区别的直接链接" title="RBTree跟BTree的区别的直接链接" translate="no">​</a></h3>
<p>我只简单回答了RBTree是BTree的子集,使用红黑颜色描述节点,通过变更颜色与左右旋来降低时间复杂度.
实际文章很多,也可以参考<a href="https://zh.wikipedia.org/zh-hans/%E7%BA%A2%E9%BB%91%E6%A0%91" target="_blank" rel="noopener noreferrer" class="">wiki</a></p>
<h3 class="anchor anchorTargetStickyNavbar_p4GZ" id="rbtree应用">RBTree应用<a href="https://shuhangli.com/2021/03/15/2021-03-15/%E9%9D%A2%E8%AF%95%E6%80%BB%E7%BB%93#rbtree%E5%BA%94%E7%94%A8" class="hash-link" aria-label="RBTree应用的直接链接" title="RBTree应用的直接链接" translate="no">​</a></h3>
<p>回答到java的hashmap,mysql(索引用的b树,这里是真的蠢).<br>
虽然文档里有<a href="https://dev.mysql.com/doc/dev/mysql-server/8.0.12/ut0rbt_8cc.html" target="_blank" rel="noopener noreferrer" class="">rbt</a>,但是有哪里用到?  有空要翻翻</p>
<h3 class="anchor anchorTargetStickyNavbar_p4GZ" id="其他">其他<a href="https://shuhangli.com/2021/03/15/2021-03-15/%E9%9D%A2%E8%AF%95%E6%80%BB%E7%BB%93#%E5%85%B6%E4%BB%96" class="hash-link" aria-label="其他的直接链接" title="其他的直接链接" translate="no">​</a></h3>
<p>聊了下seata,还包括吹出去的贡献者,得知面试官是初期贡献成员之后爆了.<br>
总的来说对方的意思是:基础不太扎实.</p>]]></content>
        <author>
            <name>shuhang li</name>
            <uri>https://github.com/suhli</uri>
        </author>
        <category label="java" term="java"/>
        <category label="javascript" term="javascript"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[从离职到建模到创业]]></title>
        <id>https://shuhangli.com/2021/03/15/2021-03-15/从离职到建模到创业</id>
        <link href="https://shuhangli.com/2021/03/15/2021-03-15/从离职到建模到创业"/>
        <updated>2021-03-15T03:43:17.000Z</updated>
        <summary type="html"><![CDATA[序]]></summary>
        <content type="html"><![CDATA[<h2 class="anchor anchorTargetStickyNavbar_p4GZ" id="序">序<a href="https://shuhangli.com/2021/03/15/2021-03-15/%E4%BB%8E%E7%A6%BB%E8%81%8C%E5%88%B0%E5%BB%BA%E6%A8%A1%E5%88%B0%E5%88%9B%E4%B8%9A#%E5%BA%8F" class="hash-link" aria-label="序的直接链接" title="序的直接链接" translate="no">​</a></h2>
<p>离职这件事我考虑了w很久,第一次出现离职的想法应该在2018年,那时候我还是个直面社会未满3年的小伙.
契机是啥现在已经忘了,突然间就感觉工作中的crud,浅尝即止的demo,写不下去的日志全无意义.
周围所有人都在随着时间的增长在快速地成长的时候,我却停在了自己的面前,像进入刺客信条的读取环节,周围的人渐渐消失,而我无论怎么奔跑都仍在原地.</p>
<!-- -->
<p>于是离职的想法就那样自然地冒了出来.</p>
<h2 class="anchor anchorTargetStickyNavbar_p4GZ" id="思前想后">思前想后<a href="https://shuhangli.com/2021/03/15/2021-03-15/%E4%BB%8E%E7%A6%BB%E8%81%8C%E5%88%B0%E5%BB%BA%E6%A8%A1%E5%88%B0%E5%88%9B%E4%B8%9A#%E6%80%9D%E5%89%8D%E6%83%B3%E5%90%8E" class="hash-link" aria-label="思前想后的直接链接" title="思前想后的直接链接" translate="no">​</a></h2>
<p>离职可以,然后呢?<br>
想了很久,没存款,没目标,没理想,于是又混混噩噩地过了近2年.</p>
<p>后来还是找了个理由离职了.</p>
<h1>建模</h1>
<h2 class="anchor anchorTargetStickyNavbar_p4GZ" id="blender">blender<a href="https://shuhangli.com/2021/03/15/2021-03-15/%E4%BB%8E%E7%A6%BB%E8%81%8C%E5%88%B0%E5%BB%BA%E6%A8%A1%E5%88%B0%E5%88%9B%E4%B8%9A#blender" class="hash-link" aria-label="blender的直接链接" title="blender的直接链接" translate="no">​</a></h2>
<p>yes!blender!<br>
<img decoding="async" loading="lazy" alt="demo view 1" src="https://shuhangli.com/assets/images/demo1-aa9d06f4f40188181b15041be4a02059.png" width="931" height="542" class="img_AkGR"></p>
<p><img decoding="async" loading="lazy" alt="demo view 2" src="https://shuhangli.com/assets/images/demo2-8dcc6b06ce71391c8ee643f718ef60a8.png" width="4032" height="3024" class="img_AkGR"></p>
<p>回头看,这学习建模的理由就是在欺骗自己.<br>
3个月过去了,基础是有一点,可随着时间的流逝,热情也在消退.
恰好有几个朋友对我曾经在酒桌上提出的方案感兴趣.</p>
<p>于是开始创业.</p>
<h1>创业</h1>
<h2 class="anchor anchorTargetStickyNavbar_p4GZ" id="关于项目">关于项目<a href="https://shuhangli.com/2021/03/15/2021-03-15/%E4%BB%8E%E7%A6%BB%E8%81%8C%E5%88%B0%E5%BB%BA%E6%A8%A1%E5%88%B0%E5%88%9B%E4%B8%9A#%E5%85%B3%E4%BA%8E%E9%A1%B9%E7%9B%AE" class="hash-link" aria-label="关于项目的直接链接" title="关于项目的直接链接" translate="no">​</a></h2>
<p>项目很简单,就是cbd写字楼下面卖早餐,我想要做的核心是快,成交快,出餐快;其次是不难吃;最后就是价格中上.</p>
<h2 class="anchor anchorTargetStickyNavbar_p4GZ" id="莽撞前期">莽撞前期<a href="https://shuhangli.com/2021/03/15/2021-03-15/%E4%BB%8E%E7%A6%BB%E8%81%8C%E5%88%B0%E5%BB%BA%E6%A8%A1%E5%88%B0%E5%88%9B%E4%B8%9A#%E8%8E%BD%E6%92%9E%E5%89%8D%E6%9C%9F" class="hash-link" aria-label="莽撞前期的直接链接" title="莽撞前期的直接链接" translate="no">​</a></h2>
<p>我一开始臆想的实现2个快速的核心就是机器,带加热功能的取餐柜;<br>
拖沓着看了几家厂商,见我不愿承担选择机器的任务和带来的责任的伙伴去了趟青岛,拿回了5台既不符合我快的定义,也很难从这机器的外型吸引顾客的机器<br>
于是开始定餐品,定包装,选点,测试机器等.<br>
说实话,这些工作内容并不枯燥,只是在习惯了互联网开发的我的看来,这些工作能选择的方式都过于低效.<br>
低效的方式让我变得有点像代码质量被人质疑的时候那样的急躁;现在看来开始的工作实在是过于草率.</p>
<h3 class="anchor anchorTargetStickyNavbar_p4GZ" id="选点">选点<a href="https://shuhangli.com/2021/03/15/2021-03-15/%E4%BB%8E%E7%A6%BB%E8%81%8C%E5%88%B0%E5%BB%BA%E6%A8%A1%E5%88%B0%E5%88%9B%E4%B8%9A#%E9%80%89%E7%82%B9" class="hash-link" aria-label="选点的直接链接" title="选点的直接链接" translate="no">​</a></h3>
<ul>
<li class="">
<p>某商住2用写字楼大堂<br>
这个点位初看非常好,既是写字楼出入口关键位置,也是早上电梯排队人流的不远处,租金也非常低.
可是到进去了之后,活动时与顾客交谈过后才知道,这位置原来有过一家OK便利店,可是已经做不下去搬走了.
这才知道甚至连点位背景都没调查就直接签约进场是有多么地愚蠢<br>
后面这个点位的日销量的事实也在提醒着这点</p>
</li>
<li class="">
<p>某写字楼入口旁,某团外卖取餐柜隔壁
这个点位位于一个十字路口旁的写字楼入口旁,物业给到我们的位置紧靠着某团外卖取餐柜.
比起上一个点位,这个点位位置竞争更加激烈,马路斜对面有一家麦当劳,麦当劳对面有OK便利店,麦当劳与OK便利店后面是一条食街,一直从这延伸到地铁口附近.
但是从后面的结果来看,这个点位的日销量却是非常的稳定,虽然扩大用户数量很困难,但它仍是所有点位最稳定,日销量最高的一个点位.
甚至就算流动早餐车就在写字楼入口另一侧的时候也能保持这种稳定的销量.</p>
</li>
<li class="">
<p>某商住2用小区入口必经之处
这点位与上一点位距离不远,但是相比起上一点位,这里附近不但连餐饮店没有,最近的便利店也在差不多1公里外.
但是这个点位的日销量并不理想,原因可能是目标人群(上班族)并不多.</p>
</li>
<li class="">
<p>cbd内某写字楼
这点位在某地铁口旁,地铁口里联通着一座商城的地下食街,但是方向不一样.
这点位是定得最草率的一个,这点位的物业与前两个为同一个,据扩展的人员(找的中介)的人的意思是,如果我们3个点都拿下的话会有优惠和免电费.
但是这个点位非常不理想,因为给到的位置在地铁口与大堂的延伸线上,在上班这一场景中并不顺路
日销量也证明了这个位置并不理想</p>
</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_p4GZ" id="餐品与包装和测试机器">餐品与包装和测试机器<a href="https://shuhangli.com/2021/03/15/2021-03-15/%E4%BB%8E%E7%A6%BB%E8%81%8C%E5%88%B0%E5%BB%BA%E6%A8%A1%E5%88%B0%E5%88%9B%E4%B8%9A#%E9%A4%90%E5%93%81%E4%B8%8E%E5%8C%85%E8%A3%85%E5%92%8C%E6%B5%8B%E8%AF%95%E6%9C%BA%E5%99%A8" class="hash-link" aria-label="餐品与包装和测试机器的直接链接" title="餐品与包装和测试机器的直接链接" translate="no">​</a></h3>
<p>定餐品与包装用了近2个月,却还是仓促上架.
这部分其实并非我主导,但是不可否认的是,我明知伙伴的拖延与低效却没起到监督的作用,像是事外人一样去看待这工作.</p>
<h2 class="anchor anchorTargetStickyNavbar_p4GZ" id="浑噩中期">浑噩中期<a href="https://shuhangli.com/2021/03/15/2021-03-15/%E4%BB%8E%E7%A6%BB%E8%81%8C%E5%88%B0%E5%BB%BA%E6%A8%A1%E5%88%B0%E5%88%9B%E4%B8%9A#%E6%B5%91%E5%99%A9%E4%B8%AD%E6%9C%9F" class="hash-link" aria-label="浑噩中期的直接链接" title="浑噩中期的直接链接" translate="no">​</a></h2>
<p>每个点位进场后我们都会开始为期3天的免费早餐活动,活动期间几乎没有损耗.
被这种热情刺激到的我们马上就被活动结束后惨淡的日销量给打肿了脸.
于是开始寻找问题.</p>
<h3 class="anchor anchorTargetStickyNavbar_p4GZ" id="餐品">餐品<a href="https://shuhangli.com/2021/03/15/2021-03-15/%E4%BB%8E%E7%A6%BB%E8%81%8C%E5%88%B0%E5%BB%BA%E6%A8%A1%E5%88%B0%E5%88%9B%E4%B8%9A#%E9%A4%90%E5%93%81" class="hash-link" aria-label="餐品的直接链接" title="餐品的直接链接" translate="no">​</a></h3>
<p>在活动中收集到的反馈基本都是挺好吃的,但是日销量的惨淡说明问题并不全在此.
剩下就是餐品过少的问题了.</p>
<h3 class="anchor anchorTargetStickyNavbar_p4GZ" id="机器">机器<a href="https://shuhangli.com/2021/03/15/2021-03-15/%E4%BB%8E%E7%A6%BB%E8%81%8C%E5%88%B0%E5%BB%BA%E6%A8%A1%E5%88%B0%E5%88%9B%E4%B8%9A#%E6%9C%BA%E5%99%A8" class="hash-link" aria-label="机器的直接链接" title="机器的直接链接" translate="no">​</a></h3>
<p>我到目前为止还是坚持核心是要快,目前位置并不能做到,但是我们也没资源去改变这一点了
另外就是APP,二手售货机原生的APP像是停留在移动时代之前,无论是界面还是功能
于是我后面便将APP重写了</p>
<p><img decoding="async" loading="lazy" alt="原生APP" src="https://shuhangli.com/assets/images/app_old-56c08bf696c5b0ce8df5b04c26d1739f.jpg" width="1440" height="1080" class="img_AkGR"></p>
<p><img decoding="async" loading="lazy" alt="重写后的APP" src="https://shuhangli.com/assets/images/app_new-aeb66d2878fb80ed86f6bf170f557526.jpg" width="1440" height="1080" class="img_AkGR"></p>
<p><img decoding="async" loading="lazy" alt="重写后的APP" src="https://shuhangli.com/assets/images/app_new2-be7991986564a5237558191fc834e116.jpg" width="862" height="1532" class="img_AkGR"></p>
<h2 class="anchor anchorTargetStickyNavbar_p4GZ" id="失败后期">失败后期<a href="https://shuhangli.com/2021/03/15/2021-03-15/%E4%BB%8E%E7%A6%BB%E8%81%8C%E5%88%B0%E5%BB%BA%E6%A8%A1%E5%88%B0%E5%88%9B%E4%B8%9A#%E5%A4%B1%E8%B4%A5%E5%90%8E%E6%9C%9F" class="hash-link" aria-label="失败后期的直接链接" title="失败后期的直接链接" translate="no">​</a></h2>
<p>人心散了怎么聚回来?
春节假期过后,上了两期新品,结果不尽人意.
同时生产核心位置的伙伴突然说要在工作日出去玩2天.
知道这消息的时候我就开始准备简历,并在App上投递了.
机器停运的2天内经过了2场远程面试,1场在线笔试,1场线下面试(其实就2间公司,一共也就投了4份简历左右)</p>
<p>于是,我感觉我要回去工作了</p>
<h1>总结</h1>
<p>不仅仅是这2年,人生至此一直是这样草率莽撞,思前顾后的却并非重点,失败的创业后面多少要有些成长吧!</p>]]></content>
        <author>
            <name>shuhang li</name>
            <uri>https://github.com/suhli</uri>
        </author>
        <category label="创业" term="创业"/>
        <category label="建模" term="建模"/>
    </entry>
</feed>