☰
JDK17+Spring Boot 3+Nacos搭建微服务开发环境实战指南
2026/10/3 2:57:02 网站建设 项目流程

最近帮同事搭一套新的微服务开发环境,顺手把整个流程记录了下来:在 IntelliJ IDEA 里面,用 JDK17 跑 Spring Boot 3,再配合 Nacos 做服务注册和配置中心。整套环境从零到两个服务互相调用、配置动态刷新全部跑通,花了一天时间。中间踩了不少坑,有些问题百度上搜出来的答案已经过时了,专门整理成这篇图文教程,给准备从 Spring Boot 2.x 升级到 3.x、或者第一次接触 Nacos 的朋友做个参考。

下面的内容会覆盖环境准备、Nacos 安装与安全配置、Spring Boot 工程创建、注册中心接入、配置中心动态刷新,最后是一份宝贵的问题排查记录。跟着做不仅能跑通,还能理解每一步为什么要这么配,以后换个版本组合也知道怎么查问题。

1. 搭建前的环境准备与版本选型

1.1 JDK17 与 Spring Boot 版本怎么搭配

先说版本选型,这是很多人第一步就栽跟头的地方。JDK17 是 Java 17 LTS 版本,2021 年 9 月发布,现在很多公司的生产环境已经从 JDK8 切到 JDK17 了。Spring Boot 这边,如果你打算用 JDK17,最推荐的是Spring Boot 3.x,因为 Spring Boot 3.0 开始官方就把 JDK17 作为基础版本,整个框架是在 Jakarta EE 9 之上重构的(注意javax.*变成了jakarta.*)。

有人会问:Spring Boot 2.7 也支持 JDK17,能不能用?能用,但我不建议新项目这么干。Spring Boot 2.7 虽然能跑在 JDK17 上,但它骨子里还是为 JDK8 设计的,很多第三方库的兼容性问题会在后面的开发中慢慢冒出来。既然是新环境,直接上 Spring Boot 3 + JDK17 是最省心的。

Spring Cloud 和 Spring Cloud Alibaba 的版本也要对应好。我这次实测下来的稳定组合是:

组件版本
JDK17(Oracle JDK 或 Adoptium/Temurin 均可)
Spring Boot3.2.x
Spring Cloud2023.0.x
Spring Cloud Alibaba2023.0.1.x
Nacos Server2.3.x 稳定版
IDEA2023.2 及以上(社区版也可以)
Maven3.8.x 或 3.9.x

这个组合是经过实际验证的,Spring Cloud Alibaba 2023.0.1.x 对应 Spring Cloud 2023.0.x,底层内置的 nacos-client 版本是 2.3.x,跟 Nacos Server 2.3.x 配合最默契。如果你用了 Nacos Server 2.2.x 或者更老的 1.x,客户端接口会有差异,后面服务注册可能会报各种奇怪的错。

JDK17 下载安装本身不难,Windows 用户直接去 Adoptium 官网(或者 Oracle 官网)下载安装包,安装完成后设置JAVA_HOME环境变量为安装路径(比如C:\Program Files\Microsoft\jdk-17.x.x),然后把%JAVA_HOME%\bin加到Path里。这里有个小细节:Windows 上安装 Oracle JDK 有时候会自动把C:\Program Files\Common Files\Oracle\Java\javapath排在环境变量前面,导致终端里java -version显示的版本跟你装的 JDK17 不一样。出现这种情况,把 Path 里的javapath删掉,或者把你的%JAVA_HOME%\bin调整到最前面即可。

1.2 IDEA 与 Maven 的基础配置

IDEA 版本方面,社区版(Community Edition)完全够用。之前有些教程说社区版不能创建 Spring Boot 项目,那是老黄历了。IDEA 2023.1 之后的社区版已经内置了 Spring Initializr 支持,新建项目可以直接选 Spring Boot 版本生成工程。如果你用的版本比较旧,也可以到 start.spring.io 网站上生成项目压缩包再导入 IDEA,效果一样。

