<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Ide on Liangweidong's blog</title><link>https://liangweidonggood.github.io/tags/ide/</link><description>Recent content in Ide on Liangweidong's blog</description><generator>Hugo -- gohugo.io</generator><language>zh-cn</language><lastBuildDate>Sun, 15 Jun 2014 00:00:00 +0800</lastBuildDate><atom:link href="https://liangweidonggood.github.io/tags/ide/index.xml" rel="self" type="application/rss+xml"/><item><title>Docker Remote API 与 2375 端口：从开启到 IDE 集成的安全实践</title><link>https://liangweidonggood.github.io/p/docker-remote-api-2375/</link><pubDate>Sun, 15 Jun 2014 00:00:00 +0800</pubDate><guid>https://liangweidonggood.github.io/p/docker-remote-api-2375/</guid><description>&lt;img src="https://liangweidonggood.github.io/p/docker-remote-api-2375/image/cover.jpg" alt="Featured image of post Docker Remote API 与 2375 端口：从开启到 IDE 集成的安全实践" /&gt;&lt;p&gt;Docker 1.0 在 2014 年 6 月正式发布时，&lt;strong&gt;伴随的不仅是一个稳定版，更是一套被广泛复用的管理接口&lt;/strong&gt;——Docker Remote API。基于 HTTP + REST 风格，把 daemon 暴露在 2375 端口（未加密）或 2376 端口（TLS 加密），让 IDEA、Portainer、Shipyard、命令行客户端都能远程控制容器。&lt;/p&gt;
&lt;p&gt;这一篇把&amp;quot;如何开启 2375 端口 + 如何用 IDEA 远程连接 + 为什么必须配 TLS&amp;quot;这条主线串起来。&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;&lt;strong&gt;阅读对象&lt;/strong&gt;：需要从开发机远程管理服务器 Docker daemon 的开发者、运维同学
&lt;strong&gt;覆盖范围&lt;/strong&gt;：systemd 开启 2375/2376 端口 + IDEA Docker 插件 + TLS 证书生成 + 风险与替代方案&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;h2 id="一为什么需要-remote-api"&gt;一、为什么需要 Remote API
&lt;/h2&gt;&lt;p&gt;本地 &lt;code&gt;docker&lt;/code&gt; 命令行直接走 &lt;code&gt;/var/run/docker.sock&lt;/code&gt; Unix socket。&lt;strong&gt;一旦要在另一台机器上管理这个 daemon，要么 SSH 登过去，要么把 daemon 暴露成 HTTP 服务&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;Remote API 的典型场景：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;开发机远程管理生产 / 测试 Docker daemon&lt;/strong&gt;——开发笔记本 IDEA 上点 &amp;ldquo;Redeploy&amp;rdquo;，触发远端容器重建&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;可视化平台集中管控&lt;/strong&gt;——Portainer、Shipyard、Rancher 通过 Remote API 拉取容器列表 / 镜像 / 日志&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;CI 节点操作远端 daemon&lt;/strong&gt;——Jenkins Agent 在 K8s 节点内，通过 Remote API 控制宿主机 Docker（早期 docker-in-docker 方案）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;到 2014 年中 Docker 1.0 时代，&lt;strong&gt;2375 是事实上的标准端口&lt;/strong&gt;。Docker 1.11+（2016-04）又新增了 2376 作为 TLS 加密端口，逐步成为生产推荐。&lt;/p&gt;
&lt;h2 id="二开启-2375-端口systemd-方式"&gt;二、开启 2375 端口（systemd 方式）
&lt;/h2&gt;&lt;p&gt;绝大多数 Linux 发行版（CentOS 7+、Debian 8+、Ubuntu 16.04+）的 Docker 由 &lt;code&gt;docker.service&lt;/code&gt; 守护，通过 systemd 管理。&lt;strong&gt;修改启动参数是开启 Remote API 的标准做法&lt;/strong&gt;。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 编辑 docker.service&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;vim /usr/lib/systemd/system/docker.service
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;在 &lt;code&gt;ExecStart&lt;/code&gt; 这一行&lt;strong&gt;追加&lt;/strong&gt; &lt;code&gt;-H tcp://0.0.0.0:2375 -H unix://var/run/docker.sock&lt;/code&gt;：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;span class="lnt"&gt;8
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-ini" data-lang="ini"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;[Service]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;Type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;notify&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;ExecStart&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/usr/bin/dockerd \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; -H fd:// \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; -H tcp://0.0.0.0:2375 \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; -H unix:///var/run/docker.sock&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;ExecReload&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/bin/kill -s HUP $MAINPID&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
 &lt;blockquote&gt;
 &lt;p&gt;&lt;strong&gt;Why 加 &lt;code&gt;-H fd://&lt;/code&gt; + &lt;code&gt;-H unix:///var/run/docker.sock&lt;/code&gt;&lt;/strong&gt;：保留 fd 协议（systemd socket activation）和 Unix socket，&lt;strong&gt;让本机 &lt;code&gt;docker&lt;/code&gt; 命令继续可用&lt;/strong&gt;。如果不加 Unix socket，本机 &lt;code&gt;docker ps&lt;/code&gt; 会全部失效。&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;p&gt;修改完之后：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;span class="lnt"&gt;8
