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

在Micronaut中使用@RequestBean结合Java Record遇编译错误

在Micronaut中使用Java Record结合@Valid和@RequestBean的简洁方案

问题重现

在Micronaut中尝试用Java Record作为@RequestBean并结合@Valid校验时,遇到如下编译错误:

/Users/user/IdeaProjects/record_test/src/main/java/com/example/ReadController.java:16:28
java: Parameter of Primary Constructor (or @Creator Method) [id] for type [com.example.ReadBean] has one of @Bindable annotations. This is not supported.
  Note1: Primary constructor is a constructor that have parameters or is annotated with @Creator.
  Note2: In case you have multiple @Creator constructors, first is used as primary constructor.

相关代码如下:

ReadBean.java

package com.example;

import io.micronaut.core.annotation.Introspected;
import io.micronaut.core.annotation.Nullable;
import io.micronaut.http.HttpRequest;
import io.micronaut.http.annotation.PathVariable;

import javax.validation.constraints.Positive;

@Introspected
public record ReadBean(HttpRequest<?> httpRequest, @PathVariable @Nullable @Positive Integer id) {
}

ReadController.java

package com.example;

import io.micronaut.http.HttpResponse;
import io.micronaut.http.MediaType;
import io.micronaut.http.annotation.Controller;
import io.micronaut.http.annotation.Get;
import io.micronaut.http.annotation.Produces;
import io.micronaut.http.annotation.RequestBean;

import javax.validation.Valid;

@Controller("/api/read")
public class ReadController {
    @Get
    @Produces(MediaType.APPLICATION_JSON)
    public HttpResponse<?> read(@Valid @RequestBean ReadBean bean) {
        return HttpResponse.ok(bean);
    }
}

现有临时方案

通过显式声明record的构造函数可以规避错误,但不够简洁:

package com.example;

import io.micronaut.core.annotation.Introspected;
import io.micronaut.core.annotation.Nullable;
import io.micronaut.http.HttpRequest;
import io.micronaut.http.annotation.PathVariable;

import javax.validation.constraints.Positive;

@Introspected
public record ReadBean(HttpRequest<?> httpRequest, @PathVariable @Nullable @Positive Integer id) {
    public ReadBean(HttpRequest<?> httpRequest, Integer id) {
        this.httpRequest = httpRequest;
        this.id = id;
    }
}

简洁解决方案

无需显式编写构造函数,只需将@PathVariable注解从record主构造函数的参数上移到对应的访问器方法(即id()方法)即可:

package com.example;

import io.micronaut.core.annotation.Introspected;
import io.micronaut.core.annotation.Nullable;
import io.micronaut.http.HttpRequest;
import io.micronaut.http.annotation.PathVariable;

import javax.validation.constraints.Positive;

@Introspected
public record ReadBean(HttpRequest<?> httpRequest, @Nullable @Positive Integer id) {
    @Override
    @PathVariable
    public @Nullable @Positive Integer id() {
        return id;
    }
}

原理说明

Micronaut禁止在record的主构造函数参数上使用@Bindable相关注解(包括@PathVariable),因为record的主构造函数会被默认视为@Creator构造函数,这类注解在构造参数上会触发绑定逻辑冲突。

将@PathVariable移到record的访问器方法上后,既可以让Micronaut正确识别路径变量的绑定规则,又能保留@Nullable和@Positive的校验作用,同时完全利用Java Record的简洁特性,无需手动编写构造函数。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 14:46:07