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面向对象程序设计:抽象类,接口用法实例分析

    Java面向对象程序设计:抽象类,接口用法实例分析

    这篇文章主要介绍了Java面向对象程序设计:抽象类,接口用法,结合实例形式分析了java抽象类与接口相关概念、原理、用法与操作注意事项,需要的朋友可以参考下
    2020-04-04
  • JavaWeb实现用户登录与注册功能

    JavaWeb实现用户登录与注册功能

    这篇文章主要为大家详细介绍了JavaWeb实现用户登录与注册功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-08-08
  • Java Stack与Queue详解

    Java Stack与Queue详解

    这篇文章主要介绍了Java Stack与Queue详解,文中有非常详细的代码示例,对正在学习Java的小伙伴们有很好地帮助,需要的朋友可以参考下
    2021-05-05
  • Java后端长时间无操作自动退出的实现方式

    Java后端长时间无操作自动退出的实现方式

    这篇文章主要介绍了Java后端长时间无操作自动退出的实现方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-01-01
  • Java实现HTML转PDF及合并PDF文件详细教程

    Java实现HTML转PDF及合并PDF文件详细教程

    之前在工作中遇到过一个需求,是将用户填写的申报,由固定模板的来生成pdf,后来想到先把内容生成html,然后再把html格式的内容转换成pdf,这篇文章主要介绍了Java实现HTML转PDF及合并PDF文件的相关资料,需要的朋友可以参考下
    2025-07-07
  • Java实战在线选课系统的实现流程

    Java实战在线选课系统的实现流程

    读万卷书不如行万里路,只学书上的理论是远远不够的,只有在实战中才能获得能力的提升,本篇文章手把手带你用java+SSM+jsp+mysql+maven实现一个在线选课系统,大家可以在过程中查缺补漏,提升水平
    2021-11-11
  • 聊聊drools session的不同

    聊聊drools session的不同

    在drools中存在2种session,一种是有状态的Session (Stateful Session),另外一种一种是无状态的Session (Stateless Session,本文通过实例代码给大家介绍drools session的不同,感兴趣的朋友一起看看吧
    2022-05-05
  • SpringBoot利用限速器RateLimiter实现单机限流的示例代码

    SpringBoot利用限速器RateLimiter实现单机限流的示例代码

    本文主要介绍了SpringBoot利用限速器RateLimiter实现单机限流的示例代码,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-01-01
  • Java Lombok简介、使用、工作原理、优缺点

    Java Lombok简介、使用、工作原理、优缺点

    这篇文章主要介绍了Java Lombok简介、使用、工作原理、优缺点的相关资料,帮助大家更好的理解和学习使用Java Lombok,感兴趣的朋友可以了解下
    2021-03-03
  • JAVA二叉树的基本操作

    JAVA二叉树的基本操作

    这篇文章主要介绍了JAVA二叉树的基本操作DEMO,想要详情了解的小伙伴请接着看下文吧
    2021-08-08

最新评论