分享免费的编程资源和教程

网站首页 > 技术教程 正文

springboot中 Validation参数校验(常规/分组/自定义校验注解)

goqiw 2025-01-12 13:53:30 技术教程 3 ℃ 0 评论

1.pom坐标

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


2.常规注解

package com.wangguo.controller;

import com.wangguo.entity.validation.CustomizeInfoValidation;
import com.wangguo.entity.validation.InfoValidation;
import com.wangguo.entity.validation.InfoValidationGroup;
import com.wangguo.handler.BusinessException;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

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

/**
 *
 * @author wangguo17
 * @create 2024/12/13
 * @description
 */

@RestController
@RequestMapping("/validation")
public class ValidationController {


    /**
     * 常规校验
     *
     * @param validation
     * @return
     */
    @PostMapping("/info")
    public String validation(@RequestBody @Validated InfoValidation validation) {
        return "success";
    }


    /**
     * 自定义注解
     *
     * @param validation
     * @return
     */
    @PostMapping("/infoCustomize")
    public String customizeValidation(@RequestBody @Validated CustomizeInfoValidation validation) {
        return "success";
    }


    /**
     * 编码 手动进行校验
     *
     * @param validationGroup
     * @return
     */
    @PostMapping("/addInfoGroup")
    public String addInfoGroup(@RequestBody @Validated InfoValidationGroup validationGroup) {
        Set<ConstraintViolation<InfoValidationGroup>> validateSet = Validation.buildDefaultValidatorFactory()
                .getValidator()
                .validate(validationGroup, new Class[]{InfoValidationGroup.AddGroup.class});
        if (!CollectionUtils.isEmpty(validateSet)) {
            String messages = validateSet.stream()
                    .map(ConstraintViolation::getMessage)
                    .reduce((m1, m2) -> m1 + ", " + m2)
                    .orElse("");
            throw new BusinessException(messages);
        }
        return "success";
    }

    /**
     * 注解自动校验 @Validated({InfoValidationGroup.AddGroup.class}
     *
     * @param validationGroup
     * @return
     */
    @PostMapping("/addInfoGroupAuto")
    public String addInfoGroupAuto(@RequestBody @Validated({InfoValidationGroup.AddGroup.class}) InfoValidationGroup validationGroup) {
        return "success";
    }


    /**
     * 分组校验
     *
     * @param validationGroup
     * @return
     */
    @PostMapping("/updateInfoGroup")
    public String updateInfoGroup(@RequestBody @Validated({InfoValidationGroup.UpdateGroup.class}) InfoValidationGroup validationGroup) {
        return "success";
    }


}
package com.wangguo.entity.validation;

import lombok.Data;

import javax.validation.constraints.*;
import java.time.LocalDate;
import java.util.List;

/**
 * @create 2024/12/13
 * @description 1.@Validated 支持分组功能 2.@Valid  常规参数校验
 */

@Data
public class InfoValidation {

    /**
     * @NotEmpty 适用类型:String  值不能为Null,以及长度不能为0
     */
    @NotEmpty(message = "name不能为空")
    private String name;

    /**
     * @NotNull 所有引用类型 被该注解修饰的字段,值不能为空;
     */
    @NotNull(message = "price不能为空")
    private Integer price;

    /**
     * @NotBlank 适用类型:String  值不能为Null、空格,以及长度不能为0
     */
    @NotBlank(message = "address不能为空 '' null")
    private String address;

    /**
     * @Size 适用类型:String、Array、Collection、Map
     */
    @Size(min = 1, max = 10, message = "昵称长度空值在1-10位,用于字符长度")
    private String nickName;
    @Size(min = 1, max = 10, message = "至少填写1项爱好")
    private List<String> enjoys;

    /**
     * @Past 适用类型:Date、Calendar、Instant、LocalDateTime、LocalDate、LocalTime等时间类型  被该注解修饰的时间字段,其值必须在当前时间之前
     * @PastOrPresent 适用类型:Date、Calendar、Instant、LocalDateTime、LocalDate、LocalTime等时间类型  被该注解修饰的时间字段,其值必须在当前时间之前或当前
     */
    @Past(message = "上学时间必须早于当前时间")
    private LocalDate schoolTime;

    /**
     * @Future 适用类型:Date、Calendar、Instant、LocalDateTime、LocalDate、LocalTime等时间类型; 被该注解修饰的时间字段,其值必须在当前时间之后
     * @FutureOrPresent 适用类型:Date、Calendar、Instant、LocalDateTime、LocalDate、LocalTime等时间类型; 被该注解修饰的时间字段,其值必须在当前时间之后或当前
     */
    @Future(message = "活动结束时间必须大于当前时间")
    private LocalDate activityEndTime;

    /**
     * @Email 验证注解的元素值是一个有效的电子邮件地址
     */
    @Email(message = "邮箱格式不正确!")
    @NotBlank(message = "邮箱不能为空!")
    private String email;

