Java项目打包完整指南:从JAR到Docker全方位解析

2025-12-12 0 775

一、Java打包工具全景图

在开始具体打包之前,我们先了解下主流的Java打包工具及其适用场景

工具 适用场景 特点 输出格式
javac + jar 简单学习项目 JDK内置,无需额外配置 JAR
Maven 企业级项目 强大的依赖管理和生命周期 JAR, WAR
Gradle 复杂大型项目 灵活配置,构建性能高 JAR, WAR, 多种格式
Spring Boot Maven Plugin Spring Boot应用 内嵌服务器,开箱即用 Executable JAR
jpackage 桌面应用程序 生成原生安装包 EXE, DMG, DEB
Docker 微服务部署 环境隔离,持续交付 Docker Image

二、传统JAR打包详解

2.1 项目结构准备

一个标准的Java项目结构如下:

MyApp/
├── src/
│   └── com/example/
│       ├── Main.java
│       └── util/
│           └── StringUtil.java
├── lib/ (第三方依赖)
└── resources/ (配置文件)

2.2 手动打包实战

对于简单的项目,我们可以使用JDK自带的工具手动打包:

# 1. 编译Java源代码
javac -d build/classes src/com/example/**/*.java

# 2. 创建清单文件(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. 运行应用
java -jar myapp.jar

2.3 自动化构建脚本

为了提高效率,我们可以编写构建脚本:

#!/bin/bash
# build.sh - Java项目自动构建脚本

echo \" 开始构建Java项目...\"

# 清理构建目录
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/

# 创建清单文件
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 \" 构建完成!输出文件: myapp.jar\"

三、Maven标准化打包

Maven是Java领域最流行的构建工具,提供了标准化的项目结构和构建流程。

3.1 标准Maven项目结构

project/
├── pom.xml
├── src/
│   ├── main/
│   │   ├── java/ (Java源代码)
│   │   │   └── com/example/
│   │   │       ├── Main.java
│   │   │       └── service/
│   │   └── resources/ (资源文件)
│   │       ├── application.properties
│   │       └── log4j2.xml
│   └── test/ (测试代码)
│       └── java/
└── target/ (构建输出目录)

3.2 基础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>
    
    
    <groupId>com.example</groupId>
    <artifactId>myapp</artifactId>
    <version>1.0.0</version>
    <packaging>jar</packaging>
    
    <properties>
        
        <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 创建可执行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>
                    
                    <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

# 运行Spring Boot应用
mvn spring-boot:run

四、Web应用WAR包打包

对于Web应用,我们需要打包成WAR格式部署到Servlet容器。

4.1 Web项目结构

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打包配置


<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>
                
                <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);
    }
}


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

五、Gradle现代化构建

Gradle以其简洁的DSL和出色的性能受到越来越多开发者的青睐。

5.1 基础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 创建胖JAR

// 使用Shadow插件创建胖JAR
plugins {
    id \'com.github.johnrengelman.shadow\' version \'7.1.2\'
}