IDEA 里用 JDK17 有三个地方要检查,漏一个都会出问题:

  1. Project Structure 里的 Project SDK:File -> Project Structure -> Project -> SDK,选择 17。
  2. Project Structure 里的 Language Level:同样在 Project 菜单里,Language Level 选择 17。如果选低了,代码里用不了 JDK17 新语法。
  3. Settings 里的 Maven 配置:File -> Settings -> Build, Execution, Deployment -> Build Tools -> Maven,这里有个Runner -> JRE选项,也要选 17。

Maven 这边,建议先配置好阿里云镜像,不然 Spring Boot 3 的依赖下载会让你怀疑人生。在 Maven 安装目录conf/settings.xml里添加以下 mirror:

<mirror> <id>aliyunmaven</id> <mirrorOf>central</mirrorOf> <name>阿里云公共仓库</name> <url>https://maven.aliyun.com/repository/public</url> </mirror>

配置完镜像后,IDEA 的 Maven 设置里要把User settings file指向这个settings.xml,然后点Reload All Maven Projects让设置生效。这里容易踩的坑是:IDEA 默认会用内置的 Maven,而不是你下载的 Maven,所以你在命令里用的 Maven 和 IDE 里用的一致不一致要看清楚,建议用 IDEA 内置的 Maven 就行,只需要把settings.xml指对。

2. Nacos 安装、启动与安全配置

2.1 下载与单机启动

Nacos(Dynamic Naming and Configuration Service)是阿里巴巴开源的服务发现和配置管理平台,在 Java 微服务生态里用得很多。它的作用可以用一句话概括:让服务互相能找到对方,并且能让配置在不重启服务的情况下动态更新。

去 Nacos 官网 GitHub Releases 页面下载最新稳定版,我用的是 2.3.2。下载nacos-server-2.3.2.zip或者.tar.gz即可。Windows 用户解压后进入bin目录,注意 Nacos 默认是集群模式启动,单机开发必须加-m standalone参数:

startup.cmd -m standalone

Mac / Linux 用户用:

sh startup.sh -m standalone

启动成功后,浏览器访问http://localhost:8848/nacos,默认用户名和密码都是nacos/nacos。注意路径里的/nacos前缀,很多新手直接访问 8848 端口发现是白屏,就是因为少了这个上下文路径。

Nacos 默认会使用内嵌的 Derby 数据库存储配置信息,这个对开发来说够用,重启数据也不会丢太多。但如果你打算一直用下去,建议提前切换到 MySQL。在conf/application.properties里把数据源改成 MySQL,再执行conf/mysql-schema.sql初始化数据库表。我这次在开发环境就是用的 Derby,就不展开 MySQL 切换了,不过建议正式环境务必切 MySQL,不然后面配置多了、集群节点一多,Derby 的并发和一致性都会成问题。

2.2 开启鉴权并修改默认密码

Nacos 默认没有开启鉴权,这意味着任何能访问你 8848 端口的人,都能看到你所有服务的注册信息、改你的配置,这是很大的安全隐患。社区里常说的“Nacos namespaces 未授权访问漏洞”“Nacos 配置泄露”,绝大多数就是因为默认没开鉴权。

开启鉴权的方法:在conf/application.properties里添加以下配置:

nacos.core.auth.enabled=true nacos.core.auth.plugin.nacos.token.secret.key=VGhpc0lzTXlDdXN0b21TZWNyZXRLZXkwMDEyMzQ1Njc4OQ== nacos.core.auth.server.identity.key=serverIdentity nacos.core.auth.server.identity.value=exampleServerIdentity

token.secret.key这个配置容易踩坑:Nacos 2.x 要求这个值必须是 Base64 编码的字符串,且原文长度不低于 32 字节,否则启动时会报错或者鉴权不生效。上面的示例值是可以用,生产环境建议自己生成一个随机值,随便找个在线工具把一段 32 字符以上的随机字符串做 Base64 编码即可。

配置完成后重启 Nacos,再用浏览器登录,会发现登录接口多了鉴权检查。启用鉴权后,你的 Spring Boot 服务在连接 Nacos 时也需要带上用户名密码,这个在后面的客户端配置里会讲到。

