☰
Spring Boot 3 + JDK 17 + Nacos 微服务注册与配置中心搭建实战指南
2026/10/3 2:57:03 网站建设 项目流程

近两年接手的老项目可真不少,一上来就是“JDK 8 + Spring Boot 2.x + 自己写注册发现”,确实能跑,但升级维护太难受。后来新项目我索性直接一套组合:IDEA + JDK 17 + Spring Boot 3 + Nacos。从社区到企业内网,这套方案已经是当前 Java 后端很常见的基础架构了。这篇文章就把我完整搭建的过程、配置、以及踩过的坑全部整理出来。

不管你是刚接触 Spring Cloud 的初学者,还是准备把老项目从 JDK 8 往上升级的开发者,这篇文章都适用。我会从JDK 17 环境配置开始,再到 IDEA 新建项目、引入 Nacos 注册中心和配置中心,每一步都给到具体操作,还会把那些在文档里查不到的经验讲清楚。建议你打开 IDEA 跟着做一遍,10 分钟就能跑通一个“服务注册 + 配置动态刷新”的最小系统。

1. 基础环境准备:JDK 17 与 IDEA 社区版

1.1 JDK 17 下载与安装,到底选哪个发行版

JDK 17 是 2021 年发布的 LTS(长期支持)版本,Oracle 官方会持续支持到 2029 年,比 JDK 11 的更新时间更长,这也是工业界逐渐把 Java 基线从 8 提到 17 的原因。Spring Boot 3.x 要求 Java 17 起步,所以如果你要玩 Spring Boot 3,这一步逃不掉。

我个人的选择顺序是这样的:

发行版适合场景注意点
Oracle JDK 17本地开发、个人学习下载需要登录 Oracle 账号,但过程很简单
Eclipse Temurin (OpenJDK)推荐日常开发使用开源免费,无账号限制
Amazon Corretto生产环境、AWS 部署更新节奏稳定,修复及时
Azul Zulu容器化运行和常用基础镜像兼容性好

日常开发我推荐下载Eclipse Temurin或者Oracle JDK。你打开浏览器搜索对应的官网,找到 JDK 17 的 Windows x64 / macOS / Linux 安装包,按照安装向导下一步就行。安装路径强烈建议不要带空格和中文,比如C:\Java\jdk-17,虽然现在的工具已经能处理,但省得后面脚本出幺蛾子。

安装完成后最关键的一步是配环境变量。右键“此电脑” → 属性 → 高级系统设置 → 环境变量,新建一个系统变量:

JAVA_HOME = C:\Java\jdk-17

然后在Path变量里添加%JAVA_HOME%\bin。这一步的目的是让命令行工具能找到java、javac,IDEA 也能通过环境变量自动识别 JDK。

配置完以后打开命令行工具(Windows 是 cmd 或 PowerShell),输入:

java -version

如果你看到类似下面的输出,说明环境已经通了:

java version "17.0.x" 2023-xx-xx LTS Java(TM) SE Runtime Environment (build 17.0.x+xx-LTS) Java HotSpot(TM) 64-Bit Server VM (build 17.0.x+xx-LTS, mixed mode, sharing)

注意:如果你电脑里同时装了 JDK 8 和 JDK 17,命令行里java -version可能显示的还是老版本。这时要检查Path变量里%JAVA_HOME%\bin是否排在 Oracle 自带 java 路径的前面。Windows 的环境变量是按顺序匹配的,把%JAVA_HOME%\bin挪到最前面即可。

1.2 IDEA 版本选择:社区版也能正常开发 Spring Boot

很多同学一搜“IDEA 破解版”或者“激活码”,其实完全没必要。JetBrains 官方提供的IntelliJ IDEA Community Edition(社区版)是免费的,而且完全支持 Spring Boot 项目创建、打开、编译和调试。

  • 新建 Spring Boot 项目:支持
  • Maven/Gradle 构建:支持
  • 断点调试:支持
  • Spring 相关插件:部分内置,够用
  • HTTP Client、终端:支持

社区版唯一缺的是 Spring 专门的高级窗口(比如 Beans 图形化展示),但这对实际开发影响很小。你直接在 IDEA 官网上找“Community Edition”下载,装好后第一次打开会询问是否导入配置,选择不导入就行。

有这个背景要知道:国内不少人跑到第三方网站下载所谓的“绿色版、破解版”,风险不光是法律问题,更致命的是可能被人植入恶意代码。写代码的工具都不干净,后面怎么敢把公司代码放进去。用社区版,功能不少、更新正常,足够日常项目折腾。

