后端校驗技術(shù)
JSR303技術(shù),JSR-303 是JAVA EE 6 中的一項子規(guī)范,叫做Bean Validation,Hibernate Validator 是 Bean Validation 的參考實現(xiàn) . Hibernate Validator 提供了 JSR 303 規(guī)范中所有內(nèi)置 constraint 的實現(xiàn),除此之外還有一些附加的 constraint,在springboot中使用也比較簡便。
1.給需要校驗的字段添加校驗注解
在javax.validation.constraints包下有許多的注解:
img
常用的校驗注解補充:
@NotBlank檢查約束字符串是不是Null還有被Trim的長度是否大于0,只對字符串,且會去掉前后空格.@NotEmpty檢查約束元素是否為NULL或者是EMPTY.@Length被檢查的字符串長度是否在指定的范圍內(nèi)@CreditCardNumber信用卡驗證@Email驗證是否是郵件地址,如果為null,不進行驗證,算通過驗證。@URL驗證是否是一個url地址
注意:一個字段可以標注多個校驗注解。
2.給需要檢驗的方法標準@Valid

image.png
如果只標注了注解字段,不啟用@valid的是不生效的。
3.捕捉校驗異常,返回提示信息
對于程序可能有很多的校驗注解,可能會出現(xiàn)多個校驗錯誤,我們可以定義一個統(tǒng)一的異常處理類,幫我們捕捉校驗錯誤并返回提示信息,這里可以利用Spring的ControllerAdvice技術(shù)。
(1).編寫統(tǒng)一異常處理類
packageio.renren.app.exception;importio.renren.common.utils.R;importlombok.extern.slf4j.Slf4j;importorg.springframework.validation.BindingResult;importorg.springframework.web.bind.MethodArgumentNotValidException;importorg.springframework.web.bind.annotation.ControllerAdvice;importorg.springframework.web.bind.annotation.ExceptionHandler;importjava.util.HashMap;importjava.util.Map;/**
* @Author zunhui
* @Email Qiangzunhui@126.com
* @Date 2020/8/5 13:45
* @Description 統(tǒng)一異常處理
*/@RestControllerAdvice(basePackages="io.renren.app.controller")@Slf4jpublicclassAppManageControllerAdvices{@ExceptionHandler(value=MethodArgumentNotValidException.class)publicRhandleVaildException(MethodArgumentNotValidException e){log.error("數(shù)據(jù)校驗出現(xiàn)問題{},異常類型:{}",e.getMessage(),e.getClass());BindingResult bindingResult=e.getBindingResult(); Map<String,String>errorMap=new HashMap<>();bindingResult.getFieldErrors().forEach((fieldError)->{errorMap.put(fieldError.getField(),fieldError.getDefaultMessage());});returnR.error(400,"數(shù)據(jù)校驗失敗").put("data",errorMap);}@ExceptionHandler(value=Throwable.class)publicRhandleException(Throwable throwable){ log.error("錯誤:",throwable);returnR.error(500,"系統(tǒng)未知異常");}}
(2)出現(xiàn)異常將異常拋出
對于校驗可能會出現(xiàn)的異常,我們將其拋出,不予捕捉感知,都交給我們的統(tǒng)一異常處理類處理,返回提示信息。

image.png
4.分組校驗(多場景的復雜校驗)
對于不同的操作,字段校驗的規(guī)則和數(shù)量可能是不同的,所以我們將校驗規(guī)則分組,對于不同的操作進行不同的校驗組,使用groups屬性。
1.想要使用分組校驗功能,根據(jù)文檔我們首先編寫不同的校驗組接口,只編寫空接口,用來表示就可以了:
//新增分組publicinterfaceAddGroup{}//修改分組publicinterfaceUpdateGroup{}
2.編寫好分組接口,對于不同的檢驗規(guī)則,標注不同的分組標識:
@NotNull(message ="修改必須指定id",groups ={UpdateGroup.class})@Null(message ="新增不能指定id",groups ={AddGroup.class})@TableIdprivate Long Id;@NotBlank(message="名稱必須提交",groups={AddGroup.class,UpdateGroup.class})private String name;
3.在controller方法上標注不同的分組校驗,使用@Validated注解:
//保存@RequestMapping("/save")//@RequiresPermissions("product:brand:save")publicRsave(@Validated({AddGroup.class})@RequestBodyBrandEntity brand){brandService.save(brand);returnR.ok();}
@Validated({AddGroup.class}):啟用不同的分組校驗規(guī)則。
注意:在使用分組校驗的情況下,對于沒有標注分組的校驗規(guī)則,默認是不生效的,只有標注了分組的校驗規(guī)則才會生效。
5.自定義校驗
1.編寫一個自定義的校驗注解
導入依賴:
<dependency><groupId>javax.validation</groupId><artifactId>validation-api</artifactId><version>2.0.1.Final</version></dependency>
編寫自定義校驗注解
packagecom.zunhui.common.valid;importjavax.validation.Constraint;importjavax.validation.Payload;importjava.lang.annotation.Documented;importjava.lang.annotation.Retention;importjava.lang.annotation.Target;importstatic java.lang.annotation.ElementType.*;importstatic java.lang.annotation.ElementType.TYPE_USE;importstatic java.lang.annotation.RetentionPolicy.RUNTIME;@Documented//指定校驗器@Constraint(validatedBy={com.zunhui.common.valid.ListValueConstraintValidator.class})@Target({METHOD,FIELD,ANNOTATION_TYPE,CONSTRUCTOR,PARAMETER,TYPE_USE})@Retention(RUNTIME)public@interfaceListValue{//配置默認的提示消息,新建配置文件ValidationMessages.properties在其中配置://com.zunhui.common.valid.ListValue.message = 必須提交指定的值Stringmessage()default="{com.zunhui.common.valid.ListValue.message}";Class<?>[]groups()default{}; Class<?extends Payload>[]payload()default{}; int[]vals()default{};}
用來驗證自定義的字段值,非0即1。
2.編寫一個自定義的校驗器
packagecom.zunhui.common.valid;importjavax.validation.ConstraintValidator;importjavax.validation.ConstraintValidatorContext;importjava.util.HashSet;importjava.util.Set;publicclassListValueConstraintValidatorimplementsConstraintValidator<ListValue,Integer>{privateSet<Integer>set=newHashSet<Integer>();//初始化方法publicvoidinitialize(ListValueconstraintAnnotation){int[]vals=constraintAnnotation.vals();for(intval:vals){set.add(val);}}//判斷是否校驗成功/**
* @param value 需要校驗的值
* @param context
* @return
*/publicbooleanisValid(Integervalue,ConstraintValidatorContextcontext){returnset.contains(value);}}
3.關(guān)聯(lián)自定義的校驗器和自定義的校驗注解
@Constraint(validatedBy ={com.zunhui.common.valid.ListValueConstraintValidator.class})
在自定義的校驗注解中添加自己的校驗器,就關(guān)聯(lián)好了,一個校驗注解可以指定多個不同類型的校驗器,適配不同類型的校驗。關(guān)聯(lián)完成就可以使用了。
4.使用
//校驗指定字段非0即1@ListValue(valus={0,1},message="提示消息,不指定則默認讀取配置文件中的")privateInteger showStatus;
測試:
save方法傳參: showStatus: 3 返回:

image.png
自定義校驗注解生效。
作者:稚友22
鏈接:http://www.itdecent.cn/p/d2ddd856cce2
來源:簡書
著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請注明出處。