{
  "version": "https://jsonfeed.org/version/1", 
  "title": "Java", 
  "description": "Sun \u516c\u53f8\u53d1\u660e\uff0c\u88ab\u5e7f\u6cdb\u4f7f\u7528\u7684\u4e00\u95e8\u7f16\u7a0b\u8bed\u8a00\u3002", 
  "home_page_url": "https://www.v2ex.com/go/java", 
  "feed_url": "https://www.v2ex.com/feed/java.json", 
  "icon": "https://cdn.v2ex.com/navatar/03af/dbd6/63_large.png?m=1644490200", 
  "favicon": "https://cdn.v2ex.com/navatar/03af/dbd6/63_normal.png?m=1644490200", 
  "items": [
    {
      "author": {
        "url": "https://www.v2ex.com/member/mmdsun", 
        "name": "mmdsun", 
        "avatar": "https://cdn.v2ex.com/avatar/c476/56f5/269732_large.png?m=1788023544"
      }, 
      "url": "https://www.v2ex.com/t/1238103", 
      "title": "\u5f00\u6e90:\u7528\u521a\u53d1\u5e03\u7684 Spring AI 2.0.1\uff0c\u64b8\u4e86\u4e00\u4e2a\u5168\u529f\u80fd Agent", 
      "id": "https://www.v2ex.com/t/1238103", 
      "date_published": "2026-08-29T17:33:34+00:00", 
      "content_html": "<p>\u7528\u521a\u53d1\u5e03\u7684 Spring AI 2.0.1 \u6846\u67b6 \u64b8\u4e86\u4e2a Agent</p>\n<p>\u524d\u51e0\u5929 Spring AI 2.0.1 \u53d1\u5e03\uff0c\u62ff\u5b83 <em>vibe coding</em> \u4e86\u4e00\u4e2a \u670d\u52a1\u7aef\u7684 Agent \u3002\n\uff08\u7c7b\u4f3c\u4e8e ChatGPT/KIMI \u7f51\u9875\u7248\u4e0d\u662f\u5ba2\u6237\u7aef\u5e94\u7528 \u5f53\u7136\u4e5f\u53ef\u4ee5 native \u6253\u5305.exe \u7535\u8111\u4e0a\u4f7f\u7528\uff09\u3002<br/>\n\u4e3b\u8981\u76ee\u7684\u662f\u6d4b\u4e00\u4e0b\u73b0\u5728 Java \u8fd9\u8fb9 AI \u751f\u6001\u8fdb\u5316\u4ec0\u4e48\u5730\u6b65\u4e86\u3002</p>\n<p>\u4e3b\u6d41\u80fd\u529b\u57fa\u672c\u90fd\u652f\u6301\u6bd4\u5982\uff1a</p>\n<ul>\n<li>\u8054\u7f51\u641c\u7d22 / \u7f51\u9875\u6293\u53d6</li>\n<li>Skills \u70ed\u63d2\u62d4</li>\n<li>MCP</li>\n<li>\u5b50\u4ee3\u7406\uff08 Subagent \uff09</li>\n<li>RAG</li>\n<li>Human-in-the-Loop \u5ba1\u6279</li>\n<li>\u6c99\u7bb1\u4ee3\u7801\u6267\u884c\uff08 code-interpreter \uff09</li>\n</ul>\n<p>\u6a21\u578b\u652f\u6301\u5f88\u591a\uff08 Anthropic / DeepSeek / OpenAI / \u81ea\u5b9a\u4e49\u6a21\u578b\uff09\u3002</p>\n<p>\u7248\u672c\uff1a<br/>\n<em>JDK 25 + Spring Boot 4.1 + Spring AI 2.0.1</em>\u3002\u9664\u524d\u7aef\u662f\u6253\u5305\u7248\u672c\u8fd8\u5728\u6539\uff0c\u5176\u4f59\u5df2\u5168\u90e8\u5f00\u6e90\u3002\u4ee3\u7801\u5f88\u7b80\u5355\u2014\u2014\u5c31\u51e0\u4e2a\u63a5\u53e3\uff0c\u6ca1\u590d\u6742\u4e1c\u897f\u4f46\u529f\u80fd\u633a\u5168\u3002\u9002\u5408\u505a\u811a\u624b\u67b6\u8d77\u6b65 AI \u9879\u76ee\u3002</p>\n<p>\u672c\u6765\u4ee5\u4e3a\u8981\u624b\u5199\u4e0d\u5c11\u4e1c\u897f\uff0c\u7ed3\u679c\u53d1\u73b0\u5b98\u7f51/\u793e\u533a\u5df2\u7ecf\u5c01\u88c5\u597d\u4e86\u5927\u90e8\u5206\uff0c\u53ea\u6709 Human-in-the-Loop \u81ea\u5df1\u5199\u4e86\u70b9</p>\n<p>\u9879\u76ee\u5730\u5740: <a href=\"https://github.com/git-syl/hermes-agent-demo\" rel=\"nofollow\">hermes-agent-demo</a> </p>\n<p>\u6548\u679c\u622a\u56fe\uff08\u5de5\u5177\u8c03\u7528\u3001\u5b50\u667a\u80fd\u4f53\u7f16\u6392\u3001Skills \u3001TODO \u4efb\u52a1\u6e05\u5355\uff09\uff1a<br/>\n\u5982\u679c\u6709\u7a7a\u4e0b\u4e00\u6b65\u4f1a\u628a\u5b50\u667a\u80fd\u4f53\u505a\u6210\uff0c\u90a3\u79cd\u865a\u62df\u5458\u5de5\u7684\u6548\u679c\u3002\u548c\u5f15\u5165\u7f16\u6392\u6846\u67b6\u4f8b\u5982 Embabel \u3002\n<img alt=\"\u8fd0\u884c\u622a\u56fe\" class=\"embedded_image\" loading=\"lazy\" referrerpolicy=\"no-referrer\" rel=\"noreferrer\" src=\"https://i.v2ex.co/LKa9LYBX.png\"/></p>\n"
    }, 
    {
      "author": {
        "url": "https://www.v2ex.com/member/g632104866", 
        "name": "g632104866", 
        "avatar": "https://cdn.v2ex.com/avatar/01d5/38d4/510131_large.png?m=1783481882"
      }, 
      "url": "https://www.v2ex.com/t/1237647", 
      "title": "\u7eaf\u5f00\u6e90 Nexus \u66ff\u4ee3\u65b9\u6848 kkRepo 1.0.0 \u6b63\u5f0f\u53d1\u5e03\uff0c\u65b0\u589e R/CRAN\u3001Go Hosted \u548c\u591a\u5957 UI \u4e3b\u9898", 
      "id": "https://www.v2ex.com/t/1237647", 
      "date_published": "2026-08-27T07:56:42+00:00", 
      "content_html": "<h1>\u524d\u8a00</h1>\n<p>\u4ece 0.x \u4e00\u8def\u8fed\u4ee3\u5230\u73b0\u5728\uff0ckkRepo \u7ec8\u4e8e\u8fce\u6765\u4e86\u9996\u4e2a\u7a33\u5b9a\u7248\u672c\uff1a<strong>kkRepo 1.0.0</strong>\u3002</p>\n<p>\u8fd9\u4e2a\u7248\u672c\u65b0\u589e\u4e86\u5b8c\u6574\u7684 R/CRAN \u4ed3\u5e93\u3001Go Hosted \u4ed3\u5e93\u548c\u591a\u5957\u53ef\u5207\u6362 UI \u4e3b\u9898\uff0c\u540c\u65f6\u5b8c\u5584\u4e86 PyPI \u4ee3\u7406\u3001\u7ec4\u4ef6\u4e0a\u4f20\u3001\u5168\u5c40\u641c\u7d22\u4e0e Maven Snapshot \u5220\u9664\u7b49\u80fd\u529b\u3002</p>\n<ul>\n<li>GitHub\uff1a<a href=\"https://github.com/klboke/kkRepo\" rel=\"nofollow\">https://github.com/klboke/kkRepo</a></li>\n<li>v1.0.0 Release\uff1a<a href=\"https://github.com/klboke/kkRepo/releases/tag/v1.0.0\" rel=\"nofollow\">https://github.com/klboke/kkRepo/releases/tag/v1.0.0</a></li>\n<li>\u5b8c\u6574\u53d8\u66f4\uff1a<a href=\"https://github.com/klboke/kkRepo/compare/v0.9.0...v1.0.0\" rel=\"nofollow\">v0.9.0...v1.0.0</a></li>\n</ul>\n<h2>kkRepo \u662f\u4ec0\u4e48\uff1f</h2>\n<p>kkRepo \u662f\u4e00\u6b3e\u793e\u533a\u9a71\u52a8\u3001\u5b8c\u5168\u5f00\u6e90\u7684\u81ea\u6258\u7ba1\u5236\u54c1\u4ed3\u5e93\uff0c\u76ee\u6807\u662f\u89e3\u51b3 Sonatype Nexus Community Edition \u5728\u683c\u5f0f\u652f\u6301\u3001\u5bb9\u91cf\u9650\u5236\u3001\u8fc1\u79fb\u548c\u9ad8\u53ef\u7528\u90e8\u7f72\u7b49\u65b9\u9762\u7684\u75db\u70b9\u3002</p>\n<p>\u9879\u76ee\u56f4\u7ed5 Nexus \u7684\u5ba2\u6237\u7aef\u534f\u8bae\u3001\u6743\u9650\u6a21\u578b\u548c <code>/repository/&lt;repo&gt;/...</code> URL \u5e03\u5c40\u5b9e\u73b0\u517c\u5bb9\uff0c\u5e76\u63d0\u4f9b\u5b58\u91cf\u4ed3\u5e93\u3001\u5236\u54c1\u3001\u7528\u6237\u3001\u89d2\u8272\u548c\u6743\u9650\u8fc1\u79fb\u80fd\u529b\uff0c\u5c3d\u91cf\u8ba9\u539f\u6709\u5ba2\u6237\u7aef\u914d\u7f6e\u548c CI \u5de5\u4f5c\u6d41\u4fdd\u6301\u4e0d\u53d8\u3002</p>\n<p>\u76ee\u524d\u5df2\u7ecf\u652f\u6301 20+ \u79cd\u4ed3\u5e93\u683c\u5f0f\u548c\u4ee3\u7406\u7c7b\u578b\uff1a</p>\n<p>Maven \u3001npm \u3001PyPI \u3001Go \u3001Helm \u3001Cargo/Rust \u3001Dart/Pub \u3001Composer/PHP \u3001Terraform \u3001Swift Package Registry \u3001Ansible Galaxy \u3001Conda \u3001APT/Debian \u3001Conan 2 \u3001Alpine/APK \u3001R/CRAN \u3001Hugging Face Models \u3001Docker/OCI \u3001NuGet \u3001RubyGems \u3001Yum \u548c Raw \u3002</p>\n<p>\u4e0d\u540c\u683c\u5f0f\u6839\u636e\u5b98\u65b9\u534f\u8bae\u652f\u6301 hosted \u3001proxy \u6216 group \u4ed3\u5e93\u3002</p>\n<h2>\u4e3a\u4ec0\u4e48\u662f 1.0.0 \uff1f</h2>\n<p>1.0.0 \u662f kkRepo \u7684\u9996\u4e2a\u7a33\u5b9a\u7248\u672c\u3002</p>\n<p>\u8fd9\u5e76\u4e0d\u610f\u5473\u7740\u9879\u76ee\u5df2\u7ecf\u505c\u6b62\u6f14\u8fdb\uff0c\u800c\u662f\u4ee3\u8868\u6838\u5fc3\u4ed3\u5e93\u3001\u6743\u9650\u3001\u5b58\u50a8\u3001\u8fc1\u79fb\u3001\u641c\u7d22\u3001\u591a\u526f\u672c\u534f\u8c03\u4ee5\u53ca JVM/Native \u90e8\u7f72\u80fd\u529b\u5df2\u7ecf\u5f62\u6210\u4e00\u6761\u7a33\u5b9a\u53d1\u5e03\u7ebf\u3002</p>\n<h2>v1.0.0 \u4e3b\u8981\u66f4\u65b0</h2>\n<h3>1. \u65b0\u589e R / CRAN \u4ed3\u5e93</h3>\n<p>v1.0.0 \u65b0\u589e R/CRAN \u7684 hosted \u3001proxy \u548c group \u4e09\u79cd\u4ed3\u5e93\u7c7b\u578b\u3002</p>\n<p>\u4e3b\u8981\u80fd\u529b\u5305\u62ec\uff1a</p>\n<ul>\n<li>Hosted \u4fdd\u5b58\u4f01\u4e1a\u5185\u90e8 R source package</li>\n<li>Proxy \u7f13\u5b58\u516c\u5f00 CRAN \u955c\u50cf</li>\n<li>Group \u7edf\u4e00\u89e3\u6790\u79c1\u6709\u5305\u548c\u516c\u5171\u5305</li>\n<li>\u81ea\u52a8\u751f\u6210\u786e\u5b9a\u6027\u7684 <code>PACKAGES.gz</code></li>\n<li>Package coordinate \u4e0d\u53ef\u53d8\uff0c\u76f8\u540c\u5185\u5bb9\u91cd\u8bd5\u5e42\u7b49</li>\n<li>Group \u6309 snapshot \u56fa\u5b9a\u5177\u4f53\u6210\u5458\u548c checksum</li>\n<li>\u652f\u6301 Cleanup Policy \u548c\u5236\u54c1\u5b89\u5168\u626b\u63cf</li>\n<li>\u652f\u6301\u591a\u526f\u672c\u53d1\u5e03\u534f\u8c03\u548c\u6545\u969c\u6062\u590d</li>\n<li>\u652f\u6301\u7ecf\u8fc7\u6570\u636e\u7ed3\u6784\u9a8c\u8bc1\u7684 Nexus 3.94 \u8fc1\u79fb</li>\n<li>\u4f7f\u7528\u771f\u5b9e R 4.5/4.6 \u5ba2\u6237\u7aef\u5b8c\u6210\u517c\u5bb9\u6027\u9a8c\u8bc1</li>\n</ul>\n<p>R \u5ba2\u6237\u7aef\u53ef\u4ee5\u76f4\u63a5\u914d\u7f6e kkRepo\uff1a</p>\n<pre><code class=\"language-r\">local({\n  repos &lt;- getOption(\"repos\")\n  repos[\"KKRepo\"] &lt;- \"https://repo.example.com/repository/r-group\"\n  options(repos = repos)\n})\n</code></pre>\n<p>\u7136\u540e\u6b63\u5e38\u4f7f\u7528\uff1a</p>\n<pre><code class=\"language-r\">install.packages(\n  \"acmepkg\",\n  repos = \"https://repo.example.com/repository/r-group\",\n  type = \"source\"\n)\n</code></pre>\n<p>\u5f53\u524d hosted \u548c group \u805a\u7126 source <code>.tar.gz</code> package \uff1b Windows \u3001macOS binary package \u53ef\u4ee5\u901a\u8fc7 proxy \u900f\u4f20\u7f13\u5b58\u3002</p>\n<h3>2. Go \u4ed3\u5e93\u8865\u9f50 Hosted \u80fd\u529b</h3>\n<p>\u6b64\u524d kkRepo \u7684 Go \u4ed3\u5e93\u4e3b\u8981\u7528\u4e8e proxy \u548c group \u3002v1.0.0 \u589e\u52a0\u4e86\u5b8c\u6574\u7684 Go hosted repository \uff0c\u53ef\u4ee5\u6b63\u5f0f\u6258\u7ba1\u4f01\u4e1a\u5185\u90e8 Go Module \u3002</p>\n<p>\u4e0a\u4f20\u4e00\u4e2a\u89c4\u8303\u7684 Module ZIP \u540e\uff0ckkRepo \u4f1a\u5728\u540c\u4e00\u4e2a\u6570\u636e\u5e93\u4e8b\u52a1\u4e2d\u751f\u6210\u5e76\u53d1\u5e03\uff1a</p>\n<ul>\n<li><code>.mod</code></li>\n<li><code>.info</code></li>\n<li><code>.zip</code></li>\n</ul>\n<p>\u8fd9\u6837\u5373\u4f7f\u90e8\u7f72\u4e86\u591a\u4e2a\u526f\u672c\uff0c\u5ba2\u6237\u7aef\u4e5f\u4e0d\u4f1a\u8bfb\u53d6\u5230\u53ea\u53d1\u5e03\u4e86\u4e00\u90e8\u5206\u7684 Module Version \u3002</p>\n<p>Go hosted \u8fd8\u652f\u6301\uff1a</p>\n<ul>\n<li>Module Path \u3001Version \u3001ZIP Root \u548c <code>go.mod</code> \u6821\u9a8c</li>\n<li><code>DENY</code>\u3001<code>ALLOW_ONCE</code> \u548c <code>ALLOW</code> \u5199\u5165\u7b56\u7565</li>\n<li>Admin UI \u548c Components API \u4e0a\u4f20</li>\n<li>Cleanup Policy</li>\n<li>\u5236\u54c1\u5b89\u5168\u626b\u63cf\u548c\u4e0b\u8f7d\u963b\u65ad</li>\n<li>Nexus Go Hosted \u6570\u636e\u8fc1\u79fb</li>\n<li>Hosted \u4e0e\u591a\u4e2a Proxy \u7ec4\u6210\u7edf\u4e00 Group</li>\n<li>\u771f\u5b9e <code>go list</code>\u3001<code>go mod download</code> \u548c <code>go mod verify</code> \u9a8c\u8bc1</li>\n</ul>\n<p>\u5ba2\u6237\u7aef\u53ea\u9700\u8981\u628a <code>GOPROXY</code> \u6307\u5411 group\uff1a</p>\n<pre><code class=\"language-bash\">go env -w GOPROXY=https://repo.example.com/repository/go-group/,direct\n</code></pre>\n<h3>3. \u65b0\u589e\u591a\u5957 UI \u4e3b\u9898</h3>\n<p>Admin \u3001Browse \u548c\u767b\u5f55\u9875\u9762\u73b0\u5728\u652f\u6301\u7edf\u4e00\u5207\u6362\u4e3b\u9898\u3002</p>\n<p>v1.0.0 \u5185\u7f6e\uff1a</p>\n<ul>\n<li>kkRepo Original</li>\n<li>Indigo</li>\n<li>Ocean</li>\n<li>Sunset</li>\n<li>JFrog-inspired</li>\n<li>Nexus-inspired</li>\n</ul>\n<p>\u4e3b\u9898\u8bbe\u7f6e\u4fdd\u5b58\u5728\u6570\u636e\u5e93\u4e2d\uff0c\u591a\u526f\u672c\u4e4b\u95f4\u4fdd\u6301\u4e00\u81f4\u3002</p>\n<p>\u7ba1\u7406\u5458\u53ef\u4ee5\u5728\u4fdd\u5b58\u524d\u5b9e\u65f6\u9884\u89c8\u4e3b\u9898\uff0c\u914d\u7f6e\u5f02\u5e38\u65f6\u4e5f\u4f1a\u5b89\u5168\u56de\u9000\u5230\u9ed8\u8ba4\u6837\u5f0f\u3002\u5347\u7ea7\u7528\u6237\u9ed8\u8ba4\u7ee7\u7eed\u4f7f\u7528\u539f\u6765\u7684 kkRepo \u8bbe\u8ba1\uff0c\u4e0d\u4f1a\u56e0\u4e3a\u5347\u7ea7\u7a81\u7136\u6539\u53d8\u754c\u9762\u3002</p>\n<h3>4. PyPI Proxy \u652f\u6301\u81ea\u5b9a\u4e49\u8fdc\u7a0b Index Path</h3>\n<p>\u8fc7\u53bb PyPI Proxy \u9ed8\u8ba4\u5047\u8bbe\u4e0a\u6e38\u7d22\u5f15\u4f4d\u4e8e <code>/simple</code>\uff0c\u4f46 PyTorch \u7b49\u4ed3\u5e93\u7684 Package Index \u53ef\u80fd\u76f4\u63a5\u4f4d\u4e8e Remote URL \u6839\u8def\u5f84\u3002</p>\n<p>v1.0.0 \u65b0\u589e <code>Remote Index Path</code>\uff1a</p>\n<ul>\n<li>\u666e\u901a PyPI \u4fdd\u6301 <code>/simple</code></li>\n<li>\u4e0a\u6e38 URL \u672c\u8eab\u5c31\u662f Index Root \u65f6\u53ef\u4ee5\u7559\u7a7a</li>\n<li>\u4e5f\u53ef\u4ee5\u914d\u7f6e <code>/api/simple</code> \u7b49\u81ea\u5b9a\u4e49\u8def\u5f84</li>\n<li>\u5ba2\u6237\u7aef\u8bbf\u95ee kkRepo \u7684\u5730\u5740\u4ecd\u4fdd\u6301 <code>/repository/&lt;repo&gt;/simple</code></li>\n</ul>\n<p>\u4f8b\u5982\u4ee3\u7406 PyTorch CPU Index \u65f6\uff0c\u53ef\u4ee5\u628a Remote URL \u914d\u7f6e\u4e3a\uff1a</p>\n<pre><code class=\"language-text\">https://download.pytorch.org/whl/cpu/\n</code></pre>\n<p>\u7136\u540e\u5c06 Remote Index Path \u7559\u7a7a\u3002</p>\n<p>\u73b0\u6709 PyPI Proxy \u5347\u7ea7\u540e\u4ecd\u7136\u4fdd\u7559 <code>/simple</code>\uff0c\u539f\u6709\u884c\u4e3a\u4e0d\u4f1a\u6539\u53d8\u3002</p>\n<h3>5. \u4e00\u6279\u517c\u5bb9\u6027\u548c\u4f7f\u7528\u4f53\u9a8c\u4fee\u590d</h3>\n<p>v1.0.0 \u8fd8\u4fee\u590d\u548c\u4f18\u5316\u4e86\uff1a</p>\n<ul>\n<li>Maven Release \u3001Snapshot \u548c Timestamped Snapshot \u5728 Browse \u4e2d\u5220\u9664\u540e\uff0c\u80fd\u591f\u6b63\u786e\u91cd\u5efa\u5bf9\u5e94 metadata</li>\n<li>PyPI Hosted \u53ef\u4ee5\u63a5\u6536\u5305\u542b\u5927\u91cf metadata \u5b57\u6bb5\u7684 Twine multipart \u4e0a\u4f20</li>\n<li>MySQL \u5168\u5c40\u641c\u7d22\u4e0d\u4f1a\u518d\u56e0\u4e3a <code>com</code> \u7b49 InnoDB Stopword \u4e22\u5931\u6709\u6548\u7ed3\u679c</li>\n<li>\u4e0a\u4f20\u9875\u9762\u6839\u636e\u4ed3\u5e93\u80fd\u529b\u5c55\u793a\u76ee\u5f55\u3001\u6587\u4ef6\u540d\u548c\u591a\u6587\u4ef6\u63a7\u4ef6</li>\n<li>NuGet \u3001RubyGems \u7b49\u683c\u5f0f\u7ee7\u7eed\u4fdd\u6301\u4e25\u683c\u7684\u5355\u6587\u4ef6\u4e0a\u4f20</li>\n<li>Browse \u641c\u7d22\u5bfc\u822a\u3001\u683c\u5f0f\u9009\u62e9\u3001\u4fa7\u680f\u6eda\u52a8\u548c\u5305\u8be6\u60c5\u5e03\u5c40\u5f97\u5230\u4f18\u5316</li>\n<li>Admin \u4e0e Browse \u4f7f\u7528\u7edf\u4e00\u7684\u6eda\u52a8\u6761\u6837\u5f0f</li>\n<li>\u4ed3\u5e93\u8bf7\u6c42\u8def\u7531\u6539\u4e3a fail-closed \u7684\u534f\u8bae Handler SPI \uff0c\u4e3a\u540e\u7eed\u6269\u5c55\u65b0\u683c\u5f0f\u63d0\u4f9b\u7edf\u4e00\u8fb9\u754c</li>\n</ul>\n<h2>\u73b0\u6709\u6838\u5fc3\u80fd\u529b</h2>\n<p>\u9664\u4e86\u4ed3\u5e93\u683c\u5f0f\uff0ckkRepo \u76ee\u524d\u8fd8\u652f\u6301\uff1a</p>\n<ul>\n<li>Nexus \u5b58\u91cf\u4ed3\u5e93\u3001\u5236\u54c1\u3001\u7528\u6237\u3001\u89d2\u8272\u548c\u6743\u9650\u8fc1\u79fb</li>\n<li>Local \u3001LDAP \u3001OIDC \u8ba4\u8bc1</li>\n<li>\u533f\u540d\u8bbf\u95ee\u7b56\u7565\u548c\u7ec6\u7c92\u5ea6\u6743\u9650\u7ba1\u7406</li>\n<li>\u5e26\u6743\u9650\u6821\u9a8c\u7684\u5168\u5c40\u5236\u54c1\u641c\u7d22</li>\n<li>CycloneDX SBOM \u548c\u6f0f\u6d1e\u626b\u63cf</li>\n<li>\u5b89\u5168\u7b56\u7565\u3001\u8c41\u514d\u548c\u53ef\u9009\u4e0b\u8f7d\u963b\u65ad</li>\n<li>\u9762\u5411\u5168\u90e8\u4ed3\u5e93\u683c\u5f0f\u7684 Cleanup Policy</li>\n<li>Prometheus \u6307\u6807\u548c Grafana \u9762\u677f</li>\n<li>MySQL \u6216 PostgreSQL \u5143\u6570\u636e\u5b58\u50a8</li>\n<li>OSS \u3001S3 \u548c File blob storage</li>\n<li>JVM \u4e0e GraalVM Native \u4e24\u79cd\u8fd0\u884c\u65f6</li>\n<li>\u591a\u526f\u672c\u9ad8\u53ef\u7528\u90e8\u7f72</li>\n<li>\u6309\u4ed3\u5e93\u914d\u7f6e HTTP \u6216 SOCKS5 \u51fa\u7ad9\u4ee3\u7406</li>\n</ul>\n<p>Native \u7248\u672c\u901a\u5e38\u7ea6 1 \u79d2\u542f\u52a8\u5c31\u7eea\uff0c\u5185\u5b58\u5360\u7528\u4f4e\u4e8e 200 MB \u3002</p>\n<h2>\u5feb\u901f\u4f53\u9a8c</h2>\n<p>\u673a\u5668\u4e0a\u5b89\u88c5\u597d Docker \u4e0e Docker Compose \u540e\u6267\u884c\uff1a</p>\n<pre><code class=\"language-bash\">curl -fsSL https://raw.githubusercontent.com/klboke/kkrepo/main/scripts/quickstart.sh | bash\n</code></pre>\n<p>\u4f7f\u7528 PostgreSQL\uff1a</p>\n<pre><code class=\"language-bash\">curl -fsSL https://raw.githubusercontent.com/klboke/kkrepo/main/scripts/quickstart.sh | KKREPO_DATABASE_TYPE=postgresql bash\n</code></pre>\n<p>\u542f\u52a8 Native \u7248\u672c\uff1a</p>\n<pre><code class=\"language-bash\">curl -fsSL https://raw.githubusercontent.com/klboke/kkrepo/main/scripts/quickstart.sh | KKREPO_RUNTIME=native bash\n</code></pre>\n<p>\u542f\u52a8\u540e\u8bbf\u95ee\uff1a</p>\n<ul>\n<li>\u7ba1\u7406\u63a7\u5236\u53f0\uff1a<code>http://127.0.0.1:19090/admin/</code></li>\n<li>\u7528\u6237\u4fa7\u6d4f\u89c8\u5668\uff1a<code>http://127.0.0.1:19090/browse/</code></li>\n<li>\u5065\u5eb7\u68c0\u67e5\uff1a<code>http://127.0.0.1:19091/actuator/health</code></li>\n</ul>\n<p>\u9996\u6b21\u8fdb\u5165\u9875\u9762\u65f6\uff0c\u5728 UI \u4e2d\u521b\u5efa <code>Local/admin</code> \u7ba1\u7406\u5458\u5bc6\u7801\u3002</p>\n<p>Quickstart \u9ed8\u8ba4\u4f7f\u7528 File blob storage \uff0c\u9002\u5408\u672c\u5730\u8bd5\u7528\uff1b\u751f\u4ea7\u73af\u5883\u5efa\u8bae\u4f7f\u7528\u72ec\u7acb\u7684 MySQL/PostgreSQL \u548c OSS/S3 \uff0c\u5e76\u66ff\u6362\u9ed8\u8ba4\u52a0\u5bc6\u5bc6\u94a5\u3002</p>\n<h2>\u5bb9\u5668\u955c\u50cf</h2>\n<p>JVM\uff1a</p>\n<pre><code class=\"language-text\">ghcr.io/klboke/kkrepo:1.0.0\nghcr.io/klboke/kkrepo:latest\n</code></pre>\n<p>Native\uff1a</p>\n<pre><code class=\"language-text\">ghcr.io/klboke/kkrepo:1.0.0-native\nghcr.io/klboke/kkrepo:native-latest\n</code></pre>\n<p>\u5b89\u5168\u626b\u63cf\u5668\uff1a</p>\n<pre><code class=\"language-text\">ghcr.io/klboke/kkrepo-scanner:1.0.0\n</code></pre>\n<p>\u6240\u6709\u53d1\u884c\u955c\u50cf\u5747\u652f\u6301 Linux AMD64 \u548c ARM64 \u3002</p>\n<p>GitHub Release \u540c\u65f6\u63d0\u4f9b JVM \u538b\u7f29\u5305\u3001AMD64/ARM64 Native \u538b\u7f29\u5305\u4ee5\u53ca\u7edf\u4e00\u7684 SHA-256 \u6821\u9a8c\u6587\u4ef6\u3002</p>\n<h2>\u4ece v0.9.0 \u5347\u7ea7</h2>\n<p>\u73b0\u6709 v0.9.0 MySQL \u548c PostgreSQL \u90e8\u7f72\u53ef\u4ee5\u901a\u8fc7 Flyway V49\u2013V50 \u539f\u5730\u5347\u7ea7\u3002</p>\n<p>\u5347\u7ea7\u524d\u8bf7\u6ce8\u610f\uff1a</p>\n<ol>\n<li>\u540c\u65f6\u5907\u4efd\u5173\u7cfb\u6570\u636e\u5e93\u548c blob store \u3002</li>\n<li>\u7b49\u5f85 Flyway \u8fc1\u79fb\u5b8c\u6210\u540e\u518d\u6062\u590d\u4e1a\u52a1\u6d41\u91cf\u3002</li>\n<li>\u65b0 schema \u5e94\u7528\u540e\uff0c\u4e0d\u8981\u6df7\u5408\u8fd0\u884c v0.9.0 \u548c v1.0.0 \u5b9e\u4f8b\u3002</li>\n<li>\u65b0\u7684 R/CRAN \u4ed3\u5e93\u4e0d\u4f1a\u81ea\u52a8\u521b\u5efa\uff0c\u9700\u8981\u7ba1\u7406\u5458\u624b\u52a8\u914d\u7f6e\u3002</li>\n<li>\u73b0\u6709 PyPI Proxy \u5728\u672a\u914d\u7f6e Remote Index Path \u65f6\u7ee7\u7eed\u4f7f\u7528 <code>/simple</code>\u3002</li>\n<li>\u73b0\u6709 Go Proxy \u548c Group \u884c\u4e3a\u4fdd\u6301\u4e0d\u53d8\uff0c\u53ea\u6709\u663e\u5f0f\u521b\u5efa\u6216\u52a0\u5165 Go Hosted \u6210\u5458\u540e\u624d\u4f1a\u542f\u7528\u65b0\u7684 Hosted \u80fd\u529b\u3002</li>\n</ol>\n<h2>\u6700\u540e</h2>\n<p>\u4ece Maven \u3001npm \u3001PyPI \uff0c\u5230 Docker \u3001Conda \u3001APT \u3001Conan \u3001Alpine \u3001R/CRAN \u548c Hugging Face Models \uff0ckkRepo \u6b63\u5728\u9010\u6b65\u8865\u9f50\u4e00\u5957\u771f\u6b63\u5f00\u6e90\u3001\u53ef\u8fc1\u79fb\u3001\u652f\u6301\u591a\u526f\u672c\u90e8\u7f72\u7684\u5236\u54c1\u4ed3\u5e93\u65b9\u6848\u3002</p>\n<p>\u5982\u679c\u4f60\u6b63\u5728\u4f7f\u7528 Nexus \uff0c\u6b22\u8fce\u62ff\u771f\u5b9e\u4ed3\u5e93\u3001\u771f\u5b9e\u5ba2\u6237\u7aef\u548c\u5b9e\u9645 CI \u6d41\u7a0b\u6d4b\u8bd5 kkRepo \u3002</p>\n<p>\u9047\u5230\u517c\u5bb9\u6027\u95ee\u9898\u6216\u8005\u5e0c\u671b\u652f\u6301\u65b0\u7684\u4ed3\u5e93\u683c\u5f0f\uff0c\u53ef\u4ee5\u76f4\u63a5\u63d0\u4ea4 Issue\uff1a</p>\n<p><a href=\"https://github.com/klboke/kkRepo/issues\" rel=\"nofollow\">https://github.com/klboke/kkRepo/issues</a></p>\n<p>\u5982\u679c\u9879\u76ee\u5bf9\u4f60\u6709\u5e2e\u52a9\uff0c\u4e5f\u6b22\u8fce Star \u3001\u53cd\u9988\u548c\u53c2\u4e0e\u8d21\u732e\u3002</p>\n"
    }, 
    {
      "author": {
        "url": "https://www.v2ex.com/member/konglizhi3362", 
        "name": "konglizhi3362", 
        "avatar": "https://cdn.v2ex.com/avatar/688d/f13f/529346_large.png?m=1787804853"
      }, 
      "url": "https://www.v2ex.com/t/1237579", 
      "title": "\u4e0d\u60f3\u5199\u4ee3\u7801\uff0c\u4f46\u60f3\u8981\u96c6\u6210\u4e00\u4e2a\u767b\u5f55\u9875\u9762\uff1f Sa-Token-Quick-Login \u5e2e\u4f60\u5b9e\u73b0\uff01", 
      "id": "https://www.v2ex.com/t/1237579", 
      "date_published": "2026-08-27T04:27:42+00:00", 
      "content_html": "<h2>\u4e00\u3001\u89e3\u51b3\u4ec0\u4e48\u95ee\u9898</h2>\n<p>Sa-Token-Quick-Login \u53ef\u4ee5\u4e3a\u4e00\u4e2a\u7cfb\u7edf\u5feb\u901f\u7684\u3001\u96f6\u4ee3\u7801 \u6ce8\u5165\u4e00\u4e2a\u767b\u5f55\u9875\u9762\u3002</p>\n<p>\u8bd5\u60f3\u4e00\u4e0b\uff0c\u5047\u5982\u6211\u4eec\u5f00\u53d1\u4e86\u4e00\u4e2a\u975e\u5e38\u7b80\u5355\u7684\u5c0f\u7cfb\u7edf\uff0c\u6bd4\u5982\u8bf4\uff1a\u670d\u52a1\u5668\u6027\u80fd\u76d1\u63a7\u9875\u9762\uff0c\n\u6211\u4eec\u5c06\u5b83\u90e8\u7f72\u5728\u670d\u52a1\u5668\u4e0a\uff0c\u901a\u8fc7\u8bbf\u95ee\u8fd9\u4e2a\u9875\u9762\uff0c\u6211\u4eec\u53ef\u4ee5\u968f\u65f6\u4e86\u89e3\u670d\u52a1\u5668\u6027\u80fd\u4fe1\u606f\uff0c\u975e\u5e38\u65b9\u4fbf\u3002</p>\n<p>\u7136\u800c\uff0c\u8fd9\u4e2a\u9875\u9762\u65b9\u4fbf\u6211\u4eec\u7684\u540c\u65f6\uff0c\u4e5f\u65b9\u4fbf\u4e86\u4e00\u4e9b\u4e0d\u6cd5\u7684\u653b\u51fb\u8005\uff0c\u7531\u4e8e\u8fd9\u4e2a\u9875\u9762\u6beb\u65e0\u9632\u62a4\u7684\u66b4\u9732\u5728\u516c\u7f51\u4e2d\uff0c\u4efb\u4f55\u4e00\u53f0\u5b89\u88c5\u4e86\u6d4f\u89c8\u5668\u7684\u7535\u8111\u90fd\u53ef\u4ee5\u968f\u65f6\u8bbf\u95ee\u5b83\uff01</p>\n<p>\u4e3a\u6b64\uff0c\u6211\u4eec\u5fc5\u987b\u7ed9\u8fd9\u4e2a\u7cfb\u7edf\u52a0\u4e0a\u4e00\u4e2a\u767b\u5f55\u8ba4\u8bc1\uff0c\u53ea\u6709\u77e5\u6653\u4e86\u540e\u53f0\u5bc6\u7801\u7684\u4eba\u5458\u624d\u53ef\u4ee5\u8fdb\u884c\u8bbf\u95ee\u3002</p>\n<p>\u7ec6\u7ec6\u60f3\u6765\uff0c\u5b8c\u6210\u8fd9\u4e2a\u529f\u80fd\u4f60\u9700\u8981\uff1a</p>\n<ol>\n<li>\u7f16\u5199\u524d\u7aef\u767b\u5f55\u9875\u9762\uff0c\u624b\u5199\u5404\u79cd\u8868\u5355\u6837\u5f0f</li>\n<li>\u5bfb\u627e\u5408\u9002\u7684 ajax \u7c7b\u5e93\uff0c<code>jQuery</code>\uff1f<code>Axios</code>\uff1f\u8fd8\u662f\u76f4\u63a5\u524d\u540e\u53f0\u4e0d\u5206\u79bb\uff1f</li>\n<li>\u5bfb\u627e\u5408\u9002\u7684\u6a21\u677f\u5f15\u64ce\uff0c\u6bd4\u5982<code>jsp</code>\u3001<code>Thymeleaf</code>\u3001<code>FreeMarker</code>\u3001<code>Velocity</code>\u2026\u2026\u9009\u54ea\u4e2a\u5462\uff1f</li>\n<li>\u5904\u7406\u540e\u53f0\u5404\u79cd\u62e6\u622a\u8ba4\u8bc1\u903b\u8f91\uff0c\u524d\u540e\u53f0\u63a5\u53e3\u5bf9\u63a5</li>\n<li>\u4f60\u53ef\u80fd\u8fd8\u4f1a\u9047\u5230\u4ee4\u4eba\u5934\u75db\u6b32\u88c2\u7684\u6a21\u677f\u5f15\u64ce\u4e2d<code>ContextPath</code>\u5904\u7406</li>\n<li>\u2026\u2026</li>\n</ol>\n<p>\u4f60\u9a6c\u4e0a\u5c31\u4f1a\u53d1\u73b0\uff0c\u5199\u4e2a\u76d1\u63a7\u9875\u4f60\u4e00\u4e0b\u5348\u5c31\u53ef\u4ee5\u641e\u5b9a\uff0c\u7136\u800c\u8fd9\u4e2a\u767b\u5f55\u9875\u4f60\u5374\u53ef\u80fd\u9700\u8981\u82b1\u4e0a\u4e24\u4e09\u5929\u7684\u65f6\u95f4\uff0c\u8fd9\u662f\u4e00\u7b14\u53ca\u5176\u4e0d\u5212\u7b97\u7684\u65f6\u95f4\u6d6a\u8d39</p>\n<p>\u90a3\u4e48\u73b0\u5728\u4f60\u53ef\u80fd\u5c31\u4f1a\u6709\u4e2a\u7591\u95ee\uff0c\u96be\u9053\u5c31\u6ca1\u6709\u4ec0\u4e48\u65b9\u6cd5\u7ed9\u6211\u7684\u5c0f\u9879\u76ee\u5feb\u901f\u589e\u52a0\u4e00\u4e2a\u767b\u5f55\u529f\u80fd\u5417\uff1f</p>\n<p>Sa-Token-Quick-Login \u4fbf\u662f\u4e3a\u4e86\u89e3\u51b3\u8fd9\u4e2a\u95ee\u9898\uff01</p>\n<blockquote>\n<p>Sa-Token \u662f\u4e00\u4e2a\u5f00\u6e90\u3001\u514d\u8d39\u3001\u4e00\u7ad9\u5f0f java \u6743\u9650\u8ba4\u8bc1\u6846\u67b6\u3002\u53ef\u89e3\u51b3\uff1a\u767b\u5f55\u8ba4\u8bc1\u3001\u6743\u9650\u8ba4\u8bc1\u3001\u5fae\u670d\u52a1\u7f51\u5173\u9274\u6743\u3001SSO \u5355\u70b9\u767b\u5f55\u3001OAuth2 \u7edf\u4e00\u8ba4\u8bc1\u3001jwt \u96c6\u6210\u3001API \u53c2\u6570\u7b7e\u540d\u3001API Key \u6388\u6743 \u7b49\u4e00\u7cfb\u5217\u6743\u9650\u76f8\u5173\u95ee\u9898\u3002</p>\n<ul>\n<li>\u5728\u7ebf\u6587\u6863\uff1a<a href=\"https://sa-token.com?way=blog\" rel=\"nofollow\">https://sa-token.com</a></li>\n<li>\u5f00\u6e90\u5730\u5740\uff1a<a href=\"https://gitee.com/dromara/sa-token\" rel=\"nofollow\">https://gitee.com/dromara/sa-token</a></li>\n</ul>\n</blockquote>\n<h2>\u4e8c\u3001\u9002\u7528\u573a\u666f</h2>\n<p>Sa-Token-Quick-Login \u65e8\u5728\u7528\u6700\u5c0f\u7684\u6210\u672c\u4e3a\u9879\u76ee\u589e\u52a0\u4e00\u4e2a\u767b\u5f55\u8ba4\u8bc1\u529f\u80fd</p>\n<ul>\n<li><strong>\u7b80\u5355</strong>\uff1a\u53ea\u9700\u8981\u5f15\u5165\u4e00\u4e2a\u4f9d\u8d56\u4fbf\u53ef\u4e3a\u7cfb\u7edf\u6ce8\u5165\u767b\u5f55\u529f\u80fd\uff0c\u5feb\u901f\u3001\u7b80\u5355\u3001\u96f6\u4ee3\u7801\uff01</li>\n<li><strong>\u4e0d\u53ef\u5b9a\u5236</strong>\uff1a\u7531\u4e8e\u767b\u5f55\u9875\u9762\u4e0d\u53ef\u5b9a\u5236\uff0c\u6240\u4ee5 Sa-Token-Quick-Login \u975e\u5e38\u4e0d\u9002\u5408\u666e\u901a\u9879\u76ee\u7684\u767b\u5f55\u8ba4\u8bc1\u6a21\u5757\uff0cSTQL \u4e5f\u65e0\u610f\u53bb\u89e3\u51b3\u6240\u6709\u9879\u76ee\u7684\u767b\u5f55\u8ba4\u8bc1\u6a21\u5757</li>\n</ul>\n<p>Sa-Token-Quick-Login \u7684\u5b9a\u4f4d\u662f\u8fd9\u6837\u7684\u573a\u666f\uff1a\u4f60\u7684\u9879\u76ee\u9700\u8981\u4e00\u4e2a\u767b\u5f55\u8ba4\u8bc1\u529f\u80fd\u3001\u8fd9\u4e2a\u8ba4\u8bc1\u9875\u9762\u53ef\u4ee5\u4e0d\u534e\u4e3d\u3001\u53ef\u4ee5\u70c2\uff0c\u4f46\u662f\u4e00\u5b9a\u8981\u6709\uff0c\u540c\u65f6\u4f60\u53c8\u4e0d\u60f3\u82b1\u8d39\u592a\u591a\u7684\u65f6\u95f4\u6d6a\u8d39\u5728\u767b\u5f55\u9875\u9762\u4e0a\uff0c\n\u90a3\u4e48\u4f60\u4fbf\u53ef\u4ee5\u5c1d\u8bd5\u4e00\u4e0b<code>Sa-Token-Quick-Login</code></p>\n<h2>\u4e09\u3001\u96c6\u6210\u6b65\u9aa4</h2>\n<p>\u9996\u5148\u6211\u4eec\u9700\u8981\u521b\u5efa\u4e00\u4e2a SpringBoot \u7684 demo \u9879\u76ee\uff0c\u6bd4\u5982\uff1a<code>sa-token-demo-quick-login</code></p>\n<h3>1 \u3001\u6dfb\u52a0 pom \u4f9d\u8d56</h3>\n<pre><code class=\"language-xml\">&lt;!-- Sa-Token \u6743\u9650\u8ba4\u8bc1, \u5728\u7ebf\u6587\u6863\uff1a https://sa-token.com --&gt;\n&lt;dependency&gt;\n    &lt;groupId&gt;cn.dev33&lt;/groupId&gt;\n    &lt;artifactId&gt;sa-token-spring-boot-starter&lt;/artifactId&gt;\n    &lt;version&gt;1.46.0&lt;/version&gt;\n&lt;/dependency&gt;\n\n&lt;!-- Sa-Token-Quick-Login \u63d2\u4ef6\u4f9d\u8d56 --&gt;\n&lt;dependency&gt;\n    &lt;groupId&gt;cn.dev33&lt;/groupId&gt;\n    &lt;artifactId&gt;sa-token-quick-login&lt;/artifactId&gt;\n    &lt;version&gt;1.46.0&lt;/version&gt;\n&lt;/dependency&gt;\n</code></pre>\n<p>Gradle \u65b9\u5f0f\uff1a</p>\n<pre><code class=\"language-gradle\">// Sa-Token \u6743\u9650\u8ba4\u8bc1\uff0c\u5728\u7ebf\u6587\u6863\uff1a https://sa-token.com\nimplementation 'cn.dev33:sa-token-spring-boot-starter:1.46.0'\n\n// Sa-Token-Quick-Login \u63d2\u4ef6\nimplementation 'cn.dev33:sa-token-quick-login:1.46.0'\n</code></pre>\n<p>\u6ce8\uff1aSpringBoot 3.x \u8bf7\u6539\u7528 <code>sa-token-spring-boot3-starter</code>\uff0cSpringBoot 4.x \u8bf7\u6539\u7528 <code>sa-token-spring-boot4-starter</code>\u3002<code>sa-token-quick-login</code> \u63d2\u4ef6\u672c\u8eab\u4e0d\u7528\u6362\u3002</p>\n<h3>2 \u3001\u542f\u52a8\u7c7b</h3>\n<pre><code class=\"language-java\">@SpringBootApplication\npublic class SaTokenQuickDemoApplication {\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(SaTokenQuickDemoApplication.class, args);\n\t}\n}\n</code></pre>\n<p>\u542f\u52a8\u6210\u529f\u540e\uff0c\u53ef\u4ee5\u7528 <code>CommandLineRunner</code> \u628a\u9ed8\u8ba4\u8d26\u53f7\u5bc6\u7801\u6253\u5370\u5230\u63a7\u5236\u53f0\uff0c\u65b9\u4fbf\u6d4b\u8bd5\uff1a</p>\n<pre><code class=\"language-java\">@Component\npublic class SaQuickStartup implements CommandLineRunner {\n\n\t@Value(\"${server.port:8080}\")\n\tprivate String port;\n\n\t@Override\n\tpublic void run(String... args) {\n\t\tSystem.out.println(\"\\n------ \u542f\u52a8\u6210\u529f ------\");\n\t\tSystem.out.println(\"home: http://localhost:\" + port);\n\t\tSystem.out.println(\"name: \" + SaQuickManager.getConfig().getName());\n\t\tSystem.out.println(\"pwd:  \" + SaQuickManager.getConfig().getPwd());\n\t}\n}\n</code></pre>\n<h3>3 \u3001\u65b0\u5efa\u6d4b\u8bd5 Controller</h3>\n<pre><code class=\"language-java\">/**\n * \u6d4b\u8bd5\u4e13\u7528 Controller \n */\n@RestController\npublic class TestController {\n\t// \u6d4f\u89c8\u5668\u8bbf\u95ee\u6d4b\u8bd5\uff1a http://localhost:8081\n\t@RequestMapping(\"/\")\n\tpublic String index() {\n\t\tString str = \"&lt;br /&gt;\"\n\t\t\t\t+ \"&lt;h1 style='text-align: center;'&gt;\u8d44\u6e90\u9875 \uff08\u767b\u5f55\u540e\u624d\u53ef\u8fdb\u5165\u672c\u9875\u9762\uff09 &lt;/h1&gt;\"\n\t\t\t\t+ \"&lt;hr/&gt;\"\n\t\t\t\t+ \"&lt;p style='text-align: center;'&gt; Sa-Token \" + SaTokenConsts.VERSION_NO + \" &lt;/p&gt;\";\n\t\treturn str;\n\t}\n}\n</code></pre>\n<p><strong>\u6ce8\uff1a</strong>\u793a\u4f8b\u6e90\u7801\u5728\u5b98\u65b9\u4ed3\u5e93 <code>/sa-token-demo/sa-token-demo-quick-login</code> \u76ee\u5f55\u4e0b\uff0cSpringBoot 3 \u793a\u4f8b\u5728 <code>/sa-token-demo/sa-token-demo-quick-login-sb3</code>\uff0c\u53ef\u7ed3\u5408\u6e90\u7801\u67e5\u770b\u5b66\u4e60\u3002<a href=\"https://sa-token.com/doc.html?way=blog#/more/download-demos\" rel=\"nofollow\">Sa-Token \u96c6\u6210\u793a\u4f8b\u5927\u5168\u4e0b\u8f7d</a></p>\n<h2>\u56db\u3001\u6d4b\u8bd5\u8bbf\u95ee</h2>\n<p>\u542f\u52a8\u9879\u76ee\uff0c\u4f7f\u7528\u6d4f\u89c8\u5668\u8bbf\u95ee\uff1a<code>http://localhost:8081</code>\uff0c\u9996\u6b21\u8bbf\u95ee\u65f6\uff0c\u7531\u4e8e\u5904\u4e8e\u672a\u767b\u5f55\u72b6\u6001\uff0c\u4f1a\u88ab\u5f3a\u5236\u8fdb\u5165\u767b\u5f55\u9875\u9762</p>\n<p><img alt=\"\u767b\u5f55\" class=\"embedded_image\" loading=\"lazy\" referrerpolicy=\"no-referrer\" rel=\"noreferrer\" src=\"https://res.dev33.cn/sa-token-blog/img/2023-4/sa-quick-login.png\"/></p>\n<p>\u4f7f\u7528\u9ed8\u8ba4\u8d26\u53f7\uff1a<code>sa / 123456</code>\u8fdb\u884c\u767b\u5f55\uff0c\u4f1a\u770b\u5230\u8d44\u6e90\u9875\u9762</p>\n<p><img alt=\"\u767b\u5f55\" class=\"embedded_image\" loading=\"lazy\" referrerpolicy=\"no-referrer\" rel=\"noreferrer\" src=\"https://res.dev33.cn/sa-token-blog/img/2023-4/sa-quick-login-index.png\"/></p>\n<p>\u4e5f\u53ef\u4ee5\u901a\u8fc7 Http Basic \u7684\u65b9\u5f0f\u76f4\u63a5\u8fdb\u884c\u8ba4\u8bc1\uff08\u4e00\u822c\u9700\u8981\u5728\u4e13\u95e8\u7684 API \u6d4b\u8bd5\u5de5\u5177\u4e0b\u624d\u80fd\u6b63\u5e38\u6d4b\u8bd5\uff0c\u6d4f\u89c8\u5668\u4f1a\u81ea\u52a8\u5ffd\u7565 <code>@</code> \u4e4b\u524d\u7684\u4fe1\u606f\uff09\uff1a</p>\n<pre><code class=\"language-url\">http://sa:123456@localhost:8081/\n</code></pre>\n<h2>\u4e94\u3001\u53ef\u914d\u7f6e\u4fe1\u606f</h2>\n<p>\u4f60\u53ef\u4ee5\u5728 yml \u4e2d\u6dfb\u52a0\u5982\u4e0b\u914d\u7f6e (\u6240\u6709\u914d\u7f6e\u90fd\u662f\u53ef\u9009\u7684) </p>\n<pre><code class=\"language-yaml\"># Sa-Token-Quick-Login \u914d\u7f6e\nsa:\n    # \u767b\u5f55\u8d26\u53f7\n    name: sa\n    # \u767b\u5f55\u5bc6\u7801\n    pwd: 123456\n    # \u662f\u5426\u81ea\u52a8\u968f\u673a\u751f\u6210\u8d26\u53f7\u5bc6\u7801 (\u6b64\u9879\u4e3a true \u65f6, name \u4e0e pwd \u5931\u6548)\n    auto: false\n    # \u662f\u5426\u5f00\u542f\u5168\u5c40\u8ba4\u8bc1(\u5173\u95ed\u540e\u5c06\u4e0d\u518d\u5f3a\u884c\u62e6\u622a)\n    auth: true\n    # \u767b\u5f55\u9875\u6807\u9898\n    title: Sa-Token \u767b\u5f55\n    # \u662f\u5426\u663e\u793a\u5e95\u90e8\u7248\u6743\u4fe1\u606f\n    copr: true\n    # \u6307\u5b9a\u62e6\u622a\u8def\u5f84\n    # include: /**\n    # \u6307\u5b9a\u6392\u9664\u8def\u5f84\n    # exclude: /1.jpg\n    # \u5c06\u672c\u5730\u78c1\u76d8\u7684\u67d0\u4e2a\u8def\u5f84\u4f5c\u4e3a\u9759\u6001\u8d44\u6e90\u5f00\u653e\n    # dir: file:E:\\static\n</code></pre>\n<h2>\u516d\u3001\u4f7f\u7528\u72ec\u7acb jar \u5305\u8fd0\u884c</h2>\n<p>\u4f7f\u7528<code>sa-token-quick-login</code>\u53ea\u9700\u5f15\u5165\u4e00\u4e2a\u4f9d\u8d56\u5373\u53ef\u4e3a\u7cfb\u7edf\u6ce8\u5165\u767b\u5f55\u6a21\u5757\uff0c\u73b0\u5728\u6211\u4eec\u66f4\u8fdb\u4e00\u6b65\uff0c\u5c06\u8fd9\u4e2a\u9879\u76ee\u6253\u6210\u4e00\u4e2a\u72ec\u7acb\u7684 jar \u5305\u3002</p>\n<p>\u901a\u8fc7\u8fd9\u4e2a jar \u5305\uff0c\u6211\u4eec\u53ef\u4ee5\u65b9\u4fbf\u7684\u90e8\u7f72\u4efb\u610f\u9759\u6001\u7f51\u7ad9\uff01\u505a\u5230\u771f\u6b63\u7684\u96f6\u7f16\u7801\u6ce8\u5165\u767b\u5f55\u529f\u80fd\u3002</p>\n<h3>\u6253\u5305\u6b65\u9aa4</h3>\n<p>\u9996\u5148\u653e\u4e0a\u61d2\u4eba\u94fe\u63a5\uff1a<a href=\"https://gitee.com/dromara/sa-token/attach_files/\" rel=\"nofollow\">sa-quick-dist.jar</a>\uff0c\u4e0d\u60f3\u624b\u52a8\u64cd\u4f5c\u7684\u540c\u5b66\u53ef\u4ee5\u76f4\u63a5\u5728\u5f00\u6e90\u4ed3\u5e93\u4e0b\u8f7d\u6253\u5305\u540e\u7684 jar \u6587\u4ef6</p>\n<p><code>sa-token-demo</code> \u662f\u72ec\u7acb\u7684\u793a\u4f8b\u5de5\u7a0b\uff0c<code>sa-token-demo-quick-login</code> \u5df2\u5305\u542b\u5728\u5176\u4e2d\uff0c\u76f4\u63a5\u8fdb\u5165\u8be5\u6a21\u5757\u6253\u5305\u5373\u53ef\u3002</p>\n<p>1 \u3001\u8fdb\u5165\u793a\u4f8b\u6a21\u5757\u76ee\u5f55</p>\n<pre><code class=\"language-cmd\">cd sa-token-demo/sa-token-demo-quick-login\n</code></pre>\n<p>2 \u3001\u6267\u884c\u6253\u5305\u547d\u4ee4</p>\n<pre><code class=\"language-cmd\">mvn clean package\n</code></pre>\n<p>3 \u3001\u8fdb\u5165 <code>target</code> \u6587\u4ef6\u5939\uff0c\u627e\u5230\u6253\u5305\u597d\u7684 jar \u6587\u4ef6</p>\n<pre><code class=\"language-cmd\">sa-token-demo-quick-login-0.0.1-SNAPSHOT.jar\n</code></pre>\n<p>4 \u3001\u6211\u4eec\u5c06\u5176\u91cd\u547d\u540d\u4e3a<code>sa-quick-dist.jar</code>\uff0c\u73b0\u5728\u8fd9\u4e2a jar \u5305\u5c31\u662f\u6211\u4eec\u7684\u6700\u7ec8\u7a0b\u5e8f\uff0c\u6211\u4eec\u5728\u8fd9\u4e2a<code>target</code>\u76ee\u5f55\u76f4\u63a5\u8fdb\u5165 cmd \uff0c\u6267\u884c\u5982\u4e0b\u547d\u4ee4\u542f\u52a8 jar \u5305</p>\n<pre><code class=\"language-cmd\">java -jar sa-quick-dist.jar\n</code></pre>\n<p>5 \u3001\u6d4b\u8bd5\u8bbf\u95ee\uff0c\u6839\u636e\u63a7\u5236\u53f0\u8f93\u51fa\u63d0\u793a\uff0c\u6211\u4eec\u4f7f\u7528\u6d4f\u89c8\u5668\u8bbf\u95ee\u6d4b\u8bd5: <code>http://localhost:8080</code></p>\n<p><img alt=\"sa-quick-start\" class=\"embedded_image\" loading=\"lazy\" referrerpolicy=\"no-referrer\" rel=\"noreferrer\" src=\"https://res.dev33.cn/sa-token-blog/img/2023-4/sa-quick-start.png\"/></p>\n<p>\u5982\u679c\u53ef\u4ee5\u8fdb\u5165\u767b\u5f55\u754c\u9762\uff0c\u5219\u4ee3\u8868\u6253\u5305\u8fd0\u884c\u6210\u529f <br/>\n\u5f53\u7136\u4ec5\u4ec5\u8fd0\u884c\u6210\u529f\u8fd8\u4e0d\u591f\uff0c\u4e0b\u9762\u6211\u4eec\u6f14\u793a\u4e00\u4e0b\u5982\u4f55\u4f7f\u7528\u8fd9\u4e2a jar \u5305\u8fdb\u884c\u9759\u6001\u7f51\u7ad9\u90e8\u7f72</p>\n<h2>\u4e03\u3001\u6240\u6709\u529f\u80fd\u793a\u4f8b</h2>\n<h3>Case 1. \u6307\u5b9a\u9759\u6001\u8d44\u6e90\u8def\u5f84</h3>\n<pre><code class=\"language-cmd\">java -jar sa-quick-dist.jar --sa.dir file:E:\\www\n</code></pre>\n<p>\u4f7f\u7528 dir \u53c2\u6570\u6307\u5b9a<code>E:\\www</code>\u76ee\u5f55\u4f5c\u4e3a\u8d44\u6e90\u76ee\u5f55\u8fdb\u884c\u90e8\u7f72 (\u73b0\u5728\u6211\u4eec\u53ef\u4ee5\u901a\u8fc7\u6d4f\u89c8\u5668\u8bbf\u95ee<code>E:\\www</code>\u76ee\u5f55\u4e0b\u7684\u6587\u4ef6\u4e86\uff01)</p>\n<h3>Case 2. \u6307\u5b9a\u767b\u5f55\u540d\u4e0e\u5bc6\u7801</h3>\n<pre><code class=\"language-cmd\">java -jar sa-quick-dist.jar --sa.name=zhang --sa.pwd=zhang123\n</code></pre>\n<p>\u73b0\u5728\uff0c\u9ed8\u8ba4\u7684\u8d26\u53f7<code>sa/123456</code>\u5c06\u88ab\u5e9f\u5f03\uff0c\u800c\u662f\u4f7f\u7528<code>zhang/zhang123</code>\u8fdb\u884c\u8d26\u53f7\u6821\u9a8c</p>\n<h3>Case 3. \u6307\u5b9a\u5176\u81ea\u52a8\u751f\u6210\u8d26\u53f7\u5bc6\u7801</h3>\n<pre><code class=\"language-cmd\">java -jar sa-quick-dist.jar --sa.auto=true\n</code></pre>\n<p>\u6bcf\u6b21\u542f\u52a8\u65f6\u968f\u673a\u751f\u6210\u8d26\u53f7\u5bc6\u7801\uff08\u4f1a\u5728\u542f\u52a8\u6210\u529f\u65f6\u6253\u5370\u5230\u63a7\u5236\u53f0\u4e0a\uff09</p>\n<h3>Case 4. \u6307\u5b9a\u767b\u5f55\u9875\u7684\u6807\u9898</h3>\n<pre><code class=\"language-cmd\">java -jar sa-quick-dist.jar --sa.title=\"XXX \u7cfb\u7edf\u767b\u5f55\"\n</code></pre>\n<h3>Case 5. \u5173\u95ed\u8d26\u53f7\u6821\u9a8c\uff0c\u4ec5\u4f5c\u4e3a\u9759\u6001\u8d44\u6e90\u90e8\u7f72\u4f7f\u7528</h3>\n<pre><code class=\"language-cmd\">java -jar sa-quick-dist.jar --sa.auth=false\n</code></pre>\n<h3>Case 6. \u6307\u5b9a\u542f\u52a8\u7aef\u53e3\uff08\u9ed8\u8ba4 8080 \uff09</h3>\n<pre><code class=\"language-cmd\">java -jar sa-quick-dist.jar --server.port=80 \n</code></pre>\n<p>\u6ce8\uff1a\u6240\u6709\u53c2\u6570\u53ef\u7ec4\u5408\u4f7f\u7528</p>\n<h2>\u516b\u3001\u4f7f\u7528 SpringBoot \u9ed8\u8ba4\u8d44\u6e90\u8def\u5f84</h2>\n<p>SpringBoot \u9ed8\u8ba4\u5f00\u653e\u4e86\u4e00\u4e9b\u8def\u5f84\u4f5c\u4e3a\u8d44\u6e90\u76ee\u5f55\uff0c\u6bd4\u5982<code>classpath:/static/</code>\uff0c\n\u600e\u4e48\u4f7f\u7528\u5462\uff1f\u6211\u4eec\u53ea\u9700\u8981\u5728 jar \u5305\u540c\u76ee\u5f55\u521b\u5efa\u4e00\u4e2a<code>\\static</code>\u6587\u4ef6\u5939\uff0c\u5c06\u9759\u6001\u8d44\u6e90\u6587\u4ef6\u590d\u5236\u5230\u6b64\u76ee\u5f55\u4e0b\uff0c\u7136\u540e\u542f\u52a8 jar \u5305\u5373\u53ef\u8bbf\u95ee</p>\n<p>\u540c\u65f6\uff0c\u6211\u4eec\u8fd8\u53ef\u4ee5\u5728 jar \u5305\u540c\u76ee\u5f55\u521b\u5efa yml \u914d\u7f6e\u6587\u4ef6\uff0c\u6765\u8986\u76d6 jar \u5305\u5185\u7684 yml \u914d\u7f6e\uff0c\u5982\u4e0b\u56fe\u6240\u793a\uff1a</p>\n<p><img alt=\"sa-quick-case.png\" class=\"embedded_image\" loading=\"lazy\" referrerpolicy=\"no-referrer\" rel=\"noreferrer\" src=\"https://res.dev33.cn/sa-token-blog/img/2023-4/sa-quick-case.png\"/></p>\n<p>\u4f8b\u5982\u5982\u4e0a\u76ee\u5f55\u4e2d<code>/static</code>\u4e2d\u6709\u4e00\u4e2a<code>1.jpg</code>\u6587\u4ef6\uff0c\u6211\u4eec\u542f\u52a8 jar \u5305\u540e\u8bbf\u95ee<code>http://localhost:8080/1.jpg</code>\u5373\u53ef\u67e5\u770b\u5230\u6b64\u6587\u4ef6\uff0c\u8fd9\u662f Springboot \u81ea\u5e26\u7684\u529f\u80fd\uff0c\u5728\u6b64\u4e0d\u518d\u8d58\u8ff0</p>\n<hr/>\n<h2>\u53c2\u8003\u8d44\u6599</h2>\n<ul>\n<li>Sa-Token \u6587\u6863\uff1a<a href=\"https://sa-token.com?way=blog\" rel=\"nofollow\">https://sa-token.com</a></li>\n<li>Quick-Login \u6587\u6863\uff1a<a href=\"https://sa-token.com/doc.html?way=blog#/plugin/quick-login\" rel=\"nofollow\">https://sa-token.com/doc.html#/plugin/quick-login</a></li>\n<li>Gitee \u5f00\u6e90\u5730\u5740\uff1a<a href=\"https://gitee.com/dromara/sa-token\" rel=\"nofollow\">https://gitee.com/dromara/sa-token</a></li>\n<li>GitHub \u5f00\u6e90\u5730\u5740\uff1a<a href=\"https://github.com/dromara/sa-token\" rel=\"nofollow\">https://github.com/dromara/sa-token</a></li>\n</ul>\n"
    }, 
    {
      "author": {
        "url": "https://www.v2ex.com/member/eddy666", 
        "name": "eddy666", 
        "avatar": "https://cdn.v2ex.com/gravatar/e4352cb4b82a4e68c5eece259b15ba3d?s=73&d=retro"
      }, 
      "url": "https://www.v2ex.com/t/1237212", 
      "title": "\u5584\u4e8e\u5b66\u4e60\u7684 Java \u540e\u7aef\u670b\u53cb\u4eec\uff0c\u60f3\u8bf7\u6559\u4e0b\u4f60\u662f\u5982\u4f55\u69a8\u5e72\u81ea\u5df1\u7684\u5de5\u4f5c\u9879\u76ee\u7ecf\u9a8c\uff0c\u628a\u5b83\u6c89\u6dc0\u4e0b\u6765\u6162\u6162\u79ef\u6512\u6210\u81ea\u5df1\u7684\u80fd\u529b\u7684\uff1f", 
      "id": "https://www.v2ex.com/t/1237212", 
      "date_published": "2026-08-25T16:00:49+00:00", 
      "content_html": "<p>\u5982\u4f55\u628a\u9879\u76ee\u7ecf\u9a8c\u6c89\u6dc0\u4e0b\u6765\uff1f\n1 \u9047\u5230\u6709\u8da3\u7684\u8bbe\u8ba1\uff0c\u4f1a\u628a\u5b9e\u73b0\u65b9\u6848\uff0c\u81ea\u5df1\u7528\u6d41\u7a0b\u56fe\u7b49 uml \uff0c\u628a\u5b8c\u6574\u7684\u65b9\u6848\uff0c\u81ea\u5df1\u68b3\u7406\u4e00\u904d\u5417\uff1f\n2 \u611f\u89c9\u6709\u5e2e\u52a9\u7684\u4ee3\u7801\u6bb5\u6bd4\u8f83\u6742\uff0c\u81ea\u5df1\u8bb0\u5f55\u5f97\u6bd4\u8f83\u6563\u3002\u6709\u65f6\u5019\u8bb0\u5b8c\u4e86\uff0c\u81ea\u5df1\u4e5f\u627e\u4e0d\u5230\uff0c\u8fd8\u4e0d\u5982\u641c\u7d22\u5f15\u64ce\u67e5\u7684\u5feb\u3002\u4f46\u662f\u6709\u4e9b\u516c\u53f8\u5185\u7684\u5c01\u88c5\u7684\u6846\u67b6\uff0c\u8fd9\u4e9b\u597d\u7684\u4ee3\u7801\u6bb5\uff0c\u662f\u516c\u7f51\u4e0a\u9762\u641c\u7d22\u4e0d\u5230\u7684\u3002</p>\n<p>3 \u77e5\u8bc6\u7ba1\u7406\u7684\u95ee\u9898\uff1a\u81ea\u5df1\u628a\u6280\u672f\u7ecf\u9a8c\u8bb0\u5f55\u4e0b\u6765\uff0c\u90a3\u4e48\u5982\u4f55\u7ba1\u7406\u5b83\uff0c\u5728\u81ea\u5df1\u9700\u8981\u65f6\uff0c\u5982\u4f55\u5feb\u901f\u627e\u5230\u7684\u3002\u5982\u679c\u8bf4\u7528\u6807\u7b7e\u7ba1\u7406\u7684\u8bdd\uff0c\u5982\u4f55\u6253\u6807\u7b7e\uff1f\u50cf\u8fd9\u6837\u4e09\u4e2a\u7ef4\u5ea6\uff1f\u5927\u5bb6\u6709\u6ca1\u6709\u4ec0\u4e48\u597d\u7684\u7ba1\u7406\u8f6f\u4ef6\uff0c\u597d\u7684\u5b9e\u8df5\u63a8\u8350\u7684\uff1f\n\uff08\u6211\u66fe\u7ecf\u60f3\u8fc7\u7528\u77e5\u8bc6\u5361+\u6253\u6807\u7b7e\u7684\u65b9\u5f0f\uff0c\u4f46\u56e0\u4e3a\u6ca1\u6709\u53cd\u9988\u6ca1\u575a\u6301\u4e0b\u6765\uff09\n3-1 \u6309\u7167\u6280\u672f\u6808\u7ef4\u5ea6\uff1a\u6570\u636e\u5e93,java \uff0cspring \uff0c\u4e2d\u95f4\u4ef6(redis,mq)\uff0c\u8ba1\u7b97\u673a\u57fa\u7840\uff0c\u7f51\u7edc\uff0c\u8bbe\u8ba1\u6a21\u5f0f\n3-2 \u5143\u7d20\u7ef4\u5ea6\uff1a\u6280\u672f\u65b9\u6848\uff0c\u4ee3\u7801\u6bb5\uff0c\u7b97\u6cd5\uff0c\u67b6\u6784\u8bbe\u8ba1\uff0c\u529f\u80fd\u8bbe\u8ba1\n3-3 \u529f\u80fd\u7ef4\u5ea6\uff1a\u4e1a\u52a1\u529f\u80fd\u5b9e\u73b0\uff0c\u9ad8\u5e76\u53d1\uff0c\u9ad8\u53ef\u7528\uff0c\u9ad8\u6027\u80fd</p>\n<p>4 \u597d\u7684\u5de5\u4f5c\u6d41\u7a0b\u5927\u5bb6\u6709\u5565\u5efa\u8bae\u5417\uff1f\n4-1 \u6bd4\u5982\u505a\u5b8c\u4e00\u4e2a\u9879\u76ee\uff0c\u5927\u5bb6\u662f\u5982\u4f55\u8ba9\u81ea\u5df1\u52a0\u73ed\u5fcd\u7740\u75b2\u60eb\uff0c\u628a\u7ecf\u9a8c\u518d\u68b3\u7406\u4e00\u904d\u3002\n4-2 \u505a\u6280\u672f\u8bbe\u8ba1\u65f6\uff0c\u662f\u4f1a\u5148\u53d1\u6563\u601d\u8003\uff0c\u5e7f\u6cdb\u6316\u6398\u9879\u76ee\u76f8\u5173\u8d44\u6599\uff0c\u53ef\u80fd\u4e5f\u662f\u6709\u4e00\u4e2a\u7b80\u5355\u7684\u8d44\u6599\u96c6\uff0c\u7136\u540e\u518d\u68b3\u7406\u51fa\u4e00\u4e2a\u6982\u8981\u8bbe\u8ba1\u51fa\u6765\u3002\u4e00\u822c\u65f6\u95f4\u4e5f\u662f\u6bd4\u8f83\u8d76\u7684\uff0c\u516c\u53f8\u4e0d\u4f1a\u7559\u592a\u591a\u65f6\u95f4\uff0c\u628a\u8bbe\u8ba1\u505a\u5f97\u592a\u5b8c\u5584\u3002\u6211\u73b0\u5728\u60f3\u5230\u7684\uff0c\u5c31\u662f\u7528\u81ea\u5df1\u7684\u4e1a\u4f59\u65f6\u95f4\uff0c\u628a\u611f\u5174\u8da3\u7684\u8bbe\u8ba1\uff0c\u6216\u8005\u6709\u6536\u83b7\u7684\u70b9\uff0c\u68b3\u7406\u4e00\u4e0b\u3002\n4-3 \u68b3\u7406\u5b8c\uff0c\u5982\u4f55\u628a\u5c0f\u6587\u7ae0\u7ba1\u7406\u8d77\u6765\uff0c\u53c8\u7ed5\u56de \u77e5\u8bc6\u7ba1\u7406\u7684\u95ee\u9898\u4e2d\u4e86</p>\n"
    }, 
    {
      "author": {
        "url": "https://www.v2ex.com/member/pigeon2049", 
        "name": "pigeon2049", 
        "avatar": "https://cdn.v2ex.com/gravatar/be33f27cc333f67eac0188933d9eddaf?s=73&d=retro"
      }, 
      "url": "https://www.v2ex.com/t/1236720", 
      "date_modified": "2026-08-24T02:44:49+00:00", 
      "content_html": "<p>\u5bbf\u4e3b\u673a\u8d1f\u8d23\u6b63\u5f0f\u8fd0\u884c\nJava \u670d\u52a1\u6700\u7ec8\u4ecd\u7531 systemd \u7ba1\u7406\uff0c\u76d1\u542c\u56fa\u5b9a\u7684 48080 \uff0c\u4e0d\u6539\u53d8\u73b0\u6709 Nginx \u914d\u7f6e\u3002</p>\n<p>Docker \u53ea\u8d1f\u8d23\u5236\u4f5c CRaC \u5feb\u7167\n\u65b0 JAR \u5728\u5bb9\u5668\u5185\u51b7\u542f\u52a8\u3001\u5b8c\u6210\u5065\u5eb7\u68c0\u67e5\u548c\u9884\u70ed\uff0c\u7136\u540e\u521b\u5efa checkpoint \u3002\u5bb9\u5668\u5185\u90e8\u4ecd\u4f7f\u7528 48080 \uff0c\u5bbf\u4e3b\u673a\u6620\u5c04\u968f\u673a\u7aef\u53e3\uff0c\u6240\u4ee5\u4e0d\u4f1a\u548c\u7ebf\u4e0a\u670d\u52a1\u51b2\u7a81\u3002</p>\n<p>\u5bb9\u5668\u548c\u5bbf\u4e3b\u673a\u4f7f\u7528\u76f8\u540c\u8def\u5f84\n\u7edf\u4e00\u6302\u8f7d\uff1a\n/opt/app-server/app-server.jar\n/opt/app-server/zulu25-crac\n/opt/app-server/crac/checkpoint\n\u907f\u514d\u6062\u590d\u65f6\u51fa\u73b0 JDK \u3001JAR \u6216\u5feb\u7167\u8def\u5f84\u4e0d\u4e00\u81f4\u3002</p>\n<p>\u5916\u90e8\u670d\u52a1\u4f7f\u7528\u7edf\u4e00\u53ef\u8fbe\u5730\u5740\nMySQL \u3001Redis \u3001TDengine \u7b49\u4ece 127.0.0.1 \u6539\u6210 172.17.0.1 \uff0c\u4fdd\u8bc1\u5bb9\u5668\u5236\u4f5c\u5feb\u7167\u548c\u5bbf\u4e3b\u673a\u6062\u590d\u540e\u90fd\u80fd\u8fde\u63a5\u3002</p>\n<p>\u5feb\u7167\u6210\u529f\u540e\u518d\u5207\u6362\nDocker checkpoint \u6210\u529f\u4e4b\u524d\uff0c\u65e7\u670d\u52a1\u7ee7\u7eed\u8fd0\u884c\u3002\u6210\u529f\u540e\u624d\u505c\u6b62\u65e7\u8fdb\u7a0b\u3001\u66ff\u6362 JAR \u548c\u5feb\u7167\uff0c\u518d\u7531 systemd \u4ece checkpoint \u5feb\u901f\u6062\u590d\u3002</p>\n<p>\u5b9e\u6d4b\u542f\u52a8\u65f6\u95f4\u4ece 2 \u5206\u949f\u538b\u5230\u4e86\u4e09\u79d2\n\u9700\u8981\u6ce8\u610f\u7684\u662f\n1.crac \u7279\u6027\u5f53\u524d\u4ec5 linux \u7aef\u53ef\u7528\n2.\u96c6\u6210 crac,\u9700\u8981\u544a\u8bc9\u5b83\u5173\u95ed\u8fde\u63a5\u7684\u987a\u5e8f\uff0c\u91cd\u542f\u8fde\u63a5\u7684\u987a\u5e8f</p>\n<pre><code>\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.baomidou.dynamic.datasource.DynamicRoutingDataSource;\nimport com.baomidou.dynamic.datasource.ds.ItemDataSource;\nimport org.crac.Context;\nimport org.crac.Core;\nimport org.crac.Resource;\nimport org.redisson.Redisson;\nimport org.redisson.api.RedissonClient;\nimport org.redisson.config.Config;\nimport org.springframework.context.ConfigurableApplicationContext;\n\nimport javax.sql.DataSource;\nimport java.lang.reflect.Field;\nimport java.lang.reflect.Modifier;\nimport java.sql.SQLException;\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.IdentityHashMap;\nimport java.util.List;\nimport java.util.Set;\n\n/**\n * Coordinates external clients that are not managed by Spring's CRaC lifecycle support.\n *\n * &lt;p&gt;This resource is registered before the Spring application starts. Spring's resource\n * is therefore called first before a checkpoint, pausing web, scheduling and messaging\n * lifecycle beans. This resource then closes database and Redis connections. On restore,\n * the connections are recreated before Spring restarts its lifecycle beans.&lt;/p&gt;\n */\npublic final class CracApplicationContextResource implements Resource {\n\n    private static volatile CracApplicationContextResource instance;\n\n    private final List&lt;RestartableRedissonClient&gt; checkpointRedissonClients = new ArrayList&lt;&gt;();\n\n    private final List&lt;DruidDataSource&gt; checkpointDataSources = new ArrayList&lt;&gt;();\n\n    private volatile ConfigurableApplicationContext applicationContext;\n\n    private CracApplicationContextResource() {\n    }\n\n    public static synchronized CracApplicationContextResource register() {\n        if (instance != null) {\n            throw new IllegalStateException(\"CRaC application resource is already registered\");\n        }\n        CracApplicationContextResource resource = new CracApplicationContextResource();\n        Core.getGlobalContext().register(resource);\n        instance = resource;\n        return resource;\n    }\n\n    public void attach(ConfigurableApplicationContext applicationContext) {\n        this.applicationContext = applicationContext;\n    }\n\n    @Override\n    public synchronized void beforeCheckpoint(Context&lt;? extends Resource&gt; context) {\n        ConfigurableApplicationContext currentContext = this.applicationContext;\n        if (currentContext == null) {\n            throw new IllegalStateException(\"Spring application context is not attached\");\n        }\n\n        System.out.println(\"[CRaC] Suspending external clients before checkpoint\");\n        this.checkpointRedissonClients.clear();\n        Set&lt;RedissonClient&gt; redissonClients = Collections.newSetFromMap(new IdentityHashMap&lt;&gt;());\n        redissonClients.addAll(currentContext.getBeansOfType(RedissonClient.class).values());\n        for (RedissonClient redissonClient : redissonClients) {\n            RestartableRedissonClient restartable = new RestartableRedissonClient(redissonClient);\n            this.checkpointRedissonClients.add(restartable);\n        }\n        for (RestartableRedissonClient redissonClient : this.checkpointRedissonClients) {\n            redissonClient.suspend();\n        }\n\n        this.checkpointDataSources.clear();\n        this.checkpointDataSources.addAll(findDruidDataSources(currentContext));\n        for (DruidDataSource dataSource : this.checkpointDataSources) {\n            dataSource.close();\n        }\n        System.out.println(\"[CRaC] External clients suspended\");\n    }\n\n    @Override\n    public synchronized void afterRestore(Context&lt;? extends Resource&gt; context) throws SQLException {\n        System.out.println(\"[CRaC] Resuming external clients after restore\");\n        for (DruidDataSource dataSource : this.checkpointDataSources) {\n            dataSource.restart();\n            dataSource.init();\n        }\n        for (RestartableRedissonClient redissonClient : this.checkpointRedissonClients) {\n            redissonClient.resume();\n        }\n        System.out.println(\"[CRaC] External clients resumed\");\n    }\n\n    private static Set&lt;DruidDataSource&gt; findDruidDataSources(ConfigurableApplicationContext context) {\n        Set&lt;DruidDataSource&gt; result = Collections.newSetFromMap(new IdentityHashMap&lt;&gt;());\n        for (DynamicRoutingDataSource routingDataSource\n                : context.getBeansOfType(DynamicRoutingDataSource.class).values()) {\n            for (DataSource dataSource : routingDataSource.getDataSources().values()) {\n                DataSource candidate = dataSource;\n                if (candidate instanceof ItemDataSource itemDataSource) {\n                    candidate = itemDataSource.getRealDataSource();\n                }\n                if (candidate instanceof DruidDataSource druidDataSource) {\n                    result.add(druidDataSource);\n                }\n            }\n        }\n        return result;\n    }\n\n    private static final class RestartableRedissonClient {\n\n        private final RedissonClient client;\n\n        private final Config config;\n\n        private RestartableRedissonClient(RedissonClient redissonClient) {\n            if (!(redissonClient instanceof Redisson)) {\n                throw new IllegalStateException(\"Unsupported RedissonClient implementation: \"\n                        + redissonClient.getClass().getName());\n            }\n            this.client = redissonClient;\n            this.config = new Config(redissonClient.getConfig());\n        }\n\n        private void suspend() {\n            this.client.shutdown();\n        }\n\n        private void resume() {\n            RedissonClient replacement = Redisson.create(new Config(this.config));\n            replaceRedissonState((Redisson) this.client, (Redisson) replacement);\n        }\n\n        private static void replaceRedissonState(Redisson target, Redisson source) {\n            try {\n                for (Field field : Redisson.class.getDeclaredFields()) {\n                    if (Modifier.isStatic(field.getModifiers())) {\n                        continue;\n                    }\n                    field.setAccessible(true);\n                    field.set(target, field.get(source));\n                }\n            } catch (ReflectiveOperationException exception) {\n                source.shutdown();\n                throw new IllegalStateException(\"Unable to restore Redisson client state\", exception);\n            }\n        }\n\n    }\n\n}\n\n</code></pre>\n<p>3.\u9700\u8981\u6307\u5b9a\u53ef\u80fd\u5f15\u7528\u7684\u6587\u4ef6\u4f4d\u7f6e  crac-resource-policies.yaml </p>\n<pre><code>root@base:/opt/app-server# cat crac-resource-policies.yaml \n# Logback keeps the active application log open across checkpoint/restore.\ntype: file\npath: /root/logs/app-server.log\naction: reopen\n---\n# RocketMQ uses its own file logger outside the Spring logging lifecycle.\ntype: file\npath: /root/logs/rocketmqlogs/rocketmq_client.log\naction: reopen\n---\n# Java2D fonts loaded from streams are backed by persistent temporary files.\ntype: file\npath: /opt/app-server/crac/tmp/+~JF*.tmp\naction: reopen\nroot@base:/opt/app-server# \n\n</code></pre>\n<p>\u542f\u52a8\u547d\u4ee4\u7c7b\u4f3c</p>\n<pre><code>root@base:/opt/app-server# cat /opt/app-server/run-app-server.sh\n#!/usr/bin/env bash\n\nset -Eeuo pipefail\n\nAPP_DIR=\"${APP_DIR:-/opt/app-server}\"\nAPP_JAR=\"${APP_DIR}/app-server.jar\"\nCRAC_JAVA_HOME=\"${CRAC_JAVA_HOME:-${APP_DIR}/zulu25-crac}\"\nJAVA_BIN=\"${CRAC_JAVA_HOME}/bin/java\"\nIMAGE_DIR=\"${APP_DIR}/crac/checkpoint\"\nTMP_DIR=\"${APP_DIR}/crac/tmp\"\nPOLICY_FILE=\"${APP_DIR}/crac-resource-policies.yaml\"\nPROFILE=\"${APP_PROFILE:-prod}\"\nAPP_TIMEZONE=\"${APP_TIMEZONE:-Asia/Shanghai}\"\n\ninstall -d -m 700 \"${IMAGE_DIR}\" \"${TMP_DIR}\"\necho \"[launcher] Trying CRaC restore from ${IMAGE_DIR}; falling back to a cold start when unavailable\"\nexec \"${JAVA_BIN}\" \\\n    -server \\\n    -Xms512m \\\n    -Xmx1024m \\\n    -XX:+HeapDumpOnOutOfMemoryError \\\n    -XX:HeapDumpPath=\"${APP_DIR}/heapdump.hprof\" \\\n    -Duser.timezone=\"${APP_TIMEZONE}\" \\\n    -Djava.io.tmpdir=\"${TMP_DIR}\" \\\n    -Djdk.crac.resource-policies=\"${POLICY_FILE}\" \\\n    -XX:CRaCEngine=warp \\\n    -XX:CRaCRestoreFrom=\"${IMAGE_DIR}\" \\\n    -XX:+CRaCIgnoreRestoreIfUnavailable \\\n    -XX:CRaCCheckpointTo=\"${IMAGE_DIR}\" \\\n    -jar \"${APP_JAR}\" \\\n    --spring.profiles.active=\"${PROFILE}\"\n</code></pre>\n<p>\u5982\u679c\u68c0\u67e5\u4e0d\u5230 checkpoint \uff0c\u4f1a\u4fdd\u5e95\u4ece jar \u51b7\u542f\u52a8</p>\n<p>\u53bb\u5e74\u6ca1\u6709 ai,\u6298\u817e\u8fd9\u4e00\u5957\u6ca1\u6210\u529f\n\u4eca\u5e74\u6709 codex \u7684\u5e2e\u52a9\uff0ccrac \u8fd9\u4e00\u5957\u5feb\u901f\u542f\u52a8\u7684\u4fbf\u6377\u6027\u6210\u529f\u5b9e\u73b0\u4e86\n\u6211\u7684\u8fd9\u4e00\u5957\u53ea\u9488\u5bf9\u5355\u4f53 springboot \u7a0b\u5e8f\n\u5982\u679c\u662f spring cloud \u611f\u89c9\u4f1a\u66f4\u53d7\u76ca\uff0c\u4e09\u79d2\u5bb9\u5668\u4e0a\u7ebf</p>\n", 
      "date_published": "2026-08-24T02:42:30+00:00", 
      "title": "Java Crac \u51e0\u4e4e\u6b63\u5f0f\u53ef\u7528", 
      "id": "https://www.v2ex.com/t/1236720"
    }, 
    {
      "author": {
        "url": "https://www.v2ex.com/member/konglizhi3362", 
        "name": "konglizhi3362", 
        "avatar": "https://cdn.v2ex.com/avatar/688d/f13f/529346_large.png?m=1787804853"
      }, 
      "url": "https://www.v2ex.com/t/1235863", 
      "title": "Sa-Token v1.46.0 \u53d1\u5e03 \ud83d\ude80\uff0c\u6765\u770b\u770b\u6709\u6ca1\u6709\u4ee4\u4f60\u5fc3\u52a8\u7684\u529f\u80fd\uff01", 
      "id": "https://www.v2ex.com/t/1235863", 
      "date_published": "2026-08-20T06:00:49+00:00", 
      "content_html": "<p>Sa-Token \u662f\u4e00\u6b3e <strong>\u5f00\u6e90</strong>\u3001<strong>\u514d\u8d39</strong> \u7684\u8f7b\u91cf\u7ea7 Java \u6743\u9650\u8ba4\u8bc1\u6846\u67b6\uff0c\u4e3b\u8981\u89e3\u51b3\uff1a<strong>\u767b\u5f55\u8ba4\u8bc1</strong>\u3001<strong>\u6743\u9650\u8ba4\u8bc1</strong>\u3001<strong>\u5355\u70b9\u767b\u5f55</strong>\u3001<strong>OAuth2.0</strong>\u3001<strong>\u5fae\u670d\u52a1\u7f51\u5173\u9274\u6743</strong> \u7b49\u4e00\u7cfb\u5217\u6743\u9650\u76f8\u5173\u95ee\u9898\u3002\ud83d\udd10</p>\n<p><img alt=\"sa-token-jss--tran\" class=\"embedded_image\" loading=\"lazy\" referrerpolicy=\"no-referrer\" rel=\"noreferrer\" src=\"https://res.dev33.cn/sa-token-blog/img/common/sa-token-jss--tran.png\"/></p>\n<p><strong>\u76ee\u524d\u6700\u65b0\u7248\u672c <code>v1.46.0</code> \u5df2\u63a8\u9001\u81f3 <code>Maven</code> \u4e2d\u592e\u4ed3\u5e93</strong> \ud83c\udf89\uff0c\u5927\u5bb6\u53ef\u4ee5\u901a\u8fc7\u5982\u4e0b\u65b9\u5f0f\u5f15\u5165\uff1a</p>\n<pre><code class=\"language-xml\">&lt;!-- Sa-Token \u6743\u9650\u8ba4\u8bc1 --&gt;\n&lt;dependency&gt;\n    &lt;groupId&gt;cn.dev33&lt;/groupId&gt;\n    &lt;artifactId&gt;sa-token-spring-boot4-starter&lt;/artifactId&gt;\n    &lt;version&gt;1.46.0&lt;/version&gt;\n&lt;/dependency&gt;\n</code></pre>\n<blockquote>\n<p>Spring Boot 3.x \u8bf7\u6539\u7528 <code>sa-token-spring-boot3-starter</code>\uff0cSpring Boot 2.x \u8bf7\u6539\u7528 <code>sa-token-spring-boot-starter</code>\u3002</p>\n</blockquote>\n<p>\u8be5\u7248\u672c\u5305\u542b\u5927\u91cf \u26cf\ufe0f\ufe0f\ufe0f\u65b0\u589e\u7279\u6027\u3001\u26cf\ufe0f\u5e95\u5c42\u91cd\u6784\u3001\u26cf\ufe0f\ufe0f\ufe0f\u4ee3\u7801\u4f18\u5316 \u7b49\uff0c\u4e0b\u9762\u5bb9\u6211\u5217\u4e3e\u51e0\u6761\u6bd4\u8f83\u91cd\u8981\u7684\u66f4\u65b0\u5185\u5bb9\u4f9b\u5927\u5bb6\u53c2\u9605\uff1a</p>\n<h3>\ud83d\udce6 \u66f4\u65b0\u70b9 1\uff1a\u65b0\u589e <code>sa-token-fory-json</code> \u63d2\u4ef6\uff0cJSON \u65b9\u6848\u518d\u6dfb\u4e00\u4f4d</h3>\n<p>\u8fd9\u662f\u5b98\u65b9\u89c4\u5212\u91cc\u300c JSON \u6a21\u5757\u96c6\u6210 Apache Fory \u300d\u7684\u843d\u5730\uff0c\u628a <a href=\"https://fory.apache.org/docs/json/\" rel=\"nofollow\">Fory JSON</a> \u63a5\u5230 <code>SaJsonTemplate</code> \u4e0a\u3002</p>\n<p>\u6b64\u524d Session / Redis \u5e8f\u5217\u5316\u4e3b\u8981\u662f Jackson \uff08 Boot \u9ed8\u8ba4\uff0cJSON \u91cc\u4f1a\u5199 <code>@class</code>\uff09\u548c Fastjson2 / Snack \uff08\u9ed8\u8ba4\u4e0d\u5199\u7c7b\u578b\u4fe1\u606f\uff09\u3002\u76f8\u5bf9 Jackson\uff1aFory \u5b98\u65b9\u6587\u6863\u7ed9\u51fa\u7684\u541e\u5410\u66f4\u9ad8\uff0c\u4e14<strong>\u9ed8\u8ba4\u4e0d\u5199\u7c7b\u578b\u4fe1\u606f</strong>\uff0c\u907f\u5f00\u591a\u6001\u53cd\u5e8f\u5217\u5316\u90a3\u6761\u9762\uff1b\u76f8\u5bf9 Fastjson2\uff1a\u7528\u6cd5\u63a5\u8fd1\uff0c\u9002\u5408\u5df2\u7ecf\u5728\u7528 Apache Fory \u3001\u6216\u4e0d\u60f3\u518d\u7ed1 Fastjson \u6808\u7684\u9879\u76ee\u3002\u5f15\u5165\u540e SPI \u81ea\u52a8\u6ce8\u5165\uff0c\u4e0d\u7528\u81ea\u5df1\u5305\u4e00\u5c42\u3002</p>\n<pre><code class=\"language-xml\">&lt;!-- Sa-Token \u6574\u5408 Apache Fory JSON --&gt;\n&lt;dependency&gt;\n    &lt;groupId&gt;cn.dev33&lt;/groupId&gt;\n    &lt;artifactId&gt;sa-token-fory-json&lt;/artifactId&gt;\n    &lt;version&gt;1.46.0&lt;/version&gt;\n&lt;/dependency&gt;\n</code></pre>\n<p>JSON \u63d2\u4ef6\u5168\u5bb6\u6876\u73b0\u5728\u662f\uff1aJackson \u3001Jackson3 \u3001Fastjson \u3001Fastjson2 \u3001<strong>Fory JSON</strong>\u3001Snack3 \u3001Snack4 \u3002Boot 2/3 \u9ed8\u8ba4\u4ecd\u662f Jackson \uff0cBoot 4 \u9ed8\u8ba4 Jackson3 \uff0c\u7528\u5f97\u987a\u4e0d\u5fc5\u4e3a\u4e86\u6362\u800c\u6362\u3002</p>\n<p>\u5728\u7ebf\u6587\u6863\uff1a<a href=\"https://sa-token.com/doc.html#/plugin/json-extend\" rel=\"nofollow\">JSON \u5e8f\u5217\u5316\u6269\u5c55</a> \ud83d\udd17</p>\n<h3>\ud83c\udf10 \u66f4\u65b0\u70b9 2\uff1a\u65b0\u589e <code>sa-token-rest-client</code> / <code>sa-token-rest-template</code> \u63d2\u4ef6</h3>\n<p>SSO \u6a21\u5f0f\u4e09\u7684 ticket \u6821\u9a8c\u3001\u5355\u70b9\u6ce8\u9500\u3001\u6d88\u606f\u63a8\u9001\u90fd\u8981\u53d1 HTTP \u3002\u6b64\u524d\u53ea\u6709 Forest \u3001OkHttps \u4e24\u5957\u7b2c\u4e09\u65b9\u5ba2\u6237\u7aef\u3002Spring \u9879\u76ee\u672c\u6765\u5c31\u6709 <code>spring-web</code>\uff0c\u518d\u4e3a SSO \u62c9\u4e00\u5957 HTTP \u5e93\uff0c\u4f9d\u8d56\u548c API \u90fd\u591a\u4e00\u5c42\u3002</p>\n<p>\u672c\u7248\u6309\u5b98\u65b9\u89c4\u5212\u8865\u4e0a Spring \u5b98\u65b9\u5ba2\u6237\u7aef\uff1a<code>sa-token-rest-template</code>\u3001<code>sa-token-rest-client</code>\u3002\u76f8\u5bf9 Forest / OkHttps\uff1a\u4e0d\u5f15\u5165\u7b2c\u4e09\u65b9 HTTP \u6808\uff0c\u8ddf Spring \u4e00\u6761\u7ebf\u3002<code>RestClient</code> \u76f8\u5bf9 <code>RestTemplate</code>\uff1a\u5b83\u662f Spring Framework 6.1+ / Boot 3.2+ \u7684\u5b98\u65b9\u7ee7\u4efb\u8005\uff0cBoot 4 \u91cc <code>RestTemplate</code> \u5df2\u6807\u8bb0 deprecated \uff0c\u65b0\u9879\u76ee\u4f18\u5148 RestClient \u3002Boot 2 \u6216 Boot 3.0\u20133.1 \u6ca1\u6709 <code>RestClient</code>\uff0c\u7ee7\u7eed\u7528 RestTemplate \u6216 Forest \u3002</p>\n<pre><code class=\"language-xml\">&lt;!-- Spring Boot 3.2+ / 4 \u4f18\u5148 RestClient --&gt;\n&lt;dependency&gt;\n    &lt;groupId&gt;cn.dev33&lt;/groupId&gt;\n    &lt;artifactId&gt;sa-token-rest-client&lt;/artifactId&gt;\n    &lt;version&gt;1.46.0&lt;/version&gt;\n&lt;/dependency&gt;\n</code></pre>\n<table>\n<thead>\n<tr>\n<th>\u8fd0\u884c\u73af\u5883</th>\n<th>\u63a8\u8350\u63d2\u4ef6</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>\u975e Spring / Solon</td>\n<td><code>sa-token-forest</code> \u6216 <code>sa-token-okhttps</code></td>\n</tr>\n<tr>\n<td>Spring Boot 2 \uff0c\u6216 Boot 3.0\u20133.1</td>\n<td><code>sa-token-rest-template</code> \u6216 <code>sa-token-forest</code></td>\n</tr>\n<tr>\n<td>Spring Boot 3.2+ / 4</td>\n<td><strong>\u4f18\u5148</strong> <code>sa-token-rest-client</code></td>\n</tr>\n</tbody></table><p>\u540c\u4e00 classpath \u53ea\u653e\u4e00\u4e2a HTTP \u63d2\u4ef6\u3002\u6ca1\u914d\u4efb\u4f55\u5904\u7406\u5668\u4f1a\u62a5\u9519\u8bef\u7801 30010 \u3002\u672c\u7248\u8fd8\u52a0\u4e86 SSO Client \u7684 Spring Boot 4 \u793a\u4f8b\u3002</p>\n<p>\u5728\u7ebf\u6587\u6863\uff1a<a href=\"https://sa-token.com/doc.html#/plugin/http-extend\" rel=\"nofollow\">HTTP \u8bf7\u6c42\u6269\u5c55</a> \ud83d\udd17</p>\n<h3>\ud83d\uddc4\ufe0f \u66f4\u65b0\u70b9 3\uff1a\u65b0\u589e <code>sa-token-alone-redisson</code> \u63d2\u4ef6\uff0c\u6743\u9650\u7f13\u5b58\u548c\u4e1a\u52a1\u7f13\u5b58\u62c6\u5f00</h3>\n<p>\u6765\u81ea GitHub <a href=\"https://github.com/dromara/Sa-Token/issues/710\" rel=\"nofollow\">#710</a>\u3001Gitee <a href=\"https://gitee.com/dromara/sa-token/issues/ICE2V0\" rel=\"nofollow\">#ICE2V0</a>\uff1aalone-redis \u8981\u80fd\u914d\u72ec\u7acb Redisson \u3002</p>\n<p><strong>\u5347\u7ea7\u6709\u4ec0\u4e48\u7528\uff1a</strong> \u73b0\u5728 <code>redisson</code> \u96c6\u6210\u4e5f\u53ef\u4ee5\u505a\u5230\u6743\u9650\u7f13\u5b58\u548c\u4e1a\u52a1\u7f13\u5b58\u5206\u79bb\u4e86\uff0c\u4f1a\u8bdd\u6570\u636e\u548c\u4e1a\u52a1 Redis \u4e0d\u518d\u6324\u5728\u540c\u4e00\u4e2a Client \u4e0a\uff0ckey \u51b2\u7a81\u3001\u8bef\u5220\u3001codec \u6253\u67b6\u90fd\u80fd\u907f\u5f00\u3002Boot 4 \u53e6\u6709 <code>sa-token-alone-redis-by-spring-boot4</code>\u3002</p>\n<pre><code class=\"language-xml\">&lt;dependency&gt;\n    &lt;groupId&gt;cn.dev33&lt;/groupId&gt;\n    &lt;artifactId&gt;sa-token-alone-redisson&lt;/artifactId&gt;\n    &lt;version&gt;1.46.0&lt;/version&gt;\n&lt;/dependency&gt;\n</code></pre>\n<p>\u5f15\u5165\u540e<strong>\u4e0d\u5fc5\u518d\u5f15</strong> <code>sa-token-redisson</code> / <code>sa-token-redisson-spring-boot-starter</code>\u3002</p>\n<pre><code class=\"language-yaml\">sa-token:\n    alone-redisson:\n        config: \n            singleServerConfig:\n                address: \"redis://127.0.0.1:6379\"\n                database: 2\n</code></pre>\n<p><code>config</code> \u4e0e <code>file</code> \u4e8c\u9009\u4e00\u3002\u793a\u4f8b\u8986\u76d6\u5355\u673a\u3001\u96c6\u7fa4\u3001Boot 3/4 \u3002</p>\n<p>Boot 4 \u6ce8\u610f\uff1aRedisson 3.45 \u7684 starter \u4ecd\u5f15\u7528\u5df2\u79fb\u9664\u7684 <code>RedisAutoConfiguration</code>\uff0c<strong>\u4e0d\u8981\u5f15</strong> <code>redisson-spring-boot-starter</code>\uff0c\u81ea\u5df1\u6ce8\u518c Bean \u3002<code>SaTokenDaoForRedisson</code> \u9ed8\u8ba4 <code>StringCodec</code>\uff0c\u5e76\u53ef\u7528 <code>setAndKeepTTL</code> \u539f\u5b50\u4fdd\u7559 TTL \u3002fix: <a href=\"https://github.com/dromara/Sa-Token/issues/791\" rel=\"nofollow\">#791</a></p>\n<p>\u5728\u7ebf\u6587\u6863\uff1a<a href=\"https://sa-token.com/doc.html#/plugin/alone-redisson\" rel=\"nofollow\">\u72ec\u7acb Redisson \u63d2\u4ef6</a> \ud83d\udd17</p>\n<h3>\ud83d\udd27 \u66f4\u65b0\u70b9 4\uff1aRedisTemplate \u68c0\u7d22\u6539 SCAN \u3001update \u4fdd TTL \u3001key \u53ef\u52a0\u524d\u7f00</h3>\n<p>\u8fd9\u51e0\u6761\u90fd\u662f\u793e\u533a\u8001\u5de5\u5355\uff1a</p>\n<ul>\n<li><code>searchData</code> \u7528 KEYS \u4f1a\u5835 Redis\uff1a<a href=\"https://github.com/dromara/Sa-Token/issues/702\" rel=\"nofollow\">#702</a></li>\n<li>update \u540e\u7eed\u671f TTL \u504f\u79fb\uff1a<a href=\"https://gitee.com/dromara/sa-token/issues/I80P5O\" rel=\"nofollow\">#I80P5O</a>\u3001<a href=\"https://gitee.com/dromara/sa-token/issues/ICWJOQ\" rel=\"nofollow\">#ICWJOQ</a></li>\n<li>\u591a\u9879\u76ee\u5171\u7528 Redis \u8981\u52a0\u524d\u7f00\uff1a<a href=\"https://github.com/dromara/Sa-Token/issues/956\" rel=\"nofollow\">#956</a></li>\n</ul>\n<p><strong>\u5347\u7ea7\u6709\u4ec0\u4e48\u7528\uff1a</strong> \u5728\u7ebf\u7528\u6237\u67e5\u8be2\u4e0d\u518d <code>KEYS *</code>\uff1b\u6539 Session \u4e0d\u4f1a\u628a\u8fc7\u671f\u65f6\u95f4\u62b9\u6210\u300c\u518d\u6d3b\u4e00\u6574\u6bb5 timeout \u300d\uff1b\u591a\u7cfb\u7edf\u5171 Redis \u53ef\u4ee5 <code>wrapKey</code> \u9694\u79bb\u5f00\u3002</p>\n<pre><code class=\"language-java\">public class MySaTokenDao extends SaTokenDaoForRedisTemplate {\n    @Override\n    public String wrapKey(String key) {\n        return \"my-app:\" + key;\n    }\n}\n</code></pre>\n<p>KEEPTTL \u9700\u8981 Redis &gt;= 6.0 \u3002</p>\n<h3>\ud83d\udd14 \u66f4\u65b0\u70b9 5\uff1a\u6ce8\u9500\u524d\u4fa6\u542c\u5668\uff0c\u4f1a\u8bdd\u6e05\u6389\u4e4b\u524d\u8fd8\u80fd\u8bfb\u73b0\u573a</h3>\n<p>\u6765\u81ea sa-token \u5c0f\u52a9\u624b\u7528\u6237\u300c\u6f6e\u6c50\u300d\u7684\u5efa\u8bae\uff1a\u4fa6\u542c\u5668\u89e6\u53d1\u65f6\u8bbe\u5907\u4fe1\u606f\u5f80\u5f80\u5df2\u7ecf\u6ca1\u4e86\uff0c\u5ba1\u8ba1\u4e0d\u597d\u8bb0\u3002</p>\n<p><strong>\u5347\u7ea7\u6709\u4ec0\u4e48\u7528\uff1a</strong> \u8e22\u4eba\u3001\u9876\u4eba\u3001\u4e3b\u52a8\u6ce8\u9500\u524d\uff0c\u8fd8\u80fd\u8bfb\u5230 Token-Session \u3001\u8bbe\u5907\u5217\u8868\uff0c\u5199\u65e5\u5fd7\u3001\u53d1\u901a\u77e5\u4e0d\u7528\u81ea\u5df1\u62a2\u65f6\u5e8f\u3002</p>\n<pre><code class=\"language-java\">@Override\npublic void doBeforeLogout(String loginType, Object loginId, String tokenValue, SaLogoutParameter logoutParameter) {\n    SaSession session = SaManager.getStpLogic(loginType).getSessionByLoginId(loginId, false);\n    SaTerminalInfo terminal = session == null ? null : session.getTerminal(tokenValue);\n    // \u8bb0\u6ce8\u9500\u65e5\u5fd7\n}\n</code></pre>\n<p>\u5bf9\u5e94\u94a9\u5b50\uff1a<code>doBeforeLogout</code> / <code>doBeforeKickout</code> / <code>doBeforeReplaced</code>\u3002\u4e0d\u8981\u7528 <code>StpUtil</code> \u8bfb\u5f53\u524d\u8bf7\u6c42\u4e0a\u4e0b\u6587\uff0c\u7528\u53c2\u6570\u91cc\u7684 <code>loginId</code>\u3001<code>tokenValue</code> \u53bb\u67e5\u3002</p>\n<p>\u5728\u7ebf\u6587\u6863\uff1a<a href=\"https://sa-token.com/doc.html#/up/global-listener\" rel=\"nofollow\">\u5168\u5c40\u4fa6\u542c\u5668</a> \ud83d\udd17</p>\n<h3>\ud83d\udccb \u66f4\u65b0\u70b9 6\uff1aSession \u65b0\u589e <code>getList</code> / <code>getSet</code> / <code>getMap</code></h3>\n<p>\u672c\u7248\u4e3b\u52a8\u8865\u9f50\u3002\u4ee5\u524d\u4ece Session \u53d6\u96c6\u5408\uff0c\u8981\u4e48 <code>get</code> \u5b8c\u518d\u5f3a\u8f6c\uff0c\u8981\u4e48\u81ea\u5df1\u5904\u7406 Redis \u56de\u6765\u7684\u88f8 List \u3002\u73b0\u5728\u628a\u5143\u7d20\u7c7b\u578b\u5199\u5728\u53c2\u6570\u4e0a\uff0c\u4e3b\u8981\u662f\u4e3a\u4e86\u8ba9\u4ee3\u7801\u5199\u5f97\u66f4\u4f18\u96c5\uff0c\u8c03\u7528\u66f4\u53cb\u5584\u3002</p>\n<pre><code class=\"language-java\">// \u4ee5\u524d\n@SuppressWarnings(\"unchecked\")\nList&lt;SysUser&gt; users = (List&lt;SysUser&gt;) session.get(\"users\");\n\n// \u73b0\u5728\nList&lt;SysUser&gt; users = session.getList(\"users\", SysUser.class);\nSet&lt;String&gt; roles = session.getSet(\"roles\", String.class);\nMap&lt;String, Long&gt; scoreMap = session.getMap(\"scoreMap\", String.class, Long.class);\n\n// \u7f3a key \u65f6\u7ed9\u9ed8\u8ba4\u96c6\u5408\nsession.getList(\"users\", SysUser.class, ArrayList::new);\n</code></pre>\n<p>OAuth2 \u7d22\u5f15\u3001SSO Client \u5217\u8868\u3001ApiKey \u7d22\u5f15\u4e5f\u5207\u5230\u8fd9\u5957 API \uff0c\u4e1a\u52a1\u4fa7\u540c\u4e00\u5957\u5199\u6cd5\u3002</p>\n<p>\u5728\u7ebf\u6587\u6863\uff1a<a href=\"https://sa-token.com/doc.html#/use/session\" rel=\"nofollow\">Session \u4f1a\u8bdd</a> \ud83d\udd17</p>\n<h3>\ud83d\udeaa \u66f4\u65b0\u70b9 7\uff1aSSO \u5ba2\u6237\u7aef\u652f\u6301\u6309\u8d26\u53f7\u5355\u70b9\u6ce8\u9500</h3>\n<p>\u793e\u533a\u63d0\u6848\uff1a\u5b50\u7cfb\u7edf\u5220\u7528\u6237\u65f6\uff0c\u5e0c\u671b\u4e00\u884c API \u901a\u77e5\u8ba4\u8bc1\u4e2d\u5fc3\u628a\u8be5\u8d26\u53f7\u5168\u7aef\u6253\u4e0b\u7ebf\u3002</p>\n<p><strong>\u5347\u7ea7\u6709\u4ec0\u4e48\u7528\uff1a</strong> \u540e\u53f0\u5c01\u53f7\u3001\u79bb\u804c\u56de\u6536\uff0c\u4e0d\u5fc5\u518d\u81ea\u5df1\u62fc SSO \u63a8\u9001\u62a5\u6587\u3002</p>\n<pre><code class=\"language-java\">// sso-server\nSaSsoServerUtil.ssoLogout(loginId);\n\n// sso-client \uff08\u672c\u5730 loginId \uff0c\u6846\u67b6\u6309\u7b56\u7565\u8f6c\u6210\u8ba4\u8bc1\u4e2d\u5fc3 id \uff09\nSaSsoClientUtil.ssoLogout(loginId);\n</code></pre>\n<p>\u5728\u7ebf\u6587\u6863\uff1a<a href=\"https://sa-token.com/doc.html#/sso/signout\" rel=\"nofollow\">Sa-Token SSO \u5355\u70b9\u6ce8\u9500</a> \ud83d\udd17</p>\n<h3>\ud83e\udde9 \u66f4\u65b0\u70b9 8\uff1a<code>SaRequest</code> / <code>SaResponse</code> / <code>SaStorage</code> \u53ef\u7b56\u7565\u521b\u5efa</h3>\n<p>\u6765\u81ea GitHub <a href=\"https://github.com/dromara/Sa-Token/issues/841\" rel=\"nofollow\">#841</a>\uff1a\u65e7\u7248\u9760\u7ee7\u627f <code>SaTokenContextForSpring</code> \u6539\u4e0a\u4e0b\u6587\uff0cv1.42 \u91cd\u6784\u540e\u90a3\u5957\u7236\u7c7b\u6ca1\u4e86\u3002</p>\n<p><strong>\u5347\u7ea7\u6709\u4ec0\u4e48\u7528\uff1a</strong> Nginx \u6539 URI \u3001\u81ea\u5b9a\u4e49 Request \u5305\u88c5\uff0c\u6539\u7b56\u7565\u51fd\u6570\u5373\u53ef\uff0c\u4e0d\u7528\u518d\u7ee7\u627f\u5df2\u5220\u9664\u7684\u4e0a\u4e0b\u6587\u7c7b\u3002</p>\n<p><code>SaStrategy</code> \u65b0\u589e <code>createSaRequest</code> / <code>createSaResponse</code> / <code>createSaStorage</code>\u3002<code>getSaTokenConfig</code> \u4e5f\u53ef\u63a5\u7ba1\u914d\u7f6e\u6765\u6e90\uff0c\u65b9\u4fbf\u4ece\u6570\u636e\u5e93\u8bfb Sa-Token \u914d\u7f6e\u3002</p>\n<h3>\u26a0\ufe0f \u66f4\u65b0\u70b9 9\uff1a\u4e24\u5904\u4e0d\u5411\u4e0b\u517c\u5bb9\uff0c\u5347\u7ea7\u5148\u770b</h3>\n<p><strong>1 \uff09<code>allowLoginIdColon</code> \u9ed8\u8ba4 false \u3002</strong> \u5b98\u65b9\u4e00\u76f4\u5f3a\u8c03 loginId \u4e0d\u8981\u5e26\u5192\u53f7\uff08\u6301\u4e45\u5316 key \u7528 <code>:</code> \u5206\u6bb5\uff09\u3002\u672c\u7248\u6e90\u7801\u76f4\u63a5\u62d2\u767b\u3002\u5b58\u91cf\u9879\u76ee\u5982\u679c loginId \u91cc\u771f\u6709\u5192\u53f7\uff1a</p>\n<pre><code class=\"language-yaml\">sa-token:\n    allow-login-id-colon: true\n</code></pre>\n<p><strong>2 \uff09<code>StpInterface.isDisabled</code> \u589e\u52a0 <code>loginType</code> \u53c2\u6570\u3002</strong> \u81ea\u5df1\u5b9e\u73b0\u4e86\u5c01\u7981\u67e5\u8be2\u7684\uff0c\u8981\u6539\u65b9\u6cd5\u7b7e\u540d\u3002</p>\n<p>\u53e6\u5916\uff1aJWT <code>extraData</code> \u7981\u6b62\u5199\u5165 <code>loginType</code>\u3001<code>loginId</code>\u3001<code>deviceType</code>\u3001<code>eff</code>\u3001<code>rnStr</code> \u7b49\u4fdd\u7559\u5b57\u6bb5\uff0c\u649e\u540d\u4f1a\u76f4\u63a5\u629b\u9519\u3002</p>\n<h3>\ud83d\udee1\ufe0f \u66f4\u65b0\u70b9 10\uff1a\u4fee\u590d OAuth2 / SSO <code>redirect</code> \u7ed5\u8fc7 <code>allow-url</code> \u6f0f\u6d1e</h3>\n<p>\u6765\u81ea\u793e\u533a\u7528\u6237\u63d0\u4ea4\u7684\u6f0f\u6d1e\u62a5\u544a\uff1aOAuth2 \u8c03\u7528 <code>/oauth2/doConfirm</code> \u65f6\uff0c<code>redirect_uri</code> \u6821\u9a8c\u53ef\u88ab\u7ed5\u8fc7\uff1b\u672c\u7248\u5ba1\u67e5\u540e\u786e\u8ba4 SSO \u7684 <code>redirect</code> \u5b58\u5728\u540c\u7c7b\u95ee\u9898\u3002</p>\n<p><strong>\u89e6\u53d1\u6761\u4ef6\u4e3a\uff08\u9700\u540c\u65f6\u6ee1\u8db3\uff09\uff1a</strong></p>\n<ol>\n<li>\u9879\u76ee\u642d\u4e86 <strong>SSO \u8ba4\u8bc1\u4e2d\u5fc3</strong> \u6216 <strong>OAuth2 \u6388\u6743\u670d\u52a1\u5668</strong>\uff1b</li>\n<li>\u8bf7\u6c42\u91cc\u53ef\u4ee5\u7531\u524d\u7aef\uff08\u6216\u653b\u51fb\u8005\uff09\u4f20\u5165 <code>redirect</code> / <code>redirect_uri</code>\uff1b</li>\n<li><code>allow-url</code> \u914d\u4e86\u4e0d\u5b89\u5168\u901a\u914d\uff08\u5982 <code>http://domain*</code>\uff0c<code>*</code>\u51fa\u73b0\u5728\u57df\u540d\u90e8\u5206\uff0c\u524d\u9762\u4e0d\u662f<code>/</code>\u6216<code>:</code>\uff09\u3002</li>\n</ol>\n<p>\u666e\u901a\u767b\u5f55\u9274\u6743\u3001\u6ca1\u7528 SSO/OAuth2 \u7684\u9879\u76ee\uff0c\u4e0e\u8fd9\u6761\u65e0\u5173\u3002<code>allow-url: \"*\"</code> \u7b49\u4e8e\u4e3b\u52a8\u653e\u5f00\u767d\u540d\u5355\uff0c\u4e5f\u4e0d\u5728\u672c\u6761\u8ba8\u8bba\u8303\u56f4\u3002</p>\n<p><strong>\u4f1a\u9020\u6210\uff1a</strong> ticket \u6216\u6388\u6743\u7801\u88ab\u4e0b\u53d1\u5230\u7b2c\u4e09\u65b9\u7ad9\u70b9\u3002</p>\n<p><strong>\u65b0\u7248\u672c\uff1a</strong> SSO \u4e0e OAuth2 \u4e24\u4fa7\u540c\u65f6\u62d2\u7edd <code>@</code>\u3001<code>%40</code>\u3001<code>%2540</code>\uff1b<code>*</code> \u53ea\u80fd\u51fa\u73b0\u5728\u6700\u540e\u4e00\u4f4d\uff0c\u4e14\u524d\u4e00\u4f4d\u5fc5\u987b\u662f <code>/</code> \u6216 <code>:</code>\uff1b<code>isUrl</code> \u652f\u6301 IPv6 \u65b9\u62ec\u53f7\u5730\u5740\u3002\u751f\u4ea7\u73af\u5883\u8bf7\u628a <code>allow-url</code> \u914d\u6210\u660e\u786e\u5730\u5740\u3002\u7528\u4e86 SSO/OAuth2 \u7684\uff0c\u5efa\u8bae\u5347\u5230 v1.46.0 \u3002</p>\n<pre><code class=\"language-yaml\">sa-token:\n    sso-server:\n        clients:\n            sso-client1:\n                allow-url: http://sa-sso-client1.com:9003/*\n</code></pre>\n<p>\u611f\u8c22\u8fd9\u4f4d\u793e\u533a\u7528\u6237\u63d0\u4ea4\u7684\u6f0f\u6d1e\u62a5\u544a\u3002</p>\n<h3>\ud83d\udd10 \u66f4\u65b0\u70b9 11\uff1a\u4fee\u590d Jackson \u591a\u6001\u53cd\u5e8f\u5217\u5316\u6f0f\u6d1e\uff0c\u65b0\u589e\u7c7b\u578b\u767d\u540d\u5355</h3>\n<p>\u8fd9\u662f\u672c\u7248\u5bf9 JSON \u53cd\u5e8f\u5217\u5316\u8def\u5f84\u7684\u4e3b\u52a8\u5ba1\u67e5\uff1a\u4f7f\u7528 Jackson / Jackson3 \u628a <code>SaSession</code> \u5199\u5165 Redis \u65f6\uff0cJSON \u91cc\u4f1a\u5e26 <code>@class</code> \u7c7b\u578b\u6807\u8bb0\uff1b\u65e7\u7248\u672c\u672a\u9650\u5236\u4e25\u683c\u9650\u5236\u53cd\u5e8f\u5217\u5316\u7c7b\u578b\u767d\u540d\u5355\uff0c\u53ef\u80fd\u4f1a\u5728\u53cd\u5e8f\u5217\u5316\u65f6\u89e6\u53d1 classpath \u4e0a\u7684\u4efb\u610f\u7c7b\u3002</p>\n<p><strong>\u89e6\u53d1\u6761\u4ef6\u4e3a\uff08\u9700\u540c\u65f6\u6ee1\u8db3\uff09\uff1a</strong> \u4f7f\u7528 <code>SaJsonTemplate</code> \u53bb\u53cd\u5e8f\u5217\u5316\u4e1a\u52a1\u4e2d\u672a\u4e25\u683c\u5ba1\u67e5\u7684 json \u5b57\u7b26\u4e32\u3002</p>\n<p><code>fastjson</code> / <code>fastjson2</code> / <code>fory-json</code> / <code>snack3</code> \u9ed8\u8ba4\u4e0d\u5199\u7c7b\u578b\u6807\u8bb0\uff0c\u4e00\u822c\u4e0d\u8d70\u8fd9\u6761\u9762\u3002\u4e0d\u53bb\u4f7f\u7528 <code>SaJsonTemplate</code> \u53bb\u53cd\u5e8f\u5217\u5316\u4e1a\u52a1\u4e2d\u672a\u4e25\u683c\u5ba1\u67e5\u7684 json \u5b57\u7b26\u4e32\u3002\u672c\u7248\u8d77 <code>sa-token-snack3</code> \u4e5f\u4e0d\u518d\u5199\u5165\u7c7b\u578b\u4fe1\u606f\u3002</p>\n<p><strong>\u4f1a\u9020\u6210\uff1a</strong> \u653b\u51fb\u8005\u63d0\u4ea4\u6076\u610f json \u5b57\u7b26\u4e32\uff0c\u53ef\u80fd\u89e6\u53d1\u591a\u6001\u53cd\u5e8f\u5217\u5316 RCE \u3002</p>\n<p><strong>\u65b0\u7248\u672c\uff1a</strong> \u589e\u52a0 <code>SaJsonStrategy</code> \u5168\u5c40\u7c7b\u578b\u767d\u540d\u5355\uff0c\u53ea\u5141\u8bb8\u767d\u540d\u5355\u5185\u7c7b\u578b\u53c2\u4e0e\u8fd9\u7c7b\u53cd\u5e8f\u5217\u5316\u3002JDK \u5e38\u89c1\u503c\u7c7b\u578b\u3001\u6846\u67b6\u5df2\u5b9e\u73b0 <code>SaJsonType</code> \u7684 Model \u9ed8\u8ba4\u5728\u540d\u5355\u91cc\uff1b<strong>\u4f60\u7684\u4e1a\u52a1\u5b9e\u4f53\u9ed8\u8ba4\u4e0d\u5728</strong>\u3002\u7528\u4e86 Jackson \u4e14 Session \u91cc\u5b58\u4e86\u81ea\u5b9a\u4e49\u5bf9\u8c61\u7684\uff0c\u5347\u7ea7\u540e\u53ef\u80fd\u770b\u5230\uff1a</p>\n<pre><code>\u65e0\u6cd5\u53cd\u5e8f\u5217\u5316\u7684\u7c7b\u578b\uff1acom.pj.model.SysUser \uff0c\u8bf7\u5148\u5c06\u5176\u6ce8\u518c\u5230 JSON \u5168\u5c40\u7c7b\u578b\u767d\u540d\u5355\n</code></pre>\n<p>\u63a8\u8350\u8ba9\u5b9e\u4f53\u5b9e\u73b0 <code>SaJsonType</code>\uff1a</p>\n<pre><code class=\"language-java\">public class SysUser implements SaJsonType {\n    // ...\n}\n</code></pre>\n<p>\u4e5f\u53ef\u4ee5\u5728 <code>SpringApplication.run</code> <strong>\u4e4b\u524d</strong> \u8c03\u7528 <code>SaJsonStrategy.instance.registerAllowType(SysUser.class)</code>\uff0c\u6216\u5728 <code>META-INF/satoken/sa-json-type.list</code> \u6309\u884c\u5199\u5b8c\u6574\u7c7b\u540d\u3002JSON \u63d2\u4ef6\u521d\u59cb\u5316\u540e\u518d\u6ce8\u518c\u4f1a\u5931\u8d25\u3002\u4e0d\u8981\u767b\u8bb0 <code>Object.class</code>\u3002\u7528\u4e86 Jackson + SaJsonTemplate \u53cd\u5e8f\u5217\u5316\u4e1a\u52a1 json \u5b57\u7b26\u4e32\u7684\uff0c\u5efa\u8bae\u5347\u5230 v1.46.0 \uff0c\u5e76\u5148\u628a\u4e1a\u52a1\u7c7b\u578b\u767b\u8bb0\u8fdb\u767d\u540d\u5355\u3002</p>\n<p>\u5728\u7ebf\u6587\u6863\uff1a<a href=\"https://sa-token.com/doc.html#/plugin/json-extend\" rel=\"nofollow\">JSON \u5e8f\u5217\u5316\u6269\u5c55</a> \ud83d\udd17</p>\n<h3>\ud83d\udce1 \u66f4\u65b0\u70b9 12\uff1a\u4fee\u590d SSE / Flux \u4e0a\u4e0b\u6587\u672a\u521d\u59cb\u5316\uff0c\u4ee5\u53ca Boot3 WebFlux <code>setStatus</code></h3>\n<p>\u8fd9\u4e24\u6761\u90fd\u662f\u793e\u533a\u62a5\u9519\u5de5\u5355\uff1aSSE \u6765\u81ea Gitee <a href=\"https://gitee.com/dromara/sa-token/issues/IC4XFE\" rel=\"nofollow\">#IC4XFE</a>\u3001<a href=\"https://gitee.com/dromara/sa-token/issues/ICB9OJ\" rel=\"nofollow\">#ICB9OJ</a>\uff1b<code>setStatus</code> \u6765\u81ea <a href=\"https://gitee.com/dromara/sa-token/issues/IIAW1A\" rel=\"nofollow\">#IIAW1A</a>\u3001GitHub <a href=\"https://github.com/dromara/Sa-Token/issues/916\" rel=\"nofollow\">#916</a>\u3002</p>\n<p><strong>SSE / Flux</strong></p>\n<p>\u5728\u4e4b\u524d\u7684\u7248\u672c\u4e2d\uff0cSpringMVC \u63a5\u53e3\u5982\u679c\u8fd4\u56de <code>SseEmitter</code>\u3001<code>Flux</code> \u7b49\u5f02\u6b65\u3001\u6d41\u5f0f\u7ed3\u679c\uff0c\u968f\u540e\u518d\u8c03 <code>StpUtil</code> / <code>SaHolder</code> \u4f1a\u62a5\uff1a</p>\n<pre><code>cn.dev33.satoken.exception.SaTokenContextException: SaTokenContext \u4e0a\u4e0b\u6587\u5c1a\u672a\u521d\u59cb\u5316\n</code></pre>\n<p>\u8fd9\u662f\u56e0\u4e3a Context Filter \u53ea\u6ce8\u518c\u4e86 <code>REQUEST</code>\u3002\u6d41\u5f0f\u8fd4\u56de\u4f1a\u518d\u8d70\u4e00\u904d <code>ASYNC</code> dispatch \uff0c\u8fc7\u6ee4\u5668\u6ca1\u6302\u4e0a\uff0cThreadLocal \u4e0a\u4e0b\u6587\u662f\u7a7a\u7684\u3002\u666e\u901a <code>@RequestMapping</code> \u4e00\u95ee\u4e00\u7b54\u4e0d\u53d7\u5f71\u54cd\u3002</p>\n<p>\u65b0\u7248\u672c\u628a Filter \u6ce8\u518c\u4e3a <code>REQUEST</code> + <code>ASYNC</code>\uff0c\u4e8c\u6b21 dispatch \u4e5f\u4f1a\u521d\u59cb\u5316\u4e0a\u4e0b\u6587\uff0c\u4e00\u822c\u4e0d\u7528\u518d\u624b\u6539 Filter \u3002</p>\n<p><strong>Boot3+ WebFlux / Gateway <code>setStatus</code></strong></p>\n<p>\u5728\u4e4b\u524d\u7684\u7248\u672c\u4e2d\uff0cBoot3+ \u7684 WebFlux \u6216 Gateway \u91cc\u8c03\u7528\uff1a</p>\n<pre><code class=\"language-java\">SaHolder.getResponse().setStatus(401);\n</code></pre>\n<p>\u4f1a\u62a5\uff1a</p>\n<pre><code>java.lang.NoSuchMethodError: 'org.springframework.http.server.reactive.ServerHttpResponse setStatusCode(org.springframework.http.HttpStatus)'\n</code></pre>\n<p>\u8fd9\u662f\u56e0\u4e3a Boot2 \u7684 <code>ServerHttpResponse.setStatusCode</code> \u5403 <code>HttpStatus</code>\uff0cBoot3 \u6539\u6210\u4e86 <code>HttpStatusCode</code>\uff0c\u65e7 Reactor starter \u5b57\u8282\u7801\u5bf9\u4e0d\u4e0a\u3002WebMVC \u7528\u6237\u4e0e\u8fd9\u6761\u65e0\u5173\u3002</p>\n<p>\u65b0\u7248\u672c\u62c6\u4e86 Boot2 / Boot3+ \u7684 Reactor \u5b9e\u73b0\uff0cBoot3+ \u8d70 <code>HttpStatusCode.valueOf(sc)</code>\uff0c\u4e0d\u518d\u62a5\u9519\u3002<code>sa-token-dependencies</code> \u4e5f\u4e0d\u518d\u9501\u6b7b Reactor \u7248\u672c\uff0c\u907f\u514d\u8ddf Spring Cloud Gateway \u6253\u67b6\u3002fix: <a href=\"https://github.com/dromara/Sa-Token/issues/622\" rel=\"nofollow\">#622</a></p>\n<h3>\ud83d\udcda \u66f4\u65b0\u70b9 13\uff1a\u6587\u6863\u7ad9\u542f\u7528 .com \u9876\u7ea7\u57df\u540d\uff0c\u535a\u5ba2\u3001\u591a\u8bed\u8a00\u3001\u5b89\u5168\u7b56\u7565</h3>\n<p>\u57df\u540d\u4ece <code><a href=\"http://sa-token.cc\" rel=\"nofollow\">sa-token.cc</a></code> \u8fc1\u5230 <a href=\"https://sa-token.com\" rel=\"nofollow\">sa-token.com</a>\uff0c\u8bf7\u5373\u4f7f\u4fee\u6539\u4e66\u7b7e\u3002\u72ec\u7acb\u535a\u5ba2\u4e0a\u7ebf\uff1b\u6587\u6863\u7ad9\u6697\u8272\u4e3b\u9898 5 \u79cd IDE \u98ce\u683c\uff1b translate.js \u591a\u8bed\u8a00\uff1b README \u6709\u82f1/\u65e5/\u97e9/\u4fc4/\u7e41\u4e2d\u3002</p>\n<p>\u968f\u673a\u6570\u6539\u7528 <code>SecureRandom</code>\u3002\u65b0\u589e <code><a href=\"http://SECURITY.md\" rel=\"nofollow\">SECURITY.md</a></code>\uff1a\u5b89\u5168\u95ee\u9898\u8d70 GitHub Private Vulnerability Reporting \u6216\u90ae\u4ef6\uff0c\u4e0d\u8981\u5f00\u516c\u5f00 Issue \u3002</p>\n<p>\u6587\u6863\u7248\u672c\u9009\u62e9\u5668\u6539\u4e3a\u52a8\u6001\u52a0\u8f7d\u3002Solon \u63d2\u4ef6\u7531 PathAnalyzer \u6362\u6210 PathMatcher \u3002</p>\n<p>\u611f\u8c22 <a href=\"https://github.com/dromara/Sa-Token/pull/933\" rel=\"nofollow\">@Ran</a> \u8865\u5145 <code><a href=\"http://SECURITY.md\" rel=\"nofollow\">SECURITY.md</a></code>\uff08 fix <a href=\"https://github.com/dromara/Sa-Token/issues/932\" rel=\"nofollow\">#932</a>\u3001<a href=\"https://github.com/dromara/Sa-Token/issues/877\" rel=\"nofollow\">#877</a>\uff09\uff1b\u611f\u8c22 <a href=\"https://gitee.com/dromara/sa-token/pulls/364\" rel=\"nofollow\">@noear</a> \u9002\u914d Solon PathMatcher \uff08 fix <a href=\"https://gitee.com/dromara/sa-token/issues/IJTNJK\" rel=\"nofollow\">#IJTNJK</a>\uff09\u3002</p>\n<h3>\ud83d\udcdc \u5b8c\u6574\u66f4\u65b0\u65e5\u5fd7</h3>\n<p>\u9664\u4e86\u4ee5\u4e0a\u63d0\u5230\u7684\u51e0\u70b9\u4ee5\u5916\uff0c\u8fd8\u6709\u66f4\u591a\u66f4\u65b0\u70b9\u65e0\u6cd5\u9010\u4e00\u8be6\u7ec6\u4ecb\u7ecd\uff0c\u4e0b\u9762\u662f v1.46.0 \u7248\u672c\u7684\u5b8c\u6574\u66f4\u65b0\u65e5\u5fd7\uff1a</p>\n<ul>\n<li>\ncore\uff1a<ul>\n<li>\u65b0\u589e\uff1a\u4fa6\u542c\u5668\u65b0\u589e\u6ce8\u9500\u524d\u94a9\u5b50 <code>doBeforeLogout</code> / <code>doBeforeKickout</code> / <code>doBeforeReplaced</code>\u3002 <strong>[\u91cd\u8981]</strong></li>\n<li>\u65b0\u589e\uff1a<code>StpInterface.isDisabled</code> \u8865\u5145 <code>loginType</code> \u53c2\u6570\u3002  <strong>[\u4e0d\u5411\u4e0b\u517c\u5bb9]</strong></li>\n<li>\u65b0\u589e\uff1a\u65b0\u589e <code>allowLoginIdColon</code> \u914d\u7f6e\uff0c\u9ed8\u8ba4\u7981\u6b62 loginId \u5305\u542b\u5192\u53f7\u3002  <strong>[\u4e0d\u5411\u4e0b\u517c\u5bb9]</strong></li>\n<li>\u4fee\u590d\uff1aJackson DefaultTyping \u591a\u6001\u53cd\u5e8f\u5217\u5316 RCE \uff0c\u65b0\u589e <code>SaJsonStrategy</code> \u5168\u5c40\u7c7b\u578b\u767d\u540d\u5355\u3002  <strong>[\u91cd\u8981]</strong> <strong>[\u6f0f\u6d1e\u4fee\u590d]</strong></li>\n<li>\u65b0\u589e\uff1a<code>getSaTokenConfig</code> \u7b56\u7565\u652f\u6301\u81ea\u5b9a\u4e49\u914d\u7f6e\u6765\u6e90\uff0c\u65b9\u4fbf\u4ece\u6570\u636e\u5e93\u4e2d\u8bfb\u53d6\u914d\u7f6e\u3002</li>\n<li>\u65b0\u589e\uff1a\u65b0\u589e <code>SaRequest</code> / <code>SaResponse</code> / <code>SaStorage</code> \u521b\u5efa\u7b56\u7565\u3002  fix: <a href=\"https://github.com/dromara/Sa-Token/issues/841\" rel=\"nofollow\">#841</a></li>\n<li>\u65b0\u589e\uff1aSession \u65b0\u589e <code>getList</code> / <code>getSet</code> / <code>getMap</code> \u7c7b\u578b\u5b89\u5168\u96c6\u5408\u8bfb\u53d6\u3002</li>\n<li>\u4fee\u6539\uff1a\u968f\u673a\u5b57\u7b26\u4e32/\u6570\u5b57\u6539\u7528 CSPRNG \uff08<code>SecureRandom</code>\uff09\u751f\u6210\u3002</li>\n<li>\u4fee\u590d\uff1a<code>isLastingCookie</code> \u4e3a null \u65f6 <code>getCookieTimeout</code> \u4e0d\u518d NPE \u3002</li>\n<li>\u4fee\u590d\uff1a<code>isUrl</code> \u652f\u6301 IPv6 \u65b9\u62ec\u53f7\u5730\u5740\u5e76\u62d2\u7edd\u88f8 IPv6 \u3002</li>\n<li>\u4fee\u590d\uff1aJSON \u53cd\u5e8f\u5217\u5316\u5bb9\u9519\u4f18\u5316\u3002  fix: <a href=\"https://gitee.com/dromara/sa-token/issues/ICOTM8\" rel=\"nofollow\">#ICOTM8</a></li>\n</ul>\n</li>\n<li>\n\u63d2\u4ef6\uff1a<ul>\n<li>\u65b0\u589e\uff1a\u65b0\u589e <code>sa-token-fory-json</code> JSON \u5e8f\u5217\u5316\u63d2\u4ef6\u3002  <strong>[\u91cd\u8981]</strong></li>\n<li>\u65b0\u589e\uff1a\u65b0\u589e HTTP \u8bf7\u6c42\u6269\u5c55\u63d2\u4ef6 <code>sa-token-rest-client</code> / <code>sa-token-rest-template</code>\u3002  <strong>[\u91cd\u8981]</strong></li>\n<li>\u65b0\u589e\uff1a\u65b0\u589e <code>sa-token-alone-redisson</code> \u72ec\u7acb\u8fde\u63a5\u63d2\u4ef6\u53ca Spring Boot 3/4 \u793a\u4f8b\u3002  <strong>[\u91cd\u8981]</strong>  fix: <a href=\"https://github.com/dromara/Sa-Token/issues/710\" rel=\"nofollow\">#710</a>\u3001<a href=\"https://gitee.com/dromara/sa-token/issues/ICE2V0\" rel=\"nofollow\">#ICE2V0</a></li>\n<li>\u65b0\u589e\uff1a\u65b0\u589e <code>sa-token-alone-redis-by-spring-boot4</code> \u63d2\u4ef6\u53ca\u793a\u4f8b\uff0c\u5b9e\u73b0 Spring Boot 4 \u4e0b\u6743\u9650\u7f13\u5b58\u4e0e\u4e1a\u52a1\u7f13\u5b58\u5206\u79bb\u3002  <strong>[\u91cd\u8981]</strong></li>\n<li>\u65b0\u589e\uff1a<code>SaTokenDaoForRedisson</code> \u652f\u6301\u6307\u5b9a Codec \uff08\u9ed8\u8ba4 <code>StringCodec</code>\uff09\uff0cupdate \u65b9\u6cd5\u6539\u7528 <code>setAndKeepTTL</code> \u539f\u5b50\u4fdd\u7559\u539f\u8fc7\u671f\u65f6\u95f4\u3002  <strong>[\u91cd\u8981]</strong>  fix: <a href=\"https://github.com/dromara/Sa-Token/issues/791\" rel=\"nofollow\">#791</a></li>\n<li>\u4fee\u590d\uff1a<code>sa-token-redis-template</code> \u53ca jdk-serializer \u5728 update key \u65f6 TTL \u504f\u79fb\u7684\u95ee\u9898\u3002  <strong>[\u91cd\u8981]</strong>  fix: <a href=\"https://gitee.com/dromara/sa-token/issues/I80P5O\" rel=\"nofollow\">#I80P5O</a>\u3001<a href=\"https://gitee.com/dromara/sa-token/issues/ICWJOQ\" rel=\"nofollow\">#ICWJOQ</a></li>\n<li>\u4fee\u590d\uff1aredis-template <code>searchData</code> \u7531 KEYS \u6539\u4e3a SCAN \u3002  <strong>[\u91cd\u8981]</strong>  fix: <a href=\"https://github.com/dromara/Sa-Token/issues/702\" rel=\"nofollow\">#702</a></li>\n<li>\u65b0\u589e\uff1aRedisTemplate Dao \u652f\u6301\u91cd\u5199 <code>wrapKey</code> \u81ea\u5b9a\u4e49\u952e\u524d\u7f00\u3002  fix: <a href=\"https://github.com/dromara/Sa-Token/issues/956\" rel=\"nofollow\">#956</a></li>\n<li>\u4fee\u590d\uff1a<code>sa-token-redis-template-jdk-serializer</code> KEEPTTL \u6cdb\u578b\u7f16\u8bd1\u9519\u8bef\u3002</li>\n<li>\u4fee\u590d\uff1aSnack3 \u5e8f\u5217\u5316\u4e0d\u518d\u5199\u5165\u7c7b\u578b\u4fe1\u606f\uff0c\u5bf9\u9f50 fastjson \u5b89\u5168\u7b56\u7565\u3002  <strong>[\u6f0f\u6d1e\u4fee\u590d]</strong></li>\n<li>\u4fee\u590d\uff1a\u96c6\u6210 JWT \u65f6 <code>extraData</code> \u7981\u6b62\u5305\u542b\u4fdd\u7559\u5b57\u6bb5\u3002  <strong>[\u4e0d\u5411\u4e0b\u517c\u5bb9]</strong></li>\n<li>\u4f18\u5316\uff1a\u5347\u7ea7 fastjson / fastjson2 \u81f3 2.0.64 \u3002</li>\n<li>\u4f18\u5316\uff1a<code>sa-token-dependencies</code> \u4e0d\u518d\u9501\u5b9a Reactor \u7248\u672c\uff0c\u907f\u514d\u4e0e Spring Cloud Gateway \u51b2\u7a81\u3002  fix: <a href=\"https://github.com/dromara/Sa-Token/issues/622\" rel=\"nofollow\">#622</a></li>\n</ul>\n</li>\n<li>\nstarter\uff1a<ul>\n<li>\u4fee\u590d\uff1aContext Filter \u6ce8\u518c REQUEST+ASYNC \uff0c\u4fee\u590d SSE/Flux \u6d41\u5f0f\u8fd4\u56de\u4e0a\u4e0b\u6587\u672a\u521d\u59cb\u5316\u3002  <strong>[\u91cd\u8981]</strong>  fix: <a href=\"https://gitee.com/dromara/sa-token/issues/IC4XFE\" rel=\"nofollow\">#IC4XFE</a>\u3001<a href=\"https://gitee.com/dromara/sa-token/issues/ICB9OJ\" rel=\"nofollow\">#ICB9OJ</a></li>\n<li>\u4fee\u590d\uff1aBoot3+ WebFlux/Gateway <code>setStatus</code> NoSuchMethodError \u3002  fix: <a href=\"https://gitee.com/dromara/sa-token/issues/IIAW1A\" rel=\"nofollow\">#IIAW1A</a>\u3001<a href=\"https://github.com/dromara/Sa-Token/issues/916\" rel=\"nofollow\">#916</a>\u3001<a href=\"https://gitee.com/dromara/sa-token/issues/IHRIBY\" rel=\"nofollow\">#IHRIBY</a></li>\n<li>\u65b0\u589e\uff1a\u65b0\u589e SSO Client Spring Boot 4 \u793a\u4f8b\u3002</li>\n<li>\u65b0\u589e\uff1a\u65b0\u589e <code>sa-token-demo-first-run</code> \u9996\u6b21\u8fd0\u884c\u5f15\u5bfc\u793a\u4f8b\u3002</li>\n<li>\u4fee\u590d\uff1ademo-ssm \u9002\u914d v1.42.0+ \u4e0a\u4e0b\u6587\u673a\u5236\u3002</li>\n</ul>\n</li>\n<li>\nSolon\uff1a<ul>\n<li>\u4f18\u5316\uff1a<code>sa-token-solon-plugin</code> \u7531 PathAnalyzer \u9002\u914d\u6539\u4e3a PathMatcher \uff0c\u4f18\u5316 Config \u793a\u4f8b\u3002  merge: <a href=\"https://gitee.com/dromara/sa-token/pulls/364\" rel=\"nofollow\">pr 364</a>  fix: <a href=\"https://gitee.com/dromara/sa-token/issues/IJTNJK\" rel=\"nofollow\">#IJTNJK</a></li>\n<li>\u4f18\u5316\uff1a\u5347\u7ea7\u4f9d\u8d56 noear-redisx \u81f3 1.8.5 \u3001noear-snack4 \u81f3 4.0.59 \u3002</li>\n</ul>\n</li>\n<li>\nSSO\uff1a<ul>\n<li>\u4fee\u590d\uff1aOAuth2/SSO <code>redirect</code> \u53c2\u6570\u7ed5\u8fc7 <code>allow-url</code> \u6821\u9a8c\u7684\u5b89\u5168\u6f0f\u6d1e\u3002  <strong>[\u91cd\u8981]</strong> <strong>[\u6f0f\u6d1e\u4fee\u590d]</strong></li>\n<li>\u65b0\u589e\uff1aSSO \u5ba2\u6237\u7aef\u65b0\u589e\u6307\u5b9a\u8d26\u53f7\u5355\u70b9\u6ce8\u9500 API \u3002</li>\n<li>\u8865\u5168\uff1a\u8865\u5168\u6700\u65b0\u7248 SSO NoSdk \u6a21\u5f0f\u5b9e\u73b0\uff0c\u65b0\u589e <code>SsoSignUtil</code>\u3002</li>\n<li>\u4fee\u590d\uff1a<code>buildServerAuthUrl</code> \u8bc6\u522b URL \u7f16\u7801\u540e\u7684 back \u53c2\u6570\uff0cback \u4e3a\u7a7a\u65f6\u8df3\u8fc7\u8ffd\u52a0\uff0c\u5e76\u589e\u5f3a\u91cd\u5b9a\u5411\u7f16\u7801/\u89e3\u7801\u5065\u58ee\u6027\u3002  fix: <a href=\"https://github.com/dromara/Sa-Token/issues/842\" rel=\"nofollow\">#842</a></li>\n<li>\u4fee\u590d\uff1a<code>getClient</code> \u7edf\u4e00\u901a\u8fc7 <code>getClients</code> \u67e5\u627e\u4ee5\u652f\u6301\u5b50\u7c7b\u8986\u76d6\u3002</li>\n<li>\u4fee\u590d\uff1aNoSdk demo \u7b7e\u540d\u6821\u9a8c\u8865\u5145\u65f6\u95f4\u7a97\u4e0e nonce \u9632\u91cd\u653e\u3002  <strong>[\u6f0f\u6d1e\u4fee\u590d]</strong></li>\n<li>\u4fee\u590d\uff1a\u8ba2\u6b63 SSO-Client \u63a5\u6536\u6d88\u606f\u63a8\u9001\u5730\u5740\u7684\u8def\u7531\u8bf4\u660e\u3002</li>\n</ul>\n</li>\n<li>\nOAuth2\uff1a<ul>\n<li>\u4fee\u590d\uff1a<code>redirect</code> \u53c2\u6570\u7ed5\u8fc7 <code>allow-url</code> \u6821\u9a8c\u7684\u5b89\u5168\u6f0f\u6d1e\u3002  <strong>[\u91cd\u8981]</strong> <strong>[\u6f0f\u6d1e\u4fee\u590d]</strong></li>\n<li>\u4fee\u6539\uff1a<code>expiresTime</code> \u4e3a -1 \u65f6\u6309\u6c38\u4e45\u6709\u6548\u5b58\u50a8 Token \u3002</li>\n<li>\u91cd\u6784\uff1a<code>doConfirm</code> \u786e\u8ba4\u6388\u6743\u6d41\u7a0b\u7edf\u4e00\u6821\u9a8c\u3002</li>\n<li>\u91cd\u6784\uff1a<code>SaOAuth2Dao</code> \u6539\u7528\u5e26 Class \u53c2\u6570\u7684 <code>getObject</code> \u53cd\u5e8f\u5217\u5316\u3002  fix: <a href=\"https://gitee.com/dromara/sa-token/issues/IK5GYU\" rel=\"nofollow\">#IK5GYU</a></li>\n<li>\u4fee\u590d\uff1aOAuth2 demo \u62d2\u7edd\u6388\u6743\u65f6\u56de\u4f20 state \u3002</li>\n<li>\u65b0\u589e\uff1aOAuth2 \u7ae0\u8282\u8865\u5145\u6570\u636e\u4e92\u901a\u540e\u7684 token \u8fc7\u671f\u7b56\u7565\u8bf4\u660e\u3002</li>\n</ul>\n</li>\n<li>\n\u6587\u6863\uff1a<ul>\n<li>\u4fee\u6539\uff1a\u5168\u4ed3\u5e93\u57df\u540d <a href=\"http://sa-token.cc\" rel=\"nofollow\">sa-token.cc</a> \u7edf\u4e00\u8fc1\u79fb\u81f3 <a href=\"http://sa-token.com\" rel=\"nofollow\">sa-token.com</a> \u3002  <strong>[\u91cd\u8981]</strong></li>\n<li>\u65b0\u589e\uff1a\u4e0a\u7ebf\u72ec\u7acb\u535a\u5ba2\u7cfb\u7edf\uff0c\u6536\u5f55\u539f\u521b\u6587\u7ae0\u3002  <strong>[\u91cd\u8981]</strong></li>\n<li>\u65b0\u589e\uff1a\u6587\u6863\u7ad9\u70b9\u591a\u8bed\u8a00\u5207\u6362\uff08\u57fa\u4e8e translate.js \uff09\u3002  <strong>[\u91cd\u8981]</strong></li>\n<li>\u65b0\u589e\uff1aREADME \u591a\u8bed\u8a00\u7248\u672c\uff08\u82f1\u6587\u3001\u65e5\u6587\u3001\u97e9\u6587\u3001\u4fc4\u6587\u3001\u7e41\u4f53\u4e2d\u6587\uff09\u4e0e\u5207\u6362\u5165\u53e3\u3002  <strong>[\u91cd\u8981]</strong></li>\n<li>\u65b0\u589e\uff1a\u65b0\u589e <code><a href=\"http://SECURITY.md\" rel=\"nofollow\">SECURITY.md</a></code> \u5b89\u5168\u7b56\u7565\u53ca\u8054\u7cfb\u90ae\u7bb1\u3002  <strong>[\u91cd\u8981]</strong>  merge: <a href=\"https://github.com/dromara/Sa-Token/pull/933\" rel=\"nofollow\">pr 933</a>  fix: <a href=\"https://github.com/dromara/Sa-Token/issues/932\" rel=\"nofollow\">#932</a>\u3001<a href=\"https://github.com/dromara/Sa-Token/issues/877\" rel=\"nofollow\">#877</a></li>\n<li>\u65b0\u589e\uff1a\u6587\u6863\u7ad9\u70b9\u6697\u8272\u4e3b\u9898\u5207\u6362\uff0c\u652f\u6301 5 \u79cd IDE \u98ce\u683c\u3002</li>\n<li>\u65b0\u589e\uff1a\u6587\u6863\u7248\u672c\u9009\u62e9\u5668\u6539\u4e3a\u52a8\u6001\u52a0\u8f7d\uff08<code>all-version-common.js</code>\uff09\u3002  merge: <a href=\"https://github.com/dromara/Sa-Token/pull/928\" rel=\"nofollow\">pr 928</a>  fix: <a href=\"https://github.com/dromara/Sa-Token/issues/900\" rel=\"nofollow\">#900</a></li>\n<li>\u65b0\u589e\uff1a\u65b0\u589e\u6e90\u7801\u8fd0\u884c\u6307\u5357\u6587\u6863\u3002</li>\n<li>\u65b0\u589e\uff1a\u65b0\u589e\u300c Sa-Token \u96c6\u6210 Demos \u793a\u4f8b\u5927\u5168\u4e0b\u8f7d\u300d\u6587\u6863\u3002</li>\n<li>\u65b0\u589e\uff1a\u5bfc\u822a\u680f\u589e\u52a0\u5b89\u5168\u63a8\u8350\u4e0e\u6848\u4f8b\u4e0b\u62c9\u83dc\u5355\u3002</li>\n<li>\u4f18\u5316\uff1a\u6587\u6863\u7ad9\u70b9\u6574\u4f53\u4f18\u5316\uff08\u4fa7\u8fb9\u680f\u3001\u9996\u9875\u3001\u6350\u8d60\u9875\u3001\u5bfc\u822a\u4ea4\u4e92\u3001API \u624b\u518c\u7b49\uff09\u3002</li>\n<li>\u540c\u6b65\uff1a\u540c\u6b65\u516c\u4f17\u53f7\u6587\u7ae0\u5217\u8868\u3001\u535a\u5ba2\u5217\u8868\u3001\u8d5e\u52a9\u8005\u540d\u5355\u3001\u4f01\u4e1a\u767b\u8bb0\u6848\u4f8b\u3002</li>\n<li>\u8865\u5145\uff1a\u8865\u5145 SSE/Flux \u6d41\u5f0f\u8fd4\u56de\u5e38\u89c1\u95ee\u9898\uff1b\u8865\u5145\u6309\u914d\u7f6e\u51b3\u5b9a\u662f\u5426\u542f\u7528 Redis \u7684\u793a\u4f8b\u3002  fix: <a href=\"https://gitee.com/dromara/sa-token/issues/I9I4ZG\" rel=\"nofollow\">#I9I4ZG</a></li>\n<li>\u4fee\u590d\uff1a\u8ba2\u6b63 API \u624b\u518c\u3001SSO/OAuth2/WebFlux/Dubbo \u7b49\u6587\u6863\u9519\u6f0f\u3002</li>\n</ul>\n</li>\n<li>\n\u5176\u5b83\uff1a<ul>\n<li>\u65b0\u589e\uff1a\u65b0\u589e\u4e50\u4e4b\u8005 java B \u7ad9\u89c6\u9891\u6559\u7a0b\u94fe\u63a5\u3002  <strong>[\u91cd\u8981]</strong></li>\n<li>\u4f18\u5316\uff1a\u7edf\u4e00\u65e5\u5fd7\u6587\u6848\u7528\u8bcd\uff0c\u300c\u5e10\u53f7\u300d\u6539\u4e3a\u300c\u8d26\u53f7\u300d\u3002</li>\n<li>\u4f18\u5316\uff1a\u7edf\u4e00 token \u7eed\u671f\u76f8\u5173\u6ce8\u91ca\u63aa\u8f9e\u3002</li>\n<li>\u4fee\u590d\uff1a\u4fee\u6b63 ConcurrentHashMap \u7684\u9519\u8bef import \u8def\u5f84\u3002  merge: <a href=\"https://gitee.com/dromara/sa-token/pulls/359\" rel=\"nofollow\">pr 359</a></li>\n</ul>\n</li>\n</ul>\n<p>\u66f4\u65b0\u65e5\u5fd7\u5728\u7ebf\u6587\u6863\u76f4\u8fbe\u94fe\u63a5\uff1a<a href=\"https://sa-token.com/doc.html#/more/update-log\" rel=\"nofollow\">https://sa-token.com/doc.html#/more/update-log</a></p>\n<h3>\ud83c\udf1f \u5176\u5b83</h3>\n<p>\u4ee3\u7801\u4ed3\u5e93\u5730\u5740\uff1a <a href=\"https://gitee.com/dromara/sa-token\" rel=\"nofollow\">https://gitee.com/dromara/sa-token</a></p>\n<p>\u6846\u67b6\u529f\u80fd\u7ed3\u6784\u56fe\uff1a</p>\n<p><img alt=\"js\" class=\"embedded_image\" loading=\"lazy\" referrerpolicy=\"no-referrer\" rel=\"noreferrer\" src=\"https://res.dev33.cn/sa-token-blog/img/common/sa-token-js4--2.png\"/></p>\n"
    }, 
    {
      "author": {
        "url": "https://www.v2ex.com/member/g632104866", 
        "name": "g632104866", 
        "avatar": "https://cdn.v2ex.com/avatar/01d5/38d4/510131_large.png?m=1783481882"
      }, 
      "url": "https://www.v2ex.com/t/1235831", 
      "title": "\u53ef\u4ee5\u4e0b\u7ebf Nexus \u4e86\uff1a\u7eaf\u5f00\u6e90\u5236\u54c1\u4ed3\u5e93 kkRepo v0.9.0 \u53d1\u5e03\uff0c\u65b0\u589e Alpine\u3001Hugging Face Models \u4e0e\u5168\u5c40\u641c\u7d22", 
      "id": "https://www.v2ex.com/t/1235831", 
      "date_published": "2026-08-20T03:46:08+00:00", 
      "content_html": "<p>\u4e0a\u6b21\u5728 V2EX \u8ddf\u5927\u5bb6\u5206\u4eab\u4e86 kkRepo v0.8.0 \uff0c\u8fd9\u6b21 v0.9.0 \u4e5f\u6b63\u5f0f\u53d1\u5e03\u4e86\u3002</p>\n<p>\u8fd9\u4e00\u7248\u4e0d\u53ea\u662f\u7ee7\u7eed\u589e\u52a0\u4ed3\u5e93\u683c\u5f0f\uff0c\u8fd8\u8865\u4e0a\u4e86\u5168\u5c40\u5236\u54c1\u641c\u7d22\u3001\u7248\u672c\u66f4\u65b0\u63d0\u9192\u3001\u4ee3\u7406\u91cd\u5b9a\u5411\u767d\u540d\u5355\uff0c\u4ee5\u53ca\u4e00\u6279\u754c\u9762\u548c\u7a33\u5b9a\u6027\u6539\u8fdb\u3002</p>\n<ul>\n<li>\u9879\u76ee\u5730\u5740\uff1a<a href=\"https://github.com/klboke/kkRepo\" rel=\"nofollow\">https://github.com/klboke/kkRepo</a></li>\n<li>v0.9.0 Release\uff1a<a href=\"https://github.com/klboke/kkRepo/releases/tag/v0.9.0\" rel=\"nofollow\">https://github.com/klboke/kkRepo/releases/tag/v0.9.0</a></li>\n</ul>\n<h2>kkRepo \u662f\u4ec0\u4e48\uff1f</h2>\n<p>kkRepo \u662f\u4e00\u6b3e\u793e\u533a\u9a71\u52a8\u3001\u5b8c\u5168\u5f00\u6e90\u7684\u81ea\u6258\u7ba1\u5236\u54c1\u4ed3\u5e93\uff0c\u76ee\u6807\u662f\u89e3\u51b3 Sonatype Nexus Community Edition \u5728\u683c\u5f0f\u652f\u6301\u3001\u5bb9\u91cf\u9650\u5236\u3001\u8fc1\u79fb\u548c\u9ad8\u53ef\u7528\u90e8\u7f72\u7b49\u65b9\u9762\u7684\u75db\u70b9\u3002</p>\n<p>\u9879\u76ee\u56f4\u7ed5 Nexus \u7684\u5ba2\u6237\u7aef\u534f\u8bae\u3001\u6743\u9650\u6a21\u578b\u548c <code>/repository/&lt;repo&gt;/...</code> URL \u5e03\u5c40\u5b9e\u73b0\u517c\u5bb9\uff0c\u5e76\u63d0\u4f9b\u5b58\u91cf\u4ed3\u5e93\u3001\u5236\u54c1\u3001\u7528\u6237\u3001\u89d2\u8272\u548c\u6743\u9650\u8fc1\u79fb\u80fd\u529b\uff0c\u5c3d\u91cf\u8ba9\u539f\u6709\u5ba2\u6237\u7aef\u914d\u7f6e\u4e0e CI \u6d41\u7a0b\u4fdd\u6301\u4e0d\u53d8\u3002</p>\n<p>\u76ee\u524d\u5df2\u7ecf\u652f\u6301 20+ \u79cd\u4ed3\u5e93\u683c\u5f0f\uff0c\u5305\u62ec\uff1a</p>\n<p>Maven \u3001npm \u3001PyPI \u3001Go \u3001Helm \u3001Cargo/Rust \u3001Dart/Pub \u3001Composer/PHP \u3001Terraform \u3001Swift Package Registry \u3001Ansible Galaxy \u3001Conda \u3001APT/Debian \u3001Conan 2 \u3001Alpine/APK \u3001Hugging Face Models \u3001Docker/OCI \u3001NuGet \u3001RubyGems \u3001Yum \u548c Raw \u3002</p>\n<p>\u4e0d\u540c\u683c\u5f0f\u6309\u534f\u8bae\u80fd\u529b\u652f\u6301 hosted \u3001proxy \u6216 group \u4ed3\u5e93\u3002</p>\n<h2>v0.9.0 \u4e3b\u8981\u66f4\u65b0</h2>\n<h3>1. \u65b0\u589e Alpine / APK \u4ed3\u5e93</h3>\n<p>\u672c\u6b21\u65b0\u589e Alpine/APK \u7684 hosted \u3001proxy \u548c group \u4e09\u79cd\u4ed3\u5e93\u7c7b\u578b\uff1a</p>\n<ul>\n<li>Hosted \u652f\u6301 APK v2 \u8f6f\u4ef6\u5305\u53d1\u5e03\u548c\u7b7e\u540d\u7d22\u5f15\u751f\u6210</li>\n<li>Proxy \u652f\u6301\u4e0a\u6e38\u7d22\u5f15\u900f\u4f20\uff0c\u4ee5\u53ca\u9a8c\u7b7e\u540e\u91cd\u65b0\u7b7e\u540d</li>\n<li>Group \u652f\u6301\u6309\u6210\u5458\u987a\u5e8f\u7edf\u4e00\u89e3\u6790\u591a\u4e2a Alpine \u4ed3\u5e93</li>\n<li>\u652f\u6301 Browse \u3001Search \u3001Cleanup \u548c\u5b89\u5168\u626b\u63cf</li>\n<li>\u4f7f\u7528\u771f\u5b9e <code>apk</code> \u5ba2\u6237\u7aef\u9a8c\u8bc1 <code>update</code>\u3001<code>search</code>\u3001<code>fetch</code>\u3001<code>add</code> \u548c <code>upgrade</code></li>\n<li>\u652f\u6301\u4ece\u7ecf\u8fc7\u9a8c\u8bc1\u7684 Nexus 3.94 \u6570\u636e\u7ed3\u6784\u8fc1\u79fb</li>\n</ul>\n<h3>2. \u65b0\u589e Hugging Face Models \u4ee3\u7406\u4ed3\u5e93</h3>\n<p>\u73b0\u5728\u53ef\u4ee5\u628a kkRepo \u4f5c\u4e3a\u56e2\u961f\u5185\u90e8\u7684 Hugging Face Models \u4ee3\u7406\uff1a</p>\n<ul>\n<li>\u652f\u6301\u901a\u8fc7 <code>HF_ENDPOINT</code> \u63a5\u5165</li>\n<li>\u652f\u6301 <code>hf download</code>\u3001<code>huggingface_hub</code> \u548c <code>snapshot_download</code></li>\n<li>\u652f\u6301 Transformers \u4e0e Diffusers \u4e0b\u8f7d\u6a21\u578b</li>\n<li>\u670d\u52a1\u7aef\u6865\u63a5 Git LFS \u4e0e Xet \u5b58\u50a8</li>\n<li>\u6309 commit \u56fa\u5b9a\u5e76\u7f13\u5b58\u6a21\u578b\u6587\u4ef6\uff0c\u907f\u514d mutable revision \u5e26\u6765\u7684\u4e0d\u786e\u5b9a\u6027</li>\n<li>\u652f\u6301\u591a\u526f\u672c\u534f\u8c03\u3001Browse \u3001Search \u3001Cleanup \u548c\u5b89\u5168\u626b\u63cf</li>\n</ul>\n<p>\u5f53\u524d\u7248\u672c\u805a\u7126 Models proxy \uff0c\u4e0d\u5305\u542b hosted/group \u3001Datasets \u3001Spaces \u548c\u63a8\u7406 API \u3002</p>\n<h3>3. \u65b0\u589e\u5e26\u6743\u9650\u6821\u9a8c\u7684\u5168\u5c40\u5236\u54c1\u641c\u7d22</h3>\n<p>Browse \u548c Admin \u73b0\u5728\u90fd\u53ef\u4ee5\u8de8\u4ed3\u5e93\u641c\u7d22\u5236\u54c1\uff1a</p>\n<ul>\n<li>\u641c\u7d22\u524d\u6821\u9a8c\u4ed3\u5e93\u6743\u9650\u548c Content Selector</li>\n<li>\u65e0\u6743\u9650\u7684\u4ed3\u5e93\u4e0e\u5236\u54c1\u4e0d\u4f1a\u51fa\u73b0\u5728\u7ed3\u679c\u4e2d</li>\n<li>\u4f7f\u7528\u7a33\u5b9a\u7684 keyset pagination</li>\n<li>\u9488\u5bf9\u5927\u89c4\u6a21 MySQL \u6570\u636e\u505a\u4e86\u81ea\u9002\u5e94\u67e5\u8be2\u4f18\u5316</li>\n<li>\u4fee\u590d\u4e86 MySQL FULLTEXT \u65e0\u6cd5\u5339\u914d\u77ed\u8bcd\u5750\u6807\u7684\u95ee\u9898</li>\n</ul>\n<p>\u8fd9\u9879\u529f\u80fd\u89e3\u51b3\u4e86\u4ed3\u5e93\u6570\u91cf\u8f83\u591a\u65f6\uff0c\u9700\u8981\u5148\u8fdb\u5165\u67d0\u4e2a\u4ed3\u5e93\u624d\u80fd\u67e5\u627e\u5236\u54c1\u7684\u95ee\u9898\u3002</p>\n<h3>4. \u5176\u4ed6\u6539\u8fdb</h3>\n<ul>\n<li>\u65b0\u589e\u57fa\u4e8e GitHub Release \u7684\u7248\u672c\u66f4\u65b0\u63d0\u9192</li>\n<li>Proxy \u4ed3\u5e93\u53ef\u4ee5\u914d\u7f6e\u53ef\u4fe1\u7684\u91cd\u5b9a\u5411\u76ee\u6807\u57df\u540d\uff0c\u540c\u65f6\u4fdd\u7559\u5168\u5c40 SSRF \u9632\u62a4</li>\n<li>\u7edf\u4e00\u8282\u70b9\u672c\u5730 TTL \u7f13\u5b58\u62bd\u8c61\uff0c\u7ee7\u7eed\u4fdd\u6301\u591a\u526f\u672c\u4e0b\u7f13\u5b58\u53ef\u4e22\u5931\u3001\u53ef\u91cd\u5efa</li>\n<li>\u4f18\u5316 Browse \u4ed3\u5e93\u8be6\u60c5\u3001OIDC/LDAP \u3001\u8d26\u53f7\u3001\u767b\u5f55\u3001\u9876\u90e8\u5bfc\u822a\u548c\u6b22\u8fce\u9875</li>\n<li>\u4fee\u590d URL \u4e2d\u7ecf\u8fc7\u767e\u5206\u53f7\u7f16\u7801\u7684 <code>+</code> \u88ab\u9519\u8bef\u89e3\u6790\u4e3a\u7a7a\u683c\u7684\u95ee\u9898</li>\n<li>\u4fee\u590d\u957f\u4ee3\u7406\u5730\u5740\u5199\u5165\u5ba1\u8ba1\u5b57\u6bb5\u65f6\u53ef\u80fd\u5bfc\u81f4 MySQL \u8bf7\u6c42\u5931\u8d25\u7684\u95ee\u9898</li>\n</ul>\n<h2>\u73b0\u6709\u6838\u5fc3\u80fd\u529b</h2>\n<p>\u9664\u4ed3\u5e93\u683c\u5f0f\u5916\uff0ckkRepo \u76ee\u524d\u8fd8\u652f\u6301\uff1a</p>\n<ul>\n<li>Nexus \u5b58\u91cf\u4ed3\u5e93\u3001\u5236\u54c1\u3001\u7528\u6237\u3001\u89d2\u8272\u548c\u6743\u9650\u8fc1\u79fb</li>\n<li>Local \u3001LDAP \u3001OIDC \u8ba4\u8bc1\u4e0e\u7ec6\u7c92\u5ea6\u6743\u9650\u7ba1\u7406</li>\n<li>CycloneDX SBOM \u3001\u6f0f\u6d1e\u626b\u63cf\u3001\u7b56\u7565\u3001\u8c41\u514d\u548c\u4e0b\u8f7d\u963b\u65ad</li>\n<li>\u9762\u5411\u5168\u90e8\u4ed3\u5e93\u683c\u5f0f\u7684 Cleanup Policy</li>\n<li>Prometheus \u6307\u6807\u548c Grafana \u9762\u677f</li>\n<li>MySQL \u6216 PostgreSQL \u5143\u6570\u636e\u5b58\u50a8</li>\n<li>OSS \u3001S3 \u548c File blob storage</li>\n<li>JVM \u4e0e GraalVM Native \u4e24\u79cd\u8fd0\u884c\u65f6</li>\n<li>\u591a\u526f\u672c\u9ad8\u53ef\u7528\u90e8\u7f72</li>\n<li>\u6309\u4ed3\u5e93\u914d\u7f6e HTTP \u6216 SOCKS5 \u51fa\u7ad9\u4ee3\u7406</li>\n</ul>\n<p>Native \u7248\u672c\u901a\u5e38\u7ea6 1 \u79d2\u542f\u52a8\u5c31\u7eea\uff0c\u5185\u5b58\u5360\u7528\u4f4e\u4e8e 200 MB \u3002</p>\n<h2>\u5feb\u901f\u4f53\u9a8c</h2>\n<p>\u673a\u5668\u4e0a\u5b89\u88c5\u597d Docker \u4e0e Docker Compose \u540e\uff0c\u6267\u884c\uff1a</p>\n<pre><code class=\"language-bash\">curl -fsSL https://raw.githubusercontent.com/klboke/kkrepo/main/scripts/quickstart.sh | bash\n</code></pre>\n<p>\u542f\u52a8 Native \u7248\u672c\uff1a</p>\n<pre><code class=\"language-bash\">curl -fsSL https://raw.githubusercontent.com/klboke/kkrepo/main/scripts/quickstart.sh | KKREPO_RUNTIME=native bash\n</code></pre>\n<p>\u542f\u52a8\u540e\u8bbf\u95ee\uff1a</p>\n<ul>\n<li>\u7ba1\u7406\u63a7\u5236\u53f0\uff1a<code>http://127.0.0.1:19090/admin/</code></li>\n<li>\u7528\u6237\u4fa7\u6d4f\u89c8\u5668\uff1a<code>http://127.0.0.1:19090/browse/</code></li>\n<li>\u5065\u5eb7\u68c0\u67e5\uff1a<code>http://127.0.0.1:19091/actuator/health</code></li>\n</ul>\n<p>\u9996\u6b21\u8fdb\u5165\u9875\u9762\u65f6\uff0c\u5728 UI \u4e2d\u521b\u5efa <code>Local/admin</code> \u7ba1\u7406\u5458\u5bc6\u7801\u3002</p>\n<p>Quickstart \u9ed8\u8ba4\u4f7f\u7528 File blob storage \uff0c\u9002\u5408\u672c\u5730\u8bd5\u7528\uff1b\u751f\u4ea7\u73af\u5883\u5efa\u8bae\u4f7f\u7528\u72ec\u7acb\u7684 MySQL/PostgreSQL \u548c OSS/S3 \u3002</p>\n<p>\u5bb9\u5668\u955c\u50cf\uff1a</p>\n<pre><code class=\"language-text\">ghcr.io/klboke/kkrepo:0.9.0\nghcr.io/klboke/kkrepo:0.9.0-native\nghcr.io/klboke/kkrepo-scanner:0.9.0\n</code></pre>\n<p>\u5747\u63d0\u4f9b Linux AMD64 \u548c ARM64 \u955c\u50cf\u3002</p>\n<h2>\u4ece v0.8.0 \u5347\u7ea7</h2>\n<p>v0.8.0 \u7684 MySQL \u548c PostgreSQL \u90e8\u7f72\u53ef\u4ee5\u901a\u8fc7 Flyway V46\u2013V48 \u539f\u5730\u5347\u7ea7\u3002</p>\n<p>\u5347\u7ea7\u524d\u8bf7\u540c\u65f6\u5907\u4efd\u5173\u7cfb\u6570\u636e\u5e93\u548c blob store \uff0c\u5e76\u7b49\u5f85\u6570\u636e\u5e93\u8fc1\u79fb\u5b8c\u6210\u540e\u518d\u6062\u590d\u6d41\u91cf\u3002\u65b0 schema \u5e94\u7528\u540e\uff0c\u4e0d\u8981\u7ee7\u7eed\u6df7\u5408\u8fd0\u884c v0.8.0 \u4e0e v0.9.0 \u5b9e\u4f8b\u3002</p>\n<p>\u7ec4\u4ef6\u6570\u636e\u91cf\u8f83\u5927\u7684\u90e8\u7f72\uff0c\u5efa\u8bae\u5728\u4f4e I/O \u65f6\u6bb5\u6267\u884c V47 \u7d22\u5f15\u8fc1\u79fb\u3002</p>\n<p>\u9879\u76ee\u76ee\u524d\u4ecd\u5904\u4e8e 1.0 \u4e4b\u524d\uff0c\u751f\u4ea7\u5347\u7ea7\u524d\u8bf7\u5148\u9605\u8bfb\u5b8c\u6574 Release Notes \u3002</p>\n<p>\u5982\u679c\u4f60\u6b63\u5728\u4f7f\u7528 Nexus \uff0c\u4e5f\u6b22\u8fce\u62ff\u771f\u5b9e\u4ed3\u5e93\u548c\u5ba2\u6237\u7aef\u6d4b\u8bd5 kkRepo \u3002\u9047\u5230\u517c\u5bb9\u6027\u95ee\u9898\u6216\u7f3a\u5c11\u7684\u4ed3\u5e93\u683c\u5f0f\uff0c\u53ef\u4ee5\u76f4\u63a5\u5728 GitHub \u63d0 Issue \u3002</p>\n<p>\u5982\u679c\u9879\u76ee\u5bf9\u4f60\u6709\u5e2e\u52a9\uff0c\u4e5f\u6b22\u8fce Star \u3001\u53cd\u9988\u548c\u53c2\u4e0e\u8d21\u732e\u3002</p>\n"
    }, 
    {
      "author": {
        "url": "https://www.v2ex.com/member/ko1haha", 
        "name": "ko1haha", 
        "avatar": "https://cdn.v2ex.com/gravatar/336fa93f33fc8bb3b2360948271327a6?s=73&d=retro"
      }, 
      "url": "https://www.v2ex.com/t/1235141", 
      "title": "Java \u8f6c native \u7a76\u7adf\u884c\u4e0d\u884c\uff1f\u65e0\u9700\u7cbe\u901a graalvm native-image \u914d\u7f6e\u5c31\u80fd\u6253\u5305 native exe \u65b9\u6cd5\u5206\u4eab\u3002", 
      "id": "https://www.v2ex.com/t/1235141", 
      "date_published": "2026-08-17T15:41:53+00:00", 
      "content_html": "<p>\u7f16\u8bd1\u4e86\u4e00\u5929\u4e00\u591c\uff01</p>\n<p>\u603b\u7b97\u628a\u6211\u7684\u8001 javafx \u9879\u76ee\u7f16\u8bd1\u6210\u6b63\u5b97\u7684 exe \u4e86\u3002</p>\n<p>\u82b1\u8d39\u8fd9\u4e48\u957f\u65f6\u95f4\uff0c\u4e5f\u6709\u6211\u8bbe\u5907\u7684\u95ee\u9898\u3002</p>\n<p>8G \u4e0a\u7f51\u672c\uff08\u4e3b\u529b\u673a\u8dd1\u522b\u7684\uff09\uff0c\u7a7a\u95f2\u5185\u5b58\u53ea\u6709\u4e00\u534a\u3002 </p>\n<p>\u914d\u7f6e\u70b9\u865a\u62df\u5185\u5b58\u3001\u6362\u6210 opencode web \u7248\u672c\uff0c\u817e\u51fa\u70b9\u5185\u5b58\uff0c\u7ee7\u7eed\u641e\u3002</p>\n<p>\u6ca1\u9519\uff0cagent \u65f6\u4ee3\uff0c\u8c01\u8fd8\u4e00\u4e2a\u4eba\u82e6\u54c8\u54c8\u5730\u7f16\u8bd1\u554a\u3002  </p>\n<p>\u5f53\u7136\u662f\u8ba9\u4eba\u5de5\u667a\u80fd\u7ed9\u6211\u6253\u5de5\u3002</p>\n<p>\u65b9\u6cd5\u5c31\u662f\uff1a\u5148\u51c6\u5907\u4e00\u4efd\u53ef\u4ee5\u8fd0\u884c\u7684 java \u7248\u672c\uff0c\u8ba9 opencode \u8c03\u7528 java.exe \u542f\u52a8\u4e3b\u7c7b\u3002</p>\n<p>\u7136\u540e\uff0c\u8ba9\u5b83\u628a\u5341\u51e0\u4e2a jar \u7528 native-image \u7f16\u8bd1\u6210 exe \uff0c\u6210\u529f\u540e opencode \u81ea\u52a8\u8c03\u8d77\u5e76\u5206\u6790\u9519\u8bef\uff0c\u4e0d\u65ad\u8fed\u4ee3\u3002</p>\n<p>\u8fd9\u5f88\u5389\u5bb3\uff0c\u6211\u90fd\u4e0d\u77e5\u9053\u54ea\u91cc\u53bb\u627e log, \u624b\u52a8\u628a exe \u62d6\u8fdb cmd \u4e5f\u6ca1\u6709\u65e5\u5fd7\u3002</p>\n<p>\u7ec8\u4e8e\uff0cjavafx \u7684\u7a97\u53e3\u8dd1\u51fa\u6765\u4e86\uff0c\u91cc\u9762 webview (webkit) \u80fd\u663e\u793a\uff0c\u4f46\u4e00\u64cd\u4f5c\u5c31\u95ea\u9000\u5d29\u6e83\u3002</p>\n<p>\u7d27\u63a5\u7740\u53d1\u73b0\uff0copencode \u7adf\u7136\u5728\u5206\u6790\u6c47\u7f16\u6307\u4ee4\u2026\u2026</p>\n<p>\u7ee7\u7eed\uff0c\u81ea\u52a8\u8fed\u4ee3\u2026\u2026</p>\n<p>\u7f16\u8bd1\u4e00\u6b21\u534a\u5c0f\u65f6\uff0c\u5fc5\u987b\u4ea4\u7ed9\u6ca1\u6709\u611f\u60c5\u7684\u673a\u5668\u4eba\uff01</p>\n<p>\u7ee7\u7eed\u8dd1\u4e86\u4e00\u4e24\u4e2a\u5c0f\u65f6\uff0c\u7ec8\u4e8e\u4fee\u597d\u4e86\uff0c\u64cd\u4f5c webview \u5185\u5bb9\u4e0d\u518d\u5d29\u6e83\uff08\u4f46\u662f\u5185\u5b58\u6d6e\u52a8\u660e\u663e\uff0c\u6bd4 java8 \u8fd8\u7cd9\uff0c\u7b80\u5355\u64cd\u4f5c\u7adf\u7136\u5728 300mb-900mb \u95f4\u6d6e\u52a8\uff01\uff09\u3002</p>\n<p>\u4ecd\u6709\u5f88\u591a\u529f\u80fd\u7f3a\u5931\uff1a\u6253\u4e0d\u5f00\u7cfb\u7edf\u7684\u6587\u4ef6\u9009\u62e9\u5668\uff08 awt/jna \u53c8\u51fa\u95ee\u9898\uff1f\uff09\u3001\u6ca1\u6709\u6b63\u786e\u542f\u52a8 web \u670d\u52a1(\u5f00\u7740\u7eaf\u8840 java \u7248\u966a\u8dd1\uff01)\u3002</p>\n<p>\u8fd8\u662f\u5f97\u653e\u5f03 javafx \u4e86\uff0c\u6ca1\u5565\u4f18\u52bf\u3002</p>\n<p>\u5982\u679c\u820d\u4e0d\u5f97\u751f\u6001\u7684\u8bdd\uff0c\u5c31\u505a\u6210 web \u670d\u52a1\u3002</p>\n<p>\u660e\u5929\u518d\u8bd5\uff0c\u673a\u5668\u592a\u70eb\u4e86\u3002</p>\n"
    }, 
    {
      "author": {
        "url": "https://www.v2ex.com/member/CodeCodeStudy", 
        "name": "CodeCodeStudy", 
        "avatar": "https://cdn.v2ex.com/gravatar/7b00614f3692cd7836df222ade2d1f07?s=73&d=retro"
      }, 
      "url": "https://www.v2ex.com/t/1232291", 
      "date_modified": "2026-08-05T09:58:06+00:00", 
      "content_html": "<p><a href=\"https://github.com/alibaba/fastjson\" rel=\"nofollow\">https://github.com/alibaba/fastjson</a></p>\n<p>This repository was archived by the owner on Jul 29, 2026. It is now read-only. </p>\n<p>26 \u5e74 7 \u6708 29 \u65e5 gg \u4e86</p>\n", 
      "date_published": "2026-08-05T09:56:25+00:00", 
      "title": "fastjson \u5c45\u7136\u505c\u6b62\u7ef4\u62a4\u4e86", 
      "id": "https://www.v2ex.com/t/1232291"
    }, 
    {
      "author": {
        "url": "https://www.v2ex.com/member/markliu2013", 
        "name": "markliu2013", 
        "avatar": "https://cdn.v2ex.com/avatar/21a2/3df3/91988_large.png?m=1668140797"
      }, 
      "url": "https://www.v2ex.com/t/1229840", 
      "title": "happens-before \u8be6\u89e3", 
      "id": "https://www.v2ex.com/t/1229840", 
      "date_published": "2026-07-26T02:21:29+00:00", 
      "content_html": "<h1>Java \u5e76\u53d1\u6838\u5fc3\uff1a\u4e3a\u4ec0\u4e48\u9700\u8981 happens-before \uff1f</h1>\n<p>\u5f88\u591a\u4eba\u5728\u5b66\u4e60 Java \u5e76\u53d1\u7684\u65f6\u5019\uff0c\u4f1a\u76f4\u63a5\u5f00\u59cb\u80cc\u8bf5\u77e5\u8bc6\u70b9\uff1a</p>\n<ul>\n<li><code>volatile</code> \u4fdd\u8bc1\u53ef\u89c1\u6027</li>\n<li><code>synchronized</code> \u4fdd\u8bc1\u7ebf\u7a0b\u5b89\u5168</li>\n<li><code>Lock</code> \u53ef\u4ee5\u624b\u52a8\u52a0\u9501</li>\n<li>happens-before \u5b58\u5728\u516b\u6761\u89c4\u5219</li>\n</ul>\n<p>\u4f46\u7edd\u5927\u591a\u6570\u4eba\u90fd\u6ca1\u6709\u5f04\u61c2\u5e95\u5c42\u6839\u6e90\u95ee\u9898\uff1a</p>\n<ol>\n<li>\u4e3a\u4ec0\u4e48\u4f1a\u8bde\u751f happens-before \u8fd9\u5957\u673a\u5236\uff1f</li>\n<li>\u4e3a\u4ec0\u4e48\u6070\u597d\u662f\u8fd9\u516b\u6761\u89c4\u5219\uff0c\u800c\u975e\u5341\u6761\u3001\u4e8c\u5341\u6761\uff1f</li>\n<li>happens-before \u4ece\u672c\u8d28\u4e0a\u89e3\u51b3\u4e86\u8ba1\u7b97\u673a\u5e76\u53d1\u4e2d\u7684\u4ec0\u4e48\u75db\u70b9\uff1f</li>\n</ol>\n<p>\u672c\u6587\u7ad9\u5728\u8bbe\u8ba1\u8005\u89c6\u89d2\uff0c\u9010\u5c42\u62c6\u89e3 Java \u5185\u5b58\u6a21\u578b\uff08 JMM \uff09\u4e2d happens-before \u7684\u8bbe\u8ba1\u521d\u8877\u4e0e\u5e95\u5c42\u539f\u7406\u3002</p>\n<h2>\u4e00\u3001\u65e0\u6027\u80fd\u4f18\u5316\u7684\u7406\u60f3\u73af\u5883\uff1a\u6839\u672c\u4e0d\u9700\u8981 happens-before</h2>\n<p>\u5047\u8bbe\u8ba1\u7b97\u673a\u8fd0\u884c\u73af\u5883\u6ee1\u8db3\u4ee5\u4e0b\u7406\u60f3\u5316\u6761\u4ef6\uff1a</p>\n<ol>\n<li>CPU \u4e25\u683c\u4f9d\u7167\u4ee3\u7801\u4e66\u5199\u987a\u5e8f\u4e32\u884c\u6267\u884c\u6307\u4ee4</li>\n<li>\u4e0d\u5b58\u5728 CPU \u591a\u7ea7\u7f13\u5b58</li>\n<li>\u7f16\u8bd1\u5668\u4e0d\u4f1a\u505a\u4efb\u4f55\u4ee3\u7801\u4f18\u5316</li>\n<li>\u5168\u7a0b\u6ca1\u6709\u6307\u4ee4\u91cd\u6392\u884c\u4e3a</li>\n<li>\u6240\u6709\u7ebf\u7a0b\u76f4\u63a5\u8bfb\u5199\u540c\u4e00\u4efd\u4e3b\u5185\u5b58\u6570\u636e</li>\n</ol>\n<p>\u6b64\u65f6\u591a\u7ebf\u7a0b\u4ea4\u4e92\u903b\u8f91\u5341\u5206\u7b80\u5355\uff1a</p>\n<ul>\n<li>\u7ebf\u7a0b A\uff1a\u4fee\u6539\u5171\u4eab\u53d8\u91cf</li>\n<li>\u7ebf\u7a0b B\uff1a\u8bfb\u53d6\u8be5\u5171\u4eab\u53d8\u91cf</li>\n</ul>\n<p>\u7ebf\u7a0b B<strong>\u4e00\u5b9a\u53ef\u4ee5\u8bfb\u53d6\u5230\u7ebf\u7a0b A \u4fee\u6539\u540e\u7684\u6700\u65b0\u503c</strong>\uff0c\u6574\u4e2a\u7a0b\u5e8f\u62e5\u6709\u5929\u7136\u7684\u5168\u5c40\u65f6\u5e8f\uff0c\u6240\u6709\u64cd\u4f5c\u7684\u5148\u540e\u987a\u5e8f\u6e05\u6670\u53ef\u8ffd\u6eaf\u3002</p>\n<blockquote>\n<p>\u7ed3\u8bba\uff1a\u7406\u60f3\u5316\u4e32\u884c\u73af\u5883\u4e0b\uff0c\u5929\u7136\u5177\u5907\u6709\u5e8f\u6027\u4e0e\u53ef\u89c1\u6027\uff0chappens-before \u6ca1\u6709\u5b58\u5728\u7684\u5fc5\u8981\u3002</p>\n</blockquote>\n<h2>\u4e8c\u3001\u771f\u5b9e\u7269\u7406\u73af\u5883\uff1a\u4e3a\u4e86\u6027\u80fd\uff0c\u5f15\u5165\u4e86\u4e09\u5c42\u7834\u574f\u987a\u5e8f\u7684\u4f18\u5316</h2>\n<p>\u73b0\u4ee3\u8ba1\u7b97\u673a\u4f53\u7cfb\u4e3a\u538b\u69a8\u786c\u4ef6\u6267\u884c\u6548\u7387\uff0c\u8bbe\u8ba1\u4e86\u5927\u91cf\u6027\u80fd\u4f18\u5316\u65b9\u6848\uff0c\u4e5f\u662f\u5e76\u53d1\u4e71\u8c61\u7684\u6e90\u5934\uff0c\u4e3b\u8981\u5206\u4e3a\u4e09\u7c7b\u3002</p>\n<h3>1. CPU \u6307\u4ee4\u91cd\u6392</h3>\n<p>CPU \u4f9d\u9760\u6d41\u6c34\u7ebf\u673a\u5236\u63d0\u5347\u8fd0\u884c\u6548\u7387\uff0c\u82e5\u6b7b\u677f\u7b49\u5f85\u4e0a\u4e00\u6761\u6307\u4ee4\u6267\u884c\u5b8c\u6bd5\u518d\u6267\u884c\u4e0b\u4e00\u6761\uff0c\u4f1a\u9020\u6210\u5927\u91cf\u786c\u4ef6\u7a7a\u95f2\u635f\u8017\u3002\nCPU \u4f1a\u5728<strong>\u5355\u7ebf\u7a0b\u8fd0\u884c\u7ed3\u679c\u4e0d\u53d8</strong>\u7684\u524d\u63d0\u4e0b\uff0c\u81ea\u7531\u8c03\u6362\u6307\u4ee4\u6267\u884c\u987a\u5e8f\u3002</p>\n<p>\u793a\u4f8b\u4ee3\u7801\uff1a</p>\n<pre><code class=\"language-java\">int a = 1;\nint b = 2;\n</code></pre>\n<p>CPU \u5b9e\u9645\u6267\u884c\u987a\u5e8f\u53ef\u80fd\u53d8\u4e3a\uff1a</p>\n<pre><code class=\"language-java\">b = 2;\na = 1;\n</code></pre>\n<p>\u5355\u7ebf\u7a0b\u8fd0\u884c\u7ed3\u679c\u65e0\u4efb\u4f55\u5dee\u5f02\uff0cCPU \u7684\u91cd\u6392\u884c\u4e3a\u662f\u88ab\u786c\u4ef6\u5141\u8bb8\u7684\u5408\u6cd5\u4f18\u5316\u3002</p>\n<h3>2. CPU \u591a\u7ea7\u7f13\u5b58\u7ed3\u6784</h3>\n<p>\u6bcf\u4e2a CPU \u6838\u5fc3\u72ec\u5360\u72ec\u7acb\u7684\u9ad8\u901f\u7f13\u5b58\uff1aL1 Cache \u3001L2 Cache \uff0c\u591a\u4e2a\u6838\u5fc3\u5171\u4eab L3 \u7f13\u5b58\u3002\n\u7ebf\u7a0b\u4fee\u6539\u53d8\u91cf\u65f6\uff0c\u6570\u636e\u53ea\u4f1a\u5148\u5199\u5165\u5f53\u524d\u6838\u5fc3\u7684\u79c1\u6709\u7f13\u5b58\uff0c\u4e0d\u4f1a\u7acb\u523b\u540c\u6b65\u5237\u65b0\u5230\u4e3b\u5185\u5b58\u3002\n\u6700\u7ec8\u73b0\u8c61\uff1a\u7ebf\u7a0b A \u4fee\u6539\u4e86\u7f13\u5b58\u6570\u636e\uff0c\u7ebf\u7a0b B \u8bfb\u53d6\u4e3b\u5185\u5b58\u53ea\u80fd\u62ff\u5230\u65e7\u6570\u636e\uff0c\u4ea7\u751f\u6570\u636e\u53ef\u89c1\u6027\u95ee\u9898\u3002</p>\n<h3>3. JIT \u7f16\u8bd1\u5668\u4f18\u5316</h3>\n<p>Java \u8fd0\u884c\u671f JIT \u7f16\u8bd1\u5668\u540c\u6837\u4f1a\u5bf9\u5b57\u8282\u7801\u505a\u4f18\u5316\u5904\u7406\uff1a</p>\n<ul>\n<li>\u6307\u4ee4\u91cd\u6392\u5e8f</li>\n<li>\u5254\u9664\u65e0\u6548\u5197\u4f59\u4ee3\u7801</li>\n<li>\u5c06\u53d8\u91cf\u7f13\u5b58\u81f3\u5bc4\u5b58\u5668\u51cf\u5c11\u5185\u5b58\u8bbf\u95ee</li>\n</ul>\n<p>\u7f16\u8bd1\u5668\u53ea\u4fdd\u969c<strong>\u5355\u7ebf\u7a0b\u6267\u884c\u903b\u8f91\u6b63\u786e</strong>\uff0c\u65e0\u6cd5\u611f\u77e5\u591a\u7ebf\u7a0b\u4e4b\u95f4\u7684\u6570\u636e\u4f9d\u8d56\u5173\u7cfb\uff0c\u591a\u7ebf\u7a0b\u573a\u666f\u4e0b\u4f18\u5316\u884c\u4e3a\u4f1a\u6253\u4e71\u6570\u636e\u65f6\u5e8f\u3002</p>\n<h2>\u4e09\u3001\u4f18\u5316\u5e26\u6765\u7684\u6076\u679c\uff1a\u591a\u7ebf\u7a0b\u884c\u4e3a\u4e0d\u53ef\u63a8\u7406\uff08\u7ecf\u5178\u6848\u4f8b\uff09</h2>\n<pre><code class=\"language-java\">int a = 0;\nboolean flag = false;\n\n// \u7ebf\u7a0b A \u6267\u884c\u903b\u8f91\na = 1;\nflag = true;\n\n// \u7ebf\u7a0b B \u6267\u884c\u903b\u8f91\nif(flag){\n    System.out.println(a);\n}\n</code></pre>\n<p>\u6309\u7167\u5e38\u89c4\u601d\u7ef4\uff1a\u53ea\u8981<code>flag = true</code>\u6210\u7acb\uff0c\u53d8\u91cf<code>a</code>\u7684\u503c\u4e00\u5b9a\u7b49\u4e8e 1 \u3002\n\u4f46\u771f\u5b9e\u8fd0\u884c\u73af\u5883\u4e2d\uff0c\u7a0b\u5e8f<strong>\u5927\u6982\u7387\u4f1a\u6253\u5370\u51fa 0</strong>\uff0c\u6210\u56e0\u5206\u4e3a\u4e09\u70b9\uff1a</p>\n<ol>\n<li>CPU/JIT \u53d1\u751f\u6307\u4ee4\u91cd\u6392\uff0c\u7ebf\u7a0b A \u5b9e\u9645\u6267\u884c\u987a\u5e8f\u53d8\u4e3a <code>flag=true \u2192 a=1</code></li>\n<li>\u7ebf\u7a0b A \u7684\u4fee\u6539\u4ec5\u5b58\u4e8e CPU \u79c1\u6709\u7f13\u5b58\uff0c\u672a\u540c\u6b65\u5230\u4e3b\u5185\u5b58\uff0c\u7ebf\u7a0b B \u8bfb\u53d6\u65e7\u7f13\u5b58\u6570\u636e</li>\n<li>\u7ebf\u7a0b B \u62a2\u5148\u8bfb\u53d6\u5230\u672a\u66f4\u65b0\u7684\u539f\u59cb\u5185\u5b58\u6570\u636e</li>\n</ol>\n<blockquote>\n<p>\u91cd\u8981\u8bf4\u660e\uff1a\u8be5\u73b0\u8c61\u4e0d\u5c5e\u4e8e JVM Bug \uff0c\u662f\u786c\u4ef6\u3001\u7f16\u8bd1\u5668\u6027\u80fd\u4f18\u5316\u5e26\u6765\u7684\u5fc5\u7136\u526f\u4f5c\u7528\u3002</p>\n</blockquote>\n<h2>\u56db\u3001JVM \u7684\u6298\u4e2d\u65b9\u6848\uff1aJMM + happens-before</h2>\n<p>\u5168\u76d8\u7981\u7528\u6240\u6709\u8f6f\u786c\u4ef6\u4f18\u5316\uff0c\u4f1a\u9020\u6210\u7a0b\u5e8f\u6027\u80fd\u65ad\u5d16\u5f0f\u4e0b\u8dcc\uff1b\u5b8c\u5168\u653e\u4efb\u65e0\u9650\u5236\u4f18\u5316\uff0c\u5f00\u53d1\u8005\u65e0\u6cd5\u9884\u5224\u591a\u7ebf\u7a0b\u4ee3\u7801\u8fd0\u884c\u884c\u4e3a\u3002</p>\n<p>JVM \u9700\u8981\u5728<strong>\u8fd0\u884c\u6027\u80fd</strong>\u4e0e<strong>\u5e76\u53d1\u6b63\u786e\u6027</strong>\u4e4b\u95f4\u505a\u5e73\u8861\uff0c\u89e3\u51b3\u65b9\u6848\u5c31\u662f <strong>Java \u5185\u5b58\u6a21\u578b\uff08 JMM \uff09</strong>\u3002\n\u800c <strong>happens-before</strong>\uff0c\u5c31\u662f JMM \u4ea4\u4ed8\u7ed9\u5f00\u53d1\u8005\u3001\u7528\u6765\u7ea6\u675f\u591a\u7ebf\u7a0b\u65f6\u5e8f\u4e0e\u53ef\u89c1\u6027\u7684\u6807\u51c6\u89c4\u5219\u4f53\u7cfb\u3002</p>\n<h2>\u4e94\u3001\u7ea0\u6b63\u8bef\u533a\uff1ahappens-before \u4e0d\u662f\u300c\u4ee3\u7801\u7269\u7406\u6267\u884c\u5148\u540e\u300d</h2>\n<p>\u5927\u4f17\u666e\u904d\u9519\u8bef\u7406\u89e3\uff1a<code>A happens-before B</code> = A \u4ee3\u7801\u7269\u7406\u65f6\u95f4\u4e0a\u4e00\u5b9a\u5148\u6267\u884c\u3001B \u540e\u6267\u884c\u3002</p>\n<h3>\u771f\u5b9e\u5b9a\u4e49</h3>\n<p>happens-before \u63cf\u8ff0\u7684\u662f<strong>\u6570\u636e\u53ef\u89c1\u6027\u4e0e\u64cd\u4f5c\u56e0\u679c\u5173\u7cfb</strong>\uff0c\u800c\u975e\u771f\u5b9e\u7684 CPU \u6267\u884c\u65f6\u5e8f\uff1a</p>\n<blockquote>\n<p>\u82e5 A happens-before B \uff0cJVM \u5f3a\u5236\u4fdd\u8bc1\uff1aB \u4e00\u5b9a\u80fd\u89c2\u6d4b\u5230 A \u6267\u884c\u5b8c\u6210\u540e\u7684\u6240\u6709\u6570\u636e\u4fee\u6539\uff0cA \u7684\u64cd\u4f5c\u7ed3\u679c\u4f1a\u5bf9 B \u4ea7\u751f\u6709\u6548\u5f71\u54cd\u3002</p>\n</blockquote>\n<p>\u4ee5 volatile \u8bfb\u5199\u4e3e\u4f8b\uff1a</p>\n<pre><code class=\"language-java\">// volatile \u5199\nflag = true;\n// volatile \u8bfb\nif(flag)\n</code></pre>\n<p>\u5e76\u4e0d\u662f CPU \u5fc5\u987b\u5148\u6267\u884c\u5199\u64cd\u4f5c\u3001\u518d\u6267\u884c\u8bfb\u64cd\u4f5c\uff1b\u771f\u5b9e\u542b\u4e49\u4e3a\uff1a\u7ebf\u7a0b\u4e00\u65e6\u8bfb\u53d6\u5230<code>flag=true</code>\u8fd9\u4e2a volatile \u6807\u8bb0\uff0c\u5199\u64cd\u4f5c\u4e4b\u524d\u6240\u6709\u53d8\u91cf\u7684\u4fee\u6539\uff0c\u5fc5\u987b\u5bf9\u5f53\u524d\u8bfb\u7ebf\u7a0b\u5168\u90e8\u53ef\u89c1\u3002</p>\n<h2>\u516d\u3001happens-before \u4e3a\u4ec0\u4e48\u521a\u597d\u662f\u516b\u6761\u89c4\u5219\uff1f</h2>\n<p>\u89c4\u5219\u6570\u91cf\u5e76\u4e0d\u662f\u5b98\u65b9\u51ed\u7a7a\u6307\u5b9a\u4e3a 8 \u6761\uff0c\u672c\u8d28\u662f\uff1a<strong>Java \u8bed\u8a00\u4e2d\u6240\u6709\u5408\u6cd5\u7684\u7ebf\u7a0b\u540c\u6b65\u3001\u901a\u4fe1\u65b9\u5f0f\uff0c\u5bf9\u5e94\u4e00\u6761 happens-before \u7ea6\u675f</strong>\uff0c\u516b\u6761\u89c4\u5219\u662f\u5bf9\u5168\u90e8\u540c\u6b65\u884c\u4e3a\u7684\u6807\u51c6\u5316\u6570\u5b66\u63cf\u8ff0\u3002</p>\n<p>\u516b\u6761\u5b8c\u6574\u89c4\u5219\u660e\u7ec6\uff1a</p>\n<ol>\n<li><strong>\u7a0b\u5e8f\u6b21\u5e8f\u89c4\u5219</strong>\uff1a\u540c\u4e00\u4e2a\u7ebf\u7a0b\u5185\uff0c\u4e66\u5199\u5728\u524d\u7684\u64cd\u4f5c happens-before \u4e66\u5199\u5728\u540e\u7684\u64cd\u4f5c\u3002</li>\n<li><strong>\u76d1\u89c6\u5668\u9501\u89c4\u5219</strong>\uff1a\u540c\u4e00\u4e2a\u9501\uff0c\u9501\u7684\u91ca\u653e\u64cd\u4f5c happens-before \u540e\u7eed\u8be5\u9501\u7684\u83b7\u53d6\u64cd\u4f5c\u3002</li>\n<li><strong>volatile \u53d8\u91cf\u89c4\u5219</strong>\uff1avolatile \u5b57\u6bb5\u7684\u5199\u5165\u64cd\u4f5c happens-before \u540e\u7eed\u5bf9\u8be5\u5b57\u6bb5\u7684\u8bfb\u53d6\u64cd\u4f5c\u3002</li>\n<li><strong>\u7ebf\u7a0b\u542f\u52a8\u89c4\u5219</strong>\uff1a<code>Thread.start()</code>\u65b9\u6cd5\u8c03\u7528\u4e4b\u524d\u7684\u6240\u6709\u4ee3\u7801\uff0chappens-before \u65b0\u542f\u52a8\u7ebf\u7a0b\u5185\u90e8\u7684\u4efb\u610f\u64cd\u4f5c\u3002</li>\n<li><strong>\u7ebf\u7a0b\u7ec8\u6b62\u89c4\u5219</strong>\uff1a\u7ebf\u7a0b\u5185\u90e8\u6240\u6709\u6267\u884c\u64cd\u4f5c\uff0chappens-before \u5176\u4ed6\u7ebf\u7a0b\u6267\u884c<code>join()</code>\u65b9\u6cd5\u5e76\u6b63\u5e38\u8fd4\u56de\u3002</li>\n<li><strong>\u7ebf\u7a0b\u4e2d\u65ad\u89c4\u5219</strong>\uff1a\u8c03\u7528<code>interrupt()</code>\u53d1\u8d77\u4e2d\u65ad\u7684\u64cd\u4f5c\uff0chappens-before \u88ab\u4e2d\u65ad\u7ebf\u7a0b\u68c0\u6d4b\u5230\u4e2d\u65ad\u6807\u8bc6\u7684\u64cd\u4f5c\u3002</li>\n<li><strong>final \u5b57\u6bb5\u89c4\u5219</strong>\uff1a\u5bf9\u8c61\u6784\u9020\u65b9\u6cd5\u5b8c\u6210\u521d\u59cb\u5316\u540e\uff0cfinal \u4fee\u9970\u5b57\u6bb5\u7684\u503c\u5bf9\u5176\u4ed6\u8bbf\u95ee\u7ebf\u7a0b\u6c38\u4e45\u53ef\u89c1\uff0c\u5b9e\u73b0\u5bf9\u8c61\u5b89\u5168\u53d1\u5e03\u3002</li>\n<li><strong>\u4f20\u9012\u6027\u89c4\u5219</strong>\uff1a\u82e5 A happens-before B \uff0cB happens-before C \uff0c\u5219\u63a8\u5bfc\u5f97\u51fa A happens-before C \u3002</li>\n</ol>\n<h2>\u4e03\u3001\u4f20\u9012\u6027\uff1ahappens-before \u4f53\u7cfb\u7684\u6838\u5fc3\u538b\u7f29\u673a\u5236</h2>\n<p>\u5982\u679c\u6ca1\u6709\u4f20\u9012\u6027\u89c4\u5219\uff0c\u7cfb\u7edf\u9700\u8981\u4e3a\u6bcf\u4e24\u6bb5\u5b58\u5728\u5148\u540e\u5173\u7cfb\u7684\u64cd\u4f5c\u5355\u72ec\u5b9a\u4e49\u7ea6\u675f\uff0c\u89c4\u5219\u6570\u91cf\u4f1a\u65e0\u9650\u81a8\u80c0\u3002</p>\n<p>\u4e3e\u4f8b\u94fe\u8def\uff1aA \u4fee\u6539\u6570\u636e \u2192 B \u91ca\u653e\u9501 \u2192 C \u83b7\u53d6\u9501\n\u4f9d\u9760\u4f20\u9012\u6027\uff0c\u81ea\u52a8\u5efa\u7acb A\u2192B\u2192C \u7684 happens-before \u5173\u7cfb\uff0cA \u7684\u6570\u636e\u4fee\u6539\u5929\u7136\u5bf9 C \u53ef\u89c1\uff1b\u65e0\u9700\u5355\u72ec\u5b9a\u4e49 A \u4e0e C \u7684\u7ed1\u5b9a\u89c4\u5219\u3002</p>\n<blockquote>\n<p>\u4f20\u9012\u6027\u662f\u6574\u4e2a happens-before \u4f53\u7cfb\u7684\u7cbe\u7b80\u538b\u7f29\u6838\u5fc3\uff0c\u7528\u6700\u5c11\u89c4\u5219\u8986\u76d6\u5168\u90e8\u65f6\u5e8f\u94fe\u8def\u3002</p>\n</blockquote>\n<h2>\u516b\u3001happens-before \u7684\u8bbe\u8ba1\u76ee\u6807\uff1a\u6784\u5efa\u6700\u5c0f\u5b8c\u5907\u7cfb\u7edf</h2>\n<p>JMM \u8bbe\u8ba1 happens-before \u65f6\u9501\u5b9a\u4e09\u5927\u6838\u5fc3\u76ee\u6807\uff1a</p>\n<ol>\n<li><strong>\u5b8c\u5907\u6027</strong>\uff1a\u5168\u8986\u76d6 Java \u6240\u6709\u7ebf\u7a0b\u540c\u6b65\u573a\u666f\uff0c\u4e0d\u5b58\u5728\u9057\u6f0f\u7684\u540c\u6b65\u5173\u7cfb</li>\n<li><strong>\u7b80\u6d01\u6027</strong>\uff1a\u63a7\u5236\u89c4\u5219\u6570\u91cf\uff0c\u964d\u4f4e\u5f00\u53d1\u8005\u5b66\u4e60\u4e0e\u4f7f\u7528\u6210\u672c</li>\n<li><strong>\u517c\u5bb9\u6027</strong>\uff1a\u6700\u5927\u9650\u5ea6\u653e\u884c CPU \u3001\u7f16\u8bd1\u5668\u7684\u5404\u7c7b\u4f18\u5316\uff0c\u4e0d\u727a\u7272\u7a0b\u5e8f\u8fd0\u884c\u6027\u80fd</li>\n</ol>\n<p>\u672c\u8d28\uff1ahappens-before \u662f\u4e00\u5957<strong>\u6700\u5c0f\u4e14\u81ea\u6d3d\u7684\u591a\u7ebf\u7a0b\u884c\u4e3a\u63a8\u7406\u7cfb\u7edf</strong>\u3002</p>\n<h2>\u4e5d\u3001\u5e76\u53d1\u95ee\u9898\u7684\u6839\u6e90\u4e0d\u662f\u91cd\u6392/\u7f13\u5b58\uff0c\u800c\u662f\u6570\u636e\u7ade\u4e89</h2>\n<p>\u6307\u4ee4\u91cd\u6392\u3001\u591a\u7ea7\u7f13\u5b58\u3001\u7f16\u8bd1\u5668\u4f18\u5316\u53ea\u662f\u5e76\u53d1\u5f02\u5e38\u7684\u5916\u5728\u8868\u73b0\uff0c\u771f\u6b63\u7684\u5143\u51f6\u662f<strong>\u6570\u636e\u7ade\u4e89\uff08 Data Race \uff09</strong>\u3002</p>\n<h3>\u6570\u636e\u7ade\u4e89\u5224\u5b9a\u4e09\u8981\u7d20\uff08\u540c\u65f6\u6ee1\u8db3\u5373\u4ea7\u751f\u6570\u636e\u7ade\u4e89\uff09</h3>\n<ol>\n<li>\u591a\u4e2a\u7ebf\u7a0b\u8bbf\u95ee\u540c\u4e00\u4e2a\u5171\u4eab\u53d8\u91cf</li>\n<li>\u81f3\u5c11\u6709\u4e00\u4e2a\u7ebf\u7a0b\u5bf9\u53d8\u91cf\u6267\u884c\u5199\u5165\u64cd\u4f5c</li>\n<li>\u8bfb\u5199\u7ebf\u7a0b\u4e4b\u95f4\u4e0d\u5b58\u5728\u4efb\u4f55 happens-before \u7ea6\u675f</li>\n</ol>\n<p>\u793a\u4f8b\uff08\u65e0\u540c\u6b65\u81ea\u589e\uff09\uff1a</p>\n<pre><code class=\"language-java\">int count = 0;\n// \u7ebf\u7a0b A\ncount++;\n// \u7ebf\u7a0b B\ncount++;\n</code></pre>\n<p>\u65e0\u9501\u3001\u65e0 volatile \u3001\u65e0\u4efb\u4f55\u540c\u6b65\u63aa\u65bd\uff0c\u4e24\u6761\u81ea\u589e\u64cd\u4f5c\u65e0\u56e0\u679c\u7ed1\u5b9a\uff0c\u7a0b\u5e8f\u6700\u7ec8\u7ed3\u679c\u4e0d\u53ef\u9884\u6d4b\u3002</p>\n<h2>\u5341\u3001JMM \u6838\u5fc3\u4fdd\u969c\u539f\u5219\uff1aDRF-SC</h2>\n<p>DRF-SC \u5168\u79f0\uff1a<code>Data Race Free \u2192 Sequential Consistency</code>\n\u7ffb\u8bd1\uff1a<strong>\u65e0\u6570\u636e\u7ade\u4e89\u7684\u7a0b\u5e8f\uff0c\u6267\u884c\u6548\u679c\u7b49\u4ef7\u4e8e\u987a\u5e8f\u4e00\u81f4\u6027\u6267\u884c</strong>\u3002</p>\n<p>\u901a\u4fd7\u89e3\u91ca\uff1a\u5f00\u53d1\u8005\u6b63\u786e\u4f7f\u7528\u540c\u6b65\u673a\u5236\u3001\u4f9d\u9760 happens-before \u6d88\u9664\u6570\u636e\u7ade\u4e89\u540e\uff0c\u591a\u7ebf\u7a0b\u4ee3\u7801\u7684\u8fd0\u884c\u903b\u8f91\u548c\u5355\u7ebf\u7a0b\u4ee3\u7801\u4e00\u6837\u5177\u5907\u7a33\u5b9a\u3001\u53ef\u9884\u671f\u7684\u6267\u884c\u7ed3\u679c\u3002\n\u53cd\u4e4b\uff1a\u4ee3\u7801\u5b58\u5728\u6570\u636e\u7ade\u4e89\u65f6\uff0cJVM \u4e0d\u4f1a\u5bf9\u7a0b\u5e8f\u8fd0\u884c\u884c\u4e3a\u505a\u4efb\u4f55\u627f\u8bfa\uff0c\u8fd0\u884c\u7ed3\u679c\u968f\u673a\u4e0d\u53ef\u63a7\u3002</p>\n<h2>\u5341\u4e00\u3001Java \u5e76\u53d1\u77e5\u8bc6\u6574\u4f53\u94fe\u8def\u68b3\u7406</h2>\n<pre><code class=\"language-mermaid\">graph TD\nA[CPU \u4e3a\u6027\u80fd\u5f15\u5165\u4e71\u5e8f\u6267\u884c+\u79c1\u6709\u7f13\u5b58] --&gt; B[JVM \u5f00\u653e\u7f16\u8bd1\u5668\u3001\u6307\u4ee4\u4f18\u5316\u6743\u9650]\nB --&gt; C[\u591a\u7ebf\u7a0b\u8bfb\u5199\u5171\u4eab\u53d8\u91cf\u6781\u6613\u4ea7\u751f\u6570\u636e\u7ade\u4e89]\nC --&gt; D[\u89e3\u51b3\u65b9\u6848\uff1a\u4f7f\u7528\u540c\u6b65\u673a\u5236\u5efa\u7acb\u7ebf\u7a0b\u65f6\u5e8f\u7ea6\u675f]\nD --&gt; E[\u5404\u7c7b\u540c\u6b65\u884c\u4e3a\u6620\u5c04\u4e3a happens-before \u5173\u7cfb]\nE --&gt; F[happens-before \u7edf\u4e00\u4fdd\u969c\u6570\u636e\u53ef\u89c1\u6027\u3001\u64cd\u4f5c\u6709\u5e8f\u6027]\nF --&gt; G[\u65e0\u6570\u636e\u7ade\u4e89 \u2192 \u7a0b\u5e8f\u884c\u4e3a\u7b49\u540c\u4e8e\u987a\u5e8f\u6267\u884c]\n</code></pre>\n<h2>\u5341\u4e8c\u3001\u5168\u6587\u603b\u7ed3</h2>\n<p>\u4e00\u53e5\u8bdd\u6982\u62ec happens-before \u7684\u8bde\u751f\u610f\u4e49\uff1a</p>\n<blockquote>\n<p>\u73b0\u4ee3\u786c\u4ef6\u4e3a\u6027\u80fd\u6253\u7834\u4e86\u539f\u59cb\u7684\u4e32\u884c\u6267\u884c\u6a21\u578b\uff0chappens-before \u662f Java \u8bbe\u8ba1\u7684\u4e00\u5957\u6298\u4e2d\u6570\u5b66\u6a21\u578b\uff1a\u65e2\u5141\u8bb8\u8f6f\u786c\u4ef6\u6b63\u5e38\u4f18\u5316\u4fdd\u969c\u6027\u80fd\uff0c\u53c8\u7ed9\u5f00\u53d1\u8005\u63d0\u4f9b\u4e86\u53ef\u63a8\u7406\u3001\u53ef\u7ba1\u63a7\u7684\u591a\u7ebf\u7a0b\u5e76\u53d1\u8fb9\u754c\u3002</p>\n</blockquote>\n<p>CPU \u91cd\u6392\u3001\u7f13\u5b58\u4e0d\u4e00\u81f4\u3001\u7f16\u8bd1\u5668\u4f18\u5316\u90fd\u4e0d\u662f\u5e76\u53d1 Bug \u7684\u672c\u6e90\u95ee\u9898\uff0c<strong>\u7ebf\u7a0b\u4e4b\u95f4\u662f\u5426\u901a\u8fc7\u540c\u6b65\u673a\u5236\u5efa\u7acb\u5408\u6cd5\u7684 happens-before \u56e0\u679c\u5173\u7cfb</strong>\uff0c\u624d\u662f\u89e3\u51b3\u5e76\u53d1\u5b89\u5168\u7684\u6838\u5fc3\u5173\u952e\u3002\nhappens-before \u5c31\u662f Java \u4f53\u7cfb\u4e2d\uff0c\u5b9a\u4e49\u7ebf\u7a0b\u6570\u636e\u56e0\u679c\u5173\u7cfb\u7684\u6807\u51c6\u6570\u5b66\u6a21\u578b\u3002</p>\n"
    }, 
    {
      "author": {
        "url": "https://www.v2ex.com/member/pc10201", 
        "name": "pc10201", 
        "avatar": "https://cdn.v2ex.com/avatar/07bf/e497/41279_large.png?m=1761100385"
      }, 
      "url": "https://www.v2ex.com/t/1228967", 
      "title": "\u534e\u4e3a\u7684\u6bd5\u6607 JDK 8 AppCDS \u7279\u6027\u7a33\u5b9a\u5417\uff1f", 
      "id": "https://www.v2ex.com/t/1228967", 
      "date_published": "2026-07-22T01:20:00+00:00", 
      "content_html": "<p>\u5176\u4ed6\u5bb6\u7684\u53d1\u884c\u7248\uff0c\u8981 java 11 \u4ee5\u4e0a\u624d\u652f\u6301 AppCDS</p>\n<p>\u534e\u4e3a\u7684\u6bd5\u6607 JDK 8 \u5e94\u8be5\u662f\u552f\u4e00\u5728 java 8 \u4e0a\u652f\u6301\u7684</p>\n<p>\u6700\u8fd1\u4f7f\u7528 k8s \u7ba1\u7406 java \u5e94\u7528\uff0c\u542f\u52a8\u901f\u5ea6\u548c\u5360\u7528\u8d44\u6e90\u592a\u611f\u4eba\u4e86</p>\n"
    }, 
    {
      "author": {
        "url": "https://www.v2ex.com/member/g632104866", 
        "name": "g632104866", 
        "avatar": "https://cdn.v2ex.com/avatar/01d5/38d4/510131_large.png?m=1783481882"
      }, 
      "url": "https://www.v2ex.com/t/1228812", 
      "title": "\u6211\u628a Java \u5f00\u53d1\u7684 kkRepo \u652f\u6301 AOT \u7f16\u8bd1\uff0c 1s \u6781\u901f\u542f\u52a8\uff0c\u7a7a\u95f2\u5185\u5b58\u5c0f\u4e8e 200MB", 
      "id": "https://www.v2ex.com/t/1228812", 
      "date_published": "2026-07-21T06:27:18+00:00", 
      "content_html": "<h1>kkRepo \u662f\u4ec0\u4e48\uff1f</h1>\n<p>kkRepo \u662f\u4e00\u6b3e\u793e\u533a\u9a71\u52a8\u3001\u5b8c\u5168\u5f00\u6e90\u7684\u81ea\u6258\u7ba1\u5236\u54c1\u4ed3\u5e93\uff0c\u65e8\u5728\u89e3\u51b3 Sonatype Nexus \u793e\u533a\u7248\u7684\u5404\u7c7b\u9650\u5236\u4e0e\u75db\u70b9\uff0c\u4e3a\u793e\u533a\u63d0\u4f9b\u5f00\u653e\u3001\u53ef\u9760\u4e14\u53ef\u6301\u7eed\u6f14\u8fdb\u7684\u5236\u54c1\u7ba1\u7406\u65b9\u6848\u3002\u76ee\u524d\u5df2\u652f\u6301 Maven \u3001npm \u3001PyPI \u3001Go \u3001Helm \u3001Cargo/Rust \u3001Dart/Pub \u3001Composer/PHP \u3001Terraform \u3001Swift Package Registry \u3001Docker/OCI \u3001NuGet \u3001RubyGems \u3001Yum \u548c Raw \u7b49\u5236\u54c1\u683c\u5f0f\u3002</p>\n<ul>\n<li><a href=\"https://github.com/klboke/kkRepo\" rel=\"nofollow\">https://github.com/klboke/kkRepo</a>  \uff0c\u70b9 star \u652f\u6301</li>\n</ul>\n<h2>\u652f\u6301 AOT \u548c JVM \u53cc\u7f16\u8bd1</h2>\n<p>\u6765\u6e90\u4e8e V2EX \u7528\u6237\u7684\u4e00\u53e5\u63d0\u9192\uff0c\u8bf4 Java \u542f\u52a8\u592a\u6162\u592a\u8017\u5185\u5b58\u4e86\uff0c\u4e8e\u662f\u6211\u628a kkRepo \u652f\u6301\u4e86 AOT \u548c JVM \u53cc\u7f16\u8bd1\uff0c\u603b\u4f53\u6765\u8bf4\u5404\u6709\u4f18\u52a3\u3002AOT \u542f\u52a8\u5feb\u5360\u7528\u8d44\u6e90\u5c11\uff0cJVM \u7684\u541e\u5410\u6bd4 AOT \u660e\u663e\u66f4\u9ad8\u3002\u73b0\u5728\u53ef\u4ee5\u81ea\u7531\u9009\u62e9\u4e86\u3002</p>\n<h4>\u542f\u52a8\u3001\u5185\u5b58\u4e0e\u5305\u4f53\u79ef</h4>\n<table>\n<thead>\n<tr>\n<th>\u6307\u6807</th>\n<th>Native</th>\n<th>JVM</th>\n<th>\u8bf4\u660e</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>\u521b\u5efa\u5bb9\u5668\u5230 readiness \u4e2d\u4f4d\u6570</td>\n<td>1.037 \u79d2</td>\n<td>11.888 \u79d2</td>\n<td>Native \u5feb 11.5 \u500d</td>\n</tr>\n<tr>\n<td>Spring \u81ea\u62a5\u542f\u52a8\u4e2d\u4f4d\u6570</td>\n<td>0.639 \u79d2</td>\n<td>9.562 \u79d2</td>\n<td>Native \u5feb 15.0 \u500d</td>\n</tr>\n<tr>\n<td>5 \u8f6e readiness \u8303\u56f4</td>\n<td>1.031-1.793 \u79d2</td>\n<td>11.295-14.762 \u79d2</td>\n<td>Native \u91cd\u542f\u7a97\u53e3\u66f4\u77ed</td>\n</tr>\n<tr>\n<td>\u7a7a\u95f2 Docker \u5185\u5b58\u4e2d\u4f4d\u6570</td>\n<td>170.4 MiB</td>\n<td>315.1 MiB</td>\n<td>Native \u5c11 45.9%</td>\n</tr>\n<tr>\n<td>\u7a7a\u95f2\u8fdb\u7a0b RSS</td>\n<td>134.4 MiB</td>\n<td>327.0 MiB</td>\n<td>Native \u5c11 58.9%</td>\n</tr>\n<tr>\n<td>\u7a7a\u95f2 CPU \u4e2d\u4f4d\u6570</td>\n<td>0.32%</td>\n<td>1.27%</td>\n<td>\u4e24\u8005\u90fd\u5f88\u4f4e\uff0cNative \u540e\u53f0\u5f00\u9500\u66f4\u5c0f</td>\n</tr>\n<tr>\n<td>\u7a7a\u95f2\u7ebf\u7a0b\u6570</td>\n<td>40</td>\n<td>50</td>\n<td>Native \u5c11 20%</td>\n</tr>\n<tr>\n<td>\u8d1f\u8f7d\u671f\u95f4\u8fdb\u7a0b RSS \u5cf0\u503c</td>\n<td>218.4 MiB</td>\n<td>389.4 MiB</td>\n<td>Native \u5c11 43.9%</td>\n</tr>\n<tr>\n<td>Docker \u955c\u50cf\u5185\u5bb9\u5927\u5c0f</td>\n<td>238 MB</td>\n<td>388 MB</td>\n<td>Native \u5c0f 38.7%</td>\n</tr>\n<tr>\n<td>Docker \u672c\u5730\u78c1\u76d8\u5360\u7528</td>\n<td>494 MB</td>\n<td>796 MB</td>\n<td>Native \u5c0f 37.9%</td>\n</tr>\n</tbody></table><h4>\u8bf7\u6c42\u6027\u80fd</h4>\n<p>\u5145\u5206\u9884\u70ed\u540e\uff0c\u4e24\u79cd\u6a21\u5f0f\u5728\u5355\u5e76\u53d1\u6d4b\u8bd5\u4e2d\u7684 P50 \u90fd\u7ea6\u4e3a 1 ms \u3002\u5dee\u5f02\u4e3b\u8981\u51fa\u73b0\u5728\u6301\u7eed\u5e76\u53d1\u9636\u6bb5\uff1a\u5b8c\u6210 JIT \u9884\u70ed\u540e\u7684 JVM \u901a\u5e38\u80fd\u63d0\u4f9b\u66f4\u9ad8\u541e\u5410\u3002</p>\n<table>\n<thead>\n<tr>\n<th>64 \u5e76\u53d1\u6301\u7eed\u8d1f\u8f7d\u7aef\u70b9</th>\n<th>Native \u8bf7\u6c42/\u79d2</th>\n<th>JVM \u8bf7\u6c42/\u79d2</th>\n<th>JVM \u541e\u5410\u53d8\u5316</th>\n<th>Native P95/P99</th>\n<th>JVM P95/P99</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>Actuator health</td>\n<td>765</td>\n<td>911</td>\n<td>+19.1%</td>\n<td>65/1006 ms</td>\n<td>44/1032 ms</td>\n</tr>\n<tr>\n<td>Browse \u9875\u9762</td>\n<td>2,071</td>\n<td>2,293</td>\n<td>+10.7%</td>\n<td>81/209 ms</td>\n<td>86/147 ms</td>\n</tr>\n<tr>\n<td>Repositories API</td>\n<td>2,084</td>\n<td>3,005</td>\n<td>+44.2%</td>\n<td>91/102 ms</td>\n<td>74/185 ms</td>\n</tr>\n</tbody></table><p>3 \u8f6e 32 \u5e76\u53d1\u3001\u6bcf\u8f6e 10,000 \u8bf7\u6c42\u7684\u7ed3\u679c\u4e5f\u5448\u73b0\u76f8\u540c\u7684\u7a33\u6001\u8d8b\u52bf\uff1a</p>\n<ul>\n<li>Browse \u4e2d\u4f4d\u541e\u5410\uff1aNative 2,529 \u8bf7\u6c42/\u79d2\uff0cJVM 3,003 \u8bf7\u6c42/\u79d2\uff0cJVM \u9ad8 18.7%\u3002</li>\n<li>Repositories API \u4e2d\u4f4d\u541e\u5410\uff1aNative 1,942 \u8bf7\u6c42/\u79d2\uff0cJVM 2,438 \u8bf7\u6c42/\u79d2\uff0cJVM \u9ad8 25.5%\u3002</li>\n</ul>\n"
    }, 
    {
      "author": {
        "url": "https://www.v2ex.com/member/joooooker21", 
        "name": "joooooker21", 
        "avatar": "https://cdn.v2ex.com/avatar/f056/9490/367231_large.png?m=1787036622"
      }, 
      "url": "https://www.v2ex.com/t/1228636", 
      "title": "fastjson1.x \u6700\u65b0\u7248\u672c\u7591\u4f3c\u53c8\u51fa RCE \u6f0f\u6d1e\u4e86", 
      "id": "https://www.v2ex.com/t/1228636", 
      "date_published": "2026-07-20T10:07:37+00:00", 
      "content_html": "<a target=\"_blank\" href=\"https://x.com/k_firsov/status/2078872293745570032\" rel=\"nofollow noopener\">https://x.com/k_firsov/status/2078872293745570032</a><br /><br />\u8fd8\u6ca1\u8fdb CVE \uff0c\u5b98\u65b9\u8fd8\u6ca1\u53cd\u9988\uff0c\u4e0d\u786e\u5b9a\u5565\u65f6\u5019\u4f1a\u516c\u5f00"
    }, 
    {
      "author": {
        "url": "https://www.v2ex.com/member/g632104866", 
        "name": "g632104866", 
        "avatar": "https://cdn.v2ex.com/avatar/01d5/38d4/510131_large.png?m=1783481882"
      }, 
      "url": "https://www.v2ex.com/t/1225805", 
      "title": "\u8bb2\u8bb2\u6211\u600e\u4e48\u83b7\u5f97 kkRepo \u7684\u9996\u4e2a\u4f01\u4e1a\u7528\u6237\uff0c\u6210\u529f\u66ff\u6362\u6389 Nexus\uff0c\u6bcf\u5e74\u8282\u7701 $1,620 PRO \u8ba2\u9605\u8d39\u7528", 
      "id": "https://www.v2ex.com/t/1225805", 
      "date_published": "2026-07-08T04:34:35+00:00", 
      "content_html": "<h1>\u524d\u8a00</h1>\n<p>kkRepo \uff08 <a href=\"https://github.com/klboke/kkRepo\" rel=\"nofollow\">https://github.com/klboke/kkRepo</a> \uff09\u4e00\u4e2a\u5bf9\u6807 Nexus \uff0c\u89e3\u51b3 Nexus \u793e\u533a\u7248\u672c\u9650\u5236\u75db\u70b9\u7684\u5f00\u6e90\u5236\u54c1\u4ed3\u5e93\u9879\u76ee\uff0c\u76ee\u524d\u5df2\u7ecf\u652f\u6301\u4e86 Maven, npm, PyPI, Go, Helm, Cargo/Rust, Docker/OCI, NuGet, RubyGems, Yum, and Raw \u8fd9\u4e9b\u4ed3\u5e93\uff0c\u4e0b\u4e00\u6b65\u6253\u7b97\u652f\u6301\u534e\u4e3a\u7684\u9e3f\u8499 ohpm \u4ed3\u5e93\u3002</p>\n<h2>\u4e3b\u52a8\u51fa\u51fb\uff0c\u5bfb\u627e\u75db\u70b9\u7528\u6237</h2>\n<p>\u9879\u76ee\u53d1\u5e03\u540e\uff0c\u6211\u5c31\u5728 Google \u641c\u7d22 \u201cnexus \u793e\u533a\u7248\u9650\u5236\u201d \u8fd9\u4e2a\u5173\u952e\u8bcd\u3002\u627e\u5230\u4e86</p>\n<ul>\n<li><a href=\"https://wiki.eryajf.net/pages/b6b711/#%E5%89%8D%E8%A8%80\" rel=\"nofollow\">https://wiki.eryajf.net/pages/b6b711/#%E5%89%8D%E8%A8%80</a> </li>\n</ul>\n<p>\u8fd9\u4e2a\u535a\u6587\uff0c\u56e0\u4e3a\u6211\u53d1\u73b0\u7c7b\u4f3c\u7684\u5185\u5bb9\uff0c\u8fd9\u4e2a\u535a\u6587\u5728 Google \u7684 SEO \u6392\u540d\u7b2c\u4e00\u3002\u7136\u540e\u5728\u535a\u6587\u4e0b\u8ddf\u5e16\u56de\u590d\u4e86\u3002</p>\n<blockquote>\n<p>\u4f60\u597d\uff0c\u6211\u4eec\u5f00\u53d1\u4e86\u4e00\u4e2a\u53ef\u4ee5\u5e73\u66ff Nexus \u7684\u8f6f\u4ef6\uff0c\u4ee3\u7801\u5b8c\u5168\u5f00\u6e90\uff0c\u4e5f\u652f\u6301\u4e00\u952e\u4ece Nexus \u8fc1\u79fb\u5230 nexus-plus \uff0c\u4e14\u6211\u4eec\u5df2\u7ecf\u5728\u751f\u4ea7\u73af\u5883\u8fd0\u884c\u5f88\u4e45\u4e86\u3002\u60f3\u8c03\u7814\u4e0b\uff0c\u56e0\u4e3a Nexus \u7684\u5f00\u6e90\u514d\u8d39\u529f\u80fd\u90e8\u5206\u9650\u5236\u7684\u8d8a\u6765\u8d8a\u591a\u7684\u60c5\u51b5\u4e0b\uff0c\u662f\u5426\u6709\u5174\u8da3\u5207\u5230 nexus-plus \u6765\u3002\u9644\u9879\u76ee\u5730\u5740\uff1a <a href=\"https://github.com/klboke/nexus-plus\" rel=\"nofollow\">https://github.com/klboke/nexus-plus</a></p>\n</blockquote>\n<p>7 \u5929\u4e4b\u540e\uff0c\u5c31\u6709\u7528\u6237\u770b\u5230\u4e86\u6211\u7684\u8bc4\u8bba\uff0c\u7136\u540e\u6210\u529f\u4e92\u52a0\u5230\u5fae\u4fe1\u3002\u5728\u5fae\u4fe1\u4e0a\u5168\u529b\u534f\u52a9\u4ed6\uff0c\u89e3\u7b54\u5404\u79cd\u7591\u95ee\u3002\u4ece\u52a0\u5fae\u4fe1\u5230\u4ed6\u4eec\u751f\u4ea7\u843d\u5730\u4e0d\u5230\u4e00\u5468\u65f6\u95f4\u3002\u4ece Nexus \u5f00\u59cb\u8fc1\u79fb\u5230 kkRepo \u53ea\u7528\u4e86 1 \u5929\u65f6\u95f4\u3002</p>\n<p><img alt=\"img\" class=\"embedded_image\" loading=\"lazy\" referrerpolicy=\"no-referrer\" rel=\"noreferrer\" src=\"https://i.imgur.com/MYKHgPd.png\"/></p>\n<p>\u4ee5\u4e0b\u6765\u81ea\u5bf9\u65b9\u7684\u771f\u5b9e\u5207\u6362<code>\u80cc\u666f</code></p>\n<blockquote>\n<p>\u6211\u4eec\u662f\u4e00\u5bb6\u5149\u4f0f\u5236\u9020\u4f01\u4e1a\uff0c\u7814\u53d1\u56e2\u961f\u8d85\u8fc7 500 \u4eba\uff0c\u8986\u76d6 50 \u591a\u4e2a\u9879\u76ee\uff0c\u5185\u90e8\u591a\u6761\u4ea7\u54c1\u7ebf\u5171\u7528\u7edf\u4e00\u7684 CI/CD \u6d41\u6c34\u7ebf\u3002\u5236\u54c1\u4ed3\u5e93\u4f5c\u4e3a\u6784\u5efa\u57fa\u7840\u8bbe\u65bd\u7684\u6838\u5fc3\u7ec4\u4ef6\uff0c\u627f\u62c5\u7740 Maven \u3001npm \u3001pypi \u7b49\u591a\u79cd\u5236\u54c1\u7684\u6258\u7ba1\u4e0e\u5206\u53d1\u804c\u8d23\uff0c\u662f\u6574\u4e2a\u7814\u53d1\u4f53\u7cfb\u7684\u5173\u952e\u57fa\u7840\u8bbe\u65bd\u3002</p>\n</blockquote>\n<blockquote>\n<p>\u8fc7\u53bb\u51e0\u5e74\uff0c\u6211\u4eec\u4e00\u76f4\u4f7f\u7528 Sonatype Nexus Repository 3.78.2-04 \uff08 Community Edition \uff09\uff0c\u901a\u8fc7 Docker Compose \u90e8\u7f72\uff0c\u5e95\u5c42\u6570\u636e\u5e93\u4f7f\u7528 PostgreSQL \uff0c\u5236\u54c1 blob \u5b58\u50a8\u4f7f\u7528 OSS \u3002\u968f\u7740\u4e1a\u52a1\u89c4\u6a21\u6269\u5927\uff0cNexus Community Edition \u7684\u4e00\u4e9b\u9650\u5236\u9010\u6e10\u66b4\u9732\u51fa\u6765\uff0c\u6700\u7ec8\u4fc3\u4f7f\u6211\u4eec\u542f\u52a8\u4e86\u5236\u54c1\u4ed3\u5e93\u7684\u5e73\u66ff\u4e0e\u8fc1\u79fb\u5de5\u4f5c\u3002</p>\n</blockquote>\n<blockquote>\n<p>\u8fc1\u79fb\u5230 kkRepo \u540e\uff0c\u5b9e\u9645\u6548\u679c\uff1a</p>\n</blockquote>\n<blockquote>\n<p>\u4e0d\u518d\u6709\u7ec4\u4ef6\u6570\u91cf\u548c\u8bf7\u6c42\u91cf\u4e0a\u9650\uff0c\u4e0d\u7528\u62c5\u5fc3\u89e6\u53d1\u786c\u6027\u5c01\u9876\n\u652f\u6301\u591a\u526f\u672c\u90e8\u7f72\u548c\u6eda\u52a8\u5347\u7ea7\uff0c\u5347\u7ea7\u4e0d\u518d\u9700\u8981\u505c\u670d\n\u53ef\u4ee5\u6309\u9700\u6269\u5bb9\uff0c\u652f\u6301\u5f39\u6027\u4f38\u7f29\n\u5143\u6570\u636e\u5728 MySQL \u4e2d\uff0cblob \u5728 OSS \u4e2d\uff0c\u6570\u636e\u5907\u4efd\u548c\u6062\u590d\u66f4\u65b9\u4fbf\nCI \u914d\u7f6e\u548c\u5ba2\u6237\u7aef\u5168\u90e8\u65e0\u9700\u4fee\u6539\uff0c\u5207\u6362\u540e\u4e1a\u52a1\u4fa7\u6ca1\u6709\u6536\u5230\u4efb\u4f55\u5931\u8d25\u53cd\u9988</p>\n</blockquote>\n<h1>\u540e\u8bb0</h1>\n<p>kkRepo \u4ece\u5f00\u6e90\u5230\u73b0\u5728\uff0c\u4e0d\u5230\u4e00\u4e2a\u6708\u7684\u65f6\u95f4\uff0c\u4e2d\u95f4\u8fd8\u7ecf\u5386\u4e86\u6539\u9879\u76ee\u540d\u79f0\u8fd9\u4e48\u72d7\u8840\u7684\u4e8b\u60c5,\u7136\u540e\u80fd\u5728\u8fd9\u4e48\u77ed\u65f6\u95f4\u5185\u5728 500 \u4eba\u7814\u53d1\u56e2\u961f\u89c4\u6a21\u7684\u4f01\u4e1a\u843d\u5730\uff0c\u5b89\u5168\u5e73\u7a33\u7684\u4ece Nexus \u8fc1\u79fb\u5230\u4e86 kkRepo \uff0c\u5b8c\u5168\u8d85\u51fa\u4e86\u6211\u7684\u9884\u671f\u3002\u8fd9\u8bc1\u660e\u4e86 kkRepo \u8fd9\u4e2a\u9879\u76ee\u6709\u771f\u5b9e\u7684\u9879\u76ee\u4ef7\u503c\uff0c\u4ee5\u53ca\u843d\u5730\u573a\u666f\u3002\u5e0c\u671b kkRepo \u8fd9\u4e2a\u9879\u76ee\u80fd\u5e2e\u52a9\u5230\u66f4\u591a\u7684\u4f01\u4e1a\uff0c\u53d1\u6325\u66f4\u5927\u7684\u4ef7\u503c\u3002</p>\n"
    }, 
    {
      "author": {
        "url": "https://www.v2ex.com/member/Adven", 
        "name": "Adven", 
        "avatar": "https://cdn.v2ex.com/gravatar/8918b39fced3705b49483d231415cecd?s=73&d=retro"
      }, 
      "url": "https://www.v2ex.com/t/1224471", 
      "title": "Sonatype \u6b63\u5f15\u5165 Maven Central \u4ed3\u5e93\u53d1\u5e03\u4f7f\u7528\u60c5\u51b5\u53ef\u89c1\u6027\u548c\u9488\u5bf9\u9ad8\u6d41\u91cf\u53d1\u5e03\u6d3b\u52a8\u7684\u9650\u5236", 
      "id": "https://www.v2ex.com/t/1224471", 
      "date_published": "2026-07-02T05:01:09+00:00", 
      "content_html": "<h3>Maven Central \u53d1\u5e03\u9650\u5236</h3>\n<p>Sonatype \u7684\u7edf\u8ba1\u6570\u636e\u663e\u793a\uff0c\u53d1\u5e03\u9700\u6c42\u9ad8\u5ea6\u96c6\u4e2d\u3002\u8fc7\u53bb 90 \u5929\u91cc\uff0c10% \u7684\u547d\u540d\u7a7a\u95f4\u5360\u636e\u4e86\u4ee5\u4e0b\u4efd\u989d\uff1a</p>\n<ul>\n<li>\u8d85\u8fc7 88% \u7684\u53d1\u5e03\u5230 Maven Central \u7684\u6587\u4ef6</li>\n<li>\u65b0\u7248\u672c\u5360\u7528\u4e86\u8d85\u8fc7 90%\u7684\u603b\u5b58\u50a8\u7a7a\u95f4</li>\n<li>\u8d85\u8fc7 70% \u7684\u65b0\u53d1\u5e03\u6d3b\u52a8</li>\n</ul>\n<p><img alt=\"publishing-limit-file-count-distribution.pn\" class=\"embedded_image\" loading=\"lazy\" referrerpolicy=\"no-referrer\" rel=\"noreferrer\" src=\"https://central.sonatype.org/images/publishing-limit-file-count-distribution.png\"/></p>\n<p><img alt=\"publishing-limit-release-size-distribution.png\" class=\"embedded_image\" loading=\"lazy\" referrerpolicy=\"no-referrer\" rel=\"noreferrer\" src=\"https://central.sonatype.org/images/publishing-limit-release-size-distribution.png\"/></p>\n<p><img alt=\"publishing-limit-release-count-distribution.png\" class=\"embedded_image\" loading=\"lazy\" referrerpolicy=\"no-referrer\" rel=\"noreferrer\" src=\"https://central.sonatype.org/images/publishing-limit-release-count-distribution.png\"/></p>\n<p>\u65b0\u7684\u9650\u5236\u653f\u7b56\u4e3b\u8981\u9488\u5bf9 Maven Central \u4e2d\u6d41\u91cf\u6700\u9ad8\u7684\u53d1\u5e03\u6a21\u5f0f\uff0c\u5176\u4f9d\u636e\u662f\u6392\u540d\u524d 10% \u7684\u53d1\u5e03\u8005\u7684\u4f7f\u7528\u6570\u636e\u3002</p>\n<p>\u666e\u901a\u7528\u6237\u7684\u9650\u5236\u5305\u62ec\uff1a</p>\n<ul>\n<li>\u53d1\u5e03\u6784\u4ef6\u5927\u5c0f   80Mb/\u6bcf\u6708</li>\n<li>\u6587\u4ef6\u8ba1\u6570      1000 \u4e2a/\u6708</li>\n<li>\u53d1\u5e03\u6570\u91cf      7 \u6b21/\u6708  </li>\n</ul>\n<p>Maven Central \u8ddf\u8e2a\u5c06\u4e09\u4e2a\u6708\u5ea6\u53d1\u5e03\u6307\u6807\uff1a\u6587\u4ef6\u6570\u91cf\u3001\u7248\u672c\u5927\u5c0f\u548c\u7248\u672c\u53d1\u5e03\u6b21\u6570\u3002</p>\n<p>\u503c\u5f97\u6ce8\u610f\u7684\u662f\uff0c\u901a\u5e38\u53d1\u5e03\u4e00\u4e2a jar \u5305\u542b\uff1asignatures, checksums, source jars, javadocs \u5bf9\u5e94\u591a\u4e2a\u6587\u4ef6\uff0c\u5b9e\u9645\u5141\u8bb8\u53d1\u5e03\u7684 jar \u5305\u6570\u91cf\u5e94\u8be5\u4f1a\u4f4e\u4e8e 1000 \uff0c\u5bf9\u4e8e\u591a\u6a21\u5757\u7684 Maven/Gradle \u9879\u76ee\uff0c\u8fd9\u4e2a\u9650\u5236\u4f1a\u7279\u522b\u4e0d\u53cb\u597d\u3002</p>\n<p>\u5b98\u65b9\u8868\u793a\u6307\u6807\u91c7\u7528\u4e09\u4e2a\u6708\u7684\u5e73\u5747\u503c\u8fdb\u884c\u8bc4\u4f30\uff0c\u5076\u5c14\u7684\u504f\u5dee\u3001\u77ed\u671f\u6fc0\u589e\u6216\u7d27\u6025\u53d1\u5e03\u6d3b\u52a8\uff08\u4f8b\u5982\u9488\u5bf9 CVE \u7684\u5b89\u5168\u4fee\u590d\uff09\u672c\u8eab\u4e0d\u4f1a\u5bfc\u81f4\u9650\u5236\u751f\u6548\u3002</p>\n<p>\u5bf9\u4e8e\u5f00\u6e90\u793e\u533a\u3001Apache \u57fa\u91d1\u4f1a\u7684\u5f00\u6e90\u9879\u76ee\uff08\u8fd9\u4e9b\u6784\u4ef6\u672c\u8eab\u4e5f\u4e0d\u4f1a\u76f4\u63a5\u53d1\u5e03\u5230\u4e2d\u592e\u4ed3\u5e93\uff09\u4e0d\u505a\u9650\u5236</p>\n<p>\u53ef\u767b\u5f55 Sonatype Maven Central \u540e\u53f0\u5e76\u5bfc\u822a\u81f3 \u201c\u53d1\u5e03\u201d-&gt; \u201c<a href=\"https://central.sonatype.com/publishing/usage\" rel=\"nofollow\">\u4f7f\u7528\u4e2d\u5fc3</a>\u201d\u6765\u67e5\u627e\u8d26\u6237\u7684\u53d1\u5e03\u4f7f\u7528\u60c5\u51b5\u3002</p>\n<p><img alt=\"usage\" class=\"embedded_image\" loading=\"lazy\" referrerpolicy=\"no-referrer\" rel=\"noreferrer\" src=\"https://i.imgur.com/CLURiK1.png\"/></p>\n<h3>Maven Central \u53d1\u5e03\u9650\u5236\u65f6\u95f4\u8868</h3>\n<table>\n<thead>\n<tr>\n<th>\u9636\u6bb5</th>\n<th>\u65e5\u671f</th>\n<th>\u4f1a\u53d1\u751f\u4ec0\u4e48</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>\u8f6f\u9650\u5236</td>\n<td>2026 \u5e74 6 \u6708 16 \u65e5</td>\n<td>\u4f7f\u7528\u60c5\u51b5\u53ef\u89c1\u6027\u548c\u901a\u77e5\u53ef\u5728\u201c\u4f7f\u7528\u4e2d\u5fc3\u201d\u67e5\u770b\u3002\u53d1\u5e03\u8005\u5728\u63a5\u8fd1\u6216\u8d85\u8fc7\u5f53\u524d\u9608\u503c\u65f6\u53ef\u80fd\u4f1a\u6536\u5230\u8b66\u544a\u3002\u53d1\u5e03\u6d3b\u52a8\u5c06\u6301\u7eed\u8fdb\u884c\uff0c\u4e0d\u4f1a\u4e2d\u65ad\u3002\u60a8\u53ef\u4ee5\u5728\u6b64\u9636\u6bb5\u67e5\u770b\u4f7f\u7528\u60c5\u51b5\u3001\u4e86\u89e3\u8d8b\u52bf\u3001\u8c03\u6574\u53d1\u5e03\u6a21\u5f0f\u3001\u7ea0\u6b63\u547d\u540d\u7a7a\u95f4\u6216\u7ec4\u7ec7\u95ee\u9898\u3001\u7533\u8bf7\u66f4\u9ad8\u7684\u9650\u5236\u6216\u8c41\u514d\uff0c\u6216\u8005\u5728\u9002\u5f53\u60c5\u51b5\u4e0b\u8bc4\u4f30 Maven Central Publisher Pro \u3002</td>\n</tr>\n<tr>\n<td>\u901f\u7387\u9650\u5236</td>\n<td>2026 \u5e74 8 \u6708 11 \u65e5</td>\n<td>\u7ecf\u5e38\u53d1\u5e03\u5185\u5bb9\u8d85\u8fc7\u514d\u8d39\u9608\u503c\u7684\u7ec4\u7ec7\u9700\u8981\u91c7\u53d6\u76f8\u5e94\u7684\u89e3\u51b3\u65b9\u6848\u2014\u2014\u8c03\u6574\u9650\u5236\u3001\u8c41\u514d\u6216 Maven Central Publisher Pro\u2014\u2014\u624d\u80fd\u7ee7\u7eed\u4e0d\u95f4\u65ad\u5730\u53d1\u5e03\u5185\u5bb9\u3002</td>\n</tr>\n</tbody></table><h3>\u7f13\u89e3\u63aa\u65bd</h3>\n<p>\u5bf9\u4e8e\u53d1\u5e03\u5927\u578b SDK \u3001\u751f\u6210\u7684\u5ba2\u6237\u7aef\u3001\u4ee3\u7406\u3001\u96c6\u6210\u3001\u5e73\u53f0\u7ec4\u4ef6\u3001\u5f00\u53d1\u8005\u5de5\u5177\u6216\u53d1\u5e03\u6d3b\u52a8\u7ecf\u5e38\u8d85\u51fa\u514d\u8d39\u9650\u989d\u7684\u7ec4\u7ec7\uff0c\u53ef\u9009 Sonatype \u63d0\u4f9b\u7684\u4ed8\u8d39\u7684 Maven Central Publisher Pro \u670d\u52a1\u3002</p>\n"
    }, 
    {
      "author": {
        "url": "https://www.v2ex.com/member/ko1haha", 
        "name": "ko1haha", 
        "avatar": "https://cdn.v2ex.com/gravatar/336fa93f33fc8bb3b2360948271327a6?s=73&d=retro"
      }, 
      "url": "https://www.v2ex.com/t/1223686", 
      "title": "\u8ba9 Java \u518d\u6b21\u4f1f\u5927\uff0c\u6ca1\u6709\u4eba\u6bd4\u6211\u66f4\u61c2\u5f97\u5982\u4f55\u6253\u5305\uff01\uff08\u5206\u4eab\u4e00\u4e2a\u56db\u4e24\u62e8\u5343\u65a4\u7684\u591a jar \u6253\u5305 exe \u65b9\u5f0f\uff09", 
      "id": "https://www.v2ex.com/t/1223686", 
      "date_published": "2026-06-29T07:31:15+00:00", 
      "content_html": "<p>Java \u786e\u5b9e\u662f\u5185\u5b58\u4e0d\u9ad8\u6548\u7684\u3002\u540c\u6837\u7684\u5185\u5b58\uff0cfultter / dart \u80fd\u591f\u521b\u5efa\u6d41\u7545\u7684\u5e94\u7528\uff0c\u800c Java \u8981\u4e48\u5361\u6210 ppt \uff0c\u8981\u4e48\u75af\u72c2\u5403\u5185\u5b58\u3002</p>\n<p>\u5206\u4eab\u6d4b\u8bd5\u4e00\u4e2a\u865a\u62df\u673a\u5185\u5b58\u56de\u6536\u6548\u7387\u7684\u65b9\u6cd5\uff08\u5927\u5bb6\u5e94\u8be5\u90fd\u4f1a\u5427\uff1a\uff09\uff1awin \u4e0b\u4f7f\u7528 procgov \u5047\u88c5\u672c\u673a\u53ea\u6709 100 mb \u5185\u5b58\uff0c\u518d\u8fd0\u884c gui \u7a0b\u5e8f\uff0c\u6d4b\u8bd5\u5361\u4e0d\u5361\u3002</p>\n<p>\u7ed3\u679c\uff0cjavafx \u5361\u6210 ppt \uff0cflutter \u5199\u7684\u684c\u9762 app \u5374\u4f9d\u7136\u6d41\u7545\uff0c\u51e0\u4e4e\u6ca1\u6709\u5361\u987f\uff01\uff08\u4f8b\u5b50\uff1adart \u5199\u7684 myune_music \u5b58\u5728\u4e25\u91cd\u7684\u5185\u5b58\u6cc4\u6f0f\uff0c\u7a0d\u5fae\u5207\u6362\u5185\u5b58\u72c2\u98d9 300mb+\uff0c\u7136\u800c\u9650\u5236 100mb \u540e\uff0c\u4f9d\u7136\u6d41\u7545\uff0c\u795e\u5947\u5427\uff01\uff09</p>\n<p>\u8fd9\u8bf4\u660e flutter / dart \u7684\u865a\u62df\u673a\u6bd4 java \u66f4\u9ad8\u7ea7 \u2014\u2014 \u5373\u4f7f\u518d\u5185\u5b58\u6cc4\u9732\u7684\u60c5\u51b5\u4e0b\u3002</p>\n<p>\u4eba\u624d\u4e0d\u65ad\u6d8c\u5165\u65b0\u7684\u9886\u57df\uff0cJava \u5df2\u7ecf\u6210\u719f\u5230\u53ef\u4ee5\u5c01\u5370\u8d77\u6765\u88c5\u88f1\uff0c\u6210\u719f\u5230\u53ef\u4ee5\u4f7f\u7528 java8 \u4e00\u4e07\u5e74\uff0c\u65b0\u7684\u6539\u8fdb\u4f3c\u4e4e\u4e5d\u725b\u4e00\u6bdb\uff0c\u518d\u4e5f\u4e0d\u80fd\u4ece\u6839\u672c\u4e0a\u63d0\u5347\u3002</p>\n<p>\u4f46\u5f53\u6211\u4ece 64 \u4f4d\u7684 java8 \u5207\u6362\u5230 32 \u4f4d\u7684 java8 \uff0c\u5185\u5b58\u9700\u6c42\u7acb\u9a6c\u51cf\u534a\uff0c\u5373\u4f7f\u9650\u5236 100mb \u5185\u5b58\uff0c\u4e5f\u6ca1\u6709\u90a3\u4e48\u5361\u4e86\u3002</p>\n<p>\u8fd9\u7ed9\u6211\u4e00\u70b9\u4fe1\u5fc3\u3002\u6211\u8fd8\u662f\u5f88\u559c\u6b22 javafx \uff0c\u4e5f\u66fe\u5347\u7ea7\u5230\u65b0\u7684 open jdk \uff0c\u6253\u5305\u65b9\u5f0f\u592a\u590d\u6742\uff0c\u800c\u4e14\u51e0\u4e4e\u6ca1\u6709\u533a\u522b\uff0c\u5c24\u5176\u662f\u6d4f\u89c8\u5668\u5185\u6838\uff0c\u6240\u4ee5\u53c8\u56de\u5230 java8 \u5e76\u9501\u6b7b\u3002</p>\n<p>\u90a3\u4e48\uff0c\u5982\u4f55\u6253\u5305\u5206\u4eab\u7ed9\u5176\u4ed6\u7528\u6237\u5462\uff1f</p>\n<p>\u641c\u904d\u5168\u7f51\uff0c\u4f3c\u4e4e\u6ca1\u6709\u597d\u7684\u65b9\u6848\uff1f</p>\n<ul>\n<li>Launch4j\uff1a \u63d0\u4f9b\u628a\u5355\u4e2a jar \u8ffd\u52a0\u5230\u9884\u5236\u7684\u542f\u52a8\u5668\u540e\u9762\u7684 blacksmith \u3002\u591a jar \u9700\u8981\u4e00\u4e2a\u4e2a\u586b\u5199\u5341\u5206\u9ebb\u70e6\u3002</li>\n<li>jsmooth\uff1a \u4e5f\u662f\u9884\u5236\u542f\u52a8\u5668.exe \uff0c\u53ef\u4ee5\u66f4\u65b9\u4fbf\u5730\u6dfb\u52a0\u591a\u4e2a jar (\u76f8\u5bf9\u8def\u5f84\uff09\u4f5c\u4e3a\u542f\u52a8\u53c2\u6570\u3002</li>\n</ul>\n<p>\u8fd9\u4e9b\u65b9\u6848\u7684\u672c\u8d28\u662f\u542f\u52a8\u5668\u3002\u56e0\u4e3a java \u7a0b\u5e8f\u7684\u672c\u8d28\u5c31\u662f\u8c03\u7528\u4e0a\u4f4d\u5f00\u53d1\u8005\u63d0\u4f9b\u7684\u865a\u62df\u673a.exe \u8fd0\u884c\u7f16\u8bd1\u540e\u7684\u5b57\u8282\u7801\u3002</p>\n<p>\u90a3\u6211\u81ea\u5df1\u5199\u4e2a\u542f\u52a8\u5668\u597d\u4e86\uff01\u7f16\u4e0d\u4e86\u865a\u62df\u673a\uff0c\u6211\u8fd8\u7f16\u4e0d\u4e86\u542f\u52a8\u5668\uff1f\u5c0f\u6837\uff0c\u4f55\u987b\u4ed6\u4eba\u9884\u5236\uff01</p>\n<p>\u5148\u8bf4\u6211\u81ea\u5df1\u5982\u4f55\u81ea\u7528\u4e00\u4e9b java \u5c0f\u5de5\u5177\u7684\uff1a\u4f7f\u7528 idea \u7f16\u8bd1\u540e\uff0c\u5199\u4e2a bat/AHK/Python \u8c03\u7528 java.exe \u8fd0\u884c\u7f16\u8bd1\u597d\u7684 class \u3002</p>\n<p>\u90a3\u4e48\u6211\u7684\u542f\u52a8\u5668\u5c31\u53ef\u4ee5\u5c01\u88c5\u8fd9\u6761\u542f\u52a8\u6307\u4ee4\u3002</p>\n<p>\u56fe\u50cf\uff08 AHK \u5199\u7684\u542f\u52a8\u5668 GUI \uff09\uff1a</p>\n<p><img alt=\"\" class=\"embedded_image\" loading=\"lazy\" referrerpolicy=\"no-referrer\" rel=\"noreferrer\" src=\"https://imgur.com/K7aA7ku.png\"/></p>\n<p>\u6ca1\u6709\u68c0\u6d4b\u5230 jvm \u7684\u65f6\u5019\uff0c\u63d0\u4f9b\u4e0b\u8f7d\u94fe\u63a5\u3002\u542f\u52a8\u6210\u529f\u540e\uff0c\u4fdd\u5b58\u5feb\u6377\u65b9\u5f0f\uff0c\u5c31\u80fd\u76f4\u63a5\u8fd0\u884c javaw.exe \uff0c\u4e0d\u518d\u9700\u8981\u542f\u52a8\u5668\uff0c\u5e72\u6389\u4e2d\u95f4\u5c42\uff01</p>\n<p>\u522b\u4eba\u8fd8\u5728\u7814\u7a76\u600e\u4e48\u4f7f\u7528\u4ed6\u4eba\u9884\u5236\u7684\u542f\u52a8\u5668.exe \uff0c\u6211\u5df2\u7ecf\u5e72\u6389\u542f\u52a8\u5668\u4e86\uff0c\u542f\u52a8\u5668\u5c31\u662f\u4e2a\u8df3\u677f\uff0c\u7528\u4e8e\u5bfc\u51fa\u5feb\u6377\u65b9\u5f0f\uff0c\u4e5f\u53ef\u4ee5\u53f3\u952e\u56fa\u5b9a\u5f00\u59cb\u83dc\u5355\uff0c\u51e0\u4e4e\u6ca1\u5565\u95ee\u9898\uff01</p>\n<p>\u5c31\u7528\u8fd9\u4e2a\u65b9\u6cd5\u53d1\u5e03\u4e9b\u5c0f\u5de5\u5177\u5427\uff0c\u8ba9 Java \u518d\u6b21\u4f1f\u5927\uff0c\u4ece\u5360\u9886\u5c0f\u5de5\u5177 &amp;&amp; \u5c0f\u6e38\u620f\u5f00\u59cb\uff01</p>\n<p><img alt=\"\" class=\"embedded_image\" loading=\"lazy\" referrerpolicy=\"no-referrer\" rel=\"noreferrer\" src=\"https://imgur.com/88gp34k.png\"/></p>\n"
    }, 
    {
      "author": {
        "url": "https://www.v2ex.com/member/g632104866", 
        "name": "g632104866", 
        "avatar": "https://cdn.v2ex.com/avatar/01d5/38d4/510131_large.png?m=1783481882"
      }, 
      "url": "https://www.v2ex.com/t/1222838", 
      "date_modified": "2026-06-25T08:52:59+00:00", 
      "content_html": "<p>\u5728\u56e2\u961f\u5f00\u53d1\u4e2d\uff0cMaven \u79c1\u670d\u51e0\u4e4e\u662f Java \u5de5\u7a0b\u7684\u57fa\u7840\u8bbe\u65bd\u6807\u914d\u3002\nkkRepo \u662f\u4e00\u4e2a\u5f00\u6e90\u7684\u81ea\u6258\u7ba1\u5236\u54c1\u4ed3\u5e93\uff0c\u652f\u6301 Maven \u3001npm \u3001PyPI \u3001Go \u3001Helm \u3001Docker/OCI \u7b49\u591a\u79cd\u5236\u54c1\u683c\u5f0f\u3002</p>\n<p>kkRepo \u9879\u76ee\u5730\u5740</p>\n<ul>\n<li><a href=\"https://github.com/klboke/kkrepo\" rel=\"nofollow\">https://github.com/klboke/kkrepo</a></li>\n<li><a href=\"https://gitee.com/kailing/kkRepo\" rel=\"nofollow\">https://gitee.com/kailing/kkRepo</a></li>\n</ul>\n<h2>\u4e00\u3001\u5feb\u901f\u542f\u52a8 kkRepo</h2>\n<p>\u672c\u5730\u4f53\u9a8c\u53ef\u4ee5\u76f4\u63a5\u4f7f\u7528\u5b98\u65b9 quickstart \u811a\u672c\uff0c\u5b83\u4f1a\u62c9\u8d77 kkRepo \u548c MySQL\uff1a</p>\n<p>curl -fsSL <a href=\"https://raw.githubusercontent.com/klboke/kkrepo/main/scripts/quickstart.sh\" rel=\"nofollow\">https://raw.githubusercontent.com/klboke/kkrepo/main/scripts/quickstart.sh</a> | bash\n\u542f\u52a8\u5b8c\u6210\u540e\u8bbf\u95ee\uff1a</p>\n<ul>\n<li>\u7ba1\u7406\u63a7\u5236\u53f0\uff1a <a href=\"http://127.0.0.1:19090/admin/\" rel=\"nofollow\">http://127.0.0.1:19090/admin/</a></li>\n<li>\u7528\u6237\u4fa7\u6d4f\u89c8\u5668\uff1a <a href=\"http://127.0.0.1:19090/browse/\" rel=\"nofollow\">http://127.0.0.1:19090/browse/</a></li>\n<li>\u5065\u5eb7\u68c0\u67e5\uff1a <a href=\"http://127.0.0.1:19091/actuator/health\" rel=\"nofollow\">http://127.0.0.1:19091/actuator/health</a></li>\n</ul>\n<p>\u9996\u6b21\u8fdb\u5165\u7ba1\u7406\u63a7\u5236\u53f0\u65f6\uff0c\u9700\u8981\u521b\u5efa\u521d\u59cb Local/admin \u7ba1\u7406\u5458\u5bc6\u7801\u3002</p>\n<h2>\u4e8c\u3001\u521b\u5efa Maven \u4ed3\u5e93</h2>\n<p>\u8fdb\u5165 /admin/ \u540e\uff0c\u5efa\u8bae\u6309 Maven \u5e38\u89c1\u7528\u6cd5\u521b\u5efa\u4e09\u7c7b\u4ed3\u5e93\uff1a</p>\n<ul>\n<li>maven-releases    hosted \uff0c\u7528\u4e8e\u53d1\u5e03\u6b63\u5f0f\u7248\u672c</li>\n<li>maven-snapshots   hosted \uff0c\u7528\u4e8e\u53d1\u5e03 SNAPSHOT \u7248\u672c</li>\n<li>maven-central     proxy \uff0c\u7528\u4e8e\u4ee3\u7406 Maven Central</li>\n<li>maven-public      group \uff0c\u7528\u4e8e\u4f9d\u8d56\u62c9\u53d6\u5165\u53e3</li>\n</ul>\n<p>\u521b\u5efa maven-central proxy \u4ed3\u5e93\u65f6\uff0c\u4e0a\u6e38\u5730\u5740\u53ef\u4ee5\u586b\u5199 Maven Central \u7684\u5b98\u65b9\u4ed3\u5e93\u5730\u5740\uff1a</p>\n<ul>\n<li><a href=\"https://repo.maven.apache.org/maven2/\" rel=\"nofollow\">https://repo.maven.apache.org/maven2/</a></li>\n</ul>\n<p>\u5982\u679c\u516c\u53f8\u5df2\u6709\u5185\u7f51 Maven \u955c\u50cf\uff0c\u4e5f\u53ef\u4ee5\u628a proxy \u7684\u4e0a\u6e38\u5730\u5740\u66ff\u6362\u6210\u5185\u90e8\u955c\u50cf\u5730\u5740\u3002</p>\n<p>\u521b\u5efa maven-public group \u4ed3\u5e93\u65f6\uff0c\u628a\u4e0b\u9762\u51e0\u4e2a\u6210\u5458\u4ed3\u5e93\u52a0\u5165 group\uff1a</p>\n<ul>\n<li>maven-releases \u3001maven-snapshots \u3001maven-central</li>\n</ul>\n<p>\u8fd9\u6837\u5ba2\u6237\u7aef\u53ea\u9700\u8981\u4ece <code>maven-public</code> \u4e00\u4e2a\u5730\u5740\u62c9\u4f9d\u8d56\uff1a\u516c\u53f8\u5185\u90e8\u53d1\u5e03\u5230\u79c1\u670d\u7684\u5305\u4f1a\u4ece maven-releases \u6216 maven-snapshots \u547d\u4e2d\uff0c\u7b2c\u4e09\u65b9\u5f00\u6e90\u4f9d\u8d56\u4f1a\u901a\u8fc7 maven-central proxy \u56de\u6e90\u5e76\u7f13\u5b58\u3002\u53d1\u5e03\u65f6\u4ecd\u7136\u5206\u522b\u5199\u5165 maven-releases \u6216 maven-snapshots \u3002</p>\n<p><img alt=\"img\" class=\"embedded_image\" loading=\"lazy\" referrerpolicy=\"no-referrer\" rel=\"noreferrer\" src=\"https://i.imgur.com/shcRqne.png\"/></p>\n", 
      "date_published": "2026-06-25T08:51:18+00:00", 
      "title": "\u4f7f\u7528 kkRepo \u642d\u5efa Maven \u79c1\u670d", 
      "id": "https://www.v2ex.com/t/1222838"
    }, 
    {
      "author": {
        "url": "https://www.v2ex.com/member/g632104866", 
        "name": "g632104866", 
        "avatar": "https://cdn.v2ex.com/avatar/01d5/38d4/510131_large.png?m=1783481882"
      }, 
      "url": "https://www.v2ex.com/t/1222552", 
      "title": "Nexus \u7684\u5e73\u66ff neuxs-plus \u5f00\u6e90\u6d89\u5acc\u5546\u6807\u4fb5\u6743\uff0c\u88ab\u8feb\u6539\u540d kkRepo", 
      "id": "https://www.v2ex.com/t/1222552", 
      "date_published": "2026-06-24T07:40:28+00:00", 
      "content_html": "<p>\u535a\u4e3b\u6700\u8fd1\u5f00\u6e90\u4e86\u4e00\u4e2a\u4ed3\u5e93\u5236\u54c1\u7ba1\u7406\u9879\u76ee nexus-plus \uff0c\u9879\u76ee\u7684\u5b9a\u4f4d\u662f\u5b8c\u5168\u5e73\u66ff Nexus \uff0c\u89e3\u51b3 Nexus \u7684\u7a33\u5b9a\u6027\u3001\u4e0d\u80fd\u591a\u526f\u672c\u90e8\u7f72\uff0c\u5f00\u6e90\u7248\u672c\u9650\u5236\u6bcf\u65e5\u8bf7\u6c42\u7b49\u95ee\u9898\u3002\u652f\u6301\u4e00\u952e\u4ece Nexus \u8fc1\u79fb\u6570\u636e\u5230 nexus-plus</p>\n<p>\u5199 JAVA \u7684\u80af\u5b9a\u90fd\u77e5\u9053 Nexus \u8fd9\u4e2a\u8f6f\u4ef6\uff0c\u8001\u724c\u7684 Maven \u79c1\u670d\u8f6f\u4ef6\uff0c\u4f46\u662f\u540e\u6765\u514d\u8d39\u7248\u672c\u52a0\u4e86\u975e\u5e38\u591a\u7684\u9650\u5236\uff0cPRO \u7248\u672c\u53c8\u5f88\u8d35\u3002Nexus \u793e\u533a\u5df2\u7ecf\u5404\u79cd\u5410\u69fd\u4e86</p>\n<p>\u6700\u5f00\u59cb\u9879\u76ee\u540d\u79f0\u662f nexus-plus, \u4e3b\u6253\u4e00\u4e2a nexus \u7684\u589e\u5f3a\u7248\uff0c\u7136\u540e\u5c31\u6536\u5230 Nexus \u7684\u6d89\u5acc\u54c1\u724c\u5546\u54c1\u4fb5\u6743\u7684\u90ae\u4ef6\uff0c\u8bf4\u7684\u975e\u5e38\u4e25\u91cd\uff0c\u4ec0\u4e48\u6d89\u5acc\u5546\u6807\u4fb5\u6743\uff0c\u9650\u671f\u4e0d\u6539\u5c31\u8d77\u8bc9\uff0c\u7136\u540e\u4f1a\u9700\u8981\u6211\u627f\u62c5\u5f8b\u5e08\u8d39\u7528\u7b49\u7b49\u3002\u6b64\u65f6\u6211\u6709\u4e24\u4e2a\u505a\u6cd5\uff1a</p>\n<ul>\n<li>\u575a\u6301 neuxs-plus \u7684\u9879\u76ee\u547d\u540d\uff0c\u7136\u540e\u7b49\u5bf9\u65b9\u4e0b\u4e00\u6b65\u52a8\u4f5c</li>\n<li>\u6539\u540d \uff0c\u591a\u4e00\u4e8b\u4e0d\u5982\u5c11\u4e00\u4e8b</li>\n</ul>\n<p>\u6700\u540e\u76f8\u4fe1\u8fd8\u662f\u6539\u540d\u7b97\u4e86\uff0c\u6240\u4ee5 kkRepo \u8fd9\u4e2a\u65b0\u7684\u54c1\u724c\u540d\u79f0\u51fa\u6765\u4e86</p>\n<ul>\n<li><a href=\"https://gitee.com/kailing/kkRepo\" rel=\"nofollow\">https://gitee.com/kailing/kkRepo</a></li>\n<li><a href=\"https://github.com/klboke/kkRepo\" rel=\"nofollow\">https://github.com/klboke/kkRepo</a></li>\n</ul>\n<p>\u5e0c\u671b\u591a\u591a\u652f\u6301\u5f00\u6e90\uff0c\u4e89\u53d6\u90fd\u7528 kkRepo \u66ff\u6362\u6389 Nexus</p>\n"
    }, 
    {
      "author": {
        "url": "https://www.v2ex.com/member/MattMin", 
        "name": "MattMin", 
        "avatar": "https://cdn.v2ex.com/avatar/5739/66be/395806_large.png?m=1781938785"
      }, 
      "url": "https://www.v2ex.com/t/1221634", 
      "title": "\u6211\u5728 IDEA tab \u91cc\u517b\u4e86\u4e00\u53ea\u732b", 
      "id": "https://www.v2ex.com/t/1221634", 
      "date_published": "2026-06-20T07:07:05+00:00", 
      "content_html": "<p>\u6211\u5199\u4e86\u4e00\u4e2a JetBrains \u63d2\u4ef6\uff0c\u540d\u5b57\u53eb Active Tab Color \u3002\u5b83\u539f\u672c\u662f\u7528\u6765\u81ea\u5b9a\u4e49\u7f16\u8f91\u5668 tab \u989c\u8272\u7684\uff0c\u4f46\u73b0\u5728\u6211\u6700\u559c\u6b22\u7684\u529f\u80fd\u5df2\u7ecf\u53d8\u6210\u4e86 Tab Cat \u3002</p>\n<p>\u5f00\u542f\u540e\uff0c\u7f16\u8f91\u5668\u7684 tab \u680f\u4e0a\u4f1a\u51fa\u73b0\u4e00\u53ea\u5c0f\u732b\u3002\u6bcf\u6b21\u5207\u6362\u6587\u4ef6\uff0c\u5b83\u90fd\u4f1a\u8ddf\u7740\u5f53\u524d\u9009\u4e2d\u7684 tab \u79fb\u52a8\uff1a</p>\n<ul>\n<li>\u8ddd\u79bb\u6bd4\u8f83\u8fd1\u65f6\uff0c\u5b83\u4f1a\u6162\u6162\u8d70\u8fc7\u53bb</li>\n<li>\u8ddd\u79bb\u6bd4\u8f83\u8fdc\u65f6\uff0c\u5b83\u4f1a\u8dd1\u8fc7\u53bb</li>\n<li>\u6539\u53d8\u65b9\u5411\u65f6\u4f1a\u5148\u8f6c\u8eab</li>\n<li>\u5230\u8fbe active tab \u540e\u4f1a\u5750\u4e0b\uff0c\u5076\u5c14\u8fd8\u4f1a\u7728\u773c</li>\n<li>Tool Window \u6253\u5f00\u3001\u5173\u95ed\u6216\u8c03\u6574\u5927\u5c0f\u65f6\uff0c\u5b83\u4e5f\u4f1a\u91cd\u65b0\u5bfb\u627e tab \u7684\u4f4d\u7f6e</li>\n</ul>\n<p>\u76ee\u524d\u53ef\u4ee5\u9009\u62e9\u4e09\u53ea\u4e0d\u540c\u7684\u5c0f\u732b\uff0c\u4e5f\u53ef\u4ee5\u8c03\u6574\u5c0f\u732b\u7684\u5927\u5c0f\u3002\u4f60\u8fd8\u53ef\u4ee5\u901a\u8fc7 Tools \u83dc\u5355\u968f\u65f6\u628a\u5b83\u53eb\u51fa\u6765\u6216\u85cf\u8d77\u6765\u3002</p>\n<p>\u63d2\u4ef6\u672c\u8eab\u4e5f\u652f\u6301\u81ea\u5b9a\u4e49 active tab \u7684\u80cc\u666f\u8272\u3001\u4e0b\u5212\u7ebf\u548c\u5916\u6846\uff0c\u8fd8\u53ef\u4ee5\u7528\u6b63\u5219\u8868\u8fbe\u5f0f\u7ed9\u4e0d\u540c\u6587\u4ef6\u540d\u8bbe\u7f6e\u4e0d\u540c\u7684 tab \u989c\u8272\u3002</p>\n<p>\u7406\u8bba\u4e0a\u5b83\u53ef\u4ee5\u8fd0\u884c\u5728 IntelliJ IDEA \u3001WebStorm \u3001PyCharm \u3001GoLand \u3001PhpStorm \u7b49\u57fa\u4e8e IntelliJ Platform \u7684 IDE \u4e2d\u3002\u76ee\u524d\u6211\u5df2\u7ecf\u5728 IntelliJ IDEA Community 2024.1.7 \u548c IntelliJ IDEA 2026.1 \u4e0a\u9a8c\u8bc1\u8fc7\u3002</p>\n<p>GitHub\uff1a <a href=\"https://github.com/MattMin/active-tab-color\" rel=\"nofollow\">https://github.com/MattMin/active-tab-color</a></p>\n<p>\u63d2\u4ef6\u5730\u5740\uff1a <a href=\"https://plugins.jetbrains.com/plugin/32245-active-tab-colorsettings.png\" rel=\"nofollow\">https://plugins.jetbrains.com/plugin/32245-active-tab-colorsettings.png</a></p>\n<p><img alt=\"tab_cat.gif\" class=\"embedded_image\" loading=\"lazy\" referrerpolicy=\"no-referrer\" rel=\"noreferrer\" src=\"https://i.imgur.com/LTmg7gk.gif\"/>\n<img alt=\"Settings.png\" class=\"embedded_image\" loading=\"lazy\" referrerpolicy=\"no-referrer\" rel=\"noreferrer\" src=\"https://i.imgur.com/WQ7gQSl.jpeg\"/></p>\n"
    }, 
    {
      "author": {
        "url": "https://www.v2ex.com/member/nc", 
        "name": "nc", 
        "avatar": "https://cdn.v2ex.com/avatar/66b3/f079/792507_large.png?m=1781351440"
      }, 
      "url": "https://www.v2ex.com/t/1220193", 
      "title": "Java \u786e\u5b9e\u662f\u5185\u5b58\u9ad8\u6548\u7684", 
      "id": "https://www.v2ex.com/t/1220193", 
      "date_published": "2026-06-13T11:51:37+00:00", 
      "content_html": "<div class=\"embedded_video_wrapper\"><iframe src=\"https://www.youtube.com/embed/M_HCG1JPMQE\" class=\"embedded_video\" allowfullscreen=\"\" type=\"text/html\" id=\"ytplayer\" frameborder=\"0\"></iframe></div><br />TLDR:<br /><br /><a target=\"_blank\" href=\"/i/pg6ufa9Ll.png\" rel=\"nofollow noopener\" target=\"_blank\" title=\"\u5728\u65b0\u7a97\u53e3\u6253\u5f00\u56fe\u7247 pg6ufa9Ll.png\"><img src=\"//i.v2ex.co/pg6ufa9Ll.png\" class=\"embedded_image\"></a>"
    }, 
    {
      "author": {
        "url": "https://www.v2ex.com/member/soap0X", 
        "name": "soap0X", 
        "avatar": "https://cdn.v2ex.com/gravatar/78cb72e2bd01326d19a49efee32ba076?s=73&d=retro"
      }, 
      "url": "https://www.v2ex.com/t/1220053", 
      "title": "\u7528 AI \u628a visualvm \u7684\u90e8\u5206\u529f\u80fd\u754c\u9762\u6362\u4e86\u4e2a\u9a6c\u7532", 
      "id": "https://www.v2ex.com/t/1220053", 
      "date_published": "2026-06-12T14:51:30+00:00", 
      "content_html": "<h3>\u5728\u8fd9\u4e2a\u9879\u76ee\u57fa\u7840\u4e0a\u6dfb\u52a0\u7684\u529f\u80fd</h3>\n<pre><code>[AnkeshGG/VitalsSystemMonitor]( https://github.com/AnkeshGG/VitalsSystemMonitor)\n</code></pre>\n<h3>\u505a\u7684\u6548\u679c\u56fe</h3>\n<pre><code>![\u76d1\u63a7\u754c\u9762]( https://i.imgur.com/w7Pgcqz.png)\n</code></pre>\n"
    }, 
    {
      "author": {
        "url": "https://www.v2ex.com/member/collery", 
        "name": "collery", 
        "avatar": "https://cdn.v2ex.com/avatar/28d5/095a/369728_large.png?m=1568608013"
      }, 
      "url": "https://www.v2ex.com/t/1213549", 
      "title": "javaer \u73b0\u5728\u51fa\u53bb\u9762\u8bd5 \u95ee\u54ea\u4e9b\u5185\u5bb9", 
      "id": "https://www.v2ex.com/t/1213549", 
      "date_published": "2026-05-18T07:55:42+00:00", 
      "content_html": "<p>\u597d\u5947\uff0c\u5728 AI \u5927\u80cc\u666f\u4e0b\uff0c\u95ee\u54ea\u4e9b\u5185\u5bb9</p>\n"
    }, 
    {
      "author": {
        "url": "https://www.v2ex.com/member/nitouge", 
        "name": "nitouge", 
        "avatar": "https://cdn.v2ex.com/avatar/4ff9/fa67/617985_large.png?m=1678329746"
      }, 
      "url": "https://www.v2ex.com/t/1205576", 
      "date_modified": "2026-04-13T11:54:52+00:00", 
      "content_html": "<p>\u6267\u884c\u987a\u5e8f\uff08\u4ece\u5c0f\u5230\u5927\uff09\uff1a\n1.TRACE_ID_ORDER - \u751f\u6210 TraceId \uff08\u6700\u9ad8\u4f18\u5148\u7ea7\uff09\n2.BLACK_LIST_ORDER - \u9ed1\u540d\u5355\u68c0\u67e5\uff08\u5c3d\u65e9\u62e6\u622a\uff09\n3.REQUEST_CONTEXT_ORDER - \u7f13\u5b58\u8bf7\u6c42\u4f53\uff08\u4e3a\u540e\u7eed\u8fc7\u6ee4\u5668\u63d0\u4f9b\u6570\u636e\uff09\n4.XSS_INJECTION_ORDER - XSS \u6ce8\u5165\u68c0\u67e5\n5.SQL_INJECTION_ORDER - SQL \u6ce8\u5165\u68c0\u67e5\n6.RATE_LIMITER_ORDER - \u9650\u6d41\u68c0\u67e5\n7.API_LOG_ORDER - API \u65e5\u5fd7\u8bb0\u5f55\n8.AUTH_ORDER - Sa-Token \u8ba4\u8bc1\u9274\u6743\n9.JWT_BLACKLIST_ORDER - JWT \u9ed1\u540d\u5355\u68c0\u67e5\n10.FORWARD_AUTH_ORDER - \u8f6c\u53d1\u8ba4\u8bc1\u4fe1\u606f\n11.\u4e1a\u52a1\u5904\u7406\n12.RESPONSE_CONTEXT_ORDER - \u7f13\u5b58\u54cd\u5e94\u4f53\n13.REMOVE_CONTEXT_ORDER - \u6e05\u7406\u4e0a\u4e0b\u6587\uff08\u6700\u4f4e\u4f18\u5148\u7ea7\uff09</p>\n<p>Auth \u662f WebFilter \uff08 SaReactorFilter \uff09\u201d\u8fd9\u4e00\u70b9\u51b3\u5b9a\u4e86\u5b83\u4e00\u5b9a\u4f1a\u5148\u4e8e\u6240\u6709 GlobalFilter \u6267\u884c\u3002\u4e5f\u5c31\u662f\u8bf4\uff0c\u6309\u4f60\u5199\u7684\u5e8f\u5217\u628a Auth \u653e\u5728\u7b2c 8 \u4f4d\uff08 TraceId \u3001\u9ed1\u540d\u5355\u3001\u6ce8\u5165\u4e4b\u540e\uff09\u662f\u505a\u4e0d\u5230\u7684\uff0c\u9664\u975e\u628a\u8ba4\u8bc1\u6539\u9020\u6210 GlobalFilter \uff08\u4e0d\u8d70 SaReactorFilter \uff09\u3002\u6240\u4ee5\uff1a</p>\n<p>\u5982\u679c\u4fdd\u7559 Sa-Token \u7684 SaReactorFilter \uff08\u63a8\u8350\u505a\u6cd5\uff09\uff0c\u5b9e\u9645\u987a\u5e8f\u4e00\u5b9a\u662f\uff1aWebFilter \u9636\u6bb5\u5148\u8ba4\u8bc1\uff0c\u518d\u8fdb\u5165 GlobalFilter \u9636\u6bb5\u505a TraceId/\u9ed1\u540d\u5355/\u6ce8\u5165/\u9650\u6d41/\u65e5\u5fd7\u7b49\u3002\n\u4f60\u7ed9\u51fa\u7684\u5e8f\u5217\u53ef\u4f5c\u4e3a GlobalFilter \u4e4b\u95f4\u7684\u76f8\u5bf9\u987a\u5e8f\uff0c\u4f46\u65e0\u6cd5\u8de8\u8d8a WebFilter \u4e0e GlobalFilter \u7684\u8fb9\u754c\n\u5982\u679c\u8ba4\u8bc1\uff08 Auth \uff09\u653e\u5728\u6700\u524d\u9762\uff0c\u672a\u8ba4\u8bc1\u6216\u975e\u6cd5\u8bf7\u6c42\u53ef\u80fd\u76f4\u63a5\u88ab\u62e6\u622a\uff0c\u5bfc\u81f4 API \u65e5\u5fd7\u548c\u4e0a\u4e0b\u6587\u5904\u7406\u6ca1\u6709\u6267\u884c\n\u6211\u8fd9\u4e2a filter \u987a\u5e8f\u662f\u5426\u6709\u95ee\u9898\uff0c\u4e0b\u9762\u662f\u6574\u7406\u7684\u90e8\u5206</p>\n<table>\n<thead>\n<tr>\n<th>Filter</th>\n<th>\u7c7b\u578b</th>\n<th>\u4f9d\u8d56</th>\n<th>\u63a8\u8350 order</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>CORS</td>\n<td>WebFilter</td>\n<td>-</td>\n<td>Integer.MIN_VALUE</td>\n</tr>\n<tr>\n<td>Auth(Sa-Token)</td>\n<td>WebFilter</td>\n<td>-</td>\n<td>-101</td>\n</tr>\n<tr>\n<td>Actuator</td>\n<td>WebFilter</td>\n<td>-</td>\n<td>-100 \uff08\u53ef\u9009\uff09</td>\n</tr>\n<tr>\n<td>TraceId</td>\n<td>GlobalFilter</td>\n<td>\u65e0</td>\n<td>Integer.MIN_VALUE</td>\n</tr>\n<tr>\n<td>RequestContext</td>\n<td>GlobalFilter</td>\n<td>TraceId</td>\n<td>Integer.MIN_VALUE+20</td>\n</tr>\n<tr>\n<td>Blacklist</td>\n<td>GlobalFilter/WebFilter</td>\n<td>\u53ef\u4f9d\u8d56 Auth</td>\n<td>Integer.MIN_VALUE+10(GlobalFilter)</td>\n</tr>\n<tr>\n<td>XSS Injection</td>\n<td>GlobalFilter</td>\n<td>RequestContext</td>\n<td>Integer.MIN_VALUE+30</td>\n</tr>\n<tr>\n<td>SQL Injection</td>\n<td>GlobalFilter</td>\n<td>RequestContext</td>\n<td>Integer.MIN_VALUE+40</td>\n</tr>\n<tr>\n<td>Rate Limiter</td>\n<td>GlobalFilter</td>\n<td>RequestContext / IP</td>\n<td>Integer.MIN_VALUE+50</td>\n</tr>\n<tr>\n<td>API Log</td>\n<td>GlobalFilter</td>\n<td>RequestContext</td>\n<td>Integer.MIN_VALUE+60</td>\n</tr>\n<tr>\n<td>JWT Blacklist</td>\n<td>GlobalFilter</td>\n<td>Auth</td>\n<td>-90</td>\n</tr>\n<tr>\n<td>Forward Auth</td>\n<td>GlobalFilter</td>\n<td>Auth</td>\n<td>-80</td>\n</tr>\n<tr>\n<td>Business</td>\n<td>\u8def\u7531\u8f6c\u53d1</td>\n<td>-</td>\n<td>-</td>\n</tr>\n<tr>\n<td>ResponseContext</td>\n<td>GlobalFilter</td>\n<td>RequestContext</td>\n<td>WRITE_RESPONSE_FILTER_ORDER-1</td>\n</tr>\n<tr>\n<td>RemoveContext</td>\n<td>GlobalFilter</td>\n<td>\u5168\u5c40\u4e0a\u4e0b\u6587</td>\n<td>Integer.MAX_VALUE</td>\n</tr>\n</tbody></table>", 
      "date_published": "2026-04-13T11:51:55+00:00", 
      "title": "sa-token + spring cloud gateway \u8fc7\u6ee4\u5668\u987a\u5e8f\u95ee\u9898", 
      "id": "https://www.v2ex.com/t/1205576"
    }, 
    {
      "author": {
        "url": "https://www.v2ex.com/member/allyn", 
        "name": "allyn", 
        "avatar": "https://cdn.v2ex.com/avatar/60ba/ce47/229916_large.png?m=1494318727"
      }, 
      "url": "https://www.v2ex.com/t/1203944", 
      "date_modified": "2026-04-07T03:01:55+00:00", 
      "content_html": "<p>\u7531\u4e8e ai agent \u7684\u7f18\u6545\uff0c\u9879\u76ee\u4e0d\u5f97\u4e0d\u8fc1\u79fb\u5230 wsl \u5185\u90e8\uff0c\u4f46\u662f\u8fc1\u79fb\u5230 wsl \u540e\u95ee\u9898\u5b9e\u5728\u592a\u591a\u4e86\uff0c\u89e3\u51b3\u4e00\u4e2a\u53c8\u6765\u4e00\u4e2a\uff0c\u5bfc\u81f4\u4e0d\u592a\u6709\u4fe1\u5fc3\u4f7f\u7528\uff0c\u6709\u6ca1\u6709\u597d\u70b9\u7684\u89e3\u51b3\u65b9\u6848\uff1f</p>\n<p>\u95ee\u9898 1\uff1a\n\u4f7f\u7528 intellij idea \u542f\u52a8 java \u7a0b\u5e8f\u7aef\u53e3\u5360\u7528\u95ee\u9898\uff08 jmx \uff09\uff0c\u5728 wsl \u4e2d\u6ca1\u6709\u627e\u5230\u5230 jmx \u5360\u7528\u7684\u7aef\u53e3\uff0c\u4f46\u662f\u53c8\u8bf4\u5360\u7528\u4e86\uff0c\u4e0d\u77e5\u9053\u4ec0\u4e48\u539f\u56e0\uff0c\u76f4\u63a5\u66b4\u529b\u5173\u95ed jmx \uff0c\u89e3\u51b3\u529e\u6cd5\uff1a\u5173\u95ed jmx</p>\n<p>\u95ee\u9898 2\uff1a\n\u5728 wsl \u4e2d\u542f\u52a8\u672c\u5730\u7aef\u53e3\u542f\u52a8 8888 \uff0clocalhost \u80fd\u8bbf\u95ee\uff0c\u5c40\u57df\u7f51\u4e0d\u80fd\u8bbf\u95ee\uff0c\u539f\u56e0\u662f wsl \u9632\u706b\u5899\u95ee\u9898\uff0c\u89e3\u51b3\u529e\u6cd5\uff1a\u4f7f\u7528 powershell \u7ba1\u7406\u5458\u6267\u884c\u547d\u4ee4</p>\n<pre><code>Set-NetFirewallHyperVVMSetting -Name '{40E0AC32-46A5-438A-A0B2-2B479E8F2E90}' -DefaultInboundAction Allow\n</code></pre>\n<p>\u95ee\u9898 3\uff1a\n\u7a0b\u5e8f\u7ec8\u4e8e\u542f\u52a8\u8d77\u6765\u4e86\uff0c\u7ed3\u679c\u65e0\u6cd5\u4f7f\u7528 java debug \u52a8\u6001\u66f4\u6539\u4ee3\u7801\uff0c\u4e5f\u65e0\u6cd5\u8fdb\u5165\u65ad\u70b9\uff0cjrebel \u4e5f\u65e0\u6cd5\u4f7f\u7528\u3002\n\u539f\u56e0\u53ef\u80fd\u662f\uff1a</p>\n<pre><code>java.lang.IllegalAccessException: Class com.intellij.spring.debugger.rt.com.intellij.spring.debugger.rt.SpringBeanDefinitionLoader can not access a member of class org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader$ConfigurationClassBeanDefinition with modifiers \"public\"\n\tat sun.reflect.Reflection.ensureMemberAccess(Reflection.java:102)\n\tat java.lang.reflect.AccessibleObject.slowCheckMemberAccess(AccessibleObject.java:296)\n\tat java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.java:288)\n\tat java.lang.reflect.Method.invoke(Method.java:491)\n\tat com.intellij.spring.debugger.rt.com.intellij.spring.debugger.rt.SpringBeanDefinitionLoader.getAnnotationMetadataClassName(SpringBeanDefinitionLoader.java:182)\n\tat com.intellij.spring.debugger.rt.com.intellij.spring.debugger.rt.SpringBeanDefinitionLoader.getBeanClassName(SpringBeanDefinitionLoader.java:121)\n\tat com.intellij.spring.debugger.rt.com.intellij.spring.debugger.rt.SpringBeanDefinitionLoader.getAllBeanDefinitions(SpringBeanDefinitionLoader.java:40)\n\tat org.springframework.context.event.ContextRefreshedEvent.&lt;init&gt;(ContextRefreshedEvent.java:37)\n\tat org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:938)\n\tat org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:586)\n\tat org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:145)\n\tat org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754)\n\tat org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:434)\n\tat org.springframework.boot.SpringApplication.run(SpringApplication.java:338)\n</code></pre>\n<p>\u8fd9\u4e2a\u5230\u76ee\u524d\u4e3a\u6b62\u8fd8\u6ca1\u6709\u89e3\u51b3\u3002</p>\n<p>\u7efc\u4e0a\u6240\u8ff0\uff0cwsl \u5f00\u53d1 java \u7a0b\u5e8f\u5b9e\u5728\u662f\u592a\u96be\u4e86\uff0c\u89e3\u51b3\u4e00\u4e2a\u53c8\u6765\u4e00\u4e2a\uff0c\u4e0a\u9762\u7684\u95ee\u9898\u5927\u5bb6\u6709\u4ec0\u4e48\u89e3\u51b3\u65b9\u6cd5\u5417\uff1f</p>\n", 
      "date_published": "2026-04-07T02:59:30+00:00", 
      "title": "\u5173\u4e8e\u5728 wsl \u4e2d\u4f7f\u7528 idea \u8fdb\u884c Java \u5f00\u53d1\u7684\u95ee\u9898", 
      "id": "https://www.v2ex.com/t/1203944"
    }, 
    {
      "author": {
        "url": "https://www.v2ex.com/member/Yum097", 
        "name": "Yum097", 
        "avatar": "https://cdn.v2ex.com/gravatar/9c0915b2c98451d329559d2caa965e0e?s=73&d=retro"
      }, 
      "url": "https://www.v2ex.com/t/1202334", 
      "title": "\u6c42\u52a9\uff0c Fortify \u6f0f\u626b\u95ee\u9898\u89e3\u51b3", 
      "id": "https://www.v2ex.com/t/1202334", 
      "date_published": "2026-03-30T13:35:44+00:00", 
      "content_html": "<p>\u6700\u8fd1\u771f\u662f\u88ab\u7532\u65b9\u7684\u6f0f\u6d1e\u626b\u63cf\u6574\u574f\u4e86\uff0c\u8981\u6c42 0 \u98ce\u9669\nHeader Manipulation \u3001Path Manipulation \u3001Often Misused: File Upload \u8fd9\u4e9b\u95ee\u9898\u6574\u6539\u4e86\u4e94\u516d\u8f6e\u4e86\uff0c\u4f9d\u65e7\u4e0d\u901a\u8fc7\uff0c\u6709\u5565\u6bd4\u8f83\u597d\u7684\u65b9\u6848\u5417</p>\n"
    }, 
    {
      "author": {
        "url": "https://www.v2ex.com/member/CloudSen", 
        "name": "CloudSen", 
        "avatar": "https://cdn.v2ex.com/avatar/861d/e780/426838_large.png?m=1778755828"
      }, 
      "url": "https://www.v2ex.com/t/1201597", 
      "title": "\u5fae\u4fe1 ClawBot \u548c\u4f01\u5fae AIBot \u7684 Java SDK", 
      "id": "https://www.v2ex.com/t/1201597", 
      "date_published": "2026-03-27T06:24:48+00:00", 
      "content_html": "<p>\u56e0\u4e3a\u4e2a\u4eba\u7528\u7684\u662f Java \u7684\u81ea\u7814 agent \uff0c\u5b98\u65b9\u53c8\u6ca1\u63d0\u4f9b java \u76f8\u5173\u7684 sdk \u3002\u56e0\u6b64\u987a\u624b\u6839\u636e\u5b98\u65b9 npm \u5305\u548c\u6587\u6863\u5c01\u88c5\u4e86\u4e00\u4e0b\uff0c\u6b22\u8fce\u4f7f\u7528\u3002<br/>\n\u4e8c\u5408\u4e00\u7684 SDK\uff1a  </p>\n<ol>\n<li>\u57fa\u4e8e WebSocket \u957f\u8fde\u63a5\u534f\u8bae\u7684\u4f01\u4e1a\u5fae\u4fe1 AI Bot Java SDK  </li>\n<li>\u57fa\u4e8e\u4e8c\u7ef4\u7801\u767b\u5f55\u3001\u957f\u8f6e\u8be2\u3001CDN \u534f\u8bae\u5c01\u88c5\u7684\u5fae\u4fe1 ClawBOT Java SDK</li>\n</ol>\n<p>\u5177\u4f53\u89c1\uff1a<br/>\n<a href=\"https://github.com/CloudSen/wx-aibot-java-sdk\" rel=\"nofollow\">https://github.com/CloudSen/wx-aibot-java-sdk</a><br/>\n\u6216<br/>\n<a href=\"https://gitee.com/CloudSen/wx-aibot-java-sdk\" rel=\"nofollow\">https://gitee.com/CloudSen/wx-aibot-java-sdk</a></p>\n"
    }, 
    {
      "author": {
        "url": "https://www.v2ex.com/member/yuhangch", 
        "name": "yuhangch", 
        "avatar": "https://cdn.v2ex.com/avatar/0cc7/3790/467934_large.png?m=1771896123"
      }, 
      "url": "https://www.v2ex.com/t/1201569", 
      "date_modified": "2026-03-27T04:53:42+00:00", 
      "content_html": "<p>.net &gt;&gt; java/ webpack &gt;&gt; vite(\u987a\u5e26\u7740)</p>\n<p>\u5927\u65b9\u5411\u662f springboot/\u4eba\u5927\u91d1\u4ed3(postgresql)</p>\n<p>\u4e3b\u8981\u662f\u4e1a\u52a1\u5c42\u9762\uff1a</p>\n<p>ORM/\u6743\u9650\u63a7\u5236/\u8f7b\u91cf OA/\u591a\u79df\u6237\uff08\u53ef\u80fd\u8fd8\u6d89\u53ca\u4e1a\u52a1\u5b9a\u5236\uff09 \u90fd\u6709\u4ec0\u4e48\u9009\u9879\uff1f</p>\n<p>\u4e4b\u524d\u4e86\u89e3\u8fc7 renren \uff0c\u770b\u8fc7\u4ee3\u7801\u611f\u89c9\u8d28\u91cf\u4e00\u822c\uff0c\u800c\u4e14\u662f MySQL native \u7684\uff0c\u6709\u70b9\u8d1f\u62c5</p>\n<p>2026 \u5e74\u5f53\u4e0b\uff0c\u8fd8\u9700\u4e0d\u9700\u8981\u627e\u6b64\u7c7b\u6846\u67b6\uff0c\u8fd8\u662f\u76f4\u63a5 Vibe coding \uff1f</p>\n<p>\u5982\u679c\u662f vibe coding \uff0c\u4e5f\u8981\u6709\u4e2a\u53c2\u8003\u7684\u67b6\u6784\uff0c\u6211\u6c34\u5e73\u6709\u9650\u95ee\u95ee\u5927\u5bb6</p>\n<p>\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014</p>\n<p>\u5173\u4e8e\u524d\u7aef\uff0c\u76ee\u524d\u5fc3\u4eea TDesign \uff0c\u6709\u6ca1\u6709\u751f\u4ea7\u6df1\u5ea6\u7528\u8fc7\u7684 V \u53cb\uff0c\u6709\u6ca1\u6709\u5751\uff1f</p>\n", 
      "date_published": "2026-03-27T04:52:54+00:00", 
      "title": "\u8001\u4e1a\u52a1\u4fe1\u521b\u91cd\u6784\u9009\u578b\u5927\u5bb6\u6709\u5565\u5efa\u8bae", 
      "id": "https://www.v2ex.com/t/1201569"
    }, 
    {
      "author": {
        "url": "https://www.v2ex.com/member/Comyn", 
        "name": "Comyn", 
        "avatar": "https://cdn.v2ex.com/avatar/91b2/7ea7/374049_large.png?m=1788924734"
      }, 
      "url": "https://www.v2ex.com/t/1200009", 
      "title": "ai \u7f16\u7a0b\u7684\u60c5\u51b5\u5728\u4f60\u4eec\u4f7f\u7528\u4ec0\u4e48 IDE", 
      "id": "https://www.v2ex.com/t/1200009", 
      "date_published": "2026-03-21T06:45:35+00:00", 
      "content_html": "<p>idea \u592a\u91cd\u4e86</p>\n"
    }, 
    {
      "author": {
        "url": "https://www.v2ex.com/member/jarryli", 
        "name": "jarryli", 
        "avatar": "https://cdn.v2ex.com/gravatar/d81c6f7c4f9170a5c78a9813d8174c50?s=73&d=retro"
      }, 
      "url": "https://www.v2ex.com/t/1199318", 
      "title": "\u4e0b\u9762\u8fd9\u6bb5 Java \u591a\u6001\u7684\u4ee3\u7801\uff0c\u5982\u4f55\u624d\u80fd\u6539\u4e3a Go\u3001 Python \u3001JS\u3001C++\u7248\u672c?", 
      "id": "https://www.v2ex.com/t/1199318", 
      "date_published": "2026-03-18T11:07:44+00:00", 
      "content_html": "<p>\u9762\u5411\u5bf9\u8c61\u5305\u62ec\u5c01\u88c5\u3001\u7ee7\u627f\u3001\u7ec4\u5408\u3001\u591a\u6001\uff0c\u5176\u4e2d\u6700\u4e0d\u597d\u7406\u89e3\uff0c\u4e5f\u6700\u5f3a\u608d\u7684\u5c31\u662f\u591a\u6001\u3002\u53ef\u4ee5\u8bf4\u638c\u63e1\u4e86\u591a\u6001\u5c31\u638c\u63e1\u4e86\u9762\u5411\u5bf9\u8c61\u4ee5\u53ca\u8bbe\u8ba1\u6a21\u5f0f\u7684\u7cbe\u9ad3\u3002</p>\n<p>\u4f46\u662f java \u91cc\u9762\u7684\u591a\u6001\u5b9e\u73b0\u592a\u8fc7\u4e8e\u4e25\u82db\uff0c\u4ee5\u81f4\u4e8e\u5176\u4ed6\u8bed\u8a00\u90fd\u65e0\u6cd5\u5b8c\u5168\u6a21\u62df\u3002\u8bf7\u770b\u4e0b\u9762\u7684\u4ee3\u7801\uff0c\u7528\u5176\u4ed6\u8bed\u8a00\u5b9e\u73b0\u7684\u65f6\u5019\u603b\u96be\u4ee5\u8fbe\u5230\u7c7b\u4f3c\u6548\u679c\u3002</p>\n<pre><code class=\"language-java\">/*\n\u591a\u6001\uff1a\u5373\u540c\u4e00\u4e2a\u884c\u4e3a\u5177\u6709\u591a\u4e2a\u4e0d\u540c\u8868\u73b0\u5f62\u5f0f\u6216\u5f62\u6001\u7684\u80fd\u529b\u3002\n\u8868\u73b0\u5f62\u5f0f\u4e3a\uff0c\u5b50\u7c7b\u91cd\u5199\u7236\u7c7b\u65b9\u6cd5\uff0c\u5b9e\u73b0\u7c7b\u5b9e\u73b0\u63a5\u53e3\u65b9\u6cd5\uff0c\u5b50\u7c7b\u91cd\u5199\u62bd\u8c61\u7c7b\u65b9\u6cd5\u7b49\u3002\n\u591a\u6001\u4e09\u4e2a\u5fc5\u8981\u6761\u4ef6\uff1a\u7ee7\u627f\u3001\u91cd\u5199\u3001\u7236\u7c7b\u5f15\u7528\u6307\u5411\u5b50\u7c7b\u5bf9\u8c61\u3002\u591a\u6001\u6709\u6548\u6d88\u9664\u7c7b\u578b\u4e4b\u95f4\u7684\u8026\u5408\uff0c\u5e76\u63d0\u4f9b\u7075\u6d3b\u7684\u53ef\u6269\u5c55\u65b9\u6848\u3002\n\u672c\u4f8b\u5b50\u7b80\u5355\u6e05\u6670\u660e\u4e86\u7684 Java \u591a\u6001\uff0c\u80fd\u770b\u61c2\u8fd9\u4e2a\u4f8b\u5b50\u5c31\u61c2\u4e86\u4ec0\u4e48\u662f\u591a\u6001\u3002\n*/\n\n// \u7236\u7c7b A\nclass A {\n    public String show(D object) {\n        return (\"A and D\");\n    }\n\n    public String show(A object) {\n        return (\"A and A\");\n    }\n\n    // \u9ed8\u8ba4\u6ce8\u91ca\u6389\u3002\u53ef\u5f00\u5173\u6ce8\u91ca\u6d4b\u8bd5\u4e0b\n    // public String show(B object) {\n    // return (\"A and B\");\n    // }\n}\n\n// \u5b50\u7c7b B\nclass B extends A {\n    public String show(B object) {\n        return (\"B and B\");\n    }\n\n    public String show(A object) {\n        return (\"B and A\");\n    }\n}\n\n// \u5b59\u5b50\u7c7b C\nclass C extends B {\n}\n\n// \u5b59\u5b50\u7c7b D\nclass D extends B {\n}\n\n// \u6d4b\u8bd5\u9a8c\u8bc1\npublic class PolymorphismSimple {\n    public static void main(String[] args) {\n        // \u7236\u7c7b\u58f0\u660e\u81ea\u5df1\n        A a = new A();\n        // \u7236\u7c7b\u58f0\u660e\u5b50\u7c7b\n        A ab = new B();\n        // \u5b50\u7c7b\u58f0\u660e\u81ea\u5df1\n        B b = new B();\n        C c = new C();\n        D d = new D();\n\n        // 1) A and A \u3002b \u7684\u7c7b\u578b\u662f B \uff0c\u4e5f\u662f B \u7684\u5b9e\u4f8b\uff0cA \u91cc\u6ca1\u6709 show(B)\u65b9\u6cd5\uff0c\u4f46\u6709 show(A)\u65b9\u6cd5\u3002B \u7684\u7236\u7c7b\u662f A \uff0c\u56e0\u6b64\u5b9a\u4f4d\u5230 A.show(A)\u3002\n        System.out.println(\"1) \" + a.show(b));\n\n        // 2) A and A \u3002c \u7684\u7c7b\u578b\u662f C \uff0c\u4e5f\u662f C \u7684\u5b9e\u4f8b\uff0cC \u7ee7\u627f B \uff0cB \u7ee7\u627f A \u3002A \u91cc\u6ca1\u6709 show(C)\u65b9\u6cd5\uff0c\u4e5f\u6ca1\u6709 show(B)\u65b9\u6cd5\uff0c\u6700\u540e\u6307\u5411 A.show(A)\u3002\n        System.out.println(\"2) \" + a.show(c));\n\n        // 3) A and D, d \u7684\u7c7b\u578b\u662f D \uff0c\u4e5f\u662f D \u7684\u5b9e\u4f8b\uff0cD \u7ee7\u627f B \uff0cB \u7ee7\u627f A \u3002A \u91cc\u6709 show(D)\u65b9\u6cd5\uff0c\u76f4\u63a5\u5b9a\u4f4d\u5230 A.show(D)\u3002\n        System.out.println(\"3) \" + a.show(d));\n\n        // 4) B and A, ab \u662f B \u7684\u5b9e\u4f8b\uff0c\u4f46\u7528 A \u58f0\u660e\uff0c\u5373\u5411\u4e0a\u8f6c\u578b\u5f97\u5230\u7684\u7c7b\u578b\u662f A \uff0c\u8fd0\u884c\u65f6\u624d\u80fd\u786e\u5b9a\u5177\u4f53\u8be5\u8c03\u7528\u54ea\u4e2a\u65b9\u6cd5\u3002\n        // ab \u662f B \u7684\u5b9e\u4f8b\u5bf9\u8c61\uff0c\u4f46\u5f15\u7528\u7c7b\u578b\u662f A \u3002\u7c7b\u578b\u662f\u5728\u7f16\u8bd1\u65f6\u786e\u5b9a\uff0c\u56e0\u6b64\u4ece\u7c7b\u578b\u5f00\u59cb\u5b9a\u4f4d\u65b9\u6cd5\u3002\n        // A \u7c7b\u4e2d\u6ca1\u6709 show(B)\u65b9\u6cd5\uff0c\u4f46\u6709 show(A)\u65b9\u6cd5\uff0c\u56e0\u4e3a A \u662f B \u7684\u7236\u7c7b\uff0cab \u4e5f\u662f A \u7684\u5b9e\u4f8b\uff0c\u4e8e\u662f\u5b9a\u4f4d\u5230 A.show(A)\u65b9\u6cd5\u3002\n        // \u7531\u4e8e B \u662f A \u7684\u5b50\u7c7b\uff0c\u4e14 B \u91cd\u5199\u4e86 A \u7684 show(A)\uff0cA \u7684\u65b9\u6cd5\u88ab\u8986\u76d6\u4e86\uff0c\u4e8e\u662f\u5b9a\u4f4d\u5230 B.show(A)\uff0c\u8fd9\u5c31\u662f\u52a8\u6001\u7ed1\u5b9a\u3002\n        // \u867d\u7136 B \u4e2d\u6709 show(B)\u65b9\u6cd5\uff0c\u4f46\u662f\u56e0\u4e3a ab \u7684\u7c7b\u578b\u662f A \uff0c\u7f16\u8bd1\u65f6\u6839\u636e\u7c7b\u578b\u5b9a\u4f4d\u5230 A \u7684\u65b9\u6cd5\uff0c\u800c\u4e0d\u662f B \u3002\n\n        // \u4ee5\u4e0b\u51e0\u79cd\u53ef\u5f00\u5173\u6253\u5f00/\u6ce8\u91ca\u4ee3\u7801\u6d4b\u8bd5\u4e0b\u3002\n        // -\n        // \u82e5 A \u91cc\u6709 show(A)\u548c show(B)\uff0cB \u91cc\u6709 show(B)\u6709 show(A)\uff0c\u5219\u7f16\u8bd1\u65f6\u5173\u8054\u5230 A.show(B)\uff0c\u56e0 B \u8986\u76d6\u4e86 A.show(B)\uff0c\u52a8\u6001\u7ed1\u5b9a\u5230 B.show(B)\u3002\n        // -\n        // \u82e5 A \u91cc\u6709 show(A)\u548c show(B)\uff0cB \u91cc\u65e0 show(B)\u6709 show(A)\uff0c\u5219\u7f16\u8bd1\u65f6\u5173\u8054\u5230 A.show(B)\uff0c\u56e0 B \u65e0\u8986\u76d6\uff0c\u5219\u76f4\u63a5\u8c03\u7528 A.show(B)\u3002\n        // -\n        // \u82e5 A \u91cc\u6709 show(A)\u65e0 show(B)\uff0cB \u91cc\u65e0 show(B)\u6709 show(A)\uff0c\u5219\u7f16\u8bd1\u65f6\u5173\u8054\u5230 A.show(A)\uff0c\u56e0 B \u8986\u76d6\u4e86 A.show(A)\uff0c\u52a8\u6001\u7ed1\u5b9a\u5230 B.show(A)\u3002\n        // -\n        // \u82e5 A \u91cc\u6709 show(A)\u65e0 show(B)\uff0cB \u91cc\u65e0 show(A)\u6709 show(B)\uff0c\u5219\u7f16\u8bd1\u65f6\u5173\u8054\u5230 A.show(A)\uff0c\u56e0 B \u65e0\u8986\u76d6\uff0c\u5219\u76f4\u63a5\u8c03\u7528 A.show(A)\u3002\n        // \u67e5\u627e\u987a\u5e8f\u4e3a\uff1a\u7f16\u8bd1\u65f6\u6839\u636e\u5f15\u7528\u7c7b\u578b\u786e\u5b9a\u6240\u5c5e\u7c7b -&gt; \u6839\u636e\u91cd\u8f7d\u53c2\u6570\u7c7b\u578b\u5b9a\u4f4d\uff08\u7c7b\u578b\u6309\u5b50-&gt;\u7236-&gt;\u7956\u9010\u7ea7\u5f80\u4e0a\u67e5\u627e\uff09\u5230\u7c7b\u7684\u5177\u4f53\u65b9\u6cd5\uff08\u5305\u62ec\u7ee7\u627f\u7684\u65b9\u6cd5\uff09 -&gt;\n        // \u8fd0\u884c\u65f6\u5b9e\u4f8b\u5bf9\u8c61\u8986\u76d6\uff08\u8986\u76d6\u53ea\u6709\u5b50-&gt;\u7236\u4e00\u5c42\uff09\u4e86\u5f15\u7528\u7c7b\u578b\u7684\u540c\u540d\u65b9\u6cd5 -&gt; \u5b9a\u4f4d\u5230\u5b9e\u4f8b\u5bf9\u8c61\u7684\u65b9\u6cd5\u3002\n        System.out.println(\"4) \" + ab.show(b));\n\n        // 5) B and A \u3002ab \u662f B \u7684\u5b9e\u4f8b\uff0c\u7c7b\u578b\u662f A \u3002\u4ece A \u7c7b\u6ca1\u627e\u5230 show(C)\u65b9\u6cd5\uff0c\u4e5f\u6ca1\u627e\u5230 A.show(B)\u65b9\u6cd5\uff0c\u627e\u5230 A.show(A)\u65b9\u6cd5\u3002A.show(A)\u88ab B.show(A)\u8986\u76d6\uff0c\u56e0\u6b64\u8c03\u7528 B.show(A)\u3002\n        System.out.println(\"5) \" + ab.show(c));\n\n        // 6) A and D \u3002A \u91cc\u9762\u6709 show(D)\u7684\u65b9\u6cd5\uff0c\u76f4\u63a5\u5b9a\u4f4d\u5230\u3002\n        System.out.println(\"6) \" + ab.show(d));\n\n        // 7) B and B \u3002B \u91cc\u9762\u6709 show(B)\u7684\u65b9\u6cd5\uff0c\u76f4\u63a5\u5b9a\u4f4d\u5230\u3002\n        System.out.println(\"7) \" + b.show(b));\n\n        // 8) B and B \u3002B \u6ca1\u6709 show(c)\u65b9\u6cd5\uff0c\u4f46\u6709 show(B)\u65b9\u6cd5\u3002C \u7ee7\u627f\u81ea B \uff0c\u7236\u7c7b\u578b\u662f B \uff0c\u56e0\u6b64\u8c03\u7528 B.show(B)\u3002\n        System.out.println(\"8) \" + b.show(c));\n\n        // 9) A and D \u3002B \u4e2d\u6ca1\u6709 show(D)\u65b9\u6cd5\uff0cB \u7ee7\u627f A \uff0cA \u91cc\u6709 show(D), \u6545\u8c03\u7528 A.show(D)\u65b9\u6cd5\u3002\n        System.out.println(\"9) \" + b.show(d));\n\n        // 10) B and A \u3002\u7236\u7c7b\u58f0\u660e\u5b50\u7c7b\uff0c\u5b58\u5728\u5411\u4e0a\u8f6c\u578b\u3002A \u91cc\u6709 show(A)\uff0c\u88ab B.show(A)\u8986\u76d6\u4e86\uff0c\u56e0\u6b64\u5b9a\u4f4d\u5230 B.show(A)\u3002\n        System.out.println(\"10) \" + ab.show(a));\n\n    }\n}\n\n/**\n * \u6d4b\u8bd5\u7ed3\u679c\n * 1) A and A\n * 2) A and A\n * 3) A and D\n * 4) B and A\n * 5) B and A\n * 6) A and D\n * 7) B and B\n * 8) B and B\n * 9) A and D\n * 10) B and A\n */\n</code></pre>\n<p>\u5176\u4ed6\u8bed\u8a00\u6a21\u62df\u5b9e\u73b0\uff1a <a href=\"https://github.com/microwind/design-patterns/tree/main/programming-paradigm/object-oriented-programming/polymorphism\" rel=\"nofollow\">https://github.com/microwind/design-patterns/tree/main/programming-paradigm/object-oriented-programming/polymorphism</a></p>\n"
    }, 
    {
      "author": {
        "url": "https://www.v2ex.com/member/Ayanokouji", 
        "name": "Ayanokouji", 
        "avatar": "https://cdn.v2ex.com/avatar/9075/dfdb/499495_large.png?m=1773811031"
      }, 
      "url": "https://www.v2ex.com/t/1199077", 
      "title": "JDK 26 \u53d1\u5e03\uff0c\u975e lts \u7248\u672c", 
      "id": "https://www.v2ex.com/t/1199077", 
      "date_published": "2026-03-18T00:32:56+00:00", 
      "content_html": "\u77e5\u9053 Applet \u8fd9\u4e1c\u897f\u7684\u5df2\u7ecf\u90fd\u8001\u4e86\u5427<br /><br /><a target=\"_blank\" href=\"https://jdk.java.net\" rel=\"nofollow noopener\">https://jdk.java.net</a><br /><a target=\"_blank\" href=\"https://openjdk.org/projects/jdk/26/\" rel=\"nofollow noopener\">https://openjdk.org/projects/jdk/26/</a><br /><br />Features<br /><br />500:\tPrepare to Make Final Mean Final<br />504:\tRemove the Applet API<br />516:\tAhead-of-Time Object Caching with Any GC<br />517:\tHTTP/3 for the HTTP Client API<br />522:\tG1 GC: Improve Throughput by Reducing Synchronization<br />524:\tPEM Encodings of Cryptographic Objects (Second Preview)<br />525:\tStructured Concurrency (Sixth Preview)<br />526:\tLazy Constants (Second Preview)<br />529:\tVector API (Eleventh Incubator)<br />530:\tPrimitive Types in Patterns, instanceof, and switch (Fourth Preview)<br /><br /><br />ps\uff1a\u672c\u5e16\u4e0d\u6b22\u8fce\u73a9 jdk8 \u6897\u7684\uff0c\u4f60\u7231\u5b66\u4e0d\u5b66\uff0c\u7231\u7528\u4e0d\u7528"
    }, 
    {
      "author": {
        "url": "https://www.v2ex.com/member/f0rb", 
        "name": "f0rb", 
        "avatar": "https://cdn.v2ex.com/gravatar/5327037325f18648036ec7f257afd825?s=73&d=retro"
      }, 
      "url": "https://www.v2ex.com/t/1195941", 
      "date_modified": "2026-03-05T02:09:39+00:00", 
      "content_html": "<p>SpringDataJPA \u652f\u6301\u901a\u8fc7 findBy \u65b9\u6cd5\u6784\u5efa\u67e5\u8be2\u8bed\u53e5\uff0c\u7136\u800c findBy \u65b9\u6cd5\u6784\u5efa\u7684\u67e5\u8be2\u6761\u4ef6\u662f\u56fa\u5b9a\u7684\uff0c\u4e0d\u652f\u6301\u5ffd\u7565\u503c\u4e3a null \u7684\u53c2\u6570\u5bf9\u5e94\u7684\u67e5\u8be2\u6761\u4ef6\uff0c\u8fd9\u5bfc\u81f4\u6211\u4eec\u9700\u8981\u4e3a\u6bcf\u4e00\u7ec4\u53c2\u6570\u7ec4\u5408\u5b9a\u4e49\u4e00\u4e2a findBy \u65b9\u6cd5\u3002\u4f8b\u5982\uff1a</p>\n<pre><code class=\"language-java\">findByAuthor\nfindByAuthorAndPublishedYearGreaterThan\nfindByAuthorAndPublishedYearLessThan\nfindByAuthorAndPublishedYearGreaterThanAndPublishedYearLessThan\n</code></pre>\n<p>\u5f53\u6761\u4ef6\u53d8\u591a\u65f6\uff0c\u65b9\u6cd5\u540d\u4f1a\u53d8\u957f\uff0c\u53c2\u6570\u4e5f\u4f1a\u53d8\u591a\uff0c\u5e76\u89e6\u53d1\u201c\u957f\u53c2\u6570\u201d\u574f\u5473\u9053\u3002\u89e3\u51b3\u8fd9\u4e00\u95ee\u9898\u7684\u91cd\u6784\u65b9\u6cd5\u662f\u201c\u5f15\u5165\u53c2\u6570\u5bf9\u8c61\u201d\uff0c\u5373\u628a\u6240\u6709\u7684\u53c2\u6570\u5b9a\u4e49\u5728\u4e00\u4e2a\u5bf9\u8c61\u91cc\u3002\u540c\u65f6\uff0c\u6211\u4eec\u628a findBy \u7684\u65b9\u6cd5\u540d\u4e2d\u5bf9\u5e94\u67e5\u8be2\u6761\u4ef6\u7684\u90e8\u5206\u4f5c\u4e3a\u8fd9\u4e2a\u5bf9\u8c61\u7684\u5b57\u6bb5\u540d\u79f0\uff0c\u6211\u4eec\u4fbf\u80fd\u4e3a\u6bcf\u4e2a\u5b57\u6bb5\u6784\u5efa\u4e00\u4e2a\u67e5\u8be2\u6761\u4ef6\uff0c\u5e76\u4e14\u6839\u636e\u5bf9\u8c61\u7684\u8d4b\u503c\u60c5\u51b5\uff0c\u52a8\u6001\u5730\u7ec4\u5408\u975e\u7a7a\u5b57\u6bb5\u5bf9\u5e94\u7684\u67e5\u8be2\u6761\u4ef6\u7ec4\u5408\u4e3a\u67e5\u8be2\u5b50\u53e5\u3002</p>\n<pre><code class=\"language-java\">public class BookQuery {\n    String author;\n    Integer publishedYearGreaterThan;\n    Integer publishedYearLessThan;\n    //...\n}\n</code></pre>\n<p>\u57fa\u4e8e\u6b64\u5bf9\u8c61\uff0c\u6211\u4eec\u53ef\u4ee5\u628a\u6240\u6709\u7684 findBy \u65b9\u6cd5\u5408\u5e76\u4e3a\u4e00\u4e2a\u6cdb\u578b\u65b9\u6cd5\uff0c\u4ece\u800c\u7b80\u5316\u67e5\u8be2\u63a5\u53e3\u7684\u8bbe\u8ba1\u3002</p>\n<pre><code class=\"language-java\">public class CrudRepository&lt;E, I, Q&gt; {\n    List&lt;E&gt; findBy(Q query);\n    //...\n}\n</code></pre>\n<p>\u63d0\u51fa\u67e5\u8be2\u5bf9\u8c61\u8fd9\u4e00\u6982\u5ff5\uff0c\u5e76\u5229\u7528\u5b83\u6765\u89e3\u51b3\u52a8\u6001\u67e5\u8be2\u95ee\u9898\uff0c\u6b63\u662f DoytoQuery \u7684\u6838\u5fc3\u529f\u80fd\u3002</p>\n", 
      "date_published": "2026-03-05T02:05:20+00:00", 
      "title": "DoytoQuery vs SpringDataJPA", 
      "id": "https://www.v2ex.com/t/1195941"
    }, 
    {
      "author": {
        "url": "https://www.v2ex.com/member/banzige", 
        "name": "banzige", 
        "avatar": "https://cdn.v2ex.com/avatar/26be/6870/676152_large.png?m=1708241972"
      }, 
      "url": "https://www.v2ex.com/t/1195318", 
      "date_modified": "2026-03-03T03:22:34+00:00", 
      "content_html": "<p>\u56e2\u961f\u51c6\u5907\u5c06\u51e0\u4e2a\u5386\u53f2\u9879\u76ee\u9010\u6b65\u90fd\u8fc1\u79fb\u5230 Java \u6280\u672f\u6808\u6765\uff0c\u51c6\u5907\u4f7f\u7528\u4e00\u4e9b\u811a\u624b\u67b6\u9879\u76ee\u6765\u505a\u3002\n\u5404\u4f4d\u5927\u4f6c\u6709\u6ca1\u6709\u63a8\u8350\u7684\u597d\u7684\u9879\u76ee\uff0c\u6216\u8005\u597d\u7528\u7684\u5e93\u6216\u6a21\u5757\u4e5f\u884c\u3002</p>\n", 
      "date_published": "2026-03-02T16:25:53+00:00", 
      "title": "\u6c42\u63a8\u8350\u6bd4\u8f83\u4f18\u79c0\u7684 springboot \u811a\u624b\u67b6\u9879\u76ee", 
      "id": "https://www.v2ex.com/t/1195318"
    }, 
    {
      "author": {
        "url": "https://www.v2ex.com/member/Waterchestnut", 
        "name": "Waterchestnut", 
        "avatar": "https://cdn.v2ex.com/avatar/e8e5/addd/139399_large.png?m=1788900498"
      }, 
      "url": "https://www.v2ex.com/t/1193117", 
      "date_modified": "2026-02-17T13:48:40+00:00", 
      "content_html": "\u6700\u8fd1\u4e00\u4e2a\u6708\u5c1d\u8bd5\u7528 vscode \u5f00\u53d1 java \uff0c\u53d1\u73b0 idea \u91cc\u81ea\u5df1\u5e38\u7528\u7684 copy reference \u529f\u80fd\u6ca1\u6709\uff0c\u5c31\u81ea\u5df1\u9020\u4e86\u8f6e\u5b50\uff0c\u5f00\u53d1\u8fc7\u7a0b\u4e2d\u52a0\u4e0a\u4e86\u81ea\u5df1\u9700\u8981\u5176\u4ed6\u529f\u80fd\uff0c\u6bd4\u5982\u652f\u6301\u590d\u5236\u5f15\u7528\u8def\u5f84\u3001REST \u63a5\u53e3\u8def\u5f84\u3001Arthas \u547d\u4ee4\u751f\u6210\u53ca JSON \u7ed3\u6784 mock \u7b49\u529f\u80fd\uff0c\u8d81\u653e\u5047\u7528 claude \u64b8\u7684\uff0c\u6bd4\u8f83\u7c97\u7cd9\uff0c\u4e3b\u8981\u662f\u6ee1\u8db3\u81ea\u5df1 vscode \u5f00\u53d1 java \u7684\u9700\u6c42\uff0c\u76ee\u6807\u662f\u6700\u7ec8\u4f7f\u7528 vscode \u5f00\u53d1 java \uff0c\u73b0\u5728\u662f vscode \u548c idea \u5e76\u884c\uff0c\u6682\u65f6\u6ca1\u6709\u7684\u529f\u80fd\u53ea\u597d diy \u4e86\uff0c\u5206\u4eab\u540c\u6837 vscode \u7684 javer \u8bd5\u7528\u4e0b\u3002<br />\u63d2\u4ef6\u5730\u5740\uff1a <a target=\"_blank\" href=\"https://marketplace.visualstudio.com/items?itemName=qinlinglong.advanced-copy-for-java\" rel=\"nofollow noopener\">https://marketplace.visualstudio.com/items?itemName=qinlinglong.advanced-copy-for-java</a><br />\u4ed3\u5e93\u5730\u5740\uff1a <a target=\"_blank\" href=\"https://github.com/qinlinglong/advanced-copy\" rel=\"nofollow noopener\">https://github.com/qinlinglong/advanced-copy</a>", 
      "date_published": "2026-02-17T13:47:43+00:00", 
      "title": "vscode \u91cc\u81ea\u7528 Java \u5f00\u53d1\u63d2\u4ef6:\u652f\u6301\u590d\u5236\u5f15\u7528\u8def\u5f84\u3001rest \u63a5\u53e3\u8def\u5f84\u3001Arthas \u547d\u4ee4\u7b49\u529f\u80fd", 
      "id": "https://www.v2ex.com/t/1193117"
    }, 
    {
      "author": {
        "url": "https://www.v2ex.com/member/HeyHudy", 
        "name": "HeyHudy", 
        "avatar": "https://cdn.v2ex.com/avatar/81c7/dc5a/530655_large.png?m=1664282378"
      }, 
      "url": "https://www.v2ex.com/t/1192599", 
      "title": "\u81ea\u8350 Java \u591a\u7ebf\u7a0b\u795e\u5668\u2014\u2014ThreadForge \uff0c\u8ba9\u591a\u7ebf\u7a0b\u4ece\u6b64\u7b80\u5355", 
      "id": "https://www.v2ex.com/t/1192599", 
      "date_published": "2026-02-13T01:02:23+00:00", 
      "content_html": "<blockquote>\n<p>\u65b0\u6625\u4e34\u8fd1\uff0c\u5148\u4f4f\u5404\u4f4d V \u53cb\u65b0\u5e74\u5feb\u4e50\uff5e</p>\n</blockquote>\n<h2>\u4ece\u573a\u666f\u5207\u5165</h2>\n<p>\u4f20\u7edf\u7684 <code>ExecutorService</code>\u3001<code>Future</code>\u3001<code>CompletableFuture</code> \u975e\u5e38\u5f3a\u5927\uff0c\u4f46\u5199\u8d77\u6765\u6bd4\u8f83\u9ebb\u70e6\uff1a</p>\n<ul>\n<li>\u7ebf\u7a0b\u6c60\u8981\u624b\u52a8\u521b\u5efa\u548c\u5173\u95ed</li>\n<li>\u8d85\u65f6\u903b\u8f91\u6bcf\u4e2a\u4efb\u52a1\u90fd\u8981\u5199\u4e00\u904d</li>\n<li>\u5931\u8d25\u4e86\u8981\u4e0d\u8981\u53d6\u6d88\u5176\u4ed6\u4efb\u52a1\uff1f\u5f97\u81ea\u5df1\u5224\u65ad</li>\n<li>\u5f02\u5e38\u600e\u4e48\u4f20\u64ad\uff1f\u8981\u4e48\u541e\u6389\uff0c\u8981\u4e48\u624b\u52a8\u5305\u88c5</li>\n<li>\u60f3\u77e5\u9053\u4efb\u52a1\u8dd1\u4e86\u591a\u4e45\uff1f\u81ea\u5df1\u6253\u65e5\u5fd7</li>\n</ul>\n<p>\u6211\u4e00\u76f4\u5728\u601d\u8003\u600e\u4e48\u80fd\u8ba9 Javaer \u7528\u591a\u7ebf\u7a0b\u7684\u65f6\u5019\u80fd\u7b80\u5355\u70b9\uff0c\u5c11\u70b9\u5f2f\u5f2f\u7ed5\u7ed5\uff0c\u4e8e\u662f\u8bde\u751f\u4e86 ThreadForge \u3002</p>\n<h2>ThreadForge\uff1a\u628a\u590d\u6742\u5ea6\u6536\u655b\u5230\u4e00\u4e2a\u53ef\u63a8\u7406\u7684\u6a21\u578b\u91cc</h2>\n<p>ThreadForge \u7684\u8bbe\u8ba1\u54f2\u5b66\u5f88\u7b80\u5355\uff1a<strong>\u5148\u964d\u4f4e\u8ba4\u77e5\u6210\u672c\uff0c\u518d\u8ffd\u6c42\u6027\u80fd\u3002</strong></p>\n<p>\u53ef\u4ee5\u628a\u5b83\u7406\u89e3\u6210\u4e00\u4e2a<strong>\u7ed3\u6784\u5316\u5e76\u53d1\u6846\u67b6</strong>\u2014\u2014\u8ba9\u4f60\u7528\u5199\u540c\u6b65\u4ee3\u7801\u7684\u601d\u7ef4\u5199\u5e76\u53d1\u4ee3\u7801\uff0c\u540c\u65f6\u81ea\u52a8\u5904\u7406\u90a3\u4e9b\u5bb9\u6613\u9057\u6f0f\u7684\u8fb9\u754c\u60c5\u51b5\u3002</p>\n<p>\u4e5f\u53ef\u4ee5\u628a\u5b83\u7406\u89e3\u6210\u5bf9\u4e8e Java \u5185\u7f6e\u5e76\u53d1\u5de5\u5177\u7684\u4e8c\u6b21\u5305\u88c5\uff0c\u76ee\u6807\u662f\u8ba9 Java \u5e76\u53d1\u66f4\u7b80\u5355\u3001\u66f4\u6e05\u6670\u3002</p>\n<h3>\u4ec0\u4e48\u662f\u7ed3\u6784\u5316\uff1f</h3>\n<p>\u770b\u4e00\u4e2a\u6700\u7b80\u5355\u7684\u4f8b\u5b50\uff1a</p>\n<pre><code class=\"language-java\">try (ThreadScope scope = ThreadScope.open()) {\n    Task&lt;String&gt; user = scope.submit(\"load-user\", () -&gt; fetchUser());\n    Task&lt;Integer&gt; orders = scope.submit(\"load-orders\", () -&gt; fetchOrders());\n    \n    scope.await(user, orders);\n    \n    // \u5230\u8fd9\u91cc,\u4e24\u4e2a\u4efb\u52a1\u80af\u5b9a\u90fd\u7ed3\u675f\u4e86\uff08\u6210\u529f\u3001\u5931\u8d25\u6216\u8d85\u65f6\uff09\n    String result = user.await() + \":\" + orders.await();\n}\n// scope \u5173\u95ed\u65f6,\u6240\u6709\u4efb\u52a1\u81ea\u52a8\u53d6\u6d88\u3001\u8d44\u6e90\u81ea\u52a8\u6e05\u7406\n</code></pre>\n<p>\u8fd9\u6bb5\u4ee3\u7801\u6709\u51e0\u4e2a\u5173\u952e\u70b9\uff1a</p>\n<ol>\n<li><strong>\u6240\u6709\u4efb\u52a1\u90fd\u7ed1\u5b9a\u5728 <code>ThreadScope</code> \u5185</strong>\uff0c\u751f\u547d\u5468\u671f\u6709\u8fb9\u754c\uff0c\u4e0d\u4f1a\u6cc4\u6f0f</li>\n<li><strong>\u9ed8\u8ba4\u5c31\u662f\u5b89\u5168\u7684</strong>\uff1a\u9ed8\u8ba4\u8d85\u65f6\u3001\u9ed8\u8ba4\u5931\u8d25\u4f20\u64ad\u3001\u81ea\u52a8\u53d6\u6d88</li>\n<li><strong>\u4ee3\u7801\u7ed3\u6784\u5c31\u662f\u4efb\u52a1\u5173\u7cfb</strong>\uff1a\u8bfb\u4ee3\u7801\u7684\u4eba\u4e00\u773c\u5c31\u80fd\u770b\u51fa\u4e24\u4e2a\u4efb\u52a1\u662f\u5e76\u53d1\u7684\uff0c\u4e14\u5fc5\u987b\u90fd\u5b8c\u6210\u624d\u80fd\u7ee7\u7eed</li>\n</ol>\n<p>\u5bf9\u6bd4\u4f20\u7edf\u5199\u6cd5\uff0c\u4f60\u9700\u8981\uff1a</p>\n<ul>\n<li>\u521b\u5efa\u7ebf\u7a0b\u6c60\uff0c\u914d\u7f6e\u6838\u5fc3\u7ebf\u7a0b\u6570\u3001\u961f\u5217\u5927\u5c0f</li>\n<li>\u63d0\u4ea4\u4efb\u52a1\uff0c\u624b\u52a8\u5904\u7406 Future</li>\n<li>\u5199 try-finally \u786e\u4fdd shutdown</li>\n<li>\u624b\u52a8\u5904\u7406\u8d85\u65f6\u548c\u5f02\u5e38\u4f20\u64ad</li>\n</ul>\n<p>\u8fd9\u91cc\u5176\u5b9e\u5c31\u80fd\u770b\u51fa\u6765 ThreadForge \u7684\u8bbe\u8ba1\u521d\u8877\u548c\u76ee\u6807\u4e86\uff0c\u5c31\u662f\u52aa\u529b\u8ba9\u6211\u4eec\u7701\u6389\u8fd9\u4e9b\u91cd\u590d\u52b3\u52a8\uff0c\u4e13\u6ce8\u4e1a\u52a1\u903b\u8f91\u3002</p>\n<h2>\u4e94\u4e2a\u8ba9\u4f60\u7701\u8111\u529b\u7684\u8bbe\u8ba1</h2>\n<h3>1. \u9ed8\u8ba4\u884c\u4e3a\u5c31\u662f\u6b63\u786e\u7684</h3>\n<pre><code class=\"language-java\">// \u9ed8\u8ba4:FAIL_FAST + 30 \u79d2\u8d85\u65f6 + \u81ea\u52a8\u53d6\u6d88\u5176\u4ed6\u4efb\u52a1\ntry (ThreadScope scope = ThreadScope.open()) {\n    Task&lt;Integer&gt; a = scope.submit(() -&gt; riskyRpc());\n    Task&lt;Integer&gt; b = scope.submit(() -&gt; anotherRpc());\n    scope.await(a, b);\n} catch (ScopeTimeoutException timeout) {\n    // \u8d85\u65f6\u4e86,\u6240\u6709\u4efb\u52a1\u5df2\u88ab\u81ea\u52a8\u53d6\u6d88\n    fallback();\n} catch (FailurePropagationException failed) {\n    // \u67d0\u4e2a\u4efb\u52a1\u5931\u8d25\u4e86,\u5176\u4ed6\u4efb\u52a1\u5df2\u88ab\u81ea\u52a8\u53d6\u6d88\n    handleError(failed);\n}\n</code></pre>\n<p>\u4e0d\u9700\u8981\u914d\u7f6e\uff0c\u4e0d\u9700\u8981\u601d\u8003\uff0c\u5f00\u7bb1\u5373\u7528\u3002</p>\n<h3>2. \u5931\u8d25\u7b56\u7565\u660e\u786e\u4e14\u7edf\u4e00</h3>\n<p>\u4e0d\u540c\u573a\u666f\u5bf9\u5931\u8d25\u7684\u5bb9\u5fcd\u5ea6\u4e0d\u540c\uff0cThreadForge \u63d0\u4f9b\u4e86 5 \u79cd\u660e\u786e\u7684\u7b56\u7565\uff1a</p>\n<ul>\n<li><code>FAIL_FAST</code>\uff1a\u5feb\u901f\u5931\u8d25\uff0c\u7acb\u5373\u53d6\u6d88\u5176\u4ed6\u4efb\u52a1\uff08\u9ed8\u8ba4\uff09</li>\n<li><code>COLLECT_ALL</code>\uff1a\u7b49\u6240\u6709\u4efb\u52a1\u7ed3\u675f\uff0c\u6c47\u603b\u6240\u6709\u5931\u8d25</li>\n<li><code>SUPERVISOR</code>\uff1a\u4e0d\u81ea\u52a8\u53d6\u6d88\uff0c\u5931\u8d25\u4fe1\u606f\u6536\u96c6\u5230 <code>Outcome</code></li>\n<li><code>CANCEL_OTHERS</code>\uff1a\u5931\u8d25\u540e\u53d6\u6d88\u5176\u4f59\u4efb\u52a1\uff0c\u4f46\u4e0d\u629b\u5f02\u5e38</li>\n<li><code>IGNORE_ALL</code>\uff1a\u5ffd\u7565\u5931\u8d25\uff0c\u53ea\u8fd4\u56de\u6210\u529f\u7684\u7ed3\u679c</li>\n</ul>\n<pre><code class=\"language-java\">// \u573a\u666f:\u6279\u91cf\u5bfc\u5165,\u5373\u4f7f\u90e8\u5206\u5931\u8d25\u4e5f\u8981\u77e5\u9053\u54ea\u4e9b\u6210\u529f\u4e86\ntry (ThreadScope scope = ThreadScope.open()\n        .withFailurePolicy(FailurePolicy.SUPERVISOR)) {\n    \n    List&lt;Task&lt;Void&gt;&gt; tasks = ids.stream()\n        .map(id -&gt; scope.submit(() -&gt; importData(id)))\n        .collect(toList());\n    \n    Outcome outcome = scope.await(tasks);\n    \n    // \u660e\u786e\u77e5\u9053\u54ea\u4e9b\u6210\u529f\u3001\u54ea\u4e9b\u5931\u8d25\n    log.info(\"\u6210\u529f: {}, \u5931\u8d25: {}\", \n        outcome.successCount(), outcome.failureCount());\n}\n</code></pre>\n<h3>3. \u5e76\u53d1\u5ea6\u63a7\u5236\u4e0d\u518d\u9700\u8981\u624b\u52a8\u7ba1\u7406\u961f\u5217</h3>\n<pre><code class=\"language-java\">// \u573a\u666f:\u8c03\u7528\u5916\u90e8 API,\u6700\u591a\u540c\u65f6 50 \u4e2a\u8bf7\u6c42\ntry (ThreadScope scope = ThreadScope.open()\n        .withConcurrencyLimit(50)) {\n    \n    List&lt;Task&lt;Result&gt;&gt; tasks = hugeIdList.stream()\n        .map(id -&gt; scope.submit(() -&gt; externalApi.call(id)))\n        .collect(toList());\n    \n    List&lt;Result&gt; results = scope.awaitAll(tasks);\n}\n// \u81ea\u52a8\u9650\u6d41,\u4e0d\u4f1a\u628a\u5916\u90e8\u670d\u52a1\u6253\u7206\n</code></pre>\n<p>\u4e0d\u9700\u8981\u81ea\u5df1\u5199\u4fe1\u53f7\u91cf\uff0c\u4e5f\u4e0d\u9700\u8981\u624b\u52a8\u5206\u6279\uff0c\u6846\u67b6\u81ea\u52a8\u5904\u7406\u3002</p>\n<h3>4. \u751f\u547d\u5468\u671f\u89c2\u6d4b\u7edf\u4e00\u6536\u53e3</h3>\n<pre><code class=\"language-java\">ThreadScope scope = ThreadScope.open()\n    .withHook(new ThreadHook() {\n        @Override\n        public void onStart(TaskInfo info) {\n            metrics.taskStarted(info.name());\n        }\n        \n        @Override\n        public void onSuccess(TaskInfo info, Duration duration) {\n            metrics.taskSuccess(info.name(), duration.toMillis());\n        }\n        \n        @Override\n        public void onFailure(TaskInfo info, Throwable error, Duration duration) {\n            log.error(\"Task {} failed after {}\", info.name(), duration, error);\n            metrics.taskFailed(info.name());\n        }\n    });\n</code></pre>\n<p>\u4e0d\u9700\u8981\u5728\u6bcf\u4e2a\u4efb\u52a1\u91cc\u91cd\u590d\u5199\u65e5\u5fd7\u548c\u76d1\u63a7\u4ee3\u7801\uff0c\u540c\u65f6\u65b0\u7684 1.0.2 \u7248\u672c\u4e2d\u5185\u7f6e\u4e86 <code>ScopeMetricsSnapshot</code> \u4f5c\u4e3a\u89c2\u6d4b\u70b9\uff0c\u76f4\u63a5 <code>.toString()</code> \u5c31\u80fd\u770b\u5230\u5b8c\u6574\u7684\u8c03\u7528\u8017\u65f6\u7b49\u60c5\u51b5 \u3002</p>\n<h3>5. \u8de8 JDK \u7248\u672c\u7684\u4e00\u81f4\u4f53\u9a8c</h3>\n<pre><code class=\"language-java\">// \u540c\u4e00\u5957 API\ntry (ThreadScope scope = ThreadScope.open()) {\n    // JDK 21+: \u81ea\u52a8\u4f7f\u7528\u865a\u62df\u7ebf\u7a0b\n    // JDK 8-20: \u81ea\u52a8\u964d\u7ea7\u5230\u7ebf\u7a0b\u6c60\n    Task&lt;String&gt; task = scope.submit(() -&gt; longRunningTask());\n    return task.await();\n}\n</code></pre>\n<p>\u4e0d\u9700\u8981\u5206\u53c9\u4ee3\u7801\uff0c\u4e0d\u9700\u8981\u5199 <code>if-else</code>\uff0c\u6846\u67b6\u81ea\u52a8\u9002\u914d\u3002</p>\n<h2>\u9002\u7528\u573a\u666f</h2>\n<p>ThreadForge \u7279\u522b\u9002\u5408\u8fd9\u4e9b\u573a\u666f\uff1a</p>\n<p><strong>\u5e76\u53d1 RPC \u805a\u5408</strong></p>\n<pre><code class=\"language-java\">try (ThreadScope scope = ThreadScope.open()) {\n    Task&lt;User&gt; user = scope.submit(() -&gt; userService.get(uid));\n    Task&lt;List&lt;Order&gt;&gt; orders = scope.submit(() -&gt; orderService.list(uid));\n    Task&lt;Profile&gt; profile = scope.submit(() -&gt; profileService.get(uid));\n    \n    scope.await(user, orders, profile);\n    \n    return buildResponse(user.await(), orders.await(), profile.await());\n}\n</code></pre>\n<p><strong>\u6279\u91cf\u6570\u636e\u5904\u7406</strong></p>\n<pre><code class=\"language-java\">try (ThreadScope scope = ThreadScope.open()\n        .withConcurrencyLimit(100)\n        .withDeadline(Duration.ofMinutes(5))) {\n    \n    List&lt;Task&lt;Void&gt;&gt; tasks = records.stream()\n        .map(r -&gt; scope.submit(() -&gt; process(r)))\n        .collect(toList());\n    \n    scope.awaitAll(tasks);\n}\n</code></pre>\n<p><strong>\u751f\u4ea7\u8005-\u6d88\u8d39\u8005\u6a21\u5f0f</strong></p>\n<pre><code class=\"language-java\">try (ThreadScope scope = ThreadScope.open()) {\n    Channel&lt;Data&gt; channel = Channel.bounded(1000);\n    \n    scope.submit(() -&gt; {\n        for (Data d : datasource) {\n            channel.send(d);\n        }\n        channel.close();\n        return null;\n    });\n    \n    List&lt;Task&lt;Void&gt;&gt; consumers = IntStream.range(0, 4)\n        .mapToObj(i -&gt; scope.submit(() -&gt; {\n            for (Data d : channel) {\n                process(d);\n            }\n            return null;\n        }))\n        .collect(toList());\n    \n    scope.awaitAll(consumers);\n}\n</code></pre>\n<h2>\u5f00\u59cb\u4f7f\u7528</h2>\n<p><strong>Maven:</strong></p>\n<pre><code class=\"language-xml\">&lt;dependency&gt;\n    &lt;groupId&gt;pub.lighting&lt;/groupId&gt;\n    &lt;artifactId&gt;threadforge-core&lt;/artifactId&gt;\n    &lt;version&gt;1.0.2&lt;/version&gt;\n&lt;/dependency&gt;\n</code></pre>\n<p><strong>Gradle:</strong></p>\n<pre><code class=\"language-gradle\">implementation(\"pub.lighting:threadforge-core:1.0.2\")\n</code></pre>\n<p><strong>\u6700\u5c0f\u793a\u4f8b:</strong></p>\n<pre><code class=\"language-java\">try (ThreadScope scope = ThreadScope.open()) {\n    Task&lt;String&gt; task = scope.submit(() -&gt; \"Hello, ThreadForge\");\n    System.out.println(task.await());\n}\n</code></pre>\n<p>\ud83d\udce6 GitHub: <a href=\"https://github.com/wuuJiawei/ThreadForge\" rel=\"nofollow\">github.com/wuuJiawei/ThreadForge</a><br/>\n\ud83d\udcd6 \u6587\u6863: \u89c1\u9879\u76ee <code>docs/api/<a href=\"http://README.md\" rel=\"nofollow\">README.md</a></code><br/>\n\ud83d\udcc4 License: MIT</p>\n<h2>\u6700\u540e</h2>\n<p>\u611f\u8c22\u6240\u6709\u770b\u5230\u8fd9\u91cc\u7684\u670b\u53cb\u3002</p>\n<p>JDK21 \u4e4b\u540e\uff0c\u5b98\u65b9\u56e2\u961f\u4e5f\u8ddf\u8fdb\u4e86\u7ed3\u6784\u5316\u5e76\u53d1\u7c7b\uff0c\u53ef\u4ee5\u79f0\u8fd9\u4e2a\u9879\u76ee\u662f\u53c8\u4e00\u4e2a\u8f6e\u5b50\uff0c\u4e5f\u53ef\u4ee5\u79f0\u5b83\u662f\u5728\u5de5\u7a0b\u5316\u91cc\u9762\u7684\u4e00\u6b21\u63a2\u8ba8\u548c\u53e6\u4e00\u79cd\u89e3\u51b3\u65b9\u6848\uff0c\u6bd5\u7adf\u7ed9\u4f4e\u7248\u672c\u7684 JDK \u4e5f\u63d0\u4f9b\u4e86\u53ef\u80fd\u6027\u3002</p>\n<p>\u6b22\u8fce\u70b9\u8d5e\u3001\u8bc4\u8bba\uff0c\u5982\u679c\u6709\u4efb\u4f55\u95ee\u9898\uff0c\u4e5f\u6b22\u8fce\u63d0\u51fa\u60a8\u7684\u5b9d\u8d35\u610f\u89c1\u3002</p>\n<p><img alt=\"jimeng-2026-02-10-3757-\u300c ThreadForge \u300d \u8fd9\u662f\u6211\u65b0\u5f00\u53d1\u7684\u5f00\u6e90\u9879\u76ee\uff0c\u5e2e\u6211\u505a\u4e00\u4e2a logo \u3002Java....png\" class=\"embedded_image\" loading=\"lazy\" referrerpolicy=\"no-referrer\" rel=\"noreferrer\" src=\"https://p0-xtjj-private.juejin.cn/tos-cn-i-73owjymdk6/0ba00f11caf64fdd9352d2290d364660%7Etplv-73owjymdk6-jj-mark-v1:0:0:0:0:5o6Y6YeR5oqA5pyv56S-5Yy6IEAg5LiA5Y-q5Y-r54Wk55CD55qE54yr:q75.awebp?policy=eyJ2bSI6MywidWlkIjoiMTczMjQ4NjA1ODc0NTA1NCJ9&amp;rk3s=f64ab15b&amp;x-orig-authkey=f32326d3454f2ac7e96d3d06cdbb035152127018&amp;x-orig-expires=1771548692&amp;x-orig-sign=XKKuqDuK8T0%2Ft0CVw5mKbJkeBLI%3D\"/></p>\n<p>\u8fd9\u662f\u8ba9\u5373\u68a6\u753b\u7684 logo \uff0c\u770b\u8d77\u6765\u6709\u70b9\u610f\u601d\uff0c\u50cf\u662f\u4e2a\u8001\u6d3e\u7684\u9879\u76ee\u3002</p>\n"
    }, 
    {
      "author": {
        "url": "https://www.v2ex.com/member/zzNaLOGIC", 
        "name": "zzNaLOGIC", 
        "avatar": "https://cdn.v2ex.com/avatar/2b01/cb58/380799_large.png?m=1715413889"
      }, 
      "url": "https://www.v2ex.com/t/1192288", 
      "title": "\u5c4e\u5c71\u8001\u9879\u76ee\u60f3\u7528 ai \u5b9e\u73b0\u81ea\u52a8\u5316\u6d4b\u8bd5\uff0c\u6709\u4ec0\u4e48\u53ef\u843d\u5730\u7684\u65b9\u6848\u4e48", 
      "id": "https://www.v2ex.com/t/1192288", 
      "date_published": "2026-02-11T09:08:21+00:00", 
      "content_html": "<p>\u5341\u6765\u5e74\u7684 mvc \u5927\u5355\u4f53 java \u9879\u76ee(\u91cc\u9762\u8fd8\u6709\u5f88\u591a jsp \u548c\u8fdc\u7a0b\u8c03\u7528)\uff0c\u4e1a\u52a1\u5197\u4f59\u9ad8\uff0c\u6ca1\u6587\u6863\uff0c\u6ca1\u6ce8\u91ca\uff0c\u800c\u4e14\u4e1a\u52a1\u4e32\u8054\u5f88\u6df1\u3002\n\u73b0\u5728\u8981\u5bf9\u8fd9\u4e2a\u7cfb\u7edf\u7684\u67d0\u4e9b\u6a21\u5757\u8fdb\u884c\u6574\u4f53\u6cbb\u7406\uff0c\u57fa\u672c\u601d\u8def\u5c31\u662f\u6536\u96c6\u95ee\u9898\uff08\u4e1a\u52a1\u53cd\u9988+\u903b\u8f91\uff09\u2014\u2014 \u68b3\u7406\u95ee\u9898 \u2014\u2014 \u8fdb\u884c\u8986\u76d6\u6027\u573a\u666f\u6d4b\u8bd5\uff08\u53ef\u4ee5\u4eba\u5de5\uff0c\u4f46\u6700\u597d\u81ea\u52a8\u5316\uff0c\u4e0d\u7136\u4eba\u5de5\u540e\u7eed\u6267\u884c\u4e0d\u4e0b\u53bb\u7684\uff09\u3002\n\u4e3b\u8981\u76ee\u7684\u5c31\u662f\u8ba9\u8fd9\u5757\u4e1a\u52a1\u81f3\u5c11\u5728\u4e0d\u4fee\u6539\u7684\u60c5\u51b5\u4e0b\uff0c\u4e0d\u8981\u7ecf\u5e38\u7206\u51fa\u5404\u79cd\u5404\u6837\u7684 bug \u548c\u6027\u80fd\u95ee\u9898\u3002\u7136\u540e\u6240\u6709\u7684\u7528\u4f8b\u7559\u7740\uff0c\u65b0\u4fee\u6539\u5fc5\u987b\u8d70\u4e00\u904d\uff0c\u786e\u4fdd\u4e0d\u51fa\u73b0 p0p1 \u7684 bug\n\u4e5f\u8bd5\u4e86\u5f88\u591a skills \u90fd\u4e0d\u5c3d\u5982\u4eba\u610f\u3002\n\u6253\u7b97\u4e0d\u81ea\u5df1\u7422\u78e8\u4e86\uff0c\u95ee\u95ee\u5927\u5bb6\u6709\u6ca1\u6709\u7c7b\u4f3c\u7684\u573a\u666f\uff0c\u6216\u8005\u601d\u8def\u53ef\u4ee5\u53c2\u8003\u7684\u3002</p>\n<p>\u7ed3\u5c3e\u9001\u4e00\u5f20$20 Googleplay \u5151\u6362\u7801\uff0c\u672c\u6765\u60f3\u7740\u81ea\u5df1\u6709\u6d77\u5916\u7269\u7406\u673a\u73af\u5883\u5e94\u8be5\u4e0d\u662f\u95ee\u9898\uff0c\u7ed3\u679c\u5929\u771f\u4e86\u3002\u4e00\u76f4\u5151\u6362\u4e0d\u6210\u529f\u7838\u624b\u91cc\u4e0d\u5982\u9001\u7ed9\u8089\u8eab\u6d77\u5916\u7684\u6709\u7f18\u4eba\u3002</p>\n<p>ADY9MWGZZPE7CT7P</p>\n"
    }, 
    {
      "author": {
        "url": "https://www.v2ex.com/member/heliotrope", 
        "name": "heliotrope", 
        "avatar": "https://cdn.v2ex.com/gravatar/f26ff0f38e2dd1247dca0a34e19b03d7?s=73&d=retro"
      }, 
      "url": "https://www.v2ex.com/t/1190775", 
      "title": "WebFlux \u9879\u76ee \u88ab\u8bbf\u95ee\u540e \u8bbf\u95ee\u65b9\u5173\u95ed\u8fde\u63a5 \u65e0\u6cd5\u6355\u83b7 SocketException: Connection reset", 
      "id": "https://www.v2ex.com/t/1190775", 
      "date_published": "2026-02-04T09:47:59+00:00", 
      "content_html": "<p>\u7a0b\u5e8f A \u8bf7\u6c42\u65b9\n\u7a0b\u5e8f B WebFlux \u5199\u7684\u7f51\u5173\n\u7a0b\u5e8f C \u670d\u52a1\u65b9</p>\n<p>\u8bf7\u6c42\u65b9 \u8bf7\u6c42 \u7f51\u5173\u65f6 \u8d85\u65f6\u8bbe\u7f6e 10 \u79d2\n\u7f51\u5173\u8bbe\u7f6e\u8d85\u65f6 60 \u79d2 \u670d\u52a1\u65b9 \u54cd\u5e94\u9700\u8981 10 \u79d2\u4ee5\u4e0a\n\u51fa\u73b0\u4e00\u4e2a\u95ee\u9898</p>\n<p>\u7f51\u5173\u4e2d\u4f7f\u7528 WebClient \u8f6c\u53d1\u8bf7\u6c42\u5230\u670d\u52a1\u65b9\u65f6\n\u5f53\u8bf7\u6c42\u65b9\u56e0\u4e3a 10 \u79d2\u8d85\u65f6\u5173\u95ed\u94fe\u63a5\n\u7f51\u5173\u53ea\u4f1a\u8f93\u51fa\n'''reactor.netty.channel.FluxReceive [0;39m - [warn,299] -  [36m[ce92646a-2, L:/192.168.101.233:9195 - R:/192.168.101.233:50853] An exception has been observed post termination, use DEBUG level to see the full stack: java.net.SocketException: Connection reset'''</p>\n<p>\u8fd8\u53ea\u662f WARN\n\u7f51\u5173\u4e2d WebClient \u5199\u7684 doOnError doFinally \u90fd\u4e0d\u4f1a\u89e6\u53d1\n\u7f51\u5173\u7684 ErrorWebExceptionHandler \u4e5f\u62e6\u622a\u4e0d\u5230\u8fd9\u4e2a\u5f02\u5e38</p>\n<p>\u76f8\u5f53\u4e8e\u65e0\u6cd5\u8bb0\u5f55\u8fd9\u4e2a\u8bf7\u6c42\u88ab\u8bf7\u6c42\u65b9\u5173\u95ed\u4e86\n\u6574\u4e2a\u8fdb\u7a0b\u88ab kill \u6389\u4e86\u4e00\u6837 \u6ca1\u6cd5\u505a\u4efb\u4f55\u64cd\u4f5c</p>\n<p>\u6c42\u6559 \u5982\u4f55\u6355\u83b7\u8fd9\u4e2a Connection reset</p>\n"
    }, 
    {
      "author": {
        "url": "https://www.v2ex.com/member/lowman", 
        "name": "lowman", 
        "avatar": "https://cdn.v2ex.com/avatar/2103/3249/401365_large.png?m=1779429918"
      }, 
      "url": "https://www.v2ex.com/t/1190774", 
      "title": "\u6709\u4eba\u7528 RUOYI \u6846\u67b6\u5417\uff1f", 
      "id": "https://www.v2ex.com/t/1190774", 
      "date_published": "2026-02-04T09:47:36+00:00", 
      "content_html": "\u6709\u4eba\u7528 RUOYI  \u6846\u67b6\u5417\uff1f\u57fa\u4e8e Spring Boot \u548c Spring Cloud Alibaba"
    }, 
    {
      "author": {
        "url": "https://www.v2ex.com/member/dzdh", 
        "name": "dzdh", 
        "avatar": "https://cdn.v2ex.com/avatar/1683/7ebf/226307_large.png?m=1757987240"
      }, 
      "url": "https://www.v2ex.com/t/1189596", 
      "title": "\u5173\u4e8e\u5546\u7528 jdk \u6536\u8d39\u7684\u95ee\u9898\uff0c\u6709\u9065\u6d4b\u5417\uff1f", 
      "id": "https://www.v2ex.com/t/1189596", 
      "date_published": "2026-01-30T09:19:55+00:00", 
      "content_html": "<p>\u95ee\u4e86 ai \u6ca1\u7b54\u51fa\u4e2a\u6240\u4ee5\u7136\uff0c</p>\n<p>\u6bd4\u5982\uff0cazul \u7684 prime \u53ef\u4ee5\u4e0b\u8f7d\u7528\u7684\uff0c\u5546\u7528\u7684\uff0c\u6211\u8981\u662f\u7528\u4e86\uff0c\u4e0d\u7ed9\u94b1\uff0c\u8fd8\u76c8\u5229\u4e86\uff0c\u5c0f\u89c4\u6a21\u6bd4\u5982\u5c31\u4e00\u53f0\u670d\u52a1\u5668\uff0cazul \u662f\u600e\u4e48\u77e5\u9053\u6211\u7528\u4e86\u7684\uff0c\u8ba9\u6211\u638f\u94b1\u7684\uff1f</p>\n<p>\u8fd8\u662f\u5c0f\u516c\u53f8\u4ed6\u4eec\u5176\u5b9e\u4e5f\u4e0d\u7ba1\uff0c\u53ea\u6709\u5927\u516c\u53f8\u624d\u4f1a\u4e3b\u52a8\u89e3\u51b3\u8fd9\u4e9b\u95ee\u9898\uff0c\n\u8fd8\u662f\u8bf4\u771f\u6709\u4ec0\u4e48\u9065\u6d4b\u4ec0\u4e48\u7684\uff1f</p>\n"
    }, 
    {
      "author": {
        "url": "https://www.v2ex.com/member/christineAlex", 
        "name": "christineAlex", 
        "avatar": "https://cdn.v2ex.com/gravatar/182191ffc94ddd770974bd7f074a1c54?s=73&d=retro"
      }, 
      "url": "https://www.v2ex.com/t/1189317", 
      "date_modified": "2026-01-29T08:40:19+00:00", 
      "content_html": "\u7248\u672c\uff1aIntelliJ IDEA 2025.1.3<br />\t macOS 26 <br /><br />\u4f7f\u7528 cmd+tab \u5207\u6362\u5176\u4ed6\u5e94\u7528\uff0c\u518d\u5207\u6362\u56de\u6765\uff0c\u5927\u6982\u7387\u51fa\u73b0 IDEA \u9875\u9762\u65e0\u6cd5\u70b9\u51fb\uff0c\u90e8\u5206\u6309\u952e\u6709\u53cd\u5e94\uff0c\u53ea\u6709\u53f3\u4e0a\u89d2\u8fdb\u5165/\u9000\u51fa\u5168\u5c4f\u624d\u80fd\u6062\u590d\u6b63\u5e38\u3002<br /><br />\u592a\u6298\u78e8\u4eba\u4e86\uff0c\u6709\u65f6\u5019\u67e5\u8d44\u6599\uff08\u95ee AI \uff09\u9700\u8981\u6d4f\u89c8\u5668\u3001IDEA \u6765\u56de\u5207\u6362\uff0c\u4f46\u7ecf\u5e38\u5361\u4f4f\uff0c\u5f88\u5f71\u54cd\u5fc3\u6001\uff0c\u5404\u4f4d\u5927\u4f6c\u9047\u89c1\u8fc7\u7c7b\u4f3c\u7684\u60c5\u51b5\u5417\uff0c\u5982\u4f55\u89e3\u51b3\u554a", 
      "date_published": "2026-01-29T08:38:29+00:00", 
      "title": "IDEA \u5728 macOS \u4e0a\u5361\u4f4f", 
      "id": "https://www.v2ex.com/t/1189317"
    }, 
    {
      "author": {
        "url": "https://www.v2ex.com/member/JieyueXing", 
        "name": "JieyueXing", 
        "avatar": "https://cdn.v2ex.com/avatar/59da/4184/624907_large.png?m=1787105867"
      }, 
      "url": "https://www.v2ex.com/t/1189255", 
      "title": "Java \uff1a 2026 \u5e74 SpringBoot, Quarkus, Solon ?", 
      "id": "https://www.v2ex.com/t/1189255", 
      "date_published": "2026-01-29T05:28:24+00:00", 
      "content_html": "<p>\u751f\u6001/\u56e2\u961f\u534f\u4f5c\uff08 Spring Boot \uff09\u3001\u4e91\u539f\u751f\u4e0e\u6548\u7387\uff08 Quarkus \uff09\u3001\u56fd\u5185\u8f7b\u91cf\u4e0e\u5feb\uff08 Solon \uff09\u3002</p>\n"
    }, 
    {
      "author": {
        "url": "https://www.v2ex.com/member/l84", 
        "name": "l84", 
        "avatar": "https://cdn.v2ex.com/gravatar/5b36cf6907724c1357419e37926f99ab?s=73&d=retro"
      }, 
      "url": "https://www.v2ex.com/t/1189114", 
      "title": "\u4f6c\u4eec\u6709\u6ca1\u6709\u6bd4\u8f83\u597d\u7684 Java \u811a\u624b\u67b6", 
      "id": "https://www.v2ex.com/t/1189114", 
      "date_published": "2026-01-28T11:22:43+00:00", 
      "content_html": "<ul>\n<li>\u7c7b\u4f3c Spring Initializr \uff0c\u6bd4\u8f83\u5e72\u51c0\uff08\u4f46\u662f\u53c8\u592a\u7b80\u5355\uff09\u3002</li>\n<li>\u6700\u597d\u53ef\u4ee5\u81ea\u5df1\u9009\u67b6\u6784\u6a21\u5f0f\uff0c\u6bd4\u5982\u516d\u8fb9\u5f62 DDD \u67b6\u6784\u3001\u7ecf\u5178\u5206\u5c42\u7b49</li>\n</ul>\n"
    }, 
    {
      "author": {
        "url": "https://www.v2ex.com/member/f0rb", 
        "name": "f0rb", 
        "avatar": "https://cdn.v2ex.com/gravatar/5327037325f18648036ec7f257afd825?s=73&d=retro"
      }, 
      "url": "https://www.v2ex.com/t/1187556", 
      "date_modified": "2026-01-22T04:03:04+00:00", 
      "content_html": "<p>GitHub \u5730\u5740\uff1a <a href=\"https://github.com/f0rb/java-orm-comparison\" rel=\"nofollow\">https://github.com/f0rb/java-orm-comparison</a></p>\n<p>\u5305\u542b SpringDataJPA/SpringJdbc/jOOQ/MyBatis-plus \u7b49\u6846\u67b6\u5f00\u53d1\u52a8\u6001\u67e5\u8be2\u529f\u80fd\u7684\u4ee3\u7801\uff0c\u4ee5\u53ca\u4e0e DoytoQuery \u7684\u4ee3\u7801\u91cf\u548c\u6027\u80fd\u5bf9\u6bd4\u3002</p>\n", 
      "date_published": "2026-01-22T03:59:09+00:00", 
      "title": "\u4e00\u4e2a\u5bf9\u6bd4 JavaORM \u6846\u67b6\u7684\u5c0f\u4ed3\u5e93", 
      "id": "https://www.v2ex.com/t/1187556"
    }, 
    {
      "author": {
        "url": "https://www.v2ex.com/member/pocketz", 
        "name": "pocketz", 
        "avatar": "https://cdn.v2ex.com/avatar/13d3/66d2/527904_large.png?m=1767746342"
      }, 
      "url": "https://www.v2ex.com/t/1183629", 
      "date_modified": "2026-01-07T01:10:37+00:00", 
      "content_html": "<h1>\u95ee\u9898</h1>\n<p>\u5982\u679c\u5bf9\u4e00\u4e2a InputStream \u8c03\u7528 read \u65b9\u6cd5\uff0c\u5728\u6ca1\u6709\u6570\u636e\u53ef\u8bfb\u53d6\u7684\u65f6\u5019\uff0c\u7406\u8bba\u4e0a\u4f1a\u5904\u4e8e\u963b\u585e\u72b6\u6001\u3002</p>\n<blockquote>\n<blockquote>\n<p>This method blocks until input data is available, end of file is detected, or an exception is thrown.</p>\n</blockquote>\n</blockquote>\n<p>\u90a3\u4e48\u5982\u679c\u4e00\u4e2a IO \u6d41\uff0c\u66fe\u7ecf\u6709\u6570\u636e\u53ef\u8bfb\u53d6\u4f46\u5df2\u7ecf\u88ab\u8bfb\u53d6\u5b8c\u6bd5\uff0c\u4f46\u540e\u7eed\u4ecd\u6709\u53ef\u80fd\u589e\u52a0\u53ef\u8bfb\u53d6\u7684\u6570\u636e\uff0c\u6b64\u65f6\u8c03\u7528 read \uff0c\u662f\u4e0d\u662f\u4ecd\u7136\u5c5e\u4e8e\u8fd9\u91cc\u6240\u8bf4\u7684\u201cblocks until input data is available\u201d\uff0c\u4e5f\u5c31\u662f\uff0c\u662f\u5426\u4f1a\u53d1\u751f\u963b\u585e\uff1f</p>\n<h1>\u4f8b\u5b50</h1>\n<p>\u6211\u83b7\u53d6\u4e86 Process \u7684 InputStream \uff0c\u91cc\u9762\u7684\u5185\u5bb9\u662f\u8fd9\u4e2a\u8fdb\u7a0b\u7684\u6807\u51c6\u8f93\u51fa\uff08\u4ee5\u53ca\u9519\u8bef\u8f93\u51fa\uff09\u3002<br/>\n\u663e\u7136\uff0c\u8fdb\u7a0b\u7684\u8f93\u51fa\u662f\u95f4\u65ad\u6027\u7684\uff0c\u6211\u60f3\u77e5\u9053\u73b0\u6709\u8f93\u51fa\u5df2\u7ecf\u88ab\u8bfb\u5b8c\u7684\u60c5\u51b5\u4e0b\uff0c\u6b64\u65f6\u518d\u8c03\u7528 read \uff0c\u662f\u5426\u8fd8\u4f1a\u5904\u4e8e\u963b\u585e\u72b6\u6001?</p>\n<pre><code class=\"language-Java\">    private ProcessBuilder dumpProcessBuilder;\n    ByteArrayOutputStream outputBuffer = new ByteArrayOutputStream(1024);\n    ...\n    dumpProcessBuilder.redirectErrorStream(true);\n    ...\n    Process dumpProcess = dumpProcessBuilder.start();\n    try (InputStream in = procForReader.getInputStream()) {\n        byte[] buf = new byte[1024];\n        int bytesRead = 0;\n        while ((bytesRead = in.read(buf)) != -1) {\n            output.write(buf, 0, outputBuffer);\n        }\n    }\n    ...\n</code></pre>\n", 
      "date_published": "2026-01-07T01:03:12+00:00", 
      "title": "\u60f3\u95ee\u4e00\u4e2a\u5173\u4e8e IO \u6d41\u7684\u7ec6\u8282", 
      "id": "https://www.v2ex.com/t/1183629"
    }, 
    {
      "author": {
        "url": "https://www.v2ex.com/member/deku9", 
        "name": "deku9", 
        "avatar": "https://cdn.v2ex.com/gravatar/4b2b0f7ee7a7ace326d7eb327e9ac154?s=73&d=retro"
      }, 
      "url": "https://www.v2ex.com/t/1183609", 
      "title": "\u5173\u4e8e\u6211\u5728\u817e\u8baf\u4e91 windows \u670d\u52a1\u5668\u8d77\u4e86\u4e00\u4e2a\u540e\u7aef\u670d\u52a1\uff0c\u4f46\u662f\u670d\u52a1\u5668\u672c\u5730\u90fd\u8bf7\u6c42\u4e0d\u5230\u7684\u95ee\u9898 11", 
      "id": "https://www.v2ex.com/t/1183609", 
      "date_published": "2026-01-06T15:47:31+00:00", 
      "content_html": "rt \uff0c\u6211\u5728\u672c\u5730\u548c\u670d\u52a1\u5668\u90fd\u8d77\u4e86\u540c\u4e00\u4e2a jar \u5305\uff0c\u4f46\u662f\u6211\u672c\u5730\u8bbf\u95ee url \u80fd\u8bf7\u6c42\u5230\u540e\u7aef\u3002<br />\u670d\u52a1\u5668\u4e0a\u8d77\u7684\u662f\u4e00\u6837\u7684 jar \u5305\uff0c\u8bbf\u95ee\u7684\u4e5f\u662f\u540c\u4e00\u4e2a url \uff0c\u4f46\u662f\u62a5 404 \u3002<br />\u672c\u5730\u548c\u670d\u52a1\u5668\u90fd\u662f\u7528 apifox \u53d1\u7684\u8bf7\u6c42\u3002<br />\u76f8\u5f53\u4e8e\u672c\u673a\u548c\u670d\u52a1\u5668\u8d77\u540c\u4e00\u4e2a jar \u5305\uff0c\u914d\u7f6e\u4e5f\u662f\u4e00\u6837\u7684\uff0c\u4f46\u662f\u670d\u52a1\u5668\u4e0a\u81ea\u5df1\u8c03\u4e0d\u901a\uff08\u672c\u5730 apifox \u8c03 locahost \u3002<br />\u6c42\u95ee\u5927\u4f6c\u8fd9\u662f\u5565\u539f\u56e0"
    }, 
    {
      "author": {
        "url": "https://www.v2ex.com/member/JYii", 
        "name": "JYii", 
        "avatar": "https://cdn.v2ex.com/avatar/6002/b4c1/487287_large.png?m=1773624099"
      }, 
      "url": "https://www.v2ex.com/t/1183220", 
      "title": "\u5206\u4eab\u4e00\u4e2a idea \u7684\u65e0\u54cd\u5e94 bug\uff0c\u5982\u679c\u4f60\u4e5f\u9047\u5230", 
      "id": "https://www.v2ex.com/t/1183220", 
      "date_published": "2026-01-05T06:10:25+00:00", 
      "content_html": "\u4eca\u5929\u6253\u5f00\u7535\u8111 idea \u54cd\u5e94\u975e\u5e38\u6162\uff0c\u4f1a\u77ac\u95f4\u5403\u6ee1 CPU \uff0c\u754c\u9762\u4e0b\u53d1\u63d0\u793a\u65e0\u54cd\u5e94\uff0c\u6211\u6ca1\u6709\u5174\u8da3 dump \uff08\u516c\u53f8\u7684\u7834\u9879\u76ee\u770b\u7740\u90fd\u6076\u5fc3\u5462\uff09\uff0c\u53bb\u5b98\u65b9\u8bba\u575b\u641c\u4e86\u641c\uff0c\u770b\u8d77\u6765\u4e0d\u6b62\u6211\u4e00\u4e2a\u4eba\u3002<br />\u770b\u8d77\u6765\u50cf\u4e2a\u5185\u5b58\u6cc4\u9732\uff0c\u5728\u6253\u5f00\u5927\u578b\u9879\u76ee\u65f6\uff0c\u8f83\u957f\u65f6\u95f4\u4e0d\u5173\u673a\u6709\u51e0\u7387\u89e6\u53d1\u3002<br /><br />\u53c2\u8003\u94fe\u63a5\uff1a<br /><a target=\"_blank\" href=\"https://youtrack.jetbrains.com/issue/IDEA-383438/IDEA-2025.3.1-freezes-when-opening-big-Maven-project-at-org.jetbrains.idea.maven.project.MavenProjectCompanion.read\" rel=\"nofollow noopener\">https://youtrack.jetbrains.com/issue/IDEA-383438/IDEA-2025.3.1-freezes-when-opening-big-Maven-project-at-org.jetbrains.idea.maven.project.MavenProjectCompanion.read</a>"
    }, 
    {
      "author": {
        "url": "https://www.v2ex.com/member/Yasuke", 
        "name": "Yasuke", 
        "avatar": "https://cdn.v2ex.com/avatar/2805/3b00/625825_large.png?m=1786427493"
      }, 
      "url": "https://www.v2ex.com/t/1182231", 
      "date_modified": "2025-12-30T10:32:49+00:00", 
      "content_html": "\u788d\u4e8e Java \u548c C/C++\u7684\u7ebf\u7a0b\u6a21\u578b\u3001\u5185\u5b58\u7ba1\u7406\u673a\u5236\u7684\u4e0d\u540c\uff0c\u73b0\u5728 JNI \u7684\u5199\u6cd5\u5b9e\u5728\u8fc7\u4e8e\u5570\u55e6\uff0c\u867d\u7136\u5b89\u5168\u4e14\u7a33\u5b9a\u3002", 
      "date_published": "2025-12-30T10:07:15+00:00", 
      "title": "JNI \u662f\u5426\u6709\u5411\"\u7b80\u6d01\"\u6f14\u5316\u7684\u53ef\u80fd\uff1f", 
      "id": "https://www.v2ex.com/t/1182231"
    }, 
    {
      "author": {
        "url": "https://www.v2ex.com/member/workWithMusic", 
        "name": "workWithMusic", 
        "avatar": "https://cdn.v2ex.com/avatar/f092/b694/683535_large.png?m=1766980311"
      }, 
      "url": "https://www.v2ex.com/t/1181887", 
      "date_modified": "2025-12-29T06:26:49+00:00", 
      "content_html": "<p>\u4f7f\u7528 springboot \u96c6\u6210 micrometer \u5b9e\u73b0\u81ea\u5b9a\u4e49 prometheus \u6307\u6807\u3002\n\u5047\u5982\u5728\u591a\u5b9e\u4f8b\u7684\u5546\u57ce\u7cfb\u7edf\u4e2d\u5b58\u5728\u4e00\u4e2a\u7528\u4e8e\u7edf\u8ba1\u5546\u54c1\u67e5\u770b\u6b21\u6570\u7684\u6307\u6807\uff0c\u540d\u4e3a item_view_count \uff0clabel\uff1a<code>item_id</code> \u3001<code>instance_id</code> \u3002\n\u5f53\u670d\u52a1\u91cd\u542f\u65f6\uff0c\u6309\u7167 micrometer \u7684\u9ed8\u8ba4\u884c\u4e3a\uff0c\u8fd9\u4e2a\u6307\u6807\u4f1a\u88ab\u7f6e\u4e3a 0 \u3002</p>\n<p>\u5bf9\u4e8e\u8fd9\u4e2a\u884c\u4e3a\u6211\u60f3\u5230\u4e86\u4e24\u79cd\u65b9\u6848\u3002</p>\n<ol>\n<li>\u5c06\u8fd9\u4e2a\u503c\u6301\u4e45\u5316\uff0c\u5e76\u4e14\u5728\u7b2c\u4e00\u6b21\u521b\u5efa\u6307\u6807\u65f6\u52a0\u8f7d\u3002</li>\n<li>\u670d\u52a1\u91cd\u542f\u540e\u4f7f\u7528\u65b0\u7684 instance_id \uff0c\u8fd9\u6837\u5728\u505a sum \u7edf\u8ba1\u65f6\u4e0d\u4f1a\u88ab\u91cd\u7f6e\u5f71\u54cd</li>\n</ol>\n<p>\u5404\u4f4d\u90fd\u662f\u5982\u4f55\u5904\u7406\u8fd9\u4e2a\u95ee\u9898\u5462\uff1f</p>\n", 
      "date_published": "2025-12-29T04:41:20+00:00", 
      "title": "\u591a\u5b9e\u4f8b springboot \u5fae\u670d\u52a1\u91cd\u542f\u65f6 Counter \u7c7b\u578b\u6307\u6807\u91cd\u7f6e\u95ee\u9898", 
      "id": "https://www.v2ex.com/t/1181887"
    }, 
    {
      "author": {
        "url": "https://www.v2ex.com/member/WngShhng", 
        "name": "WngShhng", 
        "avatar": "https://cdn.v2ex.com/avatar/4df1/42ef/328355_large.png?m=1764323245"
      }, 
      "url": "https://www.v2ex.com/t/1180696", 
      "title": "\u8ba8\u8bba\u4e2a\u95ee\u9898\uff1a\u8be5\u4e0d\u8be5\u91cd\u5199 equal \u548c hashcode", 
      "id": "https://www.v2ex.com/t/1180696", 
      "date_published": "2025-12-23T07:50:34+00:00", 
      "content_html": "<p>\u548c AI \u4ea4\u6d41\u7684\u65f6\u5019\u4ea7\u751f\u7684\u4e00\u4e2a\u95ee\u9898\uff1a</p>\n<p>AI \u7684\u5927\u81f4\u7ed3\u8bba\u662f\uff0c\u5bf9\u4e8e\u4e1a\u52a1\u7c7b\uff0c\u5982\u679c\u5b58\u5728\u660e\u786e\u7684\u552f\u4e00\u6807\u8bc6\uff0c\u6bd4\u5982 ID \uff0c\u90a3\u4e48\u5e94\u8be5\u91cd\u5199\u8fd9\u4e24\u4e2a\u65b9\u6cd5\uff0c\u8fd9\u6837\u5728\u505a\u54c8\u5e0c\u8868\u4e4b\u7c7b\u7684\u65f6\u5019\u624d\u80fd\u76f4\u63a5\u4f7f\u7528\u4e1a\u52a1\u7c7b\u3002</p>\n<p>\u4f46\u6211\u8ba4\u4e3a\u7684\u662f\uff0c\u56e0\u4e3a\u5f53\u628a\u4e00\u4e2a\u5bf9\u8c61\u653e\u8fdb\u54c8\u5e0c\u8868\u7684\u65f6\u5019\uff0c\u6211\u4f1a\u9ed8\u8ba4\u5b83\u7684 hashcode \u65b9\u6cd5\u662f\u9ed8\u8ba4\u7684\uff0c\u4e5f\u5c31\u662f\u6bcf\u4e2a\u5bf9\u8c61\u6709\u552f\u4e00\u7684\u54c8\u5e0c\u503c\u3002\u5982\u679c\u91cd\u5199\u4e86 hashcode \uff0c\u90a3\u4e48\u5728\u4f7f\u7528\u7684\u8fc7\u7a0b\u4e2d\u5982\u679c\u4e0d\u77e5\u9053\u8fd9\u4e2a\u7c7b\u590d\u5199\u4e86 hashcode \uff0c\u90a3\u4e48\u5c31\u5bb9\u6613\u5bfc\u81f4\u4ee3\u7801\u95ee\u9898\u3002</p>\n<p>\u6240\u4ee5\uff0c\u6211\u60f3\u77e5\u9053\u505a java \u540e\u7aef\u7684\uff0c\u4f60\u4eec\u4e00\u822c\u4f1a\u91cd\u5199\u5417\uff1f</p>\n<p>AI \u7684\u4e00\u90e8\u5206\u539f\u6587\uff1a</p>\n<pre><code>\u5982\u679c\u629b\u5f00 \u201c\u6570\u91cf\u5360\u6bd4\u201d\uff0c\u805a\u7126\u4e8e\u300c\u5f00\u53d1\u4e2d\u9700\u8981\u91cd\u70b9\u8bbe\u8ba1\u3001\u4fdd\u8bc1\u6b63\u786e\u6027\u7684\u6838\u5fc3\u573a\u666f\u300d\uff0c\u91cd\u5199\u7684\u9891\u7387\u4f1a\u8fdc\u9ad8\u4e8e \u201c\u4e0d\u91cd\u5199\u201d \u7684\u6838\u5fc3\u573a\u666f\uff0c\u539f\u56e0\u5982\u4e0b\uff1a\n\n\u6838\u5fc3\u7c7b\u5fc5\u91cd\u5199\uff1a\u6240\u6709\u627f\u8f7d\u4e1a\u52a1\u6570\u636e\u7684\u6838\u5fc3\u7c7b\uff08\u5982 User \u3001Order \u3001Goods \u7b49\uff09\uff0c\u51e0\u4e4e 100% \u9700\u8981\u91cd\u5199 \u2014\u2014 \u8fd9\u662f\u4fdd\u8bc1\u54c8\u5e0c\u96c6\u5408\u6b63\u5e38\u5de5\u4f5c\u3001\u4e1a\u52a1\u5bf9\u8c61\u552f\u4e00\u6027\u5224\u65ad\u3001\u5e8f\u5217\u5316\u540e\u6bd4\u5bf9\u7b49\u6838\u5fc3\u529f\u80fd\u7684\u524d\u63d0\uff0c\u4e0d\u5b58\u5728 \u201c\u53ef\u9009\u201d \u7684\u7a7a\u95f4\uff1b\n\n\u91cd\u5199\u7684 \u201c\u91cd\u590d\u6027\u201d \u66f4\u9ad8\uff1a\u4e00\u4e2a\u9879\u76ee\u4e2d\uff0c\u6570\u636e\u627f\u8f7d\u7c7b\u7684\u6570\u91cf\u867d\u5c11\uff0c\u4f46\u6bcf\u4e2a\u7c7b\u7684\u5f00\u53d1\u90fd\u5fc5\u7136\u5305\u542b \u201c\u91cd\u5199 equals/hashCode\u201d \u8fd9\u4e00\u6b65\uff08\u65e0\u8bba\u662f\u624b\u52a8\u751f\u6210\u3001Lombok \u6ce8\u89e3\u8fd8\u662f Record \u7c7b\uff09\uff0c\u5c5e\u4e8e \u201c\u5fc5\u505a\u64cd\u4f5c\u201d\uff1b\u800c\u4e0d\u91cd\u5199\u7684\u7c7b\uff0c\u53ea\u662f \u201c\u65e0\u9700\u989d\u5916\u64cd\u4f5c\u201d\uff0c\u5e76\u975e \u201c\u4e3b\u52a8\u5f00\u53d1\u884c\u4e3a\u201d\uff1b\n\n\u5de5\u5177\u7684\u666e\u53ca\u4f50\u8bc1\u9ad8\u9891\u9700\u6c42\uff1aLombok \u7684 @EqualsAndHashCode \u3001Java 16 + \u7684 Record \u7c7b\uff08\u9ed8\u8ba4\u91cd\u5199\uff09\u3001IDE \u81ea\u52a8\u751f\u6210\u529f\u80fd\uff0c\u8fd9\u4e9b\u5de5\u5177\u7684\u5e7f\u6cdb\u4f7f\u7528\uff0c\u672c\u8d28\u662f\u56e0\u4e3a \u201c\u91cd\u5199\u201d \u662f\u5f00\u53d1\u4e2d\u7684\u9ad8\u9891\u9700\u6c42\uff0c\u624d\u4f1a\u6709\u5927\u91cf\u5de5\u5177\u6765\u7b80\u5316\u8fd9\u4e00\u64cd\u4f5c\u3002\n</code></pre>\n"
    }, 
    {
      "author": {
        "url": "https://www.v2ex.com/member/heliotrope", 
        "name": "heliotrope", 
        "avatar": "https://cdn.v2ex.com/gravatar/f26ff0f38e2dd1247dca0a34e19b03d7?s=73&d=retro"
      }, 
      "url": "https://www.v2ex.com/t/1179190", 
      "date_modified": "2025-12-16T03:36:13+00:00", 
      "content_html": "<pre><code class=\"language-java\">public &lt;T&gt; void setCacheObject(final String key, final T value)\n{\n\tredisTemplate.opsForValue().set(key, value);\t\n}\n\npublic &lt;T&gt; T getCacheObject(final String key)\n{\n\tValueOperations&lt;String, T&gt; operation = redisTemplate.opsForValue();\n    return operation.get(key);\n}\n</code></pre>\n<p>\u8fd9\u4e2a\u903b\u8f91\u5728\u8c03\u7528 getCacheObject \u65f6\n\u8fd4\u56de\u5bf9\u8c61\u4f1a\u968f\u673a\u53d8\u6210 com.alibaba.fastjson.JSONObject \u6216\u8005 com.alibaba.fastjson2.JSONObject\n\u5bfc\u81f4\u5916\u90e8\u8c03\u7528\u65f6\u62a5\u7c7b\u578b\u5f3a\u5236\u8f6c\u6362\u5f02\u5e38</p>\n<p>\u5c31\u662f ruoyi \u811a\u624b\u67b6 \u91cc\u9762\u7684 RedisService\nTokenService \u91cc\u9762\u8c03\u7528 getLoginUser\n\u5c31\u4f1a\u62a5 java.lang.ClassCastException: com.alibaba.fastjson2.JSONObject cannot be cast to com.ruoyi.system.api.model.LoginUser</p>\n<p>\u800c\u4e14\u4e4b\u524d\u90fd\u6b63\u5e38 \u4e00\u6bb5\u65f6\u95f4\u6ca1\u8fd0\u884c \u518d\u8dd1\u5c31\u51fa\u73b0\u8fd9\u4e2a\u95ee\u9898\n\u5b9a\u4e49\u662f\u5728 RedisConfig</p>\n<pre><code class=\"language-java\">RedisTemplate&lt;Object, Object&gt; template = new RedisTemplate&lt;&gt;();\ntemplate.setConnectionFactory(connectionFactory);\nFastJson2JsonRedisSerializer serializer = new FastJson2JsonRedisSerializer(Object.class);\n</code></pre>\n<p>\u5168\u90e8\u90fd\u662f object \u83b7\u53d6\u5230\u5c31\u53d8 JSONObject \u4e86\n\u5b9e\u5728\u662f\u6ca1\u641e\u61c2\u54ea\u91cc\u6709\u95ee\u9898</p>\n", 
      "date_published": "2025-12-16T03:32:41+00:00", 
      "title": "\u6c42\u52a9 \u6cdb\u578b\u8f6c\u6362\u78b0\u5230\u4e00\u4e2a\u5f88\u5947\u602a\u7684\u95ee\u9898 Object \u653e Redis \u81ea\u52a8\u53d8\u6210 JSONObject \u4e86", 
      "id": "https://www.v2ex.com/t/1179190"
    }, 
    {
      "author": {
        "url": "https://www.v2ex.com/member/tiRolin", 
        "name": "tiRolin", 
        "avatar": "https://cdn.v2ex.com/gravatar/34a55186afde13a3880f2970ecaeffdc?s=73&d=retro"
      }, 
      "url": "https://www.v2ex.com/t/1176980", 
      "title": "Java Agent \u8be5\u600e\u4e48\u5feb\u901f\u5b66\u4e60\uff1f\u6709\u6559\u7a0b\u6587\u6863\u63a8\u4e00\u4e0b\u5417\uff1f", 
      "id": "https://www.v2ex.com/t/1176980", 
      "date_published": "2025-12-04T12:43:34+00:00", 
      "content_html": "<p>\u6211\u6700\u8fd1\u5165\u804c\u4e86\u4e00\u5bb6\u65b0\u516c\u53f8\uff0c\u6211\u5728\u91cc\u9762\u4e3b\u8981\u662f\u8d1f\u8d23\u505a APM \uff0c\u4e3b\u8981\u4f7f\u7528 Java Agent \u53bb\u505a\uff0c\u6211\u53bb B \u7ad9\u627e\u4e86\u4e00\u4e9b\u6559\u7a0b\uff0c\u4f46\u662f\u90fd\u53ea\u662f\u4e00\u4e9b\u7b80\u5355\u5165\u95e8\u7684\u5185\u5bb9\uff0c\u516c\u53f8\u5185\u90e8\u4e5f\u6709\u63d0\u4f9b\u4e00\u4e9b\u6559\u7a0b\uff0c\u4f46\u662f\u76ee\u524d\u6211\u53ea\u770b\u5230\u4e86\u8ddf\u516c\u53f8\u4ea7\u54c1\u672c\u8eab\u76f8\u5173\u7684\u5185\u5bb9\uff0c\u6211\u60f3\u95ee\u95ee\u5404\u4f4d\u8be5\u600e\u4e48\u5feb\u901f\u5b66\u4e60 Java Agent \u5462\uff1f\u6709\u6ca1\u6709\u4ec0\u4e48\u6559\u7a0b\u63a8\u4e00\u4e0b\uff1f\u7ed9\u6211\u5173\u952e\u5b57\u6216\u8005\u662f\u6587\u6863\u94fe\u63a5\u5c31\u597d\uff0c\u6211\u4f1a\u81ea\u5df1\u53bb\u770b\u7684\uff0c\u89c6\u9891\u4e5f\u53ef\u4ee5\uff0c\u6211\u90fd\u4f1a\u53bb\u770b\u7684\u3002</p>\n<p>\u5c0f\u5f1f\u6211\u5728\u8fd9\u91cc\u5148\u8c22\u8c22\u5404\u4f4d\u4e86</p>\n"
    }
  ]
}