日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

学习Spring Boot:(十)使用hibernate validation完成数据后端校验

發布時間:2025/7/25 javascript 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 学习Spring Boot:(十)使用hibernate validation完成数据后端校验 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前言

后臺數據的校驗也是開發中比較注重的一點,用來校驗數據的正確性,以免一些非法的數據破壞系統,或者進入數據庫,造成數據污染,由于數據檢驗可能應用到很多層面,所以系統對數據校驗要求比較嚴格且追求可變性及效率。

了解

了解一點概念性的東東。
* JSR 303 是 Java 為 Bean 數據合法性校驗提供的標準框架,它已經包含在 JavaEE 6.0 中 。
* Hibernate Validator 是 JSR 303 的一個參考實現,所以它多實現了幾個校驗規則。
* Spring 4.0 擁有自己獨立的數據校驗框架,同時支持 JSR303 標準的校驗框架。
* 在已經標注了 JSR303 注解的表單/命令對象前標注一個@Valid,Spring MVC 框架在將請求參數綁定到該入參對象后,就會調用校驗框架根據注解聲明的校驗規則實施校驗
* Spring MVC 是通過對處理方法簽名的規約來保存校驗結果的:前一個表單/命令對象的校驗結果保存到隨后的入參中,這個保存校驗結果的入參必須是 BindingResult 或Errors 類型,這兩個類都位于org.springframework.validation 包中。
* 需校驗的 Bean 對象和其綁定結果對象或錯誤對象時成對出現的,它們之間不允許聲明其他的入參
* Errors 接口提供了獲取錯誤信息的方法,如 getErrorCount() 或getFieldErrors(String field)
* BindingResult 擴展了 Errors 接口。

支持的注解

JSR 提供的校驗注解:

@Null 被的注解元素必須為 null @NotNull 被注解的元素必須不為 null @AssertTrue 被注解的元素必須為 true @AssertFalse 被注解的元素必須為 false @Min(value) 被注解的元素必須是一個數字,其值必須大于等于指定的最小值 @Max(value) 被注解的元素必須是一個數字,其值必須小于等于指定的最大值 @DecimalMin(value) 被注解的元素必須是一個數字,其值必須大于等于指定的最小值 @DecimalMax(value) 被注解的元素必須是一個數字,其值必須小于等于指定的最大值 @Size(max=, min=) 被注解的元素的大小必須在指定的范圍內 集合或數組 集合或數組的大小是否在指定范圍內 @Digits (integer, fraction) 被注解的元素必須是一個數字,驗證是否是符合指定格式的數字,interger指定整數精度,fraction指定小數精度。 @Past 被注解的元素必須是一個過去的日期 @Future 被注解的元素必須是一個將來的日期 @Pattern(regex=,flag=) 被注解的元素必須符合指定的正則表達式

Hibernate Validator 提供的校驗注解:

@NotBlank(message =) 驗證字符串非null,且長度必須大于0 @Email 被注釋的元素必須是電子郵箱地址 @Length(min=,max=) 被注解的值大小必須在指定的范圍內 @NotEmpty 被注解的字符串的必須非空 @Range(min=,max=,message=) 驗證該值必須在合適的范圍內

可以在需要驗證的屬性上,使用多個驗證方式,它們同時生效。
spring boot web 已經有 hibernate-validation 的依賴,所以不需要再手動添加依賴。

使用

首先我在我的實體類上寫了幾個校驗注解。

