springBoot中自定義一個validation注解,實現指定枚舉值校驗

緣由

在后臺寫接口的時候,經常會出現dto某個屬性是映射到一個枚舉的情況。有時候還會出現只能映射到枚舉類中部分枚舉值的情況。以前都是在service里面自行判斷,很多地方代碼冗余,所以就想著弄一個自定義的validation注解來實現。
例如下面某個DTO的屬性transmissionType,需要映射到TransmissionType枚舉類

/*** @see TransmissionType#getCode()*/
private Integer transmissionType;

代碼

新建一個接口

新建這個接口是為了后面獲取枚舉的code值,大部分時候,枚舉的code都是int類型的,所以這里也只考慮了這種情況。如果是其他類型的,需要自行改造一下。比如另外建一個類型的接口,在EnumCodeValidator類里面判斷處理。不想再建接口的話,就在此接口里面加一個返回code類型的方法。然后根據類型來決定是調用getCode獲取值還是getCodeStr獲取。

/*** 公共的接口,用于在validator里面獲取枚舉的code值,這里只考慮int類型的。*/
public interface EnumCode {int getCode();
}

新建一個注解

這個注解除了指定枚舉類之外,還可以指定要包含或排除的枚舉名稱(是名稱,在ConstraintValidator是通過枚舉name方法拿名稱的)

import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;/*** 驗證枚舉值注解<br>* 枚舉的code需要是int類型*/
@Constraint(validatedBy = EnumCodeValidator.class)
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface ValidEnumCode {/*** 對應的枚舉類的Class*/Class<? extends Enum<?>> enumClass();/*** 過濾的枚舉名稱 表示需要哪些名稱的*/String[] filterEnumName() default {};/*** 排除的名稱名稱*/String[] excludeEnumName() default {};String message() default "值必須是已存在的枚舉值";Class<?>[] groups() default {};Class<? extends Payload>[] payload() default {};
}

自定義驗證器,實現ConstraintValidator接口

import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;/*** 具體的校驗規則*/
public class EnumCodeValidator implements ConstraintValidator<ValidEnumCode, Integer> {private Class<? extends Enum<?>> enumClass;private String[] filter;private String[] exclude;@Overridepublic void initialize(ValidEnumCode constraintAnnotation) {this.enumClass = constraintAnnotation.enumClass();this.filter = constraintAnnotation.filterEnumName();this.exclude = constraintAnnotation.excludeEnumName();}@Overridepublic boolean isValid(Integer value, ConstraintValidatorContext context) {if (value == null) {return true;}Enum<?>[] enums = enumClass.getEnumConstants();boolean filterEmpty = ArrayUtil.isEmpty(filter);boolean excludeNonEmpty = ArrayUtil.isNotEmpty(exclude);List<Integer> validCodes = Arrays.stream(enums).filter(e -> {if (excludeNonEmpty) {for (String excludeName : exclude) {if (StrUtil.equals(excludeName, e.name())) {return false;}}}if (filterEmpty) {return true;}for (String filterName : filter) {if (StrUtil.equals(filterName, e.name())) {return true;}}return false;}).mapToInt(e -> ((EnumCode) e).getCode()).boxed().collect(Collectors.toList());return validCodes.contains(value);}
}

使用

枚舉類先implements EnumCode接口
在這里插入圖片描述

