一、环境与初始化
要求:
- Maven ≥ 3.8.6
 - Java 11
 
初始化方式:
# 方式一:Archetype(交互式填写 groupId/artifactId/package)
mvn archetype:generate \
-DarchetypeGroupId=org.apache.flink \
-DarchetypeArtifactId=flink-quickstart-java \
-DarchetypeVersion=2.1.0
# 方式二:一键脚本
curl https://flink.apache.org/q/quickstart.sh | bash -s 2.1.0
二、将项目导入 IDE 并能“跑起来”
- IntelliJ IDEA:原生支持 Maven 项目;在 Run/Debug Configurations 勾选
Include dependencies with “Provided” scope(旧版无此选项时,可写一个测试用例调用main()作为变通)。 - Eclipse:安装 m2e 插件导入 Maven 项目。
 
JVM 堆内存:默认堆可能偏小。
- Eclipse:
Run Configurations -> Arguments -> VM Arguments添加:-Xmx800m - IntelliJ:
Help -> Edit Custom VM Options调整。 
三、依赖管理的“黄金法则”
一个 Flink 作业通常需要三类依赖:
(1)Flink API(DataStream、Table/SQL 等)
(2)连接器/格式(Kafka、Filesystem、JSON/Avro 等)
(3)测试工具(例如 JUnit 与 Flink test utils)
(一)常见 API 依赖选择
- DataStream:
flink-streaming-java - Table(Java):
flink-table-api-java - Table + DataStream(Java 桥):
flink-table-api-java-bridge
(Scala 版本请使用_2.12对应构件) 
(二)“provided” 与 “compile” 怎么选?
- Flink 核心/运行时模块(如 
flink-clients、flink-table-runtime、flink-table-planner-loader)
在集群中已有,应设为provided(只编译,不打进 JAR)——避免 JAR 过大 和 版本冲突。 - 必须随 JAR 分发的依赖(连接器、格式库、三方 SDK)
设为compile,并用 Shade 打进 uber/fat JAR。 
一句话记忆:能让集群提供的就 provided;必须带去运行现场的就 compile + shade。
四、典型 pom.xml 片段
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<flink.version>2.1.0</flink.version>
</properties>
<dependencies>
  <!-- (一)APIs(按需添加) -->
    <dependency>
    <groupId>org.apache.flink</groupId>
    <artifactId>flink-streaming-java</artifactId>
    <version>${flink.version}</version>
    </dependency>
    <dependency>
    <groupId>org.apache.flink</groupId>
    <artifactId>flink-table-api-java</artifactId>
    <version>${flink.version}</version>
    </dependency>
    <dependency>
    <groupId>org.apache.flink</groupId>
    <artifactId>flink-table-api-java-bridge</artifactId>
    <version>${flink.version}</version>
    </dependency>
    <!-- (二)连接器/格式(随 JAR 分发,compile) -->
      <dependency>
      <groupId>org.apache.flink</groupId>
      <artifactId>flink-connector-kafka</artifactId>
      <version>${flink.version}</version>
      </dependency>
      <!-- (三)本地运行 main 需要,但集群会提供:设为 provided -->
        <dependency>
        <groupId>org.apache.flink</groupId>
        <artifactId>flink-clients</artifactId>
        <version>${flink.version}</version>
        <scope>provided</scope>
        </dependency>
        <dependency>
        <groupId>org.apache.flink</groupId>
        <artifactId>flink-table-runtime</artifactId>
        <version>${flink.version}</version>
        <scope>provided</scope>
        </dependency>
        <dependency>
        <groupId>org.apache.flink</groupId>
        <artifactId>flink-table-planner-loader</artifactId>
        <version>${flink.version}</version>
        <scope>provided</scope>
        </dependency>
        <!-- (四)测试 -->
          <dependency>
          <groupId>org.apache.flink</groupId>
          <artifactId>flink-test-utils-junit</artifactId>
          <version>${flink.version}</version>
          <scope>test</scope>
          </dependency>
          <dependency>
          <groupId>org.junit.jupiter</groupId>
          <artifactId>junit-jupiter</artifactId>
          <version>5.10.2</version>
          <scope>test</scope>
          </dependency>
        </dependencies>
五、构建与入口类
打包命令:
mvn clean package
产物位于 target/<artifact-id>-<version>.jar。
入口类(mainClass):若主类不是默认 DataStreamJob,请在 pom.xml 的打包配置(或 Shade 的 ManifestResourceTransformer)里设置 mainClass,提交 JAR 时就无需再手动 -c 指定。
六、何时需要 uber/fat JAR?
- 仅用 Flink 自带能力(如 filesystem + JSON) → 不需要 uber JAR,可直接提交普通 JAR。
 - 引入外部依赖/连接器(发行版未内置) →
(一)把依赖放进集群 classpath;
(二)Shade 成 uber/fat JAR(推荐,分发更简单)。 
提交示例:
bin/flink run -c org.example.MyJob myFatJar.jar
七、Maven Shade 插件模板(可直接粘贴)
<build>
  <plugins>
    <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-shade-plugin</artifactId>
    <version>3.1.1</version>
      <executions>
        <execution>
        <phase>package</phase>
        <goals><goal>shade</goal></goals>
          <configuration>
            <artifactSet>
              <excludes>
              <exclude>com.google.code.findbugs:jsr305</exclude>
              </excludes>
            </artifactSet>
            <filters>
              <filter>
                <!-- 不拷贝签名,避免 SecurityException -->
                <artifact>*:*</artifact>
                  <excludes>
                  <exclude>META-INF/*.SF</exclude>
                  <exclude>META-INF/*.DSA</exclude>
                  <exclude>META-INF/*.RSA</exclude>
                  </excludes>
                </filter>
              </filters>
              <transformers>
                <!-- 替换为你的主类 -->
                    <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                  <mainClass>my.programs.main.clazz</mainClass>
                  </transformer>
                  <transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
                </transformers>
              </configuration>
            </execution>
          </executions>
        </plugin>
      </plugins>
    </build>
Shade 默认会打包
compile与runtime作用域依赖;provided不会被打进 JAR。
八、实用小贴士与常见坑
小贴士
(1)IntelliJ 运行作业:勾选 Include dependencies with “Provided” scope,否则本地跑可能找不到 Flink 运行时类。
(2)连接器版本与 Flink 版本对齐,避免 classpath 冲突。
(3)固定入口类:减少提交参数,降低运维摩擦。
常见坑
(1)JAR 体积巨大或冲突:把 flink-clients/table-runtime/planner-loader 打进了 JAR → 改成 provided。
(2)NoSuchMethodError / ClassNotFound:连接器没被 shade 进来或版本不匹配 → 查 dependency:tree 并调整。
(3)IDE 能跑,集群失败:集群侧缺少匹配版本运行时模块 → 对齐集群与本地依赖。
(4)老 IntelliJ 无 provided 选项:用测试用例调用 main() 代跑。
(5)主类不对导致提交失败:pom.xml 未配置 mainClass 或写错 → 在 Shade Manifest 中显式指定。
九、你的下一步
(1)挑一个最小作业(Kafka → 清洗 → Sink),补齐 API + 连接器 依赖。
(2)用 Shade 打出一个 uber JAR,在本地与测试集群各跑一遍。
(3)把打包与提交接入 CI/CD(构建、制品库、部署到 Session/Application Cluster)。
把依赖作用域分得清、Shade 配置写得对、入口类设得明白,你的 Flink 项目就能顺滑地在本地开发、CI 构建与集群部署之间切换。祝你首个 Maven 驱动的 Flink 作业上线顺利!
                    
                
                
            
        
浙公网安备 33010602011771号