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

控制器中webServerPort字段为何被重置?

问题原因及解决办法

核心原因

@Validated注解会让Spring为MyController创建代理对象,导致事件监听的原始实例和请求处理的代理实例是两个不同的对象,各自的webServerPort字段独立存储值。

具体细节:

  • 当类上标注@Validated时,Spring会通过AOP生成代理类来实现JSR-380参数校验逻辑,此时容器中同时存在MyController的原始实例和代理实例。
  • @EventListener注解绑定在父类的方法上,事件触发时会调用原始实例的onApplicationEvent方法,因此原始实例的webServerPort被设置为8080。
  • 但处理HTTP请求时,Spring路由到的是代理实例的readStates方法,代理实例继承的webServerPort从未被赋值,所以返回int类型的默认值0。

解决方案

方案1:将端口字段改为静态变量

修改父类的webServerPort为静态字段,让原始实例和代理实例共享同一个变量值:

public abstract class AbstractController {

    @EventListener
    void onApplicationEvent(final ReactiveWebServerInitializedEvent event) {
        webServerPort = event.getWebServer().getPort();
        log.debug("webServerPort: {}", webServerPort);
    }

    @Getter
    private static int webServerPort; // 改为static
}

方案2:移除Controller上的@Validated(如果不需要校验)

如果接口不需要参数校验,直接去掉MyController上的@Validated注解,Spring就不会生成代理,控制器实例唯一,字段值会保持一致。

方案3:拆分事件监听逻辑到独立Bean

把端口监听逻辑抽成单独的组件类,避免和控制器耦合,然后在控制器中注入该组件获取端口:

@Component
public class ServerPortHolder {
    private int webServerPort;

    @EventListener
    void onApplicationEvent(final ReactiveWebServerInitializedEvent event) {
        webServerPort = event.getWebServer().getPort();
        log.debug("webServerPort: {}", webServerPort);
    }

    public int getWebServerPort() {
        return webServerPort;
    }
}

@Validated
@RestController
class MyController {
    private final ServerPortHolder portHolder;

    // 构造注入
    public MyController(ServerPortHolder portHolder) {
        this.portHolder = portHolder;
    }

    @GetMapping(path = "/")
    Mono<Void> readStates(final ServerHttpResponse response) {
        log.debug("webServerPort: {}", portHolder.getWebServerPort());
        // ... 其他逻辑
    }    
}

方案4:通过Environment获取端口

直接从Spring环境中获取端口值,无需监听事件:

@Validated
@RestController
class MyController {
    private final Environment environment;

    public MyController(Environment environment) {
        this.environment = environment;
    }

    @GetMapping(path = "/")
    Mono<Void> readStates(final ServerHttpResponse response) {
        int webServerPort = environment.getProperty("server.port", Integer.class, 0);
        log.debug("webServerPort: {}", webServerPort);
        // ... 其他逻辑
    }    
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 13:47:28