另外,登录后第一件事就是把默认密码改掉。在 Nacos 控制台右上角“修改密码”里操作即可。社区里有个高频报错:“nacos 页面修改密码报错 request error, please try again later!”,这个我遇到过,大多是 Nacos 客户端版本和 Server 版本不一致导致的,或者是在鉴权开启之前就登录了老会话。遇到这个报错,先确认 Server 和 nacos-client 版本一致,再试试清除浏览器缓存、重新登录。

2.3 Docker Compose 方式部署 Nacos(可选)

如果你用的是 Mac 或者 Linux,本地装了 Docker,也可以直接用 Docker Compose 起一个 Nacos,干净又方便。这次我在一台 Ubuntu 环境测试时用的就是 Docker 方式,写个docker-compose.yml:

services: nacos: image: nacos/nacos-server:v2.3.2 container_name: nacos environment: - MODE=standalone - NACOS_AUTH_ENABLE=true - NACOS_AUTH_TOKEN=VGhpc0lzTXlDdXN0b21TZWNyZXRLZXkwMDEyMzQ1Njc4OQ== - NACOS_AUTH_IDENTITY_KEY=serverIdentity - NACOS_AUTH_IDENTITY_VALUE=exampleServerIdentity ports: - "8848:8848" - "9848:9848"

然后执行:

docker compose up -d

这里有个 Nacos 2.x 的端口说明:Nacos 2.x 客户端默认会使用9848端口做 gRPC 通信,如果只映射了 8848 没映射 9848,服务注册和发现都会失败。这个报错在日志里往往很模糊(比如 timeout 或者 connection reset),非常容易被忽略。建议在搭建环境前就把这个端口映射加上。

启动完成后一样的地址登录控制台。Docker 方式的好处是以后不想用了docker compose down就清理干净了,不会像本机解压部署那样留一堆残留进程。

3. 创建 Spring Boot 工程并接入 Nacos

3.1 Spring Boot 工程的创建

打开 IDEA,File -> New -> Project,选择Spring Initializr。这里注意:

  • Name 填user-service(后面做服务提供方)。
  • Type 选 Maven。
  • Language 选 Java。
  • Java 版本选 17。

依赖这里只需要加一个Spring Web,剩下的 Nacos 相关依赖我们后面手动加,因为 Spring Initializr 里的 Alibaba 依赖列表不一定跟你的 Spring Boot 版本匹配,手动加更可控。

创建完工程后,确认pom.xml里 Spring Boot 版本是不是 3.2.x。然后手动添加以下依赖:

<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>3.2.5</version> </parent> <dependencies> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> <version>2023.0.1.0</version> </dependency> </dependencies>

注意:Spring Boot 3 和 Spring Cloud 的依赖管理不用再像 Spring Boot 2 那样引入spring-cloud-dependencies的import类型依赖了?不对,其实还是需要的。Spring Boot 3 的 parent 里并不会帮你管理 Spring Cloud 的版本,所以要再加两个 dependencyManagement:

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

这样依赖版本就由 BOM 统一管住了,你的业务依赖里不用写版本号。如果你不想手动管理版本,直接复制这段就行。

3.2 引入 Nacos 注册中心配置

创建一个 Spring Boot 服务接入 Nacos,核心配置在application.yml里。我这次用的配置如下:

server: port: 8080 spring: application: name: user-service cloud: nacos: discovery: server-addr: 127.0.0.1:8848 username: nacos password: nacos namespace: public config: server-addr: 127.0.0.1:8848 username: nacos password: nacos file-extension: yml

关键点展开讲:

  1. spring.application.name必须设置。Nacos 控制台里显示的服务名,就是从这里取的。如果没有这个配置,注册到 Nacos 的服务会显示为unknown。
  2. username和password:如果你按前面教程开启了鉴权,这里必须带上账号密码,否则服务启动时会报 403 或者无法注册。
  3. namespace:有两个选择,public(默认命名空间)或者具体命名空间 ID。如果你没特意创建命名空间,用public就行。如果填了不存在的命名空间 ID,服务注册界面可能什么都看不到。
  4. Nacos 地址的配置有两个位置,一个是discovery(注册中心),一个是config(配置中心),两者可以指向同一个 Nacos Server,也可以分开。

