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

Spring Boot Kotlin所有接口返回404问题排查求助

Spring Boot + Kotlin Rest Controller 全404问题排查与解决

看起来你遇到了Spring Boot和Kotlin结合开发时最常见的组件扫描问题之一——控制器完全没被Spring识别,导致所有接口都返回404。结合你已经做的排查步骤,我整理了几个关键的排查方向和解决方案:

1. 确认主启动类的包结构与组件扫描范围

Spring Boot默认会扫描主启动类所在包及其所有子包下的组件(包括@RestController、@Service、@Repository等)。如果你的主启动类(带有@SpringBootApplication注解的类)不在com.example包下,而是在更上层或下层的包,就会导致控制器无法被扫描到。

比如,主启动类在com.example.app,而控制器在com.example.controller,就超出了默认扫描范围。

解决方法:

  • 调整包结构,让主启动类位于所有业务类的根包下(比如com.example);
  • 或者在@SpringBootApplication注解中显式指定扫描的包:
    @SpringBootApplication(scanBasePackages = ["com.example.controller", "com.example.service", "com.example.repository"])
    class SpringKotlinRestApiApplication
    
    fun main(args: Array<String>) {
        runApplication<SpringKotlinRestApiApplication>(*args)
    }
    

2. 修复ComponentScan注解的使用问题

你提到添加@ComponentScan未被识别,大概率是注解的位置或配置不正确:

  • @ComponentScan应该添加在主启动类上,和@SpringBootApplication配合使用;
  • 注意@SpringBootApplication本身已经包含了@ComponentScan的功能,所以更推荐用上面提到的scanBasePackages属性来指定扫描范围,避免冲突。

3. 补全并修正pom.xml配置

你提供的pom.xml内容不完整(最后一行的kotlin-reflect依赖没写完),而且缺少关键的Kotlin Maven插件配置,这会导致Spring无法正确处理Kotlin类的反射和代理:

首先补全kotlin-reflect依赖:

<dependency>
    <groupId>org.jetbrains.kotlin</groupId>
    <artifactId>kotlin-reflect</artifactId>
</dependency>

添加完整的Kotlin Maven插件和Spring Boot插件配置:

在pom.xml的<build>节点下添加:

<build>
    <sourceDirectory>${project.basedir}/src/main/kotlin</sourceDirectory>
    <testSourceDirectory>${project.basedir}/src/test/kotlin</testSourceDirectory>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
        <plugin>
            <groupId>org.jetbrains.kotlin</groupId>
            <artifactId>kotlin-maven-plugin</artifactId>
            <configuration>
                <args>
                    <arg>-Xjsr305=strict</arg>
                </args>
                <compilerPlugins>
                    <plugin>spring</plugin>
                </compilerPlugins>
            </configuration>
            <dependencies>
                <dependency>
                    <groupId>org.jetbrains.kotlin</groupId>
                    <artifactId>kotlin-maven-allopen</artifactId>
                    <version>${kotlin.version}</version>
                </dependency>
            </dependencies>
        </plugin>
    </plugins>
</build>

这里的kotlin-maven-allopen插件非常关键——它会让Spring需要的类(比如控制器、服务)变成非final类,否则Spring无法创建代理对象,导致组件无法被正确初始化和扫描。

4. 检查控制器的导入与依赖注入

你的控制器代码中,Cricketer、CricketerRepository、CricketerService这些类的导入没有包路径(直接写类名),这可能导致编译错误或者Spring无法识别这些Bean。

比如,如果Cricketer在com.example.model包下,应该写成:

import com.example.model.Cricketer
import com.example.repository.CricketerRepository
import com.example.service.CricketerService

确保这些类本身也带有正确的注解(@Entity、@Repository、@Service),否则Spring也无法把它们作为Bean注入到控制器中。

5. 开启DEBUG日志排查扫描过程

如果以上步骤都没解决问题,可以开启Spring的DEBUG日志,查看组件扫描的详细过程:

在src/main/resources/application.properties中添加:

logging.level.org.springframework.context.annotation=DEBUG

启动项目后,在日志中查找以下内容:

  • Scanning base packages:确认扫描的包是否包含你的控制器所在的包;
  • Registering bean definition for class com.example.controller.CricketerController:如果没有这条日志,说明控制器确实没被扫描到,回到步骤1重新检查包结构和扫描配置。

你的控制器代码(格式化后)

package com.example.controller

import org.springframework.web.bind.annotation.RestController
import org.springframework.web.bind.annotation.PathVariable
import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.http.HttpStatus
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.PutMapping
import org.springframework.web.bind.annotation.DeleteMapping
import org.springframework.web.bind.annotation.RequestBody
import Cricketer
import CricketerRepository
import CricketerService
import org.springframework.web.bind.annotation.RequestMapping

@RestController
@RequestMapping("/api")
class CricketerController(private val cricketerService: CricketerService, private val cricketerRepository: CricketerRepository) {

    @GetMapping("/cricketers/{id}")
    fun getCricketer(@PathVariable("id") id: Long): ResponseEntity<Cricketer> {
        val cricketer = cricketerService.findById(id)
        return ResponseEntity<Cricketer>(cricketer as Cricketer, HttpStatus.OK);
    }

    @GetMapping("/cricketers/")
    fun getAllCricketers(): ResponseEntity<List<Cricketer>> {
        var cricketersList: ArrayList<Cricketer> = cricketerService.getAllPlayers() as (ArrayList<Cricketer>)
        return ResponseEntity<List<Cricketer>>(cricketersList, HttpStatus.OK)
    }

    @PostMapping("/cricketer/")
    fun addCricketer(@RequestBody cricketer: Cricketer): ResponseEntity<Cricketer> {
        val cCricketer: Cricketer = Cricketer(name = cricketer.name, country = cricketer.country, highestScore = cricketer.highestScore)
        cricketerRepository.save(cCricketer)
        return ResponseEntity<Cricketer>(cricketer, HttpStatus.OK)
    }

    @PutMapping("/cricketer/{id}")
    fun updateCricketer(@PathVariable("id") id: Long, @RequestBody cricketer: Cricketer): ResponseEntity<Cricketer> {
        val cCricketer = Cricketer(name = cricketer.name, country = cricketer.country, highestScore = cricketer.highestScore)
        cricketerRepository.save(cCricketer)
        return ResponseEntity<Cricketer>(cricketer, HttpStatus.OK)
    }

    @DeleteMapping("/cricketer/{id}")
    fun deleteCricketer(@PathVariable("id") id: Long): ResponseEntity<String> {
        val cCricketer: Cricketer = cricketerService.findById(id) as Cricketer
        cricketerRepository.delete(cCricketer)
        return ResponseEntity<String>("cricketer removed", HttpStatus.OK)
    }
}

你的pom.xml内容(格式化后,不完整)

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.example</groupId>
    <artifactId>Spring-Kotlin-Rest-API</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>Spring-Kotlin-Rest-API</name>
    <description>Spring Boot Kotlin REST API Example</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.2.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <kotlin.version>1.2.41</kotlin.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.module</groupId>
            <artifactId>jackson-module-kotlin</artifactId>
        </dependency>
        <dependency>
            <groupId>org.jetbrains.kotlin</groupId>
            <artifactId>kotlin-stdlib-jdk8</artifactId>
        </dependency>
        <dependency>
            <groupId>org.jetbrains.kotlin</groupId>
            <artifactId>kotlin-reflect</arti

内容的提问来源于stack exchange,提问作者Nirmal

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 07:31:54