1.3 Nacos 服务端安装,别用最新版,选对稳定版

Nacos 是阿里巴巴开源的服务注册与配置中心,同时解决了“服务发现”和“配置管理”两个问题。名字就是Name + Configuration + Service的缩写,从这个命名也能看出来它的两个核心职责。

下载地址在 GitHub 的alibaba/nacos项目里,找到 Releases 页面,选择稳定版本。有个小技巧:不要盲目追最新版,Nacos 2.x 系列里推荐 2.2.x 或 2.3.x;Nacos 3.x 增加了不少新能力,但生态配套还在磨合期,老项目踩坑概率偏高。

Windows 解压后目录结构大概是这样的:

nacos-server-2.2.3 ├── bin │ ├── startup.cmd │ ├── startup.sh │ └── shutdown.cmd ├── conf │ ├── application.properties │ └── ... ├── data └── logs

Windows 上进入bin目录,双击或命令行执行:

startup.cmd -m standalone

-m standalone表示单机模式,不开集群。如果你是 Mac 或 Linux,则执行:

sh startup.sh -m standalone

启动成功后,命令行里会显示 Nacos 的 Logo 和端口信息,默认端口是8848。浏览器访问http://localhost:8848/nacos,看到控制台登录页面就算成功。默认用户名和密码都是nacos,首次登录后建议马上改密码。

非常容易踩坑的细节:Nacos 默认启动方式其实是集群模式,没加-m standalone会报数据库连接错误或节点选举失败。第一次启动请务必确认参数加上。

如果你本机 8848 端口被占用,可以去conf/application.properties里修改server.port,改完重启。这个会在后面的常见问题里详细展开。

2. IDEA 创建 Spring Boot 3 项目:从零到可运行

2.1 新建 Project 的几个关键选择

打开 IDEA,点击New Project,左侧选Spring Boot或Spring Initializr(IDEA 版本不同菜单名可能有差异)。如果用的是社区版,没有 Spring Initializr 选项,就直接选New Project→Maven。

在初始化页面,有几个选择直接影响后面的推进方向:

  • Language:Java
  • Type:Maven(我个人更习惯 Maven,Gradle 也可以但别混着用)
  • JDK:选择 17 版本(如果下拉框为空,就选择Add JDK指向你刚才安装的路径)
  • Packaging:Jar
  • Spring Boot:3.2.x 或 3.1.x(不要选 3.0 的老版本,后续升级麻烦)
  • Dependencies:这里只需要加Spring Web,其余的 Nacos 相关我们手动引入,这样能更清楚每一步做了什么

点击Create,IDEA 会自动生成一个标准 Maven 工程,包含pom.xml、主启动类、application.properties。

首次打开 Maven 工程时,IDEA 会下载一堆依赖,这个阶段会比较慢。建议打开Settings → Build, Execution, Deployment → Build Tools → Maven,确认一下本机的 Maven 路径,尽量别用 IDEA 自带的默认配置,这样依赖下载速度和稳定性都更好。

2.2 引入 Spring Cloud Alibaba 依赖,版本兼容表按这个走

Spring Boot 3.x 并不是简单地替换版本号就行,底层已经从javax.*全部迁移到jakarta.*,所以老的 Spring Cloud 组件必须用新版本。这里最核心的就是引入Spring Cloud Alibaba的 BOM(Bill of Materials),它会统一管理 Nacos 相关组件的版本。

我整理了一张常用兼容版本表,照着填能省掉大量排错时间:

Spring BootSpring CloudSpring Cloud AlibabaNacos Server
3.2.x2023.0.x2023.0.1.02.3.x
3.1.x2022.0.x2022.0.0.02.2.x
3.0.x2022.0.x2022.0.0.0-RC22.2.x
2.7.x2021.0.x2021.0.5.02.1.x

这里我推荐选择Spring Boot 3.2.x + Spring Cloud 2023.0.x + Spring Cloud Alibaba 2023.0.1.0这套组合,稳定性和文档完整度都不错。

打开pom.xml,在<properties>标签里加:

<spring-cloud.version>2023.0.1</spring-cloud.version> <spring-cloud-alibaba.version>2023.0.1.0</spring-cloud-alibaba.version>

接着在<dependencyManagement>里统一管理版本:

<dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-alibaba-dependencies</artifactId> <version>${spring-cloud-alibaba.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>

然后在<dependencies>里添加两个关键的 Starter:

<dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> </dependency>

nacos-discovery负责服务注册与发现,nacos-config负责配置中心。如果你暂时只需要注册中心,第一个必加,第二个可以先不加,但既然 Nacos 都上了,配置中心迟早要用的,我一贯建议一起引入。

改完后点击 Maven 面板的Reload All Projects,等依赖下载完成。这个步骤如果卡很久,先检查 maven 仓库路径和镜像配置,别急着怀疑代码。

2.3 验证最小 Web 业务能跑

在项目里新建一个测试接口,确保基础链路没问题。比如新建类HelloController.java:

package com.example.demo; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class HelloController { @GetMapping("/hello") public String hello() { return "Hello Spring Boot 3 + Nacos"; } }

然后运行主类(带@SpringBootApplication的那个)。控制台里如果出现类似:

Tomcat started on port 8080 (http)

就说明项目本身已经能正常工作了。浏览器访问http://localhost:8080/hello,能看到返回内容即可。

3. 接入 Nacos 注册中心:配置、启动、看效果

3.1 服务注册的配置到底怎么写

Spring Boot 3 里,很多框架都推荐用application.yml,Nacos 配置也优先放在这。打开src/main/resources/application.yml,改成如下内容:

spring: application: name: demo-service cloud: nacos: server-addr: 127.0.0.1:8848 discovery: enabled: true server: port: 8080

说说每个配置的含义:

  • spring.application.name:服务名,注册到 Nacos 后,其他服务通过这个名字调用你。
  • spring.cloud.nacos.server-addr:Nacos 服务端地址。本地开发直接127.0.0.1:8848,如果 Nacos 部署在其他环境,这里填对应的 IP 和端口。
  • spring.cloud.nacos.discovery.enabled:是否开启服务注册,默认就开启,写上是为了明确。

写完配置,直接重新启动应用。观察控制台日志,如果没报错,看到Nacos registry, demo-service ... register finished字样,说明注册成功。

这时候登录 Nacos 控制台,在“服务管理 → 服务列表”里应该能看到一个名为demo-service的服务,状态为“健康实例”。如果你的服务出现在这里,注册链路已经 100% 跑通。

3.2 多实例注册与负载均衡效果实测

注册中心的意义不只是把服务挂上去,更关键的是消费方能够通过服务名找到多个实例,进行负载均衡。你可以先演练一下多实例:

  • 在 IDEA 里改一下server.port,比如改成8081,把项目再启动一个实例。
  • 此时 Nacos 控制台里demo-service的“实例数量”会变成 2。
  • 然后在同一个项目里再加一个接口,调RestTemplate或OpenFeign去调用http://demo-service/hello。

这里有个重要细节:RestTemplate默认不认识服务名,要配合@LoadBalanced注解才能把demo-service解析成实际 IP 列表。Launcher(主启动类)改成这样:

package com.example.demo; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.loadbalancer.LoadBalanced; import org.springframework.context.annotation.Bean; import org.springframework.web.client.RestTemplate; @SpringBootApplication public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } @Bean @LoadBalanced public RestTemplate restTemplate() { return new RestTemplate(); } }

然后写一个调用方接口:

package com.example.demo; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate; @RestController public class CallController { @Autowired private RestTemplate restTemplate; @GetMapping("/call") public String call() { return restTemplate.getForObject("http://demo-service/hello", String.class); } }

启动两个实例后,多访问几次/call,你会看到返回内容有时来自 8080 实例,有时来自 8081 实例。这就是负载均衡的真实效果,也是服务注册最核心的价值:调用方不需要关心服务 IP 是否变化,只要服务名还在 Nacos 上,就能自动找到可用节点。

4. 接入 Nacos 配置中心并实现动态刷新

4.1 把配置挪到 Nacos,bootstrap.yml 的三种姿势

注册中心只是第一步,配置文件集中管理往往更重要。你的application.yml里如果有很多环境相关的开关、调参项,放在代码库里实在不好管理,每次改配置都要重新发版,效率极低。Nacos 配置中心就是来解决这个问题的。

在 Spring Boot 3 的体系里,把配置挪到 Nacos 有两种主流的做法。

第一种(推荐):引入spring-cloud-starter-bootstrap依赖,然后使用bootstrap.yml文件。这是老社区最常见的玩法。加依赖:

<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-bootstrap</artifactId> </dependency>

然后在src/main/resources下新建bootstrap.yml:

spring: application: name: demo-service cloud: nacos: server-addr: 127.0.0.1:8848 config: file-extension: yaml group: DEFAULT_GROUP

第二种(后续社区推广的玩法):不用 bootstrap,直接在application.yml里用spring.config.import导入 Nacos 配置文件。比如:

spring: application: name: demo-service config: import: - optional:nacos:demo-service.yaml cloud: nacos: server-addr: 127.0.0.1:8848

