SpringBoot使用@Valid或者@Validated时自定义校验的场景分析

 更新时间:2025年12月30日 17:16:35   作者:乐韵天城  
文章介绍了在Java开发中,如何处理需要根据多个字段进行校验的自定义场景,通过创建自定义注解和实现相应的约束类,可以在DTO类中对这些字段进行复杂校验,最后,通过全局异常处理机制,可以统一处理校验失败的情况,本文给大家介绍的非常详细,感兴趣的朋友一起看看吧

一、自定义校验场景

平常开发项目想要校验参数是否合法一般会在类的字段上添加一些校验注解比如@NotEmpty、@Size、@Pattern等等,但这种是针对单个字段的校验,当我们有一些比较灵活的场景,比如根据多个字段进行判断应该如何做呢。

二、添加自定义注解

场景:假设我们有一个注册接口,有两个字段分别是注册类型(手机注册、邮箱注册)、联系方式,当用户以手机号注册时我们需要校验手机号是否合法,当用户以邮箱注册时我们需要校验邮箱是否合法。

自定义注解

package com.promote.demo.util;
import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
@Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE})
@Retention(RUNTIME)
@Documented
@Constraint(validatedBy = {CustomValidator.class})
public @interface Custom {
    String message() default "";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}

自定义注解的约束实现类

package com.promote.demo.util;
import cn.hutool.core.lang.PatternPool;
import com.promote.demo.model.RegisterModel;
import org.apache.commons.lang3.StringUtils;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
public class CustomValidator implements ConstraintValidator<Custom, RegisterModel> {
    @Override
    public boolean isValid(RegisterModel value, ConstraintValidatorContext context) {
        context.disableDefaultConstraintViolation();
        String type = value.getType();
        int constraints = 0;
        if (StringUtils.isNotBlank(value.getContact())) {
            //是否手机号注册
            if ("1".equals(type) && !PatternPool.MOBILE.matcher(value.getContact()).matches()) {
                context.buildConstraintViolationWithTemplate("手机号格式不正确").addConstraintViolation();
                constraints++;
            }
            //是否邮件注册
            if ("2".equals(type) && !PatternPool.EMAIL.matcher(value.getContact()).matches()) {
                context.buildConstraintViolationWithTemplate("邮箱格式不正确").addConstraintViolation();
                constraints++;
            }
        }
        return constraints <= 0;
    }
}

注册接口的DTO类

package com.promote.demo.model;
import com.promote.demo.util.Custom;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import java.io.Serializable;
@Data
@Custom
public class RegisterModel implements Serializable {
    @ApiModelProperty("注册类型")
    @NotBlank(message = "注册类型不能为空")
    private String type;
    @ApiModelProperty("联系方式")
    @NotBlank(message = "联系方式不能为空")
    private String contact;
}

全局异常

package com.promote.demo.controller;
import com.promote.demo.model.BaseResponse;
import org.springframework.http.HttpStatus;
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 java.util.List;
import java.util.stream.Collectors;
@ControllerAdvice
public class GlobalExceptionHandler {
    /**
     * 拦截参数不合法异常,自定义输出结果
     */
    @ExceptionHandler(BindException.class)
    @ResponseBody
    public BaseResponse<String> bindException (Exception ex) {
        BindException bindException = (BindException) ex;
        List<ObjectError> errors = bindException.getAllErrors();
        String msg = errors.stream().map(ObjectError::getDefaultMessage).collect(Collectors.joining(","));
        BaseResponse<String> baseResponse = new BaseResponse<>();
        baseResponse.setMsg(msg);
        baseResponse.setCode(HttpStatus.BAD_REQUEST.value());
        baseResponse.setSuccess(false);
        return baseResponse;
    }
}

三、运行效果

到此这篇关于SpringBoot使用@Valid或者@Validated时自定义校验场景分析的文章就介绍到这了,更多相关SpringBoot @Valid @Validated自定义校验内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 详解Java 本地接口 JNI 使用方法

    详解Java 本地接口 JNI 使用方法

    这篇文章主要介绍了详解Java 本地接口 JNI 使用方法的相关资料,希望通过本文大家能彻底使用JNI编程,需要的朋友可以参考下
    2017-09-09
  • RestTemplate().postForEntity的参数使用及说明

    RestTemplate().postForEntity的参数使用及说明

    `RestTemplate().postForEntity()`是SpringFramework中用于发送HTTP POST请求并获取响应的方法,该方法接受目标URL、请求体、期望的响应类型以及可选的变量参数,并返回一个包含HTTP响应信息的`ResponseEntity`对象
    2025-12-12
  • MybatisX-Generator不生成domain文件夹的问题及解决

    MybatisX-Generator不生成domain文件夹的问题及解决

    在使用MybatisX-Generator生成数据库表实体时,如果发现没有生成domain文件夹以及User.java文件,是因为MybatisX版本更新,最新版需要在options里额外勾选model才能生成domain,勾选model并点击finish后,成功生成domain文件夹及User.java文件
    2025-01-01
  • Java中日期与时间的处理及工具类封装详解

    Java中日期与时间的处理及工具类封装详解

    在项目开发中免不了有对日期时间的处理,但Java中关于日期时间的类太多了,本文就来介绍一下各种类的使用及我们项目中应该怎么选择吧
    2023-07-07
  • SpringBoot中实现订单30分钟自动取消的项目实践

    SpringBoot中实现订单30分钟自动取消的项目实践

    现在电子商务平台上订单创建成功,等待支付,一般会给30分钟的时间,本文主要介绍了SpringBoot中实现订单30分钟自动取消的项目实践,具有一定的参考价值,感兴趣的可以了解一下
    2023-10-10
  • Java多线程之CAS机制详解

    Java多线程之CAS机制详解

    这篇文章主要介绍了Java多线程之CAS机制详解,CAS指的是Compare-And-Swap(比较与交换),它是一种多线程同步的技术,常用于实现无锁算法,从而提高多线程程序的性能和扩展性,需要的朋友可以参考下
    2023-07-07
  • Java 实现判定顺序表中是否包含某个元素(思路详解)

    Java 实现判定顺序表中是否包含某个元素(思路详解)

    这篇文章主要介绍了Java 实现判定顺序表中是否包含某个元素,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-06-06
  • java中"==" 与equals方法的使用

    java中"==" 与equals方法的使用

    本篇文章介绍了,在java中"==" 与equals方法的使用。需要的朋友参考下
    2013-04-04
  • SpringBoot接收参数所有方式总结

    SpringBoot接收参数所有方式总结

    这篇文章主要介绍了SpringBoot接收参数所有方式总结,文中通过代码示例和图文结合的方式给大家介绍的非常详细,对大家的学习或工作有一定的帮助,需要的朋友可以参考下
    2024-07-07
  • MyBatis Log Free插件IDE下载与使用方式

    MyBatis Log Free插件IDE下载与使用方式

    这篇文章主要介绍了MyBatis Log Free插件IDE下载与使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-07-07

最新评论