Spring Boot Kotlin项目中Spring无法识别Controller致404问题
问题描述
通过Spring Initializer创建了一个仅引入WebFlux和Actuator依赖的新项目,Gradle配置如下:
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { id("org.springframework.boot") version "3.0.3" id("io.spring.dependency-management") version "1.1.0" kotlin("jvm") version "1.7.22" kotlin("plugin.spring") version "1.7.22" } group = "com.reacctivespring" version = "0.0.1-SNAPSHOT" java.sourceCompatibility = JavaVersion.VERSION_17 repositories { mavenCentral() } dependencies { implementation("org.springframework.boot:spring-boot-starter-webflux") implementation("org.springframework.boot:spring-boot-starter-actuator") 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") testImplementation("org.springframework.boot:spring-boot-starter-test") testImplementation("io.projectreactor:reactor-test") } tasks.withType<KotlinCompile> { kotlinOptions { freeCompilerArgs = listOf("-Xjsr305=strict") jvmTarget = "17" } } tasks.withType<Test> { useJUnitPlatform() }
随后在同一个文件中编写了完整项目代码,包含启动类、控制器及数据类:
@SpringBootApplication class WebfluxApplication fun main(args: Array<String>) { runApplication<WebfluxApplication>(*args) } @RestController class ApiController() { @GetMapping( name = "Getting my name", value = ["/api/"], produces = [MediaType.APPLICATION_JSON_VALUE] ) fun getDemo( ): Flux<Money> { return Flux.interval(Duration.ofSeconds(1)) .map { Money("Testing") } } } data class Money(val name: String)
已启用所有Actuator端点且能正常访问,但访问自定义的/api/接口时始终返回404错误,尝试过/api/和api/两种路径,改用Kotlin Flow也无效。
问题原因及解决方法
原因分析
Spring Boot的组件扫描默认仅扫描启动类所在包及其子包中的Bean。如果代码文件未指定包声明(package),所有类会默认处于默认包中,而Spring Boot对默认包的组件扫描存在限制,会导致控制器无法被正确注册到Spring容器,最终出现404。
另外,@GetMapping路径末尾带斜杠可能引发路径匹配的小问题,但核心原因还是控制器未被扫描加载。
解决方法
添加包声明:在代码文件顶部添加明确的包声明,确保启动类和控制器处于同一包下,让Spring自动扫描到控制器:
package com.reacctivespring优化请求路径(可选):将
@GetMapping的value改为"/api"(去掉末尾斜杠),这样无论请求/api还是/api/都会被正确匹配:@GetMapping( name = "Getting my name", value = ["/api"], produces = [MediaType.APPLICATION_JSON_VALUE] )
修改后的完整代码示例:
package com.reacctivespring import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication import org.springframework.web.bind.annotation.GetMapping import org.springframework.web.bind.annotation.RestController import reactor.core.publisher.Flux import java.time.Duration import org.springframework.http.MediaType @SpringBootApplication class WebfluxApplication fun main(args: Array<String>) { runApplication<WebfluxApplication>(*args) } @RestController class ApiController { @GetMapping( name = "Getting my name", value = ["/api"], produces = [MediaType.APPLICATION_JSON_VALUE] ) fun getDemo(): Flux<Money> { return Flux.interval(Duration.ofSeconds(1)) .map { Money("Testing") } } } data class Money(val name: String)
- 验证控制器注册状态:启动项目后,访问Actuator的
/actuator/mappings端点,查看所有注册的请求映射,确认/api路径是否存在,以此验证控制器是否被正确加载。
内容的提问来源于stack exchange,提问作者Saher Al-Sous
相关产品推荐
相关产品推荐

