java spring validation 自动、手动校验

 更新时间:2024年09月13日 09:39:35   作者:木辰風  
HibernateValidator简化了Java开发中的参数校验过程,提供自动和手动两种校验方式,通过引入相关依赖并使用@Validated注解,可以实现自动校验,手动校验则需要使用ValidatorUtils类,此方法有效减少代码重复,提高开发效率

参数校验是一个常见的问题,比如字段非空,字段长度限制,邮箱格式、手机格式验证等等。

避免校验规则,写一大串步骤,繁琐重复。

Hibernate Validator为此提供了一套比较完善、便捷的验证实现方式。

一、自动校验

第一步,导入依赖

项目已经引入spring-boot-starter-web包里面有hibernate-validator包,不需要引用hibernate validator依赖。

项目还未引入spring-boot-starter-web包可以引入以下依赖:

<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>4.3.1.Final</version>
</dependency>

第二步,统一异常处理

ValidateExceptionController

import com.central.common.model.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import java.util.HashMap;
import java.util.Map;
/**
 * 统一异常处理
 */
@Slf4j
@RestControllerAdvice
@Order(Ordered.HIGHEST_PRECEDENCE)
public class ValidateExceptionController {
    //如果能精确匹配到该异常就会执行这个方法,后续执行下面的方法
    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    public Result handelValidateException(MethodArgumentNotValidException e) {
        log.error("数据校验出现问题:{},异常类型:{}", e.getMessage(), e.getClass());
        Map<String, String> map = new HashMap<>();
        //1.获取校验错误结果
        BindingResult result = e.getBindingResult();
        result.getFieldErrors().forEach(fieldError -> {
            //获取每个错误的属性名字
            String field = fieldError.getField();
            //获取每个错误提示信息
            String defaultMessage = fieldError.getDefaultMessage();
            map.put(field, defaultMessage);
        });
        return Result.failed(map, "数据校验错误");
    }
}

第三步,定义接口接收实体DTO

定义校验规则,可以参考

关于Java Validation (验证注解) 见文末补充介绍。

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.io.Serializable;
import java.util.List;
@Data
@ApiModel("售后申请接口-接收实体DTO")
public class AfterServiceApplyDTO implements Serializable {
    @NotBlank(message = "订单编号不为空")
    @ApiModelProperty(value = "订单编号", required = true)
    private String grandsonOrderCode;
    @NotNull(message = "申请售后类型不为空")
    @ApiModelProperty(value = "申请售后类型: 10:退货 20:换货 30:维修", required = true)
    private Integer customerExpect;
    @NotBlank(message = "产品问题描述不为空")
    @ApiModelProperty(value = "产品问题描述", required = true)
    private String questionDesc;
    @ApiModelProperty("问题描述图片链接地址,多个图片以“,”分隔")
    private String questionPic;
    @Valid
    @NotNull(message = "客户信息实体不为空")
    @ApiModelProperty("客户信息实体")
    private AfterSaleCustomerDTO asCustomerDto;
    @Valid
    @Size(min = 1, max = 1, message = "只能申请1个商品")
    @NotNull(message = "申请单明细列表不为空")
    @ApiModelProperty("申请单明细列表")
    private List<AfterSaleDetailDTO> asDetailDtos;
}

第四步,在Contoller接口中增加参数注解@Validated

表示只校验当前参数

@Api(tags = "【售后】订单售后API接口")
@RestController
public class AfterServiceApiController {
    /**
     * 售后申请接口
     * @param afterServiceApplyDTO 售后申请参数
     * @return 操作结果
     */
    @ApiOperation("售后申请接口")
    @PostMapping("/afterService/api/apply")
    public Result apply(@Validated @RequestBody AfterServiceApplyDTO afterServiceApplyDTO) {
        // todo
        return null;
    }
}

第五步,测试结果

Postman发送错误数据触发验证测试

二、手动校验

第一步,校验工具类

ValidatorUtils

import com.central.business.afterService.dto.AfterServiceApplyDTO;
import com.central.common.model.Result;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
 * 校验工具类
 */