两种方式都能工作,我建议新手先用第一种,因为网上资料最多、报错排查起来也容易。记住一个关键点:bootstrap.yml的加载时机比application.yml早,所以 Nacos 的地址必须写在bootstrap.yml里,不然应用都启动完了还没连上配置中心。

4.2 Nacos 上创建配置 Data ID 的格式

登录 Nacos 控制台,进入“配置管理 → 配置列表”,点击“新建配置”。这里最让人头晕的往往是Data ID 的命名。

Nacos 默认的 Data ID 规则是:${spring.application.name}.${file-extension}。

也就是说,如果应用名是demo-service,file-extension配的是yaml,那么 Data ID 就是:

demo-service.yaml

注意:很多人在这里写成demo-service.yml,结果配置死活加载不进去。因为file-extension配置的是yaml,Nacos 只会去拉demo-service.yaml。要改扩展名,就得两个位置一起改。

Group 一般保持DEFAULT_GROUP即可,它用于区分同一服务在不同业务场景下的配置分组,日常开发用默认组省心。

配置内容可以简单点,先放一个自定义项,比如:

student: name: zhangsan age: 18

点击发布后,如果服务已经启动并正确连上了 Nacos,你会发现配置中心推送后,应用控制台会打出类似Refresh keys changed的日志。

4.3 动态刷新实战:用 @RefreshScope 看到即时生效

配置中心的魅力在于“不用重启就能改变行为”。我做一个最简单的演示:用@ConfigurationProperties读取配置,再暴露一个接口返回配置值,配合@RefreshScope实现动态生效。

先建一个配置类:

