Scala项目构建:SBT工具详解
SBT核心特性
SBT是Scala生态的标准构建工具,提供以下核心能力:
- 基于Scala DSL的构建脚本
- 持续编译与测试的触发执行机制
- 增量编译技术(已独立为Zinc组件)
- Java/Scala混合项目支持
- 并行任务处理
- 兼容Maven/Ivy仓库体系
环境配置
通用安装方法
- 获取启动器:
wget https://repo.typesafe.com/typesafe/ivy-releases/org.scala-sbt/sbt-launch/0.13.18/sbt-launch.jar - 创建启动脚本:
# Linux/Unix java -Xmx2G -jar $(dirname $0)/sbt-launch.jar "$@" # Windows(sbt.bat) set SCRIPT_DIR=%~dp0 java -Xmx2G -jar "%SCRIPT_DIR%sbt-launch.jar" %*
系统专属安装
# macOS brew install sbt # Linux(APT) sudo apt install sbt # Windows 下载安装包:https://www.scala-sbt.org/download.html
基础实践
最小化示例
// AppLauncher.scala
object AppLauncher {
def main(args: Array[String]): Unit =
println("构建成功")
}
执行流程:
$ sbt run [info] 运行 AppLauncher 构建成功
标准项目结构
project-root/
├── build.sbt
├── src/
│ ├── main/
│ │ ├── scala/ # Scala源码
│ │ ├── java/ # Java源码
│ │ └── resources/ # 资源文件
│ └── test/
│ ├── scala/ # 测试代码
│ └── resources/ # 测试资源
└── project/ # 构建定义
├── build.properties
└── plugins.sbt
构建配置示例
// build.sbt
projectName := "data-processor"
version := "1.0.0-RC"
scalaVersion := "2.12.15"
// 添加依赖
libraryDependencies ++= Seq(
"org.apache.kafka" % "kafka-clients" % "3.2.0",
"org.scalatest" %% "scalatest" % "3.2.12" % Test
)
// 排除冲突依赖
excludeDependencies ++= Seq(
ExclusionRule("log4j", "log4j")
)
插件配置
// project/plugins.sbt
addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "1.1.0")
addSbtPlugin("net.virtual-void" % "sbt-dependency-graph" % "0.10.0")
工作流命令
| 命令 | 功能 |
|---|---|
compile | 编译主代码 |
test | 执行测试套件 |
run | 运行主程序 |
package | 生成部署包 |
~compile | 启用实时编译 |
依赖管理
非托管依赖
// 自定义库路径 unmanagedBase := baseDirectory.value / "custom-libs"
托管依赖
libraryDependencies += "mysql" % "mysql-connector-java" % "8.0.29" // 带作用域的依赖 libraryDependencies += "junit" % "junit" % "4.13.2" % Test // 跨Scala版本依赖 libraryDependencies += "org.typelevel" %% "cats-core" % "2.7.0"
仓库配置
resolvers += "Akka仓库" at "https://repo.akka.io/maven" resolvers += "本地Maven" at "file://" + Path.userHome.absolutePath + "/.m2/repository"
高级功能
Scala构建定义
// project/BuildConfig.scala
import sbt._
import Keys._
object ProjectBuilder extends Build {
lazy val core = Project("core-module", file("core"))
.settings(scalaVersion := "2.12.15")
lazy val api = Project("api-module", file("api"))
.dependsOn(core)
}
自定义任务
// 定义任务键
val deployTask = TaskKey[Unit]("deploy", "生成部署包")
// 任务实现
deployTask := {
val jarFile = (Compile / packageBin).value
println(s"生成部署包: ${jarFile.getName}")
}
// 集成到项目
lazy val root = project
.settings(deployTask)
插件开发
// build.sbt(插件项目)
sbtPlugin := true
name := "sbt-deploy-plugin"
// 插件实现
object DeployPlugin extends AutoPlugin {
object Keys {
val targetEnv = settingKey[String]("部署环境")
}
override def projectSettings = Seq(
Keys.targetEnv := "production"
)
}
多模块项目
// project/Build.scala
object MultiModuleBuild extends Build {
lazy val root = project.aggregate(engine, web)
lazy val engine = project
.settings(libraryDependencies += "io.netty" % "netty" % "4.1.77")
lazy val web = project
.dependsOn(engine)
.settings(scalaVersion := "2.12.15")
}