Spring Boot项目如何优雅的实现接口参数校验

背景:在java后端项目开发过程中,其实有很多大一部分项目,后端都没有做接口参数校验,或者做了参数校验,但是实现方式都是简单的使用if判断;主要原因在于:API的参数校验目前缺少比较流行的方案、现有方案不适用与自己的项目、项目部署在内网要求不高、或者干脆参数校验这种事情丢给前端来做

方案一:hibernate-validator

hibernate-validator是Hibernate项目中的一个数据校验框架,是Bean Validation 的参考实现,hibernate-validator除了提供了JSR 303规范中所有内置constraint 的实现,还有一些附加的constraint 。使用hibernate-validator能够将数据校验从业务代码中脱离出来,增加代码可读性,同时也让数据校验变得更加方便、简单;
详情可以参考:https://blog.csdn.net/weixin_37162010/article/details/80252154

方案二:AOP实现方法级的参数校验

hibernate-validator是在实体类上添加注解;但对于不同的方法,所应用的校验规则也是不一样的,这样子可能就会需要创建多个实体类或者组,甚至于一些接口根本就没实体类参数;所以实际应用过程中还是有一定的困难;
基于此,我花费了一点业余时间,借鉴了hibernate-validator的思路,实现了一套基于 注解 + AOP 的方式实现接口参数校验框架
在方法体上使用@CheckParam或者@CheckParams注解标注需要校验的参数;举个栗子:

@RestController
@RequestMapping("/paramCheck")
public class ParamCheckController {

	@CheckParam(value = Check.NotEmpty, argName = "userName", msg = "你大爷的,这个是必填参数!")
	@PostMapping("/singleCheckNotEmpty")
	public Object singleCheckNotNull(String userName) {
		return 1;
	}

	@CheckParam(value = Check.DateTime, argName = "dateTime")
	@PostMapping("/singleCheckDateTime")
	public Object singleCheckDateTime(String dateTime) {
		return 1;
	}
	
	@CheckParams({
		@CheckParam(value = Check.NotNull, argName = "userId", msg = "你大爷的,这个是必填参数!"),
		@CheckParam(value = Check.NotEmpty, argName = "userName"),
		@CheckParam(value = Check.NotEmpty, argName = "dept.deptName"),
		@CheckParam(value = Check.Past, argName = "dept.createTime"),
		@CheckParam(value = Check.lt, argName = "dept.employees", express = "2") // 对集合的size判断
	})
	@PostMapping("/entityMultiCheck")
	public Object entityMultiCheck(Integer userId, String userName, @RequestBody DeptEntity dept) {
		return 1;
	}
}

具体方案实现

版本仅供参考 jdk1.8 maven3.5.0 spring boot 2.0.2.RELEASE
在方法体上使用@CheckParam或者@CheckParams注解标注需要校验的参数;
然后使用AOP切入,获取配置的参数校验规则,同时获取对应的入参值,
调用CheckUtil工具类,进行判断
在这里插入图片描述

  • Check参数校验枚举类;目前实现了下列校验方法,后续会继续补充
public enum Check {

	Null("参数必须为 null", CheckUtil::isNull),

	NotNull("参数必须不为 null", CheckUtil::isNotNull),

	Empty("参数的必须为空", CheckUtil::isEmpty),
	
	NotEmpty("参数必须非空", CheckUtil::isNotEmpty),
	
	True("参数必须为 true", CheckUtil::isTrue),

	False("参数必须为 false", CheckUtil::isFalse),

	Date("参数必须是一个日期 yyyy-MM-dd", CheckUtil::isDate),

	DateTime("参数必须是一个日期时间  yyyy-MM-dd HH:mm:ss", CheckUtil::isDateTime),

	Past("参数必须是一个过去的日期 ", CheckUtil::isPast),

	Future("参数必须是一个将来的日期 ", CheckUtil::isFuture),
	
	Today("参数必须今天的日期 ", CheckUtil::isToday),
	