shadowJar {
    archiveBaseName.set(\'myapp\')
    archiveClassifier.set(\'\')
    archiveVersion.set(\'\')
    mergeServiceFiles()
}

// 或者自定义任务
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命令

# 构建项目
./gradlew build

# 创建胖JAR
./gradlew shadowJar

# 清理构建
./gradlew clean

# 运行应用
./gradlew run

六、Docker容器化部署

容器化部署已经成为现代应用部署的标准方式。

6.1 多阶段构建Dockerfile

# 第一阶段:构建阶段
FROM maven:3.8.4-openjdk-11 AS builder
WORKDIR /app

# 拷贝pom文件并下载依赖(利用Docker缓存)
COPY pom.xml .
RUN mvn dependency:go-offline

# 拷贝源码并构建
COPY src ./src
RUN mvn clean package -DskipTests

# 第二阶段:运行阶段
FROM openjdk:11-jre-slim
WORKDIR /app

# 创建非root用户(安全考虑)
RUN groupadd -r spring && useradd -r -g spring spring
USER spring

# 从构建阶段拷贝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参数优化
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 容器操作命令

# 构建镜像
docker build -t myapp:1.0.0 .

# 运行容器
docker run -d -p 8080:8080 --name myapp myapp:1.0.0

# 使用Docker Compose
docker-compose up -d

# 查看日志
docker logs -f myapp

# 进入容器调试
docker exec -it myapp bash

七、高级打包技巧

7.1 使用jpackage创建原生安装包(JDK 14+)

# 创建跨平台安装包
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

# 构建原生镜像
RUN native-image -jar target/myapp-1.0.0.jar 
    --no-fallback 
    --enable-https 
    -H:Name=myapp-native

# 运行阶段
FROM alpine:latest
RUN apk --no-cache add libstdc++
COPY --from=builder /app/myapp-native /app/myapp-native

EXPOSE 8080
ENTRYPOINT [\"/app/myapp-native\"]

八、最佳实践总结

8.1 版本管理


<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用户运行容器
  • 定期更新基础镜像
  • 扫描镜像安全漏洞

8.3 性能优化

# 使用轻量级基础镜像
FROM openjdk:11-jre-slim

# 优化JVM参数
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 }}

结语

Java项目打包已经从简单的JAR文件发展到现代化的容器化部署。掌握这些打包技术对于Java开发者至关重要。无论是传统的Web应用还是现代的微服务,选择合适的打包方式都能大大提高开发和部署效率。

希望本文能为您提供全面的Java项目打包指导!如有任何问题,欢迎大家在评论区分享你的想法!!!

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

申明:本文由第三方发布,内容仅代表作者观点,与本网站无关。对本文以及其中全部或者部分内容的真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。本网发布或转载文章出于传递更多信息之目的,并不意味着赞同其观点或证实其描述,也不代表本网对其真实性负责。

左子网 编程相关 Java项目打包完整指南:从JAR到Docker全方位解析 https://www.zuozi.net/35799.html

常见问题
  • 1、自动:拍下后,点击(下载)链接即可下载;2、手动:拍下后,联系卖家发放即可或者联系官方找开发者发货。
查看详情
  • 1、源码默认交易周期:手动发货商品为1-3天,并且用户付款金额将会进入平台担保直到交易完成或者3-7天即可发放,如遇纠纷无限期延长收款金额直至纠纷解决或者退款!;
查看详情
  • 1、描述:源码描述(含标题)与实际源码不一致的(例:货不对板); 2、演示:有演示站时,与实际源码小于95%一致的(但描述中有”不保证完全一样、有变化的可能性”类似显著声明的除外); 3、发货:不发货可无理由退款; 4、安装:免费提供安装服务的源码但卖家不履行的; 5、收费:价格虚标,额外收取其他费用的(但描述中有显著声明或双方交易前有商定的除外); 6、其他:如质量方面的硬性常规问题BUG等。 注:经核实符合上述任一,均支持退款,但卖家予以积极解决问题则除外。
查看详情
  • 1、左子会对双方交易的过程及交易商品的快照进行永久存档,以确保交易的真实、有效、安全! 2、左子无法对如“永久包更新”、“永久技术支持”等类似交易之后的商家承诺做担保,请买家自行鉴别; 3、在源码同时有网站演示与图片演示,且站演与图演不一致时,默认按图演作为纠纷评判依据(特别声明或有商定除外); 4、在没有”无任何正当退款依据”的前提下,商品写有”一旦售出,概不支持退款”等类似的声明,视为无效声明; 5、在未拍下前,双方在QQ上所商定的交易内容,亦可成为纠纷评判依据(商定与描述冲突时,商定为准); 6、因聊天记录可作为纠纷评判依据,故双方联系时,只与对方在左子上所留的QQ、手机号沟通,以防对方不承认自我承诺。 7、虽然交易产生纠纷的几率很小,但一定要保留如聊天记录、手机短信等这样的重要信息,以防产生纠纷时便于左子介入快速处理。
查看详情

相关文章

猜你喜欢
发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务