• 简化基于Maven的Scala项目创建详解

    使用 Maven 来构建 Scala 项目方便虽然方便,但依赖于每一个开发人员都去配置一遍项目的必要依赖,包括 Scala 插件的编译配置以及 Scala 的依赖类库,让每个人通过拷贝(Copy)之前的项目配置当然可以,但难免会出些纰漏。

    而从头开始所有相关配置项都配置一遍,又略显繁琐,那么,我们可不可以想办法来进一步简化类似的基于 Maven 的 Scala 项目创建和配置?

    使用代码片段管理工具

    实际上,我们通常都会有收集的嗜好,尤其是作为一名软件开发者,都会有一套自己的代码片段管理工具或者套路,将一些常用的或者自己感觉经典的代码片段及配置内容进行摘录并保存。

    现在有很多不错的代码片段管理工具,比如 Mac 系统上的 Dash(https://kapeli.com/dash),它可以帮助我们一站式索引技术文档并管理代码片段,有了像 Dash 这样的工具,我们就可以将基于 Maven 的 Scala 项目配置文件整理成一个代码片段(Snippet)进行管理。

    然后在使用的时候直接在 Maven 的 pom.xml 中输入该代码片段的标志信息,mvn.scala.cfg`Dash 将会自动将我们配置的代码片段的内容展开并替换现有 pom.xml 的内容。

    这种方法简单、快速、模板化、可重复,但只适合单一开发人员,如果一个团队或者组织内部所有人都使用这种方式,代码片段的内容同步,以及 Dash 等软件的授权等都是随之衍生出来需要进一步解决的问题。所以,为了能够使更大层面的开发者收益,我们需要寻找更加有效的方法。

    创建 spring-boot-starter-scala 简化 Scala 依赖配置

    对于基于 Maven 的 Scala 项目来说,以下依赖是必不可少的:

    <dependency>
        <groupId>org.scala-lang</groupId>
        <artifactId>scala-library</artifactId>
        <version>${scala.version}</version>
    </dependency>
    <dependency>
        <groupId>org.scala-lang</groupId>
        <artifactId>scala-compiler</artifactId>
        <version>${scala.version}</version>
    </dependency>

    那么,我们可以先从这里进行简化,为了避免所有人都重复配置这部分依赖内容,可以构建一个 spring-boot-starter-scala 自动配置模块,这样,所有开发者只要在自己的项目中依赖这一个 spring-boot-starter-scala 自动配置模块就可以了。

    我们依然可以通过 http://start.spring.io 脚手架服务创建 spring-boot-starter-scala 项目,然后将最终的 pom.xml 配置如下:

    <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>com.keevol.springboot</groupId>
        <artifactId>spring-boot-starter-scala</artifactId>
        <version>1.0-SNAPSHOT</version>
        <packaging>jar</packaging>
        <name>spring-boot-starter-scala</name>
        <url>http://maven.apache.org</url>
        <properties>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <java.version>1.8</java.version>
            <scala.version>2.11.7</scala.version>
            <scala.maven.version>3.2.2</scala.maven.version>
        </properties>
        <build>
            <plugins>
                <plugin>
                    <groupId>net.alchim31.maven</groupId>
                    <artifactId>scala-maven-plugin</artifactId>
                    <version>${scala.maven.version}</version>
                    <executions>
                        <execution>
                            <id>compile-scala</id>
                            <phase>compile</phase>
                            <goals>
                                <goal>add-source</goal>
                                <goal>compile</goal>
                            </goals>
                        </execution>
                        <execution>
                            <id>test-compile-scala</id>
                            <phase>test-compile</phase>
                            <goals>
                                <goal>add-source</goal>
                                <goal>testCompile</goal>
                            </goals>
                        </execution>
                    </executions>
                    <configuration>
                        <recompileMode>incremental</recompileMode>
                        <scalaVersion>${scala.version}</scalaVersion>
                        <args>
                            <arg>-deprecation</arg>
                        </args>
                        <jvmArgs>
                            <jvmArg>-Xms64m</jvmArg>
                            <jvmArg>-Xmx1024m</jvmArg>
                        </jvmArgs>
                    </configuration>
                </plugin>
            </plugins>
        </build>
        <dependencies>
            <dependency>
                <groupId>org.scala-lang</groupId>
                <artifactId>scala-library</artifactId>
                <version>${scala.version}</version>
            </dependency>
            <dependency>
                <groupId>org.scala-lang</groupId>
                <artifactId>scala-compiler</artifactId>
                <version>${scala.version}</version>
            </dependency>
        </dependencies>
    </project>

    然后通过 mvn install 或者 mvn deploy 将其发布。

    现在,创建任何一个基于 Maven 的 Scala 项目时,pom.xml 配置内容就可以简化如下:

    <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>com.keevol.springboot</groupId>
        <artifactId>spring-boot-starter-scala-user</artifactId>
        <version>1.0-SNAPSHOT</version>
        <packaging>jar</packaging>
        <name>spring-boot-starter-scala-user</name>
        <url>http://maven.apache.org</url>
        <dependencies>
            <dependency>
                <groupId>com.keevol.springboot</groupId>
                <artifactId>spring-boot-starter-scala</artifactId>
                <version>1.0-SNAPSHOT</version>
            </dependency>
        </dependencies>
    </project>

    是不是更加简洁和方便了?但是,等一下,如果大家都这样认为,那就有问题了。

    实际上,这样的做法是行不通的,Maven 项目的依赖可以传递依赖(Transitive dependency),但是插件(Plugin)却不行。如果我们真得在前面的项目配置上进行工作的话,spring-boot-starter-scala-user 可以编译成功,可以打包成功,可以发布成功,但是,在整个过程中 Maven 无法识别 Scala 代码。

    所以,如果要让基于 spring-boot-starter-scala 的想法可以实现,我们需要将 scala-maven-plugin 从 spring-boot-starter-scala 项目中移到 spring-boot-starter-scala-user 项目。

    spring-boot-starter-scala 项目的配置现如下:

    <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>com.keevol.springboot</groupId>
        <artifactId>spring-boot-starter-scala</artifactId>
        <version>1.0-SNAPSHOT</version>
        <packaging>jar</packaging>
        <name>spring-boot-starter-scala</name>
        <url>http://maven.apache.org</url>
        <properties>
            <scala.version>2.11.7</scala.version>
        </properties>
        <dependencies>
            <dependency>
                <groupId>org.scala-lang</groupId>
                <artifactId>scala-library</artifactId>
                <version>${scala.version}</version>
            </dependency>
            <dependency>
                <groupId>org.scala-lang</groupId>
                <artifactId>scala-compiler</artifactId>
                <version>${scala.version}</version>
            </dependency>
        </dependencies>
    </project>

    spring-boot-starter-scala-user 的项目配置则如下:

    <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>com.keevol.springboot</groupId>
        <artifactId>spring-boot-starter-scala-user</artifactId>
        <version>1.0-SNAPSHOT</version>
        <packaging>jar</packaging>
        <name>spring-boot-starter-scala-user</name>
        <url>http://maven.apache.org</url>
        <properties>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <java.version>1.8</java.version>
            <scala.version>2.11.7</scala.version>
            <scala.maven.version>3.2.2</scala.maven.version>
        </properties>
        <build>
            <plugins>
                <plugin>
                    <groupId>net.alchim31.maven</groupId>
                    <artifactId>scala-maven-plugin</artifactId>
                    <version>${scala.maven.version}</version>
                    <executions>
                        <execution>
                            <id>compile-scala</id>
                            <phase>compile</phase>
                            <goals>
                                <goal>add-source</goal>
                                <goal>compile</goal>
                            </goals>
                        </execution>
                        <execution>
                            <id>test-compile-scala</id>
                            <phase>test-compile</phase>
                            <goals>
                                <goal>add-source</goal>
                                <goal>testCompile</goal>
                            </goals>
                        </execution>
                    </executions>
                    <configuration>
                        <recompileMode>incremental</recompileMode>
                        <scalaVersion>${scala.version}</scalaVersion>
                        <args>
                            <arg>-deprecation</arg>
                        </args>
                        <jvmArgs>
                            <jvmArg>-Xms64m</jvmArg>
                            <jvmArg>-Xmx1024m</jvmArg>
                        </jvmArgs>
                    </configuration>
                </plugin>
            </plugins>
        </build>
        <dependencies>
            <dependency>
                <groupId>com.keevol.springboot</groupId>
                <artifactId>spring-boot-starter-scala</artifactId>
                <version>1.0-SNAPSHOT</version>
            </dependency>
        </dependencies>
    </project> 

    现在看来,spring-boot-starter-scala 只是帮助我们简化了依赖管理,但对于 Scala 编译插件相关的简化则于事无补,像 spring-boot-starter-scala-user 这样的一大批基于 Maven 的 Scala 项目还是要一遍一遍地配置 Scala 编译插件相关内容。

    不过,如果我们暂时能够忍受每个项目自己配置 Scala 编译插件的话(个人、小团队一般可以甚至也愿意),可以先进一步简化依赖 spring-boot-starter-scala 项目的 SpringBoot 微服务项目的创建。

    我们经常用的 http://start.spring.io 它罗列了很多现有的 spring-boot-starter 自动配置模块供我们在创建 SpringBoot 项目的时候使用,如图 1 所示。

    SPRING INITIALIZR自动配置模块可用列表示意图
    图 1  SPRING INITIALIZR自动配置模块可用列表示意图

更多...

加载中...