Kotlin Spring中集合泛型元素的UUID校验注解使用方法
Kotlin Spring中对集合泛型元素做UUID校验的解决办法
问题场景
把Java Spring应用迁移到Kotlin Spring时,写了如下DTO类:
@JsonIgnoreProperties(ignoreUnknown = true) data class filter( @Schema( title = "Collection of ids", example = "[\"2f21b7ed-11ec-43b7-ba89-2d014d61a168\", \"367693c6-5aef-40f0-9f91-fea8ad4e76ca\"]" ) @field:NotNull @field:Size(min = 1, max = 20) val ids: Set<@UUID String>? = null, @Schema(title = "Collection of names", example = "[\"Group-A\", \"Group-B\"]") val names: @Size(min = 1, max = 20) MutableSet<String>? = null )
使用该Filter对象时,@field:NotNull校验正常,未传ids字段时Spring会返回400且不进入控制器,但Set泛型上的@UUID注解完全不生效,尝试添加@field:前缀还会触发编译错误,需要解决如何在Kotlin中为集合泛型的元素添加UUID校验注解的问题。
解决方法
1. 确认@UUID注解支持TYPE_USE目标
如果是自定义的@UUID校验注解,必须确保它的@Target包含TYPE_USE,否则无法在泛型参数上使用:
@Target(AnnotationTarget.TYPE_USE, AnnotationTarget.FIELD) @Retention(RetentionPolicy.RUNTIME) @Constraint(validatedBy = [UuidValidator::class]) annotation class UUID( val message: String = "UUID格式无效", val groups: Array<KClass<*>> = [], val payload: Array<KClass<out Payload>> = [] )
2. 给集合字段添加@Valid触发元素校验
Spring Validation默认不会自动校验集合内的元素,需要在集合字段上添加@Valid注解,才能触发元素级别的校验逻辑:
@JsonIgnoreProperties(ignoreUnknown = true) data class Filter( @Schema( title = "Collection of ids", example = "[\"2f21b7ed-11ec-43b7-ba89-2d014d61a168\", \"367693c6-5aef-40f0-9f91-fea8ad4e76ca\"]" ) @field:NotNull @field:Size(min = 1, max = 20) @field:Valid // 开启集合元素校验 val ids: Set<@UUID String>? = null, @Schema(title = "Collection of names", example = "[\"Group-A\", \"Group-B\"]") @field:Valid // 开启集合元素校验 val names: MutableSet<@Size(min = 1, max = 20) String>? = null )
注意:原names字段的@Size是校验集合本身的大小,移到泛型String上才是校验每个name的长度,需修正这个写法。
3. 用@Pattern替代自定义@UUID(无需自定义逻辑时)
如果只是校验UUID格式,没必要自定义注解,直接用Spring自带的@Pattern即可,同样要配合@Valid:
@JsonIgnoreProperties(ignoreUnknown = true) data class Filter( @Schema( title = "Collection of ids", example = "[\"2f21b7ed-11ec-43b7-ba89-2d014d61a168\", \"367693c6-5aef-40f0-9f91-fea8ad4e76ca\"]" ) @field:NotNull @field:Size(min = 1, max = 20) @field:Valid val ids: Set<@Pattern(regexp = "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$") String>? = null, // 其他字段... )
4. 确保全局方法校验已开启(可选)
需要确认Spring配置中开启了方法校验,比如在启动类上添加@Validated:
@SpringBootApplication @Validated class Application fun main(args: Array<String>) { runApplication<Application>(*args) }
同时控制器方法的参数上要添加@Valid:
@RestController @RequestMapping("/api") class MyController { @GetMapping("/filter") fun getFilteredData(@Valid filter: Filter): ResponseEntity<Any> { // 业务逻辑处理 return ResponseEntity.ok().build() } }
内容的提问来源于stack exchange,提问作者Eran Friedland
相关产品推荐
相关产品推荐

