Scala跨模块读取resources目录配置文件的方法咨询
Hey there! Since you already know Java's ways to read resources, let's focus on Scala-native solutions (plus some Scala-idiomatic twists on familiar approaches) to read config files from another module's resources directory. First, let's clarify a typical multi-module project structure to set the context:
my-scala-project/ ├── core-module/ │ ├── src/ │ │ ├── main/ │ │ │ ├── scala/ │ │ │ └── resources/ │ │ │ └── app-config.properties # The file we want to read │ └── build.sbt ├── service-module/ │ ├── src/ │ │ ├── main/ │ │ │ ├── scala/ │ │ │ │ └── com/myapp/ResourceLoader.scala # Our reader code │ │ │ └── resources/ │ └── build.sbt └── build.sbt (root project)
First, make sure your dependent module (like service-module) has a project dependency on the module with the resources (core-module) in your root build.sbt:
lazy val coreModule = project.in(file("core-module")) lazy val serviceModule = project.in(file("service-module")).dependsOn(coreModule)
Scala-Native Solutions
1. Use scala.io.Source.fromResource (Standard Library)
This is the most straightforward Scala-native way—Scala's standard library wraps Java ClassLoader logic into a clean, concise API. It automatically scans the entire classpath, so as long as the dependent module is on the classpath, it can pick up resources from other modules.
Example code in service-module:
import scala.io.Source import java.io.IOException object ResourceLoader { def readCoreConfig(): String = { // Path is relative to the root of the resources directory val configPath = "/app-config.properties" // Use fromResource to load the file safely Option(Source.fromResource(configPath)) match { case Some(source) => source.mkString case None => throw new IOException(s"Could not find resource at $configPath") } } }
- Note: If you omit the leading slash (
app-config.properties), the path is relative to the package of the calling class. Using the leading slash ensures you're targeting the root of the resources directory across modules.
2. TypeSafe Config (Scala Ecosystem Standard)
While not part of the core Scala library, TypeSafe Config is the de facto standard for configuration in Scala projects, and it's designed to work seamlessly across modules. It automatically loads all config files on the classpath, making cross-module reads trivial.
First, add the dependency to your module's build.sbt:
libraryDependencies += "com.typesafe" % "config" % "1.4.2"
Then load the config from another module:
import com.typesafe.config.ConfigFactory object ConfigLoader { def getCoreModuleConfig(): com.typesafe.config.Config = { // Loads app-config.properties from the classpath (including other modules) ConfigFactory.load("app-config.properties") } // Example: Get a specific config value def getDatabaseUrl(): String = { getCoreModuleConfig().getString("db.url") } }
- TypeSafe Config supports hierarchical configs, environment overrides, and more—perfect for complex Scala applications.
Scala-idiomatic Use of Java Approaches
Since you know Java's methods, here's how to use them in a more Scala-like way, leveraging functional programming constructs:
import scala.util.Try import java.io.InputStreamReader object JavaStyleReader { def readConfig(): Option[String] = { val inputStream = getClass.getResourceAsStream("/app-config.properties") Try(new InputStreamReader(inputStream)).map(_.readText()).toOption } }
Using Try and Option makes this safer and more aligned with Scala's functional style, avoiding null checks and explicit exception handling where unnecessary.
Key Notes
- Ensure your
resourcesdirectories are properly recognized by sbt: By default, sbt packages all files undersrc/main/resourcesinto the module's JAR, so no extra configuration is needed. - Classpath visibility: The module containing the resources must be a dependency of the module trying to read them—this ensures its JAR (and resources) are on the classpath.
内容的提问来源于stack exchange,提问作者loneStar

