spring中使用@Validated,什么是JSR 303數據校驗,spring boot中怎么使用數據校驗

文章目錄

      • 一、JSR 303后臺數據校驗
        • 1.1 什么是 JSR303?
        • 1.2 為什么使用 JSR 303?
      • 二、Spring Boot 中使用數據校驗
        • 2.1 基本注解校驗
          • 2.1.1 使用步驟
          • 2.1.2 舉例
            • @Valid注解
            • 全局統一異常處理
        • 2.2 分組校驗
          • 2.2.1 使用步驟
          • 2.2.2 舉例
            • @Validated注解
            • @Validated和@Valid的區別
        • 2.3 自定義校驗注解
          • 2.3.1 使用步驟
          • 2.3.2 舉例
        • 2.4 相關注解
          • 2.4.1 空檢查相關注解
          • 2.4.2 長度檢查
          • 2.4.3 布爾值檢查
          • 2.4.4 日期檢查
          • 2.4.5 數值檢查
          • 2.4.6 其他

一、JSR 303后臺數據校驗

1.1 什么是 JSR303?

JSR 是 Java Specification Requests 的縮寫,即 Java 規范提案。存在各種各樣的 JSR,簡單的理解為 JSR 是一種 Java 標準。JSR 303 是其中數據檢驗的一個標準(Bean Validation 1.0 (JSR 303))。

1.2 為什么使用 JSR 303?
  • 處理一段業務邏輯,首先要確保數據輸入的正確性,所以需要先對數據進行檢查,保證數據在語義上的正確性,再根據數據進行下一步的處理。

  • 前端可以通過 js 程序校驗數據是否合法,后端同樣也需要進行校驗。而后端最簡單的實現就是直接在業務方法中對數據進行處理,但是不同的業務方法可能會出現同樣的校驗操作,這樣就出現了數據的冗余。

  • 為了解決這個情況,JSR 303 出現了。JSR 303 使用 Bean Validation,即在 Bean 上添加相應的注解,去實現數據校驗。這樣在執行業務方法前,都會根據注解對數據進行校驗,從而減少自定義的校驗邏輯,減少代碼冗余。

二、Spring Boot 中使用數據校驗

2.1 基本注解校驗

之前在 Spring MVC 中介紹了數據校驗,也例舉了常用的注解。但是使注解生效必須要在 springmvc.xml 中配置,假如沒有配置文件(比如在 spring boot)中怎么辦?----> 下面詳細介紹

spring boot 中需要引入依賴:

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-validation</artifactId>
</dependency>
2.1.1 使用步驟

1、在相關的 Bean 上標注需要處理的注解,并指定需要提示的信息(若不指定,會從默認配置文件中讀取默認的信息)。

2、在相關的方法上,使用 @Valid 注解(或者 @Validated 指定組名)標記需要被校驗的數據,否則會不生效。

注意:檢測到數據異常后,系統會向外拋出異常,如果做了統一異常處理,可以根據 postman 測試的結果,找到控制臺打印出的相應的異常,并處理。

