关于Validation框架:(官方简介)
在任何时候,当你要处理一个应用程序的业务逻辑,数据校验是你必须要考虑和面对的事情。应用程序必须通过某种手段来确保输入进来的数据从语义上来讲是正确的。在通常的情况下,应用程序是分层的,不同的层由不同的开发人员来完成。很多时候同样的数据验证逻辑会出现在不同的层,这样就会导致代码冗余和一些管理的问题,比如说语义的一致性等。为了避免这样的情况发生,最好是将验证逻辑与相应的域模型进行绑定。
Bean Validation 为 JavaBean 验证定义了相应的元数据模型和 API。缺省的元数据是 Java Annotations,通过使用 XML 可以对原有的元数据信息进行覆盖和扩展。在应用程序中,通过使用 Bean Validation 或是你自己定义的 constraint,例如 @NotNull, @Max, @ZipCode, 就可以确保数据模型(JavaBean)的正确性。constraint 可以附加到字段,getter 方法,类或者接口上面。对于一些特定的需求,用户可以很容易的开发定制化的 constraint。Bean Validation 是一个运行时的数据验证框架,在验证之后验证的错误信息会被马上返回。

Bean Validation中的约束

表1. Bean验证中内置的约束

约束 详细信息
@Null 被注释的元素必须为null
@NotNull 被注释的元素必须不为null
@AssertTrue 被注释的元素必须为true
@AssertFalse 被注释的元素必须为false
@Min(value) 被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@Max(value) 被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@DecimalMin(value) 被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@DecimalMax(value) 被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@Size(max, min) 被注释的元素的大小必须在指定的范围内
@Digits (integer, fraction) 被注释的元素必须是一个数字,其值必须在可接受的范围内
@Past 被注释的元素必须是一个过去的日期
@Future 被注释的元素必须是一个将来的日期
@Pattern(value) 被注释的元素必须符合指定的正则表达式

表2. Hibernate Validator附加的约束

约束 详细信息
@Email 被注释的元素必须是电子邮箱地址
@Length 被注释的字符串的大小必须在指定的范围内
@NotEmpty 被注释的字符串的必须非空
@Range 被注释的元素必须在合适的范围内

一个 constraint 通常由 annotation 和相应的 constraint validator 组成,它们是一对多的关系。也就是说可以有多个 constraint validator 对应一个 annotation。在运行时,Bean Validation 框架本身会根据被注释元素的类型来选择合适的 constraint validator 对数据进行验证。

关于自定义校验器可以看下面两个链接:

在有时候我们需要对一些字段进行特殊校验比如 Phone 进行校验下面查看代码:

    <!--validation校验-->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-validation</artifactId>
    </dependency>

需要校验的 bean:

import com.demo.miaosha.validate.IsMobile;
import lombok.Data;
import org.hibernate.validator.constraints.Length;
import javax.validation.constraints.NotNull;
 
@Data //此注解是lombox插件,用于生产set和get以及toString等方法
public class LoginVo {
    @NotNull //不能为空
    @IsMobile //自定义注解校验是否满足手机号格式
    private String mobile;
 
    @NotNull //不能为空
    @Length(min = 32) //指定长度
    private String password;
}

自定义校验注解:

package com.demo.miaosha.validate;
 
import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.*;
import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
 
@Target({TYPE, METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER })// 约束注解应用的目标元素类型(TYPE   ,METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER等)
@Retention(RUNTIME)// 约束注解应用的时机
@Documented
@Constraint(validatedBy = { IsMobileValidator.class})// 与约束注解关联的验证器
public @interface IsMobile {
 
    boolean required() default true;//是否校验
 
    String message() default "手机号码错误"; // 约束注解验证时的输出消息
 
    Class<?>[] groups() default { };// 约束注解在验证时所属的组别
 
    Class<? extends Payload>[] payload() default { };// 约束注解的有效负载
}

校验器实现类:

import com.demo.miaosha.utils.ValidatorUtil;
import org.thymeleaf.util.StringUtils;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
 
public class IsMobileValidator implements ConstraintValidator<IsMobile,String> {
 
    private boolean required = false;
 
    //初始化方法
    @Override
    public void initialize(IsMobile constraintAnnotation) {
        required = constraintAnnotation.required();
    }
 
    //校验方法
    @Override
    public boolean isValid(String value, ConstraintValidatorContext context) {
        if (required == false) {
            return ValidatorUtil.isMobile(value);
        }else {
            if (StringUtils.isEmpty(value)) {
                return true;
            }
            return ValidatorUtil.isMobile(value);
        }
    }
}

校验器的 Util:

import org.thymeleaf.util.StringUtils;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
 
/**
 * 手机号格式校验
 */
public class ValidatorUtil {
 
    //手机号格式表达式
    private static final Pattern mobile_pattern = Pattern.compile("1\\d{10}");
 
    /**
     * 校验src是否为指定的手机号格式
     * @param src 需要校验的手机号
     * @return 是指定的手机号返回true,否则false
     */
    public static boolean isMobile(String src){
        if (StringUtils.isEmpty(src)){
            return false;
        }
        Matcher m = mobile_pattern.matcher(src);
        return m.matches();
    }
}

需要校验的 LoginVo 参数:使用 @Valid 注解校验 LoginVo 参数

    /**
     * 登录
     * @param vo 前端返回过来用户账号和密码
     * @return 登录成功的信息or失败信息
     */
    @RequestMapping(path="/do_login",method=RequestMethod.POST)
    @ResponseBody
    public Result do_login(@Valid LoginVo vo){
        log.info(vo.toString());
        String mobile = vo.getMobile();
        String password = vo.getPassword();
        ResultEnum resultEnum = miaoshaUserService.login(mobile,password);
        if (resultEnum.getCode() == 0){
            return Result.SUCCESS(resultEnum);
        }else {
            return Result.ERROR(resultEnum);
        }
    }

对校验异常捕获代码:

import com.demo.miaosha.common.ResultEnum;
import com.demo.miaosha.result.Result;
import lombok.extern.java.Log;
import org.springframework.validation.BindException;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
 
@ControllerAdvice//所谓加强Controller就是@ControllerAdvice注解,有这个注解的类中的方法的某些注解会应用到所有的Controller里,其中就包括@ExceptionHandler注解。
@ResponseBody//REST风格接口
@Log//lombox插件中的日志注解
public class GlobleExceptionHandler {
 
    @ExceptionHandler(value = Exception.class)//异常处理(@ControllerAdvice注解注释的controller层和此注解注释的方法,会对所有controller层抛出的异常进行统一处理)
    public Result<String> ExceptionHandler(HttpServletRequest request, Exception e){
        if (e instanceof BindException){
            BindException ex = (BindException)e;
            List<ObjectError> allErrors = ex.getAllErrors();//捕获的所有错误对象
            ObjectError error = allErrors.get(0);
            String defaultMessage = error.getDefaultMessage();//异常内容
            log.info(defaultMessage);//打印日志
            return Result.ERROR(ResultEnum.BIND_ERROR,defaultMessage);
        }else {
            return Result.ERROR(ResultEnum.ERROR);
        }
    }
}

注解完成异常处理LINK: https://www.jianshu.com/p/12e1a752974d
SpringMVC异常处理LINK: https://blog.csdn.net/qq_40325734/article/details/80793792

LINK:https://blog.csdn.net/ZZY1078689276/article/details/79064835
官网 LINK:https: //www.ibm.com/developerworks/cn/java/j-lo-jsr303/index.html

版权声明:本文为CSDN博主「qq_40325734」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_40325734/article/details/81782955