在 Spring Boot 中的类级别请求主体验证

问题描述 投票:0回答:1

我有一个 dto 类,我正在对其应用类级别自定义约束。我的问题是我希望它在创建和更新 api 时表现不同。在属性验证的情况下,使用不同的注释很容易实现,但在类级别上,我在寻找正确的解决方案方面遇到了一些问题。这是我想要实现的目标的一个简约示例:


interface Create
interface Update

@ValidApiDto(groups = [Create::class, Update::class])
data class ApiDto(
    val id: Long,
    val metaData: MetaDataDto,
    // many other properties
)

@Constraint(validatedBy = [ApiDtoValidator::class])
@Target(allowedTargets = [AnnotationTarget.CLASS])
@Retention(AnnotationRetention.RUNTIME)
@MustBeDocumented
annotation class ValidApiDto(
    val message: String = "Invalid api dto!",
    val groups: Array<KClass<*>> = [],
    val payload: Array<KClass<out Payload>> = []
)


class ApiDtoValidator: ConstraintValidator<ValidApiDto, ApiDto> {
    override fun isValid(dto: ApiDto, context: ConstraintValidatorContext): Boolean {
        // My logic comes here. Adapt behavior based on update or create
        return true
    }
}

@RestController
@Validated
class MyRestController {
    
    @PostMapping("/post")
    @Validated(value = [Create::class])
    fun post(@Valid dto: ApiDto): ResponseEntity<*>? {
        return null
    }
    
    @PutMapping("/put")
    @Validated(value = [Update::class])
    fun update(@Valid dto: ApiDto): ResponseEntity<*>? {
        return null
    }
}

一个验证器中是否可以有不同的逻辑?

我试图通过上下文找到传递的组,但它给了我所有可能的组,在我的情况下创建和更新。

spring-boot kotlin bean-validation
1个回答
0
投票

验证组是过滤约束的方法,即将约束分组并根据条件执行组中的约束。

如果您想要一个条件验证器实现,您可以做的是:

  1. 向约束注释添加属性:
@Constraint(validatedBy = [ApiDtoValidator::class])
@Target(allowedTargets = [AnnotationTarget.CLASS])
@Retention(AnnotationRetention.RUNTIME)
@MustBeDocumented
annotation class ValidApiDto(
    val message: String = "Invalid api dto!",
    val groups: Array<KClass<*>> = [],
    val payload: Array<KClass<out Payload>> = [],
    // add some enum, or a boolean, whatever you find more suitable:
    val type: ConstraintType = ConstraintType.CREATE 
)
  1. 使用新属性和组将 DTO 注释为:
@ValidApiDto(type = ConstraintType.CREATE, groups = [Create::class])
@ValidApiDto(type = ConstraintType.UPDATE, groups = [Update::class])
data class ApiDto(
    val id: Long,
    val metaData: MetaDataDto,
    // many other properties
)

通过这种方式,您可以将具有不同配置的约束分配给不同的验证组,并且只有相应的约束将应用于该组。

在约束验证器的实现中,您将可以访问注释属性:

class ApiDtoValidator: ConstraintValidator<ValidApiDto, ApiDto> {
    override fun initialize(ValidApiDto constraintAnnotation) {
        // access your configured type value:
        val type constraintAnnotation.type();
    }
    override fun isValid(dto: ApiDto, context: ConstraintValidatorContext): Boolean {
        // My logic comes here. Adapt behavior based on update or create
        return true
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.