常見的三種情況

  1. 必須是TransmissionType枚舉類中的屬性值
     /*** @see TransmissionType#getCode()*/@ValidEnumCode(enumClass = TransmissionType.class)private Integer transmissionType;
    
  2. 必須是TransmissionType枚舉類中的屬性值,且名稱為STRATEGYNEWS
     public R<List<LinkVO>> newArticle(@RequestParam("articleType")@ValidEnumCode(enumClass = ArticleType.class,filterEnumName = {"STRATEGY", "NEWS"}) Integer articleType) {
    
  3. 必須是TransmissionType枚舉類中的屬性值,且排除掉名稱為STRATEGYNEWS
     public R<ArticlesVO> getInfoByArticleType(@RequestParam("articleType")@ValidEnumCode(enumClass = ArticleType.class,excludeEnumName = {"STRATEGY", "NEWS"}) Integer articleType) {
    

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/79610.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/79610.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/79610.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

MySQL數據庫中篇

#作者&#xff1a;允砸兒 #日期&#xff1a;乙巳青蛇年 四月初九 筆者繼續帶朋友們了解mysql數據庫中篇的內容。多了不說&#xff0c;少了不嘮&#xff0c;咱們直接就開寫。 書接上回筆者在上篇中介紹了什么是數據庫和數據庫的一些基礎的概念&#xff0c;以及mysql數據庫的…

AI如何重塑DDoS防護行業?六大變革與未來展望

隨著AI技術的深度滲透&#xff0c;DDoS防護行業正經歷一場從“規則驅動”到“智能驅動”的范式革命。傳統依賴靜態閾值和人工規則的防御模式已難以應對新型攻擊&#xff0c;而AI的引入不僅提升了檢測精度&#xff0c;更重構了防護體系的底層邏輯。以下是AI帶來的六大核心變革及…

五一作業-day04

文章目錄 1. **ps -ef是顯示當前系統進程的命令,統計下當前系統一共有多少進程**2. **last命令用于顯示所用用戶最近1次登錄情況,awk可以取出某一列,現在要取出last命令第1列并去重統計次數**3. **secure日志是用戶的登錄日志,過濾出secure日志中的Failed password的次數(用課堂…

抽獎系統(基于Tkinter)

一、抽獎規則及使用方法 抽獎規則&#xff1a; 從1-138個號碼中隨機抽獎&#xff0c;共進行n輪抽獎&#xff0c;每個號碼僅有一次中獎機會&#xff0c;即已中獎的號碼不會再次中獎。 使用方法&#xff1a; 要求開始抽獎后屏幕上隨機滾動顯示中獎號碼&#xff0c;點擊“STOP”之…

window 系統 使用ollama + docker + deepseek R1+ Dify 搭建本地個人助手

1. 下載ollama &#xff0c;官網 下載地址&#xff1a;Download Ollama on macOS&#xff0c;選擇 Window 下載完成后&#xff0c;可在終端 使用 ollama --version 2. 下載 本地大模型&#xff0c;這里下載deepseek r1 7b 3.下載Embed模型 Embed模型 是文本工具向量化的核心工…

【學習筆記】 強化學習:實用方法論

作者選擇了由 Ian Goodfellow、Yoshua Bengio 和 Aaron Courville 三位大佬撰寫的《Deep Learning》(人工智能領域的經典教程&#xff0c;深度學習領域研究生必讀教材),開始深度學習領域學習&#xff0c;深入全面的理解深度學習的理論知識。 之前的文章參考下面的鏈接&#xf…

益鑫通汽車連接器可替代Molex,JST

# 探秘優質車規連接器 在汽車向新能源和智能化發展的進程中&#xff0c;車規連接器對汽車電子系統的穩定運行至關重要。有企業憑借技術與創新&#xff0c;在該領域表現出色。其車規連接器類型多樣&#xff0c;能滿足汽車不同系統連接需求。 一款2.54Pitch線對板連接器&#xff…

【WPF】將Bitmap圖像轉換為BitmapImage,并給Image控件顯示圖像

1.C#將Bitmap圖像轉換為BitmapImage&#xff0c;并給Image控件顯示圖像后臺實現 public void InitImage(Bitmap bitmap){try{// 將Bitmap轉換為WPF的BitmapImageBitmapImage bitmapImage;using (MemoryStream memory new MemoryStream()){bitmap.Save(memory, System.Drawing.…

Python從入門到高手8.2節-元組的常用操作符

目錄 ?8.2.1 元組的常用操作符 8.2.2 []操作符: 索引訪問元組 8.2.3 [:]操作符&#xff1a;元組的切片 8.2.4 操作符&#xff1a;元組的加法 8.2.5 *操作符&#xff1a;元組的乘法 8.2.6 元組的關系運算 8.2.7 in操作符&#xff1a;查找元素 8.2.8 五一她玩了個狗吃…

Vue3源碼學習4-effect中為什么使用WeakMap,Set?

文章目錄 前言1. 精細化依賴追蹤2. 高效的依賴收集與觸發3. 自動內存管理&#xff0c;防止內存泄漏4. 支持復雜場景 前言 在 mini vue - effect 實現中 設計&#xff08;WeakMap → Map → Set → effect函數&#xff09;有以下幾個重要原因&#xff1a; 1. 精細化依賴追蹤 W…

TinyML 邊緣智能:在資源受限 MCU 上部署 AI

前言 在物聯網(IoT)和智能邊緣計算的時代浪潮下,TinyML(微型機器學習)正以前所未有的速度改變著我們與設備交互的方式。它將 AI 推理能力放在資源極度受限的 MCU(微控制器)上,兼顧實時性、低功耗和數據隱私,成為智能家居、可穿戴設備、工業檢測等場景的核心技術。盡管…

技術白皮書:Oracle GoldenGate 優勢

本文為技術白皮書Oracle GoldenGate 優勢的翻譯及閱讀筆記。以下注釋中GoldenGate為OGG。 副標題為&#xff1a;Oracle 數據庫的變更數據捕獲 (CDC) 技術比較。版本為July, 2021, Version 2.1。 Oracle GoldenGate 被客戶和分析師公認為功能最齊全、性能最高、最值得信賴的數…

Android控件VideoView用法

一 控件UI <VideoViewandroid:id="@+id/videoView"android:layout_width="match_parent"android:layout_height="match_parent"android:scaleType="fitCenter" /> 二 配置 <?xml version="1.0" encoding="u…

React 第三十六節 Router 中 useParams 的具體使用及詳細介紹

一、useParams 的基本用法 用途&#xff1a;用于在組件中獲取當前 URL 的動態路由參數&#xff08;如 /user/:id 中的 id&#xff09;。 import { Routes, Route, useParams } from react-router-dom;// 定義路由 function App() {return (<Routes><Route path"…

C++戰勝白蟻 2024年信息素養大賽復賽 C++小學/初中組 算法創意實踐挑戰賽 真題詳細解析

目錄 C++戰勝白蟻 一、題目要求 1、編程實現 2、輸入輸出 二、算法分析 三、程序編寫 四、運行結果 五、考點分析 六、 推薦資料 1、C++資料 2、Scratch資料 3、Python資料 C++戰勝白蟻 2024年信息素養大賽 C++復賽真題 一、題目要求 1、編程實現 小明因為很長…

Linux網絡編程 day4

inet_pton&#xff1a;IP 字符串 → 網絡字節序地址 ntohl&#xff1a;網絡字節序 → 主機字節序 TCP狀態轉換圖(重點) 可以通過下面這行代碼查看目前網絡狀態 netstat -apn | grep client 1、主動發起請求端 close-->SYN-->SYN_SENT-->接收ACK、SYN-->SYN_SEN…

基于springboot+vue的個人財務管理系統

開發語言&#xff1a;Java框架&#xff1a;springbootJDK版本&#xff1a;JDK1.8服務器&#xff1a;tomcat7數據庫&#xff1a;mysql 5.7數據庫工具&#xff1a;Navicat12開發軟件&#xff1a;eclipse/myeclipse/ideaMaven包&#xff1a;Maven3.3.9 系統展示 用戶信息管理 賬…

ffmpeg 元數據-avformatcontext字段 AVDictionary *metadata;

ffmpeg 元數據 1. 解釋什么是ffmpeg元數據 ffmpeg元數據是指與音視頻文件相關的附加信息&#xff0c;這些信息不直接影響音視頻內容的播放&#xff0c;但提供了關于文件內容、創作者、版權、播放參數等的有用信息。元數據在音視頻文件的處理、管理和共享中起著重要作用。 2.…

55.[前端開發-前端工程化]Day02-包管理工具npm等

包管理工具詳解 npm、yarn、cnpm、npx、pnpm 1 npm包管理工具 代碼共享方案 包管理工具npm 2 package配置文件 npm的配置文件 方式二 常見的配置文件 常見的屬性 常見的屬性 常見的屬性 依賴的版本管理 常見屬性 npm install 命令 項目安裝 3 npm install原理 npm instal…

Spring MVC @RequestBody 注解怎么用?接收什么格式的數據?

RequestBody 注解的作用 RequestBody 將方法上的參數綁定到 HTTP 請求的 Body&#xff08;請求體&#xff09;的內容上。 當客戶端發送一個包含數據的請求體&#xff08;通常在 POST, PUT, PATCH 請求中&#xff09;時&#xff0c;RequestBody 告訴 Spring MVC 讀取這個請求體…