这里提醒一个容易踩的坑:Spring Boot 3 里,Nacos config 相关功能只依赖spring-cloud-starter-alibaba-nacos-config,而注册中心依赖是spring-cloud-starter-alibaba-nacos-discovery。如果你没有引入 config 依赖,spring.cloud.nacos.config配置会被忽略(不会报错,但不会生效)。我在第一次测试的时候只引入了 discovery,结果动态刷新一直不生效,排查了半天。

3.3 注册中心接入验证

加入依赖和配置后,启动user-service。启动成功后再写一个最简单的接口用于验证:

@RestController public class UserController { @GetMapping("/user/hello") public String hello() { return "Hello from user-service"; } }

启动完成后,打开 Nacos 控制台http://localhost:8848/nacos,进入“服务管理 -> 服务列表”,如果能看到user-service的实例,并且状态为“健康”,说明注册中心已经打通了。

如果服务列表里没有东西,优先看日志。Nacos 客户端启动时会输出类似这样一行日志:

Nacos registry, DEFAULT_GROUP user-service 127.0.0.1:8080 register finished

如果看到这一行,说明客户端已经注册成功了,控制台没显示通常是命名空间选错了,检查一下控制台左上角选的是不是public。如果没有这行日志,就要看前面有没有异常,常见的是 9848 端口不通、鉴权失败(403)、或者 Nacos 版本不兼容。

4. 配置中心接入与动态刷新

4.1 Nacos 配置中心的数据组织方式

Nacos 作为配置中心,数据是分层的:命名空间(Namespace) -> 分组(Group) -> 配置(Data ID)。这个概念理解了,后面配置管理就顺了。

  • Namespace:用来做环境隔离,比如开发、测试、生产各一个命名空间,相互之间配置不干扰。默认是public。
  • Group:默认是DEFAULT_GROUP。可以在同一个命名空间下按业务域拆分组。
  • Data ID:具体某份配置。默认的格式是${spring.application.name}.${file-extension}。比如user-service.yml。

对于单个服务,最常用的是直接在 Nacos 里创建一条 Data ID 为user-service.yml的配置,这个 Data ID 会被 Spring Boot 服务自动加载。这是 Nacos 约定优于配置的体现,因为spring.application.name加上文件后缀正好组成默认的 Data ID,不需要额外指定。

4.2 动态刷新配置实战

在user-service的pom.xml里加配置中心依赖:

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

注意:Spring Boot 3 默认不会主动加载bootstrap.yml文件,需要额外的 bootstrap 依赖。简单点说,我们在配置中心加载配置用得最多的方式是spring.config.import,即在application.yml里加一行:

spring: config: import: optional:nacos:user-service.yml

它的意思是:应用启动时把 Nacos 里 Data ID 为user-service.yml的配置导入进来。optional:前缀表示哪怕 Nacos 连不上,应用也能启动,不会因为配置中心暂时不可用就直接挂掉。

然后咱们在 Nacos 控制台新增一条配置:

  • Data ID:user-service.yml
  • Group:DEFAULT_GROUP
  • 配置格式:YAML

配置内容加一条测试配置:

user: nickname: zhangsan age: 25

在代码里写一个验证用的 Controller:

@RestController @RefreshScope public class ConfigController { @Value("${user.nickname:default}") private String nickname; @Value("${user.age:0}") private int age; @GetMapping("/config") public String config() { return "nickname=" + nickname + ", age=" + age; } }

关键点是@RefreshScope,不加这个注解的话,配置虽然能从 Nacos 拉下来,但修改后不会自动刷新到 Bean 里。加上之后,当你修改 Nacos 里的配置并发布,Spring Cloud 会通过事件机制刷新这个 Bean,再次请求/config接口就能拿到新值了。