    /**
     * @Pattern 正则表达式来进行数据校验
     */
    @NotBlank(message = "手机号不能为空!")
    @Pattern(regexp = "^1[3-9]\\d{9}#34;, message = "手机号码格式不正确")
    private String tel;


}

3.分组注解

package com.wangguo.entity.validation;

import com.wangguo.entity.validation.anno.Adress;
import lombok.Data;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;

/**
 *
 * @author wangguo17
 * @create 2024/12/16
 * @description
 */

@Data
public class InfoValidationGroup {

    public interface AddGroup {
    }

    public interface UpdateGroup {
    }


    @NotBlank(message = "ID不能为空", groups = {UpdateGroup.class})
    private String id;

    /**
     * @NotEmpty 适用类型:String  值不能为Null,以及长度不能为0
     */
    @NotEmpty(message = "name不能为空", groups = {AddGroup.class})
    private String name;

    /**
     * @NotNull 所有引用类型 被该注解修饰的字段,值不能为空;
     */
    @NotNull(message = "price不能为空")
    private Integer price;


}

4.自定义注解

package com.wangguo.entity.validation.anno;

import com.wangguo.entity.validation.validator.AdressValidator;

import javax.validation.Constraint;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * @author wangguo17
 * @create 2024/12/16
 * @description
 */
// @AdressValidator 注解校验类的具体实现类
@Constraint(validatedBy = AdressValidator.class)
// 表示注解可以应用于字段和方法上
@Target({ElementType.FIELD, ElementType.METHOD})
// 表示注解在运行时保留,因此可以通过反射机制读取。强调,可以通过反射获取,
@Retention(RetentionPolicy.RUNTIME)
public @interface Adress {

    String message() default "地址必须是中文";

    Class<?>[] groups() default {};


    Class<?>[] payload() default {};
}
package com.wangguo.entity.validation.validator;

import com.wangguo.entity.validation.anno.Adress;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author wangguo17
 * @create 2024/12/16
 * @description 自定义注解实现类
 */

public class AdressValidator implements ConstraintValidator<Adress, String> {

    /**
     * 初始化  不做变化
     *
     * @param constraintAnnotation
     */
    @Override
    public void initialize(Adress constraintAnnotation) {
        ConstraintValidator.super.initialize(constraintAnnotation);
    }

    /**
     * 校验的实现逻辑
     *
     * @param s                          校验传递的值
     * @param constraintValidatorContext 校验上下文
     * @return false  就是校验通过  true 不通过  默认false
     */
    @Override
    public boolean isValid(String s, ConstraintValidatorContext constraintValidatorContext) {
        String regex = "[\\u4e00-\\u9fff]+";
        Matcher matcher = Pattern.compile(regex).matcher(s);
        return matcher.find();
    }
}
package com.wangguo.entity.validation;

import com.wangguo.entity.validation.anno.Adress;
import lombok.Data;

import javax.validation.constraints.*;

/**
 * @create 2024/12/13
 * @description 自定义注解 @Adress
 */

@Data
public class CustomizeInfoValidation {

    /**
     * @Adress 自定义校验注解 实现类AdressValidator
     */
    @Adress(message = "地址需要是中文")
    private String adress;

    /**
     * @NotEmpty 适用类型:String  值不能为Null,以及长度不能为0
     */
    @NotEmpty(message = "name不能为空")
    private String name;




}

5.全局异常拦截

package com.wangguo.handler;

import com.wangguo.resp.Result;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.validation.BindException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

/**
 * @author wangguo17
 * @create 2024/12/13
 * @description 全局异常处理器
 */

@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {

    /**
     * 自定义异常捕获器
     */
    @SuppressWarnings("rawtypes")
    @ExceptionHandler(BusinessException.class)
    public Result handleBusinessException(BusinessException e) {
        log.error(e.getMessage(), e);
        return Result.getErrorResult(e.getMessage());
    }


    /**
     * 全局参数校验异常处理器
     */
    @ExceptionHandler(BindException.class)
    public Result<?> handleBindException(BindException e) {
        log.error(e.getMessage(), e);
        String fieldError = e.getBindingResult()
                .getFieldError().getDefaultMessage();
        if (StringUtils.isNotBlank(fieldError)) {
            return Result.getErrorResult(fieldError);
        } else {
            return Result.getErrorResult(e.getMessage());
        }
    }
}

package com.wangguo.handler;

import lombok.Data;

/**
 *
 * @author wangguo17
 * @create 2024/12/13
 * @description
 */

@Data
public class BusinessException extends RuntimeException {

    private String msg;

    @Override
    public String getMessage() {
        return msg;
    }

    public BusinessException(String msg) {
        super(msg);
        this.msg = msg;
    }
}

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表