自定義註解實現密碼的校驗以及參數錯誤的全局異常處理

自定義註解實現密碼的校驗以及參數錯誤的全局異常處理

  • 編寫自定義註解

    @Documented
    @Retention(RetentionPolicy.RUNTIME)
    // 註解的作用目標,ElementType.TYPE表示只能作用在類上
    @Target(ElementType.TYPE)
    // 註解校驗的關聯類
    @Constraint(validatedBy = PasswordValidator.class)
    public @interface PasswordEqual {
    
        // 註解中不能使用包裝類型
        int min() default 4;
    
        int max() default 24;
    
        String message() default "passwords are not equal";
    
        // groups和payload方法是註解中必須要有的兩個方法
        Class<?>[] groups() default {};
    
        Class<? extends Payload>[] payload() default {};
    }
    
  • 編寫自定義註解的關聯類

    /**
     * ConstraintValidator泛型中的第一個參數是關聯的註解,第二個參數是註解修飾的目標的類型
     */
    public class PasswordValidator implements ConstraintValidator<PasswordEqual, PersonDTO> {
    
        private int max;
    
        private int min;
    
        /**
         * 初始化方法
         * @param constraintAnnotation
         */
        @Override
        public void initialize(PasswordEqual constraintAnnotation) {
    
            this.min = constraintAnnotation.min();
            this.max = constraintAnnotation.max();
        }
    
        /**
         * 校驗的方法
         * @param personDTO
         * @param constraintValidatorContext
         * @return
         */
        @Override
        public boolean isValid(PersonDTO personDTO, ConstraintValidatorContext constraintValidatorContext) {
            if(personDTO == null) {
                return false;
            }
            String password1 = personDTO.getPassword1();
            String password2 = personDTO.getPassword2();
            if(password1==null) {
                this.setErrorMessage(constraintValidatorContext, "密碼不能爲空");
                return false;
            }
            if(password1.length()<min || password1.length()>max) {
                this.setErrorMessage(constraintValidatorContext, "密碼的長度不能少於"+this.min+"個字符, 不能超過"+this.max+"個字符");
                return false;
            }
            boolean match = password1.equals(password2);
            if(!match) {
                this.setErrorMessage(constraintValidatorContext, "兩次輸入的密碼不一致");
            }
    
            return match;
        }
    
        // 設置校驗失敗的提示消息
        private void setErrorMessage(ConstraintValidatorContext constraintValidatorContext, String errorMessage) {
            constraintValidatorContext.disableDefaultConstraintViolation();
            constraintValidatorContext
                    .buildConstraintViolationWithTemplate(errorMessage)
                    .addConstraintViolation();
        }
    }
    
  • 編寫實體類

    @PasswordEqual
    public class PersonDTO {
    
        private String password1;
    
        private String password2;
    
        public String getPassword1() {
            return password1;
        }
    
        public void setPassword1(String password1) {
            this.password1 = password1;
        }
    
        public String getPassword2() {
            return password2;
        }
    
        public void setPassword2(String password2) {
            this.password2 = password2;
        }
    }
    
  • 在控制器中使用

    @RestController
    @RequestMapping(value = "/hello")
    public class HelloWorldController {
    
        @GetMapping(value = "/say")
        public String say(@Validated PersonDTO personDTO) {
    
            return "hello, world";
        }
    }
    
  • 參數錯誤的全局異常處理

    @ControllerAdvice
    @RestController
    public class GlobalException {
    
        /**
         * 參數校驗失敗的全局異常處理
         * @param e
         * @return
         */
        // 自定義request狀態碼
        @ResponseStatus(value = HttpStatus.BAD_REQUEST)
        @ExceptionHandler(value = {BindException.class})
        public Map<String, String> handlerArgsBindException(BindException e) {
            List<ObjectError> errors = e.getAllErrors();
            Map<String, String> map = new HashMap<>();
            errors.forEach(error -> map.put(error.getObjectName(), error.getDefaultMessage()));
            return map;
        }
    }
    
    

    handlerArgsBindException只捕獲了通過URL傳參而產生的異常,對於RequestBody傳參和PathValiable產生的異常沒有做處理,可以再定義兩個異常捕獲的方法

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章