Spring Integration,springboot整合spring Validated

 2023-10-30 阅读 102 评论 0

摘要:spring Validated是基于java JSR303進一步封裝,具有校驗功能的框架,封裝了原本的@Valid,但不同于@Valid的是他具有分組功能 依賴 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-sta

spring Validated是基于java JSR303進一步封裝,具有校驗功能的框架,封裝了原本的@Valid,但不同于@Valid的是他具有分組功能

依賴

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
</dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-validation</artifactId></dependency>

代碼

Spring Integration。數據校驗需要在兩個位置用到spring Validated的注解,一個是在請求參數的位置,一個是在實體類的位置。

請求參數:

參數需要使用@Validated注解標注,表示該參數需要被校驗

  @GetMapping("/getAll")public UserVo getAll(@Validated UserVo userVo) {return userVo;}

實體類:

在屬性位置標注上對應的注解比如 @NotEmpty(message = “用戶名不為空”),表示name不能為空,為空白字符,長度不能為0

@Data
public class UserVo {@NotEmpty(message = "用戶名不為空")private String name;@Min(value = 18,message = "年齡必須大于18歲")private String age;@Email(regexp = "^\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*$",message = "郵箱格式錯誤")private String email;
}

那如果我們需要對某些字段進行校驗,或者按照某種條件進行校驗,我們該怎么做呢?
那么我們就需要分組校驗來進行
下面我們進行分組校驗測試

分組校驗

分組接口

先創建兩個接口,這兩個接口不需要任何內容,就只是用于分組標記

public interface IGroupA {
}
public interface IGroupB {
}

請求參數

我們在請求參數出設置校驗標記,
@Validated({IGroupB.class})表示只有分組為IGroupB.class才進行校驗,否則不校驗

    @GetMapping("/getAll")public UserVo getAll(@Validated({IGroupB.class}) UserVo userVo) {return userVo;}

實體類:

groups = IGroupB.class表示將這個校驗標記為IGroupB分組,如果controller不是IGroupB就不進行校驗。否則就校驗

@Data
public class UserVo {@NotEmpty(message = "用戶名不為空", groups = IGroupA.class)private String name;//只有分組為IGroupB才進行校驗@NotBlank@Min(value = 18, message = "年齡必須大于18歲", groups = {IGroupB.class})private String age;@NotBlank@Email(message = "郵箱格式錯誤", groups = {IGroupB.class})private String email;
}

如果訪問,上面的結果是:name不會校驗,age和email會進行校驗。

那如果在請求參數處同時標記IGroupA.class,IGroupB.class會怎么樣呢?

 @GetMapping("/getAll")public UserVo getAll(@Validated({IGroupA.class,IGroupB.class}) UserVo userVo) {return userVo;}

答案就是:三個都會進行校驗,那如果我們對一個進行校驗后發現不通過,后面的就不需要進行校驗該怎么辦呢?
那么我們可以采用組序列,在使用組序列驗證的時候,如果序列前邊的組驗證失敗,則后面的組將不再給予驗證。

組序列

創建一個接口:IGroup

在上面標注注解,@GroupSequence({Default.class, IGroupA.class, IGroupB.class})

import javax.validation.GroupSequence;
import javax.validation.groups.Default;@GroupSequence({Default.class, IGroupA.class, IGroupB.class})
public interface IGroup {
}

實體類

對實體類的屬性上同時標注上groups = IGroupB.class和groups = IGroupA.class)

@Data
public class UserVo {@NotEmpty(message = "用戶名不為空", groups = IGroupA.class)private String name;//只有分組為IGroupB才進行校驗@Min(value = 18, message = "年齡必須大于18歲", groups = {IGroupB.class})private String age;@Email(message = "郵箱格式錯誤", groups = {IGroupB.class})private String email;
}

請求參數

在請求參數處標注一個@Validated({IGroup.class})注解

	GetMapping("/getAll")public UserVo getAll(@Validated({IGroup.class}) UserVo userVo) {return userVo;}

再進行測試;
如果我們三個參數都填錯,那么按照順序,他只會校驗name后就不再進行校驗。
那如果我們實體類中是以另一個實體類為屬性,我們能對他進行校驗嗎?
那當然可以。

嵌套校驗

創建另一個實體類Teacher

import javax.validation.constraints.Min;
import javax.validation.constraints.NotEmpty;
@Data
public class Teacher {@NotEmpty(message = "老師姓名不能為空")private String teacherName;@Min(value = 1, message = "至少為1")private int type;
}

實體類

將其封裝到UserVo中

