打包你需要的基本类、其他的不要

本文介绍了一个用于将Java应用程序打包成Jar文件的工具类。该工具能够解析并收集指定列表文件中列出的所有类路径,然后使用JarOutputStream将这些类路径打包进单一的Jar文件中。
看了一篇瘦身文件、记录一下、http://nonconductor.bokee.com/5085956.html

源代码如下

/*
* Alipay.com Inc.
* Copyright (c) 2004-2008 All Rights Reserved.
*/
package com.beyond.web.trade;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.jar.JarOutputStream;
import java.util.zip.ZipEntry;

public class Packager {
/**
* @param args
*/
public static void main(String[] args) throws Exception {
File f = new File("C:/Documents and Settings/en.xuze/hello.list");
Packager pkger = new Packager();
pkger.debugEnabled = true;
List ret = pkger.parseOutput(new FileInputStream(f));
pkger.pkgResources(ret, "C:/Documents and Settings/en.xuze/Hello.jar");
}

private boolean debugEnabled;

public List parseOutput(InputStream in) throws IOException {
ArrayList ret = new ArrayList();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
String line = reader.readLine();
while (line != null) {
if (line.matches("\\[Loaded .* from .*")) {
if (debugEnabled)
System.out.println("Matches:" + line);
ret.add(line.substring(8, line.indexOf(" from ")));
} else {
if (debugEnabled)
System.out.println("UnMatches:" + line);
}
line = reader.readLine();
}
return ret;
}

public void pkgResources(List res, String fileName) throws IOException {
File f = new File(fileName);
if (!f.exists()) {
f.createNewFile();
}
byte[] buf = new byte[1024];
JarOutputStream out = new JarOutputStream(new FileOutputStream(fileName));

for (Iterator iterator = res.iterator(); iterator.hasNext();) {
InputStream in = null;
try {
String s = (String) iterator.next();
s = s.replace('.', '/') + ".class";
if (debugEnabled) {
System.out.println("adding: " + s);
}
in = this.getClass().getClassLoader().getResourceAsStream(s);
out.putNextEntry(new ZipEntry(s));
int w = in.read(buf);
while (w >= 0) {
out.write(buf, 0, w);
w = in.read(buf);
}
} catch (Exception e) {
e.printStackTrace();
// TODO: handle exception
} finally {
in.close();
}
}
out.finish();
out.close();
}
}
在 Maven 的**聚合项目(多模块项目)**中,打包和部署的方式与单模块项目有所同。你提到“只需要启动的 jar 包就可以了吗”,这基本是对的 —— **只要主模块(含 `main` 启动)被打成可执行 JAR,并正确依赖其他子模块,就可以运行整个应用**。 但需要满足一系列条件和配置。 --- ## ✅ 一、什么是 Maven 聚合项目? 一个典型的聚合项目结构如下: ```text my-project/ ├── pom.xml (父 POM,packaging= pom) ├── common-utils/ → 工具模块 │ └── pom.xml ├── service-core/ → 业务逻辑模块 │ └── pom.xml ├── web-api/ → Spring Boot 主模块(有 main 方法) │ └── pom.xml └── database-access/ → 数据访问模块 └── pom.xml ``` - 父 `pom.xml` 使用 `<packaging>pom</packaging>` 来聚合所有子模块。 - 子模块之间可以相互依赖。 - 只有 `web-api` 是可运行的 Spring Boot 应用(包含 `@SpringBootApplication` 和 `main()` 方法)。 --- ## ✅ 二、如何打包?—— 关键是构建“可执行 JAR” ### 步骤 1:确保主模块使用 `spring-boot-maven-plugin` 在 `web-api/pom.xml` 中添加: ```xml <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <version>3.1.0</version> <!-- 根据你的版本调整 --> <configuration> <mainClass>com.example.webapi.WebApiApplication</mainClass> </configuration> <executions> <execution> <goals> <goal>repackage</goal> </goals> </execution> </executions> </plugin> </plugins> </build> ``` 这个插件会: - 把所有依赖(包括你自己写的 `common-utils`, `service-core` 等)打进去; - 生成一个 fat jar(uber-jar),可以直接运行:`java -jar web-api.jar` --- ### 步骤 2:在父 `pom.xml` 中定义模块和依赖关系 ```xml <!-- 父 pom.xml --> <packaging>pom</packaging> <modules> <module>common-utils</module> <module>database-access</module> <module>service-core</module> <module>web-api</module> </modules> <dependencyManagement> <dependencies> <dependency> <groupId>${project.groupId}</groupId> <artifactId>common-utils</artifactId> <version>${project.version}</version> </dependency> <!-- 其他子模块也似声明 --> </dependencies> </dependencyManagement> ``` 然后在 `web-api/pom.xml` 中引用其他模块: ```xml <dependencies> <dependency> <groupId>${project.groupId}</groupId> <artifactId>common-utils</artifactId> </dependency> <dependency> <groupId>${project.groupId}</groupId> <artifactId>service-core</artifactId> </dependency> </dependencies> ``` --- ### 步骤 3:执行打包命令 在项目根目录执行: ```bash mvn clean package ``` 结果: - 所有模块依次编译、打包(`.jar` 文件生成到各自的 `target/` 目录) - 最终 `web-api/target/web-api-1.0.0.jar` 是一个**完整的可执行 JAR** - 它内部包含了: - 所有第三方依赖(如 Spring、Jackson 等) - 所有子模块的 class 文件(通过依赖引入并被打包进 fat jar) --- ## ✅ 三、部署时只需要这个 jar 吗?✅ 是的! 你可以将 `web-api/target/web-api-1.0.0.jar` 拷贝到服务器上运行: ```bash java -jar web-api-1.0.0.jar ``` > ✅ 需要单独部署 `common-utils.jar` 或 `service-core.jar` > ✅ 需要上传源码或原始模块 > ✅ 所有内容都已打包进一个 jar --- ## ❌ 常见错误 & 注意事项 | 错误 | 原因 | 解决方案 | |------|------|----------| | `No main manifest attribute` | 没有使用 `spring-boot-maven-plugin` 或未 repackage | 添加插件并启用 `repackage` | | `ClassNotFoundException` 自定义 | 子模块未被正确打包进最终 jar | 检查依赖是否正确定义,且子模块已安装 (`mvn install`) | | 启动失败,找到配置文件 | 配置文件在 classpath 下 | 确保 `src/main/resources/application.yml` 存在 | | 多个模块都有 `main` | 插件知道哪个是入口 | 明确指定 `<mainClass>` | --- ## ✅ 四、推荐最佳实践 1. **只在一个模块中使用 `spring-boot-maven-plugin`**(即启动模块) 2. 其他模块保持普通 jar,不要做成可执行 jar 3. 使用统一版本管理(`<dependencyManagement>`) 4. 构建顺序自动由 Maven 处理(根据依赖决定) 5. 如果要发布到私服,对每个子模块运行 `mvn deploy`(可选) --- ## ✅ 示例:完整可运行流程 ```bash # 在项目根目录执行 mvn clean package # 运行最终 jar java -jar web-api/target/web-api-1.0.0.jar ``` 输出似: ``` . ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v3.1.0) 2025-04-05 10:00:00 INFO ... Started WebApiApplication in 3.2 seconds ``` ✅ 成功启动整个聚合项目! --- ## ✅ 总结回答你的问题: > **“maven怎么对聚合项目打包部署。只需要启动的jar包就可以了吗?”** ✅ **答案是:是的!只要你做到以下几点:** 1. 使用 `spring-boot-maven-plugin` 构建主模块; 2. 主模块依赖了其他业务模块; 3. 执行 `mvn package` 成功生成 fat jar; 4. 将这个 jar 部署到服务器上运行即可。 其余模块需要单独部署,它们的内容已经被包含进去了。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值