最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊(cè)

SpringBoot + validator優(yōu)雅參數(shù)校驗(yàn),消除if-else

2023-06-26 23:56 作者:取個(gè)名字吧一個(gè)就好  | 我要投稿

Hi,大家好,我是搶老婆酸奶的小肥仔。

在我們?nèi)粘i_發(fā)中,參數(shù)校驗(yàn)必不可少,一般情況下我們習(xí)慣采用if-else來(lái)進(jìn)行校驗(yàn),結(jié)果就是滿屏的if-else。代碼既不優(yōu)雅,也會(huì)令人眼花繚亂,維護(hù)也是繁瑣。那么有沒(méi)有優(yōu)雅的參數(shù)校驗(yàn)?zāi)兀坑?,使?code>hibernate-validator吧,它會(huì)讓你愛(ài)不釋手。

廢話不多說(shuō),擼起來(lái)吧。

1、簡(jiǎn)介

Hibernate Validate是Bean Validation實(shí)現(xiàn)的,內(nèi)置了JSR303/JSR380中所有的constraint的實(shí)現(xiàn),同時(shí)也額外提供了很多自定義的constraint。Bean Validation為JavaBean的驗(yàn)證提供了很多相關(guān)的元數(shù)據(jù)模型和API。

參數(shù)說(shuō)明

在Hibernate Validate提供了很多注解,以實(shí)現(xiàn)對(duì)應(yīng)參數(shù)的校驗(yàn)。

參數(shù)描述@Null參數(shù)必須為null@NotNull參數(shù)不能為null@NotBlank參數(shù)不能為null和空值,一般作用在字符串類型@AssertTrue參數(shù)必須為true@AssertFalse參數(shù)必須為false@Min(value)參數(shù)必須是數(shù)字,且大于等于指定的最小值@Max(value)參數(shù)必須是數(shù)字,且小于等于指定的最大值@DecimalMin(value)參數(shù)必須是數(shù)字,且大于等于指定的最小值@DecimalMax(value)參數(shù)必須是數(shù)字,且小于等于指定的最大值@Length(min,max)指定字符長(zhǎng)度,最小值是多少,最大值是多少@Size(max,min)參數(shù)的大小必須在指定的范圍@Digits(Integer,fraction)參數(shù)必須是個(gè)數(shù)字,且大小必須在可接受范圍內(nèi)@Past參數(shù)必須是一個(gè)過(guò)去的日期@Future參數(shù)必須是一個(gè)將來(lái)的日期@Pattern(value)參數(shù)必須符合指定的正則表達(dá)式@Email參數(shù)必須符合電子郵箱地址@NotEmpty參數(shù)必須非空@Range參數(shù)必須在合適的范圍內(nèi)

2、快速開始

在SpringBoot中使用Hibernate Validate特別簡(jiǎn)單,只需要引入jar包即可。

mavan引入:

xml復(fù)制代碼<dependency> ??<groupId>org.hibernate.validator</groupId> ??<artifactId>hibernate-validator</artifactId> ??<version>6.2.3.Final</version> </dependency>

gradle引入:

xml復(fù)制代碼implementation group: 'org.hibernate.validator', name: 'hibernate-validator', version: '6.2.3.Final'

封裝統(tǒng)一異常處理類:

java復(fù)制代碼/** * @author: jiangjs * @description: 統(tǒng)一異常處理方法 * @date: 2022/6/21 11:28 **/ @RestControllerAdvice public class GlobalExceptionHandler { ? ? ?@ExceptionHandler({ConstraintViolationException.class, MethodArgumentNotValidException.class}) ?? ?public ResultUtil<String> resolveViolationException(Exception ex){ ?? ? ? ?StringJoiner messages = new StringJoiner(","); ?? ? ? ?if (ex instanceof ConstraintViolationException){ ?? ? ? ? ? ?Set<ConstraintViolation<?>> violations = ((ConstraintViolationException) ex).getConstraintViolations(); ?? ? ? ? ? ?for (ConstraintViolation<?> violation : violations) { ?? ? ? ? ? ? ? ?messages.add(violation.getMessage()); ?? ? ? ? ? ?} ?? ? ? ?} else { ?? ? ? ? ? ?List<ObjectError> allErrors = ((MethodArgumentNotValidException) ex).getBindingResult().getAllErrors(); ?? ? ? ? ? ?for (ObjectError error : allErrors) { ?? ? ? ? ? ? ? ?messages.add(error.getDefaultMessage()); ?? ? ? ? ? ?} ?? ? ? ?} ?? ? ? ?return ResultUtil.error(400,String.valueOf(messages)); ?? ?} }