3、處理異常。

  • 使用 BindingResult 處理;

  • 也可以使用 全局統一異常 處理(@RestControllerAdvice 與 @ExceptionHandler

    全局統一異常處理后續會講

2.1.2 舉例

1、在相關的 Bean 上標注注解,并寫上指定信息。

@Data
public class Emp {@NotNull(message = "id 不能為 null")private Integer id;@NotNull(message = "name 不能為 null")private String name;
}
@Valid注解

2、Controller層中使用 @Valid 注解標記需要檢測的數據。

@RestController
public class EmpController {@PostMapping("/emp")public String createEmp(@Valid @RequestBody Emp emp) {return "ok";}
}

3、測試時,假如不傳 id、name,會拋出 MethodArgumentNotValidException 異常。使用 BindingResult 可以處理異常信息,但 通常使用統一異常處理

① 使用 BindingResult:

@RestController
public class EmpController {@PostMapping("/emp")public Map createEmp(@Valid @RequestBody Emp emp, BindingResult result) {if (result.hasErrors()) {Map<String, String> map = new HashMap<>();// 獲取校驗結果,遍歷獲取捕獲到的每個校驗結果result.getFieldErrors().forEach(item -> {// 獲取校驗的信息String message = item.getDefaultMessage(); // 也獲取message的值String field = item.getField(); //獲取屬性名// 存儲得到的校驗結果map.put(field, message);});return map;}return "ok";}
}

問題:通過上面的步驟,已經可以捕獲異常、處理異常,但是每次都是在業務方法中手動處理邏輯,這樣的實現,代碼肯定會冗余。可以將其抽出,使用 統一異常處理,每次異常發生時,將其捕獲。

全局統一異常處理

② 全局統一異常處理:@RestControllerAdvice、@ExceptionHandler

@RestControllerAdvice
public class GlobalExceptionHandler {@ExceptionHandler(MethodArgumentNotValidException.class)public Map handlerValidException(MethodArgumentNotValidException e) {BindingResult result = e.getBindingResult();Map<String, String> map = new HashMap<>();// 獲取校驗結果,遍歷獲取捕獲到的每個校驗結果result.getFieldErrors().forEach(item ->{// 存儲得到的校驗結果map.put(item.getField(), item.getDefaultMessage());});return map;}
}

Controller 中不需要再用 BindingResult 去處理數據了。

2.2 分組校驗

1、為什么使用 分組校驗?

上面的過程,如果出現多個方法,都需要校驗 Bean,且校驗規則不同的時候,怎么辦呢?分組校驗就可以去解決該問題,每個分組指定不同的校驗規則,不同的方法執行不同的分組,就可以得到不同的校驗結果。

2、JSR 303 的每個注解都默認具備三個屬性

  • message 用來定義數據校驗失敗后的提示消息,默認讀取配置文件的內容。idea 全局搜索 ValidationMessages.properties,可以看到默認的信息。
  • groups 用來定義分組,它是一個 class 數組,可以指定多個分組。
  • payload()
String message() default "{javax.validation.constraints.NotNull.message}";Class<?>[] groups() default { };Class<? extends Payload>[] payload() default { };
2.2.1 使用步驟

1、定義一個空接口,用于指定分組,內部不需要任何實現。

2、指定 注解時,通過 groups 指定分組。用于指定在某個分組條件下,才去執行校驗規則。

3、在 Controller 中通過 @Validated 注解指定分組,去指定校驗。

注:使用分組校驗后,Bean 注解上若不指定分組,則不會執行校驗規則。

2.2.2 舉例

1、如:創建兩個分組接口 AddGroup、UpdateGroup。

AddGroup 用于指定 添加數據 時的校驗規則(比如:id、name 均不為 null)。

UpdateGroup 用于指定 修改數據 時的校驗規則(比如:name 不允許為 null)。

2、給 Bean 添加注解,并指定分組信息。

@Data
public class Emp {@NotNull(message = "id 不能為 null", groups = {AddGroup.class})private Integer id;@NotNull(message = "name 不能為 null", groups = {AddGroup.class, UpdateGroup.class})private String name;
}
@Validated注解

3、通過 @Validated 注解指定分組,去指定校驗

@RestController
public class EmpController {@PostMapping("/emp")public void createEmp(@Validated({AddGroup.class}) @RequestBody Emp emp) {}@PutMapping("/emp")public void UpdateEmp(@Validated({UpdateGroup.class}) @RequestBody Emp emp) {}
}
@Validated和@Valid的區別
  • @Validated:

    • Spring 框架特有的注解,是標準 JSR-303 的一個變種,提供了一個分組功能。
    • 作用在類上、方法上、方法參數上,不能作用于成員屬性上。
  • @Valid:

    • 標準 JSR-303 規范的標記型注解。

    • 作用在方法、構造函數、方法參數、成員屬性上。

2.3 自定義校驗注解

上面的注解滿足不了業務需求時,可以自定義校驗注解、然后自定義校驗規則

2.3.1 使用步驟

1、自定義一個校驗注解。可以創建一個 ValidationMessages.properties 用于保存默認的 message 信息。

2、自定義一個校驗器(即自定義校驗規則):實現 ConstraintValidator 接口,并重寫相關方法。

  • initialize :初始化,可以獲取 自定義的屬性的值。

  • isValid :校驗,可以獲取到實際的值,然后與自定義的屬性值進行比較。

3、將校驗注解 與 校驗器 關聯起來。@Constraint(validatedBy = {校驗器類.class})

2.3.2 舉例

自定義一個校驗規則,判斷數據長度是否合法。

1、自定義一個校驗注解:(比如這里是@TestValid)

@Target({FIELD})
@Retention(RUNTIME)
@Documented
@Constraint(validatedBy={JiaoYan.class})
public @interface TestValid {// 提示信息String message() default "{本自定義注解的全類名.message}";class<?>[] groups() default {};Class<? extends Payload>[] payload() default {};/*** 返回一個長度* @return 默認為 5*/int length() default 5; 
}

在這里插入圖片描述

配置文件內容為:

自定義注解的全類名.message=值不能為 Null,且長度不超過 5

2、自定義一個校驗器(比如這里是 JiaoYan)

/*** 實現 ConstraintValidator 接口,* 其中 ConstraintValidator 的泛型,一個需要指定自定義的注解,一個需要指定需要獲取的值的類型。* 比如:*  ConstraintValidator<TestValid, String> 中*      TestValid   表示自定義注解*      String      表示獲取的值的類型* 即定義規則,判斷一個 String 的值的長度是否滿足條件*/
public class JiaoYan implements ConstraintValidator<TestValid, String> {/*** 用于保存自定義的(默認)長度*/private int length;/*** 初始化方法,獲取默認數據* @param test 注解對象*/@Overridepublic void initialize(TestValid test) {length = test.length();}/*** 自定義校驗規則,如果 String 為 Null 或者 長度大于 5,則校驗失敗(返回 false)* @param value 需要校驗的值* @param context* @return true 表示校驗成功,false 表示校驗失敗*/@Overridepublic boolean isValid(String value, ConstraintValidatorContext context) {return value == null ? false : length > value.length();}
}

3、使用注解

@Data
public class Emp {@NotNull(message = "id 不能為 null", groups = {AddGroup.class})private Integer id;// 默認@TestValid()@NotNull(message = "name 不能為 null", groups = {AddGroup.class, UpdateGroup.class})private String name;// 自定義@TestValid(length = 10, message = "值不能為 Null 且長度不超過 10", groups = {AddGroup.class})private String email;
}
2.4 相關注解
2.4.1 空檢查相關注解
注解注解詳情
@Null被指定的注解元素必須為 Null
@NotNull任意類型,不能為 Null,但可以為空,比如:空數組[]、空字符串""
@NotBlank針對字符串,不能為 Null,且去除前后空格后的字符串長度要大于 0
@NotEmpty針對字符串、集合、數組,針對字符串時,不能為 Null,且長度要大于 0
2.4.2 長度檢查
注解注解詳情
@Size針對字符串、集合、數組,判斷長度是否在給定范圍內
@Length針對字符串,判斷長度是否在給定范圍內
2.4.3 布爾值檢查
注解注解詳情
@AssertTrue針對布爾值,用來判斷布爾值是否為 true
@AssertFalse針對布爾值,用來判斷布爾值是否為 false
2.4.4 日期檢查
注解注解詳情
@Past針對日期,用來判斷當前日期是否為 過去的日期
@Future針對日期,用來判斷當前日期是否為 未來的日期
2.4.5 數值檢查
注解注解詳情
@Max(value)針對字符串、數值,用來判斷是否小于等于某個指定值
@Min(value)針對字符串、數值,用來判斷是否大于等于某個指定值
2.4.6 其他
注解注解詳情
@Pattern驗證字符串是否滿足正則表達式
@Email驗證字符串是否滿足郵件格式
@Url驗證是否滿足 url 格式
@Digits驗證數字整數和小數位數,如:@Digits(integer=6, fraction=2)

文章結束!恭喜你又學會了一個知識點!!!

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

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

相關文章

ubuntu常用快捷鍵和變量記錄

alias b‘cd …/’ alias bb‘cd …/…/’ alias bbb‘cd …/…/…/’ alias bbbb‘cd …/…/…/…/’ alias bbbbb‘cd …/…/…/…/…/’ alias bbbbbb‘cd …/…/…/…/…/…/’ alias apkinfo‘aapt dump badging’ alias npp‘notepad-plus-plus’ export ANDROID_HOME/h…

AWS S3文件存儲工具類

pom依賴 <!--aws-s3--> <dependency><groupId>com.amazonaws</groupId><artifactId>aws-java-sdk-s3</artifactId><version>1.12.95</version></dependency>S3Utils import cn.hutool.core.util.ZipUtil; import com.a…

【SOC 芯片設計 DFT 學習專欄 -- 測試向量生成 ATPG (Automatic Test Pattern Generation) 】

文章目錄 OverviewATPG 的基本功能ATPG 的工作流程ATPG 應用場景示例示例 1&#xff1a;檢測單個信號的 Stuck-at Fault示例 2&#xff1a;針對 Transition Fault 的 ATPG ATPG 工具與常用工具鏈ATPG 優化與挑戰 Overview 本文主要介紹 DFT scan 中的 ATPG 功能。在 DFT (Desi…

2024 高通邊緣智能創新應用大賽智能邊緣計算賽道冠軍方案解讀

2024 高通邊緣智能創新應用大賽聚焦不同細分領域的邊緣智能創新應用落地&#xff0c;共設立三大熱門領域賽道——工業智能質檢賽道、智能邊緣計算賽道和智能機器人賽道。本文為智能邊緣計算賽道冠軍項目《端側大模型智能翻譯機》的開發思路與成果分享。 賽題要求 聚焦邊緣智能…

【Python運維】用Python和Ansible實現高效的自動化服務器配置管理

《Python OpenCV從菜鳥到高手》帶你進入圖像處理與計算機視覺的大門! 解鎖Python編程的無限可能:《奇妙的Python》帶你漫游代碼世界 隨著云計算和大規模數據中心的興起,自動化配置管理已經成為現代IT運維中不可或缺的一部分。通過自動化,企業可以大幅提高效率,降低人為錯…

微信小程序獲取后端數據

在小程序中獲取后端接口數據 通常可以使用 wx.request 方法&#xff0c;以下是一個基本示例&#xff1a; // pages/index/index.js Page({data: {// 用于存儲后端返回的數據resultData: [] },onLoad() {this.fetchData();},fetchData() {wx.request({url: https://your-backe…

應用架構模式-總體思路

采用引導式設計方法&#xff1a;以企業級架構為指導&#xff0c;形成較為齊全的規范指引。在實踐中總結重要設計形成決策要點&#xff0c;一個決策要點對應一個設計模式。自底向上總結采用該設計模式的必備條件&#xff0c;將之轉化通過簡單需求分析就能得到的業務特點&#xf…

【數據結構】雙向循環鏈表的使用

雙向循環鏈表的使用 1.雙向循環鏈表節點設計2.初始化雙向循環鏈表-->定義結構體變量 創建頭節點&#xff08;1&#xff09;示例代碼&#xff1a;&#xff08;2&#xff09;圖示 3.雙向循環鏈表節點頭插&#xff08;1&#xff09;示例代碼&#xff1a;&#xff08;2&#xff…

【Java設計模式-3】門面模式——簡化復雜系統的魔法

在軟件開發的世界里&#xff0c;我們常常會遇到復雜的系統&#xff0c;這些系統由多個子系統或模塊組成&#xff0c;各個部分之間的交互錯綜復雜。如果直接讓外部系統與這些復雜的子系統進行交互&#xff0c;不僅會讓外部系統的代碼變得復雜難懂&#xff0c;還會增加系統之間的…

Linux一些問題

修改YUM源 Centos7將yum源更換為國內源保姆級教程_centos使用中科大源-CSDN博客 直接安裝包&#xff0c;走鏈接也行 Index of /7.9.2009/os/x86_64/Packages 直接復制里面的安裝包鏈接&#xff0c;在命令行直接 yum install https://vault.centos.org/7.9.2009/os/x86_64/Pa…

微信小程序 覆蓋組件cover-view

wxml 覆蓋組件 <video src"../image/1.mp4" controls"{{false}}" event-model"bubble"> <cover-view class"controls"> <cover-view class"play" bind:tap"play"> <cover-image class"…

HTML——57. type和name屬性

<!DOCTYPE html> <html><head><meta charset"UTF-8"><title>type和name屬性</title></head><body><!--1.input元素是最常用的表單控件--><!--2.input元素不僅可以在form標簽內使用也可以在form標簽外使用-…

uniapp本地加載騰訊X5瀏覽器內核插件

概述 TbsX5webviewUTS插件封裝騰訊x5webview離線內核加載模塊&#xff0c;可以把uniapp的瀏覽器內核直接替換成Android X5 Webview(騰訊TBS)最新內核&#xff0c;提高交互體驗和流暢度。 功能說明 下載SDK插件 1.集成x5內核后哪些頁面會由x5內核渲染&#xff1f; 所有plus…

力扣hot100——二叉樹

94. 二叉樹的中序遍歷 class Solution { public:vector<int> inorderTraversal(TreeNode* root) {vector<int> ans;stack<TreeNode*> stk;while (root || stk.size()) {while (root) {stk.push(root);root root->left;}auto cur stk.top();stk.pop();a…

設計模式 創建型 單例模式(Singleton Pattern)與 常見技術框架應用 解析

單例模式&#xff08;Singleton Pattern&#xff09;是一種創建型設計模式&#xff0c;旨在確保某個類在應用程序的生命周期內只有一個實例&#xff0c;并提供一個全局訪問點來獲取該實例。這種設計模式在需要控制資源訪問、避免頻繁創建和銷毀對象的場景中尤為有用。 一、核心…

您的公司需要小型語言模型

當專用模型超越通用模型時 “越大越好”——這個原則在人工智能領域根深蒂固。每個月都有更大的模型誕生&#xff0c;參數越來越多。各家公司甚至為此建設價值100億美元的AI數據中心。但這是唯一的方向嗎&#xff1f; 在NeurIPS 2024大會上&#xff0c;OpenAI聯合創始人伊利亞…

uniapp-vue3(下)

關聯鏈接&#xff1a;uniapp-vue3&#xff08;上&#xff09; 文章目錄 七、咸蝦米壁紙項目實戰7.1.咸蝦米壁紙項目概述7.2.項目初始化公共目錄和設計稿尺寸測量工具7.3.banner海報swiper輪播器7.4.使用swiper的縱向輪播做公告區域7.5.每日推薦滑動scroll-view布局7.6.組件具名…

使用 Python 實現隨機中點位移法生成逼真的裂隙面

使用 Python 實現隨機中點位移法生成逼真的裂隙面 一、隨機中點位移法簡介 1. 什么是隨機中點位移法&#xff1f;2. 應用領域 二、 Python 代碼實現 1. 導入必要的庫2. 函數定義&#xff1a;隨機中點位移法核心邏輯3. 設置隨機數種子4. 初始化二維裂隙面5. 初始化網格的四個頂點…

mysql之組內排序ROW_NUMBER()函數

有個需求&#xff0c;需要組內排序&#xff0c;之前似乎從未接觸過此類排序&#xff0c;故查詢了一下&#xff0c;記錄sql執行結果。 表如下&#xff1a; play_log: 日期 (fdate)用戶 ID (user_id)歌曲 ID (song_id)2022-01-081000002022-01-161000002022-01-201000002022-0…

Android TV端彈出的PopupWindow沒有獲取焦點

在 TV 開發中&#xff0c;焦點管理是通過 Focus Navigation 實現的&#xff0c;PopupWindow 默認不接受焦點&#xff0c;導致遙控器無法選擇彈窗內的控件。這是因為 PopupWindow 默認不會將焦點傳遞到其內容視圖上。 要解決問題&#xff0c;可以通過以下步驟調整 PopupWindow …