当前位置: 首页 > news >正文

Spring Boot 部署与打包方式详解(Jar vs War)

Spring Boot 提供了灵活的打包选项,支持两种主要部署方式:可执行 JAR传统 WAR。以下是全面的对比与实践指南,帮助你根据项目需求选择最适合的部署方案。


📦 一、打包方式对比

特性可执行 JAR (默认)传统 WAR
启动方式java -jar app.jar部署到外部 Servlet 容器 (如 Tomcat)
内嵌服务器✅ 包含 Tomcat/Jetty/Undertow❌ 需外部容器
部署复杂度⭐ 极简 (单文件部署)⭐⭐⭐ 需容器环境
依赖管理所有依赖打包进单个 FAT JAR依赖由容器管理 (部分依赖可打包进 WAR)
热更新需第三方工具 (JRebel)支持容器级热部署
生产适用场景微服务/云原生环境传统企业级应用服务器环境
文件大小较大 (包含内嵌容器)较小 (仅应用代码)

🛠️ 二、JAR 打包部署 (默认方式)

1. 打包配置 (Maven)

确保你的 pom.xml 文件中有如下插件配置:

<build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins>
</build>

2. 打包命令

使用 Maven 进行构建:

mvn clean package
# 生成 target/appname-0.0.1-SNAPSHOT.jar

3. 运行方式

可以采用多种方式运行 JAR 文件:

# 标准启动
java -jar app.jar# 带配置文件启动
java -jar -Dspring.profiles.active=prod app.jar# 内存限制启动
java -Xms512m -Xmx1024m -jar app.jar

4. 生产环境增强

为了更好地适应生产环境,你可以采取以下措施:

  • 系统服务化 (Systemd):
[Unit]
Description=Spring Boot Service
After=syslog.target[Service]
User=appuser
ExecStart=/usr/bin/java -jar /opt/app/app.jar
SuccessExitStatus=143
  • 启动脚本封装 (带日志分割):
nohup java -jar app.jar > app.log 2>&1 &

🧩 三、WAR 打包部署 (传统方式)

1. 修改打包类型

首先,在 pom.xml 中将 <packaging> 修改为 war

<packaging>war</packaging>

2. 排除内嵌容器 (Tomcat)

由于 WAR 文件需要部署到外部容器中,因此需要排除内置的 Tomcat:

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-tomcat</artifactId><scope>provided</scope>
</dependency>

3. 初始化 Servlet 入口

修改主类以继承 SpringBootServletInitializer

public class Application extends SpringBootServletInitializer {@Overrideprotected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {return builder.sources(Application.class);}public static void main(String[] args) {SpringApplication.run(Application.class, args);}
}

4. 构建与部署

完成上述步骤后,执行打包命令并部署到 Tomcat:

mvn clean package
# 生成 target/appname-0.0.1-SNAPSHOT.war# 部署到 Tomcat
cp target/app.war $TOMCAT_HOME/webapps/

☁️ 四、云原生部署最佳实践

1. Docker 容器化部署 (JAR 方式)

编写 Dockerfile 来创建镜像:

FROM eclipse-temurin:17-jre
VOLUME /tmp
COPY target/*.jar app.jar
ENTRYPOINT ["java","-jar","/app.jar"]

然后构建和运行 Docker 镜像:

docker build -t myapp:1.0 .
docker run -d -p 8080:8080 myapp:1.0

2. 多阶段构建优化镜像

利用多阶段构建来减小最终镜像体积:

# 阶段1:构建应用
FROM maven:3.8.6 AS build
COPY src /app/src
COPY pom.xml /app
RUN mvn -f /app/pom.xml clean package# 阶段2:运行镜像
FROM eclipse-temurin:17-jre-alpine
COPY --from=build /app/target/*.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java","-jar","/app.jar"]

3. Kubernetes 部署

定义 Deployment 和 Service YAML 文件来进行 Kubernetes 部署:

# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:name: springboot-app
spec:replicas: 3selector:matchLabels:app: springboottemplate:metadata:labels:app: springbootspec:containers:- name: appimage: myregistry/springboot-app:1.0ports:- containerPort: 8080env:- name: SPRING_PROFILES_ACTIVEvalue: prod
---
# service.yaml
apiVersion: v1
kind: Service
metadata:name: springboot-service
spec:selector:app: springbootports:- protocol: TCPport: 80targetPort: 8080

⚠️ 五、关键注意事项

  1. 静态资源处理
    JAR 模式:资源放在 src/main/resources/static
    WAR 模式:资源放在 src/main/webapp

  2. 配置文件优先级
    Spring Boot 加载顺序:

1. jar 内部 application.properties  
2. jar 同级 /config/ 目录  
3. jar 同级目录  
4. 类路径 /config  
5. 类路径根目录
  1. 上下文路径设置
    JAR 模式:server.servlet.context-path=/api
    WAR 模式:通过容器设置或 application.properties

  2. 端口冲突解决

# 避免与容器端口冲突
server.port=8081
  1. WAR 部署常见问题
    类冲突:使用 <scope>provided</scope> 排除容器已有库
    路径错误:确保 SpringBootServletInitializer 正确配置

🔍 六、部署决策树

在这里插入图片描述


🚀 七、高级部署方案

  1. 性能优化启动
# 开启 AOT 优化 (Spring Boot 3+)
java -Dspring.aot.enabled=true -jar app.jar
  1. GraalVM 原生镜像
# 需配置 spring-boot-starter-parent 3.x
mvn native:compile -Pnative
  1. 蓝绿部署方案
负载均衡
版本A
版本B
  1. 健康检查端点
management:endpoint:health:probes:enabled: true # 启用K8s就绪/存活检查health:livenessstate:enabled: truereadinessstate:enabled: true

💎 总结建议

  • 优先选择 JAR: 对于大多数微服务和云原生应用来说,JAR 是理想的选择。
  • 选择 WAR 当: 需要与遗留系统集成或必须在特定应用服务器上运行时考虑使用 WAR。

  • 如果你在学习过程中遇到任何问题,欢迎在评论区留言交流!
  • 👍 如果你觉得这篇文章对你有帮助,别忘了点赞、收藏、转发哦!
http://www.lqws.cn/news/534007.html

相关文章:

  • Windows命令连接符的安全风险分析与防御策略
  • SQLMesh:数据建模与版本控制的革新者
  • inverse-design-of-grating-coupler-3d(2)
  • 鸿蒙实时音视频流处理框架开发实战——基于HarmonyOS 4.0与分布式软总线的低延时高可靠架构
  • 从提示工程(Prompt Engineering)到上下文工程(Context Engineering)
  • PyTorch 模型镜像下载与安装指南
  • R 语言简介:数据分析与统计的强大工具
  • DSP学习笔记1
  • 声网对话式AI构建商品场景语义理解能力
  • 基于SpringBoot文件管理系统中的分片上传实现
  • 使用API有效率地管理Dynadot域名,出售账户中的域名
  • OpenCV CUDA模块设备层-----逐通道最小值比较函数min()
  • SpringBoot 中 @Transactional 的使用
  • 【LLM安全】MCP(模型上下文协议)及其关键漏洞、技术细节
  • 力扣网C语言编程题:搜索插入位置
  • mac电脑安装vscode的力扣插件报错解决办法
  • element-plus 按钮 展开/隐藏
  • 百面Bert
  • Ubuntu 搭建Kubernetes 1.28版本集群
  • 代码随想录day16二叉树4
  • 参展回顾 | AI应用创新场景:数据分析助手ChatBI、璞公英教学平台亮相2025四川国际职教大会暨产教融合博览会
  • 装修选木地板还是瓷砖,都有哪些优势?
  • 第一章-人工智能概述-深度学习与AI发展(2/36)
  • MySQL备份和恢复
  • 亚矩阵云手机多开赋能Snapchat矩阵运营:技术原理与场景化破局
  • 解锁企业效率革命:Microsoft 365 Copilot 重塑办公新范式
  • 力扣第14题-最长公共前缀
  • UDP 缓冲区
  • 用Dockerfile点亮你的容器化世界:从零到精通
  • Webshell工具的流量特征分析(菜刀,蚁剑,冰蝎,哥斯拉)