2.1 參數(shù)校驗(yàn)

2.1.1 創(chuàng)建實(shí)體

java復(fù)制代碼/** ?* @author: jiangjs ?* @description: ?* @date: 2022/6/21 10:46 ?**/ @Data public class UserInfo { ?? ?private Long userId; ? ? ?@NotBlank(message = "用戶名不能為空") ?? ?private String userName; ? ? ?@NotBlank(message = "密碼不能為空") ?? ?private String password; ? ? ?@Email(message = "請(qǐng)?zhí)顚懻_的email") ?? ?@NotBlank(message = "email不能為空") ?? ?private String email; }

上述實(shí)體中,我們看到使用了@NutBlank,@Email來(lái)校驗(yàn)String參數(shù)不能null和空,同時(shí)也校驗(yàn)了email是否符合email規(guī)則。

2.1.2 測(cè)試

使用Hibernate Validate則直接在參數(shù)前使用 @Validated注解即可。

less復(fù)制代碼@PostMapping("/insertUserInfo.do") public ResultUtil<?> insertUserInfo(@Validated @RequestBody UserInfo userInfo){ ?? ?return ResultUtil.success(userInfo.toString()); }

輸出:

在參數(shù)校驗(yàn)時(shí),會(huì)根據(jù)參數(shù)的順序來(lái)進(jìn)行校驗(yàn),當(dāng)一個(gè)參數(shù)不符合規(guī)則時(shí),則直接返回校驗(yàn)結(jié)果。

  1. 我們?cè)谶M(jìn)行參數(shù)傳遞時(shí),不填寫username。

  1. 校驗(yàn)email是否符合規(guī)則

2.2 路徑參數(shù)校驗(yàn)

我們?cè)谑褂胷eastful定義接口時(shí),可能會(huì)使用@PathVariable來(lái)直接在接口url后傳遞參數(shù),有時(shí)候傳遞的參數(shù)并不符合我們定義的參數(shù)規(guī)則,此時(shí)我們可以進(jìn)行參數(shù)校驗(yàn)。

校驗(yàn)規(guī)則:參數(shù):正則表達(dá)式

java復(fù)制代碼@GetMapping("/getUserInfoByUserId.do/{userId:[0-9_]+}") public String getUserInfoByUserId(@PathVariable("userId") Integer userId){ ?? ?return String.valueOf(userId); }

定義傳遞的userId必須是由數(shù)字組成。

輸出:

當(dāng)傳遞參數(shù)不符合正則時(shí),則直接報(bào)錯(cuò)。

通過(guò)url進(jìn)行參數(shù)校驗(yàn),我們只看到了報(bào)錯(cuò),并沒(méi)有提示具體錯(cuò)誤信息,也不能像使用注解那樣自定義錯(cuò)誤信息返回。

2.3 分組校驗(yàn)

在我們?nèi)粘i_發(fā)中常常涉及到更新,在更新的時(shí)候往往需要傳遞數(shù)據(jù)的Id,但是新增的時(shí)候又不需要這個(gè)Id,此時(shí)我們可以采用分組來(lái)進(jìn)行數(shù)據(jù)Id的校驗(yàn)。

2.3.1 分組定義

java復(fù)制代碼/** ?* @author: jiangjs ?* @description: ?* @date: 2022/6/21 10:46 ?**/ @Data public class UserInfo { ?? ?public interface Update{}; ? ? ?@NotNull(message = "userId不能為空",groups = Update.class) ?? ?private Long userId; ? ? ?@NotBlank(message = "用戶名不能為空") ?? ?private String userName; ? ? ?@NotBlank(message = "密碼不能為空") ?? ?private String password; ? ? ?@Email(message = "請(qǐng)?zhí)顚懻_的email") ?? ?@NotBlank(message = "email不能為空") ?? ?private String email; ?}

我們?cè)趯?shí)體類中定義了一個(gè)接口Update,然后在注解中的groups中指定即可。

2.3.2 測(cè)試