public class ValidatorUtils {
    private static final Validator validator;
    // 第一种方式创建Validator
    static {
        // 普通模式(默认是这个模式)
        // 普通模式(会校验完所有的属性,然后返回所有的验证失败信息)
        validator = Validation.buildDefaultValidatorFactory().getValidator();
    }
    //第二种方式创建Validator
//    static {
//        // 1.普通模式(默认是这个模式)
//        // 普通模式(会校验完所有的属性,然后返回所有的验证失败信息)
//        // .failFast(false)
//        // 或 .addProperty("hibernate.validator.fail_fast", "false")
//
//        // 2.快速失败返回模式
//        // 快速失败返回模式(只要有一个验证失败,则返回)
//        // .addProperty("hibernate.validator.fail_fast", "true")
//        // 或 .failFast(true)
//        ValidatorFactory validatorFactory = Validation.byProvider(HibernateValidator.class)
//                .configure()
//                .failFast(true)
                .addProperty("hibernate.validator.fail_fast", "true")
//                .buildValidatorFactory();
//        validator = validatorFactory.getValidator();
//    }
    /**
     * 校验对象,返回校验失败List信息
     *
     * @param object 对象
     * @param groups 组
     * @return 校验失败List信息
     */
    public static List<String> validateEntity(Object object, Class<?>... groups) {
        List<String> list = new ArrayList<>();
        Set<ConstraintViolation<Object>> validate = validator.validate(object, groups);
        for (ConstraintViolation<Object> violation : validate) {
            list.add(violation.getMessage());
        }
        return list;
    }
    /**
     * 校验对象,返回校验失败Map信息
     *
     * @param object 对象
     * @param groups 组
     * @return 校验失败Map信息,key为属性(字段名),value为校验失败信息
     */
    public static Map<String, String> validateEntityProperty(Object object, Class<?>... groups) {
        Map<String, String> map = new HashMap<>();
        Set<ConstraintViolation<Object>> validate = validator.validate(object, groups);
        for (ConstraintViolation<Object> violation : validate) {
            map.put(violation.getPropertyPath().toString(), violation.getMessage());
        }
        return map;
    }
    /**
     * 校验对象,返回校验失败Result信息
     *
     * @param object 对象
     * @param groups 组
     * @return 校验失败Result,校验失败返回错误信息,成功返回成功信息
     */
    public static Result<Map<String, String>> validateEntityResult(Object object, Class<?>... groups) {
        Map<String, String> map = new HashMap<>();
        Set<ConstraintViolation<Object>> validate = validator.validate(object, groups);
        for (ConstraintViolation<Object> violation : validate) {
            map.put(violation.getPropertyPath().toString(), violation.getMessage());
        }
        if (map.size() > 0) {
            return Result.failed(map, "数据校验错误!");
        }
        return Result.succeed("数据校验成功!");
    }
    public static void main(String[] args) {
        AfterServiceApplyDTO afterServiceApplyDTO = new AfterServiceApplyDTO();
        System.out.println(validateEntityResult(afterServiceApplyDTO));
    }
}

第二步,测试结果

Result(datas={questionDesc=产品问题描述不为空, grandsonOrderCode=供应链三级订单编号不为空, reason=售后原因不为空, asCustomerDto=客户信息实体不为空, asDetailDtos=申请单明细列表不为空, businessPlatformCode=业务商城售后申请单号不为空, customerExpect=申请售后类型不为空}, resp_code=1, resp_msg=数据校验错误!)

补充:Java Validation (验证注解)

验证注解验证的数据类型说明
@AssertFalseBoolean,boolean验证注解的元素值是false
@AssertTrueBoolean,boolean验证注解的元素值是true
@NotNull任意类型验证注解的元素值不是null
@Null任意类型验证注解的元素值是null
@Min(value=值)BigDecimal,BigInteger, byte,short, int, long,等任何Number或CharSequence(存储的是数字)子类型验证注解的元素值大于等于@Min指定的value值
@Max(value=值)和@Min要求一样验证注解的元素值小于等于@Max指定的value值
@DecimalMin(value=值)和@Min要求一样验证注解的元素值大于等于@ DecimalMin指定的value值
@DecimalMax(value=值)和@Min要求一样验证注解的元素值小于等于@ DecimalMax指定的value值
@Digits(integer=整数位数, fraction=小数位数)和@Min要求一样验证注解的元素值的整数位数和小数位数上限
@Size(min=下限, max=上限)字符串、Collection、Map、数组等验证注解的元素值的在min和max(包含)指定区间之内,如字符长度、集合大小
@Pastjava.util.Date,java.util.Calendar;Joda Time类库的日期类型验证注解的元素值(日期类型)比当前时间早
@Future与@Past要求一样验证注解的元素值(日期类型)比当前时间晚
@NotBlankCharSequence子类型验证注解的元素值不为空(不为null、去除首位空格后长度为0),不同于@NotEmpty,@NotBlank只应用于字符串且在比较时会去除字符串的首位空格
@Length(min=下限, max=上限)CharSequence子类型验证注解的元素值长度在min和max区间内
@NotEmptyCharSequence子类型、Collection、Map、数组验证注解的元素值不为null且不为空(字符串长度不为0、集合大小不为0)
@Range(min=最小值, max=最大值)BigDecimal,BigInteger,CharSequence, byte, short, int, long等原子类型和包装类型验证注解的元素值在最小值和最大值之间
@Email(regexp=正则表达式,flag=标志的模式)CharSequence子类型(如String)验证注解的元素值是Email,也可以通过regexp和flag指定自定义的email格式
@Pattern(regexp=正则表达式,flag=标志的模式)String,任何CharSequence的子类型验证注解的元素值与指定的正则表达式匹配
@Valid任何非原子类型指定递归验证关联的对象如用户对象中有个地址对象属性,如果想在验证用户对象时一起验证地址对象的话,在地址对象上加@Valid注解即可级联验证