package com.example.demo.config; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.cloud.context.config.annotation.RefreshScope; import org.springframework.stereotype.Component; @Component @RefreshScope @ConfigurationProperties(prefix = "student") public class StudentConfig { private String name; private int age; // getter and setter public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }

然后加一个测试接口:

package com.example.demo.config; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("/config") public class ConfigController { @Autowired private StudentConfig studentConfig; @GetMapping public String getConfig() { return "name = " + studentConfig.getName() + ", age = " + studentConfig.getAge(); } }

启动服务后,先访问/config看到初始值。然后回到 Nacos 控制台,把配置改成name: lisi,点击发布。等个一两秒(Nacos 客户端默认有一个长轮询周期),再次访问/config,不需要重启应用,返回结果已经变了。这就是配置动态刷新。

如果没有加@RefreshScope,你会发现@ConfigurationProperties的值刷新后不会改变。这个注解的本质是在配置变化时重建 Bean,从而让新配置生效。

4.4 配置中心的命名空间、分组到底是干嘛的

我接触过不少项目,配置多了以后在 Nacos 上杂乱无章,最后连哪个配置属于哪个环境都分不清。Nacos 早就给出了隔离机制,只是很多人没用明白,这里必须掰扯清楚。

维度用途典型实践
Namespace(命名空间)环境隔离dev、test、prod建三个命名空间
Group(分组)业务分组同一个环境下区分支付、订单、用户等
Cluster(集群)地域容灾北京、上海、广州机房的实例分组

默认情况下,服务注册在public命名空间,分组是DEFAULT_GROUP。如果你的服务要指定命名空间,可以在配置文件里加:

spring: cloud: nacos: server-addr: 127.0.0.1:8848 config: namespace: 8e4f2c31-xxxx-xxxx-xxxx-xxxxxxxxxxxx

这个 namespace 不是随便填个名字就行,必须填 Nacos 控制台里创建命名空间后生成的 ID 字符串。在命名空间页面能看到这串 UUID。服务注册和配置读取的 namespace 要保持一致,否则应用启动后会默认找到public命名空间下的配置,导致“配置明明存在就是不起效”的灵异事件。

5. 常见问题与排查技巧实录

5.1 应用启动时报错:Connection refused / 路由失败

现象:项目启动时控制台抛出类似Connection refused: /127.0.0.1:8848或者nacos server is not connected。

排查思路按顺序来:

  1. 确认 Nacos 是否已启动。访问http://localhost:8848/nacos,如果打不开,回到命令行重新执行startup.cmd -m standalone。
  2. 确认server-addr配置是否正确。注意不要加http://前缀,只要IP:端口。
  3. 确认端口是否被防火墙拦了。Windows 上第一次跑 Nacos 会弹防火墙授权,没点允许的话,Java 进程无法接收外部连接。
  4. 如果你用了 Docker 部署 Nacos,注意宿主机的端口映射,容器里是 8848,映射到宿主机可能是别的端口。

5.2 项目启动成功但控制台看不到注册日志

默认情况下,Nacos 注册成功后日志里有一行Nacos registry, demo-service ... register finished。我也遇到过服务明明起来了,注册中心里就是找不到的情况。这类问题九成是spring.cloud.nacos.discovery.server-addr没配上,或spring.application.name为空。

Spring Cloud 的注册逻辑依赖应用名作为服务标识,如果应用名没设,Spring Boot 3 默认会用unknown之类的值,注册结果就会出现一串奇怪的命名。

5.3 版本兼容问题:javax 还是 jakarta

老项目升级到 JDK 17 和 Spring Boot 3 时,最常见的异常是:

java.lang.NoClassDefFoundError: javax/servlet/...

或者编译都通不过,报package javax.servlet does not exist。原因很清晰:Spring Boot 3 把底层 API 从javax迁移到了jakarta。第三方老版本库如果不支持 Spring Boot 3,引用旧版 jar 就会出现这种问题。

解决方案有两条路径:

  • 给项目里的第三方依赖换支持 Spring Boot 3 的新版本。
  • 如果实在换不了,只能用一个额外的javax兼容包,但这是非常规操作,不推荐,后续会持续踩坑。

我自己升级过一个老项目,当时有个内部框架用的是javax.annotation.*,最后花了半天把框架升了一版才彻底解决。建议新项目从一开始就别碰这种老库。

5.4 Nacos 登录报错 / 修改密码失败

有些同学会遇到“修改密码报错 request error, please try again later!”的情况。这类问题的根源往往不是代码,而是 Nacos 服务端使用的数据库问题。Nacos 默认内嵌 Derby 数据库,如果你改了密码或配置后数据库状态不一致,就可能出现各种异常。

最简单的恢复方法:备份数据后,删掉 Nacos 目录下的data文件夹和logs文件夹,重启 Nacos。这样它会把数据重新初始化,默认用户名密码回到nacos/nacos。注意如果是生产环境,别乱删,最好先评估。

5.5 引入配置中心后启动变慢或一直重试

加上spring-cloud-starter-alibaba-nacos-config后,如果bootstrap.yml里的配置写错了,应用启动时会出现很长的等待或反复重试。比如 Data ID 不存在、namespace 填错、密码不对,客户端会默认尝试几次才能结束。

建议首次接配置中心不要写复杂逻辑,先在 Nacos 上创建一个最简单的配置,确认客户端能拉取到再逐步扩展。

5.6 IDEA 里常见的 Maven 导入和运行问题

  • 导入依赖后一片红:打开 Maven 面板点刷新,如果还红,检查settings.xml的镜像配置。
  • 社区版无法创建 Spring Boot 项目:新建 Maven 项目,自己补spring-boot-starter-parent和依赖坐标就行,效果一样。
  • 运行时报 “错误: 找不到或无法加载主类”:执行mvn clean install后重新运行。
  • 代码格式化失效:IDEA 的快捷键和系统输入法冲突时容易出现,打开Settings → Keymap重新绑定即可。

6. 项目后续的一些实践心得

整套搭完后,如果你准备把这个最小项目扩展成真正可用的微服务,我有几个建议:

  1. 不要把所有配置堆到application.yml里。把 Nacos 地址、用户名密码、数据源等按环境拆开。团队协作时,公共配置放 Nacos,本地配置放 bootstrap。
  2. 开启 Nacos 鉴权。特别是部署到外网环境,一定要改默认密码、配置鉴权开关,网上关于 Nacos 未授权访问的案例不少。别因为懒酿成安全事故。
  3. 统一使用服务名调用,不要硬编码 IP。硬编码 IP 会让注册中心失去意义,出问题以后定位还特别麻烦。
  4. 多环境用 namespace 隔离,不要所有环境共享一套配置。一旦有人不小心改了生产配置,小则抖动,大则事故。

我在实际使用的过程中发现,Nacos 相比于其他注册中心,最大的好处是配置中心和服务列表在同一个控制台里,不用维护两套系统。刚开始上手时最大的成本其实是版本兼容,只要你把 Spring Boot、Spring Cloud Alibaba、Nacos Server 三者版本对齐,后面就很顺。

还有一个操蛋但很常见的教训:千万别在生产环境用 Raft 之外的单机模式跑很久。单机模式适合开发,跑生产至少 3 节点起步。如果你现在还在单机裸奔,赶紧把集群部署提上日程。搭建完这套环境后,往后加新服务就是复制粘贴的体力活,祝你尽快把这套链路跑通。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询