java復(fù)制代碼/** ?? ? * 分組校驗(yàn)數(shù)據(jù)信息:定義Update ?? ? */ ?? ?@PostMapping("/updateUserInfo.do") ?? ?public ResultUtil<?> updateUserInfo(@Validated(value = UserInfo.Update.class) @RequestBody UserInfo userInfo){ ?? ? ? ?return ResultUtil.success(userInfo.toString()); ?? ?}

在@Validated中value指定實(shí)體中定義的接口。

輸出:

2.4 校驗(yàn)傳遞

在日常開發(fā)中我們經(jīng)常會(huì)在實(shí)體中引入其他實(shí)體,并且又要對(duì)其他實(shí)體中的數(shù)據(jù)進(jìn)行數(shù)據(jù)校驗(yàn),此時(shí)就存在檢驗(yàn)傳遞,通常我們?cè)谛枰r?yàn)的實(shí)體前使用 @Valid即可。

2.4.1 定義實(shí)體

添加一個(gè)雇員信息實(shí)體:

java復(fù)制代碼/** ?* @author: jiangjs ?* @description: ?* @date: 2022/6/21 14:48 ?**/ @Data public class Employee { ?? ?@NotBlank(message = "請(qǐng)?zhí)顚懝蛦T名稱") ?? ?private String name; }

在userInfo實(shí)體中引入Employee

java復(fù)制代碼/** ?* @author: jiangjs ?* @description: ?* @date: 2022/6/21 10:46 ?**/ @Data public class UserInfo { ?? ?public interface Update{}; ? ? ?@NotNull(message = "userId不能為空",groups = Update.class) ?? ?private Long userId; ? ? ?@NotBlank(message = "用戶名不能為空") ?? ?private String userName; ? ? ?@NotBlank(message = "密碼不能為空") ?? ?private String password; ? ? ?@Email(message = "請(qǐng)?zhí)顚懻_的email") ?? ?@NotBlank(message = "email不能為空") ?? ?private String email; ? ? ?@Valid ?? ?@NotNull(message = "雇員信息不能為空") ?? ?private Employee employee; ?}

2.4.2 測(cè)試

java復(fù)制代碼@PostMapping("/insertUserInfo.do") public ResultUtil<?> insertUserInfo(@Validated @RequestBody UserInfo userInfo){ ?? ?return ResultUtil.success(userInfo.toString()); }

輸出:

2.5 自定義校驗(yàn)

在參數(shù)校驗(yàn)時(shí),可能Hibernate Validate自帶的校驗(yàn)規(guī)則并不能滿足我們業(yè)務(wù)需求,此時(shí)我們可以實(shí)現(xiàn)自定義校驗(yàn)規(guī)則。

需求:對(duì)身份證進(jìn)行校驗(yàn)。

2.5.1 定義注解

java復(fù)制代碼/** ?* @author: jiangjs ?* @description: 身份證校驗(yàn)規(guī)則 ?* @date: 2022/6/21 11:28 ?**/ @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.PARAMETER,ElementType.FIELD}) @Constraint(validatedBy = IdCodeValidator.class) public @interface IdCode { ?? ?String message() default "請(qǐng)?zhí)顚懻_的身份證信息"; ?? ?Class<?>[] groups() default {}; ?? ?Class<? extends Payload>[] payload() default {}; }

@Constraint:Hibernate Validate提供的注解,用于實(shí)現(xiàn)自定義校驗(yàn)規(guī)則。其中validatedBy就是指定進(jìn)行參數(shù)校驗(yàn)的實(shí)現(xiàn)類。

注:在自定義校驗(yàn)注解時(shí)必須帶上groups()和payload(),否則會(huì)報(bào)錯(cuò)。

2.5.2 校驗(yàn)實(shí)現(xiàn)類