&lt;/span&gt;&lt;span class="lnt"&gt;9
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 重新加载 systemd 配置&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;systemctl daemon-reload
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 重启 docker&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;systemctl restart docker
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 验证端口是否真的开了&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ss -tlnp &lt;span class="p"&gt;|&lt;/span&gt; grep &lt;span class="m"&gt;2375&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 期望输出：LISTEN 0 128 *:2375 *:* users:((&amp;#34;dockerd&amp;#34;,pid=...,fd=...))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;从远端测试一下：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 在另一台机器上&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker -H tcp://&amp;lt;docker-host&amp;gt;:2375 images
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 期望输出：该 daemon 上的镜像列表&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
 &lt;blockquote&gt;
 &lt;p&gt;&lt;strong&gt;注意&lt;/strong&gt;：&lt;code&gt;&amp;lt;docker-host&amp;gt;&lt;/code&gt; 是 daemon 所在机器的 IP。&lt;strong&gt;不要写 &lt;code&gt;0.0.0.0&lt;/code&gt;&lt;/strong&gt;——客户端必须用真实可达 IP（如内网 IP 或公网 IP）。&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;h2 id="三idea-集成-docker"&gt;三、IDEA 集成 Docker
&lt;/h2&gt;&lt;p&gt;IntelliJ IDEA（2017.2+ Ultimate 内置 Docker 插件，2017.3 起 Community 也支持）能直接连 Docker daemon。&lt;/p&gt;
&lt;h3 id="31-在-idea-中配置"&gt;3.1 在 IDEA 中配置
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;Settings → Build, Execution, Deployment → Docker&lt;/code&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;TCP Socket&lt;/strong&gt;: &lt;code&gt;tcp://&amp;lt;docker-host&amp;gt;:2375&lt;/code&gt;（明文）或 &lt;code&gt;tcp://&amp;lt;docker-host&amp;gt;:2376&lt;/code&gt;（TLS）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Docker Compose executable&lt;/strong&gt;：选 &lt;code&gt;docker-compose&lt;/code&gt; 可执行文件路径&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;如果走 TLS，需要提前准备：&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;字段&lt;/th&gt;
					&lt;th&gt;含义&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;CA cert&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;证书颁发机构（&lt;code&gt;.crt&lt;/code&gt; 文件）&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;Client cert&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;客户端证书（&lt;code&gt;.cert&lt;/code&gt; 文件）&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;Client key&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;客户端私钥（&lt;code&gt;.key&lt;/code&gt; 文件）&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;填完之后，IDEA 会在底部 Services 面板里新增 &lt;code&gt;Docker&lt;/code&gt; 节点，&lt;strong&gt;可以看到远端容器、镜像、卷、网络&lt;/strong&gt;，并支持：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;一键 Run / Debug 容器（自动构建镜像 → 启动）&lt;/li&gt;
&lt;li&gt;实时查看容器 stdout / stderr&lt;/li&gt;
&lt;li&gt;Exec into container（类似 &lt;code&gt;docker exec -it&lt;/code&gt;）&lt;/li&gt;
&lt;li&gt;资源图表（CPU / 内存 / 网络 IO）&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="32-实际工作流"&gt;3.2 实际工作流
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;[IDEA]
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ↓ Run &amp;#39;Docker&amp;#39; configuration
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ↓ docker build -t myapp:dev .
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ↓ docker run -d -p 8080:8080 myapp:dev
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;[远端 Docker daemon (2375/2376)]
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ↓ 拉取基础镜像 / 构建 / 启动容器
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ↓ 把 stdout/stderr 推回 IDEA
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;开发阶段，&lt;strong&gt;所有 build / run / debug 都在远端完成&lt;/strong&gt;，本地不需要装 Docker Desktop——这是 2014-2017 时代跨平台开发的常见模式。&lt;/p&gt;
&lt;h2 id="四风险与生产建议"&gt;四、风险与生产建议
&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;明文 2375 端口 = 把 daemon root 权限交给任何能访问到的人&lt;/strong&gt;。攻击者只要能连到这个端口，就能：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;跑特权容器 → 逃逸到宿主机&lt;/li&gt;
&lt;li&gt;拉取 / 推送任意镜像&lt;/li&gt;
&lt;li&gt;删除所有数据卷&lt;/li&gt;
&lt;li&gt;挂载宿主机任意目录&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="41-必须做的安全加固"&gt;4.1 必须做的安全加固
&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;绝不放公网&lt;/strong&gt;：2375 端口&lt;strong&gt;只能在 VPC 内网&lt;/strong&gt;开放，&lt;strong&gt;不要&lt;/strong&gt;在云厂商安全组里把 2375 对 &lt;code&gt;0.0.0.0/0&lt;/code&gt; 开放&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;必须配 TLS&lt;/strong&gt;（2376）：用 OpenSSL 生成 CA、server、client 证书，配置 &lt;code&gt;tlsverify&lt;/code&gt; + &lt;code&gt;tlscacert&lt;/code&gt; + &lt;code&gt;tlscert&lt;/code&gt; + &lt;code&gt;tlskey&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;防火墙白名单&lt;/strong&gt;：iptables / nftables / 云安全组&lt;strong&gt;只放行&lt;/strong&gt;可信 IP 段&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;避免 rootless 之外运行&lt;/strong&gt;：Docker 默认以 root 运行，&lt;strong&gt;任何 Remote API 调用都是 root 等价&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="42-最小化配置示例tls"&gt;4.2 最小化配置示例（TLS）
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 1. 生成 CA、server、client 证书（简化版，参考 dockerd 官方文档）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; /etc/docker/tls
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;openssl genrsa -aes256 -out ca-key.pem &lt;span class="m"&gt;4096&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;openssl req -new -x509 -days &lt;span class="m"&gt;365&lt;/span&gt; -key ca-key.pem -sha256 -out ca.pem
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ... 生成 server-cert.pem / server-key.pem / client-cert.pem / client-key.pem&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 2. 修改 docker.service&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;ExecStart&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/usr/bin/dockerd &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --tlsverify &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --tlscacert&lt;span class="o"&gt;=&lt;/span&gt;/etc/docker/tls/ca.pem &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --tlscert&lt;span class="o"&gt;=&lt;/span&gt;/etc/docker/tls/server-cert.pem &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --tlskey&lt;span class="o"&gt;=&lt;/span&gt;/etc/docker/tls/server-key.pem &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -H tcp://0.0.0.0:2376 &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -H unix:///var/run/docker.sock
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;systemctl daemon-reload
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;systemctl restart docker
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="43-替代方案"&gt;4.3 替代方案
&lt;/h3&gt;&lt;p&gt;如果不想在每台机器上维护 TLS 证书，&lt;strong&gt;SSH 隧道是更轻量的选择&lt;/strong&gt;：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 在客户端机器上，把远端 docker.sock 转到本地&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ssh -L 2375:localhost:2375 user@&amp;lt;docker-host&amp;gt; &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -o &lt;span class="s2"&gt;&amp;#34;StreamLocalBindUnlink=yes&amp;#34;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -- docker system
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 现在本地 docker 命令会走 SSH 隧道&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker -H tcp://localhost:2375 ps
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;或者用&lt;strong&gt;反向 SSH 隧道&lt;/strong&gt;让远端 daemon 主动连出：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 在 docker-host 上&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ssh -R 2375:unix:///var/run/docker.sock user@jumphost
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id="五常见问题"&gt;五、常见问题
&lt;/h2&gt;&lt;h3 id="51-cannot-connect-to-the-docker-daemon-at-tcp"&gt;5.1 &lt;code&gt;Cannot connect to the Docker daemon at tcp://...&lt;/code&gt;
&lt;/h3&gt;&lt;p&gt;按顺序排查：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;端口是否真的开放：&lt;code&gt;ss -tlnp | grep 2375&lt;/code&gt; / &lt;code&gt;telnet &amp;lt;host&amp;gt; 2375&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;防火墙是否放行：&lt;code&gt;iptables -L -n&lt;/code&gt; / &lt;code&gt;firewall-cmd --list-all&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;云安全组：检查入方向规则&lt;/li&gt;
&lt;li&gt;&lt;code&gt;dockerd&lt;/code&gt; 启动参数：检查 &lt;code&gt;-H tcp://0.0.0.0:2375&lt;/code&gt; 是否拼对（注意是 &lt;code&gt;tcp://&lt;/code&gt; 不是 &lt;code&gt;tcp:\\\\&lt;/code&gt;）&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="52-idea-连上之后看不到容器"&gt;5.2 IDEA 连上之后看不到容器
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;确认 IDEA 里填的端口和 daemon 一致&lt;/li&gt;
&lt;li&gt;如果是 2376，&lt;strong&gt;所有三份证书&lt;/strong&gt;都要正确（CA + client cert + client key）&lt;/li&gt;
&lt;li&gt;在 &lt;code&gt;daemon.json&lt;/code&gt; 里查看 &lt;code&gt;&amp;quot;hosts&amp;quot;&lt;/code&gt; 字段确认没被覆盖&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="53-tls-连不上"&gt;5.3 TLS 连不上
&lt;/h3&gt;&lt;p&gt;检查证书的 SAN（Subject Alternative Name）字段，&lt;strong&gt;必须包含客户端实际访问的 IP / 域名&lt;/strong&gt;。Docker 18.09+ 启用了严格的证书校验，SAN 不匹配直接 &lt;code&gt;tls: invalid certificate&lt;/code&gt; 报错。&lt;/p&gt;
&lt;h2 id="六要点回顾"&gt;六、要点回顾
&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;2375 = 明文，2376 = TLS&lt;/strong&gt;——生产环境&lt;strong&gt;只用 2376&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;保留 Unix socket&lt;/strong&gt;——&lt;code&gt;-H unix:///var/run/docker.sock&lt;/code&gt; 必须有，否则本机 &lt;code&gt;docker&lt;/code&gt; 命令会失效&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;systemd reload ≠ restart&lt;/strong&gt;——改完 docker.service 必须 &lt;code&gt;daemon-reload&lt;/code&gt; + &lt;code&gt;restart&lt;/code&gt;，reload 不会重读 service 文件&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;IDEA Docker 插件&lt;/strong&gt; 是 Remote API 最常见的消费方，从 2017.2 起 Ultimate 内置，2017.3 起 Community 可用&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;SSH 隧道是 2375 的&amp;quot;穷人版安全&amp;quot;&lt;/strong&gt;——比明文好，但仍需 root 信任 SSH 通道&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="七小结"&gt;七、小结
&lt;/h2&gt;&lt;p&gt;Remote API 打开了 Docker 生态的&amp;quot;分布式管理&amp;quot;大门——从 CI 节点到 IDE，从可视化平台到跨主机编排，&lt;strong&gt;几乎所有上层工具都建立在 Remote API 之上&lt;/strong&gt;。但 2375 明文端口的安全代价极高，&lt;strong&gt;生产部署必须走 2376 + TLS&lt;/strong&gt;。&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;&lt;strong&gt;下一步&lt;/strong&gt;：理解了 Remote API，下一层是 Docker Compose v2（2020-08 GA）的声明式管理——把多个容器、网络、卷用一个 YAML 描述，daemon 自动调谐到期望状态。Compose v2 内部仍依赖 Docker SDK（Remote API 的 Go 封装），&lt;strong&gt;2375/2376 是它的&amp;quot;地基&amp;quot;&lt;/strong&gt;。&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;h2 id="参考资料"&gt;参考资料
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.docker.com/engine/api/" target="_blank" rel="noopener"
 &gt;Docker Engine API 官方文档&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.docker.com/engine/security/protect-access/" target="_blank" rel="noopener"
 &gt;Protect the Docker daemon socket&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.jetbrains.com/help/idea/docker.html" target="_blank" rel="noopener"
 &gt;IDEA Docker 插件文档&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.docker.com/blog/docker-1-0/" target="_blank" rel="noopener"
 &gt;Docker 1.0 公告（2014-06-09）&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>IntelliJ IDEA 全攻略：Java 主流 IDE 实战与插件生态</title><link>https://liangweidonggood.github.io/p/intellij-idea-2014-quan-gong-lve/</link><pubDate>Tue, 15 Apr 2014 00:00:00 +0800</pubDate><guid>https://liangweidonggood.github.io/p/intellij-idea-2014-quan-gong-lve/</guid><description>&lt;img src="https://liangweidonggood.github.io/p/intellij-idea-2014-quan-gong-lve/image/cover.jpg" alt="Featured image of post IntelliJ IDEA 全攻略：Java 主流 IDE 实战与插件生态" /&gt;&lt;h2 id="一intellij-idea-在-2013-2014-的地位"&gt;一、IntelliJ IDEA 在 2013-2014 的地位
&lt;/h2&gt;&lt;p&gt;2013 年 12 月，JetBrains 发布 &lt;strong&gt;IntelliJ IDEA 13&lt;/strong&gt;——这是 Java IDE 史上&lt;strong&gt;第一个默认 UI 走 Darcula 暗色主题&lt;/strong&gt;的版本，也是 Maven/Gradle 项目支持大幅强化的一年。2014 年 IDEA 14 推出 Spring 4 完整支持、Java 8 lambda 调试。&lt;strong&gt;从此 IDEA 与 Eclipse 的战争就基本结束&lt;/strong&gt;——本文整理 IDEA 在这两年沉淀下来的核心用法。&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;&lt;strong&gt;阅读建议&lt;/strong&gt;：本文面向&lt;strong&gt;从 Eclipse 切换到 IDEA&lt;/strong&gt; 的 Java 开发者，重点在&lt;strong&gt;快捷键迁移 + 必备插件&lt;/strong&gt;。&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;h2 id="二安装与初始配置"&gt;二、安装与初始配置
&lt;/h2&gt;&lt;h3 id="21-下载"&gt;2.1 下载
&lt;/h3&gt;&lt;p&gt;官方 &lt;code&gt;https://www.jetbrains.com/idea/download/#section=windows&lt;/code&gt;：&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;版本&lt;/th&gt;
					&lt;th&gt;适合&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;Community&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;自由开源（JDK 11 后部分功能受限）&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;Ultimate&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;商业（Spring/Hibernate/JS 等框架）&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;Edu&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;学生教学（免费 Ultimate）&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="22-第一次启动要做的事"&gt;2.2 第一次启动要做的事
&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;&lt;code&gt;Configure → Settings → Appearance → Theme&lt;/code&gt; → &lt;strong&gt;Darcula&lt;/strong&gt;（护眼）&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Editor → Font&lt;/code&gt; → &lt;strong&gt;JetBrains Mono&lt;/strong&gt;（旧版用 Consolas）&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Editor → General → Code Completion&lt;/code&gt; → 取消 &lt;code&gt;Match case&lt;/code&gt;（&lt;strong&gt;大小写不敏感&lt;/strong&gt;）&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Build, Execution, Deployment → Compiler&lt;/code&gt; → 勾选 &lt;code&gt;Build project automatically&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Version Control → Git&lt;/code&gt; → 选 &lt;code&gt;git.exe&lt;/code&gt; 路径&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="23-内存调优"&gt;2.3 内存调优
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;Help → Change Memory Settings&lt;/code&gt;（2020+）或编辑 &lt;code&gt;idea64.exe.vmoptions&lt;/code&gt;：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;-Xms2048m
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;-Xmx4096m
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;-XX:ReservedCodeCacheSize=512m
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;-XX:+UseG1GC
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
 &lt;blockquote&gt;
 &lt;p&gt;&lt;strong&gt;2025 时代&lt;/strong&gt;：IDEA 2024+ 已经自适应内存，&lt;strong&gt;初学者不要瞎调&lt;/strong&gt;。&lt;code&gt;Ctrl+Shift+A&lt;/code&gt; 搜 &amp;ldquo;Diagnostic Tools&amp;rdquo; 看内存使用。&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;h2 id="三核心快捷键"&gt;三、核心快捷键
&lt;/h2&gt;&lt;h3 id="31-必学-10-个"&gt;3.1 必学 10 个
&lt;/h3&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;快捷键&lt;/th&gt;
					&lt;th&gt;作用&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;Double Shift&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;查找所有（类/文件/符号/动作）&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;Ctrl + N&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;查找类&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;Ctrl + Shift + N&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;查找文件&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;Ctrl + Alt + L&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;格式化代码&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;Alt + Enter&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;显示意图操作（万能修复）&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;Ctrl + B&lt;/code&gt; / &lt;code&gt;Ctrl + Click&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;跳转到声明&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;Ctrl + F12&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;当前文件结构&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;Ctrl + E&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;最近文件&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;Alt + Insert&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;生成代码（getter/setter/构造/重写）&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;Ctrl + Shift + F10&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;运行当前上下文&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="32-进阶快捷键"&gt;3.2 进阶快捷键
&lt;/h3&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;快捷键&lt;/th&gt;
					&lt;th&gt;作用&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;Ctrl + Shift + F&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;全项目查找字符串&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;Ctrl + Shift + R&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;全项目替换&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;Alt + F7&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;查找用法&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;Ctrl + Alt + H&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;方法调用层次&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;Ctrl + Shift + T&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;创建单元测试&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;Ctrl + H&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;类继承层次&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;Shift + F6&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;重命名（项目级联动）&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;Ctrl + Alt + V&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;引入变量&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;Ctrl + Alt + M&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;提取方法&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;Ctrl + Alt + T&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Surround with（if/try/for 包裹）&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="33-从-eclipse-迁移"&gt;3.3 从 Eclipse 迁移
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;Settings → Keymap → Eclipse&lt;/code&gt; 可一键切换。&lt;strong&gt;但更推荐保留 IDEA 风格&lt;/strong&gt;——&lt;code&gt;IntelliJ IDEA Keybindings&lt;/code&gt; 扩展 VSCode，&lt;strong&gt;风格统一&lt;/strong&gt;。&lt;/p&gt;
&lt;h2 id="四代码生成"&gt;四、代码生成
&lt;/h2&gt;&lt;h3 id="41-live-templates实时代码模板"&gt;4.1 Live Templates（实时代码模板）
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;Settings → Editor → Live Templates&lt;/code&gt;，IDEA 内置几十个模板：&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;模板&lt;/th&gt;
					&lt;th&gt;展开&lt;/th&gt;
					&lt;th&gt;用途&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;psvm&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;public static void main(String[] args) {}&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;main 方法&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;sout&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;System.out.println()&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;打印&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;fori&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;for (int i = 0; i &amp;lt; ; i++)&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;for 循环&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;iter&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;for (T t : list)&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;增强 for&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;ifn&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;if (var == null)&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;null 判断&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;inn&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;if (var != null)&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;非 null 判断&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;prsf&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;private static final&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;静态常量&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;psfi&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;public static final int&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;公共常量&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;thr&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;throw new &lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;异常&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;ret&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;return&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;返回&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="42-自定义-live-template"&gt;4.2 自定义 Live Template
&lt;/h3&gt;&lt;p&gt;例：自定义 &lt;code&gt;soutm&lt;/code&gt; 打印方法名：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// 模板&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;$CLASS_NAME$.$METHOD_NAME$()&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// 适用 Java&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;code&gt;$VAR$&lt;/code&gt; 语法是占位符，&lt;code&gt;$END$&lt;/code&gt; 是光标最终位置。&lt;/p&gt;
&lt;h3 id="43-postfix-completion"&gt;4.3 Postfix Completion
&lt;/h3&gt;&lt;p&gt;输入表达式后加 &lt;code&gt;.&lt;/code&gt; 自动展开：&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;输入&lt;/th&gt;
					&lt;th&gt;展开&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;list.for&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;for (T t : list) {}&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;list.fori&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;for (int i = 0; i &amp;lt; list.size(); i++) {}&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;str.sout&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;System.out.println(str);&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;obj.nn&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;if (obj != null) { }&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;obj.null&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;if (obj == null) { }&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;num.var&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;int var = num;&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;效率倍增器&lt;/strong&gt;——前期多记。&lt;/p&gt;
&lt;h2 id="五必备插件2013-2014-时代"&gt;五、必备插件（2013-2014 时代）
&lt;/h2&gt;&lt;h3 id="51-工具类"&gt;5.1 工具类
&lt;/h3&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;插件&lt;/th&gt;
					&lt;th&gt;用途&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;.env files support&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;.env 文件语法高亮&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;.ignore&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;.gitignore 模板&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;Alibaba Cloud Toolkit&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;阿里云 ECS / 部署&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;Alibaba Java Coding Guidelines&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;strong&gt;阿里代码规范检查&lt;/strong&gt;（p3c 规则）&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;Lombok&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;@Data&lt;/code&gt; &lt;code&gt;@Slf4j&lt;/code&gt; 注解支持&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;Free Mybatis plugin&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Mapper/Service 跳转&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;Mybatis Log Plugin&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;把 MyBatis 预编译 SQL 还原成可执行 SQL&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;Translation&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;划词翻译（&lt;code&gt;Translation&lt;/code&gt; 引擎选 &lt;code&gt;Google&lt;/code&gt;/&lt;code&gt;DeepL&lt;/code&gt;）&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;Key Promoter X&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;鼠标操作时&lt;strong&gt;提示快捷键&lt;/strong&gt;（学习神器）&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="52-代码生成"&gt;5.2 代码生成
&lt;/h3&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;插件&lt;/th&gt;
					&lt;th&gt;用途&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;EasyCode&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;选表 → 一键生成 Entity/Mapper/Service/Controller&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;mybatis-maven-plugin&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;Maven 插件方式生成 MyBatis 代码&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;Git Commit Template&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;规范化 commit message&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;GitToolBox&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;行内 blame、内联分支信息&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;EnvFile&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;多环境 &lt;code&gt;.env&lt;/code&gt; 切换&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;HOCON&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Play Framework 配置格式&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="53-主题--个性"&gt;5.3 主题 / 个性
&lt;/h3&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;插件&lt;/th&gt;
					&lt;th&gt;用途&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;Material Theme UI&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Google Material 风格&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;One Dark theme&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;VSCode 经典暗色&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;Atom One Dark Theme&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Atom 风格&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;IdeaVim&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;strong&gt;Vim 模式&lt;/strong&gt;（Vim 党救命）&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;Background Image Plus&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;编辑器背景图（小心被扣工资）&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="54-ideavim-配置"&gt;5.4 IdeaVim 配置
&lt;/h3&gt;&lt;p&gt;Vim 党必装。&lt;code&gt;~/.ideavimrc&lt;/code&gt;：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-vim" data-lang="vim"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;&amp;#34; 关闭搜索高亮&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;nmap&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;silent&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Esc&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; :&lt;span class="nx"&gt;nohlsearch&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;CR&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;&amp;#34; Tab 切换窗口&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;nnoremap&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;C&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;h&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;C&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;h&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;nnoremap&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;C&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;l&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;C&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;l&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;nnoremap&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;C&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;j&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;C&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;j&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;nnoremap&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;C&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;k&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;C&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;k&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;&amp;#34; 搜索时高亮当前词&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;set&lt;/span&gt; &lt;span class="nx"&gt;hlsearch&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;set&lt;/span&gt; &lt;span class="nx"&gt;incsearch&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;code&gt;:&lt;/code&gt; 命令也能用 &lt;code&gt;:w&lt;/code&gt; &lt;code&gt;:q&lt;/code&gt; &lt;code&gt;:e&lt;/code&gt; 等等。&lt;/p&gt;
&lt;h3 id="55-mybatis-代码生成easycode"&gt;5.5 MyBatis 代码生成（EasyCode）
&lt;/h3&gt;&lt;p&gt;装 &lt;code&gt;EasyCode&lt;/code&gt; + &lt;code&gt;Database&lt;/code&gt; 插件：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;右侧 &lt;code&gt;Database&lt;/code&gt; 标签 → 加 MySQL 数据源&lt;/li&gt;
&lt;li&gt;右键表 → &lt;code&gt;EasyCode → Generate Code&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;选择生成模板（默认 &lt;code&gt;MyBatis-Plus&lt;/code&gt;、&lt;code&gt;MyBatis&lt;/code&gt; 等）&lt;/li&gt;
&lt;li&gt;一键生成 &lt;code&gt;Entity&lt;/code&gt;、&lt;code&gt;Mapper&lt;/code&gt;、&lt;code&gt;Service&lt;/code&gt;、&lt;code&gt;Controller&lt;/code&gt;、&lt;code&gt;ServiceImpl&lt;/code&gt;、&lt;code&gt;Mapper.xml&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;生成的代码默认 Spring Boot 风格&lt;/strong&gt;，直接拿到项目用。&lt;/p&gt;
&lt;h2 id="六spring-boot-项目结构"&gt;六、Spring Boot 项目结构
&lt;/h2&gt;&lt;h3 id="61-推荐的目录结构"&gt;6.1 推荐的目录结构
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;java&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;example&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;demo&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="n"&gt;DemoApplication&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;java&lt;/span&gt; &lt;span class="c1"&gt;# @SpringBootApplication&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="c1"&gt;# @Configuration&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="n"&gt;controller&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="c1"&gt;# @RestController&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="n"&gt;service&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="err"&gt;│&lt;/span&gt; &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="n"&gt;impl&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="c1"&gt;# @Service&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="n"&gt;mapper&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="c1"&gt;# @Mapper&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="n"&gt;entity&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="c1"&gt;# @Data @TableName&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="n"&gt;dto&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="c1"&gt;# 数据传输对象&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="n"&gt;vo&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="c1"&gt;# 视图对象&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="n"&gt;enums&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="c1"&gt;# 枚举&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="n"&gt;common&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="c1"&gt;# 工具类&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="c1"&gt;# 统一返回 R&amp;lt;T&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="n"&gt;exception&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="c1"&gt;# 全局异常&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="n"&gt;constant&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="c1"&gt;# 常量&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="62-applicationyml-分环境"&gt;6.2 application.yml 分环境
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;span class="lnt"&gt;18
&lt;/span&gt;&lt;span class="lnt"&gt;19
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;spring&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;profiles&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;active&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;dev&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nn"&gt;---&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;spring&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;profiles&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;dev&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;datasource&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;jdbc:mysql://localhost:3306/dev&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;username&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;root&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;&amp;lt;PASSWORD&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nn"&gt;---&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;spring&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;profiles&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;prod&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;datasource&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;jdbc:mysql://prod-host:3306/prod&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;username&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;&amp;lt;USER&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;&amp;lt;PASSWORD&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;切换：&lt;code&gt;右上角 Edit Configurations → Active Profiles&lt;/code&gt;。&lt;/p&gt;
&lt;h2 id="七性能调优与排错"&gt;七、性能调优与排错
&lt;/h2&gt;&lt;h3 id="71-启动慢"&gt;7.1 启动慢
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;关闭非必要插件：&lt;code&gt;Settings → Plugins&lt;/code&gt; 取消勾选&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Help → Diagnostic Tools → Activity Monitor&lt;/code&gt; 看占用&lt;/li&gt;
&lt;li&gt;升级 SSD（&lt;strong&gt;最有效&lt;/strong&gt;）&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="72-cannot-connect-to-already-running-ide-instance"&gt;7.2 &amp;ldquo;cannot connect to already running ide instance&amp;rdquo;
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;C:\Users\&amp;lt;USER&amp;gt;\AppData\Roaming\JetBrains\IntelliJIdea2023.2\.lock&lt;/code&gt; 文件存在，&lt;strong&gt;说明有实例在跑&lt;/strong&gt;。直接删除 &lt;code&gt;.lock&lt;/code&gt; 文件即可。&lt;/p&gt;
&lt;h3 id="73-lombok-不生效"&gt;7.3 Lombok 不生效
&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;装 &lt;code&gt;Lombok&lt;/code&gt; 插件&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Settings → Build → Compiler → Annotation Processors&lt;/code&gt; → 勾选 &lt;code&gt;Enable annotation processing&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;重启 IDEA&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="74-debug-时看不到变量值"&gt;7.4 Debug 时看不到变量值
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;Settings → Build → Compiler → Debugger → HotSwap&lt;/code&gt; → 启用（部分功能 Ultimate 才有）&lt;/p&gt;
&lt;h3 id="75-maven-依赖下载慢"&gt;7.5 Maven 依赖下载慢
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;Settings → Build → Maven&lt;/code&gt; → 改 &lt;code&gt;User settings file&lt;/code&gt; 为阿里云镜像：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;span class="lnt"&gt;8
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-xml" data-lang="xml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;mirrors&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;lt;mirror&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;lt;id&amp;gt;&lt;/span&gt;aliyun&lt;span class="nt"&gt;&amp;lt;/id&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;lt;name&amp;gt;&lt;/span&gt;Aliyun Maven&lt;span class="nt"&gt;&amp;lt;/name&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;lt;url&amp;gt;&lt;/span&gt;https://maven.aliyun.com/repository/public&lt;span class="nt"&gt;&amp;lt;/url&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;lt;mirrorOf&amp;gt;&lt;/span&gt;central&lt;span class="nt"&gt;&amp;lt;/mirrorOf&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;lt;/mirror&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;/mirrors&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id="八必备快捷键速查"&gt;八、必备快捷键速查
&lt;/h2&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;类别&lt;/th&gt;
					&lt;th&gt;快捷键&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;导航&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;Ctrl+N&lt;/code&gt; 类 / &lt;code&gt;Ctrl+Shift+N&lt;/code&gt; 文件 / &lt;code&gt;Ctrl+Alt+Shift+N&lt;/code&gt; 符号&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;编辑&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;Ctrl+D&lt;/code&gt; 复制行 / &lt;code&gt;Ctrl+Y&lt;/code&gt; 删除行 / &lt;code&gt;Ctrl+/&lt;/code&gt; 注释&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;重构&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;Shift+F6&lt;/code&gt; 重命名 / &lt;code&gt;Ctrl+Alt+M&lt;/code&gt; 提取方法&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;运行&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;Shift+F10&lt;/code&gt; 运行 / &lt;code&gt;Shift+F9&lt;/code&gt; 调试&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;窗口&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;Alt+1&lt;/code&gt; 项目 / &lt;code&gt;Alt+4&lt;/code&gt; 运行 / &lt;code&gt;Alt+5&lt;/code&gt; 调试 / &lt;code&gt;Alt+9&lt;/code&gt; Git&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;VCS&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;Ctrl+K&lt;/code&gt; 提交 / &lt;code&gt;Ctrl+T&lt;/code&gt; 更新 / &lt;code&gt;Alt+9&lt;/code&gt; 日志&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="九idea-vs-eclipse-vs-vscode"&gt;九、IDEA vs Eclipse vs VSCode
&lt;/h2&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;维度&lt;/th&gt;
					&lt;th&gt;IDEA Ultimate&lt;/th&gt;
					&lt;th&gt;Eclipse&lt;/th&gt;
					&lt;th&gt;VSCode&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;Java 体验&lt;/td&gt;
					&lt;td&gt;★★★★★&lt;/td&gt;
					&lt;td&gt;★★★★&lt;/td&gt;
					&lt;td&gt;★★★（要装 Extension Pack）&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;启动速度&lt;/td&gt;
					&lt;td&gt;★★★（最慢）&lt;/td&gt;
					&lt;td&gt;★★★★&lt;/td&gt;
					&lt;td&gt;★★★★★&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;内存占用&lt;/td&gt;
					&lt;td&gt;★★（最重）&lt;/td&gt;
					&lt;td&gt;★★★&lt;/td&gt;
					&lt;td&gt;★★★★&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;前端&lt;/td&gt;
					&lt;td&gt;★★★★&lt;/td&gt;
					&lt;td&gt;★★&lt;/td&gt;
					&lt;td&gt;★★★★★&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;调试&lt;/td&gt;
					&lt;td&gt;★★★★★&lt;/td&gt;
					&lt;td&gt;★★★★&lt;/td&gt;
					&lt;td&gt;★★★&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;智能提示&lt;/td&gt;
					&lt;td&gt;★★★★★&lt;/td&gt;
					&lt;td&gt;★★★★&lt;/td&gt;
					&lt;td&gt;★★★★&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;价格&lt;/td&gt;
					&lt;td&gt;商业&lt;/td&gt;
					&lt;td&gt;免费&lt;/td&gt;
					&lt;td&gt;免费&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;经验法则&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Java 后端为主&lt;/strong&gt; → IDEA&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;多语言混合 + 前端&lt;/strong&gt; → VSCode&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;老项目 + 嵌入式&lt;/strong&gt; → Eclipse&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="十常见问题"&gt;十、常见问题
&lt;/h2&gt;&lt;h3 id="101-中文乱码"&gt;10.1 中文乱码
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;Settings → Editor → File Encodings&lt;/code&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Global Encoding&lt;/code&gt;: UTF-8&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Project Encoding&lt;/code&gt;: UTF-8&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Default encoding for properties files&lt;/code&gt;: UTF-8&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="102-maven-报错-cannot-resolve-symbol"&gt;10.2 Maven 报错 &amp;ldquo;Cannot resolve symbol&amp;rdquo;
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;File → Invalidate Caches&lt;/code&gt; → 勾选所有 → &lt;code&gt;Invalidate and Restart&lt;/code&gt;。&lt;/p&gt;
&lt;h3 id="103-tomcat-控制台中文乱码"&gt;10.3 Tomcat 控制台中文乱码
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;Help → Edit Custom VM Options&lt;/code&gt;：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;-Dfile.encoding=UTF-8
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;-Dconsole.encoding=UTF-8
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="104-spring-boot-项目启动报错-web-server-failed-to-start"&gt;10.4 Spring Boot 项目启动报错 &amp;ldquo;Web server failed to start&amp;rdquo;
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;检查 &lt;code&gt;application.yml&lt;/code&gt; 端口是否被占用：&lt;code&gt;netstat -ano | findstr 8080&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;检查 &lt;code&gt;pom.xml&lt;/code&gt; 中 &lt;code&gt;spring-boot-starter-web&lt;/code&gt; 依赖&lt;/li&gt;
&lt;li&gt;启动类是否在 &lt;code&gt;com.example&lt;/code&gt; 父包下&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="十一下一步"&gt;十一、下一步
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;想看设计建模：&lt;strong&gt;[2014-10-15 设计建模工具：Axure / PowerDesigner / VSCode]&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;想看版本控制：&lt;strong&gt;[2014-11-15 Git 与版本控制]&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;想看 Spring Boot 微服务：&lt;strong&gt;项目全流程&lt;/strong&gt; 章节&lt;/li&gt;
&lt;/ul&gt;

 &lt;blockquote&gt;
 &lt;p&gt;&lt;strong&gt;本文写于 2014 年，回看当时&lt;/strong&gt;：IDEA 2014 还是付费 Ultimate 的天下（Community 版功能弱），&lt;strong&gt;2024 年 Community 已经免费支持 Spring Boot 全功能&lt;/strong&gt;——这是 JetBrains 2024 年最大的开源让步。Alibaba 规范插件 2017 年才正式上线（p3c 2017 开源），&lt;strong&gt;p3c 已成为国内 Java 代码规范的事实标准&lt;/strong&gt;。&lt;/p&gt;

 &lt;/blockquote&gt;</description></item></channel></rss>