到此这篇关于java spring validation 自动、手动校验的文章就介绍到这了,更多相关java spring validation校验内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • java面向对象设计原则之接口隔离原则示例详解

    java面向对象设计原则之接口隔离原则示例详解

    这篇文章主要为大家介绍了java面向对象设计原则之接口隔离原则的示例详解,有需要的朋友可以借鉴参考下希望能够有所帮助,祝大家多多进步早日升职加薪
    2021-10-10
  • java注解实现websocket服务的两种方式

    java注解实现websocket服务的两种方式

    Java WebSocket是一种基于TCP协议的双向全双工消息传输技术,它允许服务器和客户端之间实时通信,具有低延迟和高效率的特点,下面这篇文章主要给大家介绍了关于java注解实现websocket服务的两种方式,需要的朋友可以参考下
    2024-08-08
  • Spring @ComponentScan注解使用案例详细讲解

    Spring @ComponentScan注解使用案例详细讲解

    @ComponentScan注解的作用可以简述为:将项目中所有被@Component注解直接或者间接标记的类---->组装成BeanDefinition---->然后以key=beanName, value=BeanDefinition的形式存储,为后续生成bean对象做准备
    2023-03-03
  • java模拟http的Get/Post请求,并设置ip与port代理的方法

    java模拟http的Get/Post请求,并设置ip与port代理的方法

    下面小编就为大家带来一篇java模拟http的Get/Post请求,并设置ip与port代理的方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-02-02
  • EasyCode插件使用详解(推荐)

    EasyCode插件使用详解(推荐)

    EasyCode是idea的一个插件,这个插件功能很强大,今天通过本文给大家分享EasyCode插件使用详解,需要的朋友可以参考下
    2020-09-09
  • 详解Java程序读取properties配置文件的方法

    详解Java程序读取properties配置文件的方法

    这篇文章主要介绍了Java读取properties配置文件的方法讲解,properties可以被看作是Java世界的ini,Java中有Properties可以操作它,需要的朋友可以参考下
    2016-04-04
  • 通过Java添加Word文本框过程详解

    通过Java添加Word文本框过程详解

    这篇文章主要介绍了通过Java添加Word文本框过程详解,在Word中,文本框是指一种可移动、可调节大小的文字或图形容器。我们可以向文本框中添加文字、图片、表格等对象,下面,将通过Java编程来实现添加以上对象到Word文本框,需要的朋友可以参考下
    2019-07-07
  • Java利用Swagger2自动生成对外接口的文档

    Java利用Swagger2自动生成对外接口的文档

    这篇文章主要介绍了Java利用Swagger2自动生成对外接口的文档,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-06-06
  • Java Web Listener实现事件监听与处理

    Java Web Listener实现事件监听与处理

    Java Web开发中的Listener是一种事件机制,通过监听Web应用程序的事件,实现对事件的处理,从而实现更加灵活和高效的应用程序开发。Listener能够监听的事件包括应用程序启动和关闭、Session创建和销毁、请求和响应对象的创建和销毁等
    2023-04-04
  • Spring mvc AJAX技术实现原理解析

    Spring mvc AJAX技术实现原理解析

    这篇文章主要介绍了Spring mvc AJAX技术实现原理解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-03-03

最新评论