You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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路径末尾带斜杠可能引发路径匹配的小问题,但核心原因还是控制器未被扫描加载。

解决方法

  1. 添加包声明:在代码文件顶部添加明确的包声明,确保启动类和控制器处于同一包下,让Spring自动扫描到控制器:

    package com.reacctivespring
    
  2. 优化请求路径(可选):将@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)
  1. 验证控制器注册状态:启动项目后,访问Actuator的/actuator/mappings端点,查看所有注册的请求映射,确认/api路径是否存在,以此验证控制器是否被正确加载。

内容的提问来源于stack exchange,提问作者Saher Al-Sous

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 05:53:21