springboot参数校验

我爱海鲸 2026-01-30 09:43:40 暂无标签

简介valid

其他的文章

公共模块:

http://www.haijin.xyz/article/930

之前的参数校验:

http://www.haijin.xyz/list/article/181

1、引入maven依赖:

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

2、相关配置:

/**
 * 通用异常处理参数校验相关异常
 *
 * @author system
 */
@Slf4j
@RestControllerAdvice(assignableTypes = TestController.class)  // 针对当前的接口进行校验拦截
@Order(1)
public class ValidationExceptionHandler {

    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public ResultData<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException e) {
        String errorMessage = Objects.requireNonNull(e.getBindingResult().getFieldError()).getDefaultMessage();
        return ResultData.builder()
                .code(ReturnCodeEnum.RC999.getCode())
                .message(errorMessage)
                .build();
    }

    @ExceptionHandler(ConstraintViolationException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public ResultData<Object> handleConstraintViolation(ConstraintViolationException e) {
        String errorMessage = e.getMessage();
        return ResultData.builder()
                .code(ReturnCodeEnum.RC999.getCode())
                .message(errorMessage)
                .build();
    }

    @ExceptionHandler(MissingServletRequestParameterException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public ResultData<Object> handleMissingServletRequestParameter(MissingServletRequestParameterException e) {
        String errorMessage = "参数不能为空:" + e.getParameterName();
        return ResultData.builder()
                .code(ReturnCodeEnum.RC999.getCode())
                .message(errorMessage)
                .build();
    }
}

3、TestController:

    @GetMapping("/test/list")
    @ResponseBody
    public ResultData<Object> queryVideoList(
            @RequestParam("type") @NotNull(message = "参数不能为空:type") Integer type) {

4、常用注解

注解 作用场景 示例
@NotBlank 字符串非空(非 null + 非空白) @NotBlank(message = "姓名不能为空")
@NotNull 任意类型非 null @NotNull(message = "年龄不能为空")
@NotEmpty 集合 / 数组非空(长度 > 0) @NotEmpty(message = "爱好不能为空")
@Email 邮箱格式校验 @Email(message = "邮箱格式错误")
@Min(value) 数字最小值 @Min(value = 18, message = "年龄最小18")
@Max(value) 数字最大值 @Max(value = 60, message = "年龄最大60")
@Pattern(regexp) 正则表达式校验 @Pattern(regexp = "^1[3-9]\\d{9}$", message = "手机号错误")
@Size(min, max) 字符串 / 集合长度范围 @Size(min = 6, max = 20, message = "密码长度6-20")

5、相关注解的校验

import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorContext;

/**
 * 手机号格式校验器
 * 
 * @author system
 */
public class PhoneFormatValidator implements ConstraintValidator<PhoneFormat, String> {

    private static final String PHONE_PATTERN = "^1[3-9]\\d{9}$";

    @Override
    public void initialize(PhoneFormat constraintAnnotation) {
    }

    @Override
    public boolean isValid(String phone, ConstraintValidatorContext context) {
        if (phone == null || phone.trim().isEmpty()) {
            return false;
        }

        if (phone.length() != 11) {
            return false;
        }

        return phone.matches(PHONE_PATTERN);
    }
}

注解

import jakarta.validation.Constraint;
import jakarta.validation.Payload;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 手机号格式校验注解
 * 11位号码
 * 
 * @author system
 */
@Documented
@Constraint(validatedBy = PhoneFormatValidator.class)
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface PhoneFormat {
    
    String message() default "手机号格式错误,应为11位号码";
    
    Class<?>[] groups() default {};
    
    Class<? extends Payload>[] payload() default {};
}
时间戳格式校验器
import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorContext;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;

/**
 * 时间戳格式校验器
 * 
 * @author system
 */
public class TimestampFormatValidator implements ConstraintValidator<TimestampFormat, String> {

    private static final String TIMESTAMP_PATTERN = "yyyyMMddHHmmss";
    private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern(TIMESTAMP_PATTERN);
    private static final int VALIDITY_MINUTES = 5;

    @Override
    public void initialize(TimestampFormat constraintAnnotation) {
    }

    @Override
    public boolean isValid(String timestamp, ConstraintValidatorContext context) {
        if (timestamp == null || timestamp.trim().isEmpty()) {
            return false;
        }

        if (timestamp.length() != 14) {
            return false;
        }

        if (!timestamp.matches("\\d{14}")) {
            return false;
        }

        try {
            LocalDateTime requestTime = LocalDateTime.parse(timestamp, FORMATTER);
            LocalDateTime now = LocalDateTime.now();
            
            if (requestTime.isAfter(now)) {
                return false;
            }
            
            LocalDateTime expireTime = requestTime.plusMinutes(VALIDITY_MINUTES);
            if (now.isAfter(expireTime)) {
                return false;
            }

            return true;
        } catch (DateTimeParseException e) {
            return false;
        }
    }
}
时间戳格式校验注解
import jakarta.validation.Constraint;
import jakarta.validation.Payload;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 时间戳格式校验注解
 * 格式:yyyyMMddHHmmss(14位数字)
 * 有效期:5分钟
 * 
 * @author system
 */
@Documented
@Constraint(validatedBy = TimestampFormatValidator.class)
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface TimestampFormat {
    
    String message() default "时间戳格式错误或已过期,格式应为yyyyMMddHHmmss,有效期为5分钟";
    
    Class<?>[] groups() default {};
    
    Class<? extends Payload>[] payload() default {};
}

使用:

    /**
     * 请求时间,格式:yyyyMMddHHmmss
     */
    @NotBlank(message = "timestamp不能为空")
    @TimestampFormat
    private String timestamp;
    
    /**
     * 手机号,11位号码
     */
    @NotBlank(message = "phone不能为空")
    @PhoneFormat
    private String phone;

 

你好:我的2025