@Data
public class UserVo {@NotEmpty(message = "用戶名不為空", groups = IGroupA.class)private String name;//只有分組為IGroupB才進行校驗@Min(value = 18, message = "年齡必須大于18歲", groups = IGroupB.class)private String age;@Email(message = "郵箱格式錯誤", groups = IGroupB.class)private String email;@NotNull(message = "用戶不能為空")@Size(min = 1,message = "至少有一個用戶")private List<Teacher>  teachers;
}

請求參數

我們訪問前端接口測試

@GetMapping("/getAll")public UserVo getAll(@Validated({IGroup.class}) UserVo userVo) {return userVo;}

參數為:
在這里插入圖片描述
發現只校驗了NotNull, 和 Size,并沒有對teacher信息里面的字段進行校驗,因為我們type給的0,那么應該校驗發出校驗,
這里teacher中的type明顯是不符合約束要求的,但是能檢測通過,是因為在student中并沒有做 嵌套校驗
在這里插入圖片描述

解決辦法

可以在teacherBeans中加上 @Valid,

@Data
public class UserVo {@NotEmpty(message = "用戶名不為空", groups = IGroupA.class)private String name;//只有分組為IGroupB才進行校驗@Min(value = 18, message = "年齡必須大于18歲", groups = IGroupB.class)private String age;@Email(message = "郵箱格式錯誤", groups = IGroupB.class)private String email;@Valid@NotNull(message = "用戶不能為空")@Size(min = 1,message = "至少有一個用戶")private List<Teacher>  teachers;
}

我們再次測試
發現結果對teacher類中的字段進行了校驗。測試成功

將@Validated的返回信息通過全局異常類同意處理

先創建一個全局異常類

/*** 統一異常處理*/
@RestControllerAdvice
public class GlobalExceptionHandler {
/*** jsr303校驗異常* @param e* @return*/@ExceptionHandler({MethodArgumentNotValidException.class})public R validatedException(MethodArgumentNotValidException e){BindingResult bindingResult = e.getBindingResult();String field = bindingResult.getFieldError().getField();if("mobile".equals(field)){return R.error().code("30").message(bindingResult.getFieldError().getDefaultMessage());}else{return R.error().code("31").message(bindingResult.getFieldError().getDefaultMessage());}}
}

參數vo實例類

@Data
public class RegisterVo implements Serializable {//手機號@NotBlank(message = "手機號碼不能為空")@Pattern(regexp = "^[1][3,4,5,7,8,9][0-9]{9}$",message = "手機號碼不正確")private String mobile;//密碼@NotBlank(message = "密碼不能為空")private String password;//@NotBlank校驗字符不為null,不為空字符串(" "),字符長度不為0("")//@NotEmpty校驗字符不為null,字符長度不為0("")@NotBlank(message = "昵稱不能為空")private String nickname;
}
    @PostMapping("register")public R register(@RequestBody @Validated RegisterVo registerVo){memberService.register(registerVo);return R.ok().message("注冊成功");}

可用注解說明

@Null 限制只能為null
@NotNull 限制必須不為null
@AssertFalse 限制必須為false
@AssertTrue 限制必須為true
@DecimalMax(value) 限制必須為一個不大于指定值的數字
@DecimalMin(value) 限制必須為一個不小于指定值的數字
@Digits(integer,fraction) 限制必須為一個小數,且整數部分的位數不能超過integer,小數部分的位數不能超過fraction
@Future 限制必須是一個將來的日期
@Max(value) 限制必須為一個不大于指定值的數字
@Min(value) 限制必須為一個不小于指定值的數字
@Past 限制必須是一個過去的日期
@Pattern(value) 限制必須符合指定的正則表達式
@Size(max,min) 限制字符長度必須在min到max之間
@Past 驗證注解的元素值(日期類型)比當前時間早
@NotEmpty 驗證注解的元素值不為null且不為空(字符串長度不為0、集合大小不為0)
@NotBlank 驗證注解的元素值不為空(不為null、去除首位空格后長度為0),不同于@NotEmpty,@NotBlank只應用于字符串且在比較時會去除字符串的空格
@Email 驗證注解的元素值是Email,也可以通過正則表達式和flag指定自定義的email格式

版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。

原文链接:https://808629.com/166835.html

发表评论:

本站为非赢利网站,部分文章来源或改编自互联网及其他公众平台,主要目的在于分享信息,版权归原作者所有,内容仅供读者参考,如有侵权请联系我们删除!

Copyright © 2022 86后生记录生活 Inc. 保留所有权利。

底部版权信息