1. 项目概述从代码到服务的最后一公里做SpringBoot开发的朋友肯定都经历过本地调试一切顺利但一到部署上线就状况百出的阶段。这感觉就像精心组装了一辆赛车在自家后院跑得飞快但真要上赛道了却发现连怎么把它运过去都是个问题。今天要聊的就是这“最后一公里”——如何把一个SpringBoot项目通过Maven打包成Jar包并让它稳定地在Windows和Linux两个主流服务器平台上跑起来。这个过程看似基础却是项目从开发环境走向生产环境的必经之路也是区分“会写代码”和“能交付服务”的关键一步。很多新手甚至一些有经验的开发者都可能在这里踩坑为什么本地能跑服务器上就报错为什么用java -jar启动后关掉终端服务就停了Linux上怎么安装合适版本的Java这些问题不解决再好的代码也只能躺在你的电脑里。接下来我会结合自己多次部署的经验把从打包、环境准备到运行、排错的完整链条拆开揉碎了讲清楚目标是让你看完就能动手一次部署成功。2. 核心思路与工具选型为什么是Jar包在开始动手之前我们先要搞清楚几个核心选择背后的逻辑。这能帮你理解每一步操作的意义而不是机械地复制命令。2.1 打包格式之争Jar vs War vs 容器镜像SpringBoot项目主要有三种部署形态传统的WAR包、可执行JAR包和Docker容器镜像。我们选择可执行JAR包是基于以下几个现实的考量内置容器的便利性SpringBoot最大的特点之一就是内置了Tomcat、Jetty或Undertow等Servlet容器。打成的可执行JAR包即fat jar或uber jar包含了应用本身、依赖库以及内嵌的Web容器。这意味着你不需要在目标服务器上预先安装和配置一个独立的Tomcat。部署变得极其简单有Java环境就能运行。这对于需要快速部署、环境隔离要求不是极端苛刻的场景是效率最高的选择。环境一致性WAR包部署到外部Tomcat时其行为会受到外部Tomcat版本、配置的极大影响。而可执行JAR包将运行时环境Web容器也打包了进去只要Java版本匹配它在任何地方的行为都几乎一致减少了“在我这儿是好的”这类问题。简化运维启动命令统一为java -jar yourapp.jar停止服务也只需找到进程ID进行kill。相比于管理Tomcat的bin/startup.sh、webapps目录、server.xml配置运维复杂度直线下降。配合后面会讲的nohup或系统服务如systemd可以轻松实现后台运行和开机自启。与云原生的过渡虽然DockerK8S是更现代的部署方式但可执行JAR是迈向容器化的一个完美中间态。你可以先熟练使用JAR包部署理解应用运行的所有依赖然后再将整个JAR包和其运行命令封装进Dockerfile平滑过渡到容器化部署。注意对于超大型、需要高度模块化部署或者必须与旧有企业级应用服务器如WebLogic、WebSphere集成的项目WAR包部署仍是必要选项。但绝大多数微服务和中小型项目可执行JAR是首选。2.2 构建工具的选择Maven的核心角色Maven在这里不只是一个“打包工具”它更是一个项目生命周期和依赖管理工具。它的核心价值在于依赖管理通过pom.xml声明所有第三方库Maven会自动从中央仓库或你配置的私服下载并处理传递性依赖确保打包时所有必需的jar文件都被收集。标准化构建流程mvn clean package这个命令背后Maven执行了清理、编译、运行测试、打包等一系列标准化的阶段phase保证了构建结果的可重复性。插件生态SpringBoot专门提供了spring-boot-maven-plugin。这个插件是生成可执行JAR的关键。它负责将应用代码、所有依赖库、资源文件等打包进一个JAR。在JAR的META-INF/MANIFEST.MF文件中设置Main-Class为org.springframework.boot.loader.JarLauncher。这个特殊的启动器负责以正确的方式加载内嵌的依赖JAR包这是SpringBoot JAR能独立运行的核心魔法。提供repackage目标确保最终生成的是可执行JAR而不是普通的库JAR。所以我们的部署流水线可以清晰地概括为编写代码 - Maven管理依赖并驱动构建 -spring-boot-maven-plugin生成可执行JAR - 上传至目标服务器 - 配置Java环境并运行。3. 实操全流程从打包到运行理论清晰了我们进入实战环节。我会按照一个标准的操作顺序来讲解并穿插每个步骤的注意事项。3.1 阶段一本地开发环境准备与打包在按打包按钮之前请先做好以下检查这能避免80%的部署失败。3.1.1 确认项目配置打开你的pom.xml文件确保以下几点打包类型packagingjar/packaging。SpringBoot默认就是jar。父项目或依赖通常通过继承spring-boot-starter-parent或引入spring-boot-dependencies来管理版本。parent groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-parent/artifactId version3.1.5/version !-- 请使用稳定版本 -- relativePath/ /parent关键插件必须有spring-boot-maven-plugin。build plugins plugin groupIdorg.springframework.boot/groupId artifactIdspring-boot-maven-plugin/artifactId /plugin /plugins /build应用入口确保你的主类带有SpringBootApplication注解的类位置正确通常Maven和插件能自动找到。如果不放心可以在插件中显式指定configuration mainClasscom.yourcompany.yourapp.Application/mainClass /configuration3.1.2 执行Maven打包命令打开终端CMD或PowerShell或直接在IDE如IntelliJ IDEA的Maven工具窗口中操作。核心命令mvn clean package -DskipTestsclean清理之前构建的target目录确保全新构建。package执行编译、测试、打包的生命周期阶段。-DskipTests跳过单元测试。在确保本地测试通过后生产打包时可以跳过以加快速度。但切记完整的CI/CD流程中不应该跳过测试。执行结果 命令成功后在项目的target目录下你会找到两个主要的JAR文件your-app-name-0.0.1-SNAPSHOT.jar这是普通的库JAR不包含依赖不能直接运行。your-app-name-0.0.1-SNAPSHOT.jar.original这是spring-boot-maven-plugin重新打包前Maven生成的原始JAR。我们要用的是同目录下最大的那个JAR文件它通常有几十MB甚至上百MB因为包含了所有依赖。这个才是可执行的fat jar。实操心得如果打包失败首先看错误信息。常见问题有依赖下载失败网络或仓库配置、编译错误、插件版本冲突。可以尝试先执行mvn clean compile看编译能否通过。在IDEA中你可以右键点击pom.xml-Maven-Reload project来刷新依赖有时能解决一些诡异的依赖问题。3.2 阶段二目标服务器环境准备打包好的JAR是“货物”服务器环境就是“赛道”和“燃料”。燃料就是Java运行时环境JRE或开发工具包JDK。3.2.1 Windows服务器安装JavaWindows环境相对简单主要是选择安装包和配置环境变量。下载JDK访问Oracle官网或Adoptium等开源发行版网站下载Windows平台的JDK安装程序如.msi格式。建议选择LTS长期支持版本如JDK 17或JDK 21以获得更稳定的支持和安全更新。安装运行安装程序记住安装路径例如C:\Program Files\Java\jdk-17。配置环境变量这是关键右键“此电脑” - “属性” - “高级系统设置” - “环境变量”。在“系统变量”部分新建变量JAVA_HOME值为你的JDK安装路径如C:\Program Files\Java\jdk-17。编辑“系统变量”中的Path新建一条记录值为%JAVA_HOME%\bin。验证打开新的命令提示符CMD输入java -version和javac -version。如果能正确显示版本信息说明配置成功。注意很多Windows服务器管理面板如宝塔也提供了一键安装Java环境的功能可视化管理更为方便。但理解手动配置的原理有助于排错。3.2.2 Linux服务器安装JavaLinux服务器是SpringBoot应用更常见的生产环境。安装方式多样推荐使用包管理器或直接下载归档文件。方法一使用包管理器安装推荐便于管理对于CentOS/RHEL/AlmaLinux/Rocky Linux系列# 1. 搜索可用的JDK包 (以OpenJDK 17为例) yum search openjdk-17 # CentOS 7/RHEL 7 # 或 dnf search openjdk-17 # CentOS 8/RHEL 8 # 2. 安装JDK (包含JRE) sudo yum install java-17-openjdk-devel # 安装开发包包含javac等 # 或 sudo yum install java-17-openjdk # 仅安装运行时环境 # 3. 验证安装 java -version对于Ubuntu/Debian系列# 1. 更新包索引 sudo apt update # 2. 安装JDK sudo apt install openjdk-17-jdk # 3. 验证安装 java -version方法二手动下载安装适用于需要特定版本或离线环境从官网下载Linux版的.tar.gz归档文件如jdk-17_linux-x64_bin.tar.gz。通过FTP/SFTP工具如WinSCP、FileZilla或scp命令将文件上传到服务器例如传到/opt目录。在服务器上执行解压和配置# 切换到安装目录 cd /opt # 解压 sudo tar -xzf jdk-17_linux-x64_bin.tar.gz # 创建软链接可选便于版本管理 sudo ln -s /opt/jdk-17 /opt/java # 配置环境变量编辑 /etc/profile 文件 sudo vim /etc/profile在/etc/profile文件末尾添加export JAVA_HOME/opt/jdk-17 # 或 /opt/java 如果你创建了软链接 export PATH$JAVA_HOME/bin:$PATH使配置生效source /etc/profile # 验证 java -version实操心得版本对齐务必确保服务器上的Java主版本号如17与本地开发、编译用的版本一致。虽然高版本Java通常可以运行低版本编译的代码但为了绝对稳定建议保持一致。选择JRE还是JDK如果服务器只运行应用安装JRE即可更轻量。如果可能需要调试、编译或使用jps、jstack等工具则安装JDK。yum/apt安装的Java其安装路径可能比较分散如/usr/lib/jvm/JAVA_HOME需要指向具体的版本目录。可以通过which java和ls -l命令追踪到实际路径。3.3 阶段三部署与运行JAR包环境就绪JAR包在手现在让它跑起来。3.3.1 上传JAR包到服务器Windows可以直接复制到服务器某个目录如D:\app。如果通过远程桌面直接拖拽即可。Linux使用scp命令或SFTP工具。# 从本地机器上传到服务器 scp target/your-app.jar useryour-server-ip:/home/user/app/建议在服务器上创建一个专门的目录来管理应用例如/opt/app或/home/username/app并设置好适当的权限。3.3.2 运行JAR包基础运行命令 无论是在Windows的CMD/PowerShell还是Linux的终端基础命令都是java -jar your-app.jar这条命令会在前台运行应用控制台会打印SpringBoot的启动日志。一旦关闭终端窗口或按下CtrlC应用就会停止。这仅适用于测试。后台运行与日志管理Linux重点在生产环境我们需要让应用在后台运行并且将日志输出到文件。使用nohup和(最常用)nohup java -jar your-app.jar app.log 21 nohup让命令忽略挂断信号SIGHUP即使终端关闭进程也不会退出。 app.log将标准输出重定向到app.log文件。21将标准错误也重定向到标准输出即所有日志都写到app.log。让命令在后台运行。命令执行后会返回一个进程IDPID记下它或用ps命令查找用于后续管理。使用systemd管理服务现代Linux发行版推荐 这是更专业、更强大的方式可以实现开机自启、自动重启、集中日志管理journalctl等。创建一个服务单元文件sudo vim /etc/systemd/system/your-app.service写入以下配置根据实际情况修改[Unit] DescriptionYour SpringBoot Application Afternetwork.target [Service] Typesimple Userappuser # 建议使用非root用户运行 WorkingDirectory/opt/app ExecStart/usr/bin/java -jar /opt/app/your-app.jar Restarton-failure RestartSec10 [Install] WantedBymulti-user.target启用并启动服务sudo systemctl daemon-reload sudo systemctl enable your-app.service sudo systemctl start your-app.service # 查看状态和日志 sudo systemctl status your-app.service sudo journalctl -u your-app.service -fWindows后台运行 在Windows上除了直接双击不推荐可以编写一个批处理文件.bat内容为start javaw -jar your-app.jar。javaw是无控制台窗口的Java启动器。使用nssmNon-Sucking Service Manager这类工具将JAR包安装为Windows服务实现后台运行和开机启动。3.3.3 传递运行参数SpringBoot支持通过命令行参数覆盖application.properties中的配置这在部署时非常有用。java -jar your-app.jar --server.port8081 --spring.profiles.activeprod--server.port8081指定应用启动在8081端口。--spring.profiles.activeprod激活名为prod的配置文件如application-prod.properties用于加载生产环境专用配置数据库地址、日志级别等。4. 部署过程中的典型问题与排查实录即使步骤清晰实际部署时也难免遇到问题。下面是我总结的几个高频问题及排查思路。4.1 问题一java -jar启动时报ClassNotFoundException或NoClassDefFoundError现象应用启动失败控制台抛出异常提示找不到某个类这个类通常是项目自身的类或某个依赖库的类。排查思路检查打包是否完整首先确认你运行的是target目录下那个最大的fat jar而不是.original文件。可以用解压工具如7-Zip打开JAR包查看BOOT-INF/classes目录下是否有你的项目编译后的类文件BOOT-INF/lib目录下是否有所有的依赖JAR。检查依赖冲突使用mvn dependency:tree命令查看依赖树检查是否有多个不同版本的相同依赖。SpringBoot内置的依赖管理通常能解决大部分问题但如果你引入了第三方库可能会引发冲突。解决方法是使用exclusions标签排除冲突的传递性依赖。检查本地仓库有时Maven本地仓库~/.m2/repository的依赖包可能损坏。尝试删除整个本地仓库或对应出错的依赖目录然后重新执行mvn clean package让Maven重新下载。4.2 问题二端口被占用 (Port xxxx was already in use)现象应用启动失败提示80、8080等端口已被占用。解决方案更换端口在启动命令中指定另一个端口如--server.port8081。找出并停止占用进程Linux:# 查找占用8080端口的进程PID sudo netstat -tlnp | grep :8080 # 或使用更现代的lsof sudo lsof -i:8080 # 终止进程 (假设PID是12345) sudo kill -9 12345Windows:# 查找占用端口的PID netstat -ano | findstr :8080 # 在任务管理器的“详细信息”选项卡中根据PID找到进程并结束或使用命令 taskkill /PID 12345 /F4.3 问题三应用启动成功但无法从外部访问现象服务器本地curl http://localhost:8080可以访问但用其他机器的浏览器访问服务器IP:8080却连接失败。排查思路检查SpringBoot服务绑定地址默认情况下SpringBoot应用监听0.0.0.0:8080表示接受所有网络接口的连接。但如果你在配置文件中设置了server.address127.0.0.1那么它只监听本地回环地址外部自然无法访问。确保配置为0.0.0.0或不设置此项。检查服务器防火墙这是最常见的原因。Linux (firewalld):# 查看开放端口 sudo firewall-cmd --list-ports # 永久开放8080端口 sudo firewall-cmd --zonepublic --add-port8080/tcp --permanent # 重载防火墙规则 sudo firewall-cmd --reloadLinux (iptables)规则较复杂需根据具体配置添加。Windows防火墙在“高级安全Windows防火墙”中添加入站规则允许特定端口如8080的TCP连接。检查云服务商安全组/网络ACL如果你使用的是阿里云、腾讯云、AWS等云服务器必须在控制台配置安全组规则允许外部IP访问你应用监听的端口。4.4 问题四使用nohup启动后如何查看和管理日志现象应用用nohup启动在后台想看看实时日志或者服务是否还活着。解决方案查看日志文件# 查看最后100行 tail -100f app.log # 持续滚动查看最新日志最常用 tail -f app.log查找进程# 根据名称查找进程 ps -ef | grep java # 或查找特定JAR包 ps -ef | grep your-app.jar输出结果中第二列是PID。停止应用# 先尝试正常终止 kill PID # 如果无效强制终止 kill -9 PID4.5 问题五JVM内存参数优化现象应用运行一段时间后变慢或崩溃可能是内存设置不合理。解决方案在java -jar命令中指定JVM参数。java -Xms512m -Xmx1024m -jar your-app.jar-Xms512m设置JVM初始堆内存为512MB。-Xmx1024m设置JVM最大堆内存为1024MB。对于生产环境需要根据服务器物理内存和应用实际使用情况来调整。通常-Xms和-Xmx设置为相同值可以避免运行期堆内存扩容带来的性能抖动。还可以添加其他参数如-XX:UseG1GC指定垃圾回收器等。4.6 问题速查表问题现象可能原因排查命令/步骤java: command not foundJava未安装或环境变量未配置which java,echo $JAVA_HOME, 检查Pathno main manifest attribute打包不正确非可执行JAR检查是否使用了正确的fat jar确认pom.xml中插件配置启动时报数据库连接错误数据库地址/密码错误或网络不通检查application-prod.properties配置用telnet或nc测试数据库端口应用响应慢CPU/内存高应用存在性能瓶颈或内存泄漏top,jps,jstack PID,jmap分析查看GC日志nohup启动后找不到进程启动命令有误或进程已崩溃检查nohup命令语法查看nohup.out或指定的日志文件部署SpringBoot JAR包是一个系统工程涉及构建、传输、环境、运行、运维多个环节。掌握这个流程意味着你具备了将代码转化为稳定服务的基本能力。从简单的java -jar到使用systemd管理再到后续结合CI/CD工具如Jenkins、GitLab CI实现自动化部署这条路会越走越宽。最关键的是每一步都要清楚自己在做什么遇到问题有条理地排查。希望这份结合了原理和实战经验的指南能让你在部署之路上少走弯路。