HDFS文件运行疑问罗列及解决

目录

[1、scope=provided 和 maven-jar-plugin作用区分](#1、scope=provided 和 maven-jar-plugin作用区分)

一、先分开讲两者各自作用

[1. scope=provided(依赖作用域,控制编译 / 运行是否可见)](#1. scope=provided(依赖作用域,控制编译 / 运行是否可见))

[scope=provided 底层规则(不受打包插件是否显式配置影响)](#scope=provided 底层规则(不受打包插件是否显式配置影响))

[2. maven-jar-plugin(基础 jar 打包插件)](#2. maven-jar-plugin(基础 jar 打包插件))

[2、如果没有 maven-jar-plugin ,hadoop依赖为scope,打包会打包进去吗](#2、如果没有 maven-jar-plugin ,hadoop依赖为scope,打包会打包进去吗)

结论先行

一、为什么不写插件也会打包?

默认无配置时的打包规则

[3、如果我的 HDFS 操作在 Linux 的 Hadoop 集群中运行,那我的 pom 点 xml 文件中是不是就可以不写 Hadoop 相关的依赖?](#3、如果我的 HDFS 操作在 Linux 的 Hadoop 集群中运行,那我的 pom 点 xml 文件中是不是就可以不写 Hadoop 相关的依赖?)

[结论:不能删掉 Hadoop 依赖,必须保留,只是 scope 设为 provided](#结论:不能删掉 Hadoop 依赖,必须保留,只是 scope 设为 provided)

[1. 编译阶段(IDEA 写代码时)必须依赖](#1. 编译阶段(IDEA 写代码时)必须依赖)

[2. 运行阶段(Linux hadoop jar)不需要打包进去](#2. 运行阶段(Linux hadoop jar)不需要打包进去)

[4、不存在 Linux 平台的 Hadoop 集群,只在 Windows 上面安装 Hadoop 可以运行吗?](#4、不存在 Linux 平台的 Hadoop 集群,只在 Windows 上面安装 Hadoop 可以运行吗?)

[5、Maven 打包的过程是什么?](#5、Maven 打包的过程是什么?)

[Maven package 完整执行流程(从 clean 到 jar 产出)](#Maven package 完整执行流程(从 clean 到 jar 产出))

[整条生命周期顺序(mvn clean package)](#整条生命周期顺序(mvn clean package))

简化一句话流程

[结合你 Hadoop 项目重点补充](#结合你 Hadoop 项目重点补充)

[6、Windows 中远程连接虚拟机中的 Hadoop 集群,然后运行 HDFS 操作的过程,用的是本地的依赖还是虚拟机中 Hadoop 集群的依赖,哪些内容用的是本地的?哪些内容是用的远程虚拟机中的?](#6、Windows 中远程连接虚拟机中的 Hadoop 集群,然后运行 HDFS 操作的过程,用的是本地的依赖还是虚拟机中 Hadoop 集群的依赖,哪些内容用的是本地的?哪些内容是用的远程虚拟机中的?)

[分两大场景讲清楚:①IDEA 本地直接运行代码 ②打包 jar 上传 Linux 运行](#分两大场景讲清楚:①IDEA 本地直接运行代码 ②打包 jar 上传 Linux 运行)

[一、场景 1:Windows IDEA 右键 Run.main (),远程连虚拟机 HDFS](#一、场景 1:Windows IDEA 右键 Run.main (),远程连虚拟机 HDFS)

[1. 哪些资源来自【Windows 本地】](#1. 哪些资源来自【Windows 本地】)

[2. 哪些资源来自【远程 Linux 虚拟机 Hadoop 集群】](#2. 哪些资源来自【远程 Linux 虚拟机 Hadoop 集群】)

[3. 一句话区分](#3. 一句话区分)

[二、场景 2:Maven 打包纯净 jar,上传 Linux,执行 hadoop jar xxx.jar](#二、场景 2:Maven 打包纯净 jar,上传 Linux,执行 hadoop jar xxx.jar)

[1. 哪些来自【Windows 本地】](#1. 哪些来自【Windows 本地】)

[2. 哪些来自【远程 Linux 虚拟机】](#2. 哪些来自【远程 Linux 虚拟机】)

[7、连 Linux 服务器的hadoop集群运行HDFS,那么在 Windows 中编写 HDFS 操作的时候,可以不安装 Hadoop 吗?](#7、连 Linux 服务器的hadoop集群运行HDFS,那么在 Windows 中编写 HDFS 操作的时候,可以不安装 Hadoop 吗?)

[情况 1:只写代码、只打包,不在 Windows 本地 Run 执行(只打包上传 Linux 跑)](#情况 1:只写代码、只打包,不在 Windows 本地 Run 执行(只打包上传 Linux 跑))

[情况 2:你需要在 Windows IDEA 里直接运行调试 HDFS 代码](#情况 2:你需要在 Windows IDEA 里直接运行调试 HDFS 代码)

[8、只写代码加打包不用装 Windows Hadoop 吗?我是说打包的时候需要编译吗?编译的时候需要读取 Hadoop 依赖包吗?](#8、只写代码加打包不用装 Windows Hadoop 吗?我是说打包的时候需要编译吗?编译的时候需要读取 Hadoop 依赖包吗?)


1、scope=provided 和 maven-jar-plugin作用区分

一、先分开讲两者各自作用
1. scope=provided(依赖作用域,控制编译 / 运行是否可见)
  1. 编译期可见 IDEA 写代码、mvn compile 编译时,能读取 hadoop-client 里的FileSystem等类,代码不红、编译成功。
  2. 本地运行 main 时可见 Windows 直接 Run 程序,类路径包含 provided 依赖。
  3. 约定语义最终运行环境会自带这套依赖,项目不用自带
  4. 核心:只是依赖可见性规则,不控制打不打进 jar,打包由插件决定。
scope=provided 底层规则(不受打包插件是否显式配置影响)

Maven 依赖作用域是依赖解析规则,优先级高于打包插件:

1、provided 含义:编译、测试阶段需要依赖;运行、打包输出阶段丢弃该依赖

2、不管是默认内置maven-jar-plugin,还是你手动配置 shade/assembly,只要依赖scope=provided:

  • 普通 jar 打包:直接忽略,不打入包
  • shade 插件:默认也不会打包 provided 依赖(除非特殊配置强制包含)
  • assembly 插件是特例:无视 scope,会强行把 provided 依赖全部打进 jar(这也是之前不推荐 assembly 的核心原因)
2. maven-jar-plugin(基础 jar 打包插件)

只做一件事: 仅打包项目自己的代码(target/classes下 class + resources 资源文件),所有第三方依赖(compile /provided)一律不打入 jar。 不管依赖 scope 是 compile 还是 provided,最终 jar 里都不会包含 hadoop、slf4j 等第三方 jar。

2、如果没有 maven-jar-plugin ,hadoop依赖为scope,打包会打包进去吗

结论先行
  1. Maven 项目里,maven-jar-plugin内置默认插件 **,你不在 pom 里显式写,它也会自动生效,不会消失;
  2. 只要 Hadoop 依赖标记 <scope>provided</scope>无论是否手动配置 maven-jar-plugin,都不会打进最终 jar 包

一、为什么不写插件也会打包?

Maven 对jar打包类型项目,内置生命周期绑定:

  • 生命周期package阶段,默认绑定 maven-jar-plugin:jar 目标
  • 就算你的<build><plugins>里完全不写这个插件,Maven 会使用插件内置默认配置,自动生成 jar 包
  • 显式写插件只是为了自定义配置(比如自动写入Main-Class主类),不写只是使用默认行为,打包动作依旧执行。
默认无配置时的打包规则

默认的maven-jar-plugin只会打包:

  • src/main/java编译后的业务 class 文件
  • src/main/resources下资源文件 自动排除
  • scope=provided 的所有依赖
  • scope=test 的测试依赖

3、如果我的 HDFS 操作在 Linux 的 Hadoop 集群中运行,那我的 pom 点 xml 文件中是不是就可以不写 Hadoop 相关的依赖?

结论:不能删掉 Hadoop 依赖,必须保留,只是 scope 设为 provided

分两层给你讲清楚:

1. 编译阶段(IDEA 写代码时)必须依赖

你的代码里有这些导入:java运行

复制代码
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.conf.Configuration;

Maven 在编译你的 .java 文件时,需要找到这些类的定义。 如果 pom 完全删掉 hadoop-client/hadoop-hdfs 依赖:

  • IDEA 代码全红报错;
  • 执行 mvn clean package 直接编译失败,打包都生成不了。

Linux 集群运行时确实自带 Hadoop jar,但编译是在 Windows 本地完成的,本地没有这些类就无法编译。

2. 运行阶段(Linux hadoop jar)不需要打包进去

所以用 <scope>provided</scope> 完美解决:

  • 编译、IDEA 开发时,Maven 加载依赖,代码不报错;
  • 打包时 maven-jar-plugin 不会把这些 jar 打进你的项目包;
  • 上传到 Linux 执行 hadoop jar,命令会自动读取集群 $HADOOP_HOME 下的依赖运行程序。

4、不存在 Linux 平台的 Hadoop 集群,只在 Windows 上面安装 Hadoop 可以运行吗?

不推荐,且体验极差,仅能本地单机伪分布式,坑非常多

1、Windows 原生没有官方完整 Hadoop,所谓 Windows Hadoop 只是第三方修改版,依赖 winutils.exe 做兼容;

2、纯 Windows 单机可以搭「本地伪分布式 HDFS」,不用 Linux 虚拟机,但兼容性、稳定性远不如 Linux;

3、你写的 HDFS Java 代码能本地读写 Windows 上的 HDFS,但大量 API、组件(MapReduce/YARN)极易报错。

5、Maven 打包的过程是什么?

Maven package 完整执行流程(从 clean 到 jar 产出)
整条生命周期顺序(mvn clean package)

1.clean 删除上一次打包生成的 target 文件夹、旧 class、旧 jar,清空产物。

2.validate 校验 检查项目基础信息、依赖是否完整、pom 是否合法。

3.compile 编译

  • 读取 pom 依赖(provided/compile/test);
  • 把 src/main/java 下的 .java 文件编译成 .class 文件;
  • 输出到 target/classes;
  • src/main/resources 资源文件(配置文件)复制到 target/classes。

4.test-compile 测试代码编译 编译 src/test/java 测试类,放到 target/test-classes。

5.test 单元测试 执行 JUnit 测试用例,测试失败直接终止打包。

6.prepare-package 打包前置准备 整理编译好的 class、资源文件。

7.package 打包阶段(核心) 根据你配置的插件执行打包: 你现在用的是 maven-jar-plugin

  • 读取 target/classes 里所有 class + 资源文件;
  • 只把自己项目的 class打进 jar;
  • provided /compile 第三方依赖全部不打入
  • 按照 manifest 配置写入主类信息;
  • 输出 jar 包到 target/xxx.jar。

8.install(package 不会执行,单独 mvn install 才走) 把打好的 jar 安装到本地 Maven 仓库,供其他项目引用。

9.deploy(单独命令才执行) 上传 jar 到远程私服仓库。

简化一句话流程

clean → 校验 → 编译主代码 → 编译测试代码 → 跑单元测试 → 打包 class 与资源 → 生成 jar

结合你 Hadoop 项目重点补充
  1. compile 阶段: scope=provided 的 Hadoop 依赖会被加载,用来识别 FileSystem、Configuration 等类,保证编译不报错。
  2. package 打包阶段: maven-jar-plugin 不会把任何第三方依赖(hadoop、日志包)塞进 jar,只打包你写的代码。
  3. Linux 运行时: hadoop jar 命令会自动加载集群自带的 Hadoop jar 作为运行依赖,弥补包里缺失的类。

6、Windows 中远程连接虚拟机中的 Hadoop 集群,然后运行 HDFS 操作的过程,用的是本地的依赖还是虚拟机中 Hadoop 集群的依赖,哪些内容用的是本地的?哪些内容是用的远程虚拟机中的?

分两大场景讲清楚:①IDEA 本地直接运行代码 ②打包 jar 上传 Linux 运行
一、场景 1:Windows IDEA 右键 Run.main (),远程连虚拟机 HDFS
1. 哪些资源来自【Windows 本地】
  1. Maven 定义的所有依赖(hadoop-client 等) pom 里 scope=provided/compile 的 Hadoop 包,运行时 IDE 会加载本地 Maven 仓库的 jar; 代码里FileSystem、Configuration等类,本地 Maven 仓库提供
  2. Windows 本地 Hadoop 客户端文件(winutils.exe、hadoop.dll) 读取系统变量HADOOP_HOME,处理 Windows 系统权限、本地临时文件,没有这个会直接报错。
  3. 你自己写的 Java 源码编译后的 Class 当前程序逻辑、连接地址、创建文件夹等业务代码,全在 Windows 内存执行。
  4. JVM 虚拟机 Windows 安装的 JDK,程序跑在 Windows 的 Java 进程里。
2. 哪些资源来自【远程 Linux 虚拟机 Hadoop 集群】
  1. HDFS 文件存储 创建目录、读写文件、查看文件列表,真实数据全部存在 Linux 虚拟机的 DataNode 磁盘。
  2. NameNode RPC 服务(端口 9000) Windows 代码只是客户端,所有 HDFS 操作请求(创建文件夹、查询文件)都通过网络发给 Linux 的 NameNode 处理。
  3. 集群权限、用户校验 校验root用户权限、文件读写权限规则由 Linux 集群控制。
  4. 实际数据读写节点 DataNode 文件读写数据流直接走 Windows ↔ Linux DataNode 网络传输。
3. 一句话区分

程序代码、Java 类库、运行环境全在 Windows;HDFS 数据、集群服务、存储全部在 Linux 虚拟机。


二、场景 2:Maven 打包纯净 jar,上传 Linux,执行 hadoop jar xxx.jar
1. 哪些来自【Windows 本地】

只有一样:你自己写的业务 Class 代码(打包进 jar,上传到 Linux)。 Maven 的 Hadoop 依赖、Windows 的 winutils 完全不参与 Linux 运行。

2. 哪些来自【远程 Linux 虚拟机】
  1. Hadoop 全套依赖包 执行hadoop jar时,自动加载$HADOOP_HOME/share/hadoop下所有 jar,提供FileSystem、Configuration类。
  2. Linux 服务器 JDK 程序跑在 Linux 的 JVM 中。
  3. winutils 完全不需要 Linux 原生支持 Hadoop,无 Windows 兼容工具需求。
  4. HDFS 集群服务、数据存储、权限校验,和场景 1 一致,全部由 Linux 集群提供。

7、连 Linux 服务器的hadoop集群运行HDFS,那么在 Windows 中编写 HDFS 操作的时候,可以不安装 Hadoop 吗?

情况 1:只写代码、只打包,不在 Windows 本地 Run 执行(只打包上传 Linux 跑)

可以完全不用安装 Windows Hadoop

  1. 仅依赖 Maven pom 里的 Hadoop 依赖(scope=provided) IDEA 靠本地 Maven 仓库里的 hadoop-client 等 jar 识别类,代码不会爆红、mvn clean package编译打包正常;
  2. 不需要配置 HADOOP_HOME、不需要 winutils.exe;
  3. 限制:你不能右键 Run main 在 Windows 本地调试,一运行就报错:找不到 winutils。
  4. 完整流程:Windows 写代码 → mvn 打包纯净 jar → 上传 Linux 执行hadoop jar
情况 2:你需要在 Windows IDEA 里直接运行调试 HDFS 代码

必须安装 Windows 适配 Hadoop、配置 HADOOP_HOME ,缺一不可。 原因: Windows 系统没有 Linux 原生文件权限接口,Hadoop 客户端运行时强制调用winutils.exe处理本地权限、临时目录,缺少直接抛出异常。 哪怕 pom 依赖齐全,没有 winutils 本地运行直接失败。

1.编码、编译、打包阶段(仅 Maven 生效,和 Windows Hadoop 无关)

  • 识别FileSystem/Configuration等类:来自本地 Maven 仓库下载的 Hadoop 依赖;

  • 编译、打包:只需要 JDK+Maven,不需要本地装 Hadoop;

  • Windows Hadoop、winutils 在这个阶段完全不参与。

  1. Windows 本地运行 main 方法阶段(必须 Windows Hadoop)

启动 Java 进程后,Hadoop 客户端底层会读取HADOOP_HOME加载 winutils,处理 Windows 系统适配; 这一步才会用到本地 Hadoop 文件夹,只打包不上线运行则不需要。

  1. Linux 服务器运行 jar 阶段(完全不需要 Windows Hadoop)

执行hadoop jar时,依赖、运行环境、系统工具全部由 Linux 集群提供,Windows 本地有没有 Hadoop 不影响。

8、只写代码加打包不用装 Windows Hadoop 吗?我是说打包的时候需要编译吗?编译的时候需要读取 Hadoop 依赖包吗?

①编码、编译、打包阶段(只需要 2 样东西)

1、JDK

2、Maven 本地仓库的 hadoop 依赖 jar 包

不需要:Windows 本地解压的 Hadoop、winutils、HADOOP_HOME 环境变量

② IDEA 本地右键 Run 运行 main 方法(才需要 Windows Hadoop)

真正启动 Java 客户端去连接 Linux HDFS 时,Hadoop 底层需要 winutils 处理 Windows 系统权限,此时才依赖本地 Hadoop 文件夹。

所以:你只打包、不本地运行,这一步不会触发。

打包一定会执行编译

mvn clean package 生命周期流程: clean → validate → compile(编译)→ test-compile → test → package package 阶段前置必须执行 compile 编译,无法跳过编译直接打包。

编译阶段必须读取 Maven 下载的 Hadoop 依赖包,来源是pom 里配置的hadoop依赖,Maven 会从远程仓库下载到你本地 Maven 仓库(.m2/repository),编译时 JDK 会加载这些 jar,识别 FileSystem、Configuration 等类,代码不爆红、编译不报错。