使用Scala开发现代应用程序:使用SBT构建

本文是我们名为“ 使用Scala开发现代应用程序 ”的学院课程的一部分。

在本课程中,我们提供一个框架和工具集,以便您可以开发现代的Scala应用程序。 我们涵盖了广泛的主题,从SBT构建和响应式应用程序到测试和数据库访问。 通过我们简单易懂的教程,您将能够在最短的时间内启动并运行自己的项目。 在这里查看

1.简介

对于许多经验丰富的Java开发人员而言,Scala编程语言并不陌生。 它已经存在了一段时间(从2004年首次公开发布以来已经正式存在),并且在最近几年吸引了很多人。

为什么要选择Scala而不是Java,Clojure,Groovy,Kotlin,Ceylon等有很多原因,我们在本教程中不会对此进行讨论。 但是,我们要谈论的是Scala社区多年来开发的工具,框架和库的生态系统,旨在为开发人员提供原生的Scala体验。

我们将从构建工具和测试框架等基础知识开始,讨论反应性应用程序的原理,访问数据存储,并发性和并行性,最后概述构建构建控制台应用程序,Web服务和全面功能的典型选择。网络应用程序。

2.构建工具:每个项目的坚实基础

每个软件项目在早期阶段都面临的首要任务之一是如何构建和管理其依赖项。 工具的选择范围从定制的外壳脚本, make ,基于XML的Apache AntApache MavenApache Ivy到真正复杂的工具(例如GradleApache Buildr)

3. SBT :(不是)简单构建工具

毫无疑问,Scala社区对项目的构建有自己的见解,而依赖管理( SBT )或简单的构建工具就是对此的直接证实。 SBT与任何其他构建工具都不同,首先是因为SBT使用Scala语言描述了构建定义。

在当前的版本0.13.11中SBT仍在向1.0版本迈进的旅程(希望很快会发生)。 安装SBT的最简单方法是将其下载为独立于平台的归档文件 ,将其解压缩到某个位置,然后将该位置包含在您的操作系统PATH环境变量中。

请注意,应该先安装适当的Java版本(至少是Java 7,但如今建议使用Java 8发行版)。

尽管SBT中的 S表示“简单” ,但对于许多开发人员而言,听起来并非如此。 可能是因为描述了项目构建的方式(本质上是键/值对),或者可能是由于存在多种创建构建定义的方法(使用.sbt.scala文件)。 尽管如此,在本节中,我们将揭开一些SBT概念的神秘面纱,希望使这个功能强大的工具真正易于理解和使用。

这里要指出的是, SBT确实是功能强大且功能丰富的工具,值得编写完整的教程。 我们将讨论一些基本概念,以便让我们快速入门,但是请随时查看在线提供全面文档

4.项目结构

大多数构建工具都试图强加一些有关项目布局外观的约定。 SBT不会再引入另一种,而是遵循与Apache Maven相同的项目布局约定,例如:

<project-name>
    | - project ;
    | - src
    | - main
    |     | - scala
    |     | - resources
    | - test
          | - scala
          | - resources

这种布局中唯一的陌生人是项目子文件夹。 它特定于SBT ,在许多情况下仅包含两个文件:

  • 具有所需SBT版本的属性 ,例如:
    sbt.version=0.13.11
  • 带有其他SBT插件列表的sbt ,例如:
    addSbtPlugin("com.typesafe.sbteclipse" % "sbteclipse-plugin" % "4.0.0")

尽管plugins.sbt仍被广泛使用,但较新的SBT版本倾向于使用一些不同的方法,如SBT文档的“ 使用插件”部分所述。

5.构建定义

正如我们已经简要介绍过的那样, SBT支持多种创建构建定义的方法:使用.sbt文件和.scala文件。 此外,关于.sbt文件,存在所谓的 .sbt文件,这些文件不再应使用,但由于我们经常在野外遇到它们,因此我们将对其进行一些讨论。

本质上,无论您要使用哪种方法,最后的结果总是相同的:将每个项目的描述作为一组键/值对提供,通常称为设置 。 除设置外SBT还具有非常重要的任务概念(例如compilepackagerun )和配置 (例如CompileRuntimeTest )。 话虽如此,根据任务和/或配置,每个设置可能具有不同的值,因此可以说设置 (或更确切地说是设置 )与某个范围(或仅范围)相关联。 在幕后,它当然比听起来复杂,但是以这种方式考虑构建定义是一个很好的起点。 出于好奇, SBT在线文档的.sbt构建定义Scopes部分会更深入地介绍细节。

