兩種方式實現Spring 業務驗證

      網友投稿 639 2022-05-30

      關注公眾號回復002,有你想要的一切

      這是 cxuan 的第 33 篇原創文章

      驗證在任何時候都非常關鍵。考慮將數據驗證作為業務邏輯開發有利也有弊,spring 認為,驗證不應該只在Web 端進行處理,在服務端也要進行相應的處理,可以防止臟數據存入數據庫中,從而避免為運維同學和測試同學造成更大的困擾,因為數據造成的bug會更加難以發現,而且開發人員關注點也不會放在數據本身的問題上,所以做服務端的驗證也是非常有必要的。考慮到上面這些問題,Spring 提供了兩種主要類型的驗證:

      一個是實現Validator 接口來創建自定義驗證器,用于服務端數據校驗。

      一種是通過Spring 對Bean Validation 支持實現的。

      通過使用 Spring Validator 接口進行驗證

      Spring 提供 Validator 接口用于驗證對象。Validator 接口通過使用 Errors 對象來工作,以便在驗證時,驗證器可以向 Errors 對象報告驗證失敗。下面是一個簡單的 對象示例

      public class Person {

      private String name;

      private int age;

      // get and set...

      }

      下面一個例子為 Person 對象提供了一種驗證方式,通過實現了 org.springframework.validation.Validator 接口 的兩個方法:

      supports(Class): 表示此 Validator 是否能夠驗證提供的類的實例

      validate(Object, org.springframework.validation.Errors): 驗證給定的對象,如果驗證錯誤,則注冊具有給定 Errors 對象。

      實現一個 Validator 非常簡單,而且Spring 也提供了 ValidationUtils 工具類幫助進行驗證。下面是一個驗證 Person 對象的例子:

      @Component

      public class PersonValidator implements Validator {

      // 此 Validator 只驗證 Person 實例

      public boolean supports(Class clazz) {

      return Person.class.equals(clazz);

      }

      public void validate(Object obj, Errors e) {

      ValidationUtils.rejectIfEmpty(e, "name", "name.empty");

      }

      }

      上面代碼示例中的靜態方法 rejectIfEmpty() 方法用于拒絕name屬性,當name 屬性是 null 或者是 空串的時候。查看 ValidationUtils 文檔關于它能夠提供的功能。

      然后再來編寫配置類 AppConfig:

      @Configuration

      @ComponentScan("com.spring.validation")

      public class AppConfig {}

      配置@ComponentScan 注解用于自動裝配,默認是使用 basePackages 掃描指定包,字符串表示。

      然后對上面的程序進行驗證

      public class SpringValidationApplicationTests {

      public static void main(String[] args) {

      AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);

      Person person = new Person();

      person.setAge(18);

      person.setName(null);

      PersonValidator personValidator = applicationContext.getBean("personValidator", PersonValidator.class);

      BeanPropertyBindingResult result = new BeanPropertyBindingResult(person,"cxuan");

      ValidationUtils.invokeValidator(personValidator,person,result);

      List allErrors = result.getAllErrors();

      allErrors.forEach(e-> System.out.println(e.getCode()));

      }

      }

      因為是基于注解的配置,所以使用 AnnotationConfigApplicationContext上下文啟動類,把配置類 AppConfig 當作參數,然后構建一個Person 類,為了測試驗證有效性,把 name 設置為 null,然后通過上下問的 getBean 方法獲得 personValidator 的實例,通過使用 BeanPropertyBindingResult 把 person 綁定為 cxuan 的名字,然后使用 ValidationUtils 工具類進行驗證,最后把驗證的結果進行檢查。

      上面程序經驗證后的結果如下:

      org.springframework.validation.ValidationUtils - Invoking validator [com.spring.validation.PersonValidator@37918c79] DEBUG org.springframework.validation.ValidationUtils - Validator found 1 errors name.empty

      使用 Bean Validation 進行驗證

      從 Spring4 開始,就已經實現對 JSR-349 Bean Validation 的全面支持。Bean Validation API 在 javax.validation.constraints 包中以 Java 注解(例如 @NonNull) 形式定義了一組可用域對象的約束。

      通過使用 Bean Validation API ,可以避免耦合到特定的驗證服務提供程序。Spring 對 Bean Validation API 提供了無縫支持,主要使用一些注解進行驗證,下面一起來看一下

      定義對象屬性上的驗證約束

      首先,將驗證約束應用于域對象屬性。使用maven 配置需要引入對應的依賴

      javax.validation

      validation-api

      1.1.0.Final

      org.hibernate

      hibernate-validator

      5.2.4.Final

      之后定義了一些實體類,使用 javax.validation.constraints 包中的注釋進行標注

      public class Singer {

      @NotNull

      @Size(min = 2,max = 60)

      private String firstName;

      private String lastName;

      @NotNull

      private Genre genre;

      private Gender gender;

      get and set...

      }

      對于 firstName ,定義了兩個約束,第一個約束由 @NotNull 進行控制,它表示該值不能為空。此外,@Size注解控制著 firstName 的長度在 2 - 60 之間。@NotNull 還用于 genre 屬性。下面是Genre 和 Gender 的枚舉類

      public enum Genre {

      POP("P"),

      JAZZ("J"),

      BLUES("B"),

      COUNTRY("C");

      private String code;

      private Genre(String code){

      this.code = code;

      兩種方式實現Spring 業務驗證

      }

      public String toString(){

      return this.code;

      }

      }

      public enum Gender {

      MALE("M"),

      FEMALE("F");

      private String code;

      Gender(String code){

      this.code = code;

      }

      @Override

      public String toString() {

      return this.code;

      }

      }

      Genre 表示歌手所屬的音樂類型,而 Gender 與音樂事業不相關,所以可以為空

      在 Spring 中配置 Bean Validation 支持

      為了在 Spring 的 ApplicationContext 中配置對 Bean Validation API 的支持,可以在Spring 的配置中定義一個 LocalValidatorFactoryBean 的 bean如下

      @Configuration

      @ComponentScan("com.spring.validation")

      public class ValidationConfig {

      @Bean

      LocalValidatorFactoryBean validatorFactoryBean(){

      return new LocalValidatorFactoryBean();

      }

      }

      聲明一個 LocalValidatorFactoryBean 的 bean 是必須的。默認情況下,Spring 會在類路徑下搜索 Hibernate Validator庫,驗證它是否存在。

      下面我們編寫一個為 Singer 類提供驗證服務的服務類

      @Service

      public class SingerValidationService {

      @Autowired

      private Validator validator;

      public Set> validateSinger(Singer singer){

      return validator.validate(singer);

      }

      }

      注入一個 javax.validation.Validator 實例(請注意與 Spring 提供的 Validator 接口不同)。一旦定義了 LocalValidatorFactoryBean ,就可以在應用程序中的任意位置創建 Validator 的句柄。要在 POJO 上進行驗證,需要調用 validator.validate 方法,驗證結果以 ConstraintViolation 接口的集合形式返回。下面是上面例子程序的驗證

      public class SpringBeanValidationTest {

      public static void main(String[] args) {

      AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(ValidationConfig.class);

      SingerValidationService singerBean = applicationContext.getBean(SingerValidationService.class);

      Singer singer = new Singer();

      singer.setFirstName("c");

      singer.setLastName("xuan");

      singer.setGenre(null);

      singer.setGender(null);

      validateSinger(singer,singerBean);

      applicationContext.close();

      }

      private static void validateSinger(Singer singer,SingerValidationService singerValidationService){

      Set> violationSet = singerValidationService.validateSinger(singer);

      listViolations(violationSet);

      }

      private static void listViolations(Set> violations){

      System.out.println("violations.size() = " + violations.size());

      for(ConstraintViolation violation : violations){

      System.out.println("Validation error for property : " + violation.getPropertyPath());

      System.out.println("with value : " + violation.getInvalidValue());

      System.out.println("with error message : " + violation.getMessage());

      }

      }

      }

      上述代碼構建了一個 Singer 類進行驗證,因為 firstname 屬性的要求是長度介于 2 - 60 之間并且不能為null,所以這里只用了一個字符驗證,genre 屬性不能為null,最核心的驗證方法就是 singerValidationService.validateSinger(singer).方法,它會調用

      public Set> validateSinger(Singer singer){

      return validator.validate(singer);

      }

      進行驗證,驗證的結果返回的是 ConstraintViolation類型,然后把對應的錯誤信息輸出,上面的錯誤信息是

      violations.size() = 2 Validation error for property : firstName with value : c with error message : 個數必須在2和60之間 Validation error for property : genre with value : null with error message : 不能為null

      可以打印出兩個錯誤,并輸出錯誤的屬性、值以及錯誤信息。

      你點的每個好看,我都認真當成了喜歡

      Spring

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:深度學習最全優化方法總結比較(SGD,Adagrad,Adadelta,Adam,Adamax,Nadam)
      下一篇:高數計算,我Python替你承包了
      相關文章
      亚洲一卡二卡三卡四卡无卡麻豆| 国产亚洲成人在线播放va| 国产亚洲精品自在线观看| jizzjizz亚洲日本少妇| 亚洲国产精品无码久久98| 亚洲欧美国产国产一区二区三区| 中文字幕无码亚洲欧洲日韩| 国产亚洲精品bv在线观看| 亚洲中文字幕一二三四区苍井空| 亚洲av无码一区二区三区观看| 亚洲国产av一区二区三区丶| 亚洲区视频在线观看| 亚洲深深色噜噜狠狠网站| 亚洲色大成网站www永久男同 | 亚洲AV一宅男色影视| 国产A在亚洲线播放| 亚洲av综合avav中文| 亚洲AV成人一区二区三区AV| 亚洲高清在线观看| 亚洲黄色在线观看| 亚洲中文无码av永久| 亚洲第一区二区快射影院| 亚洲日韩精品国产3区| 久久综合亚洲色hezyo| 国产精品亚洲一区二区三区久久| 亚洲äv永久无码精品天堂久久 | 亚洲成av人片天堂网无码】| 久久亚洲中文字幕无码| 亚洲精品无码专区久久同性男| 亚洲综合久久夜AV | 亚洲精品成人网站在线观看| 亚洲天堂久久精品| 亚洲国产精品yw在线观看| 亚洲人成网站色在线观看| 亚洲Av高清一区二区三区| 亚洲av永久无码天堂网| 亚洲国产精品国产自在在线| 亚洲精品中文字幕乱码三区| 亚洲一区影音先锋色资源| 亚洲一级黄色大片| mm1313亚洲国产精品无码试看 |