当业务需要参数校验的时候,可以直接在controller 写入校验逻辑
参数校验经验: 用户业务,前端页面校验、服务端参数 校验
管理后台:前端校验,服务端可以放开
javax.validation包提供了常见参数的校验注解,如果常见注解不能满足可以使用
@Pattern 注解 使用正则表达式校验

校验注解:
这是javax.validation包中的 主要包括上述的几个注解

注解 描述
@AssertFalse 被注释的元素必须为 false
@AssertTrue 同@AssertFalse
@DecimalMax 被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@DecimalMin
同DecimalMax
@Digits 被注释的元素是数字
@Future 将来的日期
@Max 被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@Min 被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@NotNull 不能是Null
@Null
元素是Null
@Past 被注释的元素必须是一个过去的日期
@Pattern 被注释的元素必须符合指定的正则表达式
@Szie 被注释的元素

mvc 接收参数的基本形式
1.1 @PathVariable
略:

1.2 @RequestParam
直接在@RequestParam 后添加校验注解
并在类上添加 @Validated 注解

@Validated
public class UserController extends AbstractController {

 @PostMapping("id_card/add")
    @ApiOperation(value = "用户身份证信息提交")
    Resp<Boolean> userAddInfo(@Pattern(regexp ="^[\\u4e00-\\u9fa5]{2,10}$",message = "请输入中文姓名") String username, @Pattern(regexp = "^[0-9]{18}$", message = "身份证号只支持数字,18位") @RequestParam("id_card") String id_card) {
        User user = new User();
        user.setId(userAccountService.userInfoByUuid(getCurrentUserUuid()).getId());
        user.setIdCard(id_card);
        user.setUsername(username);
        EntityUtil.prevModify(user);
        if (userAccountService.userIdCradInfoAdd(user)) {
            return Resp.success(Boolean.TRUE);
        }
        return Resp.customFail("419", "用户身份证信息添加失败");
    }
}

1.3@requestbody

如果业务逻辑复杂,参数较多情况下
使用@requestBody 接收参数,在实体中写入校验规则
Bean Validation为JavaBean提供了相应的API来给我们做参数的验证。通过Bean Validation比如@NotNull @Pattern等方法 可以方便的集成数据校验逻辑。

import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

import javax.validation.constraints.Pattern;

/**
 * @version :
 * @date :2019-08-14
 */
@Data
public class BankCardForm {
    @ApiModelProperty(value = "用户姓名", notes = "用户姓名中文")
    @Pattern(regexp = "^[\\u4e00-\\u9fa5]{2,10}$", message = "姓名只支持中文 2-10个汉字")
    private String username;

    @ApiModelProperty(value = "用户身份证号码", notes = "用户身份证号码")
    @Pattern(regexp = "^[0-9]{18}$", message = "身份证号只支持数字,18位")
    private String idCard;

    @ApiModelProperty(value = "开户行名称", notes = "开户行")
    @Pattern(regexp = "^[\\u4e00-\\u9fa5]{2,20}$", message = "开户行只支持中文 2-20个汉字")
    private String bankName;

    @ApiModelProperty(value = "银行卡号", notes = "银行卡号")
    @Pattern(regexp = "^[0-9]{15,20}$", message = "银行卡号只支持数字,15-20位")
    private String cardNo;
}

如果参数校验未通过
会抛出异常

javax.validation.ConstraintViolationException: null

接下来
我们在拦截器中统一处理异常 给前端接口

@RestControllerAdvice
@Slf4j
public class ExceptionHandlerAdvice {


    @ExceptionHandler(value = Exception.class)
    public Result defaultException(Exception ex) {
        //TODO 默认异常需要处理
        log.error("默认异常需要处理", ex);
        if (ex instanceof ResultCode) {
            return R.error(((ResultCode) ex).getCode(), ((ResultCode) ex).getMsg());
        }
        if (ex instanceof UnexpectedTypeException) {
            return R.error(451, ex.getMessage());
        }
        if(ex instanceof CrmException){
            CrmException crmException = (CrmException)ex;
            return R.error(crmException.getCode(), crmException.getMsg());
        }
        if (ex instanceof ConstraintViolationException) {
            return R.error(452, ex.getMessage());
        }
        return Result.error(SystemCodeEnum.SYSTEM_ERROR);
    }

自定义注解

自定义校验注解
定义@ListNotHasNull注解, 用于校验 List 集合中是否有null 元素

@Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
//此处指定了注解的实现类为ListNotHasNullValidatorImpl
@Constraint(validatedBy = ListNotHasNullValidatorImpl.class)
public @interface ListNotHasNull {

    /**
     * 添加value属性,可以作为校验时的条件,若不需要,可去掉此处定义
     */
    int value() default 0;

    String message() default "List集合中不能含有null元素";

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

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

    /**
     * 定义List,为了让Bean的一个属性上可以添加多套规则
     */
    @Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER})
    @Retention(RUNTIME)
    @Documented
    @interface List {
        ListNotHasNull[] value();
    }
}

注意:message、groups、payload属性都需要定义在参数校验注解中不能缺省

注解实现类
该类需要实现ConstraintValidator

import org.springframework.stereotype.Service;

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

public class ListNotHasNullValidatorImpl implements ConstraintValidator<ListNotHasNull, List> {

    private int value;

    @Override
    public void initialize(ListNotHasNull constraintAnnotation) {
        //传入value 值,可以在校验中使用
        this.value = constraintAnnotation.value();
    }

    public boolean isValid(List list, ConstraintValidatorContext constraintValidatorContext) {
        for (Object object : list) {
            if (object == null) {
                //如果List集合中含有Null元素,校验失败
                return false;
            }
        }
        return true;
    }
}

然后我们就能在之前的例子中使用该注解了:

@NotEmpty
@ListNotHasNull
private List<@Valid UserInfo> parents;

参考:

注解失效的情况

检查pom文件引用

<dependency>
			<groupId>javax.validation</groupId>
			<artifactId>validation-api</artifactId>
			<version>2.0.1.Final</version>
		</dependency>

<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>6.1.2.Final</version>
</dependency>
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>2.0.0-alpha1</version>
</dependency>

再检查idea 配置

参考资料:

参考资料:
https://www.jianshu.com/p/89a675b7c900