在接下来的两节中,我们将使用最简单的单模块项目以及更复杂的多模块项目来研究不同的SBT构建定义。 我们将讨论两种使用.sbt.scala文件的构建定义样式,因此我们可以选择一种更贴近您的想法

6.单模块项目

仅使用SBT构建定义build.sbt文件中的几行即可轻松构建包含单个模块的项目,例如:

lazy val main = (project in file("."))
  .settings(
    name := "single-module-sbt",
    version := "0.0.1-SNAPSHOT",
    scalaVersion := "2.11.8",
    libraryDependencies ++= Seq(
      "ch.qos.logback" % "logback-classic" % "1.1.2"
    ),
    resolvers += "Typesafe" at "https://repo.typesafe.com/typesafe/releases/",
    mainClass in (Compile, run) := Some("com.javacodegeeks.single.App")
  )

基本上就是完整的构建定义! 简而言之,我们只是将当前目录称为项目:

lazy val main = (project in file("."))

并定义了一对命名对(键/值对或设置),例如nameversionscalaVersion,libraryDependencies和resolvers 。 在这方面, mainClass分开站立,因为它另外包括配置( Compile )和任务( run )范围。

到目前为止,这是在Scala项目(以及SBT支持的其他语言编写的项目)中使用SBT的推荐方法。 使用.scala.sbt裸样式被认为不赞成使用。 尽管如此,让我们看看从.scala开始的这两个示例,因为您当前的项目中有一个或多个可能已经使用了它们。

基于.scala的内部版本的传统组织方式是在项目文件夹中将Build.scala文件作为入口点。 例如,相同的构建定义看起来会有些不同,但仍然足够接近:

import sbt._
import Keys._

object ProjectBuild extends Build {
  override val settings = super.settings ++ Seq(
    name := "single-module-sbt",
    version := "0.0.1-SNAPSHOT",
    scalaVersion := "2.11.8",
    libraryDependencies ++= Seq(
      "ch.qos.logback" % "logback-classic" % "1.1.2"
    ),
    resolvers += "Typesafe" at "https://repo.typesafe.com/typesafe/releases/"
  )

  lazy val main = Project(
    id = "single-module-scala",
    base = file("."),
    settings = Project.defaultSettings ++ Seq(
      mainClass in (Compile, run) := Some("com.javacodegeeks.single.App")
    )
  )
}

与以前的.sbt版本相比,此构建定义看起来更加冗长,并且编写了大量代码。 当然,它仍然可读,但是推荐方法的好处显而易见。 要阅读有关.scala构建定义的更多信息,请查看官方文档

最后,让我们看一下可能的最简单的构建定义之一,这些天使用所谓的.sbt文件。

name := "bare-module-sbt"

version := "0.0.1-SNAPSHOT"

scalaVersion := "2.11.8"

libraryDependencies ++= Seq(
  "ch.qos.logback" % "logback-classic" % "1.1.2"
)

resolvers += "Typesafe" at "https://repo.typesafe.com/typesafe/releases/"

mainClass in (Compile, run) := Some("com.javacodegeeks.bare.App")

它仍然是build.sbt ,但使用基于纯设置的方法定义(请注意,每个设置定义之间的新行都是强制性的)。 官方文档中也对此构建定义样式进行了说明。

如前所述,不建议再使用.scala.sbt裸机定义,因此在本教程中我们不再赘述

7.多模块项目

大多数现实世界的项目都组织在一组模块中,以鼓励代码重用和适当的边界。 从逻辑上讲,在这种情况下,可以在项目中的大多数(甚至所有)模块之间共享许多构建设置,任务和属性,并且正确构建工具的选择变得越来越重要。

SBT非常自然地支持多模块项目,因此无需费心添加新模块或维护非常复杂的构建定义。 让我们提出一个包含三个模块的示例多模块项目: core-moduleapi-moduleimpl-module

<project-name>
      | - project
      | - core-module
      |     | - src
      |           | - main
      |                  …
      | - api-module
      |     | - src
      |           | - main
      |                  …
      | - impl-module
            | - src
                  | - main
                         …

有很多方法来组织构建,但是在我们的情况下,项目的根文件夹是唯一包含项目文件夹和build.sbt文件的文件夹。

