參數校驗機制在web開發中是非常重要的,每當看到現在所在公司的校驗代碼,我都有頭疼,每一個接口都是重新寫參數的校驗,有些復雜的接口,參數的校驗甚至占了整個接口代碼量的挺大一部分的,看着我都有些頭疼,我知道可以優化,但是我並不知道該如何優化,正好,七月老師在這個項目中講解到了這一部分,哈哈哈
一、參數校驗機制探究
參數校驗這個是非常重要的,如果把這個參數校驗封裝好了,那真的能節省很多代碼,而且能夠節省很多時間,這個還是非常重要的啊,這里分為參數的傳遞與參數的校驗兩部分內容
1、web開發中參數傳遞方式
在springboot中參數的傳遞基本上和springmvc中是類似的,就是基本上還是那幾種的傳遞方式
(1)路由中的參數
舉例說明:/v1/banner/test/2 (獲取這個路由中的2這個參數)
在path路徑中的參數是可以通過@PathVariable注解來獲取的,注意這個可以做一個映射,參數的名的對應
1 @GetMapping("/test/{id}") 2 public String test(@PathVariable(name = "id") Integer id) { 3 diana.r(); 4 throw new ForbiddenException(10001); 5 }
(2)路由中的?后面的參數
舉例說明:/v1/banner/test/2?name=ssc (在后台中獲取name參數的數值)
這中類型的參數的獲取是利用@RequestParam注解來實現值得獲取的,這個就比較簡單了
1 @GetMapping("/test/{id}") 2 public String test(@PathVariable(name = "id") Integer id, @RequestParam String name) { 3 diana.r(); 4 throw new ForbiddenException(10001); 5 }
(3)獲取json格式的參數
也可以說是獲取對象類型的參數,我們后台處理的時候使用對象接收的,但是在頁面中進行傳遞的時候是json格式的參數,這里有一個新的概念,那就是DTO(Data Transfer Object)也就是數據傳輸對象,之后所有的參數傳輸對象我們都會用這種統一的格式進行傳遞
# DTO例子:(省略get/set方法)
1 public class PersonDTO { 2 3 private String name; 4 private Integer age; 5 }
# 如何應用DTO對象來進行參數的傳輸
這里使用@RequestBody注解進行參數的傳輸的,用的是數據傳輸對象PersonDTO來接收參數的
1 @PostMapping("/test") 2 public String test(@RequestBody PersonDTO person) { 3 diana.r(); 4 throw new ForbiddenException(10001); 5 }
2、參數校驗機制和自定義校驗
(1)基礎驗證注解
# 基礎的注解就是一些SDK中提供的注解,使用的時候一定要在類上添加@Validated注解,組合使用才能起到作用,否則如果不加上這個注解,是沒有作用的
# http body中參數和級聯驗證中,這個是稍微復雜一點的業務了,在對象中還有一個屬性是對象類型的,這個的驗證問題就也不是很復雜
(2)自定義校驗注解
說明:這里以比較兩次輸入的密碼是否相同來舉例,寫一個自定義的注解,來實現該功能
# 首先創建兩個屬性password1和password2,在PersonDTO類中進行創建的,這里使用了lombok的功能注解,簡化getter/setter的代碼
1 @Builder 2 @Getter 3 public class PersonDTO { 4 5 @Length(min = 2, max = 10, message = "name長度在2~10之間") 6 private String name; 7 private Integer age; 8 9 private String password1; 10 private String password2; 11 }
# 然后創建@PasswordEqual注解,這里需要添加兩個特定的屬性
1 @Documented 2 @Retention(RetentionPolicy.RUNTIME) 3 @Target(ElementType.TYPE) 4 public @interface PasswordEqual { 5 6 String message() default "passwords are not equals"; 7 8 // 自定義驗證注解需要默認增加這兩個模板方法的 9 Class<?>[] groups() default {}; 10 Class<? extends Payload>[] payload() default {}; 11 }
注意:注解只是一個標記,我們不可以在注解中實現業務邏輯代碼,自定義注解是有一個專門的關聯類來實現業務邏輯代碼的,這是如何進行實現的呢
# 創建自定義注解的關聯類
1 public class PasswordValidator implements ConstraintValidator<PasswordEqual, PersonDTO> { 2 3 // 泛型中第二個是自定義注解修飾的目標類 4 5 @Override 6 public boolean isValid(PersonDTO personDTO, ConstraintValidatorContext constraintValidatorContext) { 7 String password1 = personDTO.getPassword1(); 8 String password2 = personDTO.getPassword2(); 9 boolean match = password1.equals(password2); 10 return match; 11 } 12 13 }
注意:注解和關聯類是通過@Constraint注解進行組合在一起的,具體的做法就是在自定義注解中添加一個@Constraint注解指定PasswordValidator類的元類class
1 @Documented 2 @Retention(RetentionPolicy.RUNTIME) 3 @Target(ElementType.TYPE) 4 @Constraint(validatedBy = PasswordValidator.class) 5 public @interface PasswordEqual { 6 7 String message() default "passwords are not equals"; 8 9 // 自定義注解需要默認增加這兩個模板方法 10 Class<?>[] groups() default {}; 11 Class<? extends Payload>[] payload() default {}; 12 }
## 這里設計的很巧妙的,在Java中這種編程模式是很優秀的,springboot中應用了很多這種優秀的編程模式,很清晰,代碼可維護性很強
# 獲取自定義校驗注解的參數
在自定義注解中難免會有一些參數,就是在使用自定義注解的時候,我們會添加一些參數,那么如何在關聯類中處理這些參數呢?首先我們應該獲取到這些參數,重寫initialize方法
1 public class PasswordValidator implements ConstraintValidator<PasswordEqual, PersonDTO> { 2 3 // 泛型中第二個是自定義注解修飾的目標的類型 4 5 private int min; 6 private int max; 7 8 @Override 9 public void initialize(PasswordEqual constraintAnnotation) { 10 this.min = constraintAnnotation.min(); 11 this.max = constraintAnnotation.max(); 12 } 13 14 @Override 15 public boolean isValid(PersonDTO personDTO, ConstraintValidatorContext constraintValidatorContext) { 16 String password1 = personDTO.getPassword1(); 17 String password2 = personDTO.getPassword2(); 18 boolean match = password1.equals(password2); 19 return match; 20 } 21 22 }
二、LomBok工具集的使用
1、lombok在項目中安裝
這個直接就安裝在pom.xml文件中就可以了,在pom/xml文件中引入lombok的依賴,但是在idea中查看類的機構的時候,如果不安裝lombok的插件的話,是很不方便的,建議在idea中安裝一個lombok的插件
# pom.xml文件中引入(這里沒有寫版本號,maven自動安裝完成就可以了)
1 <!--lombok maven 依賴--> 2 <dependency> 3 <groupId>org.projectlombok</groupId> 4 <artifactId>lombok</artifactId> 5 </dependency>
# IDEA中安裝lombok插件(直接在plugins插件市場中搜索就可以,直接安裝)
## 安裝完之后,還需要設置一個地方,具體就是:
這樣的話,在查看對象的類結構的時候,當我們使用lombok中的注解的時候,我們就可以正常的看到具體的屬性本質是什么樣子了
注意:關於在IDEA中如何查看Structure工具欄,是通過view ---> Tool windows ---> Structure這樣查看的
2、lombok中注解的學習
(1)@Getter/@Setter注解
這兩個注解就是針對代碼中的get/set方法進行簡化的
(2)constructor構造方法注解
## @AllArgsConstructor 全參數構造方法
## @NoArgsConstructor 無參數構造方法
## @RequiredArgsConstructor 部分參數構造器
(3)@Builder注解構造器模式
這個使用的方法其實也是很簡單的,但是有些需要注意的地方,先看一下這個注解是如何使用的
1 @Builder 2 public class PersonDTO { 3 private String name; 4 private Integer age; 5 }
1 PersonDTO personDTO = PersonDTO.builder() 2 .name("ssc") 3 .age(18) 4 .build();
具體對象創建的時候,我們只能使用builder這種方式進行構建,不能通過無參數的構造方法進行構建,因為在給一個對象加上@Builder注解之后,這個對象的無參數的構造方法會被變成私有的,無法使用
解決辦法:繼續給這個對象添加注解@Setter和@NoArgsConstructor注解,使其能夠無參數構造
還有一個問題,那就是當這個數據傳輸對象作為結果返回的時候,我們是需要在加上@Getter注解的,這樣的話,才能成功將這個對象進行序列化,前端頁面才能成功的將這個結果進行接收
內容出處:七月老師《從Java后端到全棧》視頻課程