我正在尝试按照一些在线示例使用 Spring-Boot 使用当前的 Kotlin、MapStruct 和 Java 创建一个项目,因为我是 MapStruct 的新手,但是我无法将映射器注入到我的服务中。 Idea 和 Gradle(在构建任务测试中)都抱怨没有找到 bean (UnsatisfiedDependencyException)。谷歌搜索没有帮助。我错过了什么?
MWE:
build.gradle.kts
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
id("org.springframework.boot") version "2.7.4"
id("io.spring.dependency-management") version "1.0.14.RELEASE"
kotlin("jvm") version "1.7.20"
kotlin("plugin.spring") version "1.7.20"
kotlin("plugin.jpa") version "1.7.20"
}
group = "com.example"
version = "0.0.1-SNAPSHOT"
java.sourceCompatibility = JavaVersion.VERSION_17
configurations {
compileOnly {
extendsFrom(configurations.annotationProcessor.get())
}
}
repositories {
mavenCentral()
}
dependencies {
implementation("org.springframework.boot:spring-boot-starter-data-jpa")
implementation("org.springframework.boot:spring-boot-starter-web")
implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
implementation("org.jetbrains.kotlin:kotlin-reflect")
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
annotationProcessor("org.springframework.boot:spring-boot-configuration-processor")
testImplementation("org.springframework.boot:spring-boot-starter-test")
implementation("org.mapstruct:mapstruct:1.5.3.Final")
annotationProcessor("org.mapstruct:mapstruct-processor:1.5.3.Final")
}
tasks.withType<KotlinCompile> {
kotlinOptions {
freeCompilerArgs = listOf("-Xjsr305=strict")
jvmTarget = "17"
}
}
tasks.withType<Test> {
useJUnitPlatform()
}
演示应用程序.kt
package com.example.demo
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication
@SpringBootApplication
class DemoApplication
fun main(args: Array<String>) {
runApplication<DemoApplication>(*args)
}
应用程序.kt
package com.example.demo
import org.mapstruct.Mapper
import org.springframework.data.jpa.repository.JpaRepository
import org.springframework.stereotype.Repository
import org.springframework.stereotype.Service
import javax.persistence.*
@Entity
@Table(name = "items")
class Item(@Id var id: Int = 0)
data class ItemDto(val id: Int)
@Repository
interface ItemRepo : JpaRepository<Item, Int>
@Mapper(componentModel = "spring")
interface ItemMapper {
fun entToDto(item: Item) : ItemDto
fun entsToDtos(items: List<Item>) : List<ItemDto>
fun dtoToEnt(itemDto: ItemDto) : Item
}
@Service
class Srvc(private val itemMapper: ItemMapper, // XXX: no bean found for this one
private val repo: ItemRepo)
{
fun items() = itemMapper.entsToDtos(repo.findAll())
}
// controller skipped
Kapt 处于维护模式!请参阅示例:https://github.com/mapstruct/mapstruct-examples/tree/main/mapstruct-kotlin
plugin {
// ...
kotlin("kapt")
// ...
}
dependencies {
// ...
kapt("org.mapstruct:mapstruct-processor:$version")
implementation("org.mapstruct:mapstruct:$version")
// ...
}
编辑(由 mpts.cz 编写 - 对于未来的我或任何像我一样刚接触 Mapstruct 和/或 Gradle 的人):
kotlin("kapt")
annotationProcessor("org.mapstruct:mapstruct-processor:$version")
与 kapt("org.mapstruct:mapstruct-processor:$version")
implementation("org.mapstruct:mapstruct:$version")
有了这些改变,一切似乎都进展顺利。谢谢努米奇!
也许是可选的,但您可能需要添加具有真实值的 keepJavacAnnotationProcessors 才能使事情正常工作。此外,您可能还需要定义一个全局映射结构配置,如下所示:
//...
kapt {
keepJavacAnnotationProcessors = true
arguments {
arg("mapstruct.defaultComponentModel", "spring")
arg("mapstruct.unmappedTargetPolicy", "IGNORE")
}
}
//...