You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

spring-boot-maven-plugin启动检测异常及RMI绑定问题咨询

解答spring-boot-maven-plugin集成测试启动检测相关问题

针对你在使用spring-boot-maven-plugin做集成测试时遇到的启动超时和fork模式下的RMI绑定问题,我来逐个解答你的疑问,并给出实用的解决方案:

1. 插件如何检测应用是否启动?

spring-boot-maven-plugin的应用启动检测逻辑分fork=truefork=false两种完全不同的机制,核心目标都是确认Spring应用上下文是否完全初始化完成(所有Bean创建完毕、上下文刷新完成,应用处于可服务状态)。

2. fork=true时,是否通过JMX/RMI检测?使用哪个端口、哪个MBean?

没错,当fork=true(插件默认配置)时,因为插件和应用运行在不同JVM进程,所以会通过JMX + RMI跨进程检测应用状态:

  • 默认使用的RMI端口是9001,这是JMX远程连接的默认端口;
  • 依赖的MBean是org.springframework.boot:type=Admin,name=SpringApplication,插件会调用这个MBean的isReady()方法来判断应用是否启动完成;
  • 补充:这个MBean是Spring Boot自动配置的,只要你没显式设置spring.application.admin.enabled=false,就会自动注册。

3. fork=false时的检测机制是什么?

fork=false时,插件和Spring应用运行在同一个JVM进程里,检测逻辑更直接:

  • 插件会直接监听Spring应用的ContextRefreshedEvent事件,或者直接检查ApplicationContextisActive()状态来判断应用是否就绪;
  • 你遇到的“DispatcherServlet已初始化但插件未识别”的情况,大概率是因为:虽然DispatcherServlet完成了初始化,但你的应用还有其他后台任务、异步Bean或者上下文刷新后的初始化逻辑在运行,导致Spring上下文还没完全标记为“ready”状态,插件的超时时间就到了。

4. 如何解决fork=true时的绑定错误?

你遇到的BeanCreationException(无法绑定RMI端口9001)和java.io.InvalidClassException: filter status: REJECTED,可以从以下几个方向解决:

方案一:更换自定义RMI端口

如果9001端口被其他进程占用,直接指定一个未被使用的端口即可。在插件配置中添加JVM参数:

<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <configuration>
        <fork>true</fork>
        <jvmArguments>-Dcom.sun.management.jmxremote.port=9002</jvmArguments>
    </configuration>
</plugin>

如果遇到网络相关的问题,还可以指定RMI服务器的hostname:

<jvmArguments>-Dcom.sun.management.jmxremote.port=9002 -Djmx.remote.rmi.server.hostname=localhost</jvmArguments>

方案二:改用HTTP端点检测替代JMX/RMI

如果JMX相关的问题不好排查,可以直接让插件通过Spring Boot Actuator的健康端点来检测应用启动,这也是更直观的方式:

  1. 先在项目pom.xml中添加Actuator依赖:
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
  1. application.properties(或application.yml)中开启健康端点的Web暴露:
management.endpoints.web.exposure.include=health
management.endpoint.health.show-details=always
  1. 修改插件配置,指定等待的健康检查URL:
<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <configuration>
        <fork>true</fork>
        <wait>
            <url>http://localhost:8080/actuator/health</url>
            <timeout>30000</timeout> <!-- 可根据应用启动时间调整超时,单位毫秒 -->
        </wait>
    </configuration>
</plugin>

方案三:解决InvalidClassException类过滤问题

这个错误通常是JMX的类加载过滤机制导致的,可能是fork的JVM和插件所在JVM的类版本不一致,或者安全策略限制了类传输。可以尝试:

  • 确保项目中所有Spring Boot相关依赖的版本完全一致,避免类版本冲突;
  • 添加JVM参数禁用JMX的类过滤:
<jvmArguments>-Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Djmx.remote.rmi.server.hostname=localhost -Djmx.remote.class.loading=false</jvmArguments>

方案四:检查端口占用

先确认9001端口是否被其他进程占用:

  • Linux/macOS:执行lsof -i :9001netstat -tulpn | grep 9001查看占用进程
  • Windows:执行netstat -ano | findstr :9001查看占用进程的PID,然后通过任务管理器杀掉对应进程
    如果端口确实被占用,要么杀掉占用进程,要么改用其他端口。

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

火山引擎 最新活动