SpringBoot JAR和WAR方式打包并部署的詳細(xì)步驟及對(duì)比分析
一、JAR 和 WAR 打包的區(qū)別
JAR (Java ARchive)
- 獨(dú)立運(yùn)行:內(nèi)嵌Tomcat/Jetty服務(wù)器,可直接通過
java -jar運(yùn)行 - 微服務(wù)友好:適合云原生、容器化部署
- 簡(jiǎn)化部署:?jiǎn)蝹€(gè)可執(zhí)行文件,無需外部Web服務(wù)器
- 默認(rèn)方式:Spring Boot 默認(rèn)打包為可執(zhí)行JAR
WAR (Web Application ARchive)
- 傳統(tǒng)部署:需要外部Servlet容器(如Tomcat、WebLogic)
- 企業(yè)環(huán)境:適合需要部署到現(xiàn)有應(yīng)用服務(wù)器的場(chǎng)景
- 共享資源:多個(gè)應(yīng)用可共享服務(wù)器資源
- 配置分離:服務(wù)器配置與應(yīng)用分離
二、詳細(xì)打包部署步驟
項(xiàng)目結(jié)構(gòu)
my-springboot-app/ ├── src/ │ └── main/ │ ├── java/com/example/ │ └── resources/ └── pom.xml 或 build.gradle
1. 打包為可執(zhí)行JAR(默認(rèn)方式)
Maven 配置 (pom.xml)
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>my-springboot-app</artifactId>
<version>1.0.0</version>
<packaging>jar</packaging> <!-- 打包為JAR -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.1.5</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<!-- Spring Boot Maven 插件 -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>com.example.MyApplication</mainClass>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Gradle 配置 (build.gradle)
plugins {
id 'org.springframework.boot' version '3.1.5'
id 'io.spring.dependency-management' version '1.1.3'
id 'java'
}
group = 'com.example'
version = '1.0.0'
sourceCompatibility = '17'
jar {
enabled = true
archiveClassifier = '' // 移除plain后綴
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
}
// 可執(zhí)行JAR配置
bootJar {
mainClass = 'com.example.MyApplication'
archiveClassifier = ''
}
主啟動(dòng)類
package com.example;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
打包命令
# Maven mvn clean package # Gradle ./gradlew clean build
運(yùn)行JAR
# 直接運(yùn)行 java -jar target/my-springboot-app-1.0.0.jar # 指定配置文件 java -jar target/my-springboot-app-1.0.0.jar \ --spring.config.location=classpath:/,file:./config/ # 指定端口 java -jar target/my-springboot-app-1.0.0.jar \ --server.port=8081 # 生產(chǎn)環(huán)境運(yùn)行(內(nèi)存優(yōu)化) java -Xms512m -Xmx1024m -jar target/my-springboot-app-1.0.0.jar \ --spring.profiles.active=prod
2. 打包為WAR(用于外部容器)
修改Maven配置
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>my-springboot-app</artifactId>
<version>1.0.0</version>
<packaging>war</packaging> <!-- 修改為WAR -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.1.5</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<!-- 排除內(nèi)嵌Tomcat -->
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- 添加Servlet API依賴(provided scope) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope> <!-- 由外部容器提供 -->
</dependency>
</dependencies>
<build>
<finalName>myapp</finalName> <!-- WAR文件名稱 -->
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
修改啟動(dòng)類
package com.example;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
@SpringBootApplication
public class MyApplication extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(MyApplication.class);
}
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
Gradle WAR配置
plugins {
id 'org.springframework.boot' version '3.1.5'
id 'io.spring.dependency-management' version '1.1.3'
id 'java'
id 'war' // 添加war插件
}
group = 'com.example'
version = '1.0.0'
sourceCompatibility = '17'
configurations {
providedRuntime // 用于provided范圍的依賴
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat'
}
war {
archiveFileName = 'myapp.war'
}
打包WAR
# Maven mvn clean package # Gradle ./gradlew clean build
部署到外部Tomcat
準(zhǔn)備Tomcat服務(wù)器
# 下載Tomcat wget https://downloads.apache.org/tomcat/tomcat-10/v10.1.13/bin/apache-tomcat-10.1.13.tar.gz tar -xzf apache-tomcat-10.1.13.tar.gz cd apache-tomcat-10.1.13
部署WAR文件
# 復(fù)制WAR文件到webapps目錄 cp target/myapp.war /opt/tomcat/webapps/ # 或者使用管理界面部署 # 訪問 http://localhost:8080/manager/html
Tomcat配置優(yōu)化(conf/server.xml)
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443"
maxThreads="200"
minSpareThreads="10"
enableLookups="false"
acceptCount="100"
disableUploadTimeout="true"/>
啟動(dòng)/停止Tomcat
# Linux ./bin/startup.sh ./bin/shutdown.sh # Windows bin\startup.bat bin\shutdown.bat
3. 配置文件管理
application.yml 示例
# 公共配置
spring:
application:
name: my-springboot-app
# 開發(fā)環(huán)境
---
spring:
config:
activate:
on-profile: dev
server:
port: 8080
logging:
level:
root: DEBUG
# 生產(chǎn)環(huán)境
---
spring:
config:
activate:
on-profile: prod
server:
port: 8080
compression:
enabled: true
mime-types: text/html,text/xml,text/plain,application/json
logging:
file:
name: /var/log/myapp.log
level:
root: INFO
4. 容器化部署(Docker)
Dockerfile for JAR
# 使用多階段構(gòu)建 FROM eclipse-temurin:17-jdk-alpine as builder WORKDIR /app COPY mvnw . COPY .mvn .mvn COPY pom.xml . RUN ./mvnw dependency:go-offline COPY src ./src RUN ./mvnw clean package -DskipTests # 運(yùn)行階段 FROM eclipse-temurin:17-jre-alpine WORKDIR /app COPY --from=builder /app/target/*.jar app.jar EXPOSE 8080 ENTRYPOINT ["java", "-jar", "app.jar"]
Dockerfile for WAR + Tomcat
FROM tomcat:10.1-jdk17-temurin # 移除默認(rèn)應(yīng)用 RUN rm -rf /usr/local/tomcat/webapps/* # 復(fù)制WAR文件 COPY target/myapp.war /usr/local/tomcat/webapps/ROOT.war # 暴露端口 EXPOSE 8080 # 啟動(dòng)Tomcat CMD ["catalina.sh", "run"]
Docker Compose 示例
version: '3.8'
services:
app:
build: .
ports:
- "8080:8080"
environment:
- SPRING_PROFILES_ACTIVE=prod
- DB_HOST=mysql
depends_on:
- mysql
networks:
- app-network
mysql:
image: mysql:8.0
environment:
- MYSQL_ROOT_PASSWORD=rootpass
- MYSQL_DATABASE=mydb
volumes:
- mysql-data:/var/lib/mysql
networks:
- app-network
networks:
app-network:
driver: bridge
volumes:
mysql-data:
三、部署腳本示例
Linux 服務(wù)腳本(systemd)
# /etc/systemd/system/myapp.service [Unit] Description=My Spring Boot Application After=network.target [Service] Type=simple User=appuser WorkingDirectory=/opt/myapp ExecStart=/usr/bin/java -Xms512m -Xmx1024m -jar myapp.jar SuccessExitStatus=143 Restart=always RestartSec=10 [Install] WantedBy=multi-user.target
部署腳本
#!/bin/bash
# deploy.sh
APP_NAME="my-springboot-app"
JAR_PATH="target/$APP_NAME-1.0.0.jar"
DEPLOY_DIR="/opt/$APP_NAME"
BACKUP_DIR="$DEPLOY_DIR/backup"
LOG_DIR="/var/log/$APP_NAME"
# 創(chuàng)建目錄
mkdir -p $DEPLOY_DIR $BACKUP_DIR $LOG_DIR
# 備份舊版本
if [ -f "$DEPLOY_DIR/$APP_NAME.jar" ]; then
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
mv "$DEPLOY_DIR/$APP_NAME.jar" "$BACKUP_DIR/$APP_NAME-$TIMESTAMP.jar"
fi
# 復(fù)制新版本
cp $JAR_PATH "$DEPLOY_DIR/$APP_NAME.jar"
# 設(shè)置權(quán)限
chmod 755 "$DEPLOY_DIR/$APP_NAME.jar"
# 重啟服務(wù)
systemctl restart $APP_NAME
# 檢查狀態(tài)
sleep 10
systemctl status $APP_NAME
四、總結(jié)對(duì)比
| 特性 | JAR 部署 | WAR 部署 |
|---|---|---|
| 部署方式 | 獨(dú)立運(yùn)行,內(nèi)嵌容器 | 依賴外部Servlet容器 |
| 啟動(dòng)命令 | java -jar app.jar | 容器啟動(dòng)(如Tomcat) |
| 適合場(chǎng)景 | 微服務(wù)、云原生、容器化 | 傳統(tǒng)企業(yè)環(huán)境、共享服務(wù)器 |
| 依賴管理 | 包含所有依賴(fat jar) | 部分依賴由容器提供 |
| 資源占用 | 每個(gè)應(yīng)用獨(dú)立容器 | 多個(gè)應(yīng)用共享容器資源 |
| 熱部署 | 需要重啟整個(gè)應(yīng)用 | Tomcat支持部分熱部署 |
| 配置管理 | 應(yīng)用自身管理 | 可與容器配置結(jié)合 |
| 監(jiān)控 | Spring Boot Actuator | 容器管理界面 + Actuator |
選擇建議:
- 選擇JAR的情況:
- 微服務(wù)架構(gòu)
- 容器化部署(Docker/K8s)
- 云原生應(yīng)用
- 需要快速獨(dú)立部署
- 無現(xiàn)有應(yīng)用服務(wù)器
- 選擇WAR的情況:
- 傳統(tǒng)企業(yè)IT環(huán)境
- 已有Tomcat/WebLogic集群
- 需要與其他Java EE應(yīng)用共享資源
- 運(yùn)維團(tuán)隊(duì)熟悉傳統(tǒng)部署模式
- 需要與舊系統(tǒng)集成
最佳實(shí)踐:
- 對(duì)于新項(xiàng)目,優(yōu)先考慮JAR部署,更符合現(xiàn)代架構(gòu)
- 統(tǒng)一配置管理:無論JAR/WAR,使用外部配置文件
- 健康檢查:集成Spring Boot Actuator用于監(jiān)控
- 日志集中:使用Logback/SLF4J,日志輸出到文件或日志系統(tǒng)
- 安全加固:生產(chǎn)環(huán)境關(guān)閉開發(fā)特性,使用HTTPS
- 自動(dòng)化部署:結(jié)合CI/CD流水線實(shí)現(xiàn)自動(dòng)化
通過合理的打包部署策略,可以確保Spring Boot應(yīng)用在不同環(huán)境中的穩(wěn)定運(yùn)行和高效維護(hù)。
以上就是SpringBoot JAR和WAR方式打包并部署的詳細(xì)步驟及對(duì)比分析的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot JAR和WAR方式打包部署的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
idea 打包maven項(xiàng)目忽略test文件的操作
這篇文章主要介紹了idea 打包maven項(xiàng)目忽略test文件的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2021-02-02
Java Big Number操作BigInteger及BigDecimal類詳解
這篇文章主要為大家介紹了Java Big Number操作BigInteger及BigDecimal類詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-07-07
Java Testcontainers庫實(shí)現(xiàn)測(cè)試功能
這篇文章主要介紹了Java Testcontainers庫實(shí)現(xiàn)測(cè)試功能,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-09-09
VSCode搭建Java開發(fā)環(huán)境的超詳細(xì)步驟
VSCode是一款多平臺(tái)的源代碼編輯器,支持多種編程語言,它輕量級(jí)、功能強(qiáng)大,通過豐富的插件生態(tài)系統(tǒng)可以支持更多語言和運(yùn)行時(shí),如C++、C#、Java、Python等,這篇文章主要介紹了VSCode搭建Java開發(fā)環(huán)境的超詳細(xì)步驟,需要的朋友可以參考下2024-10-10
JavaSE經(jīng)典小練習(xí)項(xiàng)目之拷貝文件夾
文件拷貝是一個(gè)常見的任務(wù),無論是備份文件,還是將文件從一個(gè)位置復(fù)制到另一個(gè)位置,文件拷貝都是必不可少的,這篇文章主要給大家介紹了關(guān)于JavaSE經(jīng)典小練習(xí)項(xiàng)目之拷貝文件夾的相關(guān)資料,需要的朋友可以參考下2023-10-10
使用Java實(shí)現(xiàn)Navicat密碼的加密與解密的代碼解析
這篇文章主要介紹了使用Java實(shí)現(xiàn)Navicat密碼的加密與解密,通過本文,我們了解了如何利用Java語言實(shí)現(xiàn)對(duì)Navicat保存的數(shù)據(jù)庫密碼進(jìn)行加密和解密,需要的朋友可以參考下2025-05-05

