您好,登錄后才能下訂單哦!
這篇文章主要講解了“Spring Validation怎么實現數據校驗”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“Spring Validation怎么實現數據校驗”吧!
在開發中,我們經常遇到參數校驗的需求,比如用戶注冊的時候,要校驗用戶名不能為空、用戶名長度不超過20個字符、手機號是合法的手機號格式等等。
如果使用普通方式,我們會把校驗的代碼和真正的業務處理邏輯耦合在一起,而且如果未來要新增一種校驗邏輯也需要在修改多個地方。
而spring validation允許通過注解的方式來定義對象校驗規則,把校驗和業務邏輯分離開,讓代碼編寫更加方便。
Spring Validation其實就是對Hibernate Validator進一步的封裝,方便在Spring中使用。
Spring提供了數種數據校驗的方式:
實現org.springframework.validation.Validator接口,調用接口實現類;
通過 注解 方式進行數據校驗(按照Bean Validation方式);
基于 方法(函數) 實現數據校驗;
自定義校驗
引入Maven依賴
:
<dependencies> <!-- validator校驗相關依賴 --> <dependency> <groupId>org.hibernate.validator</groupId> <artifactId>hibernate-validator</artifactId> <version>7.0.5.Final</version> </dependency> <dependency> <groupId>org.glassfish</groupId> <artifactId>jakarta.el</artifactId> <version>4.0.1</version> </dependency> </dependencies>
注意:上述依賴還不夠,請記得添加spring的基礎依賴和Junit測試等依賴
這是一個用于測試校驗的實體類
:
/** * @author .29. * @create 2023-03-01 10:58 */ //創建實體類,定義屬性及方法,供校驗測試 public class Person { private String name; private int age; public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
這是一個實現了Validator接口的實體類
:
import org.springframework.validation.Errors; import org.springframework.validation.ValidationUtils; import org.springframework.validation.Validator; /** * @author .29. * @create 2023-03-01 11:00 */ //validator接口方式實現 校驗 public class PersonValidator implements Validator { @Override public boolean supports(Class<?> aClass) { return Person.class.equals(aClass); //比對實體類的類對象與參數是否一致 } @Override public void validate(Object o, Errors errors) { //重寫校驗方法 //設置name為空時,報錯:name.empty ValidationUtils.rejectIfEmpty(errors,"name","name.empty"); //傳入對象,強轉為實體類Person對象 Person p = (Person)o; if(p.getAge() < 0){ //設置age屬性小于零時報錯 errors.rejectValue("age","error (age < 0)"); }else if(p.getAge() > 110){//設置age屬性大于110報錯 errors.rejectValue("age","error (age > 110) too old !!"); } } }
校驗測試
:
import org.springframework.validation.BindingResult; import org.springframework.validation.DataBinder; /** * @author .29. * @create 2023-03-01 11:21 */ public class testPersonValidator { public static void main(String[] args){ Person person = new Person(); // person.setName("高啟強"); // person.setAge(29); //創建person對象的DataBinder DataBinder binder = new DataBinder(person); //設置校驗 binder.setValidator(new PersonValidator()); //校驗(當person屬性值為空時,校驗不通過) binder.validate(); //輸出校驗結果 //binder.getBindingResult() 獲取校驗結果對象 //bindingResult.getAllErrors() 獲取所有校驗到的錯誤 BindingResult bindingResult = binder.getBindingResult(); System.out.println(bindingResult.getAllErrors()); } }
沒有傳入參數時,對象為空,得到 name.empty 的校驗錯誤:
[Field error in object ‘target’ on field ‘name’: rejected value [null]; codes [name.empty.target.name,name.empty.name,name.empty.java.lang.String,name.empty]; arguments []; default message [null]]
傳入正確參數后,沒有校驗錯誤可輸出:
[]
使用Bean Validation校驗方式,就是如何將Bean Validation需要使用的javax.validation.ValidatorFactory 和javax.validation.Validator注入到容器中。spring默認有一個實現類LocalValidatorFactoryBean
,它實現了上面Bean Validation中的接口,并且也實現了org.springframework.validation.Validator接口。
這是一個配置了配置LocalValidatorFactoryBean的配置類
:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean; /** * @author .29. * @create 2023-03-01 11:34 */ //配置類 @Configuration //聲明為Spring配置類 @ComponentScan("com.haojin.spring.config") //設置需要掃描的包 public class ValidationConfig { @Bean //返回值放入ioc容器 public LocalValidatorFactoryBean validator() { return new LocalValidatorFactoryBean(); } }
這是一個用于測試校驗的實體類
:
import jakarta.validation.constraints.Max; import jakarta.validation.constraints.Min; import jakarta.validation.constraints.NotNull; /** * @author .29. * @create 2023-03-01 11:36 */ //實體類,使用注解定義校驗規則 public class User { @NotNull //不可為空 private String name; @Min(0) //最小值 @Max(110) //最大值 private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
這里總結一下常見的注解:
@NotNull 限制必須不為null
@NotEmpty 只作用于字符串類型,字符串不為空,并且長度不為0
@NotBlank 只作用于字符串類型,字符串不為空,并且trim()后不為空串
@DecimalMax(value) 限制必須為一個不大于指定值的數字
@DecimalMin(value) 限制必須為一個不小于指定值的數字
@Max(value) 限制必須為一個不大于指定值的數字
@Min(value) 限制必須為一個不小于指定值的數字
@Pattern(value) 限制必須符合指定的正則表達式
@Size(max,min) 限制字符長度必須在min到max之間
@Email 驗證注解的元素值是Email,也可以通過正則表達式和flag指定自定義的email格式
接下來設置校驗器(兩種方式):
方式一:使用java原生的jakarta.validation.Validator校驗
校驗器一號
:
import jakarta.validation.ConstraintViolation; import jakarta.validation.Validator; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.Set; /** * @author .29. * @create 2023-03-01 11:39 */ //使用java原生的jakarta.validation.Validator校驗 @Service public class MyService1 { @Autowired //自動裝配Validator對象 private Validator validator; //校驗方法 public boolean validator(User user){ //校驗后的結果存放進Set集合 Set<ConstraintViolation<User>> set = validator.validate(user); //若沒有校驗到錯誤,集合為空,返回true。 return set.isEmpty(); } }
方式二:用spring提供的validator校驗
校驗器一號
:
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.validation.BindException; import org.springframework.validation.Validator; /** * @author .29. * @create 2023-03-02 9:24 */ //使用spring提供的validate校驗方法 @Service public class MyService2 { @Autowired private Validator validator; public boolean validator2(User user){ BindException bindException = new BindException(user,user.getName()); validator.validate(user,bindException); //調用校驗方法進行校驗 System.out.println(bindException.getAllErrors()); //輸出所有錯誤信息 return bindException.hasErrors(); //若沒有異常,返回false } }
創建測試類,分別測試兩種校驗器
:
import org.junit.jupiter.api.Test; import org.springframework.context.annotation.AnnotationConfigApplicationContext; /** * @author .29. * @create 2023-03-02 9:33 */ public class testBeanValidator { @Test public void testValidatorOne(){ //獲取context對象 AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ValidationConfig.class); //校驗器的實現類對象 MyService1 myValidatorOne = context.getBean(MyService1.class); User user = new User(); boolean validator = myValidatorOne.validator(user); System.out.println(validator); } @Test public void testValidatorTwo(){ //獲取context對象 AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(ValidationConfig.class); //校驗器的實現類對象 MyService2 myValidatorTwo = annotationConfigApplicationContext.getBean(MyService2.class); User user = new User(); boolean validator = myValidatorTwo.validator2(user); System.out.println(validator); } }
這是一個配置了MethodValidationPostProcessor的配置類
:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.validation.beanvalidation.MethodValidationPostProcessor; /** * @author .29. * @create 2023-03-02 18:28 */ //配置了MethodValidationPostProcessor的配置類 @Configuration @ComponentScan("com.haojin.spring.three") public class validationPostProcessor { @Bean public MethodValidationPostProcessor methodValidationPostProcessor(){ return new MethodValidationPostProcessor(); } }
這是一個測試校驗的實體類,校驗規則通過注解設置
import jakarta.validation.constraints.*; /** * @author .29. * @create 2023-03-02 18:30 */ public class User { @NotNull private String name; @Min(0) @Max(129) private int age; //手機號格式 1開頭 第二位是(3、4、6、7、9)其一,后面是9位數字 @Pattern(regexp = "^1(3|4|6|7|9)\\d{9}$",message = "手機號碼格式錯誤") @NotBlank(message = "手機號碼不能為空") private String phone; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getPhone() { return phone; } public void setPhone(String phone) { this.phone = phone; } @Override public String toString() { return "User{" + "name='" + name + '\'' + ", age=" + age + ", phone='" + phone + '\'' + '}'; } }
定義Service類,通過注解操作對象
import jakarta.validation.Valid; import jakarta.validation.constraints.NotNull; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; /** * @author .29. * @create 2023-03-02 18:35 */ @Service @Validated public class MyService { //定義Service類,通過注解操作對象 public String testParams(@NotNull @Valid User user){ return user.toString(); } }
測試
:
import org.junit.jupiter.api.Test; import org.springframework.context.annotation.AnnotationConfigApplicationContext; /** * @author .29. * @create 2023-03-02 18:37 */ public class TestMethod { @Test public void testMyService(){ AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(validationPostProcessor.class); MyService bean = context.getBean(MyService.class); User user = new User(); bean.testParams(user); } }
自定義設置校驗規則的注解
:
import jakarta.validation.Constraint; import jakarta.validation.Payload; import java.lang.annotation.*; @Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER}) @Retention(RetentionPolicy.RUNTIME) @Documented @Constraint(validatedBy = {CannotBlankValidator.class}) public @interface CannotBlank { //默認錯誤消息 String message() default "不能包含空格"; //分組 Class<?>[] groups() default {}; //負載 Class<? extends Payload>[] payload() default {}; //指定多個時使用 @Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.TYPE_USE}) @Retention(RetentionPolicy.RUNTIME) @Documented @interface List { CannotBlank[] value(); } }
編寫校驗類
:
import jakarta.validation.ConstraintValidator; import jakarta.validation.ConstraintValidatorContext; public class CannotBlankValidator implements ConstraintValidator<CannotBlank, String> { @Override public void initialize(CannotBlank constraintAnnotation) { } @Override public boolean isValid(String value, ConstraintValidatorContext context) { //null時不進行校驗 if (value != null && value.contains(" ")) { //獲取默認提示信息 String defaultConstraintMessageTemplate = context.getDefaultConstraintMessageTemplate(); System.out.println("default message :" + defaultConstraintMessageTemplate); //禁用默認提示信息 context.disableDefaultConstraintViolation(); //設置提示語 context.buildConstraintViolationWithTemplate("can not contains blank").addConstraintViolation(); return false; } return true; } }
感謝各位的閱讀,以上就是“Spring Validation怎么實現數據校驗”的內容了,經過本文的學習后,相信大家對Spring Validation怎么實現數據校驗這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。