美文网首页springboot2
参数校验优雅写法

参数校验优雅写法

作者: 后来丶_a24d | 来源:发表于2020-04-16 11:15 被阅读0次

    目录

    • 使用validator
    • 项目实战
    • 在全局校验中增加校验异常
    • 自定义参数注解

    使用validator

    • javax.validation的一系列注解可以帮我们完成参数校验,免去繁琐的串行校验
    • pom引入
    <dependency>
        <groupId>javax.validation</groupId>
        <artifactId>validation-api</artifactId>
        <version>1.1.0.Final</version>
    </dependency>
    <!-- hibernate validator-->
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-validator</artifactId>
        <version>5.2.0.Final</version>
    </dependency>
    

    项目实战

    @PostMapping("/save/valid")
    public RspDTO save(@RequestBody @Validated UserDTO userDTO) {
        userService.save(userDTO);
        return RspDTO.success();
    }
    
    public class UserDTO implements Serializable {
    
        private static final long serialVersionUID = 1L;
    
        /*** 用户ID*/
        @NotNull(message = "用户id不能为空")
        private Long userId;
    
        /** 用户名*/
        @NotBlank(message = "用户名不能为空")
        @Length(max = 20, message = "用户名不能超过20个字符")
        @Pattern(regexp = "^[\\u4E00-\\u9FA5A-Za-z0-9\\*]*$", message = "用户昵称限制:最多20字符,包含文字、字母和数字")
        private String username;
    
        /** 手机号*/
        @NotBlank(message = "手机号不能为空")
        @Pattern(regexp = "^[1][3,4,5,6,7,8,9][0-9]{9}$", message = "手机号格式有误")
        private String mobile;
    
        /**性别*/
        private String sex;
    
        /** 邮箱*/
        @NotBlank(message = "联系邮箱不能为空")
        @Email(message = "邮箱格式不对")
        private String email;
    
        /** 密码*/
        private String password;
    
        /*** 创建时间 */
        @Future(message = "时间必须是将来时间")
        private Date createTime;
    
    }
    

    在全局校验中增加校验异常

    @RestControllerAdvice
    public class GlobalExceptionHandler {
    
        private Logger logger = LoggerFactory.getLogger(getClass());
    
        private static int DUPLICATE_KEY_CODE = 1001;
        private static int PARAM_FAIL_CODE = 1002;
        private static int VALIDATION_CODE = 1003;
    
        /**
         * 处理自定义异常
         */
        @ExceptionHandler(BizException.class)
        public RspDTO handleRRException(BizException e) {
            logger.error(e.getMessage(), e);
            return new RspDTO(e.getCode(), e.getMessage());
        }
    
        /**
         * 方法参数校验
         */
        @ExceptionHandler(MethodArgumentNotValidException.class)
        public RspDTO handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
            logger.error(e.getMessage(), e);
            return new RspDTO(PARAM_FAIL_CODE, e.getBindingResult().getFieldError().getDefaultMessage());
        }
    
        /**
         * ValidationException
         */
        @ExceptionHandler(ValidationException.class)
        public RspDTO handleValidationException(ValidationException e) {
            logger.error(e.getMessage(), e);
            return new RspDTO(VALIDATION_CODE, e.getCause().getMessage());
        }
    
        /**
         * ConstraintViolationException
         */
        @ExceptionHandler(ConstraintViolationException.class)
        public RspDTO handleConstraintViolationException(ConstraintViolationException e) {
            logger.error(e.getMessage(), e);
            return new RspDTO(PARAM_FAIL_CODE, e.getMessage());
        }
    
        @ExceptionHandler(NoHandlerFoundException.class)
        public RspDTO handlerNoFoundException(Exception e) {
            logger.error(e.getMessage(), e);
            return new RspDTO(404, "路径不存在,请检查路径是否正确");
        }
    
        @ExceptionHandler(DuplicateKeyException.class)
        public RspDTO handleDuplicateKeyException(DuplicateKeyException e) {
            logger.error(e.getMessage(), e);
            return new RspDTO(DUPLICATE_KEY_CODE, "数据重复,请检查后提交");
        }
    
    
        @ExceptionHandler(Exception.class)
        public RspDTO handleException(Exception e) {
            logger.error(e.getMessage(), e);
            return new RspDTO(500, "系统繁忙,请稍后再试");
        }
    }
    

    自定义参数注解

    • message 定制化的提示信息,主要是从ValidationMessages.properties里提取,也可以依据实际情况进行定制; groups 这里主要进行将validator进行分类,不同的类group中会执行不同的validator操作; payload 主要是针对bean的,使用不多。
    @Documented
    @Target({ElementType.PARAMETER, ElementType.FIELD})
    @Retention(RetentionPolicy.RUNTIME)
    @Constraint(validatedBy = IdentityCardNumberValidator.class)
    public @interface IdentityCardNumber {
    
        String message() default "身份证号码不合法";
    
        Class<?>[] groups() default {};
    
        Class<? extends Payload>[] payload() default {};
    }
    
    public class IdentityCardNumberValidator implements ConstraintValidator<IdentityCardNumber, Object> {
    
        @Override
        public void initialize(IdentityCardNumber identityCardNumber) {
        }
    
        @Override
        public boolean isValid(Object o, ConstraintValidatorContext constraintValidatorContext) {
            // 需要自己定义业务实现
            return IdCardValidatorUtils.isValidate18Idcard(o.toString());
        }
    }
    
    • 使用自定义注解
     @NotBlank(message = "身份证号不能为空")
     @IdentityCardNumber(message = "身份证信息有误,请核对后提交")
     private String clientCardNo;
    

    使用groups的校验

    • UserDTO在更新时候要校验userId,在保存的时候不需要校验userId,在两种情况下都要校验username,那就用上groups了
    • 定义Create, Update
    
    import javax.validation.groups.Default;
    
    public interface Create extends Default {
    }
    
    import javax.validation.groups.Default;
    
    public interface Update extends Default{
    }
    
    • 在需要使用的地方添加更新操作, 这里表示Upate时会校验参数
    @PostMapping("/update/groups")
    public RspDTO update(@RequestBody @Validated(Update.class) UserDTO userDTO) {
        userService.updateById(userDTO);
        return RspDTO.success();
    }
    
    @NotNull(message = "用户id不能为空", groups = Update.class)
    private Long userId;
    

    参考文章

    相关文章

      网友评论

        本文标题:参数校验优雅写法

        本文链接:https://www.haomeiwen.com/subject/qtzlvhtx.html