spring请求参数校验

大纲:

  1. 参数校验
  2. ConstraintValidator自定义验证

一、参数验证

@NotNull 就是参数必传
javax.validation.constraints下面有许多注解不一一赘述、字面意思也很清晰。
import lombok.Data;

import javax.validation.constraints.NotNull;

/**
 * Created by lby on 2019/6/21.
 */
@Data
public class Person {
    private String name;
    @NotNull
    private String age;

}

1.1注解验证

@Validated注解加到需要验证的请求对象上

    @RequestMapping("/hello")
    public String hello(@RequestBody @Validated Person person, BindingResult result){
        if(result.hasErrors()){
            List<FieldError> fieldErrors = result.getFieldErrors();
            fieldErrors.forEach(item->{
                System.out.println(item.getDefaultMessage());
            });

        }
        return person.getName()+person.getAge();
    }

未通过的验证信息会存放到BindingResult对象中。

1.2获取SmartValidator进行验证

SmartValidator在spring初始化完成的时候已经在ioc容器里了

    @Autowired
    SmartValidator validator;

    @RequestMapping("/hello")
    public String hello(@RequestBody Person person){
        BindingResult result = new BeanPropertyBindingResult(person,person.getClass().getSimpleName());
        validator.validate(person,result);
            if(result.hasErrors()){
                result.getAllErrors().forEach(item->{
                    System.out.println(item.getDefaultMessage());
                });
            }
        return person.getName()+person.getAge();
    }

1.3分组校验

定义分组:定义两个内部接口A和B就是2个组别。

校验分组:修改一下Person对象上的校验注解加上groups,groups里面的内容就是需要校验的组。

例:下例中需中如果校验A组则name、age都要NotNull,如果校验B则只要nameNotNull

@Data
public class Person {
    @NotNull(groups = {A.class,B.class})
    private String name;
    @NotNull(groups = {A.class})
    private String age;

    public interface A{}
    public interface B{}
}

注解校验:

@RequestBody @Validated(value = { Person.A.class}) Person person,

与之前的区别就是在@Validated中填入了需要校验的组(参数为一个数组),上例中校验A组。

smartValidatior校验:

validator.validate(person,result,Person.A.class);

与之前的区别就是validate方法传入了第三个参数来标识需要验证的组(参数为一个数组)上例中校验A组。

二、ConstraintValidator自定义验证

定义一个验证类实现ConstraintValidator接口

public class EnumValidImpl implements ConstraintValidator<EnumValid,String> {

    private String[] values;
    private String message;

    @Override
    public void initialize(EnumValid constraintAnnotation) {
        //拿待验证字段注解上的信息
        values = constraintAnnotation.value();
        message = constraintAnnotation.message();
    }

    @Override
    public boolean isValid(String value, ConstraintValidatorContext context) {
        //value就是需要校验的值
        //验证
        boolean exist = false;
        for (String evalue : values) {
            if(value.equals(evalue)){
                exist = true;
                break;
            }
        }
        //报错信息
        if (StringUtils.isBlank(message)) {
            StringBuilder sb = new StringBuilder();
            for (String s : values) {
                sb.append(s).append(";");
            }
            String msg  = sb.toString();
            msg = msg.substring(0,msg.length()-1);
            //替换原来的报错信息
            context.disableDefaultConstraintViolation();
            context.buildConstraintViolationWithTemplate("value must in:"+msg).addConstraintViolation();
        }
        return exist;
    }
}

自定义注解用于待校验的属性上

@Constraint(validatedBy = {EnumValidImpl.class })//指定这个校验注解的实现类
@Target({ ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface EnumValid {

    String[] value();

    String message() default "默认报错消息";

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

    Class<? extends Payload>[] payload() default {};

}

用法:

@Data
public class Person {
    @EnumValid({"aa","bb"})
    private String name;
    private String age;

}

我自定义的注解意思:name只能为aa,bb

原文地址:https://www.cnblogs.com/liuboyuan/p/11093383.html