java復(fù)制代碼/** ?* @author: jiangjs ?* @description: 身份證校驗(yàn) ?* @date: 2022/6/21 14:25 ?**/ public class IdCodeValidator implements ConstraintValidator<IdCode,Object> { ? ? ? ? ?/** ?? ? ? ? * 18位二代身份證號(hào)碼的正則表達(dá)式 ?? ? ? ? */ ?? ?public static final String REGEX_ID_NO_18 = "^" ?? ? ? ? ? ? ? ?// 6位地區(qū)碼 ?? ? ? ? ? ?+ "\d{6}" ?? ? ? ? ? ? ? ?// 年YYYY ?? ? ? ? ? ?+ "(18|19|([23]\d))\d{2}" ?? ? ? ? ? ? ? ?// 月MM ?? ? ? ? ? ?+ "((0[1-9])|(10|11|12))" ?? ? ? ? ? ? ? ?// 日DD ?? ? ? ? ? ?+ "(([0-2][1-9])|10|20|30|31)" ?? ? ? ? ? ? ? ?// 3位順序碼 ?? ? ? ? ? ?+ "\d{3}" ?? ? ? ? ? ? ? ?// 校驗(yàn)碼 ?? ? ? ? ? ?+ "[0-9Xx]" ?? ? ? ? ? ?+ "$"; ? ? ?/** ?? ? * 15位一代身份證號(hào)碼的正則表達(dá)式 ?? ? */ ?? ?public static final String REGEX_ID_NO_15 = "^" ?? ? ? ? ? ?+ "\d{6}" // 6位地區(qū)碼 ?? ? ? ? ? ?+ "\d{2}" // 年YYYY ?? ? ? ? ? ?+ "((0[1-9])|(10|11|12))" // 月MM ?? ? ? ? ? ?+ "(([0-2][1-9])|10|20|30|31)" // 日DD ?? ? ? ? ? ?+ "\d{3}"// 3位順序碼 ?? ? ? ? ? ?+ "$"; ?? ?@Override ?? ?public void initialize(IdCode constraintAnnotation) { ?? ? ? ?ConstraintValidator.super.initialize(constraintAnnotation); ?? ?} ? ? ?@Override ?? ?public boolean isValid(Object o, ConstraintValidatorContext constraintValidatorContext) { ?? ? ? ?String idCode = String.valueOf(o); ?? ? ? ?if (idCode.length() != 15 && idCode.length() != 18){ ?? ? ? ? ? return false; ?? ? ? } ?? ? ? ?return idCode.matches(REGEX_ID_NO_18) || idCode.matches(REGEX_ID_NO_15); ?? ?} }

ConstraintValidator:Hibernate Validate提供的接口,ConstraintValidator<A extends Annotation, T>,第一個(gè)參數(shù)必須是注解,即Annotation,第二個(gè)參數(shù)是泛型。同時(shí)在接口中提供了兩個(gè)方法:

  • initialize(A constraintAnnotation),初始化注解,

  • boolean isValid(T var1, ConstraintValidatorContext var2):校驗(yàn)參數(shù),true表示校驗(yàn)通過(guò),false表示校驗(yàn)失敗。

2.5.3 測(cè)試

java復(fù)制代碼/** ?* 自定義校驗(yàn)數(shù)據(jù)信息 ?*/ @PostMapping("/definedEmployeeInfo.do") public ResultUtil<?> definedEmployeeInfo(@Validated @RequestBody Employee employee){ ?? ?return ResultUtil.success(employee.toString()); }

在Employee中添加校驗(yàn)注解:

java復(fù)制代碼/** ?* @author: jiangjs ?* @description: ?* @date: 2022/6/21 14:48 ?**/ @Data public class Employee { ?? ?@NotBlank(message = "請(qǐng)?zhí)顚懝蛦T名稱") ?? ?private String name; ? ? ?@IdCode(message = "請(qǐng)?zhí)顚懻_的身份證信息!") ?? ?private String idCode; }

輸出:

輸入了錯(cuò)誤的身份證,則校驗(yàn)不通過(guò),提示定義的信息。

在日常工作中,使用Hibernate Validate進(jìn)行參數(shù)校驗(yàn)真的會(huì)事半功倍,同時(shí)也提供了自定義校驗(yàn)的實(shí)現(xiàn),讓我們更加專注于業(yè)務(wù)。

SpringBoot + validator優(yōu)雅參數(shù)校驗(yàn),消除if-else的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國(guó)家法律
襄城县| 四川省| 甘孜| 青龙| 祁阳县| 曲靖市| 安义县| 桂林市| 安塞县| 遂川县| 通化县| 鹰潭市| 苍南县| 怀安县| 海盐县| 青河县| 西充县| 榆林市| 南平市| 贵南县| 南江县| 金沙县| 武威市| 安乡县| 长海县| 乌鲁木齐市| 盐亭县| 巩留县| 电白县| 东乌| 乳源| 寻乌县| 定结县| 合川市| 特克斯县| 合肥市| 宜城市| 区。| 神木县| 两当县| 泌阳县|