	Enum("参数必须在枚举中 ", CheckUtil::inEnum),
	
	Email("参数必须是Email地址", CheckUtil::isEmail),

	Range("参数必须在合适的范围内", CheckUtil::inRange),

	NotIn("参数必须不在指定的范围内 ", CheckUtil::outRange),
	
	Length("参数长度必须在指定范围内", CheckUtil::inLength),
	
	gt("参数必须大于指定值", CheckUtil::isGreaterThan),
	
	lt("参数必须小于指定值", CheckUtil::isLessThan),
	
	ge("参数必须大于等于指定值", CheckUtil::isGreaterThanEqual),
	
	le("参数必须小于等于指定值", CheckUtil::isLessThanEqual),
	
	ne("参数必须不等于指定值", CheckUtil::isNotEqual),
	
	Equal("参数必须不等于指定值", CheckUtil::isEqual),
	
	Pattern("参数必须符合指定的正则表达式", CheckUtil::isPattern)	;

	public String msg;
	public BiFunction<Object, String, Boolean> fun;

	Check(String msg, BiFunction<Object, String, Boolean> fun) {
		this.msg = msg;
		this.fun = fun;
	}
}
  • CheckParam注解类
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface CheckParam {

	// 字段校验规则,格式:字段名+校验规则+冒号+错误信息,例如:id<10:ID必须少于10
	Check value() default Check.NotNull;

	// 多个值逗号隔开
	String express() default "";
	
	// 参数名称用.表示层级,最多支持2级如: entity.userName
	String argName();

	// 自定义错误提示信息
	String msg() default "";
}
  • CheckParams注解类
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface CheckParams {
    // 多个CheckParam,由上往下判断
	CheckParam[] value();
}
  • AOP切面,篇幅有限有删减,详情请下载源码查看
@Aspect
@Component
public class CheckParamAop {

	@Pointcut("@annotation(com.yuxue.validator.annotation.CheckParam)")
	public void checkParam() {
	}
	
	@Pointcut("@annotation(com.yuxue.validator.annotation.CheckParams)")
	public void checkParams() {
	}

	@Around("checkParam()") // 这里要换成自定义注解的路径
	public Object check1(ProceedingJoinPoint point) throws Throwable {
		Object obj;
		// 参数校验
		String msg = doCheck(point, false);
		if (null != msg) {
			throw new IllegalArgumentException(msg);
		}
		// 通过校验,继续执行原有方法
		obj = point.proceed();
		return obj;
	}
	
	@Around("checkParams()") // 这里要换成自定义注解的路径
	public Object check2(ProceedingJoinPoint point) throws Throwable {
		Object obj;
		// 参数校验
		String msg = doCheck(point, true);
		if (null != msg) {
			throw new IllegalArgumentException(msg);
		}
		// 通过校验,继续执行原有方法
		obj = point.proceed();
		return obj;
	}

	/**
	 * 参数校验
	 * @param point 切点
	 * @param multi 多参数校验
	 * @return 错误信息
	 */
	private String doCheck(JoinPoint point, boolean multi) {
		Method method = this.getMethod(point);
		String[] paramName = this.getParamName(point);
		Object[] arguments = point.getArgs();	// 获取接口传递的所有参数
		
		Boolean isValid = true;
		String msg = null;
		if(multi) {	// 多个参数校验
			CheckParams annotation = method.getAnnotation(CheckParams.class);	// AOP监听带注解的方法,所以不用判断注解是否为空
			CheckParam[] annos = annotation.value();
			for (CheckParam anno : annos) {
				String argName = anno.argName();
				Object value = this.getParamValue(arguments, paramName, argName);	//参数值
		        isValid = anno.value().fun.apply(value, anno.express());	// 执行判断 // 调用枚举类的 CheckUtil类方法
		        if(!isValid) {	// 只要有一个参数判断不通过,立即返回
		        	msg = anno.msg();
			        if(null == msg || "".equals(msg)) {
			        	msg = argName + ": " + anno.value().msg + " " + anno.express();
			        }
		        	break;
		        }
			}
		} else {	// 单个参数校验
			CheckParam anno = method.getAnnotation(CheckParam.class);		// AOP监听带注解的方法,所以不用判断注解是否为空
			
			String argName = anno.argName();
			Object value = this.getParamValue(arguments, paramName, argName);	//参数值
	        isValid = anno.value().fun.apply(value, anno.express());	// 执行判断 // 调用枚举类的 CheckUtil类方法
	        msg = anno.msg();
	        if(null == msg || "".equals(msg)) {
	        	msg = argName + ": " + anno.value().msg + " " + anno.express();
	        }
		}
        if(isValid) {
        	// log.info("参数校验通过");
        	return null;
        } else {
        	// log.error("参数校验不通过");
        	return msg ;
        }
	}

