Spring Validation

1 正则表达式

元字符手册

在线测试正则表达式

1、普通字符:明确的关键字

主要包括文字字符,符号。符号指的是@ % _等字符,其他在正则表达式中有特殊含义的符号需要加转义字符\

例:匹配文本中的get

正则表达式:get

匹配文本:i often get up early.

2、字符集合:关键字的值范围

单个关键字的值范围,用一堆[]包裹。如[oe]表示匹配ae。为了简化范围可以使用-符号。如[a-d]等价[abcd],[a-dz]等价[abcdz]。若想排除范围,可以使用^符号,如[^a-d]等价为除了abcd以外的字符都可以。

例:匹配文本中的get或者got

正则表达式:g[oe]t

匹配文本:I often get up early.

​ I got up late today.

3、限定符:给前一个字符追加出现次数的范围

常见的限定符号为* + ?,若以上三个不能满足需求,可以使用一堆{}符号标注具体次数。

*表示出现0次或者多次。等价于{0,}

+表示出现1次或者多次。等价于{1,}

?表示出现0次或者1次。等价于{0,1}

例:匹配文本中的god或者gooood

正则表达式:go+d

匹配文本:gd … godgoooooooooood

4、定位符:标记匹配位置的元字符

定位符只有四个,^ $ \b \B

^表示字符串的开始

$表示字符串的结尾

\b表示单词边界,字符与空格间的位置

\B表示非单词边界

例:匹配电话号码

正则表达式:`1[0-9]{10}$

5、子表达式:内嵌的子正则表达式

子表达式为内嵌的正则,用一对()包裹。

6、省略符:为了简化正则表达式的元字符

为了简化正则表达式而存在的元字符,以\开头。如\d等效于[0-9]

7、修饰符:指定匹配策略

修饰符是指定匹配策略的,不是正则表达式的一部分。

常规修饰符有4个,i g m s

2 Spring Validatiton

step1、引入Spring Validation起步依赖

1
2
3
4
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
</dependency>

step2、在参数前加上@patter等注解 或者是在实体类中添加注解。

step3、在controller类上添加@Validated注解 或者是在参数前添加@Valid注解。

但是,若两个接口使用同一个实体类,但是校验项不同,如一个接口需要ID不为空,另一个接口不必如此,那么就会产生错误。分组校验应运而生。

在实体类中,我们可以定义分组。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
public class userDTO{
    @NotNull(groups = add.class)
    private Integer id;
    // 若没有指定分组,则默认为Default分组
    private String nickName;
    private String userName;
    // 分组可以继承,如add包含所有default的校验项。
    public interface add extends Default{ // 校验项为id,nickname,username
        
    }
    public interface update extends Default{ // 校验项为nickname,username
        
    }
}
1
2
3
4
5
6
7
8
public class UserController {
   public Result add(@Requestbody @Validated(UserDTO.Add.class) UserDTO userDTO) {
       
   }
   public Result update(@Requestbody @Validated(UserDTO.update.class) UserDTO userDTO) {
       
   }
}

如上所示,先定义分组,在接口需要校验时指定分组即可。

对于一些情况,已有的注解无法满足要求,因此还需要自定义参数校验

  1. 自定义注解State
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
@Target(ElementType.FIELD)
@Target(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = StateValidation.class) // 指定提供校验规则的类
public @interface State {
    // 校验失败后的提示信息
    String message() default "状态:已读或未读";
    // 指定分组
    Class[] groups() default {};
    // 获取State注解的附加信息
    Class<? extends Payload>[] payload() default {};
}
  1. 自定义校验数据的类StateValidation实现ConstraintValidator接口
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
public class StateValidation implements ConstraintValidator<State,String> { // 注解名,校验的数据类型
	@Override
    // value:要校验的数据
	public boolean isValid(String value, ConstraintValidatorContext context)if (value==nul){
        if(value == null) {
            return false;
        }
		if (value.equals("已读") || value.equas("未读")) {
            return true;
        }
		return false;
    }
}
  1. 在需要的地方使用自定义注解

3 拦截器

加上注解之后,发生错误产生的报错信息不符合restful风格。为此添加异常处理器。

1
2
3
4
5
6
7
8
9
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {
    @ExceptionHandler(Exception,class) 
    public Result<Void> exceptionHandler(Exception e) {
        log.error("异常:{}", e.printStackTrace())
        return Result.error(StringUtils.hasLength(e.getMessage()), e.getMessage(), "操作失败");
    }
 }
updatedupdated2024-03-092024-03-09