Spring Validation的使用

7 篇文章 0 订阅

说明

技术方案使用 Spring ValidationSpring Validation 就是对 Hibernate Validator 又一层封装,Hibernate Validator对Bean校验的 JSR-303规范做了实现并扩展。

结合自定义全局异常使用。

使用背景

在实际的业务开发中,例如一个表单的提交充斥大量的字段,通常前端会进行校验,但是出于安全性考虑,后端的校验也必不可少。

在常规的场景下,我们要对请求对象的所有属性做业务校验,这样的缺点是会在业务代码中充斥大量的if判断,使代码量变大并使业务代码变得异常臃肿,使用 Spring Validation能极大的优化类似问题,让业务和基础校验松耦合。

技术实现

目前分为两种实现:

1: 自定义校验工具类(手动校验)推荐

2:接口方法类型校验

Spring Boot引入jar
<dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-validation</artifactId>
</dependency>
自定义校验工具类
import com.haircut.mumu.common.exception.ApplicationException;
import org.springframework.util.CollectionUtils;

import javax.validation.ConstraintViolation;
import javax.validation.Valid;
import javax.validation.Validation;
import java.util.Set;

/**
 * @program: ValiUtil
 * @description: 校验工具类
 * @author: xiatl
 * @create: 2020-08-08 20:02
 **/
public class ValiUtil {

    /**
     * 校验对象
     * 返回一个错误
     *
     * @param t   对象
     * @param <T> t
     */
    public static <T> void validateBySingleError(@Valid T t, Class<?> clazz) {
        Set<ConstraintViolation<@Valid T>> validateSet = Validation.buildDefaultValidatorFactory()
                .getValidator().validate(t, clazz);
        if (!CollectionUtils.isEmpty(validateSet)) {
            for (ConstraintViolation<@Valid T> vali : validateSet) {
                throw new ApplicationException(vali.getMessage());
            }
        }
    }

    /**
     * 校验对象
     * 返回全部错误
     *
     * @param t   对象
     * @param <T> t
     */
    public static <T> void validateByAllError(@Valid T t, Class<?> clazz) {
        Set<ConstraintViolation<@Valid T>> validateSet = Validation.buildDefaultValidatorFactory()
                .getValidator().validate(t, clazz);
        if (!CollectionUtils.isEmpty(validateSet)) {
            String messages = validateSet.stream()
                    .map(ConstraintViolation::getMessage)
                    .reduce((m1, m2) -> m1 + "\n" + m2)
                    .orElse("参数输入有误!");
            throw new ApplicationException(messages);
        }
    }
}
开始使用

我们默认使用分组校验(groups)

image.png

  • ValiUtil工具类接收两个参数:1. 要校验的Bean(BO),2. 分组标记
  • BO中使用注解的形式进行校验,message为校验失败抛出的异常信息,groups为校验适用的分组。
  • BO中定义了分组。
  • 示例中的save接口校验传入了UserBO.Save.class,意味着BO中只有groups中标记了UserBO.Save.class才会参与校验
  • 示例中的update接口校验传入了UserBO.Update.class,意味着BO中只有groups中标记了UserBO.Update.class才会参与校验
嵌套校验

image.png

  • 通常校验存在嵌套问题,即校验对象中包含对象或集合需要校验,只需在校验对象属性上添加@Valid校验即可
接口方法类型校验

相对于自定义工具类自行校验的方式,该方式的校验仅支持控制器层,对于请求在 Controller层校验比较友好

嵌套校验在 自定义工具类中已有描述。

开始使用

创建一个校验异常全局处理类

import com.zyj.crm.core.response.ResponseDataUtil;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;

/**
 * @program: ValidFailExceptionHandle
 * @description: 校验失败异常处理
 * @author: xiatl
 * @create: 2021-07-12 13:57
 **/
@RestControllerAdvice
public class ValidFailExceptionHandle extends ResponseEntityExceptionHandler {

    @Override
    protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
        if (ex.getBindingResult().hasErrors()) {
            String msg = ex.getBindingResult().getAllErrors().get(0).getDefaultMessage();
            return new ResponseEntity<>(ResponseDataUtil.buildError(msg), headers, status);
        }
        return new ResponseEntity<>(ResponseDataUtil.buildError(ex.getMessage()), headers, status);
    }
}

控制器层直接对请求对象添加 @Validated注解,并设置分组。

image.png

常用基本Bean校验

常用的校验注解可通过源码查看获得

image.png

。。。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值