自定义合法化参数校验注解

说明:

该方法多用于对外API,防止外部接口传入系统不识别的固定值或枚举值,导致系统ERR或造成垃圾数据

一. 引入 Maven 依赖

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

<dependency>
    <groupId>org.hibernate.validator</groupId>
    <artifactId>hibernate-validator</artifactId>
</dependency>

二. 创建自定义校验注解

import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

@Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER})
@Retention(RUNTIME)
@Documented
@Constraint(validatedBy = {EnumValueValidator.class})
public @interface EnumValue {
    //默认错误消息
    String message() default "参数不合法";

    //字符串类型
    String[] strValues() default {};

    int[] intValues() default {};

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

三. 自定义校验注解实现类

为灵活使用,该方法跳过了传入参数为空时的校验,参数为空时在接口中进行单独校验

public class EnumValueValidator implements ConstraintValidator<EnumValue, Object> {
    private String[] strValues;
    private int[] intValues;
    private String message;

    @Override
    public void initialize(EnumValue constraintAnnotation) {
        strValues = constraintAnnotation.strValues();
        intValues = constraintAnnotation.intValues();
        message = constraintAnnotation.message();
    }

    @Override
    public boolean isValid(Object value, ConstraintValidatorContext context ) {
        // 为空时跳过校验
        if (value == null || value.equals("")){
            return true;
        }

        if(value instanceof String) {
            for (String s:strValues) {
                if(s.equals(value)){
                    return true;
                }
            }
        }else if(value instanceof Integer){
            for (int s:intValues) {
                if(s == (Integer) value){
                    return true;
                }
            }
        }
        throw new ClientException(HttpStatusEnums.CLI_ERR_API_PARAM_CHECK.getCode(),
                String.format(HttpStatusEnums.CLI_ERR_API_PARAM_CHECK.getMsg(), message));
    }
}

四. 实体类为参数增加校验规则

@Data
@AllArgsConstructor
@NoArgsConstructor
public class SanheTaskEntity extends PageEntity implements Serializable {
    private static final long serialVersionUID = 480848624258596101L;
    /**
     * 整数类型案例
     */
    @EnumValue(intValues = {1}, message = "bigType")
    private Integer bigType;
    /**
     * 字符串类型案例
     */
    @EnumValue(strValues = {"0", "1"}, message = "taskType")
    private String taskType;
}

五. 为类和方法增加注解,实现参数校验:类注解(@Validated),方法注解(@Valid)

@Validated
@RestController
public class TestController {
    @PostMapping("test")
    public void test(@RequestBody @Valid SanheTaskEntity sanheTaskEntity){

    }
}