	/**
	 * 根据参数名称,获取参数值
	 */
	private Object getParamValue(Object[] arguments, String[] paramName, String argName) {
		Object value = null;
		String name = argName;
		if(argName.contains(".")) {
			name = argName.split("\\.")[0];
		}
		int index = 0;
		for (String string : paramName) {
			if(string.equals(name)) {
				value = arguments[index];	//基本类型取值	// 不做空判断,如果注解配置的参数名称不存在,则取值为null
				break;
			}
			index++;
		}
		if(argName.contains(".")) {	//从对象中取值
			argName = argName.split("\\.")[1];
			JSONObject jo = (JSONObject) JSONObject.toJSON(value);
			// 从实体对象中取值
			value = jo.get(argName);
		}
		return value;
	}
}
  • CheckUtil参数校验工具类,篇幅有限有删减,详情请下载源码查看
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.springframework.util.CollectionUtils;

public class CheckUtil {

    /**
     * 判断value == null
     * @param value       字段值
     * @param express 这里不需要,只是为了参数统一
     * @return true or false
     */
    public static Boolean isNull(Object value, String express) {
        if (null != value) {
            return Boolean.FALSE;
        }
        return Boolean.TRUE;
    }

    /**
     * 判断value != null
     * @param value       字段值
     * @param express 这里不需要,只是为了参数统一
     * @return true or false
     */
    public static Boolean isNotNull(Object value, String express) {
        if (null == value) {
            return Boolean.FALSE;
        }
        return Boolean.TRUE;
    }

    /**
     * 判断value !=null && length、size > 0
     * 支持字符串判断
     * 支持集合判断
     */
    public static Boolean isNotEmpty(Object value, String express) {
        if(isNull(value, express)) {
            return Boolean.FALSE;
        }
        if(value instanceof String && "".equals(((String) value).trim())) {
            return Boolean.FALSE;
        }
        if(value instanceof Collection && CollectionUtils.isEmpty((Collection) value)) {
            return Boolean.FALSE;
        }
        return Boolean.TRUE;
    }


    /**
     * 判断参数是否是 true
     * 支持Boolean类型
     * 支持String类型
     */
    public static Boolean isTrue(Object value, String express) {
        if(isNull(value, express)) {
            return Boolean.FALSE;
        }
        if(value instanceof Boolean) {
            return (Boolean) value;
        }
        if(value instanceof String) {
            try {
                return Boolean.parseBoolean((String) value);
            } catch (Exception e) {
                return Boolean.FALSE;
            }
        }
        return Boolean.FALSE;
    }

