java---入参校验

793 阅读3分钟

1. 校验post json方式的参数

@Validated ===>>> @NotBlank(message = "name 不能为空")===>>> MethodArgumentNotValidException.class

2. 处理非json的方式参数,如校验前端/testA?name=123&type=112 类型参数

@Validated ===>>>@NotBlank(message = "name 不能为空")===>>> BindException.class

3. 处理1和2不能处理的参数校验,如校验前端 /testB?requestParam = encodeURIComponent(JSON.stringify(obj))类型参数

//实现关键代码
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import javax.validation.Validation;
import javax.validation.Validator;

Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
Set<ConstraintViolation<T>> result = validator.validate(object, groups);

  • 3.1 具体代码如下
// groups为接口类型,选传参数;若没传,表示走没有group的校验;若传入了group,只走对应的group的校验属性
public class BaseRest {
    Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
    protected <T> void validate(T object, Class<?>... groups){
	//校验不通过时返回的set集合,若result为空,表示校验通过。
        Set<ConstraintViolation<T>> result = validator.validate(object, groups);
        if(result.iterator().hasNext()){
            throw new ConstraintViolationException(result);
        }
    }
}
// 如下,只有validate(form) 只会校验name 属性,当StringUtils.equals("edit", form.getType()))成立时会校验id 属性
@GetMapping("/validate")
public void userValidate(String requestParam) {
    UserForm form = JSON.parseObject(requestParam, UserForm.class);
    validate(form);
    if (StringUtils.equals("edit", form.getType())) {
        validate(form, EditUserValidate.class);
    }
}
@Data
public class UserForm {
    @NotNull(message = "id不能为空", groups = { EditUserValidate.class })
    private Integer id;
    @NotBlank(message = "姓名不能为空")
    private String name;
    private List<String> roleIds;
    private String type;
}
public interface EditUserValidate {
}

4.三种方式的全局拦截,把错误消息提示给前端

@RestController
@ControllerAdvice
@Slf4j
public class GlobalExceptionHandler {

    //处理json的validated的异常
    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    public Result handle(MethodArgumentNotValidException e){
        log.info("进入错误处理中心---MethodArgumentNotValidException.class---e",e);
        String message = e.getBindingResult().getFieldError().getDefaultMessage();
        return new Result(-1, message, null);
    }

    //处理非json的validated的异常
    @ExceptionHandler(value = BindException.class)
    public Result handle(BindException e) {
        log.info("进入错误处理中心---BusinessException.class---e",e);
        String message = e.getBindingResult().getFieldError().getDefaultMessage();
        return new Result(-1, message, null);
    }

    //处理手动的validator的异常
    @ExceptionHandler(value = ConstraintViolationException.class)
    public Result handle(ConstraintViolationException e) {
        log.info("进入错误处理中心---ConstraintViolationException.class---e",e);
        String message = e.getMessage();
        return new Result(-1, message, null);
    }
}

5. 校验组

// 当2个以上接口(譬如编辑类接口和新增类接口)想公用1个入参接收对象时,又想校验规则不同,可以采用校验组。
// 校验组是1个接口类型

public interface Update {
}

public interface Submit {
}

// 使用方式
@RequestMapping("/update")
public void userUpdate(@RequestBody @Validated({Default.class, Update.class}) UserForm form) {
    
}


// 如下 id 和 name 都会依次校验。但是不会校验type
@Data
public class UserForm {
    
    @NotNull(message = "id不能为空", groups = { Update.class })
    private Integer id;

    @NotBlank(message = "name不能为空")
    private String name;

    private List<String> roleIds;

    @NotBlank(message = "name不能为空", groups = { Submit.class })
    private String type;
}

6. 校验对象里面的集合(默认不会去校验集合中的每个属性)

// 需要在集合上面加上 @Valid注解,UserDTO里面的id校验才会生效
@Data
public class UserForm {
    @Valid
    private List<UserDTO> users;
}


@Data
public class UserDTO {
    @NotBlank(message = "id不能为空")
    private String id;
}

7.自定义校验器

  • 7.1 先自定义校验注解
package com.my.demo.common.validation.constrints;

import com.my.demo.common.validation.validator.UmNoValidator;

import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.*;

@Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Constraint(validatedBy = UmNoValidator.class)
public @interface UmNo {

    String message() default "不是有效的um号";

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

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

    @Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @interface List{
        UmNo[] value();
    }
}
  • 7.2 自定义校验规则类(非集合校验)
package com.my.demo.common.validation.validator;

import com.my.demo.common.validation.constrints.UmNo;
import org.apache.commons.lang.StringUtils;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;

public class UmNoValidator implements ConstraintValidator<UmNo, String> {

    @Override
    public void initialize(UmNo constraintAnnotation) {

    }
    
    // 返回值 true:表示校验通过,false:校验不通过
    @Override
    public boolean isValid(String value, ConstraintValidatorContext context) {
        if(StringUtils.isEmpty(value)){
            return true;
        }
        return value.matches("[0-9A-Za-z]{1,100}");
    }
}
  • 7.3 自定义校验规则类(集合校验)
package com.my.demo.common.validation.validator;

import com.my.demo.common.validation.constrints.UmNo;
import org.apache.commons.collections4.CollectionUtils;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.util.List;

public class UmNoListValidator implements ConstraintValidator<UmNo, List<String>> {

    @Override
    public void initialize(UmNo constraintAnnotation) {

    }

    @Override
    public boolean isValid(List<String> list, ConstraintValidatorContext context) {
        if(CollectionUtils.isEmpty(list)){
            return true;
        }
        return list.stream().allMatch(str->str.matches("[0-9A-Za-z]{1,100}"));
    }
}
  • 7.3 使用
package com.my.demo.model.form;

import com.my.demo.common.validation.constrints.UmNo;
import lombok.Data;

import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.Size;
import java.util.List;

@Data
public class UserForm {
    @UmNo(message = "不是有效的um号")
    private String um;

    @NotEmpty(message = "um列表不能为空")
    @UmNo(message = "不是有效的um号")
    @Size(max = 5, message = "最多{max}个面试官")
    private List<String> ums;
}