当前位置: 首页 > news >正文

谷粒商城 - 编写一个自定义校验注解

目录

开始

未来实现效果

第一步:编写自定义校验注解

第二步:编写自定义校验器

第三步:编写配置文件

效果演示


 

开始


未来实现效果

编写一个 @ListValue 注解,可以实现功能有:

  • 限定字段的值,例如指定只能为 1 或 2.
  • 支持自定义错误信息.
  • 支持分组校验.

第一步:编写自定义校验注解

import jakarta.validation.Constraint
import jakarta.validation.Payload
import kotlin.annotation.AnnotationRetention.RUNTIME
import kotlin.annotation.AnnotationTarget.*
import kotlin.reflect.KClass@MustBeDocumented
@Constraint(validatedBy = [ListValueConstraintValidator::class])
@Target(FUNCTION, FIELD, ANNOTATION_CLASS, CONSTRUCTOR, VALUE_PARAMETER, TYPE)
@Retention(RUNTIME)
annotation class ListValue(val message: String = "{org.cyk.gulimall.product.infra.config.exception.ListValue.message}",val groups: Array<KClass<*>> = [],val payload: Array<KClass<out Payload>> = [],val vals: IntArray = []
)

a)注解解释: 

  • @MustBeDocumented

    这个注解表示使用该注解的注解应该包含在生成的Kotlin文档中。换句话说,当使用KDoc生成文档时,应用了 MustBeDocumented 的注解将会出现在文档中。

  • @Constraint(validatedBy = [ListValueConstraintValidator::class])

    这个注解定义了该注解是一个校验约束,并且指定了用来校验该注解的逻辑类。ListValueConstraintValidator::class 是一个自定义校验类(下文中详细讲)

  • @Target

    这个注解定义了自定义注解可以应用的目标元素。可以是方法、字段、注解类型、构造函数、参数或类型使用。在Kotlin中,它们分别对应 FUNCTION, FIELD, ANNOTATION_CLASS, CONSTRUCTOR, VALUE_PARAMETER, TYPE 这样可以控制自定义注解可以应用于哪些代码元素。

  • @Retention(RUNTIME)

    这个注解定义了自定义注解的保留策略.  RUNTIME表示注解将在运行时保留,因此可以通过反射机制访问注解信息。其他可选的保留策略包括 SOURCE(只在源代码中保留)和 CLASS(在编译时保留,但在运行时不可见)。

b)成员解释:

Note:message、groups、payload 在自定义校验注解中必须要有,因为是 JSR303 中的规范(可以参考其他校验注解,例如 @NotBlank)

  • message:自定义错误信息去哪个地方取(下文中会详细讲解).
  • groups:支持分组校验功能.
  • payload:支持自定义负载信息.
  • vals:vals 是自定义的,用来给校验注解传递值,例如 @ListValue(vals = [1, 2]).

第二步:编写自定义校验器

上面提到的 @Constraint(validatedBy = [ListValueConstraintValidator::class]) 中的 ListValueConstraintValidator 就是自定义校验器,负责处理校验核心逻辑.

例如你是这样使用注解的@ListValue(vals=[1,2]) 

那么 initialize 方法就可以拿到其中 vals,进行初始化(逻辑自定义)

isValid 方法就是将来使用时触发的逻辑

import jakarta.validation.ConstraintValidator
import jakarta.validation.ConstraintValidatorContextclass ListValueConstraintValidator: ConstraintValidator<ListValue, Int> {private lateinit var set: Set<Int>/*** 初始化方法*/override fun initialize(constraintAnnotation: ListValue) {set = constraintAnnotation.vals.toSet()}/*** @param p0: 需要校验的值*/override fun isValid(p0: Int, p1: ConstraintValidatorContext): Boolean {return set.contains(p0)}}

Ps:@Constraint(validatedBy = [ ... ]) 中还可以指定多个不同的校验器,来适配不同类型的校验

第三步:编写配置文件

在编写自定义校验注解时,里面有一个成员 message,他就会去配置文件(ValidationMessages.properties)找这个配置.

