WebFlux 和 Kotlin 在多模块应用程序中使用 ReactiveCrudRepository
Posted
技术标签:
【中文标题】WebFlux 和 Kotlin 在多模块应用程序中使用 ReactiveCrudRepository【英文标题】:WebFlux and Kotlin use ReactiveCrudRepository in multimodule application 【发布时间】:2021-06-22 01:54:39 【问题描述】:我在 Kotlin 和 WebFlux 中有一个示例 SpringBoot 应用程序。我将整个应用程序划分为模块(就像我在 asp.net 中习惯的那样)。
模块:
随处引用的核心(模型、DTO、助手等...) 仅在业务中引用的数据(存储库、表...) api 中引用的业务(服务、处理程序...) api实际SpringBoot应用我现在的问题是如何正确使用 ReactiveCrudRepository 和一般的存储库。我在数据模块中有配置类来启用 R2dbcRepositories。
@Configuration
@EnableR2dbcRepositories("me.janam.data")
open class RepositoriesConfiguration
现在如果我创建表和存储库
interface IPersonRepository: ReactiveCrudRepository<PersonTable, Long>
@Query("SELECT * FROM person.person limit 1")
fun getOne(): Mono<PersonTable>
并尝试在业务模块中使用它我收到错误
Cannot access 'org.springframework.data.repository.reactive.ReactiveCrudRepository' which is a supertype of 'me.janam.data.features.person.repositories.IPersonRepository'. Check your module classpath for missing or conflicting dependencies
当然,如果我添加
implementation("org.springframework.data:spring-data-commons:2.4.6")
进入我的业务模块一切正常。但不知何故,这对我来说感觉很奇怪。这是正确的方法吗?
也不是我的主要问题的一部分,但这里是完整的配置,我想听听一些意见,因为我主要是 asp.net 开发人员。谢谢。
root - settings.gradle.kts:
rootProject.name = "springboot-example"
include(":api")
include(":business")
include(":data")
include(":core")
root - gradle.properties:
kotlin.code.style=official
kotlin_version=1.4.31
kotlinx_coroutines_reactor_version=1.4.3
r2dbc_postgresql_version=0.8.7.RELEASE
postgresql_version=42.2.19
spring_context_version=5.3.5
root - build.gradle.kts:
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins
kotlin("jvm") version "1.4.31"
id("io.spring.dependency-management") version "1.0.11.RELEASE"
subprojects
apply(plugin = "io.spring.dependency-management" )
dependencyManagement
group = "me.janam"
version = "1.0-SNAPSHOT"
repositories
mavenCentral()
dependencies
//implementation("org.springframework:spring-context:5.3.5")
testImplementation(kotlin("test-junit5"))
testImplementation("org.junit.jupiter:junit-jupiter-api:5.6.0")
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.6.0")
tasks.test
useJUnitPlatform()
tasks.withType<KotlinCompile>()
kotlinOptions.jvmTarget = "13"
核心 - build.gradle.kts:
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins
kotlin("jvm")
group = "me.janam"
version = "1.0-SNAPSHOT"
repositories
mavenCentral()
dependencies
testImplementation(kotlin("test-junit5"))
testImplementation("org.junit.jupiter:junit-jupiter-api:5.6.0")
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.6.0")
tasks.test
useJUnitPlatform()
tasks.withType<KotlinCompile>()
kotlinOptions.jvmTarget = "13"
数据 - build.gradle.kts:
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
val kotlinx_coroutines_reactor_version: String by project
val r2dbc_postgresql_version: String by project
val postgresql_version: String by project
val spring_context_version: String by project
plugins
kotlin("jvm")
group = "me.janam"
version = "1.0-SNAPSHOT"
repositories
mavenCentral()
dependencies
implementation(project(":core"))
implementation("org.springframework:spring-context:$spring_context_version")
implementation("org.springframework.boot:spring-boot-starter-data-r2dbc:2.4.4")
runtimeOnly("io.r2dbc:r2dbc-postgresql:$r2dbc_postgresql_version")
runtimeOnly("org.postgresql:postgresql:$postgresql_version")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-reactor:$kotlinx_coroutines_reactor_version")
testImplementation(kotlin("test-junit5"))
testImplementation("org.junit.jupiter:junit-jupiter-api:5.6.0")
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.6.0")
tasks.test
useJUnitPlatform()
tasks.withType<KotlinCompile>()
kotlinOptions.jvmTarget = "13"
业务 - build.gradle.kts:
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
val kotlinx_coroutines_reactor_version: String by project
val spring_context_version: String by project
plugins
kotlin("jvm")
group = "me.janam"
version = "1.0-SNAPSHOT"
repositories
mavenCentral()
dependencies
implementation(project(":core"))
implementation(project(":data"))
implementation("org.springframework:spring-context:$spring_context_version")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-reactor:$kotlinx_coroutines_reactor_version")
implementation("org.springframework.data:spring-data-commons:2.4.6") //TODO
testImplementation(kotlin("test-junit5"))
testImplementation("org.junit.jupiter:junit-jupiter-api:5.6.0")
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.6.0")
tasks.test
useJUnitPlatform()
tasks.withType<KotlinCompile>()
kotlinOptions.jvmTarget = "13"
api - build.gradle.kts:
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins
id("org.springframework.boot") version "2.4.4"
// Přesunuto do rootu
id("io.spring.dependency-management")
kotlin("jvm")
kotlin("plugin.spring") version "1.4.31"
group = "me.janam"
version = "1.0-SNAPSHOT"
//java.sourceCompatibility = JavaVersion.VERSION_13
repositories
mavenCentral()
dependencies
implementation(project(":core"))
implementation(project(":business"))
//implementation("org.springframework.boot:spring-boot-starter-data-r2dbc")
implementation("org.springframework.boot:spring-boot-starter-rsocket")
implementation("org.springframework.boot:spring-boot-starter-webflux")
implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
implementation("io.projectreactor.kotlin:reactor-kotlin-extensions")
implementation("org.jetbrains.kotlin:kotlin-reflect")
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-reactor")
//runtimeOnly("io.r2dbc:r2dbc-postgresql")
//runtimeOnly("org.postgresql:postgresql")
testImplementation("org.springframework.boot:spring-boot-starter-test")
testImplementation("io.projectreactor:reactor-test")
tasks.withType<KotlinCompile>
kotlinOptions
freeCompilerArgs = listOf("-Xjsr305=strict")
jvmTarget = "13"
tasks.withType<Test>
useJUnitPlatform()
【问题讨论】:
你的api模块需要在启动过程中正确找到所有@Configuration
注解的类。 @SpringBootApplication
是多个注释的组合,其中一个是 @ComponentScan
所以如果我猜我是对的,你必须在你的 main 方法上使用该注释,并声明所有将包含任何类型 bean 的包(带注释的类,如@Configuration、@Controller @Service 等),以便应用程序可以扫描所有这些包以在启动期间运行 bean。
你看到默认行为是spring会从主类位置扫描所有子目录来查找bean,但是你把它们放在单独的模块中。
@Toerktumlare 您好,我认为在 DI 中注册不是问题。问题是业务模块不知道 ReactiveCrudRepository 接口,我不知道是否将包含 ReactiveCrudRepository 接口的 implementation("org.springframework.data:spring-data-commons:2.4.6") 添加到业务模块中好的做法。还是我错过了什么? :(谢谢回复。
【参考方案1】:
为每个子项目添加相同的依赖集可能感觉很奇怪,但这样做完全没问题。为了在给定的子项目中使用给定的依赖项,您必须将其指定为该子项目的依赖项。
但是,有比实际将导入语句复制粘贴到每个构建文件更简洁的方法来完成此操作。我建议在您的根 build.gradle.kts
中指定一个 subprojects
部分,并将共享和公共依赖项放在那里:
subprojects
dependencies
// Put items here that are used in all/most subprojects:
implementation("org.springframework:spring-context:$spring_context_version")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-reactor:$kotlinx_coroutines_reactor_version")
// You can put this import here or just keep it in the build files
// for subprojects where it will actually get used
implementation("org.springframework.data:spring-data-commons:2.4.6")
testImplementation(kotlin("test-junit5"))
testImplementation("org.junit.jupiter:junit-jupiter-api:5.6.0")
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.6.0")
您仍然需要在每个子构建文件中使用 implementation(project(":core"))
类型语句指定其他子项目各自依赖的内容,但上面的 dependencies
块负责使指定的库在所有子项目中都可访问。
【讨论】:
以上是关于WebFlux 和 Kotlin 在多模块应用程序中使用 ReactiveCrudRepository的主要内容,如果未能解决你的问题,请参考以下文章
如何在多平台 Android 模块中配置 Kotlin jvmTarget?
Spring WebFlux Reactive 和 Kotlin Coroutines 启动错误
Spring Webflux: Kotlin DSL [片断]
如何在多平台多项目 Kotlin 构建中向另一个项目的测试添加依赖项
如何在 Spring Boot 和 Spring WebFlux 中使用“功能 bean 定义 Kotlin DSL”?