背景:在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/