目录
运行前提
一、打包
方式 1:IDEA 标准 Artifacts 打包
1.顶部菜单 File → Project Structure(快捷键 Ctrl+Alt+Shift+S)
2.左侧 Artifacts → 右上角 + → JAR → From modules with dependencies
配置弹窗
3.顶部菜单 Build → Build Artifacts → 选中你的 jar → Build编辑
4.注意
方式 2:Maven 打包(最通用,企业首选)
1)pom.xml 添加打包配置 & 主类
2)执行打包
3)注意
二、在linux系统中的hadoop平台执行
1、hadoop已经启动,hadoop命令可执行
2、安全模式已经退出
3、将打包的jar包上传到linux平台中,并使用命令chmod 755添加执行权限
4、执行jar包
附1:MkdirDemo代码
附2:hadoop jar命令使用说明
附3:打包时,是否将依赖打包进入说明
1、Hadoop 相关依赖
关键改动说明
1. 依赖 scope 调整
2. 彻底移除 maven-assembly-plugin
3. shade 插件核心能力
4. 集群运行命令(适配 hadoop jar)
方式 1:使用 shaded 大包(内置 log4j 依赖,无需额外传参)
方式 2:纯净小包 + -libjars 动态加载第三方依赖(包体积更小)
配套避坑操作
附4:打包时指定主类,hadoop jar xxx.jar 直接运行(不用写主类名)
原理
方案 1:maven-shade 插件(你现在使用的 pom,推荐)
方案 2:原生 maven-jar-plugin(无第三方依赖,轻量包),不适合此项目
关键注意事项
运行前提
1、linux中hadoop配置完成,jps显示进程正确
2、linux中hadoop命令可以运行
3、linux中已经退出hadoop安全模式
一、打包
方式 1:IDEA 标准 Artifacts 打包
1.顶部菜单File → Project Structure(快捷键Ctrl+Alt+Shift+S)
2.左侧Artifacts→ 右上角+→JAR → From modules with dependencies
配置弹窗
- Module:选择你的当前项目
- Main class:选中你的
MkdirDemo(包含 main 方法的主类) - Extract to the target JAR(把依赖打进 jar,避免 Linux 缺包报错)
- Directory for META-INF需要改为resource路径
- Apply → OK
3.顶部菜单Build → Build Artifacts→ 选中你的 jar → Build![]()
生成 jar 路径:项目根目录out/artifacts/xxx_jar/xxx.jar
4.注意
Directory for META-INF需要改为resource路径,否则
打包 Jar 时,IDEA 自动在 src/main/java 下生成了 META-INF/MANIFEST.MF;再次打包时工具尝试重新生成,触发冲突。如下图所示
方式 2:Maven 打包(最通用,企业首选)
1)pom.xml 添加打包配置 & 主类
<build> <plugins> <!-- maven打包插件,指定主类,打包所有依赖 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-assembly-plugin</artifactId> <version>3.3.0</version> <executions> <execution> <id>make-assembly</id> <phase>package</phase> <goals> <goal>single</goal> </goals> </execution> </executions> <configuration> <archive> <manifest> <!-- 填写你的主类全限定名 --> <mainClass>MkdirDemo</mainClass> </manifest> </archive> <descriptorRefs> <!-- 将所有依赖打入一个jar包 --> <descriptorRef>jar-with-dependencies</descriptorRef> </descriptorRefs> </configuration> </plugin> </plugins> </build>完整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>org.example</groupId> <artifactId>HDFS-helloworld</artifactId> <version>1.0-SNAPSHOT</version> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>RELEASE</version> </dependency> <dependency> <groupId>org.apache.hadoop</groupId> <artifactId>hadoop-hdfs</artifactId> <version>3.1.3</version> </dependency> <dependency> <groupId>org.apache.hadoop</groupId> <artifactId>hadoop-client</artifactId> <version>3.1.3</version> </dependency> <dependency> <groupId>org.apache.hadoop</groupId> <artifactId>hadoop-common</artifactId> <version>3.1.3</version> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-core</artifactId> <version>2.19.0</version> </dependency> </dependencies> <build> <plugins> <!-- maven打包插件,指定主类,打包所有依赖 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-assembly-plugin</artifactId> <version>3.3.0</version> <executions> <execution> <id>make-assembly</id> <phase>package</phase> <goals> <goal>single</goal> </goals> </execution> </executions> <configuration> <archive> <manifest> <!-- 填写你的主类全限定名 --> <mainClass>MkdirDemo</mainClass> </manifest> </archive> <descriptorRefs> <!-- 将所有依赖打入一个jar包 --> <descriptorRef>jar-with-dependencies</descriptorRef> </descriptorRefs> </configuration> </plugin> </plugins> </build> <properties> <maven.compiler.source>8</maven.compiler.source> <maven.compiler.target>8</maven.compiler.target> </properties> </project>2)执行打包
右侧 Maven 面板 →Lifecycle → package,双击执行
完成后显示finished
打包完成后,jar 包在项目/target/xxx-jar-with-dependencies.jar
3)注意
如果打包后,再次打包报错 Process terminated
原因分析:Process terminated不是具体异常,代表 Maven 打包进程被系统 / IDE 强制终止,最常见诱因是内存溢出、JDK/Maven 版本不兼容、pom 插件配置错误、IDEA 运行器配置异常,尤其你使用jar-with-dependencies(依赖全打进包)时依赖多,极易内存爆掉。
解决方案:File → Invalidate Caches... 勾选:Clear file system cache and local history → Invalidate and Restart即可
方式3:直接使用mvn命令
1:IDEA 内置 Terminal 终端(推荐,不用切文件夹)
- IDEA 底部打开
Terminal - 直接执行清理 + 打包一条命令:
运行
mvn clean packageclean:删除旧 target 文件夹、旧 jar,彻底清空package:编译代码、执行 assembly 插件打包
2:Windows CMD/PowerShell 手动执行
- CMD cd 切换到你的项目根目录(pom.xml 所在文件夹) 示例:
cd D:\javaweb\HDFS-helloworld- 执行打包:
mvn clean package三、打包成功标志
终端输出BUILD SUCCESSjar 包生成路径:项目目录/target/HDFS-helloworld-1.0-jar-with-dependencies.jar
二、在linux系统中的hadoop平台执行
1、hadoop已经启动,hadoop命令可执行
2、安全模式已经退出
3、将打包的jar包上传到linux平台中,并使用命令chmod 755添加执行权限
4、执行jar包
附1:MkdirDemo代码
主要功能是在/目录下创建bigdata文件夹
import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.FileStatus; import org.apache.hadoop.fs.FileSystem; import org.apache.hadoop.fs.Path; import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; public class MkdirDemo { public static FileSystem getFileSystem() throws IOException, URISyntaxException, InterruptedException { Configuration conf=new Configuration(); URI url=new URI("hdfs://192.168.17.128:9000"); final FileSystem fileSystem=FileSystem.get(url,conf,"root"); return fileSystem; } public static void list(String dir) throws Exception{ FileSystem fileSystem=getFileSystem(); FileStatus[] listStatus=fileSystem.listStatus(new Path(dir)); for(FileStatus fileStatus : listStatus){ boolean isDir=fileStatus.isDirectory(); String name=fileStatus.getPath().toString(); System.out.println(isDir+" "+name); } } public static void mkdir(String path) throws Exception{ final FileSystem fileSystem=getFileSystem(); fileSystem.mkdirs(new Path(path)); //遍历文件夹下的内容 list("/"); } public static void create(String path) throws Exception{ final FileSystem fileSystem=getFileSystem(); fileSystem.create(new Path(path)); //遍历文件夹下的内容 list("/"); } public static void delete(String path) throws Exception{ final FileSystem fileSystem=getFileSystem(); fileSystem.delete(new Path(path),true); //遍历文件夹下的内容 list("/"); } public static void main(String[] args) throws Exception{ mkdir("/bigdata"); // delete("bigdata"); // create("demo.txt"); } }附2:hadoop jar命令使用说明
hadoop jar jar包路径 主类全名
hadoop jar HDFS-helloworld.jar MkdirDemo
命令说明:
- hadoop 调用 Hadoop 客户端脚本,加载 Hadoop 运行环境、自带 HDFS/MapReduce 所有依赖包。
- jar 是 hadoop 子命令,专门用来执行打包好的 Java Jar 程序,底层会启动一个内置 JVM。
- HDFS-helloworld.jar 你的本地 Jar 包文件路径(当前目录下的 MkdirDemo.jar),里面存放编写 HDFS 操作代码(创建目录)。
- MkdirDemo是Jar 包内程序入口主类全名(不带包名则代表主类在默认包),等价于 java -cp xxx.jar MkdirDemo。
附3:打包时,是否将依赖打包进入说明
此处只针对场景为:HDFS操作+MR操作。
1、Hadoop 相关依赖
不需要打进 Jar 包,编译时保留、打包剔除集群执行用 hadoop jar 命令时,程序运行依赖的 Hadoop 核心包(hadoop-common、hadoop-hdfs、mapreduce、yarn 等)全部由集群服务自带,运行时自动加载,不用打入自己的业务 Jar。
Maven 中统一设置依赖作用域 provided:
<dependency> <groupId>org.apache.hadoop</groupId> <artifactId>hadoop-common</artifactId> <version>3.3.4</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.apache.hadoop</groupId> <artifactId>hadoop-hdfs</artifactId> <version>3.3.4</version> <scope>provided</scope> </dependency>- provided 含义:IDE 编译、写代码时提供依赖;打包时不会把这些 jar 打进你的包,完美规避大包冲突、内存溢出。
- 优势:解决之前 jar-with-dependencies 打包过大、进程中断、类版本冲突的问题。
- 同时删除原来添加的 maven-assembly-plugin 完整配置
- 无第三方依赖:只用原生 maven-jar-plugin
- 有第三方依赖:改用 maven-shade-plugin,并过滤所有 hadoop 类,不使用 assembly 打包后用命令执行
hadoop jar 你的包.jar 主类全路径
补充:shade 和 provided 搭配是安全的shade 可以手动配置过滤规则,主动排除org/apache/hadoop/**,配合 provided 双重保险,不会冲突:
<filter> <artifact>*:*</artifact> <excludes> <exclude>org/apache/hadoop/**</exclude> <exclude>org/apache/mapreduce/**</exclude> <exclude>org/apache/hdfs/**</exclude> </excludes> </filter>此时原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>org.example</groupId> <artifactId>HDFS-helloworld</artifactId> <version>1.0-SNAPSHOT</version> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>RELEASE</version> </dependency> <dependency> <groupId>org.apache.hadoop</groupId> <artifactId>hadoop-hdfs</artifactId> <version>3.1.3</version> </dependency> <dependency> <groupId>org.apache.hadoop</groupId> <artifactId>hadoop-client</artifactId> <version>3.1.3</version> </dependency> <dependency> <groupId>org.apache.hadoop</groupId> <artifactId>hadoop-common</artifactId> <version>3.1.3</version> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-core</artifactId> <version>2.19.0</version> </dependency> </dependencies> <build> <plugins> <!-- maven打包插件,指定主类,打包所有依赖 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-assembly-plugin</artifactId> <version>3.3.0</version> <executions> <execution> <id>make-assembly</id> <phase>package</phase> <goals> <goal>single</goal> </goals> </execution> </executions> <configuration> <archive> <manifest> <!-- 填写你的主类全限定名 --> <mainClass>MkdirDemo</mainClass> </manifest> </archive> <descriptorRefs> <!-- 将所有依赖打入一个jar包 --> <descriptorRef>jar-with-dependencies</descriptorRef> </descriptorRefs> </configuration> </plugin> </plugins> </build> <properties> <maven.compiler.source>8</maven.compiler.source> <maven.compiler.target>8</maven.compiler.target> </properties> </project>变为:
<?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>org.example</groupId> <artifactId>HDFS-helloworld</artifactId> <version>1.0-SNAPSHOT</version> <properties> <maven.compiler.source>8</maven.compiler.source> <maven.compiler.target>8</maven.compiler.target> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <hadoop.version>3.1.3</hadoop.version> </properties> <dependencies> <!-- 单元测试 --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.13.2</version> <scope>test</scope> </dependency> <!-- Hadoop全部核心依赖 scope=provided 编译用,打包剔除 --> <dependency> <groupId>org.apache.hadoop</groupId> <artifactId>hadoop-hdfs</artifactId> <version>${hadoop.version}</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.apache.hadoop</groupId> <artifactId>hadoop-client</artifactId> <version>${hadoop.version}</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.apache.hadoop</groupId> <artifactId>hadoop-common</artifactId> <version>${hadoop.version}</version> <scope>provided</scope> </dependency> <!-- 第三方日志依赖(非Hadoop自带,会被shade打进包) --> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-core</artifactId> <version>2.19.0</version> </dependency> </dependencies> <build> <plugins> <!-- 基础编译打包插件 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <version>3.3.0</version> </plugin> <!-- Shade插件:只打包第三方依赖,过滤所有Hadoop类,替代assembly --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>3.5.1</version> <executions> <execution> <phase>package</phase> <goals> <goal>shade</goal> </goals> <configuration> <!-- 过滤所有Hadoop集群自带类,不打进Jar,彻底避免冲突 --> <filters> <filter> <artifact>*:*</artifact> <excludes> <exclude>org/apache/hadoop/**</exclude> <exclude>org/apache/yarn/**</exclude> <exclude>org/apache/mapreduce/**</exclude> <exclude>org/apache/hdfs/**</exclude> <exclude>org/apache/hadoop/hdfs/**</exclude> </excludes> </filter> </filters> <!-- 自动生成MANIFEST,指定程序入口主类,无需手动创建META-INF --> <transformers> <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> <!-- 替换为你的完整主类名,如果有包名必须写全包名,例:com.bigdata.MkdirDemo --> <mainClass>MkdirDemo</mainClass> </transformer> </transformers> </configuration> </execution> </executions> </plugin> </plugins> </build> </project>关键改动说明
1. 依赖 scope 调整
- 所有
hadoop-*依赖增加<scope>provided</scope>:Maven 打包时不会把这些依赖打入 jar - junit 设置
<scope>test</scope>:仅测试阶段生效,打包不会带入测试类 - log4j-core 保留默认 compile:属于第三方日志包,shade 会将其打进 jar
2. 彻底移除 maven-assembly-plugin
原 assembly 的jar-with-dependencies会无视 provided 强制打包全部 Hadoop 依赖,和集群自带 Hadoop 类产生冲突,直接删除。
3. shade 插件核心能力
- 自动过滤所有
org/apache/hadoop/**相关 class,双重保险配合 provided - 仅打包你的业务代码 + log4j 等第三方自定义依赖
- 自动生成合法 MANIFEST.MF,不会出现 IDE
already exists in VFS报错 - 打包后生成两个 jar:
HDFS-helloworld-1.0-SNAPSHOT.jar:纯净业务包HDFS-helloworld-1.0-SNAPSHOT-shaded.jar:内置第三方依赖的可运行包
4. 集群运行命令(适配 hadoop jar)
方式 1:使用 shaded 大包(内置 log4j 依赖,无需额外传参)
bash
运行
hadoop jar HDFS-helloworld-1.0-SNAPSHOT-shaded.jar方式 2:纯净小包 + -libjars 动态加载第三方依赖(包体积更小)
bash
运行
hadoop jar HDFS-helloworld-1.0-SNAPSHOT.jar MkdirDemo -libjars log4j-core-2.19.0.jar配套避坑操作
- 删除项目内手动创建的
src/main/java/META-INF文件夹,避免 VFS 文件冲突 - 自定义配置文件、自定义 MANIFEST 资源统一放到
src/main/resources/META-INF - IDE 本地调试时如果报类找不到,临时把 Hadoop 依赖 scope 改为
compile,打包上线切回provided - 打包前执行
mvn clean package,先清空旧 target 目录
附4:打包时指定主类,hadoop jar xxx.jar 直接运行(不用写主类名)
原理
hadoop jar 读取 Jar 内部 META-INF/MANIFEST.MF 里的 Main-Class 属性,如果配置了,命令行可以省略主类全名,直接传业务参数。
下面分两种场景:普通 maven-jar(无第三方依赖)、shade 打包(带第三方依赖,你当前 pom 方案)
方案 1:maven-shade 插件(你现在使用的 pom,推荐)
shade 通过 ManifestResourceTransformer 自动写入 Main-Class,无需手动创建 META-INF 文件,完美规避 IDE VFS 文件重复报错。
关键配置片段(已整合到你之前优化后的 pom)
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>3.5.1</version> <executions> <execution> <phase>package</phase> <goals> <goal>shade</goal> </goals> <configuration> <!-- 过滤hadoop依赖,防止冲突 --> <filters> <filter> <artifact>*:*</artifact> <excludes> <exclude>org/apache/hadoop/**</exclude> <exclude>org/apache/yarn/**</exclude> <exclude>org/apache/mapreduce/**</exclude> </excludes> </filter> </filters> <!-- 自动生成MANIFEST,配置默认主类 --> <transformers> <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> <!-- 这里替换成你的完整主类名,有包必须写全包名,例如 com.test.MkdirDemo --> <mainClass>MkdirDemo</mainClass> </transformer> </transformers> </configuration> </execution> </executions> </plugin>使用效果打包后生成 xxx-shaded.jar,执行命令直接省略主类:
# 无需写 MkdirDemo,直接运行
hadoop jar HDFS-helloworld-1.0-SNAPSHOT-shaded.jar
方案 2:原生 maven-jar-plugin(无第三方依赖,轻量包),不适合此项目
如果你的项目没有 log4j 等第三方包,只用基础打包插件,通过 manifestEntries 配置主类:
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <version>3.3.0</version> <configuration> <archive> <manifest> <!-- 自动生成Main-Class --> <mainClass>MkdirDemo</mainClass> </manifest> </archive> </configuration> </plugin>运行命令:
hadoop jar HDFS-helloworld-1.0-SNAPSHOT.jar
此时完整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>org.example</groupId> <artifactId>HDFS-helloworld</artifactId> <version>1.0-SNAPSHOT</version> <properties> <maven.compiler.source>8</maven.compiler.source> <maven.compiler.target>8</maven.compiler.target> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <hadoop.version>3.1.3</hadoop.version> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.13.2</version> <scope>test</scope> </dependency> <!-- Hadoop依赖全部provided,打包不打入 --> <dependency> <groupId>org.apache.hadoop</groupId> <artifactId>hadoop-hdfs</artifactId> <version>${hadoop.version}</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.apache.hadoop</groupId> <artifactId>hadoop-client</artifactId> <version>${hadoop.version}</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.apache.hadoop</groupId> <artifactId>hadoop-common</artifactId> <version>${hadoop.version}</version> <scope>provided</scope> </dependency> <!-- 第三方日志依赖,shade会打入包内 --> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-core</artifactId> <version>2.19.0</version> </dependency> </dependencies> <build> <plugins> <!-- 基础打包插件 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <version>3.3.0</version> </plugin> <!-- Shade插件:过滤hadoop依赖 + 配置默认主类 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>3.5.1</version> <executions> <execution> <phase>package</phase> <goals> <goal>shade</goal> </goals> <configuration> <filters> <filter> <artifact>*:*</artifact> <excludes> <exclude>org/apache/hadoop/**</exclude> <exclude>org/apache/yarn/**</exclude> <exclude>org/apache/mapreduce/**</exclude> </excludes> </filter> </filters> <!-- 核心:设置Jar默认主类 --> <transformers> <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> <!-- 重点:替换为你项目的完整类名!! --> <mainClass>MkdirDemo</mainClass> </transformer> </transformers> </configuration> </execution> </executions> </plugin> </plugins> </build> </project>关键注意事项
- 主类必须写全限定名如果你的类在包下,比如
com.bigdata.MkdirDemo,不能只写MkdirDemo,否则运行报错找不到类。 - 禁止手动创建
src/main/java/META-INF/MANIFEST.MFMaven/shade 会自动生成清单文件,手动创建会触发already exists in VFSIDE 报错。 - 打包执行命令,运行
target 目录会生成两个包:mvn clean packageHDFS-helloworld-1.0-SNAPSHOT.jar:纯净源码包,无第三方依赖,不带自动主类(需要手动传主类名)HDFS-helloworld-1.0-SNAPSHOT-shaded.jar:内置第三方依赖,配置好默认主类,直接用hadoop jar运行