![Scala编程实战(原书第2版)](https://wfqqreader-1252317822.image.myqcloud.com/cover/899/48593899/b_48593899.jpg)
1.6 运行JAR文件
问题
你想使用scala或java命令来运行一个从Scala应用程序创建的JAR文件。
解决方案
首先,像我在17.1节演示的那样,创建一个最基础的sbt项目目录结构。然后在project/plugins.sbt文件中加入下面这行代码来将sbt-assembly(https://oreil.ly/Q6CUr)加入项目配置中:
![](https://epubservercos.yuewen.com/87A2C8/28235253302644106/epubprivate/OEBPS/Images/43_01.jpg?sign=1738955244-Jjv5fbQ3LuipXyeG0tz8cVpFuzX3DyAp-0-0b2f6af9d3cdba9ac983a0bb3b062cd5)
然后将下面的Hello.scala源代码文件放到该项目的根目录中:
![](https://epubservercos.yuewen.com/87A2C8/28235253302644106/epubprivate/OEBPS/Images/43_02.jpg?sign=1738955244-Yy4smn0b7Cw6awL3chO01UI5Ucrtsvsc-0-c18ab453932cd1aca93d385d462babc2)
下一步,在sbt shell中使用assembly或者show assembly来创建一个JAR文件:
![](https://epubservercos.yuewen.com/87A2C8/28235253302644106/epubprivate/OEBPS/Images/43_03.jpg?sign=1738955244-lrLunjhOl0FYj2aYkXKXFLF2W0a0OFvF-0-9b85e98ddcfd7498ad56444414f1fd22)
如上所示,show assembly命令输出了生成JAR文件的位置。这个文件名之所以以RunJarFile开头,是因为我创建的build.sbt文件中name字段的值就是RunJarFile。同样,文件名中的0.1.0部分来自该文件的version字段:
![](https://epubservercos.yuewen.com/87A2C8/28235253302644106/epubprivate/OEBPS/Images/44_01.jpg?sign=1738955244-g0zLKyJTFhq4TOdEmAuy3naWYTq1jU9G-0-f6f28d927aab9ed0b08d052c0153cf61)
接下来,创建一个名为Example的子目录,并将JAR文件复制到该目录:
![](https://epubservercos.yuewen.com/87A2C8/28235253302644106/epubprivate/OEBPS/Images/44_02.jpg?sign=1738955244-CpJ9azNIuTroo3ztdKTy6cGcyulcO3qQ-0-49100b406f14cf5e4316ceb1d50cfccb)
因为sbt-assembly会将所需要的所有东西全部打包到JAR文件中,所以可以使用下面的scala命令来运行名为hello的main方法:
![](https://epubservercos.yuewen.com/87A2C8/28235253302644106/epubprivate/OEBPS/Images/44_03.jpg?sign=1738955244-7Aimr6ceM6jGUKjibmUQMqiFb9w6Fxy9-0-5b575c98e6958c580591b72e49692852)
注意,如果JAR包中存在多个@main方法,可以通过在命令的末尾指定方法的完整路径的方式来运行它们:
![](https://epubservercos.yuewen.com/87A2C8/28235253302644106/epubprivate/OEBPS/Images/44_04.jpg?sign=1738955244-H9OU3glKCiAa9t1GXYrYQlJj5q4WyrKR-0-63ee59ecc4597e28b520004284934ffd)
讨论
如果试图使用java命令来运行JAR文件或者用sbt package而非sbt assembly来打包JAR文件,就需要手动将JAR文件的依赖添加到classpath中。比如,当使用java命令运行一个JAR文件时,需要这样做:
![](https://epubservercos.yuewen.com/87A2C8/28235253302644106/epubprivate/OEBPS/Images/44_05.jpg?sign=1738955244-LeijkzQvL578d8CzVcdWc6uDcqEBGUz3-0-c14ec4c63a7a40b9b4d77d8d8ed77423)
注意,整个java命令应该在一行,包括行末的foo.bar.Hello部分。
要使用这种方式,你需要找到scala-library.jar文件。在我的例子中,因为Scala 3发行版是手动管理的,所以它被放在了如上所示的目录中。如果使用像Coursier(https://get-coursier.io)这样的工具来管理Scala安装,那么它下载的文件可以在下面的目录里找到:
·macOS:~/Library/Caches/Coursier/v1。
·Linux:~/.cache/coursier/v1。
·Windows:%LOCALAPPDATA%\Coursier\Cache\v1。假设用户名是Alvin,通常这个路径对应的是C:\Users\Alvin\AppData\Local\Coursier\Cache\v1。
有关这些目录的最新细节,请参阅Coursier Cache网页(https://oreil.ly/Rs4dV)。
为什么要使用sbt-assembly
注意,如果应用程序使用了托管依赖或非托管依赖,并且你使用的是sbt package而非sbt assembly,就必须了解并找到所有有依赖以及有传递依赖的JAR文件,并将其包含在classpath中。这就是为什么强烈建议使用sbt assembly或类似的工具来打包。
另见
·请参阅17.11节以了解更多关于如何配置和使用sbt-assembly的细节。