这里有个容易犯的错:@ConfigurationProperties和@Value的刷新机制不一样。@Value配合@RefreshScope可以刷新,@ConfigurationProperties如果类本身没有被@RefreshScope标注,即使被注入到其他 Bean 里,刷新也不会生效。建议在项目里优先用@ConfigurationProperties,把一组配置封装成类,然后在类上加上@RefreshScope,代码更整洁:

@Component @ConfigurationProperties(prefix = "user") @RefreshScope public class UserProperties { private String nickname; private int age; // getter and setter 省略 }

启动user-service,访问/config,如果返回nickname=zhangsan, age=25,说明配置中心加载成功。然后回 Nacos 控制台把nickname改成lisi,点发布,再刷新请求,几秒内就能看到新值。

我实测时大概有 3-5 秒的延迟(因为客户端默认配置了长轮询),如果你的要求是秒级甚至毫秒级,可以调小spring.cloud.nacos.config.timeout之类参数,但是没必要,开发环境默认就很好用。

5. 服务发现与调用实战

5.1 再创建一个消费者服务

光有服务注册、没有服务调用,等于只搭了一半。咱们再来一个order-service,让它通过 Nacos 发现user-service并调用接口。

创建方式和前面一样:Spring Initializr 新建项目,order-service,端口设成 8081。pom.xml里引入跟前面一样的 discovery 依赖。

代码里关键的配置是消费端的服务发现和负载均衡。Spring Cloud 2023.0.x 默认使用的是 LoadBalancer 组件,不用再单独引入 Ribbon(Ribbon 已经进入维护状态了)。咱们在启动类里声明一个带负载均衡的RestTemplate:

@SpringBootApplication public class OrderServiceApplication { public static void main(String[] args) { SpringApplication.run(OrderServiceApplication.class, args); } @Bean @LoadBalanced public RestTemplate restTemplate() { return new RestTemplate(); } }

@LoadBalanced是点睛之笔。它会让 RestTemplate 发请求时自动把“服务名”解析成真实的 IP:Port,然后从 Nacos 拿到user-service的实例列表做负载均衡。如果忘了加这个注解,直接写http://user-service/user/hello,运行时会报“UnknownHostException”。

写一个测试接口:

@RestController public class OrderController { @Resource private RestTemplate restTemplate; @GetMapping("/order/call") public String call() { String url = "http://user-service/user/hello"; return restTemplate.getForObject(url, String.class); } }

启动order-service,访问http://localhost:8081/order/call,返回Hello from user-service就说明服务发现和调用全部打通了。

5.2 验证负载均衡与自我保护

为了直观看到负载均衡,可以同时启动两个user-service实例,一个 8080 端口,一个 8082 端口(启动时用--server.port=8082参数覆盖)。两个实例都注册到 Nacos 后,控制台的服务列表里user-service会显示两个实例。

连续访问/order/call多次,你会看到请求在两个实例之间轮询分发,日志里两个服务各自收到部分请求。这个负载均衡能力是客户端侧做的,不需要额外的网关或者代理,生产环境做多实例部署时这一点很关键。

再提一个 Nacos 的自我保护机制:当某个服务实例心跳消失(比如被强杀),默认会保留 15 秒左右才把它从健康实例列表移除。所以如果你测出“服务明明停了,但接口还能调通”的现象,别慌,等十几秒再试。这个时间可以在服务端的配置里调整,但开发环境用默认值就够了。

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

6.1 版本不匹配类问题

这一部分是全流程里踩坑最多的地方,也是社区里问得最多的。我做了一个速查表,基本覆盖了常见报错:

报错现象原因解决办法
启动报NoSuchMethodError或者ClassNotFoundException一般是 nacos-client 版本和 Spring Cloud Alibaba 版本不匹配用 BOM 统一管理版本,别手动指定不兼容的 nacos-client
服务注册到 Nacos 控制台看不到命名空间不对 / 8848 与 9848 端口未都通检查控制台命名空间、确认 9848 端口已映射
连接 Nacos 报 403 / Access denied服务端开了鉴权,客户端没配账号密码在application.yml的 discovery/config 里配置username和password
@RefreshScope注解加了还是不刷新配置中心依赖没引入 / Data ID 不对 / 没走 spring.config.import检查spring-cloud-starter-alibaba-nacos-config依赖,确认import的 Data ID
启动时说找不到nacos config配置Spring Boot 3 没识别 bootstrap.yml用spring.config.import或者在打包时引入 bootstrap 相关依赖

这里特别强调一个容易混淆的地方:Nacos 服务端版本、nacos-client 客户端版本、Spring Cloud Alibaba 版本,这三者是三个独立的东西。网上很多教程直接给一个 nacos-client 的坐标让你引入,但 Spring Cloud Alibaba 自己内置了客户端版本,你手动覆盖它极容易引发接口不兼容。尽量别手动引入 nacos-client,让 Spring Cloud Alibaba BOM 来管理。

6.2 连接与启动类问题

9848 端口不通是最隐蔽的问题。Nacos 2.x 从客户端到服务端有一半通信走 gRPC,端口是 8848+1000=9848。本机测试通常没问题,但如果你以后把服务部署到远程服务器,防火墙只开了 8848,服务注册就会时好时坏,日志里出现:

Failed to request to server: /127.0.0.1:8848, code: 501, message: Not Implemented

看到501 Not Implemented大概率就是这个原因。解决办法就是安全组或者防火墙同时放行 8848 和 9848。

启动顺序问题:Nacos Server 最好先启动,再启动 Spring Boot 服务。虽然客户端配置了optional:后连不上 Nacos 也能启动,但服务注册时机错过之后要等心跳重连,往往过了 30 秒到 1 分钟才在控制台出现,容易让人误以为配置有问题。

IDEA 社区版创建 Spring Boot 工程的问题:社区版确实能用,但如果你用的版本较早(2022.x 之前),创建项目时没有 Spring Initializr 选项,可以去 start.spring.io 生成项目,然后 File -> Open 导入即可。公司如果有安全要求不能访问外网,也可以用镜像站点,比如阿里云的https://start.aliyun.com,生成的工程结构和官方的一致,但注意这个站点的 Spring Boot 版本列表偏老,可能没有 3.2.x,生成后手动改 parent 版本即可。

6.3 配置与安全类问题

关于 Nacos 页面那个“修改密码报错 request error, please try again later!”,我这次也碰到一次。原因是 Nacos Server 是 2.2.0,而浏览器缓存的登录 Token 是开启鉴权之前的旧 Token,导致请求鉴权不过。解决办法很简单:清掉浏览器缓存,重新登录,再修改密码。

如果你在生产环境用 Nacos,强烈建议把以下几件事做了:

  1. 开启鉴权,修改默认密码。
  2. 配置访问白名单,限制 8848 端口的来源 IP。
  3. 定期备份 Nacos 的数据库(如果用 MySQL 的话)。
  4. 重要配置拆成多个 Data ID,避免超大配置块。

另外,很多人问 Nacos 的替代方案。如果是中小项目,不想引入额外组件,直接用 Spring Cloud Config + Git 也可以,但 Nacos 胜在“注册中心 + 配置中心”二合一,控制台界面也直观,运维成本低。如果是 K8s 环境,还可以考虑使用 K8s 原生的 ConfigMap + 服务发现,不过那套体系跟 Spring Cloud 生态融合程度不如 Nacos。

最后再分享一个小技巧:Nacos 控制台左侧菜单里有一个“监听查询”,可以看当前配置被哪些服务订阅了。当你在纠结“配置到底有没有被加载”的时候,去监听查询里搜 Data ID,如果能看到对应的客户端 IP,说明配置已经分发下去了,问题一定出在应用侧的刷新逻辑上,而不是配置通道。这个功能知道的人不多,排查问题却非常实用,建议先记下来。

这套环境搭完之后,后面还可以继续扩展:加一个 Spring Cloud Gateway 做统一入口,或者把配置中心的配置按环境拆分到不同命名空间,再或者接一套 Nacos 集群保证高可用。不过对于刚上手的人来说,先把注册中心和配置中心这两个核心能力玩熟,比什么都重要。

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

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

立即咨询