    /**
     * 判断参数是否是一个日期
     * 支持Date类型
     * 支持LocalDate类型
     * 支持String类型,yyyy-MM-dd、yyyyMMdd、yyyy/MM/dd格式; 默认仅支持yyyy-MM-dd
     */
    public static Boolean isDate(Object value, String express) {
        if(isNull(value, express)) {
            return Boolean.FALSE;
        }
        if(value instanceof String) {      // 通常json格式参数,都是以字符串类型传递,优先判断
            // 验证参数,不能处理掉所有异常的符号
            // String v = ((String) value).trim().replaceAll("[-/\\s]", ""); 
            String v = ((String) value); //.replaceAll("[-/]", "");
            try {
                LocalDate.parse(v, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
                return Boolean.TRUE;
            } catch (Exception e) {
                return Boolean.FALSE;
            }
        }
        if(value instanceof Date) {
            return Boolean.TRUE;
        }
        if(value instanceof LocalDate) {
            return Boolean.TRUE;
        }
        return Boolean.FALSE;
    }


    /**
     * 判断参数是否是一个日期
     * 支持Date类型
     * 支持LocalDateTime类型
     * 支持String类型,yyyy-MM-dd HH:mm:ss、yyyyMMddHHmmss、yyyy/MM/dd HH:mm:ss格式; 默认仅支持yyyy-MM-dd HH:mm:ss
     */
    public static Boolean isDateTime(Object value, String express) {
        if(isNull(value, express)) {
            return Boolean.FALSE;
        }
        if(value instanceof String) {   // 通常json格式参数,都是以字符串类型传递,优先判断
            String v = ((String) value); //.replaceAll("[-/]", "");  // 验证参数,不能处理掉所有异常的符号
            try {
                LocalDateTime.parse(v, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
                return Boolean.TRUE;
            } catch (Exception e) {
                /*try {
                    LocalDateTime.parse(v, DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
                    return Boolean.TRUE;
                } catch (Exception e1) {
                    return Boolean.FALSE;
                }*/
            	return Boolean.FALSE;
            }
        }
        if(value instanceof Date) {
            return Boolean.TRUE;
        }
        if(value instanceof LocalDateTime) {
            return Boolean.TRUE;
        }
        return Boolean.FALSE;
    }

    /**
     * 判断是否是邮箱
     * 使用正则表达式判断
     * @param value
     * @param express
     * @return
     */
    public static Boolean isEmail(Object value, String express) {
        if(isNull(value, express)) {
            return Boolean.FALSE;
        }
        if(value instanceof String) {  
            String regEx = "^([a-z0-9A-Z]+[-|\\.]?)+[a-z0-9A-Z]@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\\.)+[a-zA-Z]{2,}$";
            Pattern p = Pattern.compile(regEx);
            Matcher m = p.matcher((String) value);
            if (m.matches()) {
                return Boolean.TRUE;
            } 
        }
        return Boolean.FALSE;
    }
    
    /**
     * 判断参数的取值范围,逗号隔开,无空格;闭区间
     * 支持Integer
     * 支持Long
     * 支持Short
     * 支持Float
     * 支持Double
     * @param value
     * @param rangeStr
     * @return
     */
    public static Boolean inRange(Object value, String rangeStr) {
        if(isNull(value, rangeStr)) {
            return Boolean.FALSE;
        }
        if(null == rangeStr || "".equals(rangeStr)) {
            return Boolean.FALSE;
        }
        if(value instanceof Integer) {
        	Integer begin = Integer.valueOf(rangeStr.split(",")[0]);
        	Integer end = Integer.valueOf(rangeStr.split(",")[1]);
        	Integer v = ((Integer) value);
            return  begin <= v && v <= end;
        }
        if(value instanceof Long) {
        	Long begin = Long.valueOf(rangeStr.split(",")[0]);
        	Long end = Long.valueOf(rangeStr.split(",")[1]);
        	Long v = ((Long) value);
            return  begin <= v && v <= end;
        }
        if(value instanceof Short) {
        	Short begin = Short.valueOf(rangeStr.split(",")[0]);
        	Short end = Short.valueOf(rangeStr.split(",")[1]);
        	Short v = ((Short) value);
            return  begin <= v && v <= end;
        }
        if(value instanceof Float) {
        	Float begin = Float.valueOf(rangeStr.split(",")[0]);
        	Float end = Float.valueOf(rangeStr.split(",")[1]);
        	Float v = ((Float) value);
            return  begin <= v && v <= end;
        }
        if(value instanceof Double) {
        	Double begin = Double.valueOf(rangeStr.split(",")[0]);
        	Double end = Double.valueOf(rangeStr.split(",")[1]);
        	Double v = ((Double) value);
            return  begin <= v && v <= end;
        }
        return Boolean.FALSE;
    }
    
    /**
     * 判断参数的取值范围,逗号隔开,无空格;闭区间
     * 判断String的length范围, rangeStr取值举例:"6,18"
     * @param value
     * @param rangeStr
     * @return
     */
    public static Boolean inLength(Object value, String rangeStr) {
    	if(isNull(value, rangeStr)) {
            return Boolean.FALSE;
        }
        if(null == rangeStr || "".equals(rangeStr)) {
            return Boolean.FALSE;
        }
        if(value instanceof String) {
        	Integer begin = Integer.valueOf(rangeStr.split(",")[0]);
        	Integer end = Integer.valueOf(rangeStr.split(",")[1]);
        	Integer v = ((String) value).length();
            return  begin <= v && v <= end;
        }
        return Boolean.FALSE;
    }
    
    
    /**
     * 判断参数是否在枚举的数据中, 枚举的表达式用 英文逗号隔开,无空格,如: "男,女,太监"
     * 校验过程,不在对表达式进行校验,所以请确保表达式的格式正确
     * 支持String
     * 支持Integer Short Long
     * @param value
     * @param enumStr
     * @return
     */
    public static Boolean inEnum(Object value, String enumStr) {
        if(isNull(value, null)) {
            return Boolean.FALSE;
        }
        if(null == enumStr || "".equals(enumStr)) {
            return Boolean.FALSE;
        }
    	String[] array = enumStr.split(",");
    	Set<String> set = new HashSet<>(Arrays.asList(array));
        return set.contains(value.toString());
    }

    /**
     * 是否大于等于
     * 支持String,判断length值
     * 支持Integer
     * 支持Long
     * 支持Short
     * 支持Float
     * 支持Double
     * 支持Collection,判断size的值
     * @param value
     * @param express
     * @return
     */
    public static Boolean isGreaterThanEqual(Object value, String express) {
        if (value == null) {
            return Boolean.FALSE;
        }
        if(value instanceof Integer) {
            return ((Integer) value) >= Integer.valueOf(express);
        }
        if(value instanceof Long) {
            return ((Long) value) >= Long.valueOf(express);
        }
        if(value instanceof Short) {
            return ((Short) value) >= Short.valueOf(express);
        }
        if(value instanceof Float) {
            return ((Float) value) >= Float.valueOf(express);
        }
        if(value instanceof Double) {
            return ((Double) value) >= Double.valueOf(express);
        }
        if(value instanceof String) {
            return ((String) value).length() >= Integer.valueOf(express);
        }
        if(value instanceof Collection) {
            return  ((Collection) value).size() >= Integer.valueOf(express);
        }
        return Boolean.FALSE;
    }
    
    /**
     * 判断是否Equal指定的值
     * 支持String
     * 支持Integer
     * 支持Long
     * 支持Short
     * 支持Float
     * 支持Double
     * 支持Collection,判断size的值
     * @param value
     * @param express
     * @return
     */
    public static Boolean isEqual(Object value, String express) {
        if (value == null) {
            return Boolean.FALSE;
        }
        if(value instanceof String) {
            return ((String) value).equals(express);
        }
        if(value instanceof Integer) {
            return ((Integer) value).equals(Integer.valueOf(express));
        }
        if(value instanceof Long) {
            return ((Long) value).equals(Long.valueOf(express));
        }
        if(value instanceof Short) {
            return ((Short) value).equals(Short.valueOf(express));
        }
        if(value instanceof Float) {
            return ((Float) value).equals(Float.valueOf(express));
        }
        if(value instanceof Double) {
            return ((Double) value).equals(Double.valueOf(express));
        }
        if(value instanceof Collection) {
            return  ((Collection) value).size() == Integer.valueOf(express);
        }
        return Boolean.FALSE;
    }
    
    /**
     * 判断String是否满足正则表达式
     * @param value
     * @param regEx 正则表达式
     * @return
     */
    public static Boolean isPattern(Object value, String regEx) {
        if(isNull(value, null)) {
            return Boolean.FALSE;
        }
        if(value instanceof String) {  
            Pattern p = Pattern.compile(regEx);
            Matcher m = p.matcher((String) value);
            if (m.matches()) {
                return Boolean.TRUE;
            } 
        }
        return Boolean.FALSE;
    }
}

应用文档

在这里插入图片描述
修改Application,添加 @SpringBootApplication(scanBasePackages = {"com.yuxue"})

maven项目添加pom依赖,或者添加jar依赖包即可

<dependency>
	<groupId>com.yuxue</groupId>
	<artifactId>yx-validator</artifactId>
	<version>1.0.0</version>
</dependency>

接口参数校验使用demo

import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.yuxue.entity.DeptEntity;
import com.yuxue.entity.EmployeeEntity;
import com.yuxue.validator.annotation.CheckParam;
import com.yuxue.validator.annotation.CheckParams;
import com.yuxue.validator.enumtype.Check;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;


@Api(tags = {"check"}, description = "参数校验")
@RestController
@RequestMapping("/paramCheck")
public class ParamCheckController {

	@ApiImplicitParam(name = "userId", value = "", dataType = "Integer", paramType="query")
	@CheckParam(value = Check.NotNull, argName = "userId")
	@PostMapping("/singleCheckNotNull")
	public Object singleCheckNotNull(Integer userId) {
		System.err.println(userId);
		return 1;
	}
	
	@ApiImplicitParam(name = "userName", value = "", dataType = "String", paramType="query")
	@CheckParam(value = Check.NotEmpty, argName = "userName", msg = "你大爷的,这个是必填参数!")
	@PostMapping("/singleCheckNotEmpty")
	public Object singleCheckNotNull(String userName) {
		System.err.println(userName);
		return 1;
	}
	
	@ApiImplicitParam(name = "bl", value = "", dataType = "Boolean", paramType="query")
	@CheckParam(value = Check.True, argName = "bl")
	@PostMapping("/singleCheckTrue")
	public Object singleCheckTrue(Boolean bl) {
		System.err.println(bl);
		return 1;
	}
	
	@ApiImplicitParam(name = "date", value = "", dataType = "String", paramType="query")
	@CheckParam(value = Check.Date, argName = "date")
	@PostMapping("/singleCheckDate")
	public Object singleCheckDate(String date) {
		System.err.println(date);
		return 1;
	}
	
	@ApiImplicitParam(name = "dateTime", value = "", dataType = "String", paramType="query")
	@CheckParam(value = Check.DateTime, argName = "dateTime")
	@PostMapping("/singleCheckDateTime")
	public Object singleCheckDateTime(String dateTime) {
		System.err.println(dateTime);
		return 1;
	}
	
	@ApiImplicitParam(name = "date", value = "", dataType = "String", paramType="query")
	@CheckParam(value = Check.Past, argName = "date")
	@PostMapping("/singleCheckPast")
	public Object singleCheckPast(String date) {
		System.err.println(date);
		return 1;
	}
	
	@ApiImplicitParam(name = "dateTime", value = "", dataType = "String", paramType="query")
	@CheckParam(value = Check.Future, argName = "dateTime", msg = "参数必须是一个将来的日期或者时间,并且满足 yyyy-MM-dd HH:mm:ss格式")
	@PostMapping("/singleCheckFuture")
	public Object singleCheckFuture(String dateTime) {
		System.err.println(dateTime);
		return 1;
	}
	
	@ApiImplicitParam(name = "date", value = "", dataType = "String", paramType="query")
	@CheckParam(value = Check.Today, argName = "date")
	@PostMapping("/singleCheckToday")
	public Object singleCheckToday(String date) {
		System.err.println(date);
		return 1;
	}
	
	@ApiImplicitParam(name = "gender", value = "", dataType = "String", paramType="query")
	@CheckParam(value = Check.Enum, argName = "gender", express="男,女,太监")
	@PostMapping("/singleCheckStringEnum")
	public Object singleCheckStringEnum(String gender) {
		System.err.println(gender);
		return 1;
	}
	
	@ApiImplicitParam(name = "gender", value = "", dataType = "Integer", paramType="query")
	@CheckParam(value = Check.Enum, argName = "gender", express="0,1")
	@PostMapping("/singleCheckIntegerEnum")
	public Object singleCheckIntegerEnum(Integer gender) {
		System.err.println(gender);
		return 1;
	}
	
	@ApiImplicitParam(name = "password", value = "", dataType = "String", paramType="query")
	@CheckParam(value = Check.Length, argName = "password", express="6,18", msg="密码length必须在6-18位之间!")
	@PostMapping("/singleCheckStringLength")
	public Object singleCheckStringLength(String password) {
		System.err.println(password);
		return 1;
	}
	
	@ApiImplicitParam(name = "password", value = "", dataType = "String", paramType="query")
	@CheckParams({
		@CheckParam(value = Check.ge, argName = "password", express = "6"),
		@CheckParam(value = Check.le, argName = "password", express = "18")
	})
	@PostMapping("/singleCheckStringLength1")
	public Object singleCheckStringLength1(String password) {
		System.err.println(password);
		return 1;
	}
	
	@ApiImplicitParam(name = "age", value = "", dataType = "Integer", paramType="query")
	@CheckParam(value = Check.Range, argName = "age", express="18,50")
	@PostMapping("/singleCheckIntegerRange")
	public Object singleCheckIntegerRange(Integer age) {
		System.err.println(age);
		return 1;
	}
	
	@ApiImplicitParam(name = "age", value = "", dataType = "Integer", paramType="query")
	@CheckParams({
		@CheckParam(value = Check.ge, argName = "age", express="18"),
		@CheckParam(value = Check.le, argName = "age", express="50")
	})
	@PostMapping("/singleCheckIntegerRange1")
	public Object singleCheckIntegerRange1(Integer age) {
		System.err.println(age);
		return 1;
	}
	
	@ApiImplicitParam(name = "age", value = "", dataType = "Integer", paramType="query")
	@CheckParam(value = Check.NotIn, argName = "age", express="18,50")
	@PostMapping("/singleCheckIntegerNotIn")
	public Object singleCheckIntegerNotIn(Integer age) {
		System.err.println(age);
		return 1;
	}
	
	@ApiImplicitParam(name = "age", value = "", dataType = "Integer", paramType="query")
	@CheckParams({
		@CheckParam(value = Check.lt, argName = "age", express="18"),
		@CheckParam(value = Check.gt, argName = "age", express="50")
	})
	@PostMapping("/singleCheckIntegerNotIn1")
	public Object singleCheckIntegerNotIn1(Integer age) {
		System.err.println(age);
		return 1;
	}
	
	@ApiImplicitParam(name = "email", value = "", dataType = "String", paramType="query")
	@CheckParam(value = Check.Email, argName = "email", msg="你大爷的,输入个邮箱啊!")
	@PostMapping("/singleCheckEmail")
	public Object singleCheckEmail(String email) {
		System.err.println(email);
		return 1;
	}
	
	@ApiImplicitParam(name = "age", value = "", dataType = "Integer", paramType="query")
	@CheckParam(value = Check.ge, argName = "age", express="18", msg = "必须大于等于18岁") // gt、lt、le、ne、Equal不再举例; 具体看注释
	@PostMapping("/singleCheckIntegerGe")
	public Object singleCheckIntegerGe(Integer age) {
		System.err.println(age);
		return 1;
	}
	
	@ApiImplicitParam(name = "pattern", value = "", dataType = "String", paramType="query")
	@CheckParam(value = Check.Pattern, argName = "pattern", express="^[\u0021-\u007E]{4,16}$")
	@PostMapping("/singleCheckPattern")
	public Object singleCheckPattern(String pattern) {
		System.err.println(pattern);
		return 1;
	}
	
	@ApiImplicitParams({
		@ApiImplicitParam(name = "userId", dataType = "Integer", paramType="query"),
		@ApiImplicitParam(name = "userName", dataType = "String", paramType="query")
	})
	@CheckParams({
		@CheckParam(value = Check.NotNull, argName = "userId", msg = "你大爷的,这个是必填参数!"),
		@CheckParam(value = Check.NotNull, argName = "userName")
	})
	@PostMapping("/multiCheckNotNull")
	public Object multiCheckNotNull(Integer userId, String userName) {
		System.err.println(userId);
		System.err.println(userName);
		return 1;
	}
	
	@ApiImplicitParams({
		@ApiImplicitParam(name = "userId", dataType = "Integer", paramType="query"),
		@ApiImplicitParam(name = "userName", dataType = "String", paramType="query"),
		@ApiImplicitParam(name = "employee", dataType = "entity", paramType="body")
	})
	@CheckParams({
		@CheckParam(value = Check.NotNull, argName = "userId", msg = "你大爷的,这个是必填参数!"),
		@CheckParam(value = Check.NotEmpty, argName = "userName"),
		@CheckParam(value = Check.NotEmpty, argName = "employee.name")
	})
	@PostMapping("/entityCheckNotNull")
	public Object entityCheckNotNull(Integer userId, String userName, @RequestBody EmployeeEntity employee) {
		System.err.println(userId);
		System.err.println(userName);
		System.err.println(employee.getName());
		return 1;
	}
	
	@ApiImplicitParams({
		@ApiImplicitParam(name = "userId", dataType = "Integer", paramType="query"),
		@ApiImplicitParam(name = "userName", dataType = "String", paramType="query"),
		@ApiImplicitParam(name = "dept", dataType = "entity", paramType="body")
	})
	@CheckParams({
		@CheckParam(value = Check.NotNull, argName = "userId", msg = "你大爷的,这个是必填参数!"),
		@CheckParam(value = Check.NotEmpty, argName = "userName"),
		@CheckParam(value = Check.NotEmpty, argName = "dept.deptName"),
		@CheckParam(value = Check.Past, argName = "dept.createTime"),
		@CheckParam(value = Check.lt, argName = "dept.employees", express = "2") // 对集合的size判断
	})
	@PostMapping("/entityMultiCheck")
	public Object entityMultiCheck(Integer userId, String userName, @RequestBody DeptEntity dept) {
		System.err.println(userId);
		System.err.println(userName);
		System.err.println(dept.getDeptName());
		return 1;
	}
}

源码下载地址

码云git:https://gitee.com/admin_yu/yx-validator
CSDN下载频道:https://download.csdn.net/download/weixin_42686388/12109312

可能遇到的问题

  • 切面不生效
    修改Application,添加 @SpringBootApplication(scanBasePackages = {"com.yuxue"}) 扫描到注解即可
  • 参数校验不通过抛出异常
    本框架校验参数,发现不通过,会抛出IllegalArgumentException异常,并支持配置自定义的msg,如果未配置则显示枚举中设置的默认msg,具体的异常处理,需要自己处理
  • 参数校验方法有bug
    可以自行修改CheckUtil工具类里面对应的方法即可
    还可以可以通过yuxue1687@qq.com联系我,将问题及日志整理出来发给我,我会定期处理。也可以通过码云git提交修改后的代码请求。

参考文档

https://blog.csdn.net/weixin_37162010/article/details/80252154
https://www.jb51.net/article/139874.htm
http://hibernate.org/validator/releases/

  • 5
    点赞
  • 46
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值