因此这里我们在 resource 目录下需要创建一个 ValidationMessages.properties 配置文件,编写内容如下:

org.cyk.gulimall.product.infra.config.exception.ListValue.message=must be a specified value~

Ps:key 就是 message 默认值(一般就取 自定义校验注解的全限定类名.message ),value 就是校验错误提示的默认信息

效果演示

a)demo 如下:

    @GetMapping("/value")fun getValue(@RequestBody @Valid dto: ValueDto): ApiResp<String> {return ApiResp.ok("ok")}data class ValueDto (@field:ListValue(vals = [1, 2])val status: Int
)

a)当输入错误的值时.

Ps:这个默认错误信息,也可以在统一异常处理中,专门提取出来.

b)输入的值正确时

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • k8s-第一节-minikube
  • [从0开始轨迹预测][NMS]:NMS的应用(目标检测、轨迹预测)
  • 数据库图形化管理界面应用 Navicat Premium 使用教程
  • 基于SpringBoot构造超简易QQ邮件服务发送 第二版
  • 【持续集成_03课_Linux部署Sonar+Gogs+Jenkins】
  • HTML(30)——动画
  • QT调节屏幕亮度
  • 每日一练 - RSTP响应端口故障后的处理流程
  • springsecurity(学习自用)
  • 【漏洞复现】29网课交单平台 SQL注入
  • HTML5+JavaScript单词游戏
  • 博美犬插画:成都亚恒丰创教育科技有限公司
  • 葵花奖见证品牌实力 乐橙旗舰智能锁公开首秀引全场热议
  • java-反射 2
  • Segmentation fault (core dumped)
  • css布局,左右固定中间自适应实现
  • egg(89)--egg之redis的发布和订阅
  • Java 网络编程(2):UDP 的使用
  • maya建模与骨骼动画快速实现人工鱼
  • MobX
  • Promise面试题,控制异步流程
  • scrapy学习之路4(itemloder的使用)
  • 看图轻松理解数据结构与算法系列(基于数组的栈)
  • 可能是历史上最全的CC0版权可以免费商用的图片网站
  • 力扣(LeetCode)965
  • 面试题:给你个id,去拿到name,多叉树遍历
  • -- 数据结构 顺序表 --Java
  • 新版博客前端前瞻
  • 正则学习笔记
  • LevelDB 入门 —— 全面了解 LevelDB 的功能特性
  • LIGO、Virgo第三轮探测告捷,同时探测到一对黑洞合并产生的引力波事件 ...
  • ​RecSys 2022 | 面向人岗匹配的双向选择偏好建模
  • #宝哥教你#查看jquery绑定的事件函数
  • #知识分享#笔记#学习方法
  • (1)STL算法之遍历容器
  • (13)Hive调优——动态分区导致的小文件问题
  • (CPU/GPU)粒子继承贴图颜色发射
  • (M)unity2D敌人的创建、人物属性设置,遇敌掉血
  • (PyTorch)TCN和RNN/LSTM/GRU结合实现时间序列预测
  • (阿里云万网)-域名注册购买实名流程
  • (附源码)springboot掌上博客系统 毕业设计063131
  • (深度全面解析)ChatGPT的重大更新给创业者带来了哪些红利机会
  • (四)搭建容器云管理平台笔记—安装ETCD(不使用证书)
  • (一)utf8mb4_general_ci 和 utf8mb4_unicode_ci 适用排序和比较规则场景
  • (原創) 如何動態建立二維陣列(多維陣列)? (.NET) (C#)
  • (转) Face-Resources
  • (转)IOS中获取各种文件的目录路径的方法
  • (转)利用ant在Mac 下自动化打包签名Android程序
  • .NET 6 Mysql Canal (CDC 增量同步,捕获变更数据) 案例版
  • .net 调用海康SDK以及常见的坑解释
  • .NET/C# 中你可以在代码中写多个 Main 函数,然后按需要随时切换
  • .NET设计模式(8):适配器模式(Adapter Pattern)
  • .sh 的运行
  • @ConditionalOnProperty注解使用说明
  • @德人合科技——天锐绿盾 | 图纸加密软件有哪些功能呢?