Spring Boot(Gradle 和 Kotlin)自定义库不读取 application.yml 属性

Pau*_*Pau 6 java gradle kotlin spring-boot gradle-kotlin-dsl

我正在尝试使用 Gradle(带有 Kotlin DSL)和 Kotlin 为我的 Spring Boot 微服务制作一个 SDK(自定义库)来发送电子邮件,并使用 AWS SES 重用大部分内容和库。

首先,我在构建java库方面没有太多经验,所以可能有很多东西我做得不正确。欢迎任何反馈。

无论如何,我希望这个库从最终应用程序(微服务应用程序本身)上的文件中获取一些属性application.yml来实例化该库的一些 Bean。

该库使用JavaEmailService,并具有一些参数,以便在本地开发时使用本地电子邮件服务器,或部署版本的 AWS SES 实现。

例如,在库的 Bean 配置中我有以下代码:

@Configuration
internal class BeanConfig {
  // ... other properties

  @Value("\${sdk.mail.aws.access_key:}")
  private lateinit var awsMailAccessKey: String

  @Value("\${sdk.mail.aws.secret_key:}")
  private lateinit var awsMailSecretKey: String

  @Value("\${sdk.mail.aws.region:}")
  private lateinit var awsMailRegion: String

  @Value("\${sdk.mail.is_local:}")
  private var isLocal: Boolean? = null

  // ... other bean resolves

  @Bean
  fun amazonSimpleEmailService(): AmazonSimpleEmailService {
    if (isLocal == true) {
      return DummyAmazonSimpleEmailServiceImpl()
    }

    if (awsMailAccessKey.isEmpty() || awsMailSecretKey.isEmpty() || awsMailRegion.isEmpty()) {
      throw Exception("Missing AWS parameters (access_key, secret_key, region)")
    }

    return AmazonSimpleEmailServiceClientBuilder
      .standard()
      .withCredentials(
        AWSStaticCredentialsProvider(
          BasicAWSCredentials(
            awsMailAccessKey,
            awsMailSecretKey
          )
        )
      )
      .withRegion(Regions.fromName(awsMailRegion))
      .build()
    }
}
Run Code Online (Sandbox Code Playgroud)

我希望它从最终应用程序的文件中获取值,application.yml如下所示:

sdk:
  mail:
    is_local: false
    aws:
      access_key: ${AWS_MAIL_ACCESS_KEY:}
      secret_key: ${AWS_MAIL_SECRET_KEY:}
      region: ${${AWS_MAIL_REGION:}
Run Code Online (Sandbox Code Playgroud)

我对应包含在最终jar文件中的依赖项进行了自定义选择,因为我得到了很多依赖ClassNotFoundException项(在 Java 库生成中,也欢迎关于这部分的任何建议jar)。它最终包含了jar其工作所需的所有依赖项。

这是我运行时build.gradle.kts生成文件的文件的相关部分:jar./gradlew build

plugins {
    id("org.springframework.boot") version "2.5.0"
    id("io.spring.dependency-management") version "1.0.11.RELEASE"
    kotlin("jvm") version "1.5.10"
    kotlin("plugin.spring") version "1.5.10"
    `java-library`
    `maven-publish`
}

// ... library version, name and trivial info

dependencies {
    implementation(kotlin("stdlib"))
    implementation("org.springframework.boot:spring-boot-autoconfigure:2.5.0")
    implementation("org.springframework:spring-context-support:5.3.7")
    implementation("org.jetbrains.kotlin:kotlin-noarg:1.5.10")
    implementation("org.jetbrains.kotlin:kotlin-reflect")
    implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
    implementation("org.springframework.boot:spring-boot-starter-mail:2.5.0")
    implementation("org.springframework.cloud:spring-cloud-starter-aws:2.2.6.RELEASE")
    implementation("com.amazonaws:aws-java-sdk-ses:1.12.131")
    testImplementation("org.junit.jupiter:junit-jupiter:5.7.2")
    testImplementation("org.junit.jupiter:junit-jupiter-api:5.7.2")
    testImplementation(platform("org.junit:junit-bom:5.7.2"))
    testImplementation("io.mockk:mockk:1.10.3-jdk8")
    testImplementation("org.junit.platform:junit-platform-launcher:1.7.2")
    testImplementation("org.junit.jupiter:junit-jupiter-engine:5.7.2")
    testImplementation("org.junit.vintage:junit-vintage-engine:5.7.2")
}

tasks.withType<KotlinCompile> {
    kotlinOptions {
        freeCompilerArgs = listOf("-Xjsr305=strict")
        jvmTarget = "11"
    }
}

val exportPackages: List<String> = listOf(
    "spring-boot-starter-mail",
    "jakarta.mail",
    "jakarta.activation",
    "spring-context-support",
    "spring-boot-starter/",

    "spring-cloud-starter-aws",
    "spring-cloud-aws-context",
    "spring-cloud-aws-core",
    "javax.mail-api",
    "javax.activation",

    "aws-java-sdk-ses",
    "aws-java-sdk-core",
    "httpclient",
    "httpcore",
    "joda-time"
)

// Here the custom part
tasks.getByName<Jar>("jar") {
    enabled = true
    from (
        configurations.compileClasspath.get().mapNotNull {
            if (exportPackages.any { exportPackage -> it.path.contains(exportPackage) }) {
                if (it.isDirectory) it else zipTree(it)
            } else null
        }
    )
    duplicatesStrategy = DuplicatesStrategy.INCLUDE
}

Run Code Online (Sandbox Code Playgroud)

运行时./gradlew build我得到一个“sdk-mail-0.0.1-plain.jar”文件。如果我将该文件包含在同一存储库中的最终应用程序中,那么这部分工作得很好,如下所示:

implementation(files("lib/sdk-mail-0.0.1-plain.jar"))
Run Code Online (Sandbox Code Playgroud)

问题

当我将其发布到我们的包存储库中并将其导入最终应用程序时,就像处理任何其他库一样:

implementation("com.organization:sdk-mail:0.0.1")
Run Code Online (Sandbox Code Playgroud)

它被正确导入,并且我可以在开发过程中使用所有类,但是当我运行应用程序时,我发现两个问题:

  • 它没有找到application.yml最终应用程序中定义的属性(它在运行本地构建的 jar 时确实找到了它们)
  • 它尝试访问 EC2 以查找 AWS 凭证(例如默认区域),但显然未能成功。我想如果首先找到属性就不会发生这种情况,所以当属性问题解决后,这可能会得到解决。

这里是库中的发布配置部分build.gradle.kts:

publishing {
    repositories {
        // ... private repository settings
    }
    publications {
        create<MavenPublication>("default") {
            from(components["java"])
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我真正不明白的是,如果我在包存储库中下载已发布的 jar,并像我在本地构建项目时生成它一样添加它,它就会正常工作。我猜测 gradle 下载的发布版本有一些 spring boot 依赖项或类似的东西,但我真的没有任何线索。

有人可以帮我吗?