SpringBoot3.x与Actuator冲突解决方案

复制代码
自己手痒随便点了一下debug时候的一个推荐安装,自动引入了这个依赖,后边重新clean后打包部署的时候就报错

也算是以来冲突报错。

在Spring Boot 3.x中,如果你同时使用了Spring MVC和Actuator,并且Actuator的端点是通过MVC暴露的(即使用了spring-boot-starter-actuator),那么会自动配置两个HandlerMapping

  1. requestMappingHandlerMapping:用于常规的MVC控制器。

  2. controllerEndpointHandlerMapping:用于Actuator的端点。

SecurityConfig中,你注入了一个RequestMappingHandlerMapping,但是因为存在两个候选Bean,Spring不知道注入哪一个,所以报错。

复制代码
<!--        <dependency>-->
<!--            <groupId>org.springframework.boot</groupId>-->
<!--            <artifactId>spring-boot-starter-actuator</artifactId>-->
<!--        </dependency>-->

启动报错信息如下

report,40 - *************************** APPLICATION FAILED TO START *************************** Description: Field permitAllUrl in com.hgwy.notification.framework.config.SecurityConfig required a single bean, but 2 were found: - requestMappingHandlerMapping: defined by method 'requestMappingHandlerMapping' in class path resource org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration$EnableWebMvcConfiguration.class - controllerEndpointHandlerMapping: defined by method 'controllerEndpointHandlerMapping' in class path resource org/springframework/boot/actuate/autoconfigure/endpoint/web/servlet/WebMvcEndpointManagementContextConfiguration.class This may be due to missing parameter name information Action: Consider marking one of the beans as @Primary, updating the consumer to accept multiple beans, or using @Qualifier to identify the bean that should be consumed Ensure that your compiler is configured to use the '-parameters' flag. You may need to update both your build tool settings as well as your IDE. (See https://github.com/spring-projects/spring-framework/wiki/Upgrading-to-Spring-Framework-6.x#parameter-name-retention) Disconnected from the target VM, address: '127.0.0.1:12154', transport: 'socket' Process finished with exit code 1

自己解决:解决吧插件的依赖在maven中注释掉

ai解决:

根据错误信息,问题在于Spring Boot 3.x 和 Actuator 的兼容性,以及Spring Security配置中注入了RequestMappingHandlerMapping,但是存在两个同类型的Bean(一个来自Spring MVC,一个来自Actuator)。

在Spring Boot 3.x中,如果你同时使用了Spring MVC和Actuator,并且Actuator的端点是通过MVC暴露的(即使用了spring-boot-starter-actuator),那么会自动配置两个HandlerMapping

  1. requestMappingHandlerMapping:用于常规的MVC控制器。

  2. controllerEndpointHandlerMapping:用于Actuator的端点。

SecurityConfig中,你注入了一个RequestMappingHandlerMapping,但是因为存在两个候选Bean,Spring不知道注入哪一个,所以报错。

解决方案:

  1. 使用@Qualifier指定注入的Bean名称(例如,注入名为requestMappingHandlerMapping的Bean)。

  2. 或者,如果你不需要Actuator的端点,可以排除Actuator的自动配置。

但是,根据你的描述,在clean之前可以启动,clean之后不能启动,这可能是由于clean之后重新编译,而编译时没有使用-parameters参数,导致参数名信息丢失,进而导致@Qualifier注解(如果已经使用)没有正确生效。

因此,我们需要做两件事情:

  1. 确保在编译时使用了-parameters参数(这样Spring在注入时可以通过参数名来区分Bean)。

  2. 在代码中使用@Qualifier明确指定要注入的Bean。

步骤:

第一步:在pom.xml中配置编译器插件,确保使用-parameters参数。

第二步:修改SecurityConfig类,在注入RequestMappingHandlerMapping的地方添加@Qualifier("requestMappingHandlerMapping")

具体操作:

  1. 在pom.xml中,找到maven-compiler-plugin插件,添加配置:

    xml

    复制代码
    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.8.1</version>
        <configuration>
            <compilerArgs>
                <arg>-parameters</arg>
            </compilerArgs>
        </configuration>
    </plugin>

    如果没有这个插件,就添加它。

  2. SecurityConfig类中,找到注入RequestMappingHandlerMapping的地方,修改为:

    java

    复制代码
    @Autowired
    @Qualifier("requestMappingHandlerMapping")
    private RequestMappingHandlerMapping requestMappingHandlerMapping;

但是,如果你在SecurityConfig中并没有直接使用RequestMappingHandlerMapping,而是通过方法参数注入,那么你可能需要检查你的配置方法。例如,如果你有这样一个方法:

text

复制代码
```java
@Bean
public SecurityFilterChain filterChain(HttpSecurity http, RequestMappingHandlerMapping mapping) throws Exception {
    // ...
}
```

那么你需要在这个方法参数上添加@Qualifier

text

复制代码
```java
@Bean
public SecurityFilterChain filterChain(HttpSecurity http, 
                                       @Qualifier("requestMappingHandlerMapping") RequestMappingHandlerMapping mapping) throws Exception {
    // ...
}
```
  1. 重新编译项目。

如果问题仍然存在,可能是因为你的IDE(IntelliJ IDEA)没有使用-parameters参数进行编译。你可以在IDEA中设置:

text

复制代码
File -> Settings -> Build, Execution, Deployment -> Compiler -> Java Compiler -> Additional command line parameters: 添加`-parameters`

然后重新构建项目。

另外,如果你不想使用Actuator的MVC端点,可以尝试禁用Actuator的MVC端点,只使用JMX或者其他方式。但是,根据错误信息,你正在使用WebMvc,所以可能需要通过@Qualifier来解决。

如果上述方法都不能解决问题,你可以尝试在SecurityConfig中排除对RequestMappingHandlerMapping的自动注入,而是通过ApplicationContext来获取Bean,但这样不太优雅。

但是,根据你的错误信息,我注意到你使用的是Spring Boot 3.3.5,而Actuator是自动配置的。所以,请按照上述步骤操作。

最后,请确保你的Spring Boot版本和所有依赖版本兼容。你使用的是Spring Boot 3.3.5,那么相应的Spring Security版本应该是6.3.4(从你的依赖中可以看出),这应该是兼容的。

希望这能帮助你解决问题。

看到您正在本地使用IntelliJ IDEA运行项目,并且遇到了和服务器上一样的错误。这个问题的根本原因是Spring Boot 3.x与Spring Security配置之间的一个已知兼容性问题。

问题分析:

从日志可以看到,您在本地启动时也遇到了同样的Bean冲突:

text

复制代码
Field permitAllUrl in com.hgwy.notification.framework.config.SecurityConfig required a single bean, but 2 were found:
	- requestMappingHandlerMapping
	- controllerEndpointHandlerMapping

为什么clean之后启动不了?

  1. Maven clean会清理target目录,重新编译时可能会丢失一些编译信息

  2. Spring Boot 3.x对参数名保留有更高要求 ,需要-parameters编译参数

  3. Actuator自动配置冲突 :在Spring Boot 3.x中,Actuator会创建一个额外的controllerEndpointHandlerMapping

解决方案:

方案1:修改SecurityConfig类(最直接)

找到SecurityConfig.java文件,在RequestMappingHandlerMapping字段上添加@Qualifier注解:

java

复制代码
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

@Configuration
@EnableWebSecurity
public class SecurityConfig {
    
    @Autowired
    @Qualifier("requestMappingHandlerMapping")  // 添加这行
    private RequestMappingHandlerMapping requestMappingHandlerMapping;
    
    // 其他代码...
}

方案2:修改Maven编译配置

pom.xml中添加编译器参数:

xml

复制代码
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.11.0</version>
            <configuration>
                <source>17</source>
                <target>17</target>
                <parameters>true</parameters>  <!-- 关键配置 -->
                <compilerArgs>
                    <arg>-parameters</arg>
                </compilerArgs>
            </configuration>
        </plugin>
    </plugins>
</build>

方案3:在IDEA中配置编译器参数

  1. 打开 File → Settings → Build, Execution, Deployment → Compiler → Java Compiler

  2. 在"Additional command line parameters"中添加:-parameters

  3. 点击OK并重新构建项目

方案4:临时禁用Actuator(如果不需要)

application.ymlapplication.properties中:

yaml

复制代码
# application.yml
management:
  endpoints:
    enabled-by-default: false
  endpoint:
    health:
      enabled: true  # 只保留health端点

方案5:使用更优雅的注入方式

修改SecurityConfig中的注入方式:

java

复制代码
@Configuration
@EnableWebSecurity
public class SecurityConfig {
    
    // 方法1:使用构造器注入
    private final RequestMappingHandlerMapping requestMappingHandlerMapping;
    
    public SecurityConfig(
        @Qualifier("requestMappingHandlerMapping") 
        RequestMappingHandlerMapping requestMappingHandlerMapping
    ) {
        this.requestMappingHandlerMapping = requestMappingHandlerMapping;
    }
    
    // 方法2:使用setter注入
    /*
    @Autowired
    @Qualifier("requestMappingHandlerMapping")
    public void setRequestMappingHandlerMapping(RequestMappingHandlerMapping mapping) {
        this.requestMappingHandlerMapping = mapping;
    }
    */
}

快速修复步骤:

  1. 立即修复

    bash

    复制代码
    # 1. 停止当前运行
    # 2. 找到SecurityConfig.java,添加@Qualifier注解
    # 3. 重新运行
  2. 如果无法立即修改代码,可以临时排除Actuator:

    bash

    复制代码
    # 在pom.xml中临时注释掉actuator依赖
    <!--
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
    -->
    # 然后重新clean和编译
  3. 清理并重新构建

    bash

    复制代码
    mvn clean compile -DskipTests

验证修复:

修复后,启动日志应该显示正常,不会再有Bean冲突的错误。应用应该能够成功启动到类似这样的日志:

text

复制代码
Started RuoYiApplication in XX.XXX seconds

为什么之前可以启动?

可能是因为之前的编译产物中保留了某些参数信息,或者IDE缓存了编译结果。clean之后,所有编译产物被清除,重新编译时没有使用-parameters参数,导致Spring无法正确区分两个Bean。

请先尝试方案1(添加@Qualifier注解),这通常是最有效的解决方案。如果问题仍然存在,请告诉我具体的SecurityConfig类代码,我可以提供更精确的修复建议。

相关推荐
Flittly2 小时前
【AgentScope Java新手村系列】(16)从RAG到多路检索
java·spring boot·spring
小兔崽子去哪了3 小时前
Java 生成二维码解决方案
java·后端
人活一口气7 小时前
从JVM调优到MCP协议:Java全栈技术体系深度总结与企业级架构实践
java·spring boot
NE_STOP9 小时前
Vibe Coding -- 完整项目案例实操
java
荣码9 小时前
GraphRAG:普通RAG只能回答"点"的问题,我踩了4个坑才搞懂
java·python
SimonKing9 小时前
Google第三方授权登录
java·后端·程序员
明月光8189 小时前
从一行 @Builder 说起:重新拾起 Java 的 Lombok、注解与 Builder 模式
java
考虑考虑18 小时前
Mybatis实现批量插入
java·后端·mybatis
咖啡八杯19 小时前
GoF设计模式——中介者模式
java·后端·spring·设计模式
青石路1 天前
记一次多JDK版本问题的排查,一坑套一坑,差点没爬上来
java