Java項目打包從JAR到Docker的全方位指南
?一、Java打包工具全景圖
在開始具體打包之前,我們先了解下主流的Java打包工具及其適用場景:
| 工具 | 適用場景 | 特點(diǎn) | 輸出格式 |
|---|---|---|---|
| javac + jar | 簡單學(xué)習(xí)項目 | JDK內(nèi)置,無需額外配置 | JAR |
| Maven | 企業(yè)級項目 | 強(qiáng)大的依賴管理和生命周期 | JAR, WAR |
| Gradle | 復(fù)雜大型項目 | 靈活配置,構(gòu)建性能高 | JAR, WAR, 多種格式 |
| Spring Boot Maven Plugin | Spring Boot應(yīng)用 | 內(nèi)嵌服務(wù)器,開箱即用 | Executable JAR |
| jpackage | 桌面應(yīng)用程序 | 生成原生安裝包 | EXE, DMG, DEB |
| Docker | 微服務(wù)部署 | 環(huán)境隔離,持續(xù)交付 | Docker Image |
二、傳統(tǒng)JAR打包詳解
2.1 項目結(jié)構(gòu)準(zhǔn)備
一個標(biāo)準(zhǔn)的Java項目結(jié)構(gòu)如下:
MyApp/ ├── src/ │ └── com/example/ │ ├── Main.java │ └── util/ │ └── StringUtil.java ├── lib/ (第三方依賴) └── resources/ (配置文件)
2.2 手動打包實(shí)戰(zhàn)
對于簡單的項目,我們可以使用JDK自帶的工具手動打包:
# 1. 編譯Java源代碼 javac -d build/classes src/com/example/**/*.java # 2. 創(chuàng)建清單文件(MANIFEST.MF) cat > MANIFEST.MF << EOF Manifest-Version: 1.0 Main-Class: com.example.Main Created-By: Java Packager EOF # 3. 打包成JAR文件 jar cfm myapp.jar MANIFEST.MF -C build/classes . # 4. 運(yùn)行應(yīng)用 java -jar myapp.jar
2.3 自動化構(gòu)建腳本
為了提高效率,我們可以編寫構(gòu)建腳本:
#!/bin/bash # build.sh - Java項目自動構(gòu)建腳本 echo "?? 開始構(gòu)建Java項目..." # 清理構(gòu)建目錄 rm -rf build mkdir -p build/classes # 編譯源碼 echo "?? 編譯Java源碼..." javac -d build/classes -sourcepath src src/com/example/**/*.java # 拷貝資源文件 echo "?? 拷貝資源文件..." cp -r resources/* build/classes/ # 創(chuàng)建清單文件 echo "?? 生成清單文件..." cat > MANIFEST.MF << EOF Manifest-Version: 1.0 Main-Class: com.example.Main Class-Path: $(find lib -name "*.jar" | tr '\n' ' ') Build-Time: $(date) EOF # 打包JAR echo "?? 打包JAR文件..." jar cfm myapp.jar MANIFEST.MF -C build/classes . # 清理臨時文件 rm MANIFEST.MF echo "? 構(gòu)建完成!輸出文件: myapp.jar"
三、Maven標(biāo)準(zhǔn)化打包
Maven是Java領(lǐng)域最流行的構(gòu)建工具,提供了標(biāo)準(zhǔn)化的項目結(jié)構(gòu)和構(gòu)建流程。
3.1 標(biāo)準(zhǔn)Maven項目結(jié)構(gòu)
project/ ├── pom.xml ├── src/ │ ├── main/ │ │ ├── java/ (Java源代碼) │ │ │ └── com/example/ │ │ │ ├── Main.java │ │ │ └── service/ │ │ └── resources/ (資源文件) │ │ ├── application.properties │ │ └── log4j2.xml │ └── test/ (測試代碼) │ └── java/ └── target/ (構(gòu)建輸出目錄)
3.2 基礎(chǔ)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
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<!-- 項目坐標(biāo) -->
<groupId>com.example</groupId>
<artifactId>myapp</artifactId>
<version>1.0.0</version>
<packaging>jar</packaging>
<properties>
<!-- 統(tǒng)一版本管理 -->
<java.version>11</java.version>
<maven.compiler.version>3.8.1</maven.compiler.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.17.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<!-- 編譯器插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven.compiler.version}</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
3.3 創(chuàng)建可執(zhí)行JAR的三種方式
方式一:使用maven-jar-plugin(依賴外置)
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.2.2</version>
<configuration>
<archive>
<manifest>
<mainClass>com.example.Main</mainClass>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
</manifest>
</archive>
</configuration>
</plugin>
方式二:使用maven-assembly-plugin(胖JAR)
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.3.0</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<mainClass>com.example.Main</mainClass>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
方式三:使用maven-shade-plugin(推薦)
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.4</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>com.example.Main</mainClass>
</transformer>
<!-- 處理Spring配置文件 -->
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
<resource>META-INF/spring.handlers</resource>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
3.4 常用Maven命令
# 清理并打包 mvn clean package # 跳過測試打包 mvn clean package -DskipTests # 安裝到本地倉庫 mvn clean install # 生成源碼包和文檔 mvn source:jar javadoc:jar # 運(yùn)行Spring Boot應(yīng)用 mvn spring-boot:run
四、Web應(yīng)用WAR包打包
對于Web應(yīng)用,我們需要打包成WAR格式部署到Servlet容器。
4.1 Web項目結(jié)構(gòu)
webapp/ ├── pom.xml ├── src/ │ └── main/ │ ├── java/ │ │ └── com/example/ │ │ ├── controller/ │ │ ├── service/ │ │ └── config/ │ ├── resources/ │ └── webapp/ (Web資源) │ ├── WEB-INF/ │ │ └── web.xml │ ├── index.jsp │ └── static/ │ ├── css/ │ ├── js/ │ └── images/
4.2 WAR打包配置
<!-- 修改打包方式為war -->
<packaging>war</packaging>
<build>
<finalName>mywebapp</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.3.1</version>
<configuration>
<!-- 對于Spring Boot可以忽略web.xml -->
<failOnMissingWebXml>false</failOnMissingWebXml>
<warSourceDirectory>src/main/webapp</warSourceDirectory>
</configuration>
</plugin>
</plugins>
</build>
4.3 Spring Boot外部容器部署
@SpringBootApplication
public class Application extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
<!-- 排除內(nèi)嵌Tomcat,使用外部容器 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
五、Gradle現(xiàn)代化構(gòu)建
Gradle以其簡潔的DSL和出色的性能受到越來越多開發(fā)者的青睞。
5.1 基礎(chǔ)build.gradle配置
plugins {
id 'java'
id 'application'
}
group = 'com.example'
version = '1.0.0'
sourceCompatibility = '11'
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web:2.7.0'
testImplementation 'org.springframework.boot:spring-boot-starter-test:2.7.0'
}
application {
mainClass = 'com.example.Main'
}
5.2 創(chuàng)建胖JAR
// 使用Shadow插件創(chuàng)建胖JAR
plugins {
id 'com.github.johnrengelman.shadow' version '7.1.2'
}
shadowJar {
archiveBaseName.set('myapp')
archiveClassifier.set('')
archiveVersion.set('')
mergeServiceFiles()
}
// 或者自定義任務(wù)
task customFatJar(type: Jar) {
manifest {
attributes 'Main-Class': 'com.example.Main'
}
archiveBaseName = 'myapp-all'
from {
configurations.runtimeClasspath.collect {
it.isDirectory() ? it : zipTree(it)
}
}
with jar
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
}
5.3 常用Gradle命令
# 構(gòu)建項目 ./gradlew build # 創(chuàng)建胖JAR ./gradlew shadowJar # 清理構(gòu)建 ./gradlew clean # 運(yùn)行應(yīng)用 ./gradlew run
六、Docker容器化部署
容器化部署已經(jīng)成為現(xiàn)代應(yīng)用部署的標(biāo)準(zhǔn)方式。
6.1 多階段構(gòu)建Dockerfile
# 第一階段:構(gòu)建階段
FROM maven:3.8.4-openjdk-11 AS builder
WORKDIR /app
# 拷貝pom文件并下載依賴(利用Docker緩存)
COPY pom.xml .
RUN mvn dependency:go-offline
# 拷貝源碼并構(gòu)建
COPY src ./src
RUN mvn clean package -DskipTests
# 第二階段:運(yùn)行階段
FROM openjdk:11-jre-slim
WORKDIR /app
# 創(chuàng)建非root用戶(安全考慮)
RUN groupadd -r spring && useradd -r -g spring spring
USER spring
# 從構(gòu)建階段拷貝JAR文件
COPY --from=builder /app/target/*.jar app.jar
# 健康檢查
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD curl -f http://localhost:8080/actuator/health || exit 1
# JVM參數(shù)優(yōu)化
ENV JAVA_OPTS="-Xmx512m -Xms256m -XX:+UseG1GC -Djava.security.egd=file:/dev/./urandom"
# 暴露端口
EXPOSE 8080
# 啟動命令
ENTRYPOINT ["sh", "-c", "java $JAVA_OPTS -jar app.jar"]
6.2 Docker Compose編排
version: '3.8'
services:
app:
build: .
ports:
- "8080:8080"
environment:
- SPRING_PROFILES_ACTIVE=prod
- DATABASE_URL=jdbc:mysql://db:3306/myapp
depends_on:
- db
networks:
- app-network
deploy:
resources:
limits:
memory: 512M
reservations:
memory: 256M
db:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: rootpass
MYSQL_DATABASE: myapp
volumes:
- db_data:/var/lib/mysql
networks:
- app-network
volumes:
db_data:
networks:
app-network:
driver: bridge
6.3 容器操作命令
# 構(gòu)建鏡像 docker build -t myapp:1.0.0 . # 運(yùn)行容器 docker run -d -p 8080:8080 --name myapp myapp:1.0.0 # 使用Docker Compose docker-compose up -d # 查看日志 docker logs -f myapp # 進(jìn)入容器調(diào)試 docker exec -it myapp bash
七、高級打包技巧
7.1 使用jpackage創(chuàng)建原生安裝包(JDK 14+)
# 創(chuàng)建跨平臺安裝包 jpackage \ --name MyApp \ --input target/ \ --main-jar myapp-1.0.0.jar \ --main-class com.example.Main \ --type app-image \ --dest installers/ \ --java-options '-Xmx256m' # Windows特定選項 jpackage --type exe --win-console --icon app.ico # macOS特定選項 jpackage --type dmg --mac-package-identifier com.example.myapp # Linux特定選項 jpackage --type deb --linux-package-name myapp
7.2 GraalVM原生鏡像
FROM ghcr.io/graalvm/native-image:22 AS builder
WORKDIR /app
COPY . .
RUN mvn clean package -DskipTests
# 構(gòu)建原生鏡像
RUN native-image -jar target/myapp-1.0.0.jar \
--no-fallback \
--enable-https \
-H:Name=myapp-native
# 運(yùn)行階段
FROM alpine:latest
RUN apk --no-cache add libstdc++
COPY --from=builder /app/myapp-native /app/myapp-native
EXPOSE 8080
ENTRYPOINT ["/app/myapp-native"]
八、最佳實(shí)踐總結(jié)
8.1 版本管理
<!-- 統(tǒng)一版本管理 -->
<properties>
<java.version>11</java.version>
<maven.compiler.version>3.8.1</maven.compiler.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
8.2 安全考慮
- 使用非root用戶運(yùn)行容器
- 定期更新基礎(chǔ)鏡像
- 掃描鏡像安全漏洞
8.3 性能優(yōu)化
# 使用輕量級基礎(chǔ)鏡像 FROM openjdk:11-jre-slim # 優(yōu)化JVM參數(shù) ENV JAVA_OPTS="-XX:+UseContainerSupport -XX:MaxRAMPercentage=75.0"
8.4 CI/CD集成示例
name: Java CI/CD Pipeline
on:
push:
branches: [ main ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up JDK 11
uses: actions/setup-java@v2
with:
java-version: '11'
distribution: 'temurin'
cache: 'maven'
- name: Build and Test
run: mvn clean package
- name: Build Docker Image
run: docker build -t myapp:${{ github.sha }} .
- name: Deploy to Registry
run: |
echo ${{ secrets.DOCKER_PASSWORD }} | docker login -u ${{ secrets.DOCKER_USERNAME }} --password-stdin
docker push myapp:${{ github.sha }}
結(jié)語
Java項目打包已經(jīng)從簡單的JAR文件發(fā)展到現(xiàn)代化的容器化部署。掌握這些打包技術(shù)對于Java開發(fā)者至關(guān)重要。無論是傳統(tǒng)的Web應(yīng)用還是現(xiàn)代的微服務(wù),選擇合適的打包方式都能大大提高開發(fā)和部署效率。
以上就是Java項目打包從JAR到Docker的全方位指南的詳細(xì)內(nèi)容,更多關(guān)于Java項目打包從JAR到Docker的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
mybatis-generator-gui根據(jù)需求改動示例
這篇文章主要為大家介紹了mybatis-generator-gui根據(jù)需求改動示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-09-09
Spring使用AOP完成統(tǒng)一結(jié)果封裝實(shí)例demo
這篇文章主要介紹了Spring使用AOP完成統(tǒng)一結(jié)果封裝,本文通過實(shí)現(xiàn)demo給大家詳細(xì)講解,代碼簡單易懂,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-02-02
springmvc和js前端的數(shù)據(jù)傳遞和接收方式(兩種)
本文介紹了springmvc和js前端的數(shù)據(jù)傳遞和接收方式(兩種),詳細(xì)的介紹了兩種方式,一種是json格式傳遞,另一種是Map傳遞,具有一定的參考價值,有興趣的可以了解一下2017-12-12
maven工程打包引入本地jar包的實(shí)現(xiàn)
我們需要將jar包發(fā)布到一些指定的第三方Maven倉庫,本文主要介紹了maven工程打包引入本地jar包的實(shí)現(xiàn),具有一定的參考價值,感興趣的可以了解一下2024-02-02
基于Spring接口集成Caffeine+Redis兩級緩存
這篇文章主要介紹了基于Spring接口集成Caffeine+Redis兩級緩存,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價值,需要的小伙伴可以參考一下2022-07-07
詳解在SpringBoot中@Transactional事物操作和事物無效問題排查
這篇文章主要介紹了詳解在SpringBoot中@Transactional事物操作和事物無效問題排查,本文詳細(xì)的介紹了SpringBoot中集成使用@Transactional注解操作事物以及事物開啟后無效的問題排查,需要的朋友可以參考下2021-06-06
Java?對象在?JVM?中的內(nèi)存布局超詳細(xì)解說
這篇文章主要介紹了Java?對象在?JVM?中的內(nèi)存布局超詳細(xì)解說,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價值,需要的小伙伴可以參考一下2022-09-09

