为 Scala 项目生成可执行 Jar

问题描述

我有一个包含多个主要方法的 Scala 项目。我想生成一个fat jar,以便我可以运行其中一个main方法相关的代码

build.sbt

lazy val commonSettings = Seq(
  version := "0.1-SNAPSHOT",organization := "my.company",scalaVersion := "2.11.12",test in assembly := {}
)

lazy val app = (project in file("app")).
  settings(commonSettings: _*).
  settings(
    mainClass in assembly := Some("my.test.Category")
  )
assemblyMergeStrategy in assembly := {
  case "reference.conf" => MergeStrategy.concat
  case "meta-inf/services/org.apache.spark.sql.sources.DataSourceRegister" => MergeStrategy.concat
  case PathList("meta-inf",xs@_*) => MergeStrategy.discard
  case _ => MergeStrategy.first
}

plugins.sbt

addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.15.0")

通过这个 Manifest 文件在我的资源文件夹中成功生成

接下来我运行 sbt assembly 并成功生成了可执行的 jar。

当我运行 java -jar category-assembly-0.1.jar 时出现以下错误

没有 main manifest 属性,在 category-assembly-0.1.jar 中

我尝试了互联网上给出的许多步骤,但我不断收到此错误

更新

目前以下内容包含在我的 build.sbt 中。

lazy val spark: Project = project
  .in(file("./spark"))
  .settings(
    mainClass in assembly := Some("my.test.Category"),mainClass in (Compile,packageBin) := Some("my.test.Category"),run) := Some("my.test.Category")
  )
assemblyMergeStrategy in assembly := {
  case "reference.conf" => MergeStrategy.concat
  case "meta-inf/services/org.apache.spark.sql.sources.DataSourceRegister" => MergeStrategy.concat
  case PathList("meta-inf",xs@_*) => MergeStrategy.discard
  case _ => MergeStrategy.first
}

在构建工件并运行命令 sbt assembly 并尝试运行生成的 jar 后,我仍然遇到如下相同的错误

没有 main manifest 属性,在 category-assembly-0.1.jar 中

解决方法

我在 EMR 上部署时遇到了同样的问题。

将以下内容添加到 build.sbt 中的设置中,就可以了。

lazy val spark: Project = project
  .in(file("./spark"))
  .settings(
     ...

     // set the main class for packaging the main jar
     mainClass in (Compile,packageBin) := Some("com.orgname.name.ClassName"),mainClass in (Compile,run) := Some("com.orgname.name.ClassName"),...

  )

这实际上将项目中现有类的名称设置为默认 mainClass。我设置了 packageBin 并运行,所以你应该没问题。

不要忘记将 com.orgname.name.ClassName 重命名为您的类名。

(这只是为了刷新你的记忆)

类名由 <PackageName>/<ClassName> 组成。

例如:

package com.orgname.name

object ClassName {}