public class SysUserEntity implements Serializable {private static final long serialVersionUID = 1L;//主鍵private Long id;//用戶名@NotBlank(message = "用戶名不能為空", groups = {AddGroup.class, UpdateGroup.class})private String username;//密碼@NotBlank(message = "密碼不能為空", groups = {AddGroup.class})private String password;//手機號@Pattern(regexp = "^1([345789])\\d{9}$",message = "手機號碼格式錯誤")@NotBlank(message = "手機號碼不能為空")private String mobile;//郵箱@Email(message = "郵箱格式不正確")private String email;//創建者private Long createUserId;//創建時間private Date createDate; // ignore set and get

使用@Validated進行校驗

首先了解下:
關于@Valid和@Validated的區別聯系
* @Valid: javax.validation, 是javax,也是就是jsr303中定義的規范注解
* @Validated: org.springframework.validation.annotation, 是spring自己封裝的注解。參數校驗失敗拋出 org.springframework.validation.BindException 異常。

@Validated 是 @Valid 的一個變種,擴展了 @Valid 的功能,支持 group分組校驗 的寫法,所以為了校驗統一,盡量使用 @Validated

在controller自定義一個接口

@PostMapping("/valid")public ResponseEntity<String> valid(@Validated @RequestBody SysUserEntity user, BindingResult result) {if (result.hasErrors()) {return ResponseEntity.status(BAD_REQUEST).body("校驗失敗");}return ResponseEntity.status(OK).body("校驗成功");}

需要注意的有幾點:
* 需要校驗對象的時候,需要加上 spring 的校驗注解 @Validated ,表示我們需要 spring 對它進行校驗,而校驗的信息會存放到其后的BindingResult中。
* BindingResult 必須和檢驗對象緊鄰,中間不能穿插任何參數,如果有多個校驗對象 @Validated @RequestBody SysUserEntity user, BindingResult result, @Validated @RequestBody SysUserEntity user1, BindingResult result1。

我在前端用 Swagger 進行測試下。
我發送一個 body,將 手機號輸錯:

{"createDate": "","createUserId": 0,"email": "k@wuwii.com","id": 0,"mobile": "12354354","password": "123","username": "12312" }

后端調試下 BindingResult 的結果,發現結果:

只要注意下 errors 屬性,它是校驗所有不符合規則的,是一個數組。

分組校驗

有時候 ,我們在新增和更新的時候校驗效果是不一樣的。例如上面,我在User新增的時候需要判斷密碼是不是為空,但是更新的時候我不做校驗。這個時候就也要用到分組校驗了。

@NotBlank(message = "密碼不能為空", groups = {AddGroup.class}) private String password;

將Contoller中的校驗修改下。

(@Validated({AddGroup.class}) @RequestBody SysUserEntity user, BindingResult result)

上面的意思是只有分組是AddGroup的校驗才生效,其余的校驗忽略。

經過我測試,把分組情況分下:
1. 在controller校驗沒加分組的時候,只對實體類的沒有分組的注解有效。
2. 在controller校驗加分組的時候,只對實體類的當前分組的注解有效,沒有注解的也無效。
3. 當校驗有兩個分組的時候@Validated({AddGroup.class, UpdateGroup.class}),滿足當前兩個分組其中任意一個都可以校驗,兩個注解同時一起出現,也沒問題,而且檢驗不通過的信息不會重復。

自定義校驗

有時候系統提供給我們的校驗注解,并不夠用,我們可以自定義校驗,來滿足我們的業務需求。

例如:現在我們有一個需求,需要檢測一條信息的敏感詞匯,如sb ……文明人,舉個栗子 ……

自定義校驗注解
// 注解可以用在哪些地方 @Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER}) @Retention(RUNTIME) @Documented // 指定校驗規則實現類 @Constraint(validatedBy = {NotHaveSBValidator.class}) public @interface NotHaveSB {//默認錯誤消息String message() default "不能包含字符sb";//分組Class<?>[] groups() default {};//負載Class<? extends Payload>[] payload() default {};//指定多個時使用@Target({FIELD, METHOD, PARAMETER, ANNOTATION_TYPE})@Retention(RUNTIME)@Documented@interface List {NotHaveSB[] value();}}
規則校驗實現類
// 可以指定檢驗類型,這里選擇的是 String public class NotHaveSBValidator implements ConstraintValidator<NotHaveSB, String> {@Overridepublic void initialize(NotHaveSB notHaveSB) {}/**** @param s 待檢驗對象* @param constraintValidatorContext 檢驗上下文,可以設置檢驗的錯誤信息* @return false 代表檢驗失敗*/@Overridepublic boolean isValid(String s, ConstraintValidatorContext constraintValidatorContext) {return !StringUtils.isNotBlank(s) || !s.toLowerCase().contains("sb");} }

所有的驗證者都需要實現ConstraintValidator接口,它的接口也很形象,包含一個初始化事件方法,和一個判斷是否合法的方法。

測試一下喂

現在我的用戶類上,也沒什么多余的字段拿出來測試,暫時把 password 字段拿來測試吧。

//@NotBlank(message = "密碼不能為空", groups = AddGroup.class)@NotHaveSBprivate String password;

手動校驗

這個是我最終想要的處理方式。
由于現在都是前后端分離開發的,校驗失敗的時候,拋出自定義的異常,然后統一處理這些異常,最后將相關的錯誤提示信息返回給前端處理。

新建一個驗證工具類

public class ValidatorUtils {private static Validator validator;static {validator = Validation.buildDefaultValidatorFactory().getValidator();}/*** 手動校驗對象** @param object 待校驗對象* @param groups 待校驗的組* @throws KCException 校驗不通過,則拋出 KCException 異常*/public static void validateEntity(Object object, Class<?>... groups)throws KCException {Set<ConstraintViolation<Object>> constraintViolations = validator.validate(object, groups);if (!constraintViolations.isEmpty()) {String msg = constraintViolations.parallelStream().map(ConstraintViolation::getMessage).collect(Collectors.joining(","));throw new KCException(msg);}} }

它主要做的事情就是驗證我們的待驗證對象,驗證不同通過的時候,拋出自定義異常,在后臺統一處理異常就可以了。

在業務中直接調用就可以了,有分組添加分組就行:

@PostMapping("/valid1")public ResponseEntity<String> customValid(@RequestBody SysUserEntity user) {ValidatorUtils.validateEntity(user);return ResponseEntity.status(OK).body("校驗成功");}

最后測試一下,查看返回結果是否符合預期:

手動校驗的補充

決定還是采用注解的形式進行編碼,本來想用處理方法參數的裝配進行檢驗,寫好了發現和 @responseBody 不能同時使用,然后發現還是可以使用 @Validated 直接校驗,拋出異常, 進行捕捉異常統一處理。

@PostMapping()@ApiOperation("新增")public ResponseEntity insert(@Validated SysUserAddForm user)

在全局異常處理里面加上 處理綁定參數異常 org.springframework.validation.BindException:

/*** 參數檢驗違反約束(數據校驗)* @param e BindException* @return error message*/@org.springframework.web.bind.annotation.ExceptionHandler(BindException.class)public ResponseEntity<String> handleConstraintViolationException(BindException e) {LOGGER.debug(e.getMessage(), e);return ResponseEntity.status(BAD_REQUEST).body(e.getBindingResult().getAllErrors().stream().map(DefaultMessageSourceResolvable::getDefaultMessage).collect(Collectors.joining(",")));}

轉載于:https://www.cnblogs.com/qnight/p/8997498.html

《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀

總結

以上是生活随笔為你收集整理的学习Spring Boot:(十)使用hibernate validation完成数据后端校验的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。