Java利用自定義注解實現(xiàn)數(shù)據(jù)校驗
JSR303介紹
在Java中提供了一系列的校驗方式
這些校驗方式在javax.validation.constraints
包中
引入依賴
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency>
常用注解
@Null 驗證對象是否為null
@NotNull 驗證對象是否不為null, 無法查檢長度為0的字符串
@NotBlank 檢查約束字符串是不是Null還有被Trim的長度是否大于0,只對字符串,且會去掉前后空格.
@NotEmpty 檢查約束元素是否為NULL或者是EMPTY.
Booelan檢查
- @AssertTrue 驗證 Boolean 對象是否為 true
- @AssertFalse 驗證 Boolean 對象是否為 false
長度檢查
- @Size(min=, max=) 驗證對象(Array,Collection,Map,String)長度是否在給定的范圍之內
- @Length(min=, max=) Validates that the annotated string is between min and max included.
日期檢查
- @Past 驗證 Date 和 Calendar 對象是否在當前時間之前,驗證成立的話被注釋的元素一定是一個過去的日期
- @Future 驗證 Date 和 Calendar 對象是否在當前時間之后 ,驗證成立的話被注釋的元素一定是一個將來的日期
- @Pattern 驗證 String 對象是否符合正則表達式的規(guī)則,被注釋的元素符合制定的正則表達式,regexp:正則表達式 flags: 指定 Pattern.Flag 的數(shù)組,表示正則表達式的相關選項。
數(shù)值檢查
建議使用在Stirng,Integer類型,不建議使用在int類型上,因為表單值為“”時無法轉換為int,但可以轉換為Stirng為”“,Integer為null
- @Min 驗證 Number 和 String 對象是否大等于指定的值
- @Max 驗證 Number 和 String 對象是否小等于指定的值
- @DecimalMax 被標注的值必須不大于約束中指定的最大值. 這個約束的參數(shù)是一個通過BigDecimal定義的最大值的字符串表示.小數(shù)存在精度
- @DecimalMin 被標注的值必須不小于約束中指定的最小值. 這個約束的參數(shù)是一個通過BigDecimal定義的最小值的字符串表示.小數(shù)存在精度
- @Digits 驗證 Number 和 String 的構成是否合法
- @Digits(integer=,fraction=) 驗證字符串是否是符合指定格式的數(shù)字,interger指定整數(shù)精度,fraction指定小數(shù)精度。
- @Range(min=, max=) 被指定的元素必須在合適的范圍內
- @Range(min=10000,max=50000,message=”range.bean.wage”)
- @Valid 遞歸的對關聯(lián)對象進行校驗, 如果關聯(lián)對象是個集合或者數(shù)組,那么對其中的元素進行遞歸校驗,如果是一個map,則對其中的值部分進行校驗.(是否進行遞歸驗證)
- @CreditCardNumber信用卡驗證
- @Email 驗證是否是郵件地址,如果為null,不進行驗證,算通過驗證。
- @ScriptAssert(lang= ,script=, alias=)
- @URL(protocol=,host=, port=,regexp=, flags=)
開啟校驗
controller中加校驗注解@Valid,開啟校驗
數(shù)據(jù)校驗測試
步驟1:實體類字段上使用校驗注解 @NotNull @NotEmpty @NotBlank @Pattern
步驟2:controller中加校驗注解@Valid,開啟校驗
步驟3:給校驗的Bean后,緊跟一個BindingResult,就可以獲取到校驗的結果
public R save(@Valid @RequestBody User user, BindingResult result){}
實體中添加注解
@Data public class Student { @NotEmpty(message ="姓名不能為空") private String name; }
controller層中保存方法添加:@Valid
@PostMapping("/jsr") public AjaxResult testJrs(@Valid @RequestBody User user, BindingResult result) { String name = user.getName(); HashMap<String, Object> map = new HashMap<>(); map.put("name", name); map.put("errors", result.getFieldErrors()); return AjaxResult.success("數(shù)據(jù)校驗", map); }
數(shù)據(jù)校驗測試:測試:http://localhost:8080/test/jsr
@Data public class User { @NotEmpty(message = "姓名不能為空") @ApiModelProperty("姓名") private String name; @ApiModelProperty("學號") private String id; @ApiModelProperty("年齡") private String age; }
返回信息
{ "msg": "數(shù)據(jù)校驗", "code": 200, "data": { "name": "", "errors": [ { "codes": [ "NotEmpty.user.name", "NotEmpty.name", "NotEmpty.java.lang.String", "NotEmpty" ], "arguments": [ { "codes": [ "user.name", "name" ], "defaultMessage": "name", "code": "name" } ], "defaultMessage": "姓名不能為空", "objectName": "user", "field": "name", "rejectedValue": "", "bindingFailure": false, "code": "NotEmpty" } ] } }
自定義的封裝錯誤信息
@PostMapping("/package") public AjaxResult testPackage(@Valid @RequestBody User user, BindingResult result) { String name = user.getName(); Map<String, String> map = new HashMap<>(); map.put("name", name); if (result.hasErrors()) { //1.獲取錯誤的校驗結果 result.getFieldErrors().forEach((item) -> { //2.獲取發(fā)生錯誤時的message String message = item.getDefaultMessage(); //3.獲取發(fā)生錯誤的字段 String field = item.getField(); map.put(field, message); }); return AjaxResult.error("數(shù)據(jù)校驗", map); } else { return AjaxResult.success(map); } }
自定義的封裝錯誤信息:測試:http://localhost:80/test/package
{ "name": "", "id": "demoData", "age": "demoData" }
錯誤信息
{ "msg": "數(shù)據(jù)校驗", "code": 500, "data": { "name": "姓名不能為空" } }
統(tǒng)一異常處理
@Slf4j @RestControllerAdvice(basePackages = "com.michale.jrs303.controllers") public class FireflyMallExceptionControllerAdvice { /** * 處理數(shù)據(jù)校驗問題 * @param e * @return */ @ExceptionHandler(value = MethodArgumentNotValidException.class) public Result handleVaildException(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()); }); return Result.fail(errorMap, "數(shù)據(jù)校驗出現(xiàn)問題"); } /** * 處理其他異常 * @param throwable * @return */ @ExceptionHandler(value = Throwable.class) public Result handleException(Throwable throwable) { return Result.fail(); } }
@RequestMapping("/testException") public Result testException(@Valid @RequestBody Student student) { String name = student.getName(); Map<String, String> map = new HashMap<>(); map.put("name", name); return Result.ok(map); }
測試統(tǒng)一異常處理:測試:http://localhost:8080/testException
{ "msg": "數(shù)據(jù)校驗出現(xiàn)問題", "path": "/test/testException", "code": 414, "errors": { "name": "姓名不能為空" } }
錯誤信息
{ "code": 500, "msg": "數(shù)據(jù)校驗出現(xiàn)問題", "data": { "name": "姓名不能為空" } }
分組校驗
創(chuàng)建分組校驗接口
/** * @Author 天才小狐貍 * @Data 2022/8/11 2:03 * @Description 姓名校驗分組 */ public interface NameGroup { }
/** * @Author 天才小狐貍 * @Data 2022/8/11 2:04 * @Description 年齡校驗分組 */ public interface AgeGroup { }
添加校驗注解
@Data public class Student { @NotEmpty(message ="姓名不能為空",groups = NameGroup.class) private String name; @NotEmpty(message ="綽號不能為空",groups = NameGroup.class) private String nickName; @Min(value = 18,message = "年齡下限不能低于18歲" ,groups = AgeGroup.class) private String age; @Max(value = 60,message = "年齡上限不能超過60歲" ,groups = AgeGroup.class) private String retireAge; }
開啟分組校驗
@Validated(NameGroup.class)指定校驗分組
@RequestMapping("/testGroup") public Result testGroup(@Validated(NameGroup.class) @RequestBody Student student) { String name = student.getName(); String nickName = student.getNickName(); String age = student.getAge(); String retireAge = student.getRetireAge(); Map<String, String> map = new HashMap<>(); map.put("name", name); map.put("nickname", nickName); map.put("age", age); map.put("retireAge", retireAge); return Result.ok(map); }
測試分組校驗:http://localhost:8080/testGroup
{ "name":"", "nickName":"", "age":"17", "retireAge":"66" }
錯誤信息
{ "code": 500, "msg": "數(shù)據(jù)校驗出現(xiàn)問題", "data": { "nickName": "綽號不能為空", "name": "姓名不能為空" } }
@Validated(AgeGroup.class)指定校驗分組
@RequestMapping("/testGroup") public Result testGroup(@Validated(AgeGroup.class) @RequestBody Student student) { String name = student.getName(); String nickName = student.getNickName(); String age = student.getAge(); String retireAge = student.getRetireAge(); Map<String, String> map = new HashMap<>(); map.put("name", name); map.put("nickname", nickName); map.put("age", age); map.put("retireAge", retireAge); return Result.ok(map); }
測試分組校驗:http://localhost:8080/testGroup
{ "name":"", "nickName":"", "age":"17", "retireAge":66 }
錯誤信息
{ "code": 500, "msg": "數(shù)據(jù)校驗出現(xiàn)問題", "data": { "retireAge": "年齡上限不能超過60歲", "age": "年齡下限不能低于18歲" } }
自定義校驗
編寫自定義的校驗注解
比如要創(chuàng)建一個:@ListValue 注解,被標注的字段值只能是:0或1
@Documented @Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE }) @Retention(RUNTIME) public @interface ListValue { // 使用該屬性去Validation.properties中取 String message() default "{com.atguigu.common.valid.ListValue.message}"; Class<?>[] groups() default { }; Class<? extends Payload>[] payload() default { }; int[] value() default {}; }
設置錯誤信息:創(chuàng)建文件ValidationMessages.properties
com.firefly.common.valid.ListValue.message=必須提交指定的值 [0,1]
編寫自定義的校驗器
import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext; import java.util.HashSet; import java.util.Set; /** * @author Michale @EMail:firefly@163.com * @Date: 2022/1/8 19:23 * @Name ListValueConstraintValidator * @Description: */ public class ListValueConstraintValidator implements ConstraintValidator<ListValue, Integer> { private Set<Integer> set = new HashSet<>(); @Override public void initialize(ListValue constraintAnnotation) { //獲取注解允許的值 int[] value = constraintAnnotation.value(); for (int i : value) { set.add(i); } } @Override public boolean isValid(Integer value, ConstraintValidatorContext context) { //判斷傳入的值是否在滿足允許的值 boolean b = set.contains(value); return b; } }
關聯(lián)校驗器和校驗注解
在@ListValue注解關聯(lián)校驗器
@Constraint(validatedBy = { ListValueConstraintValidator.class})
一個校驗注解可以匹配多個校驗器
添加自定義的校驗注解
@ListValue(value = {0,1},groups = {AgeGroup.class,MyJRS303Group.class}) private Integer gender;
測試自定義校驗器:http://localhost:8080/testGroup
{ "gender":"3" }
{ "code": 500, "msg": "數(shù)據(jù)校驗出現(xiàn)問題", "data": { "gender": "必須提交指定的值 [0,1]" } }
以上就是Java利用自定義注解實現(xiàn)數(shù)據(jù)校驗的詳細內容,更多關于Java數(shù)據(jù)校驗的資料請關注腳本之家其它相關文章!
相關文章
SpringBoot基于數(shù)據(jù)庫的定時任務統(tǒng)一管理的實現(xiàn)
這篇文章主要介紹了SpringBoot基于數(shù)據(jù)庫的定時任務統(tǒng)一管理的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2019-12-12mybatis-plus通用枚舉@JsonValue接收參數(shù)報錯No enum constant
最近在使用mybatis-plus時用到了通用枚舉,遇到了問題,本文主要介紹了mybatis-plus通用枚舉@JsonValue接收參數(shù)報錯No enum constant,具有一定的參考價值,感興趣的可以了解一下2023-09-09Spring JPA事務管理與自定義操作實例解析(最新推薦)
在Spring框架中,數(shù)據(jù)持久化操作常常與事務管理緊密相關,本文將深入探討Spring Data JPA中的事務管理機制,并結合具體實例,展示如何自定義事務行為以滿足不同的業(yè)務需求,感興趣的朋友一起看看吧2024-12-12SpringBoot實現(xiàn)License認證(只校驗有效期)的詳細過程
License也就是版權許可證書,一般用于收費軟件給付費用戶提供的訪問許可證明,這篇文章主要介紹了SpringBoot實現(xiàn)License認證(只校驗有效期),需要的朋友可以參考下2024-04-04SpringBoot+Logback實現(xiàn)一個簡單的鏈路追蹤功能
Spring Boot默認使用LogBack日志系統(tǒng),并且已經引入了相關的jar包,所以我們無需任何配置便可以使用LogBack打印日志。這篇文章主要介紹了SpringBoot+Logback實現(xiàn)一個簡單的鏈路追蹤功能,需要的朋友可以參考下2019-10-10