Java校驗validate介紹和使用實例
Java校驗validate
日常開發(fā)中,我們時常需要提供可靠的 API 接口,此時對于請求的入?yún)⒕托枰r?,以保證最終數(shù)據(jù)入庫的正確性,這就成了必不可少的活。例如說,用戶注冊時,會校驗手機(jī)格式的正確性、郵箱格式的正確性、密碼非弱密碼等。
但是如果使用 if-else 這種代碼去校驗, 那么需要校驗的地方有很多情況下,代碼量就會變的十分臃腫,若是一個類請求參數(shù)校驗字段又多的化,相信各位小伙伴對不會開心,這么干肯定不合適,代碼也不優(yōu)雅,那么如何解決這個問題呢?
答案就是下面要介紹的 validation
validation介紹
validation 技術(shù)在Java中運用最早在2009 年,Java 官方提出了 Bean Validation 規(guī)范,而后經(jīng)歷了JSR303、JSR349、JSR380 三次標(biāo)準(zhǔn)的更迭,發(fā)展到了 2.0 。
Bean Validation 和 我們以前學(xué)習(xí)過的 JPA 一樣,只提供規(guī)范,不提供具體的實現(xiàn)。因此實際使用過程,常用的是 hibernate 的校驗組件:org.hibernate.hibernate-validator
常見的注解
通常情況下,在javax.validation.constraints 包下,定義了一系列的約束(constraint)注解,一共 22 個注解,快速略過即可。如下:
空和非空檢查
- @NotBlank:只能用于字符串不為 null ,并且字符串 .trim() 以后 length 要大于 0 。
- @NotEmpty:集合對象的元素不為 0 ,即集合不為空 。
- @NotNull:不能為 null 。
- @Null:必須為 null 。
數(shù)值檢查
- @DecimalMax(value):被注釋的元素必須是一個數(shù)字,其值必須小于等于指定的最大值。
- @DecimalMin(value):被注釋的元素必須是一個數(shù)字,其值必須大于等于指定的最小值。
- @Digits(integer, fraction):被注釋的元素必須是一個數(shù)字,其值必須在可接受的范圍內(nèi)。
- @Positive:判斷正數(shù)。
- @PositiveOrZero:判斷正數(shù)或 0 。
- @Max(value):該字段的值只能小于或等于該值。
- @Min(value):該字段的值只能大于或等于該值。
- @Negative:判斷負(fù)數(shù)。
- @NegativeOrZero:判斷負(fù)數(shù)或 0 。
Boolean 值檢查
- @AssertFalse:被注釋的元素必須為 true 。
- @AssertTrue:被注釋的元素必須為 false 。
長度檢查
- @Size(max, min):檢查字段的 size 是否在 min 和 max 之間,可以是字符串、數(shù)組、集合、Map 等。
日期檢查
- @Future:被注釋的元素必須是一個將來的日期。
- @FutureOrPresent:判斷日期是否是將來或現(xiàn)在日期。
- @Past:檢查該字段的日期是在過去。
- @PastOrPresent:判斷日期是否是過去或現(xiàn)在日期。
其它檢查
- @Email:被注釋的元素必須是電子郵箱地址。
- @Pattern(value):被注釋的元素必須符合指定的正則表達(dá)式。
Hibernate Validator 附加的約束注解,在org.hibernate.validator.constraints 包下,定義了一系列的約束(constraint)注解。常見的如示。
- @Range(min=, max=):被注釋的元素必須在合適的范圍內(nèi)。
- @Length(min=, max=):被注釋的字符串的大小必須在指定的范圍內(nèi)。
- @URL(protocol=,host=,port=,regexp=,flags=):被注釋的字符串必須是一個有效的 URL 。
- @SafeHtml:判斷提交的 HTML 是否安全。例如說,不能包含 javascript 腳本等等。
其他的就不一一列舉了,有感興趣的小伙伴可以去源碼包看看。
@Valid和 @Validated
- @Valid 注解,是 Bean Validation 所定義,可以添加在普通方法、構(gòu)造方法、方法參數(shù)、方法返回、成員變量上,表示它們需要進(jìn)行約束校驗。
- @Validated 注解,是 Spring Validation 鎖定義,可以添加在類、方法參數(shù)、普通方法上,表示它們需要進(jìn)行約束校驗。同時,@Validated 有 value 屬性,支持分組校驗。
對于初學(xué)者來說,很容易搞混 @Valid 和 @Validated 注解。
- ① 聲明式校驗:Spring Validation 僅對 @Validated 注解,實現(xiàn)聲明式校驗。
- ② 分組校驗:Bean Validation 提供的 @Valid注解,因為沒有分組校驗的屬性,所以無法提供分組校驗。此時,我們只能使用 @Validated 注解。
- ③ 嵌套校驗:相比來說,@Valid注解的地方,多了【成員變量】。這就導(dǎo)致,如果有嵌套對象的時候,只能使用@Valid注解。
spring-boot-starter-web 依賴?yán)?,已?jīng)默認(rèn)引入 hibernate-validator 依賴,所以本示例使用的是 Hibernate Validator 作為 Bean Validation 的實現(xiàn)框架。
1、簡單校驗
編寫實體類(這里以常用的用戶注冊為場景)
@Data public class SysUser { private Long userId; /** * 賬號 */ @NotBlank(message = "用戶名不能為空") @Size(min = 6, message = "用戶名長度不能小于6個字符") private String username; /** * 密碼 */ @NotEmpty(message = "密碼不能為空") @Size(min = 8, message = "密碼長度不能小于8個字符") private String password; /** * 手機(jī)號 */ @NotBlank(message = "手機(jī)號不能為空") @Size(min = 11, max = 11, message = "手機(jī)號長度不對") private String mobile; }
編寫前端控制器
@RestController @RequestMapping("/user") public class SysUserController { @PostMapping("/add") public R addUser(@RequestBody @Valid SysUser sysUser) { System.out.println("走到這里說明校驗成功"); System.out.println(sysUser); return R.ok(R.SUCCESS_MSG); } }
編寫前端響應(yīng)封裝實體
public class R extends HashMap<String, Object> { private static final long serialVersionUID = 1L; public static final String SUCCESS_MSG = "操作成功!"; public static final String FAIL_MSG = "操作失?。?; public R() { this.put((String) "code", 0); } public static R error() { return error(500, "未知異常,請聯(lián)系管理員"); }
public static R error(String msg) { return error(500, msg); } public static R error(int code, String msg) { R r = new R(); r.put((String) "code", code); r.put((String) "msg", msg); return r; } public static R ok(String msg) { R r = new R(); r.put((String) "msg", msg); return r; } public static R ok(Object object) { R r = new R(); r.put("result", object); return r; } public static R ok(int code, String msg) { R r = new R(); r.put((String) "code", code); r.put((String) "msg", msg); return r; } public static R ok(Map<String, Object> map) { R r = new R(); r.putAll(map); return r; } public static R ok() { return new R(); } public R put(String key, Object value) { super.put(key, value); return this; }
編寫自定義異常(用于后續(xù)業(yè)務(wù)拋出異常錯誤)
public class RRException extends RuntimeException { private static final long serialVersionUID = 1L; private String msg; private int code = 500; public RRException(String msg) { super(msg); this.msg = msg; } public RRException(String msg, Throwable e) { super(msg, e); this.msg = msg; } public RRException(String msg, int code) { super(msg); this.msg = msg; this.code = code; } public RRException(String msg, int code, Throwable e) { super(msg, e); this.msg = msg; this.code = code; } public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } public int getCode() { return code; } public void setCode(int code) { this.code = code; } }
當(dāng)訪問/user/add這個post接口時,如果參數(shù)不符合Model中定義的話,程序中就回拋出400異常狀態(tài)碼,并提示錯誤信息,如下所示。
{ “timestamp”: “2021-05-20T01:08:28.831+0000”, “status”: 400, “error”: “Bad Request”, “errors”: [ { “codes”: [ “Size.sysUser.mobile”, “Size.mobile”, “Size.java.lang.String”, “Size” ], “arguments”: [ { “codes”: [ “sysUser.mobile”, “mobile” ], “arguments”: null, “defaultMessage”: “mobile”, “code”: “mobile” }, 11, 11 ], “defaultMessage”: “手機(jī)號長度不對”, “objectName”: “sysUser”, “field”: “mobile”, “rejectedValue”: “155833013”, “bindingFailure”: false, “code”: “Size” } ], “message”: “Validation failed for object=‘sysUser'. Error count: 1”, “path”: “/user/add” }
自定義校驗注解
雖然 JSR303 和 Hibernate Validtor 已經(jīng)提供了很多校驗注解,但是當(dāng)面對復(fù)雜參數(shù)校驗時,還是不能滿足我們的要求,這時候我們就需要 自定義校驗注解。
下面以“List數(shù)組中不能含有null元素”為實例自定義校驗注解
1、注解定義如示。
@Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD, ElementType.FIELD}) @Retention(RUNTIME) @Documented @Constraint(validatedBy = ListNotHaveNullValidatorImpl.class)//此處指定了注解的實現(xiàn)類 public @interface ListNotHaveNull { /** * 添加value屬性,可以作為校驗時的條件,若不需要,可去掉此處定義 / int value() default 0; String message() default “List集合中不能含有null元素”; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; /* * 定義List,為了讓Bean的一個屬性上可以添加多套規(guī)則 */ @Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER}) @Retention(RUNTIME) @Documented @interface List { ListNotHaveNull[] value(); } }
編寫自定義校驗實現(xiàn)類
@Service public class ListNotHaveNullValidatorImpl implements ConstraintValidator<ListNotHaveNull, List> { private int value; @Override public void initialize(ListNotHaveNull constraintAnnotation) { //傳入value 值,可以在校驗中使用 this.value = constraintAnnotation.value(); } public boolean isValid(List list, ConstraintValidatorContext constraintValidatorContext) { for (Object object : list) { if (object == null) { //如果List集合中含有Null元素,校驗失敗 return false; } else if (object instanceof String) { String value = object.toString(); if (value.trim().length() == 0){ return false; } } } return true; } }
model中添加注解:
@Data public class SysRole {
private Long roleId; @NotBlank(message = "角色名不能為空") private String name; @NotEmpty(message = "資源列表不能為空") @ListNotHaveNull(message = "List 中不能含有null元素") @Valid private List<String> paths;
編寫前端控制器
@PostMapping(“/addRole”) public R addRole(@RequestBody @Valid SysRole sysRole) { System.out.println(“走到這里說明校驗成功”); System.out.println(sysRole); return R.ok(R.SUCCESS_MSG); }
使用方法同 “簡單校驗”,在在需要校驗的Model上面加上@Valid即可。
通用的Validtor校驗工具類
public class ValidatorUtils { private ValidatorUtils() { }
private static Validator validator; static { validator = Validation.buildDefaultValidatorFactory().getValidator(); } /** * 校驗對象 * * @param object 待校驗對象 * @param groups 待校驗的組 * @throws RRException 校驗不通過,則報RRException異常 */ public static void validateEntity(Object object, Class<?>... groups) throws RRException { Set<ConstraintViolation<Object>> constraintViolations = validator.validate(object, groups); if (!constraintViolations.isEmpty()) { Iterator<ConstraintViolation<Object>> iterator = constraintViolations.iterator(); StringBuilder msg = new StringBuilder(); while (iterator.hasNext()) { ConstraintViolation<Object> constraint = iterator.next(); msg.append(constraint.getMessage()).append(','); } throw new RRException(msg.toString().substring(0,msg.toString().lastIndexOf(','))); } }
使用方式,在接收到前端傳遞的參數(shù)后,使用ValidatorUtils.validateEntity(【參數(shù)名】);即可校驗,支持分組校驗,分組需要定義分組接口。
總結(jié)
到此這篇關(guān)于Java校驗validate介紹和使用的文章就介紹到這了,更多相關(guān)Java校驗validate內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
springBoot Junit測試用例出現(xiàn)@Autowired不生效的解決
這篇文章主要介紹了springBoot Junit測試用例出現(xiàn)@Autowired不生效的解決,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-09-09解決@Autowired注入空指針問題(利用Bean的生命周期)
這篇文章主要介紹了解決@Autowired注入空指針問題(利用Bean的生命周期),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-02-02Spring Security實現(xiàn)登錄認(rèn)證實戰(zhàn)教程
這篇文章主要介紹了Spring Security實現(xiàn)登錄認(rèn)證實戰(zhàn)教程,本文通過示例代碼給大家介紹的非常詳細(xì),感興趣的朋友一起看看吧2024-06-06IDEA通過git回滾到某個提交節(jié)點或某個版本的操作方法
這篇文章主要介紹了IDEA通過git回滾到某個提交節(jié)點或某個版本的方法,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-07-07springboot整合rocketmq實現(xiàn)分布式事務(wù)
大多數(shù)情況下很多公司是使用消息隊列的方式實現(xiàn)分布式事務(wù)。 本篇文章重點講解springboot環(huán)境下整合rocketmq實現(xiàn)分布式事務(wù),感興趣的可以了解一下2021-05-05Java中File、Base64、MultipartFile之間相互轉(zhuǎn)換的代碼詳解
File、Base64和MultipartFile都是在編程中常用的類或者數(shù)據(jù)類型,用于處理文件和數(shù)據(jù)的存儲、傳輸和轉(zhuǎn)換等操作,本文將給大家介紹了Java中File、Base64、MultipartFile之間相互轉(zhuǎn)換,文中有詳細(xì)的代碼示例供大家參考,需要的朋友可以參考下2024-04-04