转载

使用maven构建scala项目

构建及编译scala工程我使用过三种工具:sbt、gradle和maven。

感谢GFW,sbt的速度慢得让人心碎。即使使用诸如广谈公服等加速方案,也还是会遇到各种各样的问题(比如时不时的lock住)。所以pass。

gradle是最让人惊喜的一个方案,简洁便利上超过sbt,更远胜maven,执行速度也没短板。只有下载源码这问题让我头疼,但也是小问题。然而,关键是公司发布环境不支持gradle,所以一切休谈。

最后是maven。有人说比起gradle来,maven是老人脸上的皱纹。意思是maven的配置非常繁琐,显得过时了。比喻非常形象。但是老人的好处就是经验丰富,很多问题都能很快找到解决方案,虽然略嫌啰嗦但却让人放心。所以最终还是使用maven管理和构建生产环境中的scala项目。

介绍下如何使用maven构建scala工程。

编译

下面是一个示例pom文件:

<?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.chobit.scala</groupId>
    <artifactId>scala-maven-build</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>
 
    <properties>
        <spark.version>2.3.4</spark.version>
        <scala.version>2.13.1</scala.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
 
    <dependencies>
        <dependency>
            <groupId>org.scala-lang</groupId>
            <artifactId>scala-compiler</artifactId>
            <version>${scala.version}</version>
        </dependency>
 
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
 
 
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.scala-lang</groupId>
                <artifactId>scala-compiler</artifactId>
                <version>${scala.version}</version>
            </dependency>
            <dependency>
                <groupId>org.scala-lang</groupId>
                <artifactId>scala-reflect</artifactId>
                <version>${scala.version}</version>
            </dependency>
            <dependency>
                <groupId>org.scala-lang</groupId>
                <artifactId>scala-library</artifactId>
                <version>${scala.version}</version>
            </dependency>
        </dependencies>
    </dependencyManagement>
 
    <build>
        <sourceDirectory>src/main/scala</sourceDirectory>
        <testSourceDirectory>src/test/scala</testSourceDirectory>
 
        <plugins>
            <plugin>
                <groupId>org.scala-tools</groupId>
                <artifactId>maven-scala-plugin</artifactId>
                <version>2.15.2</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>compile</goal>
                            <goal>testCompile</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
 
        <finalName>myApp</finalName>
    </build>
 
</project>

scala环境最重要的三个依赖:scala-compiler、scala-reflect和scala-library都可以通过scala-compiler及其间接依赖获取到。

一些依赖可能会间接引用不同版本的scala,所以在 < dependencyManagement > 中做了下scala版本的统一。

< build > 中使用了 maven-scala-plugin 插件来执行scala的编译,不然在测试执行时会提示“ 错误: 找不到或无法加载主类 chobit.MyDriver ”这样的错误。

打包

如果有打包需求的话建议使用assembly插件执行打包。assembly支持的打包方案非常丰富,算是同类产品里最好的。

看个打包的示例:

首先添加assembly插件

	<plugin>
	    <groupId>org.apache.maven.plugins</groupId>
	    <artifactId>maven-assembly-plugin</artifactId>
	    <version>3.2.0</version>
 
	    <!--指定打包配置文件-->
	    <configuration>
		  <descriptors>
			<descriptor>src/main/assembly.xml</descriptor>
		  </descriptors>
	    </configuration>
 
	    <!--设定在package阶段执行assembly-->
	    <executions>
		  <execution>
			<id>make-assembly</id>
			<phase>package</phase>
			<goals>
			    <goal>single</goal>
			</goals>
		  </execution>
	    </executions>
	</plugin>

这里的配置设置了两个重要信息:

  • 打包配置文件的具体位置:src/main/assembly.xml;
  • 在package阶段自动执行assembly插件;如果没有指明,就得执行 mvn assembly : assembly 命令来进行打包。

打包配置文件的详情:

<?xml version="1.0" encoding="UTF-8"?>
 
<assembly>
 
    <!--这个id会出现在zip包名称的后面,zip文件的最终名称为:artifactId-version-id.zip -->
    <id>full</id>
 
    <!--设定打包格式,支持zip、tar、tar.gz (or tgz)、tar.bz2 (or tbz2)、jar、dir、war-->
    <formats>
        <format>zip</format>
    </formats>
 
    <dependencySets>
        <!-- 用来定制工程依赖 jar 包的打包方式,依赖包的输出路径 -->
        <dependencySet>
            <!--依赖包存储位置-->
            <outputDirectory>/libs</outputDirectory>
            <useProjectArtifact>false</useProjectArtifact>
            <includes>
                <!--配置要将哪些依赖的jar打到包里-->
                <include>org.chobit.wp:wordpress-client</include>
            </includes>
        </dependencySet>
    </dependencySets>
 
    <includeBaseDirectory>true</includeBaseDirectory>
 
    <!--指设置需要包含的其他文件-->
    <fileSets>
        <!--打包jar文件-->
        <fileSet>
            <!-- 在包中的存储位置 -->
            <outputDirectory>/</outputDirectory>
            <!-- 源文件路径 -->
            <directory>target</directory>
            <includes>
                <include>*.jar</include>
            </includes>
        </fileSet>
 
        <!--打包配置文件-->
        <fileSet>
            <outputDirectory>/</outputDirectory>
            <directory>src/main/resources</directory>
            <includes>
                <include>*.properties</include>
                <include>*.conf</include>
            </includes>
        </fileSet>
 
        <!--打包shell文件-->
        <fileSet>
            <outputDirectory>/shell</outputDirectory>
            <directory>shell</directory>
            <includes>
                <include>*.sh</include>
            </includes>
        </fileSet>
    </fileSets>
</assembly>

配置文件中的注释应该已经足够说明用法了。

这里的代码是从一个spark工程上copy来的,所以会有将工程打包成zip文件,又包含shell脚本这样的内容。

在windows主机上执行 mvn clean package 命令时,可能会遇到这样的错误:

[ERROR] OS=Windows and the assembly descriptor contains a *nix-specific root-relative reference (starting with slash): /
[ERROR] OS=Windows and the assembly descriptor contains a *nix-specific root-relative reference (starting with slash): /
[ERROR] OS=Windows and the assembly descriptor contains a *nix-specific root-relative reference (starting with slash): /shell

解决方案有两个:

  • 如果要把文件放在zip包下的根目录,可以直接将 < outputDirectory > 标签闭合,如: < outputDirectory / >
  • 如果要把文件放在zip包下的其他目录,可以使用相对路径,如: < outputDirectory > . / shell < / outputDirectory >

示例代码见: GitHub / Zhyea 。

参考文档

  • Scala With Maven
原文  https://www.zhyea.com/2019/12/16/build-scala-project-with-maven.html
正文到此结束
Loading...