在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
相关产品推荐
相关产品推荐