lazy val defaults = Seq(
  version := "0.0.1-SNAPSHOT",
  scalaVersion := "2.11.8",
  resolvers += "Typesafe" at "https://repo.typesafe.com/typesafe/releases/"
)

lazy val core = (project in file("core-module"))
  .settings(defaults: _*)
  .settings(
    name := "core-module"
  )

lazy val api = (project in file("api-module"))
  .settings(defaults: _*)
  .settings(
    name := "api-module"
  )

lazy val impl = (project in file("impl-module"))
  .settings(defaults: _*)
  .settings(
    name := "impl-module",
    libraryDependencies ++= Seq(
      "ch.qos.logback" % "logback-classic" % "1.1.2"
    ),
    mainClass in (Compile, run) := Some("com.javacodegeeks.multi.App")
  )
  .dependsOn(core)
  .dependsOn(api)

lazy val main = (project in file("."))
  .aggregate(core, api, impl)

本质上,多模块(或多项目)构建定义只是一组单独的项目,它们共享一些通用设置(例如lazy val defaults ),并使用dependsOn声明彼此的依赖关系:

lazy val impl = (project in file("impl-module"))
  …
  .dependsOn(core)
  .dependsOn(api)

SBT正在处理其他所有事务(例如构造依赖关系图和找出正确的构建顺序)。 对于那些好奇的人,在官方文档部分对此进行了很好的解释。

8.从Maven迁移

可以说,如今, Apache Maven仍然是Java生态系统中最受欢迎的构建工具之一。 可能, SBT使用externalPom配置(假设在build.sbt中有一个pom.xml文件)提供了从Apache Maven轻松迁移的路径,例如:

lazy val main = (project in file("."))
  .settings(
    organization := "com.javacodegeeks",
    name := "pom-module-sbt",
    version := "0.0.1-SNAPSHOT",
    scalaVersion := "2.11.8",
    mainClass in (Compile, run) := Some("com.javacodegeeks.maven.App"),
    externalPom()
  )

值得一提的是, externalPom的功能有限,仅导入依赖项。 有关更多详细信息,请查看官方文档

9.心灵互动

SBT绝对惊人的功能之一就是通过功能丰富的外壳实现的交互性。 就像在项目的根文件夹中键入sbt一样简单。

$ sbt
>

SBT使您可以实时与构建定义进行交互,检查各种设置并调用任意任务。 不要忘记与sbt console命令(或者只是带有交互式shell的控制台)一起使用Scala控制台的集成。

$ sbt console

[info] Starting scala interpreter...
Welcome to Scala 2.11.8 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_77).
Type in expressions for evaluation. Or try :help.

scala>

在本教程的下一部分中,我们将大量使用这些SBT超级功能,希望可以改变您对构建工具应该具有的整个概念的看法。

10.与IDE的集成

最后但并非最不重要的一点是,还有另一个非常重要的主题涉及SBT如何与流行的Java IDE集成。 令人惊讶的是,这样的集成对于开发人员如何快速开始其项目非常重要。

由于其自身的插件机制, SBT具有非常好的可扩展性。 与大多数流行的Java IDE的集成通常是通过专用插件完成的,例如:

  • sbteclipseSBT的插件,用于创建Eclipse项目定义
  • nbsbtSBT用来创建Netbeans项目定义的插件
  • ensime-sbtSBT的插件,用于创建Ensime项目定义

添加插件来构建定义就像在项目子文件夹的plugin.sbt文件中添加几行一样简单,例如在sbteclipse的情况下:

addSbtPlugin("com.typesafe.sbteclipse" % "sbteclipse-plugin" % "4.0.0")

因此,可从命令行(或从交互式外壳程序)通过相应的一个或多个任务访问插件功能,例如,对于sbteclipse,它看起来像这样:

$ sbt "eclipse with-source=true with-javadoc=true"

值得一提的是,某些JetBrains IntelliJ IDEA等IDE确实通过自己的插件生态系统提供了出色的SBT

11.结论

SBT是非常强大的构建工具,当相应地使用时,可以大大提高您的生产率。 本节讨论了非常基本的概念,但该教程的几乎所有其他部分都将引用一些新的SBT功能(或仅依赖我们已经知道的功能)。

12.接下来是什么

在本教程下一部分中,我们将讨论Scala开发社区采用的不同测试框架。 我们还将实际了解如何使用SBT来运行单个测试或测试套件并观察更改。

翻译自: https://www.javacodegeeks.com/2016/06/developing-modern-applications-scala-build-sbt.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值