Spring Boot HelloWorld 项目搭建与踩坑记录(从零到浏览器可访问)
参考教程:W3Cschool – Spring Boot HelloWorld 详解
本文不仅复现了教程里的 HelloWorld Demo,还记录了我在本地跑起来时遇到的两个典型问题:端口被占用 和 首跑依赖下载卡住,适合刚入门 Spring Boot 的同学排雷。
一、项目初始化(现代化版)
原教程使用的版本是 Spring Boot 1.3.3 + Java 8,已经比较陈旧。为了能直接在现在的开发环境里跑起来,我把版本升级到了:
- Spring Boot 3.3.4
- Java 17
- 构建工具:Maven
- 测试框架:JUnit 5
核心逻辑不变:访问 http://localhost:端口/ 返回字符串 Hello,World!。
项目结构
springboot-helloworld/
├── pom.xml
└── src/
├── main/
│ ├── java/com/example/helloworld/
│ │ ├── Application.java # 启动类
│ │ └── HelloWorldController.java # 控制器
│ └── resources/
│ └── application.properties # 配置(端口等)
└── test/
└── java/com/example/helloworld/
└── HelloWorldControllerTest.java # 单元测试
1. pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<!– Spring Boot 启动父依赖 –>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.4</version>
<relativePath/>
</parent>
<groupId>com.example</groupId>
<artifactId>springboot-helloworld</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springboot-helloworld</name>
<description>Spring Boot HelloWorld Demo</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<!– Web 依赖(内嵌 Tomcat) –>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!– 测试依赖(含 JUnit 5) –>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
2. 启动类 Application.java
package com.example.helloworld;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
3. 控制器 HelloWorldController.java
package com.example.helloworld;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloWorldController {
@RequestMapping("/")
public String sayHello() {
return "Hello,World!";
}
}
4. 单元测试 HelloWorldControllerTest.java
package com.example.helloworld;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class HelloWorldControllerTest {
@Test
public void testSayHello() {
assertEquals("Hello,World!", new HelloWorldController().sayHello());
}
}
5. 配置文件 application.properties
# 服务端口(默认 8080,这里显式声明)
server.port=8080
二、第一个坑:8080 端口被占用,页面返回奇怪的 JSON
现象
按教程 mvn spring-boot:run 之后,打开 http://localhost:8080/,页面没有显示预期的 Hello,World!,而是返回了一段 JSON:
{ "code": 200, "msg": null, "content": "ok" }
原因
8080 是很多 Web 服务/网关/代理的默认端口。我的机器上 8080 已经被别的服务占用了,所以浏览器请求根本没打到我们刚创建的 Spring Boot 应用,而是命中了那个已存在的服务,于是返回了它自己的响应。
也就是说:你的 Spring Boot 应用要么没启动起来(端口冲突报错),要么启动到了别的端口。
排查方法
# Windows 查看 8080 被谁占用
netstat -ano | findstr :8080
同时观察 mvn spring-boot:run 的控制台日志:
- 有没有 Started Application in X seconds?
- 有没有 Port 8080 was already in use?
- 成功启动时端口是不是变成了 8081 / 8082?
三、如何修改 Spring Boot 端口(4 种方式)
按优先级从高到低:
方式一:改配置文件(最常用)
src/main/resources/application.properties:
server.port=8090
或 application.yml:
server:
port: 8090
方式二:命令行参数(临时,不改文件)
mvn spring-boot:run -Dspring-boot.run.arguments=–server.port=8090
或打成 jar 后:
java -jar target/springboot-helloworld-0.0.1-SNAPSHOT.jar –server.port=8090
方式三:环境变量
# Windows PowerShell
$env:SERVER_PORT=8090
方式四:代码写死(不推荐)
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication app = new SpringApplication(Application.class);
app.setDefaultProperties(Map.of("server.port", "8090"));
app.run(args);
}
}
优先级:命令行参数 > 环境变量 > 配置文件 > 代码默认值(8080)
我们把项目改成了 server.port=8090,重新 mvn spring-boot:run 后访问 http://localhost:8090/ 即可。
四、第二个坑:首次启动一直停在下载依赖,访问 8090 也打不开
现象
改完端口再次启动,终端一直在刷:
Downloaded from aliyun-public: …/netty-bom-4.1.113.Final.pom
Downloaded from yueyun-releases: …/okhttp-bom-4.12.0.pom
…
[INFO] Scanning for projects…
这时去浏览器访问 http://localhost:8090/,依旧打不开(ERR_CONNECTION_REFUSED)。
原因
这是正常情况! 因为这是第一次运行这个项目,本地 Maven 仓库是空的,需要把 Spring Boot 框架及其所有依赖(Tomcat、Spring MVC、Jackson、Netty、OkHttp 等一大堆 jar)全部从镜像源下载下来。在下载 + 编译阶段,Tomcat 还没有启动,自然连不上。
解决:耐心等
首次启动通常需要 几分钟(取决于网速)。直到终端出现下面这些日志,才算真正启动成功:
. ____ _ __ _ _
/\\\\ / ___'_ __ _ _(_)_ __ __ _ \\ \\ \\ \\
( ( )\\___ | '_ | '_| | '_ \\/ _` | \\ \\ \\ \\
\\\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v3.3.4)
…(省略若干行)…
Started Application in X.xxx seconds
Tomcat started on port(s): 8090 (http)
看到 Started Application 和 Tomcat started on port(s): 8090 这两行后,再去刷新浏览器就能看到 Hello,World! 了。
五、第三个坑:Java 版本不匹配 —— 类文件版本 61.0,应为 52.0(最关键!)
现象
依赖下载完、端口也改好了,但 mvn spring-boot:run 编译时报错:
[ERROR] Application.java:[3,32] 无法访问 org.springframework.boot.SpringApplication
错误的类文件: …/spring-boot-3.3.4.jar
类文件具有错误的版本 61.0, 应为 52.0
Maven 构建失败:Compilation failure → 1 error
原因
| 61.0(jar 包的版本) | Java 17(Spring Boot 3.x 用这个编译的) |
| 52.0(你机器的版本) | Java 8 |
Spring Boot 从 3.0 起要求最低 JDK 17,不再支持 Java 8。所以它发布的所有 jar 包都是 Java 17 编译的。如果你的 Maven 编译器还在用 Java 8,就会直接报这个错。
⚠️ 即使 java -version 和 mvn -version 都显示 17,如果 PATH 里残留了旧 JDK 的绝对路径,Maven 编译插件可能仍会调用旧的 javac。
解决步骤
步骤 1:安装 JDK 17+
去 Adoptium (Temurin) 下载 Windows x64 的 .msi,双击安装即可。
步骤 2:设置环境变量(PowerShell 管理员)
$jdk17 = "C:\\Program Files\\Eclipse Adoptium\\jdk-17.0.19.10-hotspot"
[System.Environment]::SetEnvironmentVariable("JAVA_HOME", $jdk17, "Machine")
$oldPath = [System.Environment]::GetEnvironmentVariable("Path", "Machine")
$newPath = "%JAVA_HOME%\\bin;" + $oldPath
[System.Environment]::SetEnvironmentVariable("Path", $newPath, "Machine")
执行后必须重新开终端窗口再验证:
echo $env:JAVA_HOME # 应输出 JDK 17 目录
java -version # 应显示 17.x
mvn -version # 应显示 17.x
步骤 3:在 pom.xml 中锁死编译器(关键!)
即使环境变量设对了,最保险的做法还是在 pom.xml 中强制指定:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>17</source>
<target>17</target>
<fork>true</fork>
<executable>${JAVA_HOME}/bin/javac</executable>
</configuration>
</plugin>
| <source>17</source> | 源代码兼容 Java 17 |
| <target>17</target> | 编译产物目标为 Java 17 字节码 |
| <fork>true</fork> | 编译在独立进程中运行 |
| <executable>${JAVA_HOME}/bin/javac</executable> | 直接用 JAVA_HOME 下的 javac,绕过 PATH 中的旧 JDK |
步骤 4:清缓存 + 重跑
# 删掉上次失败留下的 .lastUpdated 标记
Get-ChildItem –Path "E:\\soft\\maven-repository" –Recurse –Filter "*.lastUpdated" | Remove-Item –Force
# 清理项目构建产物 + 强制重下载 + 启动
cd E:\\JAVA\\spring
mvn clean spring-boot:run –P !midea-internal –U
启动成功标志
终端出现:
Started Application in X.xxx seconds
Tomcat started on port(s): 8090 (http)
浏览器访问 http://localhost:8090/ 显示 Hello,World! ✅
六、最终效果
浏览器访问 http://localhost:8090/:
Hello,World!
命令行测试:
curl http://localhost:8090/
# 输出:Hello,World!
总结
| 1 | 端口被占用 | 返回他人服务的 JSON | 8080 已被占用 | 改用 8090 |
| 2 | 首跑卡住 | 一直 Downloading | 首次下载全部依赖 | 耐心等 Started Application |
| 3 | Java 版本不匹配 | class file version 61.0 / 52.0 | JDK 是 8,但 Spring Boot 3.x 要 17 | 装 JDK 17 + 设 JAVA_HOME + pom.xml 锁编译器 |
一句话避坑指南:




