化繁為簡,使用Hibernate Validator實現參數校驗

前言

? ? ? ? 在之前的悅享校園的開發中使用了SSM框架,由于當時并沒有使用參數參數校驗工具,方法的入參判斷使用了大量的if else語句,代碼十分臃腫,因此最近在重構代碼時,將框架改為SpringBoot后,引入了Hibernate Validator校驗工具對參數進行優雅校驗(SSM同樣可用)。本文將通過實例來演示如何使用該框架。

環境配置

JDK 1.8

Spring Boot 2.7.12

導入依賴

        <!--SpringBoot 2.3開始,校驗包單獨組件,需要手動引入 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-validation</artifactId></dependency>

基礎校驗

在正式開始之前,需要先對以下的內容作以了解,方便后續的學習。

校驗注解

Hibernate Validator,提供了豐富的校驗注解來供我們使用,這里列舉一些比較常用的:

注解解釋
@Null

驗證對象是否為空

@NotNull

驗證對象是否為非空

@NotBlank

用于String對象,驗證字符串不為空且trim()后長度大于0

@Length

驗證對象的長度是否符合

@Size

驗證對象長度是否在給定的范圍之內(用于Array,Collection,Map,String)

@Min

入參對象的值不能小于該值(用于Number和String)

@Max

入參對象的值不能大于該值(用于Number和String)

@Digits

驗證number和string的構成是否合法

@Past

驗證date和calendar對象是否在當前時間之前

@Future

驗證date和calendar對象是否在當前時間之后

@Pattern

驗證是否符合正則表達式規則

@Email驗證郵箱
@Positive

驗證輸入的對象是否非負數

@Range

驗證輸入的對象的值是否在指定范圍內

參數綁定

@PathVariable

該注解用于接收具有Restful風格的參數,如/api/v1/1001,最終userId的值為1001

如下代碼中,使用name屬性可以指定GetMapping中的id名稱與之對應,從而可以自定義參數名稱userId,而不是使用默認名稱id

@GetMapping("/v1/{id}")
public void getMsg(@PathVariable(name = "id") Integer userId){}

@RequestParam

該注解用于接收查詢參數,如/api/v1/product?user="123",則user的值為123。該注解也可用于接收form-data類型的數據。

當在參數前使用@RequireParam時,當請求該方法時,對應的參數必須存在,否則會引發異常,可使用@RequireParam(required = false)指明該參數非必須,該注解在入參為null時可提供默認值。

@GetMapping("/v1/product")
public void getMsg(@RequestParam String user){}

@RequestBody

該注解用于接收JSON格式的數據,如請求為{"name":123,"age":18},需要有對應的實體類作為映射。

@PostMapping("/v1/user")
public void getMsg(@RequestBody User user){}

@Validated

該注解可以作用于類、方法、參數上,用于開啟參數校驗。

@Valid

該注解可以作用于方法、參數、字段、構造器上,同樣可以用于參數校驗。

單參校驗

將@Validated注解用于類上,可以不用在每個方法的參數上重復開啟校驗,使用前面提的基礎校驗即可對參數作約束。?

校驗方法

@RestController
@RequestMapping("/v1/hello")
@Slf4j
@Validated
public class HelloController {/*** GetMapping 請求* @param name 用戶名稱* @param uid  用戶uid* @return*/@GetMapping("/{id}")public ResultDataVO getMsg(@RequestParam String name,@Max(value = 10,message = "最大值不能超過10")@PathVariable(name = "id") int uid) {log.info("訪問hello下的msg方法。");String result = "Hello,"+name+" id "+uid;return ResultDataVO.success(result);}
}

請求參數????????響應結果

?由于我們沒有給String參數賦值,因此默認為空字符串。但由于在uid上使用了@Max注解,因此當入參為100時便會出現異常,而返回的JSON格式為全局的響應處理,在后續的文章會提到。

對象校驗

當我們在使用中,往往會遇到多個參數的情況,由于get請求對參數長度有限制,且參數會拼接在URL中, 因此對于此場景我們一般使用對象的方式來接收參數,而對于我們的參數也將傳入也將用JSON格式。

由于使用JSON格式傳參,將使用@RequestBody注解,除此之外還要使用@Validated或@Valid注解,關于兩者的選擇,只需要記住分組校驗使用@Validated,否則二者均可。

即使在類上添加了@Validated注解,此處仍然需要以上兩個注解之一,否則參數校驗將無效。

校驗方法

@RestController
@RequestMapping("/v1/hello")
@Slf4j
@Validated
public class HelloController {/*** 對象校驗示例* @param user* @return */@PostMapping("/msg")public ResultDataVO(@RequestBody @Valid UserDTO user){return ResultDataVO.success(user.toString());}
}

UserDTO

@Data
@AllArgsConstructor
@NoArgsConstructor
public class UserDTO {/*** id*/@Min(value = 1,message = "id值不合法")@Positiveprivate Integer id;/*** 昵稱*/@NotBlank(message = "用戶名不能為空")@Length(min = 4,max=10,message = "用戶名必須在4-10個字符之間")private String username;/*** 年齡*/@Range(min = 1,max=120,message = "年齡不在合法范圍內")@NotNull(message = "age不能為空")private Integer age;
}

上述代碼中,參數為UserDTO對象,其中包含三個待校驗的字段,由于未涉及到分組校驗,因此校驗方法中參數前使用@Valid注解(@Validated注解亦可),注意入參的字段名稱需要和UserDTO中的名稱一致。

請求參數

?響應結果

分組校驗

假設有這樣的場景,在用戶登錄和修改密碼中,兩者分別需要如下參數,登錄時需要用戶名、密碼,而修改時需要密碼、新密碼,為了方便管理,只使用了一個DTO類來存放上述的字段,此時由于這些參數需要在不同的場景下校驗,而加上基礎校驗的注解會導致所有參數均被校驗,面對此問題,我們將使用分組校驗來解決。

可以看到如何代碼中,均是使用了@Validate注解,且注解中含有一個分組接口,使用該接口可以幫助我們告知程序該對那些參數進行校驗。

校驗方法

@RestController
@Slf4j
@RequestMapping("/local/auth")
@Validated
public class LocalAuthController {@Autowiredprivate LocalAuthService localAuthService;/*** 用戶登錄接口* @param localAuthDTO 賬號對象* @return*/@PostMapping("/login")LocalAuthVO loginCheck(@RequestBody @Validated(AuthCheckSequence.class) LocalAuthDTO localAuthDTO){return localAuthService.userLoginCheck(localAuthDTO);}/*** 用戶修改密碼接口* @param localAuthDTO 賬號對象* @return*/@PutMapping("/password")ResultDataVO userChangePassword(@RequestBody@Validated(AuthChangeSequence.class)LocalAuthDTO localAuthDTO){return localAuthService.userModifyPassword(localAuthDTO);}
}

分組接口

AuthChangeSequence?

/*** 分組校驗,用戶登錄*/public interface AuthCheckSequence {}

AuthCheckSequence?

/*** 分組校驗,密碼修改*/
public interface AuthChangeSequence {}

LocalAuthDTO?

@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class LocalAuthDTO {/*** 用戶名*/@NotBlank(message = "用戶名不能為空",groups = AuthCheckSequence.class)@Pattern(regexp = "^[a-zA-Z0-9]{3,8}$", message = "用戶名必須由3-8個字母或數字組成",groups = AuthCheckSequence.UsernameCheck.class)private String username;/*** 密碼*/@NotBlank(message = "密碼不能為空",groups = AuthCheckSequence.class)@Size(min = 6,max = 18, message = "密碼長度必須在6到18位之間",groups = AuthCheckSequence.PasswordCheck.class)private String password;/*** 新密碼,修改密碼時使用*/@NotBlank(message = "新密碼不能為空",groups = AuthChangeSequence.class)@Size(min = 6,max = 18, message = "新密碼長度必須在6到18位之間",groups = AuthChangeSequence.ChangePassword.class)private String newPassword;
}

請求參數

響應結果

從上圖所示請求結果可以看出,使用@Validated注解+分組校驗接口后,將只對該參數中標明了對應分組接口的字段進行校驗,并不會對全部參數進行校驗。????????

順序校驗

由于用戶人數增多,我們將在對用戶進行分組,將在LocalAuthDTO中引入新的字段,而我們所期望的是能夠按照用戶類型,用戶名,密碼的順序來校驗,而不是像之前對象校驗最終顯示的結果那樣,隨機進行校驗并返回結果,因此需要使用在分組校驗的基礎上做一些改進,使其可以按照我們所指定的順序執行校驗,以前面登錄為例:

校驗方法

@RestController
@Slf4j
@RequestMapping("/local/auth")
@Validated
public class LocalAuthController {@Autowiredprivate LocalAuthService localAuthService;/*** 用戶登錄接口* @param localAuthDTO 賬號對象* @return*/@PostMapping("/login")LocalAuthVO loginCheck(@RequestBody @Validated(AuthCheckSequence.class) LocalAuthDTO localAuthDTO){return localAuthService.userLoginCheck(localAuthDTO);}
}

?AuthCheckSequence

通過在該分組接口中新建接口,并使用@GroupSequence注解中參數的順序來實現校驗參數的順序。如下將標識使用AuthCheckSequence分組的參數將按照用戶類型、用戶名???????、密碼的順序進行校驗。

@GroupSequence({AuthCheckSequence.UserTypeCheck.class, AuthCheckSequence.UsernameCheck.class, AuthCheckSequence.PasswordCheck.class})
public interface AuthCheckSequence {/*** 用戶類型*/interface UserTypeCheck {};/*** 用戶名校驗*/interface UsernameCheck {};/*** 密碼校驗*/interface PasswordCheck {};
}

LocalAuthDTO

@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class LocalAuthDTO {/*** 用戶類型 1.用戶 2.商家 3.管理員,目前僅支持用戶和商家類型注冊*/@NotNull(message = "用戶類型不能為空",groups = AuthCheckSequence.UserTypeCheck.class)@Range(min = 1,max = 3,message = "用戶類型不合法",groups =         AuthCheckSequence.UserTypeCheck.class)private Integer userType;/*** 用戶名*/@NotBlank(message = "用戶名不能為空",groups = AuthCheckSequence.UsernameCheck.class)@Pattern(regexp = "^[a-zA-Z0-9]{3,8}$", message = "用戶名必須由3-8個字母或數字組成",groups = AuthCheckSequence.UsernameCheck.class)private String username;/*** 密碼*/@NotBlank(message = "密碼不能為空",groups = AuthCheckSequence.PasswordCheck.class)@Size(min = 6,max = 18, message = "密碼長度必須在6到18位之間",groups = AuthCheckSequence.PasswordCheck.class)private String password;
}

請求參數

?響應結果

?

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

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

相關文章

有一種新型病毒在 3Ds Max 環境中傳播,如何避免?

3ds Max渲染慢&#xff0c;可以使用渲云渲染農場&#xff1a; 渲云渲染農場解決本地渲染慢、電腦配置不足、緊急項目渲染等問題&#xff0c;可批量渲染&#xff0c;批量出結果&#xff0c;速度快&#xff0c;效率高。 此外3dmax支持的CG MAGIC插件專業版正式上線&#xff0c;…

機器學習筆記(1):機器學習入門的概念

導航 一、 人工智能&#xff0c;機器學習&#xff0c;深度學習和傳統學習二、數學基礎三、編程語言 如果你剛剛入門機器學習&#xff0c;會接觸到了非常多的概念。比如人工智能&#xff0c;機器學習&#xff0c;深度學習&#xff0c;神機網絡&#xff0c;強化學習&#xff0c;各…

0基礎學習VR全景平臺篇 第85篇:智慧眼-如何分配角色的權限?

一、功能說明 角色權限&#xff0c;是指給智慧眼的所有角色成員分配具體的操作權限。 二、后臺編輯界面 1、點擊“添加權限”&#xff0c;選擇其可操作的“權限”。注意權限只能逐項選擇&#xff0c;所以如果某個角色擁有多項權限的話&#xff0c;那么需要進行多次添加。“快…

uniapp app 實現右上角回首頁;點homeButton返回上一頁;onNavigationBarButtonTap不生效問題

場景&#xff1a; app&#xff0c;Android移動端 實現點擊右上角圖標&#xff0c;回首頁。 問題&#xff1a;用了官網的 homeButton&#xff0c;圖標正常展示了&#xff0c;也可點擊&#xff0c;但每次點擊后是會返回上一頁而非首頁。 后來查到說&#xff0c;要結合onNavigatio…

linux兩臺服務器互相備份文件(sshpass + crontab)

crontab crontab是linux系統自帶的定時調度軟件&#xff0c;可用于設置周期性被執行的指令&#xff0c;一般用在每天的非高峰負荷時間段運行作業&#xff0c;可在無需人工干預的情況下運行作業。支持在一周或一月中的不同時段運行。 crontab命令允許用戶提交、編輯或刪除相應的…

滴滴Ceph分布式存儲系統優化之鎖優化

摘自&#xff1a;https://mp.weixin.qq.com/s/oWujGOLLGItu1Bv5AuO0-A 2020-09-02 21:45 0.引言 Ceph是國際知名的開源分布式存儲系統&#xff0c;在工業界和學術界都有著重要的影響。Ceph的架構和算法設計發表在國際系統領域頂級會議OSDI、SOSP、SC等上。Ceph社區得到Red Hat…

Transformers架構系列---transformers庫的使用

Transformers最初是由Google發布的論文 Attention is All You Need (2017) 提出的一種新的深度學習網絡架構,這篇論文證明了序列模型(如 LSTM)可以完全被注意力機制取代,甚至可以獲得更好的性能。Transformers網絡結構自2017年提出之后僅僅一兩年的時間內就一直在NLP領域及…

Vue:使用Promise.all()方法并行執行多個請求

在Vue中&#xff0c;可以使用Promise.all()方法來并行執行多個請求。當需要同時執行多個異步請求時&#xff0c;可以將這些請求封裝為Promise對象并使用Promise.all()方法來執行它們。 示例1&#xff1a; 以下是一個示例代碼&#xff0c;展示了如何通過Promise.all()方法并行…

C語言——動態內存管理

動態內存管理詳解 前言&#xff1a;一、為什么存在動態內存分配二、動態內存函數2.1malloc函數2.2calloc函數2.3realloc函數2.4free函數 三、常見的動態內存錯誤3.1 對NULL指針解引用操作3.2 對動態開辟空間的越界訪問3.3 對非動態開辟內存使用free釋放3.4 使用free釋放動態開辟…

Unity UI內存泄漏優化

項目一運行&#xff0c;占用的內存越來越多&#xff0c;不會釋放&#xff0c;導致GC越來越頻繁&#xff0c;越來越慢&#xff0c;這些都是為什么呢&#xff0c;今天從UI方面談起。 首先讓我們來聊聊什么是內存泄漏呢&#xff1f; 一般來講內存泄漏就是指我們的應用向內存申請…

Rabbitmq消息不丟失

目錄 一、消息不丟失1.消息確認2.消息確認業務封裝2.1 發送確認消息測試2.2 消息發送失敗&#xff0c;設置重發機制 一、消息不丟失 消息的不丟失&#xff0c;在MQ角度考慮&#xff0c;一般有三種途徑&#xff1a; 1&#xff0c;生產者不丟數據 2&#xff0c;MQ服務器不丟數據…

設計HTML5列表和超鏈接

在網頁中&#xff0c;大部分信息都是列表結構&#xff0c;如菜單欄、圖文列表、分類導航、新聞列表、欄目列表等。HTML5定義了一套列表標簽&#xff0c;通過列表結構實現對網頁信息的合理排版。另外&#xff0c;網頁中還包含大量超鏈接&#xff0c;通過它實現網頁、位置的跳轉&…

C語言“牽手”微店商品詳情數據方法,微店商品詳情API接口申請指南

微店平臺的商品詳情通常包括以下信息&#xff1a; 商品名稱&#xff1a;展示商品的名稱&#xff0c;用于描述商品的特性和分類。 商品圖片&#xff1a;展示商品的圖片&#xff0c;可以有多張圖片以展示不同角度和細節。 商品價格&#xff1a;顯示商品的銷售價格&#xff0c;可…

nodejs服務后臺持續運行三種方法

nodejs服務后臺持續運行三種方法 一、利用 forever 推薦 forever是一個nodejs守護進程&#xff0c;完全由命令行操控。forever會監控nodejs服務&#xff0c;并在服務掛掉后進行重啟。 1、安裝 forever npm install forever -g 2、啟動服務 service forever start 3、使用…

小程序CSS button按鈕自定義高度之后不居中

問題&#xff1a; 按鈕設置高度后不居中 <view><button class"btn1" size"">Save</button> </view> page {font-size: 30rpx; }.btn1 {margin-top: 100rpx;height: 190rpx;background: linear-gradient(90deg, #FF8A06, #FF571…

Wi-Fi 安全在學校中的重要性

Wi-Fi 是教育機構的基礎設施&#xff0c;從在線家庭作業門戶到虛擬教師會議&#xff0c;應有盡有。大多數 K-12 管理員對自己的 Wi-Fi 網絡的安全性充滿信心&#xff0c;并認為他們現有的網絡安全措施已經足夠。 不幸的是&#xff0c;這種信心往往是錯誤的。Wi-Fi 安全雖然經常…

【數據結構OJ題】鏈表中倒數第k個結點

原題鏈接&#xff1a;https://www.nowcoder.com/practice/529d3ae5a407492994ad2a246518148a?tpId13&&tqId11167&rp2&ru/activity/oj&qru/ta/coding-interviews/question-ranking 目錄 1. 題目描述 2. 思路分析 3. 代碼實現 1. 題目描述 2. 思路分析 …

VectorStyler for Mac: 讓你的創意無限綻放的全新設計工具

VectorStyler for Mac是一款專為Mac用戶打造的矢量設計工具&#xff0c;它結合了功能強大的矢量編輯器和創意無限的樣式編輯器&#xff0c;讓你的創意無限綻放。 VectorStyler for Mac擁有直觀簡潔的用戶界面&#xff0c;讓你能夠輕松上手。它提供了豐富的矢量繪圖工具&#x…

JavaWeb博客項目--推薦算法--完整代碼及思路

基于用戶的協同過濾算法&#xff08;UserCF&#xff09; 因為我寫的是博客項目&#xff0c;博客數量可能比用戶數量還多 所以選擇基于用戶的協同過濾算法 重要思想 當要向用戶u進行推薦時&#xff0c;我們先找出與用戶u最相似的幾個用戶&#xff0c;再從這幾個用戶的喜歡的物…